Split up project into client, server, common and master

This commit is contained in:
0xboobface 2018-11-18 22:42:13 +01:00
parent e87611fe3d
commit cda330ddbd
159 changed files with 1016 additions and 844 deletions

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<projectDescription> <projectDescription>
<name>ctbrec</name> <name>ctbrec-client</name>
<comment></comment> <comment></comment>
<projects> <projects>
</projects> </projects>

View File

@ -3,9 +3,14 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>ctbrec</groupId>
<artifactId>client</artifactId> <artifactId>client</artifactId>
<version>1.9.0</version>
<parent>
<groupId>ctbrec</groupId>
<artifactId>master</artifactId>
<version>1.9.0</version>
<relativePath>../master</relativePath>
</parent>
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@ -60,76 +65,58 @@
</build> </build>
<dependencies> <dependencies>
<dependency>
<groupId>ctbrec</groupId>
<artifactId>common</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.jsoup</groupId> <groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId> <artifactId>jsoup</artifactId>
<version>1.10.3</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.squareup.okhttp3</groupId> <groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId> <artifactId>okhttp</artifactId>
<version>3.10.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.squareup.moshi</groupId> <groupId>com.squareup.moshi</groupId>
<artifactId>moshi</artifactId> <artifactId>moshi</artifactId>
<version>1.5.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.json</groupId> <groupId>org.json</groupId>
<artifactId>json</artifactId> <artifactId>json</artifactId>
<version>20180130</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.slf4j</groupId> <groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId> <artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>ch.qos.logback</groupId> <groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId> <artifactId>logback-classic</artifactId>
<version>1.2.3</version>
<scope>runtime</scope> <scope>runtime</scope>
</dependency> </dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>[9.3.24.v20180605,)</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<version>[9.3.24.v20180605,)</version>
</dependency>
<dependency> <dependency>
<groupId>com.iheartradio.m3u8</groupId> <groupId>com.iheartradio.m3u8</groupId>
<artifactId>open-m3u8</artifactId> <artifactId>open-m3u8</artifactId>
<version>0.2.4</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.jcodec</groupId> <groupId>org.jcodec</groupId>
<artifactId>jcodec</artifactId> <artifactId>jcodec</artifactId>
<version>0.2.3</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.openjfx</groupId> <groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId> <artifactId>javafx-controls</artifactId>
<version>11</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.openjfx</groupId> <groupId>org.openjfx</groupId>
<artifactId>javafx-web</artifactId> <artifactId>javafx-web</artifactId>
<version>11</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.google.guava</groupId> <groupId>com.google.guava</groupId>
<artifactId>guava</artifactId> <artifactId>guava</artifactId>
<version>17.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@ -1,125 +0,0 @@
package ctbrec.sites.cam4;
import java.io.IOException;
import java.net.HttpCookie;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ctbrec.io.HttpClient;
import javafx.application.Platform;
import okhttp3.Cookie;
import okhttp3.HttpUrl;
import okhttp3.Request;
import okhttp3.Response;
public class Cam4HttpClient extends HttpClient {
private static final transient Logger LOG = LoggerFactory.getLogger(Cam4HttpClient.class);
public Cam4HttpClient() {
super("cam4");
}
@Override
public synchronized boolean login() throws IOException {
if(loggedIn) {
return true;
}
boolean cookiesWorked = checkLoginSuccess();
if(cookiesWorked) {
loggedIn = true;
LOG.debug("Logged in with cookies");
return true;
}
BlockingQueue<Boolean> queue = new LinkedBlockingQueue<>();
Runnable showDialog = () -> {
// login with javafx WebView
Cam4LoginDialog loginDialog = new Cam4LoginDialog();
// transfer cookies from WebView to OkHttp cookie jar
transferCookies(loginDialog);
try {
queue.put(true);
} catch (InterruptedException e) {
LOG.error("Error while signaling termination", e);
}
};
if(Platform.isFxApplicationThread()) {
showDialog.run();
} else {
Platform.runLater(showDialog);
try {
queue.take();
} catch (InterruptedException e) {
LOG.error("Error while waiting for login dialog to close", e);
throw new IOException(e);
}
}
loggedIn = checkLoginSuccess();
return loggedIn;
}
/**
* check, if the login worked by requesting unchecked mail
* @throws IOException
*/
private boolean checkLoginSuccess() throws IOException {
String mailUrl = Cam4.BASE_URI + "/mail/unreadThreads";
Request req = new Request.Builder()
.url(mailUrl)
.addHeader("X-Requested-With", "XMLHttpRequest")
.build();
Response response = execute(req);
if(response.isSuccessful() && response.body().contentLength() > 0) {
JSONObject json = new JSONObject(response.body().string());
return json.has("status") && Objects.equals("success", json.getString("status"));
} else {
response.close();
return false;
}
}
private void transferCookies(Cam4LoginDialog loginDialog) {
HttpUrl redirectedUrl = HttpUrl.parse(loginDialog.getUrl());
List<Cookie> cookies = new ArrayList<>();
for (HttpCookie webViewCookie : loginDialog.getCookies()) {
if(webViewCookie.getDomain().contains("cam4")) {
Cookie cookie = Cookie.parse(redirectedUrl, webViewCookie.toString());
LOG.debug("{} {} {}", webViewCookie.getDomain(), webViewCookie.getName(), webViewCookie.getValue());
cookies.add(cookie);
}
}
cookieJar.saveFromResponse(redirectedUrl, cookies);
HttpUrl origUrl = HttpUrl.parse(Cam4LoginDialog.URL);
cookies = new ArrayList<>();
for (HttpCookie webViewCookie : loginDialog.getCookies()) {
if(webViewCookie.getDomain().contains("cam4")) {
Cookie cookie = Cookie.parse(origUrl, webViewCookie.toString());
cookies.add(cookie);
}
}
cookieJar.saveFromResponse(origUrl, cookies);
}
protected int getTokenBalance() throws IOException {
if(!loggedIn) {
login();
}
throw new RuntimeException("Not implemented, yet");
}
}

View File

@ -126,6 +126,7 @@ public class JavaFxModel implements Model {
@Override @Override
public void receiveTip(int tokens) throws IOException { public void receiveTip(int tokens) throws IOException {
SiteUiFactory.getUi(getSite()).login();
delegate.receiveTip(tokens); delegate.receiveTip(tokens);
} }
@ -136,11 +137,13 @@ public class JavaFxModel implements Model {
@Override @Override
public boolean follow() throws IOException { public boolean follow() throws IOException {
SiteUiFactory.getUi(getSite()).login();
return delegate.follow(); return delegate.follow();
} }
@Override @Override
public boolean unfollow() throws IOException { public boolean unfollow() throws IOException {
SiteUiFactory.getUi(getSite()).login();
return delegate.unfollow(); return delegate.unfollow();
} }

View File

@ -126,7 +126,7 @@ public class SettingsTab extends Tab implements TabSelectionListener {
rightSide.getChildren().add(credentialsAccordion); rightSide.getChildren().add(credentialsAccordion);
for (int i = 0; i < sites.size(); i++) { for (int i = 0; i < sites.size(); i++) {
Site site = sites.get(i); Site site = sites.get(i);
ConfigUI siteConfig = site.getConfigurationGui(); ConfigUI siteConfig = SiteUiFactory.getUi(site).getConfigUI();
if(siteConfig != null) { if(siteConfig != null) {
TitledPane pane = new TitledPane(site.getName(), siteConfig.createConfigPanel()); TitledPane pane = new TitledPane(site.getName(), siteConfig.createConfigPanel());
credentialsAccordion.getPanes().add(pane); credentialsAccordion.getPanes().add(pane);

View File

@ -14,7 +14,8 @@ public class SiteTabPane extends TabPane {
setSide(Side.LEFT); setSide(Side.LEFT);
// add all tabs // add all tabs
for (Tab tab : site.getTabProvider().getTabs(scene)) { TabProvider tabProvider = SiteUiFactory.getUi(site).getTabProvider();
for (Tab tab : tabProvider.getTabs(scene)) {
getTabs().add(tab); getTabs().add(tab);
} }

View File

@ -0,0 +1,12 @@
package ctbrec.ui;
import java.io.IOException;
import ctbrec.sites.ConfigUI;
public interface SiteUI {
public TabProvider getTabProvider();
public ConfigUI getConfigUI();
public boolean login() throws IOException;
}

View File

@ -0,0 +1,53 @@
package ctbrec.ui;
import ctbrec.sites.Site;
import ctbrec.sites.bonga.BongaCams;
import ctbrec.sites.cam4.Cam4;
import ctbrec.sites.camsoda.Camsoda;
import ctbrec.sites.chaturbate.Chaturbate;
import ctbrec.sites.mfc.MyFreeCams;
import ctbrec.ui.sites.bonga.BongaCamsSiteUi;
import ctbrec.ui.sites.cam4.Cam4SiteUi;
import ctbrec.ui.sites.camsoda.CamsodaSiteUi;
import ctbrec.ui.sites.chaturbate.ChaturbateSiteUi;
import ctbrec.ui.sites.myfreecams.MyFreeCamsSiteUi;
public class SiteUiFactory {
private static BongaCamsSiteUi bongaSiteUi;
private static Cam4SiteUi cam4SiteUi;
private static CamsodaSiteUi camsodaSiteUi;
private static ChaturbateSiteUi ctbSiteUi;
private static MyFreeCamsSiteUi mfcSiteUi;
public static SiteUI getUi(Site site) {
if (site instanceof BongaCams) {
if (bongaSiteUi == null) {
bongaSiteUi = new BongaCamsSiteUi((BongaCams) site);
}
return bongaSiteUi;
} else if (site instanceof Cam4) {
if (cam4SiteUi == null) {
cam4SiteUi = new Cam4SiteUi((Cam4) site);
}
return cam4SiteUi;
} else if (site instanceof Camsoda) {
if (camsodaSiteUi == null) {
camsodaSiteUi = new CamsodaSiteUi((Camsoda) site);
}
return camsodaSiteUi;
} else if (site instanceof Chaturbate) {
if (ctbSiteUi == null) {
ctbSiteUi = new ChaturbateSiteUi((Chaturbate) site);
}
return ctbSiteUi;
} else if (site instanceof MyFreeCams) {
if (mfcSiteUi == null) {
mfcSiteUi = new MyFreeCamsSiteUi((MyFreeCams) site);
}
return mfcSiteUi;
}
throw new RuntimeException("Unknown site " + site.getName());
}
}

View File

@ -401,6 +401,7 @@ public class ThumbCell extends StackPane {
return CompletableFuture.supplyAsync(() -> { return CompletableFuture.supplyAsync(() -> {
try { try {
if(follow) { if(follow) {
SiteUiFactory.getUi(model.getSite()).login();
boolean followed = model.follow(); boolean followed = model.follow();
if(followed) { if(followed) {
return true; return true;
@ -415,6 +416,7 @@ public class ThumbCell extends StackPane {
return false; return false;
} }
} else { } else {
SiteUiFactory.getUi(model.getSite()).login();
boolean unfollowed = model.unfollow(); boolean unfollowed = model.unfollow();
if(unfollowed) { if(unfollowed) {
Platform.runLater(() -> thumbCellList.remove(ThumbCell.this)); Platform.runLater(() -> thumbCellList.remove(ThumbCell.this));

View File

@ -366,6 +366,7 @@ public class ThumbOverviewTab extends Tab implements TabSelectionListener {
if(tipText.matches("[1-9]\\d*")) { if(tipText.matches("[1-9]\\d*")) {
int tokens = Integer.parseInt(tipText); int tokens = Integer.parseInt(tipText);
try { try {
SiteUiFactory.getUi(site).login();
cell.getModel().receiveTip(tokens); cell.getModel().receiveTip(tokens);
Map<String, Object> event = new HashMap<>(); Map<String, Object> event = new HashMap<>();
event.put("event", "tokens.sent"); event.put("event", "tokens.sent");
@ -485,7 +486,8 @@ public class ThumbOverviewTab extends Tab implements TabSelectionListener {
} }
private double getFollowedTabYPosition() { private double getFollowedTabYPosition() {
Tab followedTab = site.getTabProvider().getFollowedTab(); TabProvider tabProvider = SiteUiFactory.getUi(site).getTabProvider();
Tab followedTab = tabProvider.getFollowedTab();
TabPane tabPane = getTabPane(); TabPane tabPane = getTabPane();
int idx = tabPane.getTabs().indexOf(followedTab); int idx = tabPane.getTabs().indexOf(followedTab);
for (Node node : tabPane.getChildrenUnmodifiable()) { for (Node node : tabPane.getChildrenUnmodifiable()) {

View File

@ -35,6 +35,7 @@ public class TipDialog extends TextInputDialog {
@Override @Override
protected Integer call() throws Exception { protected Integer call() throws Exception {
if (!Objects.equals(System.getenv("CTBREC_DEV"), "1")) { if (!Objects.equals(System.getenv("CTBREC_DEV"), "1")) {
SiteUiFactory.getUi(site).login();
return site.getTokenBalance(); return site.getTokenBalance();
} else { } else {
return 1_000_000; return 1_000_000;

View File

@ -58,6 +58,7 @@ public class TokenLabel extends Label {
@Override @Override
protected Integer call() throws Exception { protected Integer call() throws Exception {
if (!Objects.equals(System.getenv("CTBREC_DEV"), "1")) { if (!Objects.equals(System.getenv("CTBREC_DEV"), "1")) {
SiteUiFactory.getUi(site).login();
return site.getTokenBalance(); return site.getTokenBalance();
} else { } else {
return 1_000_000; return 1_000_000;

View File

@ -1,7 +1,8 @@
package ctbrec.sites.bonga; package ctbrec.ui.sites.bonga;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.sites.ConfigUI; import ctbrec.sites.ConfigUI;
import ctbrec.sites.bonga.BongaCams;
import ctbrec.ui.DesktopIntegration; import ctbrec.ui.DesktopIntegration;
import ctbrec.ui.SettingsTab; import ctbrec.ui.SettingsTab;
import javafx.geometry.Insets; import javafx.geometry.Insets;

View File

@ -1,4 +1,4 @@
package ctbrec.sites.bonga; package ctbrec.ui.sites.bonga;
import java.io.File; import java.io.File;
import java.io.InputStream; import java.io.InputStream;
@ -15,6 +15,7 @@ import org.slf4j.LoggerFactory;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.OS; import ctbrec.OS;
import ctbrec.sites.bonga.BongaCams;
import javafx.concurrent.Worker.State; import javafx.concurrent.Worker.State;
import javafx.scene.Scene; import javafx.scene.Scene;
import javafx.scene.control.ProgressIndicator; import javafx.scene.control.ProgressIndicator;

View File

@ -0,0 +1,112 @@
package ctbrec.ui.sites.bonga;
import java.io.IOException;
import java.net.HttpCookie;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ctbrec.sites.ConfigUI;
import ctbrec.sites.bonga.BongaCams;
import ctbrec.sites.bonga.BongaCamsHttpClient;
import ctbrec.ui.SiteUI;
import ctbrec.ui.TabProvider;
import javafx.application.Platform;
import okhttp3.Cookie;
import okhttp3.CookieJar;
import okhttp3.HttpUrl;
public class BongaCamsSiteUi implements SiteUI {
private static final transient Logger LOG = LoggerFactory.getLogger(BongaCamsSiteUi.class);
private BongaCamsTabProvider tabProvider;
private BongaCamsConfigUI configUi;
private BongaCams bongaCams;
public BongaCamsSiteUi(BongaCams bongaCams) {
this.bongaCams = bongaCams;
tabProvider = new BongaCamsTabProvider(bongaCams);
configUi = new BongaCamsConfigUI(bongaCams);
}
@Override
public TabProvider getTabProvider() {
return tabProvider;
}
@Override
public ConfigUI getConfigUI() {
return configUi;
}
@Override
public boolean login() throws IOException {
boolean automaticLogin = bongaCams.login();
if(automaticLogin) {
return true;
} else {
BlockingQueue<Boolean> queue = new LinkedBlockingQueue<>();
Runnable showDialog = () -> {
// login with javafx WebView
BongaCamsLoginDialog loginDialog = new BongaCamsLoginDialog();
// transfer cookies from WebView to OkHttp cookie jar
transferCookies(loginDialog);
try {
queue.put(true);
} catch (InterruptedException e) {
LOG.error("Error while signaling termination", e);
}
};
if(Platform.isFxApplicationThread()) {
showDialog.run();
} else {
Platform.runLater(showDialog);
try {
queue.take();
} catch (InterruptedException e) {
LOG.error("Error while waiting for login dialog to close", e);
throw new IOException(e);
}
}
BongaCamsHttpClient httpClient = (BongaCamsHttpClient)bongaCams.getHttpClient();
boolean loggedIn = httpClient.checkLoginSuccess();
if(loggedIn) {
LOG.info("Logged in. User ID is {}", httpClient.getUserId());
} else {
LOG.info("Login failed");
}
return loggedIn;
}
}
private void transferCookies(BongaCamsLoginDialog loginDialog) {
BongaCamsHttpClient httpClient = (BongaCamsHttpClient)bongaCams.getHttpClient();
CookieJar cookieJar = httpClient.getCookieJar();
HttpUrl redirectedUrl = HttpUrl.parse(loginDialog.getUrl());
List<Cookie> cookies = new ArrayList<>();
for (HttpCookie webViewCookie : loginDialog.getCookies()) {
Cookie cookie = Cookie.parse(redirectedUrl, webViewCookie.toString());
cookies.add(cookie);
}
cookieJar.saveFromResponse(redirectedUrl, cookies);
HttpUrl origUrl = HttpUrl.parse(BongaCamsLoginDialog.URL);
cookies = new ArrayList<>();
for (HttpCookie webViewCookie : loginDialog.getCookies()) {
Cookie cookie = Cookie.parse(origUrl, webViewCookie.toString());
cookies.add(cookie);
}
cookieJar.saveFromResponse(origUrl, cookies);
}
}

View File

@ -1,9 +1,10 @@
package ctbrec.sites.bonga; package ctbrec.ui.sites.bonga;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import ctbrec.recorder.Recorder; import ctbrec.recorder.Recorder;
import ctbrec.sites.bonga.BongaCams;
import ctbrec.ui.PaginatedScheduledService; import ctbrec.ui.PaginatedScheduledService;
import ctbrec.ui.TabProvider; import ctbrec.ui.TabProvider;
import ctbrec.ui.ThumbOverviewTab; import ctbrec.ui.ThumbOverviewTab;
@ -16,9 +17,9 @@ public class BongaCamsTabProvider extends TabProvider {
private Recorder recorder; private Recorder recorder;
private Tab friendsTab; private Tab friendsTab;
public BongaCamsTabProvider(Recorder recorder, BongaCams bongaCams) { public BongaCamsTabProvider(BongaCams bongaCams) {
this.recorder = recorder;
this.bongaCams = bongaCams; this.bongaCams = bongaCams;
this.recorder = bongaCams.getRecorder();
} }
@Override @Override

View File

@ -1,4 +1,4 @@
package ctbrec.sites.bonga; package ctbrec.ui.sites.bonga;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
@ -11,6 +11,8 @@ import org.slf4j.LoggerFactory;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.Model; import ctbrec.Model;
import ctbrec.sites.bonga.BongaCams;
import ctbrec.sites.bonga.BongaCamsModel;
import ctbrec.ui.PaginatedScheduledService; import ctbrec.ui.PaginatedScheduledService;
import javafx.concurrent.Task; import javafx.concurrent.Task;
import okhttp3.Request; import okhttp3.Request;

View File

@ -1,7 +1,8 @@
package ctbrec.sites.cam4; package ctbrec.ui.sites.cam4;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.sites.ConfigUI; import ctbrec.sites.ConfigUI;
import ctbrec.sites.cam4.Cam4;
import ctbrec.ui.DesktopIntegration; import ctbrec.ui.DesktopIntegration;
import ctbrec.ui.SettingsTab; import ctbrec.ui.SettingsTab;
import javafx.geometry.Insets; import javafx.geometry.Insets;

View File

@ -1,5 +1,6 @@
package ctbrec.sites.cam4; package ctbrec.ui.sites.cam4;
import ctbrec.sites.cam4.Cam4;
import ctbrec.ui.FollowedTab; import ctbrec.ui.FollowedTab;
import ctbrec.ui.ThumbOverviewTab; import ctbrec.ui.ThumbOverviewTab;
import javafx.concurrent.WorkerStateEvent; import javafx.concurrent.WorkerStateEvent;

View File

@ -1,4 +1,4 @@
package ctbrec.sites.cam4; package ctbrec.ui.sites.cam4;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
@ -16,9 +16,12 @@ import org.slf4j.LoggerFactory;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.Model; import ctbrec.Model;
import ctbrec.io.HtmlParser;
import ctbrec.io.HttpException; import ctbrec.io.HttpException;
import ctbrec.ui.HtmlParser; import ctbrec.sites.cam4.Cam4;
import ctbrec.sites.cam4.Cam4Model;
import ctbrec.ui.PaginatedScheduledService; import ctbrec.ui.PaginatedScheduledService;
import ctbrec.ui.SiteUiFactory;
import javafx.concurrent.Task; import javafx.concurrent.Task;
import okhttp3.Request; import okhttp3.Request;
import okhttp3.Response; import okhttp3.Response;
@ -48,11 +51,13 @@ public class Cam4FollowedUpdateService extends PaginatedScheduledService {
return new Task<List<Model>>() { return new Task<List<Model>>() {
@Override @Override
public List<Model> call() throws IOException { public List<Model> call() throws IOException {
// login first
SiteUiFactory.getUi(site).login();
List<Model> models = new ArrayList<>(); List<Model> models = new ArrayList<>();
String username = Config.getInstance().getSettings().cam4Username; String username = Config.getInstance().getSettings().cam4Username;
String url = site.getBaseUrl() + '/' + username + "/edit/friends_favorites"; String url = site.getBaseUrl() + '/' + username + "/edit/friends_favorites";
Request req = new Request.Builder().url(url).build(); Request req = new Request.Builder().url(url).build();
try(Response response = site.getHttpClient().execute(req, true)) { try(Response response = site.getHttpClient().execute(req)) {
if(response.isSuccessful()) { if(response.isSuccessful()) {
String content = response.body().string(); String content = response.body().string();
Elements cells = HtmlParser.getTags(content, "div#favorites div.ff_thumb"); Elements cells = HtmlParser.getTags(content, "div#favorites div.ff_thumb");

View File

@ -1,4 +1,4 @@
package ctbrec.sites.cam4; package ctbrec.ui.sites.cam4;
import java.io.File; import java.io.File;
import java.io.InputStream; import java.io.InputStream;
@ -15,6 +15,7 @@ import org.slf4j.LoggerFactory;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.OS; import ctbrec.OS;
import ctbrec.sites.cam4.Cam4;
import javafx.concurrent.Worker.State; import javafx.concurrent.Worker.State;
import javafx.scene.Scene; import javafx.scene.Scene;
import javafx.scene.control.ProgressIndicator; import javafx.scene.control.ProgressIndicator;

View File

@ -0,0 +1,113 @@
package ctbrec.ui.sites.cam4;
import java.io.IOException;
import java.net.HttpCookie;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ctbrec.sites.ConfigUI;
import ctbrec.sites.cam4.Cam4;
import ctbrec.sites.cam4.Cam4HttpClient;
import ctbrec.ui.SiteUI;
import ctbrec.ui.TabProvider;
import javafx.application.Platform;
import okhttp3.Cookie;
import okhttp3.CookieJar;
import okhttp3.HttpUrl;
public class Cam4SiteUi implements SiteUI {
private static final transient Logger LOG = LoggerFactory.getLogger(Cam4SiteUi.class);
private Cam4TabProvider tabProvider;
private Cam4ConfigUI configUI;
private Cam4 cam4;
public Cam4SiteUi(Cam4 cam4) {
this.cam4 = cam4;
tabProvider = new Cam4TabProvider(cam4);
configUI = new Cam4ConfigUI();
}
@Override
public TabProvider getTabProvider() {
return tabProvider;
}
@Override
public ConfigUI getConfigUI() {
return configUI;
}
@Override
public boolean login() throws IOException {
boolean automaticLogin = cam4.login();
if(automaticLogin) {
return true;
} else {
BlockingQueue<Boolean> queue = new LinkedBlockingQueue<>();
Runnable showDialog = () -> {
// login with javafx WebView
Cam4LoginDialog loginDialog = new Cam4LoginDialog();
// transfer cookies from WebView to OkHttp cookie jar
transferCookies(loginDialog);
try {
queue.put(true);
} catch (InterruptedException e) {
LOG.error("Error while signaling termination", e);
}
};
if(Platform.isFxApplicationThread()) {
showDialog.run();
} else {
Platform.runLater(showDialog);
try {
queue.take();
} catch (InterruptedException e) {
LOG.error("Error while waiting for login dialog to close", e);
throw new IOException(e);
}
}
Cam4HttpClient httpClient = (Cam4HttpClient) cam4.getHttpClient();
boolean loggedIn = httpClient.checkLoginSuccess();
return loggedIn;
}
}
private void transferCookies(Cam4LoginDialog loginDialog) {
Cam4HttpClient httpClient = (Cam4HttpClient) cam4.getHttpClient();
CookieJar cookieJar = httpClient.getCookieJar();
HttpUrl redirectedUrl = HttpUrl.parse(loginDialog.getUrl());
List<Cookie> cookies = new ArrayList<>();
for (HttpCookie webViewCookie : loginDialog.getCookies()) {
if(webViewCookie.getDomain().contains("cam4")) {
Cookie cookie = Cookie.parse(redirectedUrl, webViewCookie.toString());
LOG.debug("{} {} {}", webViewCookie.getDomain(), webViewCookie.getName(), webViewCookie.getValue());
cookies.add(cookie);
}
}
cookieJar.saveFromResponse(redirectedUrl, cookies);
HttpUrl origUrl = HttpUrl.parse(Cam4LoginDialog.URL);
cookies = new ArrayList<>();
for (HttpCookie webViewCookie : loginDialog.getCookies()) {
if(webViewCookie.getDomain().contains("cam4")) {
Cookie cookie = Cookie.parse(origUrl, webViewCookie.toString());
cookies.add(cookie);
}
}
cookieJar.saveFromResponse(origUrl, cookies);
}
}

View File

@ -1,9 +1,10 @@
package ctbrec.sites.cam4; package ctbrec.ui.sites.cam4;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import ctbrec.recorder.Recorder; import ctbrec.recorder.Recorder;
import ctbrec.sites.cam4.Cam4;
import ctbrec.ui.TabProvider; import ctbrec.ui.TabProvider;
import ctbrec.ui.ThumbOverviewTab; import ctbrec.ui.ThumbOverviewTab;
import javafx.scene.Scene; import javafx.scene.Scene;
@ -15,9 +16,9 @@ public class Cam4TabProvider extends TabProvider {
private Recorder recorder; private Recorder recorder;
private Cam4FollowedTab followed; private Cam4FollowedTab followed;
public Cam4TabProvider(Cam4 cam4, Recorder recorder) { public Cam4TabProvider(Cam4 cam4) {
this.cam4 = cam4; this.cam4 = cam4;
this.recorder = recorder; this.recorder = cam4.getRecorder();
} }
@Override @Override

View File

@ -1,4 +1,4 @@
package ctbrec.sites.cam4; package ctbrec.ui.sites.cam4;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
@ -8,7 +8,6 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadFactory;
import org.eclipse.jetty.util.StringUtil;
import org.json.JSONObject; import org.json.JSONObject;
import org.jsoup.nodes.Element; import org.jsoup.nodes.Element;
import org.jsoup.select.Elements; import org.jsoup.select.Elements;
@ -17,9 +16,13 @@ import org.slf4j.LoggerFactory;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.Model; import ctbrec.Model;
import ctbrec.StringUtil;
import ctbrec.io.HtmlParser;
import ctbrec.io.HttpException; import ctbrec.io.HttpException;
import ctbrec.ui.HtmlParser; import ctbrec.sites.cam4.Cam4;
import ctbrec.sites.cam4.Cam4Model;
import ctbrec.ui.PaginatedScheduledService; import ctbrec.ui.PaginatedScheduledService;
import ctbrec.ui.SiteUiFactory;
import javafx.concurrent.Task; import javafx.concurrent.Task;
import okhttp3.Request; import okhttp3.Request;
import okhttp3.Response; import okhttp3.Response;
@ -58,8 +61,11 @@ public class Cam4UpdateService extends PaginatedScheduledService {
} else { } else {
String url = Cam4UpdateService.this.url + "&page=" + page; String url = Cam4UpdateService.this.url + "&page=" + page;
LOG.debug("Fetching page {}", url); LOG.debug("Fetching page {}", url);
if(loginRequired) {
SiteUiFactory.getUi(site).login();
}
Request request = new Request.Builder().url(url).build(); Request request = new Request.Builder().url(url).build();
try (Response response = site.getHttpClient().execute(request, loginRequired)) { try (Response response = site.getHttpClient().execute(request)) {
if (response.isSuccessful()) { if (response.isSuccessful()) {
JSONObject json = new JSONObject(response.body().string()); JSONObject json = new JSONObject(response.body().string());
String html = json.getString("html"); String html = json.getString("html");

View File

@ -1,7 +1,8 @@
package ctbrec.sites.camsoda; package ctbrec.ui.sites.camsoda;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.sites.ConfigUI; import ctbrec.sites.ConfigUI;
import ctbrec.sites.camsoda.Camsoda;
import ctbrec.ui.DesktopIntegration; import ctbrec.ui.DesktopIntegration;
import ctbrec.ui.SettingsTab; import ctbrec.ui.SettingsTab;
import javafx.geometry.Insets; import javafx.geometry.Insets;

View File

@ -1,5 +1,6 @@
package ctbrec.sites.camsoda; package ctbrec.ui.sites.camsoda;
import ctbrec.sites.camsoda.Camsoda;
import ctbrec.ui.FollowedTab; import ctbrec.ui.FollowedTab;
import ctbrec.ui.ThumbOverviewTab; import ctbrec.ui.ThumbOverviewTab;
import javafx.concurrent.WorkerStateEvent; import javafx.concurrent.WorkerStateEvent;

View File

@ -1,4 +1,4 @@
package ctbrec.sites.camsoda; package ctbrec.ui.sites.camsoda;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
@ -12,7 +12,10 @@ import org.json.JSONObject;
import ctbrec.Model; import ctbrec.Model;
import ctbrec.io.HttpException; import ctbrec.io.HttpException;
import ctbrec.sites.camsoda.Camsoda;
import ctbrec.sites.camsoda.CamsodaModel;
import ctbrec.ui.PaginatedScheduledService; import ctbrec.ui.PaginatedScheduledService;
import ctbrec.ui.SiteUiFactory;
import javafx.concurrent.Task; import javafx.concurrent.Task;
import okhttp3.Request; import okhttp3.Request;
import okhttp3.Response; import okhttp3.Response;
@ -32,8 +35,9 @@ public class CamsodaFollowedUpdateService extends PaginatedScheduledService {
public List<Model> call() throws IOException { public List<Model> call() throws IOException {
List<Model> models = new ArrayList<>(); List<Model> models = new ArrayList<>();
String url = camsoda.getBaseUrl() + "/api/v1/user/current"; String url = camsoda.getBaseUrl() + "/api/v1/user/current";
SiteUiFactory.getUi(camsoda).login();
Request request = new Request.Builder().url(url).build(); Request request = new Request.Builder().url(url).build();
try(Response response = camsoda.getHttpClient().execute(request, true)) { try(Response response = camsoda.getHttpClient().execute(request)) {
if (response.isSuccessful()) { if (response.isSuccessful()) {
JSONObject json = new JSONObject(response.body().string()); JSONObject json = new JSONObject(response.body().string());
if(json.has("status") && json.getBoolean("status")) { if(json.has("status") && json.getBoolean("status")) {

View File

@ -1,4 +1,4 @@
package ctbrec.sites.camsoda; package ctbrec.ui.sites.camsoda;
import java.io.File; import java.io.File;
import java.io.InputStream; import java.io.InputStream;
@ -9,6 +9,7 @@ import java.util.Base64;
import java.util.List; import java.util.List;
import ctbrec.OS; import ctbrec.OS;
import ctbrec.sites.camsoda.Camsoda;
import javafx.concurrent.Worker.State; import javafx.concurrent.Worker.State;
import javafx.scene.Scene; import javafx.scene.Scene;
import javafx.scene.control.ProgressIndicator; import javafx.scene.control.ProgressIndicator;

View File

@ -1,4 +1,4 @@
package ctbrec.sites.camsoda; package ctbrec.ui.sites.camsoda;
import java.io.IOException; import java.io.IOException;
import java.security.InvalidKeyException; import java.security.InvalidKeyException;
@ -21,8 +21,10 @@ import org.slf4j.LoggerFactory;
import ctbrec.Model; import ctbrec.Model;
import ctbrec.recorder.Recorder; import ctbrec.recorder.Recorder;
import ctbrec.sites.camsoda.Camsoda;
import ctbrec.ui.AutosizeAlert; import ctbrec.ui.AutosizeAlert;
import ctbrec.ui.DesktopIntegration; import ctbrec.ui.DesktopIntegration;
import ctbrec.ui.SiteUiFactory;
import ctbrec.ui.TabSelectionListener; import ctbrec.ui.TabSelectionListener;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.beans.value.ChangeListener; import javafx.beans.value.ChangeListener;
@ -203,6 +205,7 @@ public class CamsodaShowsTab extends Tab implements TabSelectionListener {
setCursor(Cursor.WAIT); setCursor(Cursor.WAIT);
new Thread(() -> { new Thread(() -> {
try { try {
SiteUiFactory.getUi(model.getSite()).login();
model.follow(); model.follow();
} catch (Exception e) { } catch (Exception e) {
LOG.error("Couldn't follow model {}", model, e); LOG.error("Couldn't follow model {}", model, e);

View File

@ -0,0 +1,107 @@
package ctbrec.ui.sites.camsoda;
import java.io.IOException;
import java.net.HttpCookie;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ctbrec.sites.ConfigUI;
import ctbrec.sites.camsoda.Camsoda;
import ctbrec.sites.camsoda.CamsodaHttpClient;
import ctbrec.ui.SiteUI;
import ctbrec.ui.TabProvider;
import ctbrec.ui.sites.cam4.Cam4LoginDialog;
import javafx.application.Platform;
import okhttp3.Cookie;
import okhttp3.HttpUrl;
public class CamsodaSiteUi implements SiteUI {
private static final transient Logger LOG = LoggerFactory.getLogger(CamsodaSiteUi.class);
private CamsodaTabProvider tabProvider;
private CamsodaConfigUI configUi;
private Camsoda camsoda;
public CamsodaSiteUi(Camsoda camsoda) {
this.camsoda = camsoda;
tabProvider = new CamsodaTabProvider(camsoda);
configUi = new CamsodaConfigUI(camsoda);
}
@Override
public TabProvider getTabProvider() {
return tabProvider;
}
@Override
public ConfigUI getConfigUI() {
return configUi;
}
@Override
public boolean login() throws IOException {
boolean automaticLogin = camsoda.login();
return automaticLogin;
}
@SuppressWarnings("unused")
private boolean loginWithDialog() throws IOException {
BlockingQueue<Boolean> queue = new LinkedBlockingQueue<>();
Runnable showDialog = () -> {
// login with javafx WebView
CamsodaLoginDialog loginDialog = new CamsodaLoginDialog();
// transfer cookies from WebView to OkHttp cookie jar
transferCookies(loginDialog);
try {
queue.put(true);
} catch (InterruptedException e) {
LOG.error("Error while signaling termination", e);
}
};
if(Platform.isFxApplicationThread()) {
showDialog.run();
} else {
Platform.runLater(showDialog);
try {
queue.take();
} catch (InterruptedException e) {
LOG.error("Error while waiting for login dialog to close", e);
throw new IOException(e);
}
}
CamsodaHttpClient httpClient = (CamsodaHttpClient)camsoda.getHttpClient();
boolean loggedIn = httpClient.checkLoginSuccess();
return loggedIn;
}
private void transferCookies(CamsodaLoginDialog loginDialog) {
HttpUrl redirectedUrl = HttpUrl.parse(loginDialog.getUrl());
List<Cookie> cookies = new ArrayList<>();
for (HttpCookie webViewCookie : loginDialog.getCookies()) {
Cookie cookie = Cookie.parse(redirectedUrl, webViewCookie.toString());
cookies.add(cookie);
}
camsoda.getHttpClient().getCookieJar().saveFromResponse(redirectedUrl, cookies);
HttpUrl origUrl = HttpUrl.parse(Cam4LoginDialog.URL);
cookies = new ArrayList<>();
for (HttpCookie webViewCookie : loginDialog.getCookies()) {
Cookie cookie = Cookie.parse(origUrl, webViewCookie.toString());
cookies.add(cookie);
}
camsoda.getHttpClient().getCookieJar().saveFromResponse(origUrl, cookies);
}
}

View File

@ -1,4 +1,4 @@
package ctbrec.sites.camsoda; package ctbrec.ui.sites.camsoda;
import static ctbrec.sites.camsoda.Camsoda.*; import static ctbrec.sites.camsoda.Camsoda.*;
@ -6,6 +6,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import ctbrec.recorder.Recorder; import ctbrec.recorder.Recorder;
import ctbrec.sites.camsoda.Camsoda;
import ctbrec.ui.TabProvider; import ctbrec.ui.TabProvider;
import ctbrec.ui.ThumbOverviewTab; import ctbrec.ui.ThumbOverviewTab;
import javafx.scene.Scene; import javafx.scene.Scene;
@ -17,9 +18,9 @@ public class CamsodaTabProvider extends TabProvider {
private Recorder recorder; private Recorder recorder;
CamsodaFollowedTab followedTab; CamsodaFollowedTab followedTab;
public CamsodaTabProvider(Camsoda camsoda, Recorder recorder) { public CamsodaTabProvider(Camsoda camsoda) {
this.camsoda = camsoda; this.camsoda = camsoda;
this.recorder = recorder; this.recorder = camsoda.getRecorder();
followedTab = new CamsodaFollowedTab("Followed", camsoda); followedTab = new CamsodaFollowedTab("Followed", camsoda);
} }

View File

@ -1,4 +1,4 @@
package ctbrec.sites.camsoda; package ctbrec.ui.sites.camsoda;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
@ -6,15 +6,18 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.eclipse.jetty.util.StringUtil;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONObject; import org.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import ctbrec.Model; import ctbrec.Model;
import ctbrec.StringUtil;
import ctbrec.io.HttpException; import ctbrec.io.HttpException;
import ctbrec.sites.camsoda.Camsoda;
import ctbrec.sites.camsoda.CamsodaModel;
import ctbrec.ui.PaginatedScheduledService; import ctbrec.ui.PaginatedScheduledService;
import ctbrec.ui.SiteUiFactory;
import javafx.concurrent.Task; import javafx.concurrent.Task;
import okhttp3.Request; import okhttp3.Request;
import okhttp3.Response; import okhttp3.Response;
@ -45,8 +48,11 @@ public class CamsodaUpdateService extends PaginatedScheduledService {
} else { } else {
String url = CamsodaUpdateService.this.url; String url = CamsodaUpdateService.this.url;
LOG.debug("Fetching page {}", url); LOG.debug("Fetching page {}", url);
if(loginRequired) {
SiteUiFactory.getUi(camsoda).login();
}
Request request = new Request.Builder().url(url).build(); Request request = new Request.Builder().url(url).build();
try(Response response = camsoda.getHttpClient().execute(request, loginRequired)) { try(Response response = camsoda.getHttpClient().execute(request)) {
if (response.isSuccessful()) { if (response.isSuccessful()) {
JSONObject json = new JSONObject(response.body().string()); JSONObject json = new JSONObject(response.body().string());
if(json.has("status") && json.getBoolean("status")) { if(json.has("status") && json.getBoolean("status")) {

View File

@ -1,7 +1,8 @@
package ctbrec.sites.chaturbate; package ctbrec.ui.sites.chaturbate;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.sites.ConfigUI; import ctbrec.sites.ConfigUI;
import ctbrec.sites.chaturbate.Chaturbate;
import ctbrec.ui.DesktopIntegration; import ctbrec.ui.DesktopIntegration;
import ctbrec.ui.SettingsTab; import ctbrec.ui.SettingsTab;
import javafx.geometry.Insets; import javafx.geometry.Insets;

View File

@ -1,5 +1,6 @@
package ctbrec.sites.chaturbate; package ctbrec.ui.sites.chaturbate;
import ctbrec.sites.chaturbate.Chaturbate;
import ctbrec.ui.FollowedTab; import ctbrec.ui.FollowedTab;
import ctbrec.ui.ThumbOverviewTab; import ctbrec.ui.ThumbOverviewTab;
import javafx.concurrent.WorkerStateEvent; import javafx.concurrent.WorkerStateEvent;

View File

@ -0,0 +1,37 @@
package ctbrec.ui.sites.chaturbate;
import java.io.IOException;
import ctbrec.sites.ConfigUI;
import ctbrec.sites.chaturbate.Chaturbate;
import ctbrec.ui.SiteUI;
import ctbrec.ui.TabProvider;
public class ChaturbateSiteUi implements SiteUI {
private ChaturbateTabProvider tabProvider;
private ChaturbateConfigUi configUi;
private Chaturbate chaturbate;
public ChaturbateSiteUi(Chaturbate chaturbate) {
this.chaturbate = chaturbate;
tabProvider = new ChaturbateTabProvider(chaturbate);
configUi = new ChaturbateConfigUi();
}
@Override
public TabProvider getTabProvider() {
return tabProvider;
}
@Override
public ConfigUI getConfigUI() {
return configUi;
}
@Override
public boolean login() throws IOException {
return chaturbate.login();
}
}

View File

@ -1,4 +1,4 @@
package ctbrec.sites.chaturbate; package ctbrec.ui.sites.chaturbate;
import static ctbrec.sites.chaturbate.Chaturbate.*; import static ctbrec.sites.chaturbate.Chaturbate.*;
@ -6,6 +6,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import ctbrec.recorder.Recorder; import ctbrec.recorder.Recorder;
import ctbrec.sites.chaturbate.Chaturbate;
import ctbrec.ui.TabProvider; import ctbrec.ui.TabProvider;
import ctbrec.ui.ThumbOverviewTab; import ctbrec.ui.ThumbOverviewTab;
import javafx.scene.Scene; import javafx.scene.Scene;
@ -17,9 +18,9 @@ public class ChaturbateTabProvider extends TabProvider {
private Recorder recorder; private Recorder recorder;
private ChaturbateFollowedTab followedTab; private ChaturbateFollowedTab followedTab;
public ChaturbateTabProvider(Chaturbate chaturbate, Recorder recorder) { public ChaturbateTabProvider(Chaturbate chaturbate) {
this.chaturbate = chaturbate; this.chaturbate = chaturbate;
this.recorder = recorder; this.recorder = chaturbate.getRecorder();
this.followedTab = new ChaturbateFollowedTab("Followed", BASE_URI + "/followed-cams/", chaturbate); this.followedTab = new ChaturbateFollowedTab("Followed", BASE_URI + "/followed-cams/", chaturbate);
} }

View File

@ -1,4 +1,4 @@
package ctbrec.sites.chaturbate; package ctbrec.ui.sites.chaturbate;
import java.io.IOException; import java.io.IOException;
import java.util.Collections; import java.util.Collections;
@ -7,12 +7,15 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadFactory;
import org.eclipse.jetty.util.StringUtil;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import ctbrec.Model; import ctbrec.Model;
import ctbrec.StringUtil;
import ctbrec.sites.chaturbate.Chaturbate;
import ctbrec.sites.chaturbate.ChaturbateModelParser;
import ctbrec.ui.PaginatedScheduledService; import ctbrec.ui.PaginatedScheduledService;
import ctbrec.ui.SiteUiFactory;
import javafx.concurrent.Task; import javafx.concurrent.Task;
import okhttp3.Request; import okhttp3.Request;
import okhttp3.Response; import okhttp3.Response;
@ -51,8 +54,11 @@ public class ChaturbateUpdateService extends PaginatedScheduledService {
} else { } else {
String url = ChaturbateUpdateService.this.url + "?page="+page+"&keywords=&_=" + System.currentTimeMillis(); String url = ChaturbateUpdateService.this.url + "?page="+page+"&keywords=&_=" + System.currentTimeMillis();
LOG.debug("Fetching page {}", url); LOG.debug("Fetching page {}", url);
if(loginRequired) {
SiteUiFactory.getUi(chaturbate).login();
}
Request request = new Request.Builder().url(url).build(); Request request = new Request.Builder().url(url).build();
Response response = chaturbate.getHttpClient().execute(request, loginRequired); Response response = chaturbate.getHttpClient().execute(request);
if (response.isSuccessful()) { if (response.isSuccessful()) {
List<Model> models = ChaturbateModelParser.parseModels(chaturbate, response.body().string()); List<Model> models = ChaturbateModelParser.parseModels(chaturbate, response.body().string());
response.close(); response.close();

View File

@ -1,4 +1,4 @@
package ctbrec.sites.mfc; package ctbrec.ui.sites.myfreecams;
import java.io.IOException; import java.io.IOException;
@ -7,13 +7,19 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.eclipse.jetty.util.StringUtil;
import org.json.JSONObject; import org.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import ctbrec.Model; import ctbrec.Model;
import ctbrec.StringUtil;
import ctbrec.sites.mfc.MyFreeCams;
import ctbrec.sites.mfc.MyFreeCamsClient;
import ctbrec.sites.mfc.MyFreeCamsModel;
import ctbrec.sites.mfc.SessionState;
import ctbrec.sites.mfc.User;
import ctbrec.ui.PaginatedScheduledService; import ctbrec.ui.PaginatedScheduledService;
import ctbrec.ui.SiteUiFactory;
import javafx.concurrent.Task; import javafx.concurrent.Task;
import okhttp3.Request; import okhttp3.Request;
import okhttp3.Response; import okhttp3.Response;
@ -42,12 +48,13 @@ public class FriendsUpdateService extends PaginatedScheduledService {
return Collections.emptyList(); return Collections.emptyList();
} else { } else {
List<MyFreeCamsModel> models = new ArrayList<>(); List<MyFreeCamsModel> models = new ArrayList<>();
SiteUiFactory.getUi(myFreeCams).login();
String url = myFreeCams.getBaseUrl() + "/php/manage_lists2.php?passcode=&list_type=friends&data_mode=online&get_user_list=1"; String url = myFreeCams.getBaseUrl() + "/php/manage_lists2.php?passcode=&list_type=friends&data_mode=online&get_user_list=1";
Request req = new Request.Builder() Request req = new Request.Builder()
.url(url) .url(url)
.header("Referer", myFreeCams.getBaseUrl()) .header("Referer", myFreeCams.getBaseUrl())
.build(); .build();
try(Response resp = myFreeCams.getHttpClient().execute(req, true)) { try(Response resp = myFreeCams.getHttpClient().execute(req)) {
if(resp.isSuccessful()) { if(resp.isSuccessful()) {
String body = resp.body().string().substring(4); String body = resp.body().string().substring(4);
try { try {

View File

@ -1,4 +1,4 @@
package ctbrec.sites.mfc; package ctbrec.ui.sites.myfreecams;
import java.io.IOException; import java.io.IOException;
@ -6,6 +6,7 @@ import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import ctbrec.Model; import ctbrec.Model;
import ctbrec.sites.mfc.MyFreeCamsClient;
import ctbrec.ui.PaginatedScheduledService; import ctbrec.ui.PaginatedScheduledService;
import javafx.concurrent.Task; import javafx.concurrent.Task;

View File

@ -1,7 +1,8 @@
package ctbrec.sites.mfc; package ctbrec.ui.sites.myfreecams;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.sites.ConfigUI; import ctbrec.sites.ConfigUI;
import ctbrec.sites.mfc.MyFreeCams;
import ctbrec.ui.DesktopIntegration; import ctbrec.ui.DesktopIntegration;
import ctbrec.ui.SettingsTab; import ctbrec.ui.SettingsTab;
import javafx.geometry.Insets; import javafx.geometry.Insets;

View File

@ -1,8 +1,9 @@
package ctbrec.sites.mfc; package ctbrec.ui.sites.myfreecams;
import static ctbrec.sites.mfc.FriendsUpdateService.Mode.*; import static ctbrec.ui.sites.myfreecams.FriendsUpdateService.Mode.*;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import ctbrec.sites.mfc.MyFreeCams;
import ctbrec.ui.FollowedTab; import ctbrec.ui.FollowedTab;
import ctbrec.ui.ThumbOverviewTab; import ctbrec.ui.ThumbOverviewTab;
import javafx.geometry.Insets; import javafx.geometry.Insets;

View File

@ -0,0 +1,37 @@
package ctbrec.ui.sites.myfreecams;
import java.io.IOException;
import ctbrec.sites.ConfigUI;
import ctbrec.sites.mfc.MyFreeCams;
import ctbrec.ui.SiteUI;
import ctbrec.ui.TabProvider;
public class MyFreeCamsSiteUi implements SiteUI {
private MyFreeCamsTabProvider tabProvider;
private MyFreeCamsConfigUI configUi;
private MyFreeCams myFreeCams;
public MyFreeCamsSiteUi(MyFreeCams myFreeCams) {
this.myFreeCams = myFreeCams;
tabProvider = new MyFreeCamsTabProvider(myFreeCams);
configUi = new MyFreeCamsConfigUI(myFreeCams);
}
@Override
public TabProvider getTabProvider() {
return tabProvider;
}
@Override
public ConfigUI getConfigUI() {
return configUi;
}
@Override
public boolean login() throws IOException {
return myFreeCams.login();
}
}

View File

@ -1,10 +1,11 @@
package ctbrec.sites.mfc; package ctbrec.ui.sites.myfreecams;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import ctbrec.recorder.Recorder; import ctbrec.recorder.Recorder;
import ctbrec.sites.mfc.MyFreeCams;
import ctbrec.ui.PaginatedScheduledService; import ctbrec.ui.PaginatedScheduledService;
import ctbrec.ui.TabProvider; import ctbrec.ui.TabProvider;
import ctbrec.ui.ThumbOverviewTab; import ctbrec.ui.ThumbOverviewTab;
@ -17,9 +18,9 @@ public class MyFreeCamsTabProvider extends TabProvider {
private MyFreeCams myFreeCams; private MyFreeCams myFreeCams;
private MyFreeCamsFriendsTab friends; private MyFreeCamsFriendsTab friends;
public MyFreeCamsTabProvider(MyFreeCamsClient client, Recorder recorder, MyFreeCams myFreeCams) { public MyFreeCamsTabProvider(MyFreeCams myFreeCams) {
this.recorder = recorder;
this.myFreeCams = myFreeCams; this.myFreeCams = myFreeCams;
this.recorder = myFreeCams.getRecorder();
} }
@Override @Override

View File

@ -1,4 +1,4 @@
package ctbrec.sites.mfc; package ctbrec.ui.sites.myfreecams;
import java.io.IOException; import java.io.IOException;
@ -6,6 +6,7 @@ import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import ctbrec.Model; import ctbrec.Model;
import ctbrec.sites.mfc.MyFreeCamsClient;
import ctbrec.ui.PaginatedScheduledService; import ctbrec.ui.PaginatedScheduledService;
import javafx.concurrent.Task; import javafx.concurrent.Task;

View File

@ -1,10 +1,11 @@
package ctbrec.sites.mfc; package ctbrec.ui.sites.myfreecams;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import ctbrec.Model; import ctbrec.Model;
import ctbrec.sites.mfc.MyFreeCamsClient;
import ctbrec.ui.PaginatedScheduledService; import ctbrec.ui.PaginatedScheduledService;
import javafx.concurrent.Task; import javafx.concurrent.Task;

15
common/.classpath Normal file
View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>

2
common/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/bin/
/target/

23
common/.project Normal file
View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>ctbrec-common</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,2 @@
eclipse.preferences.version=1
encoding/<project>=UTF-8

View File

@ -0,0 +1,13 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.release=disabled
org.eclipse.jdt.core.compiler.source=1.8

View File

@ -0,0 +1,4 @@
activeProfiles=
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1

65
common/pom.xml Normal file
View File

@ -0,0 +1,65 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>common</artifactId>
<parent>
<groupId>ctbrec</groupId>
<artifactId>master</artifactId>
<version>1.9.0</version>
<relativePath>../master</relativePath>
</parent>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
</dependency>
<dependency>
<groupId>com.squareup.moshi</groupId>
<artifactId>moshi</artifactId>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
</dependency>
<dependency>
<groupId>com.iheartradio.m3u8</groupId>
<artifactId>open-m3u8</artifactId>
</dependency>
<dependency>
<groupId>org.jcodec</groupId>
<artifactId>jcodec</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-web</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,11 @@
package ctbrec;
public class StringUtil {
public static boolean isBlank(String s) {
return s == null || s.trim().isEmpty();
}
public static boolean isNotBlank(String s) {
return !isBlank(s);
}
}

View File

@ -1,4 +1,4 @@
package ctbrec.ui; package ctbrec.io;
import org.jsoup.Jsoup; import org.jsoup.Jsoup;
import org.jsoup.nodes.Document; import org.jsoup.nodes.Document;

View File

@ -23,6 +23,7 @@ import ctbrec.Config;
import ctbrec.Settings.ProxyType; import ctbrec.Settings.ProxyType;
import okhttp3.ConnectionPool; import okhttp3.ConnectionPool;
import okhttp3.Cookie; import okhttp3.Cookie;
import okhttp3.CookieJar;
import okhttp3.Credentials; import okhttp3.Credentials;
import okhttp3.OkHttpClient; import okhttp3.OkHttpClient;
import okhttp3.OkHttpClient.Builder; import okhttp3.OkHttpClient.Builder;
@ -91,18 +92,19 @@ public abstract class HttpClient {
} }
} }
public Response execute(Request request) throws IOException { // public Response execute(Request request) throws IOException {
Response resp = execute(request, false); // Response resp = execute(request, false);
return resp; // return resp;
} // }
public Response execute(Request req, boolean requiresLogin) throws IOException { // public Response execute(Request req, boolean requiresLogin) throws IOException {
if(requiresLogin && !loggedIn) { public Response execute(Request req) throws IOException {
loggedIn = login(); // if(requiresLogin && !loggedIn) {
if(!loggedIn) { // loggedIn = login();
throw new IOException("403 Unauthorized"); // if(!loggedIn) {
} // throw new IOException("403 Unauthorized");
} // }
// }
Response resp = client.newCall(req).execute(); Response resp = client.newCall(req).execute();
return resp; return resp;
} }
@ -209,4 +211,8 @@ public abstract class HttpClient {
return auth; return auth;
} }
} }
public CookieJar getCookieJar() {
return cookieJar;
}
} }

View File

@ -36,13 +36,13 @@ import ctbrec.Model;
import ctbrec.OS; import ctbrec.OS;
import ctbrec.Recording; import ctbrec.Recording;
import ctbrec.Recording.STATUS; import ctbrec.Recording.STATUS;
import ctbrec.io.HttpClient;
import ctbrec.io.HttpException; import ctbrec.io.HttpException;
import ctbrec.io.StreamRedirectThread; import ctbrec.io.StreamRedirectThread;
import ctbrec.recorder.PlaylistGenerator.InvalidPlaylistException; import ctbrec.recorder.PlaylistGenerator.InvalidPlaylistException;
import ctbrec.recorder.download.Download; import ctbrec.recorder.download.Download;
import ctbrec.recorder.download.HlsDownload; import ctbrec.recorder.download.HlsDownload;
import ctbrec.recorder.download.MergedHlsDownload; import ctbrec.recorder.download.MergedHlsDownload;
import ctbrec.recorder.server.RecorderHttpClient;
public class LocalRecorder implements Recorder { public class LocalRecorder implements Recorder {
@ -722,4 +722,9 @@ public class LocalRecorder implements Recorder {
lock.unlock(); lock.unlock();
} }
} }
@Override
public HttpClient getHttpClient() {
return client;
}
} }

View File

@ -7,6 +7,7 @@ import java.util.List;
import ctbrec.Model; import ctbrec.Model;
import ctbrec.Recording; import ctbrec.Recording;
import ctbrec.io.HttpClient;
public interface Recorder { public interface Recorder {
public void startRecording(Model model) throws IOException, InvalidKeyException, NoSuchAlgorithmException, IllegalStateException; public void startRecording(Model model) throws IOException, InvalidKeyException, NoSuchAlgorithmException, IllegalStateException;
@ -39,4 +40,6 @@ public interface Recorder {
* @return * @return
*/ */
public List<Model> getOnlineModels(); public List<Model> getOnlineModels();
public HttpClient getHttpClient();
} }

View File

@ -1,4 +1,4 @@
package ctbrec.recorder.server; package ctbrec.recorder;
import java.io.IOException; import java.io.IOException;

View File

@ -357,4 +357,9 @@ public class RemoteRecorder implements Recorder {
public List<Model> getOnlineModels() { public List<Model> getOnlineModels() {
return onlineModels; return onlineModels;
} }
@Override
public HttpClient getHttpClient() {
return client;
}
} }

View File

@ -1,8 +1,11 @@
package ctbrec.sites; package ctbrec.sites;
import ctbrec.recorder.Recorder;
public abstract class AbstractSite implements Site { public abstract class AbstractSite implements Site {
private boolean enabled; private boolean enabled;
private Recorder recorder;
@Override @Override
public void setEnabled(boolean enabled) { public void setEnabled(boolean enabled) {
@ -13,4 +16,14 @@ public abstract class AbstractSite implements Site {
public boolean isEnabled() { public boolean isEnabled() {
return enabled; return enabled;
} }
@Override
public void setRecorder(Recorder recorder) {
this.recorder = recorder;
}
@Override
public Recorder getRecorder() {
return recorder;
}
} }

View File

@ -0,0 +1,7 @@
package ctbrec.sites;
import java.io.IOException;
public class NeedsManualLoginException extends IOException {
}

View File

@ -5,25 +5,23 @@ import java.io.IOException;
import ctbrec.Model; import ctbrec.Model;
import ctbrec.io.HttpClient; import ctbrec.io.HttpClient;
import ctbrec.recorder.Recorder; import ctbrec.recorder.Recorder;
import ctbrec.ui.TabProvider;
public interface Site { public interface Site {
public String getName(); public String getName();
public String getBaseUrl(); public String getBaseUrl();
public String getAffiliateLink(); public String getAffiliateLink();
public void setRecorder(Recorder recorder); public void setRecorder(Recorder recorder);
public TabProvider getTabProvider(); public Recorder getRecorder();
public Model createModel(String name); public Model createModel(String name);
public Integer getTokenBalance() throws IOException; public Integer getTokenBalance() throws IOException;
public String getBuyTokensLink(); public String getBuyTokensLink();
public void login() throws IOException; public boolean login() throws IOException;
public HttpClient getHttpClient(); public HttpClient getHttpClient();
public void init() throws IOException; public void init() throws IOException;
public void shutdown(); public void shutdown();
public boolean supportsTips(); public boolean supportsTips();
public boolean supportsFollow(); public boolean supportsFollow();
public boolean isSiteForModel(Model m); public boolean isSiteForModel(Model m);
public ConfigUI getConfigurationGui();
public boolean credentialsAvailable(); public boolean credentialsAvailable();
public void setEnabled(boolean enabled); public void setEnabled(boolean enabled);
public boolean isEnabled(); public boolean isEnabled();

View File

@ -8,10 +8,7 @@ import ctbrec.Config;
import ctbrec.Model; import ctbrec.Model;
import ctbrec.io.HttpClient; import ctbrec.io.HttpClient;
import ctbrec.io.HttpException; import ctbrec.io.HttpException;
import ctbrec.recorder.Recorder;
import ctbrec.sites.AbstractSite; import ctbrec.sites.AbstractSite;
import ctbrec.sites.ConfigUI;
import ctbrec.ui.TabProvider;
import okhttp3.FormBody; import okhttp3.FormBody;
import okhttp3.Request; import okhttp3.Request;
import okhttp3.RequestBody; import okhttp3.RequestBody;
@ -22,8 +19,6 @@ public class BongaCams extends AbstractSite {
public static final String BASE_URL = "https://bongacams.com"; public static final String BASE_URL = "https://bongacams.com";
private BongaCamsHttpClient httpClient; private BongaCamsHttpClient httpClient;
private Recorder recorder;
private BongaCamsTabProvider tabProvider;
@Override @Override
public String getName() { public String getName() {
@ -40,19 +35,6 @@ public class BongaCams extends AbstractSite {
return "http://bongacams2.com/track?c=610249"; return "http://bongacams2.com/track?c=610249";
} }
@Override
public void setRecorder(Recorder recorder) {
this.recorder = recorder;
}
@Override
public TabProvider getTabProvider() {
if(tabProvider == null) {
tabProvider = new BongaCamsTabProvider(recorder, this);
}
return tabProvider;
}
@Override @Override
public Model createModel(String name) { public Model createModel(String name) {
BongaCamsModel model = new BongaCamsModel(); BongaCamsModel model = new BongaCamsModel();
@ -80,7 +62,7 @@ public class BongaCams extends AbstractSite {
.addHeader("X-Requested-With", "XMLHttpRequest") .addHeader("X-Requested-With", "XMLHttpRequest")
.post(body) .post(body)
.build(); .build();
try(Response response = getHttpClient().execute(request, true)) { try(Response response = getHttpClient().execute(request)) {
if(response.isSuccessful()) { if(response.isSuccessful()) {
JSONObject json = new JSONObject(response.body().string()); JSONObject json = new JSONObject(response.body().string());
if(json.optString("status").equals("online")) { if(json.optString("status").equals("online")) {
@ -101,8 +83,8 @@ public class BongaCams extends AbstractSite {
} }
@Override @Override
public void login() throws IOException { public boolean login() throws IOException {
getHttpClient().login(); return credentialsAvailable() && getHttpClient().login();
} }
@Override @Override
@ -139,11 +121,6 @@ public class BongaCams extends AbstractSite {
return m instanceof BongaCamsModel; return m instanceof BongaCamsModel;
} }
@Override
public ConfigUI getConfigurationGui() {
return new BongaCamsConfigUI(this);
}
@Override @Override
public boolean credentialsAvailable() { public boolean credentialsAvailable() {
String username = Config.getInstance().getSettings().bongaUsername; String username = Config.getInstance().getSettings().bongaUsername;

View File

@ -1,14 +1,10 @@
package ctbrec.sites.bonga; package ctbrec.sites.bonga;
import java.io.IOException; import java.io.IOException;
import java.net.HttpCookie;
import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONObject; import org.json.JSONObject;
@ -18,10 +14,8 @@ import org.slf4j.LoggerFactory;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.io.HttpClient; import ctbrec.io.HttpClient;
import ctbrec.io.HttpException; import ctbrec.io.HttpException;
import javafx.application.Platform;
import okhttp3.Cookie; import okhttp3.Cookie;
import okhttp3.FormBody; import okhttp3.FormBody;
import okhttp3.HttpUrl;
import okhttp3.Request; import okhttp3.Request;
import okhttp3.RequestBody; import okhttp3.RequestBody;
import okhttp3.Response; import okhttp3.Response;
@ -72,48 +66,14 @@ public class BongaCamsHttpClient extends HttpClient {
return true; return true;
} }
BlockingQueue<Boolean> queue = new LinkedBlockingQueue<>(); return false;
Runnable showDialog = () -> {
// login with javafx WebView
BongaCamsLoginDialog loginDialog = new BongaCamsLoginDialog();
// transfer cookies from WebView to OkHttp cookie jar
transferCookies(loginDialog);
try {
queue.put(true);
} catch (InterruptedException e) {
LOG.error("Error while signaling termination", e);
}
};
if(Platform.isFxApplicationThread()) {
showDialog.run();
} else {
Platform.runLater(showDialog);
try {
queue.take();
} catch (InterruptedException e) {
LOG.error("Error while waiting for login dialog to close", e);
throw new IOException(e);
}
}
loggedIn = checkLoginSuccess();
if(loggedIn) {
LOG.info("Logged in. User ID is {}", userId);
} else {
LOG.info("Login failed");
}
return loggedIn;
} }
/** /**
* Check, if the login worked by requesting roomdata and looking * Check, if the login worked by requesting roomdata and looking
* @throws IOException * @throws IOException
*/ */
private boolean checkLoginSuccess() throws IOException { public boolean checkLoginSuccess() throws IOException {
String modelName = getAnyModelName(); String modelName = getAnyModelName();
// we request the roomData of a random model, because it contains // we request the roomData of a random model, because it contains
// user data, if the user is logged in, which we can use to verify, that the login worked // user data, if the user is logged in, which we can use to verify, that the login worked
@ -180,24 +140,6 @@ public class BongaCamsHttpClient extends HttpClient {
} }
} }
private void transferCookies(BongaCamsLoginDialog loginDialog) {
HttpUrl redirectedUrl = HttpUrl.parse(loginDialog.getUrl());
List<Cookie> cookies = new ArrayList<>();
for (HttpCookie webViewCookie : loginDialog.getCookies()) {
Cookie cookie = Cookie.parse(redirectedUrl, webViewCookie.toString());
cookies.add(cookie);
}
cookieJar.saveFromResponse(redirectedUrl, cookies);
HttpUrl origUrl = HttpUrl.parse(BongaCamsLoginDialog.URL);
cookies = new ArrayList<>();
for (HttpCookie webViewCookie : loginDialog.getCookies()) {
Cookie cookie = Cookie.parse(origUrl, webViewCookie.toString());
cookies.add(cookie);
}
cookieJar.saveFromResponse(origUrl, cookies);
}
// @Override // @Override
// public boolean login() throws IOException { // public boolean login() throws IOException {
// String url = BongaCams.BASE_URL + "/login"; // String url = BongaCams.BASE_URL + "/login";

View File

@ -165,7 +165,7 @@ public class BongaCamsModel extends AbstractModel {
.addHeader("X-Requested-With", "XMLHttpRequest") .addHeader("X-Requested-With", "XMLHttpRequest")
.post(body) .post(body)
.build(); .build();
try(Response response = site.getHttpClient().execute(request, true)) { try(Response response = site.getHttpClient().execute(request)) {
if(response.isSuccessful()) { if(response.isSuccessful()) {
JSONObject json = new JSONObject(response.body().string()); JSONObject json = new JSONObject(response.body().string());
if(!json.optString("status").equals("success")) { if(!json.optString("status").equals("success")) {

View File

@ -2,15 +2,10 @@ package ctbrec.sites.cam4;
import java.io.IOException; import java.io.IOException;
import org.slf4j.LoggerFactory;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.Model; import ctbrec.Model;
import ctbrec.io.HttpClient; import ctbrec.io.HttpClient;
import ctbrec.recorder.Recorder;
import ctbrec.sites.AbstractSite; import ctbrec.sites.AbstractSite;
import ctbrec.sites.ConfigUI;
import ctbrec.ui.TabProvider;
public class Cam4 extends AbstractSite { public class Cam4 extends AbstractSite {
@ -19,8 +14,6 @@ public class Cam4 extends AbstractSite {
public static final String AFFILIATE_LINK = BASE_URI + "/?referrerId=1514a80d87b5effb456cca02f6743aa1"; public static final String AFFILIATE_LINK = BASE_URI + "/?referrerId=1514a80d87b5effb456cca02f6743aa1";
private HttpClient httpClient; private HttpClient httpClient;
private Recorder recorder;
private Cam4TabProvider tabProvider;
@Override @Override
public String getName() { public String getName() {
@ -37,19 +30,6 @@ public class Cam4 extends AbstractSite {
return AFFILIATE_LINK; return AFFILIATE_LINK;
} }
@Override
public void setRecorder(Recorder recorder) {
this.recorder = recorder;
}
@Override
public TabProvider getTabProvider() {
if(tabProvider == null) {
tabProvider = new Cam4TabProvider(this, recorder);
}
return tabProvider;
}
@Override @Override
public Model createModel(String name) { public Model createModel(String name) {
Cam4Model m = new Cam4Model(); Cam4Model m = new Cam4Model();
@ -73,11 +53,8 @@ public class Cam4 extends AbstractSite {
} }
@Override @Override
public void login() throws IOException { public boolean login() throws IOException {
if (credentialsAvailable()) { return credentialsAvailable() && getHttpClient().login();
boolean success = getHttpClient().login();
LoggerFactory.getLogger(getClass()).debug("Login success: {}", success);
}
} }
@Override @Override
@ -117,9 +94,4 @@ public class Cam4 extends AbstractSite {
String username = Config.getInstance().getSettings().cam4Username; String username = Config.getInstance().getSettings().cam4Username;
return username != null && !username.trim().isEmpty(); return username != null && !username.trim().isEmpty();
} }
@Override
public ConfigUI getConfigurationGui() {
return new Cam4ConfigUI();
}
} }

View File

@ -0,0 +1,65 @@
package ctbrec.sites.cam4;
import java.io.IOException;
import java.util.Objects;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ctbrec.io.HttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class Cam4HttpClient extends HttpClient {
private static final transient Logger LOG = LoggerFactory.getLogger(Cam4HttpClient.class);
public Cam4HttpClient() {
super("cam4");
}
@Override
public synchronized boolean login() throws IOException {
if(loggedIn) {
return true;
}
boolean cookiesWorked = checkLoginSuccess();
if(cookiesWorked) {
loggedIn = true;
LOG.debug("Logged in with cookies");
return true;
}
return false;
}
/**
* check, if the login worked by requesting unchecked mail
* @throws IOException
*/
public boolean checkLoginSuccess() throws IOException {
String mailUrl = Cam4.BASE_URI + "/mail/unreadThreads";
Request req = new Request.Builder()
.url(mailUrl)
.addHeader("X-Requested-With", "XMLHttpRequest")
.build();
Response response = execute(req);
if(response.isSuccessful() && response.body().contentLength() > 0) {
JSONObject json = new JSONObject(response.body().string());
return json.has("status") && Objects.equals("success", json.getString("status"));
} else {
response.close();
return false;
}
}
protected int getTokenBalance() throws IOException {
if(!loggedIn) {
login();
}
throw new RuntimeException("Not implemented, yet");
}
}

View File

@ -24,11 +24,10 @@ import com.iheartradio.m3u8.data.PlaylistData;
import ctbrec.AbstractModel; import ctbrec.AbstractModel;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.io.HtmlParser;
import ctbrec.io.HttpException; import ctbrec.io.HttpException;
import ctbrec.recorder.download.StreamSource; import ctbrec.recorder.download.StreamSource;
import ctbrec.sites.Site; import ctbrec.sites.Site;
import ctbrec.ui.CamrecApplication;
import ctbrec.ui.HtmlParser;
import okhttp3.FormBody; import okhttp3.FormBody;
import okhttp3.Request; import okhttp3.Request;
import okhttp3.RequestBody; import okhttp3.RequestBody;
@ -168,7 +167,7 @@ public class Cam4Model extends AbstractModel {
.url(url) .url(url)
.addHeader("X-Requested-With", "XMLHttpRequest") .addHeader("X-Requested-With", "XMLHttpRequest")
.build(); .build();
Response response = site.getHttpClient().execute(req, true); Response response = site.getHttpClient().execute(req);
boolean success = response.isSuccessful(); boolean success = response.isSuccessful();
response.close(); response.close();
return success; return success;
@ -185,7 +184,7 @@ public class Cam4Model extends AbstractModel {
// we have to use a client without any cam4 cookies here, otherwise // we have to use a client without any cam4 cookies here, otherwise
// this request is redirected to the login page. no idea why // this request is redirected to the login page. no idea why
try(Response response = CamrecApplication.httpClient.execute(req)) { try(Response response = site.getRecorder().getHttpClient().execute(req)) {
String broadCasterId = null; String broadCasterId = null;
if(response.isSuccessful()) { if(response.isSuccessful()) {
String content = response.body().string(); String content = response.body().string();
@ -209,7 +208,7 @@ public class Cam4Model extends AbstractModel {
.post(body) .post(body)
.addHeader("X-Requested-With", "XMLHttpRequest") .addHeader("X-Requested-With", "XMLHttpRequest")
.build(); .build();
Response resp = site.getHttpClient().execute(req, true); Response resp = site.getHttpClient().execute(req);
if(resp.isSuccessful()) { if(resp.isSuccessful()) {
return Objects.equals(resp.body().string(), "Ok"); return Objects.equals(resp.body().string(), "Ok");
} else { } else {

View File

@ -8,19 +8,14 @@ import ctbrec.Config;
import ctbrec.Model; import ctbrec.Model;
import ctbrec.io.HttpClient; import ctbrec.io.HttpClient;
import ctbrec.io.HttpException; import ctbrec.io.HttpException;
import ctbrec.recorder.Recorder;
import ctbrec.sites.AbstractSite; import ctbrec.sites.AbstractSite;
import ctbrec.sites.ConfigUI;
import ctbrec.ui.TabProvider;
import okhttp3.Request; import okhttp3.Request;
import okhttp3.Response; import okhttp3.Response;
public class Camsoda extends AbstractSite { public class Camsoda extends AbstractSite {
public static final String BASE_URI = "https://www.camsoda.com"; public static final String BASE_URI = "https://www.camsoda.com";
private Recorder recorder;
private HttpClient httpClient; private HttpClient httpClient;
private CamsodaTabProvider tabProvider;
@Override @Override
public String getName() { public String getName() {
@ -42,19 +37,6 @@ public class Camsoda extends AbstractSite {
return BASE_URI; return BASE_URI;
} }
@Override
public void setRecorder(Recorder recorder) {
this.recorder = recorder;
}
@Override
public TabProvider getTabProvider() {
if(tabProvider == null) {
tabProvider = new CamsodaTabProvider(this, recorder);
}
return tabProvider;
}
@Override @Override
public Model createModel(String name) { public Model createModel(String name) {
CamsodaModel model = new CamsodaModel(); CamsodaModel model = new CamsodaModel();
@ -73,7 +55,7 @@ public class Camsoda extends AbstractSite {
String username = Config.getInstance().getSettings().camsodaUsername; String username = Config.getInstance().getSettings().camsodaUsername;
String url = BASE_URI + "/api/v1/user/" + username; String url = BASE_URI + "/api/v1/user/" + username;
Request request = new Request.Builder().url(url).build(); Request request = new Request.Builder().url(url).build();
try(Response response = getHttpClient().execute(request, true)) { try(Response response = getHttpClient().execute(request)) {
if(response.isSuccessful()) { if(response.isSuccessful()) {
JSONObject json = new JSONObject(response.body().string()); JSONObject json = new JSONObject(response.body().string());
if(json.has("user")) { if(json.has("user")) {
@ -90,10 +72,8 @@ public class Camsoda extends AbstractSite {
} }
@Override @Override
public void login() throws IOException { public boolean login() throws IOException {
if(credentialsAvailable()) { return credentialsAvailable() && getHttpClient().login();
getHttpClient().login();
}
} }
@Override @Override
@ -135,9 +115,4 @@ public class Camsoda extends AbstractSite {
String username = Config.getInstance().getSettings().camsodaUsername; String username = Config.getInstance().getSettings().camsodaUsername;
return username != null && !username.trim().isEmpty(); return username != null && !username.trim().isEmpty();
} }
@Override
public ConfigUI getConfigurationGui() {
return new CamsodaConfigUI(this);
}
} }

View File

@ -1,12 +1,7 @@
package ctbrec.sites.camsoda; package ctbrec.sites.camsoda;
import java.io.IOException; import java.io.IOException;
import java.net.HttpCookie;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import org.json.JSONObject; import org.json.JSONObject;
import org.jsoup.nodes.Element; import org.jsoup.nodes.Element;
@ -14,14 +9,10 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.io.HtmlParser;
import ctbrec.io.HttpClient; import ctbrec.io.HttpClient;
import ctbrec.io.HttpException; import ctbrec.io.HttpException;
import ctbrec.sites.cam4.Cam4LoginDialog;
import ctbrec.ui.HtmlParser;
import javafx.application.Platform;
import okhttp3.Cookie;
import okhttp3.FormBody; import okhttp3.FormBody;
import okhttp3.HttpUrl;
import okhttp3.Request; import okhttp3.Request;
import okhttp3.Response; import okhttp3.Response;
@ -76,45 +67,11 @@ public class CamsodaHttpClient extends HttpClient {
} }
} }
@SuppressWarnings("unused")
private boolean loginWithDialog() throws IOException {
BlockingQueue<Boolean> queue = new LinkedBlockingQueue<>();
Runnable showDialog = () -> {
// login with javafx WebView
CamsodaLoginDialog loginDialog = new CamsodaLoginDialog();
// transfer cookies from WebView to OkHttp cookie jar
transferCookies(loginDialog);
try {
queue.put(true);
} catch (InterruptedException e) {
LOG.error("Error while signaling termination", e);
}
};
if(Platform.isFxApplicationThread()) {
showDialog.run();
} else {
Platform.runLater(showDialog);
try {
queue.take();
} catch (InterruptedException e) {
LOG.error("Error while waiting for login dialog to close", e);
throw new IOException(e);
}
}
loggedIn = checkLoginSuccess();
return loggedIn;
}
/** /**
* check, if the login worked * check, if the login worked
* @throws IOException * @throws IOException
*/ */
private boolean checkLoginSuccess() throws IOException { public boolean checkLoginSuccess() throws IOException {
String url = Camsoda.BASE_URI + "/api/v1/user/current"; String url = Camsoda.BASE_URI + "/api/v1/user/current";
Request request = new Request.Builder().url(url).build(); Request request = new Request.Builder().url(url).build();
try(Response response = execute(request)) { try(Response response = execute(request)) {
@ -127,29 +84,11 @@ public class CamsodaHttpClient extends HttpClient {
} }
} }
private void transferCookies(CamsodaLoginDialog loginDialog) {
HttpUrl redirectedUrl = HttpUrl.parse(loginDialog.getUrl());
List<Cookie> cookies = new ArrayList<>();
for (HttpCookie webViewCookie : loginDialog.getCookies()) {
Cookie cookie = Cookie.parse(redirectedUrl, webViewCookie.toString());
cookies.add(cookie);
}
cookieJar.saveFromResponse(redirectedUrl, cookies);
HttpUrl origUrl = HttpUrl.parse(Cam4LoginDialog.URL);
cookies = new ArrayList<>();
for (HttpCookie webViewCookie : loginDialog.getCookies()) {
Cookie cookie = Cookie.parse(origUrl, webViewCookie.toString());
cookies.add(cookie);
}
cookieJar.saveFromResponse(origUrl, cookies);
}
protected String getCsrfToken() throws IOException { protected String getCsrfToken() throws IOException {
if(csrfToken == null) { if(csrfToken == null) {
String url = Camsoda.BASE_URI; String url = Camsoda.BASE_URI;
Request request = new Request.Builder().url(url).build(); Request request = new Request.Builder().url(url).build();
try(Response response = execute(request, true)) { try(Response response = execute(request)) {
if(response.isSuccessful()) { if(response.isSuccessful()) {
Element meta = HtmlParser.getTag(response.body().string(), "meta[name=\"_token\"]"); Element meta = HtmlParser.getTag(response.body().string(), "meta[name=\"_token\"]");
csrfToken = meta.attr("content"); csrfToken = meta.attr("content");

View File

@ -188,7 +188,7 @@ public class CamsodaModel extends AbstractModel {
.addHeader("Accept-Language", "en") .addHeader("Accept-Language", "en")
.addHeader("X-CSRF-Token", csrfToken) .addHeader("X-CSRF-Token", csrfToken)
.build(); .build();
try(Response response = site.getHttpClient().execute(request, true)) { try(Response response = site.getHttpClient().execute(request)) {
if(!response.isSuccessful()) { if(!response.isSuccessful()) {
throw new HttpException(response.code(), response.message()); throw new HttpException(response.code(), response.message());
} }
@ -210,7 +210,7 @@ public class CamsodaModel extends AbstractModel {
.addHeader("Accept-Language", "en") .addHeader("Accept-Language", "en")
.addHeader("X-CSRF-Token", csrfToken) .addHeader("X-CSRF-Token", csrfToken)
.build(); .build();
try(Response response = site.getHttpClient().execute(request, true)) { try(Response response = site.getHttpClient().execute(request)) {
if (response.isSuccessful()) { if (response.isSuccessful()) {
return true; return true;
} else { } else {
@ -233,7 +233,7 @@ public class CamsodaModel extends AbstractModel {
.addHeader("Accept-Language", "en") .addHeader("Accept-Language", "en")
.addHeader("X-CSRF-Token", csrfToken) .addHeader("X-CSRF-Token", csrfToken)
.build(); .build();
try (Response response = site.getHttpClient().execute(request, true)) { try (Response response = site.getHttpClient().execute(request)) {
if (response.isSuccessful()) { if (response.isSuccessful()) {
return true; return true;
} else { } else {

View File

@ -26,13 +26,10 @@ import com.squareup.moshi.Moshi;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.Model; import ctbrec.Model;
import ctbrec.io.HtmlParser;
import ctbrec.io.HttpClient; import ctbrec.io.HttpClient;
import ctbrec.io.HttpException; import ctbrec.io.HttpException;
import ctbrec.recorder.Recorder;
import ctbrec.sites.AbstractSite; import ctbrec.sites.AbstractSite;
import ctbrec.sites.ConfigUI;
import ctbrec.ui.HtmlParser;
import ctbrec.ui.TabProvider;
import okhttp3.FormBody; import okhttp3.FormBody;
import okhttp3.Request; import okhttp3.Request;
import okhttp3.RequestBody; import okhttp3.RequestBody;
@ -44,9 +41,7 @@ public class Chaturbate extends AbstractSite {
public static final String BASE_URI = "https://chaturbate.com"; public static final String BASE_URI = "https://chaturbate.com";
public static final String AFFILIATE_LINK = BASE_URI + "/in/?track=default&tour=grq0&campaign=55vTi"; public static final String AFFILIATE_LINK = BASE_URI + "/in/?track=default&tour=grq0&campaign=55vTi";
public static final String REGISTRATION_LINK = BASE_URI + "/in/?track=default&tour=g4pe&campaign=55vTi"; public static final String REGISTRATION_LINK = BASE_URI + "/in/?track=default&tour=g4pe&campaign=55vTi";
private Recorder recorder;
private ChaturbateHttpClient httpClient; private ChaturbateHttpClient httpClient;
private ChaturbateTabProvider tabProvider;
@Override @Override
public void init() throws IOException { public void init() throws IOException {
@ -68,19 +63,6 @@ public class Chaturbate extends AbstractSite {
return getBaseUrl() + "/in/?track=default&tour=LQps&campaign=55vTi&room=0xb00bface"; return getBaseUrl() + "/in/?track=default&tour=LQps&campaign=55vTi&room=0xb00bface";
} }
@Override
public TabProvider getTabProvider() {
if(tabProvider == null) {
tabProvider = new ChaturbateTabProvider(this, recorder);
}
return tabProvider;
}
@Override
public void setRecorder(Recorder recorder) {
this.recorder = recorder;
}
@Override @Override
public Model createModel(String name) { public Model createModel(String name) {
ChaturbateModel m = new ChaturbateModel(this); ChaturbateModel m = new ChaturbateModel(this);
@ -98,7 +80,7 @@ public class Chaturbate extends AbstractSite {
String url = "https://chaturbate.com/p/" + username + "/"; String url = "https://chaturbate.com/p/" + username + "/";
Request req = new Request.Builder().url(url).build(); Request req = new Request.Builder().url(url).build();
Response resp = getHttpClient().execute(req, true); Response resp = getHttpClient().execute(req);
if (resp.isSuccessful()) { if (resp.isSuccessful()) {
String profilePage = resp.body().string(); String profilePage = resp.body().string();
String tokenText = HtmlParser.getText(profilePage, "span.tokencount"); String tokenText = HtmlParser.getText(profilePage, "span.tokencount");
@ -115,19 +97,8 @@ public class Chaturbate extends AbstractSite {
} }
@Override @Override
public void login() { public boolean login() throws IOException {
if (credentialsAvailable()) { return credentialsAvailable() && getHttpClient().login();
new Thread() {
@Override
public void run() {
try {
getHttpClient().login();
} catch (IOException e1) {
LOG.warn("Initial login failed", e1);
}
};
}.start();
}
} }
@Override @Override
@ -196,7 +167,7 @@ public class Chaturbate extends AbstractSite {
.addHeader("Referer", "https://chaturbate.com/"+name+"/") .addHeader("Referer", "https://chaturbate.com/"+name+"/")
.addHeader("X-Requested-With", "XMLHttpRequest") .addHeader("X-Requested-With", "XMLHttpRequest")
.build(); .build();
try(Response response = getHttpClient().execute(req, true)) { try(Response response = getHttpClient().execute(req)) {
if(!response.isSuccessful()) { if(!response.isSuccessful()) {
throw new IOException(response.code() + " " + response.message()); throw new IOException(response.code() + " " + response.message());
} }
@ -312,11 +283,6 @@ public class Chaturbate extends AbstractSite {
} }
} }
@Override
public ConfigUI getConfigurationGui() {
return new ChaturbateConfigUi();
}
@Override @Override
public boolean credentialsAvailable() { public boolean credentialsAvailable() {
String username = Config.getInstance().getSettings().username; String username = Config.getInstance().getSettings().username;

View File

@ -7,8 +7,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import ctbrec.Config; import ctbrec.Config;
import ctbrec.io.HtmlParser;
import ctbrec.io.HttpClient; import ctbrec.io.HttpClient;
import ctbrec.ui.HtmlParser;
import okhttp3.Cookie; import okhttp3.Cookie;
import okhttp3.FormBody; import okhttp3.FormBody;
import okhttp3.Request; import okhttp3.Request;
@ -115,8 +115,8 @@ public class ChaturbateHttpClient extends HttpClient {
} }
@Override @Override
public Response execute(Request req, boolean requiresLogin) throws IOException { public Response execute(Request req) throws IOException {
Response resp = super.execute(req, requiresLogin); Response resp = super.execute(req);
extractCsrfToken(req); extractCsrfToken(req);
return resp; return resp;
} }

View File

@ -152,7 +152,7 @@ public class ChaturbateModel extends AbstractModel {
.header("X-CSRFToken", ((ChaturbateHttpClient)site.getHttpClient()).getToken()) .header("X-CSRFToken", ((ChaturbateHttpClient)site.getHttpClient()).getToken())
.header("X-Requested-With", "XMLHttpRequest") .header("X-Requested-With", "XMLHttpRequest")
.build(); .build();
resp = site.getHttpClient().execute(req, true); resp = site.getHttpClient().execute(req);
if(resp.isSuccessful()) { if(resp.isSuccessful()) {
String msg = resp.body().string(); String msg = resp.body().string();
if(!msg.equalsIgnoreCase("ok")) { if(!msg.equalsIgnoreCase("ok")) {

Some files were not shown because too many files have changed in this diff Show More