import discord from redbot.core import commands, Config, app_commands from typing import Optional import datetime # --- Modal for the Review Form --- class ReviewModal(discord.ui.Modal, title="Service Review"): service_type = discord.ui.TextInput( label="Service Type", placeholder="e.g., HPM, Staff, PM, Commission, etc." ) rating = discord.ui.TextInput( label="Rating (1-10)", placeholder="Please enter a number from 1 to 10.", max_length=2 ) review_text = discord.ui.TextInput( label="Your Review", style=discord.TextStyle.paragraph, placeholder="Please provide details about your experience.", max_length=1500 ) toxicity = discord.ui.TextInput( label="Toxicity Level (ntox/stox)", placeholder="ntox (non-toxic) or stox (semi-toxic)" ) def __init__(self, cog: "ServiceReview"): super().__init__() self.cog = cog async def on_submit(self, interaction: discord.Interaction): guild = interaction.guild if not guild: # This should not happen due to guild_only decorator return channel_id = await self.cog.config.guild(guild).review_channel() if not channel_id: await interaction.response.send_message( "The review channel has not been configured by an administrator.", ephemeral=True ) return channel = guild.get_channel(channel_id) if not isinstance(channel, discord.TextChannel): await interaction.response.send_message( "The configured review channel is invalid. Please contact an administrator.", ephemeral=True ) return embed = discord.Embed(title="New Service Review", color=discord.Color.purple()) embed.set_author(name=f"{interaction.user.name} ({interaction.user.id})", icon_url=interaction.user.display_avatar.url) embed.add_field(name="Service Type", value=self.service_type.value, inline=False) embed.add_field(name="Rating", value=f"{self.rating.value}/10", inline=True) embed.add_field(name="Toxicity", value=self.toxicity.value, inline=True) embed.add_field(name="Review", value=self.review_text.value, inline=False) embed.set_footer(text=f"User ID: {interaction.user.id}") try: review_message = await channel.send(embed=embed) # **FIX:** Log the timestamp for the DataManager async with self.cog.config.guild(guild).submitted_reviews() as reviews: reviews[str(review_message.id)] = datetime.datetime.now(datetime.timezone.utc).isoformat() await interaction.response.send_message("Thank you! Your review has been submitted successfully.", ephemeral=True) except discord.Forbidden: await interaction.response.send_message( "I don't have permission to send messages in the review channel. Please contact an administrator.", ephemeral=True ) except discord.HTTPException as e: await interaction.response.send_message(f"An error occurred while trying to send your review: {e}", ephemeral=True) # --- Main Cog Class --- class ServiceReview(commands.Cog): """A cog for users to leave service reviews for staff.""" def __init__(self, bot): self.bot = bot self.config = Config.get_conf(self, identifier=1234567891, force_registration=True) default_guild = { "review_channel": None, "submitted_reviews": {} # **FIX:** Added for DataManager logging } self.config.register_guild(**default_guild) @app_commands.command(name="srev") @app_commands.guild_only() async def service_review(self, interaction: discord.Interaction): """Leave a review for a staff member or service.""" modal = ReviewModal(self) await interaction.response.send_modal(modal) @commands.group(aliases=["srset"]) # type: ignore @commands.guild_only() @commands.admin_or_permissions(manage_guild=True) async def srevset(self, ctx: commands.Context): """Configure ServiceReview settings.""" pass @srevset.command(name="channel") async def set_review_channel(self, ctx: commands.Context, channel: discord.TextChannel): """Set the channel where service reviews will be sent.""" if not ctx.guild: return await self.config.guild(ctx.guild).review_channel.set(channel.id) await ctx.send(f"Service review channel has been set to {channel.mention}") async def setup(bot): await bot.add_cog(ServiceReview(bot))