Merge branch 'dev' into pp
This commit is contained in:
commit
4f8e7dbca2
14
CHANGELOG.md
14
CHANGELOG.md
|
@ -1,12 +1,24 @@
|
|||
3.9.0
|
||||
========================
|
||||
* Added support for Manyvids Live.
|
||||
Things that work:
|
||||
* Recording streams. Even more than one (this was a problem first, because
|
||||
they allow only one stream per session)
|
||||
* Search
|
||||
Things that don't work:
|
||||
* login / favorites
|
||||
* tipping
|
||||
* media player isn't working because of their authetication mechanism
|
||||
* Fixed bug in recorder servlet. Actions for unpin and notes were mixed up
|
||||
and not properly synchronized between the server and the client
|
||||
* Recordings now start immediately for newly added models
|
||||
* Added confirmation dialog for "Pause All" and "Resume All"
|
||||
* Added confirmation dialog for "Pause All", "Resume All" and shutdown
|
||||
* Fix: recording started event was not fired in client / server mode
|
||||
* CTB Recorder now stops recording, if less than 100 MiB space is left
|
||||
* New event, which is fired, if the disk is full (or less than the configured
|
||||
threshold is available)
|
||||
* Fixed: MFC models changing to other models (I think, I found the problem.
|
||||
Can't be sure 100%)
|
||||
|
||||
3.8.6
|
||||
========================
|
||||
|
|
|
@ -14,7 +14,6 @@ import java.util.ArrayList;
|
|||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -317,24 +316,12 @@ public class CamrecApplication extends Application {
|
|||
}
|
||||
|
||||
private void registerAlertSystem() {
|
||||
new Thread(() -> {
|
||||
try {
|
||||
// don't register before 1 minute has passed, because directly after
|
||||
// the start of ctbrec, an event for every online model would be fired,
|
||||
// which is annoying as f
|
||||
Thread.sleep(TimeUnit.MINUTES.toMillis(1));
|
||||
|
||||
for (EventHandlerConfiguration eventHandlerConfig : Config.getInstance().getSettings().eventHandlers) {
|
||||
EventHandler handler = new EventHandler(eventHandlerConfig);
|
||||
EventBusHolder.register(handler);
|
||||
LOG.debug("Registered event handler for {} {}", eventHandlerConfig.getEvent(), eventHandlerConfig.getName());
|
||||
}
|
||||
LOG.debug("Alert System registered");
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
LOG.info("Interrupted before alter system has been registered");
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
private void registerActiveRecordingsCounter() {
|
||||
|
|
|
@ -22,6 +22,9 @@ public class ShowNotification extends Action {
|
|||
switch(evt.getType()) {
|
||||
case MODEL_STATUS_CHANGED:
|
||||
ModelStateChangedEvent modelEvent = (ModelStateChangedEvent) evt;
|
||||
if (modelEvent.getOldState() == Model.State.UNKNOWN) {
|
||||
return;
|
||||
}
|
||||
Model m = modelEvent.getModel();
|
||||
msg = m.getDisplayName() + " is now " + modelEvent.getNewState().toString();
|
||||
break;
|
||||
|
|
|
@ -23,6 +23,7 @@ import ctbrec.event.EventHandlerConfiguration;
|
|||
import ctbrec.event.EventHandlerConfiguration.ActionConfiguration;
|
||||
import ctbrec.event.EventHandlerConfiguration.PredicateConfiguration;
|
||||
import ctbrec.event.ExecuteProgram;
|
||||
import ctbrec.event.MatchAllPredicate;
|
||||
import ctbrec.event.ModelPredicate;
|
||||
import ctbrec.event.ModelStatePredicate;
|
||||
import ctbrec.event.RecordingStatePredicate;
|
||||
|
@ -152,6 +153,11 @@ public class ActionSettingsPanel extends GridPane {
|
|||
pc.getConfiguration().put("state", recordingState.getValue().name());
|
||||
pc.setName("state = " + recordingState.getValue().toString());
|
||||
config.getPredicates().add(pc);
|
||||
} else if(event.getValue() == Event.Type.NO_SPACE_LEFT) {
|
||||
PredicateConfiguration pc = new PredicateConfiguration();
|
||||
pc.setType(MatchAllPredicate.class.getName());
|
||||
pc.setName("no space left");
|
||||
config.getPredicates().add(pc);
|
||||
}
|
||||
if(!modelSelectionPane.isAllSelected()) {
|
||||
PredicateConfiguration pc = new PredicateConfiguration();
|
||||
|
@ -200,7 +206,7 @@ public class ActionSettingsPanel extends GridPane {
|
|||
if(event.getValue() == Event.Type.RECORDING_STATUS_CHANGED && recordingState.getValue() == null) {
|
||||
throw new IllegalStateException("Select a state");
|
||||
}
|
||||
if(modelSelectionPane.getSelectedItems().isEmpty() && !modelSelectionPane.isAllSelected()) {
|
||||
if(event.getValue() != Event.Type.NO_SPACE_LEFT && modelSelectionPane.getSelectedItems().isEmpty() && !modelSelectionPane.isAllSelected()) {
|
||||
throw new IllegalStateException("Select one or more models or tick off \"all\"");
|
||||
}
|
||||
if(!(showNotification.isSelected() || playSound.isSelected() || executeProgram.isSelected())) {
|
||||
|
@ -231,10 +237,23 @@ public class ActionSettingsPanel extends GridPane {
|
|||
event.getItems().clear();
|
||||
event.getItems().add(Event.Type.MODEL_STATUS_CHANGED);
|
||||
event.getItems().add(Event.Type.RECORDING_STATUS_CHANGED);
|
||||
event.getItems().add(Event.Type.NO_SPACE_LEFT);
|
||||
event.setOnAction(evt -> modelState.setVisible(event.getSelectionModel().getSelectedItem() == Event.Type.MODEL_STATUS_CHANGED));
|
||||
event.getSelectionModel().select(Event.Type.MODEL_STATUS_CHANGED);
|
||||
layout.add(event, 1, row++);
|
||||
|
||||
event.getSelectionModel().selectedItemProperty().addListener((obs, oldV, newV) -> {
|
||||
boolean modelRelatedStuffDisabled = false;
|
||||
if(newV == Event.Type.NO_SPACE_LEFT) {
|
||||
modelRelatedStuffDisabled = true;
|
||||
modelSelectionPane.selectAll();
|
||||
}
|
||||
|
||||
modelState.setDisable(modelRelatedStuffDisabled);
|
||||
recordingState.setDisable(modelRelatedStuffDisabled);
|
||||
modelSelectionPane.setDisable(modelRelatedStuffDisabled);
|
||||
});
|
||||
|
||||
layout.add(new Label("State"), 0, row);
|
||||
modelState.getItems().clear();
|
||||
modelState.getItems().addAll(Model.State.values());
|
||||
|
|
|
@ -118,4 +118,8 @@ public class ListSelectionPane<T extends Comparable<T>> extends GridPane {
|
|||
public boolean isAllSelected() {
|
||||
return selectAll.isSelected();
|
||||
}
|
||||
|
||||
public void selectAll() {
|
||||
selectAll.setSelected(true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
package ctbrec.ui.sites.cam4;
|
||||
|
||||
import static ctbrec.Model.State.*;
|
||||
import static ctbrec.io.HttpConstants.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
|
@ -64,7 +68,11 @@ public class Cam4UpdateService extends PaginatedScheduledService {
|
|||
if(loginRequired) {
|
||||
SiteUiFactory.getUi(site).login();
|
||||
}
|
||||
Request request = new Request.Builder().url(url).build();
|
||||
Request request = new Request.Builder()
|
||||
.url(url)
|
||||
.header(ACCEPT_LANGUAGE, Locale.ENGLISH.getLanguage())
|
||||
.header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
|
||||
.build();
|
||||
try (Response response = site.getHttpClient().execute(request)) {
|
||||
if (response.isSuccessful()) {
|
||||
JSONObject json = new JSONObject(response.body().string());
|
||||
|
@ -76,11 +84,15 @@ public class Cam4UpdateService extends PaginatedScheduledService {
|
|||
Element profileLink = HtmlParser.getTag(boxHtml, "a.profile-preview");
|
||||
String path = profileLink.attr("href");
|
||||
String slug = path.substring(1);
|
||||
Cam4Model model = (Cam4Model) site.createModel(slug);
|
||||
Cam4Model model = site.createModel(slug);
|
||||
String playlistUrl = profileLink.attr("data-hls-preview-url");
|
||||
model.setPlaylistUrl(playlistUrl);
|
||||
model.setPreview("https://snapshots.xcdnpro.com/thumbnails/" + model.getName() + "?s=" + System.currentTimeMillis());
|
||||
model.setDescription(parseDesription(boxHtml));
|
||||
model.setOnlineState(ONLINE);
|
||||
if(boxHtml.contains("In private show")) {
|
||||
model.setOnlineState(PRIVATE);
|
||||
}
|
||||
models.add(model);
|
||||
}
|
||||
return models;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package ctbrec.ui.sites.streamate;
|
||||
|
||||
import static ctbrec.Model.State.*;
|
||||
import static ctbrec.io.HttpConstants.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -81,6 +82,7 @@ public class StreamateFollowedService extends PaginatedScheduledService {
|
|||
model.setPreview(p.getString("thumbnail"));
|
||||
boolean online = p.optBoolean("online") && notPrivateEtc(p);
|
||||
model.setOnline(online);
|
||||
model.setOnlineState(online ? ONLINE : OFFLINE);
|
||||
if (online == showOnline) {
|
||||
models.add(model);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package ctbrec.ui.sites.streamate;
|
||||
|
||||
import static ctbrec.Model.State.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -52,6 +54,7 @@ public class StreamateUpdateService extends PaginatedScheduledService {
|
|||
List<Model> models = new ArrayList<>();
|
||||
String content = response.body().string();
|
||||
JSONObject json = new JSONObject(content);
|
||||
System.err.println(json.toString(2));
|
||||
JSONArray performers = json.getJSONArray("performers");
|
||||
for (int i = 0; i < performers.length(); i++) {
|
||||
JSONObject p = performers.getJSONObject(i);
|
||||
|
@ -59,7 +62,9 @@ public class StreamateUpdateService extends PaginatedScheduledService {
|
|||
StreamateModel model = (StreamateModel) streamate.createModel(nickname);
|
||||
model.setId(p.getLong("id"));
|
||||
model.setPreview(p.getString("thumbnail"));
|
||||
model.setOnline(p.optBoolean("online"));
|
||||
boolean online = p.optBoolean("online");
|
||||
model.setOnline(online);
|
||||
model.setOnlineState(online ? ONLINE : OFFLINE);
|
||||
// TODO figure out, what all the states mean
|
||||
// liveState {…}
|
||||
// exclusiveShow false
|
||||
|
@ -69,6 +74,11 @@ public class StreamateUpdateService extends PaginatedScheduledService {
|
|||
// preGoldShow true
|
||||
// privateChat false
|
||||
// specialShow false
|
||||
if (p.optBoolean("onBreak")) {
|
||||
model.setOnlineState(AWAY);
|
||||
} else if (p.optBoolean("goldShow") || p.optBoolean("privateChat") || p.optBoolean("exclusiveShow")) {
|
||||
model.setOnlineState(PRIVATE);
|
||||
}
|
||||
models.add(model);
|
||||
}
|
||||
return models;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package ctbrec.ui.sites.stripchat;
|
||||
|
||||
import static ctbrec.Model.State.*;
|
||||
import static ctbrec.io.HttpConstants.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -68,6 +69,7 @@ public class StripchatFollowedUpdateService extends PaginatedScheduledService {
|
|||
try (Response response = stripchat.getHttpClient().execute(request)) {
|
||||
if (response.isSuccessful()) {
|
||||
JSONObject json = new JSONObject(response.body().string());
|
||||
System.err.println(json.toString(2));
|
||||
if (json.has("models")) {
|
||||
JSONArray users = json.getJSONArray("models");
|
||||
for (int i = 0; i < users.length(); i++) {
|
||||
|
@ -75,6 +77,7 @@ public class StripchatFollowedUpdateService extends PaginatedScheduledService {
|
|||
StripchatModel model = stripchat.createModel(user.optString("username"));
|
||||
model.setDescription(user.optString("description"));
|
||||
model.setPreview(user.optString("previewUrlThumbBig"));
|
||||
model.setOnlineState(mapStatus(user.optString("status")));
|
||||
models.add(model);
|
||||
}
|
||||
}
|
||||
|
@ -114,4 +117,17 @@ public class StripchatFollowedUpdateService extends PaginatedScheduledService {
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected ctbrec.Model.State mapStatus(String status) {
|
||||
switch (status) {
|
||||
case "public":
|
||||
return ONLINE;
|
||||
case "idle":
|
||||
return AWAY;
|
||||
case "off":
|
||||
return OFFLINE;
|
||||
default:
|
||||
return UNKNOWN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,6 +75,7 @@ public class StripchatUpdateService extends PaginatedScheduledService {
|
|||
model.setDescription("");
|
||||
model.setPreview(jsonModel.optString("snapshotUrl"));
|
||||
model.setDisplayName(model.getName());
|
||||
model.setOnlineState(Model.State.ONLINE);
|
||||
models.add(model);
|
||||
} catch (Exception e) {
|
||||
LOG.warn("Couldn't parse one of the models: {}", jsonModel, e);
|
||||
|
|
|
@ -18,7 +18,12 @@ public abstract class Event {
|
|||
/**
|
||||
* This event is fired whenever the state of a recording changes.
|
||||
*/
|
||||
RECORDING_STATUS_CHANGED("recording status changed");
|
||||
RECORDING_STATUS_CHANGED("recording status changed"),
|
||||
|
||||
/**
|
||||
* This event is fired when the disk space is exhausted
|
||||
*/
|
||||
NO_SPACE_LEFT("no space left");
|
||||
|
||||
private String desc;
|
||||
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
package ctbrec.event;
|
||||
|
||||
import ctbrec.event.EventHandlerConfiguration.PredicateConfiguration;
|
||||
|
||||
public class MatchAllPredicate extends EventPredicate {
|
||||
|
||||
@Override
|
||||
public boolean test(Event evt) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(PredicateConfiguration pc) {
|
||||
// noop
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package ctbrec.event;
|
||||
|
||||
public class NoSpaceLeftEvent extends Event {
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return Type.NO_SPACE_LEFT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "No space left on device";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "No space left on device";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getExecutionParams() {
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
}
|
|
@ -49,6 +49,7 @@ import ctbrec.Recording.State;
|
|||
import ctbrec.event.Event;
|
||||
import ctbrec.event.EventBusHolder;
|
||||
import ctbrec.event.ModelIsOnlineEvent;
|
||||
import ctbrec.event.NoSpaceLeftEvent;
|
||||
import ctbrec.event.RecordingStateChangedEvent;
|
||||
import ctbrec.io.HttpClient;
|
||||
import ctbrec.recorder.download.Download;
|
||||
|
@ -111,6 +112,7 @@ public class NextGenLocalRecorder implements Recorder {
|
|||
if (!recordingProcesses.isEmpty() && !enoughSpaceForRecording()) {
|
||||
LOG.info("No space left -> Stopping all recordings");
|
||||
stopRecordingProcesses();
|
||||
EventBusHolder.BUS.post(new NoSpaceLeftEvent());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LOG.error("Couldn't check space left on device", e);
|
||||
|
@ -577,7 +579,7 @@ public class NextGenLocalRecorder implements Recorder {
|
|||
boolean enoughSpaceForRecording() throws IOException {
|
||||
long minimum = config.getSettings().minimumSpaceLeftInBytes;
|
||||
if (minimum == 0) { // 0 means don't check
|
||||
return true;
|
||||
return getFreeSpaceBytes() > 100 * 1024 * 1024; // leave at least 100 MiB free
|
||||
} else {
|
||||
return getFreeSpaceBytes() > minimum;
|
||||
}
|
||||
|
@ -678,8 +680,7 @@ public class NextGenLocalRecorder implements Recorder {
|
|||
|
||||
@Override
|
||||
public void setNote(Recording rec, String note) throws IOException {
|
||||
rec.setNote(note);
|
||||
recordingManager.saveRecording(rec);
|
||||
recordingManager.setNote(rec, note);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -11,6 +11,8 @@ import java.time.Duration;
|
|||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
@ -217,8 +219,9 @@ public class RecordingManager {
|
|||
public void pin(Recording recording) throws IOException {
|
||||
recordingsLock.lock();
|
||||
try {
|
||||
recording.setPinned(true);
|
||||
saveRecording(recording);
|
||||
Recording local = getRecording(recording);
|
||||
local.setPinned(true);
|
||||
saveRecording(local);
|
||||
} finally {
|
||||
recordingsLock.unlock();
|
||||
}
|
||||
|
@ -227,10 +230,31 @@ public class RecordingManager {
|
|||
public void unpin(Recording recording) throws IOException {
|
||||
recordingsLock.lock();
|
||||
try {
|
||||
recording.setPinned(false);
|
||||
saveRecording(recording);
|
||||
Recording local = getRecording(recording);
|
||||
local.setPinned(false);
|
||||
saveRecording(local);
|
||||
} finally {
|
||||
recordingsLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void setNote(Recording rec, String note) throws IOException {
|
||||
recordingsLock.lock();
|
||||
try {
|
||||
Recording local = getRecording(rec);
|
||||
local.setNote(note);
|
||||
saveRecording(local);
|
||||
} finally {
|
||||
recordingsLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private Recording getRecording(Recording rec) {
|
||||
for (Recording r : getAll()) {
|
||||
if(Objects.equals(r, rec)) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
throw new NoSuchElementException("Recording not found");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import ctbrec.Hmac;
|
|||
import ctbrec.Model;
|
||||
import ctbrec.Recording;
|
||||
import ctbrec.event.EventBusHolder;
|
||||
import ctbrec.event.NoSpaceLeftEvent;
|
||||
import ctbrec.event.RecordingStateChangedEvent;
|
||||
import ctbrec.io.BandwidthMeter;
|
||||
import ctbrec.io.HttpClient;
|
||||
|
@ -57,6 +58,7 @@ public class RemoteRecorder implements Recorder {
|
|||
private List<Site> sites;
|
||||
private long spaceTotal = -1;
|
||||
private long spaceFree = -1;
|
||||
private boolean noSpaceLeftDetected = false;
|
||||
|
||||
private Config config;
|
||||
private HttpClient client;
|
||||
|
@ -184,6 +186,7 @@ public class RemoteRecorder implements Recorder {
|
|||
private static final String COULDNT_SYNCHRONIZE_WITH_SERVER = "Couldn't synchronize with server";
|
||||
private static final String COULDNT_SYNCHRONIZE_WITH_SERVER_HTTP_STATUS = "Couldn't synchronize with server. HTTP status: {} - {}";
|
||||
private volatile boolean running = false;
|
||||
private static final long ONE_HUNDRED_MIB = 100 * 1024 * 1024;
|
||||
|
||||
public SyncThread() {
|
||||
setName("RemoteRecorder SyncThread");
|
||||
|
@ -218,6 +221,16 @@ public class RemoteRecorder implements Recorder {
|
|||
long throughput = resp.getLong("throughput");
|
||||
Duration timeframe = Duration.ofSeconds(resp.getInt("throughputTimeframe"));
|
||||
BandwidthMeter.setThroughput(throughput, timeframe);
|
||||
long minimumSpaceLeftInBytes = resp.optLong("minimumSpaceLeftInBytes");
|
||||
if (minimumSpaceLeftInBytes > 0 && minimumSpaceLeftInBytes >= spaceFree
|
||||
|| minimumSpaceLeftInBytes == 0 && spaceFree < ONE_HUNDRED_MIB) {
|
||||
if (!noSpaceLeftDetected) {
|
||||
EventBusHolder.BUS.post(new NoSpaceLeftEvent());
|
||||
}
|
||||
noSpaceLeftDetected = true;
|
||||
} else {
|
||||
noSpaceLeftDetected = false;
|
||||
}
|
||||
} else {
|
||||
LOG.error(COULDNT_SYNCHRONIZE_WITH_SERVER_HTTP_STATUS, response.code(), json);
|
||||
}
|
||||
|
@ -319,6 +332,18 @@ public class RemoteRecorder implements Recorder {
|
|||
}
|
||||
}
|
||||
}
|
||||
// fire recording started event
|
||||
List<Recording> justStarted = new ArrayList<>(newRecordings);
|
||||
justStarted.removeAll(recordings);
|
||||
for (Recording recording : justStarted) {
|
||||
if (recording.getStatus() == Recording.State.RECORDING) {
|
||||
File file = new File(recording.getPath());
|
||||
RecordingStateChangedEvent evt = new RecordingStateChangedEvent(file, recording.getStatus(), recording.getModel(),
|
||||
recording.getStartDate());
|
||||
EventBusHolder.BUS.post(evt);
|
||||
}
|
||||
}
|
||||
|
||||
recordings = newRecordings;
|
||||
} else {
|
||||
LOG.error(SERVER_RETURNED_ERROR, resp.status, resp.msg);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package ctbrec.sites.manyvids;
|
||||
|
||||
import static ctbrec.StringUtil.*;
|
||||
import static ctbrec.io.HttpConstants.*;
|
||||
import static ctbrec.sites.manyvids.MVLive.*;
|
||||
|
||||
|
@ -182,7 +183,7 @@ public class MVLiveClient {
|
|||
String respJson = jsonArray.getString(i);
|
||||
JSONObject response = new JSONObject(respJson);
|
||||
String address = response.optString("address");
|
||||
if (!address.isBlank()) {
|
||||
if (isNotBlank(address)) {
|
||||
Message message = futureResponses.get(address);
|
||||
if (message != null) {
|
||||
message.handleResponse(response);
|
||||
|
|
|
@ -320,6 +320,7 @@ public class MyFreeCamsClient {
|
|||
LOG.error("Error while decoding ctxenc URL", e);
|
||||
} catch (Exception e) {
|
||||
LOG.error("Exception occured while processing websocket message {}", msgBuffer, e);
|
||||
ws.close(1000, "");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import static ctbrec.Model.State.*;
|
|||
import static ctbrec.io.HttpConstants.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Duration;
|
||||
|
@ -52,23 +53,21 @@ public class Showup extends AbstractSite {
|
|||
|
||||
@Override
|
||||
public Model createModel(String name) {
|
||||
// try {
|
||||
// for (Model m : getModelList()) {
|
||||
// if (Objects.equal(m.getName(), name)) {
|
||||
// return m;
|
||||
// }
|
||||
// }
|
||||
// } catch (IOException e) {
|
||||
// throw new ModelNotFoundException(name, e);
|
||||
// }
|
||||
// throw new ModelNotFoundException(name);
|
||||
ShowupModel model = new ShowupModel();
|
||||
model.setSite(this);
|
||||
model.setName(name);
|
||||
model.setUrl(BASE_URL + '/' + URLEncoder.encode(name, StandardCharsets.UTF_8));
|
||||
model.setUrl(BASE_URL + '/' + safeUrlEncode(name));
|
||||
return model;
|
||||
}
|
||||
|
||||
private String safeUrlEncode(String s) {
|
||||
try {
|
||||
return URLEncoder.encode(s, StandardCharsets.UTF_8.name());
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
public List<Model> getModelList() throws IOException {
|
||||
if(Duration.between(lastModelListUpdate, Instant.now()).getSeconds() > 10) {
|
||||
lastModelListUpdate = Instant.now();
|
||||
|
|
|
@ -8,6 +8,7 @@ import org.json.JSONObject;
|
|||
import org.junit.Test;
|
||||
|
||||
import ctbrec.ReflectionUtil;
|
||||
import ctbrec.StringUtil;
|
||||
|
||||
public class MyFreeCamsClientTest {
|
||||
|
||||
|
@ -22,7 +23,7 @@ public class MyFreeCamsClientTest {
|
|||
assertEquals(439895060, msg.getReceiver());
|
||||
assertEquals(1, msg.getArg1());
|
||||
assertEquals(0, msg.getArg2());
|
||||
assertTrue(msg.getMessage().isBlank());
|
||||
assertTrue(StringUtil.isBlank(msg.getMessage()));
|
||||
|
||||
input = new StringBuilder("00207820 439461784 439895060 12 507930 %7B%22lv%22%3A4%2C%22nm%22%3A%22Nivea%22%2C%22pid%22%3A1%2C%22sid%22%3A439461784%2C%22uid%22%3A507930%2C%22vs%22%3A12%2C%22u%22%3A%7B%22age%22%3A33%2C%22avatar%22%3A1%2C%22blurb%22%3A%22I%20love%20when%20my%20nose%20touch%20your%20belly%20when%20I%20do%20you%20a%20blowjob!%20When%20I%20look%20into%20your%20horny%20eyes%20when%22%2C%22camserv%22%3A1367%2C%22chat_color%22%3A%22FF0000%22%2C%22chat_font%22%3A0%2C%22chat_opt%22%3A1%2C%22ethnic%22%3A%22Caucasian%22%2C%22photos%22%3A74%2C%22profile%22%3A1%2C%22status%22%3A%22%22%7D%2C%22m%22%3A%7B%22camscore%22%3A7505.700%2C%22continent%22%3A%22EU%22%2C%22flags%22%3A605224%2C%22hidecs%22%3Atrue%2C%22kbit%22%3A0%2C%22lastnews%22%3A0%2C%22mg%22%3A0%2C%22missmfc%22%3A2%2C%22new_model%22%3A0%2C%22rank%22%3A0%2C%22rc%22%3A20%2C%22sfw%22%3A0%2C%22topic%22%3A%22hi%253A)%255Bnone%255D-Topless%252C500-snap4life%252C50-spanks%252C180-flash%252C700-10%2520mins%2520of%2520Nora%2520fun%252C666-shot%252C27%252C270%2520%253C3%22%7D%2C%22x%22%3A%7B%22fcext%22%3A%7B%22sm%22%3A%22%22%2C%22sfw%22%3A0%7D%2C%22share%22%3A%7B%22follows%22%3A11%2C%22albums%22%3A0%2C%22clubs%22%3A0%2C%22tm_album%22%3A0%2C%22collections%22%3A0%2C%22stores%22%3A0%2C%22goals%22%3A0%2C%22polls%22%3A0%2C%22things%22%3A0%2C%22recent_album_tm%22%3A0%2C%22recent_club_tm%22%3A0%2C%22recent_collection_tm%22%3A0%2C%22recent_goal_tm%22%3A0%2C%22recent_item_tm%22%3A0%2C%22recent_poll_tm%22%3A0%2C%22recent_story_tm%22%3A0%2C%22recent_album_thumb%22%3A%22%22%2C%22recent_club_thumb%22%3A%22%22%2C%22recent_collection_thumb%22%3A%22%22%2C%22recent_goal_thumb%22%3A%22%22%2C%22recent_item_thumb%22%3A%22%22%2C%22recent_poll_thumb%22%3A%22%22%2C%22recent_story_thumb%22%3A%22%22%2C%22recent_album_title%22%3A%22%22%2C%22recent_club_title%22%3A%22%22%2C%22recent_collection_title%22%3A%22%22%2C%22recent_goal_title%22%3A%22%22%2C%22recent_item_title%22%3A%22%22%2C%22recent_poll_title%22%3A%22%22%2C%22recent_story_title%22%3A%22%22%2C%22recent_album_slug%22%3A%22%22%2C%22recent_collection_slug%22%3A%22%22%2C%22tipmenus%22%3A0%7D%7D%7D");
|
||||
msg = ReflectionUtil.call(client, "parseMessage", input);
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.slf4j.LoggerFactory;
|
|||
import com.squareup.moshi.JsonAdapter;
|
||||
import com.squareup.moshi.Moshi;
|
||||
|
||||
import ctbrec.Config;
|
||||
import ctbrec.Model;
|
||||
import ctbrec.Recording;
|
||||
import ctbrec.io.BandwidthMeter;
|
||||
|
@ -211,6 +212,7 @@ public class RecorderServlet extends AbstractCtbrecServlet {
|
|||
jsonResponse.put("spaceFree", recorder.getFreeSpaceBytes());
|
||||
jsonResponse.put("throughput", BandwidthMeter.getThroughput());
|
||||
jsonResponse.put("throughputTimeframe", BandwidthMeter.MEASURE_TIMEFRAME.getSeconds());
|
||||
jsonResponse.put("minimumSpaceLeftInBytes", Config.getInstance().getSettings().minimumSpaceLeftInBytes);
|
||||
resp.getWriter().write(jsonResponse.toString());
|
||||
break;
|
||||
case "changePriority":
|
||||
|
|
Loading…
Reference in New Issue