diff --git a/.gitignore b/.gitignore index 557f9c3..ea46b8c 100644 --- a/.gitignore +++ b/.gitignore @@ -149,7 +149,7 @@ cython_debug/ .vscode/ # Project -auth/auth.json +config # MacOS (should be included in your local .gitignore) .DS_Store \ No newline at end of file diff --git a/README.md b/README.md index c33fc90..d24dc3a 100644 --- a/README.md +++ b/README.md @@ -55,9 +55,10 @@ $ python3 -m pip install -U ".[voice]" 1. Paste your dicord bot token in the `"token"` field inside `auth/auth.json`. -2. (Optional) If you're using the database, you need to configure the database field `auth/auth.json`. +2. Configure the prefix in the `config\bot.json`. -3. (Optional) Edit line `10` in `bot.py` to change the bot prefix : `command_prefix=commands.when_mentioned_or("`*PREFIX_HERE*`")`. +3. If you're using the database, you need to configure the `config\database.json` file. +:warning: If you're NOT using any database, delete the following cogs: `fridaycake`, `me` & `birthday`. ## SQL diff --git a/auth/auth.json b/auth/auth.json deleted file mode 100644 index d651380..0000000 --- a/auth/auth.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "token": "*************************************.******.**********************", - "database": { - "host": "127.0.0.1", - "port": 3306, - "user": "user", - "password": "********", - "birthday": { - "database": "discord_algosup", - "table": "table_birthday", - - "guild_id": 332234497078853644, - "channel_id": 332234497078853644 - }, - "fridaycake": { - "database": "discord_algosup", - "table": "table_fridaycake" - }, - "me": { - "database": "discord_algosup", - "table": "table_me" - } - } -} \ No newline at end of file diff --git a/bot.py b/bot.py index a52d1bb..9e90cb9 100644 --- a/bot.py +++ b/bot.py @@ -2,26 +2,36 @@ import json import discord +from classes.database import DataSQL from discord.ext import commands -intents = discord.Intents.all() - -bot = commands.Bot(command_prefix=commands.when_mentioned_or("?"), description='Algobot', intents=intents, help_command=None) - base_directory = os.path.dirname(os.path.abspath(__file__)) -auth_file = os.path.join(base_directory, "auth", "auth.json") - -with open(auth_file, "r") as data: json_data = json.load(data) - -if __name__ == '__main__': - cogs_directory = os.path.join(base_directory, "cogs") - for cog in os.listdir(cogs_directory): - actual = os.path.splitext(cog) - if actual[1] == '.py': - bot.load_extension('cogs.'+actual[0]) +bot_file = os.path.join(base_directory, "config", "bot.json") +database_file = os.path.join(base_directory, "config", "database.json") + +with open(bot_file, "r") as bdata, open(database_file, "r") as ddata: + bot_data, database_data = json.load(bdata), json.load(ddata) + +async def initBot() -> None: + """Initialize the bot.""" + if __name__ == '__main__': + # Database connector + bot.database_data, server = database_data, database_data["server"] + bot.database = DataSQL(server["host"], server["port"]) + await bot.database.auth(server["user"], server["password"], server["database"]) + + # Cogs loader + cogs_directory = os.path.join(base_directory, "cogs") + for cog in os.listdir(cogs_directory): + actual = os.path.splitext(cog) + if actual[1] == '.py': + bot.load_extension('cogs.'+actual[0]) + +bot = commands.Bot(command_prefix=commands.when_mentioned_or(bot_data["bot_prefix"]), description=bot_data["bot_description"], intents=discord.Intents.all(), help_command=None) +bot.loop.create_task(initBot()) @bot.event async def on_ready(): print("Logged in as: "+str(bot.user)+"\nVersion: "+str(discord.__version__)) -bot.run(json_data["token"], reconnect=True) \ No newline at end of file +bot.run(bot_data["token"], reconnect=True) \ No newline at end of file diff --git a/classes/database.py b/classes/database.py index 9603f25..2215825 100644 --- a/classes/database.py +++ b/classes/database.py @@ -1,7 +1,8 @@ -from datetime import datetime, date import aiomysql import asyncio +from datetime import datetime, date + class DataSQL(): def __init__(self, host:str = "127.0.0.1", port:int = 3306, loop:asyncio.AbstractEventLoop = None) -> None: self.loop, self.host, self.port, self.connector = loop, host, port, None diff --git a/cogs/admin.py b/cogs/admin.py index c87655e..d9d020e 100644 --- a/cogs/admin.py +++ b/cogs/admin.py @@ -17,7 +17,7 @@ def help_custom(self): description = "Show the list of admin commands." return emoji, label, description - async def reload_views(self): + async def reload_views(self) -> list[str]: modules, infants = [], [] for module in sys.modules.items(): if isinstance(module[1], types.ModuleType): @@ -32,7 +32,7 @@ async def reload_views(self): return infants - async def reload_cogs(self, cogs): + async def reload_cogs(self, cogs) -> list[str]: victims = [] for cog in cogs: norm_cog = self.bot.get_cog(cog[5:len(cog)]) diff --git a/cogs/birthday.py b/cogs/birthday.py index 71b8b83..a956906 100644 --- a/cogs/birthday.py +++ b/cogs/birthday.py @@ -1,25 +1,18 @@ -import os -import json import time import random import asyncio import discord -from classes.database import DataSQL - from datetime import datetime, date from discord.ext import commands, tasks -auth_directory = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "auth", "auth.json") -with open(auth_directory, "r") as data: database_data = json.load(data)["database"] -birthday_data = database_data["birthday"] - class Birthday(commands.Cog, name="birthday"): """I'll wish you soon a happy birthday!""" def __init__(self, bot): self.bot = bot - self.bot.loop.create_task(self.initBirthday()) + self.birthday_data = self.bot.database_data["birthday"] + self.daily_birthday.start() def help_custom(self): @@ -28,20 +21,16 @@ def help_custom(self): description = "Maybe I'll wish you soon a happy birthday!" return emoji, label, description - async def initBirthday(self): - self.database = DataSQL(database_data["host"], database_data["port"]) - await self.database.auth(database_data["user"], database_data["password"], birthday_data["database"]) - def cog_unload(self): self.daily_birthday.cancel() @tasks.loop(hours=1) async def daily_birthday(self): if datetime.now().hour == 9: - guild = self.bot.get_guild(int(birthday_data["guild_id"])) - channel = guild.get_channel(int(birthday_data["channel_id"])) + guild = self.bot.get_guild(int(self.birthday_data["guild_id"])) + channel = guild.get_channel(int(self.birthday_data["channel_id"])) - response = await self.database.select(birthday_data["table"], "*") + response = await self.bot.database.select(self.birthday_data["table"], "*") for data in response: user_id, user_birth = data[0], data[1] @@ -62,7 +51,7 @@ async def daily_birthday(self): @daily_birthday.before_loop async def before_daily_birthday(self): await self.bot.wait_until_ready() - while self.database.connector is None: await asyncio.sleep(0.01) #wait_for initBirthday + while self.bot.database.connector is None: await asyncio.sleep(0.01) #wait_for initBirthday @commands.command(name='birthday', aliases=['bd', 'setbirthday', 'setbirth', 'birth']) @commands.cooldown(1, 10, commands.BucketType.user) @@ -73,9 +62,9 @@ async def birthday(self, ctx, date: str = None): dataDate = datetime.strptime(date, "%d/%m/%Y").date() if dataDate.year > datetime.now().year - 15 or dataDate.year < datetime.now().year - 99: raise commands.CommandError("Please provide your real year of birth.") # Insert - await self.database.insert(birthday_data["table"], {"user_id": ctx.author.id, "user_birth": dataDate}) + await self.bot.database.insert(self.birthday_data["table"], {"user_id": ctx.author.id, "user_birth": dataDate}) # Update - await self.database.update(birthday_data["table"], "user_birth", dataDate, "user_id = "+str(ctx.author.id)) + await self.bot.database.update(self.birthday_data["table"], "user_birth", dataDate, "user_id = "+str(ctx.author.id)) await self.show_birthday_message(ctx, ctx.author) except ValueError: @@ -93,7 +82,7 @@ async def show_birthday(self, ctx, user:discord.Member = None): await self.show_birthday_message(ctx, user) async def show_birthday_message(self, ctx, user:discord.Member) -> None: - response = await self.database.lookup(birthday_data["table"], "user_birth", "user_id", str(user.id)) + response = await self.bot.database.lookup(self.birthday_data["table"], "user_birth", "user_id", str(user.id)) if response: dataDate : date = response[0][0] timestamp = round(time.mktime(dataDate.timetuple())) diff --git a/cogs/errors.py b/cogs/errors.py index f5f2b88..c83e14e 100644 --- a/cogs/errors.py +++ b/cogs/errors.py @@ -1,7 +1,4 @@ -import discord - from discord.ext import commands -from discord.ext.commands import errors class Errors(commands.Cog, name="errors", command_attrs=dict(hidden=True)): """Errors handler""" diff --git a/cogs/fridaycake.py b/cogs/fridaycake.py index 2fe0233..7662f09 100644 --- a/cogs/fridaycake.py +++ b/cogs/fridaycake.py @@ -1,11 +1,8 @@ -import os -import json import random import discord import asyncio from views import fridaycake -from classes.database import DataSQL from datetime import date, timedelta, datetime from discord.ext import commands @@ -13,11 +10,6 @@ holidays = [(date(2022, 2, 12), date(2022, 2, 19)), (date(2022, 4, 10), date(2022, 4, 23))] #Saturday -> Saturday start = date(2022, 2, 4)#date(2021, 10, 8)#date(2021, 2, 7) #year #month #day (first friday) -seed = 2 - -auth_directory = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "auth", "auth.json") -with open(auth_directory, "r") as data: database_data = json.load(data)["database"] -fridaycake_data = database_data["fridaycake"] def isDateInHole(date : datetime, holes : list) -> bool: for hole in holes: @@ -52,28 +44,26 @@ def mix_participants(participants : list, seed : int, n_group : int) -> list[lis class FridayCake(commands.Cog, name="fridaycake", command_attrs=dict(hidden=False)): """FridayCake's event commands.""" def __init__(self, bot): - self.bot, self.seed = bot, seed + self.bot = bot self.cakes = ['🎂', '🥮', '🥧', '🥯', '🧁', '🫓', '🧇', '🍞', '🍮', '🍰', '🥐'] + self.fridaycake_data = self.bot.database_data["fridaycake"] + self.seed = self.fridaycake_data["seed"] + self.bot.loop.create_task(self.initFridaycake()) + async def initFridaycake(self): + participants = await self.bot.database.select(self.fridaycake_data["table"], "user_id, user_name", "user_isin = 1") + participants = [[*row] for row in participants] #convert tuple of tuples to list of lists + self.participants = mix_participants(participants, self.seed, 2) + self.nparticipants = len(participants) #mandatory in fridaycake view + def help_custom(self): emoji = random.choice(self.cakes) label = "FridayCake" description = "Commands relative to the FridayCake event !" return emoji, label, description - def cog_unload(self) -> None: - self.database.close() - - async def initFridaycake(self): - self.database = DataSQL(database_data["host"], database_data["port"]) - await self.database.auth(database_data["user"], database_data["password"], database_data["fridaycake"]["database"]) - - participants = await self.database.select(fridaycake_data["table"], "user_id, user_name", "user_isin = 1") - participants = [[*row] for row in participants] #convert tuple of tuples to list of lists - self.participants = mix_participants(participants, seed, 2) - self.nparticipants = len(participants) #mandatory in fridaycake view def all(self, ctx): author = ctx.message.author diff --git a/cogs/me.py b/cogs/me.py index d0312b7..b8aa9d0 100644 --- a/cogs/me.py +++ b/cogs/me.py @@ -1,22 +1,14 @@ -import os -import json import discord -from classes.database import DataSQL - from discord.ext import commands -auth_directory = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "auth", "auth.json") -with open(auth_directory, "r") as data: database_data = json.load(data)["database"] -me_data = database_data["me"] -max_lenght_me = 255 - class Me(commands.Cog, name="me", command_attrs=dict(hidden=False)): """FridayCake's event commands.""" def __init__(self, bot): self.bot = bot - - self.bot.loop.create_task(self.initMe()) + + self.me_data = self.bot.database_data["me"] + self.max_lenght_me = self.me_data["max_length"] def help_custom(self): emoji = '🤸' @@ -24,13 +16,6 @@ def help_custom(self): description = "Set and show a brief description of yourself." return emoji, label, description - def cog_unload(self) -> None: - self.database.close() - - async def initMe(self): - self.database = DataSQL(database_data["host"], database_data["port"]) - await self.database.auth(database_data["user"], database_data["password"], database_data["fridaycake"]["database"]) - @commands.command(name='me', aliases=['description']) @commands.cooldown(1, 10, commands.BucketType.user) async def me(self, ctx, *args:str): @@ -38,11 +23,11 @@ async def me(self, ctx, *args:str): if len(args): try: text = " ".join(args).replace("'", "''") - if len(text) > max_lenght_me: raise commands.CommandError("The max-lenght of your *me* is set to: __"+str(max_lenght_me)+"__ (yours is "+str(len(text))+").") + if len(text) > self.max_lenght_me: raise commands.CommandError("The max-lenght of your *me* is set to: __"+str(self.max_lenght_me)+"__ (yours is "+str(len(text))+").") # Insert - await self.database.insert(me_data["table"], {"user_id": ctx.author.id, "user_me": text}) + await self.bot.database.insert(self.me_data["table"], {"user_id": ctx.author.id, "user_me": text}) # Update - await self.database.update(me_data["table"], "user_me", text, "user_id = "+str(ctx.author.id)) + await self.bot.database.update(self.me_data["table"], "user_me", text, "user_id = "+str(ctx.author.id)) await self.show_me_message(ctx, ctx.author) except Exception as e: raise commands.CommandError(str(e)) @@ -57,7 +42,7 @@ async def show_me(self, ctx, user:discord.Member = None): await self.show_me_message(ctx, user) async def show_me_message(self, ctx, user:discord.Member) -> None: - response = await self.database.lookup(me_data["table"], "user_me", "user_id", str(user.id)) + response = await self.bot.database.lookup(self.me_data["table"], "user_me", "user_id", str(user.id)) message = " ".join(response[0]) if len(response) else "No description provided.." await ctx.send("• **"+ user.display_name + "** " + message) diff --git a/cogs/usefull.py b/cogs/usefull.py index 9fed63a..f6c1558 100644 --- a/cogs/usefull.py +++ b/cogs/usefull.py @@ -1,5 +1,3 @@ -import discord - from discord.ext import commands class Usefull(commands.Cog, name="usefull", command_attrs=dict(hidden=False)): diff --git a/config/bot.json b/config/bot.json new file mode 100644 index 0000000..d57990d --- /dev/null +++ b/config/bot.json @@ -0,0 +1,5 @@ +{ + "token": "*************************************.******.**********************", + "bot_description": "Algobot", + "bot_prefix": "?" +} \ No newline at end of file diff --git a/config/database.json b/config/database.json new file mode 100644 index 0000000..99f5c41 --- /dev/null +++ b/config/database.json @@ -0,0 +1,25 @@ +{ + "server": { + "host": "127.0.0.1", + "port": 3306, + "user": "user", + "password": "********", + "database": "database" + }, + "birthday": { + "table": "table_birthday", + + "guild_id": 332234497078853644, + "channel_id": 332234497078853644 + }, + "fridaycake": { + "table": "table_fridaycake", + + "seed": 2 + }, + "me": { + "table": "table_me", + + "max_length": 255 + } +} \ No newline at end of file