Add CamSoda login dialog
This dialog is shown, if the normal login didn't work. For example, if you log in several times in a short amount of time, they respond with "Please confirm that you are not a robot" and you have to log in with a captcha
This commit is contained in:
parent
efbae57113
commit
5333e427ad
|
@ -1,19 +1,37 @@
|
|||
package ctbrec.sites.camsoda;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.HttpCookie;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ctbrec.Config;
|
||||
import ctbrec.io.HttpClient;
|
||||
import ctbrec.sites.cam4.Cam4LoginDialog;
|
||||
import javafx.application.Platform;
|
||||
import okhttp3.Cookie;
|
||||
import okhttp3.FormBody;
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
public class CamsodaHttpClient extends HttpClient {
|
||||
|
||||
private static final transient Logger LOG = LoggerFactory.getLogger(CamsodaHttpClient.class);
|
||||
|
||||
@Override
|
||||
public boolean login() throws IOException {
|
||||
if(loggedIn) {
|
||||
return true;
|
||||
}
|
||||
|
||||
String url = Camsoda.BASE_URI + "/api/v1/auth/login";
|
||||
FormBody body = new FormBody.Builder()
|
||||
.add("username", Config.getInstance().getSettings().camsodaUsername)
|
||||
|
@ -27,7 +45,12 @@ public class CamsodaHttpClient extends HttpClient {
|
|||
if(response.isSuccessful()) {
|
||||
JSONObject resp = new JSONObject(response.body().string());
|
||||
if(resp.has("error")) {
|
||||
throw new IOException(resp.getString("error"));
|
||||
String error = resp.getString("error");
|
||||
if(Objects.equals(error, "Please confirm that you are not a robot.")) {
|
||||
return loginWithDialog();
|
||||
} else {
|
||||
throw new IOException(resp.getString("error"));
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
@ -35,4 +58,63 @@ public class CamsodaHttpClient extends HttpClient {
|
|||
throw new IOException(response.code() + " " + response.message());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean loginWithDialog() throws IOException {
|
||||
BlockingQueue<Boolean> queue = new LinkedBlockingQueue<>();
|
||||
|
||||
Runnable showDialog = () -> {
|
||||
// login with javafx WebView
|
||||
CamsodaLoginDialog loginDialog = new CamsodaLoginDialog();
|
||||
|
||||
// transfer cookies from WebView to OkHttp cookie jar
|
||||
transferCookies(loginDialog);
|
||||
|
||||
try {
|
||||
queue.put(true);
|
||||
} catch (InterruptedException e) {
|
||||
LOG.error("Error while signaling termination", e);
|
||||
}
|
||||
};
|
||||
|
||||
if(Platform.isFxApplicationThread()) {
|
||||
showDialog.run();
|
||||
} else {
|
||||
Platform.runLater(showDialog);
|
||||
try {
|
||||
queue.take();
|
||||
} catch (InterruptedException e) {
|
||||
LOG.error("Error while waiting for login dialog to close", e);
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
loggedIn = checkLoginSuccess();
|
||||
return loggedIn;
|
||||
}
|
||||
|
||||
/**
|
||||
* check, if the login worked
|
||||
* @throws IOException
|
||||
*/
|
||||
private boolean checkLoginSuccess() throws IOException {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void transferCookies(CamsodaLoginDialog loginDialog) {
|
||||
HttpUrl redirectedUrl = HttpUrl.parse(loginDialog.getUrl());
|
||||
List<Cookie> cookies = new ArrayList<>();
|
||||
for (HttpCookie webViewCookie : loginDialog.getCookies()) {
|
||||
Cookie cookie = Cookie.parse(redirectedUrl, webViewCookie.toString());
|
||||
cookies.add(cookie);
|
||||
}
|
||||
cookieJar.saveFromResponse(redirectedUrl, cookies);
|
||||
|
||||
HttpUrl origUrl = HttpUrl.parse(Cam4LoginDialog.URL);
|
||||
cookies = new ArrayList<>();
|
||||
for (HttpCookie webViewCookie : loginDialog.getCookies()) {
|
||||
Cookie cookie = Cookie.parse(origUrl, webViewCookie.toString());
|
||||
cookies.add(cookie);
|
||||
}
|
||||
cookieJar.saveFromResponse(origUrl, cookies);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
package ctbrec.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 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 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() {
|
||||
for (HttpCookie httpCookie : cookies) {
|
||||
System.out.println(httpCookie);
|
||||
}
|
||||
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; }";
|
||||
}
|
Loading…
Reference in New Issue