Added support for dynamic module loading

This commit is contained in:
Suwako Moriya 2019-03-01 15:26:14 +01:00
parent fe449618f0
commit 791b53c9d6
3 changed files with 83 additions and 7 deletions

13
main.py
View File

@ -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):

36
modules/git.py Normal file
View File

@ -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="""\
</prefix>git update
=> Execute les commandes suivantes dans le dossier du bot:
```BASH
git fetch --all
git reset --hard origin/<branch_name>```
"""
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)

View File

@ -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
</prefix>modules enable <module/modules>
=> Charge et active le / les modules spécifié(s)
=> Charge et active le / les module(s) spécifié(s)
</prefix>modules disable <module/modules>
=> Désactive et décharge le / les modules spécifié(s)
=> Désactive et décharge le / les module(s) spécifié(s)
</prefix>modules reload <module/modules>
=> Désactive, décharge, puis recharge et réactive le / les module(s) spécifié(s)
=> <module/modules>
==> 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: