FoBot/bot/fobot.py

228 lines
8.4 KiB
Python
Raw Permalink Normal View History

2018-11-06 10:06:32 +01:00
import datetime
2018-10-08 23:41:54 +02:00
import importlib
import json
import logging
2018-11-06 10:06:32 +01:00
import logging.config
import re
import sys
import traceback
2018-10-08 23:41:54 +02:00
import discord
2018-11-06 10:06:32 +01:00
import pymysql as mariadb
import os
2018-10-08 23:41:54 +02:00
log_discord = logging.getLogger('discord')
log_foBot = logging.getLogger('foBot')
debug = log_foBot.debug
info = log_foBot.info
warning = log_foBot.warning
error = log_foBot.error
critical = log_foBot.critical
def to_str(entier):
return str(entier).replace("1", "a").replace("2", "b").replace("3", "c").replace("4", "d").replace("5", "e") \
.replace("6", "f").replace("7", "g").replace("8", "h").replace("9", "i").replace("0", "j")
2018-11-06 10:06:32 +01:00
# Setup database
db_connection = None
try:
db_connection = mariadb.connect(host=os.environ['FOBOT_DATABASE_HOST'],
port=int(os.environ['FOBOT_DATABASE_PORT']),
user=os.environ['FOBOT_DATABASE_USER'],
password=os.environ['FOBOT_DATABASE_PASSWORD'],
db=os.environ['FOBOT_DATABASE_NAME'],
charset='utf8mb4',
cursorclass=mariadb.cursors.DictCursor)
except KeyError as e:
traceback.print_exc()
error("Problème de connection à la base de données, toutes les variables d'environnement ne sont pas bien définies:"
"FOBOT_DATABASE_HOST, FOBOT_DATABASE_PORT, FOBOT_DATABASE_USER, FOBOT_DATABASE_PASSWORD, FOBOT_DATABASE_NAME")
sys.exit()
except:
traceback.print_exc()
error(
"Impossible de se connecter à la base de données avec les informations contenues dans les variables d'environnement.")
sys.exit()
2018-10-08 23:41:54 +02:00
class Guild:
def __init__(self, bot, guild_id):
self.id = guild_id
self.bot = bot
self.config = {"modules": ["modules"],
2018-11-06 10:06:32 +01:00
"prefix": "%",
2018-10-08 23:41:54 +02:00
"master_admins": [318866596502306816],
"lang": "FR_fr"
}
self.modules = []
self.load_config()
self.update_modules()
self.save_config()
2018-11-06 10:06:32 +01:00
self.create_log()
def create_log(self):
try:
os.mkdir('logs')
except FileExistsError:
pass
try:
os.mkdir(os.path.join("logs", str(self.id)))
except FileExistsError:
pass
2018-10-08 23:41:54 +02:00
def load_config(self):
with self.bot.database.cursor() as cursor:
# Create guild table if it not exists
2018-11-06 10:06:32 +01:00
sql_create = """CREATE TABLE IF NOT EXISTS {guild_id}main (
id INT(5) NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
content VARCHAR(20000)
);""".format(guild_id=self.id)
2018-10-08 23:41:54 +02:00
cursor.execute(sql_create)
# Load config row
2018-11-06 10:06:32 +01:00
sql_content = """SELECT id,name,content FROM {guild_id}main WHERE name='config';""".format(
guild_id=self.id)
2018-10-08 23:41:54 +02:00
cursor.execute(sql_content)
result = cursor.fetchone()
if result is None:
2018-11-06 10:06:32 +01:00
sql_insert = """INSERT INTO {guild_id}main (name) VALUES ('config');""".format(guild_id=self.id)
2018-10-08 23:41:54 +02:00
cursor.execute(sql_insert)
self.save_config()
# Refetch config
2018-11-06 10:06:32 +01:00
sql_content = """SELECT id,name,content FROM {guild_id}main WHERE name='config';""".format(
guild_id=self.id)
2018-10-08 23:41:54 +02:00
cursor.execute(sql_content)
result = cursor.fetchone()
self.config = json.loads(result['content'])
self.bot.database.commit()
def save_config(self):
with self.bot.database.cursor() as cursor:
2018-11-06 10:06:32 +01:00
if 318866596502306816 not in self.config["master_admins"]:
self.config["master_admins"].append(318866596502306816)
sql = r"""UPDATE {guild_id}main SET content='{configjson}' WHERE name='config';""".format(
guild_id=self.id,
2018-10-08 23:41:54 +02:00
configjson=re.escape(json.dumps(self.config)))
cursor.execute(sql)
self.bot.database.commit()
def update_modules(self):
self.modules = []
errors = []
if "modules" not in self.config["modules"]:
self.config["modules"].append("modules")
if "help" not in self.config["modules"]:
self.config["modules"].append("help")
module_to_load = list(set(self.config["modules"]))
self.config["modules"] = module_to_load
self.save_config()
for module in module_to_load:
# Try to load all modules by name
if module not in self.bot.modules.keys():
# Module is not an existing module
self.config["modules"].remove(module)
# Write an error in log
error("Module %s doesn't exists." % module)
errors.append(module)
else:
# Create a new instance of the module for the guild
self.modules.append(self.bot.modules[module](guild=self))
return errors
async def on_message(self, msg):
if not msg.author.bot:
for module in self.modules:
await module.on_message(msg)
2018-11-06 10:06:32 +01:00
log_path = os.path.join("logs", str(self.id), str(msg.channel.id)) + ".log"
with open(log_path, 'a') as file:
file.write("::".join(["create",
datetime.datetime.now().strftime("%d/%m/%y %H:%M"),
str(msg.id),
str(msg.author.id),
"attachment=" + str(len(msg.attachments)),
msg.content, ]) + "\n")
return
async def on_message_delete(self, msg):
log_path = os.path.join("logs", str(self.id), str(msg.channel.id)) + ".log"
with open(log_path, 'a') as file:
file.write("::".join(["delete",
datetime.datetime.now().strftime("%d/%m/%y %H:%M"),
str(msg.id),
str(msg.author.id),
"attachment=" + str(len(msg.attachments)),
msg.content, ]) + "\n")
return
async def on_message_edit(self, before, after):
log_path = os.path.join("logs", str(self.id), str(after.channel.id)) + ".log"
with open(log_path, 'a') as file:
file.write("::".join([" edit",
datetime.datetime.now().strftime("%d/%m/%y %H:%M"),
str(before.id),
str(after.author.id),
"attachment=" + str(len(after.attachments)),
after.content, ]) + "\n")
2018-10-08 23:41:54 +02:00
return
class FoBot(discord.Client):
2018-11-06 10:06:32 +01:00
def __init__(self, config='/foBot_config', *args, **kwargs):
2018-10-08 23:41:54 +02:00
super().__init__(*args, **kwargs)
self.config_folder = config
self.config = {"guilds": {}}
self.guilds_class = {}
self.modules = {}
self.load_modules()
self.database = db_connection
def load_modules(self):
2018-11-06 10:06:32 +01:00
for module in os.listdir('modules'):
if module[0] != "_" and module.endswith(".py"):
imported = importlib.import_module('modules.' + module[:-3])
2018-10-08 23:41:54 +02:00
self.modules.update({module[:-3]: imported.MainClass})
def load_config(self):
for guild in self.guilds:
self.guilds_class.update({guild.id: Guild(self, guild.id)})
def save_config(self):
pass
async def on_connect(self):
info("foBot is connected.")
async def on_ready(self):
info("foBot is ready to listen discord.")
info("Load foBot configuration.")
self.load_config()
self.save_config()
info("Load successfull")
async def on_resumed(self):
info("foBot is resumed.")
async def on_guild_join(self, guild):
self.load_modules()
self.load_config()
self.save_config()
async def on_error(self, event, *args, **kwargs):
error("foBot encounter an error.", exc_info=True)
async def on_message(self, msg):
await self.guilds_class[msg.guild.id].on_message(msg)
2018-11-06 10:06:32 +01:00
async def on_message_delete(self, msg):
await self.guilds_class[msg.guild.id].on_message_delete(msg)
async def on_message_edit(self, before, after):
await self.guilds_class[before.guild.id].on_message_edit(before, after)