def __init__(self, clients, msg_writer, markov_chain): self.clients = clients self.msg_writer = msg_writer self.markov_chain = markov_chain self.channel_manager = ChannelManager(clients) self.random_manager = ResourceManager('random_comments.txt') self.trigger_startup_log() self.process_recent_messages()
def __init__(self, slack_clients): self.clients = slack_clients self.loud_manager = LoudManager() self.whos_that_pokemon_manager = WhosThatPokemonManager() self.hogwarts_house_sorter = HogwartsHouseSorter() self.equation_manager = EquationManager() self.explanation_manager = ResourceManager('explanations.txt') self.drawing_manager = ResourceManager('draw_me.txt') self.forever_manager = ResourceManager('forever.txt') self.help_manager = ResourceManager('help_text.txt') self.sass_manager = ResourceManager('sass.txt') self.channel_manager = ChannelManager(slack_clients)
def initialize(): """ Initializes the application and checks if the channels need updated. """ load_variables() Files.initialize() ChannelManager.initialize() if datastore.should_update_template(): datastore.fetch() ChannelManager.load_from_config(Config.get())
def __init__(self, token): self.token = token # Slacker is a Slack Web API Client self.web = Slacker(token) # SlackClient is a Slack Websocket RTM API Client self.rtm = SlackClient(token) self.msg_writer = Messenger(self) self.channel_manager = ChannelManager(self) # Set up bot_id self.bot_id = None self.startUp()
def __init__(self, slack_clients, msg_writer, markov_chain): self.clients = slack_clients self.msg_writer = msg_writer self.game_manager = GameManager(self.msg_writer) self.user_manager = UserManager(self.clients, self.msg_writer) self.tictactoe_manager = TicTacToeManager( self.msg_writer, self.user_manager, self.game_manager ) self.response_master = Response_master(self.msg_writer) self.user_manager = UserManager(self.clients, self.msg_writer) self.rude_manager = RudeManager(self.msg_writer) self.channel_manager = ChannelManager(slack_clients) self.markov_chain = markov_chain markov_files = ['hpOne.txt', 'lotrOne.txt', 'memoriesOfIce.txt'] self.lotrMarkov = Markov(2, msg_writer, markov_files)
def __init__(self, clients, msg_writer, markov_chain): self.clients = clients self.msg_writer = msg_writer self.markov_chain = markov_chain self.channel_manager = ChannelManager(clients) self.trigger_startup_log() self.process_recent_messages()
def __init__(self, clients, msg_writer, markov_chain): self.clients = clients self.msg_writer = msg_writer self.markov_chain = markov_chain self.channel_manager = ChannelManager(clients) self.random_manager = ResourceManager('random_comments.txt') self.trigger_startup_log() self.process_recent_messages() self.news_links = NewsManager()
def __init__(self, slack_clients): self.clients = slack_clients self.loud_manager = LoudManager() self.whos_that_pokemon_manager = WhosThatPokemonManager() self.equation_manager = EquationManager() self.explanation_manager = ResourceManager('explanations.txt') self.help_manager = ResourceManager('help_text.txt') self.sass_manager = ResourceManager('sass.txt') self.channel_manager = ChannelManager(slack_clients)
def __init__(self, slack_clients, msg_writer, markov_chain): self.clients = slack_clients self.msg_writer = msg_writer self.game_manager = GameManager(self.msg_writer) self.user_manager = UserManager(self.clients, self.msg_writer) self.response_master = Response_master(self.msg_writer) self.user_manager = UserManager(self.clients, self.msg_writer) self.channel_manager = ChannelManager(slack_clients) self.markov_chain = markov_chain
def scan_run(): """ Main loop of the application. Runs all channels, sleeps until next channel run time, and checks for channel updates if the interval is up. """ # Run all channels and then sleep until the next channel should run while running: if should_upload: wait_time = ChannelManager.run_channels() time.sleep(wait_time) else: time.sleep(5)
def __init__(self, slack_clients): self.clients = slack_clients self.loud_manager = LoudManager() self.whos_that_pokemon_manager = WhosThatPokemonManager() self.hogwarts_house_sorter = HogwartsHouseSorter() self.equation_manager = EquationManager() self.explanation_manager = ResourceManager('explanations.txt') self.drawing_manager = ResourceManager('draw_me.txt') self.forever_manager = ResourceManager('forever.txt') self.help_manager = ResourceManager('help_text.txt') self.sass_manager = ResourceManager('sass.txt') self.channel_manager = ChannelManager(slack_clients) self.news_links = NewsManager()
class Messenger(object): def __init__(self, slack_clients): self.clients = slack_clients self.loud_manager = LoudManager() self.whos_that_pokemon_manager = WhosThatPokemonManager() self.hogwarts_house_sorter = HogwartsHouseSorter() self.equation_manager = EquationManager() self.explanation_manager = ResourceManager('explanations.txt') self.drawing_manager = ResourceManager('draw_me.txt') self.forever_manager = ResourceManager('forever.txt') self.help_manager = ResourceManager('help_text.txt') self.sass_manager = ResourceManager('sass.txt') self.channel_manager = ChannelManager(slack_clients) self.news_links = NewsManager() def erase_history(self, msg_text, channel_id, now_timestamp): try: tokens = re.findall('[0-9]+', msg_text) delete_num = int(tokens[0]) count = 0 response = self.clients.get_message_history(channel_id) if 'messages' in response: for message in response['messages']: if ( 'ts' in message and 'pinned_to' not in message and self.clients.is_message_from_me(message) and not re.search(DONT_DELETE, message['text'].lower()) ): response = self.clients.delete_message( channel_id, message['ts'] ) count += 1 if count >= delete_num: break if count < delete_num: msg = ("Erased " + str(count) + " messages: I " "can only see the 100 most recent messages") self.send_message(msg, channel_id) except Exception: msg = "Correct usage is `zac erase <num>`" self.send_message(msg, channel_id) pass def __del__(self): closing_msgs = ["No!! Don't kill me! I want to live!", "Good BYEEE!!!", "I'm dying again :sob:", "Have you gotten tired of this face :zacefron: ?"] txt = random.choice(closing_msgs) self.send_message(txt) def send_slow_message_as_other(self, msg_text, channel, username, emoji): self.send_message_as_other( msg_text, channel, username, emoji, slow=True ) def send_message_as_other( self, msg_text, channel, username, emoji, slow=False ): msg_text = msg_text.replace('&', "&") channel = self.channel_manager.get_channel_id(channel) if (slow): self.clients.send_user_typing_pause(channel) return self.clients.send_message_as_other( msg_text, channel, username, emoji ) def write_slow(self, msg_text, channel=None): return self.send_message(msg_text, channel, slow=True) def send_message( self, msg_text, channel=None, slow=False, react_emoji=None ): msg_text = msg_text.replace('&', "&") msg_text = msg_text.replace('"', "\"") # channel = self.channel_manager.get_channel_id(channel) if channel is None: channel = TESTING_CHANNEL if slow is True: self.clients.send_user_typing_pause(channel) response = self.clients.send_message(msg_text, channel) if 'ok' in response and react_emoji is not None: self.send_reaction(react_emoji, channel, response['ts']) return response def update_message( self, updated_msg_text, ts, channel=None, slow=False, react_emoji=None ): updated_msg_text = updated_msg_text.replace('&', "&") channel = self.channel_manager.get_channel_id(channel) if channel is None: channel = TESTING_CHANNEL if slow is True: self.clients.send_user_typing_pause(channel) response = self.clients.update_message( updated_msg_text, channel, ts ) if 'ok' in response and react_emoji is not None: self.send_reaction(react_emoji, channel, response['ts']) return response def send_attachment(self, txt, channel_id, attachment): self.clients.send_attachment(txt, channel_id, attachment) def write_error(self, err_msg, channel_id=None): txt = (":face_with_head_bandage: my maker didn't handle this error " "very well:\n>```{}```").format(err_msg) self.send_message(txt, channel_id) def send_reaction(self, emoji_name, channel_id, timestamp): self.clients.send_reaction(emoji_name, channel_id, timestamp) def get_emoji(self): return self.clients.get_random_emoji() def write_message_deleted(self, channel_id): # Dont post if messages were deleted inside of #zac-testing if channel_id != self.channel_manager.get_channel_id('zac-testing'): txt = ("I SAW THAT! _Someone_ deleted a message from channel: " "<#{}>").format(channel_id) self.send_message(txt) def write_left_channel(self, channel_id): self.send_message('...well THAT was something', channel_id) def write_joined_channel(self, channel_id, user_id): if channel_id == self.channel_manager.get_channel_id('zac-testing'): txt = ("Hey <@{}>! Welcome to the Testing (aka the Weather) " "channel. Please MUTE this channel or be inundaded with " "notifications!").format(user_id) self.write_slow(txt, channel_id) self.write_xkcd("15", channel_id) else: self.write_greeting(channel_id, user_id) def write_help_message(self, channel_id): help_txt = self.help_manager.get_all() count = self.help_manager.get_count() txt = ( "I'm Zac. I'll *_respond_* to the following {} commands:\n{}" ).format(count-1, help_txt) info_text = ( "Hi, I'm Zac Efron. You can find out more information about me " "in #zac-testing. Merci :zacefron:" ) self.write_slow(info_text, channel_id) self.write_slow(txt, 'zac-testing') def write_french(self, msg_text, channel_id): target = get_target(FRENCH_FLAG, msg_text).replace('_', '') self.write_slow('_le {}_'.format(target), channel_id) def write_greeting(self, channel_id, user_id): greetings = ['Hi', 'Hello', 'Nice to meet you', 'Howdy', 'Salutations'] txt = '{}, <@{}>!'.format(random.choice(greetings), user_id) self.write_slow(txt, channel_id) def write_spelling_mistake(self, channel_id, timestamp): emoji_name = "spelft_it_wronbg_again_i_see" self.send_reaction(emoji_name, channel_id, timestamp) def write_prompt(self, channel_id): bot_uid = self.clients.bot_user_id() txt = ("I'm sorry, I didn't quite understand... Can I help you? " "(e.g. `<@" + bot_uid + "> help`)") self.write_slow(txt, channel_id) def write_joke(self, channel_id): # answer = ( # "Wenn ist das Nunstück git und Slotermeyer? Ja! Beiherhund das " # "Oder die Flipperwaldt gersput!" # ) url = "http://api.icndb.com/jokes/random" answer = requests.get(url).json()['value']['joke'] self.write_slow(answer, channel_id) def write_encouragement(self, msg_text, channel_id): encouragements = [ "Get your shit together", "You can do it", "I'm here for you", "Do you just think about yourself", "You're the best", ] target = get_target(ENCOURAGE_FLAG, msg_text) txt = '{} {}'.format(random.choice(encouragements), target) self.write_slow(txt, channel_id) def write_cast_pokemon(self, lower_msg_text, channel_id): pkmn = pokemon_i_choose_you(lower_msg_text) if pkmn is not None: self.send_message(pkmn, channel_id) def write_whos_that_pokemon(self, channel_id): txt = self.whos_that_pokemon_manager.whos_that_pkmn() self.send_message(txt, channel_id) def write_pokemon_guessed_response(self, msg_text, channel_id, user_id): text = self.whos_that_pokemon_manager.check_response(user_id, msg_text) if text is not None: self.send_message(text, channel_id) def write_sad(self, channel_id): txt = "I'm crying into my tea. :joy:" attachment = { "pretext": "This always cracks me up. :wink:", "title": "/giphy bloopin", "title_link": ("http://giphy.com/gifs/friday-rebecca-black-hurrr-" "13FsSYo3fzfT2g"), "text": txt, "fallback": txt, "image_url": "http://i.giphy.com/13FsSYo3fzfT2g.gif", "color": "#7CD197", } self.send_attachment(txt, channel_id, attachment) def demo_attachment(self, channel_id): txt = ("Beep Beep Boop is a ridiculously simple hosting platform for " "your Slackbots.") attachment = { "pretext": "We bring bots to life. :sunglasses: :thumbsup:", "title": "Host, deploy and share your bot in seconds.", "title_link": "https://beepboophq.com/", "text": txt, "fallback": txt, "image_url": ("https://storage.googleapis.com/beepboophq/_assets/" "bot-1.22f6fb.png"), "color": "#7CD197", } self.send_attachment(txt, channel_id, attachment) def write_weather(self, channel_id): self.write_slow(weather_manager.getCurrentWeather(), channel_id) def write_loud(self, orig_msg): if not is_zac_mention(orig_msg): self.loud_manager.write_loud_to_file(orig_msg) def respond_loud(self, orig_msg, channel_id): if is_zac_mention(orig_msg) or random.random() < 0.8: message = self.loud_manager.get_random_loud(); if message: self.send_message(self.loud_manager.get_random_loud(), channel_id) def write_hogwarts_house(self, msg_text, channel_id, user_id): response = self.hogwarts_house_sorter.sort_into_house(msg_text) self.write_slow('<@{}>: {}'.format(user_id, response), channel_id) def write_explanation(self, channel_id): self.write_slow(self.explanation_manager.get_response(), channel_id) def write_sass(self, msg_txt, channel_id): target = get_target(SASS_FLAG, msg_txt) sass = 'Hey, {}! {}'.format(target, self.sass_manager.get_response()) self.write_slow(sass, channel_id) def write_solution(self, msg_text, channel_id): self.write_slow(self.equation_manager.solve(msg_text), channel_id) def write_sweetpotato_me(self, msg_text, channel_id): target = get_target(SWEETPOTATO_FLAG, msg_text) txt = 'Here, {}! :sweet_potato:'.format(target) self.write_slow(txt, channel_id) def write_draw_me(self, channel_id): self.write_slow(self.drawing_manager.get_response(), channel_id) def write_forever(self, channel_id): original_msg = self.forever_manager.get_response() response = self.write_slow(original_msg, channel_id) new_msg = '~{}~ Just kidding! :laughing:'.format(original_msg.strip()) self.update_message( new_msg, response['ts'], channel_id, slow=True, react_emoji='trollface' ) def write_flip(self, channel_id): self.send_message(u"(╯°□°)╯︵ ┻━┻", channel_id) def write_unflip(self, channel_id): self.send_message(u"┬─┬ノ( º _ ºノ)", channel_id) def write_sup_son(self, channel_id): self.send_message(u"¯\_(ツ)_/¯", channel_id) def write_riri_me(self, msg_text, channel_id): target = get_target(RIRI_FLAG, msg_text).upper() if target != "": txt = ' '.join(target for num in range(5)) else: txt = "WHY WOULD YOU JUST TYPE RIRI?\n" self.write_slow(txt, channel_id) def write_xkcd(self, lower_msg_text, channel_id): requestedComic = lower_msg_text[lower_msg_text.find('xkcd') + 4:] txt = xkcd_manager.getImageLocation(requestedComic) self.write_slow(txt, channel_id) def write_terminal_command(self, lower_msg_text, channel_id): response = terminal_manager.run_terminal_command(lower_msg_text) self.send_message(response, channel_id) def google(self, msg_text, channel_id): try: tokens = re.split(GOOGLE_FLAG, msg_text) query = "" for num in range(len(tokens)): if num > 0: query += "+" + tokens[num].strip() if len(query) > 1: query = query[1:] url = ( "https://www.googleapis.com/customsearch/v1?key=AIzaSyDs8-" "StJem2hqcu2L-J4PceBPVx5Jk6txk&cx=004179257401026011423:y4" "vp3hnjgvo&q=" ) + query response = requests.get(url).json() result = response['items'][0]['link'] self.send_message(result, channel_id) except Exception as e: self.write_error(str(e)) def link_945(self, msg_text, channel_id, user_name): my_news = msg_text.partition("zac add news ")[2] rank = self.news_links.add_news(my_news, user_name) result = 'Added <{}> from `{}` to the news. It\'s rank is #{}'.format( my_news, user_name, rank ) self.send_message(result, channel_id) def write_lmao(self, channel_id): self.send_message("lmao", channel_id) def write_hal(self, channel_id, user_name): reply = "I'm sorry <@{}>, I'm afraid I can't do that.".format( user_name ) self.send_message(reply, channel_id) def write_hackernews(self, channel_id): article = get_hackernews_article() self.send_message(article, channel_id)
class TimeTriggeredEventManager(object): def __init__(self, clients, msg_writer, markov_chain): self.clients = clients self.msg_writer = msg_writer self.markov_chain = markov_chain self.channel_manager = ChannelManager(clients) self.trigger_startup_log() self.process_recent_messages() def send_message(self, msg_txt, channel=None): self.msg_writer.send_message(msg_txt, channel) def get_emoji(self): return self.clients.get_random_emoji() def clean_channels_history(self): result = 'Erased messages: ' testing_channel = self.channel_manager.get_channel_id(TESTING_CHANNEL) for channel_id in self.channel_manager.get_all_channel_ids(): if channel_id != testing_channel: count = self._erase_channel_messages(channel_id, log_days=3) if count != 0: result += '<#{}> ({}), '.format( str(channel_id), str(count) ) if result.endswith(', '): result = result[:-2] else: result = 'No messages erased during general clean up' self.send_message(result) def clean_testing_channel_history(self): testing_channel = self.channel_manager.get_channel_id(TESTING_CHANNEL) total_count = 0 for num in range(10): count = self._erase_channel_messages(testing_channel, log_days=1) total_count += count if count == 0: break result = 'Erased {} total messages from <#{}> in {} passes'.format( str(total_count), str(testing_channel), str(num) ) self.send_message(result) def _erase_channel_messages(self, channel_id, log_days=0): count = 0 now_ts = float(time.time()) response = self.clients.get_message_history(channel_id) if 'messages' in response: for message in response['messages']: if ( 'ts' in message and 'pinned_to' not in message and self.clients.is_message_from_me(message) ): # Delete everything older than `log_days` old # Delete items older than a day old # Unless they are weather posts or startup logs # Always delete the message deletions messages if ( (now_ts - (60*60*24*log_days)) > float(message['ts']) or ( (now_ts - (60*60*24)) > float(message['ts']) and not re.search( DONT_DELETE, message['text'].lower() ) or ( re.search( "I SAW THAT! _Someone_ deleted a message", message['text'] ) ) ) ): self.clients.delete_message(channel_id, message['ts']) count += 1 return count def process_recent_messages(self): testing_channel = self.channel_manager.get_channel_id(TESTING_CHANNEL) count_markov = 0 count_louds = 0 for channel_id in self.channel_manager.get_all_channel_ids(): if channel_id != testing_channel: response = self.clients.get_message_history(channel_id) if 'messages' in response: for message in response['messages']: if not self.clients.is_message_from_me(message): if 'text' in message: msg_text = message['text'] # Add markovs if should_add_markov(message): self.markov_chain.add_single_line(msg_text) count_markov += 1 # Add louds if should_add_loud(message): self.msg_writer.write_loud(msg_text) count_louds += 1 result = ( "Added " + str(count_markov) + " messages to markov " "and " + str(count_louds) + " loud messages" ) self.send_message(result) def trigger_random_markov(self, channel): if random.random() < 0.10: channel_id = self.channel_manager.get_channel_id(channel) now_timestamp = float(time.time()) response = self.clients.get_message_history(channel_id, 1) if 'messages' in response: for message in response['messages']: if ( 'user' in message and 'ts' in message and not self.clients.is_message_from_me(message) and not contains_tag(message['text']) and 'markov' not in message['text'] ): # Post only 3 - 5 minutes after latest message if ( now_timestamp - (60*5) <= float(message['ts']) and now_timestamp - (60*2) >= float(message['ts']) ): try: txt = str(self.markov_chain) self.send_message(txt, channel) self.trigger_method_log('random markov') except Exception: err_msg = traceback.format_exc() logging.error( 'Unexpected error: {}'.format(err_msg) ) self.msg_writer.write_error(err_msg) pass def trigger_ping(self, day, hour, minute, second): msg = ('Ping on ' + day + ' ' + str(hour) + ':' + str(minute) + ':' + str(second) + ' :' + str(self.get_emoji()) + ':') self.send_message(msg) def trigger_method_log(self, method_name): msg = 'Event: {}'.format(method_name) self.send_message(msg) def trigger_startup_log(self): day, hour, minute, second = _get_datetime() msg = ('I came back to life on ' + day + ' ' + str(hour) + ':' + str(minute) + ':' + str(second) + ' :' + str(self.get_emoji()) + ':') self.send_message(msg) def trigger_weather(self): response = weather_manager.getCurrentWeather() self.send_message(response) def trigger_tuesday(self): txt = "DON'T FORGET IT'S TUESDAY _ALLL_ DAY TODAY" self.msg_writer.send_message_as_other( txt, 'random', 'zac', ':rolled_up_newspaper:' ) def trigger_timed_event(self): day, hour, minute, second = _get_datetime() # leaves 10-ish seconds to trigger since method is called every 10-ish # seconds and we want the if statement to trigger once per min only if(second >= 5 and second <= 16): try: # self.trigger_ping(day, hour, minute, second) if hour == 1: if minute == 15: self.clean_channels_history() if minute == 0 or minute == 30: self.clean_testing_channel_history() if hour % 3 == 0 and minute == 0: self.trigger_weather() if hour >= 9 and hour <= 16: self.trigger_random_markov('random') self.trigger_random_markov('work') if day == 'Tuesday' and hour == 14 and minute == 43: self.trigger_tuesday() except Exception as e: self.msg_writer.write_error(e)
class RtmEventHandler(object): bold_pattern = re.compile( "(((?<!.)| )\*(?=\S)(?!\*).+?(?<!\*)(?<=\S)\*( |(?!.)))" # btw this doesn't work exactly properly # if you want to fix it, don't use a regex # this is a commit to revive zac ) def __init__(self, slack_clients, msg_writer, markov_chain): self.clients = slack_clients self.msg_writer = msg_writer self.game_manager = GameManager(self.msg_writer) self.user_manager = UserManager(self.clients, self.msg_writer) self.tictactoe_manager = TicTacToeManager( self.msg_writer, self.user_manager, self.game_manager ) self.response_master = Response_master(self.msg_writer) self.user_manager = UserManager(self.clients, self.msg_writer) self.rude_manager = RudeManager(self.msg_writer) self.channel_manager = ChannelManager(slack_clients) self.markov_chain = markov_chain markov_files = ['hpOne.txt', 'lotrOne.txt', 'memoriesOfIce.txt'] self.lotrMarkov = Markov(2, msg_writer, markov_files) def handle(self, event): if 'type' in event: self._handle_by_type(event['type'], event) def _handle_by_type(self, event_type, event): # See https://api.slack.com/rtm for a full list of events if event_type == 'error': self.msg_writer.write_error(json.dumps(event), event['channel']) elif event_type == 'message': self._handle_message(event) elif event_type == 'channel_joined': # you joined a channel self.msg_writer.write_help_message(event['channel']['id']) elif event_type == 'group_joined': # you joined a private group self.msg_writer.write_help_message(event['channel']) elif ( event_type == 'reaction_added' and 'user' in event and not self.clients.is_message_from_me(event) ): if 'channel' in event['item']: msg = event['item'] self.response_master.process_reaction( event['reaction'], msg['channel'], msg['ts'] ) else: pass def _is_edited_with_star(self, message): return '*' in re.sub(self.bold_pattern, '', message) def _is_edited_by_user(self, event): if 'subtype' in event: if event['subtype'] == 'message_changed': if 'message' in event: event_msg = event['message'] # Dont allow zac to spam his own message edits if self.clients.is_message_from_me(event_msg): return False if ( 'user' in event_msg and 'edited' in event_msg and 'user' in event_msg['edited'] and not is_bot_message(event_msg['edited']) ): user1 = event_msg['user'] user2 = event_msg['edited']['user'] return user1 == user2 return False def _handle_message(self, event): if 'subtype' in event: # if self._is_edited_by_user(event): # self.msg_writer.write_spelling_mistake( # event['channel'], event['message']['ts'] # ) if ( event['subtype'] == 'channel_join' and not self.clients.is_message_from_me(event) ): self.msg_writer.write_joined_channel( event['channel'], event['user'] ) elif event['subtype'] == 'message_deleted': self.msg_writer.write_message_deleted(event['channel']) elif event['subtype'] == 'channel_leave': self.msg_writer.write_left_channel(event['channel']) # Filter out messages from the bot itself if 'user' in event and not self.clients.is_message_from_me(event): logging.info("Handling event") msg_txt = event['text'] channel_id = event['channel'] user_id = event['user'] ts = event['ts'] user_name = self.user_manager.get_user_by_id(user_id) lower_txt = msg_txt.lower() # Markov chain addition and response if should_add_markov(event): self.markov_chain.add_single_line(msg_txt) if ( channel_id == self.channel_manager.get_channel_id('markov') or lower_txt == 'markov' ): self.msg_writer.send_message(str(self.lotrMarkov), channel_id) # Respond to messages handled by rude_manager and response_manager self.rude_manager.run(channel_id, user_id) self.response_master.process_message( msg_txt, channel_id, user_id, ts ) # Command line # logging.info("lower_txt: "+str(lower_txt.split())) try: token = lower_txt.split()[0] if token == '#>' or token == u'#>': # logging.info("entering terminal command mode") self.msg_writer.write_terminal_command( lower_txt, channel_id ) return 0 # Do not continue execution except: pass # Return channel and user information if lower_txt == 'channelinfo': self.msg_writer.send_message(channel_id, channel_id) elif lower_txt == 'channelname': self.msg_writer.send_message( self.channel_manager.get_channel_by_id(channel_id), channel_id ) elif lower_txt == 'userinfo': self.msg_writer.send_message(user_id, channel_id) elif lower_txt == 'allusersinfo': self.user_manager.print_all_users(channel_id) elif lower_txt == 'allchannelinfo': self.msg_writer.send_message( str(self.channel_manager.get_all_channel_ids()), channel_id ) elif lower_txt == 'allchannelname': self.msg_writer.send_message( str(self.channel_manager.get_all_channel_names()), channel_id ) elif lower_txt == 'ayy': self.msg_writer.write_lmao(channel_id) # Loud addition and response if should_add_loud(event): self.msg_writer.write_loud(msg_txt) self.msg_writer.respond_loud(msg_txt, channel_id) # if self._is_edited_with_star(msg_txt): # self.msg_writer.write_spelling_mistake(channel_id, ts) # Respond to message text if re.search('i choose you', lower_txt): self.msg_writer.write_cast_pokemon(lower_txt, channel_id) if re.search('weather', lower_txt): self.msg_writer.write_weather(channel_id) if re.search('riri', lower_txt): self.msg_writer.write_riri_me(msg_txt, channel_id) if 'xkcd' in lower_txt: self.msg_writer.write_xkcd(lower_txt, channel_id) if ( 'tictactoe' in lower_txt or ' ttt' in lower_txt or lower_txt.startswith('ttt') ): self.tictactoe_manager.get_message( channel_id, lower_txt, user_name ) # Respond to message text with `zac` included if is_zac_mention(msg_txt) or self.clients.is_bot_mention(msg_txt): if re.search('erase|delete', lower_txt): self.msg_writer.erase_history( msg_txt, channel_id, ts ) if 'help' in lower_txt: self.msg_writer.write_help_message(channel_id) if 'joke' in lower_txt: self.msg_writer.write_joke(channel_id) if 'french' in lower_txt: self.msg_writer.write_french(msg_txt, channel_id) if re.search('who\'?s that pokemon', msg_txt): self.msg_writer.write_whos_that_pokemon(channel_id) if re.search(' ?zac it\'?s', lower_txt): self.msg_writer.write_pokemon_guessed_response( msg_txt, channel_id, user_id ) if re.search('attachment|beep boop link', lower_txt): self.msg_writer.demo_attachment(channel_id) if 'sad ' in lower_txt: self.msg_writer.write_sad(channel_id) if 'sort me' in lower_txt: self.msg_writer.write_hogwarts_house( msg_txt, channel_id, user_id ) if re.search('encourage ', lower_txt): self.msg_writer.write_encouragement(msg_txt, channel_id) if 'sass ' in lower_txt: self.msg_writer.write_sass(msg_txt, channel_id) if 'solve' in lower_txt: self.msg_writer.write_solution(msg_txt, channel_id) if re.search('explain|why', lower_txt): self.msg_writer.write_explanation(channel_id) if re.search('sweetpotato|sweet potato', lower_txt): self.msg_writer.write_sweetpotato_me(msg_txt, channel_id) if re.search('draw me', lower_txt): self.msg_writer.write_draw_me(channel_id) if re.search('love|forever|relationship', lower_txt): self.msg_writer.write_forever(channel_id) if re.search('unflip', lower_txt): self.msg_writer.write_unflip(channel_id) elif re.search('flip|rageflip', lower_txt): self.msg_writer.write_flip(channel_id) if re.search('sup son', lower_txt): self.msg_writer.write_sup_son(channel_id) if lower_txt == "zac": self.msg_writer.write_prompt(channel_id) # The word google must be specified in lower case if 'zac google ' in msg_txt: self.msg_writer.google(msg_txt, channel_id) if msg_txt.startswith('zac add news '): user_name = self.user_manager.get_user_by_id(user_id) self.msg_writer.link_945(msg_txt, channel_id, user_name) if re.search('open the pod bay doors', lower_txt): self.msg_writer.write_hal(channel_id, user_name) if re.search('hackernews', lower_txt): self.msg_writer.write_hackernews(channel_id) else: # self.msg_writer.write_prompt(channel_id) pass
class TimeTriggeredEventManager(object): def __init__(self, clients, msg_writer, markov_chain): self.clients = clients self.msg_writer = msg_writer self.markov_chain = markov_chain self.channel_manager = ChannelManager(clients) self.random_manager = ResourceManager('random_comments.txt') self.trigger_startup_log() self.process_recent_messages() self.news_links = NewsManager() def send_message(self, msg_txt, channel=None): self.msg_writer.send_message(msg_txt, channel) def get_emoji(self): return self.clients.get_random_emoji() def clean_channels_history(self): result = 'Erased messages: ' testing_channel = self.channel_manager.get_channel_id(TESTING_CHANNEL) for channel_id in self.channel_manager.get_all_channel_ids(): if channel_id != testing_channel: count = self._erase_channel_messages(channel_id, log_days=3) if count != 0: result += '<#{}> ({}), '.format( str(channel_id), str(count) ) if result.endswith(', '): result = result[:-2] else: result = 'No messages erased during general clean up' self.send_message(result) def clean_testing_channel_history(self): testing_channel = self.channel_manager.get_channel_id(TESTING_CHANNEL) total_count = 0 for num in range(10): count = self._erase_channel_messages(testing_channel, log_days=1) total_count += count if count == 0: break result = 'Erased {} total messages from <#{}> in {} passes'.format( str(total_count), str(testing_channel), str(num) ) self.send_message(result) def _erase_channel_messages(self, channel_id, log_days=0): count = 0 now_ts = float(time.time()) response = self.clients.get_message_history(channel_id) if 'messages' in response: for message in response['messages']: if ( 'ts' in message and 'pinned_to' not in message and self.clients.is_message_from_me(message) ): # Delete everything older than `log_days` old # Delete items older than a day old # Unless they are weather posts or startup logs # Always delete the message deletions messages if ( (now_ts - (60*60*24*log_days)) > float(message['ts']) or ( (now_ts - (60*60*24)) > float(message['ts']) and not re.search( DONT_DELETE, message['text'].lower() ) or ( re.search( "I SAW THAT! _Someone_ deleted a message", message['text'] ) ) ) ): self.clients.delete_message(channel_id, message['ts']) count += 1 return count def process_recent_messages(self): testing_channel = self.channel_manager.get_channel_id(TESTING_CHANNEL) count_markov = 0 count_louds = 0 for channel_id in self.channel_manager.get_all_channel_ids(): if channel_id != testing_channel: response = self.clients.get_message_history(channel_id) if 'messages' in response: for message in response['messages']: if not self.clients.is_message_from_me(message): if 'text' in message: msg_text = message['text'] # Add markovs if should_add_markov(message): self.markov_chain.add_single_line(msg_text) count_markov += 1 # Add louds if should_add_loud(message): self.msg_writer.write_loud(msg_text) count_louds += 1 result = ( "Added " + str(count_markov) + " messages to markov " "and " + str(count_louds) + " loud messages" ) self.send_message(result) def trigger_random_markov(self): if random.random() < 0.15: channel_id = self.channel_manager.get_channel_id('random') now_timestamp = float(time.time()) response = self.clients.get_message_history(channel_id, 1) if 'messages' in response: for message in response['messages']: if ( 'user' in message and 'ts' in message and not self.clients.is_message_from_me(message) and not contains_tag(message['text']) and 'markov' not in message['text'] ): # Post only 3 - 5 minutes after latest message if ( now_timestamp - (60*5) <= float(message['ts']) and now_timestamp - (60*2) >= float(message['ts']) ): try: txt = str(self.markov_chain) self.send_message(txt, 'random') self.trigger_method_log('random markov') except Exception: err_msg = traceback.format_exc() logging.error( 'Unexpected error: {}'.format(err_msg) ) self.msg_writer.write_error(err_msg) pass def trigger_markov(self): try: self.msg_writer.send_message(str(self.markov_chain), 'markov') except Exception: err_msg = traceback.format_exc() logging.error('Unexpected error: {}'.format(err_msg)) self.msg_writer.write_error(err_msg) pass def trigger_ping(self, day, hour, minute, second): msg = ('Ping on ' + day + ' ' + str(hour) + ':' + str(minute) + ':' + str(second) + ' :' + str(self.get_emoji()) + ':') self.send_message(msg) def trigger_method_log(self, method_name): msg = 'Event: {}'.format(method_name) self.send_message(msg) def trigger_startup_log(self): day, hour, minute, second = _get_datetime() msg = ('I came back to life on ' + day + ' ' + str(hour) + ':' + str(minute) + ':' + str(second) + ' :' + str(self.get_emoji()) + ':') self.send_message(msg) def trigger_wine_club(self): tags = ['here'] msg = ("WINE CLUB IN THE LOUNGE :wine_glass: :wine_glass: " ":wine_glass: :wine_glass: :wine_glass:") txt = '<!{}> {}'.format(random.choice(tags), msg) self.msg_writer.send_message_as_other( txt, 'random', 'zac', ':wine_glass:' ) def trigger_random_phrase(self): if random.random() < 0.01: comment = self.random_manager.get_response() txt = '{} :{}:'.format(comment, self.get_emoji()) self.send_message(txt, 'random') self.trigger_method_log('wine club') def trigger_weather(self): response = weather_manager.getCurrentWeather() self.send_message(response) def trigger_tuesday(self): txt = "DON'T FORGET IT'S TUESDAY _ALLL_ DAY TODAY" self.msg_writer.send_message_as_other( txt, 'random', 'zac', ':rolled_up_newspaper:' ) def trigger_945(self): emojis = ['sunglasses', 'zacefron', 'coffee'] mornings = [ "Good morning", "Morning", "Guten Morgen", "Bonjour", "Ohayou", "Good morning to you", "Aloha", "Konnichiwashington", "Buenos dias", "GLUTEN MORNING", ":sunny: Good morning", "Where have you been. MORNING" ] coffee_msgs = [ 'The mochaccino tastes _amazing_ this morning!', 'Eh, mochaccino ain\'t so great today...', 'HELP! MOCHACCINO EVERYWHERE!', 'The mochaccino machine won\'t stop dripping help I need an adult', 'WHAT! wHY is my mochaccino _decaf_??!', 'I haven\'t had my mochaccino yet don\'t talk to me', 'WHERE\'S MY MUG I NEED MOCHACCINO!!', 'Mochaccino mochaccino mochaccino', 'Mochaccino is SO GOOD TODAY HOLY HELL', ( 'Today\'s mochaccino is like an angel pooped out a nice hot ' 'cup of coffee mmmmm~' ), 'Mochaccino status: passable', 'MOCHACCINO MOCHACCINO MOCHACCINO!!!', 'Who\'s ready for a nice cup o\' mochaccino?', '_le mochaccino_' ] kip_msgs = [ '@945', '945!', '#945', ':paw_prints: 945!', '~945~', ':horse: 945! giddyup', '945! :heart:', '945! :sweet_potato:', '945!........', '945 time', '945 quickie', '945 o\'clock', '945! :sheep: :panda_face: :slowpoke:', '945! :boom:', ':eggplant: 945.', '945 :coffee:', '_le 945_', '_le fast 945_' ] morning_msg = '{}! :{}:'.format( random.choice(mornings), self.get_emoji() ) coffee_msg = '{} :coffee:'.format(random.choice(coffee_msgs)) kip_msg = '{} :{}:'.format(random.choice(kip_msgs), self.get_emoji()) msg = '{}\n{}'.format(random.choice(morning_msg, coffee_msg), kip_msg) self.msg_writer.send_message_as_other( msg, 'random', 'zac', ':{}:'.format(random.choice(emojis)) ) def post_news(self, iteration): link, user_name = self.news_links.get_news() if link is not None and link != "": if iteration == 0: self.trigger_945() iteration += 1 txt = "News: " + link if user_name is None or user_name == "": user_name = 'zacefron' self.msg_writer.send_message_as_other( txt, 'random', user_name, ':{}:'.format(user_name) ) self.post_news(iteration) def trigger_timed_event(self): day, hour, minute, second = _get_datetime() # leaves 10-ish seconds to trigger since method is called every 10-ish # seconds and we wantz the if statement to trigger once per min only if(second >= 5 and second <= 15): # self.trigger_ping(day, hour, minute, second) if hour == 1: if minute == 15: self.clean_channels_history() if minute == 0 or minute == 30: self.clean_testing_channel_history() if hour % 3 == 0 and minute == 0: self.trigger_weather() if minute == 15: self.trigger_markov() if hour >= 9 and hour <= 16: self.trigger_random_markov() if (day != 'Saturday' and day != 'Sunday'): if hour == 9: if minute == 45: self.post_news(0) if day == 'Friday': if hour == 16 and minute == 45: self.trigger_wine_club() if hour == 17: self.trigger_random_phrase() if day == 'Tuesday': if hour == 14 and minute == 7: self.trigger_tuesday()
class Messenger(object): def __init__(self, slack_clients): self.clients = slack_clients self.loud_manager = LoudManager() self.whos_that_pokemon_manager = WhosThatPokemonManager() self.hogwarts_house_sorter = HogwartsHouseSorter() self.equation_manager = EquationManager() self.explanation_manager = ResourceManager('explanations.txt') self.drawing_manager = ResourceManager('draw_me.txt') self.forever_manager = ResourceManager('forever.txt') self.help_manager = ResourceManager('help_text.txt') self.sass_manager = ResourceManager('sass.txt') self.channel_manager = ChannelManager(slack_clients) def erase_history(self, msg_text, channel_id, now_timestamp): try: tokens = re.findall('[0-9]+', msg_text) delete_num = int(tokens[0]) count = 0 response = self.clients.get_message_history(channel_id) if 'messages' in response: for message in response['messages']: if ('ts' in message and 'pinned_to' not in message and self.clients.is_message_from_me(message) and not re.search(DONT_DELETE, message['text'].lower())): response = self.clients.delete_message( channel_id, message['ts']) count += 1 if count >= delete_num: break if count < delete_num: msg = ("Erased " + str(count) + " messages: I " "can only see the 100 most recent messages") self.send_message(msg, channel_id) except Exception: msg = "Correct usage is `bolton erase <num>`" self.send_message(msg, channel_id) pass def __del__(self): closing_msgs = [ "No!! Don't kill me! I want to live!", "Good BYEEE!!!", "I'm dying again :sob:", "Have you gotten tired of this face :boltonefron: ?" ] txt = random.choice(closing_msgs) self.send_message(txt) def send_slow_message_as_other(self, msg_text, channel, username, emoji): self.clients.send_user_typing_pause(channel) self.send_message_as_other(msg_text, channel, username, emoji) def send_message_as_other(self, msg_text, channel, username, emoji): msg_text = msg_text.replace('&', "&") # msg = msg.replace('<', "<") # msg = msg.replace('>', ">") # msg = msg.decode("utf8", "ignore") return self.clients.send_message_as_other(msg_text, channel, username, emoji) def write_slow(self, msg_text, channel=None): return self.send_message(msg_text, channel, slow=True) def send_message(self, msg_text, channel=None, slow=False, react_emoji=None): msg_text = msg_text.replace('&', "&") # msg = msg.replace('<', "<") # msg = msg.replace('>', ">") # msg = msg.decode("utf8", "ignore") if channel is None: channel = TESTING_CHANNEL if slow is True: self.clients.send_user_typing_pause(channel) response = self.clients.send_message(msg_text, channel) if 'ok' in response and react_emoji is not None: self.send_reaction(react_emoji, channel, response['ts']) return response def update_message(self, updated_msg_text, ts, channel=None, slow=False, react_emoji=None): updated_msg_text = updated_msg_text.replace('&', "&") if channel is None: channel = TESTING_CHANNEL if slow is True: self.clients.send_user_typing_pause(channel) response = self.clients.update_message(updated_msg_text, channel, ts) if 'ok' in response and react_emoji is not None: self.send_reaction(react_emoji, channel, response['ts']) return response def send_attachment(self, txt, channel_id, attachment): self.clients.send_attachment(txt, channel_id, attachment) def write_error(self, err_msg, channel_id=None): txt = (":face_with_head_bandage: my maker didn't handle this error " "very well:\n>```{}```").format(err_msg) self.send_message(txt, channel_id) def send_reaction(self, emoji_name, channel_id, timestamp): self.clients.send_reaction(emoji_name, channel_id, timestamp) def get_emoji(self): return self.clients.get_random_emoji() def write_message_deleted(self, channel_id): # Dont post if messages were deleted inside of #bolton-testing if channel_id != self.channel_manager.get_channel_id('bolton-testing'): txt = ("I SAW THAT! _Someone_ deleted a message from channel: " "<#{}>").format(channel_id) self.send_message(txt) def write_left_channel(self, channel_id): self.send_message('...well THAT was something', channel_id) def write_joined_channel(self, channel_id, user_id): if channel_id == self.channel_manager.get_channel_id('bolton-testing'): txt = ("Hey <@{}>! Welcome to the Testing (aka the Weather) " "channel. Please MUTE this channel or be inundaded with " "notifications!").format(user_id) self.write_slow(txt, channel_id) self.write_xkcd(channel_id, "15") else: self.write_greeting(channel_id, user_id) def write_help_message(self, channel_id): help_txt = self.help_manager.get_all() count = self.help_manager.get_count() txt = ( "I'm bolton. I'll *_respond_* to the following {} commands:\n{}" ).format(count - 1, help_txt) self.write_slow(txt, channel_id) def write_french(self, msg_text, channel_id): target = get_target(FRENCH_FLAG, msg_text).replace('_', '') self.write_slow('_le {}_'.format(target), channel_id) def write_greeting(self, channel_id, user_id): greetings = ['Hi', 'Hello', 'Nice to meet you', 'Howdy', 'Salutations'] txt = '{}, <@{}>!'.format(random.choice(greetings), user_id) self.write_slow(txt, channel_id) def write_spelling_mistake(self, channel_id, timestamp): emoji_name = "spelft_it_wronbg_again_i_see" self.send_reaction(emoji_name, channel_id, timestamp) def write_prompt(self, channel_id): bot_uid = self.clients.bot_user_id() txt = ("I'm sorry, I didn't quite understand... Can I help you? " "(e.g. `<@" + bot_uid + "> help`)") self.write_slow(txt, channel_id) def write_joke(self, channel_id): answer = ( "Wenn ist das Nunstück git und Slotermeyer? Ja! Beiherhund das " "Oder die Flipperwaldt gersput!") self.write_slow(answer, channel_id) def write_encouragement(self, msg_text, channel_id): encouragements = [ "Get your shit together", "You can do it", "I'm here for you", "Do you just think about yourself", "You're the best", ] target = get_target(ENCOURAGE_FLAG, msg_text) txt = '{} {}'.format(random.choice(encouragements), target) self.write_slow(txt, channel_id) def write_cast_pokemon(self, lower_msg_text, channel_id): pkmn = pokemon_i_choose_you(lower_msg_text) if pkmn is not None: self.send_message(pkmn, channel_id) def write_whos_that_pokemon(self, channel_id): txt = self.whos_that_pokemon_manager.whos_that_pkmn() self.send_message(txt, channel_id) def write_pokemon_guessed_response(self, msg_text, channel_id, user_id): text = self.whos_that_pokemon_manager.check_response(user_id, msg_text) if text is not None: self.send_message(text, channel_id) def write_sad(self, channel_id): txt = "I'm crying into my tea. :joy:" attachment = { "pretext": "This always cracks me up. :wink:", "title": "/giphy bloopin", "title_link": ("http://giphy.com/gifs/friday-rebecca-black-hurrr-" "13FsSYo3fzfT2g"), "text": txt, "fallback": txt, "image_url": "http://i.giphy.com/13FsSYo3fzfT2g.gif", "color": "#7CD197", } self.send_attachment(txt, channel_id, attachment) def demo_attachment(self, channel_id): txt = ("Beep Beep Boop is a ridiculously simple hosting platform for " "your Slackbots.") attachment = { "pretext": "We bring bots to life. :sunglasses: :thumbsup:", "title": "Host, deploy and share your bot in seconds.", "title_link": "https://beepboophq.com/", "text": txt, "fallback": txt, "image_url": ("https://storage.googleapis.com/beepboophq/_assets/" "bot-1.22f6fb.png"), "color": "#7CD197", } self.send_attachment(txt, channel_id, attachment) def write_weather(self, channel_id): self.write_slow(weather_manager.getCurrentWeather(), channel_id) def write_loud(self, orig_msg): if not is_bolton_mention(orig_msg): self.loud_manager.write_loud_to_file(orig_msg) def respond_loud(self, orig_msg, channel_id): if is_bolton_mention(orig_msg) or random.random() < 0.25: self.send_message(self.loud_manager.get_random_loud(), channel_id) def write_hogwarts_house(self, msg_text, channel_id, user_id): response = self.hogwarts_house_sorter.sort_into_house(msg_text) self.write_slow('<@{}>: {}'.format(user_id, response), channel_id) def write_explanation(self, channel_id): self.write_slow(self.explanation_manager.get_response(), channel_id) def write_sass(self, msg_txt, channel_id): target = get_target(SASS_FLAG, msg_txt) sass = 'Hey, {}! {}'.format(target, self.sass_manager.get_response()) self.write_slow(sass, channel_id) def write_solution(self, msg_text, channel_id): self.write_slow(self.equation_manager.solve(msg_text), channel_id) def write_sweetpotato_me(self, msg_text, channel_id): target = get_target(SWEETPOTATO_FLAG, msg_text) txt = 'Here, {}! :sweet_potato:'.format(target) self.write_slow(txt, channel_id) def write_draw_me(self, channel_id): self.write_slow(self.drawing_manager.get_response(), channel_id) def write_forever(self, channel_id): original_msg = self.forever_manager.get_response() response = self.write_slow(original_msg, channel_id) new_msg = '~{}~ Just kidding! :laughing:'.format(original_msg.strip()) self.update_message(new_msg, response['ts'], channel_id, slow=True, react_emoji='trollface') def write_flip(self, channel_id): self.send_message(u"(╯°□°)╯︵ ┻━┻", channel_id) def write_unflip(self, channel_id): self.send_message(u"┬─┬ノ( º _ ºノ)", channel_id) def write_sup_son(self, channel_id): self.send_message(u"¯\_(ツ)_/¯", channel_id) def write_riri_me(self, msg_text, channel_id): target = get_target(RIRI_FLAG, msg_text).upper() if target != "": txt = ' '.join(target for num in range(5)) else: txt = "WHY WOULD YOU JUST TYPE RIRI?\n" self.write_slow(txt, channel_id) def write_xkcd(self, lower_msg_text, channel_id): requestedComic = lower_msg_text[lower_msg_text.find('xkcd') + 4:] txt = xkcd_manager.getImageLocation(requestedComic) self.write_slow(txt, channel_id) def write_terminal_command(self, lower_msg_text, channel_id): logger.info("In Messenger for terminal_manager") response = terminal_manager.run_terminal_command(lower_msg_text) self.send_message(response, channel_id)
class Messenger(object): def __init__(self, slack_clients): self.clients = slack_clients self.loud_manager = LoudManager() self.whos_that_pokemon_manager = WhosThatPokemonManager() self.equation_manager = EquationManager() self.explanation_manager = ResourceManager('explanations.txt') self.help_manager = ResourceManager('help_text.txt') self.sass_manager = ResourceManager('sass.txt') self.channel_manager = ChannelManager(slack_clients) def erase_history(self, msg_text, channel_id, now_timestamp): try: tokens = re.findall('[0-9]+', msg_text) delete_num = int(tokens[0]) count = 0 response = self.clients.get_message_history(channel_id) if 'messages' in response: for message in response['messages']: if ( 'ts' in message and 'pinned_to' not in message and self.clients.is_message_from_me(message) and not re.search(DONT_DELETE, message['text'].lower()) ): response = self.clients.delete_message( channel_id, message['ts'] ) count += 1 if count >= delete_num: break if count < delete_num: msg = ("Erased " + str(count) + " messages: I " "can only see the 100 most recent messages") self.send_message(msg, channel_id) except Exception: msg = "Correct usage is `zac erase <num>`" self.send_message(msg, channel_id) pass def __del__(self): closing_msgs = ["No!! Don't kill me! I want to live!", "Good BYEEE!!!", "I'm dying again :sob:", "Have you gotten tired of this face :zacefron: ?"] txt = random.choice(closing_msgs) self.send_message(txt) def send_slow_message_as_other(self, msg_text, channel, username, emoji): self.send_message_as_other( msg_text, channel, username, emoji, slow=True ) def send_message_as_other( self, msg_text, channel, username, emoji, slow=False ): msg_text = msg_text.replace('&', "&") channel = self.channel_manager.get_channel_id(channel) if (slow): self.clients.send_user_typing_pause(channel) return self.clients.send_message_as_other( msg_text, channel, username, emoji ) def write_slow(self, msg_text, channel=None): return self.send_message(msg_text, channel, slow=True) def send_message( self, msg_text, channel=None, slow=False, react_emoji=None ): msg_text = msg_text.replace('&', "&") msg_text = msg_text.replace('"', "\"") # channel = self.channel_manager.get_channel_id(channel) if channel is None: channel = TESTING_CHANNEL if slow is True: self.clients.send_user_typing_pause(channel) response = self.clients.send_message(msg_text, channel) if 'ok' in response and react_emoji is not None: self.send_reaction(react_emoji, channel, response['ts']) return response def update_message( self, updated_msg_text, ts, channel=None, slow=False, react_emoji=None ): updated_msg_text = updated_msg_text.replace('&', "&") channel = self.channel_manager.get_channel_id(channel) if channel is None: channel = TESTING_CHANNEL if slow is True: self.clients.send_user_typing_pause(channel) response = self.clients.update_message( updated_msg_text, channel, ts ) if 'ok' in response and react_emoji is not None: self.send_reaction(react_emoji, channel, response['ts']) return response def send_attachment(self, txt, channel_id, attachment): self.clients.send_attachment(txt, channel_id, attachment) def write_error(self, err_msg, channel_id=None): txt = (":face_with_head_bandage: my maker didn't handle this error " "very well:\n>```{}```").format(err_msg) self.send_message(txt, channel_id) def send_reaction(self, emoji_name, channel_id, timestamp): self.clients.send_reaction(emoji_name, channel_id, timestamp) def get_emoji(self): return self.clients.get_random_emoji() def write_message_deleted(self, channel_id): # Dont post if messages were deleted inside of #zac-testing if channel_id != self.channel_manager.get_channel_id('zac-testing'): txt = ("I SAW THAT! _Someone_ deleted a message from channel: " "<#{}>").format(channel_id) self.send_message(txt) def write_left_channel(self, channel_id): self.send_message('...well THAT was something', channel_id) def write_joined_channel(self, channel_id, user_id): if channel_id == self.channel_manager.get_channel_id('zac-testing'): txt = ("Hey <@{}>! Welcome to the Testing (aka the Weather) " "channel. Please MUTE this channel or be inundaded with " "notifications!").format(user_id) self.write_slow(txt, channel_id) else: self.write_greeting(channel_id, user_id) def write_help_message(self, channel_id): help_txt = self.help_manager.get_all() count = self.help_manager.get_count() txt = ( "I'm Zac. I'll *_respond_* to the following {} commands:\n{}" ).format(count-1, help_txt) info_text = ( "Hi, I'm Zac Efron. You can find out more information about me " "in #zac-testing. Merci :zacefron:" ) self.write_slow(info_text, channel_id) self.write_slow(txt, 'zac-testing') def write_french(self, msg_text, channel_id): target = get_target(FRENCH_FLAG, msg_text).replace('_', '') self.write_slow('_le {}_'.format(target), channel_id) def write_greeting(self, channel_id, user_id): greetings = ['Hi', 'Hello', 'Nice to meet you', 'Howdy', 'Salutations'] txt = '{}, <@{}>!'.format(random.choice(greetings), user_id) self.write_slow(txt, channel_id) def write_spelling_mistake(self, channel_id, timestamp): emoji_name = "spelft_it_wronbg_again_i_see" self.send_reaction(emoji_name, channel_id, timestamp) def write_prompt(self, channel_id): bot_uid = self.clients.bot_user_id() txt = ("I'm sorry, I didn't quite understand... Can I help you? " "(e.g. `<@" + bot_uid + "> help`)") self.write_slow(txt, channel_id) def write_cast_pokemon(self, lower_msg_text, channel_id): pkmn = pokemon_i_choose_you(lower_msg_text) if pkmn is not None: self.send_message(pkmn, channel_id) def write_whos_that_pokemon(self, channel_id): txt = self.whos_that_pokemon_manager.whos_that_pkmn() self.send_message(txt, channel_id) def write_pokemon_guessed_response(self, msg_text, channel_id, user_id): text = self.whos_that_pokemon_manager.check_response(user_id, msg_text) if text is not None: self.send_message(text, channel_id) def write_weather(self, channel_id): self.write_slow(weather_manager.getCurrentWeather(), channel_id) def write_loud(self, orig_msg): if not is_zac_mention(orig_msg): self.loud_manager.write_loud_to_file(orig_msg) def respond_loud(self, orig_msg, channel_id): if is_zac_mention(orig_msg) or random.random() < 0.8: message = self.loud_manager.get_random_loud(); if message: self.send_message(self.loud_manager.get_random_loud(), channel_id) def write_explanation(self, channel_id): self.write_slow(self.explanation_manager.get_response(), channel_id) def write_sass(self, msg_txt, channel_id): target = get_target(SASS_FLAG, msg_txt) sass = 'Hey, {}! {}'.format(target, self.sass_manager.get_response()) self.write_slow(sass, channel_id) def write_solution(self, msg_text, channel_id): self.write_slow(self.equation_manager.solve(msg_text), channel_id) def write_sweetpotato_me(self, msg_text, channel_id): target = get_target(SWEETPOTATO_FLAG, msg_text) txt = 'Here, {}! :sweet_potato:'.format(target) self.write_slow(txt, channel_id) def write_riri_me(self, msg_text, channel_id): target = get_target(RIRI_FLAG, msg_text).upper() if target != "": txt = ' '.join(target for num in range(5)) else: txt = "WHY WOULD YOU JUST TYPE RIRI?\n" self.write_slow(txt, channel_id) def write_terminal_command(self, lower_msg_text, channel_id): response = terminal_manager.run_terminal_command(lower_msg_text) self.send_message(response, channel_id) def google(self, msg_text, channel_id): try: tokens = re.split(GOOGLE_FLAG, msg_text) query = "" for num in range(len(tokens)): if num > 0: query += "+" + tokens[num].strip() if len(query) > 1: query = query[1:] url = ( "https://www.googleapis.com/customsearch/v1?key=AIzaSyDs8-" "StJem2hqcu2L-J4PceBPVx5Jk6txk&cx=004179257401026011423:y4" "vp3hnjgvo&q=" ) + query response = requests.get(url).json() result = response['items'][0]['link'] self.send_message(result, channel_id) except Exception as e: self.write_error(str(e))
class RtmEventHandler(object): bold_pattern = re.compile( "(((?<!.)| )\*(?=\S)(?!\*).+?(?<!\*)(?<=\S)\*( |(?!.)))" ) def __init__(self, slack_clients, msg_writer, markov_chain): self.clients = slack_clients self.msg_writer = msg_writer self.game_manager = GameManager(self.msg_writer) self.user_manager = UserManager(self.clients, self.msg_writer) self.tictactoe_manager = TicTacToeManager( self.msg_writer, self.user_manager, self.game_manager ) self.response_master = Response_master(self.msg_writer) self.user_manager = UserManager(self.clients, self.msg_writer) self.rude_manager = RudeManager(self.msg_writer) self.channel_manager = ChannelManager(slack_clients) self.markov_chain = markov_chain markov_files = ['hpOne.txt', 'lotrOne.txt', 'memoriesOfIce.txt'] self.lotrMarkov = Markov(2, msg_writer, markov_files) def handle(self, event): if 'type' in event: self._handle_by_type(event['type'], event) def _handle_by_type(self, event_type, event): # See https://api.slack.com/rtm for a full list of events if event_type == 'error': self.msg_writer.write_error(json.dumps(event), event['channel']) elif event_type == 'message': self._handle_message(event) elif event_type == 'channel_joined': # you joined a channel self.msg_writer.write_help_message(event['channel']['id']) elif event_type == 'group_joined': # you joined a private group self.msg_writer.write_help_message(event['channel']) elif ( event_type == 'reaction_added' and 'user' in event and not self.clients.is_message_from_me(event) ): if 'channel' in event['item']: msg = event['item'] self.response_master.process_reaction( event['reaction'], msg['channel'], msg['ts'] ) else: pass def _is_edited_with_star(self, message): return '*' in re.sub(self.bold_pattern, '', message) def _is_edited_by_user(self, event): if 'subtype' in event: if event['subtype'] == 'message_changed': if 'message' in event: event_msg = event['message'] # Dont allow bolton to spam his own message edits if self.clients.is_message_from_me(event_msg): return False if ( 'user' in event_msg and 'edited' in event_msg and 'user' in event_msg['edited'] and not is_bot_message(event_msg['edited']) ): user1 = event_msg['user'] user2 = event_msg['edited']['user'] return user1 == user2 return False def _handle_message(self, event): if 'subtype' in event: if self._is_edited_by_user(event): self.msg_writer.write_spelling_mistake( event['channel'], event['message']['ts'] ) elif ( event['subtype'] == 'channel_join' and not self.clients.is_message_from_me(event) ): self.msg_writer.write_joined_channel( event['channel'], event['user'] ) elif event['subtype'] == 'message_deleted': self.msg_writer.write_message_deleted(event['channel']) elif event['subtype'] == 'channel_leave': self.msg_writer.write_left_channel(event['channel']) # Filter out messages from the bot itself if 'user' in event and not self.clients.is_message_from_me(event): logging.info("Handling event") msg_txt = event['text'] channel_id = event['channel'] user_id = event['user'] ts = event['ts'] user_name = self.user_manager.get_user_by_id(user_id) lower_txt = msg_txt.lower() # Markov chain addition and response if should_add_markov(event): self.markov_chain.add_single_line(msg_txt) if ( channel_id == self.channel_manager.get_channel_id('bolton_weather') or lower_txt == 'markov' ): self.msg_writer.send_message(str(self.lotrMarkov), channel_id) # Respond to messages handled by rude_manager and response_manager self.rude_manager.run(channel_id, user_id) self.response_master.process_message( msg_txt, channel_id, user_id, ts ) # Command line # logging.info("lower_txt: "+str(lower_txt.split())) try: token = lower_txt.split()[0] if token == '#>' or token == u'#>': # logging.info("entering terminal command mode") self.msg_writer.write_terminal_command( lower_txt, channel_id ) return 0 # Do not continue execution except: pass # Return channel and user information if lower_txt == 'channelinfo': self.msg_writer.send_message(channel_id, channel_id) if lower_txt == 'userinfo': self.msg_writer.send_message(user_id, channel_id) if lower_txt == 'allusersinfo': self.user_manager.print_all_users(channel_id) # Loud addition and response if should_add_loud(event): self.msg_writer.write_loud(msg_txt) self.msg_writer.respond_loud(msg_txt, channel_id) if self._is_edited_with_star(msg_txt): self.msg_writer.write_spelling_mistake(channel_id, ts) # Respond to message text if re.search('i choose you', lower_txt): self.msg_writer.write_cast_pokemon(lower_txt, channel_id) if re.search('weather', lower_txt): self.msg_writer.write_weather(channel_id) if re.search('riri', lower_txt): self.msg_writer.write_riri_me(msg_txt, channel_id) if 'xkcd' in lower_txt: self.msg_writer.write_xkcd(lower_txt, channel_id) if ( 'tictactoe' in lower_txt or ' ttt' in lower_txt or lower_txt.startswith('ttt') ): self.tictactoe_manager.get_message( channel_id, lower_txt, user_name ) # Respond to message text with `bolton` included if is_bolton_mention(msg_txt) or self.clients.is_bot_mention(msg_txt): if re.search('erase|delete', lower_txt): self.msg_writer.erase_history( msg_txt, channel_id, ts ) if 'help' in lower_txt: self.msg_writer.write_help_message(channel_id) if 'joke' in lower_txt: self.msg_writer.write_joke(channel_id) if 'french' in lower_txt: self.msg_writer.write_french(msg_txt, channel_id) if re.search('who\'?s that pokemon', msg_txt): self.msg_writer.write_whos_that_pokemon(channel_id) if re.search(' ?bolton it\'?s', lower_txt): self.msg_writer.write_pokemon_guessed_response( msg_txt, channel_id, user_id ) if re.search('attachment|beep boop link', lower_txt): self.msg_writer.demo_attachment(channel_id) if 'sad ' in lower_txt: self.msg_writer.write_sad(channel_id) if 'sort me' in lower_txt: self.msg_writer.write_hogwarts_house( msg_txt, channel_id, user_id ) if re.search('encourage ', lower_txt): self.msg_writer.write_encouragement(msg_txt, channel_id) if 'sass ' in lower_txt: self.msg_writer.write_sass(msg_txt, channel_id) if 'solve' in lower_txt: self.msg_writer.write_solution(msg_txt, channel_id) if re.search('explain|why', lower_txt): self.msg_writer.write_explanation(channel_id) if re.search('sweetpotato|sweet potato', lower_txt): self.msg_writer.write_sweetpotato_me(msg_txt, channel_id) if re.search('draw me', lower_txt): self.msg_writer.write_draw_me(channel_id) if re.search('love|forever|relationship', lower_txt): self.msg_writer.write_forever(channel_id) if re.search('unflip', lower_txt): self.msg_writer.write_unflip(channel_id) elif re.search('flip|rageflip', lower_txt): self.msg_writer.write_flip(channel_id) if re.search('sup son', lower_txt): self.msg_writer.write_sup_son(channel_id) if lower_txt == "bolton": self.msg_writer.write_prompt(channel_id) else: pass
class TimeTriggeredEventManager(object): def __init__(self, clients, msg_writer, markov_chain): self.clients = clients self.msg_writer = msg_writer self.markov_chain = markov_chain self.channel_manager = ChannelManager(clients) self.random_manager = ResourceManager('random_comments.txt') self.trigger_startup_log() self.process_recent_messages() def send_message(self, msg_txt, channel=None): self.msg_writer.send_message(msg_txt, channel) def get_emoji(self): return self.clients.get_random_emoji() def clean_channels_history(self): result = 'Erased messages: ' testing_channel = self.channel_manager.get_channel_id(TESTING_CHANNEL) for channel_id in self.channel_manager.get_all_channel_ids(): if channel_id != testing_channel: count = self._erase_channel_messages(channel_id, log_days=3) if count != 0: result += '<#{}> ({}), '.format(str(channel_id), str(count)) if result.endswith(', '): result = result[:-2] else: result = 'No messages erased during general clean up' self.send_message(result) def clean_testing_channel_history(self): testing_channel = self.channel_manager.get_channel_id(TESTING_CHANNEL) total_count = 0 for num in range(10): count = self._erase_channel_messages(testing_channel, log_days=1) total_count += count if count == 0: break result = 'Erased {} total messages from <#{}> in {} passes'.format( str(total_count), str(testing_channel), str(num)) self.send_message(result) def _erase_channel_messages(self, channel_id, log_days=0): count = 0 now_ts = float(time.time()) response = self.clients.get_message_history(channel_id) if 'messages' in response: for message in response['messages']: if ('ts' in message and 'pinned_to' not in message and self.clients.is_message_from_me(message)): # Delete everything older than `log_days` old # Delete items older than a day old # Unless they are weather posts or startup logs # Always delete the message deletions messages if ((now_ts - (60 * 60 * 24 * log_days)) > float(message['ts']) or ((now_ts - (60 * 60 * 24)) > float(message['ts']) and not re.search(DONT_DELETE, message['text'].lower()) or (re.search("I SAW THAT! _Someone_ deleted a message", message['text'])))): self.clients.delete_message(channel_id, message['ts']) count += 1 return count def process_recent_messages(self): testing_channel = self.channel_manager.get_channel_id(TESTING_CHANNEL) count_markov = 0 count_louds = 0 for channel_id in self.channel_manager.get_all_channel_ids(): if channel_id != testing_channel: response = self.clients.get_message_history(channel_id) if 'messages' in response: for message in response['messages']: if not self.clients.is_message_from_me(message): if 'text' in message: msg_text = message['text'] # Add markovs if should_add_markov(message): self.markov_chain.add_single_line(msg_text) count_markov += 1 # Add louds if should_add_loud(message): self.msg_writer.write_loud(msg_text) count_louds += 1 result = ("Added " + str(count_markov) + " messages to markov " "and " + str(count_louds) + " loud messages") self.send_message(result) def trigger_random_markov(self): if random.random() < 0.15: channel_id = self.channel_manager.get_channel_id( 'boltonsexybutt-co') now_timestamp = float(time.time()) response = self.clients.get_message_history(channel_id, 1) if 'messages' in response: for message in response['messages']: if ('user' in message and 'ts' in message and not self.clients.is_message_from_me(message) and not contains_tag(message['text']) and 'markov' not in message['text']): # Post only 3 - 5 minutes after latest message if (now_timestamp - (60 * 5) <= float(message['ts']) and now_timestamp - (60 * 2) >= float(message['ts'])): try: txt = str(self.markov_chain) self.send_message(txt, 'boltonsexybutt-co') self.trigger_method_log('random markov') except Exception: err_msg = traceback.format_exc() logging.error( 'Unexpected error: {}'.format(err_msg)) self.msg_writer.write_error(err_msg) pass def trigger_morning(self): responses = [ "Good morning", "Morning", "Guten Morgen", "Bonjour", "Ohayou", "Good morning to you", "Aloha", "Konnichiwashington", "Buenos dias", "GLUTEN MORNING", ":sunny: Good morning", "Where have you been. MORNING" ] txt = '{}! :{}:'.format(random.choice(responses), self.get_emoji()) self.msg_writer.send_message_as_other(txt, 'boltonsexybutt-co', 'bolton', ':sunglasses:') # self.send_message(txt, 'boltonsexybutt-co') def trigger_markov(self): try: self.msg_writer.send_message(str(self.markov_chain), 'bolton_weather') except Exception: err_msg = traceback.format_exc() logging.error('Unexpected error: {}'.format(err_msg)) self.msg_writer.write_error(err_msg) pass def trigger_ping(self, day, hour, minute, second): msg = ('Ping on ' + day + ' ' + str(hour) + ':' + str(minute) + ':' + str(second) + ' :' + str(self.get_emoji()) + ':') self.send_message(msg) def trigger_method_log(self, method_name): msg = 'Event: {}'.format(method_name) self.send_message(msg) def trigger_startup_log(self): day, hour, minute, second = _get_datetime() msg = ('I came back to life on ' + day + ' ' + str(hour) + ':' + str(minute) + ':' + str(second) + ' :' + str(self.get_emoji()) + ':') self.send_message(msg) def trigger_wine_club(self): tags = ['channel', 'here'] msg = ("WINE CLUB IN THE LOUNGE :wine_glass: :wine_glass: " ":wine_glass: :wine_glass: :wine_glass:") txt = '<!{}> {}'.format(random.choice(tags), msg) self.msg_writer.send_message_as_other(txt, 'boltonsexybutt-co', 'bolton', ':wine_glass:') def trigger_random_phrase(self): if random.random() < 0.02: comment = self.random_manager.get_response() txt = '{} :{}:'.format(comment, self.get_emoji()) self.send_message(txt, 'boltonsexybutt-co') self.trigger_method_log('wine club') def trigger_weather(self): response = weather_manager.getCurrentWeather() self.send_message(response) def trigger_tuesday(self): txt = "DON'T FORGET IT'S TUESDAY _ALLL_ DAY TODAY" self.msg_writer.send_message_as_other(txt, 'boltonsexybutt-co', 'bolton', ':rolled_up_newspaper:') def trigger_945(self): kip_msgs = [ '@945', '945!', '#945', ':paw_prints: 945!', '~945~', ':horse: 945! giddyup', '945! :heart:', '945! :sweet_potato:', '945!........', '945 time', '945 quickie', '945 o\'clock', '945! :sheep: :panda_face: :slowpoke:', '945! :boom:', ':eggplant: 945.', '945 :coffee:', '_le 945_', '_le fast 945_' ] txt = '{} :{}:'.format(random.choice(kip_msgs), self.get_emoji()) self.msg_writer.send_message_as_other(txt, 'boltonsexybutt-co', 'bolton', ':boltonefron:') # self.send_message(txt, 'boltonsexybutt-co') def trigger_mochaccino(self): msgs = [ 'The mochaccino tastes _amazing_ this morning!', 'Eh, mochaccino ain\'t so great today...', 'HELP! MOCHACCINO EVERYWHERE!', ('The mochaccino machine won\'t stop dripping help I need an ' 'adult'), 'WHAT! wHY is my mochaccino _decaf_??!', 'I haven\'t had my mochaccino yet don\'t talk to me', 'WHERE\'S MY MUG I NEED MOCHACCINO!!', 'Mochaccino mochaccino mochaccino', 'Mochaccino is SO GOOD TODAY HOLY HELL', ('Today\'s mochaccino is like an angel pooped out a nice hot ' 'cup of coffee mmmmm~'), 'Mochaccino status: passable', 'MOCHACCINO MOCHACCINO MOCHACCINO!!!', 'Who\'s ready for a nice cup o\' mochaccino?', '_le mochaccino_' ] txt = '{} :coffee:'.format(random.choice(msgs)) self.msg_writer.send_message_as_other(txt, 'boltonsexybutt-co', 'bolton', ':coffee:') def trigger_timed_event(self): day, hour, minute, second = _get_datetime() # leaves 10-ish seconds to trigger since method is called every 10-ish # seconds and we wantz the if statement to trigger once per min only if (second >= 5 and second <= 15): # self.trigger_ping(day, hour, minute, second) if hour == 1: if minute == 15: self.clean_channels_history() if minute == 0 or minute == 30: self.clean_testing_channel_history() if hour % 3 == 0 and minute == 0: self.trigger_weather() if minute == 15: self.trigger_markov() if hour >= 9 and hour <= 16: self.trigger_random_markov() if (day != 'Saturday' and day != 'Sunday'): if hour == 8 and minute == 45: self.trigger_morning() if hour == 9: if minute == 45: self.trigger_945() elif minute == 0: self.trigger_mochaccino() if day == 'Friday': if hour == 16 and minute == 45: self.trigger_wine_club() if hour >= 17 and hour <= 18: self.trigger_random_phrase() if day == 'Tuesday': if hour == 14 and minute == 7: self.trigger_tuesday()
class SlackClients(object): def __init__(self, token): self.token = token # Slacker is a Slack Web API Client self.web = Slacker(token) # SlackClient is a Slack Websocket RTM API Client self.rtm = SlackClient(token) self.msg_writer = Messenger(self) self.channel_manager = ChannelManager(self) # Set up bot_id self.bot_id = None self.startUp() def startUp(self): response = self.send_message_as_other('Initializing bot_id...', TESTING_CHANNEL, 'bolton', ':boltonefron:') if self.bot_id is None and 'message' in response: message = response['message'] if 'bot_id' in message: self.bot_id = message['bot_id'] self.msg_writer.erase_history( 'bolton erase 1', self.channel_manager.get_channel_id(TESTING_CHANNEL), float(time.time())) # msg_text = 'Initialized bot_id: ' + self.bot_id # self.send_message(msg_text, TESTING_CHANNEL) def bot_user_id(self): return self.rtm.server.login_data['self']['id'] def is_message_from_me(self, message): if 'user' in message and message['user'] == self.bot_user_id(): return True elif ( 'bot_id' in message and self.bot_id is not None and (message['bot_id'] == self.bot_id # message['bot_id'] == 'B1S057DV0' or # message['bot_id'] == 'B15JNU2AU' )): return True return False def is_bot_mention(self, message): bot_user_name = self.rtm.server.login_data['self']['id'] if re.search("@{}".format(bot_user_name), message): return True else: return False def send_user_typing_pause(self, channel_id, sleep_time=3.0): user_typing_json = {"type": "typing", "channel": channel_id} self.rtm.server.send_to_websocket(user_typing_json) time.sleep(sleep_time) # this method only gets a team's custom emojis and NOT all slack emojis def get_random_emoji(self): response = self.rtm.api_call('emoji.list') emojis = response['emoji'].items() return emojis[int(random.random() * len(emojis))][0] def send_message_as_other(self, msg_text, channel_id, username, emoji): response = self.rtm.api_call('chat.postMessage', token=str(self.token), channel=channel_id, text=msg_text, link_names=1, username=username, unfurl_links=True, icon_emoji=emoji) # Make sure the message gets sent to bolton-testing at least if 'error' in response: response = str(response) + "\nOriginal message:\n" + msg_text self.send_message(response, TESTING_CHANNEL) return response def send_message(self, msg_text, channel): response = self.rtm.api_call('chat.postMessage', token=str(self.token), channel=channel, text=msg_text, as_user=True, link_names=1, unfurl_links=True) # Make sure the message gets sent to bolton-testing at least if 'error' in response: response = str(response) + "\nOriginal message:\n" + msg_text self.send_message(response, TESTING_CHANNEL) return response def update_message(self, updated_msg_text, channel, timestamp): response = self.rtm.api_call('chat.update', token=str(self.token), channel=channel, text=updated_msg_text, as_user=True, link_names=1, unfurl_links=True, ts=timestamp) # Make sure the message gets sent to bolton-testing at least if 'error' in response: response = (str(response) + "\nOriginal message:\n" + updated_msg_text) self.send_message(response, TESTING_CHANNEL) return response def get_message_history(self, channel_id, count=None): response = self.rtm.api_call('channels.history', token=str(self.token), channel=channel_id, count=count) if 'error' in response: error_msg = "`get_message_history` error:\n" + str(response) self.msg_writer.write_error(error_msg) return response def delete_message(self, channel_id, timestamp): response = self.rtm.api_call('chat.delete', token=str(self.token), channel=channel_id, as_user=True, ts=timestamp) if 'error' in response: error_msg = "`delete_message` error:\n" + str(response) self.msg_writer.write_error(error_msg) return response def send_attachment(self, txt, channel_id, attachment): # this does not return the response object that rtm does return self.web.chat.post_message(channel_id, txt, attachments=[attachment], as_user='******') def get_users(self): response = self.rtm.api_call('users.list', token=str(self.token)) if 'error' in response: error_msg = "`get_users` error:\n" + str(response) self.msg_writer.write_error(error_msg) return response def get_channels(self): response = self.rtm.api_call( 'channels.list', token=str(self.token), exclude_archived=1, ) if 'error' in response: error_msg = "`get_channels` error:\n" + str(response) self.msg_writer.write_error(error_msg) return response def get_groups(self): return self.rtm.api_call('groups.list', token=str(self.token)) def get_ims(self): return self.rtm.api_call('im.list', token=str(self.token)) def send_reaction(self, emoji_name, channel, timestamp): response = self.rtm.api_call("reactions.add", token=str(self.token), name=emoji_name, channel=channel, timestamp=timestamp) if 'error' in response and response['error'] != 'already_reacted': error_msg = "`send_reaction` error:\n" + str(response) self.msg_writer.write_error(error_msg) return response def upload_file_to_slack(self, filepath, filename, channel): my_file = os.path.join(filepath, filename) return self.web.files.upload(my_file, channels=channel)