Skip to content

Commit 02c99c7

Browse files
author
Conch
authored
Merge pull request #68 from WhoIsConch/master
Feat: Convert modmail to forum channel, other changes
2 parents 8fb3ca7 + 8be2ff3 commit 02c99c7

File tree

3 files changed

+75
-55
lines changed

3 files changed

+75
-55
lines changed

cogs/modmail.py

Lines changed: 70 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,85 @@
11
import typing
2-
import aiohttp
3-
from ext.consts import MODMAIL_CHANNEL_ID, MODMAIL_WEBHOOK_URL
2+
from ext.consts import MODMAIL_CHANNEL_ID, MODMAIL_ROLE_ID, MODMAIL_CLOSED, MODMAIL_OPEN
43
from discord.ext import commands
54
import discord
65
from ext.ui.view import YesNoView
7-
import os
86

7+
def none_if_error(func):
8+
def wrapper(*args, **kwargs):
9+
try:
10+
return func(*args, **kwargs)
11+
except Exception:
12+
return None
13+
14+
return wrapper
915

1016
class ModMail(commands.Cog):
1117
def __init__(self, bot: commands.Bot):
1218
self.bot = bot
13-
self.current_modmail = {}
14-
self.opposite_current_modmail = {}
15-
self.channel: typing.Optional[discord.TextChannel] = None
19+
self.sessions = [] # [{user: discord.Member, thread: discord.Thread}]
20+
self.channel: typing.Optional[discord.ForumChannel] = None
21+
22+
@none_if_error
23+
def get_thread(self, user) -> discord.Thread | None:
24+
return [i['thread'] for i in self.sessions if i['user'] == user][0]
25+
26+
@none_if_error
27+
def get_user(self, thread) -> discord.Member | discord.User | None:
28+
return [i['user'] for i in self.sessions if i['thread'] == thread][0]
29+
30+
async def send_webhook_message(
31+
self,
32+
message: discord.Message,
33+
thread: discord.Thread
34+
):
35+
webhook = thread.parent.webhooks()[0]
36+
await webhook.send(
37+
username=message.author.name,
38+
content=message.content,
39+
avatar_url=message.author.display_avatar.url,
40+
files=message.attachments,
41+
allowed_mentions=discord.AllowedMentions(
42+
users=False, everyone=False, roles=False
43+
),
44+
thread=thread,
45+
)
46+
await message.add_reaction("✅")
47+
48+
async def close_thread(self, thread: discord.Thread):
49+
await thread.add_tags(thread.parent.get_tag(MODMAIL_CLOSED))
50+
await thread.remove_tags(thread.parent.get_tag(MODMAIL_OPEN))
51+
await thread.edit(locked=True, archived=True)
52+
self.sessions.remove({'user': self.get_user(thread), 'thread': thread})
1653

1754
@commands.hybrid_command()
18-
async def close(self, ctx):
19-
if not ctx.guild:
20-
if ctx.author in self.current_modmail:
21-
thread = self.current_modmail[ctx.author]
22-
await thread.edit(locked=True)
23-
self.current_modmail.pop(ctx.author)
24-
self.opposite_current_modmail.pop(thread)
25-
await ctx.send("Your modmail ticket has successfully closed!")
26-
elif ctx.channel in self.opposite_current_modmail:
27-
member = self.opposite_current_modmail[ctx.channel]
55+
async def close(self, ctx: commands.Context):
56+
if not ctx.guild and (thread := self.get_thread(ctx.author)):
57+
await thread.send("This ticket has been closed by the user.")
58+
await self.close_thread(thread)
59+
await ctx.send("Your modmail ticket has successfully closed!")
60+
61+
elif member := self.get_user(ctx.channel):
2862
view = YesNoView(
2963
yes_message="Your modmail ticket has successfully closed!",
3064
no_message="Aborted.",
3165
)
3266
await member.send(content="Do you want to close the ticket?", view=view)
3367
await view.wait()
3468
if view.yes:
35-
await ctx.channel.edit(locked=True)
36-
self.current_modmail.pop(member)
37-
self.opposite_current_modmail.pop(ctx.channel)
69+
await self.close_thread(ctx.channel)
3870
else:
3971
await ctx.channel.send("Member refused to close the ticket.")
4072

4173
@commands.Cog.listener()
4274
async def on_message(self, message: discord.Message):
43-
if (
44-
not self.channel
45-
): # I was unsure if getting the channel in the __init__ is wise
46-
self.channel = self.bot.get_channel(MODMAIL_CHANNEL_ID)
75+
if not self.channel:
76+
self.channel: discord.ForumChannel = self.bot.get_channel(MODMAIL_CHANNEL_ID)
4777

48-
if message.author.bot or message.content.startswith(self.bot.command_prefix):
78+
if message.author.bot or message.content.startswith(self.bot.command_prefix[0]):
4979
return
5080

5181
if not message.guild:
52-
if message.author not in self.current_modmail:
82+
if not (thread := self.get_thread(message.author)):
5383
view = YesNoView(
5484
yes_message="Your modmail ticket has been successfully created!",
5585
no_message="Aborted.",
@@ -59,37 +89,24 @@ async def on_message(self, message: discord.Message):
5989
)
6090
await view.wait()
6191
if view.yes:
62-
msg_sent = await self.channel.send(
63-
message.content,
92+
thread, _ = await self.channel.create_thread(
93+
name=f"Modmail @{message.author.name}",
94+
content="New ModMail ticket created by "\
95+
f"{message.author.mention}, <@&{MODMAIL_ROLE_ID}>",
6496
files=message.attachments,
65-
allowed_mentions=discord.AllowedMentions(
66-
users=False, everyone=False, roles=False
67-
),
68-
)
69-
thread = await self.channel.create_thread(
70-
name=f"{message.author.name} vs mods", message=msg_sent
97+
applied_tags=[self.channel.get_tag(MODMAIL_OPEN)],
7198
)
72-
self.current_modmail[message.author] = thread
73-
self.opposite_current_modmail[thread] = message.author
99+
await self.send_webhook_message(message, thread)
100+
101+
self.sessions.append({'user': message.author, 'thread': thread})
74102
else:
75-
thread = self.current_modmail[message.author]
76-
async with aiohttp.ClientSession() as session:
77-
webhook = discord.Webhook.from_url(
78-
MODMAIL_WEBHOOK_URL, session=session
79-
)
80-
await webhook.send(
81-
content=message.content,
82-
avatar_url=message.author.display_avatar.url,
83-
files=message.attachments,
84-
allowed_mentions=discord.AllowedMentions(
85-
users=False, everyone=False, roles=False
86-
),
87-
thread=thread,
88-
)
89-
await message.add_reaction("✅")
90-
elif message.channel in self.opposite_current_modmail:
91-
member = self.opposite_current_modmail[message.channel]
92-
await member.send("⚒️ staff: " + message.content, files=message.attachments)
103+
await self.send_webhook_message(message, thread)
104+
105+
elif member := self.get_user(message.channel):
106+
await member.send(
107+
f"⚒️ @{message.author.name}: " + message.content,
108+
files=message.attachments
109+
)
93110

94111

95112
async def setup(bot):

ext/consts.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,10 @@ def release_format(self):
151151
READ_HELP_RULES_ROLE_ID = 903133599715459153
152152
TCR_STAFF_ROLE_ID = 795145820210462771
153153
TCR_MEMBER_ROLE_ID = 744403871262179430
154-
MODMAIL_CHANNEL_ID = 1144329989072900106
154+
MODMAIL_CHANNEL_ID = 1144791467391455242 # conch: 1144827896171610185
155+
MODMAIL_ROLE_ID = 788799215417032705
156+
MODMAIL_OPEN = 1144842655671517305 # conch internal: 1144839090609602611
157+
MODMAIL_CLOSED = 1144842686579359837 # conch: 1144839107353256017
155158

156159
# mods pls fill this up
157160
TICKET_CATEGORY_ID = 0

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ bs4==0.0.1
88
button_paginator @ git+https://github.com/andrewthederp/Button_paginator
99
charset-normalizer==2.0.12
1010
colorthief==0.2.1
11-
discord.py @ git+https://github.com/Rapptz/discord.py@db5a22d7912557c55fc047f30f42ef10b6a63289
11+
discord.py
1212
DiscordUtils==1.3.4
1313
frozenlist==1.3.0
1414
humanize==4.1.0

0 commit comments

Comments
 (0)