From a0a8c7de1aa70227225935b6e5615c0344af5026 Mon Sep 17 00:00:00 2001 From: frarol96 Date: Sun, 10 Aug 2025 15:12:42 +0000 Subject: [PATCH] Delete bot.py --- bot.py | 204 --------------------------------------------------------- 1 file changed, 204 deletions(-) delete mode 100644 bot.py diff --git a/bot.py b/bot.py deleted file mode 100644 index b0e8457..0000000 --- a/bot.py +++ /dev/null @@ -1,204 +0,0 @@ -import os -import asyncio -import discord -from discord.ext import commands -from dotenv import load_dotenv -from configparser import ConfigParser -from data_manager import DataManager -import pathlib -import os, asyncio, xml.etree.ElementTree as ET -import aiohttp - -VERSION="0.0.9" - -# ---------- Env & config loading ---------- - -load_dotenv() - -TOKEN = os.getenv('DISCORD_TOKEN', '').strip() -CONFIG_PATH = os.getenv('SHAI_CONFIG', '/config/settings.conf') - -config = ConfigParser() -read_files = config.read(CONFIG_PATH) -if not read_files: - print(f"[Config] INFO: no config at {CONFIG_PATH} (or unreadable). Will rely on env + defaults.") - -# Ensure DEFAULT section exists -if 'DEFAULT' not in config: - config['DEFAULT'] = {} - -def _overlay_env_into_config(cfg: ConfigParser): - """ - Overlay all SHAI_* environment variables into cfg['DEFAULT'] so env wins. - Also accept SHAI_DATA_FILE or SHAI_DATA for data_file. - """ - d = cfg['DEFAULT'] - - # Map SHAI_* -> lower-case keys (e.g. SHAI_MOD_CHANNEL_ID -> 'mod_channel_id') - for k, v in os.environ.items(): - if not k.startswith('SHAI_'): - continue - key = k[5:].lower() # drop 'SHAI_' prefix - if key == 'data': - key = 'data_file' - d[key] = str(v) - - if not d.get('data_file', '').strip(): - d['data_file'] = '/data/data.json' - -# Apply overlay so env takes precedence everywhere -_overlay_env_into_config(config) - -# ---------- Discord intents ---------- - -intents = discord.Intents.default() -intents.guilds = True -intents.members = True -intents.message_content = True -intents.reactions = True -intents.emojis_and_stickers = True -intents.voice_states = True - -# ---------- Bot + DataManager ---------- - -data_file = config['DEFAULT']['data_file'] # guaranteed present by overlay -if not TOKEN: - print("[Config] WARNING: DISCORD_TOKEN not set (env). Bot will fail to log in.") - -bot = commands.Bot(command_prefix='!', intents=intents) -bot.config = config -bot.data_manager = DataManager(data_file) - -# ---------- Self-check helpers ---------- - -async def _guild_selfcheck(g: discord.Guild, cfg): - problems = [] - - def _need_channel(id_key, *perms): - raw = cfg.get(id_key) - if not raw: - problems.append(f"Missing config key: {id_key}") - return - try: - cid = int(raw) - except Exception: - problems.append(f"Bad channel id for {id_key}: {raw}") - return - ch = g.get_channel(cid) - if not ch: - problems.append(f"Channel not found: {id_key}={cid}") - return - me = g.me - p = ch.permissions_for(me) - for perm in perms: - if not getattr(p, perm, False): - problems.append(f"Missing permission on #{ch.name}: {perm}") - - _need_channel('mod_channel_id', 'read_messages', 'send_messages', 'add_reactions', 'read_message_history') - _need_channel('modlog_channel_id', 'read_messages', 'send_messages') - _need_channel('pirates_list_channel_id', 'read_messages', 'send_messages') - - if problems: - print(f"[SelfCheck:{g.name}]") - for p in problems: - print(" -", p) - -async def _fetch_latest_from_rss(url: str): - try: - timeout = aiohttp.ClientTimeout(total=8) - async with aiohttp.ClientSession(timeout=timeout) as sess: - async with sess.get(url) as resp: - if resp.status != 200: - return None, None - text = await resp.text() - # Gitea RSS structure: - 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() - # Try to extract short sha from link tail if it's a commit URL - sha = None - if '/commit/' in link: - sha = link.rsplit('/commit/', 1)[-1][:7] - # Many Gitea feeds put the commit subject in - subject = title if title else None - return subject, sha - except Exception: - return None, None - -# ---------- boot notice ---------- - -async def _post_boot_notice(): - - msg = f"Self-update and reboot successful! (v.{VERSION})" - - ch_id_raw = bot.config['DEFAULT'].get('modlog_channel_id', '') - try: - ch_id = int(ch_id_raw) if ch_id_raw else 0 - except Exception: - ch_id = 0 - if not ch_id: - return - for g in bot.guilds: - ch = g.get_channel(ch_id) - if ch: - try: - await ch.send(msg) - except Exception: - pass - break - -# ---------- events ---------- - -@bot.event -async def on_ready(): - print(f"Logged in as {bot.user} (ID: {bot.user.id})") - print("[Intents] members:", bot.intents.members, "/ message_content:", bot.intents.message_content, "/ voice_states:", bot.intents.voice_states) - - await asyncio.gather(*[_guild_selfcheck(g, bot.config['DEFAULT']) for g in bot.guilds]) - - # Slash command sync - try: - dev_gid = bot.config['DEFAULT'].get('dev_guild_id') - if dev_gid: - guild = bot.get_guild(int(dev_gid)) - if guild: - synced = await bot.tree.sync(guild=guild) - print(f"[Slash] Synced {len(synced)} commands to {guild.name}") - else: - synced = await bot.tree.sync() - print(f"[Slash] Synced {len(synced)} commands globally (dev_guild_id not in cache)") - else: - synced = await bot.tree.sync() - print(f"[Slash] Synced {len(synced)} commands globally") - except Exception as e: - print("[Slash] Sync failed:", repr(e)) - - # Boot notice in modlog - await _post_boot_notice() - -# ---------- Auto-discover extensions ---------- - -modules_path = pathlib.Path(__file__).parent / 'modules' -extensions = [] -for folder in modules_path.iterdir(): - if folder.is_dir(): - for file in folder.glob('*.py'): - if file.name == '__init__.py': - continue - extensions.append(f"modules.{folder.name}.{file.stem}") - -async def main(): - async with bot: - for ext in extensions: - try: - await bot.load_extension(ext) - print(f"[Modules] Loaded: {ext}") - except Exception as e: - print(f"[Modules] Failed to load {ext}:", repr(e)) - await bot.start(TOKEN) - -if __name__ == '__main__': - asyncio.run(main())