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