Code cleanup

This commit is contained in:
0xb00bface 2021-05-14 14:42:16 +02:00
parent bc72aca69e
commit 7d23ebccfe
3 changed files with 245 additions and 238 deletions

View File

@ -62,7 +62,6 @@ public class DashDownload extends AbstractDownload {
private boolean running = false;
private File targetFile;
private File finalFile;
public DashDownload(HttpClient httpClient, String manifestUrl) {
this.httpClient = httpClient;
@ -92,7 +91,7 @@ public class DashDownload extends AbstractDownload {
throw httpException;
} else {
LOG.debug("Couldn't load manifest", httpException);
waitSomeTime(100 * tries);
waitSomeTime(100l * tries);
}
} else {
internalStop();
@ -114,7 +113,7 @@ public class DashDownload extends AbstractDownload {
int downloaded = downloadInitChunksForVideoAndAudio(isVideo, mpd, segmentTemplate, representation);
String media = segmentTemplate.getMedia();
media = media.replaceAll("\\$RepresentationID\\$", representation.getId()); // NOSONAR
media = media.replace("$RepresentationID$", representation.getId()); // NOSONAR
List<S> segments = segmentTemplate.getSegmentTimeline().getS();
if (!segments.isEmpty()) {
@ -128,7 +127,7 @@ public class DashDownload extends AbstractDownload {
} else {
lastAudioTimestamp = timestamp;
}
String segmentUrl = media.replaceAll("\\$Time\\$", timestamp.toString());
String segmentUrl = media.replace("$Time$", timestamp.toString());
duration = s.getD();
URL absUrl = new URL(new URL(mpd.getLocation().get(0)), segmentUrl);
download(downloadDir.toFile().getCanonicalPath(), absUrl, isVideo);
@ -157,7 +156,7 @@ public class DashDownload extends AbstractDownload {
int loadedFileCount = 0;
if (isVideo && !videoInitLoaded || !isVideo && !audioInitLoaded) {
String initialization = segmentTemplate.getInitializationAttribute();
initialization = initialization.replaceAll("\\$RepresentationID\\$", representation.getId());
initialization = initialization.replace("$RepresentationID$", representation.getId());
URL initUrl = new URL(new URL(mpd.getLocation().get(0)), initialization);
File file = download(downloadDir.toFile().getCanonicalPath(), initUrl, isVideo);
if (file != null) {
@ -198,7 +197,7 @@ public class DashDownload extends AbstractDownload {
try (Response response = httpClient.execute(request)) {
if (!response.isSuccessful()) {
LOG.trace("Loading segment failed, try {}, {} size:{} {}", tries, response.code(), response.headers().values(CONTENT_LENGTH), url);
waitSomeTime(tries * 80);
waitSomeTime(tries * 80l);
} else {
InputStream in = response.body().byteStream();
String absFile = url.getFile();
@ -229,7 +228,7 @@ public class DashDownload extends AbstractDownload {
this.config = config;
this.model = model;
this.startTime = startTime;
finalFile = Config.getInstance().getFileForRecording(model, "mp4", startTime);
File finalFile = Config.getInstance().getFileForRecording(model, "mp4", startTime);
targetFile = new File(finalFile.getParentFile(), finalFile.getName() + ".part");
downloadDir = targetFile.toPath();
}
@ -260,6 +259,9 @@ public class DashDownload extends AbstractDownload {
} else {
throw e;
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
LOG.error("Error while downloading dash stream", e);
} catch (Exception e) {
LOG.error("Error while downloading dash stream", e);
} finally {
@ -422,8 +424,7 @@ public class DashDownload extends AbstractDownload {
@Override
public void finalizeDownload() {
// TODO Auto-generated method stub
// nothing to do here
}
}

View File

@ -51,7 +51,7 @@ public class Flirt4FreeModel extends AbstractModel {
private String streamHost;
private String streamUrl;
int[] resolution = new int[2];
private Object monitor = new Object();
private transient Object monitor = new Object();
private boolean online = false;
private boolean isInteractiveShow = false;
private boolean isNew = false;
@ -81,9 +81,22 @@ public class Flirt4FreeModel extends AbstractModel {
.build();
try (Response response = getSite().getHttpClient().execute(request)) {
if (response.isSuccessful()) {
String body = response.body().string();
parseOnlineState(response.body().string());
} else {
throw new HttpException(response.code(), response.message());
}
}
} finally {
lastOnlineRequest = System.currentTimeMillis();
releaseSlot();
}
}
return online;
}
private void parseOnlineState(String body) {
if (body.trim().isEmpty()) {
return false;
return;
}
JSONObject json = new JSONObject(body);
online = Objects.equals(json.optString("status"), "online"); // online is true, even if the model is in private or away
@ -96,16 +109,6 @@ public class Flirt4FreeModel extends AbstractModel {
onlineState = Model.State.OFFLINE;
}
}
} else {
throw new HttpException(response.code(), response.message());
}
}
} finally {
lastOnlineRequest = System.currentTimeMillis();
releaseSlot();
}
}
return online;
}
private void updateModelId(JSONObject json) {
@ -120,7 +123,7 @@ public class Flirt4FreeModel extends AbstractModel {
}
}
private void loadModelInfo() throws IOException, InterruptedException {
private void loadModelInfo() throws IOException {
String url = getSite().getBaseUrl() + "/webservices/chat-room-interface.php?a=login_room&model_id=" + id;
LOG.trace("Loading url {}", url);
Request request = new Request.Builder()
@ -135,7 +138,6 @@ public class Flirt4FreeModel extends AbstractModel {
if (response.isSuccessful()) {
JSONObject json = new JSONObject(response.body().string());
if (json.optString("status").equals("success")) {
// LOG.debug("chat-room-interface {}", json.toString(2));
JSONObject config = json.getJSONObject("config");
JSONObject performer = config.getJSONObject("performer");
setUrl(getSite().getBaseUrl() + "/rooms/" + getName() + '/');
@ -191,6 +193,7 @@ public class Flirt4FreeModel extends AbstractModel {
}
masterPlaylist = getMasterPlaylist();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new ExecutionException(e);
}
List<StreamSource> sources = new ArrayList<>();
@ -236,7 +239,7 @@ public class Flirt4FreeModel extends AbstractModel {
private void loadStreamUrl() throws IOException, InterruptedException {
loadModelInfo();
Objects.requireNonNull(chatHost, "chatHost is null");
String h = chatHost.replaceAll("chat", "chat-vip");
String h = chatHost.replace("chat", "chat-vip");
String url = "https://" + h + "/chat?token=" + URLEncoder.encode(chatToken, "utf-8") + "&port_to_be=" + chatPort;
LOG.trace("Opening chat websocket {}", url);
Request req = new Request.Builder()
@ -258,10 +261,9 @@ public class Flirt4FreeModel extends AbstractModel {
public void onMessage(WebSocket webSocket, String text) {
LOG.trace("Chat wbesocket for {}: {}", getName(), text);
JSONObject json = new JSONObject(text);
//LOG.debug("WS {}", text);
if (json.optString("command").equals("8011")) {
JSONObject data = json.getJSONObject("data");
streamHost = data.getString("stream_host"); // TODO look, if the stream_host is equal to the one encoded in base64 in some of the ajax requests (parameters)
streamHost = data.getString("stream_host");
online = true;
isInteractiveShow = data.optString("devices").equals("1");
String roomState = data.optString("room_state");
@ -285,7 +287,7 @@ public class Flirt4FreeModel extends AbstractModel {
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
LOG.error("Chat websocket for {} failed", getName(), t);
synchronized (monitor) {
monitor.notify();
monitor.notifyAll();
}
response.close();
}
@ -294,7 +296,7 @@ public class Flirt4FreeModel extends AbstractModel {
public void onClosed(WebSocket webSocket, int code, String reason) {
LOG.trace("Chat websocket for {} closed {} {}", getName(), code, reason);
synchronized (monitor) {
monitor.notify();
monitor.notifyAll();
}
}
});
@ -311,25 +313,15 @@ public class Flirt4FreeModel extends AbstractModel {
@Override
public void invalidateCacheEntries() {
// nothing to do here
}
@Override
public void receiveTip(Double tokens) throws IOException {
try {
// if(tokens < 50 || tokens > 750000) {
// throw new RuntimeException("Tip amount has to be between 50 and 750000");
// }
// make sure we are logged in and all necessary model data is available
getSite().login();
acquireSlot();
try {
loadStreamUrl();
} catch (InterruptedException e) {
throw new IOException("Couldn't send tip", e);
} finally {
releaseSlot();
}
fetchStreamUrl();
// send the tip
int giftId = isInteractiveShow ? 775 : 171;
@ -370,10 +362,23 @@ public class Flirt4FreeModel extends AbstractModel {
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IOException("Couldn't acquire request slot", e);
}
}
private void fetchStreamUrl() throws InterruptedException, IOException {
acquireSlot();
try {
loadStreamUrl();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IOException("Couldn't send tip", e);
} finally {
releaseSlot();
}
}
private String getUserIdt() throws IOException, InterruptedException {
if (userIdt.isEmpty()) {
acquireSlot();
@ -429,6 +434,7 @@ public class Flirt4FreeModel extends AbstractModel {
try {
return changeFavoriteStatus(true);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IOException("Couldn't change follow status for model " + getName(), e);
}
}
@ -438,7 +444,10 @@ public class Flirt4FreeModel extends AbstractModel {
try {
isOnline(true);
return changeFavoriteStatus(false);
} catch (ExecutionException | InterruptedException e) {
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IOException("Couldn't change follow status for model " + getName(), e);
} catch (ExecutionException e) {
throw new IOException("Couldn't change follow status for model " + getName(), e);
}
}
@ -509,12 +518,10 @@ public class Flirt4FreeModel extends AbstractModel {
}
private void acquireSlot() throws InterruptedException {
//LOG.debug("Acquire: {} - Queue: {}", requestThrottle.availablePermits(), requestThrottle.getQueueLength());
requestThrottle.acquire();
long now = System.currentTimeMillis();
long millisSinceLastRequest = now - lastRequest;
if(millisSinceLastRequest < 500) {
//LOG.debug("Sleeping: {}", (500-millisSinceLastRequest));
Thread.sleep(500 - millisSinceLastRequest);
}
}
@ -522,6 +529,5 @@ public class Flirt4FreeModel extends AbstractModel {
private void releaseSlot() {
lastRequest = System.currentTimeMillis();
requestThrottle.release();
// LOG.debug("Release: {}", requestThrottle.availablePermits());
}
}

View File

@ -4,6 +4,7 @@ import static javax.servlet.http.HttpServletResponse.*;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.time.Instant;
@ -57,12 +58,11 @@ public class RecorderServlet extends AbstractCtbrecServlet {
String json = null;
try {
PrintWriter responseWriter = resp.getWriter();
json = body(req);
boolean isRequestAuthenticated = checkAuthentication(req, json);
if (!isRequestAuthenticated) {
resp.setStatus(SC_UNAUTHORIZED);
String response = "{\"status\": \"error\", \"msg\": \"HMAC does not match\"}";
resp.getWriter().write(response);
sendError(resp, SC_UNAUTHORIZED, "{\"status\": \"error\", \"msg\": \"HMAC does not match\"}");
return;
}
@ -76,24 +76,27 @@ public class RecorderServlet extends AbstractCtbrecServlet {
JsonAdapter<Request> requestAdapter = moshi.adapter(Request.class);
Request request = requestAdapter.fromJson(json);
if (request.action != null) {
sendError(resp, SC_BAD_REQUEST, "{\"status\": \"error\", \"msg\": \"action is missing\"}");
return;
}
switch (request.action) {
case "start":
LOG.debug("Starting recording for model {} - {}", request.model.getName(), request.model.getUrl());
recorder.addModel(request.model);
String response = "{\"status\": \"success\", \"msg\": \"Recording started\"}";
resp.getWriter().write(response);
responseWriter.write(response);
break;
case "startByUrl":
LOG.debug("Starting recording for model {}", request.model.getUrl());
startByUrl(request);
response = "{\"status\": \"success\", \"msg\": \"Recording started\"}";
resp.getWriter().write(response);
responseWriter.write(response);
break;
case "startByName":
LOG.debug("Starting recording for model {}", request.model.getUrl());
startByName(request);
response = "{\"status\": \"success\", \"msg\": \"Recording started\"}";
resp.getWriter().write(response);
responseWriter.write(response);
break;
case "stop":
GlobalThreadPool.submit(() -> {
@ -104,7 +107,7 @@ public class RecorderServlet extends AbstractCtbrecServlet {
}
});
response = "{\"status\": \"success\", \"msg\": \"Stopping recording\"}";
resp.getWriter().write(response);
responseWriter.write(response);
break;
case "stopAt":
GlobalThreadPool.submit(() -> {
@ -115,86 +118,85 @@ public class RecorderServlet extends AbstractCtbrecServlet {
}
});
response = "{\"status\": \"success\", \"msg\": \"Stopping recording\"}";
resp.getWriter().write(response);
responseWriter.write(response);
break;
case "list":
resp.getWriter().write("{\"status\": \"success\", \"msg\": \"List of models\", \"models\": [");
responseWriter.write("{\"status\": \"success\", \"msg\": \"List of models\", \"models\": [");
JsonAdapter<Model> modelAdapter = new ModelJsonAdapter();
List<Model> models = recorder.getModels();
for (Iterator<Model> iterator = models.iterator(); iterator.hasNext();) {
Model model = iterator.next();
resp.getWriter().write(modelAdapter.toJson(model));
responseWriter.write(modelAdapter.toJson(model));
if (iterator.hasNext()) {
resp.getWriter().write(',');
responseWriter.write(',');
}
}
resp.getWriter().write("]}");
responseWriter.write("]}");
break;
case "listOnline":
resp.getWriter().write("{\"status\": \"success\", \"msg\": \"List of online models\", \"models\": [");
responseWriter.write("{\"status\": \"success\", \"msg\": \"List of online models\", \"models\": [");
modelAdapter = new ModelJsonAdapter();
models = recorder.getOnlineModels();
for (Iterator<Model> iterator = models.iterator(); iterator.hasNext();) {
Model model = iterator.next();
resp.getWriter().write(modelAdapter.toJson(model));
responseWriter.write(modelAdapter.toJson(model));
if (iterator.hasNext()) {
resp.getWriter().write(',');
responseWriter.write(',');
}
}
resp.getWriter().write("]}");
responseWriter.write("]}");
break;
case "recordings":
resp.getWriter().write("{\"status\": \"success\", \"msg\": \"List of recordings\", \"recordings\": [");
responseWriter.write("{\"status\": \"success\", \"msg\": \"List of recordings\", \"recordings\": [");
JsonAdapter<Recording> recAdapter = moshi.adapter(Recording.class);
List<Recording> recordings = recorder.getRecordings();
for (Iterator<Recording> iterator = recordings.iterator(); iterator.hasNext();) {
Recording recording = iterator.next();
String recJSON = recAdapter.toJson(recording);
LOG.debug("Rec: {}", recJSON);
resp.getWriter().write(recJSON);
responseWriter.write(recJSON);
if (iterator.hasNext()) {
resp.getWriter().write(',');
responseWriter.write(',');
}
}
resp.getWriter().write("]}");
responseWriter.write("]}");
break;
case "delete":
recorder.delete(request.recording);
recAdapter = moshi.adapter(Recording.class);
resp.getWriter().write("{\"status\": \"success\", \"msg\": \"List of recordings\", \"recordings\": [");
resp.getWriter().write(recAdapter.toJson(request.recording));
resp.getWriter().write("]}");
responseWriter.write("{\"status\": \"success\", \"msg\": \"List of recordings\", \"recordings\": [");
responseWriter.write(recAdapter.toJson(request.recording));
responseWriter.write("]}");
break;
case "pin":
recorder.pin(request.recording);
recAdapter = moshi.adapter(Recording.class);
resp.getWriter().write("{\"status\": \"success\", \"msg\": \"List of recordings\", \"recordings\": [");
resp.getWriter().write(recAdapter.toJson(request.recording));
resp.getWriter().write("]}");
responseWriter.write("{\"status\": \"success\", \"msg\": \"List of recordings\", \"recordings\": [");
responseWriter.write(recAdapter.toJson(request.recording));
responseWriter.write("]}");
break;
case "unpin":
recorder.unpin(request.recording);
recAdapter = moshi.adapter(Recording.class);
resp.getWriter().write("{\"status\": \"success\", \"msg\": \"Note saved\", \"recordings\": [");
resp.getWriter().write(recAdapter.toJson(request.recording));
resp.getWriter().write("]}");
responseWriter.write("{\"status\": \"success\", \"msg\": \"Note saved\", \"recordings\": [");
responseWriter.write(recAdapter.toJson(request.recording));
responseWriter.write("]}");
break;
case "setNote":
recorder.setNote(request.recording, request.recording.getNote());
recAdapter = moshi.adapter(Recording.class);
resp.getWriter().write("{\"status\": \"success\", \"msg\": \"List of recordings\", \"recordings\": [");
resp.getWriter().write(recAdapter.toJson(request.recording));
resp.getWriter().write("]}");
responseWriter.write("{\"status\": \"success\", \"msg\": \"List of recordings\", \"recordings\": [");
responseWriter.write(recAdapter.toJson(request.recording));
responseWriter.write("]}");
break;
case "rerunPostProcessing":
recorder.rerunPostProcessing(request.recording);
recAdapter = moshi.adapter(Recording.class);
resp.getWriter().write("{\"status\": \"success\", \"msg\": \"Post-Processing triggered\"}");
responseWriter.write("{\"status\": \"success\", \"msg\": \"Post-Processing triggered\"}");
break;
case "switch":
recorder.switchStreamSource(request.model);
response = "{\"status\": \"success\", \"msg\": \"Resolution switched\"}";
resp.getWriter().write(response);
responseWriter.write(response);
break;
case "suspend":
LOG.debug("Suspend recording for model {} - {}", request.model.getName(), request.model.getUrl());
@ -206,13 +208,13 @@ public class RecorderServlet extends AbstractCtbrecServlet {
}
});
response = "{\"status\": \"success\", \"msg\": \"Suspending recording\"}";
resp.getWriter().write(response);
responseWriter.write(response);
break;
case "resume":
LOG.debug("Resume recording for model {} - {}", request.model.getName(), request.model.getUrl());
recorder.resumeRecording(request.model);
response = "{\"status\": \"success\", \"msg\": \"Recording resumed\"}";
resp.getWriter().write(response);
responseWriter.write(response);
break;
case "space":
JSONObject jsonResponse = new JSONObject();
@ -222,22 +224,22 @@ public class RecorderServlet extends AbstractCtbrecServlet {
jsonResponse.put("throughput", BandwidthMeter.getThroughput());
jsonResponse.put("throughputTimeframe", BandwidthMeter.getTimeframe().toMillis());
jsonResponse.put("minimumSpaceLeftInBytes", Config.getInstance().getSettings().minimumSpaceLeftInBytes);
resp.getWriter().write(jsonResponse.toString());
responseWriter.write(jsonResponse.toString());
break;
case "changePriority":
recorder.priorityChanged(request.model);
response = "{\"status\": \"success\"}";
resp.getWriter().write(response);
responseWriter.write(response);
break;
case "pauseRecorder":
recorder.pause();
response = "{\"status\": \"success\"}";
resp.getWriter().write(response);
responseWriter.write(response);
break;
case "resumeRecorder":
recorder.resume();
response = "{\"status\": \"success\"}";
resp.getWriter().write(response);
responseWriter.write(response);
break;
case "saveModelGroup":
recorder.saveModelGroup(request.modelGroup);
@ -251,29 +253,27 @@ public class RecorderServlet extends AbstractCtbrecServlet {
sendModelGroups(resp, recorder.getModelGroups());
break;
default:
resp.setStatus(SC_BAD_REQUEST);
response = "{\"status\": \"error\", \"msg\": \"Unknown action ["+request.action+"]\"}";
resp.getWriter().write(response);
sendError(resp, SC_BAD_REQUEST, "{\"status\": \"error\", \"msg\": \"Unknown action [" + request.action + "]\"}");
break;
}
} else {
resp.setStatus(SC_BAD_REQUEST);
String response = "{\"status\": \"error\", \"msg\": \"action is missing\"}";
resp.getWriter().write(response);
}
} catch(Throwable t) {
} catch(Exception e) {
resp.setStatus(SC_INTERNAL_SERVER_ERROR);
JSONObject response = new JSONObject();
response.put("status", "error");
response.put("msg", t.getMessage());
response.put("msg", e.getMessage());
resp.getWriter().write(response.toString());
LOG.error("Unexpected error", t);
LOG.error("Unexpected error", e);
if (json != null) {
LOG.debug("Request: {}", json);
}
}
}
private void sendError(HttpServletResponse resp, int code, String body) throws IOException {
resp.setStatus(code);
resp.getWriter().write(body);
}
private void sendModelGroups(HttpServletResponse resp, Set<ModelGroup> modelGroups) throws IOException {
JSONObject jsonResponse = new JSONObject();
jsonResponse.put("status", "success");