diff --git a/client/.gitignore b/client/.gitignore index 2c4e8e27..222879c9 100644 --- a/client/.gitignore +++ b/client/.gitignore @@ -6,3 +6,4 @@ /ctbrec-tunnel.sh /jre/ /server-local.sh +/browser/ diff --git a/client/pom.xml b/client/pom.xml index 435967b8..c21fedba 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -4,7 +4,7 @@ 4.0.0 client - + ctbrec master @@ -80,7 +80,7 @@ org.openjfx - javafx-web + javafx-media diff --git a/client/src/assembly/linux-jre.xml b/client/src/assembly/linux-jre.xml index 4cf3b8ba..182be496 100644 --- a/client/src/assembly/linux-jre.xml +++ b/client/src/assembly/linux-jre.xml @@ -38,5 +38,13 @@ ctbrec/jre false + + browser/ctbrec-minimal-browser-linux-x64 + + **/* + + ctbrec/browser + false + diff --git a/client/src/assembly/linux.xml b/client/src/assembly/linux.xml index 96e803e9..a692495d 100644 --- a/client/src/assembly/linux.xml +++ b/client/src/assembly/linux.xml @@ -29,4 +29,14 @@ ctbrec + + + browser/ctbrec-minimal-browser-linux-x64 + + **/* + + ctbrec/browser + false + + diff --git a/client/src/assembly/macos-jre.xml b/client/src/assembly/macos-jre.xml index ec549040..31f2ff40 100644 --- a/client/src/assembly/macos-jre.xml +++ b/client/src/assembly/macos-jre.xml @@ -38,5 +38,13 @@ ctbrec/jre false + + browser/ctbrec-minimal-browser-darwin-x64 + + **/* + + ctbrec/browser + false + diff --git a/client/src/assembly/macos.xml b/client/src/assembly/macos.xml index fb7620ab..f9c9fcca 100644 --- a/client/src/assembly/macos.xml +++ b/client/src/assembly/macos.xml @@ -29,4 +29,14 @@ ctbrec + + + browser/ctbrec-minimal-browser-darwin-x64 + + **/* + + ctbrec/browser + false + + diff --git a/client/src/assembly/win64-jre.xml b/client/src/assembly/win64-jre.xml index f994af4c..06a6cb8d 100644 --- a/client/src/assembly/win64-jre.xml +++ b/client/src/assembly/win64-jre.xml @@ -40,5 +40,13 @@ ctbrec/jre false + + browser/ctbrec-minimal-browser-win32-x64 + + **/* + + ctbrec/browser + false + diff --git a/client/src/assembly/win64.xml b/client/src/assembly/win64.xml index fd31b626..1f1cf1e7 100644 --- a/client/src/assembly/win64.xml +++ b/client/src/assembly/win64.xml @@ -31,4 +31,14 @@ ctbrec + + + browser/ctbrec-minimal-browser-win32-x64 + + **/* + + ctbrec/browser + false + + diff --git a/client/src/main/java/ctbrec/ui/CamrecApplication.java b/client/src/main/java/ctbrec/ui/CamrecApplication.java index 29ff5a0c..0e8cf692 100644 --- a/client/src/main/java/ctbrec/ui/CamrecApplication.java +++ b/client/src/main/java/ctbrec/ui/CamrecApplication.java @@ -196,6 +196,10 @@ public class CamrecApplication extends Application { System.exit(1); }); } + try { + ExternalBrowser.getInstance().close(); + } catch (IOException e) { + } } }.start(); }); diff --git a/client/src/main/java/ctbrec/ui/DonateTabHtml.java b/client/src/main/java/ctbrec/ui/DonateTabHtml.java deleted file mode 100644 index de1fc23e..00000000 --- a/client/src/main/java/ctbrec/ui/DonateTabHtml.java +++ /dev/null @@ -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); - } - } -} diff --git a/client/src/main/java/ctbrec/ui/ExternalBrowser.java b/client/src/main/java/ctbrec/ui/ExternalBrowser.java new file mode 100644 index 00000000..648014d7 --- /dev/null +++ b/client/src/main/java/ctbrec/ui/ExternalBrowser.java @@ -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 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 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(); + } +} diff --git a/client/src/main/java/ctbrec/ui/WebbrowserTab.java b/client/src/main/java/ctbrec/ui/WebbrowserTab.java deleted file mode 100644 index cf904a3e..00000000 --- a/client/src/main/java/ctbrec/ui/WebbrowserTab.java +++ /dev/null @@ -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()); - }); - } -} diff --git a/client/src/main/java/ctbrec/ui/sites/bonga/BongaCamsElectronLoginDialog.java b/client/src/main/java/ctbrec/ui/sites/bonga/BongaCamsElectronLoginDialog.java new file mode 100644 index 00000000..82df391b --- /dev/null +++ b/client/src/main/java/ctbrec/ui/sites/bonga/BongaCamsElectronLoginDialog.java @@ -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 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); + } + } + } + }; +} diff --git a/client/src/main/java/ctbrec/ui/sites/bonga/BongaCamsLoginDialog.java b/client/src/main/java/ctbrec/ui/sites/bonga/BongaCamsLoginDialog.java deleted file mode 100644 index 099d0c7c..00000000 --- a/client/src/main/java/ctbrec/ui/sites/bonga/BongaCamsLoginDialog.java +++ /dev/null @@ -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 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 getCookies() { - // for (HttpCookie httpCookie : cookies) { - // LOG.debug("Cookie: {}", httpCookie); - // } - return cookies; - } - - public String getUrl() { - return url; - } -} diff --git a/client/src/main/java/ctbrec/ui/sites/bonga/BongaCamsSiteUi.java b/client/src/main/java/ctbrec/ui/sites/bonga/BongaCamsSiteUi.java index 8e123696..46a6b1f3 100644 --- a/client/src/main/java/ctbrec/ui/sites/bonga/BongaCamsSiteUi.java +++ b/client/src/main/java/ctbrec/ui/sites/bonga/BongaCamsSiteUi.java @@ -1,9 +1,6 @@ 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; @@ -15,10 +12,6 @@ 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 { @@ -50,31 +43,25 @@ public class BongaCamsSiteUi implements SiteUI { return true; } else { BlockingQueue 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 = () -> { - // 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); - } + try { + queue.put(true); + } catch (InterruptedException e) { + LOG.error("Error while signaling termination", e); + } + }).start(); + 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(); @@ -87,26 +74,4 @@ public class BongaCamsSiteUi implements SiteUI { return loggedIn; } } - - - private void transferCookies(BongaCamsLoginDialog loginDialog) { - BongaCamsHttpClient httpClient = (BongaCamsHttpClient)bongaCams.getHttpClient(); - CookieJar cookieJar = httpClient.getCookieJar(); - - HttpUrl redirectedUrl = HttpUrl.parse(loginDialog.getUrl()); - List 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); - } } diff --git a/client/src/main/java/ctbrec/ui/sites/cam4/Cam4ElectronLoginDialog.java b/client/src/main/java/ctbrec/ui/sites/cam4/Cam4ElectronLoginDialog.java new file mode 100644 index 00000000..117849d0 --- /dev/null +++ b/client/src/main/java/ctbrec/ui/sites/cam4/Cam4ElectronLoginDialog.java @@ -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 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(); + } +} diff --git a/client/src/main/java/ctbrec/ui/sites/cam4/Cam4LoginDialog.java b/client/src/main/java/ctbrec/ui/sites/cam4/Cam4LoginDialog.java deleted file mode 100644 index 65c13019..00000000 --- a/client/src/main/java/ctbrec/ui/sites/cam4/Cam4LoginDialog.java +++ /dev/null @@ -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 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 getCookies() { - return cookies; - } - - public String getUrl() { - return url; - } -} diff --git a/client/src/main/java/ctbrec/ui/sites/cam4/Cam4SiteUi.java b/client/src/main/java/ctbrec/ui/sites/cam4/Cam4SiteUi.java index 8e61b411..fbc18c81 100644 --- a/client/src/main/java/ctbrec/ui/sites/cam4/Cam4SiteUi.java +++ b/client/src/main/java/ctbrec/ui/sites/cam4/Cam4SiteUi.java @@ -1,9 +1,6 @@ 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; @@ -16,9 +13,6 @@ 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); @@ -46,18 +40,19 @@ public class Cam4SiteUi implements SiteUI { @Override public synchronized boolean login() throws IOException { boolean automaticLogin = cam4.login(); - if(automaticLogin) { + if (automaticLogin) { return true; } else { BlockingQueue queue = new LinkedBlockingQueue<>(); Runnable showDialog = () -> { - // login with javafx WebView - Cam4LoginDialog loginDialog = new Cam4LoginDialog(); - - // transfer cookies from WebView to OkHttp cookie jar - transferCookies(loginDialog); + // login with external browser + try { + new Cam4ElectronLoginDialog(cam4.getHttpClient().getCookieJar()); + } catch (Exception e1) { + LOG.error("Error logging in with external browser", e1); + } try { queue.put(true); @@ -66,16 +61,12 @@ public class Cam4SiteUi implements SiteUI { } }; - 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); - } + 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(); @@ -83,31 +74,4 @@ public class Cam4SiteUi implements SiteUI { return loggedIn; } } - - - private void transferCookies(Cam4LoginDialog loginDialog) { - Cam4HttpClient httpClient = (Cam4HttpClient) cam4.getHttpClient(); - CookieJar cookieJar = httpClient.getCookieJar(); - - HttpUrl redirectedUrl = HttpUrl.parse(loginDialog.getUrl()); - List 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); - } } diff --git a/client/src/main/java/ctbrec/ui/sites/camsoda/CamsodaLoginDialog.java b/client/src/main/java/ctbrec/ui/sites/camsoda/CamsodaLoginDialog.java deleted file mode 100644 index e08731ea..00000000 --- a/client/src/main/java/ctbrec/ui/sites/camsoda/CamsodaLoginDialog.java +++ /dev/null @@ -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 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 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; }"; -} diff --git a/client/src/main/java/ctbrec/ui/sites/camsoda/CamsodaSiteUi.java b/client/src/main/java/ctbrec/ui/sites/camsoda/CamsodaSiteUi.java index af1be6ab..2b2a2eb7 100644 --- a/client/src/main/java/ctbrec/ui/sites/camsoda/CamsodaSiteUi.java +++ b/client/src/main/java/ctbrec/ui/sites/camsoda/CamsodaSiteUi.java @@ -1,24 +1,14 @@ 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 { @@ -50,58 +40,57 @@ public class CamsodaSiteUi implements SiteUI { return automaticLogin; } - - @SuppressWarnings("unused") - private boolean loginWithDialog() throws IOException { - BlockingQueue 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 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); - } + // @SuppressWarnings("unused") + // private boolean loginWithDialog() throws IOException { + // BlockingQueue queue = new LinkedBlockingQueue<>(); + // + // Runnable showDialog = () -> { + // // login with external browser + // 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 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(Camsoda.BASE_URI); + // cookies = new ArrayList<>(); + // for (HttpCookie webViewCookie : loginDialog.getCookies()) { + // Cookie cookie = Cookie.parse(origUrl, webViewCookie.toString()); + // cookies.add(cookie); + // } + // camsoda.getHttpClient().getCookieJar().saveFromResponse(origUrl, cookies); + // } } diff --git a/client/src/main/java/ctbrec/ui/sites/jasmin/LiveJasminConfigUi.java b/client/src/main/java/ctbrec/ui/sites/jasmin/LiveJasminConfigUi.java index 2cf66c02..f1c8c8db 100644 --- a/client/src/main/java/ctbrec/ui/sites/jasmin/LiveJasminConfigUi.java +++ b/client/src/main/java/ctbrec/ui/sites/jasmin/LiveJasminConfigUi.java @@ -73,19 +73,20 @@ public class LiveJasminConfigUi extends AbstractConfigUI { GridPane.setColumnSpan(password, 2); layout.add(password, 1, row++); - layout.add(new Label("LiveJasmin Session ID"), 0, row); - TextField sessionId = new TextField(); - sessionId.setText(Config.getInstance().getSettings().livejasminSession); - sessionId.textProperty().addListener((ob, o, n) -> { - if(!n.equals(Config.getInstance().getSettings().livejasminSession)) { - Config.getInstance().getSettings().livejasminSession = n; - save(); - } - }); - GridPane.setFillWidth(sessionId, true); - GridPane.setHgrow(sessionId, Priority.ALWAYS); - GridPane.setColumnSpan(sessionId, 2); - layout.add(sessionId, 1, row++); + // layout.add(new Label("LiveJasmin Session ID"), 0, row); + // TextField sessionId = new TextField(); + // sessionId.setText(Config.getInstance().getSettings().livejasminSession); + // sessionId.textProperty().addListener((ob, o, n) -> { + // if(!n.equals(Config.getInstance().getSettings().livejasminSession)) { + // Config.getInstance().getSettings().livejasminSession = n; + // save(); + // } + // }); + // GridPane.setFillWidth(sessionId, true); + // GridPane.setHgrow(sessionId, Priority.ALWAYS); + // GridPane.setColumnSpan(sessionId, 2); + // GridPane.setMargin(sessionId, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN)); + // layout.add(sessionId, 1, row++); Button createAccount = new Button("Create new Account"); createAccount.setOnAction((e) -> DesktopIntegration.open(liveJasmin.getAffiliateLink())); @@ -93,7 +94,6 @@ public class LiveJasminConfigUi extends AbstractConfigUI { GridPane.setColumnSpan(createAccount, 2); GridPane.setMargin(username, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN)); GridPane.setMargin(password, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN)); - GridPane.setMargin(sessionId, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN)); GridPane.setMargin(createAccount, new Insets(0, 0, 0, SettingsTab.CHECKBOX_MARGIN)); username.setPrefWidth(300); diff --git a/client/src/main/java/ctbrec/ui/sites/jasmin/LiveJasminElectronLoginDialog.java b/client/src/main/java/ctbrec/ui/sites/jasmin/LiveJasminElectronLoginDialog.java new file mode 100644 index 00000000..86879d9e --- /dev/null +++ b/client/src/main/java/ctbrec/ui/sites/jasmin/LiveJasminElectronLoginDialog.java @@ -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 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); + } + } + } + } + }; +} diff --git a/client/src/main/java/ctbrec/ui/sites/jasmin/LiveJasminFollowedUpdateService.java b/client/src/main/java/ctbrec/ui/sites/jasmin/LiveJasminFollowedUpdateService.java index b0cf8089..a660344c 100644 --- a/client/src/main/java/ctbrec/ui/sites/jasmin/LiveJasminFollowedUpdateService.java +++ b/client/src/main/java/ctbrec/ui/sites/jasmin/LiveJasminFollowedUpdateService.java @@ -15,6 +15,7 @@ import ctbrec.io.HttpException; import ctbrec.sites.jasmin.LiveJasmin; import ctbrec.sites.jasmin.LiveJasminModel; import ctbrec.ui.PaginatedScheduledService; +import ctbrec.ui.SiteUiFactory; import javafx.concurrent.Task; import okhttp3.Request; import okhttp3.Response; @@ -37,6 +38,10 @@ public class LiveJasminFollowedUpdateService extends PaginatedScheduledService { return new Task>() { @Override public List 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 //LOG.debug("Fetching page {}", url); Request request = new Request.Builder() diff --git a/client/src/main/java/ctbrec/ui/sites/jasmin/LiveJasminLoginDialog.java b/client/src/main/java/ctbrec/ui/sites/jasmin/LiveJasminLoginDialog.java deleted file mode 100644 index f6071d54..00000000 --- a/client/src/main/java/ctbrec/ui/sites/jasmin/LiveJasminLoginDialog.java +++ /dev/null @@ -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 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 getCookies() { - for (HttpCookie httpCookie : cookies) { - LOG.debug("Cookie: {}", httpCookie); - } - return cookies; - } - - public String getUrl() { - return url; - } -} diff --git a/client/src/main/java/ctbrec/ui/sites/jasmin/LiveJasminSiteUi.java b/client/src/main/java/ctbrec/ui/sites/jasmin/LiveJasminSiteUi.java index f0115555..10f20ab8 100644 --- a/client/src/main/java/ctbrec/ui/sites/jasmin/LiveJasminSiteUi.java +++ b/client/src/main/java/ctbrec/ui/sites/jasmin/LiveJasminSiteUi.java @@ -1,9 +1,8 @@ package ctbrec.ui.sites.jasmin; 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; @@ -13,9 +12,6 @@ import ctbrec.sites.jasmin.LiveJasmin; import ctbrec.sites.jasmin.LiveJasminHttpClient; import ctbrec.ui.SiteUI; import ctbrec.ui.TabProvider; -import okhttp3.Cookie; -import okhttp3.CookieJar; -import okhttp3.HttpUrl; public class LiveJasminSiteUi implements SiteUI { @@ -28,12 +24,6 @@ public class LiveJasminSiteUi implements SiteUI { this.liveJasmin = liveJasmin; tabProvider = new LiveJasminTabProvider(liveJasmin); configUi = new LiveJasminConfigUi(liveJasmin); - try { - login(); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } } @Override @@ -49,74 +39,42 @@ public class LiveJasminSiteUi implements SiteUI { @Override public synchronized boolean login() throws IOException { boolean automaticLogin = liveJasmin.login(); - return automaticLogin; - // if(automaticLogin) { - // return true; - // } else { - // BlockingQueue 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; - // } - } + if(automaticLogin) { + return true; + } else { + BlockingQueue queue = new LinkedBlockingQueue<>(); - private void transferCookies(LiveJasminLoginDialog loginDialog) { - LiveJasminHttpClient httpClient = (LiveJasminHttpClient)liveJasmin.getHttpClient(); - CookieJar cookieJar = httpClient.getCookieJar(); + new Thread (() -> { + // login with external browser window + try { + //LiveJasminElectronLoginDialog dialog = + new LiveJasminElectronLoginDialog(liveJasmin.getHttpClient().getCookieJar()); + } catch (IOException e1) { + LOG.error("Error logging in with external browser", e1); + } - String[] urls = { - "https://www.livejasmin.com", - "http://www.livejasmin.com", - "https://m.livejasmin.com", - "http://m.livejasmin.com", - "https://livejasmin.com", - "http://livejasmin.com" - }; + try { + queue.put(true); + } catch (InterruptedException e) { + LOG.error("Error while signaling termination", e); + } + }).start(); - for (String u : urls) { - HttpUrl url = HttpUrl.parse(u); - List cookies = new ArrayList<>(); - for (HttpCookie webViewCookie : loginDialog.getCookies()) { - Cookie cookie = Cookie.parse(url, webViewCookie.toString()); - cookies.add(cookie); + try { + queue.take(); + } catch (InterruptedException e) { + LOG.error("Error while waiting for login dialog to close", e); + throw new IOException(e); } - 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; } } } diff --git a/client/src/main/java/ctbrec/ui/sites/jasmin/LiveJasminTabProvider.java b/client/src/main/java/ctbrec/ui/sites/jasmin/LiveJasminTabProvider.java index 998c2ba7..ee135d5d 100644 --- a/client/src/main/java/ctbrec/ui/sites/jasmin/LiveJasminTabProvider.java +++ b/client/src/main/java/ctbrec/ui/sites/jasmin/LiveJasminTabProvider.java @@ -8,6 +8,7 @@ import ctbrec.ui.TabProvider; import ctbrec.ui.ThumbOverviewTab; import javafx.scene.Scene; import javafx.scene.control.Tab; +import javafx.util.Duration; public class LiveJasminTabProvider extends TabProvider { @@ -43,6 +44,7 @@ public class LiveJasminTabProvider extends TabProvider { LiveJasminUpdateService s = new LiveJasminUpdateService(liveJasmin, url); ThumbOverviewTab tab = new ThumbOverviewTab(title, s, liveJasmin); tab.setRecorder(liveJasmin.getRecorder()); + s.setPeriod(Duration.seconds(60)); return tab; } } diff --git a/client/src/main/java/ctbrec/ui/sites/jasmin/LiveJasminUpdateService.java b/client/src/main/java/ctbrec/ui/sites/jasmin/LiveJasminUpdateService.java index e810fcab..e19a3b3d 100644 --- a/client/src/main/java/ctbrec/ui/sites/jasmin/LiveJasminUpdateService.java +++ b/client/src/main/java/ctbrec/ui/sites/jasmin/LiveJasminUpdateService.java @@ -48,7 +48,7 @@ public class LiveJasminUpdateService extends PaginatedScheduledService { .name("listPageOrderType") .value("most_popular") .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); Request request = new Request.Builder() @@ -56,7 +56,7 @@ public class LiveJasminUpdateService extends PaginatedScheduledService { .addHeader("User-Agent", Config.getInstance().getSettings().httpUserAgent) .addHeader("Accept", "application/json, text/javascript, */*") .addHeader("Accept-Language", "en") - .addHeader("Referer", liveJasmin.getBaseUrl()) + .addHeader("Referer", liveJasmin.getBaseUrl() + "/en/girls/") .addHeader("X-Requested-With", "XMLHttpRequest") .build(); try (Response response = liveJasmin.getHttpClient().execute(request)) { diff --git a/common/pom.xml b/common/pom.xml index 4308d633..8242591a 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -57,7 +57,7 @@ org.openjfx - javafx-web + javafx-media provided diff --git a/common/src/main/java/ctbrec/OS.java b/common/src/main/java/ctbrec/OS.java index e86842e4..268e8cbf 100644 --- a/common/src/main/java/ctbrec/OS.java +++ b/common/src/main/java/ctbrec/OS.java @@ -8,8 +8,11 @@ import java.awt.TrayIcon; import java.awt.TrayIcon.MessageType; import java.io.File; import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Arrays; import java.util.Map.Entry; import org.slf4j.Logger; @@ -61,6 +64,46 @@ public class OS { 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() { Settings settings = new Settings(); if(getOsType() == TYPE.WINDOWS) { diff --git a/common/src/main/java/ctbrec/Settings.java b/common/src/main/java/ctbrec/Settings.java index 649fb393..1e6612cf 100644 --- a/common/src/main/java/ctbrec/Settings.java +++ b/common/src/main/java/ctbrec/Settings.java @@ -36,6 +36,7 @@ public class Settings { public boolean localRecording = true; public int httpPort = 8080; 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 httpServer = "localhost"; public String recordingsDir = System.getProperty("user.home") + File.separator + "ctbrec"; diff --git a/common/src/main/java/ctbrec/io/CookieJarImpl.java b/common/src/main/java/ctbrec/io/CookieJarImpl.java index 69192ecb..324fb93a 100644 --- a/common/src/main/java/ctbrec/io/CookieJarImpl.java +++ b/common/src/main/java/ctbrec/io/CookieJarImpl.java @@ -25,7 +25,7 @@ public class CookieJarImpl implements CookieJar { @Override public void saveFromResponse(HttpUrl url, List cookies) { - String host = getHost(url); + String host = getDomain(url); List cookiesForUrl = cookieStore.get(host); if (cookiesForUrl != null) { cookiesForUrl = new ArrayList(cookiesForUrl); //unmodifiable @@ -52,7 +52,7 @@ public class CookieJarImpl implements CookieJar { @Override public List loadForRequest(HttpUrl url) { - String host = getHost(url); + String host = getDomain(url); List cookies = cookieStore.get(host); LOG.debug("Cookies for {}", url); 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"); } - private String getHost(HttpUrl url) { - String host = url.host(); - if (host.startsWith("www.")) { - host = host.substring(4); - } - return host; + private String getDomain(HttpUrl url) { + // String host = url.host(); + // if (host.startsWith("www.")) { + // host = host.substring(4); + // } + // return host; + return url.topPrivateDomain(); } @Override diff --git a/common/src/main/java/ctbrec/sites/jasmin/LiveJasmin.java b/common/src/main/java/ctbrec/sites/jasmin/LiveJasmin.java index cc53d667..1b3fd206 100644 --- a/common/src/main/java/ctbrec/sites/jasmin/LiveJasmin.java +++ b/common/src/main/java/ctbrec/sites/jasmin/LiveJasmin.java @@ -151,7 +151,7 @@ public class LiveJasmin extends AbstractSite { @Override public boolean credentialsAvailable() { - return !Config.getInstance().getSettings().livejasminSession.isEmpty(); + return !Config.getInstance().getSettings().livejasminUsername.isEmpty(); } } diff --git a/common/src/main/java/ctbrec/sites/jasmin/LiveJasminHttpClient.java b/common/src/main/java/ctbrec/sites/jasmin/LiveJasminHttpClient.java index b979ee53..1d495599 100644 --- a/common/src/main/java/ctbrec/sites/jasmin/LiveJasminHttpClient.java +++ b/common/src/main/java/ctbrec/sites/jasmin/LiveJasminHttpClient.java @@ -1,7 +1,6 @@ package ctbrec.sites.jasmin; import java.io.IOException; -import java.util.Collections; import java.util.NoSuchElementException; import org.slf4j.Logger; @@ -29,19 +28,6 @@ public class LiveJasminHttpClient extends HttpClient { 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 // Cookie captchaCookie = new Cookie.Builder() // .domain("livejasmin.com") @@ -152,10 +138,17 @@ public class LiveJasminHttpClient extends HttpClient { .followRedirects(false) .followSslRedirects(false) .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() .url(url) - .addHeader("User-Agent", Config.getInstance().getSettings().httpUserAgent) + .addHeader("User-Agent", Config.getInstance().getSettings().httpUserAgentMobile) .addHeader("Accept", "application/json, text/javascript, */*") .addHeader("Accept-Language", "en") .addHeader("Referer", LiveJasmin.BASE_URL) @@ -166,13 +159,18 @@ public class LiveJasminHttpClient extends HttpClient { if(response.isSuccessful()) { return true; } else { + // if(response.code() >= 300 && response.code() < 400) { + // for (String name : response.headers().names()) { + // LOG.debug("{}: {}", name, response.header(name)); + // } + // } return false; } } } 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) { return sessionCookie.value(); } else { diff --git a/common/src/main/java/ctbrec/sites/jasmin/LiveJasminModel.java b/common/src/main/java/ctbrec/sites/jasmin/LiveJasminModel.java index 24204da7..8722c6f4 100644 --- a/common/src/main/java/ctbrec/sites/jasmin/LiveJasminModel.java +++ b/common/src/main/java/ctbrec/sites/jasmin/LiveJasminModel.java @@ -280,6 +280,7 @@ public class LiveJasminModel extends AbstractModel { // } else { // return new LiveJasminWebSocketDownload(getSite().getHttpClient()); // } - return new LiveJasminChunkedHttpDownload(getSite().getHttpClient()); + //return new LiveJasminChunkedHttpDownload(getSite().getHttpClient()); + return new LiveJasminWebSocketDownload(getSite().getHttpClient()); } } diff --git a/master/pom.xml b/master/pom.xml index bc994b4a..34ff1e30 100644 --- a/master/pom.xml +++ b/master/pom.xml @@ -85,6 +85,11 @@ javafx-web 11 + + org.openjfx + javafx-media + 11 + com.google.guava guava