interactive bots: Create Giphy bot
This commit is contained in:
parent
8d35f25fd6
commit
5d05703482
133
contrib_bots/lib/giphy.py
Normal file
133
contrib_bots/lib/giphy.py
Normal file
|
@ -0,0 +1,133 @@
|
|||
# To use this plugin, you need to set up the Giphy API key for this bot in
|
||||
# ~/.giphy_config
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
from six.moves.configparser import SafeConfigParser
|
||||
import requests
|
||||
import logging
|
||||
import sys
|
||||
import os
|
||||
import re
|
||||
|
||||
GIPHY_TRANSLATE_API = 'http://api.giphy.com/v1/gifs/translate'
|
||||
|
||||
if not os.path.exists(os.environ['HOME'] + '/.giphy_config'):
|
||||
print('Giphy bot config file not found, please set up it in ~/.giphy_config'
|
||||
'\n\nUsing format:\n\n[giphy-config]\nkey=<giphy API key here>\n\n')
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
class GiphyHandler(object):
|
||||
'''
|
||||
This plugin posts a GIF in response to the keywords provided by the user.
|
||||
Images are provided by Giphy, through the public API.
|
||||
The bot looks for messages starting with "@giphy" or @mention of the bot
|
||||
and responds with a message with the GIF based on provided keywords.
|
||||
It also responds to private messages.
|
||||
'''
|
||||
def usage(self):
|
||||
return '''
|
||||
This plugin allows users to post GIFs provided by Giphy.
|
||||
Users should preface keywords with "@giphy" or the Giphy-bot @mention.
|
||||
The bot responds also to private messages.
|
||||
'''
|
||||
|
||||
def triage_message(self, message, client):
|
||||
# To prevent infinite loop in private message, bot will detect
|
||||
# if the sender name is the bot name it will return false.
|
||||
if message['type'] == 'private':
|
||||
return client.full_name != message['sender_full_name']
|
||||
|
||||
# Return True if we want to (possibly) response to this message.
|
||||
original_content = message['content']
|
||||
is_giphy_called = (original_content.startswith('@giphy ') or
|
||||
message['is_mentioned'])
|
||||
|
||||
return is_giphy_called
|
||||
|
||||
def handle_message(self, message, client, state_handler):
|
||||
bot_response = get_bot_giphy_response(message, client)
|
||||
|
||||
if message['type'] == 'private':
|
||||
client.send_message(dict(
|
||||
type='private',
|
||||
to=message['sender_email'],
|
||||
content=bot_response,
|
||||
))
|
||||
else:
|
||||
client.send_message(dict(
|
||||
type='stream',
|
||||
to=message['display_recipient'],
|
||||
subject=message['subject'],
|
||||
content=bot_response,
|
||||
))
|
||||
|
||||
|
||||
class GiphyNoResultException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def get_giphy_api_key_from_config():
|
||||
config = SafeConfigParser()
|
||||
with open(os.environ['HOME'] + '/.giphy_config', 'r') as config_file:
|
||||
config.readfp(config_file)
|
||||
return config.get("giphy-config", "key")
|
||||
|
||||
|
||||
def get_url_gif_giphy(keyword, api_key):
|
||||
# Return a URL for a Giphy GIF based on keywords given.
|
||||
# In case of error, e.g. failure to fetch a GIF URL, it will
|
||||
# return a number.
|
||||
query = {'s': keyword,
|
||||
'api_key': api_key}
|
||||
try:
|
||||
data = requests.get(GIPHY_TRANSLATE_API, params=query)
|
||||
except requests.exceptions.ConnectionError as e: # Usually triggered by bad connection.
|
||||
logging.warning(e)
|
||||
raise
|
||||
|
||||
search_status = data.json()['meta']['status']
|
||||
if search_status != 200 or not data.ok:
|
||||
raise requests.exceptions.ConnectionError
|
||||
|
||||
try:
|
||||
gif_url = data.json()['data']['images']['original']['url']
|
||||
except (TypeError, KeyError): # Usually triggered by no result in Giphy.
|
||||
raise GiphyNoResultException()
|
||||
|
||||
return gif_url
|
||||
|
||||
|
||||
def get_bot_giphy_response(message, client):
|
||||
# Handle the message that called through mention.
|
||||
if message['is_mentioned']:
|
||||
bot_mention = r'^@(\*\*{0}\*\*\s|{0}\s)(?=.*)'.format(client.full_name)
|
||||
start_with_mention = re.compile(bot_mention).match(message['content'])
|
||||
if start_with_mention:
|
||||
keyword = message['content'][len(start_with_mention.group()):]
|
||||
else:
|
||||
return 'Please mention me first, then type the keyword.'
|
||||
# Handle the message that called through the specified keyword.
|
||||
elif message['content'].startswith('@giphy '):
|
||||
keyword = message['content'][len('@giphy '):]
|
||||
# Handle the private message.
|
||||
elif message['type'] == 'private':
|
||||
keyword = message['content']
|
||||
|
||||
# Each exception has a specific reply should "gif_url" return a number.
|
||||
# The bot will post the appropriate message for the error.
|
||||
try:
|
||||
gif_url = get_url_gif_giphy(keyword, get_giphy_api_key_from_config())
|
||||
except requests.exceptions.ConnectionError:
|
||||
return ('Uh oh, sorry :slightly_frowning_face:, I '
|
||||
'cannot process your request right now. But, '
|
||||
'let\'s try again later! :grin:')
|
||||
except GiphyNoResultException:
|
||||
return ('Sorry, I don\'t have a GIF for "%s"! '
|
||||
':astonished:' % (keyword))
|
||||
return ('[Click to enlarge](%s)'
|
||||
'[](/static/images/interactive-bot/giphy/powered-by-giphy.png)'
|
||||
% (gif_url))
|
||||
|
||||
handler_class = GiphyHandler
|
Loading…
Reference in a new issue