Beispiel #1
0
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
Beispiel #2
0
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..."
Beispiel #3
0
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')
Beispiel #4
0
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'
Beispiel #5
0
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'
Beispiel #6
0
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
Beispiel #7
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..."
Beispiel #8
0
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')
Beispiel #9
0
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())
Beispiel #10
0
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)
Beispiel #11
0
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'
Beispiel #12
0
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)
Beispiel #13
0
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
Beispiel #14
0
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'
Beispiel #15
0
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)
Beispiel #16
0
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)
Beispiel #17
0
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'
Beispiel #18
0
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 })
Beispiel #19
0
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..."
Beispiel #20
0
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)
Beispiel #21
0
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)
Beispiel #22
0
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)
Beispiel #23
0
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'
Beispiel #24
0
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')
Beispiel #25
0
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)
Beispiel #26
0
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)
Beispiel #27
0
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
Beispiel #28
0
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')
Beispiel #29
0
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())
Beispiel #30
0
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')