Skip to content

Commit

Permalink
feat: version 3.28 (#95)
Browse files Browse the repository at this point in the history
* feat: version 3.28

* fix: da locale location

* chore: rework deps to include disnake[speed] explicitly

* fix: failing to close threads due to missing state

We now save a thread_id instead of trying to find the thread via message.id

Closes #98

* chore: update some deps

* migrate to new disnake syntax

* Upgrade disnake and disnake ext componenets (#99)

* migrate to new disnake syntax

* Start working on new buttons

* Implement all new buttons

* fix: Dockerfile builds
  • Loading branch information
Skelmis authored Jan 26, 2025
1 parent 1f9d5d3 commit d6dd385
Show file tree
Hide file tree
Showing 21 changed files with 1,330 additions and 907 deletions.
14 changes: 5 additions & 9 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
FROM python:3.10

# Set pip to have cleaner logs and no saved cache
ENV PIP_NO_CACHE_DIR=false

RUN mkdir -p /bot
WORKDIR bot
FROM python:3.11-alpine

WORKDIR /code
RUN pip install poetry

COPY ./pyproject.toml /bot/pyproject.toml
COPY ./poetry.lock /bot/poetry.lock

RUN poetry install

COPY . /bot
COPY . /code


CMD poetry run python3 main.py
CMD ["poetry", "run", "python", "main.py"]
1,339 changes: 849 additions & 490 deletions poetry.lock

Large diffs are not rendered by default.

13 changes: 7 additions & 6 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
[tool.poetry]
name = "suggestions bot"
version = "3.27"
version = "3.28"
description = "A Discord bot designed to build better communities by encouraging a positive and constructive relationship between community and staff."
authors = ["Your Name <[email protected]>"]
authors = ["Suggestions Bot"]
license = "AGPL-3.0"
readme = "README.md"
readme = "readme.md"
package-mode = false

[tool.poetry.dependencies]
python = "^3.10"
disnake = "2.9.2"
disnake = {extras = ["speed"], version = "2.10.1"}
alaric = "^1.5.0"
function-cooldowns = "^2.0.1"
httpx = "^0.27.2"
httpx = "^0.28.1"
orjson = "^3.10.11"
skelmis-commons = "^1.4.0"
zonis = "^2.1.0"
aiobotocore = "^2.15.2"
logoo = "^1.5.1"
disnake-ext-components = {git = "https://github.com/suggestionsbot/disnake-ext-components.git", rev = "91689ed74ffee73f631453a39e548af9b824826d"}
typing-extensions = "^4.12.2"
python-dotenv = "^1.0.1"
humanize = "^4.11.0"
disnake-ext-components = {git = "https://github.com/DisnakeCommunity/disnake-ext-components.git", rev = "rewrite"}


[tool.poetry.group.dev.dependencies]
Expand Down
11 changes: 10 additions & 1 deletion suggestions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,13 @@
from .bot import SuggestionsBot
from .main import create_bot

__all__ = ("SuggestionsBot", "State", "Colors", "Emojis", "ErrorCode", "Stats")
__all__ = (
"SuggestionsBot",
"State",
"Colors",
"Emojis",
"ErrorCode",
"Stats",
"Garven",
"buttons",
)
11 changes: 8 additions & 3 deletions suggestions/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from cooldowns import CallableOnCooldown
from disnake import Locale, LocalizationKeyError, Thread
from disnake.abc import PrivateChannel, GuildChannel
from disnake.ext import commands
from disnake.ext import commands, components
from disnake.state import AutoShardedConnectionState
from logoo import Logger

Expand Down Expand Up @@ -58,7 +58,7 @@

class SuggestionsBot(commands.AutoShardedInteractionBot):
def __init__(self, *args, **kwargs):
self.version: str = "Public Release 3.27"
self.version: str = "Public Release 3.28"
self.main_guild_id: int = 601219766258106399
self.legacy_beta_role_id: int = 995588041991274547
self.automated_beta_role_id: int = 998173237282361425
Expand Down Expand Up @@ -119,6 +119,11 @@ def __init__(self, *args, **kwargs):
# gateway_params=GatewayParams(zlib=False),
)

from suggestions import buttons

self.component_manager = components.get_manager()
self.component_manager.add_to_bot(self) # type: ignore

self._has_dispatched_initial_ready: bool = False
self._initial_ready_future: asyncio.Future = asyncio.Future()

Expand Down Expand Up @@ -777,7 +782,7 @@ async def on_slash_command_error(
"author_id": interaction.author.id,
},
)
return
raise exception

ih: InteractionHandler = await InteractionHandler.fetch_handler(
interaction.id, self
Expand Down
27 changes: 27 additions & 0 deletions suggestions/buttons/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from .suggestions_components import (
SuggestionUpVote,
SuggestionDownVote,
SuggestionsQueueApprove,
SuggestionsQueueReject,
)
from .virtual_queue import (
QueueButton,
QueueNextButton,
QueuePreviousButton,
QueueStopButton,
VirtualApproveButton,
VirtualRejectButton,
)

__all__ = (
"SuggestionUpVote",
"SuggestionDownVote",
"SuggestionsQueueApprove",
"SuggestionsQueueReject",
"QueueButton",
"QueueNextButton",
"QueuePreviousButton",
"VirtualApproveButton",
"VirtualRejectButton",
"QueueStopButton",
)
153 changes: 153 additions & 0 deletions suggestions/buttons/suggestions_components.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
from __future__ import annotations

import typing

import logoo
from disnake.ext import components
from disnake.ext.components import interaction

from suggestions.clunk2 import update_suggestion_message
from suggestions.interaction_handler import InteractionHandler
from suggestions.objects import Suggestion, QueuedSuggestion
from suggestions.objects.suggestion import SuggestionState
from suggestions.utility import wrap_with_error_handler

if typing.TYPE_CHECKING:
from suggestions.cogs.suggestion_cog import SuggestionsCog

logger = logoo.Logger(__name__)
manager = components.get_manager("suggestions")


@manager.register # type: ignore
class SuggestionUpVote(components.RichButton):
suggestion_id: str

@wrap_with_error_handler()
async def callback( # type: ignore
self,
inter: components.MessageInteraction,
) -> None:
ih: InteractionHandler = await InteractionHandler.new_handler(inter._wrapped)
suggestion: Suggestion = await Suggestion.from_id(
self.suggestion_id, inter.guild_id, ih.bot.state
)
if suggestion.state != SuggestionState.pending:
return await ih.send(
translation_key="SUGGESTION_UP_VOTE_INNER_NO_MORE_CASTING"
)

member_id = inter.author.id
if member_id in suggestion.up_voted_by:
return await ih.send(
translation_key="SUGGESTION_UP_VOTE_INNER_ALREADY_VOTED"
)

if member_id in suggestion.down_voted_by:
suggestion.down_voted_by.discard(member_id)
suggestion.up_voted_by.add(member_id)
await ih.bot.state.suggestions_db.upsert(suggestion, suggestion)
# await suggestion.update_vote_count(self.bot, inter)
# lock.enqueue(suggestion.update_vote_count(self.bot, inter))
await ih.send(translation_key="SUGGESTION_UP_VOTE_INNER_MODIFIED_VOTE")
logger.debug(
f"Member {member_id} modified their vote on {self.suggestion_id} to a up vote",
extra_metadata={
"suggestion_id": self.suggestion_id,
"guild_id": inter.guild_id,
},
)
else:
suggestion.up_voted_by.add(member_id)
await ih.bot.state.suggestions_db.upsert(suggestion, suggestion)
await ih.send(translation_key="SUGGESTION_UP_VOTE_INNER_REGISTERED_VOTE")
logger.debug(
f"Member {member_id} up voted {self.suggestion_id}",
extra_metadata={
"suggestion_id": self.suggestion_id,
"guild_id": inter.guild_id,
},
)

await update_suggestion_message(suggestion=suggestion, bot=ih.bot)


@manager.register # type: ignore
class SuggestionDownVote(components.RichButton):
suggestion_id: str

@wrap_with_error_handler()
async def callback( # type: ignore
self,
inter: interaction.MessageInteraction,
) -> None:
ih: InteractionHandler = await InteractionHandler.new_handler(inter._wrapped)
suggestion: Suggestion = await Suggestion.from_id(
self.suggestion_id, inter.guild_id, ih.bot.state
)
if suggestion.state != SuggestionState.pending:
return await ih.send(
translation_key="SUGGESTION_DOWN_VOTE_INNER_NO_MORE_CASTING"
)

member_id = inter.author.id
if member_id in suggestion.down_voted_by:
return await ih.send(
translation_key="SUGGESTION_DOWN_VOTE_INNER_ALREADY_VOTED"
)

if member_id in suggestion.up_voted_by:
suggestion.up_voted_by.discard(member_id)
suggestion.down_voted_by.add(member_id)
await ih.bot.state.suggestions_db.upsert(suggestion, suggestion)
await ih.send(translation_key="SUGGESTION_DOWN_VOTE_INNER_MODIFIED_VOTE")
logger.debug(
f"Member {member_id} modified their vote on {self.suggestion_id} to a down vote",
extra_metadata={
"suggestion_id": self.suggestion_id,
"guild_id": inter.guild_id,
},
)
else:
suggestion.down_voted_by.add(member_id)
await ih.bot.state.suggestions_db.upsert(suggestion, suggestion)
await ih.send(translation_key="SUGGESTION_DOWN_VOTE_INNER_REGISTERED_VOTE")
logger.debug(
f"Member {member_id} down voted {self.suggestion_id}",
extra_metadata={
"suggestion_id": self.suggestion_id,
"guild_id": inter.guild_id,
},
)

await update_suggestion_message(suggestion=suggestion, bot=ih.bot)


@manager.register # type:ignore
class SuggestionsQueueApprove(components.RichButton):
@wrap_with_error_handler()
async def callback(self, inter: interaction.MessageInteraction):
ih = await InteractionHandler.new_handler(inter._wrapped)
qs = await QueuedSuggestion.from_message_id(
inter.message.id, inter.message.channel.id, ih.bot.state
)
cog: SuggestionsCog = ih.bot.cogs.get("SuggestionsCog") # type: ignore
await cog.qs_core.resolve_queued_suggestion(
ih, queued_suggestion=qs, was_approved=True
)
await ih.send(translation_key="PAGINATION_INNER_QUEUE_ACCEPTED")


@manager.register # type:ignore
class SuggestionsQueueReject(components.RichButton):
@wrap_with_error_handler()
async def callback(self, inter: interaction.MessageInteraction):
ih = await InteractionHandler.new_handler(inter._wrapped)
qs = await QueuedSuggestion.from_message_id(
inter.message.id, inter.message.channel.id, ih.bot.state
)
cog: SuggestionsCog = ih.bot.cogs.get("SuggestionsCog") # type: ignore
await cog.qs_core.resolve_queued_suggestion(
ih, queued_suggestion=qs, was_approved=False
)
await ih.send(translation_key="PAGINATION_INNER_QUEUE_REJECTED")
63 changes: 63 additions & 0 deletions suggestions/buttons/virtual_queue.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
from __future__ import annotations

import typing

import logoo
from disnake.ext import components
from disnake.ext.components import interaction

from suggestions.interaction_handler import InteractionHandler
from suggestions.utility import wrap_with_error_handler

if typing.TYPE_CHECKING:
from suggestions.cogs.suggestion_queue_cog import SuggestionsQueueCog

logger = logoo.Logger(__name__)
manager = components.get_manager("suggestions")


class QueueButton(components.RichButton):
pid: str

@wrap_with_error_handler()
async def callback( # type: ignore
self,
inter: interaction.MessageInteraction,
):
ih = await InteractionHandler.new_handler(inter._wrapped)
cog: SuggestionsQueueCog = ih.bot.cogs.get("SuggestionsQueueCog") # type: ignore
await getattr(cog.core, core_mapping[self.__class__])(ih, self.pid) # type: ignore


@manager.register # type: ignore
class VirtualApproveButton(QueueButton):
pass


@manager.register # type: ignore
class VirtualRejectButton(QueueButton):
pass


@manager.register # type: ignore
class QueueStopButton(QueueButton):
pass


@manager.register # type: ignore
class QueueNextButton(QueueButton):
pass


@manager.register # type: ignore
class QueuePreviousButton(QueueButton):
pass


core_mapping = {
VirtualApproveButton: "virtual_approve_button",
VirtualRejectButton: "virtual_reject_button",
QueueStopButton: "stop_button",
QueueNextButton: "next_button",
QueuePreviousButton: "previous_button",
}
2 changes: 1 addition & 1 deletion suggestions/clunk2/edits.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
from logoo import Logger

from suggestions.low_level import MessageEditing
from suggestions.objects import Suggestion

if TYPE_CHECKING:
from suggestions.objects import Suggestion
from suggestions import SuggestionsBot

logger = Logger(__name__)
Expand Down
2 changes: 1 addition & 1 deletion suggestions/cogs/blacklist_cog.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ def __init__(self, bot):
self.state: State = self.bot.state

@commands.slash_command(
dm_permission=False,
default_member_permissions=disnake.Permissions(manage_guild=True),
)
@commands.contexts(guild=True)
async def user(self, interaction: disnake.GuildCommandInteraction): ...

@user.sub_command_group()
Expand Down
2 changes: 1 addition & 1 deletion suggestions/cogs/guild_config_cog.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ def __init__(self, bot):
self.stats: Stats = self.bot.stats

@commands.slash_command(
dm_permission=False,
default_member_permissions=disnake.Permissions(manage_guild=True),
)
@commands.contexts(guild=True)
@cooldowns.cooldown(1, 3, bucket=InteractionBucket.author)
async def config(self, interaction: disnake.GuildCommandInteraction):
"""Configure the bot for your guild."""
Expand Down
Loading

0 comments on commit d6dd385

Please sign in to comment.