forked from j62/ctbrec
Introduce external browser for logins
Since the JavaFX integrated browser does not work reliably for recaptcha and in general does not behave like standard browsers, I now use an external browser for the logins. The dependency to javafx-web has been removed. The external browser is based on electron, which uses chromium as internal browser. The implementation can be found at https://github.com/0xboobface/ctbrec-minimal-browser The browser is a minimal browser, which only shows the web page content without any other controls. It is launched by ctbrec in a new process and remote controlled over a socket connection. I first tried to control it via stdin/stdout, but it turns out, that stdin is not supported by electron on windows.
This commit is contained in:
parent
77753bd377
commit
a6709bd6db
|
@ -6,3 +6,4 @@
|
||||||
/ctbrec-tunnel.sh
|
/ctbrec-tunnel.sh
|
||||||
/jre/
|
/jre/
|
||||||
/server-local.sh
|
/server-local.sh
|
||||||
|
/browser/
|
||||||
|
|
|
@ -80,7 +80,7 @@
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.openjfx</groupId>
|
<groupId>org.openjfx</groupId>
|
||||||
<artifactId>javafx-web</artifactId>
|
<artifactId>javafx-media</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
|
|
@ -38,5 +38,13 @@
|
||||||
<outputDirectory>ctbrec/jre</outputDirectory>
|
<outputDirectory>ctbrec/jre</outputDirectory>
|
||||||
<filtered>false</filtered>
|
<filtered>false</filtered>
|
||||||
</fileSet>
|
</fileSet>
|
||||||
|
<fileSet>
|
||||||
|
<directory>browser/ctbrec-minimal-browser-linux-x64</directory>
|
||||||
|
<includes>
|
||||||
|
<include>**/*</include>
|
||||||
|
</includes>
|
||||||
|
<outputDirectory>ctbrec/browser</outputDirectory>
|
||||||
|
<filtered>false</filtered>
|
||||||
|
</fileSet>
|
||||||
</fileSets>
|
</fileSets>
|
||||||
</assembly>
|
</assembly>
|
||||||
|
|
|
@ -29,4 +29,14 @@
|
||||||
<outputDirectory>ctbrec</outputDirectory>
|
<outputDirectory>ctbrec</outputDirectory>
|
||||||
</file>
|
</file>
|
||||||
</files>
|
</files>
|
||||||
|
<fileSets>
|
||||||
|
<fileSet>
|
||||||
|
<directory>browser/ctbrec-minimal-browser-linux-x64</directory>
|
||||||
|
<includes>
|
||||||
|
<include>**/*</include>
|
||||||
|
</includes>
|
||||||
|
<outputDirectory>ctbrec/browser</outputDirectory>
|
||||||
|
<filtered>false</filtered>
|
||||||
|
</fileSet>
|
||||||
|
</fileSets>
|
||||||
</assembly>
|
</assembly>
|
||||||
|
|
|
@ -38,5 +38,13 @@
|
||||||
<outputDirectory>ctbrec/jre</outputDirectory>
|
<outputDirectory>ctbrec/jre</outputDirectory>
|
||||||
<filtered>false</filtered>
|
<filtered>false</filtered>
|
||||||
</fileSet>
|
</fileSet>
|
||||||
|
<fileSet>
|
||||||
|
<directory>browser/ctbrec-minimal-browser-darwin-x64</directory>
|
||||||
|
<includes>
|
||||||
|
<include>**/*</include>
|
||||||
|
</includes>
|
||||||
|
<outputDirectory>ctbrec/browser</outputDirectory>
|
||||||
|
<filtered>false</filtered>
|
||||||
|
</fileSet>
|
||||||
</fileSets>
|
</fileSets>
|
||||||
</assembly>
|
</assembly>
|
||||||
|
|
|
@ -29,4 +29,14 @@
|
||||||
<outputDirectory>ctbrec</outputDirectory>
|
<outputDirectory>ctbrec</outputDirectory>
|
||||||
</file>
|
</file>
|
||||||
</files>
|
</files>
|
||||||
|
<fileSets>
|
||||||
|
<fileSet>
|
||||||
|
<directory>browser/ctbrec-minimal-browser-darwin-x64</directory>
|
||||||
|
<includes>
|
||||||
|
<include>**/*</include>
|
||||||
|
</includes>
|
||||||
|
<outputDirectory>ctbrec/browser</outputDirectory>
|
||||||
|
<filtered>false</filtered>
|
||||||
|
</fileSet>
|
||||||
|
</fileSets>
|
||||||
</assembly>
|
</assembly>
|
||||||
|
|
|
@ -40,5 +40,13 @@
|
||||||
<outputDirectory>ctbrec/jre</outputDirectory>
|
<outputDirectory>ctbrec/jre</outputDirectory>
|
||||||
<filtered>false</filtered>
|
<filtered>false</filtered>
|
||||||
</fileSet>
|
</fileSet>
|
||||||
|
<fileSet>
|
||||||
|
<directory>browser/ctbrec-minimal-browser-win32-x64</directory>
|
||||||
|
<includes>
|
||||||
|
<include>**/*</include>
|
||||||
|
</includes>
|
||||||
|
<outputDirectory>ctbrec/browser</outputDirectory>
|
||||||
|
<filtered>false</filtered>
|
||||||
|
</fileSet>
|
||||||
</fileSets>
|
</fileSets>
|
||||||
</assembly>
|
</assembly>
|
||||||
|
|
|
@ -31,4 +31,14 @@
|
||||||
<outputDirectory>ctbrec</outputDirectory>
|
<outputDirectory>ctbrec</outputDirectory>
|
||||||
</file>
|
</file>
|
||||||
</files>
|
</files>
|
||||||
|
<fileSets>
|
||||||
|
<fileSet>
|
||||||
|
<directory>browser/ctbrec-minimal-browser-win32-x64</directory>
|
||||||
|
<includes>
|
||||||
|
<include>**/*</include>
|
||||||
|
</includes>
|
||||||
|
<outputDirectory>ctbrec/browser</outputDirectory>
|
||||||
|
<filtered>false</filtered>
|
||||||
|
</fileSet>
|
||||||
|
</fileSets>
|
||||||
</assembly>
|
</assembly>
|
||||||
|
|
|
@ -196,6 +196,10 @@ public class CamrecApplication extends Application {
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
ExternalBrowser.getInstance().close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}.start();
|
}.start();
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
package ctbrec.ui;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import javafx.scene.control.Tab;
|
|
||||||
import javafx.scene.web.WebEngine;
|
|
||||||
import javafx.scene.web.WebView;
|
|
||||||
|
|
||||||
public class DonateTabHtml extends Tab {
|
|
||||||
|
|
||||||
private static final transient Logger LOG = LoggerFactory.getLogger(DonateTabHtml.class);
|
|
||||||
|
|
||||||
private WebView browser;
|
|
||||||
|
|
||||||
public DonateTabHtml() {
|
|
||||||
setClosable(false);
|
|
||||||
setText("Donate");
|
|
||||||
|
|
||||||
browser = new WebView();
|
|
||||||
try {
|
|
||||||
WebEngine webEngine = browser.getEngine();
|
|
||||||
webEngine.load("https://0xboobface.github.io/ctbrec/#donate");
|
|
||||||
webEngine.setJavaScriptEnabled(true);
|
|
||||||
webEngine.setOnAlert((e) -> {
|
|
||||||
System.out.println(e.getData());
|
|
||||||
});
|
|
||||||
setContent(browser);
|
|
||||||
} catch (Exception e) {
|
|
||||||
LOG.error("Couldn't load donate.html", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,141 @@
|
||||||
|
package ctbrec.ui;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.net.Socket;
|
||||||
|
import java.util.concurrent.locks.Lock;
|
||||||
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import ctbrec.OS;
|
||||||
|
import ctbrec.io.StreamRedirectThread;
|
||||||
|
|
||||||
|
public class ExternalBrowser implements AutoCloseable {
|
||||||
|
private static final transient Logger LOG = LoggerFactory.getLogger(ExternalBrowser.class);
|
||||||
|
private static final ExternalBrowser INSTANCE = new ExternalBrowser();
|
||||||
|
private Lock lock = new ReentrantLock();
|
||||||
|
|
||||||
|
private Process p;
|
||||||
|
private Consumer<String> messageListener;
|
||||||
|
private InputStream in;
|
||||||
|
private OutputStream out;
|
||||||
|
private Socket socket;
|
||||||
|
private Thread reader;
|
||||||
|
private volatile boolean stopped = true;
|
||||||
|
|
||||||
|
public static ExternalBrowser getInstance() {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run(String jsonConfig, Consumer<String> messageListener) throws InterruptedException, IOException {
|
||||||
|
lock.lock();
|
||||||
|
stopped = false;
|
||||||
|
this.messageListener = messageListener;
|
||||||
|
|
||||||
|
p = new ProcessBuilder(OS.getBrowserCommand()).start();
|
||||||
|
new StreamRedirectThread(p.getInputStream(), System.err);
|
||||||
|
new StreamRedirectThread(p.getErrorStream(), System.err);
|
||||||
|
LOG.debug("Browser started");
|
||||||
|
|
||||||
|
connectToRemoteControlSocket();
|
||||||
|
LOG.debug("Connected to remote control server. Sending config {}", jsonConfig);
|
||||||
|
|
||||||
|
out.write(jsonConfig.getBytes("utf-8"));
|
||||||
|
out.write('\n');
|
||||||
|
out.flush();
|
||||||
|
|
||||||
|
LOG.debug("Waiting for browser to terminate");
|
||||||
|
p.waitFor();
|
||||||
|
int exitValue = p.exitValue();
|
||||||
|
p = null;
|
||||||
|
LOG.debug("Browser Process terminated with {}", exitValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void connectToRemoteControlSocket() {
|
||||||
|
for (int i = 0; i < 20; i++) {
|
||||||
|
try {
|
||||||
|
socket = new Socket("localhost", 3202);
|
||||||
|
in = socket.getInputStream();
|
||||||
|
out = socket.getOutputStream();
|
||||||
|
reader = new Thread(this::readBrowserOutput);
|
||||||
|
reader.start();
|
||||||
|
return;
|
||||||
|
} catch (IOException e) {
|
||||||
|
if(i == 19) {
|
||||||
|
LOG.error("Connection to remote control socket failed", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// wait a bit, so that the remote server socket can be opened by electron
|
||||||
|
try {
|
||||||
|
Thread.sleep(100);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void executeJavaScript(String javaScript) throws IOException {
|
||||||
|
//LOG.debug("Executing JS {}", javaScript);
|
||||||
|
JSONObject script = new JSONObject();
|
||||||
|
script.put("execute", javaScript);
|
||||||
|
out.write(script.toString().getBytes("utf-8"));
|
||||||
|
out.write('\n');
|
||||||
|
out.flush();
|
||||||
|
if(javaScript.equals("quit")) {
|
||||||
|
stopped = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
if(stopped) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
stopped = true;
|
||||||
|
executeJavaScript("quit");
|
||||||
|
if(socket != null) {
|
||||||
|
socket.close();
|
||||||
|
socket = null;
|
||||||
|
}
|
||||||
|
messageListener = null;
|
||||||
|
reader = null;
|
||||||
|
in = null;
|
||||||
|
out = null;
|
||||||
|
if(p != null) {
|
||||||
|
p.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void readBrowserOutput() {
|
||||||
|
LOG.debug("Browser output reader started");
|
||||||
|
try {
|
||||||
|
BufferedReader br = new BufferedReader(new InputStreamReader(in));
|
||||||
|
String line;
|
||||||
|
while( !Thread.interrupted() && (line = br.readLine()) != null ) {
|
||||||
|
if(!line.startsWith("{")) {
|
||||||
|
System.err.println(line);
|
||||||
|
} else {
|
||||||
|
if(messageListener != null) {
|
||||||
|
messageListener.accept(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
if(!stopped) {
|
||||||
|
LOG.error("Couldn't read browser output", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void release() {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,31 +0,0 @@
|
||||||
package ctbrec.ui;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.OS;
|
|
||||||
import ctbrec.ui.controls.Dialogs;
|
|
||||||
import javafx.scene.control.Tab;
|
|
||||||
import javafx.scene.web.WebEngine;
|
|
||||||
import javafx.scene.web.WebView;
|
|
||||||
|
|
||||||
public class WebbrowserTab extends Tab {
|
|
||||||
|
|
||||||
private static final transient Logger LOG = LoggerFactory.getLogger(WebbrowserTab.class);
|
|
||||||
|
|
||||||
public WebbrowserTab(String uri) {
|
|
||||||
WebView browser = new WebView();
|
|
||||||
WebEngine webEngine = browser.getEngine();
|
|
||||||
webEngine.setUserDataDirectory(new File(OS.getConfigDir(), "webengine"));
|
|
||||||
webEngine.setJavaScriptEnabled(true);
|
|
||||||
webEngine.load(uri);
|
|
||||||
setContent(browser);
|
|
||||||
|
|
||||||
webEngine.setOnError(evt -> {
|
|
||||||
LOG.error("Couldn't load {}", uri, evt.getException());
|
|
||||||
Dialogs.showError("Error", "Couldn't load " + uri, evt.getException());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,124 @@
|
||||||
|
package ctbrec.ui.sites.bonga;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import ctbrec.Config;
|
||||||
|
import ctbrec.sites.bonga.BongaCams;
|
||||||
|
import ctbrec.ui.ExternalBrowser;
|
||||||
|
import okhttp3.Cookie;
|
||||||
|
import okhttp3.Cookie.Builder;
|
||||||
|
import okhttp3.CookieJar;
|
||||||
|
import okhttp3.HttpUrl;
|
||||||
|
|
||||||
|
public class BongaCamsElectronLoginDialog {
|
||||||
|
|
||||||
|
private static final transient Logger LOG = LoggerFactory.getLogger(BongaCamsElectronLoginDialog.class);
|
||||||
|
public static final String DOMAIN = "bongacams.com";
|
||||||
|
public static final String URL = BongaCams.BASE_URL + "/login";
|
||||||
|
private CookieJar cookieJar;
|
||||||
|
private ExternalBrowser browser;
|
||||||
|
|
||||||
|
public BongaCamsElectronLoginDialog(CookieJar cookieJar) throws IOException {
|
||||||
|
this.cookieJar = cookieJar;
|
||||||
|
browser = ExternalBrowser.getInstance();
|
||||||
|
try {
|
||||||
|
JSONObject config = new JSONObject();
|
||||||
|
config.put("url", URL);
|
||||||
|
config.put("w", 640);
|
||||||
|
config.put("h", 480);
|
||||||
|
JSONObject msg = new JSONObject();
|
||||||
|
msg.put("config", config);
|
||||||
|
browser.run(msg.toString(), msgHandler);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new IOException("Couldn't wait for login dialog", e);
|
||||||
|
} finally {
|
||||||
|
browser.close();
|
||||||
|
browser.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Consumer<String> msgHandler = (line) -> {
|
||||||
|
if(!line.startsWith("{")) {
|
||||||
|
System.err.println(line);
|
||||||
|
} else {
|
||||||
|
JSONObject json = new JSONObject(line);
|
||||||
|
//LOG.debug("Browser: {}", json.toString(2));
|
||||||
|
if(json.has("url")) {
|
||||||
|
String url = json.getString("url");
|
||||||
|
if(url.endsWith("/login")) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(500);
|
||||||
|
String username = Config.getInstance().getSettings().bongaUsername;
|
||||||
|
if (username != null && !username.trim().isEmpty()) {
|
||||||
|
browser.executeJavaScript("$('input[name=\"log_in[username]\"]').attr('value','" + username + "')");
|
||||||
|
}
|
||||||
|
String password = Config.getInstance().getSettings().bongaPassword;
|
||||||
|
if (password != null && !password.trim().isEmpty()) {
|
||||||
|
browser.executeJavaScript("$('input[name=\"log_in[password]\"]').attr('value','" + password + "')");
|
||||||
|
}
|
||||||
|
String[] simplify = new String[] {
|
||||||
|
"$('div#header').css('display','none');",
|
||||||
|
"$('div.footer').css('display','none');",
|
||||||
|
"$('div.footer_copy').css('display','none')",
|
||||||
|
"$('div[class~=\"banner_top_index\"]').css('display','none');",
|
||||||
|
"$('td.menu_container').css('display','none');",
|
||||||
|
"$('div[class~=\"fancybox-overlay\"]').css('display','none');"
|
||||||
|
};
|
||||||
|
for (String js : simplify) {
|
||||||
|
browser.executeJavaScript(js);
|
||||||
|
}
|
||||||
|
} catch(Exception e) {
|
||||||
|
LOG.warn("Couldn't auto fill username and password for BongaCams", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(json.has("cookies")) {
|
||||||
|
JSONArray _cookies = json.getJSONArray("cookies");
|
||||||
|
for (int i = 0; i < _cookies.length(); i++) {
|
||||||
|
JSONObject cookie = _cookies.getJSONObject(i);
|
||||||
|
if(cookie.getString("domain").contains(DOMAIN)) {
|
||||||
|
Builder b = new Cookie.Builder()
|
||||||
|
.path(cookie.getString("path"))
|
||||||
|
.domain(DOMAIN)
|
||||||
|
.name(cookie.getString("name"))
|
||||||
|
.value(cookie.getString("value"))
|
||||||
|
.expiresAt(Double.valueOf(cookie.optDouble("expirationDate")).longValue());
|
||||||
|
if(cookie.optBoolean("hostOnly")) {
|
||||||
|
b.hostOnlyDomain(DOMAIN);
|
||||||
|
}
|
||||||
|
if(cookie.optBoolean("httpOnly")) {
|
||||||
|
b.httpOnly();
|
||||||
|
}
|
||||||
|
if(cookie.optBoolean("secure")) {
|
||||||
|
b.secure();
|
||||||
|
}
|
||||||
|
Cookie c = b.build();
|
||||||
|
cookieJar.saveFromResponse(HttpUrl.parse(BongaCams.BASE_URL), Collections.singletonList(c));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
URL _url = new URL(url);
|
||||||
|
if (Objects.equals(_url.getPath(), "/")) {
|
||||||
|
browser.close();
|
||||||
|
}
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
LOG.error("Couldn't parse new url {}", url, e);
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOG.error("Couldn't send shutdown request to external browser", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,120 +0,0 @@
|
||||||
package ctbrec.ui.sites.bonga;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.net.CookieHandler;
|
|
||||||
import java.net.CookieManager;
|
|
||||||
import java.net.HttpCookie;
|
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.Config;
|
|
||||||
import ctbrec.OS;
|
|
||||||
import ctbrec.sites.bonga.BongaCams;
|
|
||||||
import javafx.concurrent.Worker.State;
|
|
||||||
import javafx.scene.Scene;
|
|
||||||
import javafx.scene.control.ProgressIndicator;
|
|
||||||
import javafx.scene.image.Image;
|
|
||||||
import javafx.scene.layout.Region;
|
|
||||||
import javafx.scene.layout.StackPane;
|
|
||||||
import javafx.scene.web.WebEngine;
|
|
||||||
import javafx.scene.web.WebView;
|
|
||||||
import javafx.stage.Stage;
|
|
||||||
|
|
||||||
public class BongaCamsLoginDialog {
|
|
||||||
|
|
||||||
private static final transient Logger LOG = LoggerFactory.getLogger(BongaCamsLoginDialog.class);
|
|
||||||
public static final String URL = BongaCams.BASE_URL + "/login";
|
|
||||||
private List<HttpCookie> cookies = null;
|
|
||||||
private String url;
|
|
||||||
private Region veil;
|
|
||||||
private ProgressIndicator p;
|
|
||||||
|
|
||||||
public BongaCamsLoginDialog() {
|
|
||||||
Stage stage = new Stage();
|
|
||||||
stage.setTitle("BongaCams Login");
|
|
||||||
InputStream icon = getClass().getResourceAsStream("/icon.png");
|
|
||||||
stage.getIcons().add(new Image(icon));
|
|
||||||
CookieManager cookieManager = new CookieManager();
|
|
||||||
CookieHandler.setDefault(cookieManager);
|
|
||||||
WebView webView = createWebView(stage);
|
|
||||||
|
|
||||||
veil = new Region();
|
|
||||||
veil.setStyle("-fx-background-color: rgba(0, 0, 0, 0.4)");
|
|
||||||
p = new ProgressIndicator();
|
|
||||||
p.setMaxSize(140, 140);
|
|
||||||
|
|
||||||
StackPane stackPane = new StackPane();
|
|
||||||
stackPane.getChildren().addAll(webView, veil, p);
|
|
||||||
|
|
||||||
stage.setScene(new Scene(stackPane, 640, 480));
|
|
||||||
stage.showAndWait();
|
|
||||||
cookies = cookieManager.getCookieStore().getCookies();
|
|
||||||
}
|
|
||||||
|
|
||||||
private WebView createWebView(Stage stage) {
|
|
||||||
WebView browser = new WebView();
|
|
||||||
WebEngine webEngine = browser.getEngine();
|
|
||||||
webEngine.setJavaScriptEnabled(true);
|
|
||||||
webEngine.setUserAgent(Config.getInstance().getSettings().httpUserAgent);
|
|
||||||
webEngine.locationProperty().addListener((obs, oldV, newV) -> {
|
|
||||||
try {
|
|
||||||
URL _url = new URL(newV);
|
|
||||||
if (Objects.equals(_url.getPath(), "/")) {
|
|
||||||
stage.close();
|
|
||||||
}
|
|
||||||
} catch (MalformedURLException e) {
|
|
||||||
LOG.error("Couldn't parse new url {}", newV, e);
|
|
||||||
}
|
|
||||||
url = newV.toString();
|
|
||||||
});
|
|
||||||
webEngine.getLoadWorker().stateProperty().addListener((observable, oldState, newState) -> {
|
|
||||||
if (newState == State.SUCCEEDED) {
|
|
||||||
veil.setVisible(false);
|
|
||||||
p.setVisible(false);
|
|
||||||
//System.out.println("############# " + webEngine.getLocation());
|
|
||||||
//System.out.println(webEngine.getDocument().getDocumentElement().getTextContent());
|
|
||||||
try {
|
|
||||||
String username = Config.getInstance().getSettings().bongaUsername;
|
|
||||||
if (username != null && !username.trim().isEmpty()) {
|
|
||||||
webEngine.executeScript("$('input[name=\"log_in[username]\"]').attr('value','" + username + "')");
|
|
||||||
}
|
|
||||||
String password = Config.getInstance().getSettings().bongaPassword;
|
|
||||||
if (password != null && !password.trim().isEmpty()) {
|
|
||||||
webEngine.executeScript("$('input[name=\"log_in[password]\"]').attr('value','" + password + "')");
|
|
||||||
}
|
|
||||||
webEngine.executeScript("$('div[class~=\"fancybox-overlay\"]').css('display','none')");
|
|
||||||
webEngine.executeScript("$('div#header').css('display','none')");
|
|
||||||
webEngine.executeScript("$('div.footer').css('display','none')");
|
|
||||||
webEngine.executeScript("$('div.footer_copy').css('display','none')");
|
|
||||||
webEngine.executeScript("$('div[class~=\"banner_top_index\"]').css('display','none')");
|
|
||||||
webEngine.executeScript("$('td.menu_container').css('display','none')");
|
|
||||||
} catch(Exception e) {
|
|
||||||
LOG.warn("Couldn't auto fill username and password for BongaCams", e);
|
|
||||||
}
|
|
||||||
} else if (newState == State.CANCELLED || newState == State.FAILED) {
|
|
||||||
veil.setVisible(false);
|
|
||||||
p.setVisible(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
webEngine.setUserDataDirectory(new File(OS.getConfigDir(), "webengine"));
|
|
||||||
webEngine.load(URL);
|
|
||||||
return browser;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<HttpCookie> getCookies() {
|
|
||||||
// for (HttpCookie httpCookie : cookies) {
|
|
||||||
// LOG.debug("Cookie: {}", httpCookie);
|
|
||||||
// }
|
|
||||||
return cookies;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUrl() {
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,9 +1,6 @@
|
||||||
package ctbrec.ui.sites.bonga;
|
package ctbrec.ui.sites.bonga;
|
||||||
|
|
||||||
import java.io.IOException;
|
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.BlockingQueue;
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
|
||||||
|
@ -15,10 +12,6 @@ import ctbrec.sites.bonga.BongaCams;
|
||||||
import ctbrec.sites.bonga.BongaCamsHttpClient;
|
import ctbrec.sites.bonga.BongaCamsHttpClient;
|
||||||
import ctbrec.ui.SiteUI;
|
import ctbrec.ui.SiteUI;
|
||||||
import ctbrec.ui.TabProvider;
|
import ctbrec.ui.TabProvider;
|
||||||
import javafx.application.Platform;
|
|
||||||
import okhttp3.Cookie;
|
|
||||||
import okhttp3.CookieJar;
|
|
||||||
import okhttp3.HttpUrl;
|
|
||||||
|
|
||||||
public class BongaCamsSiteUi implements SiteUI {
|
public class BongaCamsSiteUi implements SiteUI {
|
||||||
|
|
||||||
|
@ -50,31 +43,25 @@ public class BongaCamsSiteUi implements SiteUI {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
BlockingQueue<Boolean> queue = new LinkedBlockingQueue<>();
|
BlockingQueue<Boolean> queue = new LinkedBlockingQueue<>();
|
||||||
|
try {
|
||||||
|
new Thread(() -> {
|
||||||
|
// login with external browser window
|
||||||
|
try {
|
||||||
|
new BongaCamsElectronLoginDialog(bongaCams.getHttpClient().getCookieJar());
|
||||||
|
} catch (Exception e1) {
|
||||||
|
LOG.error("Error logging in with external browser", e1);
|
||||||
|
}
|
||||||
|
|
||||||
Runnable showDialog = () -> {
|
try {
|
||||||
// login with javafx WebView
|
queue.put(true);
|
||||||
BongaCamsLoginDialog loginDialog = new BongaCamsLoginDialog();
|
} catch (InterruptedException e) {
|
||||||
|
LOG.error("Error while signaling termination", e);
|
||||||
// transfer cookies from WebView to OkHttp cookie jar
|
}
|
||||||
transferCookies(loginDialog);
|
}).start();
|
||||||
|
queue.take();
|
||||||
try {
|
} catch (InterruptedException e) {
|
||||||
queue.put(true);
|
LOG.error("Error while waiting for login dialog to close", e);
|
||||||
} catch (InterruptedException e) {
|
throw new IOException(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();
|
BongaCamsHttpClient httpClient = (BongaCamsHttpClient)bongaCams.getHttpClient();
|
||||||
|
@ -87,26 +74,4 @@ public class BongaCamsSiteUi implements SiteUI {
|
||||||
return loggedIn;
|
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,127 @@
|
||||||
|
package ctbrec.ui.sites.cam4;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import ctbrec.Config;
|
||||||
|
import ctbrec.sites.cam4.Cam4;
|
||||||
|
import ctbrec.ui.ExternalBrowser;
|
||||||
|
import okhttp3.Cookie;
|
||||||
|
import okhttp3.Cookie.Builder;
|
||||||
|
import okhttp3.CookieJar;
|
||||||
|
import okhttp3.HttpUrl;
|
||||||
|
|
||||||
|
public class Cam4ElectronLoginDialog {
|
||||||
|
|
||||||
|
private static final transient Logger LOG = LoggerFactory.getLogger(Cam4ElectronLoginDialog.class);
|
||||||
|
public static final String DOMAIN = "cam4.com";
|
||||||
|
public static final String URL = Cam4.BASE_URI + "/login";
|
||||||
|
private CookieJar cookieJar;
|
||||||
|
private ExternalBrowser browser;
|
||||||
|
|
||||||
|
public Cam4ElectronLoginDialog(CookieJar cookieJar) throws IOException {
|
||||||
|
this.cookieJar = cookieJar;
|
||||||
|
browser = ExternalBrowser.getInstance();
|
||||||
|
try {
|
||||||
|
JSONObject config = new JSONObject();
|
||||||
|
config.put("url", URL);
|
||||||
|
config.put("w", 480);
|
||||||
|
config.put("h", 640);
|
||||||
|
JSONObject msg = new JSONObject();
|
||||||
|
msg.put("config", config);
|
||||||
|
browser.run(msg.toString(), msgHandler);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new IOException("Couldn't wait for login dialog", e);
|
||||||
|
} finally {
|
||||||
|
browser.close();
|
||||||
|
browser.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Consumer<String> msgHandler = (line) -> {
|
||||||
|
if(!line.startsWith("{")) {
|
||||||
|
System.err.println(line);
|
||||||
|
} else {
|
||||||
|
JSONObject json = new JSONObject(line);
|
||||||
|
if(json.has("url")) {
|
||||||
|
String url = json.getString("url");
|
||||||
|
|
||||||
|
if(url.endsWith("/login")) {
|
||||||
|
try {
|
||||||
|
String username = Config.getInstance().getSettings().cam4Username;
|
||||||
|
if (username != null && !username.trim().isEmpty()) {
|
||||||
|
browser.executeJavaScript("document.querySelector('#loginPageForm input[name=\"username\"]').value = '" + username + "';");
|
||||||
|
}
|
||||||
|
String password = Config.getInstance().getSettings().cam4Password;
|
||||||
|
if (password != null && !password.trim().isEmpty()) {
|
||||||
|
browser.executeJavaScript("document.querySelector('#loginPageForm input[name=\"password\"]').value = '" + password + "';");
|
||||||
|
}
|
||||||
|
browser.executeJavaScript("document.getElementById('footer').setAttribute('style', 'display:none');");
|
||||||
|
browser.executeJavaScript("document.getElementById('promptArea').setAttribute('style', 'display:none');");
|
||||||
|
browser.executeJavaScript("document.getElementById('content').setAttribute('style', 'padding: 0');");
|
||||||
|
browser.executeJavaScript("document.querySelector('div[class~=\"navbar\"]').setAttribute('style', 'display:none');");
|
||||||
|
} catch(Exception e) {
|
||||||
|
LOG.warn("Couldn't auto fill username and password for Cam4", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(json.has("cookies")) {
|
||||||
|
JSONArray _cookies = json.getJSONArray("cookies");
|
||||||
|
try {
|
||||||
|
URL _url = new URL(url);
|
||||||
|
for (int i = 0; i < _cookies.length(); i++) {
|
||||||
|
JSONObject cookie = _cookies.getJSONObject(i);
|
||||||
|
if(cookie.getString("domain").contains("cam4")) {
|
||||||
|
String domain = cookie.getString("domain");
|
||||||
|
if(domain.startsWith(".")) {
|
||||||
|
domain = domain.substring(1);
|
||||||
|
}
|
||||||
|
Cookie c = createCookie(domain, cookie);
|
||||||
|
cookieJar.saveFromResponse(HttpUrl.parse(url), Collections.singletonList(c));
|
||||||
|
c = createCookie("cam4.com", cookie);
|
||||||
|
cookieJar.saveFromResponse(HttpUrl.parse(Cam4.BASE_URI), Collections.singletonList(c));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Objects.equals(_url.getPath(), "/")) {
|
||||||
|
try {
|
||||||
|
browser.close();
|
||||||
|
} catch(IOException e) {
|
||||||
|
LOG.error("Couldn't send close request to browser", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
LOG.error("Couldn't parse new url {}", url, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private Cookie createCookie(String domain, JSONObject cookie) {
|
||||||
|
Builder b = new Cookie.Builder()
|
||||||
|
.path(cookie.getString("path"))
|
||||||
|
.domain(domain)
|
||||||
|
.name(cookie.getString("name"))
|
||||||
|
.value(cookie.getString("value"))
|
||||||
|
.expiresAt(Double.valueOf(cookie.optDouble("expirationDate")).longValue());
|
||||||
|
if(cookie.optBoolean("hostOnly")) {
|
||||||
|
b.hostOnlyDomain(domain);
|
||||||
|
}
|
||||||
|
if(cookie.optBoolean("httpOnly")) {
|
||||||
|
b.httpOnly();
|
||||||
|
}
|
||||||
|
if(cookie.optBoolean("secure")) {
|
||||||
|
b.secure();
|
||||||
|
}
|
||||||
|
return b.build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,112 +0,0 @@
|
||||||
package ctbrec.ui.sites.cam4;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.net.CookieHandler;
|
|
||||||
import java.net.CookieManager;
|
|
||||||
import java.net.HttpCookie;
|
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.Config;
|
|
||||||
import ctbrec.OS;
|
|
||||||
import ctbrec.sites.cam4.Cam4;
|
|
||||||
import javafx.concurrent.Worker.State;
|
|
||||||
import javafx.scene.Scene;
|
|
||||||
import javafx.scene.control.ProgressIndicator;
|
|
||||||
import javafx.scene.image.Image;
|
|
||||||
import javafx.scene.layout.Region;
|
|
||||||
import javafx.scene.layout.StackPane;
|
|
||||||
import javafx.scene.web.WebEngine;
|
|
||||||
import javafx.scene.web.WebView;
|
|
||||||
import javafx.stage.Stage;
|
|
||||||
|
|
||||||
public class Cam4LoginDialog {
|
|
||||||
|
|
||||||
private static final transient Logger LOG = LoggerFactory.getLogger(Cam4LoginDialog.class);
|
|
||||||
public static final String URL = Cam4.BASE_URI + "/login";
|
|
||||||
private List<HttpCookie> cookies = null;
|
|
||||||
private String url;
|
|
||||||
private Region veil;
|
|
||||||
private ProgressIndicator p;
|
|
||||||
|
|
||||||
public Cam4LoginDialog() {
|
|
||||||
Stage stage = new Stage();
|
|
||||||
stage.setTitle("Cam4 Login");
|
|
||||||
InputStream icon = getClass().getResourceAsStream("/icon.png");
|
|
||||||
stage.getIcons().add(new Image(icon));
|
|
||||||
CookieManager cookieManager = new CookieManager();
|
|
||||||
CookieHandler.setDefault(cookieManager);
|
|
||||||
WebView webView = createWebView(stage);
|
|
||||||
|
|
||||||
veil = new Region();
|
|
||||||
veil.setStyle("-fx-background-color: rgba(0, 0, 0, 0.4)");
|
|
||||||
p = new ProgressIndicator();
|
|
||||||
p.setMaxSize(140, 140);
|
|
||||||
|
|
||||||
StackPane stackPane = new StackPane();
|
|
||||||
stackPane.getChildren().addAll(webView, veil, p);
|
|
||||||
|
|
||||||
stage.setScene(new Scene(stackPane, 480, 854));
|
|
||||||
stage.showAndWait();
|
|
||||||
cookies = cookieManager.getCookieStore().getCookies();
|
|
||||||
}
|
|
||||||
|
|
||||||
private WebView createWebView(Stage stage) {
|
|
||||||
WebView browser = new WebView();
|
|
||||||
WebEngine webEngine = browser.getEngine();
|
|
||||||
webEngine.setJavaScriptEnabled(true);
|
|
||||||
webEngine.setUserAgent(Config.getInstance().getSettings().httpUserAgent);
|
|
||||||
webEngine.locationProperty().addListener((obs, oldV, newV) -> {
|
|
||||||
try {
|
|
||||||
URL _url = new URL(newV);
|
|
||||||
if (Objects.equals(_url.getPath(), "/")) {
|
|
||||||
stage.close();
|
|
||||||
}
|
|
||||||
} catch (MalformedURLException e) {
|
|
||||||
LOG.error("Couldn't parse new url {}", newV, e);
|
|
||||||
}
|
|
||||||
url = newV.toString();
|
|
||||||
});
|
|
||||||
webEngine.getLoadWorker().stateProperty().addListener((observable, oldState, newState) -> {
|
|
||||||
if (newState == State.SUCCEEDED) {
|
|
||||||
veil.setVisible(false);
|
|
||||||
p.setVisible(false);
|
|
||||||
try {
|
|
||||||
String username = Config.getInstance().getSettings().cam4Username;
|
|
||||||
if (username != null && !username.trim().isEmpty()) {
|
|
||||||
webEngine.executeScript("$('input[name=username]').attr('value','" + username + "')");
|
|
||||||
}
|
|
||||||
String password = Config.getInstance().getSettings().cam4Password;
|
|
||||||
if (password != null && !password.trim().isEmpty()) {
|
|
||||||
webEngine.executeScript("$('input[name=password]').attr('value','" + password + "')");
|
|
||||||
}
|
|
||||||
webEngine.executeScript("$('div[class~=navbar]').css('display','none')");
|
|
||||||
webEngine.executeScript("$('div#footer').css('display','none')");
|
|
||||||
webEngine.executeScript("$('div#content').css('padding','0')");
|
|
||||||
} catch(Exception e) {
|
|
||||||
LOG.warn("Couldn't auto fill username and password for Cam4", e);
|
|
||||||
}
|
|
||||||
} else if (newState == State.CANCELLED || newState == State.FAILED) {
|
|
||||||
veil.setVisible(false);
|
|
||||||
p.setVisible(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
webEngine.setUserDataDirectory(new File(OS.getConfigDir(), "webengine"));
|
|
||||||
webEngine.load(URL);
|
|
||||||
return browser;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<HttpCookie> getCookies() {
|
|
||||||
return cookies;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUrl() {
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,9 +1,6 @@
|
||||||
package ctbrec.ui.sites.cam4;
|
package ctbrec.ui.sites.cam4;
|
||||||
|
|
||||||
import java.io.IOException;
|
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.BlockingQueue;
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
|
||||||
|
@ -16,9 +13,6 @@ import ctbrec.sites.cam4.Cam4HttpClient;
|
||||||
import ctbrec.ui.SiteUI;
|
import ctbrec.ui.SiteUI;
|
||||||
import ctbrec.ui.TabProvider;
|
import ctbrec.ui.TabProvider;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import okhttp3.Cookie;
|
|
||||||
import okhttp3.CookieJar;
|
|
||||||
import okhttp3.HttpUrl;
|
|
||||||
|
|
||||||
public class Cam4SiteUi implements SiteUI {
|
public class Cam4SiteUi implements SiteUI {
|
||||||
private static final transient Logger LOG = LoggerFactory.getLogger(Cam4SiteUi.class);
|
private static final transient Logger LOG = LoggerFactory.getLogger(Cam4SiteUi.class);
|
||||||
|
@ -46,18 +40,19 @@ public class Cam4SiteUi implements SiteUI {
|
||||||
@Override
|
@Override
|
||||||
public synchronized boolean login() throws IOException {
|
public synchronized boolean login() throws IOException {
|
||||||
boolean automaticLogin = cam4.login();
|
boolean automaticLogin = cam4.login();
|
||||||
if(automaticLogin) {
|
if (automaticLogin) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
BlockingQueue<Boolean> queue = new LinkedBlockingQueue<>();
|
BlockingQueue<Boolean> queue = new LinkedBlockingQueue<>();
|
||||||
|
|
||||||
Runnable showDialog = () -> {
|
Runnable showDialog = () -> {
|
||||||
// login with javafx WebView
|
// login with external browser
|
||||||
Cam4LoginDialog loginDialog = new Cam4LoginDialog();
|
try {
|
||||||
|
new Cam4ElectronLoginDialog(cam4.getHttpClient().getCookieJar());
|
||||||
// transfer cookies from WebView to OkHttp cookie jar
|
} catch (Exception e1) {
|
||||||
transferCookies(loginDialog);
|
LOG.error("Error logging in with external browser", e1);
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
queue.put(true);
|
queue.put(true);
|
||||||
|
@ -66,16 +61,12 @@ public class Cam4SiteUi implements SiteUI {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if(Platform.isFxApplicationThread()) {
|
Platform.runLater(showDialog);
|
||||||
showDialog.run();
|
try {
|
||||||
} else {
|
queue.take();
|
||||||
Platform.runLater(showDialog);
|
} catch (InterruptedException e) {
|
||||||
try {
|
LOG.error("Error while waiting for login dialog to close", e);
|
||||||
queue.take();
|
throw new IOException(e);
|
||||||
} catch (InterruptedException e) {
|
|
||||||
LOG.error("Error while waiting for login dialog to close", e);
|
|
||||||
throw new IOException(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Cam4HttpClient httpClient = (Cam4HttpClient) cam4.getHttpClient();
|
Cam4HttpClient httpClient = (Cam4HttpClient) cam4.getHttpClient();
|
||||||
|
@ -83,31 +74,4 @@ public class Cam4SiteUi implements SiteUI {
|
||||||
return loggedIn;
|
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,110 +0,0 @@
|
||||||
package ctbrec.ui.sites.camsoda;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.net.CookieHandler;
|
|
||||||
import java.net.CookieManager;
|
|
||||||
import java.net.HttpCookie;
|
|
||||||
import java.util.Base64;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import ctbrec.OS;
|
|
||||||
import ctbrec.sites.camsoda.Camsoda;
|
|
||||||
import javafx.concurrent.Worker.State;
|
|
||||||
import javafx.scene.Scene;
|
|
||||||
import javafx.scene.control.ProgressIndicator;
|
|
||||||
import javafx.scene.image.Image;
|
|
||||||
import javafx.scene.layout.Region;
|
|
||||||
import javafx.scene.layout.StackPane;
|
|
||||||
import javafx.scene.web.WebEngine;
|
|
||||||
import javafx.scene.web.WebView;
|
|
||||||
import javafx.stage.Stage;
|
|
||||||
|
|
||||||
// FIXME this dialog does not help, because google's recaptcha does not work
|
|
||||||
// with WebView even though it does work in Cam4LoginDialog
|
|
||||||
public class CamsodaLoginDialog {
|
|
||||||
|
|
||||||
public static final String URL = Camsoda.BASE_URI;
|
|
||||||
private List<HttpCookie> cookies = null;
|
|
||||||
private String url;
|
|
||||||
private Region veil;
|
|
||||||
private ProgressIndicator p;
|
|
||||||
|
|
||||||
public CamsodaLoginDialog() {
|
|
||||||
Stage stage = new Stage();
|
|
||||||
stage.setTitle("CamSoda Login");
|
|
||||||
InputStream icon = getClass().getResourceAsStream("/icon.png");
|
|
||||||
stage.getIcons().add(new Image(icon));
|
|
||||||
CookieManager cookieManager = new CookieManager();
|
|
||||||
CookieHandler.setDefault(cookieManager);
|
|
||||||
WebView webView = createWebView(stage);
|
|
||||||
|
|
||||||
veil = new Region();
|
|
||||||
veil.setStyle("-fx-background-color: rgba(1, 1, 1)");
|
|
||||||
p = new ProgressIndicator();
|
|
||||||
p.setMaxSize(140, 140);
|
|
||||||
|
|
||||||
p.setVisible(true);
|
|
||||||
veil.visibleProperty().bind(p.visibleProperty());
|
|
||||||
|
|
||||||
StackPane stackPane = new StackPane();
|
|
||||||
stackPane.getChildren().addAll(webView, veil, p);
|
|
||||||
|
|
||||||
stage.setScene(new Scene(stackPane, 400, 358));
|
|
||||||
stage.showAndWait();
|
|
||||||
cookies = cookieManager.getCookieStore().getCookies();
|
|
||||||
}
|
|
||||||
|
|
||||||
private WebView createWebView(Stage stage) {
|
|
||||||
WebView browser = new WebView();
|
|
||||||
WebEngine webEngine = browser.getEngine();
|
|
||||||
webEngine.setJavaScriptEnabled(true);
|
|
||||||
webEngine.locationProperty().addListener((obs, oldV, newV) -> {
|
|
||||||
// try {
|
|
||||||
// URL _url = new URL(newV);
|
|
||||||
// if (Objects.equals(_url.getPath(), "/")) {
|
|
||||||
// stage.close();
|
|
||||||
// }
|
|
||||||
// } catch (MalformedURLException e) {
|
|
||||||
// LOG.error("Couldn't parse new url {}", newV, e);
|
|
||||||
// }
|
|
||||||
url = newV.toString();
|
|
||||||
System.out.println(newV.toString());
|
|
||||||
});
|
|
||||||
webEngine.getLoadWorker().stateProperty().addListener((observable, oldState, newState) -> {
|
|
||||||
if (newState == State.SUCCEEDED) {
|
|
||||||
webEngine.executeScript("document.querySelector('a[ng-click=\"signin();\"]').click()");
|
|
||||||
p.setVisible(false);
|
|
||||||
|
|
||||||
// TODO make this work
|
|
||||||
// String username = Config.getInstance().getSettings().camsodaUsername;
|
|
||||||
// if (username != null && !username.trim().isEmpty()) {
|
|
||||||
// webEngine.executeScript("document.querySelector('input[name=\"loginUsername\"]').value = '" + username + "'");
|
|
||||||
// }
|
|
||||||
// String password = Config.getInstance().getSettings().camsodaPassword;
|
|
||||||
// if (password != null && !password.trim().isEmpty()) {
|
|
||||||
// webEngine.executeScript("document.querySelector('input[name=\"loginPassword\"]').value = '" + password + "'");
|
|
||||||
// }
|
|
||||||
} else if (newState == State.CANCELLED || newState == State.FAILED) {
|
|
||||||
p.setVisible(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
webEngine.setUserStyleSheetLocation("data:text/css;base64," + Base64.getEncoder().encodeToString(CUSTOM_STYLE.getBytes()));
|
|
||||||
webEngine.setUserDataDirectory(new File(OS.getConfigDir(), "webengine"));
|
|
||||||
webEngine.load(URL);
|
|
||||||
return browser;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<HttpCookie> getCookies() {
|
|
||||||
return cookies;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUrl() {
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final String CUSTOM_STYLE = ""
|
|
||||||
+ ".ngdialog.ngdialog-theme-custom { padding: 0 !important }"
|
|
||||||
+ ".ngdialog-overlay { background: black !important; }";
|
|
||||||
}
|
|
|
@ -1,24 +1,14 @@
|
||||||
package ctbrec.ui.sites.camsoda;
|
package ctbrec.ui.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.concurrent.BlockingQueue;
|
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import ctbrec.sites.ConfigUI;
|
import ctbrec.sites.ConfigUI;
|
||||||
import ctbrec.sites.camsoda.Camsoda;
|
import ctbrec.sites.camsoda.Camsoda;
|
||||||
import ctbrec.sites.camsoda.CamsodaHttpClient;
|
|
||||||
import ctbrec.ui.SiteUI;
|
import ctbrec.ui.SiteUI;
|
||||||
import ctbrec.ui.TabProvider;
|
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 {
|
public class CamsodaSiteUi implements SiteUI {
|
||||||
|
|
||||||
|
@ -50,58 +40,57 @@ public class CamsodaSiteUi implements SiteUI {
|
||||||
return automaticLogin;
|
return automaticLogin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @SuppressWarnings("unused")
|
||||||
@SuppressWarnings("unused")
|
// private boolean loginWithDialog() throws IOException {
|
||||||
private boolean loginWithDialog() throws IOException {
|
// BlockingQueue<Boolean> queue = new LinkedBlockingQueue<>();
|
||||||
BlockingQueue<Boolean> queue = new LinkedBlockingQueue<>();
|
//
|
||||||
|
// Runnable showDialog = () -> {
|
||||||
Runnable showDialog = () -> {
|
// // login with external browser
|
||||||
// login with javafx WebView
|
// CamsodaLoginDialog loginDialog = new CamsodaLoginDialog();
|
||||||
CamsodaLoginDialog loginDialog = new CamsodaLoginDialog();
|
//
|
||||||
|
// // transfer cookies from WebView to OkHttp cookie jar
|
||||||
// transfer cookies from WebView to OkHttp cookie jar
|
// transferCookies(loginDialog);
|
||||||
transferCookies(loginDialog);
|
//
|
||||||
|
// try {
|
||||||
try {
|
// queue.put(true);
|
||||||
queue.put(true);
|
// } catch (InterruptedException e) {
|
||||||
} catch (InterruptedException e) {
|
// LOG.error("Error while signaling termination", e);
|
||||||
LOG.error("Error while signaling termination", e);
|
// }
|
||||||
}
|
// };
|
||||||
};
|
//
|
||||||
|
// if(Platform.isFxApplicationThread()) {
|
||||||
if(Platform.isFxApplicationThread()) {
|
// showDialog.run();
|
||||||
showDialog.run();
|
// } else {
|
||||||
} else {
|
// Platform.runLater(showDialog);
|
||||||
Platform.runLater(showDialog);
|
// try {
|
||||||
try {
|
// queue.take();
|
||||||
queue.take();
|
// } catch (InterruptedException e) {
|
||||||
} catch (InterruptedException e) {
|
// LOG.error("Error while waiting for login dialog to close", e);
|
||||||
LOG.error("Error while waiting for login dialog to close", e);
|
// throw new IOException(e);
|
||||||
throw new IOException(e);
|
// }
|
||||||
}
|
// }
|
||||||
}
|
//
|
||||||
|
// CamsodaHttpClient httpClient = (CamsodaHttpClient)camsoda.getHttpClient();
|
||||||
CamsodaHttpClient httpClient = (CamsodaHttpClient)camsoda.getHttpClient();
|
// boolean loggedIn = httpClient.checkLoginSuccess();
|
||||||
boolean loggedIn = httpClient.checkLoginSuccess();
|
// return loggedIn;
|
||||||
return loggedIn;
|
// }
|
||||||
}
|
//
|
||||||
|
// private void transferCookies(CamsodaLoginDialog loginDialog) {
|
||||||
private void transferCookies(CamsodaLoginDialog loginDialog) {
|
// HttpUrl redirectedUrl = HttpUrl.parse(loginDialog.getUrl());
|
||||||
HttpUrl redirectedUrl = HttpUrl.parse(loginDialog.getUrl());
|
// List<Cookie> cookies = new ArrayList<>();
|
||||||
List<Cookie> cookies = new ArrayList<>();
|
// for (HttpCookie webViewCookie : loginDialog.getCookies()) {
|
||||||
for (HttpCookie webViewCookie : loginDialog.getCookies()) {
|
// Cookie cookie = Cookie.parse(redirectedUrl, webViewCookie.toString());
|
||||||
Cookie cookie = Cookie.parse(redirectedUrl, webViewCookie.toString());
|
// cookies.add(cookie);
|
||||||
cookies.add(cookie);
|
// }
|
||||||
}
|
// camsoda.getHttpClient().getCookieJar().saveFromResponse(redirectedUrl, cookies);
|
||||||
camsoda.getHttpClient().getCookieJar().saveFromResponse(redirectedUrl, cookies);
|
//
|
||||||
|
// HttpUrl origUrl = HttpUrl.parse(Camsoda.BASE_URI);
|
||||||
HttpUrl origUrl = HttpUrl.parse(Cam4LoginDialog.URL);
|
// cookies = new ArrayList<>();
|
||||||
cookies = new ArrayList<>();
|
// for (HttpCookie webViewCookie : loginDialog.getCookies()) {
|
||||||
for (HttpCookie webViewCookie : loginDialog.getCookies()) {
|
// Cookie cookie = Cookie.parse(origUrl, webViewCookie.toString());
|
||||||
Cookie cookie = Cookie.parse(origUrl, webViewCookie.toString());
|
// cookies.add(cookie);
|
||||||
cookies.add(cookie);
|
// }
|
||||||
}
|
// camsoda.getHttpClient().getCookieJar().saveFromResponse(origUrl, cookies);
|
||||||
camsoda.getHttpClient().getCookieJar().saveFromResponse(origUrl, cookies);
|
// }
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,19 +73,20 @@ public class LiveJasminConfigUi extends AbstractConfigUI {
|
||||||
GridPane.setColumnSpan(password, 2);
|
GridPane.setColumnSpan(password, 2);
|
||||||
layout.add(password, 1, row++);
|
layout.add(password, 1, row++);
|
||||||
|
|
||||||
layout.add(new Label("LiveJasmin Session ID"), 0, row);
|
// layout.add(new Label("LiveJasmin Session ID"), 0, row);
|
||||||
TextField sessionId = new TextField();
|
// TextField sessionId = new TextField();
|
||||||
sessionId.setText(Config.getInstance().getSettings().livejasminSession);
|
// sessionId.setText(Config.getInstance().getSettings().livejasminSession);
|
||||||
sessionId.textProperty().addListener((ob, o, n) -> {
|
// sessionId.textProperty().addListener((ob, o, n) -> {
|
||||||
if(!n.equals(Config.getInstance().getSettings().livejasminSession)) {
|
// if(!n.equals(Config.getInstance().getSettings().livejasminSession)) {
|
||||||
Config.getInstance().getSettings().livejasminSession = n;
|
// Config.getInstance().getSettings().livejasminSession = n;
|
||||||
save();
|
// save();
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
GridPane.setFillWidth(sessionId, true);
|
// GridPane.setFillWidth(sessionId, true);
|
||||||
GridPane.setHgrow(sessionId, Priority.ALWAYS);
|
// GridPane.setHgrow(sessionId, Priority.ALWAYS);
|
||||||
GridPane.setColumnSpan(sessionId, 2);
|
// GridPane.setColumnSpan(sessionId, 2);
|
||||||
layout.add(sessionId, 1, row++);
|
// GridPane.setMargin(sessionId, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));
|
||||||
|
// layout.add(sessionId, 1, row++);
|
||||||
|
|
||||||
Button createAccount = new Button("Create new Account");
|
Button createAccount = new Button("Create new Account");
|
||||||
createAccount.setOnAction((e) -> DesktopIntegration.open(liveJasmin.getAffiliateLink()));
|
createAccount.setOnAction((e) -> DesktopIntegration.open(liveJasmin.getAffiliateLink()));
|
||||||
|
@ -93,7 +94,6 @@ public class LiveJasminConfigUi extends AbstractConfigUI {
|
||||||
GridPane.setColumnSpan(createAccount, 2);
|
GridPane.setColumnSpan(createAccount, 2);
|
||||||
GridPane.setMargin(username, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));
|
GridPane.setMargin(username, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));
|
||||||
GridPane.setMargin(password, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));
|
GridPane.setMargin(password, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));
|
||||||
GridPane.setMargin(sessionId, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));
|
|
||||||
GridPane.setMargin(createAccount, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));
|
GridPane.setMargin(createAccount, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN));
|
||||||
|
|
||||||
username.setPrefWidth(300);
|
username.setPrefWidth(300);
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
package ctbrec.ui.sites.jasmin;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import ctbrec.Config;
|
||||||
|
import ctbrec.sites.jasmin.LiveJasmin;
|
||||||
|
import ctbrec.ui.ExternalBrowser;
|
||||||
|
import okhttp3.Cookie;
|
||||||
|
import okhttp3.Cookie.Builder;
|
||||||
|
import okhttp3.CookieJar;
|
||||||
|
import okhttp3.HttpUrl;
|
||||||
|
|
||||||
|
public class LiveJasminElectronLoginDialog {
|
||||||
|
|
||||||
|
private static final transient Logger LOG = LoggerFactory.getLogger(LiveJasminElectronLoginDialog.class);
|
||||||
|
public static final String URL = LiveJasmin.BASE_URL + "/en/auth/login";
|
||||||
|
private CookieJar cookieJar;
|
||||||
|
private ExternalBrowser browser;
|
||||||
|
|
||||||
|
public LiveJasminElectronLoginDialog(CookieJar cookieJar) throws IOException {
|
||||||
|
this.cookieJar = cookieJar;
|
||||||
|
browser = ExternalBrowser.getInstance();
|
||||||
|
try {
|
||||||
|
JSONObject config = new JSONObject();
|
||||||
|
config.put("url", URL);
|
||||||
|
config.put("w", 640);
|
||||||
|
config.put("h", 720);
|
||||||
|
JSONObject msg = new JSONObject();
|
||||||
|
msg.put("config", config);
|
||||||
|
browser.run(msg.toString(), msgHandler);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new IOException("Couldn't wait for login dialog", e);
|
||||||
|
} finally {
|
||||||
|
browser.close();
|
||||||
|
browser.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Consumer<String> msgHandler = (line) -> {
|
||||||
|
//LOG.debug("Browser: {}", line);
|
||||||
|
if(!line.startsWith("{")) {
|
||||||
|
System.err.println(line);
|
||||||
|
} else {
|
||||||
|
JSONObject json = new JSONObject(line);
|
||||||
|
if(json.has("url")) {
|
||||||
|
String url = json.getString("url");
|
||||||
|
if(url.endsWith("/auth/login")) {
|
||||||
|
try {
|
||||||
|
String username = Config.getInstance().getSettings().livejasminUsername;
|
||||||
|
if (username != null && !username.trim().isEmpty()) {
|
||||||
|
browser.executeJavaScript("document.querySelector('#login_form input[name=\"username\"]').value = '" + username + "';");
|
||||||
|
}
|
||||||
|
String password = Config.getInstance().getSettings().livejasminPassword;
|
||||||
|
if (password != null && !password.trim().isEmpty()) {
|
||||||
|
browser.executeJavaScript("document.querySelector('#login_form input[name=\"password\"]').value = '" + password + "';");
|
||||||
|
}
|
||||||
|
browser.executeJavaScript("document.getElementById('header_container').setAttribute('style', 'display:none');");
|
||||||
|
browser.executeJavaScript("document.getElementById('footer').setAttribute('style', 'display:none');");
|
||||||
|
browser.executeJavaScript("document.getElementById('react-container').setAttribute('style', 'display:none');");
|
||||||
|
browser.executeJavaScript("document.getElementById('inner_container').setAttribute('style', 'padding: 0; margin: 1em');");
|
||||||
|
browser.executeJavaScript("document.querySelector('div[class~=\"content_box\"]').setAttribute('style', 'margin: 1em');");
|
||||||
|
} catch(Exception e) {
|
||||||
|
LOG.warn("Couldn't auto fill username and password", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(json.has("cookies")) {
|
||||||
|
JSONArray _cookies = json.getJSONArray("cookies");
|
||||||
|
for (int i = 0; i < _cookies.length(); i++) {
|
||||||
|
JSONObject cookie = _cookies.getJSONObject(i);
|
||||||
|
Builder b = new Cookie.Builder()
|
||||||
|
.path("/")
|
||||||
|
.domain("livejasmin.com")
|
||||||
|
.name(cookie.getString("name"))
|
||||||
|
.value(cookie.getString("value"))
|
||||||
|
.expiresAt(0);
|
||||||
|
Cookie c = b.build();
|
||||||
|
cookieJar.saveFromResponse(HttpUrl.parse(LiveJasmin.BASE_URL), Collections.singletonList(c));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(url.contains("/member/")) {
|
||||||
|
try {
|
||||||
|
browser.close();
|
||||||
|
} catch(IOException e) {
|
||||||
|
LOG.error("Couldn't send close request to browser", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -15,6 +15,7 @@ import ctbrec.io.HttpException;
|
||||||
import ctbrec.sites.jasmin.LiveJasmin;
|
import ctbrec.sites.jasmin.LiveJasmin;
|
||||||
import ctbrec.sites.jasmin.LiveJasminModel;
|
import ctbrec.sites.jasmin.LiveJasminModel;
|
||||||
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;
|
||||||
|
@ -37,6 +38,10 @@ public class LiveJasminFollowedUpdateService 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 {
|
||||||
|
boolean loggedIn = SiteUiFactory.getUi(liveJasmin).login();
|
||||||
|
if(!loggedIn) {
|
||||||
|
throw new RuntimeException("Couldn't login on livejasmin.com");
|
||||||
|
}
|
||||||
//String _url = url + ((page-1) * 36); // TODO find out how to switch pages
|
//String _url = url + ((page-1) * 36); // TODO find out how to switch pages
|
||||||
//LOG.debug("Fetching page {}", url);
|
//LOG.debug("Fetching page {}", url);
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
|
|
|
@ -1,170 +0,0 @@
|
||||||
package ctbrec.ui.sites.jasmin;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.net.CookieHandler;
|
|
||||||
import java.net.CookieManager;
|
|
||||||
import java.net.HttpCookie;
|
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import org.json.JSONObject;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import ctbrec.Config;
|
|
||||||
import ctbrec.OS;
|
|
||||||
import ctbrec.io.HttpException;
|
|
||||||
import ctbrec.sites.jasmin.LiveJasmin;
|
|
||||||
import javafx.concurrent.Worker.State;
|
|
||||||
import javafx.scene.Scene;
|
|
||||||
import javafx.scene.control.ProgressIndicator;
|
|
||||||
import javafx.scene.image.Image;
|
|
||||||
import javafx.scene.layout.Region;
|
|
||||||
import javafx.scene.layout.StackPane;
|
|
||||||
import javafx.scene.web.WebEngine;
|
|
||||||
import javafx.scene.web.WebView;
|
|
||||||
import javafx.stage.Stage;
|
|
||||||
import okhttp3.Request;
|
|
||||||
import okhttp3.Response;
|
|
||||||
|
|
||||||
public class LiveJasminLoginDialog {
|
|
||||||
|
|
||||||
private static final transient Logger LOG = LoggerFactory.getLogger(LiveJasminLoginDialog.class);
|
|
||||||
public static final String URL = "https://m.livejasmin.com/en/list"; // #login-modal
|
|
||||||
private List<HttpCookie> cookies = null;
|
|
||||||
private String url;
|
|
||||||
private Region veil;
|
|
||||||
private ProgressIndicator p;
|
|
||||||
private LiveJasmin liveJasmin;
|
|
||||||
|
|
||||||
public LiveJasminLoginDialog(LiveJasmin liveJasmin) throws IOException {
|
|
||||||
this.liveJasmin = liveJasmin;
|
|
||||||
Stage stage = new Stage();
|
|
||||||
stage.setTitle("LiveJasmin Login");
|
|
||||||
InputStream icon = getClass().getResourceAsStream("/icon.png");
|
|
||||||
stage.getIcons().add(new Image(icon));
|
|
||||||
CookieManager cookieManager = new CookieManager();
|
|
||||||
CookieHandler.setDefault(cookieManager);
|
|
||||||
WebView webView = createWebView(stage);
|
|
||||||
|
|
||||||
veil = new Region();
|
|
||||||
veil.setStyle("-fx-background-color: rgba(0, 0, 0, 0.4)");
|
|
||||||
p = new ProgressIndicator();
|
|
||||||
p.setMaxSize(140, 140);
|
|
||||||
|
|
||||||
StackPane stackPane = new StackPane();
|
|
||||||
stackPane.getChildren().addAll(webView, veil, p);
|
|
||||||
|
|
||||||
stage.setScene(new Scene(stackPane, 360, 480));
|
|
||||||
stage.showAndWait();
|
|
||||||
cookies = cookieManager.getCookieStore().getCookies();
|
|
||||||
}
|
|
||||||
|
|
||||||
private WebView createWebView(Stage stage) throws IOException {
|
|
||||||
|
|
||||||
|
|
||||||
WebView browser = new WebView();
|
|
||||||
WebEngine webEngine = browser.getEngine();
|
|
||||||
webEngine.setJavaScriptEnabled(true);
|
|
||||||
//webEngine.setUserAgent("Mozilla/5.0 (Android 9.0; Mobile; rv:63.0) Gecko/63.0 Firefox/63.0");
|
|
||||||
webEngine.setUserAgent("Mozilla/5.0 (Mobile; rv:30.0) Gecko/20100101 Firefox/30.0");
|
|
||||||
webEngine.locationProperty().addListener((obs, oldV, newV) -> {
|
|
||||||
try {
|
|
||||||
URL _url = new URL(newV);
|
|
||||||
if (Objects.equals(_url.getPath(), "/")) {
|
|
||||||
stage.close();
|
|
||||||
}
|
|
||||||
} catch (MalformedURLException e) {
|
|
||||||
LOG.error("Couldn't parse new url {}", newV, e);
|
|
||||||
}
|
|
||||||
url = newV.toString();
|
|
||||||
});
|
|
||||||
webEngine.getLoadWorker().stateProperty().addListener((observable, oldState, newState) -> {
|
|
||||||
if (newState == State.SUCCEEDED) {
|
|
||||||
veil.setVisible(false);
|
|
||||||
p.setVisible(false);
|
|
||||||
// try {
|
|
||||||
// //webEngine.executeScript("$('#eighteen-plus-modal').hide();");
|
|
||||||
// //webEngine.executeScript("$('body').html('"+loginForm+"');");
|
|
||||||
// //webEngine.executeScript("$('#listpage').append('"+loginForm+"');");
|
|
||||||
// // webEngine.executeScript("$('#main-menu-button').click();");
|
|
||||||
// // webEngine.executeScript("$('#login-menu').click();");
|
|
||||||
// String username = Config.getInstance().getSettings().livejasminUsername;
|
|
||||||
// if (username != null && !username.trim().isEmpty()) {
|
|
||||||
// webEngine.executeScript("$('#username').attr('value','" + username + "')");
|
|
||||||
// }
|
|
||||||
// String password = Config.getInstance().getSettings().livejasminPassword;
|
|
||||||
// if (password != null && !password.trim().isEmpty()) {
|
|
||||||
// webEngine.executeScript("$('#password').attr('value','" + password + "')");
|
|
||||||
// }
|
|
||||||
// } catch(Exception e) {
|
|
||||||
// LOG.warn("Couldn't auto fill username and password for LiveJasmin", e);
|
|
||||||
// }
|
|
||||||
} else if (newState == State.CANCELLED || newState == State.FAILED) {
|
|
||||||
veil.setVisible(false);
|
|
||||||
p.setVisible(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
webEngine.setUserDataDirectory(new File(OS.getConfigDir(), "webengine"));
|
|
||||||
webEngine.load(URL);
|
|
||||||
return browser;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getLoginForm() throws IOException {
|
|
||||||
callBaseUrl(); // to get cookies
|
|
||||||
String url = "https://m.livejasmin.com/en/auth/window/get-login-window?isAjax=1";
|
|
||||||
Request request = new Request.Builder()
|
|
||||||
.url(url)
|
|
||||||
.addHeader("User-Agent", "Mozilla/5.0 (Android 9.0; Mobile; rv:63.0) Gecko/63.0 Firefox/63.0")
|
|
||||||
.addHeader("Accept", "application/json, text/javascript, */*")
|
|
||||||
.addHeader("Accept-Language", "en")
|
|
||||||
.addHeader("Referer", LiveJasmin.BASE_URL)
|
|
||||||
.addHeader("X-Requested-With", "XMLHttpRequest")
|
|
||||||
.build();
|
|
||||||
try(Response response = liveJasmin.getHttpClient().execute(request)) {
|
|
||||||
if(response.isSuccessful()) {
|
|
||||||
String body = response.body().string();
|
|
||||||
JSONObject json = new JSONObject(body);
|
|
||||||
System.out.println(json.toString(2));
|
|
||||||
if(json.optBoolean("success")) {
|
|
||||||
JSONObject data = json.getJSONObject("data");
|
|
||||||
return data.getString("content");
|
|
||||||
} else {
|
|
||||||
throw new IOException("Request was not successful: " + body);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new HttpException(response.code(), response.message());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void callBaseUrl() throws IOException {
|
|
||||||
String url = liveJasmin.getBaseUrl();
|
|
||||||
Request request = new Request.Builder()
|
|
||||||
.url(url)
|
|
||||||
.header("User-Agent", Config.getInstance().getSettings().httpUserAgent)
|
|
||||||
.build();
|
|
||||||
try(Response response = liveJasmin.getHttpClient().execute(request)) {
|
|
||||||
if(response.isSuccessful()) {
|
|
||||||
|
|
||||||
} else {
|
|
||||||
throw new HttpException(response.code(), response.message());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<HttpCookie> getCookies() {
|
|
||||||
for (HttpCookie httpCookie : cookies) {
|
|
||||||
LOG.debug("Cookie: {}", httpCookie);
|
|
||||||
}
|
|
||||||
return cookies;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUrl() {
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,9 +1,8 @@
|
||||||
package ctbrec.ui.sites.jasmin;
|
package ctbrec.ui.sites.jasmin;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.HttpCookie;
|
import java.util.concurrent.BlockingQueue;
|
||||||
import java.util.ArrayList;
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -13,9 +12,6 @@ import ctbrec.sites.jasmin.LiveJasmin;
|
||||||
import ctbrec.sites.jasmin.LiveJasminHttpClient;
|
import ctbrec.sites.jasmin.LiveJasminHttpClient;
|
||||||
import ctbrec.ui.SiteUI;
|
import ctbrec.ui.SiteUI;
|
||||||
import ctbrec.ui.TabProvider;
|
import ctbrec.ui.TabProvider;
|
||||||
import okhttp3.Cookie;
|
|
||||||
import okhttp3.CookieJar;
|
|
||||||
import okhttp3.HttpUrl;
|
|
||||||
|
|
||||||
public class LiveJasminSiteUi implements SiteUI {
|
public class LiveJasminSiteUi implements SiteUI {
|
||||||
|
|
||||||
|
@ -28,12 +24,6 @@ public class LiveJasminSiteUi implements SiteUI {
|
||||||
this.liveJasmin = liveJasmin;
|
this.liveJasmin = liveJasmin;
|
||||||
tabProvider = new LiveJasminTabProvider(liveJasmin);
|
tabProvider = new LiveJasminTabProvider(liveJasmin);
|
||||||
configUi = new LiveJasminConfigUi(liveJasmin);
|
configUi = new LiveJasminConfigUi(liveJasmin);
|
||||||
try {
|
|
||||||
login();
|
|
||||||
} catch (IOException e) {
|
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -49,74 +39,42 @@ public class LiveJasminSiteUi implements SiteUI {
|
||||||
@Override
|
@Override
|
||||||
public synchronized boolean login() throws IOException {
|
public synchronized boolean login() throws IOException {
|
||||||
boolean automaticLogin = liveJasmin.login();
|
boolean automaticLogin = liveJasmin.login();
|
||||||
return automaticLogin;
|
if(automaticLogin) {
|
||||||
// if(automaticLogin) {
|
return true;
|
||||||
// return true;
|
} else {
|
||||||
// } else {
|
BlockingQueue<Boolean> queue = new LinkedBlockingQueue<>();
|
||||||
// BlockingQueue<Boolean> queue = new LinkedBlockingQueue<>();
|
|
||||||
//
|
|
||||||
// Runnable showDialog = () -> {
|
|
||||||
// // login with javafx WebView
|
|
||||||
// LiveJasminLoginDialog loginDialog;
|
|
||||||
// try {
|
|
||||||
// loginDialog = new LiveJasminLoginDialog(liveJasmin);
|
|
||||||
// // transfer cookies from WebView to OkHttp cookie jar
|
|
||||||
// transferCookies(loginDialog);
|
|
||||||
// } catch (IOException e1) {
|
|
||||||
// LOG.error("Couldn't load login dialog", e1);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// 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);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// LiveJasminHttpClient httpClient = (LiveJasminHttpClient)liveJasmin.getHttpClient();
|
|
||||||
// boolean loggedIn = httpClient.checkLoginSuccess();
|
|
||||||
// if(loggedIn) {
|
|
||||||
// LOG.info("Logged in.");
|
|
||||||
// } else {
|
|
||||||
// LOG.info("Login failed");
|
|
||||||
// }
|
|
||||||
// return loggedIn;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
private void transferCookies(LiveJasminLoginDialog loginDialog) {
|
new Thread (() -> {
|
||||||
LiveJasminHttpClient httpClient = (LiveJasminHttpClient)liveJasmin.getHttpClient();
|
// login with external browser window
|
||||||
CookieJar cookieJar = httpClient.getCookieJar();
|
try {
|
||||||
|
//LiveJasminElectronLoginDialog dialog =
|
||||||
|
new LiveJasminElectronLoginDialog(liveJasmin.getHttpClient().getCookieJar());
|
||||||
|
} catch (IOException e1) {
|
||||||
|
LOG.error("Error logging in with external browser", e1);
|
||||||
|
}
|
||||||
|
|
||||||
String[] urls = {
|
try {
|
||||||
"https://www.livejasmin.com",
|
queue.put(true);
|
||||||
"http://www.livejasmin.com",
|
} catch (InterruptedException e) {
|
||||||
"https://m.livejasmin.com",
|
LOG.error("Error while signaling termination", e);
|
||||||
"http://m.livejasmin.com",
|
}
|
||||||
"https://livejasmin.com",
|
}).start();
|
||||||
"http://livejasmin.com"
|
|
||||||
};
|
|
||||||
|
|
||||||
for (String u : urls) {
|
try {
|
||||||
HttpUrl url = HttpUrl.parse(u);
|
queue.take();
|
||||||
List<Cookie> cookies = new ArrayList<>();
|
} catch (InterruptedException e) {
|
||||||
for (HttpCookie webViewCookie : loginDialog.getCookies()) {
|
LOG.error("Error while waiting for login dialog to close", e);
|
||||||
Cookie cookie = Cookie.parse(url, webViewCookie.toString());
|
throw new IOException(e);
|
||||||
cookies.add(cookie);
|
|
||||||
}
|
}
|
||||||
cookieJar.saveFromResponse(url, cookies);
|
|
||||||
|
LiveJasminHttpClient httpClient = (LiveJasminHttpClient)liveJasmin.getHttpClient();
|
||||||
|
boolean loggedIn = httpClient.checkLoginSuccess();
|
||||||
|
if(loggedIn) {
|
||||||
|
LOG.info("Logged in");
|
||||||
|
} else {
|
||||||
|
LOG.info("Login failed");
|
||||||
|
}
|
||||||
|
return loggedIn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import ctbrec.ui.TabProvider;
|
||||||
import ctbrec.ui.ThumbOverviewTab;
|
import ctbrec.ui.ThumbOverviewTab;
|
||||||
import javafx.scene.Scene;
|
import javafx.scene.Scene;
|
||||||
import javafx.scene.control.Tab;
|
import javafx.scene.control.Tab;
|
||||||
|
import javafx.util.Duration;
|
||||||
|
|
||||||
public class LiveJasminTabProvider extends TabProvider {
|
public class LiveJasminTabProvider extends TabProvider {
|
||||||
|
|
||||||
|
@ -43,6 +44,7 @@ public class LiveJasminTabProvider extends TabProvider {
|
||||||
LiveJasminUpdateService s = new LiveJasminUpdateService(liveJasmin, url);
|
LiveJasminUpdateService s = new LiveJasminUpdateService(liveJasmin, url);
|
||||||
ThumbOverviewTab tab = new ThumbOverviewTab(title, s, liveJasmin);
|
ThumbOverviewTab tab = new ThumbOverviewTab(title, s, liveJasmin);
|
||||||
tab.setRecorder(liveJasmin.getRecorder());
|
tab.setRecorder(liveJasmin.getRecorder());
|
||||||
|
s.setPeriod(Duration.seconds(60));
|
||||||
return tab;
|
return tab;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ public class LiveJasminUpdateService extends PaginatedScheduledService {
|
||||||
.name("listPageOrderType")
|
.name("listPageOrderType")
|
||||||
.value("most_popular")
|
.value("most_popular")
|
||||||
.build();
|
.build();
|
||||||
cookieJar.saveFromResponse(HttpUrl.parse("https://www.livejasmin.com"), Collections.singletonList(sortCookie));
|
cookieJar.saveFromResponse(HttpUrl.parse("https://livejasmin.com"), Collections.singletonList(sortCookie));
|
||||||
|
|
||||||
LOG.debug("Fetching page {}", url);
|
LOG.debug("Fetching page {}", url);
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
|
@ -56,7 +56,7 @@ public class LiveJasminUpdateService extends PaginatedScheduledService {
|
||||||
.addHeader("User-Agent", Config.getInstance().getSettings().httpUserAgent)
|
.addHeader("User-Agent", Config.getInstance().getSettings().httpUserAgent)
|
||||||
.addHeader("Accept", "application/json, text/javascript, */*")
|
.addHeader("Accept", "application/json, text/javascript, */*")
|
||||||
.addHeader("Accept-Language", "en")
|
.addHeader("Accept-Language", "en")
|
||||||
.addHeader("Referer", liveJasmin.getBaseUrl())
|
.addHeader("Referer", liveJasmin.getBaseUrl() + "/en/girls/")
|
||||||
.addHeader("X-Requested-With", "XMLHttpRequest")
|
.addHeader("X-Requested-With", "XMLHttpRequest")
|
||||||
.build();
|
.build();
|
||||||
try (Response response = liveJasmin.getHttpClient().execute(request)) {
|
try (Response response = liveJasmin.getHttpClient().execute(request)) {
|
||||||
|
|
|
@ -57,7 +57,7 @@
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.openjfx</groupId>
|
<groupId>org.openjfx</groupId>
|
||||||
<artifactId>javafx-web</artifactId>
|
<artifactId>javafx-media</artifactId>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
|
@ -8,8 +8,11 @@ import java.awt.TrayIcon;
|
||||||
import java.awt.TrayIcon.MessageType;
|
import java.awt.TrayIcon.MessageType;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -61,6 +64,46 @@ public class OS {
|
||||||
return configDir;
|
return configDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String[] getBrowserCommand(String...args) {
|
||||||
|
if(System.getenv("CTBREC_BROWSER") != null) {
|
||||||
|
String cmd[] = new String[args.length + 1];
|
||||||
|
cmd[0] = System.getenv("CTBREC_BROWSER");
|
||||||
|
System.arraycopy(args, 0, cmd, 1, args.length);
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
URI uri = OS.class.getProtectionDomain().getCodeSource().getLocation().toURI();
|
||||||
|
File jar = new File(uri.getPath());
|
||||||
|
File browserDir = new File(jar.getParentFile(), "browser");
|
||||||
|
String[] cmd;
|
||||||
|
switch (getOsType()) {
|
||||||
|
case LINUX:
|
||||||
|
cmd = new String[args.length + 1];
|
||||||
|
cmd[0] = new File(browserDir, "ctbrec-minimal-browser").getAbsolutePath();
|
||||||
|
System.arraycopy(args, 0, cmd, 1, args.length);
|
||||||
|
break;
|
||||||
|
case WINDOWS:
|
||||||
|
cmd = new String[args.length + 1];
|
||||||
|
cmd[0] = new File(browserDir, "ctbrec-minimal-browser.exe").getAbsolutePath();
|
||||||
|
System.arraycopy(args, 0, cmd, 1, args.length);
|
||||||
|
break;
|
||||||
|
case MAC:
|
||||||
|
cmd = new String[args.length + 2];
|
||||||
|
cmd[0] = "open";
|
||||||
|
cmd[1] = new File(browserDir, "ctbrec-minimal-browser.app").getAbsolutePath();
|
||||||
|
System.arraycopy(args, 0, cmd, 2, args.length);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("Unsupported operating system " + System.getProperty("os.name"));
|
||||||
|
}
|
||||||
|
LOG.debug("Browser command: {}", Arrays.toString(cmd));
|
||||||
|
return cmd;
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static Settings getDefaultSettings() {
|
public static Settings getDefaultSettings() {
|
||||||
Settings settings = new Settings();
|
Settings settings = new Settings();
|
||||||
if(getOsType() == TYPE.WINDOWS) {
|
if(getOsType() == TYPE.WINDOWS) {
|
||||||
|
|
|
@ -36,6 +36,7 @@ public class Settings {
|
||||||
public boolean localRecording = true;
|
public boolean localRecording = true;
|
||||||
public int httpPort = 8080;
|
public int httpPort = 8080;
|
||||||
public int httpTimeout = 10000;
|
public int httpTimeout = 10000;
|
||||||
|
public String httpUserAgentMobile = "Mozilla/5.0 (Android 9.0; Mobile; rv:63.0) Gecko/63.0 Firefox/63.0";
|
||||||
public String httpUserAgent = "Mozilla/5.0 Gecko/20100101 Firefox/62.0";
|
public String httpUserAgent = "Mozilla/5.0 Gecko/20100101 Firefox/62.0";
|
||||||
public String httpServer = "localhost";
|
public String httpServer = "localhost";
|
||||||
public String recordingsDir = System.getProperty("user.home") + File.separator + "ctbrec";
|
public String recordingsDir = System.getProperty("user.home") + File.separator + "ctbrec";
|
||||||
|
|
|
@ -25,7 +25,7 @@ public class CookieJarImpl implements CookieJar {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
|
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
|
||||||
String host = getHost(url);
|
String host = getDomain(url);
|
||||||
List<Cookie> cookiesForUrl = cookieStore.get(host);
|
List<Cookie> cookiesForUrl = cookieStore.get(host);
|
||||||
if (cookiesForUrl != null) {
|
if (cookiesForUrl != null) {
|
||||||
cookiesForUrl = new ArrayList<Cookie>(cookiesForUrl); //unmodifiable
|
cookiesForUrl = new ArrayList<Cookie>(cookiesForUrl); //unmodifiable
|
||||||
|
@ -52,7 +52,7 @@ public class CookieJarImpl implements CookieJar {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Cookie> loadForRequest(HttpUrl url) {
|
public List<Cookie> loadForRequest(HttpUrl url) {
|
||||||
String host = getHost(url);
|
String host = getDomain(url);
|
||||||
List<Cookie> cookies = cookieStore.get(host);
|
List<Cookie> cookies = cookieStore.get(host);
|
||||||
LOG.debug("Cookies for {}", url);
|
LOG.debug("Cookies for {}", url);
|
||||||
Optional.ofNullable(cookies).ifPresent(cookiez -> cookiez.forEach(c -> {
|
Optional.ofNullable(cookies).ifPresent(cookiez -> cookiez.forEach(c -> {
|
||||||
|
@ -72,12 +72,13 @@ public class CookieJarImpl implements CookieJar {
|
||||||
throw new NoSuchElementException("No cookie named " + name + " for " + url.host() + " available");
|
throw new NoSuchElementException("No cookie named " + name + " for " + url.host() + " available");
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getHost(HttpUrl url) {
|
private String getDomain(HttpUrl url) {
|
||||||
String host = url.host();
|
// String host = url.host();
|
||||||
if (host.startsWith("www.")) {
|
// if (host.startsWith("www.")) {
|
||||||
host = host.substring(4);
|
// host = host.substring(4);
|
||||||
}
|
// }
|
||||||
return host;
|
// return host;
|
||||||
|
return url.topPrivateDomain();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -151,7 +151,7 @@ public class LiveJasmin extends AbstractSite {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean credentialsAvailable() {
|
public boolean credentialsAvailable() {
|
||||||
return !Config.getInstance().getSettings().livejasminSession.isEmpty();
|
return !Config.getInstance().getSettings().livejasminUsername.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package ctbrec.sites.jasmin;
|
package ctbrec.sites.jasmin;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -29,19 +28,6 @@ public class LiveJasminHttpClient extends HttpClient {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set session cookie, if session id is available
|
|
||||||
if(!Config.getInstance().getSettings().livejasminSession.isEmpty()) {
|
|
||||||
Cookie captchaCookie = new Cookie.Builder()
|
|
||||||
.domain("livejasmin.com")
|
|
||||||
.name("session")
|
|
||||||
.value(Config.getInstance().getSettings().livejasminSession)
|
|
||||||
.build();
|
|
||||||
getCookieJar().saveFromResponse(HttpUrl.parse("https://livejasmin.com"), Collections.singletonList(captchaCookie));
|
|
||||||
getCookieJar().saveFromResponse(HttpUrl.parse("https://www.livejasmin.com"), Collections.singletonList(captchaCookie));
|
|
||||||
getCookieJar().saveFromResponse(HttpUrl.parse("https://m.livejasmin.com"), Collections.singletonList(captchaCookie));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// loadMainPage(); // to get initial cookies
|
// loadMainPage(); // to get initial cookies
|
||||||
// Cookie captchaCookie = new Cookie.Builder()
|
// Cookie captchaCookie = new Cookie.Builder()
|
||||||
// .domain("livejasmin.com")
|
// .domain("livejasmin.com")
|
||||||
|
@ -152,10 +138,17 @@ public class LiveJasminHttpClient extends HttpClient {
|
||||||
.followRedirects(false)
|
.followRedirects(false)
|
||||||
.followSslRedirects(false)
|
.followSslRedirects(false)
|
||||||
.build();
|
.build();
|
||||||
String url = LiveJasmin.BASE_URL + "/en/free/favourite/get-favourite-list";
|
|
||||||
|
// getCookieJar().getCookies().entrySet().forEach((e) -> {
|
||||||
|
// e.getValue().forEach(c -> {
|
||||||
|
// LOG.debug("LOGIN CHECK: Cookie {} {}={}", e.getKey(), c.name(), c.value());
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
|
||||||
|
String url = "https://m.livejasmin.com/en/member/favourite/get-favourite-list?ajax=1";
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
.url(url)
|
.url(url)
|
||||||
.addHeader("User-Agent", Config.getInstance().getSettings().httpUserAgent)
|
.addHeader("User-Agent", Config.getInstance().getSettings().httpUserAgentMobile)
|
||||||
.addHeader("Accept", "application/json, text/javascript, */*")
|
.addHeader("Accept", "application/json, text/javascript, */*")
|
||||||
.addHeader("Accept-Language", "en")
|
.addHeader("Accept-Language", "en")
|
||||||
.addHeader("Referer", LiveJasmin.BASE_URL)
|
.addHeader("Referer", LiveJasmin.BASE_URL)
|
||||||
|
@ -166,13 +159,18 @@ public class LiveJasminHttpClient extends HttpClient {
|
||||||
if(response.isSuccessful()) {
|
if(response.isSuccessful()) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
// if(response.code() >= 300 && response.code() < 400) {
|
||||||
|
// for (String name : response.headers().names()) {
|
||||||
|
// LOG.debug("{}: {}", name, response.header(name));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSessionId() {
|
public String getSessionId() {
|
||||||
Cookie sessionCookie = getCookieJar().getCookie(HttpUrl.parse("https://www.livejasmin.com"), "session");
|
Cookie sessionCookie = getCookieJar().getCookie(HttpUrl.parse(LiveJasmin.BASE_URL), "session");
|
||||||
if(sessionCookie != null) {
|
if(sessionCookie != null) {
|
||||||
return sessionCookie.value();
|
return sessionCookie.value();
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -280,6 +280,7 @@ public class LiveJasminModel extends AbstractModel {
|
||||||
// } else {
|
// } else {
|
||||||
// return new LiveJasminWebSocketDownload(getSite().getHttpClient());
|
// return new LiveJasminWebSocketDownload(getSite().getHttpClient());
|
||||||
// }
|
// }
|
||||||
return new LiveJasminChunkedHttpDownload(getSite().getHttpClient());
|
//return new LiveJasminChunkedHttpDownload(getSite().getHttpClient());
|
||||||
|
return new LiveJasminWebSocketDownload(getSite().getHttpClient());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,6 +85,11 @@
|
||||||
<artifactId>javafx-web</artifactId>
|
<artifactId>javafx-web</artifactId>
|
||||||
<version>11</version>
|
<version>11</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.openjfx</groupId>
|
||||||
|
<artifactId>javafx-media</artifactId>
|
||||||
|
<version>11</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.google.guava</groupId>
|
<groupId>com.google.guava</groupId>
|
||||||
<artifactId>guava</artifactId>
|
<artifactId>guava</artifactId>
|
||||||
|
|
Loading…
Reference in New Issue