forked from j62/ctbrec
Save model notes on server, when running in client/server mode
This commit is contained in:
parent
63ffe78c36
commit
86e8f00aaf
|
@ -19,6 +19,9 @@ import ctbrec.io.BandwidthMeter;
|
|||
import ctbrec.io.ByteUnitFormatter;
|
||||
import ctbrec.io.HttpClient;
|
||||
import ctbrec.io.HttpException;
|
||||
import ctbrec.notes.LocalModelNotesService;
|
||||
import ctbrec.notes.ModelNotesService;
|
||||
import ctbrec.notes.RemoteModelNotesService;
|
||||
import ctbrec.recorder.NextGenLocalRecorder;
|
||||
import ctbrec.recorder.OnlineMonitor;
|
||||
import ctbrec.recorder.Recorder;
|
||||
|
@ -98,6 +101,7 @@ public class CamrecApplication extends Application {
|
|||
private final List<Site> sites = new ArrayList<>();
|
||||
public static HttpClient httpClient;
|
||||
public static PortraitStore portraitStore;
|
||||
public static ModelNotesService modelNotesService;
|
||||
public static String title;
|
||||
private Stage primaryStage;
|
||||
private RecordingsTab recordingsTab;
|
||||
|
@ -127,6 +131,7 @@ public class CamrecApplication extends Application {
|
|||
initSites();
|
||||
startOnlineMonitor();
|
||||
createPortraitStore();
|
||||
createModelNotesService();
|
||||
createGui(primaryStage);
|
||||
checkForUpdates();
|
||||
registerClipboardListener();
|
||||
|
@ -141,6 +146,14 @@ public class CamrecApplication extends Application {
|
|||
}
|
||||
}
|
||||
|
||||
private void createModelNotesService() {
|
||||
if (config.getSettings().localRecording) {
|
||||
modelNotesService = new LocalModelNotesService(config);
|
||||
} else {
|
||||
modelNotesService = new RemoteModelNotesService(httpClient, config);
|
||||
}
|
||||
}
|
||||
|
||||
private void registerTrayIconListener() {
|
||||
EventBusHolder.BUS.register(new Object() {
|
||||
@Subscribe
|
||||
|
@ -244,7 +257,7 @@ public class CamrecApplication extends Application {
|
|||
|
||||
var modelsTab = new RecordedTab(recorder, sites);
|
||||
tabPane.getTabs().add(modelsTab);
|
||||
recordingsTab = new RecordingsTab("Recordings", recorder, config);
|
||||
recordingsTab = new RecordingsTab("Recordings", recorder, config, modelNotesService);
|
||||
tabPane.getTabs().add(recordingsTab);
|
||||
if (config.getSettings().recentlyWatched) {
|
||||
tabPane.getTabs().add(new RecentlyWatchedTab(recorder, sites));
|
||||
|
|
|
@ -188,7 +188,7 @@ public class Player {
|
|||
}
|
||||
|
||||
private void expandPlaceHolders(String[] cmdline) {
|
||||
ModelVariableExpander expander = new ModelVariableExpander(model, Config.getInstance(), null, null);
|
||||
ModelVariableExpander expander = new ModelVariableExpander(model, CamrecApplication.modelNotesService, null, null);
|
||||
for (int i = 0; i < cmdline.length; i++) {
|
||||
var param = cmdline[i];
|
||||
param = expander.expand(param);
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
package ctbrec.ui.action;
|
||||
|
||||
import ctbrec.Model;
|
||||
import ctbrec.notes.ModelNotesService;
|
||||
import ctbrec.ui.CamrecApplication;
|
||||
import ctbrec.ui.controls.Dialogs;
|
||||
import javafx.scene.Cursor;
|
||||
import javafx.scene.Node;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ctbrec.Config;
|
||||
import ctbrec.Model;
|
||||
import ctbrec.ui.controls.Dialogs;
|
||||
import javafx.scene.Cursor;
|
||||
import javafx.scene.Node;
|
||||
|
||||
public class EditNotesAction {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(EditNotesAction.class);
|
||||
|
||||
private Node source;
|
||||
private Model model;
|
||||
private Runnable callback;
|
||||
private final Node source;
|
||||
private final Model model;
|
||||
private final Runnable callback;
|
||||
|
||||
public EditNotesAction(Node source, Model selectedModel, Runnable callback) {
|
||||
this.source = source;
|
||||
|
@ -27,26 +27,30 @@ public class EditNotesAction {
|
|||
|
||||
public void execute() {
|
||||
source.setCursor(Cursor.WAIT);
|
||||
String notes = Config.getInstance().getSettings().modelNotes.getOrDefault(model.getUrl(), "");
|
||||
Optional<String> newNotes = Dialogs.showTextInput(source.getScene(), "Model Notes", "Notes for " + model.getName(), notes);
|
||||
newNotes.ifPresent(n -> {
|
||||
if (!n.trim().isEmpty()) {
|
||||
Config.getInstance().getSettings().modelNotes.put(model.getUrl(), n);
|
||||
} else {
|
||||
Config.getInstance().getSettings().modelNotes.remove(model.getUrl());
|
||||
}
|
||||
try {
|
||||
Config.getInstance().save();
|
||||
} catch (IOException e) {
|
||||
LOG.warn("Couldn't save config", e);
|
||||
}
|
||||
});
|
||||
if (callback != null) {
|
||||
try {
|
||||
callback.run();
|
||||
} catch (Exception e) {
|
||||
LOG.error("Error while executing callback", e);
|
||||
ModelNotesService notesService = CamrecApplication.modelNotesService;
|
||||
try {
|
||||
String notes = notesService.loadModelNotes(model.getUrl()).orElse("");
|
||||
Optional<String> newNotes = Dialogs.showTextInput(source.getScene(), "Model Notes", "Notes for " + model.getName(), notes);
|
||||
newNotes.ifPresent(n -> {
|
||||
try {
|
||||
if (!n.trim().isEmpty()) {
|
||||
notesService.writeModelNotes(model.getUrl(), n);
|
||||
} else {
|
||||
notesService.removeModelNotes(model.getUrl());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LOG.warn("Couldn't save config", e);
|
||||
}
|
||||
});
|
||||
if (callback != null) {
|
||||
try {
|
||||
callback.run();
|
||||
} catch (Exception e) {
|
||||
LOG.error("Error while executing callback", e);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Dialogs.showError(source.getScene(), "Model Notes", "Could not change model notes", e);
|
||||
}
|
||||
source.setCursor(Cursor.DEFAULT);
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import ctbrec.StringUtil;
|
|||
import ctbrec.UnknownModel;
|
||||
import ctbrec.recorder.Recorder;
|
||||
import ctbrec.sites.chaturbate.Chaturbate;
|
||||
import ctbrec.ui.CamrecApplication;
|
||||
import ctbrec.ui.controls.Dialogs;
|
||||
import ctbrec.variableexpansion.ConfigVariableExpander;
|
||||
import ctbrec.variableexpansion.ModelVariableExpander;
|
||||
|
@ -77,7 +78,7 @@ public class VariablePlayGroundDialogFactory {
|
|||
}
|
||||
};
|
||||
|
||||
ModelVariableExpander modelVariableExpander = new ModelVariableExpander(unknownModel, config, recorder, errorHandler);
|
||||
ModelVariableExpander modelVariableExpander = new ModelVariableExpander(unknownModel, CamrecApplication.modelNotesService, recorder, errorHandler);
|
||||
RecordingVariableExpander recordingVariableExpander = new RecordingVariableExpander(recording, errorHandler);
|
||||
ConfigVariableExpander configVariableExpander = new ConfigVariableExpander(config, errorHandler);
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import ctbrec.Recording.State;
|
|||
import ctbrec.event.EventBusHolder;
|
||||
import ctbrec.event.RecordingStateChangedEvent;
|
||||
import ctbrec.io.UrlUtil;
|
||||
import ctbrec.notes.ModelNotesService;
|
||||
import ctbrec.recorder.ProgressListener;
|
||||
import ctbrec.recorder.Recorder;
|
||||
import ctbrec.recorder.RecordingPinnedException;
|
||||
|
@ -74,6 +75,7 @@ public class RecordingsTab extends Tab implements TabSelectionListener, Shutdown
|
|||
|
||||
private ScheduledService<List<JavaFxRecording>> updateService;
|
||||
private final Config config;
|
||||
private final ModelNotesService modelNotesService;
|
||||
private final Recorder recorder;
|
||||
private long spaceTotal = -1;
|
||||
private long spaceFree = -1;
|
||||
|
@ -89,10 +91,11 @@ public class RecordingsTab extends Tab implements TabSelectionListener, Shutdown
|
|||
Label spaceUsedValue;
|
||||
Lock recordingsLock = new ReentrantLock();
|
||||
|
||||
public RecordingsTab(String title, Recorder recorder, Config config) {
|
||||
public RecordingsTab(String title, Recorder recorder, Config config, ModelNotesService modelNotesService) {
|
||||
super(title);
|
||||
this.recorder = recorder;
|
||||
this.config = config;
|
||||
this.modelNotesService = modelNotesService;
|
||||
createGui();
|
||||
setClosable(false);
|
||||
initializeUpdateService();
|
||||
|
@ -156,7 +159,16 @@ public class RecordingsTab extends Tab implements TabSelectionListener, Shutdown
|
|||
TableColumn<JavaFxRecording, String> modelNotes = new TableColumn<>("Model Notes");
|
||||
modelNotes.setId("modelNotes");
|
||||
modelNotes.setPrefWidth(400);
|
||||
modelNotes.setCellValueFactory(cdf -> new SimpleStringProperty(config.getModelNotes(cdf.getValue().getModel())));
|
||||
modelNotes.setCellValueFactory(cdf -> {
|
||||
String modelNts;
|
||||
try {
|
||||
modelNts = modelNotesService.loadModelNotes(cdf.getValue().getModel().getUrl()).orElse("");
|
||||
} catch (IOException e) {
|
||||
LOG.warn("Could not load model notes", e);
|
||||
modelNts = "";
|
||||
}
|
||||
return new SimpleStringProperty(modelNts);
|
||||
});
|
||||
|
||||
table.getColumns().addAll(name, date, status, progress, size, resolution, notes, modelNotes);
|
||||
table.setItems(observableRecordings);
|
||||
|
@ -261,7 +273,7 @@ public class RecordingsTab extends Tab implements TabSelectionListener, Shutdown
|
|||
Recording recording = table.getSelectionModel().getSelectedItem();
|
||||
if (recording != null) {
|
||||
var state = recording.getStatus();
|
||||
if(state == FINISHED || state == RECORDING) {
|
||||
if (state == FINISHED || state == RECORDING) {
|
||||
play(recording);
|
||||
}
|
||||
}
|
||||
|
@ -448,10 +460,10 @@ public class RecordingsTab extends Tab implements TabSelectionListener, Shutdown
|
|||
|
||||
var tmp = new CustomMouseBehaviorContextMenu();
|
||||
ModelMenuContributor.newContributor(getTabPane(), Config.getInstance(), recorder) //
|
||||
.withStartStopCallback(m -> getTabPane().setCursor(Cursor.DEFAULT)) //
|
||||
.removeModelAfterIgnore(true) //
|
||||
.afterwards(table::refresh) //
|
||||
.contributeToMenu(List.of(recordings.get(0).getModel()), tmp);
|
||||
.withStartStopCallback(m -> getTabPane().setCursor(Cursor.DEFAULT)) //
|
||||
.removeModelAfterIgnore(true) //
|
||||
.afterwards(table::refresh) //
|
||||
.contributeToMenu(List.of(recordings.get(0).getModel()), tmp);
|
||||
var modelSubMenu = new Menu("Model");
|
||||
modelSubMenu.getItems().addAll(tmp.getItems());
|
||||
contextMenu.getItems().add(modelSubMenu);
|
||||
|
|
|
@ -79,7 +79,7 @@ public abstract class AbstractRecordedModelsTab extends Tab implements TabSelect
|
|||
protected StatePersistingTableView<JavaFxModel> table;
|
||||
protected List<TableColumn<JavaFxModel, ?>> columns = new ArrayList<>();
|
||||
protected LoadingCache<Model, Image> portraitCache = CacheBuilder.newBuilder()
|
||||
.expireAfterAccess(1, TimeUnit.DAYS)
|
||||
.expireAfterWrite(10, TimeUnit.MINUTES)
|
||||
.maximumSize(1000)
|
||||
.build(CacheLoader.from(this::loadModelPortrait));
|
||||
|
||||
|
@ -346,7 +346,12 @@ public abstract class AbstractRecordedModelsTab extends Tab implements TabSelect
|
|||
|
||||
@Override
|
||||
public String get() {
|
||||
String modelNotes = Config.getInstance().getModelNotes(m);
|
||||
String modelNotes;
|
||||
try {
|
||||
modelNotes = CamrecApplication.modelNotesService.loadModelNotes(m.getUrl()).orElse("");
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return modelNotes;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -345,9 +345,9 @@ public class Config {
|
|||
}
|
||||
}
|
||||
|
||||
public String getModelNotes(Model m) {
|
||||
return Config.getInstance().getSettings().modelNotes.getOrDefault(m.getUrl(), "");
|
||||
}
|
||||
// public String getModelNotes(Model m) {
|
||||
// return Config.getInstance().getSettings().modelNotes.getOrDefault(m.getUrl(), "");
|
||||
// }
|
||||
|
||||
public void disableSaving() {
|
||||
savingDisabled = true;
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
package ctbrec;
|
||||
|
||||
import okhttp3.Request;
|
||||
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
public class RemoteService {
|
||||
|
||||
protected void addHmacIfNeeded(byte[] msg, Request.Builder builder) throws InvalidKeyException, NoSuchAlgorithmException {
|
||||
if (Config.getInstance().getSettings().requireAuthentication) {
|
||||
byte[] key = Config.getInstance().getSettings().key;
|
||||
String hmac = Hmac.calculate(msg, key);
|
||||
builder.addHeader("CTBREC-HMAC", hmac);
|
||||
}
|
||||
}
|
||||
|
||||
protected void addHmacIfNeeded(String msg, Request.Builder builder) throws InvalidKeyException, NoSuchAlgorithmException {
|
||||
addHmacIfNeeded(msg.getBytes(UTF_8), builder);
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ package ctbrec.image;
|
|||
import ctbrec.Config;
|
||||
import ctbrec.GlobalThreadPool;
|
||||
import ctbrec.Hmac;
|
||||
import ctbrec.RemoteService;
|
||||
import ctbrec.io.HttpClient;
|
||||
import ctbrec.io.HttpException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
@ -24,7 +25,7 @@ import static ctbrec.io.HttpConstants.MIMETYPE_IMAGE_JPG;
|
|||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
@Slf4j
|
||||
public class RemotePortraitStore implements PortraitStore {
|
||||
public class RemotePortraitStore extends RemoteService implements PortraitStore {
|
||||
|
||||
private final HttpClient httpClient;
|
||||
private final Config config;
|
||||
|
@ -99,14 +100,6 @@ public class RemotePortraitStore implements PortraitStore {
|
|||
}
|
||||
}
|
||||
|
||||
private void addHmacIfNeeded(byte[] msg, Request.Builder builder) throws InvalidKeyException, NoSuchAlgorithmException {
|
||||
if (Config.getInstance().getSettings().requireAuthentication) {
|
||||
byte[] key = Config.getInstance().getSettings().key;
|
||||
String hmac = Hmac.calculate(msg, key);
|
||||
builder.addHeader("CTBREC-HMAC", hmac);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writePortrait(String modelUrl, byte[] data) throws IOException {
|
||||
RequestBody body = RequestBody.create(data, MediaType.parse(MIMETYPE_IMAGE_JPG));
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
package ctbrec.notes;
|
||||
|
||||
import ctbrec.Config;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class LocalModelNotesService implements ModelNotesService {
|
||||
|
||||
private final Config config;
|
||||
|
||||
@Override
|
||||
public Optional<String> loadModelNotes(String modelUrl) {
|
||||
return Optional.ofNullable(config.getSettings().modelNotes.get(modelUrl));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> loadAllModelNotes() throws IOException {
|
||||
return Collections.unmodifiableMap(config.getSettings().modelNotes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeModelNotes(String modelUrl, String notes) {
|
||||
config.getSettings().modelNotes.put(modelUrl, notes);
|
||||
save();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeModelNotes(String modelUrl) {
|
||||
config.getSettings().modelNotes.remove(modelUrl);
|
||||
save();
|
||||
}
|
||||
|
||||
private void save() {
|
||||
try {
|
||||
config.save();
|
||||
} catch (IOException e) {
|
||||
log.warn("Could not save the settings", e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package ctbrec.notes;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface ModelNotesService {
|
||||
|
||||
Optional<String> loadModelNotes(String modelUrl) throws IOException;
|
||||
|
||||
Map<String, String> loadAllModelNotes() throws IOException;
|
||||
|
||||
void writeModelNotes(String modelUrl, String notes) throws IOException;
|
||||
|
||||
void removeModelNotes(String modelUrl) throws IOException;
|
||||
}
|
|
@ -0,0 +1,154 @@
|
|||
package ctbrec.notes;
|
||||
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import ctbrec.Config;
|
||||
import ctbrec.GlobalThreadPool;
|
||||
import ctbrec.RemoteService;
|
||||
import ctbrec.io.HttpClient;
|
||||
import ctbrec.io.HttpException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.Response;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URLEncoder;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
@Slf4j
|
||||
public class RemoteModelNotesService extends RemoteService implements ModelNotesService {
|
||||
|
||||
private final HttpClient httpClient;
|
||||
private final Config config;
|
||||
|
||||
private final LoadingCache<String, String> cache = CacheBuilder.newBuilder()
|
||||
.expireAfterWrite(3, TimeUnit.SECONDS)
|
||||
.maximumSize(10000)
|
||||
.build(CacheLoader.from(this::updateCache));
|
||||
|
||||
public RemoteModelNotesService(HttpClient httpClient, Config config) {
|
||||
this.httpClient = httpClient;
|
||||
this.config = config;
|
||||
transferOldNotesToServer(config.getSettings().modelNotes);
|
||||
}
|
||||
|
||||
private void transferOldNotesToServer(Map<String, String> modelNotes) {
|
||||
LocalModelNotesService localModelNotesStore = new LocalModelNotesService(config);
|
||||
GlobalThreadPool.submit(() -> {
|
||||
try {
|
||||
Thread.sleep(3000);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
List<String> successfullyTransfered = new ArrayList<>();
|
||||
for (Map.Entry<String, String> entry : modelNotes.entrySet()) {
|
||||
try {
|
||||
log.info("Uploading model notes to server {} - {}", entry.getKey(), entry.getValue());
|
||||
RemoteModelNotesService.this.writeModelNotes(entry.getKey(), entry.getValue());
|
||||
successfullyTransfered.add(entry.getKey());
|
||||
} catch (Exception e) {
|
||||
log.warn("Could not transfer model notes from local to remote store: {} {} - {}", entry.getKey(), entry.getValue(), e.getLocalizedMessage());
|
||||
}
|
||||
}
|
||||
for (String s : successfullyTransfered) {
|
||||
localModelNotesStore.removeModelNotes(s);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private String updateCache(String modelUrl) {
|
||||
try {
|
||||
var modelNotes = loadAllModelNotes();
|
||||
for (Map.Entry<String, String> entry : modelNotes.entrySet()) {
|
||||
cache.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
return modelNotes.get(modelUrl);
|
||||
} catch (Exception e) {
|
||||
throw new CacheLoader.InvalidCacheLoadException("Loading of model notes from server failed");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> loadAllModelNotes() throws IOException {
|
||||
Request.Builder builder = new Request.Builder().url(config.getServerUrl() + "/models/notes");
|
||||
try {
|
||||
addHmacIfNeeded(new byte[0], builder);
|
||||
log.trace("Loading all model notes from server");
|
||||
try (Response resp = httpClient.execute(builder.build())) {
|
||||
if (resp.isSuccessful()) {
|
||||
Map<String, String> result = new HashMap<>();
|
||||
JSONObject json = new JSONObject(resp.body().string());
|
||||
JSONArray names = json.names();
|
||||
for (int i = 0; i < names.length(); i++) {
|
||||
String name = names.getString(i);
|
||||
result.put(name, json.getString(name));
|
||||
}
|
||||
return Collections.unmodifiableMap(result);
|
||||
} else {
|
||||
throw new HttpException(resp.code(), resp.message());
|
||||
}
|
||||
}
|
||||
} catch (InvalidKeyException | NoSuchAlgorithmException e) {
|
||||
throw new IOException("Could not load model notes from server", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<String> loadModelNotes(String modelUrl) throws IOException {
|
||||
try {
|
||||
log.trace("Loading model notes for {}", modelUrl);
|
||||
return Optional.of(cache.get(modelUrl));
|
||||
} catch (ExecutionException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeModelNotes(String modelUrl, String notes) throws IOException {
|
||||
Request.Builder builder = new Request.Builder()
|
||||
.url(config.getServerUrl() + "/models/notes/" + URLEncoder.encode(modelUrl, UTF_8))
|
||||
.post(RequestBody.create(notes, MediaType.parse("text/plain")));
|
||||
try {
|
||||
addHmacIfNeeded(notes, builder);
|
||||
try (Response resp = httpClient.execute(builder.build())) {
|
||||
if (resp.isSuccessful()) {
|
||||
cache.put(modelUrl, notes);
|
||||
} else {
|
||||
throw new HttpException(resp.code(), resp.message());
|
||||
}
|
||||
}
|
||||
} catch (InvalidKeyException | NoSuchAlgorithmException e) {
|
||||
throw new IOException("Could not write model notes to server", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeModelNotes(String modelUrl) throws IOException {
|
||||
Request.Builder builder = new Request.Builder()
|
||||
.url(config.getServerUrl() + "/models/notes/" + URLEncoder.encode(modelUrl, UTF_8))
|
||||
.delete();
|
||||
try {
|
||||
addHmacIfNeeded(new byte[0], builder);
|
||||
try (Response resp = httpClient.execute(builder.build())) {
|
||||
if (resp.isSuccessful()) {
|
||||
cache.invalidate(modelUrl);
|
||||
} else {
|
||||
throw new HttpException(resp.code(), resp.message());
|
||||
}
|
||||
}
|
||||
} catch (InvalidKeyException | NoSuchAlgorithmException e) {
|
||||
throw new IOException("Could not delete model notes from server", e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@ import ctbrec.*;
|
|||
import ctbrec.Recording.State;
|
||||
import ctbrec.event.*;
|
||||
import ctbrec.io.HttpClient;
|
||||
import ctbrec.notes.LocalModelNotesService;
|
||||
import ctbrec.recorder.download.Download;
|
||||
import ctbrec.recorder.postprocessing.PostProcessingContext;
|
||||
import ctbrec.recorder.postprocessing.PostProcessor;
|
||||
|
@ -228,6 +229,7 @@ public class NextGenLocalRecorder implements Recorder {
|
|||
ctx.setRecorder(this);
|
||||
ctx.setRecording(recording);
|
||||
ctx.setRecordingManager(recordingManager);
|
||||
ctx.setModelNotesService(new LocalModelNotesService(config));
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package ctbrec.recorder.postprocessing;
|
|||
|
||||
import ctbrec.Config;
|
||||
import ctbrec.Recording;
|
||||
import ctbrec.notes.ModelNotesService;
|
||||
import ctbrec.variableexpansion.ConfigVariableExpander;
|
||||
import ctbrec.variableexpansion.ModelVariableExpander;
|
||||
import ctbrec.variableexpansion.RecordingVariableExpander;
|
||||
|
@ -18,8 +19,9 @@ public abstract class AbstractPlaceholderAwarePostProcessor extends AbstractPost
|
|||
public String fillInPlaceHolders(String input, PostProcessingContext ctx, AntlrSyntacErrorAdapter errorListener) {
|
||||
Recording rec = ctx.getRecording();
|
||||
Config config = ctx.getConfig();
|
||||
ModelNotesService modelNotesService = ctx.getModelNotesService();
|
||||
|
||||
ModelVariableExpander modelExpander = new ModelVariableExpander(rec.getModel(), config, ctx.getRecorder(), errorListener);
|
||||
ModelVariableExpander modelExpander = new ModelVariableExpander(rec.getModel(), modelNotesService, ctx.getRecorder(), errorListener);
|
||||
RecordingVariableExpander recordingExpander = new RecordingVariableExpander(rec, errorListener);
|
||||
ConfigVariableExpander configExpander = new ConfigVariableExpander(config, errorListener);
|
||||
modelExpander.getPlaceholderValueSuppliers().putAll(recordingExpander.getPlaceholderValueSuppliers());
|
||||
|
|
|
@ -2,45 +2,17 @@ package ctbrec.recorder.postprocessing;
|
|||
|
||||
import ctbrec.Config;
|
||||
import ctbrec.Recording;
|
||||
import ctbrec.notes.ModelNotesService;
|
||||
import ctbrec.recorder.Recorder;
|
||||
import ctbrec.recorder.RecordingManager;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class PostProcessingContext {
|
||||
|
||||
private Recorder recorder;
|
||||
private Recording recording;
|
||||
private RecordingManager recordingManager;
|
||||
private Config config;
|
||||
|
||||
public Recorder getRecorder() {
|
||||
return recorder;
|
||||
}
|
||||
|
||||
public void setRecorder(Recorder recorder) {
|
||||
this.recorder = recorder;
|
||||
}
|
||||
|
||||
public Recording getRecording() {
|
||||
return recording;
|
||||
}
|
||||
|
||||
public void setRecording(Recording recording) {
|
||||
this.recording = recording;
|
||||
}
|
||||
|
||||
public RecordingManager getRecordingManager() {
|
||||
return recordingManager;
|
||||
}
|
||||
|
||||
public void setRecordingManager(RecordingManager recordingManager) {
|
||||
this.recordingManager = recordingManager;
|
||||
}
|
||||
|
||||
public Config getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public void setConfig(Config config) {
|
||||
this.config = config;
|
||||
}
|
||||
private ModelNotesService modelNotesService;
|
||||
}
|
||||
|
|
|
@ -1,26 +1,28 @@
|
|||
package ctbrec.variableexpansion;
|
||||
|
||||
import ctbrec.Config;
|
||||
import ctbrec.Model;
|
||||
import ctbrec.ModelGroup;
|
||||
import ctbrec.StringUtil;
|
||||
import ctbrec.notes.ModelNotesService;
|
||||
import ctbrec.recorder.Recorder;
|
||||
import ctbrec.sites.Site;
|
||||
import ctbrec.variableexpansion.functions.AntlrSyntacErrorAdapter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
import static java.util.Optional.ofNullable;
|
||||
|
||||
@Slf4j
|
||||
public class ModelVariableExpander extends AbstractVariableExpander {
|
||||
|
||||
public ModelVariableExpander(Model model, Config config, Recorder recorder, AntlrSyntacErrorAdapter errorListener) {
|
||||
public ModelVariableExpander(Model model, ModelNotesService modelNotesService, 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()));
|
||||
placeholderValueSuppliers.put("modelNotes", getSanitizedModelNotes(config, model));
|
||||
placeholderValueSuppliers.put("modelNotes", getSanitizedModelNotes(modelNotesService, model));
|
||||
placeholderValueSuppliers.put("siteName", ofNullable(model).map(Model::getSite).map(Site::getName));
|
||||
placeholderValueSuppliers.put("modelGroupName", modelGroup.map(ModelGroup::getName));
|
||||
placeholderValueSuppliers.put("modelGroupId", modelGroup.map(ModelGroup::getId).map(UUID::toString));
|
||||
|
@ -30,7 +32,12 @@ public class ModelVariableExpander extends AbstractVariableExpander {
|
|||
return fillInPlaceHolders(input, placeholderValueSuppliers);
|
||||
}
|
||||
|
||||
private Optional<Object> getSanitizedModelNotes(Config config, Model m) {
|
||||
return ofNullable(config.getModelNotes(m)).map(StringUtil::sanitize);
|
||||
private Optional<Object> getSanitizedModelNotes(ModelNotesService modelNotesService, Model m) {
|
||||
try {
|
||||
return modelNotesService.loadModelNotes(m.getUrl()).map(StringUtil::sanitize);
|
||||
} catch (Exception e) {
|
||||
log.warn("Could not load model notes", e);
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package ctbrec.recorder.postprocessing;
|
|||
|
||||
import ctbrec.Config;
|
||||
import ctbrec.Recording;
|
||||
import ctbrec.notes.ModelNotesService;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
@ -14,6 +15,7 @@ import java.util.Locale;
|
|||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
class AbstractPlaceholderAwarePostProcessorTest extends AbstractPpTest {
|
||||
|
@ -21,6 +23,7 @@ class AbstractPlaceholderAwarePostProcessorTest extends AbstractPpTest {
|
|||
Recording rec;
|
||||
Config config;
|
||||
Move placeHolderAwarePp;
|
||||
ModelNotesService modelNotesService;
|
||||
|
||||
@Override
|
||||
@BeforeEach
|
||||
|
@ -34,6 +37,8 @@ class AbstractPlaceholderAwarePostProcessorTest extends AbstractPpTest {
|
|||
rec.setSingleFile(true);
|
||||
config = mockConfig();
|
||||
placeHolderAwarePp = new Move();
|
||||
modelNotesService = mock(ModelNotesService.class);
|
||||
when(modelNotesService.loadModelNotes(any())).thenReturn(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -157,7 +162,6 @@ class AbstractPlaceholderAwarePostProcessorTest extends AbstractPpTest {
|
|||
@Test
|
||||
void testMissingValueForPlaceholder() {
|
||||
String input = "asdf_${modelNotes}_asdf";
|
||||
when(config.getModelNotes(any())).thenReturn(null);
|
||||
assertEquals("asdf_${modelNotes}_asdf", placeHolderAwarePp.fillInPlaceHolders(input, createPostProcessingContext(rec, null, config)));
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import ctbrec.Config;
|
|||
import ctbrec.Model;
|
||||
import ctbrec.Recording;
|
||||
import ctbrec.Settings;
|
||||
import ctbrec.notes.ModelNotesService;
|
||||
import ctbrec.recorder.Recorder;
|
||||
import ctbrec.recorder.RecordingManager;
|
||||
import ctbrec.sites.Site;
|
||||
|
@ -18,6 +19,7 @@ import java.io.IOException;
|
|||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.time.Instant;
|
||||
import java.util.Optional;
|
||||
|
||||
import static java.nio.file.StandardOpenOption.*;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
|
@ -34,6 +36,7 @@ public abstract class AbstractPpTest {
|
|||
RecordingManager recordingManager;
|
||||
|
||||
MockedStatic<Config> configStatic;
|
||||
ModelNotesService modelNotesService;
|
||||
|
||||
@BeforeEach
|
||||
public void setup() throws IOException {
|
||||
|
@ -48,6 +51,8 @@ public abstract class AbstractPpTest {
|
|||
Files.writeString(postProcessed.toPath(), "foobar", CREATE_NEW, WRITE, TRUNCATE_EXISTING);
|
||||
Files.createDirectories(originalDir.toPath());
|
||||
FileUtils.touch(new File(originalDir, "playlist.m3u8"));
|
||||
modelNotesService = mock(ModelNotesService.class);
|
||||
when(modelNotesService.loadModelNotes(any())).thenReturn(Optional.of("tag, foo, bar"));
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
|
@ -63,7 +68,6 @@ public abstract class AbstractPpTest {
|
|||
Config config = mock(Config.class);
|
||||
Settings settings = mockSettings();
|
||||
when(config.getSettings()).thenReturn(settings);
|
||||
when(config.getModelNotes(any())).thenReturn("tag, foo, bar");
|
||||
when(config.getConfigDir()).thenReturn(new File(baseDir.toFile(), "config"));
|
||||
configStatic = mockStatic(Config.class);
|
||||
configStatic.when(Config::getInstance).thenReturn(config);
|
||||
|
|
|
@ -4,6 +4,7 @@ import ctbrec.Config;
|
|||
import ctbrec.Model;
|
||||
import ctbrec.Settings;
|
||||
import ctbrec.UnknownModel;
|
||||
import ctbrec.notes.ModelNotesService;
|
||||
import ctbrec.recorder.Recorder;
|
||||
import ctbrec.sites.chaturbate.Chaturbate;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
|
@ -11,6 +12,9 @@ import org.junit.jupiter.api.BeforeEach;
|
|||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.MockedStatic;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
@ -21,8 +25,10 @@ class ModelVariableExpanderTest {
|
|||
Config config;
|
||||
MockedStatic<Config> configStatic;
|
||||
|
||||
ModelNotesService modelNotesService;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
void setup() throws IOException {
|
||||
UnknownModel unknownModel = new UnknownModel();
|
||||
Chaturbate chaturbate = new Chaturbate();
|
||||
unknownModel.setName("Pussy_Galore");
|
||||
|
@ -30,6 +36,8 @@ class ModelVariableExpanderTest {
|
|||
unknownModel.setSite(chaturbate);
|
||||
this.model = unknownModel;
|
||||
this.config = mockConfig();
|
||||
this.modelNotesService = mock(ModelNotesService.class);
|
||||
when(modelNotesService.loadModelNotes(any())).thenReturn(Optional.of("tag, foo, bar"));
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
|
@ -43,7 +51,7 @@ class ModelVariableExpanderTest {
|
|||
@Test
|
||||
void testMultipleVariablesAsParameter() {
|
||||
Recorder recorder = mock(Recorder.class);
|
||||
ModelVariableExpander modelVariableExpander = new ModelVariableExpander(model, config, recorder, null);
|
||||
ModelVariableExpander modelVariableExpander = new ModelVariableExpander(model, modelNotesService, recorder, null);
|
||||
assertEquals("pussy_galore asdf pussy_galore", modelVariableExpander.expand("$lower(${modelName} ASDF ${modelName})"));
|
||||
}
|
||||
|
||||
|
@ -51,7 +59,6 @@ class ModelVariableExpanderTest {
|
|||
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;
|
||||
|
|
|
@ -14,10 +14,12 @@ import java.io.IOException;
|
|||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
|
||||
|
||||
public abstract class AbstractCtbrecServlet extends HttpServlet {
|
||||
|
||||
public static final String INTERNAL_SERVER_ERROR = "Internal Server Error";
|
||||
protected static final String HMAC_ERROR_DOCUMENT = "{\"status\": \"error\", \"msg\": \"HMAC does not match\"}";
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AbstractCtbrecServlet.class);
|
||||
|
||||
boolean checkAuthentication(HttpServletRequest req, String body) throws InvalidKeyException, NoSuchAlgorithmException {
|
||||
|
@ -93,6 +95,7 @@ public abstract class AbstractCtbrecServlet extends HttpServlet {
|
|||
void sendResponse(HttpServletResponse resp, int httpStatus, String message) {
|
||||
try {
|
||||
resp.setStatus(httpStatus);
|
||||
resp.setCharacterEncoding(UTF_8.toString());
|
||||
resp.getWriter().print(message);
|
||||
} catch (IOException e) {
|
||||
LOG.error("Couldn't write response", e);
|
||||
|
|
|
@ -237,6 +237,10 @@ public class HttpServer {
|
|||
holder.getRegistration().setMultipartConfig(multipartConfig);
|
||||
defaultContext.addServlet(holder, ImageServlet.BASE_URL + "/*");
|
||||
|
||||
ModelServlet modelServlet = new ModelServlet(config);
|
||||
holder = new ServletHolder(modelServlet);
|
||||
defaultContext.addServlet(holder, ModelServlet.BASE_URL + "/*");
|
||||
|
||||
if (this.config.getSettings().webinterface) {
|
||||
startWebInterface(defaultContext, basicAuthContext);
|
||||
}
|
||||
|
|
|
@ -22,8 +22,6 @@ import static javax.servlet.http.HttpServletResponse.*;
|
|||
public class ImageServlet extends AbstractCtbrecServlet {
|
||||
|
||||
public static final String BASE_URL = "/image";
|
||||
public static final String INTERNAL_SERVER_ERROR = "Internal Server Error";
|
||||
private static final String HMAC_ERROR_DOCUMENT = "{\"status\": \"error\", \"msg\": \"HMAC does not match\"}";
|
||||
private static final Pattern URL_PATTERN_PORTRAIT_BY_ID = Pattern.compile(BASE_URL + "/portrait/([0-9a-fA-F]{8}\\b-[0-9a-fA-F]{4}\\b-[0-9a-fA-F]{4}\\b-[0-9a-fA-F]{4}\\b-[0-9a-fA-F]{12})");
|
||||
private static final Pattern URL_PATTERN_PORTRAIT_BY_URL = Pattern.compile(BASE_URL + "/portrait/url/(.*)");
|
||||
private final PortraitStore portraitStore;
|
||||
|
@ -31,7 +29,7 @@ public class ImageServlet extends AbstractCtbrecServlet {
|
|||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
|
||||
String requestURI = req.getRequestURI();
|
||||
String requestURI = req.getRequestURI().substring(req.getContextPath().length());
|
||||
try {
|
||||
boolean authenticated = checkAuthentication(req, "");
|
||||
if (!authenticated) {
|
||||
|
@ -55,7 +53,6 @@ public class ImageServlet extends AbstractCtbrecServlet {
|
|||
}
|
||||
|
||||
private void servePortrait(HttpServletResponse resp, String portraitId) throws IOException {
|
||||
log.debug("serving portrait {}", portraitId);
|
||||
Optional<byte[]> imageData = portraitStore.loadModelPortraitById(portraitId);
|
||||
if (imageData.isPresent()) {
|
||||
resp.setStatus(SC_OK);
|
||||
|
@ -71,7 +68,7 @@ public class ImageServlet extends AbstractCtbrecServlet {
|
|||
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
|
||||
String requestURI = req.getRequestURI();
|
||||
String requestURI = req.getRequestURI().substring(req.getContextPath().length());
|
||||
try {
|
||||
byte[] data = bodyAsByteArray(req);
|
||||
boolean authenticated = checkAuthentication(req, data);
|
||||
|
@ -93,7 +90,7 @@ public class ImageServlet extends AbstractCtbrecServlet {
|
|||
|
||||
@Override
|
||||
protected void doDelete(HttpServletRequest req, HttpServletResponse resp) {
|
||||
String requestURI = req.getRequestURI();
|
||||
String requestURI = req.getRequestURI().substring(req.getContextPath().length());
|
||||
try {
|
||||
boolean authenticated = checkAuthentication(req, "");
|
||||
if (!authenticated) {
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
package ctbrec.recorder.server;
|
||||
|
||||
import ctbrec.Config;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static javax.servlet.http.HttpServletResponse.*;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class ModelServlet extends AbstractCtbrecServlet {
|
||||
|
||||
public static final String BASE_URL = "/models";
|
||||
|
||||
private static final Pattern URL_PATTERN_ALL_MODEL_NOTES = Pattern.compile(BASE_URL + "/notes/?");
|
||||
private static final Pattern URL_PATTERN_MODEL_NOTES = Pattern.compile(BASE_URL + "/notes/(.+?)");
|
||||
private final Config config;
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
|
||||
String requestURI = req.getRequestURI().substring(req.getContextPath().length());
|
||||
try {
|
||||
boolean authenticated = checkAuthentication(req, "");
|
||||
if (!authenticated) {
|
||||
sendResponse(resp, SC_UNAUTHORIZED, HMAC_ERROR_DOCUMENT);
|
||||
return;
|
||||
}
|
||||
|
||||
Matcher m;
|
||||
if ((m = URL_PATTERN_MODEL_NOTES.matcher(requestURI)).matches()) {
|
||||
String modelUrl = URLDecoder.decode(m.group(1), UTF_8);
|
||||
String notes = config.getSettings().modelNotes.getOrDefault(modelUrl, "");
|
||||
log.debug("Model Notes Request {} - {}", modelUrl, notes);
|
||||
resp.setContentType("text/plain");
|
||||
sendResponse(resp, SC_OK, notes);
|
||||
} else if ((URL_PATTERN_ALL_MODEL_NOTES.matcher(requestURI)).matches()) {
|
||||
JSONObject notes = new JSONObject();
|
||||
config.getSettings().modelNotes.forEach(notes::put);
|
||||
resp.setContentType("application/json");
|
||||
sendResponse(resp, SC_OK, notes.toString());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error(INTERNAL_SERVER_ERROR, e);
|
||||
sendResponse(resp, SC_INTERNAL_SERVER_ERROR, INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
|
||||
String requestURI = req.getRequestURI().substring(req.getContextPath().length());
|
||||
try {
|
||||
var body = body(req);
|
||||
log.info("Notes: [{}]", body);
|
||||
boolean authenticated = checkAuthentication(req, body);
|
||||
if (!authenticated) {
|
||||
sendResponse(resp, SC_UNAUTHORIZED, HMAC_ERROR_DOCUMENT);
|
||||
return;
|
||||
}
|
||||
|
||||
Matcher m;
|
||||
if ((m = URL_PATTERN_MODEL_NOTES.matcher(requestURI)).matches()) {
|
||||
String modelUrl = URLDecoder.decode(m.group(1), UTF_8);
|
||||
config.getSettings().modelNotes.put(modelUrl, body);
|
||||
config.save();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error(INTERNAL_SERVER_ERROR, e);
|
||||
sendResponse(resp, SC_INTERNAL_SERVER_ERROR, INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doDelete(HttpServletRequest req, HttpServletResponse resp) {
|
||||
String requestURI = req.getRequestURI().substring(req.getContextPath().length());
|
||||
try {
|
||||
boolean authenticated = checkAuthentication(req, "");
|
||||
if (!authenticated) {
|
||||
sendResponse(resp, SC_UNAUTHORIZED, HMAC_ERROR_DOCUMENT);
|
||||
return;
|
||||
}
|
||||
|
||||
Matcher m;
|
||||
if ((m = URL_PATTERN_MODEL_NOTES.matcher(requestURI)).matches()) {
|
||||
String modelUrl = URLDecoder.decode(m.group(1), UTF_8);
|
||||
config.getSettings().modelNotes.remove(modelUrl);
|
||||
config.save();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error(INTERNAL_SERVER_ERROR, e);
|
||||
sendResponse(resp, SC_INTERNAL_SERVER_ERROR, INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue