91 lines
3.1 KiB
Python
91 lines
3.1 KiB
Python
"""
|
||
Provides a command to fetch random or specific xkcd comics.
|
||
Usage: !xkcd -> random comic
|
||
!xkcd <number> -> comic #<number> (e.g. !xkcd 538)
|
||
"""
|
||
|
||
import aiohttp
|
||
import tempfile
|
||
import random
|
||
import os
|
||
import simplematrixbotlib as botlib
|
||
|
||
XKCD_LATEST_URL = "https://xkcd.com/info.0.json"
|
||
XKCD_COMIC_URL = "https://xkcd.com/{}/info.0.json"
|
||
|
||
async def handle_command(room, message, bot, prefix, config):
|
||
match = botlib.MessageMatch(room, message, bot, prefix)
|
||
if not (match.prefix() and match.command("xkcd")):
|
||
return
|
||
|
||
args = match.args()
|
||
|
||
try:
|
||
async with aiohttp.ClientSession() as session:
|
||
# Get latest comic number
|
||
async with session.get(XKCD_LATEST_URL, timeout=10) as resp:
|
||
resp.raise_for_status()
|
||
latest_data = await resp.json()
|
||
latest_num = latest_data["num"]
|
||
|
||
# Determine target comic number
|
||
if args and args[0].isdigit():
|
||
requested_num = int(args[0])
|
||
if requested_num < 1 or requested_num > latest_num:
|
||
await bot.api.send_text_message(
|
||
room.room_id,
|
||
f"❌ Comic #{requested_num} doesn't exist. Valid range: 1 – {latest_num}."
|
||
)
|
||
return
|
||
comic_num = requested_num
|
||
else:
|
||
comic_num = random.randint(1, latest_num)
|
||
|
||
# Fetch the comic data
|
||
comic_url = XKCD_COMIC_URL.format(comic_num)
|
||
async with session.get(comic_url, timeout=10) as resp:
|
||
resp.raise_for_status()
|
||
comic_data = await resp.json()
|
||
|
||
image_url = comic_data["img"]
|
||
title = comic_data.get("safe_title", comic_data.get("title", "xkcd"))
|
||
alt = comic_data.get("alt", "")
|
||
|
||
# Download the image
|
||
async with session.get(image_url, timeout=10) as img_resp:
|
||
img_resp.raise_for_status()
|
||
image_data = await img_resp.read()
|
||
|
||
with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp:
|
||
tmp.write(image_data)
|
||
img_path = tmp.name
|
||
|
||
# Send image
|
||
await bot.api.send_image_message(room_id=room.room_id, image_filepath=img_path)
|
||
|
||
# Send comic info as text (optional but helpful)
|
||
info = f"**#{comic_num} – {title}**"
|
||
if alt:
|
||
info += f"\n*{alt}*"
|
||
await bot.api.send_markdown_message(room.room_id, info)
|
||
|
||
os.remove(img_path)
|
||
|
||
except aiohttp.ClientError as e:
|
||
await bot.api.send_text_message(room.room_id, f"❌ Network error fetching xkcd: {e}")
|
||
except Exception as e:
|
||
await bot.api.send_text_message(room.room_id, f"❌ Error: {str(e)}")
|
||
|
||
__version__ = "1.1.0"
|
||
__author__ = "Funguy Bot"
|
||
__description__ = "Fetch random or specific xkcd comics"
|
||
__help__ = """
|
||
<details>
|
||
<summary><strong>!xkcd</strong> – xkcd comics</summary>
|
||
<ul>
|
||
<li><code>!xkcd</code> – random comic</li>
|
||
<li><code>!xkcd <number></code> – specific comic (e.g. <code>!xkcd 538</code>)</li>
|
||
</ul>
|
||
</details>
|
||
"""
|