j'espere que ca marche

This commit is contained in:
fomys 2019-05-22 21:30:06 +02:00
parent 0a0d86a376
commit bd152db5c4
8 changed files with 269 additions and 524 deletions

1
.gitignore vendored
View File

@ -64,7 +64,6 @@ target/
.swp.* .swp.*
temp.zip temp.zip
storage/*
config/* config/*
.idea/* .idea/*

335
main.py
View File

@ -189,13 +189,7 @@ setup_logging()
log_discord = logging.getLogger('discord') log_discord = logging.getLogger('discord')
log_LBI = logging.getLogger('LBI') log_LBI = logging.getLogger('LBI')
log_communication = logging.getLogger('communication')
debug = log_LBI.debug
info = log_LBI.info
warning = log_LBI.warning
error = log_LBI.error
critical = log_LBI.critical
def load_modules_info(): def load_modules_info():
for mod in os.listdir("modules"): for mod in os.listdir("modules"):
@ -318,265 +312,10 @@ class LBI(discord.Client):
self.modules = {} self.modules = {}
@event @event
async def on_ready(self): async def dispatch(self, event, *args, **kwargs):
super().dispatch(event, *args, **kwargs)
for module in self.modules.values(): for module in self.modules.values():
await module["initialized_class"].on_ready() await module["initialized_class"].dispatch(event, *args, **kwargs)
@event
async def on_socket_raw_receive(self, message):
for module in self.modules.values():
await module["initialized_class"].on_socket_raw_receive(message)
@event
async def on_socket_raw_send(self, payload):
for module in self.modules.values():
await module["initialized_class"].on_socket_raw_send(payload)
@event
async def on_typing(self, channel, user, when):
for module in self.modules.values():
await module["initialized_class"].on_typing(channel, user, when)
@event
async def on_message(self, message):
print(message.content)
try:
for module in self.modules.values():
await module["initialized_class"]._on_message(message)
except RuntimeError:
info("Liste des modules changée pendant l'execution d'un on_message")
@event
async def on_message_delete(self, message):
for module in self.modules.values():
await module["initialized_class"].on_message_delete(message)
@event
async def on_raw_message_delete(self, payload):
for module in self.modules.values():
await module["initialized_class"].on_raw_message_delete(payload)
@event
async def on_raw_bulk_message_delete(self, payload):
for module in self.modules.values():
await module["initialized_class"].on_raw_bulk_message_delete(payload)
@event
async def on_message_edit(self, before, after):
for module in self.modules.values():
await module["initialized_class"].on_message_edit(before, after)
@event
async def on_raw_message_edit(self, payload):
for module in self.modules.values():
await module["initialized_class"].on_raw_message_edit(payload)
@event
async def on_reaction_add(self, reaction, user):
for module in self.modules.values():
await module["initialized_class"].on_reaction_add(reaction, user)
@event
async def on_raw_reaction_add(self, payload):
for module in self.modules.values():
await module["initialized_class"].on_raw_reaction_add(payload)
@event
async def on_reaction_remove(self, reaction, user):
for module in self.modules.values():
await module["initialized_class"].on_reaction_remove(reaction, user)
@event
async def on_raw_reaction_remove(self, payload):
for module in self.modules.values():
await module["initialized_class"].on_raw_reaction_remove(payload)
@event
async def on_reaction_clear(self, message, reactions):
for module in self.modules.values():
await module["initialized_class"].on_reaction_clear(message, reactions)
@event
async def on_raw_reaction_clear(self, payload):
for module in self.modules.values():
await module["initialized_class"].on_raw_reaction_clear(payload)
@event
async def on_private_channel_delete(self, channel):
for module in self.modules.values():
await module["initialized_class"].on_private_channel_delete(channel)
@event
async def on_private_channel_create(self, channel):
for module in self.modules.values():
await module["initialized_class"].on_private_channel_create(channel)
@event
async def on_private_channel_update(self, before, after):
for module in self.modules.values():
await module["initialized_class"].on_private_channel_update(before, after)
@event
async def on_private_channel_pins_update(self, channel, last_pin):
for module in self.modules.values():
await module["initialized_class"].on_private_channel_pins_update(channel, last_pin)
@event
async def on_guild_channel_delete(self, channel):
for module in self.modules.values():
await module["initialized_class"].on_guild_channel_delete(channel)
@event
async def on_guild_channel_create(self, channel):
for module in self.modules.values():
await module["initialized_class"].on_guild_channel_create(channel)
@event
async def on_guild_channel_update(self, before, after):
for module in self.modules.values():
await module["initialized_class"].on_guild_channel_update(before, after)
@event
async def on_guild_channel_pins_update(self, channel, last_pin):
for module in self.modules.values():
await module["initialized_class"].on_guild_channel_pins_update(channel, last_pin)
@event
async def on_member_join(self, member):
for module in self.modules.values():
await module["initialized_class"].on_member_join(member)
@event
async def on_member_remove(self, member):
for module in self.modules.values():
await module["initialized_class"].on_member_remove(member)
@event
async def on_member_update(self, before, after):
for module in self.modules.values():
await module["initialized_class"].on_member_update(before, after)
@event
async def on_guild_join(self, guild):
for module in self.modules.values():
await module["initialized_class"].on_guild_join(guild)
@event
async def on_guild_remove(self, guild):
for module in self.modules.values():
await module["initialized_class"].on_guild_remove(guild)
@event
async def on_guild_update(self, before, after):
for module in self.modules.values():
await module["initialized_class"].on_guild_update(before, after)
@event
async def on_guild_role_create(self, role):
for module in self.modules.values():
await module["initialized_class"].on_guild_role_create(role)
@event
async def on_guild_role_delete(self, role):
for module in self.modules.values():
await module["initialized_class"].on_guild_role_delete(role)
@event
async def on_guild_role_update(self, before, after):
for module in self.modules.values():
await module["initialized_class"].on_guild_role_update(before, after)
@event
async def on_guild_emojis_update(self, guild, before, after):
for module in self.modules.values():
await module["initialized_class"].on_guild_emojis_update(guild, before, after)
@event
async def on_guild_available(self, guild):
for module in self.modules.values():
await module["initialized_class"].on_guild_available(guild)
@event
async def on_guild_unavailable(self, guild):
for module in self.modules.values():
await module["initialized_class"].on_guild_unavailable(guild)
@event
async def on_voice_state_update(self, member, before, after):
for module in self.modules.values():
await module["initialized_class"].on_voice_state_update(member, before, after)
@event
async def on_member_ban(self, guild, user):
for module in self.modules.values():
await module["initialized_class"].on_member_ban(guild, user)
@event
async def on_member_unban(self, guild, user):
for module in self.modules.values():
await module["initialized_class"].on_member_unban(guild, user)
@event
async def on_group_join(self, channel, user):
for module in self.modules.values():
await module["initialized_class"].on_group_join(channel, user)
@event
async def on_group_remove(self, channel, user):
for module in self.modules.values():
await module["initialized_class"].on_group_remove(channel, user)
@event
async def on_relationship_add(self, relationship):
for module in self.modules.values():
await module["initialized_class"].on_relationship_add(relationship)
@event
async def on_relationship_remove(self, relationship):
for module in self.modules.values():
await module["initialized_class"].on_relationship_remove(relationship)
@event
async def on_relationship_update(self, before, after):
for module in self.modules.values():
await module["initialized_class"].on_relationship_update(before, after)
@event
async def on_connect(self):
for module in self.modules.values():
await module["initialized_class"].on_connect()
@event
async def on_shard_ready(self):
for module in self.modules.values():
await module["initialized_class"].on_shard_ready()
@event
async def on_resumed(self):
print("resumed")
for module in self.modules.values():
await module["initialized_class"].on_resumed()
@event
async def on_error(self, event_, *args, **kwargs):
print(event_, *args, **kwargs)
print(traceback.format_exc())
for module in self.modules.values():
await module["initialized_class"].on_error(event_, *args, **kwargs)
@event
async def on_guild_integrations_update(self, guild):
for module in self.modules.values():
await module["initialized_class"].on_guild_integrations_update(guild)
@event
async def on_webhooks_update(self, channel):
for module in self.modules.values():
await module["initialized_class"].on_webhooks_update(channel)
@event
async def on_toto(self, data):
print(data)
class ClientById: class ClientById:
@ -629,34 +368,52 @@ class ClientById:
channel = self.client.get_channel(id_) channel = self.client.get_channel(id_)
return channel.send(*args, **kwargs) return channel.send(*args, **kwargs)
async def get_role(self, id_):
for guild in self.client.guilds:
role = discord.utils.get(guild.roles, id=id_)
if role:
return role
return None
class Communication:
debug = log_communication.debug
info = log_communication.info
warning = log_communication.warning
error = log_communcation.error
critical = log_communication.critical
def __init__(self, client, sock_file=os.path.join("tmp", os.path.dirname(os.path.realpath(__file__))+".sock")):
self.sock_file = sock_file
self.client = client
async def start():
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
try:
os.remove(self.sock_file)
except OSError:
pass
s.bind(sock_file)
while True:
data = conn.recv(1024)
content = data.decode("utf8")
log("Received:"+content)
if content.startwith("setparam"):
await parse_set_param(content)
async def parse_set_param(self, data):
content = content[8:]
values = content.split("$¤$")
for value in values:
await client.dispatch("setparam", *values.split("$=$"))
client = LBI() client = LBI()
communication = Communication()
def read_sock():
print("connect")
import socket, os
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
try:
os.remove("/tmp/bot.sock") # TODO: Changer le nom du socket car il en faut un par bot
except OSError:
pass
s.bind("/tmp/bot.sock") # TODO: Voir ici aussi
s.listen(1)
conn, addr = s.accept()
while 1:
data = conn.recv(1024)
print(data)
content = data.decode("utf8")
if content.startswith("send"):
print("okip")
client.dispatch("toto", data)
conn.send(data)
async def start_bot(): async def start_bot():
await client.start('TOKEN', max_messages=500000) await client.start('TOKEN', max_messages=500000)
async def start_communication():
await communication.start()
async def stop_bot(): async def stop_bot():
await client.logout() await client.logout()
@ -666,6 +423,6 @@ async def main():
loop = asyncio.get_running_loop() loop = asyncio.get_running_loop()
with concurrent.futures.ProcessPoolExecutor() as pool: with concurrent.futures.ProcessPoolExecutor() as pool:
await loop.run_in_executor(pool, start_bot) await loop.run_in_executor(pool, start_bot)
await loop.run_in_executor(pool, read_sock) await loop.run_in_executor(pool, start_communication)
asyncio.run(main()) asyncio.run(main())

View File

@ -1,40 +1,16 @@
"""Base class for module, never use directly !!!""" """Base class for module, never use directly !!!"""
import asyncio
import sys
import os import os
import pickle import pickle
import traceback
import zipfile import zipfile
import discord import discord
from storage import FSStorage
class Storage: from storage.path import join
def __init__(self, base_path, client):
self.client = client
self.base_path = base_path
try:
os.makedirs(base_path)
except FileExistsError:
self.client.info("Le dossier {dossier} a déjà été créé.".format(dossier=self.base_path))
def mkdir(self, directory):
try:
os.makedirs(self.path(directory))
except FileExistsError:
self.client.info("Le dossier {dossier} a déjà été créé.".format(dossier=directory))
def mkzip(self, files, name):
with zipfile.ZipFile(self.path(files), 'w', zipfile.ZIP_DEFLATED) as zip_file:
for file in files:
zip_file.write(self.path(file), compress_type=zipfile.ZIP_DEFLATED)
return name
def open(self, filename, *args, **kwargs):
return open(self.path(filename), *args, **kwargs)
def path(self, filename):
return os.path.join(self.base_path, filename)
def exists(self, filename):
return os.path.exists(self.path(filename))
class BaseClass: class BaseClass:
@ -49,6 +25,7 @@ class BaseClass:
help_active = False help_active = False
color = 0x000000 color = 0x000000
command_text = None command_text = None
super_users = []
authorized_roles = [] authorized_roles = []
def __init__(self, client): def __init__(self, client):
@ -61,7 +38,7 @@ class BaseClass:
self.client = client self.client = client
if not os.path.isdir(os.path.join("storage", self.name)): if not os.path.isdir(os.path.join("storage", self.name)):
os.makedirs(os.path.join("storage", self.name)) os.makedirs(os.path.join("storage", self.name))
self.storage = Storage(os.path.join(self.client.base_path, self.name), client) self.storage = FSStorage(join(self.client.base_path, self.name))
async def send_help(self, channel): async def send_help(self, channel):
embed = discord.Embed( embed = discord.Embed(
@ -175,10 +152,9 @@ class BaseClass:
i += 1 i += 1
return sub_command, args_, kwargs return sub_command, args_, kwargs
async def _on_message(self, message): async def on_message(self, message):
"""Override this function to deactivate command_text parsing""" """Override this function to deactivate command_text parsing"""
await self.parse_command(message) await self.parse_command(message)
await self.on_message(message)
async def command(self, message, args, kwargs): async def command(self, message, args, kwargs):
"""Override this function to handle all messages starting with `{prefix}{command_text}` """Override this function to handle all messages starting with `{prefix}{command_text}`
@ -203,206 +179,34 @@ class BaseClass:
"""Check if pickle file exists""" """Check if pickle file exists"""
return self.storage.exists(object_name) return self.storage.exists(object_name)
def on_load(self): def dispatch(self, event, *args, **kwargs):
"""This function is called when module is loaded""" # Method to call
pass method = 'on_' + event
try:
# Try to get coro, if not exists pass without raise an error
coro = getattr(self, method)
except AttributeError:
pass
else:
# Run event
asyncio.ensure_future(self._run_event(coro, method, *args, **kwargs), loop=self.loop)
async def on_socket_raw_receive(self, message): async def _run_event(self, coro, event_name, *args, **kwargs):
"""Override this function to handle this event.""" # Run event
pass try:
await coro(*args, **kwargs)
except asyncio.CancelledError:
# If function is cancelled pass silently
pass
except Exception:
try:
# Call error function
await self.on_error(event_name, *args, **kwargs)
except asyncio.CancelledError:
# If error event is canceled pass silently
pass
async def on_socket_raw_send(self, payload): async def on_error(self, event_method, *args, **kwargs):
"""Override this function to handle this event.""" # Basic error handler
pass print('Ignoring exception in {}'.format(event_method), file=sys.stderr)
traceback.print_exc()
async def on_typing(self, channel, user, when):
"""Override this function to handle this event."""
pass
async def on_message(self, message):
"""Override this function to handle this event."""
pass
async def on_message_delete(self, message):
"""Override this function to handle this event."""
pass
async def on_raw_message_delete(self, payload):
"""Override this function to handle this event."""
pass
async def on_raw_bulk_message_delete(self, payload):
"""Override this function to handle this event."""
pass
async def on_message_edit(self, before, after):
"""Override this function to handle this event."""
pass
async def on_raw_message_edit(self, payload):
"""Override this function to handle this event."""
pass
async def on_reaction_add(self, reaction, user):
"""Override this function to handle this event."""
pass
async def on_raw_reaction_add(self, payload):
"""Override this function to handle this event."""
pass
async def on_reaction_remove(self, reaction, user):
"""Override this function to handle this event."""
pass
async def on_raw_reaction_remove(self, payload):
"""Override this function to handle this event."""
pass
async def on_reaction_clear(self, message, reactions):
"""Override this function to handle this event."""
pass
async def on_raw_reaction_clear(self, payload):
"""Override this function to handle this event."""
pass
async def on_private_channel_delete(self, channel):
"""Override this function to handle this event."""
pass
async def on_private_channel_create(self, channel):
"""Override this function to handle this event."""
pass
async def on_private_channel_update(self, before, after):
"""Override this function to handle this event."""
pass
async def on_private_channel_pins_update(self, channel, last_pin):
"""Override this function to handle this event."""
pass
async def on_guild_channel_delete(self, channel):
"""Override this function to handle this event."""
pass
async def on_guild_channel_create(self, channel):
"""Override this function to handle this event."""
pass
async def on_guild_channel_update(self, before, after):
"""Override this function to handle this event."""
pass
async def on_guild_channel_pins_update(self, channel, last_pin):
"""Override this function to handle this event."""
pass
async def on_member_join(self, member):
"""Override this function to handle this event."""
pass
async def on_member_remove(self, member):
"""Override this function to handle this event."""
pass
async def on_member_update(self, before, after):
"""Override this function to handle this event."""
pass
async def on_guild_join(self, guild):
"""Override this function to handle this event."""
pass
async def on_guild_remove(self, guild):
"""Override this function to handle this event."""
pass
async def on_guild_update(self, before, after):
"""Override this function to handle this event."""
pass
async def on_guild_role_create(self, role):
"""Override this function to handle this event."""
pass
async def on_guild_role_delete(self, role):
"""Override this function to handle this event."""
pass
async def on_guild_role_update(self, before, after):
"""Override this function to handle this event."""
pass
async def on_guild_emojis_update(self, guild, before, after):
"""Override this function to handle this event."""
pass
async def on_guild_available(self, guild):
"""Override this function to handle this event."""
pass
async def on_guild_unavailable(self, guild):
"""Override this function to handle this event."""
pass
async def on_voice_state_update(self, member, before, after):
"""Override this function to handle this event."""
pass
async def on_member_ban(self, guild, user):
"""Override this function to handle this event."""
pass
async def on_member_unban(self, guild, user):
"""Override this function to handle this event."""
pass
async def on_group_join(self, channel, user):
"""Override this function to handle this event."""
pass
async def on_group_remove(self, channel, user):
"""Override this function to handle this event."""
pass
async def on_relationship_add(self, relationship):
"""Override this function to handle this event."""
pass
async def on_relationship_remove(self, relationship):
"""Override this function to handle this event."""
pass
async def on_relationship_update(self, before, after):
"""Override this function to handle this event."""
pass
async def on_ready(self):
"""Override this function to handle this event."""
pass
async def on_connect(self):
"""Override this function to handle this event."""
pass
async def on_shard_ready(self):
"""Override this function to handle this event."""
pass
async def on_resumed(self):
"""Override this function to handle this event."""
pass
async def on_error(self, event, *args, **kwargs):
"""Override this function to handle this event."""
pass
async def on_guild_integrations_update(self, guild):
"""Override this function to handle this event."""
pass
async def on_webhooks_update(self, channel):
"""Override this function to handle this event."""
pass

View File

@ -32,3 +32,4 @@ class Api:
await self._download("modules/"+module+"/"+version, filename="temp.zip") await self._download("modules/"+module+"/"+version, filename="temp.zip")
with zipfile.ZipFile('temp.zip', "r") as z: with zipfile.ZipFile('temp.zip', "r") as z:
z.extractall(os.path.join("modules", module)) z.extractall(os.path.join("modules", module))
#78.200.118.13:8000

69
storage/FileSystem.py Normal file
View File

@ -0,0 +1,69 @@
import os
from storage.base import Storage
class FSStorage(Storage):
"""
Simple filesystem storage
"""
def __init__(self, base_path="storage"):
super().__init__()
self.base_path = os.path.abspath(base_path)
os.makedirs(self.base_path)
self.current_dir = "/"
def _topath(self, path):
"""Transform a path to a full path"""
if path.startswith("/"):
return os.path.join(self.base_path, # Always add baspath to avoid going outside protected zone
os.path.abspath(os.path.join(self.base_path,
os.path.normpath(path))).lstrip(self.base_path))
else:
return os.path.join(self.base_path, # Always add baspath to avoid going outside protected zone
os.path.abspath(os.path.join(self.base_path,
self.current_dir,
os.path.normpath(path))).lstrip(self.base_path))
def access(self, path):
# Normalize path and transform it to absolute path, remove base_path part and add it again to avoid going
# outside protected folder
return os.access(self._topath(path))
def chdir(self, path):
self.current_dir = self._topath(path)
return self.current_dir
def getcwd(self):
return self.current_dir
def listdir(self, path="."):
return os.listdir(self._topath(path))
def mkdir(self, path):
os.mkdir(self._topath(path))
return self._topath(path)
def makedirs(self, path, exist_ok=False):
os.makedirs(self._topath(path), exist_ok=exist_ok)
return self._topath(path)
def remove(self, path):
os.remove(self._topath(path))
def rename(self, src, dst):
os.rename(self._topath(src), self._topath(dst))
return self._topath(dst)
def rmdir(self, path):
os.rmdir(self._topath(path))
def sync(self):
os.sync()
def open(self, path, mode):
return open(path, mode)
def exists(self, path):
return os.path.exists(path)

1
storage/__init__.py Normal file
View File

@ -0,0 +1 @@
from storage.FileSystem import FSStorage

107
storage/base.py Normal file
View File

@ -0,0 +1,107 @@
class Storage:
"""Basic class for storage interface
When implementing function be precautionous to forbidden going outside restricted storage zone (storage/modulename
for example).
All path are on unix format (`/folder1/folder2/file`)
"""
def __init__(self):
pass
async def access(self, path):
"""
Return if path is accessible
:param path: Path to check
:return: Boolean
"""
pass
async def chdir(self, path):
"""
Change working directory for this storage module
:param path: Path to go
:return: New path
"""
pass
async def getcwd(self):
"""
Get current working directory
:return: Current working directory
"""
pass
async def listdir(self, path="."):
"""
List all files and folders in directory `path`
:param path: Folder to list
:return: List of filename
"""
pass
async def mkdir(self, path):
"""
Create directory `path`
:param path: directory to create
:return: Path to new directory
"""
pass
async def makedirs(self, path, exist_ok=False):
"""
Create directory `path`
:param path: directory to create
:return: Path to new directory
"""
pass
async def remove(self, path):
"""
Remove file `path`
:param path: File to remove
:return: None
"""
pass
async def rename(self, src, dst):
"""
Rename file `src` to `dst`
:param src: Source file
:param dst: Destination file
:return: New path
"""
pass
async def rmdir(self, path):
"""
Remove dir `path`
:param path: Directory to remove
:return: None
"""
pass
async def sync(self):
"""
Force writing everything on disk (or storage support)
:return: None
"""
pass
async def open(self, path, mode):
"""
Return a file object
:param path: Path of file
:param mode: mode to open file
:return: file object
"""
pass
async def exists(self, path):
"""
Return if a file or a folder exists
:param path: Path to test
:return: True if file exists
"""
pass

7
storage/path.py Normal file
View File

@ -0,0 +1,7 @@
def join(*args):
"""
Join list of path
:param args: List of path
:return: Joined path
"""
return "/".join(args)