Files
disbord/services/interaction/feedback_modals.py
Travis Vasceannie 3acb779569 chore: remove .env.example and add new files for project structure
- Deleted .env.example file as it is no longer needed.
- Added .gitignore to manage ignored files and directories.
- Introduced CLAUDE.md for AI provider integration documentation.
- Created dev.sh for development setup and scripts.
- Updated Dockerfile and Dockerfile.production for improved build processes.
- Added multiple test files and directories for comprehensive testing.
- Introduced new utility and service files for enhanced functionality.
- Organized codebase with new directories and files for better maintainability.
2025-08-27 23:00:19 -04:00

331 lines
12 KiB
Python

"""
Feedback Modal Components for Discord Voice Chat Quote Bot
Provides interactive modal dialogs for collecting different types of feedback
from users to improve the quote analysis system.
"""
import logging
from typing import Optional
import discord
from .feedback_system import FeedbackSystem, FeedbackType
logger = logging.getLogger(__name__)
class FeedbackRatingModal(discord.ui.Modal):
"""Modal for collecting rating and general feedback"""
def __init__(self, feedback_system: FeedbackSystem, quote_id: Optional[int] = None):
super().__init__(title="Rate the Analysis")
self.feedback_system = feedback_system
self.quote_id = quote_id
# Rating input
self.rating_input = discord.ui.TextInput(
label="Rating (1-5 stars)",
placeholder="Rate the analysis quality from 1 (poor) to 5 (excellent)",
min_length=1,
max_length=1,
)
self.add_item(self.rating_input)
# Feedback text
self.feedback_input = discord.ui.TextInput(
label="Feedback (Optional)",
placeholder="Tell us what you liked or what could be improved...",
style=discord.TextStyle.paragraph,
min_length=0,
max_length=1000,
required=False,
)
self.add_item(self.feedback_input)
async def on_submit(self, interaction: discord.Interaction):
"""Handle modal submission"""
try:
# Validate rating
try:
rating = int(self.rating_input.value.strip())
if not 1 <= rating <= 5:
raise ValueError()
except ValueError:
await interaction.response.send_message(
"❌ Please enter a valid rating between 1 and 5.", ephemeral=True
)
return
# Get feedback text
feedback_text = (
self.feedback_input.value.strip()
or f"User rated the analysis {rating}/5 stars"
)
# Collect feedback
feedback_id = await self.feedback_system.collect_feedback(
user_id=interaction.user.id,
guild_id=interaction.guild_id,
feedback_type=FeedbackType.OVERALL,
text_feedback=feedback_text,
rating=rating,
quote_id=self.quote_id,
)
if feedback_id:
# Create success embed
embed = discord.Embed(
title="✅ Feedback Submitted",
description=f"Thank you for rating the analysis **{rating}/5 stars**!",
color=0x2ECC71,
)
embed.add_field(
name="Your Impact",
value="Your feedback helps improve the AI's analysis accuracy for everyone.",
inline=False,
)
await interaction.response.send_message(embed=embed, ephemeral=True)
else:
await interaction.response.send_message(
"❌ Failed to submit feedback. You may have reached the daily limit.",
ephemeral=True,
)
except Exception as e:
logger.error(f"Error in feedback rating modal: {e}")
await interaction.response.send_message(
"❌ An error occurred while submitting your feedback.", ephemeral=True
)
class CategoryFeedbackModal(discord.ui.Modal):
"""Modal for collecting category-specific feedback"""
def __init__(self, feedback_system: FeedbackSystem, quote_id: Optional[int] = None):
super().__init__(title="Category Feedback")
self.feedback_system = feedback_system
self.quote_id = quote_id
# Category selection
self.category_input = discord.ui.TextInput(
label="Category (funny, dark, silly, suspicious, asinine)",
placeholder="Which category would you like to provide feedback on?",
min_length=3,
max_length=20,
)
self.add_item(self.category_input)
# Suggested score
self.score_input = discord.ui.TextInput(
label="Suggested Score (0-10)",
placeholder="What score do you think this category should have?",
min_length=1,
max_length=4,
)
self.add_item(self.score_input)
# Reasoning
self.reasoning_input = discord.ui.TextInput(
label="Reasoning",
placeholder="Why do you think this score is more accurate?",
style=discord.TextStyle.paragraph,
min_length=10,
max_length=500,
)
self.add_item(self.reasoning_input)
async def on_submit(self, interaction: discord.Interaction):
"""Handle modal submission"""
try:
# Validate category
category = self.category_input.value.strip().lower()
valid_categories = ["funny", "dark", "silly", "suspicious", "asinine"]
if category not in valid_categories:
await interaction.response.send_message(
f"❌ Invalid category. Please use one of: {', '.join(valid_categories)}",
ephemeral=True,
)
return
# Validate score
try:
score = float(self.score_input.value.strip())
if not 0 <= score <= 10:
raise ValueError()
except ValueError:
await interaction.response.send_message(
"❌ Please enter a valid score between 0 and 10.", ephemeral=True
)
return
# Get reasoning
reasoning = self.reasoning_input.value.strip()
# Create feedback text
feedback_text = f"Category feedback for '{category}': Suggested score {score}/10. Reasoning: {reasoning}"
# Create categories feedback
categories_feedback = {category: score}
# Collect feedback
feedback_id = await self.feedback_system.collect_feedback(
user_id=interaction.user.id,
guild_id=interaction.guild_id,
feedback_type=FeedbackType.CATEGORY,
text_feedback=feedback_text,
quote_id=self.quote_id,
categories_feedback=categories_feedback,
)
if feedback_id:
embed = discord.Embed(
title="✅ Category Feedback Submitted",
description=f"Thank you for the feedback on **{category}** category!",
color=0x2ECC71,
)
embed.add_field(
name="Your Suggestion",
value=f"**Category:** {category.title()}\n**Suggested Score:** {score}/10\n**Reasoning:** {reasoning[:100]}{'...' if len(reasoning) > 100 else ''}",
inline=False,
)
await interaction.response.send_message(embed=embed, ephemeral=True)
else:
await interaction.response.send_message(
"❌ Failed to submit feedback. You may have reached the daily limit.",
ephemeral=True,
)
except Exception as e:
logger.error(f"Error in category feedback modal: {e}")
await interaction.response.send_message(
"❌ An error occurred while submitting your feedback.", ephemeral=True
)
class GeneralFeedbackModal(discord.ui.Modal):
"""Modal for collecting general feedback and suggestions"""
def __init__(self, feedback_system: FeedbackSystem, quote_id: Optional[int] = None):
super().__init__(title="General Feedback")
self.feedback_system = feedback_system
self.quote_id = quote_id
# Feedback type selection
self.type_input = discord.ui.TextInput(
label="Feedback Type (accuracy, relevance, suggestion)",
placeholder="What type of feedback are you providing?",
min_length=3,
max_length=20,
)
self.add_item(self.type_input)
# Main feedback
self.feedback_input = discord.ui.TextInput(
label="Your Feedback",
placeholder="Share your thoughts, suggestions, or report issues...",
style=discord.TextStyle.paragraph,
min_length=10,
max_length=1000,
)
self.add_item(self.feedback_input)
# Optional improvement suggestion
self.suggestion_input = discord.ui.TextInput(
label="Improvement Suggestion (Optional)",
placeholder="How could we make this better?",
style=discord.TextStyle.paragraph,
min_length=0,
max_length=500,
required=False,
)
self.add_item(self.suggestion_input)
async def on_submit(self, interaction: discord.Interaction):
"""Handle modal submission"""
try:
# Validate feedback type
feedback_type_str = self.type_input.value.strip().lower()
# Map string to enum
feedback_type_map = {
"accuracy": FeedbackType.ACCURACY,
"relevance": FeedbackType.RELEVANCE,
"suggestion": FeedbackType.SUGGESTION,
"overall": FeedbackType.OVERALL,
}
feedback_type = feedback_type_map.get(feedback_type_str)
if not feedback_type:
valid_types = list(feedback_type_map.keys())
await interaction.response.send_message(
f"❌ Invalid feedback type. Please use one of: {', '.join(valid_types)}",
ephemeral=True,
)
return
# Get feedback text
main_feedback = self.feedback_input.value.strip()
suggestion = self.suggestion_input.value.strip()
# Combine feedback
feedback_text = main_feedback
if suggestion:
feedback_text += f" | Improvement suggestion: {suggestion}"
# Collect feedback
feedback_id = await self.feedback_system.collect_feedback(
user_id=interaction.user.id,
guild_id=interaction.guild_id,
feedback_type=feedback_type,
text_feedback=feedback_text,
quote_id=self.quote_id,
)
if feedback_id:
embed = discord.Embed(
title="✅ Feedback Submitted",
description=f"Thank you for your **{feedback_type_str}** feedback!",
color=0x2ECC71,
)
embed.add_field(
name="Your Feedback",
value=main_feedback[:200]
+ ("..." if len(main_feedback) > 200 else ""),
inline=False,
)
if suggestion:
embed.add_field(
name="Your Suggestion",
value=suggestion[:200]
+ ("..." if len(suggestion) > 200 else ""),
inline=False,
)
embed.add_field(
name="Next Steps",
value="Our team will review your feedback and use it to improve the system.",
inline=False,
)
await interaction.response.send_message(embed=embed, ephemeral=True)
else:
await interaction.response.send_message(
"❌ Failed to submit feedback. You may have reached the daily limit.",
ephemeral=True,
)
except Exception as e:
logger.error(f"Error in general feedback modal: {e}")
await interaction.response.send_message(
"❌ An error occurred while submitting your feedback.", ephemeral=True
)
# Background processing functions have been moved to feedback_system.py
# to avoid circular dependencies and improve code organization