Fix Model tab not showing models

This commit is contained in:
Jafea7 2025-05-11 16:41:27 +10:00
parent 656df854e7
commit 70fea40a84
4 changed files with 111 additions and 87 deletions

View File

@ -1,15 +1,15 @@
package ctbrec.ui.sites.stripchat; package ctbrec.ui.sites.stripchat;
import lombok.extern.slf4j.Slf4j;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.sites.stripchat.Stripchat; import ctbrec.sites.stripchat.Stripchat;
import ctbrec.ui.ExternalBrowser; import ctbrec.ui.ExternalBrowser;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Cookie; import okhttp3.Cookie;
import okhttp3.Cookie.Builder; import okhttp3.Cookie.Builder;
import okhttp3.CookieJar; import okhttp3.CookieJar;
import okhttp3.HttpUrl; import okhttp3.HttpUrl;
import org.json.JSONObject; import org.json.JSONObject;
import java.io.IOException; import java.io.IOException;
import java.util.Collections; import java.util.Collections;
import java.util.function.Consumer; import java.util.function.Consumer;

View File

@ -1,17 +1,18 @@
package ctbrec.ui.sites.stripchat; package ctbrec.ui.sites.stripchat;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException; import java.io.IOException;
import ctbrec.sites.stripchat.Stripchat; import ctbrec.sites.stripchat.Stripchat;
import ctbrec.sites.stripchat.StripchatHttpClient; import ctbrec.sites.stripchat.StripchatHttpClient;
import ctbrec.ui.controls.Dialogs; import ctbrec.ui.controls.Dialogs;
import ctbrec.ui.sites.AbstractSiteUi; import ctbrec.ui.sites.AbstractSiteUi;
import ctbrec.ui.sites.ConfigUI; import ctbrec.ui.sites.ConfigUI;
import ctbrec.ui.tabs.TabProvider; import ctbrec.ui.tabs.TabProvider;
import lombok.extern.slf4j.Slf4j;
@Slf4j @Slf4j
public class StripchatSiteUi extends AbstractSiteUi { public class StripchatSiteUi extends AbstractSiteUi {
private StripchatTabProvider tabProvider; private StripchatTabProvider tabProvider;
private StripchatConfigUI configUi; private StripchatConfigUI configUi;
private Stripchat site; private Stripchat site;

View File

@ -1,7 +1,5 @@
package ctbrec.ui.sites.stripchat; package ctbrec.ui.sites.stripchat;
import lombok.extern.slf4j.Slf4j;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.Model; import ctbrec.Model;
import ctbrec.io.HttpException; import ctbrec.io.HttpException;
@ -9,8 +7,10 @@ import ctbrec.sites.stripchat.Stripchat;
import ctbrec.sites.stripchat.StripchatModel; import ctbrec.sites.stripchat.StripchatModel;
import ctbrec.ui.SiteUiFactory; import ctbrec.ui.SiteUiFactory;
import javafx.concurrent.Task; import javafx.concurrent.Task;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Request; import okhttp3.Request;
import org.json.JSONObject; import org.json.JSONObject;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -21,6 +21,7 @@ import static ctbrec.io.HttpConstants.*;
@Slf4j @Slf4j
public class StripchatUpdateService extends AbstractStripchatUpdateService { public class StripchatUpdateService extends AbstractStripchatUpdateService {
private final String url; private final String url;
private final boolean loginRequired; private final boolean loginRequired;
private final Stripchat stripchat; private final Stripchat stripchat;

View File

@ -1,38 +1,35 @@
package ctbrec.sites.stripchat; package ctbrec.sites.stripchat;
import lombok.extern.slf4j.Slf4j;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.StringUtil; import ctbrec.StringUtil;
import ctbrec.io.HttpClient; import ctbrec.io.HttpClient;
import ctbrec.io.HttpException; import ctbrec.io.HttpException;
import lombok.Getter; // import ctbrec.sites.stripchat.Stripchat;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import okhttp3.*; import okhttp3.*;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import java.time.Instant;
import java.util.Base64;
import java.nio.charset.StandardCharsets;
import java.io.IOException; import java.io.IOException;
import java.net.URLDecoder; import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Base64;
import static ctbrec.io.HttpConstants.*; import static ctbrec.io.HttpConstants.*;
import static java.nio.charset.StandardCharsets.UTF_8; import static java.nio.charset.StandardCharsets.UTF_8;
@Slf4j @Slf4j
public class StripchatHttpClient extends HttpClient { public class StripchatHttpClient extends HttpClient {
Stripchat stripchatInstance = new Stripchat();
public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
private long userId = 0; private long userId;
private String csrfToken; private String csrfToken;
@Getter
private String csrfTimestamp; private String csrfTimestamp;
@Getter
private String csrfNotifyTimestamp; private String csrfNotifyTimestamp;
@Getter
private String jwtToken; private String jwtToken;
private Instant jwtTokenExp; private Instant jwtTokenExp;
@ -42,11 +39,9 @@ public class StripchatHttpClient extends HttpClient {
@Override @Override
public boolean login() throws IOException { public boolean login() throws IOException {
// refresh token if needed getCsrfToken(); // Always load CSRF token (as in v5.0.24)
getCsrfToken();
// already logged in if (loggedIn && isJwtTokenValid()) { // Ensure JWT is valid as in v5.0.24
if (loggedIn && isJwtTokenValid()) {
return true; return true;
} }
@ -54,63 +49,75 @@ public class StripchatHttpClient extends HttpClient {
if (checkLoginSuccess()) { if (checkLoginSuccess()) {
loggedIn = true; loggedIn = true;
log.debug("Logged in with cookies"); log.debug("Logged in with cookies");
// Check if CSRF token needs to be loaded after logging in via cookies
if (csrfToken == null) {
loadCsrfToken();
}
return true; return true;
} }
// Proceed to the login HTTP request if not already logged in
String url = Stripchat.getBaseUri() + "/api/front/auth/login"; String url = Stripchat.getBaseUri() + "/api/front/auth/login";
JSONObject requestParams = new JSONObject(); JSONObject requestParams = new JSONObject()
requestParams.put("loginOrEmail", config.getSettings().stripchatUsername); .put("loginOrEmail", config.getSettings().stripchatUsername)
requestParams.put("password", config.getSettings().stripchatPassword); .put("password", config.getSettings().stripchatPassword)
requestParams.put("remember", true); .put("remember", true)
requestParams.put("csrfToken", csrfToken); .put("csrfToken", csrfToken)
requestParams.put("csrfTimestamp", csrfTimestamp); .put("csrfTimestamp", csrfTimestamp)
requestParams.put("csrfNotifyTimestamp", csrfNotifyTimestamp); .put("csrfNotifyTimestamp", csrfNotifyTimestamp);
RequestBody body = RequestBody.Companion.create(requestParams.toString(), JSON); RequestBody body = RequestBody.Companion.create(requestParams.toString(), JSON);
Request request = new Request.Builder() Request request = new Request.Builder()
.url(url) .url(url)
.header(ACCEPT, MIMETYPE_APPLICATION_JSON) .header(ACCEPT, MIMETYPE_APPLICATION_JSON)
.header(USER_AGENT, config.getSettings().httpUserAgent) .header(USER_AGENT, config.getSettings().httpUserAgent)
.header(ORIGIN, Stripchat.getBaseUri()) .header(ORIGIN, Stripchat.getBaseUri())
.header(REFERER, Stripchat.getBaseUri()) .header(REFERER, Stripchat.getBaseUri())
.header(CONTENT_TYPE, MIMETYPE_APPLICATION_JSON) .header(CONTENT_TYPE, MIMETYPE_APPLICATION_JSON)
.post(body) .post(body)
.build(); .build();
try (Response response = execute(request)) { try (Response response = execute(request)) {
if (response.isSuccessful()) { if (response.isSuccessful()) {
JSONObject resp = new JSONObject(response.body().string()); JSONObject resp = new JSONObject(response.body().string());
if (resp.has("user")) { if (resp.has("user")) {
JSONObject user = resp.getJSONObject("user"); JSONObject user = resp.getJSONObject("user");
userId = user.optLong("id"); userId = user.optLong("id");
return true; return true; // Successful login
} else { } else {
return false; return false; // No user found
} }
} else { } else {
log.info("Auto-Login failed: {} {} {}", response.code(), response.message(), url); log.info("Auto-Login failed: {} {} {}", response.code(), response.message(), url);
return false; return false; // Request failed
} }
} }
} }
private void loadCsrfToken() throws IOException { private void loadCsrfToken() throws IOException {
String url = Stripchat.getBaseUri() + "/api/front/v3/config/initial?requestPath=%2F&timezoneOffset=0"; csrfToken = "";
Request request = new Request.Builder() csrfTimestamp = "";
.url(url) csrfNotifyTimestamp = "";
.header(ACCEPT, MIMETYPE_APPLICATION_JSON)
.header(USER_AGENT, config.getSettings().httpUserAgent) String url = Stripchat.getBaseUri() + "/api/front/v3/config/initial?requestPath=%2F&timezoneOffset=0&disableClient=0&uniq=" + stripchatInstance.getUniq();
.header(ORIGIN, Stripchat.getBaseUri()) Request request = buildJsonGetRequest(url);
.header(REFERER, Stripchat.getBaseUri())
.header(CONTENT_TYPE, MIMETYPE_APPLICATION_JSON)
.build();
try (Response response = execute(request)) { try (Response response = execute(request)) {
if (response.isSuccessful()) { if (response.isSuccessful()) {
JSONObject resp = new JSONObject(response.body().string()); JSONObject resp = new JSONObject(response.body().string());
JSONObject data = resp.getJSONObject("initial").getJSONObject("client"); JSONObject initial = resp.optJSONObject("initial");
csrfToken = data.optString("csrfToken"); if (initial != null) {
csrfTimestamp = data.optString("csrfTimestamp"); JSONObject client = initial.optJSONObject("client");
csrfNotifyTimestamp = data.optString("csrfNotifyTimestamp"); if (client != null) {
log.debug("Stripchat token CSRF: {} [{}]", csrfToken, csrfNotifyTimestamp); csrfToken = client.optString("csrfToken");
csrfTimestamp = client.optString("csrfTimestamp");
csrfNotifyTimestamp = client.optString("csrfNotifyTimestamp");
log.debug("Stripchat CSRF token (v3): {} [{}]", csrfToken, csrfNotifyTimestamp);
}
}
if (csrfToken.isBlank()) {
log.debug("Stripchat CSRF token not found");
}
} else { } else {
throw new HttpException(response.code(), response.message()); throw new HttpException(response.code(), response.message());
} }
@ -118,29 +125,30 @@ public class StripchatHttpClient extends HttpClient {
} }
private void loadJwtToken() throws IOException { private void loadJwtToken() throws IOException {
String url = Stripchat.getBaseUri() + "/api/front/v3/config/dynamic"; jwtToken = "";
Request request = new Request.Builder()
.url(url) String url = Stripchat.getBaseUri() + "/api/front/v3/config/dynamic?uniq=" + stripchatInstance.getUniq();
.header(ACCEPT, MIMETYPE_APPLICATION_JSON) Request request = buildJsonGetRequest(url);
.header(USER_AGENT, config.getSettings().httpUserAgent)
.header(ORIGIN, Stripchat.getBaseUri())
.header(REFERER, Stripchat.getBaseUri())
.header(CONTENT_TYPE, MIMETYPE_APPLICATION_JSON)
.build();
try (Response response = execute(request)) { try (Response response = execute(request)) {
if (response.isSuccessful()) { if (response.isSuccessful()) {
JSONObject resp = new JSONObject(response.body().string()); JSONObject resp = new JSONObject(response.body().string());
JSONObject dynamic = resp.getJSONObject("dynamic"); JSONObject dynamic = resp.optJSONObject("dynamic");
jwtToken = dynamic.optString("jwtToken"); if (dynamic != null) {
if (StringUtil.isNotBlank(jwtToken)) { jwtToken = dynamic.optString("jwtToken");
}
if (jwtToken != null && !jwtToken.isBlank()) {
String[] parts = jwtToken.split("\\."); String[] parts = jwtToken.split("\\.");
if (parts.length > 1) { if (parts.length > 1) {
String decString = new String(Base64.getDecoder().decode(parts[1]), StandardCharsets.UTF_8); String payload = new String(Base64.getDecoder().decode(parts[1]), StandardCharsets.UTF_8);
JSONObject body = new JSONObject(decString); JSONObject body = new JSONObject(payload);
jwtTokenExp = Instant.ofEpochSecond(body.optLong("exp")); jwtTokenExp = Instant.ofEpochSecond(body.optLong("exp"));
} }
log.debug("Stripchat JWT token (v3): {} [{}]", jwtToken, jwtTokenExp);
} else {
log.debug("Stripchat JWT token not found");
} }
log.debug("Stripchat token JWT: {} [{}]", jwtToken, jwtTokenExp);
} else { } else {
throw new HttpException(response.code(), response.message()); throw new HttpException(response.code(), response.message());
} }
@ -152,22 +160,22 @@ public class StripchatHttpClient extends HttpClient {
* @throws IOException * @throws IOException
*/ */
public boolean checkLoginSuccess() throws IOException { public boolean checkLoginSuccess() throws IOException {
getJwtToken(); try {
getCsrfToken(); getJwtToken();
getCsrfToken();
} catch (Exception e) {
log.info("Login check returned unsuccessful: {}", e.getLocalizedMessage());
jwtToken = "";
csrfToken = "";
return false;
}
return StringUtil.isNotBlank(jwtToken) && StringUtil.isNotBlank(csrfToken); return StringUtil.isNotBlank(jwtToken) && StringUtil.isNotBlank(csrfToken);
} }
public long getUserId() throws JSONException, IOException { public long getUserId() throws JSONException, IOException {
if (userId == 0) { if (userId == 0L) {
String url = Stripchat.getBaseUri() + "/api/front/users/username/" + config.getSettings().stripchatUsername; String url = Stripchat.getBaseUri() + "/api/front/users/username/" + config.getSettings().stripchatUsername;
Request request = new Request.Builder() Request request = buildJsonGetRequest(url);
.url(url)
.header(ACCEPT, MIMETYPE_APPLICATION_JSON)
.header(USER_AGENT, config.getSettings().httpUserAgent)
.header(ORIGIN, Stripchat.getBaseUri())
.header(REFERER, Stripchat.getBaseUri())
.header(CONTENT_TYPE, MIMETYPE_APPLICATION_JSON)
.build();
try (Response response = execute(request)) { try (Response response = execute(request)) {
if (response.isSuccessful()) { if (response.isSuccessful()) {
JSONObject resp = new JSONObject(response.body().string()); JSONObject resp = new JSONObject(response.body().string());
@ -186,6 +194,7 @@ public class StripchatHttpClient extends HttpClient {
Cookie cookie = getCookieJar().getCookie(HttpUrl.parse(Stripchat.getBaseUri()), "baseAmpl"); Cookie cookie = getCookieJar().getCookie(HttpUrl.parse(Stripchat.getBaseUri()), "baseAmpl");
String json = URLDecoder.decode(cookie.value(), UTF_8); String json = URLDecoder.decode(cookie.value(), UTF_8);
JSONObject ampl = new JSONObject(json); JSONObject ampl = new JSONObject(json);
ampl.put("ep", new JSONObject());
return ampl; return ampl;
} catch (Exception ex) { } catch (Exception ex) {
return new JSONObject(); return new JSONObject();
@ -203,11 +212,11 @@ public class StripchatHttpClient extends HttpClient {
public String getCsrfToken() { public String getCsrfToken() {
try { try {
if (!isTokenValid()) { if (!isTokenValid()) {
loadCsrfToken(); loadCsrfToken(); // Uses v3 API load
} }
} catch (Exception e) { } catch (Exception e) {
log.debug("Invalid CSRF Token {}: {}", csrfToken, e.getMessage()); log.debug("Invalid CSRF Token {}: {}", csrfToken, e.getMessage());
csrfToken = ""; csrfToken = ""; // Reset token on failure
} }
return csrfToken; return csrfToken;
} }
@ -215,11 +224,11 @@ public class StripchatHttpClient extends HttpClient {
public String getJwtToken() { public String getJwtToken() {
try { try {
if (!isJwtTokenValid()) { if (!isJwtTokenValid()) {
loadJwtToken(); loadJwtToken(); // Uses v3 API load
} }
} catch (Exception e) { } catch (Exception e) {
log.debug("Invalid JWT Token {}: {}", jwtToken, e.getMessage()); log.debug("Invalid JWT Token {}: {}", jwtToken, e.getMessage());
jwtToken = ""; jwtToken = ""; // Reset token on failure
} }
return jwtToken; return jwtToken;
} }
@ -228,7 +237,7 @@ public class StripchatHttpClient extends HttpClient {
if (StringUtil.isBlank(jwtToken) || jwtTokenExp == null) { if (StringUtil.isBlank(jwtToken) || jwtTokenExp == null) {
return false; return false;
} }
return jwtTokenExp.isAfter(Instant.now()); return jwtTokenExp.isAfter(Instant.now().minus(3L, ChronoUnit.HOURS));
} }
private boolean isTokenValid() { private boolean isTokenValid() {
@ -237,9 +246,22 @@ public class StripchatHttpClient extends HttpClient {
} }
try { try {
Instant notifyTime = Instant.parse(csrfNotifyTimestamp); Instant notifyTime = Instant.parse(csrfNotifyTimestamp);
return notifyTime.isAfter(Instant.now()); return notifyTime.isAfter(Instant.now().minus(3L, ChronoUnit.HOURS));
} catch (Exception e) { }
catch (Exception e) {
return false; return false;
} }
} }
private Request buildJsonGetRequest(String url) {
return new Request.Builder()
.url(url)
.header(ACCEPT, MIMETYPE_APPLICATION_JSON)
.header(USER_AGENT, config.getSettings().httpUserAgent)
.header(ORIGIN, Stripchat.getBaseUri())
.header(REFERER, Stripchat.getBaseUri())
.header(CONTENT_TYPE, MIMETYPE_APPLICATION_JSON)
.build();
}
} }