Add new file

This commit is contained in:
ザカリアス・ウィリアム・ポージー 2025-05-09 23:07:04 +09:00
parent 1ae2f1b66d
commit 34295577a4

161
cogs/serverconfig.py Normal file
View File

@ -0,0 +1,161 @@
import discord
from discord.ext import commands
from discord import app_commands
import os
import json
# Path to the JSON config file
CONFIG_FILE = "/home/server/serverconfig.json"
def load_config() -> dict:
"""Load the server configuration from file.
If the file does not exist or is invalid, create a new empty configuration."""
if not os.path.exists(CONFIG_FILE):
with open(CONFIG_FILE, "w") as f:
json.dump({}, f)
return {}
try:
with open(CONFIG_FILE, "r") as f:
return json.load(f)
except json.JSONDecodeError:
return {}
def save_config(data: dict) -> None:
"""Save the configuration JSON to file."""
with open(CONFIG_FILE, "w") as f:
json.dump(data, f, indent=4)
async def global_disabled_check(interaction: discord.Interaction) -> bool:
"""
Global check for all app (slash) commands.
If the command (except for serverconfig itself) is marked as disabled in this servers config,
send an ephemeral message and prevent execution.
"""
# If interaction comes from a DM, allow it.
if interaction.guild is None:
return True
# Always allow the serverconfig command so admins can change settings.
if interaction.command and interaction.command.name == "serverconfig":
return True
config = load_config()
guild_id = str(interaction.guild.id)
disabled_commands = config.get(guild_id, [])
if interaction.command and interaction.command.name in disabled_commands:
if not interaction.response.is_done():
await interaction.response.send_message(
"This command has been disabled by server admins.", ephemeral=True
)
# Raising a CheckFailure prevents the command from running.
raise app_commands.CheckFailure("Command disabled.")
return True
class ServerConfigCog(commands.Cog):
def __init__(self, bot: commands.Bot):
self.bot = bot
@app_commands.command(
name="serverconfig",
description="Enable or disable a command in this server."
)
@app_commands.describe(
command="The name of the command to configure",
enabled="Type 'yes' to enable or 'no' to disable."
)
async def serverconfig(
self,
interaction: discord.Interaction,
command: str,
enabled: str
):
# Check if the user has admin permissions.
if not interaction.user.guild_permissions.administrator:
await interaction.response.send_message(
"You do not have permission to use this command.",
ephemeral=True
)
return
# Normalize the enabled flag.
enabled_flag = enabled.lower()
if enabled_flag not in ["yes", "no"]:
await interaction.response.send_message(
"Invalid 'enabled' option. Please use 'yes' or 'no'.",
ephemeral=True
)
return
# Verify that the provided command exists.
found = False
# Check the classic text commands.
for cmd in self.bot.commands:
if cmd.name == command:
found = True
break
# Also check application (slash) commands from the tree.
if not found:
for cmd in self.bot.tree.get_commands():
if cmd.name == command:
found = True
break
if not found:
await interaction.response.send_message(
f"The command '{command}' was not found.",
ephemeral=True
)
return
# Load the configuration.
config = load_config()
guild_id = str(interaction.guild.id)
if guild_id not in config:
config[guild_id] = []
if enabled_flag == "no":
# Add the command to the disabled list if not already present.
if command not in config[guild_id]:
config[guild_id].append(command)
save_config(config)
await interaction.response.send_message(
f"Command '{command}' has been **disabled** in this server.",
ephemeral=True
)
else: # enabled_flag == "yes"
# Remove the command from the disabled list if present.
if command in config[guild_id]:
config[guild_id].remove(command)
save_config(config)
await interaction.response.send_message(
f"Command '{command}' has been **enabled** in this server.",
ephemeral=True
)
@serverconfig.autocomplete("command")
async def command_autocomplete(
self, interaction: discord.Interaction, current: str
) -> list[app_commands.Choice[str]]:
"""
Autocomplete for the 'command' parameter.
It searches both classic and slash commands for matches.
"""
choices = set()
# Get names of text commands.
for cmd in self.bot.commands:
choices.add(cmd.name)
# Get names of app commands.
for cmd in self.bot.tree.get_commands():
choices.add(cmd.name)
# Filter and send at most 25 matching choices.
filtered = [
app_commands.Choice(name=cmd, value=cmd)
for cmd in choices
if current.lower() in cmd.lower()
]
return filtered[:25]
async def setup(bot: commands.Bot):
# Register the global check it will run for every application (slash) command.
bot.tree.add_check(global_disabled_check)
await bot.add_cog(ServerConfigCog(bot))