From 791b53c9d6199f3ad93182e227fbfffdfc5a8354 Mon Sep 17 00:00:00 2001 From: Suwako Moriya Date: Fri, 1 Mar 2019 15:26:14 +0100 Subject: [PATCH] Added support for dynamic module loading --- main.py | 13 +++++++++---- modules/git.py | 36 ++++++++++++++++++++++++++++++++++++ modules/modules.py | 41 ++++++++++++++++++++++++++++++++++++++--- 3 files changed, 83 insertions(+), 7 deletions(-) create mode 100644 modules/git.py diff --git a/main.py b/main.py index 76be0bb..c767115 100755 --- a/main.py +++ b/main.py @@ -25,6 +25,7 @@ async def auth(user, moduleName): async def on_ready(): print("Bienvenue, {0.user}, l'heure est venue de faire des fractales.".format(client)) panic=False + error=None async def panicLoad(): print("--PANIC LOAD--") panic=True @@ -54,14 +55,16 @@ async def on_ready(): print("Module {0} initialisé.".format('modules')) try: await modules['modules'][1].on_ready() - except: - pass - except: + except Exception as e: + error=e + except Exception as e: print("[ERROR] Le module {0} n'a pas pu être initialisé.".format('modules')) await panicLoad() - except: + error=e + except Exception as e: print("[ERROR] Le module {0} n'a pas pu être chargé.".format('modules.py')) await panicLoad() + error=e else: await panicLoad() @@ -73,6 +76,8 @@ async def on_ready(): for moduleName in list(modules.keys()): if (not moduleName=='modules') and 'on_ready' in modules[moduleName][1].events: await modules[moduleName][1].on_ready() + if error: + raise error @client.event async def on_error(event, *args, **kwargs): diff --git a/modules/git.py b/modules/git.py new file mode 100644 index 0000000..44e7a54 --- /dev/null +++ b/modules/git.py @@ -0,0 +1,36 @@ +#dummy module +import asyncio +import os +class MainClass(): + def __init__(self, client, modules, owners, prefix): + self.client = client + self.modules = modules + self.owners = owners + self.prefix = prefix + self.events=['on_message'] #events list + self.command="%sgit"%self.prefix #command prefix (can be empty to catch every single messages) + + self.name="Git" + self.description="Module de gestion de Git" + self.interactive=True + self.authlist=[] + self.color=0xdc0000 + self.help="""\ + git update + => Execute les commandes suivantes dans le dossier du bot: + ```BASH + git fetch --all + git reset --hard origin/``` +""" + async def on_message(self, message): + args=message.content.split(' ') + if len(args)==2 and args[1]=='update': + with os.popen('git fetch --all') as stdin: + await message.channel.send(stdin.read()) + with os.popen('git symbolic-ref HEAD 2>/dev/null') as stdin: + branch=stdin.read().replace('refs/heads/', '') + with os.popen('git reset --hard origin/%s'%branch) as stdin: + await message.channel.send(stdin.read()) + await message.channel.send(message.author.mention+", Le dépôt a été mis à jour (fetch + reset --hard).") + else: + await self.modules['help'][1].send_help(message.channel, self) diff --git a/modules/modules.py b/modules/modules.py index ca4e614..b036bf3 100644 --- a/modules/modules.py +++ b/modules/modules.py @@ -2,8 +2,18 @@ import discord import asyncio import os import importlib +import shutil +import random +import time +temp_dir="temp_load" +moduleFiles="modules" class MainClass(): def __init__(self, client, modules, owners, prefix): + if os.path.exists("storage/"+moduleFiles+"/"+temp_dir): + shutil.rmtree("storage/"+moduleFiles+"/"+temp_dir) + if not os.path.exists("storage/"+moduleFiles): + os.mkdir("storage/"+moduleFiles) + os.mkdir("storage/"+moduleFiles+"/"+temp_dir) self.states={} for moduleName in os.listdir('modules'): if moduleName.endswith(".py"): @@ -28,10 +38,13 @@ class MainClass(): => Liste les modules ainsi que leurs états modules enable - => Charge et active le / les modules spécifié(s) + => Charge et active le / les module(s) spécifié(s) modules disable - => Désactive et décharge le / les modules spécifié(s) + => Désactive et décharge le / les module(s) spécifié(s) + + modules reload + => Désactive, décharge, puis recharge et réactive le / les module(s) spécifié(s) => ==> Unique module ou liste de module séparés par des virgules @@ -64,6 +77,25 @@ class MainClass(): await message.channel.send(message.author.mention + ", le module {0} a été désactivé.".format(moduleName)) else: await message.channel.send(message.author.mention + ", le module {0} n'existe pas.".format(moduleName)) + elif args[1]=='reload': + for moduleName in args[2].split(','): + if moduleName == 'modules': + await message.channel.send(message.author.mention + ", le module {0} ne peut pas être rechargé car il est nécéssaire pour gérer les modules.".format(moduleName)) + else: + if moduleName in self.modules.keys(): + self.unload_module(moduleName) + await message.channel.send(message.author.mention + ", le module {0} a été désactivé.".format(moduleName)) + else: + await message.channel.send(message.author.mention + ", le module {0} n'est pas chargé.".format(moduleName)) + if moduleName + '.py' in os.listdir('modules'): + try: + self.enable_module(moduleName) + await message.channel.send(message.author.mention + ", le module {0} a été activé".format(moduleName)) + except Exception as e: + error=e + await message.channel.send(message.author.mention + ", le module {0} **n'a pas pu être activé**".format(moduleName)) + else: + await message.channel.send(message.author.mention + ", le module {0} n'existe pas.".format(moduleName)) else: await self.modules['help'][1].send_help(message.channel, self) if error: @@ -86,7 +118,10 @@ class MainClass(): if moduleName + ".py" in os.listdir('modules'): if not moduleName in list(self.states.keys()) or self.states[moduleName] == 'not loaded': try: - self.modules.update({moduleName:[importlib.import_module('modules.' + moduleName)]}) + tmpstr=str("storage/"+moduleFiles+"/"+temp_dir+"/"+moduleName+"-%s.py")%random.randint(1,100000000000000000000000000000000) + shutil.copy2("modules/%s.py"%moduleName, tmpstr) + time.sleep(0.1) + self.modules.update({moduleName:[importlib.import_module(tmpstr.replace('/','.')[:-3:])]}) print("Module {0} chargé.".format(moduleName)) self.states[moduleName] = 'loaded' except: