forked from j62/ctbrec
First working implementation for Stripchat
This commit is contained in:
parent
9e2a2d8cf8
commit
e4b9da7685
|
@ -47,6 +47,7 @@ import ctbrec.sites.flirt4free.Flirt4Free;
|
||||||
import ctbrec.sites.jasmin.LiveJasmin;
|
import ctbrec.sites.jasmin.LiveJasmin;
|
||||||
import ctbrec.sites.mfc.MyFreeCams;
|
import ctbrec.sites.mfc.MyFreeCams;
|
||||||
import ctbrec.sites.streamate.Streamate;
|
import ctbrec.sites.streamate.Streamate;
|
||||||
|
import ctbrec.sites.stripchat.Stripchat;
|
||||||
import ctbrec.ui.news.NewsTab;
|
import ctbrec.ui.news.NewsTab;
|
||||||
import ctbrec.ui.settings.SettingsTab;
|
import ctbrec.ui.settings.SettingsTab;
|
||||||
import ctbrec.ui.tabs.DonateTabFx;
|
import ctbrec.ui.tabs.DonateTabFx;
|
||||||
|
@ -98,6 +99,7 @@ public class CamrecApplication extends Application {
|
||||||
sites.add(new LiveJasmin());
|
sites.add(new LiveJasmin());
|
||||||
sites.add(new MyFreeCams());
|
sites.add(new MyFreeCams());
|
||||||
sites.add(new Streamate());
|
sites.add(new Streamate());
|
||||||
|
sites.add(new Stripchat());
|
||||||
loadConfig();
|
loadConfig();
|
||||||
registerAlertSystem();
|
registerAlertSystem();
|
||||||
registerActiveRecordingsCounter();
|
registerActiveRecordingsCounter();
|
||||||
|
|
|
@ -10,6 +10,7 @@ import ctbrec.sites.flirt4free.Flirt4Free;
|
||||||
import ctbrec.sites.jasmin.LiveJasmin;
|
import ctbrec.sites.jasmin.LiveJasmin;
|
||||||
import ctbrec.sites.mfc.MyFreeCams;
|
import ctbrec.sites.mfc.MyFreeCams;
|
||||||
import ctbrec.sites.streamate.Streamate;
|
import ctbrec.sites.streamate.Streamate;
|
||||||
|
import ctbrec.sites.stripchat.Stripchat;
|
||||||
import ctbrec.ui.sites.bonga.BongaCamsSiteUi;
|
import ctbrec.ui.sites.bonga.BongaCamsSiteUi;
|
||||||
import ctbrec.ui.sites.cam4.Cam4SiteUi;
|
import ctbrec.ui.sites.cam4.Cam4SiteUi;
|
||||||
import ctbrec.ui.sites.camsoda.CamsodaSiteUi;
|
import ctbrec.ui.sites.camsoda.CamsodaSiteUi;
|
||||||
|
@ -19,6 +20,7 @@ import ctbrec.ui.sites.flirt4free.Flirt4FreeSiteUi;
|
||||||
import ctbrec.ui.sites.jasmin.LiveJasminSiteUi;
|
import ctbrec.ui.sites.jasmin.LiveJasminSiteUi;
|
||||||
import ctbrec.ui.sites.myfreecams.MyFreeCamsSiteUi;
|
import ctbrec.ui.sites.myfreecams.MyFreeCamsSiteUi;
|
||||||
import ctbrec.ui.sites.streamate.StreamateSiteUi;
|
import ctbrec.ui.sites.streamate.StreamateSiteUi;
|
||||||
|
import ctbrec.ui.sites.stripchat.StripchatSiteUi;
|
||||||
|
|
||||||
public class SiteUiFactory {
|
public class SiteUiFactory {
|
||||||
|
|
||||||
|
@ -31,6 +33,9 @@ public class SiteUiFactory {
|
||||||
private static LiveJasminSiteUi jasminSiteUi;
|
private static LiveJasminSiteUi jasminSiteUi;
|
||||||
private static MyFreeCamsSiteUi mfcSiteUi;
|
private static MyFreeCamsSiteUi mfcSiteUi;
|
||||||
private static StreamateSiteUi streamateSiteUi;
|
private static StreamateSiteUi streamateSiteUi;
|
||||||
|
private static StripchatSiteUi stripchatSiteUi;
|
||||||
|
|
||||||
|
private SiteUiFactory () {}
|
||||||
|
|
||||||
public static synchronized SiteUI getUi(Site site) {
|
public static synchronized SiteUI getUi(Site site) {
|
||||||
if (site instanceof BongaCams) {
|
if (site instanceof BongaCams) {
|
||||||
|
@ -78,6 +83,11 @@ public class SiteUiFactory {
|
||||||
jasminSiteUi = new LiveJasminSiteUi((LiveJasmin) site);
|
jasminSiteUi = new LiveJasminSiteUi((LiveJasmin) site);
|
||||||
}
|
}
|
||||||
return jasminSiteUi;
|
return jasminSiteUi;
|
||||||
|
} else if (site instanceof Stripchat) {
|
||||||
|
if (stripchatSiteUi == null) {
|
||||||
|
stripchatSiteUi = new StripchatSiteUi((Stripchat) site);
|
||||||
|
}
|
||||||
|
return stripchatSiteUi;
|
||||||
}
|
}
|
||||||
throw new RuntimeException("Unknown site " + site.getName());
|
throw new RuntimeException("Unknown site " + site.getName());
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
package ctbrec.ui.sites.stripchat;
|
||||||
|
|
||||||
|
import ctbrec.Config;
|
||||||
|
import ctbrec.Settings;
|
||||||
|
import ctbrec.sites.stripchat.Stripchat;
|
||||||
|
import ctbrec.ui.DesktopIntegration;
|
||||||
|
import ctbrec.ui.settings.SettingsTab;
|
||||||
|
import ctbrec.ui.sites.AbstractConfigUI;
|
||||||
|
import javafx.geometry.Insets;
|
||||||
|
import javafx.scene.Parent;
|
||||||
|
import javafx.scene.control.Button;
|
||||||
|
import javafx.scene.control.CheckBox;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.control.PasswordField;
|
||||||
|
import javafx.scene.control.TextField;
|
||||||
|
import javafx.scene.layout.GridPane;
|
||||||
|
import javafx.scene.layout.Priority;
|
||||||
|
|
||||||
|
public class StripchatConfigUI extends AbstractConfigUI {
|
||||||
|
private Stripchat stripchat;
|
||||||
|
|
||||||
|
public StripchatConfigUI(Stripchat stripchat) {
|
||||||
|
this.stripchat = stripchat;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Parent createConfigPanel() {
|
||||||
|
GridPane layout = SettingsTab.createGridLayout();
|
||||||
|
Settings settings = Config.getInstance().getSettings();
|
||||||
|
|
||||||
|
int row = 0;
|
||||||
|
Label l = new Label("Active");
|
||||||
|
layout.add(l, 0, row);
|
||||||
|
CheckBox enabled = new CheckBox();
|
||||||
|
enabled.setSelected(!settings.disabledSites.contains(stripchat.getName()));
|
||||||
|
enabled.setOnAction(e -> {
|
||||||
|
if(enabled.isSelected()) {
|
||||||
|
settings.disabledSites.remove(stripchat.getName());
|
||||||
|
} else {
|
||||||
|
settings.disabledSites.add(stripchat.getName());
|
||||||
|
}
|
||||||
|
save();
|
||||||
|
});
|
||||||
|
GridPane.setMargin(enabled, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));
|
||||||
|
layout.add(enabled, 1, row++);
|
||||||
|
|
||||||
|
layout.add(new Label("Stripchat User"), 0, row);
|
||||||
|
TextField username = new TextField(Config.getInstance().getSettings().stripchatUsername);
|
||||||
|
username.textProperty().addListener((ob, o, n) -> {
|
||||||
|
if(!n.equals(Config.getInstance().getSettings().stripchatUsername)) {
|
||||||
|
Config.getInstance().getSettings().stripchatUsername = username.getText();
|
||||||
|
stripchat.getHttpClient().logout();
|
||||||
|
save();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
GridPane.setFillWidth(username, true);
|
||||||
|
GridPane.setHgrow(username, Priority.ALWAYS);
|
||||||
|
GridPane.setColumnSpan(username, 2);
|
||||||
|
layout.add(username, 1, row++);
|
||||||
|
|
||||||
|
layout.add(new Label("Stripchat Password"), 0, row);
|
||||||
|
PasswordField password = new PasswordField();
|
||||||
|
password.setText(Config.getInstance().getSettings().stripchatPassword);
|
||||||
|
password.textProperty().addListener((ob, o, n) -> {
|
||||||
|
if(!n.equals(Config.getInstance().getSettings().stripchatPassword)) {
|
||||||
|
Config.getInstance().getSettings().stripchatPassword = password.getText();
|
||||||
|
stripchat.getHttpClient().logout();
|
||||||
|
save();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
GridPane.setFillWidth(password, true);
|
||||||
|
GridPane.setHgrow(password, Priority.ALWAYS);
|
||||||
|
GridPane.setColumnSpan(password, 2);
|
||||||
|
layout.add(password, 1, row++);
|
||||||
|
|
||||||
|
Button createAccount = new Button("Create new Account");
|
||||||
|
createAccount.setOnAction(e -> DesktopIntegration.open(stripchat.getAffiliateLink()));
|
||||||
|
layout.add(createAccount, 1, row);
|
||||||
|
GridPane.setColumnSpan(createAccount, 2);
|
||||||
|
GridPane.setMargin(username, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));
|
||||||
|
GridPane.setMargin(password, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));
|
||||||
|
GridPane.setMargin(createAccount, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));
|
||||||
|
return layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
package ctbrec.ui.sites.stripchat;
|
||||||
|
|
||||||
|
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);
|
||||||
|
status = new Label("Logging in...");
|
||||||
|
grid.getChildren().add(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void createGui() {
|
||||||
|
super.createGui();
|
||||||
|
addOnlineOfflineSelector();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addOnlineOfflineSelector() {
|
||||||
|
ToggleGroup group = new ToggleGroup();
|
||||||
|
RadioButton online = new RadioButton("online");
|
||||||
|
online.setToggleGroup(group);
|
||||||
|
RadioButton 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 -> {
|
||||||
|
queue.clear();
|
||||||
|
((StripchatFollowedUpdateService)updateService).showOnline(online.isSelected());
|
||||||
|
updateService.restart();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onSuccess() {
|
||||||
|
grid.getChildren().remove(status);
|
||||||
|
super.onSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onFail(WorkerStateEvent event) {
|
||||||
|
String msg = "";
|
||||||
|
if (event.getSource().getException() != null) {
|
||||||
|
msg = ": " + event.getSource().getException().getMessage();
|
||||||
|
}
|
||||||
|
status.setText("Login failed" + msg);
|
||||||
|
super.onFail(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void selected() {
|
||||||
|
status.setText("Logging in...");
|
||||||
|
super.selected();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setScene(Scene scene) {
|
||||||
|
scene.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
|
||||||
|
if (this.isSelected() && event.getCode() == KeyCode.DELETE) {
|
||||||
|
follow(selectedThumbCells, false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,119 @@
|
||||||
|
package ctbrec.ui.sites.stripchat;
|
||||||
|
|
||||||
|
import static ctbrec.io.HttpConstants.*;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import ctbrec.Config;
|
||||||
|
import ctbrec.Model;
|
||||||
|
import ctbrec.io.HttpException;
|
||||||
|
import ctbrec.sites.stripchat.Stripchat;
|
||||||
|
import ctbrec.sites.stripchat.StripchatHttpClient;
|
||||||
|
import ctbrec.sites.stripchat.StripchatModel;
|
||||||
|
import ctbrec.ui.SiteUiFactory;
|
||||||
|
import ctbrec.ui.tabs.PaginatedScheduledService;
|
||||||
|
import javafx.concurrent.Task;
|
||||||
|
import okhttp3.MediaType;
|
||||||
|
import okhttp3.Request;
|
||||||
|
import okhttp3.RequestBody;
|
||||||
|
import okhttp3.Response;
|
||||||
|
|
||||||
|
public class StripchatFollowedUpdateService extends PaginatedScheduledService {
|
||||||
|
private Stripchat stripchat;
|
||||||
|
private boolean showOnline = true;
|
||||||
|
|
||||||
|
public StripchatFollowedUpdateService(Stripchat stripchat) {
|
||||||
|
this.stripchat = stripchat;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Task<List<Model>> createTask() {
|
||||||
|
return new Task<List<Model>>() {
|
||||||
|
@Override
|
||||||
|
public List<Model> call() throws IOException {
|
||||||
|
JSONArray favoriteModelIds = loadFavoriteModelIds();
|
||||||
|
List<Model> models = loadModels(favoriteModelIds);
|
||||||
|
return models;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Model> loadModels(JSONArray favoriteModelIds) throws IOException {
|
||||||
|
List<Model> models = new ArrayList<>();
|
||||||
|
StripchatHttpClient client = (StripchatHttpClient) stripchat.getHttpClient();
|
||||||
|
String url = stripchat.getBaseUrl() + "/api/front/users/list";
|
||||||
|
JSONObject requestParams = new JSONObject();
|
||||||
|
requestParams.put("userIds", favoriteModelIds);
|
||||||
|
requestParams.put("csrfToken", client.getCsrfToken());
|
||||||
|
requestParams.put("csrfTimestamp", client.getCsrfTimestamp());
|
||||||
|
requestParams.put("csrfNotifyTimestamp", client.getCsrfNotifyTimestamp());
|
||||||
|
RequestBody body = RequestBody.create(MediaType.parse("application/json"), requestParams.toString());
|
||||||
|
Request request = new Request.Builder()
|
||||||
|
.url(url)
|
||||||
|
.header(ACCEPT, MIMETYPE_APPLICATION_JSON)
|
||||||
|
.header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
|
||||||
|
.header(ORIGIN, Stripchat.BASE_URI)
|
||||||
|
.header(REFERER, Stripchat.BASE_URI + "/favorites")
|
||||||
|
.header(CONTENT_TYPE, MIMETYPE_APPLICATION_JSON)
|
||||||
|
.post(body)
|
||||||
|
.build();
|
||||||
|
try (Response response = stripchat.getHttpClient().execute(request)) {
|
||||||
|
if (response.isSuccessful()) {
|
||||||
|
JSONObject json = new JSONObject(response.body().string());
|
||||||
|
if (json.has("users")) {
|
||||||
|
JSONArray users = json.getJSONArray("users");
|
||||||
|
for (int i = 0; i < users.length(); i++) {
|
||||||
|
JSONObject user = users.getJSONObject(i);
|
||||||
|
StripchatModel model = stripchat.createModel(user.optString("username"));
|
||||||
|
model.setDescription(user.optString("description"));
|
||||||
|
model.setPreview(user.optString("previewUrlThumbBig"));
|
||||||
|
boolean online = Objects.equals(user.optString("status"), "public");
|
||||||
|
if (showOnline == online) {
|
||||||
|
models.add(model);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new HttpException(response.code(), response.message());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return models;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JSONArray loadFavoriteModelIds() throws IOException {
|
||||||
|
SiteUiFactory.getUi(stripchat).login();
|
||||||
|
long userId = ((StripchatHttpClient) stripchat.getHttpClient()).getUserId();
|
||||||
|
String url = stripchat.getBaseUrl() + "/api/front/users/" + userId + "/favorites";
|
||||||
|
Request request = new Request.Builder()
|
||||||
|
.url(url)
|
||||||
|
.header(ACCEPT, MIMETYPE_APPLICATION_JSON)
|
||||||
|
.header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
|
||||||
|
.header(ORIGIN, Stripchat.BASE_URI)
|
||||||
|
.header(REFERER, Stripchat.BASE_URI + "/favorites")
|
||||||
|
.header(CONTENT_TYPE, MIMETYPE_APPLICATION_JSON)
|
||||||
|
.build();
|
||||||
|
try (Response response = stripchat.getHttpClient().execute(request)) {
|
||||||
|
if (response.isSuccessful()) {
|
||||||
|
JSONObject json = new JSONObject(response.body().string());
|
||||||
|
if(json.has("userIds")) {
|
||||||
|
JSONArray userIds = json.getJSONArray("userIds");
|
||||||
|
return userIds;
|
||||||
|
} else {
|
||||||
|
return new JSONArray();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new HttpException(response.code(), response.message());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void showOnline(boolean online) {
|
||||||
|
this.showOnline = online;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
package ctbrec.ui.sites.stripchat;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import ctbrec.sites.ConfigUI;
|
||||||
|
import ctbrec.sites.stripchat.Stripchat;
|
||||||
|
import ctbrec.ui.sites.AbstractSiteUi;
|
||||||
|
import ctbrec.ui.tabs.TabProvider;
|
||||||
|
|
||||||
|
public class StripchatSiteUi extends AbstractSiteUi {
|
||||||
|
|
||||||
|
private StripchatTabProvider tabProvider;
|
||||||
|
private StripchatConfigUI configUi;
|
||||||
|
private Stripchat stripchat;
|
||||||
|
|
||||||
|
public StripchatSiteUi(Stripchat stripchat) {
|
||||||
|
this.stripchat = stripchat;
|
||||||
|
tabProvider = new StripchatTabProvider(stripchat);
|
||||||
|
configUi = new StripchatConfigUI(stripchat);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TabProvider getTabProvider() {
|
||||||
|
return tabProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ConfigUI getConfigUI() {
|
||||||
|
return configUi;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized boolean login() throws IOException {
|
||||||
|
boolean automaticLogin = stripchat.login();
|
||||||
|
return automaticLogin;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
package ctbrec.ui.sites.stripchat;
|
||||||
|
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import ctbrec.recorder.Recorder;
|
||||||
|
import ctbrec.sites.stripchat.Stripchat;
|
||||||
|
import ctbrec.ui.tabs.TabProvider;
|
||||||
|
import ctbrec.ui.tabs.ThumbOverviewTab;
|
||||||
|
import javafx.scene.Scene;
|
||||||
|
import javafx.scene.control.Tab;
|
||||||
|
|
||||||
|
public class StripchatTabProvider extends TabProvider {
|
||||||
|
|
||||||
|
private String urlTemplate;
|
||||||
|
private Stripchat stripchat;
|
||||||
|
private Recorder recorder;
|
||||||
|
|
||||||
|
StripchatFollowedTab followedTab;
|
||||||
|
|
||||||
|
|
||||||
|
public StripchatTabProvider(Stripchat stripchat) {
|
||||||
|
this.stripchat = stripchat;
|
||||||
|
this.recorder = stripchat.getRecorder();
|
||||||
|
followedTab = new StripchatFollowedTab("Followed", stripchat);
|
||||||
|
urlTemplate = stripchat.getBaseUrl() + "/api/front/models?primaryTag={0}&sortBy=viewersRating&withMixedTags=true&parentTag=";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Tab> getTabs(Scene scene) {
|
||||||
|
List<Tab> tabs = new ArrayList<>();
|
||||||
|
tabs.add(createTab("Girls", MessageFormat.format(urlTemplate, "girls")));
|
||||||
|
tabs.add(createTab("Couples", MessageFormat.format(urlTemplate, "couples")));
|
||||||
|
tabs.add(createTab("Boys", MessageFormat.format(urlTemplate, "men")));
|
||||||
|
tabs.add(createTab("Trans", MessageFormat.format(urlTemplate, "trans")));
|
||||||
|
followedTab.setRecorder(recorder);
|
||||||
|
followedTab.setScene(scene);
|
||||||
|
tabs.add(followedTab);
|
||||||
|
return tabs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Tab getFollowedTab() {
|
||||||
|
return followedTab;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Tab createTab(String title, String url) {
|
||||||
|
StripchatUpdateService updateService = new StripchatUpdateService(url, false, stripchat);
|
||||||
|
ThumbOverviewTab tab = new ThumbOverviewTab(title, updateService, stripchat);
|
||||||
|
tab.setRecorder(recorder);
|
||||||
|
return tab;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,97 @@
|
||||||
|
package ctbrec.ui.sites.stripchat;
|
||||||
|
|
||||||
|
import static ctbrec.io.HttpConstants.*;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import ctbrec.Config;
|
||||||
|
import ctbrec.Model;
|
||||||
|
import ctbrec.StringUtil;
|
||||||
|
import ctbrec.io.HttpException;
|
||||||
|
import ctbrec.sites.stripchat.Stripchat;
|
||||||
|
import ctbrec.sites.stripchat.StripchatModel;
|
||||||
|
import ctbrec.ui.SiteUiFactory;
|
||||||
|
import ctbrec.ui.tabs.PaginatedScheduledService;
|
||||||
|
import javafx.concurrent.Task;
|
||||||
|
import okhttp3.Request;
|
||||||
|
import okhttp3.Response;
|
||||||
|
|
||||||
|
public class StripchatUpdateService extends PaginatedScheduledService {
|
||||||
|
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(StripchatUpdateService.class);
|
||||||
|
|
||||||
|
private String url;
|
||||||
|
private boolean loginRequired;
|
||||||
|
private Stripchat stripchat;
|
||||||
|
int modelsPerPage = 60;
|
||||||
|
|
||||||
|
public StripchatUpdateService(String url, boolean loginRequired, Stripchat stripchat) {
|
||||||
|
this.url = url;
|
||||||
|
this.loginRequired = loginRequired;
|
||||||
|
this.stripchat = stripchat;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Task<List<Model>> createTask() {
|
||||||
|
return new Task<List<Model>>() {
|
||||||
|
@Override
|
||||||
|
public List<Model> call() throws IOException {
|
||||||
|
List<Model> models = new ArrayList<>();
|
||||||
|
if(loginRequired && StringUtil.isBlank(ctbrec.Config.getInstance().getSettings().username)) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
} else {
|
||||||
|
int offset = (getPage() - 1) * modelsPerPage;
|
||||||
|
int limit = offset + modelsPerPage;
|
||||||
|
String paginatedUrl = url + "&offset=" + offset + "&limit=" + limit;
|
||||||
|
LOG.debug("Fetching page {}", paginatedUrl);
|
||||||
|
if(loginRequired) {
|
||||||
|
SiteUiFactory.getUi(stripchat).login();
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
.build();
|
||||||
|
try (Response response = stripchat.getHttpClient().execute(request)) {
|
||||||
|
if (response.isSuccessful()) {
|
||||||
|
JSONObject json = new JSONObject(response.body().string());
|
||||||
|
if(json.has("models")) {
|
||||||
|
JSONArray jsonModels = json.getJSONArray("models");
|
||||||
|
for (int i = 0; i < jsonModels.length(); i++) {
|
||||||
|
JSONObject jsonModel = jsonModels.getJSONObject(i);
|
||||||
|
try {
|
||||||
|
StripchatModel model = stripchat.createModel(jsonModel.getString("username"));
|
||||||
|
model.setDescription("");
|
||||||
|
model.setPreview(jsonModel.optString("snapshotUrl"));
|
||||||
|
model.setDisplayName(model.getName());
|
||||||
|
models.add(model);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOG.warn("Couldn't parse one of the models: {}", jsonModel, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return models;
|
||||||
|
} else {
|
||||||
|
LOG.debug("Response was not successful: {}", json);
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new HttpException(response.code(), response.message());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -376,7 +376,7 @@ public class ThumbCell extends StackPane {
|
||||||
throw new HttpException(resp.code(), resp.message());
|
throw new HttpException(resp.code(), resp.message());
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.error("Error loading image", e);
|
LOG.warn("Error loading thumbnail: {}", e.getLocalizedMessage());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,6 +112,8 @@ public class Settings {
|
||||||
public String startTab = "Settings";
|
public String startTab = "Settings";
|
||||||
public String streamatePassword = "";
|
public String streamatePassword = "";
|
||||||
public String streamateUsername = "";
|
public String streamateUsername = "";
|
||||||
|
public String stripchatUsername = "";
|
||||||
|
public String stripchatPassword = "";
|
||||||
public boolean transportLayerSecurity = true;
|
public boolean transportLayerSecurity = true;
|
||||||
public int thumbWidth = 180;
|
public int thumbWidth = 180;
|
||||||
public boolean updateThumbnails = true;
|
public boolean updateThumbnails = true;
|
||||||
|
|
|
@ -5,6 +5,7 @@ public class HttpConstants {
|
||||||
public static final String ACCEPT = "Accept";
|
public static final String ACCEPT = "Accept";
|
||||||
public static final String ACCEPT_LANGUAGE = "Accept-Language";
|
public static final String ACCEPT_LANGUAGE = "Accept-Language";
|
||||||
public static final String CONNECTION = "Connection";
|
public static final String CONNECTION = "Connection";
|
||||||
|
public static final String CONTENT_TYPE = "Content-Type";
|
||||||
public static final String KEEP_ALIVE = "keep-alive";
|
public static final String KEEP_ALIVE = "keep-alive";
|
||||||
public static final String MIMETYPE_APPLICATION_JSON = "application/json";
|
public static final String MIMETYPE_APPLICATION_JSON = "application/json";
|
||||||
public static final String ORIGIN = "Origin";
|
public static final String ORIGIN = "Origin";
|
||||||
|
|
|
@ -0,0 +1,183 @@
|
||||||
|
package ctbrec.sites.stripchat;
|
||||||
|
|
||||||
|
import static ctbrec.io.HttpConstants.*;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import ctbrec.Config;
|
||||||
|
import ctbrec.Model;
|
||||||
|
import ctbrec.io.HttpClient;
|
||||||
|
import ctbrec.io.HttpException;
|
||||||
|
import ctbrec.sites.AbstractSite;
|
||||||
|
import okhttp3.Request;
|
||||||
|
import okhttp3.Response;
|
||||||
|
|
||||||
|
public class Stripchat extends AbstractSite {
|
||||||
|
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(Stripchat.class);
|
||||||
|
public static final String BASE_URI = "https://stripchat.com";
|
||||||
|
private HttpClient httpClient;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "Stripchat";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getBaseUrl() {
|
||||||
|
return BASE_URI;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAffiliateLink() {
|
||||||
|
return "https://go.strpjmp.com?creativeId=1&campaignId=1&sourceId=app&path=%2F&userId=cd0bfa6152f1e2b55f8e8218de2f32c7e6c41d9846a390a2113ed4a5edfc95d8";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getBuyTokensLink() {
|
||||||
|
return getAffiliateLink();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StripchatModel createModel(String name) {
|
||||||
|
StripchatModel model = new StripchatModel();
|
||||||
|
model.setName(name);
|
||||||
|
model.setUrl(getBaseUrl() + "/" + name);
|
||||||
|
model.setSite(this);
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Double getTokenBalance() throws IOException {
|
||||||
|
if (!credentialsAvailable()) {
|
||||||
|
throw new IOException("Account settings not available");
|
||||||
|
}
|
||||||
|
|
||||||
|
String username = Config.getInstance().getSettings().camsodaUsername;
|
||||||
|
String url = BASE_URI + "/api/v1/user/" + username;
|
||||||
|
Request request = new Request.Builder().url(url).build();
|
||||||
|
try(Response response = getHttpClient().execute(request)) {
|
||||||
|
if(response.isSuccessful()) {
|
||||||
|
JSONObject json = new JSONObject(response.body().string());
|
||||||
|
if(json.has("user")) {
|
||||||
|
JSONObject user = json.getJSONObject("user");
|
||||||
|
if(user.has("tokens")) {
|
||||||
|
return (double) user.getInt("tokens");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new HttpException(response.code(), response.message());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new RuntimeException("Tokens not found in response");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized boolean login() throws IOException {
|
||||||
|
return credentialsAvailable() && getHttpClient().login();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpClient getHttpClient() {
|
||||||
|
if(httpClient == null) {
|
||||||
|
httpClient = new StripchatHttpClient();
|
||||||
|
}
|
||||||
|
return httpClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init() throws IOException {
|
||||||
|
// noop
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void shutdown() {
|
||||||
|
if(httpClient != null) {
|
||||||
|
httpClient.shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportsTips() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportsFollow() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportsSearch() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Model> search(String q) throws IOException, InterruptedException {
|
||||||
|
String url = BASE_URI + "/api/v1/browse/autocomplete?s=" + URLEncoder.encode(q, "utf-8");
|
||||||
|
Request req = new Request.Builder()
|
||||||
|
.url(url)
|
||||||
|
.addHeader(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
|
||||||
|
.build();
|
||||||
|
try(Response response = getHttpClient().execute(req)) {
|
||||||
|
if(response.isSuccessful()) {
|
||||||
|
JSONObject json = new JSONObject(response.body().string());
|
||||||
|
if(json.optBoolean("status")) {
|
||||||
|
List<Model> models = new ArrayList<>();
|
||||||
|
JSONArray results = json.getJSONArray("results");
|
||||||
|
for (int i = 0; i < results.length(); i++) {
|
||||||
|
JSONObject result = results.getJSONObject(i);
|
||||||
|
StripchatModel model = createModel(result.getString("username"));
|
||||||
|
String thumb = result.getString("thumb");
|
||||||
|
if(thumb != null) {
|
||||||
|
model.setPreview("https:" + thumb);
|
||||||
|
}
|
||||||
|
if(result.has("display_name")) {
|
||||||
|
model.setDisplayName(result.getString("display_name"));
|
||||||
|
}
|
||||||
|
models.add(model);
|
||||||
|
}
|
||||||
|
return models;
|
||||||
|
} else {
|
||||||
|
LOG.warn("Search result: {}", json.toString(2));
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new HttpException(response.code(), response.message());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSiteForModel(Model m) {
|
||||||
|
return m instanceof StripchatModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean credentialsAvailable() {
|
||||||
|
String username = Config.getInstance().getSettings().stripchatUsername;
|
||||||
|
return username != null && !username.trim().isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Model createModelFromUrl(String url) {
|
||||||
|
Matcher m = Pattern.compile("https?://(?:.*?\\.)?stripchat.com/([^/]*?)/?").matcher(url);
|
||||||
|
if (m.matches()) {
|
||||||
|
String modelName = m.group(1);
|
||||||
|
return createModel(modelName);
|
||||||
|
} else {
|
||||||
|
return super.createModelFromUrl(url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,129 @@
|
||||||
|
package ctbrec.sites.stripchat;
|
||||||
|
|
||||||
|
import static ctbrec.io.HttpConstants.*;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import ctbrec.Config;
|
||||||
|
import ctbrec.io.HttpClient;
|
||||||
|
import ctbrec.io.HttpException;
|
||||||
|
import okhttp3.MediaType;
|
||||||
|
import okhttp3.Request;
|
||||||
|
import okhttp3.RequestBody;
|
||||||
|
import okhttp3.Response;
|
||||||
|
|
||||||
|
public class StripchatHttpClient extends HttpClient {
|
||||||
|
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(StripchatHttpClient.class);
|
||||||
|
|
||||||
|
private long userId;
|
||||||
|
private String csrfToken;
|
||||||
|
private String csrfTimestamp;
|
||||||
|
private String csrfNotifyTimestamp;
|
||||||
|
|
||||||
|
public StripchatHttpClient() {
|
||||||
|
super("stripchat");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean login() throws IOException {
|
||||||
|
if(loggedIn) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// persisted cookies might let us log in
|
||||||
|
if(checkLoginSuccess()) {
|
||||||
|
loggedIn = true;
|
||||||
|
LOG.debug("Logged in with cookies");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (csrfToken == null) {
|
||||||
|
loadCsrfToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
String url = Stripchat.BASE_URI + "/api/front/auth/login";
|
||||||
|
JSONObject requestParams = new JSONObject();
|
||||||
|
requestParams.put("loginOrEmail", Config.getInstance().getSettings().stripchatUsername);
|
||||||
|
requestParams.put("password", Config.getInstance().getSettings().stripchatPassword);
|
||||||
|
requestParams.put("remember", true);
|
||||||
|
requestParams.put("csrfToken", csrfToken);
|
||||||
|
requestParams.put("csrfTimestamp", csrfTimestamp);
|
||||||
|
requestParams.put("csrfNotifyTimestamp", csrfNotifyTimestamp);
|
||||||
|
RequestBody body = RequestBody.create(MediaType.parse("application/json"), requestParams.toString());
|
||||||
|
Request request = new Request.Builder()
|
||||||
|
.url(url)
|
||||||
|
.header(ACCEPT, MIMETYPE_APPLICATION_JSON)
|
||||||
|
.header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
|
||||||
|
.header(ORIGIN, Stripchat.BASE_URI)
|
||||||
|
.header(REFERER, Stripchat.BASE_URI)
|
||||||
|
.header(CONTENT_TYPE, MIMETYPE_APPLICATION_JSON)
|
||||||
|
.post(body)
|
||||||
|
.build();
|
||||||
|
try (Response response = execute(request)) {
|
||||||
|
if (response.isSuccessful()) {
|
||||||
|
JSONObject resp = new JSONObject(response.body().string());
|
||||||
|
if(resp.has("user")) {
|
||||||
|
JSONObject user = resp.getJSONObject("user");
|
||||||
|
userId = user.optLong("id");
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new HttpException(response.code(), response.message());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadCsrfToken() throws IOException {
|
||||||
|
String url = Stripchat.BASE_URI + "/api/front/config";
|
||||||
|
Request request = new Request.Builder()
|
||||||
|
.url(url)
|
||||||
|
.header(ACCEPT, MIMETYPE_APPLICATION_JSON)
|
||||||
|
.header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
|
||||||
|
.header(ORIGIN, Stripchat.BASE_URI)
|
||||||
|
.header(REFERER, Stripchat.BASE_URI)
|
||||||
|
.header(CONTENT_TYPE, MIMETYPE_APPLICATION_JSON)
|
||||||
|
.build();
|
||||||
|
try (Response response = execute(request)) {
|
||||||
|
if (response.isSuccessful()) {
|
||||||
|
JSONObject resp = new JSONObject(response.body().string());
|
||||||
|
JSONObject data = resp.getJSONObject("data");
|
||||||
|
csrfToken = data.optString("csrfToken");
|
||||||
|
csrfTimestamp = data.optString("csrfTimestamp");
|
||||||
|
csrfNotifyTimestamp = data.optString("csrfNotifyTimestamp");
|
||||||
|
} else {
|
||||||
|
throw new HttpException(response.code(), response.message());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* check, if the login worked
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public boolean checkLoginSuccess() {
|
||||||
|
return userId > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getUserId() {
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCsrfNotifyTimestamp() {
|
||||||
|
return csrfNotifyTimestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCsrfTimestamp() {
|
||||||
|
return csrfTimestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCsrfToken() {
|
||||||
|
return csrfToken;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,205 @@
|
||||||
|
package ctbrec.sites.stripchat;
|
||||||
|
|
||||||
|
import static ctbrec.io.HttpConstants.*;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import javax.xml.bind.JAXBException;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import com.iheartradio.m3u8.ParseException;
|
||||||
|
import com.iheartradio.m3u8.PlaylistException;
|
||||||
|
|
||||||
|
import ctbrec.AbstractModel;
|
||||||
|
import ctbrec.Config;
|
||||||
|
import ctbrec.io.HttpException;
|
||||||
|
import ctbrec.recorder.download.StreamSource;
|
||||||
|
import okhttp3.MediaType;
|
||||||
|
import okhttp3.Request;
|
||||||
|
import okhttp3.RequestBody;
|
||||||
|
import okhttp3.Response;
|
||||||
|
|
||||||
|
public class StripchatModel extends AbstractModel {
|
||||||
|
private String status = null;
|
||||||
|
private int[] resolution = new int[] {0, 0};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOnline(boolean ignoreCache) throws IOException, ExecutionException, InterruptedException {
|
||||||
|
if (ignoreCache || status == null) {
|
||||||
|
JSONObject jsonResponse = loadModelInfo();
|
||||||
|
if (jsonResponse.has("user")) {
|
||||||
|
JSONObject user = jsonResponse.getJSONObject("user");
|
||||||
|
status = user.optString("status");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Objects.equals(status, "public");
|
||||||
|
}
|
||||||
|
|
||||||
|
private JSONObject loadModelInfo() throws IOException {
|
||||||
|
String url = getSite().getBaseUrl() + "/api/front/users/username/" + URLEncoder.encode(getName(), StandardCharsets.UTF_8.name());
|
||||||
|
Request req = new Request.Builder()
|
||||||
|
.url(url)
|
||||||
|
.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(REFERER, getUrl())
|
||||||
|
.build();
|
||||||
|
try (Response response = site.getHttpClient().execute(req)) {
|
||||||
|
if (response.isSuccessful()) {
|
||||||
|
JSONObject jsonResponse = new JSONObject(response.body().string());
|
||||||
|
return jsonResponse;
|
||||||
|
} else {
|
||||||
|
throw new HttpException(response.code(), response.message());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<StreamSource> getStreamSources() throws IOException, ExecutionException, ParseException, PlaylistException, JAXBException {
|
||||||
|
String name = URLEncoder.encode(getName(), StandardCharsets.UTF_8.name());
|
||||||
|
String url = getSite().getBaseUrl() + "/api/front/models/username/" + name + "/cam?triggerRequest=loadCam";
|
||||||
|
Request req = new Request.Builder()
|
||||||
|
.url(url)
|
||||||
|
.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(REFERER, getUrl())
|
||||||
|
.build();
|
||||||
|
try (Response response = site.getHttpClient().execute(req)) {
|
||||||
|
if (response.isSuccessful()) {
|
||||||
|
JSONObject jsonResponse = new JSONObject(response.body().string());
|
||||||
|
String streamName = jsonResponse.optString("streamName");
|
||||||
|
JSONObject viewServers = jsonResponse.getJSONObject("viewServers");
|
||||||
|
String serverName = viewServers.optString("flashphoner-hls");
|
||||||
|
JSONObject broadcastSettings = jsonResponse.getJSONObject("broadcastSettings");
|
||||||
|
List<StreamSource> sources = new ArrayList<>();
|
||||||
|
StreamSource best = new StreamSource();
|
||||||
|
best.height = broadcastSettings.optInt("height");
|
||||||
|
best.width = broadcastSettings.optInt("width");
|
||||||
|
best.mediaPlaylistUrl = "https://b-" + serverName + ".stripst.com/hls/" + streamName + "/" + streamName + ".m3u8";
|
||||||
|
sources.add(best);
|
||||||
|
Object resolutionObject = broadcastSettings.get("resolutions");
|
||||||
|
if (resolutionObject instanceof JSONObject) {
|
||||||
|
JSONObject resolutions = (JSONObject) resolutionObject;
|
||||||
|
JSONArray heights = resolutions.names();
|
||||||
|
for (int i = 0; i < heights.length(); i++) {
|
||||||
|
String h = heights.getString(i);
|
||||||
|
StreamSource streamSource = new StreamSource();
|
||||||
|
streamSource.height = Integer.parseInt(h.replace("p", ""));
|
||||||
|
streamSource.width = streamSource.height * best.getWidth() / best.getHeight();
|
||||||
|
String source = streamName + "-" + streamSource.height + "p";
|
||||||
|
streamSource.mediaPlaylistUrl = "https://b-" + serverName + ".stripst.com/hls/" + source + "/" + source + ".m3u8";
|
||||||
|
sources.add(streamSource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sources.stream().sorted((a, b) -> a.height - b.height).collect(Collectors.toList());
|
||||||
|
} else {
|
||||||
|
throw new HttpException(response.code(), response.message());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invalidateCacheEntries() {
|
||||||
|
status = null;
|
||||||
|
resolution = new int[] { 0, 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void receiveTip(Double tokens) throws IOException {
|
||||||
|
// not implemented
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] getStreamResolution(boolean failFast) throws ExecutionException {
|
||||||
|
if (!failFast) {
|
||||||
|
try {
|
||||||
|
List<StreamSource> sources = getStreamSources();
|
||||||
|
if (!sources.isEmpty()) {
|
||||||
|
StreamSource best = sources.get(sources.size() - 1);
|
||||||
|
resolution = new int[] { best.getWidth(), best.getHeight() };
|
||||||
|
}
|
||||||
|
} catch (IOException | ParseException | PlaylistException | JAXBException e) {
|
||||||
|
throw new ExecutionException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return resolution;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean follow() throws IOException {
|
||||||
|
JSONObject modelInfo = loadModelInfo();
|
||||||
|
JSONObject user = modelInfo.getJSONObject("user");
|
||||||
|
long modelId = user.optLong("id");
|
||||||
|
|
||||||
|
StripchatHttpClient client = (StripchatHttpClient) getSite().getHttpClient();
|
||||||
|
String url = Stripchat.BASE_URI + "/api/front/users/" + client.getUserId() + "/favorites/" + modelId;
|
||||||
|
JSONObject requestParams = new JSONObject();
|
||||||
|
requestParams.put("csrfToken", client.getCsrfToken());
|
||||||
|
requestParams.put("csrfTimestamp", client.getCsrfTimestamp());
|
||||||
|
requestParams.put("csrfNotifyTimestamp", client.getCsrfNotifyTimestamp());
|
||||||
|
RequestBody body = RequestBody.create(MediaType.parse("application/json"), requestParams.toString());
|
||||||
|
Request request = new Request.Builder()
|
||||||
|
.url(url)
|
||||||
|
.header(ACCEPT, MIMETYPE_APPLICATION_JSON)
|
||||||
|
.header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
|
||||||
|
.header(ORIGIN, Stripchat.BASE_URI)
|
||||||
|
.header(REFERER, Stripchat.BASE_URI)
|
||||||
|
.header(CONTENT_TYPE, MIMETYPE_APPLICATION_JSON)
|
||||||
|
.put(body)
|
||||||
|
.build();
|
||||||
|
try (Response response = client.execute(request)) {
|
||||||
|
if (response.isSuccessful()) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
throw new HttpException(response.code(), response.message());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean unfollow() throws IOException {
|
||||||
|
JSONObject modelInfo = loadModelInfo();
|
||||||
|
JSONObject user = modelInfo.getJSONObject("user");
|
||||||
|
long modelId = user.optLong("id");
|
||||||
|
JSONArray favoriteIds = new JSONArray();
|
||||||
|
favoriteIds.put(modelId);
|
||||||
|
|
||||||
|
StripchatHttpClient client = (StripchatHttpClient) getSite().getHttpClient();
|
||||||
|
String url = Stripchat.BASE_URI + "/api/front/users/" + client.getUserId() + "/favorites";
|
||||||
|
JSONObject requestParams = new JSONObject();
|
||||||
|
requestParams.put("favoriteIds", favoriteIds);
|
||||||
|
requestParams.put("csrfToken", client.getCsrfToken());
|
||||||
|
requestParams.put("csrfTimestamp", client.getCsrfTimestamp());
|
||||||
|
requestParams.put("csrfNotifyTimestamp", client.getCsrfNotifyTimestamp());
|
||||||
|
RequestBody body = RequestBody.create(MediaType.parse("application/json"), requestParams.toString());
|
||||||
|
Request request = new Request.Builder()
|
||||||
|
.url(url)
|
||||||
|
.header(ACCEPT, MIMETYPE_APPLICATION_JSON)
|
||||||
|
.header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
|
||||||
|
.header(ORIGIN, Stripchat.BASE_URI)
|
||||||
|
.header(REFERER, Stripchat.BASE_URI)
|
||||||
|
.header(CONTENT_TYPE, MIMETYPE_APPLICATION_JSON)
|
||||||
|
.delete(body)
|
||||||
|
.build();
|
||||||
|
try (Response response = client.execute(request)) {
|
||||||
|
if (response.isSuccessful()) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
throw new HttpException(response.code(), response.message());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue