readapte esse codigo python de comandos do discordpy para usar menus interativos, modais e até botões, em um unico menu organizado com paginas e adaptado em um unico comando(/settings):

import discord
from discord import app_commands
from discord.ui import Modal, TextInput, Select, View
from model_selector import get_models, ModelSelector
from discord import Interaction

def is_admin(user):
return user.guild_permissions.administrator

def admin_only():
async def predicate(interaction: discord.Interaction):
if not is_admin(interaction.user):
await interaction.response.send_message("Only administrators can use this command.", ephemeral=True)
return False
return True
return app_commands.check(predicate)

def setup_config_commands(tree, get_guild_config, save_guild_configs, get_guild_history, save_guild_histories):
class SystemInstructionModal(Modal, title="Set Instructions for the Model"):
instruction = TextInput(
label="System Instruction",
style=discord.TextStyle.paragraph,
placeholder="Enter the system instruction here...",
max_length=4000,
required=True
)

def init(self, current_instruction):
super().init()
self.instruction.default = current_instruction

async def on_submit(self, interaction: discord.Interaction):
config = get_guild_config(str(interaction.guild_id))
config["system_instruction"] = self.instruction.value
await save_guild_configs()
await interaction.response.send_message("System instruction updated successfully!", ephemeral=True)

@tree.command(name="system_instruction", description="Set the system instruction for the model")
@admin_only()
async def set_system_instruction(interaction: discord.Interaction):
config = get_guild_config(str(interaction.guild_id))
current_instruction = config.get("system_instruction", "")
modal = SystemInstructionModal(current_instruction)
await interaction.response.send_modal(modal)

class ConfigModal(Modal, title="Configure Bot Settings"):
temperature = TextInput(label="Temperature (0-2)", default="0.8", required=True)
top_p = TextInput(label="Top P (0-1)", default="0.95", required=True)
top_k = TextInput(label="Top K (0-100)", default="64", required=True)
max_tokens = TextInput(label="Max Output Tokens (0-2048)", default="1024", required=True)
max_history = TextInput(label="Max History (0-10000)", default="10000", required=True)

def init(self, config):
super().init()
self.temperature.default = str(config.get("temperature", 0.8))
self.top_p.default = str(config.get("top_p", 0.95))
self.top_k.default = str(config.get("top_k", 64))
self.max_tokens.default = str(config.get("max_output_tokens", 500))
self.max_history.default = str(config.get("max_history", 10000))

async def on_submit(self, interaction: discord.Interaction):
config = get_guild_config(str(interaction.guild_id))
errors = []

try:
temp = float(self.temperature.value)
if not 0 <= temp <= 2:
errors.append("Temperature must be between 0 and 2")
else:
config["temperature"] = temp
except ValueError:
errors.append("Temperature must be a number")

try:
top_p = float(self.top_p.value)
if not 0 <= top_p <= 1:
errors.append("Top P must be between 0 and 1")
else:
config["top_p"] = top_p
except ValueError:
errors.append("Top P must be a number")

try:
top_k = int(self.top_k.value)
if not 0 <= top_k <= 100:
errors.append("Top K must be between 0 and 100")
else:
config["top_k"] = top_k
except ValueError:
errors.append("Top K must be an integer")

try:
max_tokens = int(self.max_tokens.value)
if not 0 <= max_tokens <= 4096:
errors.append("Max Output Tokens must be between 0 and 2048")
else:
config["max_output_tokens"] = max_tokens
except ValueError:
errors.append("Max Output Tokens must be an integer")

try:
max_history = int(self.max_history.value)
if not 0 <= max_history <= 10000:
errors.append("Max History must be between 0 and 10000")
else:
config["max_history"] = max_history
except ValueError:
errors.append("Max History must be an integer")

if errors:
error_message = "\n".join(errors)
await interaction.response.send_message(f"Error: {error_message}", ephemeral=True)
else:
await save_guild_configs()
await interaction.response.send_message("Configuration updated successfully!", ephemeral=True)

@tree.command(name="settings", description="Configure LLM settings")
@admin_only()
async def configure(interaction: discord.Interaction):
config = get_guild_config(str(interaction.guild_id))
modal = ConfigModal(config)
await interaction.response.send_modal(modal)

@tree.command(name="filter_safety", description="Set the safety settings for the model")
@admin_only()
@app_commands.describe(
category="Safety category to configure",
level="Safety level to set"
)
@app_commands.choices(
category=[
app_commands.Choice(name="Sexually Explicit", value="HARM_CATEGORY_SEXUALLY_EXPLICIT"),
app_commands.Choice(name="Hate Speech", value="HARM_CATEGORY_HATE_SPEECH"),
app_commands.Choice(name="Harassment", value="HARM_CATEGORY_HARASSMENT"),
app_commands.Choice(name="Dangerous Content", value="HARM_CATEGORY_DANGEROUS_CONTENT")
],
level=[
app_commands.Choice(name="No Filter", value="BLOCK_NONE"),
app_commands.Choice(name="Low Detection", value="BLOCK_ONLY_HIGH"),
app_commands.Choice(name="Normal Detection", value="BLOCK_MEDIUM_AND_ABOVE"),
app_commands.Choice(name="High Detection", value="BLOCK_LOW_AND_ABOVE")
]
)
async def set_safety(interaction: discord.Interaction, category: app_commands.Choice[str], level: app_commands.Choice[str]):
config = get_guild_config(str(interaction.guild_id))
config["safety_settings"][category.value] = level.value
await save_guild_configs()
await interaction.response.send_message(f"Safety setting for {category.name} set to {level.name}", ephemeral=True)

class ChannelSelectMenu(Select):
def init(self, channels, action):
options = [
discord.SelectOption(label=channel.name, value=str(channel.id)) for channel in channels
]
super().init(placeholder="Select a channel...", min_values=1, max_values=1, options=options)
self.action = action

async def callback(self, interaction: Interaction):
selected_channel_id = int(self.values[0])
config = get_guild_config(str(interaction.guild_id))

if self.action == "add":
if selected_channel_id not in config["allowed_channels"]:
config["allowed_channels"].append(selected_channel_id)
await save_guild_configs()
await interaction.response.send_message(f"Added <#{selected_channel_id}> to allowed channels", ephemeral=True)
else:
await interaction.response.send_message(f"<#{selected_channel_id}> is already an allowed channel", ephemeral=True)
elif self.action == "remove":
if selected_channel_id in config["allowed_channels"]:
config["allowed_channels"].remove(selected_channel_id)
await save_guild_configs()
await interaction.response.send_message(f"Removed <#{selected_channel_id}> from allowed channels", ephemeral=True)
else:
await interaction.response.send_message(f"<#{selected_channel_id}> is not in the allowed channels list", ephemeral=True)

class ChannelActionView(View):
def init(self, channels, action):
super().init()
self.add_item(ChannelSelectMenu(channels, action))

@tree.command(name="manage_allowed_channel", description="Add or remove allowed channels")
@admin_only()
@app_commands.describe(action="Add or remove a channel")
@app_commands.choices(action=[
app_commands.Choice(name="Add Channel", value="add"),
app_commands.Choice(name="Remove Channel", value="remove")
])
async def manage_allowed_channel(interaction: discord.Interaction, action: app_commands.Choice[str]):
channels = interaction.guild.text_channels
view = ChannelActionView(channels, action.value)
await interaction.response.send_message(f"Select a channel to {action.name.lower()}: ", view=view, ephemeral=True)

@tree.command(name="toggle_mentions", description="Toggle whether the bot requires a mention to respond")
@admin_only()
async def toggle_mention_requirement(interaction: discord.Interaction):
config = get_guild_config(str(interaction.guild_id))
config["require_mention"] = not config["require_mention"]
await save_guild_configs()
status = "required" if config["require_mention"] else "not required"
await interaction.response.send_message(f"Mention is now {status} for the bot to respond", ephemeral=True)

@tree.command(name="show_settings", description="Display current bot setings for this guild")
@admin_only()
async def show_guild_config(interaction: discord.Interaction):
guild_id = str(interaction.guild_id)
config = get_guild_config(guild_id)

embed = discord.Embed(title=f"Guild Settings for {interaction.guild.name}", color=0x00ff00)

{config.get('selected_model', 'gemini-1.5-pro')}", inline=False)">
{config.get('require_mention', False)}", inline=False)">
{config.get('temperature', 1)}", inline=True)">
{config.get('top_p', 0.95)}", inline=True)">
{config.get('top_k', 64)}", inline=True)">
{config.get('max_output_tokens', 500)}", inline=True)">
{config.get('max_history', 10000)}", inline=True)">
allowed_channels = config.get("allowed_channels", [])
channels_str = ", ".join(f"<#{channel_id}>" for channel_id in allowed_channels) or "None"
{channels_str}", inline=False)">

await interaction.response.send_message(embed=embed, ephemeral=True)

@tree.command(name="models", description="Select a Gemini model to use")
@admin_only()
async def select_model(interaction: discord.Interaction):
try:
models = get_models()

if models:
config = get_guild_config(str(interaction.guild_id))
view = ModelSelector(models, config, save_guild_configs)
await interaction.response.send_message(embed=view.get_current_embed(), view=view, ephemeral=True)
else:
await interaction.response.send_message("No models found.", ephemeral=True)

except Exception as e:
await interaction.response.send_message(f"Error while retrieving models: {str(e)}", ephemeral=True)