Refactor RubyAPI cog to support global configuration. Update commands to manage API key, interaction URL, and verification URL globally instead of per guild. Implement cog-wide checks to restrict command usage to bot team members only, enhancing security and usability.
Some checks are pending
Run pre-commit / Run pre-commit (push) Waiting to run

This commit is contained in:
Valerie 2025-05-25 04:29:13 -04:00
parent 5a5814bed2
commit 0b8483511b

View file

@ -1,7 +1,7 @@
from typing import Optional
import aiohttp
import discord
from redbot.core import commands, Config
from redbot.core import commands, Config, checks
from redbot.core.bot import Red
from redbot.core.utils.chat_formatting import box
@ -14,37 +14,40 @@ class RubyAPI(commands.Cog):
self.config = Config.get_conf(self, identifier=867530999, force_registration=True)
self.session = aiohttp.ClientSession()
default_guild = {
"interaction_url": "https://ruby.valerie.lol/api/interactions",
"verify_url": "https://ruby.valerie.lol/verify-user",
"enabled": False,
default_global = {
"interaction_url": "https://ruby.valerie.lol/api/verify-user", # Default interaction URL
"verify_url": "https://ruby.valerie.lol/api/verify-user", # Default verify URL
"enabled": True, # Enabled by default
"api_key": None
}
self.config.register_guild(**default_guild)
self.config.register_global(**default_global)
def cog_unload(self):
if self.session:
self.bot.loop.create_task(self.session.close())
async def cog_check(self, ctx: commands.Context) -> bool:
"""Cog-wide check to ensure only bot team members can use commands."""
return await self.bot.is_owner(ctx.author) or await self.bot.is_co_owner(ctx.author)
@commands.group(name="rubyapi")
@commands.admin_or_permissions(manage_guild=True)
async def rubyapi(self, ctx: commands.Context):
"""Ruby API configuration commands."""
"""Ruby API configuration commands. Bot team only."""
pass
@rubyapi.command(name="enable")
async def enable_integration(self, ctx: commands.Context, toggle: bool):
"""Enable or disable Ruby API integration."""
await self.config.guild(ctx.guild).enabled.set(toggle)
"""Enable or disable Ruby API integration globally."""
await self.config.enabled.set(toggle)
status = "enabled" if toggle else "disabled"
await ctx.send(f"Ruby API integration has been {status}.")
await ctx.send(f"Ruby API integration has been {status} globally.")
@rubyapi.command(name="setkey")
async def set_api_key(self, ctx: commands.Context, api_key: str):
"""Set the API key for authentication."""
await self.config.guild(ctx.guild).api_key.set(api_key)
await ctx.send("API key has been set. I'll delete your message for security.")
await self.config.api_key.set(api_key)
await ctx.send("API key has been set globally. I'll delete your message for security.")
try:
await ctx.message.delete()
except discord.HTTPException:
@ -56,8 +59,8 @@ class RubyAPI(commands.Cog):
if not url.startswith(("http://", "https://")):
return await ctx.send("Please provide a valid URL starting with http:// or https://")
await self.config.guild(ctx.guild).interaction_url.set(url)
await ctx.send("Interaction endpoint URL has been updated.")
await self.config.interaction_url.set(url)
await ctx.send("Interaction endpoint URL has been updated globally.")
@rubyapi.command(name="setverify")
async def set_verify_url(self, ctx: commands.Context, url: str):
@ -65,21 +68,21 @@ class RubyAPI(commands.Cog):
if not url.startswith(("http://", "https://")):
return await ctx.send("Please provide a valid URL starting with http:// or https://")
await self.config.guild(ctx.guild).verify_url.set(url)
await ctx.send("Verification endpoint URL has been updated.")
await self.config.verify_url.set(url)
await ctx.send("Verification endpoint URL has been updated globally.")
@rubyapi.command(name="settings")
async def show_settings(self, ctx: commands.Context):
"""Show current Ruby API settings."""
guild_config = await self.config.guild(ctx.guild).all()
config = await self.config.all()
enabled = "Yes" if guild_config["enabled"] else "No"
interaction_url = guild_config["interaction_url"]
verify_url = guild_config["verify_url"]
has_api_key = "Yes" if guild_config["api_key"] else "No"
enabled = "Yes" if config["enabled"] else "No"
interaction_url = config["interaction_url"]
verify_url = config["verify_url"]
has_api_key = "Yes" if config["api_key"] else "No"
message = (
"Ruby API Settings:\n"
"Ruby API Global Settings:\n"
f"Enabled: {enabled}\n"
f"API Key Set: {has_api_key}\n"
f"Interaction URL: {interaction_url}\n"
@ -91,7 +94,7 @@ class RubyAPI(commands.Cog):
async def _make_api_request(self, url: str, method: str = "GET", **kwargs):
"""Make an API request with proper headers and error handling."""
headers = kwargs.pop("headers", {})
if api_key := kwargs.pop("api_key", None):
if api_key := await self.config.api_key():
headers["Authorization"] = f"Bearer {api_key}"
try:
@ -107,13 +110,13 @@ class RubyAPI(commands.Cog):
@commands.command()
async def verifyuser(self, ctx: commands.Context, user: Optional[discord.Member] = None):
"""Verify a user's linked roles."""
if not await self.config.guild(ctx.guild).enabled():
return await ctx.send("Ruby API integration is not enabled in this server.")
"""Verify a user's linked roles. Bot team only."""
if not await self.config.enabled():
return await ctx.send("Ruby API integration is not enabled globally.")
user = user or ctx.author
verify_url = await self.config.guild(ctx.guild).verify_url()
api_key = await self.config.guild(ctx.guild).api_key()
verify_url = await self.config.verify_url()
api_key = await self.config.api_key()
if not api_key:
return await ctx.send("API key has not been set. Please set it using `[p]rubyapi setkey`")
@ -127,8 +130,7 @@ class RubyAPI(commands.Cog):
result = await self._make_api_request(
verify_url,
method="POST",
json=payload,
api_key=api_key
json=payload
)
if "error" in result:
@ -155,17 +157,10 @@ class RubyAPI(commands.Cog):
@commands.Cog.listener()
async def on_interaction(self, interaction: discord.Interaction):
"""Handle incoming Discord interactions."""
if not interaction.guild:
return
if not await self.config.guild(interaction.guild).enabled():
if not await self.config.enabled():
return
interaction_url = await self.config.guild(interaction.guild).interaction_url()
api_key = await self.config.guild(interaction.guild).api_key()
if not api_key:
return # Silent return if API key is not set
interaction_url = await self.config.interaction_url()
# Forward the interaction to the API
payload = {
@ -186,8 +181,7 @@ class RubyAPI(commands.Cog):
result = await self._make_api_request(
interaction_url,
method="POST",
json=payload,
api_key=api_key
json=payload
)
# Handle the API response if needed