Skip to content

Commit 53e032a

Browse files
committed
feat: implement event handler system, fix #98
1 parent e942e3e commit 53e032a

File tree

9 files changed

+143
-110
lines changed

9 files changed

+143
-110
lines changed

Teapot.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from dotenv import load_dotenv
1010

1111
import teapot
12+
from teapot.event_handler.loader import EventHandlerLoader
1213

1314
print(f"""
1415
_____ _
@@ -83,12 +84,15 @@
8384
print(
8485
f"Connected to database ({teapot.config.db_host()}:{teapot.config.db_port()}) in {round(time.perf_counter() - time_start, 2)}s")
8586

87+
8688
intents = discord.Intents.all()
8789
intents.members = True
8890
intents.message_content = True
8991
intents.typing = False
9092
bot = dcmd.Bot(intents=intents, command_prefix=teapot.config.bot_prefix(), help_command=None)
9193

94+
event_handler_loader = EventHandlerLoader(bot) # Event Handler
95+
9296

9397
@bot.event
9498
async def on_ready():

teapot/cogs/nqn.py

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
class Emoji(commands.Cog):
66
def __init__(self, bot):
77
self.bot = bot
8-
self.on_message_send(bot)
98

109
async def getemote(self, arg):
1110
emoji = utils.get(self.bot.emojis, name=arg.strip(":"))
@@ -61,41 +60,6 @@ async def getinstr(self, content):
6160

6261
return ret
6362

64-
def on_message_send(self, bot):
65-
@bot.event
66-
async def on_message(message):
67-
if message.author.bot: # check is author bot
68-
return
69-
70-
if ":" in message.content:
71-
msg = await self.getinstr(message.content)
72-
ret = ""
73-
em = False
74-
smth = message.content.split(":")
75-
if len(smth) > 1:
76-
for word in msg:
77-
if word.startswith(":") and word.endswith(":") and len(word) > 1:
78-
emoji = await self.getemote(word)
79-
if emoji is not None:
80-
em = True
81-
ret += f" {emoji}"
82-
else:
83-
ret += f" {word}"
84-
else:
85-
ret += f" {word}"
86-
87-
else:
88-
ret += msg
89-
90-
if em:
91-
webhooks = await message.channel.webhooks()
92-
webhook = utils.get(webhooks, name="Imposter NQN")
93-
if webhook is None:
94-
webhook = await message.channel.create_webhook(name="Imposter NQN")
95-
96-
await webhook.send(ret, username=message.author.name, avatar_url=message.author.display_avatar.url)
97-
await message.delete()
98-
9963

10064
async def setup(bot):
10165
await bot.add_cog(Emoji(bot))

teapot/event_handler/__init__.py

Whitespace-only changes.

teapot/event_handler/db_handler.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import teapot
2+
3+
async def on_message_handler(bot, message):
4+
if teapot.config.storage_type() == "mysql":
5+
try:
6+
database = teapot.database.__init__()
7+
db = teapot.database.db(database)
8+
db.execute("SELECT * FROM `users` WHERE user_id = '" + str(message.author.id) + "'")
9+
if db.rowcount == 0:
10+
db.execute("INSERT INTO `users`(user_id, user_name, user_display_name) VALUES(%s, %s, %s)",
11+
(message.author.id, message.author.name, message.author.display_name))
12+
database.commit()
13+
db.execute("SELECT * FROM `channels` WHERE channel_id = '" + str(message.channel.id) + "'")
14+
if db.rowcount == 0:
15+
db.execute("INSERT INTO `channels`(channel_id, channel_name) VALUES(%s, %s)",
16+
(message.channel.id, message.channel.name))
17+
database.commit()
18+
db.execute(
19+
"INSERT INTO `guild_logs`(timestamp, guild_id, channel_id, message_id, user_id, action_type, message) VALUES(%s, %s, %s, %s, %s, %s, %s)",
20+
(teapot.time(), message.guild.id, message.channel.id, message.id, message.author.id,
21+
"MESSAGE_SEND", message.content))
22+
database.commit()
23+
except Exception as e:
24+
print(e)

teapot/event_handler/loader.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
from discord.ext import commands
2+
import importlib
3+
import os
4+
5+
class EventHandlerLoader:
6+
"""
7+
Dynamically loads event handler modules and registers a unified on_message event.
8+
9+
As discord only allows one on_message event, this loader collects all on_message handlers
10+
from the event_handler submodules and calls them sequentially.
11+
"""
12+
def __init__(self, bot: commands.Bot):
13+
self.bot = bot
14+
self.handlers = []
15+
self.load_event_handlers()
16+
self.register_on_message()
17+
18+
def load_event_handlers(self):
19+
"""
20+
Scan for all python file in the event_handler directory to find on_message handlers.
21+
"""
22+
handler_dir = os.path.dirname(__file__)
23+
for fname in os.listdir(handler_dir):
24+
if fname.endswith('.py') and fname not in ('__init__.py', 'loader.py'):
25+
mod_name = f'teapot.event_handler.{fname[:-3]}'
26+
module = importlib.import_module(mod_name)
27+
if hasattr(module, 'on_message_handler'):
28+
self.handlers.append(module.on_message_handler)
29+
30+
def get_registered_handlers(self):
31+
return self.handlers
32+
33+
def register_on_message(self):
34+
@self.bot.event
35+
async def on_message(message):
36+
for handler in self.handlers:
37+
await handler(self.bot, message)
38+
await self.bot.process_commands(message)
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
from discord import utils
2+
3+
async def on_message_handler(bot, message):
4+
if message.author.bot:
5+
return
6+
if ":" in message.content:
7+
emoji_cog = bot.get_cog("Emoji") # obtain the Emoji Cog instance
8+
if emoji_cog is None:
9+
return
10+
msg = await emoji_cog.getinstr(message.content)
11+
ret = ""
12+
em = False
13+
smth = message.content.split(":")
14+
if len(smth) > 1:
15+
for word in msg:
16+
if word.startswith(":") and word.endswith(":") and len(word) > 1:
17+
emoji = await emoji_cog.getemote(word)
18+
if emoji is not None:
19+
em = True
20+
ret += f" {emoji}"
21+
else:
22+
ret += f" {word}"
23+
else:
24+
ret += f" {word}"
25+
else:
26+
ret += msg
27+
if em:
28+
webhooks = await message.channel.webhooks()
29+
webhook = utils.get(webhooks, name="Imposter NQN")
30+
if webhook is None:
31+
webhook = await message.channel.create_webhook(name="Imposter NQN")
32+
await webhook.send(ret, username=message.author.name, avatar_url=message.author.display_avatar.url)
33+
await message.delete()
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import teapot
2+
from teapot.events import predict_prob
3+
import discord
4+
5+
async def on_message_handler(bot, message):
6+
punctuations = '!()-[]{};:\'"\\,<>./?@#$%^&*_~'
7+
msg = ""
8+
for char in message.content.lower():
9+
if char not in punctuations:
10+
msg = msg + char
11+
prob = predict_prob([msg])
12+
if prob >= 0.8:
13+
em = discord.Embed(title=f"AI Analysis Results", color=0xC54B4F)
14+
em.add_field(name='PROFANITY DETECTED! ', value=str(prob[0]))
15+
await message.channel.send(embed=em)
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import discord
2+
import teapot
3+
4+
async def on_message_handler(bot, message):
5+
punctuations = '!()-[]{};:\'"\\,<>./?@#$%^&*_~'
6+
msg = ""
7+
for char in message.content.lower():
8+
if char not in punctuations:
9+
msg = msg + char
10+
if msg.startswith("system call "):
11+
content = msg[12:].split(" ")
12+
if content[0].lower() == "inspect":
13+
if content[1].lower() == "entire":
14+
if content[2].lower() == "command":
15+
if content[3].lower() == "list":
16+
em = discord.Embed(title=f"🍢 SAO Command List", color=0x7400FF)
17+
em.set_thumbnail(url="https://cdn.discordapp.com/attachments/668816286784159763/674285661510959105/Kirito-Sao-Logo-1506655414__76221.1550241566.png")
18+
em.add_field(name='Commands', value="generate xx element\ngenerate xx element xx shape\ninspect entire command list")
19+
em.set_footer(text=f"{teapot.copyright()} | Code licensed under the MIT License")
20+
await message.channel.send(embed=em)
21+
elif content[0].lower() == "generate":
22+
if content[-1].lower() == "element":
23+
em = discord.Embed(title=f"✏ Generated {content[1].lower()} element!", color=0xFF0000)
24+
await message.channel.send(embed=em)
25+
if content[-1].lower() == "shape":
26+
if content[2].lower() == "element":
27+
em = discord.Embed(title=f"✏ Generated {content[-2].lower()} shaped {content[1].lower()} element!", color=0xFF0000)
28+
await message.channel.send(embed=em)

teapot/events.py

Lines changed: 1 addition & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ def __init__(bot):
99
join(bot)
1010
leave(bot)
1111
on_guild_join(bot)
12-
message_send(bot)
12+
# on_message is now handled by event_handler/loader.py
1313
message_edit(bot)
1414
message_delete(bot)
1515
on_command_error(bot)
@@ -51,79 +51,6 @@ async def on_guild_join(ctx):
5151
if teapot.config.storage_type() == "mysql":
5252
teapot.database.create_guild_table(ctx.guild)
5353

54-
55-
def message_send(bot):
56-
@bot.event
57-
async def on_message(message):
58-
if teapot.config.storage_type() == "mysql":
59-
try:
60-
database = teapot.database.__init__()
61-
db = teapot.database.db(database)
62-
db.execute("SELECT * FROM `users` WHERE user_id = '" + str(message.author.id) + "'")
63-
if db.rowcount == 0:
64-
db.execute("INSERT INTO `users`(user_id, user_name, user_display_name) VALUES(%s, %s, %s)",
65-
(message.author.id, message.author.name, message.author.display_name))
66-
database.commit()
67-
68-
db.execute("SELECT * FROM `channels` WHERE channel_id = '" + str(message.channel.id) + "'")
69-
if db.rowcount == 0:
70-
db.execute("INSERT INTO `channels`(channel_id, channel_name) VALUES(%s, %s)",
71-
(message.channel.id, message.channel.name))
72-
database.commit()
73-
db.execute(
74-
"INSERT INTO `guild_logs`(timestamp, guild_id, channel_id, message_id, user_id, action_type, message) VALUES(%s, %s, %s, %s, %s, %s, %s)",
75-
(teapot.time(), message.guild.id, message.channel.id, message.id, message.author.id,
76-
"MESSAGE_SEND", message.content))
77-
database.commit()
78-
except Exception as e:
79-
print(e)
80-
await bot.process_commands(message)
81-
82-
@bot.event
83-
async def on_message(message):
84-
# SAO Easter Egg
85-
punctuations = '!()-[]{};:\'"\\,<>./?@#$%^&*_~'
86-
# remove punctuation from the string
87-
msg = ""
88-
for char in message.content.lower():
89-
if char not in punctuations:
90-
msg = msg + char
91-
92-
# profanity check
93-
prob = predict_prob([msg])
94-
if prob >= 0.8:
95-
em = discord.Embed(title=f"AI Analysis Results", color=0xC54B4F) # TODO: this will be replaced with cloud detection soon
96-
em.add_field(name='PROFANITY DETECTED! ', value=str(prob[0]))
97-
await message.channel.send(embed=em)
98-
99-
if msg.startswith("system call "):
100-
content = msg[12:].split(" ")
101-
if content[0].lower() == "inspect":
102-
if content[1].lower() == "entire":
103-
if content[2].lower() == "command":
104-
if content[3].lower() == "list":
105-
em = discord.Embed(title=f"🍢 SAO Command List", color=0x7400FF)
106-
em.set_thumbnail(
107-
url="https://cdn.discordapp.com/attachments/668816286784159763/674285661510959105/Kirito-Sao-Logo-1506655414__76221.1550241566.png")
108-
em.add_field(name='Commands',
109-
value="generate xx element\ngenerate xx element xx shape\ninspect entire command list")
110-
111-
em.set_footer(text=f"{teapot.copyright()} | Code licensed under the MIT License")
112-
await message.channel.send(embed=em)
113-
elif content[0].lower() == "generate":
114-
if content[-1].lower() == "element":
115-
em = discord.Embed(title=f"✏ Generated {content[1].lower()} element!",
116-
color=0xFF0000)
117-
await message.channel.send(embed=em)
118-
if content[-1].lower() == "shape":
119-
if content[2].lower() == "element":
120-
em = discord.Embed(
121-
title=f"✏ Generated {content[-2].lower()} shaped {content[1].lower()} element!",
122-
color=0xFF0000)
123-
await message.channel.send(embed=em)
124-
await bot.process_commands(message)
125-
126-
12754
def message_edit(bot):
12855
@bot.event
12956
async def on_raw_message_edit(ctx):

0 commit comments

Comments
 (0)