Example #1
0
def load():
    global client, room

    client = Client("stackexchange.com")
    client.login(email, password)

    room = client.get_room(room_num)

    def f():
        room.join()
        room.watch(on_se_chat_message)

    GameThread(target=f).start()
Example #2
0
def start():
    client = Client("stackexchange.com")
    client.login(os.environ["USER"], os.environ["PASS"])

    room = client.get_room(config.room_id)

    _post_lines(room, config.preamble)

    skip_state.wait(config.preamble_time)
    skip_state.clear()

    while _voice_next(room):
        _change_state(EventState.DISCUSSION)

        if not skip_state.wait(config.discussion_time - 60):
            _post_lines(room, config.warning)

            skip_state.wait(60)
            skip_state.clear()

    _change_state(EventState.END)
    _post_lines(room, config.finale)
Example #3
0
    def test_se_message_echo(host_id, room_id):
        """
        Tests that we are able to send a message, and recieve it back,
        send a reply, and recieve that back, within a reasonable amount
        of time.

        This is a lot of complexity for a single test, but we don't want
        to flood Stack Exchange with more test messages than necessary.
        """

        client = Client(host_id)
        client.login(live_testing.email, live_testing.password)

        timeout_duration = 60

        pending_events = Queue.Queue()

        def get_event(predicate):
            """
            Waits until it has seen a message passing the specified
            predicate from both polling and sockets.

            Asserts that it has not waited longer than the specified
            timeout, and asserts that the events from difference sources
            have the same ID.

            This may dequeue any number of additional unrelated events
            while it is running, so it's not appropriate if you are
            trying to wait for multiple events at once.
            """

            socket_event = None
            polling_event = None

            timeout = time.time() + timeout_duration

            while not (socket_event and polling_event) and time.time() < timeout:
                try:
                    is_socket, event = pending_events.get(timeout=1)
                except Queue.Empty:
                    continue

                if predicate(event):
                    logger.info("Expected event (is_socket==%r): %r", is_socket, event)
                    if is_socket:
                        assert socket_event is None
                        socket_event = event
                    else:
                        assert polling_event is None
                        polling_event = event
                else:
                    logger.debug("Unexpected events: %r", event)

            assert socket_event and polling_event
            assert type(socket_event) is type(polling_event)
            assert socket_event.id == polling_event.id

            return socket_event

        logger.debug("Joining chat")

        room = client.get_room(room_id)

        room.join()

        room.watch_polling(lambda event, _: pending_events.put((False, event)), 5)
        room.watch_socket(lambda event, _: pending_events.put((True, event)))

        time.sleep(2)  # Avoid race conditions

        test_message_nonce = uuid.uuid4().hex
        test_message_content = TEST_MESSAGE_FORMAT.format(test_message_nonce)

        logger.debug("Sending test message")
        room.send_message(test_message_content)

        @get_event
        def test_message_posted(event):
            return isinstance(event, events.MessagePosted) and test_message_nonce in event.content

        logger.debug("Observed test edit")

        test_reply_nonce = uuid.uuid4().hex
        test_reply_content = TEST_MESSAGE_FORMAT.format(test_reply_nonce)

        logger.debug("Sending test reply")
        test_message_posted.message.reply(test_reply_content)

        # XXX: The limitations of get_event don't allow us to also
        # XXX: look for the corresponding MessagePosted event.
        @get_event
        def test_reply(event):
            return isinstance(event, events.MessageReply) and test_reply_nonce in event.content

        logger.debug("Observed test reply")

        assert test_reply.parent_message_id == test_message_posted.message.id
        assert test_reply.message.parent.id == test_reply.parent_message_id
        assert test_message_posted.message.id == test_message_posted.message.id
        assert test_reply.message.parent is test_message_posted.message

        # unsafe - html content is unstable; may be inconsistent between views
        # assert test_reply.message.parent.content == test_message_posted.content

        test_edit_nonce = uuid.uuid4().hex
        test_edit_content = TEST_MESSAGE_FORMAT.format(test_edit_nonce)

        logger.debug("Sending test edits")

        # Send a lot of edits in a row, to ensure we don't lose any
        # from throttling being ignored.
        test_message_posted.message.edit("**this is a** test edit and should be edited again")
        test_message_posted.message.edit("this is **another test edit** and should be edited again")
        test_message_posted.message.edit("this is **yet** another test edit and **should be edited again**")
        test_message_posted.message.edit(test_edit_content)

        @get_event
        def test_edit(event):
            return isinstance(event, events.MessageEdited) and test_edit_nonce in event.content

        logger.debug("Observed final test edit")

        assert test_message_posted.message is test_edit.message
        assert test_edit.message.id == test_message_posted.message.id
        assert test_edit.message.edits == 4
        assert test_edit.message.content_source == test_edit_content

        # it should be safe to assume that there isn't so much activity
        # that these events will have been flushed out of recent_events.
        assert test_message_posted in client._recently_gotten_objects
        assert test_reply in client._recently_gotten_objects
        assert test_edit in client._recently_gotten_objects

        client.logout()
Example #4
0
    def test_se_message_echo(host_id, room_id):
        """
        Tests that we are able to send a message, and recieve it back,
        send a reply, and recieve that back, within a reasonable amount
        of time.

        This is a lot of complexity for a single test, but we don't want
        to flood Stack Exchange with more test messages than necessary.
        """

        client = Client(host_id)
        client.login(live_testing.email, live_testing.password)

        timeout_duration = 60

        pending_events = queue.Queue()

        def get_event(predicate):
            """
            Waits until it has seen a message passing the specified
            predicate from both polling and sockets.

            Asserts that it has not waited longer than the specified
            timeout, and asserts that the events from difference sources
            have the same ID.

            This may dequeue any number of additional unrelated events
            while it is running, so it's not appropriate if you are
            trying to wait for multiple events at once.
            """

            socket_event = None
            polling_event = None

            timeout = time.time() + timeout_duration

            while (not (socket_event and polling_event)
                   and time.time() < timeout):
                try:
                    is_socket, event = pending_events.get(timeout=1)
                except queue.Empty:
                    continue

                if predicate(event):
                    logger.info("Expected event (is_socket==%r): %r",
                                is_socket, event)
                    if is_socket:
                        assert socket_event is None
                        socket_event = event
                    else:
                        assert polling_event is None
                        polling_event = event
                else:
                    logger.debug("Unexpected events: %r", event)

            assert socket_event and polling_event
            assert type(socket_event) is type(polling_event)
            assert socket_event.id == polling_event.id

            return socket_event

        logger.debug("Joining chat")

        room = client.get_room(room_id)

        room.join()

        room.watch_polling(lambda event, _: pending_events.put((False, event)),
                           5)
        room.watch_socket(lambda event, _: pending_events.put((True, event)))

        time.sleep(2)  # Avoid race conditions

        test_message_nonce = uuid.uuid4().hex
        test_message_content = TEST_MESSAGE_FORMAT.format(test_message_nonce)

        logger.debug("Sending test message")
        room.send_message(test_message_content)

        @get_event
        def test_message_posted(event):
            return (isinstance(event, events.MessagePosted)
                    and test_message_nonce in event.content)

        logger.debug("Observed test edit")

        test_reply_nonce = uuid.uuid4().hex
        test_reply_content = TEST_MESSAGE_FORMAT.format(test_reply_nonce)

        logger.debug("Sending test reply")
        test_message_posted.message.reply(test_reply_content)

        # XXX: The limitations of get_event don't allow us to also
        # XXX: look for the corresponding MessagePosted event.
        @get_event
        def test_reply(event):
            return (isinstance(event, events.MessageReply)
                    and test_reply_nonce in event.content)

        logger.debug("Observed test reply")

        assert test_reply.parent_message_id == test_message_posted.message.id
        assert test_reply.message.parent.id == test_reply.parent_message_id
        assert test_message_posted.message.id == test_message_posted.message.id
        assert test_reply.message.parent is test_message_posted.message

        # unsafe - html content is unstable; may be inconsistent between views
        # assert test_reply.message.parent.content == test_message_posted.content

        test_edit_nonce = uuid.uuid4().hex
        test_edit_content = TEST_MESSAGE_FORMAT.format(test_edit_nonce)

        logger.debug("Sending test edits")

        # Send a lot of edits in a row, to ensure we don't lose any
        # from throttling being ignored.
        test_message_posted.message.edit(
            "**this is a** test edit and should be edited again")
        test_message_posted.message.edit(
            "this is **another test edit** and should be edited again")
        test_message_posted.message.edit(
            "this is **yet** another test edit and **should be edited again**")
        test_message_posted.message.edit(test_edit_content)

        @get_event
        def test_edit(event):
            return (isinstance(event, events.MessageEdited)
                    and test_edit_nonce in event.content)

        logger.debug("Observed final test edit")

        assert test_message_posted.message is test_edit.message
        assert test_edit.message.id == test_message_posted.message.id
        assert test_edit.message.edits == 4
        assert test_edit.message.content_source == test_edit_content

        # it should be safe to assume that there isn't so much activity
        # that these events will have been flushed out of recent_events.
        assert test_message_posted in client._recently_gotten_objects
        assert test_reply in client._recently_gotten_objects
        assert test_edit in client._recently_gotten_objects

        client.logout()
Example #5
0
def main():
    """
    Main thread of the bot
    """

    debug_mode = False

    #Get config for the mode (debug/prod)
    try:
        if sys.argv[1] == "--debug":
            print("Using debug config.")
            utils.config = Struct(**config.debug_config)
            debug_mode = True
        else:
            raise IndexError
    except IndexError:
        print(
            "Using productive config. \nIf you intended to use the debug config, use the '--debug' command line option"
        )
        utils.config = Struct(**config.prod_config)

    #Set version
    utils.config.botVersion = "v1.0.0"

    #Initialize SE API class instance
    utils.se_api = stackexchange_api.se_api(utils.config.stackExchangeApiKey)

    try:
        #Login and connection to chat
        print("Logging in and joining chat room...")
        utils.room_number = utils.config.room
        client = Client(utils.config.chatHost)
        client.login(utils.config.email, utils.config.password)
        utils.client = client
        room = client.get_room(utils.config.room)
        try:
            room.join()
        except ValueError as e:
            if str(e).startswith(
                    "invalid literal for int() with base 10: 'login?returnurl=http%3a%2f%2fchat.stackoverflow.com%2fchats%2fjoin%2ffavorite"
            ):
                raise chatexchange.browser.LoginError(
                    "Too many recent logins. Please wait a bit and try again.")

        room.watch_socket(on_message)
        print(room.get_current_user_names())
        utils.room_owners = room.owners

        main_logger.info(
            f"Joined room '{room.name}' on {utils.config.chatHost}")

        #Redunda pining
        stop_redunda = threading.Event()
        redunda_thread = redunda.RedundaThread(stop_redunda, utils.config,
                                               main_logger)
        redunda_thread.start()

        if debug_mode:
            room.send_message(
                f"[ [Hermes](https://git.io/fNmlf) ] {utils.config.botVersion} started in debug mode on {utils.config.botOwner}/{utils.config.botMachine}."
            )
        else:
            room.send_message(
                f"[ [Hermes](https://git.io/fNmlf) ] {utils.config.botVersion} started on {utils.config.botOwner}/{utils.config.botMachine}."
            )

        while True:
            message = input()

            if message in ["restart", "reboot"]:
                os._exit(1)
            else:
                room.send_message(message)

    except KeyboardInterrupt:
        os._exit(0)
    except BaseException as e:
        print(e)
        os._exit(1)
Example #6
0
def main():
    """
    Main thread of the bot
    """
    debug_mode = False

    #Get config for the mode (debug/prod)
    try:
        if sys.argv[1] == "--debug":
            print("Using debug config.")
            utils.config = Struct(**config.debug_config)
            debug_mode = True
        else:
            raise IndexError
    except IndexError:
        print(
            "Using productive config. \nIf you intended to use the debug config, use the '--debug' command line option"
        )
        utils.config = Struct(**config.prod_config)

    #Set version
    utils.config.botVersion = "v2.5.0"

    #Initialize SE API class instance
    utils.se_api = stackexchange_api.se_api(utils.config.stackExchangeApiKey)

    try:
        #Login and connection to chat
        print("Logging in and joining chat room...")
        utils.room_number = utils.config.room
        client = Client(utils.config.chatHost)
        client.login(utils.config.email, utils.config.password)
        utils.client = client
        room = client.get_room(utils.config.room)
        try:
            room.join()
        except ValueError as e:
            if str(e).startswith(
                    "invalid literal for int() with base 10: 'login?returnurl"
            ) or str(e).startswith("failed to get "):
                raise chatexchange.browser.LoginError(
                    "Too many recent logins. Please wait a bit and try again.")

        try:
            room.watch_polling(on_message, 3)
        except (BaseException, HTTPError) as e:
            main_logger.error(e)
            main_logger.error(
                "Recovered from above exception, trying to reboot...")
            os._exit(1)

        print(room.get_current_user_names())
        utils.room_owners = room.owners

        main_logger.info(
            f"Joined room '{room.name}' on {utils.config.chatHost}")

        #Initialize Firebase database
        if os.path.isfile("./service_account_key.json"):
            cred = credentials.Certificate("./service_account_key.json")
            firebase_admin.initialize_app(cred, {
                'databaseURL':
                "https://rankoverflow-56959.firebaseio.com/",
            })

        #Automated flag checking
        thread_list = []

        try:
            stop_auto_checking_lp = threading.Event()
            auto_check_lp_thread = fac.AutoFlagThread(stop_auto_checking_lp,
                                                      utils, 0, room,
                                                      thread_list)
            auto_check_lp_thread.start()
            thread_list.append(auto_check_lp_thread)
        except BaseException as e:
            print(e)
            main_logger.error(f"CRITICAL ERROR: {e}")

        try:
            stop_auto_checking_hp = threading.Event()
            auto_check_hp_thread = fac.AutoFlagThread(stop_auto_checking_hp,
                                                      utils, 1, None,
                                                      thread_list)
            auto_check_hp_thread.start()
            thread_list.append(auto_check_hp_thread)
        except BaseException as e:
            print(e)
            main_logger.error(f"CRITICAL ERROR: {e}")

        #Redunda pinging
        if debug_mode:
            room.send_message(
                f"[ [CheckYerFlags](https://stackapps.com/q/7792) ] {utils.config.botVersion} started in debug mode on {utils.config.botOwner}/{utils.config.botMachine}."
            )
        else:
            stop_redunda = threading.Event()
            redunda_thread = redunda.RedundaThread(stop_redunda, utils.config,
                                                   main_logger)
            redunda_thread.start()
            room.send_message(
                f"[ [CheckYerFlags](https://stackapps.com/q/7792) ] {utils.config.botVersion} started on {utils.config.botOwner}/{utils.config.botMachine}."
            )

        while True:
            message = input()

            if message in ["restart", "reboot"]:
                os._exit(1)
            else:
                room.send_message(message)

    except KeyboardInterrupt:
        os._exit(0)
    except BaseException as e:
        print(e)
        os._exit(1)