# This Python file uses the following encoding: utf-8 # trunk-ignore-all(bandit/B311) # pylint: disable=line-too-long # pylint: disable=too-many-lines """Discord entrypoint for the Conjurer bot. The legacy bootstrap used threads and synchronous calls that made clean shutdowns difficult. We now run everything from a single asyncio event loop with cooperative shutdown signals so the bot can stop gracefully. """ import asyncio import logging import random import threading from logging import handlers import discord from discord.ext import commands from communication_subroutine import comm_subroutine from constants import ENCODING, LOGFILE, TOKEN logger = logging.getLogger("discord") logger.setLevel(logging.INFO) handler = handlers.RotatingFileHandler( filename=LOGFILE, encoding=ENCODING, mode="a", maxBytes=6 * 1024 * 1024, backupCount=6, ) formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") handler.setFormatter(formatter) logger.addHandler(handler) # *=========================================== Initializations intents = discord.Intents.default() intents.message_content = True intents.typing = True intents.presences = True intents.members = True intents.messages = True intents.voice_states = True intents.moderation = True # on_member_ban - wyswietl na glownym kanale pieczatke "Niech spierdala" # on_member_unban - "mam wyjebane" random.seed() client = commands.Bot(intents=intents, command_prefix="$") # *=========================================== Define Events @client.event async def on_ready(): """Metoda wywoływana przy połączeniu do serwera.""" logger = logging.getLogger("discord") logger.debug("SAMPLE DEBUG LOG") logger.info("%s has connected to Discord!", client.user) # TODO: load vs reload logger.info("Reactor: online") await client.load_extension("administration_commands") await client.load_extension("librarian_commands") await client.load_extension("music_commands") await client.load_extension("radio_commands") await client.load_extension("ai_commands") await client.load_extension("other_commands") await client.load_extension("voice_recognition_commands") await client.load_extension("file_search_commands") await client.load_extension("latex_commands") logger.info("Sensors: online") logger.info(client.cogs) await client.tree.sync() for com in client.commands: logger.info("Command %s is awejleble", com.qualified_name) logger.info("Logged in as ----> %s", client.user) logger.info("ID:%s ", client.user.id) logger.info("All systems: operational") async def _run_comm_subroutine(stop_event: threading.Event) -> None: await asyncio.to_thread(comm_subroutine, stop_event) async def _run_bot(token: str, shutdown_event: asyncio.Event) -> None: try: await client.start(token, log_handler=None) finally: shutdown_event.set() async def main() -> None: if not TOKEN: logger.error("Discord token missing – set DISCORD_TOKEN or configure netrc") return shutdown_event = asyncio.Event() comm_stop_event = threading.Event() comm_task = asyncio.create_task(_run_comm_subroutine(comm_stop_event)) bot_task = asyncio.create_task(_run_bot(TOKEN, shutdown_event)) try: await shutdown_event.wait() except (KeyboardInterrupt, asyncio.CancelledError): logger.info("Shutdown signal received") comm_stop_event.set() await client.close() finally: comm_stop_event.set() if not client.is_closed(): await client.close() await asyncio.gather(bot_task, comm_task, return_exceptions=True) if __name__ == "__main__": asyncio.run(main())