Skip to content

Commit

Permalink
Merge branch 'shop' into beta
Browse files Browse the repository at this point in the history
  • Loading branch information
yiays committed Sep 1, 2024
2 parents 22a79b6 + 4492e90 commit 3adc6f6
Show file tree
Hide file tree
Showing 6 changed files with 538 additions and 405 deletions.
13 changes: 12 additions & 1 deletion babel/confessionbot_en.ini
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ editor_message_label = Message:
editor_message_placeholder = The text that will become your anonymous message
confession_sent_channel = Done, your message has been sent to {channel}.
confession_sent_below = Done, your message is below.
confession_vetting = Your message will now go through the vetting process, if approved, it will appear on {channel}.
confession_vetting = Your message will now go through the vetting process, if approved, it will appear in {channel}.
confession_vetting_denied = Your message failed vetting.
confession_vetting_accepted = Your message was accepted and posted to {channel}.
nosendchannel = You can't send anonymous messages here! Use this command in a channel from the {p:list}.
Expand Down Expand Up @@ -196,10 +196,21 @@ vetting_deny_button = Deny
; marketplace
shop_disclaimer = {c:main/botname} cannot gurantee transactions will be successful. Usernames are shared privately once a seller accepts an offer.
button_offer = Make an offer{listing? ({listing})|}
button_accept = Accept offer ({listing?{listing}|seller only})
button_withdraw = Withdraw {sell?listing|offer} ({sell?seller|buyer} only)
offer_price_label = Offer amount (with currency):
offer_price_example = US$30
offer_method_label = Payment method:
offer_method_example = PayPal, Crypto, Bank Transfer
error_embed_deleted = Listing information has been deleted - can't make an offer.
error_self_offer = You can't make an offer to yourself.
error_old_offer = This listing was created by an older version of {c:main/botname} and is no longer supported.
error_wrong_person = Only the creator of this {buy?listing|offer} can perform this action.
sale_complete = # {listing} sold
Congratulations, {sell?your item has been sold to|you have agreed to buy an item from} {other}. Get in touch with them in order to arrange payment and delivery.
For your records, the listing and offer are attached below.{sell? If you have no more of this item to sell, withdraw your listing from the server.|}
offer_for = Offer for {listing}
listing_withdrawn = This listing was withdrawn
offer_withdrawn = This offer was withdrawn
offer_accepted = This offer was accepted by the seller

1 change: 1 addition & 0 deletions config/config.factory.ini
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ changelog = > 1.0.0
- 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
- Fixed DM Notifications being re-enabled after a restart
[premium]
icon =
Expand Down
173 changes: 27 additions & 146 deletions extensions/confessions.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

from __future__ import annotations

import re, time, hashlib
import re, time
from typing import Optional, Union, TYPE_CHECKING
import disnake
from disnake.ext import commands
Expand All @@ -19,8 +19,7 @@
from configparser import SectionProxy

from overlay.extensions.confessions_common import (
ChannelType, ChannelSelectView, ConfessionData, NoMemberCacheError, Crypto,
findvettingchannel, get_guildchannels
ChannelType, ChannelSelectView, ConfessionData, NoMemberCacheError, Crypto, get_guildchannels
)


Expand Down Expand Up @@ -72,14 +71,6 @@ def __init__(self, bot:MerelyBot):

# Utility functions

def get_anonid(self, guildid:int, userid:int) -> str:
""" Calculates the current anon-id for a user """
offset = int(self.config.get(f"{guildid}_shuffle", fallback=0))
encrypted = self.crypto.encrypt(
guildid.to_bytes(8, 'big') + userid.to_bytes(8, 'big') + offset.to_bytes(2, 'big')
)
return hashlib.sha256(encrypted).hexdigest()[-6:]

def generate_list(
self,
user:disnake.User,
Expand Down Expand Up @@ -163,76 +154,6 @@ async def safe_fetch_channel(
)
return None

# Checks

def check_banned(self, guild_id:int, anonid:str) -> bool:
""" Verify the user hasn't been banned """
if anonid in self.config.get(f"{guild_id}_banned", fallback='').split(','):
return False
return True

def check_image(self, guild_id:int, image:disnake.Attachment) -> bool:
""" Only allow images to be sent if imagesupport is enabled and the image is valid """
if image and image.content_type.startswith('image') and image.size < 25_000_000:
# Discord size limit
if bool(self.config.get(f"{guild_id}_imagesupport", fallback=True)):
return True
return False
raise commands.BadArgument

def check_spam(self, content:str | None):
""" Verify message doesn't contain spam as defined in [confessions] spam_flags """
for spamflag in self.config.get('spam_flags', fallback=None).splitlines():
if content and re.match(spamflag, content):
return False
return True

def check_all(
self,
guild_id:int,
channel_id:int,
anonid:str,
content:str | None = None,
image:disnake.Attachment | None = None,
embed:disnake.Embed | None = None
) -> tuple[str, dict[str:str]] | None:
"""
Run all pre-send checks on this confession
In the event that a check fails, return the relevant babel key
"""
guildchannels = get_guildchannels(self.config, guild_id)

if channel_id in guildchannels:
if guildchannels[channel_id] == ChannelType.marketplace() and embed is None:
#BABEL: wrongcommand
return ('wrongcommand', {'cmd':'sell'})
else:
#BABEL: nosendchannel
return ('nosendchannel', {})

if not self.check_banned(guild_id, anonid):
#BABEL: nosendbanned
return ('nosendbanned', {})

if image:
try:
if not self.check_image(guild_id, image):
#BABEL: nosendimages
return ('nosendimages', {})
except commands.BadArgument:
#BABEL: inavlidimage
return ('invalidimage', {})

if not self.check_spam(content):
#BABEL: nospam
return ('nospam', {})

if 'feedback' not in guildchannels[channel_id].name:
vetting = findvettingchannel(guildchannels)
if vetting and 'ConfessionsModeration' not in self.bot.cogs:
#BABEL: no_moderation
return ('no_moderation', {})

# Modals

class ConfessionModal(disnake.ui.Modal):
Expand All @@ -258,18 +179,17 @@ def __init__(
]
)

self.parent = parent
self.data = data

async def callback(self, inter:disnake.ModalInteraction):
""" Send the completed confession """
await self.parent.confess(
inter,
inter.text_values['content'],
None,
channel=self.data.targetchannel,
data=self.data
)
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)
return
if vetting is False:
return
await self.data.send_confession(inter, True)

# Events

Expand Down Expand Up @@ -330,9 +250,9 @@ async def confess_message(self, inter:disnake.MessageCommandInteraction):
@commands.slash_command()
async def confess(
self,
inter: disnake.GuildCommandInteraction,
content: Optional[str] = commands.Param(default=None, max_length=3900),
image: Optional[disnake.Attachment] = None,
inter:disnake.GuildCommandInteraction,
content:Optional[str] = commands.Param(default=None, max_length=3900),
image:Optional[disnake.Attachment] = None,
**kwargs
):
"""
Expand All @@ -343,67 +263,28 @@ async def confess(
content: The text of your anonymous message, leave blank for a paragraph editor
image: An optional image that appears below the text
"""

channel = inter.channel
if 'channel' in kwargs:
channel = kwargs['channel']
else:
channel = inter.channel

anonid = self.get_anonid(inter.guild_id, inter.author.id)

result = self.check_all(
inter.guild_id,
channel.id,
anonid,
content,
image,
kwargs['embed'] if 'embed' in kwargs else None
)
if result:
await inter.response.send_message(self.babel(inter, result[0], **result[1]), ephemeral=True)
return

if 'data' in kwargs:
pendingconfession = kwargs['data']
else:
pendingconfession = ConfessionData(
self,
author=inter.author,
targetchannel=channel,
embed=kwargs['embed'] if 'embed' in kwargs else None,
reference=kwargs['reference'] if 'reference' in kwargs else None
)
guildchannels = get_guildchannels(self.config, inter.guild_id)
channeltype = guildchannels[channel.id]

if content or image:
if content is None:
content = ''

vetting = findvettingchannel(guildchannels)
reference = None
if 'reference' in kwargs:
reference = kwargs['reference']

pendingconfession = ConfessionData(self)
pendingconfession.create(inter.author, channel, reference=reference)
pendingconfession.set_content(content)
if image:
await inter.response.defer(ephemeral=True)
await pendingconfession.add_image(attachment=image)

if image:
await pendingconfession.download_image(image.url)
if 'embed' in kwargs and isinstance(kwargs['embed'], disnake.Embed):
pendingconfession.embed = kwargs['embed']
pendingconfession.anonid = anonid
pendingconfession.embed.colour = disnake.Colour(int(anonid,16))
pendingconfession.embed.set_author(name='Anon-' + anonid)
if image:
pendingconfession.embed.set_image(pendingconfession.image_url)
else:
await pendingconfession.generate_embed(anonid, vetting or channeltype.anonid, content)

if channeltype == ChannelType.marketplace() and 'reference' not in kwargs:
pendingconfession.marketplace_button = True
# --- From here, all state should be in pendingconfession, not in parameters ---

if vetting and 'feedback' not in channeltype.name:
vchannel = inter.guild.get_channel(vetting)
await self.bot.cogs['ConfessionsModeration'].send_vetting(inter, pendingconfession, vchannel)
if pendingconfession.content or pendingconfession.file:
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)

else:
Expand Down
Loading

0 comments on commit 3adc6f6

Please sign in to comment.