Add online/offline switch on followed tab for Stripchat
This commit is contained in:
parent
b07a478d03
commit
c376f30c56
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue