def urbanDictionary(): """!ud <... term ...>""" import sys import json import requests msg = Message._create_message(flask.request.form) term = msg.textBody responses = [] if term: if sys.version < '3': from urllib import quote as urlquote else: from urllib.parse import quote as urlquote url = 'http://api.urbandictionary.com/v0/define?term=' + urlquote(term) else: # no term provided. Send a random one. url = 'http://api.urbandictionary.com/v0/random' r = requests.get(url) data = json.loads(r.content) if not data['list']: return ["Sorry, couldn't find that..."] clean = lambda x: x.replace('\r\n', '\n').strip() for entry in data['list'][:1]: responses.append(str(data['list'][0]['word'])) output = 'def: ' + clean(entry['definition']) + '\n' output += 'ex: ' + clean(entry['example']) responses.append(str(output)) return responses
def searchImage(): """!img <... query ...>""" # use imgur's API to return the link to the first non-album result. from json import loads import random import requests msg = Message._create_message(flask.request.form) searchText = msg.textBody url = "https://api.imgur.com/3/gallery/search/{{sort}}/{{window}}/{{page}}" querystring = {"q": searchText} headers = {'authorization': 'Client-ID 01aa1688f43ca6c'} response = requests.request("GET", url, headers=headers, params=querystring) a = loads(response.text)['data'] # a = filter(lambda x: 'imgur.com/a/' not in x['link'], a) if len(a) > 0: # imageUrl = a[0]['link'] # return random.choice(a)['link'] try: return random.choice(a)['link'] except: # there was an error finding a link key in the item's dict. return "Sorry, I couldn't find a photo of that..." else: return "Sorry, I couldn't find a photo of that..."
def poll(): """!poll <topic>\\n<opt1>\\n<opt2> ...""" msg = Message._create_message(flask.request.form) options = msg.textBody.split('\n') response = [] if len(options) < 2: return 'Please specify a topic with options delimited by newlines.' # set this to the current poll for our group. poll_data = { "letter_options" : set(), "options" : options[1:], "question" : options[0], "votes" : {} } response.append(poll_data['question']) for i, cur_option in enumerate(poll_data["options"]): _option_letter = chr(ord('a') + i) poll_data["letter_options"].add(_option_letter) response.append("{0}. {1}".format(_option_letter, cur_option)) # mongo doesn't like sets so I have to convert to list. poll_data["letter_options"] = list(poll_data["letter_options"]) db.mUpdate('polls', {'group' : msg.chatId}, {'group' : msg.chatId, 'data' : poll_data }) return reduce_output(response, delimiter='\n')
def identify(): """!identify <image> Queries clarif.ai to identify the top 10 concepts within an image. Usage: !identify <image>""" msg = Message._create_message(flask.request.form) fileName = msg.fileName if fileName == 'noFile': return 'Please supply a file.' elif fileName == 'fileError': return 'There was an error selecting the last file transfer.' else: from clarifai.rest import ClarifaiApp from clarifai.rest import Image as ClImage app = ClarifaiApp(api_key=app.config['CLARIFAI_KEY']) model = app.models.get('general-v1.3') image = ClImage(file_obj=open(fileName, 'rb')) imageData = model.predict([image]) try: imageData = imageData['outputs'][0]['data']['concepts'][:10] imageData = [x['name'] for x in imageData] return reduce_output(imageData, delimiter=', ') except: return 'Error'
def identify(): """!identify <image>""" msg = Message._create_message(flask.request.form) fileName = msg.fileName if fileName == 'noFile': return 'Please supply a file.' elif fileName == 'fileError': return 'There was an error selecting the last file transfer.' else: from clarifai.rest import ClarifaiApp from clarifai.rest import Image as ClImage app = ClarifaiApp(api_key='ab4ea7efce5a4398bcbed8329a3d81c7') model = app.models.get('general-v1.3') image = ClImage(file_obj=open(fileName, 'rb')) imageData = model.predict([image]) try: imageData = imageData['outputs'][0]['data']['concepts'][:10] imageData = [x['name'] for x in imageData] return reduce_output(imageData, delimiter=', ') except: return 'Error'
def define(): """!define <word> <... meaning ...>""" msg = Message._create_message(flask.request.form) textBody = msg.textBody if len(textBody) == 0: return 'Please supply a word to define.' try: textBody = textBody.split(' ', 1) if len(textBody) == 2: defnName, meaning = textBody[0], textBody[1] else: return 'Please supply a meaning for the word.' except: # There was an error. return 'Error adding definition. No unicode pls :(' defnName = clean(defnName) q = db.findDefn(defnName) if q: db.updateDefn(defnName, meaning) return ('%s updated.' % defnName) else: db.addDefn(defnName, meaning) return ('%s added.' % defnName) return 0
def searchImage(): """!img <... query ...> Query imgur.com to return a url to a related image (selects randomly from results). Usage: !img flower""" # use imgur's API to return the link to the first non-album result. from json import loads import random import requests msg = Message._create_message(flask.request.form) searchText = msg.textBody url = "https://api.imgur.com/3/gallery/search/{{sort}}/{{window}}/{{page}}" querystring = {"q": searchText} headers = {'authorization': app.config['IMGUR_CLIENT_ID']} response = requests.request("GET", url, headers=headers, params=querystring) a = loads(response.text)['data'] # a = filter(lambda x: 'imgur.com/a/' not in x['link'], a) if len(a) > 0: try: return random.choice(a).get( 'link', 'Error selecting link from response...') except: # there was an error finding a link key in the item's dict. return "Sorry, I couldn't find a photo of that..." else: return "Sorry, I couldn't find a photo of that..."
def sue_help(): help_docs = [] msg = Message._create_message(flask.request.form) # iterate through our routes, getting the doc-strings we defined as # miniature man-pages for these commands. for r in app.url_map.iter_rules(): current_doc = app.view_functions[r.endpoint].__doc__ if current_doc and ('static' not in r.rule): docString = current_doc.strip() firstLine = docString.split('\n', 1)[0] # if someone wants help about a specific command, get them # the extra info we placed after the first line-break. if msg.textBody: if firstLine.split(' ', 1)[0].replace('!', '') == msg.textBody.lower(): specificDocumentation = docString.split('\n', 1) if len(specificDocumentation) == 2: return reduce_output(specificDocumentation[1].strip(), delimiter='\n') else: return 'No documentation for {0} yet. Add it to the\ repo! https://github.com/inculi/Sue'.format( msg.textBody) # else: # print(firstLine.split(' ',1)[0].replace('!','')) # print(msg.textBody.lower()) help_docs.append(firstLine) return reduce_output(sorted(help_docs), delimiter='\n')
def sue_random(): """!random <upper> <lower>""" msg = Message._create_message(flask.request.form) if not msg: return 'Error with message.' textBody = msg.textBody.lower() print(textBody) randRange = sorted(textBody.split(' ')) if len(randRange) != 2: # can't have a range between 3 elements return sue_random.__doc__ numberBased = set(map(lambda x: x.isdigit(), randRange)) try: if numberBased == {True}: # 1 - 123 randRange = [int(x) for x in randRange] randRange.sort() return str(random.randint(randRange[0], randRange[1])) elif numberBased == {False}: # a - z randRange = [ord(x) for x in randRange] randRange.sort() return str(chr(random.randint(randRange[0], randRange[1]))) else: return str(random.random()) except: return str(random.random())
def poll(): """!poll <topic>\\n<opt1>\\n<opt2> ... Create a poll for people to !vote on. Usage: !poll which movie? grand budapest tron bee movie""" msg = Message._create_message(flask.request.form) options = tokenize(msg.textBody) if len(options) < 2: return 'Please specify a topic with options delimited by newlines.' if '?' in options[0]: # Injected user data may have messed up tokenization... # !poll Where should we have lunch? #lunchplaces (no comma) # instead of: !poll Where should we have lunch?, #lunchplaces (comma) firstQuestionIdx = options[0].find('?') if options[0][-1] != '?': # The question ended earlier in the string. Find it. pollQuestion, firstOption = options[0].split('?', 1) options = [pollQuestion.strip() + '?', firstOption.strip()] + options[1:] return create_poll(options, msg)
def lewd(): """!lewd <image>""" # detect whether an image is lewd or not msg = Message._create_message(flask.request.form) fileName = msg.fileName if fileName == 'noFile': return 'Please supply a file.' elif fileName == 'fileError': return 'There was an error selecting the last file transfer.' else: from clarifai.rest import ClarifaiApp from clarifai.rest import Image as ClImage app = ClarifaiApp(api_key='ab4ea7efce5a4398bcbed8329a3d81c7') model = app.models.get('nsfw-v1.0') image = ClImage(file_obj=open(fileName, 'rb')) responses = [] imageData = model.predict([image]) result = imageData['outputs'][0]['data']['concepts'][0] if result['name'] == u'nsfw': responses.append('LEEEWWWDDD!!!!!') responses.append('accuracy: %f' % result['value']) return responses else: return 'not lewd'
def movie(): # Used to get information about movies that are currently being stored/ # downloaded. # TODO: Implement. # return 'Needs to be implemented.' print('doing something') msg = Message._create_message(flask.request.form) return query_couch_potato(msg.textBody)
def echo(): """!echo <... text ...> Used to debug member-defined data structures. You: !echo !choose #lunchplaces Sue: !choose fuego, antonios, potbelly, taco bell""" msg = Message._create_message(flask.request.form) return msg.textBody
def callDefn(): msg = Message._create_message(flask.request.form) defnName = msg.command q = db.findDefn(defnName) if q: return str(q[u'meaning']) else: return 'Not found. Add it with !define'
def name(): """!name <newname>""" msg = Message._create_message(flask.request.form) sender = msg.sender textBody = msg.textBody # make changes to our names collection. if len(textBody) == 0: return 'Please specify a name.' else: db.updateName(sender, textBody) return '{0} shall now be known as {1}'.format(sender, textBody)
def shuffle(): """!shuffle <1> <2> ... <n> Shuffles and then returns your input.""" from functools import reduce msg = Message._create_message(flask.request.form) items = tokenize(msg.textBody) random.shuffle(items) return reduce(lambda x,y: str(x)+' '+str(y), items)
def whoami(): """!whoami""" msg = Message._create_message(flask.request.form) sender = msg.sender # load names from pickle file nameFound = db.findName(sender) if nameFound: print('You are {0}.'.format(nameFound)) return 'You are {0}.'.format(nameFound) else: return 'I do not know you. Set your name with !name'
def lunchPlaces(): """!lunchPlaces <place1>, <place2>, ...""" msg = Message._create_message(flask.request.form) # split by commas and trim whitespace lunchPlaces = [each.strip() for each in msg.textBody.split(',')] # add lunchPlaces to the mongo polls collection db.mUpdate('polls', {'group' : msg.chatId}, {'group' : msg.chatId, 'lunchPlaces' : lunchPlaces })
def wiki(): """!wiki <... topic ...>""" import wikipedia as wikip msg = Message._create_message(flask.request.form) searchTerm = msg.textBody try: data = wikip.summary(searchTerm, sentences=1) if len(data) < 50: data = wikip.summary(searchTerm, sentences=2) return str(data) except: return "Hmm, couldn't find that..."
def choose(): """!choose <1> <2> ... <n> Returns a random object in your space-delimited argument. Usage: !choose up down left right""" msg = Message._create_message(flask.request.form) options = tokenize(msg.textBody) meguminOption = ('megumin' in map(lambda x: x.lower(), options)) if meguminOption and msg.sender == '+12107485865': return 'megumin' elif meguminOption and msg.sender == '+12108342408': return 'Roses are Red, Violets are Blue. Megumin best girl and glorious waifu.' else: return random.choice(options)
def image(): """!i <param> <image> Available parameters are: smile, smile2, hot, old, young, hollywood, glasses, hitman, mustache, pan, heisenberg, female, female2, male """ global VALID_IMAGE_PARAMS msg = Message._create_message(flask.request.form) _param = msg.textBody.lower() paramAliases = { 'mustache' : 'mustache_free', 'glasses' : 'fun_glasses', 'smile2' : 'smile_2', 'female2' : 'female_2' } if _param not in VALID_IMAGE_PARAMS: _param = paramAliases.get(_param) if not _param: return 'Not a valid parameter. See !help i' if msg.fileName == 'noFile': return 'Please supply a file.' elif msg.fileName == 'fileError': return 'There was an error selecting the last file transfer.' import faces import uuid try: img = faces.FaceAppImage(file=open(msg.fileName, 'rb')) outimg = img.apply_filter(_param, cropped=False) except faces.ImageHasNoFaces: return 'No faces on this image.' except faces.BadInfo as ex: return str(ex) # Create the directory for us to store these files if it doesn't exist. if not os.path.exists('resources/iout/'): os.mkdir('resources/iout') outPath = os.path.abspath('resources/iout/{}.jpg'.format(uuid.uuid4())) with open(outPath, 'wb') as f: f.write(outimg) return DataResponse(outPath)
def choose(): """!choose <1> <2> ... <n>""" msg = Message._create_message(flask.request.form) print(msg.__dict__) textBody = msg.textBody sender = msg.buddyId options = textBody.split(' ') meguminOption = 'megumin' in map(lambda x: x.lower(), options) if meguminOption and sender == '12107485865': return 'megumin' elif meguminOption and sender == '12108342408': return 'http://megumin.club Roses are Red, Violets are Blue. Megumin best girl and glorious waifu.' else: return random.choice(options)
def process_reply(): if app.config['DEBUG']: print(flask.request.form) command = check_command(flask.request.form) if not command: return '' # get a list of our available functions sue_funcs = {} for r in app.url_map.iter_rules(): sue_funcs[r.rule] = app.view_functions[r.endpoint] f = sue_funcs.get('/' + command) if f: # get the response back from Sue. sue_response = f() # cast her response to a string. (ex: lists are reduced). if isinstance(sue_response, list): sue_response = reduce_output(sue_response, delimiter='\n') elif not isinstance(sue_response, str): try: sue_response = str(sue_response) except: sue_response = "Couldn't convert from {0} to str".format( type(sue_response)) # message metadata will be used to direct response output. msg = Message._create_message(flask.request.form) if msg.platform is 'imessage': # forward to applescript handler Response(msg, sue_response) return 'success' elif msg.platform is 'signal': # return to GET request from run_signal.py return sue_response else: print('Unfamiliar message platform: {0}'.format(msg.platform)) return 'failure' else: # see if it is user defined sue_response = sue_funcs['/callDefn']() Response(flask.request.form, sue_response) return 'success'
def vote(): """!vote <letter> Used to vote on a poll that is currently ongoing. Usage: !vote a""" msg = Message._create_message(flask.request.form) options = msg.textBody.split(' ') poll_data = db.mFind('polls', 'group', msg.chatId).get('data', {}) if not poll_data: return 'Could not find a poll for your group. Make one with !poll' response = [] # if there is actually a correct input if len(options) == 1: the_letter = options[0].lower() if the_letter in poll_data.get('letter_options', []): poll_data['votes'][msg.sender] = the_letter else: return 'That is not a option in this poll.' response.append(poll_data["question"]) # display the new status total_letters = poll_data.get('letter_options') voted_letters = list(poll_data.get('votes', {}).values()) vote_counts = [voted_letters.count(x) for x in total_letters] for cnt, ltr, option in zip(vote_counts, total_letters, poll_data['options']): # (0 votes) A. Dog vote_plurality = 'vote' if (cnt == 1) else 'votes' # thanks, Rick :/ response.append( '({0} {1}) {2}. {3}'.format(cnt, vote_plurality, ltr, option) ) # mongo doesn't like sets so I have to convert to list. db.mUpdate('polls', {'group' : msg.chatId}, {'group' : msg.chatId, 'data' : poll_data }) return reduce_output(response, delimiter='\n')
def wikis(): """!wiki <... topic ...> , <... search filter ...>""" import wikipedia as wikip msg = Message._create_message(flask.request.form) searchTerm = msg.textBody.split(',', 1) if len(searchTerm) != 2: return ('Please separate the topic and search term with a comma.\ \nEx: !wikis george washington, was born') from nltk.tokenize import sent_tokenize searchTerm = [x.lower().strip() for x in searchTerm] data = sent_tokenize(wikip.page(searchTerm[0]).content) data = [x for x in data if searchTerm[1] in x.lower()] data = data[:10] # we don't want too many sentences. if len(data) == 0: return 'No sentences match that...' for sent in data: return str(sent)
def lunch(): """!lunch Creates a poll to vote on a lunchplace, using the defn of !lunchplaces as \ the input. """ # we need the chatId for when we search the database... msg = Message._create_message(flask.request.form) # retrieve the group-specific lunchplaces places = db.findDefn('lunchplaces').get('meaning','') # if lunchPlaces isn't in the database if not places: return "Please !define lunchplaces <place1>, <place2>, ..." options = ["Where should we get lunch?"] options.extend([x.strip() for x in places.split(',')]) return create_poll(options, msg)
def person(): """!person <image> Queries clarif.ai to identify the age, gender, and 'multicultural apperance'\ of detected faces in the photo. Usage: !person <image>""" msg = Message._create_message(flask.request.form) fileName = msg.fileName if fileName == 'noFile': return 'Please supply a file.' elif fileName == 'fileError': return 'There was an error selecting the last file transfer.' else: from clarifai.rest import ClarifaiApp from clarifai.rest import Image as ClImage responses = [] app = ClarifaiApp(api_key=app.config['CLARIFAI_KEY']) model = app.models.get('demographics') image = ClImage(file_obj=open(fileName, 'rb')) imageData = model.predict([image]) imageData = imageData['outputs'][0]['data'] if 'regions' not in imageData: return 'No faces detected.' for face in imageData['regions']: face = face.get('data',{}).get('face') try: if face: face_age = face['age_appearance']['concepts'][0]['name'] face_gender = face['gender_appearance']['concepts'][0]['name'] face_culture = face['multicultural_appearance']['concepts'][0]['name'] responses.append('age : %s' % face_age) responses.append('gender : %s' % face_gender) responses.append('ethnicity : %s' % face_culture) except: return 'Error' return responses
def lunch(): """!lunch""" # retrieve the group-specific lunchPlaces options = db.mFind('polls', 'group', msg.chatId).get('lunchPlaces', None) # if lunchPlaces isn't in the database if options == None: return "There are no lunchPlaces set,\nset with !lunchPlaces <place1>, <place2>, ..." options = ["Where should we get lunch?"] + options msg = Message._create_message(flask.request.form) # # the rest of this code is copy-paste from !poll # response = [] if len(options) < 2: return 'Please specify a topic with options delimited by newlines.' # set this to the current poll for our group. poll_data = { "letter_options" : set(), "options" : options[1:], "question" : options[0], "votes" : {} } response.append(poll_data['question']) for i, cur_option in enumerate(poll_data["options"]): _option_letter = chr(ord('a') + i) poll_data["letter_options"].add(_option_letter) response.append("{0}. {1}".format(_option_letter, cur_option)) # mongo doesn't like sets so I have to convert to list. poll_data["letter_options"] = list(poll_data["letter_options"]) db.mUpdate('polls', {'group' : msg.chatId}, {'group' : msg.chatId, 'data' : poll_data }) return reduce_output(response, delimiter='\n')
def sue_random(): """!random <upper> <lower> Returns a random number between two positive integers. Usage: !random 1 10 Return a random letter between two letters Usage: !random a z Return a random floating point number between 0 and 1 (0.47655569922929364) Usage: !random""" msg = Message._create_message(flask.request.form) if not msg: return 'Error with message.' textBody = msg.textBody.lower() randRange = sorted(textBody.split(' ')) if len(randRange) != 2: # can't have a range between 3 elements return sue_random.__doc__ numberBased = set(map(lambda x: x.isdigit(), randRange)) try: if numberBased == {True}: # 1 - 123 randRange = [int(x) for x in randRange] randRange.sort() return str(random.randint(randRange[0],randRange[1])) elif numberBased == {False}: # a - z randRange = [ord(x) for x in randRange] randRange.sort() return str(chr(random.randint(randRange[0],randRange[1]))) else: return str(random.random()) except: return str(random.random())
def vote(): """!vote <letter>""" msg = Message._create_message(flask.request.form) options = msg.textBody.split(' ') poll_data = db.mFind('polls', 'group', msg.chatId).get('data', {}) print(poll_data) if not poll_data: return 'Could not find a poll for your group. Make one with !poll' response = [] # if there is actually a correct input if len(options) == 1: the_letter = options[0].lower() if the_letter in poll_data.get('letter_options', set()): poll_data['votes'][msg.sender] = the_letter else: return 'That is not a option in this poll.' response.append(poll_data["question"]) # display the new status votes = poll_data.get('votes', {}).values() vote_counts = [list(votes).count(x) for x in poll_data.get('letter_options')] entries = list(zip(vote_counts, poll_data['letter_options'], poll_data.get('options', ['?']))) entries.sort(key=lambda x: x[1]) for num_votes, letter, option in entries: # (0 votes) A. Dog response.append( '({0} votes) {1}. {2}'.format(num_votes, letter, option) ) # mongo doesn't like sets so I have to convert to list. db.mUpdate('polls', {'group' : msg.chatId}, {'group' : msg.chatId, 'data' : poll_data }) return reduce_output(response, delimiter='\n')