Skip to content

Commit 417f303

Browse files
committed
add multiple users to a thread (resolve #3066), new group config options
1 parent 00eb779 commit 417f303

File tree

4 files changed

+401
-80
lines changed

4 files changed

+401
-80
lines changed

cogs/modmail.py

Lines changed: 236 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -671,108 +671,271 @@ async def title(self, ctx, *, name: str):
671671
await ctx.message.pin()
672672
await self.bot.add_reaction(ctx.message, sent_emoji)
673673

674-
@commands.command(cooldown_after_parsing=True)
674+
@commands.command(usage="<users> [options]", cooldown_after_parsing=True)
675675
@checks.has_permissions(PermissionLevel.SUPPORTER)
676676
@checks.thread_only()
677677
@commands.cooldown(1, 600, BucketType.channel)
678-
async def adduser(self, ctx, user: discord.Member, *, options: str.lower = ""):
678+
async def adduser(self, ctx, *users: Union[discord.Member, str]):
679679
"""Adds a user to a modmail thread
680680
681681
`options` can be `silent` or `silently`.
682682
"""
683-
684-
curr_thread = await self.bot.threads.find(recipient=user)
685-
if curr_thread:
683+
silent = False
684+
for u in users:
685+
if isinstance(u, str):
686+
if "silent" in u or "silently" in u:
687+
silent = True
688+
users.remove(u) # remove all strings so users is a List[Member]
689+
else:
690+
# u is a discord.Member
691+
curr_thread = await self.bot.threads.find(recipient=u)
692+
if curr_thread:
693+
em = discord.Embed(
694+
title="Error",
695+
description=f"{u.mention} is already in a thread: {curr_thread.channel.mention}.",
696+
color=self.bot.error_color,
697+
)
698+
await ctx.send(embed=em)
699+
ctx.command.reset_cooldown(ctx)
700+
return
701+
if not silent:
686702
em = discord.Embed(
687-
title="Error",
688-
description=f"User is already in a thread: {curr_thread.channel.mention}.",
689-
color=self.bot.error_color,
703+
title=self.bot.config["private_added_to_group_title"],
704+
description=self.bot.config["private_added_to_group_description"].format(moderator=ctx.author),
705+
color=self.bot.main_color,
690706
)
691-
await ctx.send(embed=em)
692-
ctx.command.reset_cooldown(ctx)
693-
else:
694-
if "silent" not in options and "silently" not in options:
695-
em = discord.Embed(
696-
title="New Thread (Group)",
697-
description=f"{ctx.author.name} has added you to a Modmail thread.",
698-
color=self.bot.main_color,
699-
)
700-
if self.bot.config["show_timestamp"]:
701-
em.timestamp = datetime.utcnow()
702-
em.set_footer(text=f"{ctx.author}", icon_url=ctx.author.avatar_url)
703-
await user.send(embed=em)
707+
if self.bot.config["show_timestamp"]:
708+
em.timestamp = datetime.utcnow()
709+
em.set_footer(text=str(ctx.author), icon_url=ctx.author.avatar_url)
710+
for u in users:
711+
await u.send(embed=em)
704712

705-
em = discord.Embed(
706-
title="New User",
707-
description=f"{ctx.author.name} has added {user.name} to the Modmail thread.",
708-
color=self.bot.main_color,
709-
)
710-
if self.bot.config["show_timestamp"]:
711-
em.timestamp = datetime.utcnow()
712-
em.set_footer(text=f"{user}", icon_url=user.avatar_url)
713+
em = discord.Embed(
714+
title=self.bot.config["public_added_to_group_title"],
715+
description=self.bot.config["private_added_to_group_description"].format(moderator=ctx.author, users=', '.join(u.name for u in users)),
716+
color=self.bot.main_color,
717+
)
718+
if self.bot.config["show_timestamp"]:
719+
em.timestamp = datetime.utcnow()
720+
em.set_footer(text=f"{users[0]}", icon_url=users[0].avatar_url)
713721

714-
for i in ctx.thread.recipients:
715-
if i != user:
716-
await i.send(embed=em)
722+
for i in ctx.thread.recipients:
723+
if i not in users:
724+
await i.send(embed=em)
717725

718-
await ctx.thread.add_user(user)
719-
sent_emoji, _ = await self.bot.retrieve_emoji()
720-
await self.bot.add_reaction(ctx.message, sent_emoji)
726+
await ctx.thread.add_users(users)
727+
sent_emoji, _ = await self.bot.retrieve_emoji()
728+
await self.bot.add_reaction(ctx.message, sent_emoji)
721729

722-
@commands.command(cooldown_after_parsing=True)
730+
@commands.command(usage="<users...> [options]", cooldown_after_parsing=True)
723731
@checks.has_permissions(PermissionLevel.SUPPORTER)
724732
@checks.thread_only()
725733
@commands.cooldown(1, 600, BucketType.channel)
726-
async def removeuser(self, ctx, user: discord.Member, *, options: str.lower = ""):
734+
async def removeuser(self, ctx, *users: Union[discord.Member, str]):
727735
"""Removes a user from a modmail thread
728736
729737
`options` can be `silent` or `silently`.
730738
"""
739+
silent = False
740+
for u in users:
741+
if isinstance(u, str):
742+
if "silent" in u or "silently" in u:
743+
silent = True
744+
users.remove(u) # remove all strings so users is a List[Member]
745+
else:
746+
# u is a discord.Member
747+
curr_thread = await self.bot.threads.find(recipient=u)
748+
if ctx.thread != curr_thread:
749+
em = discord.Embed(
750+
title="Error",
751+
description=f"{u.mention} is not in this thread.",
752+
color=self.bot.error_color,
753+
)
754+
await ctx.send(embed=em)
755+
ctx.command.reset_cooldown(ctx)
756+
return
757+
elif ctx.thread.recipient == u:
758+
em = discord.Embed(
759+
title="Error",
760+
description=f"{u.mention} is the main recipient of the thread and cannot be removed.",
761+
color=self.bot.error_color,
762+
)
763+
await ctx.send(embed=em)
764+
ctx.command.reset_cooldown(ctx)
765+
return
731766

732-
curr_thread = await self.bot.threads.find(recipient=user)
733-
if ctx.thread != curr_thread:
767+
if not silent:
734768
em = discord.Embed(
735-
title="Error",
736-
description="User is not in this thread.",
737-
color=self.bot.error_color,
769+
title=self.bot.config["private_removed_from_group_title"],
770+
description=self.bot.config["private_removed_from_group_description"].format(moderator=ctx.author),
771+
color=self.bot.main_color,
738772
)
739-
await ctx.send(embed=em)
740-
ctx.command.reset_cooldown(ctx)
741-
elif ctx.thread.recipient == user:
773+
if self.bot.config["show_timestamp"]:
774+
em.timestamp = datetime.utcnow()
775+
em.set_footer(text=str(ctx.author), icon_url=ctx.author.avatar_url)
776+
for u in users:
777+
await u.send(embed=em)
778+
742779
em = discord.Embed(
743-
title="Error",
744-
description="User is the main recipient of the thread and cannot be removed.",
745-
color=self.bot.error_color,
780+
title=self.bot.config["public_removed_from_group_title"],
781+
description=self.bot.config["private_removed_from_group_description"].format(moderator=ctx.author, users=', '.join(u.name for u in users)),
782+
color=self.bot.main_color,
746783
)
747-
await ctx.send(embed=em)
748-
ctx.command.reset_cooldown(ctx)
749-
else:
750-
if "silent" not in options and "silently" not in options:
751-
em = discord.Embed(
752-
title="Removed From Thread (Group)",
753-
description=f"{ctx.author.name} has been removed from the Modmail thread.",
754-
color=self.bot.main_color,
755-
)
756-
if self.bot.config["show_timestamp"]:
757-
em.timestamp = datetime.utcnow()
758-
em.set_footer(text=f"{ctx.author}", icon_url=ctx.author.avatar_url)
759-
await user.send(embed=em)
784+
if self.bot.config["show_timestamp"]:
785+
em.timestamp = datetime.utcnow()
786+
em.set_footer(text=f"{users[0]}", icon_url=users[0].avatar_url)
760787

761-
em = discord.Embed(
762-
title="User Removed",
763-
description=f"{ctx.author.name} has removed {user.name} from the Modmail thread.",
764-
color=self.bot.main_color,
765-
)
766-
if self.bot.config["show_timestamp"]:
767-
em.timestamp = datetime.utcnow()
768-
em.set_footer(text=f"{user}", icon_url=user.avatar_url)
788+
for i in ctx.thread.recipients:
789+
if i not in users:
790+
await i.send(embed=em)
791+
792+
await ctx.thread.remove_users(users)
793+
sent_emoji, _ = await self.bot.retrieve_emoji()
794+
await self.bot.add_reaction(ctx.message, sent_emoji)
795+
796+
@commands.command(usage="<users...> [options]", cooldown_after_parsing=True)
797+
@checks.has_permissions(PermissionLevel.SUPPORTER)
798+
@checks.thread_only()
799+
@commands.cooldown(1, 600, BucketType.channel)
800+
async def anonadduser(self, ctx, *users: Union[discord.Member, str]):
801+
"""Adds a user to a modmail thread anonymously
802+
803+
`options` can be `silent` or `silently`.
804+
"""
805+
silent = False
806+
for u in users:
807+
if isinstance(u, str):
808+
if "silent" in u or "silently" in u:
809+
silent = True
810+
users.remove(u) # remove all strings so users is a List[Member]
811+
else:
812+
# u is a discord.Member
813+
curr_thread = await self.bot.threads.find(recipient=u)
814+
if curr_thread:
815+
em = discord.Embed(
816+
title="Error",
817+
description=f"{u.mention} is already in a thread: {curr_thread.channel.mention}.",
818+
color=self.bot.error_color,
819+
)
820+
await ctx.send(embed=em)
821+
ctx.command.reset_cooldown(ctx)
822+
return
823+
if not silent:
824+
em = discord.Embed(
825+
title=self.bot.config["private_added_to_group_title"],
826+
description=self.bot.config["private_added_to_group_description_anon"],
827+
color=self.bot.main_color,
828+
)
829+
if self.bot.config["show_timestamp"]:
830+
em.timestamp = datetime.utcnow()
831+
832+
tag = self.bot.config["mod_tag"]
833+
if tag is None:
834+
tag = str(ctx.author.top_role)
835+
name = self.bot.config["anon_username"]
836+
if name is None:
837+
name = tag
838+
avatar_url = self.bot.config["anon_avatar_url"]
839+
if avatar_url is None:
840+
avatar_url = self.bot.guild.icon_url
841+
em.set_footer(text=name, icon_url=avatar_url)
842+
843+
for u in users:
844+
await u.send(embed=em)
769845

770-
for i in ctx.thread.recipients:
846+
em = discord.Embed(
847+
title=self.bot.config["public_added_to_group_title"],
848+
description=self.bot.config["private_added_to_group_description_anon"].format(moderator=ctx.author, users=', '.join(u.name for u in users)),
849+
color=self.bot.main_color,
850+
)
851+
if self.bot.config["show_timestamp"]:
852+
em.timestamp = datetime.utcnow()
853+
em.set_footer(text=f"{users[0]}", icon_url=users[0].avatar_url)
854+
855+
for i in ctx.thread.recipients:
856+
if i not in users:
771857
await i.send(embed=em)
772858

773-
await ctx.thread.remove_user(user)
774-
sent_emoji, _ = await self.bot.retrieve_emoji()
775-
await self.bot.add_reaction(ctx.message, sent_emoji)
859+
await ctx.thread.add_users(users)
860+
sent_emoji, _ = await self.bot.retrieve_emoji()
861+
await self.bot.add_reaction(ctx.message, sent_emoji)
862+
863+
@commands.command(usage="<users...> [options]", cooldown_after_parsing=True)
864+
@checks.has_permissions(PermissionLevel.SUPPORTER)
865+
@checks.thread_only()
866+
@commands.cooldown(1, 600, BucketType.channel)
867+
async def anonremoveuser(self, ctx, *users: Union[discord.Member, str]):
868+
"""Removes a user from a modmail thread anonymously
869+
870+
`options` can be `silent` or `silently`.
871+
"""
872+
silent = False
873+
for u in users:
874+
if isinstance(u, str):
875+
if "silent" in u or "silently" in u:
876+
silent = True
877+
users.remove(u) # remove all strings so users is a List[Member]
878+
else:
879+
# u is a discord.Member
880+
curr_thread = await self.bot.threads.find(recipient=u)
881+
if ctx.thread != curr_thread:
882+
em = discord.Embed(
883+
title="Error",
884+
description=f"{u.mention} is not in this thread.",
885+
color=self.bot.error_color,
886+
)
887+
await ctx.send(embed=em)
888+
ctx.command.reset_cooldown(ctx)
889+
return
890+
elif ctx.thread.recipient == u:
891+
em = discord.Embed(
892+
title="Error",
893+
description=f"{u.mention} is the main recipient of the thread and cannot be removed.",
894+
color=self.bot.error_color,
895+
)
896+
await ctx.send(embed=em)
897+
ctx.command.reset_cooldown(ctx)
898+
return
899+
900+
if not silent:
901+
em = discord.Embed(
902+
title=self.bot.config["private_removed_from_group_title"],
903+
description=self.bot.config["private_removed_from_group_description_anon"].format(moderator=ctx.author),
904+
color=self.bot.main_color,
905+
)
906+
if self.bot.config["show_timestamp"]:
907+
em.timestamp = datetime.utcnow()
908+
909+
tag = self.bot.config["mod_tag"]
910+
if tag is None:
911+
tag = str(ctx.author.top_role)
912+
name = self.bot.config["anon_username"]
913+
if name is None:
914+
name = tag
915+
avatar_url = self.bot.config["anon_avatar_url"]
916+
if avatar_url is None:
917+
avatar_url = self.bot.guild.icon_url
918+
em.set_footer(text=name, icon_url=avatar_url)
919+
920+
for u in users:
921+
await u.send(embed=em)
922+
923+
em = discord.Embed(
924+
title=self.bot.config["public_removed_from_group_title"],
925+
description=self.bot.config["private_removed_from_group_description"].format(moderator=ctx.author, users=', '.join(u.name for u in users)),
926+
color=self.bot.main_color,
927+
)
928+
if self.bot.config["show_timestamp"]:
929+
em.timestamp = datetime.utcnow()
930+
em.set_footer(text=f"{users[0]}", icon_url=users[0].avatar_url)
931+
932+
for i in ctx.thread.recipients:
933+
if i not in users:
934+
await i.send(embed=em)
935+
936+
await ctx.thread.remove_users(users)
937+
sent_emoji, _ = await self.bot.retrieve_emoji()
938+
await self.bot.add_reaction(ctx.message, sent_emoji)
776939

777940
@commands.group(invoke_without_command=True)
778941
@checks.has_permissions(PermissionLevel.SUPPORTER)

core/config.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,19 @@ class ConfigManager:
8383
"silent_alert_on_mention": False,
8484
"show_timestamp": True,
8585
"anonymous_snippets": False,
86+
# group conversations
87+
"private_added_to_group_title": "New Thread (Group)",
88+
"private_added_to_group_description": "{moderator.name} has added you to a Modmail thread.",
89+
"private_added_to_group_description_anon": "A moderator has added you to a Modmail thread.",
90+
"public_added_to_group_title": "New User",
91+
"public_added_to_group_description": "{moderator.name} has added {users} to the Modmail thread.",
92+
"public_added_to_group_description_anon": "A moderator has added {users} to the Modmail thread.",
93+
"private_removed_from_group_title": "Removed From Thread (Group)",
94+
"private_removed_from_group_description": "{moderator.name} has removed you from the Modmail thread.",
95+
"private_removed_from_group_description_anon": "A moderator has removed you from the Modmail thread.",
96+
"public_removed_from_group_title": "User Removed",
97+
"public_removed_from_group_description": "{moderator.name} has removed {users} from the Modmail thread.",
98+
"public_removed_from_group_description_anon": "A moderator has removed {users} from the Modmail thread.",
8699
# moderation
87100
"recipient_color": str(discord.Color.gold()),
88101
"mod_color": str(discord.Color.green()),

0 commit comments

Comments
 (0)