import os import discord import aiohttp import xml.etree.ElementTree as ET async def _fetch_latest_subject_sha(rss_url: str) -> tuple[str | None, str | None]: """Best-effort: read latest commit subject + short sha from a Gitea RSS feed.""" try: timeout = aiohttp.ClientTimeout(total=8) async with aiohttp.ClientSession(timeout=timeout) as sess: async with sess.get(rss_url) as resp: if resp.status != 200: return None, None text = await resp.text() root = ET.fromstring(text) item = root.find('./channel/item') if item is None: return None, None title = (item.findtext('title') or '').strip() link = (item.findtext('link') or '').strip() sha = link.rsplit('/commit/', 1)[-1][:7] if '/commit/' in link else None return (title or None), sha except Exception: return None, None async def post_boot_notice(bot): """ Posts a boot status message to the configured modlog channel. Primary source: SHAI_BOOT_* env vars set by the wrapper. Fallback: if absent, and SHAI_REPO_RSS is set, show the latest commit subject. """ status = os.getenv("SHAI_BOOT_STATUS", "").strip() # 'fetched_new' | 'cached_no_update' | 'cache_only_error' | '' desc = os.getenv("SHAI_BOOT_DESC", "").strip() old_v = os.getenv("SHAI_BOOT_OLD", "").strip() new_v = os.getenv("SHAI_BOOT_NEW", "").strip() line = None if status == "fetched_new": line = f"Successfully fetched, cached, and booted new version: v{old_v or '0.0.0.0'} → v{new_v}" elif status == "cached_no_update": line = f"Successfully booted from cached version: v{new_v}. No new update found" elif status == "cache_only_error": line = f"Successfully booted from cached version: v{new_v}. Program repository not accessible!" # If wrapper didn’t set a status, optionally show latest commit subject from RSS (if provided) if not line: rss = os.getenv("SHAI_REPO_RSS", "").strip() if rss: subject, sha = await _fetch_latest_subject_sha(rss) if subject and len(subject) > 5: line = f"Booted (no BSM env). Latest commit: {subject}" + (f" ({sha})" if sha else "") if not line: return # nothing to say try: ch_id = int(bot.config['DEFAULT'].get('modlog_channel_id', "0") or 0) except Exception: ch_id = 0 if not ch_id: return ch = None for g in bot.guilds: ch = g.get_channel(ch_id) if ch: break if not ch: return try: msg = line if not desc else f"{line}\n_{desc}_" await ch.send(msg, allowed_mentions=discord.AllowedMentions.none()) except Exception: pass