Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrated reaction role cog to new extension format #276

Open
wants to merge 10 commits into
base: dev
Choose a base branch
from
64 changes: 0 additions & 64 deletions bot/cogs/roles.py

This file was deleted.

13 changes: 1 addition & 12 deletions bot/config.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import json
import logging
from typing import Dict, List
from typing import List
FirePlank marked this conversation as resolved.
Show resolved Hide resolved

from pydantic import BaseModel, BaseSettings, PostgresDsn, ValidationError, validator

Expand Down Expand Up @@ -62,16 +62,6 @@ class Postgres(BaseModel):
uri: PostgresDsn


class ReactionRoles(BaseModel):
required_role_id: int # [lvl 20] Developer
roles: Dict[int, int] # Dict[emoji_id, role_id]
message_id: int

@validator("roles", pre=True)
def val_func(cls, val):
return {int(k): v for k, v in json.loads(val).items()}


class Tags(BaseModel):
log_channel_id: int
required_role_id: int # [lvl 30] Engineer
Expand Down Expand Up @@ -110,7 +100,6 @@ class Settings(BaseSettings):
postgres: Postgres
guild: Guild
moderation: Moderation
reaction_roles: ReactionRoles
tags: Tags
timathon: Timathon
hastebin: Hastebin
Expand Down
7 changes: 7 additions & 0 deletions bot/extensions/selectable_roles/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from bot.core import DiscordBot

from .commands import SelectableRoleCommands


async def setup(bot: DiscordBot) -> None:
await bot.add_cog(SelectableRoleCommands(bot=bot))
93 changes: 93 additions & 0 deletions bot/extensions/selectable_roles/commands.py
FirePlank marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import discord
from discord import app_commands
from discord.ext import commands

from bot import core
from bot.extensions.selectable_roles.views import CreateSelectableRoleView, SelectableRoleOptions
from utils.transformers import MessageTransformer


@app_commands.default_permissions(administrator=True)
class SelectableRoleCommands(commands.GroupCog, group_name="selectable-role"):
def __init__(self, bot: core.DiscordBot):
self.bot = bot

# TODO: Make the view work even after a restart
self._create_selectable_role_view = CreateSelectableRoleView(timeout=None)
self.bot.add_view(self._create_selectable_role_view)

@app_commands.command()
async def create(self, interaction: core.InteractionType, title: str, channel: discord.TextChannel = None):
"""Create a new selectable role message"""

if channel is None:
channel = interaction.channel

await channel.send(title, view=self._create_selectable_role_view)
await interaction.response.send_message(
FirePlank marked this conversation as resolved.
Show resolved Hide resolved
"Successfully created selectable role message! Please add role options to it by using /selectable-role add",
ephemeral=True,
)

@app_commands.command()
async def add(
self,
interaction: core.InteractionType,
message: app_commands.Transform[discord.Message, MessageTransformer],
text: str,
role: discord.Role,
emoji: str,
):
"""Add a selectable role to a message"""

if message.author != self.bot.user:
return await interaction.response.send_message(
"This message is not a selectable role message.", ephemeral=True
)

emoji = discord.utils.get(interaction.guild.emojis, name=emoji)
view = discord.ui.View.from_message(message, timeout=None)
options = []
if view.children:
options = view.children[0].options

view = CreateSelectableRoleView(timeout=None)
view.add_item(
SelectableRoleOptions(
options + [discord.SelectOption(label=role.name, description=text, value=str(role.id), emoji=emoji)]
)
)

await message.edit(view=view)
await interaction.response.send_message("Successfully added role to selectable role message!", ephemeral=True)

@app_commands.command()
async def remove(
self,
interaction: core.InteractionType,
message: app_commands.Transform[discord.Message, MessageTransformer],
role: discord.Role,
):
"""Remove a selectable role from a message"""

if message.author != self.bot.user:
return await interaction.response.send_message(
"This message is not a selectable role message.", ephemeral=True
)

view = discord.ui.View.from_message(message, timeout=None)
options = []
if view.children:
options = view.children[0].options
options = [option for option in options if option.value != str(role.id)]

if len(options) == 0:
await message.edit(view=None)
else:
view = CreateSelectableRoleView(timeout=None)
view.add_item(SelectableRoleOptions(options))
await message.edit(view=view)

await interaction.response.send_message(
"Successfully removed role from selectable role message!", ephemeral=True
)
29 changes: 29 additions & 0 deletions bot/extensions/selectable_roles/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import discord
from discord import ui

from bot import core


class SelectableRoleOptions(discord.ui.Select):
def __init__(self, options: list[discord.SelectOption]):
super().__init__(
placeholder="Select a role",
custom_id=CreateSelectableRoleView.DROPDOWN_CUSTOM_ID,
options=options,
)

async def callback(self, interaction: core.InteractionType):
selected_role_id = int(self.values[0])
role = interaction.guild.get_role(selected_role_id)

other_roles = [
interaction.guild.get_role(int(option.value)) for option in self.options if option != selected_role_id
]

await interaction.user.remove_roles(*other_roles, reason="Selectable role")
await interaction.user.add_roles(role, reason="Selectable role")
await interaction.response.send_message(f"Successfully added {role.mention} to you!", ephemeral=True)


class CreateSelectableRoleView(ui.View):
DROPDOWN_CUSTOM_ID = "extensions:selectable_roles:dropdown"
2 changes: 1 addition & 1 deletion cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,9 @@ async def main(ctx):
"bot.extensions.custom_roles",
"bot.extensions.polls",
"bot.extensions.youtube",
"bot.extensions.selectable_roles",
"bot.cogs._help",
"bot.cogs.clashofcode",
"bot.cogs.roles",
)

intents = discord.Intents.all()
Expand Down
8 changes: 0 additions & 8 deletions example.env
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,6 @@ MODERATION__STAFF_ROLE_ID=
NOTIFICATION__CHANNEL_ID=0
NOTIFICATION__ROLE_ID=0

# --- Reaction Roles
# Access to reaction roles
REACTION_ROLES__REQUIRED_ROLE_ID=0
# Dict[emoji_id: int, role_id: int]
# Leave no space or use double quotes `"` e.g: "{\"0\": 0}"
REACTION_ROLES__ROLES={"0":0}
REACTION_ROLES__MESSAGE_ID=0

# --- Tags
TAGS__LOG_CHANNEL_ID=0
# Access to tag commands
Expand Down
3 changes: 1 addition & 2 deletions utils/transformers.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ async def transform(self, interaction: core.InteractionType, value: str, /):
try:
parts: list[str] = value.split("/")

# check that there are 2 parts
if len(parts) != 2:
return await interaction.channel.fetch_message(int(value))

Expand All @@ -23,7 +22,7 @@ async def transform(self, interaction: core.InteractionType, value: str, /):
channel = interaction.guild.get_channel(channel_id)
return await channel.fetch_message(message_id)
except (ValueError, TypeError, IndexError, AttributeError):
await interaction.response.send_message("Please provide a valid message URL.", ephemeral=True)
await interaction.response.send_message("Please provide a valid message ID.", ephemeral=True)
FirePlank marked this conversation as resolved.
Show resolved Hide resolved
except discord.HTTPException:
await interaction.response.send_message("Sorry, I couldn't find that message...", ephemeral=True)

Expand Down
Loading