diff --git a/tuxbot/cogs/Polls/functions/converters.py b/tuxbot/cogs/Polls/functions/converters.py new file mode 100644 index 0000000..235627a --- /dev/null +++ b/tuxbot/cogs/Polls/functions/converters.py @@ -0,0 +1,59 @@ +from discord.ext import commands +from tuxbot.cogs.Polls.functions.exceptions import ( + TooLongProposition, + InvalidChannel, + BadPoll, +) +from tuxbot.cogs.Polls.models import Poll + +_ = lambda x: x + + +class PollConverter(commands.Converter): + async def convert(self, ctx, argument): + try: + poll = await commands.MessageConverter().convert(ctx, argument) + + if poll.channel.id != ctx.channel.id: + raise InvalidChannel( + _("Please provide a message in this channel") + ) + + if ( + poll.author.id != ctx.bot.user.id + or len(poll.embeds) != 1 + or poll.embeds[0].to_dict().get("footer", {}).get("text", None) + is None + ): + raise BadPoll(_("Unable to find this poll")) + + poll_id = poll.embeds[0].to_dict().get("footer").get("text") + poll_id = poll_id.replace("ID: #", "") + + if not poll_id.isdigit(): + raise BadPoll(_("Unable to find this poll")) + except commands.BadArgument: + poll_id = str(argument).replace("ID:", "").replace("#", "") + + if not poll_id.isdigit(): + raise BadPoll(_("Unable to find this poll")) + + poll = await Poll.get_or_none(id=int(poll_id)) + + if poll.channel_id != ctx.channel.id: + raise InvalidChannel(_("Please provide a message in this channel")) + + if poll is None: + raise BadPoll(_("Unable to find this poll")) + + return poll + + +class NewPropositionConvertor(commands.Converter): + async def convert(self, ctx, argument): + if len(argument) > 30: + raise TooLongProposition( + _("Your proposal must be smaller than 30") + ) + + return argument diff --git a/tuxbot/cogs/Polls/functions/emotes.py b/tuxbot/cogs/Polls/functions/emotes.py new file mode 100644 index 0000000..77c2cc5 --- /dev/null +++ b/tuxbot/cogs/Polls/functions/emotes.py @@ -0,0 +1,10 @@ +emotes = [chr(0x1F1E6 + i) for i in range(26)] +check = [chr(0x2714), chr(0x2716)] + + +def get(count): + return emotes[:count] + + +def get_index(emote): + return emotes.index(emote) diff --git a/tuxbot/cogs/Polls/functions/exceptions.py b/tuxbot/cogs/Polls/functions/exceptions.py new file mode 100644 index 0000000..1ef1247 --- /dev/null +++ b/tuxbot/cogs/Polls/functions/exceptions.py @@ -0,0 +1,13 @@ +from discord.ext import commands + + +class BadPoll(commands.BadArgument): + pass + + +class InvalidChannel(commands.BadArgument): + pass + + +class TooLongProposition(commands.BadArgument): + pass diff --git a/tuxbot/cogs/Polls/locales/en-US.po b/tuxbot/cogs/Polls/locales/en-US.po index d7bc028..d81c7cc 100644 --- a/tuxbot/cogs/Polls/locales/en-US.po +++ b/tuxbot/cogs/Polls/locales/en-US.po @@ -1,4 +1,5 @@ -# English translations for Tuxbot-bot package. +# French translations for Tuxbot-bot package +# Traductions françaises du paquet Tuxbot-bot. # Copyright (C) 2020 THE Tuxbot-bot'S COPYRIGHT HOLDER # This file is distributed under the same license as the Tuxbot-bot package. # Automatically generated, 2020. @@ -16,3 +17,33 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: tuxbot/cogs/Polls/polls.py:92 +msgid "**Preparation**" +msgstr "" + +#: tuxbot/cogs/Polls/polls.py:221 +#, python-brace-format +msgid "Proposed addition for survey #{id}" +msgstr "" + +#: tuxbot/cogs/Polls/polls.py:226 +#, python-brace-format +msgid "Requested by {author}" +msgstr "" + +#: tuxbot/cogs/Polls/functions/converters.py:20 +#: tuxbot/cogs/Polls/functions/converters.py:45 +msgid "Please provide a message in this channel" +msgstr "" + +#: tuxbot/cogs/Polls/functions/converters.py:29 +#: tuxbot/cogs/Polls/functions/converters.py:35 +#: tuxbot/cogs/Polls/functions/converters.py:40 +#: tuxbot/cogs/Polls/functions/converters.py:48 +msgid "Unable to find this poll" +msgstr "" + +#: tuxbot/cogs/Polls/functions/converters.py:57 +msgid "Your proposal must be smaller than 30" +msgstr "" \ No newline at end of file diff --git a/tuxbot/cogs/Polls/locales/fr-FR.po b/tuxbot/cogs/Polls/locales/fr-FR.po index 5f7d0d1..aae95e2 100644 --- a/tuxbot/cogs/Polls/locales/fr-FR.po +++ b/tuxbot/cogs/Polls/locales/fr-FR.po @@ -17,3 +17,33 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: tuxbot/cogs/Polls/polls.py:92 +msgid "**Preparation**" +msgstr "**Préparation**" + +#: tuxbot/cogs/Polls/polls.py:221 +#, python-brace-format +msgid "Proposed addition for poll #{id}" +msgstr "Proposition d'ajout pour le sondage #{id}" + +#: tuxbot/cogs/Polls/polls.py:226 +#, python-brace-format +msgid "Requested by {author}" +msgstr "Demandé par {author}" + +#: tuxbot/cogs/Polls/functions/converters.py:20 +#: tuxbot/cogs/Polls/functions/converters.py:45 +msgid "Please provide a message in this channel" +msgstr "Veuillez fournir un message dans ce salon" + +#: tuxbot/cogs/Polls/functions/converters.py:29 +#: tuxbot/cogs/Polls/functions/converters.py:35 +#: tuxbot/cogs/Polls/functions/converters.py:40 +#: tuxbot/cogs/Polls/functions/converters.py:48 +msgid "Unable to find this poll" +msgstr "Impossible de trouver ce sondage" + +#: tuxbot/cogs/Polls/functions/converters.py:57 +msgid "Your proposal must be smaller than 30" +msgstr "Votre proposition doit être inférieure à 30" \ No newline at end of file diff --git a/tuxbot/cogs/Polls/locales/messages.pot b/tuxbot/cogs/Polls/locales/messages.pot index 9c11528..2b182f1 100644 --- a/tuxbot/cogs/Polls/locales/messages.pot +++ b/tuxbot/cogs/Polls/locales/messages.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Tuxbot-bot\n" "Report-Msgid-Bugs-To: rick@gnous.eu\n" -"POT-Creation-Date: 2020-10-21 01:15+0200\n" +"POT-Creation-Date: 2021-01-20 17:24+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -16,3 +16,33 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" + +#: tuxbot/cogs/Polls/polls.py:92 +msgid "**Preparation**" +msgstr "" + +#: tuxbot/cogs/Polls/polls.py:221 +#, python-brace-format +msgid "Proposed addition for poll #{id}" +msgstr "" + +#: tuxbot/cogs/Polls/polls.py:226 +#, python-brace-format +msgid "Requested by {author}" +msgstr "" + +#: tuxbot/cogs/Polls/functions/converters.py:20 +#: tuxbot/cogs/Polls/functions/converters.py:45 +msgid "Please provide a message in this channel" +msgstr "" + +#: tuxbot/cogs/Polls/functions/converters.py:29 +#: tuxbot/cogs/Polls/functions/converters.py:35 +#: tuxbot/cogs/Polls/functions/converters.py:40 +#: tuxbot/cogs/Polls/functions/converters.py:48 +msgid "Unable to find this poll" +msgstr "" + +#: tuxbot/cogs/Polls/functions/converters.py:57 +msgid "Your proposal must be smaller than 30" +msgstr "" diff --git a/tuxbot/cogs/Polls/models/__init__.py b/tuxbot/cogs/Polls/models/__init__.py index e622fc8..45cd8bf 100644 --- a/tuxbot/cogs/Polls/models/__init__.py +++ b/tuxbot/cogs/Polls/models/__init__.py @@ -1,2 +1,3 @@ from .polls import * from .responses import * +from .suggests import * diff --git a/tuxbot/cogs/Polls/models/suggests.py b/tuxbot/cogs/Polls/models/suggests.py new file mode 100644 index 0000000..1032e7d --- /dev/null +++ b/tuxbot/cogs/Polls/models/suggests.py @@ -0,0 +1,22 @@ +import tortoise +from tortoise import fields + + +class Suggest(tortoise.Model): + suggest_id = fields.BigIntField(pk=True) + poll = fields.ForeignKeyField("models.Poll") + user_id = fields.BigIntField() + + proposition = fields.CharField(max_length=30) + + class Meta: + table = "suggests" + + def __str__(self): + return ( + f"" + ) + + __repr__ = __str__ diff --git a/tuxbot/cogs/Polls/polls.py b/tuxbot/cogs/Polls/polls.py index abfdd1e..b34e2fd 100644 --- a/tuxbot/cogs/Polls/polls.py +++ b/tuxbot/cogs/Polls/polls.py @@ -12,7 +12,10 @@ from tuxbot.core.i18n import ( Translator, ) from .functions import emotes as utils_emotes +from .functions.converters import NewPropositionConvertor, PollConverter +from .functions.exceptions import InvalidChannel, BadPoll, TooLongProposition from .models import Poll, Response +from .models.suggests import Suggest log = logging.getLogger("tuxbot.cogs.Polls") _ = Translator("Polls", __file__) @@ -22,6 +25,10 @@ class Polls(commands.Cog, name="Polls"): def __init__(self, bot: Tux): self.bot = bot + async def cog_command_error(self, ctx, error): + if isinstance(error, (InvalidChannel, BadPoll, TooLongProposition)): + await ctx.send(_(str(error), ctx, self.bot.config)) + @commands.Cog.listener() async def on_raw_reaction_add(self, pld: discord.RawReactionActionEvent): poll = await self.get_poll(pld) @@ -200,6 +207,33 @@ class Polls(commands.Cog, name="Polls"): await message.remove_reaction(pld.emoji.name, user) + async def propose_new( + self, ctx: ContextPlus, poll: PollConverter, new: str + ): + await Suggest.create(poll=poll, user_id=ctx.author.id, proposition=new) + + if isinstance(poll, Poll): + # pylint: disable=pointless-string-statement + """Just to change type for PyCharm""" + + e = discord.Embed( + title=_( + "Proposed addition for poll #{id}", ctx, self.bot.config + ).format(id=poll.id), + description=new, + ) + e.set_footer( + text=_("Requested by {author}", ctx, self.bot.config).format( + author=ctx.author.name + ), + icon_url=ctx.author.avatar_url_as(format="png"), + ) + + message = await ctx.send(embed=e) + + for emote in utils_emotes.check: + await message.add_reaction(emote) + # ========================================================================= # ========================================================================= @@ -208,7 +242,7 @@ class Polls(commands.Cog, name="Polls"): if ctx.invoked_subcommand is None: await ctx.send_help("poll") - @_poll.group(name="create", aliases=["new", "nouveau"]) + @_poll.command(name="create", aliases=["new", "nouveau"]) async def _poll_create(self, ctx: ContextPlus, *, poll: str): args: list = poll.lower().split() is_anonymous = False @@ -235,3 +269,13 @@ class Polls(commands.Cog, name="Polls"): answers.append(" ".join(args[start:end]).capitalize()) await self.create_poll(ctx, question, answers, anonymous=is_anonymous) + + @_poll.command(name="propose", aliases=["suggest", "ajout"]) + async def _poll_propose( + self, + ctx: ContextPlus, + poll: PollConverter, + *, + new: NewPropositionConvertor, + ): + await self.propose_new(ctx, poll, str(new))