#!/usr/bin/env python3 from discord.ext import commands, tasks from discord import Intents import glob import logging import json class DiscordBot(commands.Bot): __AUTHOR__ = 'anima' __VERSION__ = '1.0.0' def __init__(self, *, intents: Intents = Intents().all(), **options: tasks.Any) -> None: # lod config file with open("bot.conf", 'r') as f: self.botConfig = json.load(f) # setup logging self.log = logging.getLogger(__name__) self._set_loglevel() logHandler = logging.FileHandler('DiscordBot.log') logHandler.setFormatter(logging.Formatter('%(asctime)s %(levelname)s - %(name)s : %(message)s')) self.log.addHandler(logHandler) # init bot with prefix, intents and commands super().__init__(command_prefix=self.botConfig['prefix'], intents=intents, **options) self.add_commands() def _set_loglevel(self, level: str = 'info'): """ allow to change log level external of class """ match level: case 'info': self.log.setLevel(logging.INFO) case 'warn': self.log.setLevel(logging.WARNING) case 'error': self.log.setLevel(logging.ERROR) case 'crit': self.log.setLevel(logging.CRITICAL) case 'debug': self.log.setLevel(logging.DEBUG) def run(self, token: str = None, *, reconnect: bool = True) -> None: # load token from config file if none given if token == None: token = self.botConfig['token'] return super().run(token, reconnect=reconnect) async def on_ready(self) -> None: self.log.info(f'Bot starts as {self.user}') print(f'Bot starts as {self.user}') # initate cogs to extend functions await self.load_cogs() self.fetch_guilds() for guild in self.guilds: self.log.info(f'Connect to Server {guild.name} (id: {guild.id})') print(f'Connect to Server {guild.name} (id: {guild.id})') # start background loops self.mainloop.start() async def load_cogs(self, reload: bool = False) -> None: # fetch all cog.py files and add these to bot for cogFile in glob.glob('**/cogs/**/cog.py', recursive=True): cogPath = cogFile[:-3].replace('/', '.') if reload: self.log.info(f'Try reload cog from: {cogPath}') await self.reload_extension(cogPath) else: self.log.info(f'Try load cog from: {cogPath}') await self.load_extension(cogPath) self.log.debug(f'Cogs loaded: {self.extensions}') for cog in self.extensions.keys(): print(f'Cog loaded: {cog}') def add_commands(self): @self.command(name="relmods", pass_context=True) @commands.has_role('@admin') async def reload_cogs(ctx) -> None: """ allow on the fily reload of cogs """ await self.load_cogs(reload=True) cogs = '' for cog in self.extensions.keys(): cogs += '✅ ' + cog.split('.')[-1] + '\n' await ctx.send(f'Reload Modules ... \n{cogs}') @tasks.loop(minutes=1) async def mainloop(self): await self.wait_until_ready() self.log.debug('Run mainloop') def main(): bot = DiscordBot() bot._set_loglevel('debug') bot.run() if __name__ == "__main__": main()