def getStrength(house, status, requester): reply = '' if houseIsValid(house) and statusIsValid(status): # get total house strength (status-independent) house_strength = students.count({'house': house}) # get modal house strength (status-dependent) and build reply if status in ['present', 'absent']: status_strength = students.count({ 'house': house, 'status': status }) reply += 'Strength for \'%s\' in \'%s\': %d/%d' % ( status, house, status_strength, house_strength) else: reply += 'Total strength for \'%s\' house is %d' % (house, house_strength) else: # catch shitty parameters logger.info('%s: /strength query failed (invalid parameters)' % whoIs(requester)) return 'Invalid house or status. See \'/help strength\'' logger.info('%s: Returning strength for \'%s\' house' % (whoIs(requester), house)) return reply
def updater(cg, name, field, content, requester): reply = 'Updating \'%s\' for \'%s\' in \'%s\' cg.\n\n' % (field, name, cg) if cgIsValid(cg): # check if result was found if cgls.find({'name': name, 'cg': cg}) == None: # no results reply += 'Could not find \'%s\' from \'%s\' cg.' % (name, cg) else: # got results if fieldIsValid(field) and field != 'cg': logger.info( '%s: Updating \'%s\' for \'%s\' in \'%s\' with: \'%s\'' % (whoIs(requester), field, name, cg, content)) cgls.update_one({ 'name': name, 'cg': cg }, {'$set': { field: content }}) # perform update reply += 'Successfully updated \'%s\' field for \'%s\' in \'%s\' with: \'%s\'' % ( field, name, cg, content) else: reply += 'Invalid field.' return reply
def updater(house, name, field, content, requester): reply = 'Updating \'%s\' for \'%s\' in \'%s\' house.\n\n' % (field, name, house) if houseIsValid(house): # check if result was found if students.find_one({'name': name, 'house': house}) == None: # no results reply += 'Could not find \'%s\' from \'%s\' house.' % (name, house) else: # got results if fieldIsValid(field) and field != 'house': logger.info( '%s: Updating \'%s\' for \'%s\' in \'%s\' with: \'%s\'' % (whoIs(requester), field, name, house, content)) students.update_one({ 'name': name, 'house': house }, {'$set': { field: content }}) # perform update reply += 'Successfully updated \'%s\' field for \'%s\' in \'%s\' with: \'%s\'' % ( field, name, house, content) else: reply += 'Invalid field.' return reply
def find(house, pattern, verbose, requester): reply = '' if houseIsValid(house): # query for database cursor results = students.find( {'name': { '$regex': '.*' + pattern + '.*'}, 'house': house } ) # sort results results.sort( [ ('color', -1), ('name', 1) ] ) # what info to send back (determined by verbose flag) if verbose is True: details = ['name', 'house', 'status', 'diet', 'medical', 'addedby'] else: details = ['name', 'house', 'status'] # build the reply reply += 'Finding any names containing \'%s\' for \'%s\'\n\n' % (pattern, house) reply += enumerator(results, details) else: # catch shitty parameters logger.info('%s: /find query failed (invalid parameters)' % whoIs(requester)) return 'Invalid house. See \'/help find\'' logger.info('%s: Returning find query for pattern \'%s\' for \'%s\'' % (whoIs(requester), pattern, house)) return reply
def find(cg, pattern, requester): reply = '' if cgIsValid(cg): # query for database cursor results = cgls.find({ 'name': { '$regex': '.*' + pattern + '.*' }, 'cg': cg }) # sort results results.sort([('name', 1)]) details = ['name', 'chatID'] # build the reply reply += 'Finding any names containing \'%s\' for \'%s\'\n\n' % ( pattern, cg) reply += enumerator(results, details) else: # catch shitty parameters logger.info('%s: /find query failed (invalid parameters)' % whoIs(requester)) return 'Invalid cg. See \'/help find\'' logger.info('%s: Returning find query for pattern \'%s\' for \'%s\'' % (whoIs(requester), pattern, cg)) return reply
def find(house, pattern, verbose, requester): reply = '' if houseIsValid(house): # query for database cursor results = students.find({ 'name': { '$regex': '.*' + pattern + '.*' }, 'house': house }) # sort results results.sort([('color', -1), ('name', 1)]) # what info to send back (determined by verbose flag) if verbose is True: details = ['name', 'house', 'status', 'diet', 'medical', 'addedby'] else: details = ['name', 'house', 'status'] # build the reply reply += 'Finding any names containing \'%s\' for \'%s\'\n\n' % ( pattern, house) reply += enumerator(results, details) else: # catch shitty parameters logger.info('%s: /find query failed (invalid parameters)' % whoIs(requester)) return 'Invalid house. See \'/help find\'' logger.info('%s: Returning find query for pattern \'%s\' for \'%s\'' % (whoIs(requester), pattern, house)) return reply
def updateAttendanceLog(house, name, isIn, requester): if houseIsValid(house): if isIn == True: entry = 'In @ %s' % makeTimestamp() else: entry = 'Out @ %s' % makeTimestamp() students.update_one( {'name': name, 'house': house}, { '$push': {'statuslog': entry} } ) logger.info('%s: Appended status log entry to \'%s\' from \'%s\'' % (whoIs(requester), name.title(), house.title()))
def setAttendanceDoneForEvent(cg, isFirstTry): logger.info('%s has added its attendance record.' % cg) isit = False if lastToSubmitAttendance(): isit = True # subsequent tries will not increment the tally count, allowing CGs to edit their attendance before all CGs have submitted. if isFirstTry: events.update_one({'done': False}, {'$inc': {'tally': 1}}) return isit
def remove(house, name, requester): reply = 'Removed \'%s\' of \'%s\' house from database.' % (name, house) # perform remove if students.find( {'name': name, 'house': house }).count() == 0: return 'No such record found.' elif students.find( {'name': name, 'house': house }).count() == 1: students.remove( {'name': name, 'house': house}, 1 ) logger.info(whoIs(requester) + ': ' + reply) return reply return 'Multiple records with the same name and house found. Contact Darren for removal.'
def remove(house, name, requester): reply = 'Removed \'%s\' of \'%s\' house from database.' % (name, house) # perform remove if students.find({'name': name, 'house': house}).count() == 0: return 'No such record found.' elif students.find({'name': name, 'house': house}).count() == 1: students.remove({'name': name, 'house': house}, 1) logger.info(whoIs(requester) + ': ' + reply) return reply return 'Multiple records with the same name and house found. Contact Darren for removal.'
def remove(cg, name, requester): reply = 'Removed \'%s\' of \'%s\' cg from database.' % (name, cg) name = name.title() cg = cg.lower() # perform remove if cgls.find({'name': name, 'cg': cg}).count() == 0: return 'No such record found.' elif cgls.find({'name': name, 'cg': cg}).count() >= 1: cgls.delete_one({'name': name, 'cg': cg}) logger.info(whoIs(requester) + ': ' + reply) return reply return 'Multiple records with the same name and cg found. Contact Justin for removal.'
def updateAttendanceLog(house, name, isIn, requester): if houseIsValid(house): if isIn == True: entry = 'In @ %s' % makeTimestamp() else: entry = 'Out @ %s' % makeTimestamp() students.update_one({ 'name': name, 'house': house }, {'$push': { 'statuslog': entry }}) logger.info('%s: Appended status log entry to \'%s\' from \'%s\'' % (whoIs(requester), name.title(), house.title()))
def request_add(target_id, message, to_add_cg, to_add_id, to_add_name): logger.info('Superadmin attention was requested from %s to %s' % (chat_id, target_id)) reply_markup = ReplyKeyboardMarkup( keyboard=[ [ KeyboardButton(text='/add %s %s %s' % (to_add_cg, to_add_name, to_add_id)) ], ['Reject'], ], one_time_keyboard=True, ) #self.sendMessage(target_id, message, reply_markup=reply_markup) bot.sendMessage(target_id, message, reply_markup=reply_markup)
def getEnumerate(house, requester): if houseIsValid(house): # cover the all case and single house case if house == 'all': houses = ['black', 'blue', 'green', 'orange', 'purple', 'red'] else: houses = [house] reply = '' for target_house in houses: reply += '=====================\n' reply += target_house.upper() + '\n\n' for status in ['present', 'absent']: # query for database cursor results = students.find({ 'house': target_house, 'status': status }) # sort results results.sort([('color', 1), ('name', 1)]) reply += status.title() + '\n' # catch empty house/mode query if results.count() == 0: reply += 'No records found.\n' else: # build the reply message i = 1 for person in results: reply += '%d. %-15s' % (i, person['name'].title()) i += 1 if (i + 1) % 2 == 0: reply += '\n' reply += '\n' else: # catch invalid parameters logger.info('%s: /enum query failed (invalid parameters)' % whoIs(requester)) return 'Invalid house or status. See \'/help enumerate\'' logger.info('%s: Returning enumeration for \'%s\' in \'%s\'' % (whoIs(requester), status, house)) return reply
def updater(house, name, field, content, requester): reply = 'Updating \'%s\' for \'%s\' in \'%s\' house.\n\n' % (field, name, house) if houseIsValid(house): # check if result was found if students.find_one( {'name': name, 'house':house} ) == None: # no results reply += 'Could not find \'%s\' from \'%s\' house.' % (name, house) else: # got results if fieldIsValid(field) and field != 'house': logger.info('%s: Updating \'%s\' for \'%s\' in \'%s\' with: \'%s\'' % (whoIs(requester), field, name, house, content)) students.update_one( {'name': name, 'house': house}, { '$set': { field: content } } ) # perform update reply += 'Successfully updated \'%s\' field for \'%s\' in \'%s\' with: \'%s\'' % (field, name, house, content) else: reply += 'Invalid field.' return reply
def getEnumerate(cg, requester): if cgIsValid(cg): # cover the all case and single cg case if cg == 'all': cgs = authorized.cg_list else: cgs = [cg] reply = '' for target_cg in cgs: reply += '=====================\n' reply += target_cg.upper() + '\n\n' # query for database cursor results = cgls.find({'cg': target_cg}) # sort results results.sort([('name', 1)]) #reply += status.title() + '\n' # catch empty cg/mode query if results.count() == 0: reply += 'No records found.\n' else: # build the reply message i = 1 for person in results: reply += '%d. %-15s' % (i, person['name'].title()) i += 1 if (i + 1) % 2 == 0: reply += '\n' reply += '\n' else: # catch invalid parameters logger.info('%s: /enum query failed (invalid parameters)' % whoIs(requester)) return 'Invalid cg or status. See \'/help enumerate\'' #logger.info('%s: Returning enumeration for \'%s\' in \'%s\'' % (whoIs(requester), status, cg)) logger.info('%s: Returning enumeration for \'%s\'' % (whoIs(requester), cg)) return reply
def getStrength(house, status, requester): reply = '' if houseIsValid(house) and statusIsValid(status): # get total house strength (status-independent) house_strength = students.count( {'house': house} ) # get modal house strength (status-dependent) and build reply if status in ['present', 'absent']: status_strength = students.count( {'house': house, 'status': status} ) reply += 'Strength for \'%s\' in \'%s\': %d/%d' % (status, house, status_strength, house_strength) else: reply += 'Total strength for \'%s\' house is %d' % (house, house_strength) else: # catch shitty parameters logger.info('%s: /strength query failed (invalid parameters)' % whoIs(requester)) return 'Invalid house or status. See \'/help strength\'' logger.info('%s: Returning strength for \'%s\' house' % (whoIs(requester), house)) return reply
def getEnumerate(house, requester): if houseIsValid(house): # cover the all case and single house case if house == 'all': houses = ['black', 'blue', 'green', 'orange', 'purple', 'red'] else: houses = [house] reply = '' for target_house in houses: reply += '=====================\n' reply += target_house.upper() + '\n\n' for status in ['present','absent']: # query for database cursor results = students.find( {'house': target_house, 'status': status} ) # sort results results.sort( [ ('color', 1), ('name', 1) ] ) reply += status.title() + '\n' # catch empty house/mode query if results.count() == 0: reply += 'No records found.\n' else: # build the reply message i = 1 for person in results: reply += '%d. %-15s' % (i, person['name'].title()) i += 1 if (i+1)%2 == 0: reply += '\n' reply += '\n' else: # catch invalid parameters logger.info('%s: /enum query failed (invalid parameters)' % whoIs(requester)) return 'Invalid house or status. See \'/help enumerate\'' logger.info('%s: Returning enumeration for \'%s\' in \'%s\'' % (whoIs(requester), status, house)) return reply
def add(house, name, requester): if houseIsValid(house): # check for duplicate name if students.find( {'name': name, 'house': house }).count() != 0: logger.warn('%s: /add failed due to duplicate entry' % (whoIs(requester))) return 'There is already someone with that name and house in the database. /add failed.' timestamp = str(datetime.datetime.now()) logger.info('%s: Adding \'%s\' from \'%s\'' % (whoIs(requester), name, house)) student = { 'name': name, 'type': 'freshman', 'color': house, 'house': [house, 'all'], 'status': 'present', 'statuslog': ['Initial Registration @ ' + makeTimestamp()], 'diet': 'NIL', 'medical': 'NIL', 'addedby': whoIs(requester) } students.insert_one(student) logger.info('%s: Added \'%s\' to \'%s\' house' % (whoIs(requester), name, house)) return 'Successfully added \'%s\' of \'%s\' house into database.' % (name, house) logger.info('%s: /add query failed (invalid parameters)' % whoIs(requester)) return 'Invalid house name. See \'/help add\''
def add(house, name, requester): if houseIsValid(house): # check for duplicate name if students.find({'name': name, 'house': house}).count() != 0: logger.warn('%s: /add failed due to duplicate entry' % (whoIs(requester))) return 'There is already someone with that name and house in the database. /add failed.' timestamp = str(datetime.datetime.now()) logger.info('%s: Adding \'%s\' from \'%s\'' % (whoIs(requester), name, house)) student = { 'name': name, 'type': 'freshman', 'color': house, 'house': [house, 'all'], 'status': 'present', 'statuslog': ['Initial Registration @ ' + makeTimestamp()], 'diet': 'NIL', 'medical': 'NIL', 'addedby': whoIs(requester) } students.insert_one(student) logger.info('%s: Added \'%s\' to \'%s\' house' % (whoIs(requester), name, house)) return 'Successfully added \'%s\' of \'%s\' house into database.' % ( name, house) logger.info('%s: /add query failed (invalid parameters)' % whoIs(requester)) return 'Invalid house name. See \'/help add\''
def add(cg, name, chatID): if cgIsValid(cg): # check for duplicate name if cgls.find({'name': name, 'cg': cg}).count() != 0: logger.warn('/add failed due to duplicate entry') return timestamp = str(datetime.now()) logger.info('Adding \'%s\' from \'%s\' of id %s' % (name, cg, chatID)) cgl = {'name': name, 'cg': [cg, 'all'], 'chatID': chatID} cgls.insert_one(cgl) logger.info('Added %s of id \'%s\' to \'%s\' cg' % (name, chatID, cg)) return 'Thanks for waiting, %s. Welcome.' % name logger.info('/add failed (CG does not exist)') return
#!/usr/bin/python import datetime import time from voglogger import logger from authorized import whoIs import pymongo # establish connection to mongodb server try: connection = pymongo.MongoClient('monty', 27017) logger.info('Successfully connected to MongoDB daemon') except pymongo.errors.ConnectionFailure as e: logger.error('Failed to connect to MongoDB: %s' % e) logger.error('VOGLBot exiting!') sys.exit(1) db = connection['voglbot'] students = db['students'] ### helper functions ### def houseIsValid(house): houses = { 'green': True, 'black': True, 'purple': True, 'blue': True, 'red': True, 'orange': True, 'all': True,
def forceDeleteEvent(): reset() events.delete_one({}) logger.info('Event manually deleted.') return 'Done.'
def removeById(chatID): logger.info('%s (%s) left.' % (whoIs(chatID), chatID)) return cgls.delete_one({'chatID': str(chatID)})
def reply(reply): logger.info('Replied \'%s\' to %s' % (reply, chat_id)) #self.sendMessage(chat_id, reply) self.sender.sendMessage(reply)
def on_chat_message(self, message): content_type, chat_type, chat_id = telepot.glance(message) command = message['text'] # For headmaster to track replies from /count sequence try: reply_source_message_id = ( message['reply_to_message'])['message_id'] headcount_input = (message['text']) except: reply_source_message_id = None headcount_input = -1 logger.info('Received \'%s\' from \'%s\' (%s)' % (command, manager.getName(chat_id), chat_id)) # To save time def reply(reply): logger.info('Replied \'%s\' to %s' % (reply, chat_id)) #self.sendMessage(chat_id, reply) self.sender.sendMessage(reply) def dm(target_id, message): logger.info('%s messaged \'%s\' to %s' % (chat_id, reply, target_id)) #self.sendMessage(target_id, message) bot.sendMessage(target_id, message) def yell(message): broadcaster.yell('all', message, chat_id) logger.info('%s yelled by %s.' % message, (str(chat_id))) def request_add(target_id, message, to_add_cg, to_add_id, to_add_name): logger.info('Superadmin attention was requested from %s to %s' % (chat_id, target_id)) reply_markup = ReplyKeyboardMarkup( keyboard=[ [ KeyboardButton(text='/add %s %s %s' % (to_add_cg, to_add_name, to_add_id)) ], ['Reject'], ], one_time_keyboard=True, ) #self.sendMessage(target_id, message, reply_markup=reply_markup) bot.sendMessage(target_id, message, reply_markup=reply_markup) # Groups cannot talk to the bot if chat_id < 0: return # Return a system ready flag to the admin when the command is complete. adminFlag = False # ================================ COMMANDS FOR ADMINS # This is for superadministrators. if authorized.isSuperadmin(chat_id): if command == '/alethea': reply('Alethea is wonderful <3') return elif command.startswith('/rm'): matches = re.match( '\/rm\s+(MJ|VJA|VJB|TPJA|TPJB|TJ|DMH|CJ\sA|CJ\sB|CJ\sC|SA\sA|SA\sB|AJ\/YJ|SR|NY\/EJ|RJA|RJB\/SJI|RJC|IJ)\s+([a-zA-Z ]+)', command, re.IGNORECASE) if matches is None: reply( 'SUPERADMIN: Please follow the appropriate format: \'/rm CG Their Name' ) else: cg = matches.group(1) name = matches.group(2) rm_message = 'Attempting to remove %s from %s.' % (name, cg) logger.info(rm_message) reply(manager.remove(cg, name, chat_id)) return elif command == '/event clear': reply(manager.forceDeleteEvent()) return # This is for administrators. if authorized.isAdmin(chat_id): # /admin if command == '/admin': adminFlag = True reply( 'You are an admin. Commands available:\n/admin - View this\n/yell AUDIENCE: MSG\n/ls - Show all users in database\n/find FROM NAME - Show list of names you are finding.\n/update HOUSE NAME FIELD PARAM\n/purge HOUSE NAME\n/scoreb - Show scoreboard\n/award HOUSE POINTS' ) elif command.startswith('/add'): matches = re.match( '\/add\s+(MJ|VJA|VJB|TPJA|TPJB|TJ|DMH|CJ\sA|CJ\sB|CJ\sC|SA\sA|SA\sB|AJ\/YJ|SR|NY\/EJ|RJA|RJB\/SJI|RJC|IJ)\s+([0-9]+)\s+([a-zA-Z ]+)', command, re.IGNORECASE) if matches is None: reply( 'ADMIN: Please follow the appropriate format: \'/add cg chat_id Their Name\'' ) else: cg = matches.group(1) target_id = matches.group(2) name = matches.group(3) added_message = 'Attempting to register %s (%s) into %s.' % ( target_id, name, cg) logger.info(added_message) bot.sendMessage( target_id, manager.add(cg.lower(), name.title(), target_id)) logger.info('Succesfully registered %s (%s) into %s.' % (target_id, name, cg)) reply('%s (%s) added' % (name, cg.upper())) return elif command.startswith('/update'): if command == '/update': reply('/update HOUSE NAME FIELD PARAM') return else: adminFlag = True house, name, field, content = re.match( '/update\s+([a-zA-Z]+)\s+([a-zA-Z\s]+)\s+(name|type)\s+([a-zA-Z]+)\s*', command).groups() reply( manager.updater(house.lower(), name.title(), field.lower(), content.lower(), chat_id)) elif command.startswith('/ls'): if command == '/ls': reply( 'Did you mean /ls la?\n\nla: List all users\ncg: List all users in cg' ) return elif command == '/ls la': adminFlag = True reply(manager.getEnumerate('all', chat_id)) else: adminFlag = True cg = re.match('/ls\s([a-zA-Z]+)', command).group(1).lower() reply(manager.getEnumerate(cg, chat_id)) elif command.startswith('/find'): if command == '/find': reply('Enter search params!') return else: adminFlag = True house, name = re.match('/find\s([a-zA-Z]+)\s([a-zA-Z\s]+)', command).groups() reply(manager.find(cg.lower(), name.title(), chat_id)) elif command.startswith('/event'): if command == '/event': reply( 'Use format \'/event new Event Name\' or \'/event end\' or \'/event reopen\'' ) return elif command == '/event reopen': adminFlag = True reply(manager.reopenEvent()) broadcaster.yell(bot, 'all', 'Attendance taking reopened.', chat_id) elif command == '/event end': adminFlag = True reply(manager.forceEndEvent()) broadcaster.yell(bot, 'all', 'Attendance taking has ended.', chat_id) elif command.startswith('/event new'): adminFlag = True event_name = command.replace('/event new ', '') if manager.eventDoesNotExist(): broadcaster.yell( bot, 'all', 'Counting attendance for %s has begun. Get /count -ing' % event_name, chat_id) reply(manager.raiseEvent(event_name)) elif command == '/event report': adminFlag = True reply(printGrandTally()) else: reply('Improper parameters supplied for /event') return elif command.startswith('/yell'): if command == ('/yell'): reply('/yell what?') return adminFlag = True message = command.replace('/yell ', '') broadcaster.yell(bot, 'all', str(message), chat_id) reply('Message yelled to all.') if adminFlag == True: reply('System ready.') return # /24601 if command == '/24601': reply(str(chat_id)) return # /cg if command == '/cg': reply('Use the following CG abbreviation codes:') reply('\n'.join(str(x) for x in authorized.cg_list)) return # /stop if command == '/stop': if manager.removeById(chat_id): reply('Goodbye.') else: reply('You cannot stop what you did not begin.') return # ================================ COMMANDS FOR REGISTERED USERS # This is for registered participants if authorized.isRegistered(chat_id): # Tracking Headmaster queries if self.track_reply: # Obtain CG at first run. if self._query_cg == None: self._query_cg = manager.getCG(chat_id) # Throw warning messages if user exits halfway through. if command == 'exit': if self._progress == 0: reply('/count process interrupted. Your data is safe.') else: reply( '/count process interrupted. Your data is corrupted. Please try again.' ) self.close() # Check if user is counting for the first time. if self._progress == 0: self._first_try = manager.isFirstTry(self._query_cg) # Edit each field of the attendance as we go along. try: count = int(command) if count < 0: raise Exception('Think positive only.') manager.updateAttendance(self._query_cg, question_order[self._progress], count) except Exception as e: reply(str(e)) reply('Your data is corrupted. Please restart /count.') self.close() self._progress += 1 # Complete method if all fields have been populated. if self._progress >= question_limit: self.sender.sendMessage( str(getCGFinalString(self._query_cg))) if manager.setAttendanceDoneForEvent( self._query_cg, self._first_try): reply( 'Congratulations! You are the last to submit your attendance. Here you go ~' ) else: reply( 'Congratulations! You are not the last to submit your attendance. Peace.' ) reply(manager.submitGrandAttendance(self._query_cg)) self.close() # otherwise send the next question self.sender.sendMessage( str(question_bank.get(question_order[self._progress]))) else: # /help [<command>] if command == '/help': reply(helper.getNaiveHelp()) elif command.startswith('/help'): keyword = re.match('\s*/help\s+([a-z]+)\s*', command).group(1) reply(helper.getHelp(keyword)) # /retrieve_key elif command == '/retrieve_key': reply(str(chat_id)) # /me elif command == '/me': reply(manager.getMe(chat_id)) elif command == 'alethea': bot.sendSticker(chat_id, 'CAADBQADxQYAAszG4gK3wUYfyR3TSQI') elif command == '/count': if not manager.eventDoesNotExist( ) and not manager.eventHasEnded(): # self.sender.sendMessage('Shall we begin?', # reply_markup=InlineKeyboardMarkup( # inline_keyboard=[[ # InlineKeyboardButton(text='Ok', callback_data='start'), # ]] # ) # ) # self.close() _progress = 0 reply( 'WARNING: You will potentially override existing data if you do not go through with the full procedure. If so, type exit to leave now.' ) reply( str( question_bank.get( question_order[self._progress]))) self.track_reply = True else: reply( 'No one is counting attendance now. You may wish to do other productive things.' ) # Handles replies from Headmaster # elif reply_source_message_id != None: # if self._query_cg == None: # self._query_cg = manager.getCG(chat_id).lower() # logging.info(self._query_cg) # if self._progress >= question_limit: # self.sender.sendMessage(str(manager.getCGFinalString(self._query_cg), reply_markup=None)) # _progress = 0 # self.close() # if headcount_input == -1: # reply('NaN. Restart.') # self.close() # try: # if manager.updateAttendance(self._query_cg, question_order[self._progress], int(headcount_input)): # logging.info('Database updated.') # self._progress += 1 # self.sender.sendMessage(str(question_bank.get(question_order[self._progress])), reply_markup= # ForceReply(force_reply=True)) # except ValueError: # reply('NaN. Restart.') # self.close() else: reply(easter.responseHandler(command)) # ================================ COMMANDS FOR UNREGISTERED USERS # for '/start' elif command == '/start': reply( 'Hello there. Please enter \'/start Full Name CG\'\n\nEg: /start Alethea Sim TJ\n' ) reply('For full list of CG abbreviations type in /cg') reply( 'Please note that currently only JC East, North and South may use this system.' ) elif command.startswith('/start'): regex_pattern = '\/start\s+([a-zA-Z ]+)\s+(' # extract all given cgs in authorized into a regex id pattern for cg in authorized.cg_list: regex_pattern += cg + '|' regex_pattern = rreplace(regex_pattern, '|', ')', 1) matches = re.match(regex_pattern, command, re.IGNORECASE) if matches is None: reply( 'Either you did not follow the appropriate format: \'/start Your Name CG\' or you did not use the correct CG code. (/cg)' ) else: name = matches.group(1).title() cg = matches.group(2).lower() # map CG to appropriate cluster cluster = authorized.getCluster(cg) approver_id = authorized.address_book.get(cluster) request_message = '%s (%s) from %s, %s wants to register.' % ( chat_id, name, cluster, cg) logger.info(request_message) reply('Hello, %s!' % name) # ask rep to approve registration request_add(authorized.superadmin, request_message, cg, name, chat_id) request_add(approver_id, request_message, cg, name, chat_id) reply( 'Your request was sent to your cluster rep (JC %s) for approval. If you do not hear back within a minute, try again.' % authorized.getClusterFriendlyString(cluster)) # otherwise it must be trying to talk to ARIADNE! else: reply( 'You are not registered. Hit /start or contact Justin (@njyjn) for more information.' ) return
def dm(target_id, message): logger.info('%s messaged \'%s\' to %s' % (chat_id, reply, target_id)) #self.sendMessage(target_id, message) bot.sendMessage(target_id, message)
def yell(message): broadcaster.yell('all', message, chat_id) logger.info('%s yelled by %s.' % message, (str(chat_id)))
#!/usr/bin/python import datetime import time from voglogger import logger from authorized import whoIs import pymongo # establish connection to mongodb server try: connection = pymongo.MongoClient('monty', 27017) logger.info('Successfully connected to MongoDB daemon') except pymongo.errors.ConnectionFailure as e: logger.error('Failed to connect to MongoDB: %s' % e) logger.error('VOGLBot exiting!') sys.exit(1) db = connection['voglbot'] students = db['students'] ### helper functions ### def houseIsValid(house): houses = { 'green': True, 'black': True, 'purple': True, 'blue': True, 'red': True, 'orange': True, 'all': True, }
inform(self, ['Yuchuan'], '!! %s (%s) medical info updated: %s' % (name.title(), house.title(), message)) else: self.sendMessage(chat_id, 'Update failed. No such house/person.') elif command.startswith('/diet'): matches = re.match('/diet\s+([a-z]+)\s+(.+)\s*:\s*(.+)', command) if matches != None: house, name, message = matches.groups() self.sendMessage(chat_id, updater(house, name, 'diet', message, chat_id)) else: self.sendMessage(chat_id, 'Update failed. No such house/person.') elif command.startswith('/log'): house, name = re.search('/log\s+([a-z]+)\s+(.+)', command).groups() self.sendMessage(chat_id, getAttendanceLog(house, name, chat_id)) self._previous = command return logger.info('VOGLBot is listening ...') # the timeout here refers to when a delegator starts over #bot = telepot.DelegatorBot(TOKEN, [ # (per_chat_id(), create_open(VOGLBot, timeout=120)), #]) #bot.message_loop(run_forever=True) bot = VOGLBot(TOKEN) bot.message_loop() while 1: time.sleep(10)
def on_chat_message(self, message): content_type, chat_type, chat_id = telepot.glance(message) # check for message type if content_type != 'text': self.sendMessage(chat_id, 'This bot can only receive text messages!') return command = message['text'].lower() logger.info('Received \'%s\' from %s' % (command, whoIs(chat_id)) ) # message for /start if command == '/start': self.sendMessage(chat_id, 'Hi! I\'m VOGLBot, a friendly robot assistant for USC FOP 2016.') self.sendMessage(chat_id, 'You are \'%s\'. If you do not see your name displayed, you cannot use this bot.' % whoIs(chat_id)) return # deny unauthorized user access if chat_id not in getIDs(authorized): logger.warning('Attempted unauthorized access by %s.' % whoIs(chat_id)) self.sendMessage(chat_id, 'You are not authorized to use this bot. Contact Darren at 92328340 or @ohdearren if this is a mistake.') return # do stuff if command == '/help': self.sendMessage(chat_id, helper.naiveHelp()) elif command.startswith('/help'): matches = re.match('/help ([a-z]+)', command) self.sendMessage(chat_id, helper.getHelp(matches.group(1))) # registration-type commands elif command.startswith('/add'): matches = re.match(register_re, command) self.sendMessage(chat_id, add(matches.group(2), matches.group(3), chat_id)) elif command.startswith('/remove'): matches = re.match(register_re, command) self.sendMessage(chat_id, remove(matches.group(2), matches.group(3), chat_id)) elif command.startswith('/strength'): matches = re.match(register_re, command) self.sendMessage(chat_id, getStrength(matches.group(2), matches.group(3), chat_id)) elif command.startswith('/enum'): house = re.match('\s*/enum\s+([a-z]+)', command).group(1) self.sendMessage(chat_id, getEnumerate(house, chat_id)) elif command.startswith('/find'): matches = re.match(register_re, command) self.sendMessage(chat_id, find(matches.group(2), matches.group(3), False, chat_id)) elif command.startswith('/vfind'): matches = re.match(register_re, command) self.sendMessage(chat_id, find(matches.group(2), matches.group(3), True, chat_id)) elif command.startswith('/in'): matches = re.match('/in\s+([a-z]+)\s+(.+)', command) if matches != None: house, name = matches.groups() self.sendMessage(chat_id, updater(house, name, 'status', 'present', chat_id)) inform(self, ['Yuchuan'], '!! %s (%s) checked in' % (name.title(), house.title())) updateAttendanceLog(house, name, True, chat_id) else: self.sendMessage(chat_id, 'Update failed. No such house/person.') elif command.startswith('/out'): matches = re.match('/out\s+([a-z]+)\s+(.+)', command) if matches != None: house, name = matches.groups() self.sendMessage(chat_id, updater(house, name, 'status', 'absent', chat_id)) inform(self, ['Yuchuan'], '!! %s (%s) checked out' % (name.title(), house.title())) updateAttendanceLog(house, name, False, chat_id) else: self.sendMessage(chat_id, 'Update failed. No such house/person.') elif command.startswith('/medical'): matches = re.match('/medical\s+([a-z]+)\s+(.+)\s*:\s*(.+)', command) if matches != None: house, name, message = matches.groups() self.sendMessage(chat_id, updater(house, name, 'medical', message, chat_id)) inform(self, ['Yuchuan'], '!! %s (%s) medical info updated: %s' % (name.title(), house.title(), message)) else: self.sendMessage(chat_id, 'Update failed. No such house/person.') elif command.startswith('/diet'): matches = re.match('/diet\s+([a-z]+)\s+(.+)\s*:\s*(.+)', command) if matches != None: house, name, message = matches.groups() self.sendMessage(chat_id, updater(house, name, 'diet', message, chat_id)) else: self.sendMessage(chat_id, 'Update failed. No such house/person.') elif command.startswith('/log'): house, name = re.search('/log\s+([a-z]+)\s+(.+)', command).groups() self.sendMessage(chat_id, getAttendanceLog(house, name, chat_id)) self._previous = command return