interactive bots: Create xkcd bot.

This commit is contained in:
Rafid Aslam 2016-12-27 20:12:03 +07:00 committed by Alicja Raszkowska
parent 2a8c57d77a
commit db39b52d3f
8 changed files with 171 additions and 0 deletions

131
contrib_bots/lib/xkcd.py Normal file
View file

@ -0,0 +1,131 @@
from random import randint
import logging
import requests
XKCD_TEMPLATE_URL = 'https://xkcd.com/%s/info.0.json'
LATEST_XKCD_URL = 'https://xkcd.com/info.0.json'
class XkcdHandler(object):
'''
This plugin provides several commands that can be used for fetch a comic
strip from https://xkcd.com. The bot looks for messages starting with
"@xkcd" and responds with a message with the comic based on provided
commands.
'''
def usage(self):
return '''
This plugin allows users to fetch a comic strip provided by
https://xkcd.com. Users should preface the command with "@xkcd".
There are several commands to use this bot:
- @xkcd help -> To show all commands the bot supports.
- @xkcd latest -> To fetch the latest comic strip from xkcd.
- @xkcd random -> To fetch a random comic strip from xkcd.
- @xkcd <comic_id> -> To fetch a comic strip based on
`<comic_id>`, e.g `@xkcd 1234`.
'''
def triage_message(self, message, client):
# Return True if we want to (possibly) response to this message
original_content = message['content']
is_xkcd_called = original_content.startswith('@xkcd ')
is_xkcd_called_without_command = original_content == '@xkcd'
return is_xkcd_called or is_xkcd_called_without_command
def handle_message(self, message, client, state_handler):
xkcd_bot_response = get_xkcd_bot_response(message)
client.send_message(dict(
type='stream',
to=message['display_recipient'],
subject=message['subject'],
content=xkcd_bot_response,
))
class XkcdBotCommand(object):
LATEST = 0
RANDOM = 1
COMIC_ID = 2
class XkcdNotFoundError(Exception):
pass
class XkcdServerError(Exception):
pass
def get_xkcd_bot_response(message):
original_content = message['content'].strip()
cropped = original_content[len('@xkcd '):]
command = cropped.strip()
xkcd_called_without_command = original_content == '@xkcd'
commands_help = ("%s"
"\n* `@xkcd help` to show this help message."
"\n* `@xkcd latest` to fetch the latest comic strip from xkcd."
"\n* `@xkcd random` to fetch a random comic strip from xkcd."
"\n* `@xkcd <comic id>` to fetch a comic strip based on `<comic id>` "
"e.g `@xkcd 1234`.")
try:
if command == 'help' or xkcd_called_without_command:
return commands_help % ('xkcd bot supports these commands:')
elif command == 'latest':
fetched = fetch_xkcd_query(XkcdBotCommand.LATEST)
elif command == 'random':
fetched = fetch_xkcd_query(XkcdBotCommand.RANDOM)
elif command.isdigit():
fetched = fetch_xkcd_query(XkcdBotCommand.COMIC_ID, cropped.strip())
else:
return commands_help % ('xkcd bot only supports these commands:')
except (requests.exceptions.ConnectionError, XkcdServerError):
logging.exception('Connection error occurred when trying to connect to xkcd server')
return 'Sorry, I cannot process your request right now, please try again later!'
except XkcdNotFoundError:
logging.exception('XKCD server responded 404 when trying to fetch comic with id %s'
% (command))
return 'Sorry, there is likely no xkcd comic strip with id: #%s' % (command)
else:
return ("#%s: **%s**\n[%s](%s)" % (fetched['num'],
fetched['title'],
fetched['alt'],
fetched['img']))
def fetch_xkcd_query(mode, comic_id=None):
try:
if mode == XkcdBotCommand.LATEST: # Fetch the latest comic strip.
url = LATEST_XKCD_URL
elif mode == XkcdBotCommand.RANDOM: # Fetch a random comic strip.
latest = requests.get(LATEST_XKCD_URL)
if latest.status_code != 200:
raise XkcdServerError()
latest_id = latest.json()['num']
random_id = randint(1, latest_id)
url = XKCD_TEMPLATE_URL % (str(random_id))
elif mode == XkcdBotCommand.COMIC_ID: # Fetch specific comic strip by id number.
if comic_id is None:
raise Exception('Missing comic_id argument')
url = XKCD_TEMPLATE_URL % (comic_id)
fetched = requests.get(url)
if fetched.status_code == 404:
raise XkcdNotFoundError()
elif fetched.status_code != 200:
raise XkcdServerError()
xkcd_json = fetched.json()
except requests.exceptions.ConnectionError as e:
logging.warning(e)
raise
return xkcd_json
handler_class = XkcdHandler

View file

@ -0,0 +1,40 @@
# xkcd bot
xkcd bot is a Zulip bot that can fetch a comic strip from xkcd. To use xkcd
bot you can simply call it with `@xkcd` followed by a command. Like this:
```
@xkcd <command>
```
xkcd bot has four commands:
1. `help`
This command is used to list all commands that can be used with this bot.
You can use this command by typing `@xkcd help` in a stream.
![](xkcd-help.png)
2. `latest`
This command is used to fetch the latest comic strip from xkcd. You can use
this command by typing `@xkcd latest` in a stream.
![](xkcd-latest.png)
3. `random`
This command is used to fetch a random comic strip from xkcd. You can use
this command by typing `@xkcd random` in a stream, xkcd bot will post a
random xkcd comic strip.
![](xkcd-random.png)
4. `<comic_id>`
To fetch a comic strip based on id, you can directly use `@xkcd <comic_id>`,
for example if you want to fetch a comic strip with id 1234, you can type
`@xkcd 1234`, xkcd bot will post a comic strip with id 1234.
![](xkcd-specific-id.png)
If you type a wrong command to xkcd bot, xkcd bot will post information
you'd get from `@xkcd help`.
![](xkcd-wrong-command.png)
And if you type a wrong id, xkcd bot will post a message that an xkcd comic
strip with that id is not available.
![](xkcd-wrong-id.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB