Skip to content

Commit

Permalink
#4: + more detailed exceptions
Browse files Browse the repository at this point in the history
  • Loading branch information
FelixSFD committed Jul 26, 2018
1 parent 777f50d commit bddf863
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 18 deletions.
21 changes: 21 additions & 0 deletions src/main/java/org/sobotics/chatexchange/chat/ChatHost.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,24 @@ public enum ChatHost {
META_STACK_EXCHANGE("meta.stackexchange.com");

private final String name, baseUrl;

/**
* Host that is used for the login
*
* This might be a different host, because stackexchange.com does not have a login
*/
private final String loginHost;

private ChatHost(String name) {
this.name = name;
this.baseUrl = "https://chat." + name;

if (this.name.equalsIgnoreCase("stackexchange.com")) {
//stackexchange.com doesn't have a login, so we have to use meta
this.loginHost = "meta.stackexchange.com";
} else {
this.loginHost = this.name;
}
}

/**
Expand All @@ -31,5 +45,12 @@ public String getName() {
public String getBaseUrl() {
return baseUrl;
}

/**
* @return Host that is used for the login
*/
public String getLoginHost() {
return this.loginHost;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package org.sobotics.chatexchange.chat;

/**
* Exception when the login fails. Contains information about the hosts
*
* @author FelixSFD
*/
public class ChatLoginException extends Exception {
private static final long serialVersionUID = 3836431112726533617L;

/**
* {@link ChatHost} that was used for the login
*/
private ChatHost host;

/**
* Initializes the exception
* @param chatHost {@link ChatHost} that was used for the login
* @param message Error-message
*/
public ChatLoginException(ChatHost chatHost, String message) {
super(message);
this.host = chatHost;
}

/**
* {@inheritDoc}
*/
@Override
public String getMessage() {
String msg = "Unable to login to " + this.host.getName();

if (!this.host.getName().equalsIgnoreCase(this.host.getLoginHost())) {
msg += " (via " + this.host.getLoginHost() + ")";
}

msg += ": " + super.getMessage();

return msg;
}

/**
* {@inheritDoc}
*/
@Override
public String getLocalizedMessage() {
return this.getMessage();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -79,26 +79,25 @@ public StackExchangeClient(String email, String password) {
* Logs in to s given site
* @param email The user's e-mail-address
* @param password The password
* @param The host of the main site (NOT the chat.*! Use ChatHost.getName())
* @param host {@link ChatHost} of the {@link Room}
* @throws ChatLoginException if the login fails
* */
private void seLogin(String email, String password, String host) throws IOException {
String originalHost = host;
private void seLogin(String email, String password, ChatHost host) throws IOException, ChatLoginException {
String originalHost = host.getName();
String loginHost = host.getLoginHost();

if (host.equalsIgnoreCase(ChatHost.STACK_EXCHANGE.getName())) {
host = ChatHost.META_STACK_EXCHANGE.getName();
}

//The login-form has a hidden field called "fkey" which needs to be sent along with the mail and password
Response response = httpClient.get("https://"+host+"/users/login", cookies);
Response response = httpClient.get("https://"+loginHost+"/users/login", cookies);
String fkey = response.parse().select("input[name='fkey']").val();

response = httpClient.post("https://"+host+"/users/login", cookies, "email", email, "password", password, "fkey", fkey);
response = httpClient.post("https://"+loginHost+"/users/login", cookies, "email", email, "password", password, "fkey", fkey);

//Create account on that site if necessary
Element formElement = response.parse().getElementById("logout-user");
if (formElement != null) {
if (!this.autoCreateAccount) {
throw new IllegalStateException("Unable to login to Stack Exchange. The user does not have an account on " + originalHost);
throw new ChatLoginException(host, "The user does not have an account on this site!");
} // if autoCreate

Elements formInputs = formElement.getElementsByTag("input");
Expand All @@ -117,21 +116,27 @@ private void seLogin(String email, String password, String host) throws IOExcept

String[] formDataArray = formData.toArray(new String[formData.size()]);

String formUrl = "https://" + host + formElement.attr("action");
String formUrl = "https://" + loginHost + formElement.attr("action");

Response formResponse = httpClient.post(formUrl, cookies, formDataArray);
if (formResponse.parse().getElementsByClass("js-inbox-button").first() == null) {
LOGGER.debug(formResponse.parse().html());
throw new IllegalStateException("Unable to create account on " + host + "! Please create the account manually.");
throw new ChatLoginException(host, "Unable to create account! Please create the account manually.");
} // if
} // if


//Check for captcha
Element captchaElement = response.parse().getElementById("nocaptcha-form");
if (captchaElement != null) {
throw new ChatLoginException(host, "Captcha found! Please wait some time before trying to login again.");
}

// check if login succeeded
Response checkResponse = httpClient.get("https://"+originalHost+"/users/current", cookies);
if (checkResponse.parse().getElementsByClass("js-inbox-button").first() == null) {
LOGGER.debug(checkResponse.parse().html());
throw new IllegalStateException("Unable to login to Stack Exchange. (Site: " + originalHost + " via " + host + ")");
throw new ChatLoginException(host, "Maybe your login credentials are wrong.");
} // if
} // seLogin

Expand Down Expand Up @@ -163,10 +168,9 @@ private void SEOpenIdLogin(String email, String password) throws IOException {
* @param host Host of the chat room to join.
* @param roomId Id of the room to join.
* @return <code>Room</code> joined.
* @throws ChatLoginException when the login failed
*/
public Room joinRoom(ChatHost host, int roomId) {
String mainSiteHost = host.getName();

public Room joinRoom(ChatHost host, int roomId) throws ChatLoginException {
boolean alreadyLoggedIn = false;

for (Room room : this.rooms) {
Expand All @@ -179,10 +183,10 @@ public Room joinRoom(ChatHost host, int roomId) {
if (!alreadyLoggedIn) {
//not logged in on that site yet
try {
this.seLogin(email, password, mainSiteHost);
this.seLogin(email, password, host);
} catch (IOException e) {
LOGGER.error("Unable to login on " + mainSiteHost + " for " + host.getBaseUrl(), e);
throw new ChatOperationException("Login to " + mainSiteHost + " failed!");
LOGGER.error("Login failed due to IOException!", e);
throw new ChatLoginException(host, "IOException: " + e.getMessage());
}
}

Expand Down

0 comments on commit bddf863

Please sign in to comment.