diff --git a/src/main/java/org/sobotics/chatexchange/chat/ChatHost.java b/src/main/java/org/sobotics/chatexchange/chat/ChatHost.java index 9252855..049e054 100644 --- a/src/main/java/org/sobotics/chatexchange/chat/ChatHost.java +++ b/src/main/java/org/sobotics/chatexchange/chat/ChatHost.java @@ -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; + } } /** @@ -33,6 +47,13 @@ public String getBaseUrl() { } /** + * @return Host that is used for the login + */ + public String getLoginHost() { + return this.loginHost; + } + + /** * Compares the host to another object * @param otherHost other object * @return true, if the name is the same diff --git a/src/main/java/org/sobotics/chatexchange/chat/ChatLoginException.java b/src/main/java/org/sobotics/chatexchange/chat/ChatLoginException.java new file mode 100644 index 0000000..8935c2c --- /dev/null +++ b/src/main/java/org/sobotics/chatexchange/chat/ChatLoginException.java @@ -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(); + } +} diff --git a/src/main/java/org/sobotics/chatexchange/chat/StackExchangeClient.java b/src/main/java/org/sobotics/chatexchange/chat/StackExchangeClient.java index ef9cf97..1d88747 100644 --- a/src/main/java/org/sobotics/chatexchange/chat/StackExchangeClient.java +++ b/src/main/java/org/sobotics/chatexchange/chat/StackExchangeClient.java @@ -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"); @@ -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 @@ -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 Room 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) { @@ -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()); } }