From 1c8d9bf67890569033904dfa1dfdc373d95e8bf2 Mon Sep 17 00:00:00 2001 From: 0xb00bface <0xboobface@gmail.com> Date: Sun, 29 Oct 2023 14:23:33 +0100 Subject: [PATCH] Use the thumbnail for the online check by @winkru In case a model is not online, CB returns a default image. We do a HEAD request and check the size of the response. If it is 21971 bytes, we assume that it is the default image and also that the model is offline. The request hits the CDN instead of the main site, so request throttling should not kick in. --- .../sites/chaturbate/ChaturbateModel.java | 42 +++++++++++++++---- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/common/src/main/java/ctbrec/sites/chaturbate/ChaturbateModel.java b/common/src/main/java/ctbrec/sites/chaturbate/ChaturbateModel.java index e01d3920..3a50e3d2 100644 --- a/common/src/main/java/ctbrec/sites/chaturbate/ChaturbateModel.java +++ b/common/src/main/java/ctbrec/sites/chaturbate/ChaturbateModel.java @@ -55,9 +55,15 @@ public class ChaturbateModel extends AbstractModel { // NOSONAR public boolean isOnline(boolean ignoreCache) throws IOException, ExecutionException, InterruptedException { String roomStatus; if (ignoreCache) { - StreamInfo info = loadStreamInfo(); - roomStatus = Optional.ofNullable(info).map(i -> i.room_status).orElse(""); - LOG.trace("Model {} room status: {}", getName(), Optional.ofNullable(info).map(i -> i.room_status).orElse("unknown")); + if (isOffline()) { + roomStatus = "offline"; + onlineState = State.OFFLINE; + LOG.trace("Model {} offline", getName()); + } else { + StreamInfo info = getStreamInfo(); + roomStatus = Optional.ofNullable(info).map(i -> i.room_status).orElse(""); + LOG.trace("Model {} room status: {}", getName(), Optional.ofNullable(info).map(i -> i.room_status).orElse("unknown")); + } } else { StreamInfo info = getStreamInfo(true); roomStatus = Optional.ofNullable(info).map(i -> i.room_status).orElse(""); @@ -65,6 +71,24 @@ public class ChaturbateModel extends AbstractModel { // NOSONAR return Objects.equals(PUBLIC, roomStatus); } + private boolean isOffline() { + String normalizedName = getName().toLowerCase().trim(); + String previewUrl = "https://roomimg.stream.highwebmedia.com/ri/" + normalizedName + ".jpg?" + Instant.now().getEpochSecond(); + Request req = new Request.Builder() + .url(previewUrl) + .header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent) + .head() + .build(); + try (Response response = getSite().getHttpClient().execute(req)) { + if (response.isSuccessful()) { + return response.header("Content-Length", "0").equals("21971"); + } + } catch (Exception ex) { + // fail silently + } + return false; + } + @Override public int[] getStreamResolution(boolean failFast) throws ExecutionException { if (failFast) { @@ -97,8 +121,12 @@ public class ChaturbateModel extends AbstractModel { // NOSONAR if (failFast) { setOnlineStateByRoomStatus(Optional.ofNullable(streamInfo).map(si -> si.room_status).orElse("Unknown")); } else { - streamInfo = loadStreamInfo(); - setOnlineStateByRoomStatus(streamInfo.room_status); + if (isOffline()) { + onlineState = OFFLINE; + } else { + streamInfo = loadStreamInfo(); + setOnlineStateByRoomStatus(streamInfo.room_status); + } } return onlineState; } @@ -233,7 +261,7 @@ public class ChaturbateModel extends AbstractModel { // NOSONAR } private StreamInfo loadStreamInfo() throws IOException { - if (Duration.between(lastStreamInfoRequest, Instant.now()).getSeconds() < 2) { + if (streamInfo != null && Duration.between(lastStreamInfoRequest, Instant.now()).getSeconds() < 5) { return streamInfo; } RequestBody body = new FormBody.Builder() @@ -250,7 +278,7 @@ public class ChaturbateModel extends AbstractModel { // NOSONAR lastStreamInfoRequest = Instant.now(); if (response.isSuccessful()) { String content = response.body().string(); - LOG.trace("Raw stream info: {}", content); + LOG.trace("Raw stream info for model {}: {}", getName(), content); Moshi moshi = new Moshi.Builder().build(); JsonAdapter adapter = moshi.adapter(StreamInfo.class); streamInfo = adapter.fromJson(content);