package me.corriekay.pokegoutil.data.managers; import com.pokegoapi.api.PokemonGo; import com.pokegoapi.api.player.PlayerProfile; import com.pokegoapi.auth.CredentialProvider; import com.pokegoapi.auth.GoogleUserCredentialProvider; import com.pokegoapi.auth.PtcCredentialProvider; import com.pokegoapi.exceptions.CaptchaActiveException; import com.pokegoapi.exceptions.LoginFailedException; import com.pokegoapi.exceptions.RemoteServerException; import com.pokegoapi.exceptions.hash.HashException; import me.corriekay.pokegoutil.data.enums.LoginType; import me.corriekay.pokegoutil.data.models.BpmResult; import me.corriekay.pokegoutil.data.models.LoginData; import me.corriekay.pokegoutil.data.models.PlayerAccount; import me.corriekay.pokegoutil.utils.ConfigKey; import me.corriekay.pokegoutil.utils.ConfigNew; import me.corriekay.pokegoutil.utils.helpers.LoginHelper; import okhttp3.OkHttpClient; /** * This controller does the login/log off, and different account information (aka player data). */ public final class AccountManager { private static AccountManager instance; private final ConfigNew config = ConfigNew.getConfig(); private PokemonGo go; private PlayerAccount playerAccount; public static AccountManager getInstance() { if (instance == null) { instance = new AccountManager(); // DO any required initialization stuff here } return instance; } private AccountManager() { } /** * Deletes the specified LoginType from the config.json. * <p> * <p>Also SaveAuth settings will be deleted * * @param type the LoginType to be removed */ private void deleteLoginData(final LoginType type) { deleteLoginData(type, true); } /** * Deletes the specific LoginType from config.json. If deleteSaveAuth is true, SaveAuth settings will be deleted * * @param type the LoginType to be removed * @param deleteSaveAuth if true, SaveAuth will be deleted */ private void deleteLoginData(final LoginType type, final boolean deleteSaveAuth) { if (deleteSaveAuth) { config.delete(ConfigKey.LOGIN_SAVE_AUTH); } switch (type) { case ALL: config.delete(ConfigKey.LOGIN_GOOGLE_AUTH_TOKEN); config.delete(ConfigKey.LOGIN_GOOGLE_APP_USERNAME); config.delete(ConfigKey.LOGIN_GOOGLE_APP_PASSWORD); config.delete(ConfigKey.LOGIN_PTC_USERNAME); config.delete(ConfigKey.LOGIN_PTC_PASSWORD); break; case GOOGLE_AUTH: config.delete(ConfigKey.LOGIN_GOOGLE_AUTH_TOKEN); break; case GOOGLE_APP_PASSWORD: config.delete(ConfigKey.LOGIN_GOOGLE_APP_USERNAME); config.delete(ConfigKey.LOGIN_GOOGLE_APP_PASSWORD); break; case PTC: config.delete(ConfigKey.LOGIN_PTC_USERNAME); config.delete(ConfigKey.LOGIN_PTC_PASSWORD); break; default: } } public LoginData getLoginData() { final LoginData loginData = new LoginData( config.getString(ConfigKey.LOGIN_PTC_USERNAME), config.getString(ConfigKey.LOGIN_PTC_PASSWORD), config.getString(ConfigKey.LOGIN_GOOGLE_AUTH_TOKEN)); if (loginData.isValidGoogleLogin()) { loginData.setSavedToken(true); } return loginData; } /** * Returns the logged in playerAccount. * * @return the logged in playerAccount */ public PlayerAccount getPlayerAccount() { return playerAccount; } public PlayerProfile getPlayerProfile() { return go != null ? go.getPlayerProfile() : null; } private void initOtherControllers() { InventoryManager.initialize(go); PokemonBagManager.initialize(go); ProfileManager.initialize(go); } /** * Login to Pokemon Go with the login data. * * @param loginData the login data used to login * @return results of the login */ public BpmResult login(final LoginData loginData) { switch (loginData.getLoginType()) { case GOOGLE_AUTH: if (loginData.isValidGoogleLogin()) { return logOnGoogleAuth(loginData); } break; case PTC: if (loginData.isValidPtcLogin()) { return logOnPtc(loginData); } break; default: } return new BpmResult("Invalid Login Type"); } /** * Login using GoogleAuth. * * @param loginData the login data used to login * @return results of the login */ private BpmResult logOnGoogleAuth(final LoginData loginData) { OkHttpClient http; CredentialProvider cp; http = new OkHttpClient(); final String authCode = loginData.getToken(); final boolean saveAuth = config.getBool(ConfigKey.LOGIN_SAVE_AUTH); boolean shouldRefresh = false; if (loginData.isSavedToken() && saveAuth) { shouldRefresh = true; } try { final GoogleUserCredentialProvider provider; if (shouldRefresh) { provider = new GoogleUserCredentialProvider(http, authCode); } else { provider = new GoogleUserCredentialProvider(http); provider.login(authCode); } if (provider.isTokenIdExpired()) { throw new LoginFailedException(); } cp = provider; if (saveAuth && !shouldRefresh) { config.setString(ConfigKey.LOGIN_GOOGLE_AUTH_TOKEN, provider.getRefreshToken()); } else if (!saveAuth) { deleteLoginData(LoginType.GOOGLE_AUTH); } } catch (LoginFailedException | RemoteServerException | CaptchaActiveException e) { deleteLoginData(LoginType.GOOGLE_APP_PASSWORD); return new BpmResult(e.getMessage()); } try { prepareLogin(cp, http); return new BpmResult(); } catch (LoginFailedException | RemoteServerException | CaptchaActiveException | HashException e) { deleteLoginData(LoginType.ALL); return new BpmResult(e.getMessage()); } } /** * Login using PTC. * * @param loginData the login data used to login * @return results of the login */ private BpmResult logOnPtc(final LoginData loginData) { OkHttpClient http; CredentialProvider cp; http = new OkHttpClient(); final String username = loginData.getUsername(); final String password = loginData.getPassword(); final boolean saveAuth = config.getBool(ConfigKey.LOGIN_SAVE_AUTH); try { cp = new PtcCredentialProvider(http, username, password); config.setString(ConfigKey.LOGIN_PTC_USERNAME, username); if (saveAuth) { config.setString(ConfigKey.LOGIN_PTC_PASSWORD, password); } else { deleteLoginData(LoginType.PTC); } } catch (LoginFailedException | RemoteServerException | CaptchaActiveException e) { deleteLoginData(LoginType.PTC); return new BpmResult(e.getMessage()); } try { prepareLogin(cp, http); return new BpmResult(); } catch (LoginFailedException | RemoteServerException | CaptchaActiveException | HashException e) { deleteLoginData(LoginType.ALL); return new BpmResult(e.getMessage()); } } /** * Do login process and initialize GUI. * * @param cp contains the credential provider * @param http http client * @throws LoginFailedException login failed * @throws RemoteServerException server error * @throws CaptchaActiveException captcha active error * @throws HashException */ private void prepareLogin(final CredentialProvider cp, final OkHttpClient http) throws LoginFailedException, RemoteServerException, CaptchaActiveException, HashException { go = new PokemonGo(http); LoginHelper.login(go, cp, api -> { playerAccount = new PlayerAccount(go.getPlayerProfile()); initOtherControllers(); }); } /** * The value will be saved for saveAuth in config.json. * * @param shouldSave settings for saveAuth */ public void setSaveLogin(final boolean shouldSave) { config.setBool(ConfigKey.LOGIN_SAVE_AUTH, shouldSave); } }