def set_other_timeout_cb(bot, message, *args, **kwargs): ''' Update the timeout of any user. Specify user by id or nick. ''' if not isadmin(bot, message): return try: cmd = extract_query(message) cmdl = cmd.split() is_id = operator.methodcaller('isdigit') if is_id(cmdl[0]): id_ = int(cmdl[0]) else: try: id_ = nick_to_id(bot, cmdl[0]) except KeyError: return 'Unknown nick.' timeout = int(cmdl[1]) bot.cursor.execute('UPDATE users SET timeout = ? WHERE id = ?', (timeout, id_)) bot.conn.commit() return 'Timeout for user {} updated to {}'.format(id_, timeout) except ValueError: return 'IT BROKE'
def wolfram_cb(bot, message, *args, **kwargs): ''' (Attempt to) answer query using the WolframAlpha API. Results may not be interpreted as you'd expect, open link for explanation. ''' if not CLIENT: return _('Not connected to WolframAlpha!') query = extract_query(message) LOGGER.debug('Query to WolframAlpha: %s', query) entity = OutgoingChatstateProtocolEntity( ChatstateProtocolEntity.STATE_TYPING, message.getFrom()) bot.toLower(entity) result = CLIENT.query(query) entity = OutgoingChatstateProtocolEntity( ChatstateProtocolEntity.STATE_PAUSED, message.getFrom()) bot.toLower(entity) restext = _('Result from WolframAlpha:\n') results = [ p.text.encode('utf-8') for p in result.pods if p.title in ('Result', 'Value', 'Decimal approximation', 'Exact result') ] if not results: return _('No result.') restext += '\n'.join(results) + '\n' restext += 'Link: https://wolframalpha.com/input/?i={}'.format( urllib.quote(query).replace('%20', '+')) return restext
def list_other_nicks_cb(bot, message, *args, **kwargs): ''' List all nicks of another user. Specify user by id or nick. ''' cmd = extract_query(message) if IS_ID(cmd): bot.cursor.execute( 'SELECT id,jid,lastactive,primary_nick FROM users WHERE id = ?', (cmd,)) else: try: userjid = nick_to_jid(bot, cmd) bot.cursor.execute( 'SELECT id,jid,lastactive,primary_nick FROM users WHERE jid = ?', (userjid,)) except KeyError: return 'Unknown (nick)name' result = bot.cursor.fetchone() if not result: return 'Unknown ID' # nick resolution errors earlier reply = 'Nicks for {} ({}/{}):\n'.format(result[3], result[1], result[0]) bot.cursor.execute('SELECT name FROM nicks WHERE jid = ?', (result[1],)) results = bot.cursor.fetchall() for row in results: reply = reply + row[0] + ' ' return reply
def list_other_nicks_cb(bot, message, *args, **kwargs): ''' List all nicks of another user. Specify user by id or nick. ''' cmd = extract_query(message) if IS_ID(cmd): bot.cursor.execute( 'SELECT id,jid,lastactive,primary_nick FROM users WHERE id = ?', (cmd, )) else: try: userjid = nick_to_jid(bot, cmd) bot.cursor.execute( 'SELECT id,jid,lastactive,primary_nick FROM users WHERE jid = ?', (userjid, )) except KeyError: return 'Unknown (nick)name' result = bot.cursor.fetchone() if not result: return 'Unknown ID' # nick resolution errors earlier reply = 'Nicks for {} ({}/{}):\n'.format(result[3], result[1], result[0]) bot.cursor.execute('SELECT name FROM nicks WHERE jid = ?', (result[1], )) results = bot.cursor.fetchall() for row in results: reply = reply + row[0] + ' ' return reply
def wolfram_cb(bot, message, *args, **kwargs): ''' (Attempt to) answer query using the WolframAlpha API. Results may not be interpreted as you'd expect, open link for explanation. ''' if not CLIENT: return _('Not connected to WolframAlpha!') query = extract_query(message) LOGGER.debug('Query to WolframAlpha: %s', query) entity = OutgoingChatstateProtocolEntity( ChatstateProtocolEntity.STATE_TYPING, message.getFrom()) bot.toLower(entity) result = CLIENT.query(query) entity = OutgoingChatstateProtocolEntity( ChatstateProtocolEntity.STATE_PAUSED, message.getFrom()) bot.toLower(entity) restext = _('Result from WolframAlpha:\n') results = [p.text.encode('utf-8') for p in result.pods if p.title in ('Result', 'Value', 'Decimal approximation', 'Exact result')] if not results: return _('No result.') restext += '\n'.join(results) + '\n' restext += 'Link: https://wolframalpha.com/input/?i={}'.format( urllib.quote(query).replace('%20', '+')) return restext
def duckduckgo_cb(bot, message, *args, **kwargs): ''' Answer query using DuckDuckGo. ''' try: query = extract_query(message) return duckduckgo.get_zci(query) except ValueError: return 'Sorry, no results.' except AttributeError: return 'Sorry, no results.'
def help_cb(bot, message, *args, **kwargs): ''' Give moral and spiritual guidance in using this bot. When you select one command, a longer text will be sent! ''' cmd = extract_query(message) if not cmd: return HELP_OVERVIEW else: try: return pydoc.getdoc(COMMAND_DICT[cmd.upper()]) except KeyError: return 'Sorry, that command is not known.'
def set_own_timeout_cb(bot, message, *args, **kwargs): ''' Update your mention timeout. Your timeout is the amount of time (in seconds) that has to elapse before you receive @mentions. A value of 0 means you receive all mentions. ''' try: cmd = extract_query(message) timeout = int(cmd) bot.cursor.execute('UPDATE users SET timeout = ? WHERE jid = ?', (timeout, determine_sender(message))) bot.conn.commit() return 'Ok' except ValueError: LOGGER.error('Timeout set failure: %s', cmd) return 'IT BROKE'
def diceroll_cb(bot, message, *args, **kwargs): ''' Roll some dice! Usage: include a 'XdY' pattern somewhere in your message, optionally followed by a modifier. Examples: - roll 1d6 -> rolls one six-sided die - roll 2d10 + 5 -> rolls two ten-sided dice, adds up the result, and adds 5 Supported operators are: +, -, /, *, % (modulo), ^ (power). ''' query = extract_query(message) match = DICE_PATTERN.search(query) if match is None: return number = int(match.group('number')) sides = int(match.group('sides')) if sides < 0 or number < 0: return # Maar hoe dan if number > 50 and message.participant: return # Probably spam results = [] for _ in xrange(number): results.append(random.randint(1, sides)) result = '' for item in results: result = result + str(item) result = result + ' + ' result = result.rstrip(' + ') som = sum(results) if len(results) > 1: result = result + ' = ' + str(som) if match.group(3) != None: try: modresult = DICE_MODIFIER_OPERATORS[match.group('operator')]( som, int(match.group('modifier'))) result = '{orig}, {som} {operator} {modifier} = {modresult}'.format( orig=result, som=som, operator=match.group('operator'), modifier=match.group('modifier'), modresult=modresult) except KeyError: pass # unrecognized operator, skip modifier return result
def addreminder_cb(bot, message, *args, **kwargs): ''' (Hopefully) sends user a message at the given time ''' body = extract_query(message) timespec = body.split()[0] try: trytime = dateutil.parser.parse(body, parserinfo=datefinder.BPI, fuzzy=True) except ValueError: trytime = datetime.datetime( 1970, 1, 1) # job is dropped if no other date is found delta = None if timespec in datefinder.DURATION_MARKERS or datefinder.STRICT_CLOCK_REGEX.match( timespec): try: delta = datetime.datetime.now() + datefinder.find_timedelta(body) except ValueError: delta = None elif timespec in datefinder.CLOCK_MARKERS: try: trytime = datefinder.find_first_time(body) except ValueError: LOGGER.error('Cannot find time in "%s"', body) if delta: deadline = delta else: deadline = trytime if deadline < datetime.datetime.now(): LOGGER.error('Parsing %s failed, invalid deadline') return 'Sorry, limitations prevent parsing that kind of time.' LOGGER.debug('Parsed reminder command "%s"', body) LOGGER.info('Deadline %s from message "%s".', deadline, body) reply = 'Reminder set for {}.'.format(deadline) replymessage = TextMessageProtocolEntity(to=determine_sender(message), body=reply) bot.toLower(replymessage) bot.scheduler.add_job(rpc.remote_send, 'date', [body, determine_sender(message)], run_date=deadline) return
def remove_own_nick_cb(bot, message, *args, **kwargs): ''' Remove one of your nicks. Specify a nick by id (see mynicks) or the nick itself. ''' cmd = extract_query(message) if IS_ID(cmd): bot.cursor.execute('SELECT id,name,jid FROM nicks WHERE id = ?', (cmd, )) else: bot.cursor.execute('SELECT id,name,jid FROM nicks WHERE name = ?', (cmd, )) result = bot.cursor.fetchone() if result is None: return 'Unknown nick' if result[2] != determine_sender(message): return 'That\'s not you' bot.cursor.execute('DELETE FROM nicks WHERE id = ?', (result[0], )) bot.conn.commit() LOGGER.info('Nick %s removed.', cmd) return 'Nick {} removed.'.format(cmd)
def add_own_nick_cb(bot, message, *args, **kwargs): ''' Add a new nick to yourself. Nicknames can be removed using 'rmnick'. ''' cmd = extract_query(message) cmdl = cmd.split() sender = determine_sender(message) newnick = cmdl[0].lower() if len(newnick) > 16: return 'Too long' if IS_ID(newnick): return 'Pls' try: LOGGER.info('Nick %s added to jid %s', newnick, sender) bot.cursor.execute('INSERT INTO nicks (name, jid) VALUES (?,?)', (newnick, sender)) bot.conn.commit() return 'Ok.' except sqlite3.IntegrityError: return 'Nick exists'
def anonsend_cb(bot, message, *args, **kwargs): ''' Send a mention under the group name and not the author's name ''' if not message.participant: return try: groupname = jid_to_nick(bot, message.getFrom()) except KeyError: return 'This group is not enrolled in the BrotherBother program, sorry' text = extract_query(message, 2) body = '{}: {}'.format(groupname, text) # Who was mentioned? nick = message.getBody().split()[2] try: recipient = nick_to_jid(bot, nick) except KeyError: return 'Unknown recipient!' entity = TextMessageProtocolEntity(body, to=recipient) bot.toLower(entity)
def addreminder_cb(bot, message, *args, **kwargs): ''' (Hopefully) sends user a message at the given time ''' body = extract_query(message) timespec = body.split()[0] try: trytime = dateutil.parser.parse(body, parserinfo=datefinder.BPI, fuzzy=True) except ValueError: trytime = datetime.datetime(1970, 1, 1) # job is dropped if no other date is found delta = None if timespec in datefinder.DURATION_MARKERS or datefinder.STRICT_CLOCK_REGEX.match(timespec): try: delta = datetime.datetime.now() + datefinder.find_timedelta(body) except ValueError: delta = None elif timespec in datefinder.CLOCK_MARKERS: try: trytime = datefinder.find_first_time(body) except ValueError: LOGGER.error('Cannot find time in "%s"', body) if delta: deadline = delta else: deadline = trytime if deadline < datetime.datetime.now(): LOGGER.error('Parsing %s failed, invalid deadline') return 'Sorry, limitations prevent parsing that kind of time.' LOGGER.debug('Parsed reminder command "%s"', body) LOGGER.info('Deadline %s from message "%s".', deadline, body) reply = 'Reminder set for {}.'.format(deadline) replymessage = TextMessageProtocolEntity( to=determine_sender(message), body=reply) bot.toLower(replymessage) bot.scheduler.add_job( rpc.remote_send, 'date', [body, determine_sender(message)], run_date=deadline) return
def register_user_cb(bot, message, *args, **kwargs): ''' Assign a primary nick to a user. ''' if not isadmin(bot, message): return cmd = extract_query(message) try: cmdl = cmd.split() id_ = int(cmdl[0]) name = cmdl[1] bot.cursor.execute('UPDATE users SET primary_nick = ? WHERE id = ?', (name, id_)) bot.conn.commit() LOGGER.info(bot.cursor.rowcount) LOGGER.info('User %s registered as %s.', id_, name) return 'Ok' except IndexError as ex: LOGGER.warning('Invalid message') LOGGER.warning(ex) return 'Malformed command' except sqlite3.IntegrityError as ex: LOGGER.error('Error during register') LOGGER.error(ex) return 'Error'
def remove_own_nick_cb(bot, message, *args, **kwargs): ''' Remove one of your nicks. Specify a nick by id (see mynicks) or the nick itself. ''' cmd = extract_query(message) if IS_ID(cmd): bot.cursor.execute('SELECT id,name,jid FROM nicks WHERE id = ?', (cmd,)) else: bot.cursor.execute('SELECT id,name,jid FROM nicks WHERE name = ?', (cmd,)) result = bot.cursor.fetchone() if result is None: return 'Unknown nick' if result[2] != determine_sender(message): return 'That\'s not you' bot.cursor.execute('DELETE FROM nicks WHERE id = ?', (result[0],)) bot.conn.commit() LOGGER.info('Nick %s removed.', cmd) return 'Nick {} removed.'.format(cmd)