Add playground dialog for post-processing variables/functions and update the documentation
This commit is contained in:
parent
e63107cd93
commit
f2df8deb0c
|
@ -278,7 +278,8 @@ public class SettingsTab extends Tab implements TabSelectionListener {
|
|||
Group.of("Post-Processing",
|
||||
Setting.of("Threads", postProcessingThreads),
|
||||
Setting.of("Steps", postProcessingStepPanel),
|
||||
Setting.of("", createHelpButton("Post-Processing Help", "http://localhost:5689/docs/PostProcessing.md")))),
|
||||
Setting.of("", createHelpButton("Post-Processing Help", "http://localhost:5689/docs/PostProcessing.md")),
|
||||
Setting.of("", createVariablePlayGroundButton()))),
|
||||
Category.of("Events & Actions", new ActionSettingsPanel(recorder)), Category.of("Ignore List", ignoreList),
|
||||
Category.of("Sites", siteCategories.toArray(new Category[0])),
|
||||
Category.of("Proxy",
|
||||
|
@ -377,6 +378,12 @@ public class SettingsTab extends Tab implements TabSelectionListener {
|
|||
return postProcessingHelpButton;
|
||||
}
|
||||
|
||||
private Button createVariablePlayGroundButton() {
|
||||
var postProcessingHelpButton = new Button("Variable Playground");
|
||||
postProcessingHelpButton.setOnAction(e -> new VariablePlayGroundDialogFactory().openDialog(this.getTabPane().getScene(), config, recorder));
|
||||
return postProcessingHelpButton;
|
||||
}
|
||||
|
||||
private void bindEnabledProperty(Setting s, BooleanExpression bindTo) {
|
||||
try {
|
||||
s.getGui().disableProperty().bind(bindTo);
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
package ctbrec.ui.settings;
|
||||
|
||||
import ctbrec.Config;
|
||||
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.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 org.antlr.v4.runtime.RecognitionException;
|
||||
import org.antlr.v4.runtime.Recognizer;
|
||||
|
||||
import java.nio.file.Paths;
|
||||
import java.time.Instant;
|
||||
|
||||
public class VariablePlayGroundDialogFactory {
|
||||
public void openDialog(Scene parent, Config config, Recorder recorder) {
|
||||
Chaturbate chaturbate = new Chaturbate();
|
||||
UnknownModel unknownModel = new UnknownModel();
|
||||
unknownModel.setName("Pussy_Galore");
|
||||
unknownModel.setDisplayName("Pussy Galore");
|
||||
unknownModel.setSite(chaturbate);
|
||||
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();
|
||||
Label result = new Label();
|
||||
Label error = new Label();
|
||||
|
||||
pane.add(new Label("Expression"), 0, 0);
|
||||
TextField input = new TextField();
|
||||
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);
|
||||
|
||||
pane.add(result, 0, 2);
|
||||
GridPane.setColumnSpan(result, 2);
|
||||
|
||||
pane.setHgap(5);
|
||||
pane.vgapProperty().bind(pane.hgapProperty());
|
||||
Dialogs.showCustomInput(parent, "Playground", pane, (obs, oldV, newV) -> {
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,8 +1,10 @@
|
|||
#### Post-Processing
|
||||
|
||||
The post-processing gives you the possibility to execute different actions after a recording has finished. You can use that to convert
|
||||
the files to another format, create preview images, rename / move the file etc.
|
||||
|
||||
##### Available Steps
|
||||
|
||||
- **create a copy** - Creates a copy of the original recording. All following post-processing steps are executed on the copy, not on the
|
||||
original recording. This means, that the post-processing can be rerun in case a step failed, because the original recording is still
|
||||
available.
|
||||
|
@ -21,17 +23,20 @@ the files to another format, create preview images, rename / move the file etc.
|
|||
- **create contactsheet** - create a contact sheet with preview images of the recording
|
||||
|
||||
#### Planned for future releases
|
||||
|
||||
- **call a webhook** - call a URL once a recording is finished
|
||||
- **create timeline thumbnails** - create a small thumbnail for every second or every few seconds, which can be used to very fast
|
||||
scan through a recording
|
||||
|
||||
#### How to configure the server to do post-processing
|
||||
|
||||
There is currently no user interface to configure the post-processing for the server. It has to be added manually to the server config.
|
||||
I suggest to start the app and configure the post-processing steps in the settings. Afterwards you close the app and copy the
|
||||
post-processing section from the settings.json to your server.json file. To find out, where these files are on your system, read
|
||||
[Configuration File](ConfigurationFile.md).
|
||||
|
||||
The part you have to copy is
|
||||
|
||||
```
|
||||
postProcessors: [
|
||||
...
|
||||
|
@ -43,16 +48,13 @@ The part you have to copy is
|
|||
<a id="variables" />
|
||||
|
||||
###### Available variables:
|
||||
|
||||
- **${modelName}** - the name of the recorded model
|
||||
- **${modelDisplayName}** - the name of the recorded model, which is shown on the webpage. Might be the same as
|
||||
- **${modelDisplayName}** - the name of the recorded model, which is shown on the webpage. Might be the same as
|
||||
${modelName}
|
||||
- **${modelSanitizedName}** - sanitized name of the model. The following characters are replaced by an underscore:
|
||||
\\, /, ', " and space
|
||||
- **${modelGroupName}** - name of the model group, if the model is part of a group
|
||||
- **${modelGroupId}** - the unique ID of the model group, if the model is part of a group
|
||||
- **${siteName}** - the name of the cam site, the model streams on
|
||||
- **${siteSanitizedName}** - sanitized name of the site. The following characters are replaced by an underscore:
|
||||
\\, /, ', " and space
|
||||
- **${fileSuffix}** - the file extension of the recording. E.g. ts or mp4. In case of a standard server recording,
|
||||
this will be empty
|
||||
- **${epochSecond}** - timestamp of the recording in seconds since 1970-01-01 (unixtime)
|
||||
|
@ -60,16 +62,31 @@ The part you have to copy is
|
|||
\\, /, ', " and space
|
||||
- **${recordingNotes}** - sanitized recording notes. The following characters are replaced by an underscore:
|
||||
\\, /, ', " and space. Useful for the download of recordings from the server.
|
||||
- **${recordingsDir}** - the base directory of all recordings. Same as Recordings Directory in the Recorder settings
|
||||
- **${recordingsDir}** - the base directory of all recordings. Same as Recordings Directory in the Recorder settings
|
||||
section.
|
||||
- **${absolutePath}** - the absolute path in the filesystem to the recording file (or the recording directory in case of
|
||||
a server recording)
|
||||
- **${absoluteParentPath}** - the absolute path to the parent directory of the recording in the filesystem (or the
|
||||
- **${absoluteParentPath}** - the absolute path to the parent directory of the recording in the filesystem (or the
|
||||
recording dir in case of a server recording)
|
||||
- **${utcDateTime}** and **${localDateTime}** - the timestamp of the recording in the UTC or your local timezone. If no
|
||||
pattern is given, the default ```yyyy-MM-dd_HH-mm-ss``` is used. You can also define your own pattern using the following
|
||||
symbols. For example ```${localDateTime(yyyyMMdd-HHmmss)}``` would lead to 20200928-173605.
|
||||
- **${utcDateTime}** and **${localDateTime}** - the timestamp of the recording in the UTC or your local timezone
|
||||
|
||||
#### Functions
|
||||
|
||||
- **$trim** - removes all leading and trailing space - `$trim( hello world )` becomes `hello world`
|
||||
- **$upper** - converts all of the characters to upper case - `$upper(hello world)` becomes `HELLO WORLD`
|
||||
- **$lower** - converts all of the characters to lower case - `$lower(hElLo WORLD)` becomes `hello world`
|
||||
- **$capitalize** - capitalizes words changing the first character to upper case - `$capitalize(hElLo WorLD)` becomes `HElLo WorLD`
|
||||
- **$sanitize** - removes problematic characters - `$sanitize(hEl'Lo / WO"RLD)` becomes `hEl_Lo___WO_RLD`. The following characters are replaced by an
|
||||
underscore:
|
||||
\\, /, ', " and space
|
||||
- **$orElse** - provide an alternative in case a variable is not set - `$orElse(${variable},someValue)` - becomes `${variable}`, if it is set or `someValue`, if
|
||||
`${variable}` is not set
|
||||
- **$format** - formats a date, can be used with a pattern or without.
|
||||
Examples:
|
||||
- `$format(${localDateTime})` - becomes something like `2023-02-26_12-23-15`
|
||||
- `$format(${localDateTime},yyyyMMdd-HHmmss)` would lead to `20200928-173605`
|
||||
<table class="table-striped">
|
||||
|
||||
<thead>
|
||||
<tr><th scope="col">Symbol</th> <th scope="col">Meaning</th> <th scope="col">Presentation</th> <th scope="col">Examples</th>
|
||||
</tr></thead>
|
||||
|
@ -118,16 +135,10 @@ The part you have to copy is
|
|||
</tr></tbody>
|
||||
</table>
|
||||
|
||||
|
||||
For more information see: [DateTimeFormatter](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/time/format/DateTimeFormatter.html)
|
||||
###### Fallback values:
|
||||
You can define a fallback value for each variable in case there is no value available for the variable. The syntax is
|
||||
|
||||
${placeholder?foobar}
|
||||
|
||||
Let's for example say you have created some model groups. For models, which are part of a group, you want to use the group name. But for models, which
|
||||
are not part of a group you want to use the sanitized name. You can achieve that by using the following expression:
|
||||
For more information see: [DateTimeFormatter](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/time/format/DateTimeFormatter.html)
|
||||
|
||||
${modelGroupName?${modelSanitizedName}}
|
||||
#### Full Example
|
||||
|
||||
It can be read like "use the modelGroupName, but if that is not available use modelSanitizedName".
|
||||
`$orElse(${modelGroupName},$sanitize(${modelName}))_$format(${localDateTime})_${recordingNotes}`
|
||||
|
|
|
@ -66,7 +66,7 @@ public class Settings {
|
|||
public int defaultPriority = 50;
|
||||
public boolean determineResolution = false;
|
||||
public List<String> disabledSites = new ArrayList<>();
|
||||
public String downloadFilename = "${modelSanitizedName}-$format(${localDateTime})";
|
||||
public String downloadFilename = "$sanitize(${modelName})_$format(${localDateTime})";
|
||||
public List<EventHandlerConfiguration> eventHandlers = new ArrayList<>();
|
||||
public boolean eventsSuspended = false;
|
||||
public boolean fastScrollSpeed = true;
|
||||
|
|
|
@ -10,7 +10,9 @@ 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 org.antlr.v4.runtime.tree.ParseTree;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -28,6 +30,10 @@ import static java.util.Optional.ofNullable;
|
|||
public abstract class AbstractPlaceholderAwarePostProcessor extends AbstractPostProcessor {
|
||||
|
||||
public String fillInPlaceHolders(String input, PostProcessingContext ctx) {
|
||||
return this.fillInPlaceHolders(input, ctx, null);
|
||||
}
|
||||
|
||||
public String fillInPlaceHolders(String input, PostProcessingContext ctx, AntlrSyntacErrorAdapter errorListener) {
|
||||
Recording rec = ctx.getRecording();
|
||||
Config config = ctx.getConfig();
|
||||
|
||||
|
@ -42,21 +48,16 @@ public abstract class AbstractPlaceholderAwarePostProcessor extends AbstractPost
|
|||
variables.put("utcDateTime", getUtcDateTime(rec));
|
||||
variables.put("localDateTime", getLocalDateTime(rec));
|
||||
|
||||
return fillInPlaceHolders(input, variables);
|
||||
return fillInPlaceHolders(input, variables, errorListener);
|
||||
}
|
||||
|
||||
private String fillInPlaceHolders(String input, Map<String, Optional<Object>> variables) {
|
||||
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);
|
||||
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);
|
||||
ParseTree parseTree = parser.line();
|
||||
ParserVisitor visitor = new ParserVisitor(variables);
|
||||
return visitor.visit(parseTree);
|
||||
|
|
|
@ -16,7 +16,7 @@ public class Move extends AbstractPlaceholderAwarePostProcessor {
|
|||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(Move.class);
|
||||
public static final String PATH_TEMPLATE = "path.template";
|
||||
public static final String DEFAULT = "${modelSanitizedName}" + File.separatorChar + "$format(${localDateTime})";
|
||||
public static final String DEFAULT = "$sanitize(${modelName})" + File.separatorChar + "$format(${localDateTime})";
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
|
|
|
@ -13,8 +13,8 @@ public class Rename extends AbstractPlaceholderAwarePostProcessor {
|
|||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(Rename.class);
|
||||
public static final String FILE_NAME_TEMPLATE = "filename.template";
|
||||
public static final String DEFAULT = "${modelSanitizedName}_$format(${localDateTime}).${fileSuffix}";
|
||||
public static final String DEFAULT_DIR = "${modelSanitizedName}_$format(${localDateTime})";
|
||||
public static final String DEFAULT = "$sanitize(${modelName})_$format(${localDateTime}).${fileSuffix}";
|
||||
public static final String DEFAULT_DIR = "$sanitize(${modelName})_$format(${localDateTime})";
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
|
|
|
@ -18,10 +18,8 @@ public class ModelVariableExpander extends AbstractVariableExpander {
|
|||
Optional<ModelGroup> modelGroup = Optional.ofNullable(recorder).flatMap(r -> r.getModelGroup(model));
|
||||
placeholderValueSuppliers.put("modelName", ofNullable(model.getName()));
|
||||
placeholderValueSuppliers.put("modelDisplayName", ofNullable(model.getDisplayName()));
|
||||
placeholderValueSuppliers.put("modelSanitizedName",getSanitizedName(model));
|
||||
placeholderValueSuppliers.put("modelNotes",getSanitizedModelNotes(config, model));
|
||||
placeholderValueSuppliers.put("modelNotes", getSanitizedModelNotes(config, model));
|
||||
placeholderValueSuppliers.put("siteName", ofNullable(model).map(Model::getSite).map(Site::getName));
|
||||
placeholderValueSuppliers.put("siteSanitizedName",getSanitizedSiteName(model));
|
||||
placeholderValueSuppliers.put("modelGroupName", modelGroup.map(ModelGroup::getName));
|
||||
placeholderValueSuppliers.put("modelGroupId", modelGroup.map(ModelGroup::getId).map(UUID::toString));
|
||||
}
|
||||
|
@ -30,19 +28,6 @@ public class ModelVariableExpander extends AbstractVariableExpander {
|
|||
return fillInPlaceHolders(input, placeholderValueSuppliers);
|
||||
}
|
||||
|
||||
private Optional<Object> getSanitizedName(Model model) {
|
||||
String name = model.getSanitizedNamed();
|
||||
if (StringUtil.isBlank(name)) {
|
||||
return Optional.empty();
|
||||
} else {
|
||||
return Optional.of(name);
|
||||
}
|
||||
}
|
||||
|
||||
private Optional<Object> getSanitizedSiteName(Model model) {
|
||||
return ofNullable(model).map(Model::getSite).map(Site::getName).map(StringUtil::sanitize);
|
||||
}
|
||||
|
||||
private Optional<Object> getSanitizedModelNotes(Config config, Model m) {
|
||||
return ofNullable(config.getModelNotes(m)).map(StringUtil::sanitize);
|
||||
}
|
||||
|
|
|
@ -7,7 +7,10 @@ import java.util.Optional;
|
|||
|
||||
public class Capitalize implements VarArgsFunction<Object, String> {
|
||||
@Override
|
||||
public String apply(Object[] params) {
|
||||
public String apply(Object... params) {
|
||||
if (params == null || params.length == 0) {
|
||||
return "";
|
||||
}
|
||||
return Optional.ofNullable(params).map(p -> p[0]).map(String.class::cast).map(StringUtil::capitalize).orElse("");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,23 +9,30 @@ import java.util.Optional;
|
|||
|
||||
public class Format implements VarArgsFunction<Object, String> {
|
||||
@Override
|
||||
public String apply(Object[] params) {
|
||||
public String apply(Object... params) {
|
||||
return Optional.ofNullable(params).map(p -> {
|
||||
String format = "yyyy-MM-dd_HH-mm-ss";
|
||||
if (p.length > 1) {
|
||||
format = (String) p[1];
|
||||
}
|
||||
ZonedDateTime zdt;
|
||||
if (p[0] instanceof String date) {
|
||||
try {
|
||||
zdt = ZonedDateTime.parse(date);
|
||||
} catch (DateTimeParseException e) {
|
||||
try {
|
||||
if (p.length == 0) {
|
||||
return "";
|
||||
}
|
||||
} else {
|
||||
zdt = (ZonedDateTime) p[0];
|
||||
String format = "yyyy-MM-dd_HH-mm-ss";
|
||||
if (p.length > 1) {
|
||||
format = (String) p[1];
|
||||
}
|
||||
ZonedDateTime zdt;
|
||||
if (p != null && p.length > 0 && p[0] instanceof String date) {
|
||||
try {
|
||||
zdt = ZonedDateTime.parse(date);
|
||||
} catch (DateTimeParseException e) {
|
||||
return "";
|
||||
}
|
||||
} else {
|
||||
zdt = (ZonedDateTime) p[0];
|
||||
}
|
||||
return DateTimeFormatter.ofPattern(format).format(zdt);
|
||||
} catch (Exception e) {
|
||||
return "";
|
||||
}
|
||||
return DateTimeFormatter.ofPattern(format).format(zdt);
|
||||
})
|
||||
.orElse("");
|
||||
}
|
||||
|
|
|
@ -6,7 +6,10 @@ import java.util.Optional;
|
|||
|
||||
public class Lower implements VarArgsFunction<Object, String> {
|
||||
@Override
|
||||
public String apply(Object[] params) {
|
||||
public String apply(Object... params) {
|
||||
if (params == null || params.length == 0) {
|
||||
return "";
|
||||
}
|
||||
return Optional.ofNullable(params).map(sa -> sa[0]).map(String.class::cast).map(String::toLowerCase).orElse("");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,15 +8,19 @@ import java.util.Optional;
|
|||
public class OrElse implements VarArgsFunction<Object, String> {
|
||||
@Override
|
||||
public String apply(Object... params) {
|
||||
if (params.length < 2) {
|
||||
throw new IllegalArgumentException("OrElse needs two parameters");
|
||||
if (params == null || params.length < 1) {
|
||||
return "";
|
||||
}
|
||||
String fallback = "";
|
||||
if (params.length >= 2) {
|
||||
fallback = String.valueOf(params[1]);
|
||||
}
|
||||
|
||||
Optional<String> result = Optional.ofNullable(params[0]).map(String::valueOf);
|
||||
if (result.isPresent() && StringUtil.isNotBlank(result.get())) {
|
||||
return result.get();
|
||||
} else {
|
||||
return String.valueOf(params[1]);
|
||||
return fallback;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,10 @@ import java.util.Optional;
|
|||
|
||||
public class Sanitize implements VarArgsFunction<Object, String> {
|
||||
@Override
|
||||
public String apply(Object[] params) {
|
||||
public String apply(Object... params) {
|
||||
if (params == null || params.length == 0) {
|
||||
return "";
|
||||
}
|
||||
return Optional.ofNullable(params).map(p -> p[0]).map(String.class::cast).map(StringUtil::sanitize).orElse("");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,10 @@ import java.util.Optional;
|
|||
|
||||
public class Trim implements VarArgsFunction<Object, String> {
|
||||
@Override
|
||||
public String apply(Object[] params) {
|
||||
public String apply(Object... params) {
|
||||
if (params == null || params.length == 0) {
|
||||
return "";
|
||||
}
|
||||
return Optional.ofNullable(params).map(sa -> sa[0]).map(String.class::cast).map(String::trim).orElse("");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,10 @@ import java.util.Optional;
|
|||
|
||||
public class Upper implements VarArgsFunction<Object, String> {
|
||||
@Override
|
||||
public String apply(Object[] params) {
|
||||
public String apply(Object... params) {
|
||||
if (params == null || params.length == 0) {
|
||||
return "";
|
||||
}
|
||||
return Optional.ofNullable(params).map(sa -> sa[0]).map(String.class::cast).map(String::toUpperCase).orElse("");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ class AbstractPlaceholderAwarePostProcessorTest extends AbstractPpTest {
|
|||
assertEquals("asdf_Mockita Boobilicious_asdf", placeHolderAwarePp.fillInPlaceHolders(input, createPostProcessingContext(rec, null, config)));
|
||||
input = "asdf_${modelDisplayName}_asdf";
|
||||
assertEquals("asdf_Mockita Boobilicious_asdf", placeHolderAwarePp.fillInPlaceHolders(input, createPostProcessingContext(rec, null, config)));
|
||||
input = "asdf_${modelSanitizedName}_asdf";
|
||||
input = "asdf_$sanitize(${modelName})_asdf";
|
||||
assertEquals("asdf_Mockita_Boobilicious_asdf", placeHolderAwarePp.fillInPlaceHolders(input, createPostProcessingContext(rec, null, config)));
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,7 @@ class AbstractPlaceholderAwarePostProcessorTest extends AbstractPpTest {
|
|||
void testSiteNameReplacement() {
|
||||
String input = "asdf_${siteName}_asdf";
|
||||
assertEquals("asdf_Chaturbate_asdf", placeHolderAwarePp.fillInPlaceHolders(input, createPostProcessingContext(rec, null, config)));
|
||||
input = "asdf_${siteSanitizedName}_asdf";
|
||||
input = "asdf_$sanitize(${siteName})_asdf";
|
||||
assertEquals("asdf_Chaturbate_asdf", placeHolderAwarePp.fillInPlaceHolders(input, createPostProcessingContext(rec, null, config)));
|
||||
}
|
||||
|
||||
|
@ -137,7 +137,7 @@ class AbstractPlaceholderAwarePostProcessorTest extends AbstractPpTest {
|
|||
|
||||
@Test
|
||||
void testPlaceholderDefaultValues() {
|
||||
String input = "asdf_$orElse(${modelGroupName},$orElse(${modelSanitizedName},anonymous))_asdf";
|
||||
String input = "asdf_$orElse(${modelGroupName},$orElse($sanitize(${modelName}),anonymous))_asdf";
|
||||
PostProcessingContext ctx = createPostProcessingContext(rec, null, config);
|
||||
ctx.getRecording().getModel().setName(null);
|
||||
assertEquals("asdf_anonymous_asdf", placeHolderAwarePp.fillInPlaceHolders(input, ctx));
|
||||
|
|
|
@ -1,19 +1,18 @@
|
|||
package ctbrec.recorder.postprocessing;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
import ctbrec.Config;
|
||||
import ctbrec.Model;
|
||||
import ctbrec.Recording;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import ctbrec.Config;
|
||||
import ctbrec.Model;
|
||||
import ctbrec.Recording;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
class RenameDirectoryTest extends AbstractPpTest {
|
||||
|
||||
|
@ -29,7 +28,7 @@ class RenameDirectoryTest extends AbstractPpTest {
|
|||
pp.postprocess(createPostProcessingContext(rec, recordingManager, config));
|
||||
|
||||
Matcher m = Pattern.compile("Mockita_Boobilicious_\\d{4}-\\d{2}-\\d{2}_\\d{2}-\\d{2}-\\d{2}").matcher(rec.getAbsoluteFile().getName());
|
||||
assertTrue(m.matches());
|
||||
assertTrue(m.matches(), () -> rec.getAbsoluteFile().getName() + " does not match");
|
||||
assertEquals(rec.getAbsoluteFile(), rec.getPostProcessedFile());
|
||||
assertNotEquals(rec.getAbsoluteFile(), original);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
package ctbrec.variableexpansion.functions;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class CapitalizeTest {
|
||||
Capitalize capitalize = new Capitalize();
|
||||
|
||||
@Test
|
||||
void testNullParams() {
|
||||
assertEquals("", capitalize.apply((Object[]) null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEmptyParams() {
|
||||
assertEquals("", capitalize.apply());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNormalStrings() {
|
||||
assertEquals("Hello World", capitalize.apply("hello world"));
|
||||
assertEquals("HElLo WoRlD", capitalize.apply("hElLo woRlD"));
|
||||
assertEquals("HELLO WORLD", capitalize.apply("HELLO WORLD"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSpecialCharacters() {
|
||||
assertEquals("He{LLo Wo\n$rlD", capitalize.apply("he{LLo wo\n$rlD"));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package ctbrec.variableexpansion.functions;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class FormatTest {
|
||||
|
||||
Format format = new Format();
|
||||
|
||||
@Test
|
||||
void testNullParams() {
|
||||
assertEquals("", format.apply((Object[]) null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEmptyParams() {
|
||||
assertEquals("", format.apply());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testZonedDateTimeParameter() {
|
||||
String expected = "2023-02-26_17-11-23";
|
||||
String zdt = "2023-02-26T17:11:23.363270467+01:00[Europe/Berlin]";
|
||||
assertEquals(expected, format.apply(ZonedDateTime.parse(zdt)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testStringParameter() {
|
||||
String expected = "2023-02-26_17-11-23";
|
||||
String zdt = "2023-02-26T17:11:23.363270467+01:00[Europe/Berlin]";
|
||||
assertEquals(expected, format.apply(zdt));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInvalidStringParameter() {
|
||||
assertEquals("", format.apply("bullshit"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIStringParameterWithPattern() {
|
||||
String expected = "20230226-171123";
|
||||
String zdt = "2023-02-26T17:11:23.363270467+01:00[Europe/Berlin]";
|
||||
assertEquals(expected, format.apply(zdt, "yyyyMMdd-HHmmss"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIStringParameterWithInvalidPattern() {
|
||||
String expected = "";
|
||||
String zdt = "2023-02-26T17:11:23.363270467+01:00[Europe/Berlin]";
|
||||
assertEquals(expected, format.apply(zdt, "asdft"));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package ctbrec.variableexpansion.functions;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class LowerTest {
|
||||
Lower lower = new Lower();
|
||||
|
||||
@Test
|
||||
void testNullParams() {
|
||||
assertEquals("", lower.apply((Object[]) null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEmptyParams() {
|
||||
assertEquals("", lower.apply());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNormalStrings() {
|
||||
assertEquals("hello world", lower.apply("hello world"));
|
||||
assertEquals("hello world", lower.apply("hElLo woRlD"));
|
||||
assertEquals("hello world", lower.apply("HELLO WORLD"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSpecialCharacters() {
|
||||
assertEquals("he{llo\nwo$rld", lower.apply("he{LLo\nwo$rlD"));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package ctbrec.variableexpansion.functions;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class OrElseTest {
|
||||
OrElse orElse = new OrElse();
|
||||
|
||||
@Test
|
||||
void testNullParams() {
|
||||
assertEquals("", orElse.apply((Object[]) null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEmptyParams() {
|
||||
assertEquals("", orElse.apply());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHappyPath() {
|
||||
assertEquals("world", orElse.apply("world", "hello"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFallback() {
|
||||
assertEquals("hello", orElse.apply("", "hello"));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package ctbrec.variableexpansion.functions;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class SanitizeTest {
|
||||
Sanitize sanitize = new Sanitize();
|
||||
|
||||
@Test
|
||||
void testNullParams() {
|
||||
assertEquals("", sanitize.apply((Object[]) null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEmptyParams() {
|
||||
assertEquals("", sanitize.apply());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNormalStrings() {
|
||||
assertEquals("hel!lo", sanitize.apply("hel!lo"));
|
||||
assertEquals("hE$lLo", sanitize.apply("hE$lLo"));
|
||||
assertEquals("HELL%O", sanitize.apply("HELL%O"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSpecialCharacters() {
|
||||
assertEquals("asdf_asdf", sanitize.apply("asdf asdf"));
|
||||
assertEquals("asdf_asdf", sanitize.apply("asdf\"asdf"));
|
||||
assertEquals("asdf_asdf", sanitize.apply("asdf'asdf"));
|
||||
assertEquals("asdf_asdf", sanitize.apply("asdf\\asdf"));
|
||||
assertEquals("asdf_asdf", sanitize.apply("asdf/asdf"));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package ctbrec.variableexpansion.functions;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class TrimTest {
|
||||
Trim trim = new Trim();
|
||||
|
||||
@Test
|
||||
void testNullParams() {
|
||||
assertEquals("", trim.apply((Object[]) null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEmptyParams() {
|
||||
assertEquals("", trim.apply());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNormalStrings() {
|
||||
assertEquals("hello", trim.apply("hello"));
|
||||
assertEquals("hello", trim.apply(" hello "));
|
||||
assertEquals("hello", trim.apply(" hello "));
|
||||
assertEquals("hello", trim.apply("\thello\t"));
|
||||
assertEquals("hello", trim.apply("\nhello\n"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSpecialCharacters() {
|
||||
assertEquals("he{LLo\nwo $rlD", trim.apply("he{LLo\nwo $rlD"));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package ctbrec.variableexpansion.functions;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class UpperTest {
|
||||
Upper upper = new Upper();
|
||||
|
||||
@Test
|
||||
void testNullParams() {
|
||||
assertEquals("", upper.apply((Object[]) null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEmptyParams() {
|
||||
assertEquals("", upper.apply());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNormalStrings() {
|
||||
assertEquals("HELLO WORLD", upper.apply("hello world"));
|
||||
assertEquals("HELLO WORLD", upper.apply("hElLo woRlD"));
|
||||
assertEquals("HELLO WORLD", upper.apply("HELLO WORLD"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSpecialCharacters() {
|
||||
assertEquals("HE{LLO\nWO$RLD", upper.apply("he{LLo\nwo$rlD"));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue