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

Custom Role command #246

Merged
merged 15 commits into from
Nov 13, 2023
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions bot/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ class ErrorHandling(BaseModel):
webhook_url: str


class CustomRoles(BaseModel):
log_channel_id: int


class Settings(BaseSettings):
aoc: AoC
bot: Bot
Expand All @@ -111,6 +115,7 @@ class Settings(BaseSettings):
timathon: Timathon
hastebin: Hastebin
errors: ErrorHandling
custom_roles: CustomRoles

class Config:
env_file = ".env"
Expand Down
9 changes: 9 additions & 0 deletions bot/extensions/custom_roles/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from bot.core import DiscordBot

from .commands import CustomRoles
from .events import CustomRoleEvents


async def setup(bot: DiscordBot) -> None:
await bot.add_cog(CustomRoles(bot=bot))
await bot.add_cog(CustomRoleEvents(bot=bot))
106 changes: 106 additions & 0 deletions bot/extensions/custom_roles/commands.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import datetime

import discord
from discord import app_commands
from discord.ext import commands
from discord.utils import escape_markdown, format_dt

from bot import core
from bot.models import CustomRole


class CustomRoles(commands.Cog):
def __init__(self, bot):
self.bot = bot

def role_embed(self, heading: str, user: discord.Member, role: discord.Role):
embed = discord.Embed(
description=f"### {heading} {user.mention}\n\n**Name**\n{escape_markdown(role.name)}\n**Color**\n"
f"{role.color}\n**Created**\n {format_dt(role.created_at)}",
color=role.color,
timestamp=datetime.datetime.utcnow(),
)
embed.set_footer(text=user.name)
embed.set_thumbnail(url=user.avatar)
return embed

@app_commands.command(description="Manage custom role")
@app_commands.default_permissions(administrator=True)
@app_commands.describe(name="Updating Custom Role name", color="Updating custom role name")
async def myrole(self, interaction: core.InteractionType, name: str = None, color: str = None):
if color:
try:
color = discord.Color(int(color, 16))
except ValueError:
return await interaction.response.send_message("Invalid HEX value", ephemeral=True)

query = """SELECT * FROM custom_roles
WHERE guild_id = $1 AND user_id = $2"""
before = await CustomRole.fetchrow(query, interaction.guild.id, interaction.user.id)

# Insert data if it doesn't exist
if before is None:
# Validate the name parameter
if name is None:
return await interaction.response.send_message("You don't have a custom role yet!", ephemeral=True)

# Create and assign the role to user
discord_role = await interaction.guild.create_role(name=name, colour=color or discord.Color.default())
await interaction.user.add_roles(discord_role)

query = """INSERT INTO custom_roles (user_id, guild_id, role_id, name, color)
VALUES ($1, $2, $3, $4, $5)
RETURNING *"""
record = await CustomRole.fetchrow(
query,
interaction.user.id,
interaction.guild.id,
discord_role.id,
discord_role.name,
str(discord_role.color),
)
# Persist the role
self.bot.dispatch(
"persist_roles", guild_id=interaction.guild.id, user_id=interaction.user.id, role_ids=[discord_role.id]
)
# Log the role
self.bot.dispatch("custom_role_create", data=record)

return await interaction.response.send_message(
embed=self.role_embed("**Custom Role has been assigned**", interaction.user, discord_role),
ephemeral=True,
)

# Return role information if no parameter is passed
if not name and not color:
sarzz2 marked this conversation as resolved.
Show resolved Hide resolved
return await interaction.response.send_message(
embed=self.role_embed("Custom Role for", interaction.user, interaction.guild.get_role(before.role_id)),
ephemeral=True,
)

# Editing the role
await interaction.guild.get_role(before.role_id).edit(
name=name or before.name,
colour=color or discord.Color(int(before.color.lstrip("#"), 16)),
)

# Update data in DB
query = """UPDATE custom_roles
SET name = $4, color = $5
WHERE guild_id = $1 AND user_id = $2 AND role_id = $3
RETURNING *"""
after = await CustomRole.fetchrow(
query, interaction.guild.id, interaction.user.id, before.role_id, name, color or before.color
)
self.bot.dispatch("custom_role_update", before, after)

return await interaction.response.send_message(
embed=self.role_embed(
"**Custom Role has been updated**", interaction.user, interaction.guild.get_role(before.role_id)
),
ephemeral=True,
)


async def setup(bot: commands.Bot):
await bot.add_cog(CustomRoles(bot=bot))
58 changes: 58 additions & 0 deletions bot/extensions/custom_roles/events.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import datetime

import discord
from discord.ext import commands

from bot import core
from bot.config import settings
from bot.models.custom_roles import CustomRole


class CustomRoleEvents(commands.Cog):
"""Events for Levelling in discord."""

def __init__(self, bot: core.DiscordBot):
self.bot = bot
self.updated_at: dict[int, datetime] = {}

@property
def custom_roles_logs_channel(self) -> discord.TextChannel | None:
return self.bot.guild.get_channel(settings.custom_roles.log_channel_id)

@commands.Cog.listener()
async def on_guild_role_update(self, before, after):
# TODO send an embed for updating role manually
pass

@commands.Cog.listener()
async def on_custom_role_create(self, data: CustomRole):
"""Logs the creation of new role"""
embed = discord.Embed(
description=f"### <@{data.user_id}> Custom Role Created",
color=discord.Color.brand_green(),
timestamp=datetime.datetime.utcnow(),
)
embed.add_field(name="Name", value=data.name)
embed.add_field(name="Color", value=str(data.color))
embed.set_thumbnail(url=(await self.bot.fetch_user(data.user_id)).avatar)

return await self.custom_roles_logs_channel.send(embed=embed)

@commands.Cog.listener()
async def on_custom_role_update(self, before: CustomRole, after: CustomRole):
"""Logs the update of custom role."""
embed = discord.Embed(
description=f"### <@{before.user_id}> Custom Role Updated",
color=discord.Color.brand_green(),
timestamp=datetime.datetime.utcnow(),
)

embed.add_field(name="Old Name", value=before.name)
embed.add_field(name="New Name", value=after.name)
embed.add_field(name="\u200B", value="\u200B")
embed.add_field(name="Old Color", value=before.color)
embed.add_field(name="New Color", value=str(after.color))
embed.add_field(name="\u200B", value="\u200B")
embed.set_thumbnail(url=(await self.bot.fetch_user(before.user_id)).avatar)

return await self.custom_roles_logs_channel.send(embed=embed)
2 changes: 2 additions & 0 deletions bot/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from .custom_roles import CustomRole
from .gconfig import FilterConfig
from .levelling_ignored_channels import IgnoredChannel
from .levelling_roles import LevellingRole
Expand All @@ -20,4 +21,5 @@
PersistedRole,
IgnoredChannel,
LevellingRole,
CustomRole,
sarzz2 marked this conversation as resolved.
Show resolved Hide resolved
) # Fixes F401
1 change: 1 addition & 0 deletions bot/models/custom_roles.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

class CustomRole(Model):
id: int
user_id: int | None
guild_id: int
role_id: int
name: str
Expand Down
1 change: 1 addition & 0 deletions bot/models/migrations/005_down__custom_role.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE custom_roles DROP COLUMN user_id;
1 change: 1 addition & 0 deletions bot/models/migrations/005_up__custom_roles.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE custom_roles ADD COLUMN user_id BIGINT;
1 change: 1 addition & 0 deletions cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ async def main(ctx):
"bot.extensions.tags",
"bot.extensions.levelling",
"bot.extensions.persistent_roles",
"bot.extensions.custom_roles",
"bot.cogs._help",
"bot.cogs.clashofcode",
"bot.cogs.roles",
Expand Down
3 changes: 3 additions & 0 deletions example.env
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,6 @@ TAGS__REQUIRED_ROLE_ID=0
# --- Timathon
TIMATHON__CHANNEL_ID=0
TIMATHON__PARTICIPANT_ROLE_ID=0

# --- Custom Roles
CUSTOM_ROLES__LOG_CHANNEL_ID = 0