Skip to content

Commit

Permalink
Give users a second chance if they use /confess in the wrong channel
Browse files Browse the repository at this point in the history
  • Loading branch information
yiays committed Sep 2, 2024
1 parent d8b34dc commit 7fedba2
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 55 deletions.
2 changes: 1 addition & 1 deletion babel/confessionbot_en.ini
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ nosendchannel = You can't send anonymous messages here! Use this command in a ch
nosendbanned = No can do, you've been banned on this server.
nosendimages = No can do, this server has disabled anonymous images.
invalidimage = This doesn't appear to be a valid image file.
wrongcommand = You must use the {p:{cmd}} command in this channel.
wrongcommand = You must use the {p:{cmd}} command in {channel}.
; setup
setup_start = Below is this channel's current configuration, you can configure any channels from here.
*Press help below for more information about how this channel works.*
Expand Down
1 change: 1 addition & 0 deletions config/config.factory.ini
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ changelog = > 1.0.0
> 2.6.0
- New channel type added: Marketplace - Users can list items they would like to sell, other users can make anonymous offers, then their usernames are shared with each other privately
- You can now reply to a message by choosing "Confession Reply" in the right-click menu of a message
- If you send a confession to the wrong channel by mistake, you now get a chance to redirect it to another channel
- Simplified setup screen by hiding untraceable versions of channels, these can now be toggled with a button
- Improved the information found in the /premium command
- Improved the lists of commands featured in /help
Expand Down
28 changes: 21 additions & 7 deletions extensions/confessions.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,17 +179,17 @@ def __init__(
]
)

self.data = data
self.confession = data

async def callback(self, inter:disnake.ModalInteraction):
""" Send the completed confession """
self.data.set_content(inter.text_values['content'])
if vetting := await self.data.check_vetting(inter):
await inter.bot.cogs['ConfessionsModeration'].send_vetting(inter, self.data, vetting)
self.confession.set_content(inter.text_values['content'])
if vetting := await self.confession.check_vetting(inter):
await inter.bot.cogs['ConfessionsModeration'].send_vetting(inter, self.confession, vetting)
return
if vetting is False:
return
await self.data.send_confession(inter, True)
await self.confession.send_confession(inter, success_message=True)

# Events

Expand Down Expand Up @@ -233,7 +233,8 @@ async def confession_request(self, msg:disnake.Message):
await msg.reply(
self.babel(msg, 'channelprompt') +
(' ' + self.babel(msg, 'channelprompt_pager', page=1) if len(matches) > 25 else ''),
view=ChannelSelectView(msg, self, matches))
view=ChannelSelectView(msg, self, matches)
)

# Context menu commands

Expand Down Expand Up @@ -278,14 +279,27 @@ async def confess(
await pendingconfession.add_image(attachment=image)

# --- From here, all state should be in pendingconfession, not in parameters ---
matches,_ = self.listavailablechannels(inter.author)
if not matches:
await inter.send(self.babel(inter, 'inaccessiblelocal'), ephemeral=True)
return

if pendingconfession.content or pendingconfession.file:
if pendingconfession.channeltype == ChannelType.unset():
# User used /confess in the wrong channel, give them a chance to choose another
await inter.send(
self.babel(inter, 'channelprompt') +
(' ' + self.babel(inter, 'channelprompt_pager', page=1) if len(matches) > 25 else ''),
view=ChannelSelectView(inter, self, matches, confession=pendingconfession),
ephemeral=True
)
return
if vetting := await pendingconfession.check_vetting(inter):
await self.bot.cogs['ConfessionsModeration'].send_vetting(inter, pendingconfession, vetting)
return
if vetting is False:
return
await pendingconfession.send_confession(inter, True)
await pendingconfession.send_confession(inter, success_message=True)

else:
await inter.response.send_modal(
Expand Down
97 changes: 52 additions & 45 deletions extensions/confessions_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,12 +209,14 @@ def __init__(
self,
origin:disnake.Message | disnake.Interaction,
parent:Confessions | ConfessionsSetup,
matches:list[tuple[disnake.TextChannel, ChannelType]]
matches:list[tuple[disnake.TextChannel, ChannelType]],
confession:ConfessionData | None = None
):
super().__init__()
self.origin = origin
self.parent = parent
self.matches = matches
self.confession = confession
self.soleguild = matches[0][0].guild if all((m.guild for m,_ in matches)) else None
self.update_list()
self.channel_selector.placeholder = self.parent.babel(origin, 'channelprompt_placeholder')
Expand Down Expand Up @@ -248,7 +250,8 @@ def update_list(self):
disnake.SelectOption(
label='#' + channel.name + ('' if self.soleguild else f' (from {channel.guild.name})'),
value=channel.id,
emoji=channeltype.icon
emoji=channeltype.icon,
default=channel.id == self.selection.id if self.selection else False
) for channel,channeltype in self.matches[start:start+25]
]

Expand All @@ -268,6 +271,7 @@ async def channel_selector(self, _:disnake.ui.Select, inter:disnake.MessageInter
view=self
)
return
self.update_list()
guildchannels = get_guildchannels(self.parent.config, self.selection.guild.id)
vetting = findvettingchannel(guildchannels)
channeltype = guildchannels[self.selection.id]
Expand All @@ -281,48 +285,42 @@ async def channel_selector(self, _:disnake.ui.Select, inter:disnake.MessageInter
@disnake.ui.button(disabled=True, style=disnake.ButtonStyle.primary)
async def send_button(self, _:disnake.Button, inter:disnake.MessageInteraction):
""" Send the confession """
if isinstance(self.origin, disnake.Interaction):
raise Exception("This function is not designed for Interactions!")
if self.parent.__cog_name__ != 'Confessions':
raise Exception("Confessions cannot be sent unless the parent is Confessions!")

if self.selection is None:
if self.selection is None or self.done:
self.disable(inter)
return

guildchannels = get_guildchannels(self.parent.config, self.selection.guild.id)
channeltype = guildchannels.get(self.selection.id)

pendingconfession = ConfessionData(self.parent)
pendingconfession.create(author=inter.author, targetchannel=self.selection)
pendingconfession.set_content(self.origin.content)
if self.confession is None:
self.confession = ConfessionData(self.parent)
self.confession.create(author=inter.author, targetchannel=self.selection)
self.confession.set_content(self.origin.content)

if self.origin.attachments:
await inter.response.defer(ephemeral=True)
await pendingconfession.add_image(attachment=self.origin.attachments[0])
if self.origin.attachments:
await inter.response.defer(ephemeral=True)
await self.confession.add_image(attachment=self.origin.attachments[0])
else:
# Override targetchannel as this has changed
self.confession.create(author=inter.author, targetchannel=self.selection)

if not await pendingconfession.check_all(inter):
return
vetting = await pendingconfession.check_vetting(inter, guildchannels)
if vetting and 'feedback' not in channeltype.name:
if vetting := await self.confession.check_vetting(inter):
await self.parent.bot.cogs['ConfessionsModeration'].send_vetting(
inter, pendingconfession, vetting
inter, self.confession, vetting
)
await self.disable(inter)
await inter.delete_original_response()
return
if vetting is False:
return

await pendingconfession.send_confession(inter)

self.send_button.label = self.parent.babel(inter, 'channelprompt_button_sent')
self.channel_selector.disabled = True
self.send_button.disabled = True
self.done = True
await inter.edit_original_message(
content=self.parent.babel(
inter, 'confession_sent_channel', channel=self.selection.mention
),
view=self
)
if await self.confession.send_confession(inter):
self.send_button.label = self.parent.babel(inter, 'channelprompt_button_sent')
self.channel_selector.disabled = True
self.send_button.disabled = True
self.done = True
await inter.edit_original_message(
content=self.parent.babel(
inter, 'confession_sent_channel', channel=self.selection.mention
),
view=None
)

def change_page(self, pagediff:int):
""" Add or remove pagediff to self.page and trigger on_page_change event """
Expand Down Expand Up @@ -363,16 +361,27 @@ async def disable(self, inter:disnake.MessageInteraction):
self.channel_selector.disabled = True
self.send_button.disabled = True
self.done = True
await inter.message.edit(view=self)
if inter.response.is_done():
await inter.message.edit(view=self)
else:
await inter.response.edit_message(view=self)

async def on_timeout(self):
if isinstance(self.origin, disnake.Interaction):
raise Exception("This function is not designed for Interactions!")
try:
if isinstance(self.origin, disnake.Interaction):
if not self.done:
for component in self.children:
if isinstance(component, (disnake.ui.Button, disnake.ui.Select)):
component.disabled = True
await self.origin.edit_original_response(
content=self.parent.babel(self.origin.author, 'timeouterror'),
view=self
)
else:
await self.origin.delete_original_response()
return
if not self.done:
await self.origin.reply(
self.parent.babel(self.origin.author, 'timeouterror')
)
await self.origin.reply(self.parent.babel(self.origin.author, 'timeouterror'))
async for msg in self.origin.channel.history(after=self.origin):
if (
isinstance(msg.reference, disnake.MessageReference) and
Expand All @@ -381,7 +390,7 @@ async def on_timeout(self):
await msg.delete()
return
except disnake.HTTPException:
pass
pass # Message was probably dismissed, don't worry about it

# Data classes

Expand Down Expand Up @@ -578,11 +587,9 @@ def check_spam(self):
async def check_vetting(
self,
inter:disnake.Interaction,
guildchannels:dict[int, ChannelType] | None = None
) -> disnake.TextChannel | bool | None:
""" Check if vetting is required, this is not a part of check_all """
if guildchannels is None:
guildchannels = get_guildchannels(self.config, self.targetchannel.guild.id)
guildchannels = get_guildchannels(self.config, self.targetchannel.guild.id)
vetting = findvettingchannel(guildchannels)
if vetting and self.channeltype.vetted:
if 'ConfessionsModeration' not in self.bot.cogs:
Expand Down
11 changes: 9 additions & 2 deletions extensions/confessions_moderation.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,18 @@ async def send_vetting(
data:"ConfessionData",
vettingchannel:disnake.TextChannel
):
""" Send confession to a vetting channel for approval """
"""
Send confession to a vetting channel for approval
Checks are performed at this stage
"""
preface = self.babel(vettingchannel.guild, 'vetmessagecta', channel=data.targetchannel.mention)
view = self.PendingConfessionView(self, data)
success = await data.send_confession(
inter, channel=vettingchannel, webhook_override=False, preface_override=preface, view=view
inter,
channel=vettingchannel,
webhook_override=False,
preface_override=preface,
view=view
)

if success:
Expand Down

0 comments on commit 7fedba2

Please sign in to comment.