def _hype_stats_command(self, session: InboundMessageSession): stats_filename = self._config.get('hype_stats_filename') if not stats_filename or \ stats_filename and not os.path.exists(stats_filename): session.reply('{} This command is currently unavailable!'.format( gen_roar())) return try: with open(stats_filename) as file: doc = json.load(file) text_1 = '[{duration}] Lines/sec {averages_str} ' \ '· Hints/sec {hint_averages_str}'.format( duration=doc['stats']['duration'], averages_str=doc['stats']['averages_str'], hint_averages_str=doc['stats']['hint_averages_str'], ) text_2 = 'Chat {chat_graph} · Hint {hint_graph}'.format( chat_graph=doc['stats']['chat_graph'], hint_graph=doc['stats']['hint_graph'], ) except (ValueError, KeyError, IndexError): _logger.exception('Error formatting stats') else: session.say(text_1) session.say(text_2)
def _debug_echo_command(self, session: InboundMessageSession): text = session.match.group(1).strip() formatted_text = '{} {} {}'.format( gen_roar(), self._censor_text(session, text), self._censor_text(session, text, extra_censor=True)) session.reply(formatted_text, escape_links=True)
def _try_say_or_reply_too_long(cls, formatted_text, session: InboundMessageSession): if cls.is_too_long(formatted_text): session.reply(cls.TOO_LONG_TEXT_TEMPLATE.format(gen_roar())) return False else: session.say(formatted_text) return True
def _mail_status_command(self, session: InboundMessageSession): unread_count = self._database.get_status_count("unread") read_count = self._database.get_status_count("read") session.reply( "{roar} {unread} unread, {read} read, {total} total!".format( roar=gen_roar(), unread=unread_count, read=read_count, total=unread_count + read_count ) )
def _mail_status_command(self, session: InboundMessageSession): unread_count = self._database.get_status_count('unread') read_count = self._database.get_status_count('read') session.reply( '{roar} {unread} unread, {read} read, {total} total!'.format( roar=gen_roar(), unread=unread_count, read=read_count, total=unread_count + read_count))
def _wow_command(self, session: InboundMessageSession): if self._tellnext_generator: platform_name = session.get_platform_name() max_len = 500 if platform_name == 'discord' else 400 session.say('> {}'.format( self._censor_text( session, self._tellnext_generator.get_paragraph(max_len))), multiline=True) else: session.reply('{} Feature not available!'.format(gen_roar()))
def _mail_command(self, session: InboundMessageSession): if session.message['channel'] in self._mail_disabled_channels: session.reply('{} My mail services cannot be used here.'.format( gen_roar().replace('!', '.'))) return mail_text = session.match.group(2).strip() if mail_text: self._send_mail(mail_text, session) else: self._read_mail(session)
def _send_mail(self, mail_text: str, session: InboundMessageSession): if len(mail_text) > self.MAIL_MAX_LEN: session.reply('{} Your message is too burdensome! ' 'Send a concise version instead. ' '({}/{})'.format(gen_roar(), len(mail_text), self.MAIL_MAX_LEN)) return try: platform_name = session.get_platform_name() username = '******'.format(session.message['username'], session.message['user_id'] or '', platform_name) self._database.put_mail(username, mail_text, session.message['channel']) except SenderOutboxFullError: session.reply('{} How embarrassing! Your outbox is full!'.format( gen_roar())) except MailbagFullError: session.reply( '{} Incredulous! My mailbag is full! Read one instead!'.format( gen_roar())) else: session.reply('Tremendous! I will deliver this mail to the next ' 'recipient without fail! {}'.format(gen_roar()))
def _greeting_command(self, session: InboundMessageSession): is_set = session.match.group(1) text = session.match.group(3).strip() if is_set: self._database.set_greeting( session.message['channel'], session.message['user_id'] or session.message['username'], text) session.reply('{} Greeting saved'.format(gen_roar())) else: greeting = self._database.get_greeting(session.message['channel']) if greeting: formatted_text = '{} {}'.format(gen_roar(), greeting) else: formatted_text = '{}'.format(gen_roar()) session.say(formatted_text, multiline=True)
def _generate_match_command(self, session: InboundMessageSession): if not self._match_generator: session.reply("{} Feature not available!".format(gen_roar())) return args = session.match.group(1).lower().split() try: session.reply("{} {}".format(gen_roar(), self._match_generator.get_match_string(args))) except MatchError as error: session.reply("{} An error generating a match: {}".format(gen_roar(), error)) except (ValueError, IndexError, TypeError): _logger.exception("Generate match error") session.reply("{} An error occurred when generating a match!".format(gen_roar()))
def _try_say_or_reply_too_long(self, formatted_text, session: InboundMessageSession): platform_name = session.get_platform_name() if platform_name == 'twitch' and self._bot.twitch_char_limit: max_length = 500 max_byte_length = 1800 elif platform_name == 'discord': max_length = 2000 max_byte_length = max_length * 4 else: max_length = 400 max_byte_length = 400 if len(formatted_text) > max_length or self.is_too_long( formatted_text, max_byte_length): session.reply(self.TOO_LONG_TEXT_TEMPLATE.format(gen_roar())) return False else: session.say(formatted_text) return True
def _mail_status_command(self, session: InboundMessageSession): unread_count = self._database.get_status_count('unread') read_count = self._database.get_status_count('read') channel = session.message['channel'] disabled = channel in self._mail_disabled_channels restricted = channel in self._config.get('mail_restricted_channels', ()) session.reply( '{roar} {unread} unread, {read} read, {total} total! ' '(Channel={channel}, Disabled={disabled}, Restricted={restricted})' .format( roar=gen_roar(), unread=unread_count, read=read_count, total=unread_count + read_count, channel=channel, disabled=disabled, restricted=restricted, ))
def _donation_trigger(self, session: InboundMessageSession): points = session.match.group(1).replace('.', '').replace(',', '') + '0' minutes = _random.randint(20, 1200) / 10 formatted_text = '{} {} {} {}'.format( _random.choice([ 'Thanks for donating!', 'Thank you for your donation!', 'Thank you for donating!' ]), _random.choice([ 'You gained {} points.'.format(points), 'You now have {} points.'.format(points), 'Your balance is now {} points.'.format(points), ]), _random.choice([ 'Your donation will be read by the streamer in {} minutes.'. format(minutes), 'Your donation has been queued. ' '{} donations waiting to be read.'.format(int(minutes)), 'Please wait {} minutes for your donation to be processed.'. format(minutes), ]), _random.choice(['<3', '<3', ':)', ':)', ':o'])) session.reply(formatted_text)
def _hype_stats_command(self, session: InboundMessageSession): stats_filename = self._config.get("hype_stats_filename") if not stats_filename or stats_filename and not os.path.exists(stats_filename): session.reply("{} This command is currently unavailable!".format(gen_roar())) return try: with open(stats_filename) as file: doc = json.load(file) text_1 = "[{duration}] Lines/sec {averages_str} " "· Hints/sec {hint_averages_str}".format( duration=doc["stats"]["duration"], averages_str=doc["stats"]["averages_str"], hint_averages_str=doc["stats"]["hint_averages_str"], ) text_2 = "Chat {chat_graph} · Hint {hint_graph}".format( chat_graph=doc["stats"]["chat_graph"], hint_graph=doc["stats"]["hint_graph"] ) except (ValueError, KeyError, IndexError): _logger.exception("Error formatting stats") else: session.say(text_1) session.say(text_2)
def _generate_match_command(self, session: InboundMessageSession): if not self._match_generator: session.reply('{} Feature not available!'.format(gen_roar())) return args = session.match.group(1).lower().split() try: session.reply('{} {}'.format( gen_roar(), self._match_generator.get_match_string(args))) except MatchError as error: session.reply('{} An error generating a match: {}'.format( gen_roar(), error)) except (ValueError, IndexError, TypeError): _logger.exception('Generate match error') session.reply( '{} An error occurred when generating a match!'.format( gen_roar()))
def _mail_command(self, session: InboundMessageSession): if session.message['channel'] in self._mail_disabled_channels: session.reply('{} My mail services cannot be used here.'.format( gen_roar().replace('!', '.'))) return mail_text = session.match.group(2).strip() if mail_text: if len(mail_text) > self.MAIL_MAX_LEN: session.reply('{} Your message is too burdensome! ' 'Send a concise version instead. ' '({}/{})'.format(gen_roar(), len(mail_text), self.MAIL_MAX_LEN)) return try: self._database.put_mail(session.message['username'], mail_text) except SenderOutboxFullError: session.reply( '{} How embarrassing! Your outbox is full!'.format( gen_roar())) except MailbagFullError: session.reply( '{} Incredulous! My mailbag is full! Read one instead!'. format(gen_roar())) else: session.reply( 'Tremendous! I will deliver this mail to the next ' 'recipient without fail! {}'.format(gen_roar())) else: if _random.random() < 0.3: mail_info = self._database.get_old_mail() else: if _random.random() < 0.7: skip_username = session.message['username'] else: skip_username = None mail_info = self._database.get_mail( skip_username=skip_username) if not mail_info and _random.random() < 0.3: mail_info = self._database.get_old_mail() if not mail_info: session.reply( '{} Outlandish! There is no new mail! You should send some!' .format(gen_roar())) else: session.reply( '{roar} I am delivering mail! ' 'Here it is, {date}, from {username}: {msg}'.format( roar=gen_roar(), username=mail_info['username'].title(), date=arrow.get(mail_info['timestamp']).humanize(), msg=mail_info['text']), multiline=True)
def _regex_command(self, session: InboundMessageSession): channel = session.message["channel"] if self._avoid_pikalaxbot and "pikalaxbot" in self._user_list[channel]: session.skip_rate_limit = True return # Special split http://stackoverflow.com/a/21107911/1524507 parts = re.split(r"(?<!\\)/", session.match.group(1)) if not (2 <= len(parts) <= 3): return search_pattern = parts[0] replacement = parts[1] options = parts[2] if len(parts) == 3 else "" flags = 0 count = 1 if "i" in options: flags |= re.IGNORECASE if "g" in options: count = 0 try: pattern = re.compile(search_pattern, flags) except re.error as error: session.reply("{} {}!".format(gen_roar(), error.args[0].title())) return for history_message in reversed(self._recent_messages_for_regex[session.message["channel"]]): text = history_message["text"] channel = session.message["channel"] if text.startswith("s/"): continue try: matched = self._regex_server.search(pattern, text) except RegexTimeout: _logger.warning("Regex DoS by %s on %s", session.message["username"], session.message["channel"]) session.reply(gen_roar().upper()) return if matched: try: new_text = pattern.sub(replacement, text, count=count) except re.error as error: session.reply("{} {}!".format(gen_roar(), error.args[0].title())) return if _random.random() < 0.05: new_text = gen_roar() fake_out = True else: fake_out = False formatted_text = "{user} wishes to {stacked}correct " "{target_user}: {text}".format( user=session.message["nick"], target_user=history_message["nick"], text=new_text, stacked="re" if history_message.get("stacked") else "", ) ok = self._try_say_or_reply_too_long(formatted_text, session) if not ok: return if not fake_out: stacked_message = copy.copy(history_message) stacked_message["text"] = new_text stacked_message["stacked"] = True self._recent_messages_for_regex[channel].append(stacked_message) return session.reply("{} Your request does not apply to any recent messages!".format(gen_roar()))
def _regex_command(self, session: InboundMessageSession): channel = session.message['channel'] if self._avoid_pikalaxbot and 'pikalaxbot' in self._user_list[channel]: session.skip_rate_limit = True return # Special split http://stackoverflow.com/a/21107911/1524507 parts = re.split(r'(?<!\\)/', session.match.group(1)) if not (2 <= len(parts) <= 3): return search_pattern = parts[0] replacement = parts[1].replace('\\/', '/') options = parts[2] if len(parts) == 3 else '' flags = 0 count = 1 if 'i' in options: flags |= re.IGNORECASE if 'g' in options: count = 0 try: pattern = re.compile(search_pattern, flags) except re.error as error: session.reply('{} {}!'.format(gen_roar(), error.args[0].title())) return for history_message in reversed( self._recent_messages_for_regex[session.message['channel']]): text = history_message['text'] channel = session.message['channel'] if text.startswith('s/') or text.startswith('!s/'): continue try: matched = self._regex_server.search(pattern, text) except RegexTimeout: _logger.warning('Regex DoS by %s on %s', session.message['username'], session.message['channel']) session.reply(gen_roar().upper()) return if matched: try: new_text = pattern.sub(replacement, text, count=count) except re.error as error: session.reply('{} {}!'.format(gen_roar(), error.args[0].title())) return if _random.random() < 0.05: new_text = gen_roar() fake_out = True else: fake_out = False formatted_text = '{user} wishes to {stacked}correct ' \ '{target_user}: {text}'.format( user=session.message['nick'], target_user=history_message['nick'], text=new_text, stacked='re' if history_message.get('stacked') else '', ) ok = self._try_say_or_reply_too_long(formatted_text, session) if not ok: return if not fake_out: stacked_message = copy.copy(history_message) stacked_message['text'] = new_text stacked_message['stacked'] = True self._recent_messages_for_regex[channel].append( stacked_message) return session.reply( '{} Your request does not apply to any recent messages!'.format( gen_roar()))
def _wow_command(self, session: InboundMessageSession): if self._tellnext_generator: session.say("> {}".format(self._tellnext_generator.get_paragraph())) else: session.reply("{} Feature not available!".format(gen_roar()))
def _help_command(self, session: InboundMessageSession): session.reply('{} {}'.format(gen_roar(), self._help_text), escape_links=True)
def _wow_command(self, session: InboundMessageSession): if self._tellnext_generator: session.say('> {}'.format( self._tellnext_generator.get_paragraph())) else: session.reply('{} Feature not available!'.format(gen_roar()))
def _read_mail(self, session: InboundMessageSession): platform_name = session.get_platform_name() if _random.random() < 0.95: skip_username = session.message['username'] skip_user_id = '{}@{}'.format(session.message['user_id'], platform_name) else: skip_username = None skip_user_id = None channel = None if session.message['channel'] in self._config.get( 'mail_restricted_channels', ()): channel = session.message['channel'] _logger.debug('Restricting mail to channel %s', channel) mail_info = None if _random.random() < 0.3: mail_info = self._database.get_old_mail( skip_username=skip_username, skip_user_id=skip_user_id, channel=channel) if not mail_info: mail_info = self._database.get_mail(skip_username=skip_username, skip_user_id=skip_user_id) if not mail_info and _random.random() < 0.6: mail_info = self._database.get_old_mail() if not mail_info: session.reply( '{} Outlandish! There is no new mail! You should send some!'. format(gen_roar())) else: # From Discord proxy, space is escaped to \s and # lowercase to |s via IRC rules username = mail_info['username'].split('!', 1)[0]\ .replace('|s', ' ').title() username_extra = '' sender_platform = mail_info['username'].partition( '@')[-1] or 'twitch' if platform_name != sender_platform: username_extra = ' ({})'.format(sender_platform.title()) session.reply( '{roar} I am delivering mail! ' 'Here it is, {date}, from {username}{username_extra}: {msg}'. format(roar=gen_roar(), username=username, username_extra=username_extra, date=arrow.get(mail_info['timestamp']).humanize(), msg=self._censor_text( session, mail_info['text'], extra_censor=True if channel else False)), multiline=True, escape_links=True, )
def _help_command(self, session: InboundMessageSession): session.reply("{} {}".format(gen_roar(), self._help_text))
def _mail_command(self, session: InboundMessageSession): if session.message["channel"] in self._mail_disabled_channels: session.reply("{} My mail services cannot be used here.".format(gen_roar().replace("!", "."))) return mail_text = session.match.group(2).strip() if mail_text: if len(mail_text) > self.MAIL_MAX_LEN: session.reply( "{} Your message is too burdensome! " "Send a concise version instead. " "({}/{})".format(gen_roar(), len(mail_text), self.MAIL_MAX_LEN) ) return try: self._database.put_mail(session.message["username"], mail_text) except SenderOutboxFullError: session.reply("{} How embarrassing! Your outbox is full!".format(gen_roar())) except MailbagFullError: session.reply("{} Incredulous! My mailbag is full! Read one instead!".format(gen_roar())) else: session.reply( "Tremendous! I will deliver this mail to the next " "recipient without fail! {}".format(gen_roar()) ) else: if _random.random() < 0.3: mail_info = self._database.get_old_mail() else: if _random.random() < 0.7: skip_username = session.message["username"] else: skip_username = None mail_info = self._database.get_mail(skip_username=skip_username) if not mail_info and _random.random() < 0.3: mail_info = self._database.get_old_mail() if not mail_info: session.reply("{} Outlandish! There is no new mail! You should send some!".format(gen_roar())) else: session.reply( "{roar} I am delivering mail! " "Here it is, {date}, from {username}: {msg}".format( roar=gen_roar(), username=mail_info["username"].title(), date=arrow.get(mail_info["timestamp"]).humanize(), msg=mail_info["text"], ), multiline=True, )