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()
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)
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()
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()
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)
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)