diff --git a/main.py b/main.py index 62a9ac1..d5b8ac9 100644 --- a/main.py +++ b/main.py @@ -395,17 +395,33 @@ class ClientById: channel = self.client.get_channel(id_) return channel.send(*args, **kwargs) - async def get_role(self, id_=None, name=None): + async def get_role(self, id_=None, name=None, guild=None, case_sensitive=True): + guilds = self.client.guilds + if guild is not None: + guilds = [guild] if id_ is not None: - for guild in self.client.guilds: + for guild in guilds: role = discord.utils.get(guild.roles, id=id_) if role: return role if name is not None: - for guild in self.client.guilds: - role = discord.utils.get(guild.roles, name=name) - if role: - return role + if case_sensitive: + for guild in guilds: + role = discord.utils.get(guild.roles, name=name) + if role: + return role + else: + name = name.lower() + role = None + + for guild in guilds: + for role_ in guild.roles: + if role_.name.lower() == name: + role = role_ + break + if role is not None: + break + return role return None diff --git a/modules/avalon/__init__.py b/modules/avalon/__init__.py new file mode 100644 index 0000000..9f7ef53 --- /dev/null +++ b/modules/avalon/__init__.py @@ -0,0 +1,56 @@ +import datetime + +import discord + +import utils.emojis +from modules.base import BaseClassPython + + +class MainClass(BaseClassPython): + name = "Avalon" + help = { + "description": "Maître du jeu Avalon.", + "commands": { + "`{prefix}{command} join`": "", + "`{prefix}{command} quit`": "", + "`{prefix}{command} players list`": "", + "`{prefix}{command} players kick (/<@mention>)`": "", + "`{prefix}{command} roles setup`": "", + "`{prefix}{command} roles list`": "", + } + } + help_active = True + command_text = "perdu" + color = 0xff6ba6 + + def __init__(self, client): + super().__init__(client) + self.config.init({"spectate_channel": 0, + "illustrations":{"merlin":"", + "perceval":"", + "gentil":"", + "assassin":"", + "mordred":"", + "morgane":"", + "oberon":"", + "mechant":""}, + "couleurs":{"merlin":"", + "perceval":0, + "gentil":0, + "assassin":0, + "mordred":0, + "morgane":0, + "oberon":0, + "mechant":0, + "test":15}, + "test":{"merlin":"", + "perceval":0, + "gentil":0, + "assassin":0, + "mordred":0, + "morgane":0, + "oberon":0, + "mechant":0, + "test":15} + }) + diff --git a/modules/avalon/roles.py b/modules/avalon/roles.py new file mode 100644 index 0000000..e69de29 diff --git a/modules/base/Base.py b/modules/base/Base.py index 32269d0..9fe5c24 100644 --- a/modules/base/Base.py +++ b/modules/base/Base.py @@ -37,14 +37,17 @@ class BaseClass: self.config.init({"authorized_roles": self.authorized_roles, "authorized_users": self.authorized_users}) async def send_help(self, channel): + if not self.help_active: + return + embed = discord.Embed( title="[{nom}] - Aide".format(nom=self.name), - description=self.help["description"].format(prefix=self.client.config['prefix']), + description="*" + self.help["description"].format(prefix=self.client.config['prefix']) + "*", color=self.color ) for command, description in self.help["commands"].items(): embed.add_field(name=command.format(prefix=self.client.config['prefix'], command=self.command_text), - value=description.format(prefix=self.client.config['prefix'], command=self.command_text), + value="-> " + description.format(prefix=self.client.config['prefix'], command=self.command_text), inline=False) await channel.send(embed=embed) @@ -165,6 +168,9 @@ class BaseClass: Function which is executed for all command_text doesn't match with a `com_{subcommand}` function""" pass + async def com_help(self, message, args, kwargs): + await self.send_help(message.channel) + async def unauthorized(self, message): await message.channel.send("Vous n'êtes pas autorisé à effectuer cette commande") diff --git a/modules/clean/__init__.py b/modules/clean/__init__.py new file mode 100644 index 0000000..3d9bdae --- /dev/null +++ b/modules/clean/__init__.py @@ -0,0 +1,19 @@ +from modules.base import BaseClassPython + +class MainClass(BaseClassPython): + name = "clean" + authorized_roles=[522918472548745217] + help = { + "description": "Supprime des messages", + "commands": { + "`{prefix}{command}`": "Supprime tous les messages du bot dans le salon" + } + } + command_text = "clean" + + async def command(self, message, args, kwargs): + def is_me(m): + return m.author == self.client.user + + deleted = await message.channel.purge(limit=10000000, check=is_me) + await message.channel.send('Deleted {} message(s)'.format(len(deleted))) diff --git a/modules/clean/version.json b/modules/clean/version.json new file mode 100644 index 0000000..b27fd9a --- /dev/null +++ b/modules/clean/version.json @@ -0,0 +1,11 @@ +{ + "version":"0.1.0", + "type": "python", + "dependencies": { + + }, + "bot_version": { + "min": "0.1.0", + "max": "0.1.0" + } +} \ No newline at end of file diff --git a/modules/errors/__init__.py b/modules/errors/__init__.py index ce919f3..41991e9 100644 --- a/modules/errors/__init__.py +++ b/modules/errors/__init__.py @@ -1,106 +1,106 @@ -import asyncio -import random -import traceback - -import discord -from discord import Message - -from modules.base import BaseClassPython - - -class MainClass(BaseClassPython): - name = "errors" - help_active = True - authorized_users = [431043517217898496] - authorized_roles = [] - color = 0xdb1348 - help = { - "description": "Montre toutes les erreurs du bot dans discord.", - "commands": { - "`{prefix}{command}`": "Renvoie une erreur de test.", - } - } - command_text = "unicorn" - - def __init__(self, client): - super().__init__(client) - self.config.init({"dev_chan": [], "memes": [""], "icon": ""}) - self.errorsList = None - - async def on_load(self): - if self.objects.save_exists('errorsList'): - self.errorsList = self.objects.load_object('errorsList') - else: - self.errorsList = [] - - async def on_ready(self): - for i in range(len(self.errorsList)): - try: - msg_id = self.errorsList.pop(0) - channel = self.client.get_channel(msg_id["channel_id"]) - to_delete = await channel.fetch_message(msg_id["msg_id"]) - await to_delete.delete() - except: - raise - await self.objects.save_object('errorsList', self.errorsList) - - async def command(self, message, args, kwargs): - raise Exception("KERNEL PANIC!!!") - - async def on_error(self, event, *args, **kwargs): - """Send error message""" - # Search first channel instance found in arg, then search in kwargs - channel = None - for arg in args: - if type(arg) == Message: - channel = arg.channel - break - if type(arg) == discord.TextChannel: - channel = arg - break - if channel is None: - for _, v in kwargs.items(): - if type(v) == discord.Message: - channel = v.channel - break - if type(v) == discord.TextChannel: - channel = v - break # Create embed - embed = discord.Embed( - title="[Erreur] Aïe :/", - description="```python\n{0}```".format(traceback.format_exc()), - color=self.color) - embed.set_image(url=random.choice(self.config.memes)) - message_list = None - - # Send message to dev channels - for chanid in self.config.dev_chan: - try: - await self.client.get_channel(chanid).send( - embed=embed.set_footer(text="Ce message ne s'autodétruira pas.", icon_url=self.config.icon)) - except BaseException as e: - raise e - # Send message to current channel if exists - if channel is not None: - message = await channel.send(embed=embed.set_footer(text="Ce message va s'autodétruire dans une minute", - icon_url=self.config.icon)) - msg_id = {"channel_id": message.channel.id, "msg_id": message.id} - self.errorsList.append(msg_id) - # Save message in errorsList now to keep them if a reboot happend during next 60 seconds - self.objects.save_object('errorsList', self.errorsList) - - # Wait 60 seconds and delete message - await asyncio.sleep(60) - try: - channel = self.client.get_channel(msg_id["channel_id"]) - delete_message = await channel.fetch_message(msg_id["msg_id"]) - await delete_message.delete() - except: - raise - finally: - try: - self.errorsList.remove(msg_id) - except ValueError: - pass - # Save now to avoid deleting unkown message - self.objects.save_object('errorsList', self.errorsList) +import asyncio +import random +import traceback + +import discord +from discord import Message + +from modules.base import BaseClassPython + + +class MainClass(BaseClassPython): + name = "errors" + help_active = True + authorized_users = [431043517217898496] + authorized_roles = [] + color = 0xdb1348 + help = { + "description": "Montre toutes les erreurs du bot dans discord.", + "commands": { + "`{prefix}{command}`": "Renvoie une erreur de test.", + } + } + command_text = "unicorn" + + def __init__(self, client): + super().__init__(client) + self.config.init({"dev_chan": [], "memes": [""], "icon": ""}) + self.errorsList = None + + async def on_load(self): + if self.objects.save_exists('errorsList'): + self.errorsList = self.objects.load_object('errorsList') + else: + self.errorsList = [] + + async def on_ready(self): + for i in range(len(self.errorsList)): + try: + msg_id = self.errorsList.pop(0) + channel = self.client.get_channel(msg_id["channel_id"]) + to_delete = await channel.fetch_message(msg_id["msg_id"]) + await to_delete.delete() + except: + raise + self.objects.save_object('errorsList', self.errorsList) + + async def command(self, message, args, kwargs): + raise Exception("KERNEL PANIC!!!") + + async def on_error(self, event, *args, **kwargs): + """Send error message""" + # Search first channel instance found in arg, then search in kwargs + channel = None + for arg in args: + if type(arg) == Message: + channel = arg.channel + break + if type(arg) == discord.TextChannel: + channel = arg + break + if channel is None: + for _, v in kwargs.items(): + if type(v) == discord.Message: + channel = v.channel + break + if type(v) == discord.TextChannel: + channel = v + break # Create embed + embed = discord.Embed( + title="[Erreur] Aïe :/", + description="```python\n{0}```".format(traceback.format_exc()), + color=self.color) + embed.set_image(url=random.choice(self.config.memes)) + message_list = None + + # Send message to dev channels + for chanid in self.config.dev_chan: + try: + await self.client.get_channel(chanid).send( + embed=embed.set_footer(text="Ce message ne s'autodétruira pas.", icon_url=self.config.icon)) + except BaseException as e: + raise e + # Send message to current channel if exists + if channel is not None: + message = await channel.send(embed=embed.set_footer(text="Ce message va s'autodétruire dans une minute", + icon_url=self.config.icon)) + msg_id = {"channel_id": message.channel.id, "msg_id": message.id} + self.errorsList.append(msg_id) + # Save message in errorsList now to keep them if a reboot happend during next 60 seconds + self.objects.save_object('errorsList', self.errorsList) + + # Wait 60 seconds and delete message + await asyncio.sleep(60) + try: + channel = self.client.get_channel(msg_id["channel_id"]) + delete_message = await channel.fetch_message(msg_id["msg_id"]) + await delete_message.delete() + except: + raise + finally: + try: + self.errorsList.remove(msg_id) + except ValueError: + pass + # Save now to avoid deleting unkown message + self.objects.save_object('errorsList', self.errorsList) diff --git a/modules/newmember/__init__.py b/modules/newmember/__init__.py new file mode 100644 index 0000000..2b5ab64 --- /dev/null +++ b/modules/newmember/__init__.py @@ -0,0 +1,34 @@ +import discord +import sys +from modules.base import BaseClassPython + + +class MainClass(BaseClassPython): + name = "NewMember" + color = 0xff071f + help_active = False + help = { + "description": "Module d'accueil", + "commands": { + } + } + + def __init__(self, client): + super().__init__(client) + self.config.init({"new_role":430845952388104212, + "guild":297780867286433792, + "motd":"Bienvenue sur le serveur de la communauté d'E-penser. Nous vous prions de lire le règlement afin d'accéder au serveur complet."}) + + async def on_ready(self): + guild = self.client.get_guild(self.config.guild) + for i, member in enumerate(guild.members): + if len(member.roles) == 1: + await member.add_roles(await self.client.id.get_role(id_=self.config.new_role, + guild=guild)) + if i%50==0: + print(i, member) + + async def on_member_join(self, member): + await member.add_roles(await self.client.id.get_role(id_=self.config.new_role, + guild=self.client.get_guild(self.config.guild))) + await member.send(self.config.motd) diff --git a/modules/newmember/version.json b/modules/newmember/version.json new file mode 100644 index 0000000..b27fd9a --- /dev/null +++ b/modules/newmember/version.json @@ -0,0 +1,11 @@ +{ + "version":"0.1.0", + "type": "python", + "dependencies": { + + }, + "bot_version": { + "min": "0.1.0", + "max": "0.1.0" + } +} \ No newline at end of file diff --git a/modules/purge/__init__.py b/modules/purge/__init__.py new file mode 100644 index 0000000..0d9b0cc --- /dev/null +++ b/modules/purge/__init__.py @@ -0,0 +1,41 @@ +import discord +import sys +from modules.base import BaseClassPython + +class MainClass(BaseClassPython): + name = "Purge" + color = 0xff0004 + help_active = True + authorized_roles=[522918472548745217] + help = { + "description": "Suppression de messages en block.", + "commands": { + "`{prefix}{command} `": "Supprime tous les messages du salon jusqu'au message spécifié", + } + } + command_text = "purge" + + async def command(self, message, args, kwargs): + message_id = None + try: + message_id = int(args[0]) + except ValueError: + pass + if len(args) and message_id is not None: + messages_list=[] + done=False + async for current in message.channel.history(limit=None): + if int(current.id) == message_id: + done = True + break + elif message.id != current.id: + messages_list.append(current) + if done: + chunks = [messages_list[x:x+99] for x in range(0, len(messages_list), 99)] + for chunk in chunks: + await message.channel.delete_messages(chunk) + await message.channel.send(f"**{len(messages_list)}** messages supprimés.") + else: + await message.channel.send("Le message spécifié n'a pas été trouvé.") + else: + await message.channel.send("Arguments invalides.") diff --git a/modules/purge/version.json b/modules/purge/version.json new file mode 100644 index 0000000..b27fd9a --- /dev/null +++ b/modules/purge/version.json @@ -0,0 +1,11 @@ +{ + "version":"0.1.0", + "type": "python", + "dependencies": { + + }, + "bot_version": { + "min": "0.1.0", + "max": "0.1.0" + } +} \ No newline at end of file diff --git a/modules/readrules/__init__.py b/modules/readrules/__init__.py new file mode 100644 index 0000000..e80b0b6 --- /dev/null +++ b/modules/readrules/__init__.py @@ -0,0 +1,37 @@ +import discord +import sys +from modules.base import BaseClassPython + + +class MainClass(BaseClassPython): + name = "ReadRules" + color = 0xff071f + help_active = False + help = { + "description": "Module d'accueil", + "commands": { + } + } + + def __init__(self, client): + super().__init__(client) + self.config.init({"accepted_role":430846685380345876, + "new_role":430845952388104212, + "listen_chan":430995739636793345, + "log_chan":429977240202248192, + "passwords":["cacahuète","cacahuete","cacahuètes","cacahuetes"], + "succes_pm":"Félicitations, vous êtes désormais un **e-penseur** accompli. Bienvenue sur le serveur E-penser.", + "succes":" est désormais un **e-penseur** accompli."}) + + async def on_message(self, message): + if message.channel.id == self.config.listen_chan: + if message.content.lower() in self.config.passwords: + new_role = await self.client.id.get_role(id_=self.config.new_role, guild=message.channel.guild) + if new_role in message.author.roles: + await message.author.remove_roles(new_role) + await message.author.add_roles(await self.client.id.get_role(id_=self.config.accepted_role, + guild=message.channel.guild)) + await message.author.send(self.config.succes_pm) + await message.channel.guild.get_channel(self.config.log_chan).send(message.author.mention + self.config.succes) + else: + await message.author.send(f"Le mot de passe que vous avez entré est incorrect : `{message.content}`.\nNous vous prions de lire le règlement afin d'accéder au serveur complet.") diff --git a/modules/readrules/version.json b/modules/readrules/version.json new file mode 100644 index 0000000..b27fd9a --- /dev/null +++ b/modules/readrules/version.json @@ -0,0 +1,11 @@ +{ + "version":"0.1.0", + "type": "python", + "dependencies": { + + }, + "bot_version": { + "min": "0.1.0", + "max": "0.1.0" + } +} \ No newline at end of file diff --git a/modules/restart/__init__.py b/modules/restart/__init__.py new file mode 100644 index 0000000..f16e33a --- /dev/null +++ b/modules/restart/__init__.py @@ -0,0 +1,22 @@ +import discord +import sys +from modules.base import BaseClassPython + + +class MainClass(BaseClassPython): + name = "Restart" + color = 0xff071f + help_active = True + authorized_roles = [431043517217898496] + help = { + "description": "Module gérant les redémarrages de Nikola Tesla", + "commands": { + "`{prefix}{command}`": "Redémarre le bot.", + } + } + command_text = "restart" + + async def command(self, message, args, kwargs): + await message.channel.send(f"{message.author.mention}, Le bot va redémarrer.") + await self.client.logout() + sys.exit(0) diff --git a/modules/restart/version.json b/modules/restart/version.json new file mode 100644 index 0000000..b27fd9a --- /dev/null +++ b/modules/restart/version.json @@ -0,0 +1,11 @@ +{ + "version":"0.1.0", + "type": "python", + "dependencies": { + + }, + "bot_version": { + "min": "0.1.0", + "max": "0.1.0" + } +} \ No newline at end of file diff --git a/modules/roles/__init__.py b/modules/roles/__init__.py index 60e30b0..fa40202 100644 --- a/modules/roles/__init__.py +++ b/modules/roles/__init__.py @@ -8,34 +8,103 @@ class MainClass(BaseClassPython): color = 0xffb593 help_active = True help = { - "description": "Modulé gérant l'attribution des roles", + "description": "Module gérant l'attribution des roles", "commands": { "`{prefix}{command} list`": "Liste les roles", - "`{prefix}{command} `": "S'attribuer le role " + "`{prefix}{command} add [role] ...`": "S'attribuer le(s) rôle(s) ([role]...)", + "`{prefix}{command} remove [role] ...`": "Se désattribuer le(s) rôle(s) ([role]...)", + "`{prefix}{command} toggle [role] ...`": "S'attribuer (ou désattribuer) le(s) rôle(s) ([role]...)", + "`{prefix}{command} [role] ...`": "Alias de `{prefix}{command} toggle`", } } command_text = "roles" def __init__(self, client): super().__init__(client) - self.config.init({"roles": {}}) + self.config.init({"guild":297780867286433792, + "roles": {"435559220860157952":"Rôle mentionné lors des jeux."}}) async def com_list(self, message, args, kwargs): response = discord.Embed(title="Roles disponibles", color=self.color) for id_ in self.config.roles.keys(): - role = await self.client.id.get_role(int(id_)) - response.add_field(name=role.name, value=self.config.roles[id_], inline=True) + print(id_,type(id_)) + role = message.guild.get_role(int(id_)) + if role is not None: + response.add_field(name=role.name, value=f" -> `{self.config.roles[id_]}`", inline=True) await message.channel.send(embed=response) async def com_add(self, message, args, kwargs): + guild = self.client.get_guild(self.config.guild) + member = guild.get_member(message.author.id) if len(args) <= 1: await message.channel.send("Il manque des arguments à la commande") - for role in args[0:]: - drole = await self.client.id.get_role(name="Invité") - if drole is None or str(drole.id) not in self.config.roles.keys(): - await message.channel.send(f"Le role {role} n'est pas disponible.") + for role_ in args[1:]: + role = await self.client.id.get_role(name=role_, guild=guild, case_sensitive=False) + if role is None or str(role.id) not in self.config.roles.keys(): + await message.channel.send(f"Le role {role_} n'est pas disponible.") else: - try: - await message.author.add_roles(drole) - except discord.errors.Forbidden: - await message.channel.send(f"Je n'ai pas la permission d'attribuer le role {role}.") + await self.tryaddrole(message, member, role) + + async def com_remove(self, message, args, kwargs): + guild = self.client.get_guild(self.config.guild) + member = guild.get_member(message.author.id) + if len(args) <= 1: + await message.channel.send("Il manque des arguments à la commande") + for role_ in args[1:]: + role = await self.client.id.get_role(name=role_, guild=guild, case_sensitive=False) + if role is None or str(role.id) not in self.config.roles.keys(): + await message.channel.send(f"Le role {role_} n'est pas disponible.") + else: + await self.tryremoverole(message, member, role) + + async def com_toggle(self, message, args, kwargs): + guild = self.client.get_guild(self.config.guild) + member = guild.get_member(message.author.id) + if len(args) <= 1: + await message.channel.send("Il manque des arguments à la commande") + for role_ in args[1:]: + role = await self.client.id.get_role(name=role_, guild=guild, case_sensitive=False) + if role is None or str(role.id) not in self.config.roles.keys(): + await message.channel.send(f"Le role {role_} n'est pas disponible.") + else: + await self.trytogglerole(message, member, role) + + async def command(self, message, args, kwargs): + guild = self.client.get_guild(self.config.guild) + member = guild.get_member(message.author.id) + if len(args) < 1: + await message.channel.send("Il manque des arguments à la commande") + for role_ in args: + role = await self.client.id.get_role(name=role_, guild=guild, case_sensitive=False) + if role is None or str(role.id) not in self.config.roles.keys(): + await message.channel.send(f"Le role {role_} n'est pas disponible.") + else: + await self.trytogglerole(message, member, role) + + async def trytogglerole(self, message, member, role): + if role in member.roles: + await self.tryremoverole(message, member, role) + else: + await self.tryaddrole(message, member, role) + + async def tryaddrole(self, message, member, role): + if role in member.roles: + await message.channel.send(f"Vous avez déjà le rôle {role}.") + return + try: + await member.add_roles(role, reason="Auto-attribution") + except discord.errors.Forbidden: + await message.channel.send(f"Je n'ai pas la permission de vous attribuer le rôle {role}.") + else: + await message.channel.send(f"Vous avez reçu le rôle {role}.") + + async def tryremoverole(self, message, member, role): + if not role in member.roles: + await message.channel.send(f"Vous n'avez pas le rôle {role}.") + return + try: + await member.remove_roles(role, reason="Auto-désattribution") + except discord.errors.Forbidden: + await message.channel.send(f"Je n'ai pas la permission de vous retirer le rôle {role}.") + else: + await message.channel.send(f"Vous avez perdu le rôle {role}.") diff --git a/storage/jsonencoder.py b/storage/jsonencoder.py index 804e286..c2d7013 100644 --- a/storage/jsonencoder.py +++ b/storage/jsonencoder.py @@ -5,30 +5,29 @@ data_type = "__data_type" content = "__content" -class Encoder(json.JSONEncoder): - def __init__(self): - super().__init__() - self.custom = {} - - def register(self, type_, encode, decode, decode_args={}): - self.custom.update({type_: (encode, decode, decode_args)}) - - def default(self, obj): - if isinstance(obj, tuple(self.custom.keys())): - return {data_type: f'{type(obj)}', content: self.custom[type(obj)][0](obj)} - if isinstance(obj, (datetime.datetime)): - return {data_type: 'datetime.datetime', 'iso': obj.isoformat()} - if isinstance(obj, (datetime.timedelta)): - return {data_type: 'datetime.timedelta', 'totalseconds': obj.total_seconds()} - return json.JSONEncoder.default(self, obj) +class Encoder(): + def __init__(self, *args, **kwargs): + self.custom = {Encoder:(lambda x:x, lambda x:x)} + self.JSONEncoder.custom = self.custom + def register(self, type_, encode, decode): + self.custom.update({type_: (encode, decode)}) def hook(self, dct): if data_type in dct: for ty in self.custom.keys(): if str(ty) == dct[data_type]: - return self.custom[ty][1](dct[content], **self.custom[ty][2]) + return self.custom[ty][1](dct[content]) if dct[data_type] == "datetime.datetime": return datetime.datetime.fromisoformat(dct['iso']) elif dct[data_type] == "datetime.timedelta": return datetime.timedelta(seconds=dct['totalseconds']) return dct + class JSONEncoder(json.JSONEncoder) : + def default(self, obj): + if isinstance(obj, tuple(self.custom.keys())): + return {data_type: f'{type(obj)}', content: self.custom[type(obj)][0](obj)} + if isinstance(obj, (datetime.datetime)): + return {data_type: 'datetime.datetime', 'iso': obj.isoformat()} + if isinstance(obj, (datetime.timedelta)): + return {data_type: 'datetime.timedelta', 'totalseconds': obj.total_seconds()} + return json.JSONEncoder.default(self, obj) diff --git a/storage/objects.py b/storage/objects.py index ba9826e..0f696fa 100644 --- a/storage/objects.py +++ b/storage/objects.py @@ -8,12 +8,12 @@ class Objects: def __init__(self, path: str): self.path = os.path.abspath(path) os.makedirs(os.path.join(self.path, "objects"), exist_ok=True) - self.encoder = jsonencoder.Encoder + self.encoder = jsonencoder.Encoder() def save_object(self, object_name, object_instance): """Save object into json file""" with open(os.path.join(self.path, "objects", object_name + ".json"), "w") as file: - json.dump(object_instance, file, cls=self.encoder) + json.dump(object_instance, file, cls=self.encoder.JSONEncoder) def load_object(self, object_name): """Load object from json file"""