Skip to content

Commit 2de68dd

Browse files
committed
add role handler client
1 parent 4958e3d commit 2de68dd

File tree

3 files changed

+96
-1
lines changed

3 files changed

+96
-1
lines changed

src/zuffer/cli.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from .commands import login
33
from .commands import create_channels
44
from .commands import embed
5-
from .commands import welcome, list, play_music
5+
from .commands import welcome, list, play_music, handle_roles
66

77
@click.group(invoke_without_command=True)
88
@click.version_option(package_name="zuffer")
@@ -23,3 +23,4 @@ def main(ctx: click.Context):
2323
main.add_command(welcome.welcome_group)
2424
main.add_command(list.list_command)
2525
main.add_command(play_music.play_music)
26+
main.add_command(handle_roles.handle_roles)
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import click
2+
import discord
3+
from ..core import auth, clients
4+
5+
@click.command(name="handle-roles")
6+
@click.option("-private", is_flag=True, help="One member can have only one role")
7+
def handle_roles(private):
8+
token = auth.get_token()
9+
if token is not None:
10+
intents = discord.Intents.all()
11+
client = clients.RoleHandlerClient(unique=private, intents=intents)
12+
client.run(token)

src/zuffer/core/clients.py

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,3 +282,85 @@ def after_callback(error):
282282
await message.channel.send(f"Error joining voice channel: {str(e)}")
283283
else:
284284
await message.channel.send("You need to be in a voice channel first!")
285+
286+
class RoleHandlerClient(discord.Client):
287+
def __init__(self, *, intents: discord.Intents, unique: bool = False, **kwargs):
288+
super().__init__(intents=intents, **kwargs)
289+
self.unique = unique
290+
self.tree = discord.app_commands.CommandTree(self)
291+
292+
async def setup_hook(self):
293+
@self.tree.command(name="claim", description="Claim a role by its name")
294+
async def claim(interaction: discord.Interaction, identifier: str):
295+
await self._handle_claim(interaction, identifier)
296+
297+
@self.tree.command(name="unclaim", description="Drop a role you have claimed")
298+
async def unclaim(interaction: discord.Interaction, identifier: str):
299+
await self._handle_unclaim(interaction, identifier)
300+
301+
await self.tree.sync()
302+
303+
async def on_ready(self):
304+
if (self.user is not None):
305+
print(f"Logged in as {self.user} (ID: {self.user.id})")
306+
print("------")
307+
308+
async def _handle_claim(self, interaction: discord.Interaction, identifier: str):
309+
if not isinstance(interaction.user, discord.Member):
310+
await interaction.response.send_message("This command can only be used in a server.", ephemeral=True)
311+
return
312+
if interaction.guild is not None:
313+
role = discord.utils.get(interaction.guild.roles, name=identifier)
314+
if not role:
315+
await interaction.response.send_message(f"Role '{identifier}' not found.", ephemeral=True)
316+
return
317+
else:
318+
await interaction.response.send_message("This command can only be used in a server.", ephemeral=True)
319+
return
320+
321+
if self.unique and len(interaction.user.roles) > 1:
322+
for user_role in interaction.user.roles:
323+
if user_role.name != "@everyone" and user_role != role:
324+
await interaction.response.send_message(
325+
f"You already have the role '{user_role.name}'. "
326+
f"Use `/unclaim {user_role.name}` to remove it first.",
327+
ephemeral=True
328+
)
329+
return
330+
if role in interaction.user.roles:
331+
await interaction.response.send_message(f"You already have the '{identifier}' role.", ephemeral=True)
332+
return
333+
334+
try:
335+
await interaction.user.add_roles(role)
336+
await interaction.response.send_message(f"Successfully claimed the '{identifier}' role!", ephemeral=True)
337+
except discord.Forbidden:
338+
await interaction.response.send_message("I don't have permission to assign that role.", ephemeral=True)
339+
except Exception as e:
340+
await interaction.response.send_message(f"An error occurred: {str(e)}", ephemeral=True)
341+
342+
async def _handle_unclaim(self, interaction: discord.Interaction, identifier: str):
343+
if not isinstance(interaction.user, discord.Member):
344+
await interaction.response.send_message("This command can only be used in a server.", ephemeral=True)
345+
return
346+
347+
if interaction.guild is None:
348+
await interaction.response.send_message("This command can only be used in a server.", ephemeral=True)
349+
return
350+
351+
role = discord.utils.get(interaction.guild.roles, name=identifier)
352+
if not role:
353+
await interaction.response.send_message(f"Role '{identifier}' not found.", ephemeral=True)
354+
return
355+
356+
if role not in interaction.user.roles:
357+
await interaction.response.send_message(f"You don't have the '{identifier}' role.", ephemeral=True)
358+
return
359+
360+
try:
361+
await interaction.user.remove_roles(role)
362+
await interaction.response.send_message(f"Successfully removed the '{identifier}' role!", ephemeral=True)
363+
except discord.Forbidden:
364+
await interaction.response.send_message("I don't have permission to remove that role.", ephemeral=True)
365+
except Exception as e:
366+
await interaction.response.send_message(f"An error occurred: {str(e)}", ephemeral=True)

0 commit comments

Comments
 (0)