import discord from discord.ext import commands, tasks from discord import app_commands import typing # Need this for Optional import logging from .gelbooru_watcher_base_cog import GelbooruWatcherBaseCog # Setup logger for this cog log = logging.getLogger(__name__) class SafebooruCog(GelbooruWatcherBaseCog): # Removed name="Safebooru" # Define the command group specific to this cog safebooruwatch = app_commands.Group( name="safebooruwatch", description="Manage Safebooru tag watchers for new posts.", ) def __init__(self, bot: commands.Bot): super().__init__( bot=bot, cog_name="Safebooru", api_base_url="https://safebooru.org/index.php", # Corrected base URL default_tags="hatsune_miku 1girl", # Example default is_nsfw_site=False, # Safebooru is generally SFW command_group_name="safebooruwatch", main_command_name="safebooru", post_url_template="https://safebooru.org/index.php?page=post&s=view&id={}", ) # --- Prefix Command --- @commands.command(name="safebooru") async def safebooru_prefix( self, ctx: commands.Context, *, tags: typing.Optional[str] = None ): """Search for images on Safebooru with the provided tags.""" actual_tags = tags or self.default_tags loading_msg = await ctx.reply( f"Fetching data from {self.cog_name}, please wait..." ) response = await self._fetch_posts_logic( "prefix_internal", actual_tags, hidden=False ) if isinstance(response, tuple): content, all_results = response view = self.GelbooruButtons(self, actual_tags, all_results, hidden=False) await loading_msg.edit(content=content, view=view) elif isinstance(response, str): # Error await loading_msg.edit(content=response, view=None) # --- Slash Command --- @app_commands.command( name="safebooru", description="Get random image from Safebooru with specified tags", ) @app_commands.describe( tags="The tags to search for (e.g., '1girl cat_ears')", hidden="Set to True to make the response visible only to you (default: False)", ) async def safebooru_slash( self, interaction: discord.Interaction, tags: typing.Optional[str] = None, hidden: bool = False, ): """Slash command version of safebooru.""" actual_tags = tags or self.default_tags await self._slash_command_logic(interaction, actual_tags, hidden) # --- New Browse Command --- @app_commands.command( name="safeboorubrowse", description="Browse Safebooru results with navigation buttons", ) @app_commands.describe( tags="The tags to search for (e.g., '1girl dog_ears')", hidden="Set to True to make the response visible only to you (default: False)", ) async def safebooru_browse_slash( self, interaction: discord.Interaction, tags: typing.Optional[str] = None, hidden: bool = False, ): """Browse Safebooru results with navigation buttons.""" actual_tags = tags or self.default_tags await self._browse_slash_command_logic(interaction, actual_tags, hidden) # --- safebooruwatch slash command group --- @safebooruwatch.command( name="add", description="Watch for new Safebooru posts with specific tags in a channel or thread.", ) @app_commands.describe( tags="The tags to search for (e.g., '1girl cat_ears').", channel="The parent channel for the subscription. Must be a Forum Channel if using forum mode.", thread_target="Optional: Name or ID of a thread within the channel (for TextChannels only).", post_title="Optional: Title for a new forum post if 'channel' is a Forum Channel.", ) @app_commands.checks.has_permissions(manage_guild=True) async def safebooruwatch_add( self, interaction: discord.Interaction, tags: str, channel: typing.Union[discord.TextChannel, discord.ForumChannel], thread_target: typing.Optional[str] = None, post_title: typing.Optional[str] = None, ): await interaction.response.defer(ephemeral=True) await self._watch_add_logic( interaction, tags, channel, thread_target, post_title ) @safebooruwatch.command( name="request", description="Request a new Safebooru tag watch (requires moderator approval).", ) @app_commands.describe( tags="The tags you want to watch.", forum_channel="The Forum Channel where a new post for this watch should be created.", post_title="Optional: A title for the new forum post (defaults to tags).", ) async def safebooruwatch_request( self, interaction: discord.Interaction, tags: str, forum_channel: discord.ForumChannel, post_title: typing.Optional[str] = None, ): await interaction.response.defer(ephemeral=True) await self._watch_request_logic(interaction, tags, forum_channel, post_title) @safebooruwatch.command( name="pending_list", description="Lists all pending Safebooru watch requests." ) @app_commands.checks.has_permissions(manage_guild=True) async def safebooruwatch_pending_list(self, interaction: discord.Interaction): await self._watch_pending_list_logic(interaction) @safebooruwatch.command( name="approve_request", description="Approves a pending Safebooru watch request.", ) @app_commands.describe(request_id="The ID of the request to approve.") @app_commands.checks.has_permissions(manage_guild=True) async def safebooruwatch_approve_request( self, interaction: discord.Interaction, request_id: str ): await interaction.response.defer(ephemeral=True) await self._watch_approve_request_logic(interaction, request_id) @safebooruwatch.command( name="reject_request", description="Rejects a pending Safebooru watch request." ) @app_commands.describe( request_id="The ID of the request to reject.", reason="Optional reason for rejection.", ) @app_commands.checks.has_permissions(manage_guild=True) async def safebooruwatch_reject_request( self, interaction: discord.Interaction, request_id: str, reason: typing.Optional[str] = None, ): await interaction.response.defer(ephemeral=True) await self._watch_reject_request_logic(interaction, request_id, reason) @safebooruwatch.command( name="list", description="List active Safebooru tag watches for this server." ) @app_commands.checks.has_permissions(manage_guild=True) async def safebooruwatch_list(self, interaction: discord.Interaction): await self._watch_list_logic(interaction) @safebooruwatch.command( name="remove", description="Stop watching for new Safebooru posts using a subscription ID.", ) @app_commands.describe( subscription_id="The ID of the subscription to remove (get from 'list' command)." ) @app_commands.checks.has_permissions(manage_guild=True) async def safebooruwatch_remove( self, interaction: discord.Interaction, subscription_id: str ): await self._watch_remove_logic(interaction, subscription_id) @safebooruwatch.command( name="send_test", description="Send a test new Safebooru post message using a subscription ID.", ) @app_commands.describe(subscription_id="The ID of the subscription to test.") @app_commands.checks.has_permissions(manage_guild=True) async def safebooruwatch_send_test( self, interaction: discord.Interaction, subscription_id: str ): await self._watch_test_message_logic(interaction, subscription_id) async def setup(bot: commands.Bot): await bot.add_cog(SafebooruCog(bot)) log.info("SafebooruCog (refactored) added to bot.")