This repository has been archived by the owner on Aug 2, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathphoton_bot.py
97 lines (87 loc) · 3.48 KB
/
photon_bot.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
"""
An easily expandable Discord Bot written in Python 3 using the pycord library.
"""
import configparser
import importlib
import os
import discord
from discord.flags import Intents
class plugin_types:
"""
An enum representing the different types of plugin that the bot can load
"""
COMMAND = 0
EVENT = 1
TASK = 2
class PhotonBot:
"""
Represents a Discord bot being handled by the Photon Bot Framework.
The `discord.Bot` instance itself can be found under `discord_bot`,
the loaded config file under `config` and the bot's starting datetime under
`start_time`. The bot will automatically load plugins specified in config
file when an instance is created.
"""
__version__ = "1.0.0"
def __init__(self, config_path: str):
"""
Create an instance of discord.Bot with all Intents and load plugins
specified in the config file. Does not open a connection to Discord.
"""
## A (hopefully) temporary fix to a bug in pycord.
## /~https://github.com/Pycord-Development/pycord/issues/1393
# Ensure that command function parameter checks always pass
discord.commands.core.SlashCommand._check_required_params = (
lambda self, params: iter(params.items())
)
# Stop the 'ctx' parameter being considered as a Discord command option
old_func = discord.commands.core.SlashCommand._parse_options
discord.commands.core.SlashCommand._parse_options = (
lambda self, params: old_func(self, params)[1:]
)
self.discord_bot = discord.Bot(intents=Intents.all())
self.config = configparser.ConfigParser(
interpolation=configparser.BasicInterpolation()
)
self.config.read(config_path)
self.directory_location = os.path.dirname(__file__)
self.variables = {}
self.start_time = None
# Load plugins specified in config file
for cmd_plugin in self.config['Plugins']['Commands'].split(","):
self.load_plugin(cmd_plugin.strip(), plugin_types.COMMAND)
for event_plugin in self.config['Plugins']['Events'].split(","):
self.load_plugin(event_plugin.strip(), plugin_types.EVENT)
for task_plugin in self.config['Plugins']['Tasks'].split(","):
self.load_plugin(task_plugin.strip(), plugin_types.TASK)
def load_plugin(self, name: str, plugin_type: int):
"""
Manually load a plugin. The plugin name should not include the
directory as that will automatically be inferred based on the plugin
type.
"""
old_cwd = os.getcwd()
os.chdir(self.directory_location)
try:
if plugin_type == 0:
importlib.import_module(
f"plugins.commands.{name}"
).register_commands(self)
elif plugin_type == 1:
importlib.import_module(
f"plugins.events.{name}"
).register_events(self)
elif plugin_type == 2:
importlib.import_module(
f"plugins.tasks.{name}"
).register_tasks(self)
else:
raise ValueError(f"Invalid plugin type '{plugin_type}'")
finally:
os.chdir(old_cwd)
def start(self, *args, **kwargs):
"""
Login and open a connection to Discord
"""
self.discord_bot.run(
*args, **kwargs, token=self.config['DiscordAuth']['Token']
)