Changed Incidents to work with both a TimeFrame and last 50 messages.
This commit is contained in:
		| @@ -8,6 +8,16 @@ from utils.database import Database | |||||||
| db = Database() | db = Database() | ||||||
|  |  | ||||||
|  |  | ||||||
|  | import discord | ||||||
|  | from discord import app_commands | ||||||
|  | from typing import Optional, List | ||||||
|  | from datetime import datetime | ||||||
|  | import logging | ||||||
|  | import uuid | ||||||
|  | from utils.database import Database | ||||||
|  |  | ||||||
|  | db = Database() | ||||||
|  |  | ||||||
| class IncidentModal(discord.ui.Modal): | class IncidentModal(discord.ui.Modal): | ||||||
|     def __init__(self): |     def __init__(self): | ||||||
|         super().__init__(title="Log Incident") |         super().__init__(title="Log Incident") | ||||||
| @@ -17,24 +27,75 @@ class IncidentModal(discord.ui.Modal): | |||||||
|             required=True |             required=True | ||||||
|         ) |         ) | ||||||
|         self.message_count = discord.ui.TextInput( |         self.message_count = discord.ui.TextInput( | ||||||
|             label="Messages to capture (1-50)", |             label="Recent messages to capture (1-50)", | ||||||
|             default="10", |             placeholder="Leave blank to use timeframe", | ||||||
|             required=True |             default="", | ||||||
|  |             required=False | ||||||
|  |         ) | ||||||
|  |         self.start_time = discord.ui.TextInput( | ||||||
|  |             label="Start time (YYYY-MM-DD HH:MM)", | ||||||
|  |             placeholder="Optional - Example: 2024-05-10 14:30", | ||||||
|  |             required=False | ||||||
|  |         ) | ||||||
|  |         self.end_time = discord.ui.TextInput( | ||||||
|  |             label="End time (YYYY-MM-DD HH:MM)", | ||||||
|  |             placeholder="Optional - Example: 2024-05-10 15:00", | ||||||
|  |             required=False | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|         self.add_item(self.reason) |         self.add_item(self.reason) | ||||||
|         self.add_item(self.message_count) |         self.add_item(self.message_count) | ||||||
|  |         self.add_item(self.start_time) | ||||||
|  |         self.add_item(self.end_time) | ||||||
|  |  | ||||||
|     async def on_submit(self, interaction: discord.Interaction): |     async def on_submit(self, interaction: discord.Interaction): | ||||||
|         try: |         try: | ||||||
|  |             messages = [] | ||||||
|  |             capture_mode = "count" | ||||||
|  |             capture_param = "" | ||||||
|  |             start_time = None | ||||||
|  |             end_time = None | ||||||
|  |  | ||||||
|  |             # Determine capture mode | ||||||
|  |             if self.start_time.value or self.end_time.value: | ||||||
|  |                 if not all([self.start_time.value, self.end_time.value]): | ||||||
|  |                     raise ValueError("Both start and end times required for timeframe") | ||||||
|  |  | ||||||
|  |                 start_time = datetime.strptime(self.start_time.value, "%Y-%m-%d %H:%M") | ||||||
|  |                 end_time = datetime.strptime(self.end_time.value, "%Y-%m-%d %H:%M") | ||||||
|  |                  | ||||||
|  |                 if start_time >= end_time: | ||||||
|  |                     raise ValueError("End time must be after start time") | ||||||
|  |                  | ||||||
|  |                 if (end_time - start_time).total_seconds() > 86400: | ||||||
|  |                     raise ValueError("Maximum timeframe duration is 24 hours") | ||||||
|  |  | ||||||
|  |                 async for msg in interaction.channel.history( | ||||||
|  |                     limit=None, | ||||||
|  |                     after=start_time, | ||||||
|  |                     before=end_time | ||||||
|  |                 ): | ||||||
|  |                     messages.append(msg) | ||||||
|  |                  | ||||||
|  |                 messages = messages[::-1]  # Oldest first | ||||||
|  |                 capture_mode = "timeframe" | ||||||
|  |                 capture_param = f"{start_time.strftime('%Y-%m-%d %H:%M')} to {end_time.strftime('%Y-%m-%d %H:%M')}" | ||||||
|  |                  | ||||||
|  |             else: | ||||||
|  |                 if not self.message_count.value: | ||||||
|  |                     raise ValueError("Please provide either message count or timeframe") | ||||||
|  |                  | ||||||
|                 count = int(self.message_count.value) |                 count = int(self.message_count.value) | ||||||
|                 if not 1 <= count <= 50: |                 if not 1 <= count <= 50: | ||||||
|                 raise ValueError |                     raise ValueError("Message count must be between 1-50") | ||||||
|                  |                  | ||||||
|                 messages = [ |                 messages = [ | ||||||
|                     msg async for msg in interaction.channel.history(limit=count) |                     msg async for msg in interaction.channel.history(limit=count) | ||||||
|                 ][::-1] |                 ][::-1] | ||||||
|  |                 capture_mode = "count" | ||||||
|  |                 capture_param = str(count) | ||||||
|  |  | ||||||
|  |             # Format messages | ||||||
|             formatted_messages = [{ |             formatted_messages = [{ | ||||||
|                 "id": msg.id, |                 "id": msg.id, | ||||||
|                 "author_id": msg.author.id, |                 "author_id": msg.author.id, | ||||||
| @@ -42,34 +103,45 @@ class IncidentModal(discord.ui.Modal): | |||||||
|                 "timestamp": msg.created_at |                 "timestamp": msg.created_at | ||||||
|             } for msg in messages] |             } for msg in messages] | ||||||
|  |  | ||||||
|             incident_id = f"incident_{int(datetime.now().timestamp())}" |             # Generate unique ID | ||||||
|  |             incident_id = f"incident_{uuid.uuid4().hex[:8]}" | ||||||
|  |  | ||||||
|             success = db.add_incident( |             success = db.add_incident( | ||||||
|                 incident_id=incident_id, |                 incident_id=incident_id, | ||||||
|                 reason=self.reason.value, |                 reason=self.reason.value, | ||||||
|                 moderator_id=interaction.user.id, |                 moderator_id=interaction.user.id, | ||||||
|                 messages=formatted_messages |                 messages=formatted_messages, | ||||||
|  |                 capture_mode=capture_mode, | ||||||
|  |                 capture_param=capture_param, | ||||||
|  |                 start_time=start_time, | ||||||
|  |                 end_time=end_time | ||||||
|             ) |             ) | ||||||
|  |  | ||||||
|             if not success: |             if not success: | ||||||
|                 raise Exception("Database storage failed") |                 raise Exception("Database storage failed - check server logs") | ||||||
|  |  | ||||||
|             embed = discord.Embed( |             embed = discord.Embed( | ||||||
|                 title="Incident Logged", |                 title="✅ Incident Logged", | ||||||
|                 description=f"**ID:** `{incident_id}`\n**Reason:** {self.reason.value}", |                 description=f"**ID:** `{incident_id}`\n**Mode:** {capture_mode.title()}", | ||||||
|                 color=0xff0000 |                 color=0xff0000 | ||||||
|             ) |             ) | ||||||
|             preview = messages[0].content[:50] + "..." if messages else "No messages" |             embed.add_field(name="Reason", value=self.reason.value[:500], inline=False) | ||||||
|  |              | ||||||
|  |             if messages: | ||||||
|  |                 preview = f"{messages[0].content[:100]}..." if len(messages[0].content) > 100 else messages[0].content | ||||||
|                 embed.add_field(name="First Message", value=preview, inline=False) |                 embed.add_field(name="First Message", value=preview, inline=False) | ||||||
|  |  | ||||||
|  |             await interaction.response.send_message(embed=embed, ephemeral=True) | ||||||
|  |  | ||||||
|  |         except ValueError as e: | ||||||
|             await interaction.response.send_message( |             await interaction.response.send_message( | ||||||
|                 embed=embed, |                 f"❌ Validation Error: {str(e)}", | ||||||
|                 ephemeral=True |                 ephemeral=True | ||||||
|             ) |             ) | ||||||
|  |         except Exception as e: | ||||||
|         except ValueError: |             logging.error(f"Incident submission error: {str(e)}", exc_info=True) | ||||||
|             await interaction.response.send_message( |             await interaction.response.send_message( | ||||||
|                 "❌ Please enter a number between 1-50", |                 "⚠️ Failed to log incident - please check input format", | ||||||
|                 ephemeral=True |                 ephemeral=True | ||||||
|             ) |             ) | ||||||
|  |  | ||||||
| @@ -158,9 +230,14 @@ async def setup(client): | |||||||
|  |  | ||||||
|             embed = discord.Embed( |             embed = discord.Embed( | ||||||
|                 title=f"Incident {incident_id}", |                 title=f"Incident {incident_id}", | ||||||
|                 description=f"**Reason:** {incident['details']['reason']}", |                 description=( | ||||||
|  |                     f"**Reason:** {incident['details']['reason']}\n" | ||||||
|  |                     f"**Capture Mode:** {incident['details']['capture_mode'].title()}\n" | ||||||
|  |                     f"**Params:** {incident['details']['capture_param']}" | ||||||
|  |                     ), | ||||||
|                     color=0xff0000 |                     color=0xff0000 | ||||||
|                 ) |                 ) | ||||||
|  |  | ||||||
|             embed.add_field( |             embed.add_field( | ||||||
|                 name="Messages", |                 name="Messages", | ||||||
|                 value=messages[:1020] + "..." if len(messages) > 1024 else messages, |                 value=messages[:1020] + "..." if len(messages) > 1024 else messages, | ||||||
|   | |||||||
| @@ -4,6 +4,11 @@ from datetime import datetime | |||||||
| from typing import List, Dict, Optional | from typing import List, Dict, Optional | ||||||
|  |  | ||||||
|  |  | ||||||
|  | import sqlite3 | ||||||
|  | import logging | ||||||
|  | from datetime import datetime | ||||||
|  | from typing import List, Dict, Optional | ||||||
|  |  | ||||||
| class Database: | class Database: | ||||||
|     def __init__(self, db_path: str = "data/moments.db"): |     def __init__(self, db_path: str = "data/moments.db"): | ||||||
|         self.db_path = db_path |         self.db_path = db_path | ||||||
| @@ -12,6 +17,10 @@ class Database: | |||||||
|     def _init_db(self): |     def _init_db(self): | ||||||
|         """Initialize database tables""" |         """Initialize database tables""" | ||||||
|         with self._get_connection() as conn: |         with self._get_connection() as conn: | ||||||
|  |             # Drop tables if they exist (for development) | ||||||
|  |             conn.execute("DROP TABLE IF EXISTS incidents") | ||||||
|  |             conn.execute("DROP TABLE IF EXISTS incident_messages") | ||||||
|  |  | ||||||
|             conn.execute(""" |             conn.execute(""" | ||||||
|                 CREATE TABLE IF NOT EXISTS funny_moments ( |                 CREATE TABLE IF NOT EXISTS funny_moments ( | ||||||
|                     id INTEGER PRIMARY KEY AUTOINCREMENT, |                     id INTEGER PRIMARY KEY AUTOINCREMENT, | ||||||
| @@ -27,7 +36,11 @@ class Database: | |||||||
|                     id TEXT PRIMARY KEY, |                     id TEXT PRIMARY KEY, | ||||||
|                     reason TEXT NOT NULL, |                     reason TEXT NOT NULL, | ||||||
|                     moderator_id INTEGER NOT NULL, |                     moderator_id INTEGER NOT NULL, | ||||||
|                     timestamp DATETIME NOT NULL |                     timestamp DATETIME NOT NULL, | ||||||
|  |                     capture_mode TEXT NOT NULL, | ||||||
|  |                     capture_param TEXT, | ||||||
|  |                     start_time DATETIME, | ||||||
|  |                     end_time DATETIME | ||||||
|                 ) |                 ) | ||||||
|             """) |             """) | ||||||
|  |  | ||||||
| @@ -42,34 +55,32 @@ class Database: | |||||||
|                     FOREIGN KEY (incident_id) REFERENCES incidents(id) |                     FOREIGN KEY (incident_id) REFERENCES incidents(id) | ||||||
|                 ) |                 ) | ||||||
|             """) |             """) | ||||||
|  |  | ||||||
|             conn.commit() |             conn.commit() | ||||||
|  |  | ||||||
|     def _get_connection(self): |     def _get_connection(self): | ||||||
|         return sqlite3.connect(self.db_path) |         return sqlite3.connect(self.db_path) | ||||||
|  |  | ||||||
|     def add_funny_moment(self, message_link: str, author_id: int, description: str = None) -> int: |     def add_incident(self, incident_id: str, reason: str, moderator_id: int,  | ||||||
|         """Store a funny moment in database""" |                     messages: List[Dict], capture_mode: str, capture_param: str, | ||||||
|         with self._get_connection() as conn: |                     start_time: datetime = None, end_time: datetime = None) -> bool: | ||||||
|             cursor = conn.cursor() |  | ||||||
|             cursor.execute(""" |  | ||||||
|                 INSERT INTO funny_moments  |  | ||||||
|                 (message_link, description, author_id, timestamp) |  | ||||||
|                 VALUES (?, ?, ?, ?) |  | ||||||
|             """, (message_link, description, author_id, datetime.now())) |  | ||||||
|             conn.commit() |  | ||||||
|             return cursor.lastrowid |  | ||||||
|  |  | ||||||
|     def add_incident(self, incident_id: str, reason: str, moderator_id: int, messages: List[Dict]) -> bool: |  | ||||||
|         """Store an incident with related messages""" |         """Store an incident with related messages""" | ||||||
|         try: |         try: | ||||||
|             with self._get_connection() as conn: |             with self._get_connection() as conn: | ||||||
|                 # Add incident record |                 # Add incident record | ||||||
|                 conn.execute(""" |                 conn.execute(""" | ||||||
|                     INSERT INTO incidents  |                     INSERT INTO incidents  | ||||||
|                     (id, reason, moderator_id, timestamp) |                     (id, reason, moderator_id, timestamp, capture_mode, capture_param, start_time, end_time) | ||||||
|                     VALUES (?, ?, ?, ?) |                     VALUES (?, ?, ?, ?, ?, ?, ?, ?) | ||||||
|                 """, (incident_id, reason, moderator_id, datetime.now())) |                 """, ( | ||||||
|  |                     incident_id, | ||||||
|  |                     reason, | ||||||
|  |                     moderator_id, | ||||||
|  |                     datetime.now(), | ||||||
|  |                     capture_mode, | ||||||
|  |                     capture_param, | ||||||
|  |                     start_time, | ||||||
|  |                     end_time | ||||||
|  |                 )) | ||||||
|  |  | ||||||
|                 # Add incident messages |                 # Add incident messages | ||||||
|                 for msg in messages: |                 for msg in messages: | ||||||
| @@ -88,9 +99,21 @@ class Database: | |||||||
|                 conn.commit() |                 conn.commit() | ||||||
|                 return True |                 return True | ||||||
|         except Exception as e: |         except Exception as e: | ||||||
|             logging.error(f"Failed to save incident: {e}") |             logging.error(f"Failed to save incident: {str(e)}") | ||||||
|             return False |             return False | ||||||
|  |  | ||||||
|  |     def add_funny_moment(self, message_link: str, author_id: int, description: str = None) -> int: | ||||||
|  |         """Store a funny moment in database""" | ||||||
|  |         with self._get_connection() as conn: | ||||||
|  |             cursor = conn.cursor() | ||||||
|  |             cursor.execute(""" | ||||||
|  |                 INSERT INTO funny_moments  | ||||||
|  |                 (message_link, description, author_id, timestamp) | ||||||
|  |                 VALUES (?, ?, ?, ?) | ||||||
|  |             """, (message_link, description, author_id, datetime.now())) | ||||||
|  |             conn.commit() | ||||||
|  |             return cursor.lastrowid | ||||||
|  |  | ||||||
|     def get_incident(self, incident_id: str) -> Optional[Dict]: |     def get_incident(self, incident_id: str) -> Optional[Dict]: | ||||||
|         """Retrieve an incident with its messages""" |         """Retrieve an incident with its messages""" | ||||||
|         with self._get_connection() as conn: |         with self._get_connection() as conn: | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user