Add online/offline switch on followed tab for Stripchat

This commit is contained in:
0xb00bface 2023-11-05 15:21:24 +01:00
parent b07a478d03
commit c376f30c56
3 changed files with 137 additions and 134 deletions

View File

@ -4,14 +4,17 @@ import ctbrec.sites.stripchat.Stripchat;
import ctbrec.ui.tabs.FollowedTab;
import ctbrec.ui.tabs.ThumbOverviewTab;
import javafx.concurrent.WorkerStateEvent;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.RadioButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.HBox;
public class StripchatFollowedTab extends ThumbOverviewTab implements FollowedTab {
private Label status;
boolean showOnline = true;
public StripchatFollowedTab(String title, Stripchat stripchat) {
super(title, new StripchatFollowedUpdateService(stripchat), stripchat);
@ -19,6 +22,34 @@ public class StripchatFollowedTab extends ThumbOverviewTab implements FollowedTa
grid.getChildren().add(status);
}
@Override
protected void createGui() {
super.createGui();
addOnlineOfflineSelector();
}
private void addOnlineOfflineSelector() {
var group = new ToggleGroup();
var online = new RadioButton("online");
online.setToggleGroup(group);
var offline = new RadioButton("offline");
offline.setToggleGroup(group);
pagination.getChildren().add(online);
pagination.getChildren().add(offline);
HBox.setMargin(online, new Insets(5, 5, 5, 40));
HBox.setMargin(offline, new Insets(5, 5, 5, 5));
online.setSelected(true);
group.selectedToggleProperty().addListener(e -> {
if (online.isSelected()) {
((StripchatFollowedUpdateService) updateService).setOnline(true);
} else {
((StripchatFollowedUpdateService) updateService).setOnline(false);
}
queue.clear();
updateService.restart();
});
}
@Override
protected void onSuccess() {
grid.getChildren().remove(status);

View File

@ -8,27 +8,30 @@ import ctbrec.sites.stripchat.StripchatHttpClient;
import ctbrec.sites.stripchat.StripchatModel;
import ctbrec.ui.SiteUiFactory;
import javafx.concurrent.Task;
import okhttp3.HttpUrl;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Request;
import okhttp3.Response;
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.IOException;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.*;
import static ctbrec.Model.State.*;
import static ctbrec.io.HttpConstants.*;
@Slf4j
public class StripchatFollowedUpdateService extends AbstractStripchatUpdateService {
private static final int PAGE_SIZE = 48;
private static final String FAVORITES = "/favorites";
private static final Random RNG = new Random();
private static final int MODELS_PER_PAGE = 60;
private final Stripchat stripchat;
private final boolean loginRequired;
private String url;
public StripchatFollowedUpdateService(Stripchat stripchat) {
this.stripchat = stripchat;
this.loginRequired = true;
this.url = stripchat.getBaseUrl() + "/api/front/models/favorites?sortBy=lastAdded";
}
@Override
@ -36,97 +39,80 @@ public class StripchatFollowedUpdateService extends AbstractStripchatUpdateServi
return new Task<>() {
@Override
public List<Model> call() throws IOException {
return loadModels();
}
};
}
private List<Model> loadModels() throws IOException {
int startIndex = (getPage() - 1) * PAGE_SIZE;
JSONArray favoriteModelIds = loadFavoriteModelIds();
List<Integer> modelIdsToLoad = new ArrayList<>(PAGE_SIZE);
List<Model> models;
if (startIndex < favoriteModelIds.length()) {
int modelsOnPage = Math.min(PAGE_SIZE, favoriteModelIds.length() - startIndex - 1);
for (var i = 0; i < modelsOnPage; i++) {
modelIdsToLoad.add(favoriteModelIds.getInt(startIndex + i));
}
models = loadModels(modelIdsToLoad);
} else {
models = Collections.emptyList();
}
return models;
}
private List<Model> loadModels(List<Integer> modelIdsToLoad) throws IOException {
List<Model> models = new ArrayList<>();
var urlBuilder = HttpUrl.parse(stripchat.getBaseUrl() + "/api/front/models/list").newBuilder();
for (var i = 0; i < modelIdsToLoad.size(); i++) {
urlBuilder.addQueryParameter("modelIds[" + i + "]", modelIdsToLoad.get(i).toString());
}
var request = new Request.Builder()
.url(urlBuilder.build())
.header(ACCEPT, "*/*")
.header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
.header(REFERER, Stripchat.baseUri + FAVORITES)
.header(CONTENT_TYPE, MIMETYPE_APPLICATION_JSON)
.build();
try (var response = stripchat.getHttpClient().execute(request)) {
if (response.isSuccessful()) {
var json = new JSONObject(response.body().string());
if (json.has("models")) {
var users = json.getJSONArray("models");
for (var i = 0; i < users.length(); i++) {
var user = users.getJSONObject(i);
StripchatModel model = stripchat.createModel(user.optString("username"));
model.setDescription(user.optString("description"));
model.setPreview(getPreviewUrl(user));
model.setOnlineState(mapStatus(user.optString("status")));
model.setLastSeen(Instant.now());
models.add(model);
if (loginRequired && !stripchat.credentialsAvailable()) {
return Collections.emptyList();
} else {
int offset = (getPage() - 1) * MODELS_PER_PAGE;
int limit = MODELS_PER_PAGE;
String paginatedUrl = url + "&offset=" + offset + "&limit=" + limit + "&uniq=" + getUniq();
log.debug("Fetching page {}", paginatedUrl);
if (loginRequired) {
SiteUiFactory.getUi(stripchat).login();
}
String jwtToken = ((StripchatHttpClient) stripchat.getHttpClient()).getJwtToken();
Request request = new Request.Builder()
.url(paginatedUrl)
.header(ACCEPT, MIMETYPE_APPLICATION_JSON)
.header(ACCEPT_LANGUAGE, Locale.ENGLISH.getLanguage())
.header(X_REQUESTED_WITH, XML_HTTP_REQUEST)
.header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
.header("Authorization", Optional.ofNullable(jwtToken).orElse(""))
.build();
try (Response response = stripchat.getHttpClient().execute(request)) {
if (response.isSuccessful()) {
List<Model> models = new ArrayList<>();
JSONObject json = new JSONObject(response.body().string());
if (json.has("totalCount") && offset >= json.getInt("totalCount")) {
return Collections.emptyList();
}
if (json.has("models")) {
JSONArray jsonModels = json.getJSONArray("models");
models.addAll(parseModels(jsonModels));
} else {
log.debug("Response was not successful: {}", json);
return Collections.emptyList();
}
return models;
} else {
throw new HttpException(response.code(), response.message());
}
}
}
} else {
throw new HttpException(response.code(), response.message());
}
};
}
private List<Model> parseModels(JSONArray jsonModels) {
List<Model> models = new ArrayList<>();
for (var i = 0; i < jsonModels.length(); i++) {
var jsonModel = jsonModels.getJSONObject(i);
try {
StripchatModel model = stripchat.createModel(jsonModel.getString("username"));
model.setPreview(getPreviewUrl(jsonModel));
model.setDisplayName(model.getName());
models.add(model);
} catch (Exception e) {
log.warn("Couldn't parse one of the models: {}", jsonModel, e);
}
}
return models;
}
private JSONArray loadFavoriteModelIds() throws IOException {
SiteUiFactory.getUi(stripchat).login();
stripchat.getHttpClient().login();
long userId = ((StripchatHttpClient) stripchat.getHttpClient()).getUserId();
String url = stripchat.getBaseUrl() + "/api/front/users/" + userId + FAVORITES;
var request = new Request.Builder()
.url(url)
.header(ACCEPT, MIMETYPE_APPLICATION_JSON)
.header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
.header(ORIGIN, Stripchat.baseUri)
.header(REFERER, Stripchat.baseUri + FAVORITES)
.header(CONTENT_TYPE, MIMETYPE_APPLICATION_JSON)
.build();
try (var response = stripchat.getHttpClient().execute(request)) {
if (response.isSuccessful()) {
var json = new JSONObject(response.body().string());
if (json.has("modelIds")) {
var userIds = json.getJSONArray("modelIds");
return userIds;
} else {
return new JSONArray();
}
} else {
throw new HttpException(response.code(), response.message());
}
public void setOnline(boolean online) {
if (online) {
url = stripchat.getBaseUrl() + "/api/front/models/favorites?sortBy=lastAdded";
} else {
url = stripchat.getBaseUrl() + "/api/front/models/favorites/offline?sortBy=lastAdded";
}
}
protected ctbrec.Model.State mapStatus(String status) {
return switch (status) {
case "public" -> ONLINE;
case "idle" -> AWAY;
case "off" -> OFFLINE;
default -> UNKNOWN;
};
private String getUniq() {
String dict = "0123456789abcdefghijklmnopqarstvwxyz";
char[] text = new char[16];
for (int i = 0; i < 16; i++) {
text[i] = dict.charAt(RNG.nextInt(dict.length()));
}
return new String(text);
}
}

View File

@ -1,31 +1,37 @@
package ctbrec.sites.stripchat;
import static ctbrec.io.HttpConstants.*;
import java.io.IOException;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ctbrec.Config;
import ctbrec.StringUtil;
import ctbrec.io.HttpClient;
import ctbrec.io.HttpException;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import static ctbrec.io.HttpConstants.*;
@Slf4j
public class StripchatHttpClient extends HttpClient {
private static final Logger LOG = LoggerFactory.getLogger(StripchatHttpClient.class);
public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
private long userId;
@Getter
private String csrfToken;
@Getter
private String csrfTimestamp;
@Getter
private String csrfNotifyTimestamp;
@Getter
private String jwtToken;
public StripchatHttpClient(Config config) {
super("stripchat", config);
@ -43,7 +49,7 @@ public class StripchatHttpClient extends HttpClient {
// persisted cookies might let us log in
if (checkLoginSuccess()) {
loggedIn = true;
LOG.debug("Logged in with cookies");
log.debug("Logged in with cookies");
if (csrfToken == null) {
loadCsrfToken();
}
@ -75,7 +81,7 @@ public class StripchatHttpClient extends HttpClient {
try (Response response = execute(request)) {
if (response.isSuccessful()) {
JSONObject resp = new JSONObject(response.body().string());
if(resp.has("user")) {
if (resp.has("user")) {
JSONObject user = resp.getJSONObject("user");
userId = user.optLong("id");
return true;
@ -83,14 +89,14 @@ public class StripchatHttpClient extends HttpClient {
return false;
}
} else {
LOG.info("Auto-Login failed: {} {} {}", response.code(), response.message(), url);
log.info("Auto-Login failed: {} {} {}", response.code(), response.message(), url);
return false;
}
}
}
private void loadCsrfToken() throws IOException {
String url = Stripchat.baseUri + "/api/front/v2/config/data?requestPath=%2F&timezoneOffset=0";
String url = Stripchat.baseUri + "/api/front/v2/config?requestPath=%2F&timezoneOffset=0";
Request request = new Request.Builder()
.url(url)
.header(ACCEPT, MIMETYPE_APPLICATION_JSON)
@ -106,6 +112,8 @@ public class StripchatHttpClient extends HttpClient {
csrfToken = data.optString("csrfToken");
csrfTimestamp = data.optString("csrfTimestamp");
csrfNotifyTimestamp = data.optString("csrfNotifyTimestamp");
JSONObject config = resp.getJSONObject("config");
jwtToken = config.optString("jwtToken");
} else {
throw new HttpException(response.code(), response.message());
}
@ -113,28 +121,18 @@ public class StripchatHttpClient extends HttpClient {
}
/**
* check, if the login worked
* check, if the login worked
*
* @throws IOException
*/
public boolean checkLoginSuccess() throws IOException {
userId = getUserId();
String url = Stripchat.baseUri + "/api/front/users/" + userId + "/favorites";
Request request = new Request.Builder()
.url(url)
.header(ACCEPT, MIMETYPE_APPLICATION_JSON)
.header(USER_AGENT, config.getSettings().httpUserAgent)
.header(ORIGIN, Stripchat.baseUri)
.header(REFERER, Stripchat.baseUri + "/favorites")
.header(CONTENT_TYPE, MIMETYPE_APPLICATION_JSON)
.build();
try (Response response = execute(request)) {
if (response.isSuccessful()) {
return true;
}
try {
loadCsrfToken();
} catch (Exception e) {
LOG.info("Login check returned unsuccessful: {}", e.getLocalizedMessage());
log.info("Login check returned unsuccessful: {}", e.getLocalizedMessage());
return false;
}
return false;
return StringUtil.isNotBlank(jwtToken);
}
public long getUserId() throws JSONException, IOException {
@ -160,16 +158,4 @@ public class StripchatHttpClient extends HttpClient {
}
return userId;
}
public String getCsrfNotifyTimestamp() {
return csrfNotifyTimestamp;
}
public String getCsrfTimestamp() {
return csrfTimestamp;
}
public String getCsrfToken() {
return csrfToken;
}
}