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()
Exemple #2
0
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()
Exemple #3
0
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()