Improved grammar to allow multiple expressions in a function parameter
This commit is contained in:
parent
699a99608e
commit
69ea8e0b92
|
@ -170,7 +170,7 @@ public class Player {
|
|||
StreamSource best;
|
||||
int maxRes = Config.getInstance().getSettings().maximumResolutionPlayer;
|
||||
if (maxRes > 0 && !sources.isEmpty()) {
|
||||
for (Iterator<StreamSource> iterator = sources.iterator(); iterator.hasNext();) {
|
||||
for (Iterator<StreamSource> iterator = sources.iterator(); iterator.hasNext(); ) {
|
||||
StreamSource streamSource = iterator.next();
|
||||
if (streamSource.height > 0 && maxRes < streamSource.height) {
|
||||
LOG.trace("Res too high {} > {}", streamSource.height, maxRes);
|
||||
|
@ -188,7 +188,7 @@ public class Player {
|
|||
}
|
||||
|
||||
private void expandPlaceHolders(String[] cmdline) {
|
||||
ModelVariableExpander expander = new ModelVariableExpander(model, Config.getInstance(), null);
|
||||
ModelVariableExpander expander = new ModelVariableExpander(model, Config.getInstance(), null, null);
|
||||
for (int i = 0; i < cmdline.length; i++) {
|
||||
var param = cmdline[i];
|
||||
param = expander.expand(param);
|
||||
|
|
|
@ -1,43 +1,49 @@
|
|||
package ctbrec.ui.action;
|
||||
|
||||
import java.io.File;
|
||||
import java.time.Instant;
|
||||
|
||||
import ctbrec.Config;
|
||||
import ctbrec.GlobalThreadPool;
|
||||
import ctbrec.Model;
|
||||
import ctbrec.Settings.DirectoryStructure;
|
||||
import ctbrec.ui.DesktopIntegration;
|
||||
import ctbrec.ui.controls.Dialogs;
|
||||
import javafx.scene.Cursor;
|
||||
import javafx.scene.Node;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.File;
|
||||
import java.time.Instant;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class OpenRecordingsDir {
|
||||
|
||||
private Model selectedModel;
|
||||
private Node source;
|
||||
|
||||
public OpenRecordingsDir(Node source, Model selectedModel) {
|
||||
this.source = source;
|
||||
this.selectedModel = selectedModel;
|
||||
}
|
||||
private final Node source;
|
||||
private final Model selectedModel;
|
||||
|
||||
public void execute() {
|
||||
source.setCursor(Cursor.WAIT);
|
||||
var fileForRecording = Config.getInstance().getFileForRecording(selectedModel, ".mp4", Instant.now());
|
||||
final File dir = getModelDirectory(fileForRecording);
|
||||
var dir = Config.getInstance().getFileForRecording(selectedModel, ".mp4", Instant.now());
|
||||
dir = findDeepestExistingDir(dir);
|
||||
log.info("Directory for model is {}", dir.getAbsolutePath());
|
||||
if (dir.exists()) {
|
||||
GlobalThreadPool.submit(() -> DesktopIntegration.open(dir));
|
||||
final File directory = dir;
|
||||
GlobalThreadPool.submit(() -> DesktopIntegration.open(directory));
|
||||
} else {
|
||||
Dialogs.showError(source.getScene(), "Directory does not exist", "There are no recordings for this model", null);
|
||||
}
|
||||
source.setCursor(Cursor.DEFAULT);
|
||||
}
|
||||
|
||||
private File getModelDirectory(File fileForRecording) {
|
||||
var dir = fileForRecording.getParentFile();
|
||||
if (Config.getInstance().getSettings().recordingsDirStructure == DirectoryStructure.ONE_PER_RECORDING) {
|
||||
dir = dir.getParentFile();
|
||||
private File findDeepestExistingDir(File dir) {
|
||||
while (!dir.exists()) {
|
||||
if (dir.getParentFile() == null) {
|
||||
return dir;
|
||||
} else {
|
||||
dir = dir.getParentFile();
|
||||
if (dir.exists()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
|
|
|
@ -123,6 +123,7 @@ public class SettingsTab extends Tab implements TabSelectionListener {
|
|||
private LocalTimeProperty timeoutRecordingEndingAt;
|
||||
private SimpleLongProperty recordUntilDefaultDurationInMinutes;
|
||||
private SimpleStringProperty dateTimeFormat;
|
||||
private final VariablePlayGroundDialogFactory variablePlayGroundDialogFactory = new VariablePlayGroundDialogFactory();
|
||||
|
||||
public SettingsTab(List<Site> sites, Recorder recorder) {
|
||||
this.sites = sites;
|
||||
|
@ -379,9 +380,9 @@ public class SettingsTab extends Tab implements TabSelectionListener {
|
|||
}
|
||||
|
||||
private Button createVariablePlayGroundButton() {
|
||||
var postProcessingHelpButton = new Button("Variable Playground");
|
||||
postProcessingHelpButton.setOnAction(e -> new VariablePlayGroundDialogFactory().openDialog(this.getTabPane().getScene(), config, recorder));
|
||||
return postProcessingHelpButton;
|
||||
var button = new Button("Variable Playground");
|
||||
button.setOnAction(e -> variablePlayGroundDialogFactory.openDialog(this.getTabPane().getScene(), config, recorder));
|
||||
return button;
|
||||
}
|
||||
|
||||
private void bindEnabledProperty(Setting s, BooleanExpression bindTo) {
|
||||
|
|
|
@ -5,42 +5,53 @@ import ctbrec.Recording;
|
|||
import ctbrec.StringUtil;
|
||||
import ctbrec.UnknownModel;
|
||||
import ctbrec.recorder.Recorder;
|
||||
import ctbrec.recorder.postprocessing.PostProcessingContext;
|
||||
import ctbrec.sites.chaturbate.Chaturbate;
|
||||
import ctbrec.ui.controls.Dialogs;
|
||||
import ctbrec.ui.tabs.DownloadPostprocessor;
|
||||
import ctbrec.variableexpansion.ConfigVariableExpander;
|
||||
import ctbrec.variableexpansion.ModelVariableExpander;
|
||||
import ctbrec.variableexpansion.RecordingVariableExpander;
|
||||
import ctbrec.variableexpansion.functions.AntlrSyntacErrorAdapter;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.Priority;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.antlr.v4.runtime.RecognitionException;
|
||||
import org.antlr.v4.runtime.Recognizer;
|
||||
|
||||
import java.nio.file.Paths;
|
||||
import java.time.Instant;
|
||||
|
||||
@Slf4j
|
||||
public class VariablePlayGroundDialogFactory {
|
||||
|
||||
private GridPane pane;
|
||||
|
||||
public void openDialog(Scene parent, Config config, Recorder recorder) {
|
||||
if (pane == null) {
|
||||
initGui(config, recorder);
|
||||
}
|
||||
|
||||
Dialogs.showCustomInput(parent, "Playground", pane, (obs, oldV, newV) -> {
|
||||
});
|
||||
}
|
||||
|
||||
private void initGui(Config config, Recorder recorder) {
|
||||
Chaturbate chaturbate = new Chaturbate();
|
||||
UnknownModel unknownModel = new UnknownModel();
|
||||
unknownModel.setName("Pussy_Galore");
|
||||
unknownModel.setDisplayName("Pussy Galore");
|
||||
unknownModel.setSite(chaturbate);
|
||||
unknownModel.setUrl("http://camsite.example/pussy_galore");
|
||||
Recording recording = new Recording();
|
||||
recording.setAbsoluteFile(Paths.get("ctbrec", "recs", "pussy_galore", "2023-02-26_14-05-56").toFile());
|
||||
recording.setStartDate(Instant.now());
|
||||
recording.setStatus(Recording.State.POST_PROCESSING);
|
||||
recording.setNote("notes about the recording");
|
||||
recording.setModel(unknownModel);
|
||||
PostProcessingContext ctx = new PostProcessingContext();
|
||||
ctx.setConfig(config);
|
||||
ctx.setRecorder(recorder);
|
||||
ctx.setRecording(recording);
|
||||
DownloadPostprocessor postprocessor = new DownloadPostprocessor();
|
||||
|
||||
GridPane pane = new GridPane();
|
||||
pane = new GridPane();
|
||||
Label result = new Label();
|
||||
Label error = new Label();
|
||||
|
||||
|
@ -49,18 +60,6 @@ public class VariablePlayGroundDialogFactory {
|
|||
input.setMinWidth(600);
|
||||
pane.add(input, 1, 0);
|
||||
GridPane.setHgrow(input, Priority.ALWAYS);
|
||||
input.setOnKeyTyped(evt -> {
|
||||
String r = postprocessor.fillInPlaceHolders(input.getText(), ctx, new AntlrSyntacErrorAdapter() {
|
||||
@Override
|
||||
public void syntaxError(Recognizer<?, ?> recognizer, Object o, int line, int pos, String s, RecognitionException e) {
|
||||
error.setText(String.format("Syntax error at %d:%d %s", line, pos, s));
|
||||
}
|
||||
});
|
||||
result.setText(r);
|
||||
if (StringUtil.isNotBlank(r)) {
|
||||
error.setText("");
|
||||
}
|
||||
});
|
||||
|
||||
pane.add(error, 0, 1);
|
||||
GridPane.setColumnSpan(error, 2);
|
||||
|
@ -70,7 +69,31 @@ public class VariablePlayGroundDialogFactory {
|
|||
|
||||
pane.setHgap(5);
|
||||
pane.vgapProperty().bind(pane.hgapProperty());
|
||||
Dialogs.showCustomInput(parent, "Playground", pane, (obs, oldV, newV) -> {
|
||||
|
||||
AntlrSyntacErrorAdapter errorHandler = new AntlrSyntacErrorAdapter() {
|
||||
@Override
|
||||
public void syntaxError(Recognizer<?, ?> recognizer, Object o, int line, int pos, String s, RecognitionException e) {
|
||||
error.setText(String.format("Syntax error at %d:%d %s", line, pos, s));
|
||||
}
|
||||
};
|
||||
|
||||
ModelVariableExpander modelVariableExpander = new ModelVariableExpander(unknownModel, config, recorder, errorHandler);
|
||||
RecordingVariableExpander recordingVariableExpander = new RecordingVariableExpander(recording, errorHandler);
|
||||
ConfigVariableExpander configVariableExpander = new ConfigVariableExpander(config, errorHandler);
|
||||
|
||||
input.setOnKeyTyped(evt -> {
|
||||
try {
|
||||
String r = input.getText();
|
||||
modelVariableExpander.getPlaceholderValueSuppliers().putAll(recordingVariableExpander.getPlaceholderValueSuppliers());
|
||||
modelVariableExpander.getPlaceholderValueSuppliers().putAll(configVariableExpander.getPlaceholderValueSuppliers());
|
||||
r = modelVariableExpander.expand(r);
|
||||
result.setText(r);
|
||||
if (StringUtil.isNotBlank(r)) {
|
||||
error.setText("");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Error", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,11 +2,13 @@ grammar PostProcessing;
|
|||
|
||||
line: (text | variable | functionCall)* EOF;
|
||||
|
||||
functionCall: '$' identifier '(' (expression (',' expression)*)? ')';
|
||||
functionCall: '$' identifier '(' (parameter (',' parameter)*)? ')';
|
||||
|
||||
text: CH+?;
|
||||
identifier: CH+?;
|
||||
|
||||
parameter: expression*;
|
||||
|
||||
variable: '${' identifier '}';
|
||||
|
||||
expression
|
||||
|
|
|
@ -183,9 +183,8 @@ public class Config {
|
|||
}
|
||||
|
||||
private void migrateOldSettings() {
|
||||
// 4.7.18
|
||||
// 5.0.0
|
||||
convertChaturbateModelNamesToLowerCase();
|
||||
|
||||
}
|
||||
|
||||
private void convertChaturbateModelNamesToLowerCase() {
|
||||
|
|
|
@ -2,29 +2,11 @@ package ctbrec.recorder.postprocessing;
|
|||
|
||||
import ctbrec.Config;
|
||||
import ctbrec.Recording;
|
||||
import ctbrec.StringUtil;
|
||||
import ctbrec.variableexpansion.ConfigVariableExpander;
|
||||
import ctbrec.variableexpansion.ModelVariableExpander;
|
||||
import ctbrec.variableexpansion.ParserVisitor;
|
||||
import ctbrec.variableexpansion.VariableExpansionException;
|
||||
import ctbrec.variableexpansion.antlr.PostProcessingLexer;
|
||||
import ctbrec.variableexpansion.antlr.PostProcessingParser;
|
||||
import ctbrec.variableexpansion.RecordingVariableExpander;
|
||||
import ctbrec.variableexpansion.functions.AntlrSyntacErrorAdapter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.antlr.v4.runtime.CharStream;
|
||||
import org.antlr.v4.runtime.CharStreams;
|
||||
import org.antlr.v4.runtime.CommonTokenStream;
|
||||
import org.antlr.v4.runtime.tree.ParseTree;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import static java.util.Optional.ofNullable;
|
||||
|
||||
@Slf4j
|
||||
public abstract class AbstractPlaceholderAwarePostProcessor extends AbstractPostProcessor {
|
||||
|
@ -37,58 +19,11 @@ public abstract class AbstractPlaceholderAwarePostProcessor extends AbstractPost
|
|||
Recording rec = ctx.getRecording();
|
||||
Config config = ctx.getConfig();
|
||||
|
||||
ModelVariableExpander modelExpander = new ModelVariableExpander(rec.getModel(), config, ctx.getRecorder());
|
||||
Map<String, Optional<Object>> variables = new HashMap<>(modelExpander.getPlaceholderValueSuppliers());
|
||||
variables.put("recordingNotes", getSanitizedRecordingNotes(rec));
|
||||
variables.put("fileSuffix", getFileSuffix(rec));
|
||||
variables.put("recordingsDir", Optional.of(config.getSettings().recordingsDir));
|
||||
variables.put("absolutePath", Optional.of(rec.getPostProcessedFile().getAbsolutePath()));
|
||||
variables.put("absoluteParentPath", Optional.of(rec.getPostProcessedFile().getParentFile().getAbsolutePath()));
|
||||
variables.put("epochSecond", ofNullable(rec.getStartDate()).map(Instant::getEpochSecond).map(l -> Long.toString(l))); // NOSONAR
|
||||
variables.put("utcDateTime", getUtcDateTime(rec));
|
||||
variables.put("localDateTime", getLocalDateTime(rec));
|
||||
|
||||
return fillInPlaceHolders(input, variables, errorListener);
|
||||
}
|
||||
|
||||
private String fillInPlaceHolders(String input, Map<String, Optional<Object>> variables, AntlrSyntacErrorAdapter errorListener) {
|
||||
try (StringReader reader = new StringReader(input)) {
|
||||
CharStream s = CharStreams.fromReader(reader);
|
||||
PostProcessingLexer lexer = new PostProcessingLexer(s);
|
||||
CommonTokenStream tokens = new CommonTokenStream(lexer);
|
||||
PostProcessingParser parser = new PostProcessingParser(tokens);
|
||||
Optional.ofNullable(errorListener).ifPresent(parser::addErrorListener);
|
||||
ParseTree parseTree = parser.line();
|
||||
ParserVisitor visitor = new ParserVisitor(variables);
|
||||
return visitor.visit(parseTree);
|
||||
} catch (IOException e) {
|
||||
throw new VariableExpansionException("Couldn't replace placeholders", e);
|
||||
}
|
||||
}
|
||||
|
||||
protected Optional<Object> getUtcDateTime(Recording rec) {
|
||||
return Optional.ofNullable(rec)
|
||||
.map(Recording::getStartDate)
|
||||
.map(i -> i.atZone(ZoneOffset.UTC));
|
||||
}
|
||||
|
||||
protected Optional<Object> getLocalDateTime(Recording rec) {
|
||||
return Optional.ofNullable(rec)
|
||||
.map(Recording::getStartDate)
|
||||
.map(i -> i.atZone(ZoneId.systemDefault()));
|
||||
}
|
||||
|
||||
private Optional<Object> getFileSuffix(Recording rec) {
|
||||
if (rec.isSingleFile()) {
|
||||
String filename = rec.getPostProcessedFile().getName();
|
||||
return Optional.of(filename.substring(filename.lastIndexOf('.') + 1));
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
private Optional<Object> getSanitizedRecordingNotes(Recording rec) {
|
||||
Optional<String> notes = ofNullable(rec.getNote());
|
||||
return notes.map(StringUtil::sanitize);
|
||||
ModelVariableExpander modelExpander = new ModelVariableExpander(rec.getModel(), config, ctx.getRecorder(), errorListener);
|
||||
RecordingVariableExpander recordingExpander = new RecordingVariableExpander(rec, errorListener);
|
||||
ConfigVariableExpander configExpander = new ConfigVariableExpander(config, errorListener);
|
||||
modelExpander.getPlaceholderValueSuppliers().putAll(recordingExpander.getPlaceholderValueSuppliers());
|
||||
modelExpander.getPlaceholderValueSuppliers().putAll(configExpander.getPlaceholderValueSuppliers());
|
||||
return modelExpander.expand(input);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,11 @@ import ctbrec.variableexpansion.antlr.PostProcessingLexer;
|
|||
import ctbrec.variableexpansion.antlr.PostProcessingParser;
|
||||
import ctbrec.variableexpansion.functions.AntlrSyntacErrorAdapter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.antlr.v4.runtime.*;
|
||||
import org.antlr.v4.runtime.CharStream;
|
||||
import org.antlr.v4.runtime.CharStreams;
|
||||
import org.antlr.v4.runtime.CommonTokenStream;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.HashMap;
|
||||
|
@ -17,18 +20,19 @@ abstract class AbstractVariableExpander {
|
|||
|
||||
protected Map<String, Optional<Object>> placeholderValueSuppliers = new HashMap<>();
|
||||
|
||||
protected AntlrSyntacErrorAdapter errorListener;
|
||||
|
||||
AbstractVariableExpander(@Nullable AntlrSyntacErrorAdapter errorListener) {
|
||||
this.errorListener = errorListener;
|
||||
}
|
||||
|
||||
protected String fillInPlaceHolders(String input, Map<String, Optional<Object>> variables) {
|
||||
try (StringReader reader = new StringReader(input)) {
|
||||
CharStream s = CharStreams.fromReader(reader);
|
||||
PostProcessingLexer lexer = new PostProcessingLexer(s);
|
||||
CommonTokenStream tokens = new CommonTokenStream(lexer);
|
||||
PostProcessingParser parser = new PostProcessingParser(tokens);
|
||||
parser.addErrorListener(new AntlrSyntacErrorAdapter() {
|
||||
@Override
|
||||
public void syntaxError(Recognizer<?, ?> recognizer, Object o, int line, int pos, String s, RecognitionException e) {
|
||||
log.warn("Syntax error at {}:{} {}", line, pos, s);
|
||||
}
|
||||
});
|
||||
Optional.ofNullable(errorListener).ifPresent(parser::addErrorListener);
|
||||
PostProcessingParser.LineContext ctx = parser.line();
|
||||
ParserVisitor visitor = new ParserVisitor(variables);
|
||||
return visitor.visit(ctx);
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
package ctbrec.variableexpansion;
|
||||
|
||||
import ctbrec.Config;
|
||||
import ctbrec.variableexpansion.functions.AntlrSyntacErrorAdapter;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class ConfigVariableExpander extends AbstractVariableExpander {
|
||||
|
||||
public ConfigVariableExpander(Config config, AntlrSyntacErrorAdapter errorListener) {
|
||||
super(errorListener);
|
||||
placeholderValueSuppliers.put("recordingsDir", Optional.of(config.getSettings().recordingsDir));
|
||||
}
|
||||
|
||||
public String expand(String input) {
|
||||
return fillInPlaceHolders(input, placeholderValueSuppliers);
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@ import ctbrec.ModelGroup;
|
|||
import ctbrec.StringUtil;
|
||||
import ctbrec.recorder.Recorder;
|
||||
import ctbrec.sites.Site;
|
||||
import ctbrec.variableexpansion.functions.AntlrSyntacErrorAdapter;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
@ -14,7 +15,8 @@ import static java.util.Optional.ofNullable;
|
|||
|
||||
public class ModelVariableExpander extends AbstractVariableExpander {
|
||||
|
||||
public ModelVariableExpander(Model model, Config config, Recorder recorder) {
|
||||
public ModelVariableExpander(Model model, Config config, Recorder recorder, AntlrSyntacErrorAdapter errorListener) {
|
||||
super(errorListener);
|
||||
Optional<ModelGroup> modelGroup = Optional.ofNullable(recorder).flatMap(r -> r.getModelGroup(model));
|
||||
placeholderValueSuppliers.put("modelName", ofNullable(model.getName()));
|
||||
placeholderValueSuppliers.put("modelDisplayName", ofNullable(model.getDisplayName()));
|
||||
|
|
|
@ -30,8 +30,8 @@ public class ParserVisitor extends PostProcessingBaseVisitor<String> {
|
|||
String identifier = ctx.identifier().getText();
|
||||
VarArgsFunction<Object, String> function = functions.get(identifier);
|
||||
if (function != null) {
|
||||
List<PostProcessingParser.ExpressionContext> parameters = ctx.expression();
|
||||
List<String> params = parameters.stream().map(this::visitExpression).toList();
|
||||
List<PostProcessingParser.ParameterContext> parameters = ctx.parameter();
|
||||
List<String> params = parameters.stream().map(this::visitParameter).toList();
|
||||
return function.apply(params.toArray(new Object[0]));
|
||||
} else {
|
||||
return ctx.getText();
|
||||
|
@ -45,7 +45,7 @@ public class ParserVisitor extends PostProcessingBaseVisitor<String> {
|
|||
if (value != null && value.isPresent()) { // NOSONAR
|
||||
return value.get().toString();
|
||||
} else {
|
||||
return "";
|
||||
return ctx.getText();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
package ctbrec.variableexpansion;
|
||||
|
||||
import ctbrec.Recording;
|
||||
import ctbrec.StringUtil;
|
||||
import ctbrec.variableexpansion.functions.AntlrSyntacErrorAdapter;
|
||||
|
||||
import java.io.File;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.Optional;
|
||||
|
||||
import static java.util.Optional.ofNullable;
|
||||
|
||||
public class RecordingVariableExpander extends AbstractVariableExpander {
|
||||
|
||||
public RecordingVariableExpander(Recording rec, AntlrSyntacErrorAdapter errorListener) {
|
||||
super(errorListener);
|
||||
placeholderValueSuppliers.put("recordingNotes", getSanitizedRecordingNotes(rec));
|
||||
placeholderValueSuppliers.put("fileSuffix", getFileSuffix(rec));
|
||||
placeholderValueSuppliers.put("absolutePath", Optional.of(rec).map(Recording::getPostProcessedFile).map(File::getAbsolutePath));
|
||||
placeholderValueSuppliers.put("absoluteParentPath", Optional.of(rec).map(Recording::getPostProcessedFile).map(File::getParentFile).map(File::getAbsolutePath));
|
||||
placeholderValueSuppliers.put("epochSecond", ofNullable(rec.getStartDate()).map(Instant::getEpochSecond).map(l -> Long.toString(l))); // NOSONAR
|
||||
placeholderValueSuppliers.put("utcDateTime", getUtcDateTime(rec));
|
||||
placeholderValueSuppliers.put("localDateTime", getLocalDateTime(rec));
|
||||
}
|
||||
|
||||
public String expand(String input) {
|
||||
return fillInPlaceHolders(input, placeholderValueSuppliers);
|
||||
}
|
||||
|
||||
protected Optional<Object> getUtcDateTime(Recording rec) {
|
||||
return Optional.ofNullable(rec)
|
||||
.map(Recording::getStartDate)
|
||||
.map(i -> i.atZone(ZoneOffset.UTC));
|
||||
}
|
||||
|
||||
protected Optional<Object> getLocalDateTime(Recording rec) {
|
||||
return Optional.ofNullable(rec)
|
||||
.map(Recording::getStartDate)
|
||||
.map(i -> i.atZone(ZoneId.systemDefault()));
|
||||
}
|
||||
|
||||
private Optional<Object> getFileSuffix(Recording rec) {
|
||||
if (rec.isSingleFile()) {
|
||||
String filename = rec.getPostProcessedFile().getName();
|
||||
return Optional.of(filename.substring(filename.lastIndexOf('.') + 1));
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
private Optional<Object> getSanitizedRecordingNotes(Recording rec) {
|
||||
Optional<String> notes = ofNullable(rec.getNote());
|
||||
return notes.map(StringUtil::sanitize);
|
||||
}
|
||||
|
||||
}
|
|
@ -4,8 +4,13 @@ import ctbrec.StringUtil;
|
|||
import ctbrec.variableexpansion.VarArgsFunction;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class OrElse implements VarArgsFunction<Object, String> {
|
||||
|
||||
private static final Pattern VARIABLE_PATTERN = Pattern.compile("\\$\\{[^${}]+}");
|
||||
|
||||
@Override
|
||||
public String apply(Object... params) {
|
||||
if (params == null || params.length < 1) {
|
||||
|
@ -18,7 +23,13 @@ public class OrElse implements VarArgsFunction<Object, String> {
|
|||
|
||||
Optional<String> result = Optional.ofNullable(params[0]).map(String::valueOf);
|
||||
if (result.isPresent() && StringUtil.isNotBlank(result.get())) {
|
||||
return result.get();
|
||||
String param = result.get();
|
||||
Matcher m = VARIABLE_PATTERN.matcher(param);
|
||||
if (m.find()) {
|
||||
return fallback;
|
||||
} else {
|
||||
return result.get();
|
||||
}
|
||||
} else {
|
||||
return fallback;
|
||||
}
|
||||
|
|
|
@ -49,9 +49,9 @@ class AbstractPlaceholderAwarePostProcessorTest extends AbstractPpTest {
|
|||
@Test
|
||||
void testSiteNameReplacement() {
|
||||
String input = "asdf_${siteName}_asdf";
|
||||
assertEquals("asdf_Chaturbate_asdf", placeHolderAwarePp.fillInPlaceHolders(input, createPostProcessingContext(rec, null, config)));
|
||||
assertEquals("asdf_Stripchat_asdf", placeHolderAwarePp.fillInPlaceHolders(input, createPostProcessingContext(rec, null, config)));
|
||||
input = "asdf_$sanitize(${siteName})_asdf";
|
||||
assertEquals("asdf_Chaturbate_asdf", placeHolderAwarePp.fillInPlaceHolders(input, createPostProcessingContext(rec, null, config)));
|
||||
assertEquals("asdf_Stripchat_asdf", placeHolderAwarePp.fillInPlaceHolders(input, createPostProcessingContext(rec, null, config)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -158,7 +158,7 @@ class AbstractPlaceholderAwarePostProcessorTest extends AbstractPpTest {
|
|||
void testMissingValueForPlaceholder() {
|
||||
String input = "asdf_${modelNotes}_asdf";
|
||||
when(config.getModelNotes(any())).thenReturn(null);
|
||||
assertEquals("asdf__asdf", placeHolderAwarePp.fillInPlaceHolders(input, createPostProcessingContext(rec, null, config)));
|
||||
assertEquals("asdf_${modelNotes}_asdf", placeHolderAwarePp.fillInPlaceHolders(input, createPostProcessingContext(rec, null, config)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -7,7 +7,7 @@ import ctbrec.Settings;
|
|||
import ctbrec.recorder.Recorder;
|
||||
import ctbrec.recorder.RecordingManager;
|
||||
import ctbrec.sites.Site;
|
||||
import ctbrec.sites.chaturbate.Chaturbate;
|
||||
import ctbrec.sites.stripchat.Stripchat;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
@ -71,7 +71,7 @@ public abstract class AbstractPpTest {
|
|||
}
|
||||
|
||||
Model mockModel() {
|
||||
Site site = new Chaturbate();
|
||||
Site site = new Stripchat();
|
||||
Model model = site.createModel("Mockita Boobilicious");
|
||||
model.setDisplayName("Mockita Boobilicious");
|
||||
return model;
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
package ctbrec.variableexpansion;
|
||||
|
||||
import ctbrec.Config;
|
||||
import ctbrec.Model;
|
||||
import ctbrec.Settings;
|
||||
import ctbrec.UnknownModel;
|
||||
import ctbrec.recorder.Recorder;
|
||||
import ctbrec.sites.chaturbate.Chaturbate;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.MockedStatic;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
class ModelVariableExpanderTest {
|
||||
|
||||
Model model;
|
||||
Config config;
|
||||
MockedStatic<Config> configStatic;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
UnknownModel unknownModel = new UnknownModel();
|
||||
Chaturbate chaturbate = new Chaturbate();
|
||||
unknownModel.setName("Pussy_Galore");
|
||||
unknownModel.setDisplayName("Pussy Galore");
|
||||
unknownModel.setSite(chaturbate);
|
||||
this.model = unknownModel;
|
||||
this.config = mockConfig();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void teardown() {
|
||||
if (configStatic != null) {
|
||||
configStatic.close();
|
||||
configStatic = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMultipleVariablesAsParameter() {
|
||||
Recorder recorder = mock(Recorder.class);
|
||||
ModelVariableExpander modelVariableExpander = new ModelVariableExpander(model, config, recorder, null);
|
||||
assertEquals("pussy_galore asdf pussy_galore", modelVariableExpander.expand("$lower(${modelName} ASDF ${modelName})"));
|
||||
}
|
||||
|
||||
Config mockConfig() {
|
||||
Config config = mock(Config.class);
|
||||
Settings settings = mockSettings();
|
||||
when(config.getSettings()).thenReturn(settings);
|
||||
when(config.getModelNotes(any())).thenReturn("tag, foo, bar");
|
||||
configStatic = mockStatic(Config.class);
|
||||
configStatic.when(Config::getInstance).thenReturn(config);
|
||||
return config;
|
||||
}
|
||||
|
||||
Settings mockSettings() {
|
||||
Settings settings = new Settings();
|
||||
settings.recordingsDir = "/tmp/rec";
|
||||
return settings;
|
||||
}
|
||||
}
|
|
@ -24,6 +24,6 @@ class OrElseTest {
|
|||
|
||||
@Test
|
||||
void testFallback() {
|
||||
assertEquals("hello", orElse.apply("", "hello"));
|
||||
assertEquals("hello", orElse.apply("asdf ${variable} asdf", "hello"));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue