def init(username, password, try_cookies=True): global _clients global _rooms global _room_data global _last_messages for site in _clients.keys(): client = Client(site) logged_in = False if try_cookies: if GlobalVars.cookies is None: datahandling._remove_pickle("cookies.p") GlobalVars.cookies = {} else: cookies = GlobalVars.cookies try: if site in cookies and cookies[site] is not None: client.login_with_cookie(cookies[site]) logged_in = True log('debug', 'Logged in using cached cookies') except LoginError as e: exc_type, exc_obj, exc_tb = sys.exc_info() log('debug', 'Login error {}: {}'.format(exc_type.__name__, exc_obj)) log('debug', 'Falling back to credential-based login') del cookies[site] datahandling.dump_cookies() if not logged_in: for retry in range(3): try: GlobalVars.cookies[site] = client.login(username, password) break except Exception as e: exc_type, exc_obj, exc_tb = sys.exc_info() log('debug', 'Login error {}: {}'.format(exc_type.__name__, exc_obj)) else: raise Exception("Failed to log into " + site + ", max retries exceeded") _clients[site] = client if os.path.exists("rooms_custom.yml"): parse_room_config("rooms_custom.yml") else: parse_room_config("rooms.yml") if not GlobalVars.standby_mode: join_command_rooms() if os.path.isfile("messageData.p"): try: _last_messages = pickle.load(open("messageData.p", "rb")) except EOFError: pass threading.Thread(name="pickle ---rick--- runner", target=pickle_last_messages, daemon=True).start() threading.Thread(name="message sender", target=send_messages, daemon=True).start() if try_cookies: datahandling.dump_cookies()
def init(username, password, try_cookies=True): global _clients global _rooms global _room_data global _last_messages for site in _clients.keys(): client = Client(site) logged_in = False if try_cookies: if GlobalVars.cookies is None: datahandling.remove_pickle("cookies.p") GlobalVars.cookies = {} else: cookies = GlobalVars.cookies try: if site in cookies and cookies[site] is not None: try: # This implements a quick login to only chat using the existing cookies. It doesn't # require accessing main SE sites, so should be available when SE is in read-only mode. # Ideally, we'll update ChatExchange with something similar. client._br.session.cookies.update(cookies[site]) # client.get_me() will raise an exception if the cookies don't work. me = client.get_me() if me.id > 0: client.logged_in = True logged_in = True log( 'debug', 'chat.{}: Logged in to chat only using cached cookies' .format(site)) except Exception: # This is a fallback using the ChatExchange functionality we've been using for a long time. log( 'debug', 'chat.{}: chat-only login failed. Falling back to normal cookies' .format(site)) client.login_with_cookie(cookies[site]) logged_in = True log( 'debug', 'chat.{}: Logged in using cached cookies'. format(site)) except LoginError as e: exc_type, exc_obj, exc_tb = sys.exc_info() log( 'debug', 'chat.{}: Login error {}: {}'.format( site, exc_type.__name__, exc_obj)) log( 'debug', 'chat.{}: Falling back to credential-based login'. format(site)) # Instead of deleting the cookies, start with a clean slate of a new client. client = Client(site) if not logged_in: for retry in range(3): try: GlobalVars.cookies[site] = client.login(username, password) break except Exception as e: exc_type, exc_obj, exc_tb = sys.exc_info() log( 'debug', 'chat.{}: Login error {}: {}'.format( site, exc_type.__name__, exc_obj)) if exc_type.__name__ == 'LoginError' and str( exc_obj) == 'fkey input not found': # ChatExchange didn't find the `fkey` <input> in the SE login page. Under most operating # conditions, this means that we've either lost connectivity to SE entirely or SE # is in read-only mode and isn't accepting login attempts. Under those conditions, # there's nothing which we or SD can do other than wait for SE to resolve the issue. # So, instead of spinning the CPU hard in order to retry at the maximum rate, we delay a bit. # The situations where the problem is on our end rather than on SE's end tend sleep_time = 30 * (retry + 1) log( 'warning', 'Login to SE appears unavailable. Can be caused by: SD config issue,' + ' bad network connection, or Stack Exchange is down/read-only.' + ' Sleeping for {} seconds.'.format(sleep_time)) time.sleep(sleep_time) else: raise Exception("Failed to log into " + site + ", max retries exceeded") _clients[site] = client if os.path.exists("rooms_custom.yml"): parse_room_config("rooms_custom.yml") else: parse_room_config("rooms.yml") if not GlobalVars.standby_mode: join_command_rooms() if datahandling.has_pickle("messageData.p"): try: _last_messages = datahandling.load_pickle("messageData.p") except EOFError: pass threading.Thread(name="pickle ---rick--- runner", target=pickle_last_messages, daemon=True).start() threading.Thread(name="message sender", target=send_messages, daemon=True).start() if try_cookies: datahandling.dump_cookies()