104 lines
3.6 KiB
Python
104 lines
3.6 KiB
Python
#!/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() |