Skip to content

Commit

Permalink
Feature branch: Version 3.18 (#57)
Browse files Browse the repository at this point in the history
* chore: bump version

* Add the pt-BR locale (#54)

* Create pt_BR.json

* Update pt_BR.json

* Update pt_BR.json

* Update pt_BR.json

* Update pt_BR.json

* Update pt_BR.json

* Create python-app.yml

* Update python-app.yml

* Delete python-app.yml

* Clarifications and updates

* Fixing some mistakes

* feat: add some recognition to translation providers

* feat: add block listing for suggestions

* fix: tests

* feat: add en_US locale (#62)

* fix: update strings

Copied file/strings from master, not the current working branch for 3.18

---------

Co-authored-by: Davi <[email protected]>
Co-authored-by: Anthony Collier <[email protected]>
Co-authored-by: Anthony Collier <[email protected]>
  • Loading branch information
4 people authored Oct 11, 2023
1 parent 9e23beb commit de76bb9
Show file tree
Hide file tree
Showing 12 changed files with 446 additions and 3 deletions.
14 changes: 13 additions & 1 deletion suggestions/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
ConfiguredChannelNoLongerExists,
UnhandledError,
QueueImbalance,
BlocklistedUser,
)
from suggestions.http_error_parser import try_parse_http_error
from suggestions.objects import Error, GuildConfig, UserConfig
Expand All @@ -45,7 +46,7 @@

class SuggestionsBot(commands.AutoShardedInteractionBot, BotBase):
def __init__(self, *args, **kwargs):
self.version: str = "Public Release 3.17"
self.version: str = "Public Release 3.18"
self.main_guild_id: int = 601219766258106399
self.legacy_beta_role_id: int = 995588041991274547
self.automated_beta_role_id: int = 998173237282361425
Expand Down Expand Up @@ -414,6 +415,17 @@ async def on_slash_command_error(
ephemeral=True,
)

elif isinstance(exception, BlocklistedUser):
return await interaction.send(
embed=self.error_embed(
"Blocked Action",
"Administrators from this guild have removed your ability to run this action.",
error_code=ErrorCode.BLOCKLISTED_USER,
error=error,
),
ephemeral=True,
)

elif isinstance(exception, ConfiguredChannelNoLongerExists):
return await interaction.send(
embed=self.error_embed(
Expand Down
17 changes: 16 additions & 1 deletion suggestions/checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
from disnake.ext import commands

from suggestions.exceptions import (
BetaOnly,
MissingSuggestionsChannel,
MissingLogsChannel,
BlocklistedUser,
)

if TYPE_CHECKING:
Expand Down Expand Up @@ -62,3 +62,18 @@ async def check(interaction: disnake.Interaction):
return True

return commands.check(check) # type: ignore


def ensure_user_is_not_blocklisted():
async def check(interaction: disnake.Interaction):
guild_config: Optional[GuildConfig] = await fetch_guild_config(interaction)

if not bool(guild_config):
return True

if interaction.author.id in guild_config.blocked_users:
raise BlocklistedUser

return True

return commands.check(check) # type: ignore
2 changes: 2 additions & 0 deletions suggestions/codes.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ class ErrorCode(IntEnum):
MISSING_SEND_PERMISSIONS_IN_SUGGESTION_CHANNEL = 18
MISSING_THREAD_CREATE_PERMISSIONS = 19
QUEUE_IMBALANCE = 20
MISSING_QUEUE_CHANNEL = 21
BLOCKLISTED_USER = 22

@classmethod
def from_value(cls, value: int) -> ErrorCode:
Expand Down
140 changes: 140 additions & 0 deletions suggestions/cogs/blacklist_cog.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
from __future__ import annotations

import logging
from typing import TYPE_CHECKING

import disnake
from bot_base import NonExistentEntry
from disnake.ext import commands

from suggestions.objects import GuildConfig, Suggestion

if TYPE_CHECKING:
from suggestions import State, SuggestionsBot

log = logging.getLogger(__name__)


class BlacklistCog(commands.Cog):
def __init__(self, bot):
self.bot: SuggestionsBot = bot
self.state: State = self.bot.state

@commands.slash_command()
async def user(self, interaction: disnake.GuildCommandInteraction):
...

@user.sub_command_group()
async def blocklist(self, interaction: disnake.GuildCommandInteraction):
...

@blocklist.sub_command()
async def add(
self,
interaction: disnake.GuildCommandInteraction,
suggestion_id: str = commands.Param(),
):
"""
{{USER_BLOCKLIST_ADD}}
Parameters
----------
suggestion_id: str {{SUGGESTION_ID}}
"""
await interaction.response.defer(ephemeral=True)
suggestion: Suggestion = await Suggestion.from_id(
suggestion_id, interaction.guild_id, self.state
)
guild_config: GuildConfig = await GuildConfig.from_id(
interaction.guild_id, self.state
)
if suggestion.suggestion_author_id in guild_config.blocked_users:
return await interaction.send(
"This user is already blocked from creating new suggestions.",
ephemeral=True,
)

guild_config.blocked_users.add(suggestion.suggestion_author_id)
await self.bot.db.guild_configs.upsert(guild_config, guild_config)
await interaction.send(
"I have added that user to the blocklist. "
"They will be unable to create suggestions in the future.",
ephemeral=True,
)

@blocklist.sub_command()
async def remove(
self,
interaction: disnake.GuildCommandInteraction,
suggestion_id: str = commands.Param(default=None),
user_id: str = commands.Param(default=None),
):
"""
{{USER_BLOCKLIST_REMOVE}}
Parameters
----------
suggestion_id: str {{SUGGESTION_ID}}
user_id: str {{USER_ID}}
"""
await interaction.response.defer(ephemeral=True)
if suggestion_id and user_id:
return await interaction.send(
"Providing suggestion_id and user_id at the same time is not supported.",
ephemeral=True,
)

if suggestion_id:
suggestion: Suggestion = await Suggestion.from_id(
suggestion_id, interaction.guild_id, self.state
)
user_id = suggestion.suggestion_author_id

if user_id:
try:
user_id = int(user_id)
except ValueError:
return await interaction.send("User id is not valid.", ephemeral=True)

guild_config: GuildConfig = await GuildConfig.from_id(
interaction.guild_id, self.state
)
guild_config.blocked_users.discard(user_id)
await self.bot.db.guild_configs.upsert(guild_config, guild_config)
await interaction.send("I have un-blocklisted that user for you.")

@add.autocomplete("suggestion_id")
@remove.autocomplete("suggestion_id")
async def get_sid_for(
self,
interaction: disnake.ApplicationCommandInteraction,
user_input: str,
):
try:
values: list[str] = self.state.autocomplete_cache.get_entry(
interaction.guild_id
)
except NonExistentEntry:
values: list[str] = await self.state.populate_sid_cache(
interaction.guild_id
)
else:
if not values:
log.debug(
"Values was found, but empty in guild %s thus populating",
interaction.guild_id,
)
values: list[str] = await self.state.populate_sid_cache(
interaction.guild_id
)

possible_choices = [v for v in values if user_input.lower() in v.lower()]

if len(possible_choices) > 25:
return []

return possible_choices


def setup(bot):
bot.add_cog(BlacklistCog(bot))
1 change: 1 addition & 0 deletions suggestions/cogs/suggestion_cog.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ async def suggestion_down_vote(
dm_permission=False,
)
@cooldowns.cooldown(1, 3, bucket=InteractionBucket.author)
@checks.ensure_user_is_not_blocklisted()
@checks.ensure_guild_has_suggestions_channel()
async def suggest(
self,
Expand Down
4 changes: 4 additions & 0 deletions suggestions/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,7 @@ class UnhandledError(Exception):

class QueueImbalance(disnake.DiscordException):
"""This queued suggestion has already been dealt with in another queue."""


class BlocklistedUser(CheckFailure):
"""This user is blocked from taking this action in this guild."""
10 changes: 9 additions & 1 deletion suggestions/locales/en_GB.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,5 +113,13 @@
"CONFIG_GET_INNER_IMAGES_IN_SUGGESTIONS_MESSAGE": "This guild {} have images in suggestions.",
"CONFIG_SUGGESTIONS_IMAGES_ENABLE_INNER_MESSAGE": "All new suggestions can include images.",
"CONFIG_SUGGESTIONS_IMAGES_DISABLE_INNER_MESSAGE": "All new suggestions cannot include images.",
"VIEW_VOTERS_INNER_EMBED_TITLE": "Viewing voters"
"VIEW_VOTERS_INNER_EMBED_TITLE": "Viewing voters",
"USER_BLOCKLIST_ADD_NAME": "add",
"USER_BLOCKLIST_ADD_DESCRIPTION": "Remove a users ability to create suggestions.",
"USER_BLOCKLIST_REMOVE_NAME": "remove",
"USER_BLOCKLIST_REMOVE_DESCRIPTION": "Re-add a users ability to create suggestions.",
"SUGGESTION_ID_NAME": "suggestion_id",
"SUGGESTION_ID_DESCRIPTION": "The suggestions ID you wish to reference.",
"USER_ID_NAME": "user_id",
"USER_ID_DESCRIPTION": "The users discord id."
}
125 changes: 125 additions & 0 deletions suggestions/locales/en_US.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
{
"SUGGEST_NAME": "suggest",
"SUGGEST_DESCRIPTION": "Create a new suggestion.",
"SUGGEST_ARG_SUGGESTION_NAME": "suggestion",
"SUGGEST_ARG_SUGGESTION_DESCRIPTION": "Your suggestion.",
"SUGGEST_ARG_IMAGE_NAME": "image",
"SUGGEST_ARG_IMAGE_DESCRIPTION": "An image to add to your suggestion. Images currently expire after a couple weeks.",
"SUGGEST_ARG_ANONYMOUSLY_NAME": "anonymously",
"SUGGEST_ARG_ANONYMOUSLY_DESCRIPTION": "Submit your suggestion anonymously.",
"APPROVE_NAME": "approve",
"APPROVE_DESCRIPTION": "Approve a suggestion",
"APPROVE_ARG_SUGGESTION_ID_NAME": "suggestion_id",
"APPROVE_ARG_SUGGESTION_ID_DESCRIPTION": "The sID you wish to approve",
"APPROVE_ARG_RESPONSE_NAME": "response",
"APPROVE_ARG_RESPONSE_DESCRIPTION": "An optional response to add to the suggestion",
"REJECT_NAME": "reject",
"REJECT_DESCRIPTION": "Reject a suggestion",
"REJECT_ARG_SUGGESTION_ID_NAME": "suggestion_id",
"REJECT_ARG_SUGGESTION_ID_DESCRIPTION": "The sID you wish to reject",
"REJECT_ARG_RESPONSE_NAME": "response",
"REJECT_ARG_RESPONSE_DESCRIPTION": "An optional response to add to the suggestion",
"CLEAR_NAME": "clear",
"CLEAR_DESCRIPTION": "Remove a suggestion and any associated messages.",
"CLEAR_ARG_SUGGESTION_ID_NAME": "suggestion_id",
"CLEAR_ARG_SUGGESTION_ID_DESCRIPTION": "The sID you wish to reject",
"CLEAR_ARG_RESPONSE_NAME": "response",
"CLEAR_ARG_RESPONSE_DESCRIPTION": "An optional response to add to the suggestion",
"STATS_NAME": "stats",
"STATS_DESCRIPTION": "Get bot stats!",
"INFO_NAME": "info",
"INFO_DESCRIPTION": "View bot information.",
"INFO_ARG_SUPPORT_NAME": "support",
"INFO_ARG_SUPPORT_DESCRIPTION": "Set this to receive info relevant to receiving official support.",
"PING_NAME": "ping",
"PING_DESCRIPTION": "Pong!",
"SUGGESTION_UP_VOTE_INNER_NO_MORE_CASTING": "You can no longer cast votes on this suggestion.",
"SUGGESTION_UP_VOTE_INNER_ALREADY_VOTED": "You have already up voted this suggestion.",
"SUGGESTION_UP_VOTE_INNER_MODIFIED_VOTE": "I have changed your vote from a down vote to an up vote for this suggestion.\nThe suggestion will be updated shortly.",
"SUGGESTION_UP_VOTE_INNER_REGISTERED_VOTE": "Thanks!\nI have registered your up vote.",
"SUGGESTION_DOWN_VOTE_INNER_NO_MORE_CASTING": "You can no longer cast votes on this suggestion.",
"SUGGESTION_DOWN_VOTE_INNER_ALREADY_VOTED": "You have already down voted this suggestion.",
"SUGGESTION_DOWN_VOTE_INNER_MODIFIED_VOTE": "I have changed your vote from an up vote to a down vote for this suggestion.\nThe suggestion will be updated shortly.",
"SUGGESTION_DOWN_VOTE_INNER_REGISTERED_VOTE": "Thanks!\nI have registered your down vote.",
"VIEW_VOTERS_INNER_TITLE_PREFIX": "Voters",
"VIEW_UP_VOTERS_INNER_TITLE_PREFIX": "Up voters",
"VIEW_DOWN_VOTERS_INNER_TITLE_PREFIX": "Down voters",
"DISPLAY_DATA_INNER_OLD_SUGGESTION_TYPE": "Suggestions using reactions are not supported by this command.",
"DISPLAY_DATA_INNER_NO_VOTERS": "There are no voters to show you for this.",
"VOTER_PAGINATOR_INNER_EMBED_TITLE": "{} for suggestion `{}`",
"VOTER_PAGINATOR_INNER_EMBED_FOOTER": "Page {} of {}",
"APPROVE_INNER_MESSAGE": "You have approved **{}**",
"REJECT_INNER_MESSAGE": "You have rejected **{}**",
"CLEAR_INNER_MESSAGE": "I have cleared `{}` for you.",
"SUGGEST_INNER_SUGGESTION_SENT": "Hey, {}. Your suggestion has been sent to {} to be voted on!\n\nPlease wait until it gets approved or rejected by a staff member.\n\nYour suggestion ID (sID) for reference is **{}**.",
"SUGGEST_INNER_SUGGESTION_SENT_FOOTER": "Guild ID: {} | sID: {}",
"SUGGEST_INNER_THANKS": "Thanks for your suggestion!",
"SUGGEST_INNER_SENT_TO_QUEUE": "Your suggestion has been sent to the queue for processing.",
"SUGGEST_INNER_NO_ANONYMOUS_SUGGESTIONS": "Your guild does not allow anonymous suggestions.",
"SUGGEST_INNER_NO_IMAGES_IN_SUGGESTIONS": "Your guild does not allow images in suggestions.",
"CONFIG_ANONYMOUS_ENABLE_INNER_SUCCESS": "I have enabled anonymous suggestions for this guild.",
"CONFIG_ANONYMOUS_DISABLE_INNER_SUCCESS": "I have disabled anonymous suggestions for this guild.",
"SUGGESTION_OBJECT_LOCK_THREAD": "Locking this thread as the suggestion has reached a resolution.",
"CONFIG_CHANNEL_INNER_MESSAGE": "I have set this guilds suggestion channel to {}",
"CONFIG_LOGS_INNER_MESSAGE": "I have set this guilds log channel to {}",
"CONFIG_GET_INNER_BASE_EMBED_DESCRIPTION": "Configuration for {}\n",
"CONFIG_GET_INNER_PARTIAL_LOG_CHANNEL_SET": "Log channel: <#{}>",
"CONFIG_GET_INNER_PARTIAL_LOG_CHANNEL_NOT_SET": "Not set",
"CONFIG_GET_INNER_PARTIAL_SUGGESTION_CHANNEL_SET": "Suggestion channel: <#{}>",
"CONFIG_GET_INNER_PARTIAL_SUGGESTION_CHANNEL_NOT_SET": "Not set",
"CONFIG_GET_INNER_PARTIAL_DM_RESPONSES_SET": "will",
"CONFIG_GET_INNER_PARTIAL_DM_RESPONSES_NOT_SET": "will not",
"CONFIG_GET_INNER_PARTIAL_DM_RESPONSES_MESSAGE": "Dm responses: I {} DM users on actions such as suggest",
"CONFIG_GET_INNER_PARTIAL_THREADS_SET": "will",
"CONFIG_GET_INNER_PARTIAL_THREADS_NOT_SET": "will not",
"CONFIG_GET_INNER_PARTIAL_THREADS_MESSAGE": "I {} create threads for new suggestions",
"CONFIG_GET_INNER_KEEP_LOGS_SET": "Suggestion logs will be kept in your suggestions channel.",
"CONFIG_GET_INNER_KEEP_LOGS_NOT_SET": "Suggestion logs will be kept in your logs channel.",
"CONFIG_GET_INNER_ANONYMOUS_SUGGESTIONS_SET": "can",
"CONFIG_GET_INNER_ANONYMOUS_SUGGESTIONS_NOT_SET": "cannot",
"CONFIG_GET_INNER_ANONYMOUS_SUGGESTIONS_MESSAGE": "This guild {} have anonymous suggestions.",
"CONFIG_GET_INNER_AUTO_ARCHIVE_THREADS_SET": "will",
"CONFIG_GET_INNER_AUTO_ARCHIVE_THREADS_NOT_SET": "will not",
"CONFIG_GET_INNER_AUTO_ARCHIVE_THREADS_MESSAGE": "I {} automatically archive threads created for suggestions.",
"CONFIG_DM_ENABLE_INNER_MESSAGE": "I have enabled DM messages for this guild.",
"CONFIG_DM_DISABLE_INNER_MESSAGE": "I have disabled DM messages for this guild.",
"CONFIG_THREAD_ENABLE_INNER_MESSAGE": "I have enabled threads on new suggestions for this guild.",
"CONFIG_THREAD_DISABLE_INNER_MESSAGE": "I have disabled thread creation on new suggestions for this guild.",
"CONFIG_KEEPLOGS_ENABLE_INNER_MESSAGE": "Suggestions will now stay in your suggestions channel instead of going to logs.",
"CONFIG_KEEPLOGS_DISABLE_INNER_MESSAGE": "Suggestions will now be moved to your logs channel when finished.",
"CONFIG_AUTO_ARCHIVE_THREADS_ENABLE_INNER_MESSAGE": "Automatically created threads for suggestions will now be archived upon suggestion resolution.",
"CONFIG_AUTO_ARCHIVE_THREADS_DISABLE_INNER_MESSAGE": "Automatically created threads for suggestions will no longer be archived upon suggestion resolution.",
"CONFIG_SUGGESTIONS_QUEUE_ENABLE_INNER_MESSAGE": "All new suggestions will be sent to your suggestions queue.",
"CONFIG_SUGGESTIONS_QUEUE_DISABLE_INNER_MESSAGE": "All new suggestions will be sent directly to your suggestions channel.",
"CONFIG_ANONYMOUS_RESOLUTION_ENABLE_INNER_MESSAGE": "All further suggestions will not show the moderator who resolved them.",
"CONFIG_ANONYMOUS_RESOLUTION_DISABLE_INNER_MESSAGE": "All further suggestions will show the moderator who resolved them.",
"CONFIG_GET_INNER_SUGGESTIONS_QUEUE_SET": "In use.",
"CONFIG_GET_INNER_SUGGESTIONS_QUEUE_NOT_SET": "Not in use.",
"CONFIG_GET_INNER_SUGGESTIONS_QUEUE_MESSAGE": "Suggestions queue is $TEXT",
"CONFIG_GET_INNER_ANONYMOUS_RESOLUTION_NOT_SET": "Suggesters are shown who resolved their suggestions.",
"CONFIG_GET_INNER_ANONYMOUS_RESOLUTION_SET": "Suggesters are not shown who resolved their suggestions.",
"PAGINATION_INNER_SESSION_EXPIRED": "This pagination session has expired, please start a new one with `/queue view`",
"PAGINATION_INNER_NEXT_ITEM": "Viewing next item in queue.",
"PAGINATION_INNER_PREVIOUS_ITEM": "Viewing previous item in queue.",
"PAGINATION_INNER_QUEUE_EXPIRED": "This queue has expired.",
"PAGINATION_INNER_QUEUE_CANCELLED": "I have cancelled this queue for you.",
"PAGINATION_INNER_QUEUE_ACCEPTED": "I have accepted that suggestion from the queue.",
"PAGINATION_INNER_QUEUE_REJECTED": "I have removed that suggestion from the queue.",
"QUEUE_VIEW_INNER_NOTHING_QUEUED": "Your guild has no suggestions in the queue.",
"QUEUE_VIEW_INNER_PRIOR_QUEUE": "These suggestions were queued before your guild disabled the suggestions queue.",
"QUEUE_INNER_USER_REJECTED": "Your queued suggestion was rejected.",
"CONFIG_GET_INNER_IMAGES_IN_SUGGESTIONS_SET": "can",
"CONFIG_GET_INNER_IMAGES_IN_SUGGESTIONS_NOT_SET": "cannot",
"CONFIG_GET_INNER_IMAGES_IN_SUGGESTIONS_MESSAGE": "This guild {} have images in suggestions.",
"CONFIG_SUGGESTIONS_IMAGES_ENABLE_INNER_MESSAGE": "All new suggestions can include images.",
"CONFIG_SUGGESTIONS_IMAGES_DISABLE_INNER_MESSAGE": "All new suggestions cannot include images.",
"VIEW_VOTERS_INNER_EMBED_TITLE": "Viewing voters",
"USER_BLOCKLIST_ADD_NAME": "add",
"USER_BLOCKLIST_ADD_DESCRIPTION": "Remove a users ability to create suggestions.",
"USER_BLOCKLIST_REMOVE_NAME": "remove",
"USER_BLOCKLIST_REMOVE_DESCRIPTION": "Re-add a users ability to create suggestions.",
"SUGGESTION_ID_NAME": "suggestion_id",
"SUGGESTION_ID_DESCRIPTION": "The suggestions ID you wish to reference.",
"USER_ID_NAME": "user_id",
"USER_ID_DESCRIPTION": "The users discord id."
}
Loading

0 comments on commit de76bb9

Please sign in to comment.