From 0b4b02e1442562b01f1bab5edbc90a2fe391931c Mon Sep 17 00:00:00 2001 From: Sebastian Schmittner Date: Tue, 31 Jan 2023 20:26:27 +0100 Subject: [PATCH 1/4] added module to query comics from xkcd. This module is derived from the apod module. Signed-off-by: Sebastian Schmittner --- modules/xkcd.py | 98 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 modules/xkcd.py diff --git a/modules/xkcd.py b/modules/xkcd.py new file mode 100644 index 0000000..1690404 --- /dev/null +++ b/modules/xkcd.py @@ -0,0 +1,98 @@ +import os +import re +import html + +import requests +from nio import AsyncClient, UploadError +from nio import UploadResponse + +from modules.common.module import BotModule +from modules.common.exceptions import UploadFailed + + +class Xkcd: + """ + Uses the XKCD (json) api https://xkcd.com/json.html to fetch web comics and metadata and display them in chats. + """ + def __init__(self, title, img, alt, num): + self.title = title + self.img = img + self.alt = alt + self.num = num + + + @staticmethod + def create_from_json(json): + return Xkcd(json.get("title"), json.get("img"), json.get("alt"), json.get("num")) + + def __str__(self): + return "title: {} || explanation: {} || date: {} || original-url: {}".format(self.title, + self.explanation, + self.date, + self.hdurl) + + +class MatrixModule(BotModule): + + def __init__(self, name): + super().__init__(name) + self.uri_get_latest = 'https://xkcd.com/info.0.json' + + + async def matrix_message(self, bot, room, event): + self.logger.debug(f"room: {room.name} sender: {event.sender} queried the xkcd module with body: {event.body}") + + args = event.body.split() + + if len(args) == 1: + await self.send_xkcd(bot, room, self.uri_get_latest) + elif len(args) == 2: + if args[1] == "help": + await self.command_help(bot, room) + else: + xkcd_id = args[1] + if re.match("\d+", date) is not None: + await self.send_xkcd(bot, room, self.uri_get_by_id(xkcd_id)) + else: + await bot.send_text(room, "Invalid comic id. ids must be positive integers.") + + async def send_xkcd(self, bot, room, uri): + self.logger.debug(f"send request using uri {uri}") + response = requests.get(uri) + + if response.status_code != 200: + self.logger.error("unable to request api. response: [status: %d text: %s]", response.status_code, response.text) + return await bot.send_text(room, "sorry. something went wrong accessing the api") + + xkcd = Xkcd.create_from_json(response.json()) + self.logger.debug(xkcd) + + img_url = xkcd.img + try: + matrix_uri = None + matrix_uri, mimetype, w, h, size = bot.get_uri_cache(img_url) + except (TypeError, ValueError): + self.logger.debug(f"Not found in cache: {img_url}") + try: + matrix_uri, mimetype, w, h, size = await bot.upload_image(img_url) + except (UploadFailed, TypeError, ValueError): + await bot.send_text(room, f"Something went wrong uploading {apimg_url}.") + + await bot.send_html(room, f"{html.escape(xkcd.title)} ({html.escape(xkcd.num)})", f"{xkcd.title} ({xkcd.num})") + await bot.send_image(room, matrix_uri, img_url, None, mimetype, w, h, size) + await bot.send_text(room, f"{xkcd.alt}") + + def uri_get_by_id(self, id): + return 'https://xkcd.com/' + int(id) + '/info.0.json' + + def help(self): + return 'Sends latest/any specified XCKD web comic to the room. See https://xkcd.com/ ' + + async def command_help(self, bot, room): + msg = """commands: + - no arguments: fetch latest xkcd comic + - (\d+) fetch and display the xkcd comic with the given id + - help - show command help + """ + await bot.send_text(room, msg) + From 43e7dca53ba9d056331c9669bba0dc3b49ca7910 Mon Sep 17 00:00:00 2001 From: Sebastian Schmittner Date: Tue, 31 Jan 2023 20:44:26 +0100 Subject: [PATCH 2/4] fixing minor bugs in xkcd bot Signed-off-by: Sebastian Schmittner --- modules/xkcd.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/xkcd.py b/modules/xkcd.py index 1690404..68c99bf 100644 --- a/modules/xkcd.py +++ b/modules/xkcd.py @@ -51,7 +51,7 @@ class MatrixModule(BotModule): await self.command_help(bot, room) else: xkcd_id = args[1] - if re.match("\d+", date) is not None: + if re.match("\d+", xkcd_id) is not None: await self.send_xkcd(bot, room, self.uri_get_by_id(xkcd_id)) else: await bot.send_text(room, "Invalid comic id. ids must be positive integers.") @@ -78,12 +78,12 @@ class MatrixModule(BotModule): except (UploadFailed, TypeError, ValueError): await bot.send_text(room, f"Something went wrong uploading {apimg_url}.") - await bot.send_html(room, f"{html.escape(xkcd.title)} ({html.escape(xkcd.num)})", f"{xkcd.title} ({xkcd.num})") + await bot.send_html(room, f"{html.escape(xkcd.title)} ({html.escape(str(xkcd.num))})", f"{xkcd.title} ({str(xkcd.num)})") await bot.send_image(room, matrix_uri, img_url, None, mimetype, w, h, size) await bot.send_text(room, f"{xkcd.alt}") def uri_get_by_id(self, id): - return 'https://xkcd.com/' + int(id) + '/info.0.json' + return 'https://xkcd.com/' + str(int(id)) + '/info.0.json' def help(self): return 'Sends latest/any specified XCKD web comic to the room. See https://xkcd.com/ ' From 656f0748ea8fea537c7db356ebb5c8c23495575f Mon Sep 17 00:00:00 2001 From: Sebastian Schmittner Date: Tue, 31 Jan 2023 21:00:09 +0100 Subject: [PATCH 3/4] read me Signed-off-by: Sebastian Schmittner --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.md b/README.md index d44a61f..40b0983 100644 --- a/README.md +++ b/README.md @@ -371,6 +371,17 @@ The module uses a demo API Key which can be replaced by your own api key by sett You can create one at https://api.nasa.gov/#signUp +### XKCD + +Fetch comic strips from [XKCD](https://xkcd.com) (A webcomic of romance, +sarcasm, math, and language) and post them to the room. + +Command: + +* !xkcd - Sends latest XKCD comic strip to the room +* !xkcd ID - Sends xkcd number ID to the room +* !xkcd help - show command help + ### Inspirobot From 91dfcf8328e6873cf92d312d0736136b610bab4e Mon Sep 17 00:00:00 2001 From: Sebastian Schmittner Date: Tue, 31 Jan 2023 21:04:26 +0100 Subject: [PATCH 4/4] flake Signed-off-by: Sebastian Schmittner --- modules/xkcd.py | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/modules/xkcd.py b/modules/xkcd.py index 68c99bf..25b36ad 100644 --- a/modules/xkcd.py +++ b/modules/xkcd.py @@ -1,10 +1,7 @@ -import os import re import html import requests -from nio import AsyncClient, UploadError -from nio import UploadResponse from modules.common.module import BotModule from modules.common.exceptions import UploadFailed @@ -20,7 +17,6 @@ class Xkcd: self.alt = alt self.num = num - @staticmethod def create_from_json(json): return Xkcd(json.get("title"), json.get("img"), json.get("alt"), json.get("num")) @@ -38,7 +34,6 @@ class MatrixModule(BotModule): super().__init__(name) self.uri_get_latest = 'https://xkcd.com/info.0.json' - async def matrix_message(self, bot, room, event): self.logger.debug(f"room: {room.name} sender: {event.sender} queried the xkcd module with body: {event.body}") @@ -51,7 +46,7 @@ class MatrixModule(BotModule): await self.command_help(bot, room) else: xkcd_id = args[1] - if re.match("\d+", xkcd_id) is not None: + if re.match("\\d+", xkcd_id) is not None: await self.send_xkcd(bot, room, self.uri_get_by_id(xkcd_id)) else: await bot.send_text(room, "Invalid comic id. ids must be positive integers.") @@ -76,7 +71,7 @@ class MatrixModule(BotModule): try: matrix_uri, mimetype, w, h, size = await bot.upload_image(img_url) except (UploadFailed, TypeError, ValueError): - await bot.send_text(room, f"Something went wrong uploading {apimg_url}.") + await bot.send_text(room, f"Something went wrong uploading {img_url}.") await bot.send_html(room, f"{html.escape(xkcd.title)} ({html.escape(str(xkcd.num))})", f"{xkcd.title} ({str(xkcd.num)})") await bot.send_image(room, matrix_uri, img_url, None, mimetype, w, h, size) @@ -91,8 +86,7 @@ class MatrixModule(BotModule): async def command_help(self, bot, room): msg = """commands: - no arguments: fetch latest xkcd comic - - (\d+) fetch and display the xkcd comic with the given id + - (\\d+) fetch and display the xkcd comic with the given id - help - show command help """ await bot.send_text(room, msg) -