Source code for csbot.plugins.xkcd

import html
import random

from ..plugin import Plugin
from ..util import simple_http_get_async, cap_string, is_ascii
from .linkinfo import LinkInfoResult


[docs]def fix_json_unicode(data): """Attempts to fix the unicode & HTML silliness that is included in the json data. Why Randall, Why? """ for tag in data: # Skip non-strings if type(data[tag]) != str: continue # Remove HTML escape characters data[tag] = html.unescape(data[tag]) if is_ascii(data[tag]): continue try: data[tag] = data[tag].encode("latin-1").decode("utf-8") except (UnicodeEncodeError, UnicodeDecodeError): pass return data
[docs]async def get_info(number=None): """Gets the json data for a particular comic (or the latest, if none provided). """ if number: url = "http://xkcd.com/{}/info.0.json".format(number) else: url = "http://xkcd.com/info.0.json" async with simple_http_get_async(url) as httpdata: if httpdata.status != 200: return None # Only care about part of the data httpjson = await httpdata.json() data = {key: httpjson[key] for key in ["title", "alt", "num"]} # Unfuck up unicode strings data = fix_json_unicode(data) data["url"] = "http://xkcd.com/" + str(data["num"]) return data
[docs]class xkcd(Plugin): """A plugin that does some xkcd things. Based on williebot xkcd plugin. """
[docs] class XKCDError(Exception): pass
async def _xkcd(self, user_str): """Get the url and title stuff. Returns a string of the response. """ latest = await get_info() if not latest: raise self.XKCDError("Error getting comics") latest_num = latest["num"] if not user_str or user_str in {'0', 'latest', 'current', 'newest'}: requested = latest elif user_str in {'rand', 'random'}: requested = await get_info(random.randint(1, latest_num)) else: try: num = int(user_str) if 1 <= num <= latest_num: requested = await get_info(num) else: raise self.XKCDError("Comic #{} is invalid. The latest is #{}" .format(num, latest_num)) except ValueError: # TODO: google search? raise self.XKCDError("Invalid comic number") # Only happens for invalid comics (like 404) if not requested: raise self.XKCDError("So. It has come to this") return (requested["url"], requested["title"], cap_string(requested["alt"], 120))
[docs] @Plugin.integrate_with('linkinfo') def linkinfo_integrate(self, linkinfo): """Handle recognised xkcd urls.""" async def page_handler(url, match): """Use the main _xkcd function, then modify the result (if success) so it looks nicer. """ # Remove leading and trailing '/' try: response = await self._xkcd(url.path.strip('/')) return LinkInfoResult(url.geturl(), '{1} - "{2}"'.format(*response)) except self.XKCDError: return None linkinfo.register_handler(lambda url: url.netloc == "xkcd.com", page_handler, exclusive=True)
[docs] @Plugin.command('xkcd') async def randall_is_awesome(self, e): """Well, Randall sucks at unicode actually :( """ try: result = await self._xkcd(e["data"]) e.reply("{} [{} - \"{}\"]".format(*result)) except self.XKCDError as ex: e.reply(str(ex))