Add ControlPanel integration and refactor autoroom creation logic
Some checks are pending
Run pre-commit / Run pre-commit (push) Waiting to run
Some checks are pending
Run pre-commit / Run pre-commit (push) Waiting to run
This update introduces the ControlPanel class to the AutoRoom cog, enhancing the autoroom creation process. The autoroom source configuration has been streamlined by renaming variables for clarity. Additionally, the logic for creating associated text channels has been improved, ensuring better handling of permissions and channel creation. The waiting room functionality has also been adjusted to correctly reference the voice channel's text chat.
This commit is contained in:
parent
4c69cf7ab9
commit
fa6cd01476
3 changed files with 275 additions and 73 deletions
|
@ -16,6 +16,7 @@ from .c_autoroomset import AutoRoomSetCommands, channel_name_template
|
|||
from .pcx_lib import Perms, SettingDisplay
|
||||
from .pcx_template import Template
|
||||
from .waiting_room import WaitingRoom
|
||||
from .control_panel import ControlPanel
|
||||
|
||||
|
||||
class CompositeMetaClass(type(commands.Cog), type(ABC)):
|
||||
|
@ -117,6 +118,7 @@ class AutoRoom(
|
|||
self.config.register_channel(**self.default_channel_settings)
|
||||
self.template = Template()
|
||||
self.waiting_room = WaitingRoom(self)
|
||||
self.control_panel = ControlPanel(self)
|
||||
self.bucket_autoroom_create = commands.CooldownMapping.from_cooldown(
|
||||
2, 60, lambda member: member
|
||||
)
|
||||
|
@ -409,13 +411,13 @@ class AutoRoom(
|
|||
async def _process_autoroom_create(
|
||||
self,
|
||||
autoroom_source: discord.VoiceChannel,
|
||||
autoroom_source_config: dict[str, Any],
|
||||
asc: dict[str, Any],
|
||||
member: discord.Member,
|
||||
) -> None:
|
||||
"""Create a voice channel for a member in an AutoRoom Source channel."""
|
||||
"""Actually do channel creation for autoroom."""
|
||||
# Check perms for guild, source, and dest
|
||||
guild = autoroom_source.guild
|
||||
dest_category = guild.get_channel(autoroom_source_config["dest_category_id"])
|
||||
dest_category = guild.get_channel(asc["dest_category_id"])
|
||||
if not isinstance(dest_category, discord.CategoryChannel):
|
||||
return
|
||||
required_check, optional_check, _ = self.check_perms_source_dest(
|
||||
|
@ -452,7 +454,7 @@ class AutoRoom(
|
|||
voice_channel.name for voice_channel in dest_category.voice_channels
|
||||
]
|
||||
new_channel_name = await self._generate_channel_name(
|
||||
autoroom_source_config, member, taken_channel_names
|
||||
asc, member, taken_channel_names
|
||||
)
|
||||
|
||||
# Generate overwrites
|
||||
|
@ -478,20 +480,20 @@ class AutoRoom(
|
|||
perms.overwrite(target, permissions)
|
||||
if member_roles and target in member_roles:
|
||||
# If we have member roles and this target is one, apply AutoRoom type permissions
|
||||
perms.update(target, autoroom_source_config["perms"]["access"])
|
||||
perms.update(target, asc["perms"]["access"])
|
||||
|
||||
# Update overwrites for default role to account for AutoRoom type
|
||||
if member_roles:
|
||||
perms.update(guild.default_role, autoroom_source_config["perms"]["deny"])
|
||||
perms.update(guild.default_role, asc["perms"]["deny"])
|
||||
else:
|
||||
perms.update(guild.default_role, autoroom_source_config["perms"]["access"])
|
||||
perms.update(guild.default_role, asc["perms"]["access"])
|
||||
|
||||
# Bot overwrites
|
||||
perms.update(guild.me, self.perms_bot_dest)
|
||||
|
||||
# AutoRoom Owner overwrites
|
||||
if autoroom_source_config["room_type"] != "server":
|
||||
perms.update(member, autoroom_source_config["perms"]["owner"])
|
||||
if asc["room_type"] != "server":
|
||||
perms.update(member, asc["perms"]["owner"])
|
||||
|
||||
# Admin/moderator/bot overwrites
|
||||
# Add bot roles to be allowed
|
||||
|
@ -504,83 +506,34 @@ class AutoRoom(
|
|||
additional_allowed_roles += await self.bot.get_admin_roles(guild)
|
||||
for role in additional_allowed_roles:
|
||||
# Add all the mod/admin roles, if required
|
||||
perms.update(role, autoroom_source_config["perms"]["allow"])
|
||||
perms.update(role, asc["perms"]["allow"])
|
||||
|
||||
# Create new AutoRoom
|
||||
# Create the voice channel
|
||||
new_voice_channel = await guild.create_voice_channel(
|
||||
name=new_channel_name,
|
||||
category=dest_category,
|
||||
bitrate=min(
|
||||
int(guild.bitrate_limit),
|
||||
int(autoroom_source.bitrate),
|
||||
),
|
||||
user_limit=autoroom_source.user_limit,
|
||||
reason="AutoRoom: New AutoRoom needed.",
|
||||
overwrites=perms.overwrites if perms.overwrites else {},
|
||||
bitrate=min(autoroom_source.bitrate, int(guild.bitrate_limit)),
|
||||
user_limit=autoroom_source.user_limit,
|
||||
)
|
||||
await self.config.channel(new_voice_channel).source_channel.set(
|
||||
autoroom_source.id
|
||||
)
|
||||
if autoroom_source_config["room_type"] != "server":
|
||||
await self.config.channel(new_voice_channel).owner.set(member.id)
|
||||
try:
|
||||
await member.move_to(
|
||||
new_voice_channel, reason="AutoRoom: Move user to new AutoRoom."
|
||||
)
|
||||
except discord.HTTPException:
|
||||
await self._process_autoroom_delete(new_voice_channel, member)
|
||||
return
|
||||
|
||||
# Create optional legacy text channel
|
||||
new_legacy_text_channel = None
|
||||
if autoroom_source_config["legacy_text_channel"]:
|
||||
# Sanity check on required permissions
|
||||
for perm_name in self.perms_bot_dest_legacy_text:
|
||||
if not getattr(dest_perms, perm_name):
|
||||
return
|
||||
# Generate overwrites
|
||||
perms = Perms()
|
||||
perms.update(guild.me, self.perms_bot_dest_legacy_text)
|
||||
perms.update(guild.default_role, self.perms_legacy_text_deny)
|
||||
if autoroom_source_config["room_type"] != "server":
|
||||
perms.update(member, self.perms_autoroom_owner_legacy_text)
|
||||
else:
|
||||
perms.update(member, self.perms_legacy_text_allow)
|
||||
# Admin/moderator overwrites
|
||||
additional_allowed_roles_text = []
|
||||
if await self.config.guild(guild).mod_access():
|
||||
# Add mod roles to be allowed
|
||||
additional_allowed_roles_text += await self.bot.get_mod_roles(guild)
|
||||
if await self.config.guild(guild).admin_access():
|
||||
# Add admin roles to be allowed
|
||||
additional_allowed_roles_text += await self.bot.get_admin_roles(guild)
|
||||
for role in additional_allowed_roles_text:
|
||||
# Add all the mod/admin roles, if required
|
||||
perms.update(role, self.perms_legacy_text_allow)
|
||||
# Create text channel
|
||||
text_channel_topic = await self.template.render(
|
||||
autoroom_source_config["text_channel_topic"],
|
||||
self.get_template_data(member),
|
||||
)
|
||||
new_legacy_text_channel = await guild.create_text_channel(
|
||||
name=new_channel_name.replace("'s ", " "),
|
||||
category=dest_category,
|
||||
topic=text_channel_topic,
|
||||
reason="AutoRoom: New legacy text channel needed.",
|
||||
overwrites=perms.overwrites if perms.overwrites else {},
|
||||
)
|
||||
|
||||
await self.config.channel(new_voice_channel).associated_text_channel.set(
|
||||
new_legacy_text_channel.id
|
||||
)
|
||||
# Create control panel in the voice channel's text chat
|
||||
await self.control_panel.create_control_panel(new_voice_channel)
|
||||
|
||||
# Send text chat hint if enabled
|
||||
if autoroom_source_config["text_channel_hint"]:
|
||||
if asc["text_channel_hint"]:
|
||||
with suppress(Exception):
|
||||
hint = await self.template.render(
|
||||
autoroom_source_config["text_channel_hint"],
|
||||
asc["text_channel_hint"],
|
||||
self.get_template_data(member),
|
||||
)
|
||||
if hint:
|
||||
if new_legacy_text_channel:
|
||||
await new_legacy_text_channel.send(hint)
|
||||
if new_voice_channel:
|
||||
await new_voice_channel.send(hint)
|
||||
else:
|
||||
await new_voice_channel.send(hint[:2000].strip())
|
||||
|
||||
|
@ -1079,3 +1032,53 @@ class AutoRoom(
|
|||
# Update the bot role list to remove nonexistent roles
|
||||
await self.config.guild(guild).bot_access.set(bot_role_ids)
|
||||
return bot_roles
|
||||
|
||||
async def _create_autoroom_legacy_text_channel(
|
||||
self,
|
||||
autoroom_source: discord.VoiceChannel,
|
||||
autoroom_source_config: dict[str, Any],
|
||||
member: discord.Member,
|
||||
autoroom: discord.VoiceChannel,
|
||||
) -> discord.TextChannel | None:
|
||||
"""Create a legacy text channel for an AutoRoom."""
|
||||
# Sanity check on required permissions
|
||||
for perm_name in self.perms_bot_dest_legacy_text:
|
||||
if not getattr(autoroom_source.permissions_for(autoroom_source.guild.me), perm_name):
|
||||
return None
|
||||
|
||||
# Generate overwrites
|
||||
perms = Perms()
|
||||
perms.update(autoroom_source.guild.me, self.perms_bot_dest_legacy_text)
|
||||
perms.update(autoroom_source.guild.default_role, self.perms_legacy_text_deny)
|
||||
if autoroom_source_config["room_type"] != "server":
|
||||
perms.update(member, self.perms_autoroom_owner_legacy_text)
|
||||
else:
|
||||
perms.update(member, self.perms_legacy_text_allow)
|
||||
# Admin/moderator overwrites
|
||||
additional_allowed_roles_text = []
|
||||
if await self.config.guild(autoroom_source.guild).mod_access():
|
||||
# Add mod roles to be allowed
|
||||
additional_allowed_roles_text += await self.bot.get_mod_roles(autoroom_source.guild)
|
||||
if await self.config.guild(autoroom_source.guild).admin_access():
|
||||
# Add admin roles to be allowed
|
||||
additional_allowed_roles_text += await self.bot.get_admin_roles(autoroom_source.guild)
|
||||
for role in additional_allowed_roles_text:
|
||||
# Add all the mod/admin roles, if required
|
||||
perms.update(role, self.perms_legacy_text_allow)
|
||||
# Create text channel
|
||||
text_channel_topic = await self.template.render(
|
||||
autoroom_source_config["text_channel_topic"],
|
||||
self.get_template_data(member),
|
||||
)
|
||||
text_channel = await autoroom_source.guild.create_text_channel(
|
||||
name=autoroom.name.replace("'s ", " "),
|
||||
category=autoroom.category,
|
||||
topic=text_channel_topic,
|
||||
reason="AutoRoom: New legacy text channel needed.",
|
||||
overwrites=perms.overwrites if perms.overwrites else {},
|
||||
)
|
||||
|
||||
await self.config.channel(autoroom).associated_text_channel.set(
|
||||
text_channel.id
|
||||
)
|
||||
return text_channel
|
||||
|
|
199
autoroom/control_panel.py
Normal file
199
autoroom/control_panel.py
Normal file
|
@ -0,0 +1,199 @@
|
|||
"""Control panel functionality for AutoRoom cog."""
|
||||
|
||||
from typing import Any, Optional
|
||||
|
||||
import discord
|
||||
from discord import ui
|
||||
from redbot.core import Config
|
||||
from redbot.core.bot import Red
|
||||
|
||||
class ControlPanelView(ui.View):
|
||||
"""View for AutoRoom control panel buttons."""
|
||||
|
||||
def __init__(self, cog: Any):
|
||||
super().__init__(timeout=None)
|
||||
self.cog = cog
|
||||
|
||||
@discord.ui.button(label="🔓 Public", style=discord.ButtonStyle.green, custom_id="autoroom_public")
|
||||
async def public_button(self, interaction: discord.Interaction, button: discord.ui.Button):
|
||||
"""Make the AutoRoom public."""
|
||||
if not interaction.message:
|
||||
return
|
||||
|
||||
# Get the AutoRoom info
|
||||
autoroom_info = await self.cog.get_autoroom_info(interaction.channel)
|
||||
if not autoroom_info:
|
||||
await interaction.response.send_message("This is not an AutoRoom.", ephemeral=True)
|
||||
return
|
||||
|
||||
# Check if the interaction user is the owner
|
||||
if interaction.user.id != autoroom_info["owner"]:
|
||||
await interaction.response.send_message("Only the AutoRoom owner can use these buttons.", ephemeral=True)
|
||||
return
|
||||
|
||||
# Make the AutoRoom public
|
||||
await self.cog._process_allow_deny(interaction, "allow")
|
||||
await interaction.response.send_message("AutoRoom is now public.", ephemeral=True)
|
||||
|
||||
@discord.ui.button(label="🔒 Locked", style=discord.ButtonStyle.grey, custom_id="autoroom_locked")
|
||||
async def locked_button(self, interaction: discord.Interaction, button: discord.ui.Button):
|
||||
"""Make the AutoRoom locked."""
|
||||
if not interaction.message:
|
||||
return
|
||||
|
||||
# Get the AutoRoom info
|
||||
autoroom_info = await self.cog.get_autoroom_info(interaction.channel)
|
||||
if not autoroom_info:
|
||||
await interaction.response.send_message("This is not an AutoRoom.", ephemeral=True)
|
||||
return
|
||||
|
||||
# Check if the interaction user is the owner
|
||||
if interaction.user.id != autoroom_info["owner"]:
|
||||
await interaction.response.send_message("Only the AutoRoom owner can use these buttons.", ephemeral=True)
|
||||
return
|
||||
|
||||
# Make the AutoRoom locked
|
||||
await self.cog._process_allow_deny(interaction, "lock")
|
||||
await interaction.response.send_message("AutoRoom is now locked.", ephemeral=True)
|
||||
|
||||
@discord.ui.button(label="🔐 Private", style=discord.ButtonStyle.red, custom_id="autoroom_private")
|
||||
async def private_button(self, interaction: discord.Interaction, button: discord.ui.Button):
|
||||
"""Make the AutoRoom private."""
|
||||
if not interaction.message:
|
||||
return
|
||||
|
||||
# Get the AutoRoom info
|
||||
autoroom_info = await self.cog.get_autoroom_info(interaction.channel)
|
||||
if not autoroom_info:
|
||||
await interaction.response.send_message("This is not an AutoRoom.", ephemeral=True)
|
||||
return
|
||||
|
||||
# Check if the interaction user is the owner
|
||||
if interaction.user.id != autoroom_info["owner"]:
|
||||
await interaction.response.send_message("Only the AutoRoom owner can use these buttons.", ephemeral=True)
|
||||
return
|
||||
|
||||
# Make the AutoRoom private
|
||||
await self.cog._process_allow_deny(interaction, "deny")
|
||||
await interaction.response.send_message("AutoRoom is now private.", ephemeral=True)
|
||||
|
||||
@discord.ui.button(label="👥 Add User", style=discord.ButtonStyle.blurple, custom_id="autoroom_add_user")
|
||||
async def add_user_button(self, interaction: discord.Interaction, button: discord.ui.Button):
|
||||
"""Add a user to the AutoRoom."""
|
||||
if not interaction.message:
|
||||
return
|
||||
|
||||
# Get the AutoRoom info
|
||||
autoroom_info = await self.cog.get_autoroom_info(interaction.channel)
|
||||
if not autoroom_info:
|
||||
await interaction.response.send_message("This is not an AutoRoom.", ephemeral=True)
|
||||
return
|
||||
|
||||
# Check if the interaction user is the owner
|
||||
if interaction.user.id != autoroom_info["owner"]:
|
||||
await interaction.response.send_message("Only the AutoRoom owner can use these buttons.", ephemeral=True)
|
||||
return
|
||||
|
||||
# Create a modal for user selection
|
||||
modal = UserSelectModal(self.cog, "allow")
|
||||
await interaction.response.send_modal(modal)
|
||||
|
||||
@discord.ui.button(label="🚫 Remove User", style=discord.ButtonStyle.danger, custom_id="autoroom_remove_user")
|
||||
async def remove_user_button(self, interaction: discord.Interaction, button: discord.ui.Button):
|
||||
"""Remove a user from the AutoRoom."""
|
||||
if not interaction.message:
|
||||
return
|
||||
|
||||
# Get the AutoRoom info
|
||||
autoroom_info = await self.cog.get_autoroom_info(interaction.channel)
|
||||
if not autoroom_info:
|
||||
await interaction.response.send_message("This is not an AutoRoom.", ephemeral=True)
|
||||
return
|
||||
|
||||
# Check if the interaction user is the owner
|
||||
if interaction.user.id != autoroom_info["owner"]:
|
||||
await interaction.response.send_message("Only the AutoRoom owner can use these buttons.", ephemeral=True)
|
||||
return
|
||||
|
||||
# Create a modal for user selection
|
||||
modal = UserSelectModal(self.cog, "deny")
|
||||
await interaction.response.send_modal(modal)
|
||||
|
||||
class UserSelectModal(ui.Modal, title="Select User"):
|
||||
"""Modal for selecting a user to add/remove."""
|
||||
|
||||
def __init__(self, cog: Any, action: str):
|
||||
super().__init__()
|
||||
self.cog = cog
|
||||
self.action = action
|
||||
self.user_id = ui.TextInput(
|
||||
label="User ID or @mention",
|
||||
placeholder="Enter user ID or @mention",
|
||||
required=True
|
||||
)
|
||||
self.add_item(self.user_id)
|
||||
|
||||
async def on_submit(self, interaction: discord.Interaction):
|
||||
"""Handle the modal submission."""
|
||||
user_input = self.user_id.value.strip()
|
||||
|
||||
# Try to get user from mention
|
||||
if user_input.startswith("<@") and user_input.endswith(">"):
|
||||
user_id = int(user_input[2:-1])
|
||||
else:
|
||||
try:
|
||||
user_id = int(user_input)
|
||||
except ValueError:
|
||||
await interaction.response.send_message("Invalid user ID or mention.", ephemeral=True)
|
||||
return
|
||||
|
||||
user = interaction.guild.get_member(user_id)
|
||||
if not user:
|
||||
await interaction.response.send_message("User not found in this server.", ephemeral=True)
|
||||
return
|
||||
|
||||
# Process the allow/deny action
|
||||
await self.cog._process_allow_deny(interaction, self.action, member_or_role=user)
|
||||
await interaction.response.send_message(f"User {user.mention} has been {'allowed' if self.action == 'allow' else 'denied'} access.", ephemeral=True)
|
||||
|
||||
class ControlPanel:
|
||||
"""Handles control panel functionality."""
|
||||
|
||||
def __init__(self, cog: Any):
|
||||
self.cog = cog
|
||||
self.bot: Red = cog.bot
|
||||
self.config: Config = cog.config
|
||||
|
||||
async def create_control_panel(self, autoroom: discord.VoiceChannel) -> None:
|
||||
"""Create the control panel embed in the voice channel's text chat."""
|
||||
autoroom_info = await self.cog.get_autoroom_info(autoroom)
|
||||
if not autoroom_info:
|
||||
return
|
||||
|
||||
owner = autoroom.guild.get_member(autoroom_info["owner"])
|
||||
if not owner:
|
||||
return
|
||||
|
||||
# Get the voice channel's text chat
|
||||
text_channel = autoroom.guild.get_channel(autoroom.id)
|
||||
if not text_channel:
|
||||
return
|
||||
|
||||
embed = discord.Embed(
|
||||
title="AutoRoom Control Panel",
|
||||
description=f"Control panel for {autoroom.mention}\nOwner: {owner.mention}",
|
||||
color=discord.Color.blue()
|
||||
)
|
||||
|
||||
# Add current status
|
||||
status = "Public" if autoroom.permissions_for(autoroom.guild.default_role).connect else "Private"
|
||||
embed.add_field(name="Status", value=status, inline=True)
|
||||
|
||||
# Add member count
|
||||
embed.add_field(name="Members", value=str(len(autoroom.members)), inline=True)
|
||||
|
||||
# Create view with buttons
|
||||
view = ControlPanelView(self.cog)
|
||||
|
||||
# Send the embed
|
||||
await text_channel.send(embed=embed, view=view)
|
|
@ -141,8 +141,8 @@ class WaitingRoom:
|
|||
if not autoroom_info:
|
||||
return
|
||||
|
||||
# Get the text channel
|
||||
text_channel = await self.cog.get_autoroom_legacy_text_channel(autoroom)
|
||||
# Get the voice channel's text chat
|
||||
text_channel = autoroom.guild.get_channel(autoroom.id)
|
||||
if not text_channel:
|
||||
return
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue