diff --git a/client/src/main/java/ctbrec/ui/Player.java b/client/src/main/java/ctbrec/ui/Player.java index c65d622b..371a1f76 100644 --- a/client/src/main/java/ctbrec/ui/Player.java +++ b/client/src/main/java/ctbrec/ui/Player.java @@ -170,7 +170,7 @@ public class Player { StreamSource best; int maxRes = Config.getInstance().getSettings().maximumResolutionPlayer; if (maxRes > 0 && !sources.isEmpty()) { - for (Iterator iterator = sources.iterator(); iterator.hasNext();) { + for (Iterator 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); diff --git a/client/src/main/java/ctbrec/ui/action/OpenRecordingsDir.java b/client/src/main/java/ctbrec/ui/action/OpenRecordingsDir.java index c4186dd9..6bdb03d8 100644 --- a/client/src/main/java/ctbrec/ui/action/OpenRecordingsDir.java +++ b/client/src/main/java/ctbrec/ui/action/OpenRecordingsDir.java @@ -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; } diff --git a/client/src/main/java/ctbrec/ui/settings/SettingsTab.java b/client/src/main/java/ctbrec/ui/settings/SettingsTab.java index 39ca8e2d..4957abab 100644 --- a/client/src/main/java/ctbrec/ui/settings/SettingsTab.java +++ b/client/src/main/java/ctbrec/ui/settings/SettingsTab.java @@ -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 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) { diff --git a/client/src/main/java/ctbrec/ui/settings/VariablePlayGroundDialogFactory.java b/client/src/main/java/ctbrec/ui/settings/VariablePlayGroundDialogFactory.java index 25a00b49..965c745e 100644 --- a/client/src/main/java/ctbrec/ui/settings/VariablePlayGroundDialogFactory.java +++ b/client/src/main/java/ctbrec/ui/settings/VariablePlayGroundDialogFactory.java @@ -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); + } }); } } diff --git a/common/src/main/antlr4/ctbrec/variableexpansion/antlr/PostProcessing.g4 b/common/src/main/antlr4/ctbrec/variableexpansion/antlr/PostProcessing.g4 index ca25c780..80abce5e 100644 --- a/common/src/main/antlr4/ctbrec/variableexpansion/antlr/PostProcessing.g4 +++ b/common/src/main/antlr4/ctbrec/variableexpansion/antlr/PostProcessing.g4 @@ -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 diff --git a/common/src/main/java/ctbrec/Config.java b/common/src/main/java/ctbrec/Config.java index a59a3682..9ceb8726 100644 --- a/common/src/main/java/ctbrec/Config.java +++ b/common/src/main/java/ctbrec/Config.java @@ -183,9 +183,8 @@ public class Config { } private void migrateOldSettings() { - // 4.7.18 + // 5.0.0 convertChaturbateModelNamesToLowerCase(); - } private void convertChaturbateModelNamesToLowerCase() { diff --git a/common/src/main/java/ctbrec/recorder/postprocessing/AbstractPlaceholderAwarePostProcessor.java b/common/src/main/java/ctbrec/recorder/postprocessing/AbstractPlaceholderAwarePostProcessor.java index b96425ba..18b1edcc 100644 --- a/common/src/main/java/ctbrec/recorder/postprocessing/AbstractPlaceholderAwarePostProcessor.java +++ b/common/src/main/java/ctbrec/recorder/postprocessing/AbstractPlaceholderAwarePostProcessor.java @@ -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> 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> 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 getUtcDateTime(Recording rec) { - return Optional.ofNullable(rec) - .map(Recording::getStartDate) - .map(i -> i.atZone(ZoneOffset.UTC)); - } - - protected Optional getLocalDateTime(Recording rec) { - return Optional.ofNullable(rec) - .map(Recording::getStartDate) - .map(i -> i.atZone(ZoneId.systemDefault())); - } - - private Optional 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 getSanitizedRecordingNotes(Recording rec) { - Optional 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); } } diff --git a/common/src/main/java/ctbrec/variableexpansion/AbstractVariableExpander.java b/common/src/main/java/ctbrec/variableexpansion/AbstractVariableExpander.java index 169dfd55..ce384574 100644 --- a/common/src/main/java/ctbrec/variableexpansion/AbstractVariableExpander.java +++ b/common/src/main/java/ctbrec/variableexpansion/AbstractVariableExpander.java @@ -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> placeholderValueSuppliers = new HashMap<>(); + protected AntlrSyntacErrorAdapter errorListener; + + AbstractVariableExpander(@Nullable AntlrSyntacErrorAdapter errorListener) { + this.errorListener = errorListener; + } + protected String fillInPlaceHolders(String input, Map> 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); diff --git a/common/src/main/java/ctbrec/variableexpansion/ConfigVariableExpander.java b/common/src/main/java/ctbrec/variableexpansion/ConfigVariableExpander.java new file mode 100644 index 00000000..568d92dd --- /dev/null +++ b/common/src/main/java/ctbrec/variableexpansion/ConfigVariableExpander.java @@ -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); + } +} diff --git a/common/src/main/java/ctbrec/variableexpansion/ModelVariableExpander.java b/common/src/main/java/ctbrec/variableexpansion/ModelVariableExpander.java index 323d059b..0165ed46 100644 --- a/common/src/main/java/ctbrec/variableexpansion/ModelVariableExpander.java +++ b/common/src/main/java/ctbrec/variableexpansion/ModelVariableExpander.java @@ -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 = Optional.ofNullable(recorder).flatMap(r -> r.getModelGroup(model)); placeholderValueSuppliers.put("modelName", ofNullable(model.getName())); placeholderValueSuppliers.put("modelDisplayName", ofNullable(model.getDisplayName())); diff --git a/common/src/main/java/ctbrec/variableexpansion/ParserVisitor.java b/common/src/main/java/ctbrec/variableexpansion/ParserVisitor.java index b77eed7a..4863a6d2 100644 --- a/common/src/main/java/ctbrec/variableexpansion/ParserVisitor.java +++ b/common/src/main/java/ctbrec/variableexpansion/ParserVisitor.java @@ -30,8 +30,8 @@ public class ParserVisitor extends PostProcessingBaseVisitor { String identifier = ctx.identifier().getText(); VarArgsFunction function = functions.get(identifier); if (function != null) { - List parameters = ctx.expression(); - List params = parameters.stream().map(this::visitExpression).toList(); + List parameters = ctx.parameter(); + List 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 { if (value != null && value.isPresent()) { // NOSONAR return value.get().toString(); } else { - return ""; + return ctx.getText(); } } diff --git a/common/src/main/java/ctbrec/variableexpansion/RecordingVariableExpander.java b/common/src/main/java/ctbrec/variableexpansion/RecordingVariableExpander.java new file mode 100644 index 00000000..2f6066fc --- /dev/null +++ b/common/src/main/java/ctbrec/variableexpansion/RecordingVariableExpander.java @@ -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 getUtcDateTime(Recording rec) { + return Optional.ofNullable(rec) + .map(Recording::getStartDate) + .map(i -> i.atZone(ZoneOffset.UTC)); + } + + protected Optional getLocalDateTime(Recording rec) { + return Optional.ofNullable(rec) + .map(Recording::getStartDate) + .map(i -> i.atZone(ZoneId.systemDefault())); + } + + private Optional 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 getSanitizedRecordingNotes(Recording rec) { + Optional notes = ofNullable(rec.getNote()); + return notes.map(StringUtil::sanitize); + } + +} diff --git a/common/src/main/java/ctbrec/variableexpansion/functions/OrElse.java b/common/src/main/java/ctbrec/variableexpansion/functions/OrElse.java index eb76cd20..4d079a37 100644 --- a/common/src/main/java/ctbrec/variableexpansion/functions/OrElse.java +++ b/common/src/main/java/ctbrec/variableexpansion/functions/OrElse.java @@ -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 { + + 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 { Optional 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; } diff --git a/common/src/test/java/ctbrec/recorder/postprocessing/AbstractPlaceholderAwarePostProcessorTest.java b/common/src/test/java/ctbrec/recorder/postprocessing/AbstractPlaceholderAwarePostProcessorTest.java index 251f82e9..c442c9e1 100644 --- a/common/src/test/java/ctbrec/recorder/postprocessing/AbstractPlaceholderAwarePostProcessorTest.java +++ b/common/src/test/java/ctbrec/recorder/postprocessing/AbstractPlaceholderAwarePostProcessorTest.java @@ -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 diff --git a/common/src/test/java/ctbrec/recorder/postprocessing/AbstractPpTest.java b/common/src/test/java/ctbrec/recorder/postprocessing/AbstractPpTest.java index 36bc9462..7b858f5f 100644 --- a/common/src/test/java/ctbrec/recorder/postprocessing/AbstractPpTest.java +++ b/common/src/test/java/ctbrec/recorder/postprocessing/AbstractPpTest.java @@ -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; diff --git a/common/src/test/java/ctbrec/variableexpansion/ModelVariableExpanderTest.java b/common/src/test/java/ctbrec/variableexpansion/ModelVariableExpanderTest.java new file mode 100644 index 00000000..cd10276c --- /dev/null +++ b/common/src/test/java/ctbrec/variableexpansion/ModelVariableExpanderTest.java @@ -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 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; + } +} diff --git a/common/src/test/java/ctbrec/variableexpansion/functions/OrElseTest.java b/common/src/test/java/ctbrec/variableexpansion/functions/OrElseTest.java index b6852133..4ea48502 100644 --- a/common/src/test/java/ctbrec/variableexpansion/functions/OrElseTest.java +++ b/common/src/test/java/ctbrec/variableexpansion/functions/OrElseTest.java @@ -24,6 +24,6 @@ class OrElseTest { @Test void testFallback() { - assertEquals("hello", orElse.apply("", "hello")); + assertEquals("hello", orElse.apply("asdf ${variable} asdf", "hello")); } }