From bcf1221356edc0729032d9c2f02a1c0a85810a9a Mon Sep 17 00:00:00 2001 From: Tert0 <62036464+Tert0@users.noreply.github.com> Date: Sun, 3 Oct 2021 19:34:40 +0200 Subject: [PATCH 01/13] Migrated Polls to Discord Interactions --- general/polls/cog.py | 176 +++++++++++++++++++++--------- general/polls/translations/en.yml | 8 ++ 2 files changed, 130 insertions(+), 54 deletions(-) diff --git a/general/polls/cog.py b/general/polls/cog.py index ee9efefc5..0a9c4d9f4 100644 --- a/general/polls/cog.py +++ b/general/polls/cog.py @@ -2,9 +2,11 @@ import string from typing import Optional, Tuple -from discord import Embed, Message, PartialEmoji, Member, Forbidden, Guild +from discord import Embed, Message, PartialEmoji, Member, Forbidden, Guild, Interaction, SelectOption, \ + InteractionResponded from discord.ext import commands from discord.ext.commands import Context, guild_only, CommandError +from discord.ui import View, Select from discord.utils import utcnow from PyDrocsid.cog import Cog @@ -13,6 +15,7 @@ from PyDrocsid.events import StopEventHandling from PyDrocsid.settings import RoleSettings from PyDrocsid.translations import t +from PyDrocsid.redis import redis from PyDrocsid.util import is_teamler, check_wastebasket from .colors import Colors from .permissions import PollsPermission @@ -34,59 +37,124 @@ async def get_teampoll_embed(message: Message) -> Tuple[Optional[Embed], Optiona return None, None -async def send_poll( - ctx: Context, - title: str, - args: str, - field: Optional[Tuple[str, str]] = None, - allow_delete: bool = True, -): - question, *options = [line.replace("\x00", "\n") for line in args.replace("\\\n", "\x00").split("\n") if line] +class PollsCog(Cog, name="Polls"): + CONTRIBUTORS = [ + Contributor.MaxiHuHe04, + Contributor.Defelo, + Contributor.TNT2k, + Contributor.wolflu, + Contributor.Tert0 + ] + + def __init__(self, team_roles: list[str]): + self.team_roles: list[str] = team_roles + + async def send_poll( + self, + ctx: Context, + title: str, + args: str, + field: Optional[Tuple[str, str]] = None, + allow_delete: bool = True, + team_poll: bool = False, + ): + question, *options = [line.replace("\x00", "\n") for line in args.replace("\\\n", "\x00").split("\n") if line] - if not options: - raise CommandError(t.missing_options) - if len(options) > MAX_OPTIONS - allow_delete: - raise CommandError(t.too_many_options(MAX_OPTIONS - allow_delete)) + if not options: + raise CommandError(t.missing_options) + if len(options) > MAX_OPTIONS - allow_delete: + raise CommandError(t.too_many_options(MAX_OPTIONS - allow_delete)) - options = [PollOption(ctx, line, i) for i, line in enumerate(options)] + options = [PollOption(ctx, line, i) for i, line in enumerate(options)] - if any(len(str(option)) > EmbedLimits.FIELD_VALUE for option in options): - raise CommandError(t.option_too_long(EmbedLimits.FIELD_VALUE)) + if any(len(str(option)) > EmbedLimits.FIELD_VALUE for option in options): + raise CommandError(t.option_too_long(EmbedLimits.FIELD_VALUE)) - embed = Embed(title=title, description=question, color=Colors.Polls, timestamp=utcnow()) - embed.set_author(name=str(ctx.author), icon_url=ctx.author.display_avatar.url) - if allow_delete: - embed.set_footer(text=t.created_by(ctx.author, ctx.author.id), icon_url=ctx.author.display_avatar.url) + embed = Embed(title=title, description=question, color=Colors.Polls, timestamp=utcnow()) + embed.set_author(name=str(ctx.author), icon_url=ctx.author.display_avatar.url) + + if allow_delete: + embed.set_footer(text=t.created_by(ctx.author, ctx.author.id), icon_url=ctx.author.display_avatar.url) - if len(set(map(lambda x: x.emoji, options))) < len(options): - raise CommandError(t.option_duplicated) + if len(set(map(lambda x: x.emoji, options))) < len(options): + raise CommandError(t.option_duplicated) - for option in options: - embed.add_field(name="** **", value=str(option), inline=False) + if field: + embed.add_field(name=field[0], value=field[1], inline=False) - if field: - embed.add_field(name=field[0], value=field[1], inline=False) + view = View(timeout=None) - poll: Message = await ctx.send(embed=embed) + vote_select = Select(placeholder=t.poll_select_placeholder, max_values=len(options)) + + for i, option in enumerate(options): + vote_select.add_option(label=option.option, description=t.votes(0, cnt=0), emoji=option.emoji) - try: for option in options: - await poll.add_reaction(option.emoji) - if allow_delete: - await poll.add_reaction(name_to_emoji["wastebasket"]) - except Forbidden: - raise CommandError(t.could_not_add_reactions(ctx.channel.mention)) + if len([item for item in options if item.option == option.option]) > 1: + raise CommandError("cant have to items with same name") # TODO Translation + async def poll_vote(interaction: Interaction): + def get_option_by_label(label: str, select: Select) -> SelectOption: + for option in select.options: + if option.label == label: + return option -class PollsCog(Cog, name="Polls"): - CONTRIBUTORS = [Contributor.MaxiHuHe04, Contributor.Defelo, Contributor.TNT2k, Contributor.wolflu] + def get_redis_key(message: Message, member: Member, option: SelectOption) -> str: + return f"poll_vote:{message.id}:{member.id}:{vote_select.options.index(option)}" - def __init__(self, team_roles: list[str]): - self.team_roles: list[str] = team_roles + def get_team_poll_redis_key(message: Message, member: Member) -> str: + return f"team_poll_vote:{message.id}:{member.id}" + + if interaction.data["component_type"] != 3: # Component Type 3 is the Select + return + if interaction.data.get("values") is None: + return + values = interaction.data["values"] + for value in values: + selected_option = get_option_by_label(value, vote_select) + + redis_key: str = get_redis_key(interaction.message, interaction.user, selected_option) + team_poll_redis_key: str = get_team_poll_redis_key(interaction.message, interaction.user) + vote_value = 1 + if await redis.exists(redis_key): + vote_value = -1 + await redis.delete(redis_key) + + vote_count: int = int(re.match(r"[\-]?[0-9]+", selected_option.description).group(0)) + selected_option.description = t.votes(vote_count + vote_value, cnt=vote_count + vote_value) + if vote_value == 1: + await redis.set(redis_key, 1) + if team_poll: + await redis.sadd(team_poll_redis_key, vote_select.options.index(selected_option)) + elif vote_value == -1: + if team_poll: + await redis.srem(team_poll_redis_key, vote_select.options.index(selected_option)) + + if team_poll: + _, index = await get_teampoll_embed(interaction.message) + value = await self.get_reacted_teamlers(interaction.message) + embed.set_field_at(index, name=tg.status, value=value, inline=False) + + await interaction.message.edit(content="** **", embed=embed, view=view) + + vote_select.callback = poll_vote + view.add_item(vote_select) + + poll: Message = await ctx.send(content="** **", embed=embed, view=view) # TODO Remove Content from Message + # Content will get sent as WorkARound for https://github.com/Pycord-Development/pycord/issues/192 + + try: + if allow_delete: + await poll.add_reaction(name_to_emoji["wastebasket"]) + except Forbidden: + raise CommandError(t.could_not_add_reactions(ctx.channel.mention)) async def get_reacted_teamlers(self, message: Optional[Message] = None) -> str: guild: Guild = self.bot.guilds[0] + def get_team_poll_redis_key(member: Member) -> str: + return f"team_poll_vote:{message.id}:{member.id}" + teamlers: set[Member] = set() for role_name in self.team_roles: if not (team_role := guild.get_role(await RoleSettings.get(role_name))): @@ -95,11 +163,11 @@ async def get_reacted_teamlers(self, message: Optional[Message] = None) -> str: teamlers.update(member for member in team_role.members if not member.bot) if message: - for reaction in message.reactions: - if reaction.me: - teamlers.difference_update(await reaction.users().flatten()) + teamlers = {teamler for teamler in teamlers if + len(await redis.smembers(get_team_poll_redis_key(teamler))) < 1} teamlers: list[Member] = list(teamlers) + if not teamlers: return t.teampoll_all_voted @@ -164,7 +232,7 @@ async def poll(self, ctx: Context, *, args: str): Starts a poll. Multiline options can be specified using a `\\` at the end of a line """ - await send_poll(ctx, t.poll, args) + await self.send_poll(ctx, t.poll, args) @commands.command(usage=t.poll_usage, aliases=["teamvote", "tp"]) @PollsPermission.team_poll.check @@ -175,12 +243,13 @@ async def teampoll(self, ctx: Context, *, args: str): Multiline options can be specified using a `\\` at the end of a line """ - await send_poll( + await self.send_poll( ctx, t.team_poll, args, field=(tg.status, await self.get_reacted_teamlers()), allow_delete=False, + team_poll=True, ) @commands.command(aliases=["yn"]) @@ -216,17 +285,16 @@ async def team_yesno(self, ctx: Context, *, text: str): Starts a yes/no poll and shows, which teamler has not voted yet. """ - embed = Embed(title=t.team_poll, description=text, color=Colors.Polls, timestamp=utcnow()) - embed.set_author(name=str(ctx.author), icon_url=ctx.author.display_avatar.url) - - embed.add_field(name=tg.status, value=await self.get_reacted_teamlers(), inline=False) - - message: Message = await ctx.send(embed=embed) - try: - await message.add_reaction(name_to_emoji["+1"]) - await message.add_reaction(name_to_emoji["-1"]) - except Forbidden: - raise CommandError(t.could_not_add_reactions(message.channel.mention)) + await self.send_poll( + ctx, + t.team_poll, + f"""{text} + {name_to_emoji["+1"]} {t.yes} + {name_to_emoji["-1"]} {t.no}""", + field=(tg.status, await self.get_reacted_teamlers()), + allow_delete=False, + team_poll=True, + ) class PollOption: @@ -245,7 +313,7 @@ def __init__(self, ctx: Context, line: str, number: int): self.emoji = unicode_emoji self.option = text.strip() elif (match := re.match(r"^:([^: ]+):$", emoji_candidate)) and ( - unicode_emoji := name_to_emoji.get(match.group(1).replace(":", "")) + unicode_emoji := name_to_emoji.get(match.group(1).replace(":", "")) ): self.emoji = unicode_emoji self.option = text.strip() diff --git a/general/polls/translations/en.yml b/general/polls/translations/en.yml index e779d9255..527f5bf79 100644 --- a/general/polls/translations/en.yml +++ b/general/polls/translations/en.yml @@ -3,6 +3,7 @@ permissions: delete: delete polls poll: Poll +anonymous_poll: Anonymous Poll team_poll: Team Poll vote_explanation: Vote using the reactions below! too_many_options: You specified too many options. The maximum amount is {}. @@ -24,3 +25,10 @@ created_by: Created by @{} ({}) can_not_use_wastebucket_as_option: "You can not use :wastebasket: as option" foreign_message: "You are not allowed to add yes/no reactions to foreign messages!" could_not_add_reactions: Could not add reactions because I don't have `add_reactions` permission in {}. +poll_select_placeholder: Select an Option to Vote! +votes: + zero: "{} Votes" + one: "{} Vote" + many: "{} Votes" +yes: Yes +no: No From d4ef8abd128d0b716c836b9921aea986b33e3c0c Mon Sep 17 00:00:00 2001 From: Tert0 <62036464+Tert0@users.noreply.github.com> Date: Sun, 3 Oct 2021 19:38:05 +0200 Subject: [PATCH 02/13] Reformatted Code --- general/polls/cog.py | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/general/polls/cog.py b/general/polls/cog.py index 0a9c4d9f4..653cb769e 100644 --- a/general/polls/cog.py +++ b/general/polls/cog.py @@ -2,8 +2,7 @@ import string from typing import Optional, Tuple -from discord import Embed, Message, PartialEmoji, Member, Forbidden, Guild, Interaction, SelectOption, \ - InteractionResponded +from discord import Embed, Message, PartialEmoji, Member, Forbidden, Guild, Interaction, SelectOption from discord.ext import commands from discord.ext.commands import Context, guild_only, CommandError from discord.ui import View, Select @@ -25,6 +24,7 @@ t = t.polls MAX_OPTIONS = 20 # Discord reactions limit +# TODO Remove Limit or change it default_emojis = [name_to_emoji[f"regional_indicator_{x}"] for x in string.ascii_lowercase] @@ -43,20 +43,20 @@ class PollsCog(Cog, name="Polls"): Contributor.Defelo, Contributor.TNT2k, Contributor.wolflu, - Contributor.Tert0 + Contributor.Tert0, ] def __init__(self, team_roles: list[str]): self.team_roles: list[str] = team_roles async def send_poll( - self, - ctx: Context, - title: str, - args: str, - field: Optional[Tuple[str, str]] = None, - allow_delete: bool = True, - team_poll: bool = False, + self, + ctx: Context, + title: str, + args: str, + field: Optional[Tuple[str, str]] = None, + allow_delete: bool = True, + team_poll: bool = False, ): question, *options = [line.replace("\x00", "\n") for line in args.replace("\\\n", "\x00").split("\n") if line] @@ -163,8 +163,9 @@ def get_team_poll_redis_key(member: Member) -> str: teamlers.update(member for member in team_role.members if not member.bot) if message: - teamlers = {teamler for teamler in teamlers if - len(await redis.smembers(get_team_poll_redis_key(teamler))) < 1} + teamlers = { + teamler for teamler in teamlers if len(await redis.smembers(get_team_poll_redis_key(teamler))) < 1 + } teamlers: list[Member] = list(teamlers) @@ -313,7 +314,7 @@ def __init__(self, ctx: Context, line: str, number: int): self.emoji = unicode_emoji self.option = text.strip() elif (match := re.match(r"^:([^: ]+):$", emoji_candidate)) and ( - unicode_emoji := name_to_emoji.get(match.group(1).replace(":", "")) + unicode_emoji := name_to_emoji.get(match.group(1).replace(":", "")) ): self.emoji = unicode_emoji self.option = text.strip() From 55b0588d92c450f22a10980bfd226ec40b8da124 Mon Sep 17 00:00:00 2001 From: Tert0 <62036464+Tert0@users.noreply.github.com> Date: Sun, 3 Oct 2021 19:39:52 +0200 Subject: [PATCH 03/13] Removed unused Code --- general/polls/cog.py | 56 +++++++------------------------------------- 1 file changed, 8 insertions(+), 48 deletions(-) diff --git a/general/polls/cog.py b/general/polls/cog.py index 653cb769e..474bbb219 100644 --- a/general/polls/cog.py +++ b/general/polls/cog.py @@ -50,13 +50,13 @@ def __init__(self, team_roles: list[str]): self.team_roles: list[str] = team_roles async def send_poll( - self, - ctx: Context, - title: str, - args: str, - field: Optional[Tuple[str, str]] = None, - allow_delete: bool = True, - team_poll: bool = False, + self, + ctx: Context, + title: str, + args: str, + field: Optional[Tuple[str, str]] = None, + allow_delete: bool = True, + team_poll: bool = False, ): question, *options = [line.replace("\x00", "\n") for line in args.replace("\\\n", "\x00").split("\n") if line] @@ -186,46 +186,6 @@ async def on_raw_reaction_add(self, message: Message, emoji: PartialEmoji, membe await message.delete() raise StopEventHandling - embed, index = await get_teampoll_embed(message) - if embed is None: - return - - if not await is_teamler(member): - try: - await message.remove_reaction(emoji, member) - except Forbidden: - pass - raise StopEventHandling - - for reaction in message.reactions: - if reaction.emoji == emoji.name: - break - else: - return - - if not reaction.me: - return - - value = await self.get_reacted_teamlers(message) - embed.set_field_at(index, name=tg.status, value=value, inline=False) - await message.edit(embed=embed) - - async def on_raw_reaction_remove(self, message: Message, _, member: Member): - if member.bot or message.guild is None: - return - embed, index = await get_teampoll_embed(message) - if embed is not None: - user_reacted = False - for reaction in message.reactions: - if reaction.me and member in await reaction.users().flatten(): - user_reacted = True - break - if not user_reacted and await is_teamler(member): - value = await self.get_reacted_teamlers(message) - embed.set_field_at(index, name=tg.status, value=value, inline=False) - await message.edit(embed=embed) - return - @commands.command(usage=t.poll_usage, aliases=["vote"]) @guild_only() async def poll(self, ctx: Context, *, args: str): @@ -314,7 +274,7 @@ def __init__(self, ctx: Context, line: str, number: int): self.emoji = unicode_emoji self.option = text.strip() elif (match := re.match(r"^:([^: ]+):$", emoji_candidate)) and ( - unicode_emoji := name_to_emoji.get(match.group(1).replace(":", "")) + unicode_emoji := name_to_emoji.get(match.group(1).replace(":", "")) ): self.emoji = unicode_emoji self.option = text.strip() From a14139aefa97d9247cc13abaeafe76cbb56f641f Mon Sep 17 00:00:00 2001 From: Tert0 <62036464+Tert0@users.noreply.github.com> Date: Sun, 3 Oct 2021 19:43:17 +0200 Subject: [PATCH 04/13] Fixed Codestyle --- general/polls/cog.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/general/polls/cog.py b/general/polls/cog.py index 474bbb219..2d4a4feaa 100644 --- a/general/polls/cog.py +++ b/general/polls/cog.py @@ -274,7 +274,7 @@ def __init__(self, ctx: Context, line: str, number: int): self.emoji = unicode_emoji self.option = text.strip() elif (match := re.match(r"^:([^: ]+):$", emoji_candidate)) and ( - unicode_emoji := name_to_emoji.get(match.group(1).replace(":", "")) + unicode_emoji := name_to_emoji.get(match.group(1).replace(":", "")) ): self.emoji = unicode_emoji self.option = text.strip() From 24a7b246db5c94492514ec020423fa150d3a7cd9 Mon Sep 17 00:00:00 2001 From: Tert0 <62036464+Tert0@users.noreply.github.com> Date: Sun, 3 Oct 2021 19:43:35 +0200 Subject: [PATCH 05/13] Fixed Codestyle --- general/polls/cog.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/general/polls/cog.py b/general/polls/cog.py index 2d4a4feaa..c1adc90ee 100644 --- a/general/polls/cog.py +++ b/general/polls/cog.py @@ -50,13 +50,13 @@ def __init__(self, team_roles: list[str]): self.team_roles: list[str] = team_roles async def send_poll( - self, - ctx: Context, - title: str, - args: str, - field: Optional[Tuple[str, str]] = None, - allow_delete: bool = True, - team_poll: bool = False, + self, + ctx: Context, + title: str, + args: str, + field: Optional[Tuple[str, str]] = None, + allow_delete: bool = True, + team_poll: bool = False, ): question, *options = [line.replace("\x00", "\n") for line in args.replace("\\\n", "\x00").split("\n") if line] From caa388f013c71434bbcdbeacf8cf95c07c5b62c8 Mon Sep 17 00:00:00 2001 From: Tert0 <62036464+Tert0@users.noreply.github.com> Date: Sun, 3 Oct 2021 19:45:18 +0200 Subject: [PATCH 06/13] Removed unused Var --- general/polls/cog.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/general/polls/cog.py b/general/polls/cog.py index c1adc90ee..4565282ad 100644 --- a/general/polls/cog.py +++ b/general/polls/cog.py @@ -86,7 +86,7 @@ async def send_poll( vote_select = Select(placeholder=t.poll_select_placeholder, max_values=len(options)) - for i, option in enumerate(options): + for _, option in enumerate(options): vote_select.add_option(label=option.option, description=t.votes(0, cnt=0), emoji=option.emoji) for option in options: From e367308cd0daf6bd6c93dcfdee6cf2a56f63dc2f Mon Sep 17 00:00:00 2001 From: Tert0 <62036464+Tert0@users.noreply.github.com> Date: Sun, 3 Oct 2021 19:52:28 +0200 Subject: [PATCH 07/13] Update general/polls/translations/en.yml Co-authored-by: Tristan <45330667+Tristan-H11@users.noreply.github.com> --- general/polls/translations/en.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/general/polls/translations/en.yml b/general/polls/translations/en.yml index 527f5bf79..e50c917fb 100644 --- a/general/polls/translations/en.yml +++ b/general/polls/translations/en.yml @@ -25,7 +25,7 @@ created_by: Created by @{} ({}) can_not_use_wastebucket_as_option: "You can not use :wastebasket: as option" foreign_message: "You are not allowed to add yes/no reactions to foreign messages!" could_not_add_reactions: Could not add reactions because I don't have `add_reactions` permission in {}. -poll_select_placeholder: Select an Option to Vote! +poll_select_placeholder: Select an option to vote! votes: zero: "{} Votes" one: "{} Vote" From 31719a13a30fc57c8c7bcb803aad447dd070e3f3 Mon Sep 17 00:00:00 2001 From: Tert0 <62036464+Tert0@users.noreply.github.com> Date: Sun, 3 Oct 2021 19:52:47 +0200 Subject: [PATCH 08/13] Update general/polls/translations/en.yml Co-authored-by: Tristan <45330667+Tristan-H11@users.noreply.github.com> --- general/polls/translations/en.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/general/polls/translations/en.yml b/general/polls/translations/en.yml index e50c917fb..17ce4fdc9 100644 --- a/general/polls/translations/en.yml +++ b/general/polls/translations/en.yml @@ -27,8 +27,8 @@ foreign_message: "You are not allowed to add yes/no reactions to foreign message could_not_add_reactions: Could not add reactions because I don't have `add_reactions` permission in {}. poll_select_placeholder: Select an option to vote! votes: - zero: "{} Votes" - one: "{} Vote" - many: "{} Votes" + zero: "{} votes" + one: "{} vote" + many: "{} votes" yes: Yes no: No From a25d598b2f34fe973cc2e0bbd5d7fa37242e3b7b Mon Sep 17 00:00:00 2001 From: Tert0 <62036464+Tert0@users.noreply.github.com> Date: Mon, 4 Oct 2021 17:36:25 +0200 Subject: [PATCH 09/13] Added Error Hadnling, Improved Code(Style) --- general/polls/cog.py | 32 ++++++++++++++----------------- general/polls/translations/en.yml | 8 ++++---- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/general/polls/cog.py b/general/polls/cog.py index 4565282ad..7e1282eb2 100644 --- a/general/polls/cog.py +++ b/general/polls/cog.py @@ -1,6 +1,6 @@ import re import string -from typing import Optional, Tuple +from typing import Optional, Tuple, List from discord import Embed, Message, PartialEmoji, Member, Forbidden, Guild, Interaction, SelectOption from discord.ext import commands @@ -23,8 +23,7 @@ tg = t.g t = t.polls -MAX_OPTIONS = 20 # Discord reactions limit -# TODO Remove Limit or change it +MAX_OPTIONS = 25 # Discord Select Item Limit default_emojis = [name_to_emoji[f"regional_indicator_{x}"] for x in string.ascii_lowercase] @@ -60,6 +59,9 @@ async def send_poll( ): question, *options = [line.replace("\x00", "\n") for line in args.replace("\\\n", "\x00").split("\n") if line] + if len(options) != len(set(options)): + raise CommandError(t.option_name_duplicated) + if not options: raise CommandError(t.missing_options) if len(options) > MAX_OPTIONS - allow_delete: @@ -67,7 +69,7 @@ async def send_poll( options = [PollOption(ctx, line, i) for i, line in enumerate(options)] - if any(len(str(option)) > EmbedLimits.FIELD_VALUE for option in options): + if any(len(str(option)) > 100 for option in options): # Max Char Length of Select Option = 100 raise CommandError(t.option_too_long(EmbedLimits.FIELD_VALUE)) embed = Embed(title=title, description=question, color=Colors.Polls, timestamp=utcnow()) @@ -76,9 +78,6 @@ async def send_poll( if allow_delete: embed.set_footer(text=t.created_by(ctx.author, ctx.author.id), icon_url=ctx.author.display_avatar.url) - if len(set(map(lambda x: x.emoji, options))) < len(options): - raise CommandError(t.option_duplicated) - if field: embed.add_field(name=field[0], value=field[1], inline=False) @@ -87,17 +86,13 @@ async def send_poll( vote_select = Select(placeholder=t.poll_select_placeholder, max_values=len(options)) for _, option in enumerate(options): - vote_select.add_option(label=option.option, description=t.votes(0, cnt=0), emoji=option.emoji) - - for option in options: - if len([item for item in options if item.option == option.option]) > 1: - raise CommandError("cant have to items with same name") # TODO Translation + vote_select.add_option(label=option.option, description=t.votes(cnt=0), emoji=option.emoji) async def poll_vote(interaction: Interaction): def get_option_by_label(label: str, select: Select) -> SelectOption: - for option in select.options: - if option.label == label: - return option + possible_options: List[SelectOption] = list(filter(lambda option: option.label == label, select.options)) + if len(possible_options) == 1: + return possible_options[0] def get_redis_key(message: Message, member: Member, option: SelectOption) -> str: return f"poll_vote:{message.id}:{member.id}:{vote_select.options.index(option)}" @@ -121,7 +116,7 @@ def get_team_poll_redis_key(message: Message, member: Member) -> str: await redis.delete(redis_key) vote_count: int = int(re.match(r"[\-]?[0-9]+", selected_option.description).group(0)) - selected_option.description = t.votes(vote_count + vote_value, cnt=vote_count + vote_value) + selected_option.description = t.votes(cnt=vote_count + vote_value) if vote_value == 1: await redis.set(redis_key, 1) if team_poll: @@ -140,8 +135,9 @@ def get_team_poll_redis_key(message: Message, member: Member) -> str: vote_select.callback = poll_vote view.add_item(vote_select) - poll: Message = await ctx.send(content="** **", embed=embed, view=view) # TODO Remove Content from Message - # Content will get sent as WorkARound for https://github.com/Pycord-Development/pycord/issues/192 + poll: Message = await ctx.send(content="** **", embed=embed, view=view) + # TODO Remove Content from Message + # Content will get sent as WorkARound for https://github.com/Pycord-Development/pycord/issues/192 try: if allow_delete: diff --git a/general/polls/translations/en.yml b/general/polls/translations/en.yml index 17ce4fdc9..5fe945dd0 100644 --- a/general/polls/translations/en.yml +++ b/general/polls/translations/en.yml @@ -9,7 +9,6 @@ vote_explanation: Vote using the reactions below! too_many_options: You specified too many options. The maximum amount is {}. option_too_long: Options are limited to {} characters. missing_options: Missing options -option_duplicated: You may not use the same emoji twice! empty_option: Empty option poll_usage: | @@ -27,8 +26,9 @@ foreign_message: "You are not allowed to add yes/no reactions to foreign message could_not_add_reactions: Could not add reactions because I don't have `add_reactions` permission in {}. poll_select_placeholder: Select an option to vote! votes: - zero: "{} votes" - one: "{} vote" - many: "{} votes" + zero: "{cnt} votes" + one: "{cnt} vote" + many: "{cnt} votes" yes: Yes no: No +option_name_duplicated: "You can't have a duplicated Option!" From 217cd2ddca765cf51c97e985997fc55d6605aec4 Mon Sep 17 00:00:00 2001 From: Tert0 <62036464+Tert0@users.noreply.github.com> Date: Mon, 4 Oct 2021 19:09:55 +0200 Subject: [PATCH 10/13] Fixed PEP8 --- general/polls/cog.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/general/polls/cog.py b/general/polls/cog.py index 7e1282eb2..98eb6f0ce 100644 --- a/general/polls/cog.py +++ b/general/polls/cog.py @@ -90,7 +90,9 @@ async def send_poll( async def poll_vote(interaction: Interaction): def get_option_by_label(label: str, select: Select) -> SelectOption: - possible_options: List[SelectOption] = list(filter(lambda option: option.label == label, select.options)) + possible_options: List[SelectOption] = list( + filter(lambda option: option.label == label, select.options) + ) if len(possible_options) == 1: return possible_options[0] From 37aa204a36a4666c13a06b3dfeea9efa83adbe9b Mon Sep 17 00:00:00 2001 From: Tert0 <62036464+Tert0@users.noreply.github.com> Date: Mon, 4 Oct 2021 19:13:56 +0200 Subject: [PATCH 11/13] Fixed PEP8 --- general/polls/cog.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/general/polls/cog.py b/general/polls/cog.py index 98eb6f0ce..727ff3928 100644 --- a/general/polls/cog.py +++ b/general/polls/cog.py @@ -91,7 +91,7 @@ async def send_poll( async def poll_vote(interaction: Interaction): def get_option_by_label(label: str, select: Select) -> SelectOption: possible_options: List[SelectOption] = list( - filter(lambda option: option.label == label, select.options) + filter(lambda option: option.label == label, select.options), ) if len(possible_options) == 1: return possible_options[0] From 64af042401b890e46db1531dc418c99345dcb7c6 Mon Sep 17 00:00:00 2001 From: Tert0 <62036464+Tert0@users.noreply.github.com> Date: Mon, 4 Oct 2021 20:05:39 +0200 Subject: [PATCH 12/13] Changed requested changes --- general/polls/translations/en.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/general/polls/translations/en.yml b/general/polls/translations/en.yml index 5fe945dd0..c77aa0f3f 100644 --- a/general/polls/translations/en.yml +++ b/general/polls/translations/en.yml @@ -26,7 +26,6 @@ foreign_message: "You are not allowed to add yes/no reactions to foreign message could_not_add_reactions: Could not add reactions because I don't have `add_reactions` permission in {}. poll_select_placeholder: Select an option to vote! votes: - zero: "{cnt} votes" one: "{cnt} vote" many: "{cnt} votes" yes: Yes From 9df92d53b34b3c0b52f1c340bbed71f25ff67d17 Mon Sep 17 00:00:00 2001 From: Tert0 <62036464+Tert0@users.noreply.github.com> Date: Mon, 4 Oct 2021 21:18:37 +0200 Subject: [PATCH 13/13] Improved Code --- general/polls/cog.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/general/polls/cog.py b/general/polls/cog.py index 727ff3928..da55abf69 100644 --- a/general/polls/cog.py +++ b/general/polls/cog.py @@ -9,7 +9,6 @@ from discord.utils import utcnow from PyDrocsid.cog import Cog -from PyDrocsid.embeds import EmbedLimits from PyDrocsid.emojis import name_to_emoji, emoji_to_name from PyDrocsid.events import StopEventHandling from PyDrocsid.settings import RoleSettings @@ -70,7 +69,7 @@ async def send_poll( options = [PollOption(ctx, line, i) for i, line in enumerate(options)] if any(len(str(option)) > 100 for option in options): # Max Char Length of Select Option = 100 - raise CommandError(t.option_too_long(EmbedLimits.FIELD_VALUE)) + raise CommandError(t.option_too_long(100)) embed = Embed(title=title, description=question, color=Colors.Polls, timestamp=utcnow()) embed.set_author(name=str(ctx.author), icon_url=ctx.author.display_avatar.url) @@ -112,20 +111,20 @@ def get_team_poll_redis_key(message: Message, member: Member) -> str: redis_key: str = get_redis_key(interaction.message, interaction.user, selected_option) team_poll_redis_key: str = get_team_poll_redis_key(interaction.message, interaction.user) - vote_value = 1 + if await redis.exists(redis_key): vote_value = -1 await redis.delete(redis_key) - - vote_count: int = int(re.match(r"[\-]?[0-9]+", selected_option.description).group(0)) - selected_option.description = t.votes(cnt=vote_count + vote_value) - if vote_value == 1: + if team_poll: + await redis.srem(team_poll_redis_key, vote_select.options.index(selected_option)) + else: + vote_value = 1 await redis.set(redis_key, 1) if team_poll: await redis.sadd(team_poll_redis_key, vote_select.options.index(selected_option)) - elif vote_value == -1: - if team_poll: - await redis.srem(team_poll_redis_key, vote_select.options.index(selected_option)) + + vote_count: int = int(re.match(r"[\-]?[0-9]+", selected_option.description).group(0)) + selected_option.description = t.votes(cnt=vote_count + vote_value) if team_poll: _, index = await get_teampoll_embed(interaction.message)