Initial commit: Miku Discord Bot
This commit is contained in:
577
bot/utils/dm_logger.py
Normal file
577
bot/utils/dm_logger.py
Normal file
@@ -0,0 +1,577 @@
|
||||
"""
|
||||
DM Logger Utility
|
||||
Handles logging all DM conversations with timestamps and file attachments
|
||||
"""
|
||||
|
||||
import os
|
||||
import json
|
||||
import discord
|
||||
from datetime import datetime
|
||||
from typing import List, Optional
|
||||
import globals
|
||||
|
||||
# Directory for storing DM logs
|
||||
DM_LOG_DIR = "memory/dms"
|
||||
BLOCKED_USERS_FILE = "memory/blocked_users.json"
|
||||
|
||||
class DMLogger:
|
||||
def __init__(self):
|
||||
"""Initialize the DM logger and ensure directory exists"""
|
||||
os.makedirs(DM_LOG_DIR, exist_ok=True)
|
||||
os.makedirs("memory", exist_ok=True)
|
||||
print(f"📁 DM Logger initialized: {DM_LOG_DIR}")
|
||||
|
||||
def _get_user_log_file(self, user_id: int) -> str:
|
||||
"""Get the log file path for a specific user"""
|
||||
return os.path.join(DM_LOG_DIR, f"{user_id}.json")
|
||||
|
||||
def _load_user_logs(self, user_id: int) -> dict:
|
||||
"""Load existing logs for a user, create new if doesn't exist"""
|
||||
log_file = self._get_user_log_file(user_id)
|
||||
print(f"📁 DM Logger: Loading logs from {log_file}")
|
||||
|
||||
if os.path.exists(log_file):
|
||||
try:
|
||||
with open(log_file, 'r', encoding='utf-8') as f:
|
||||
logs = json.load(f)
|
||||
print(f"📁 DM Logger: Successfully loaded logs for user {user_id}: {len(logs.get('conversations', []))} conversations")
|
||||
return logs
|
||||
except Exception as e:
|
||||
print(f"⚠️ DM Logger: Failed to load DM logs for user {user_id}: {e}")
|
||||
return {"user_id": user_id, "username": "Unknown", "conversations": []}
|
||||
else:
|
||||
print(f"📁 DM Logger: No log file found for user {user_id}, creating new")
|
||||
return {"user_id": user_id, "username": "Unknown", "conversations": []}
|
||||
|
||||
def _save_user_logs(self, user_id: int, logs: dict):
|
||||
"""Save logs for a user"""
|
||||
log_file = self._get_user_log_file(user_id)
|
||||
try:
|
||||
with open(log_file, 'w', encoding='utf-8') as f:
|
||||
json.dump(logs, f, indent=2, ensure_ascii=False)
|
||||
except Exception as e:
|
||||
print(f"⚠️ Failed to save DM logs for user {user_id}: {e}")
|
||||
|
||||
def log_user_message(self, user: discord.User, message: discord.Message, is_bot_message: bool = False):
|
||||
"""Log a user message in DMs"""
|
||||
user_id = user.id
|
||||
username = user.display_name or user.name
|
||||
|
||||
# Load existing logs
|
||||
logs = self._load_user_logs(user_id)
|
||||
logs["username"] = username # Update username in case it changed
|
||||
|
||||
# Create message entry
|
||||
message_entry = {
|
||||
"timestamp": datetime.now().isoformat(),
|
||||
"message_id": message.id,
|
||||
"is_bot_message": is_bot_message,
|
||||
"content": message.content if message.content else "",
|
||||
"attachments": [],
|
||||
"reactions": [] # Track reactions: [{emoji, reactor_id, reactor_name, is_bot, added_at}]
|
||||
}
|
||||
|
||||
# Log file attachments
|
||||
if message.attachments:
|
||||
for attachment in message.attachments:
|
||||
attachment_info = {
|
||||
"filename": attachment.filename,
|
||||
"url": attachment.url,
|
||||
"size": attachment.size,
|
||||
"content_type": attachment.content_type
|
||||
}
|
||||
message_entry["attachments"].append(attachment_info)
|
||||
|
||||
# Log embeds
|
||||
if message.embeds:
|
||||
message_entry["embeds"] = [embed.to_dict() for embed in message.embeds]
|
||||
|
||||
# Add to conversations
|
||||
logs["conversations"].append(message_entry)
|
||||
|
||||
# Keep only last 1000 messages to prevent files from getting too large
|
||||
if len(logs["conversations"]) > 1000:
|
||||
logs["conversations"] = logs["conversations"][-1000:]
|
||||
print(f"📝 DM logs for user {username} trimmed to last 1000 messages")
|
||||
|
||||
# Save logs
|
||||
self._save_user_logs(user_id, logs)
|
||||
|
||||
if is_bot_message:
|
||||
print(f"🤖 DM logged: Bot -> {username} ({len(message_entry['attachments'])} attachments)")
|
||||
else:
|
||||
print(f"💬 DM logged: {username} -> Bot ({len(message_entry['attachments'])} attachments)")
|
||||
|
||||
def get_user_conversation_summary(self, user_id: int) -> dict:
|
||||
"""Get a summary of conversations with a user"""
|
||||
logs = self._load_user_logs(user_id)
|
||||
|
||||
if not logs["conversations"]:
|
||||
return {"user_id": str(user_id), "username": logs["username"], "message_count": 0, "last_message": None}
|
||||
|
||||
total_messages = len(logs["conversations"])
|
||||
user_messages = len([msg for msg in logs["conversations"] if not msg["is_bot_message"]])
|
||||
bot_messages = total_messages - user_messages
|
||||
|
||||
# Get last message info
|
||||
last_message = logs["conversations"][-1]
|
||||
|
||||
return {
|
||||
"user_id": str(user_id), # Convert to string to prevent JS precision loss
|
||||
"username": logs["username"],
|
||||
"total_messages": total_messages,
|
||||
"user_messages": user_messages,
|
||||
"bot_messages": bot_messages,
|
||||
"last_message": {
|
||||
"timestamp": last_message["timestamp"],
|
||||
"content": last_message["content"][:100] + "..." if len(last_message["content"]) > 100 else last_message["content"],
|
||||
"is_bot_message": last_message["is_bot_message"]
|
||||
}
|
||||
}
|
||||
|
||||
def get_all_dm_users(self) -> List[dict]:
|
||||
"""Get summary of all users who have DMed the bot"""
|
||||
users = []
|
||||
|
||||
if not os.path.exists(DM_LOG_DIR):
|
||||
return users
|
||||
|
||||
for filename in os.listdir(DM_LOG_DIR):
|
||||
if filename.endswith('.json'):
|
||||
try:
|
||||
user_id = int(filename.replace('.json', ''))
|
||||
summary = self.get_user_conversation_summary(user_id)
|
||||
users.append(summary)
|
||||
except ValueError:
|
||||
continue
|
||||
|
||||
# Sort by last message timestamp (most recent first)
|
||||
users.sort(key=lambda x: x["last_message"]["timestamp"] if x["last_message"] else "", reverse=True)
|
||||
return users
|
||||
|
||||
def search_user_conversations(self, user_id: int, query: str, limit: int = 10) -> List[dict]:
|
||||
"""Search conversations with a specific user"""
|
||||
logs = self._load_user_logs(user_id)
|
||||
results = []
|
||||
|
||||
query_lower = query.lower()
|
||||
for message in reversed(logs["conversations"]): # Search from newest to oldest
|
||||
if query_lower in message["content"].lower():
|
||||
results.append(message)
|
||||
if len(results) >= limit:
|
||||
break
|
||||
|
||||
return results
|
||||
|
||||
def log_conversation(self, user_id: str, user_message: str, bot_response: str, attachments: list = None):
|
||||
"""Log a conversation exchange (user message + bot response) for API usage"""
|
||||
try:
|
||||
user_id_int = int(user_id)
|
||||
|
||||
# Get user object - try to find it from the client
|
||||
import globals
|
||||
user = globals.client.get_user(user_id_int)
|
||||
if not user:
|
||||
# If we can't find the user, create a mock user for logging purposes
|
||||
class MockUser:
|
||||
def __init__(self, user_id):
|
||||
self.id = user_id
|
||||
self.display_name = "Unknown"
|
||||
self.name = "Unknown"
|
||||
|
||||
user = MockUser(user_id_int)
|
||||
|
||||
# Create mock message objects for logging
|
||||
class MockMessage:
|
||||
def __init__(self, content, message_id=0, attachments=None):
|
||||
self.content = content
|
||||
self.id = message_id
|
||||
self.attachments = attachments or []
|
||||
self.embeds = []
|
||||
|
||||
# Log the user message (trigger)
|
||||
if user_message:
|
||||
user_msg = MockMessage(user_message)
|
||||
self.log_user_message(user, user_msg, is_bot_message=False)
|
||||
|
||||
# Log the bot response with attachments
|
||||
bot_attachments = []
|
||||
if attachments:
|
||||
for filename in attachments:
|
||||
# Create mock attachment for filename logging
|
||||
class MockAttachment:
|
||||
def __init__(self, filename):
|
||||
self.filename = filename
|
||||
self.url = ""
|
||||
self.size = 0
|
||||
self.content_type = "unknown"
|
||||
|
||||
bot_attachments.append(MockAttachment(filename))
|
||||
|
||||
bot_msg = MockMessage(bot_response, attachments=bot_attachments)
|
||||
self.log_user_message(user, bot_msg, is_bot_message=True)
|
||||
|
||||
print(f"📝 Conversation logged for user {user_id}: user='{user_message[:50]}...', bot='{bot_response[:50]}...'")
|
||||
|
||||
except Exception as e:
|
||||
print(f"⚠️ Failed to log conversation for user {user_id}: {e}")
|
||||
|
||||
def export_user_conversation(self, user_id: int, format: str = "json") -> str:
|
||||
"""Export all conversations with a user in specified format"""
|
||||
logs = self._load_user_logs(user_id)
|
||||
|
||||
if format.lower() == "txt":
|
||||
# Export as readable text file
|
||||
export_file = os.path.join(DM_LOG_DIR, f"{user_id}_export.txt")
|
||||
|
||||
with open(export_file, 'w', encoding='utf-8') as f:
|
||||
f.write(f"DM Conversation Log: {logs['username']} (ID: {user_id})\n")
|
||||
f.write("=" * 50 + "\n\n")
|
||||
|
||||
for msg in logs["conversations"]:
|
||||
timestamp = msg["timestamp"]
|
||||
sender = "🤖 Miku" if msg["is_bot_message"] else f"👤 {logs['username']}"
|
||||
content = msg["content"] if msg["content"] else "[No text content]"
|
||||
|
||||
f.write(f"[{timestamp}] {sender}:\n{content}\n")
|
||||
|
||||
if msg["attachments"]:
|
||||
f.write("📎 Attachments:\n")
|
||||
for attachment in msg["attachments"]:
|
||||
f.write(f" - {attachment['filename']} ({attachment['size']} bytes)\n")
|
||||
|
||||
f.write("\n" + "-" * 30 + "\n\n")
|
||||
|
||||
return export_file
|
||||
else:
|
||||
# Default to JSON
|
||||
return self._get_user_log_file(user_id)
|
||||
|
||||
def _load_blocked_users(self) -> dict:
|
||||
"""Load the blocked users list"""
|
||||
if os.path.exists(BLOCKED_USERS_FILE):
|
||||
try:
|
||||
with open(BLOCKED_USERS_FILE, 'r', encoding='utf-8') as f:
|
||||
return json.load(f)
|
||||
except Exception as e:
|
||||
print(f"⚠️ Failed to load blocked users: {e}")
|
||||
return {"blocked_users": []}
|
||||
return {"blocked_users": []}
|
||||
|
||||
def _save_blocked_users(self, blocked_data: dict):
|
||||
"""Save the blocked users list"""
|
||||
try:
|
||||
with open(BLOCKED_USERS_FILE, 'w', encoding='utf-8') as f:
|
||||
json.dump(blocked_data, f, indent=2, ensure_ascii=False)
|
||||
except Exception as e:
|
||||
print(f"⚠️ Failed to save blocked users: {e}")
|
||||
|
||||
def is_user_blocked(self, user_id: int) -> bool:
|
||||
"""Check if a user is blocked"""
|
||||
blocked_data = self._load_blocked_users()
|
||||
return user_id in blocked_data.get("blocked_users", [])
|
||||
|
||||
def block_user(self, user_id: int, username: str = None) -> bool:
|
||||
"""Block a user from sending DMs to Miku"""
|
||||
try:
|
||||
blocked_data = self._load_blocked_users()
|
||||
if user_id not in blocked_data["blocked_users"]:
|
||||
blocked_data["blocked_users"].append(user_id)
|
||||
|
||||
# Store additional info about blocked users
|
||||
if "blocked_user_info" not in blocked_data:
|
||||
blocked_data["blocked_user_info"] = {}
|
||||
|
||||
blocked_data["blocked_user_info"][str(user_id)] = {
|
||||
"username": username or "Unknown",
|
||||
"blocked_at": datetime.now().isoformat(),
|
||||
"blocked_by": "admin"
|
||||
}
|
||||
|
||||
self._save_blocked_users(blocked_data)
|
||||
print(f"🚫 User {user_id} ({username}) has been blocked")
|
||||
return True
|
||||
else:
|
||||
print(f"⚠️ User {user_id} is already blocked")
|
||||
return False
|
||||
except Exception as e:
|
||||
print(f"❌ Failed to block user {user_id}: {e}")
|
||||
return False
|
||||
|
||||
def unblock_user(self, user_id: int) -> bool:
|
||||
"""Unblock a user"""
|
||||
try:
|
||||
blocked_data = self._load_blocked_users()
|
||||
if user_id in blocked_data["blocked_users"]:
|
||||
blocked_data["blocked_users"].remove(user_id)
|
||||
|
||||
# Remove user info as well
|
||||
if "blocked_user_info" in blocked_data and str(user_id) in blocked_data["blocked_user_info"]:
|
||||
username = blocked_data["blocked_user_info"][str(user_id)].get("username", "Unknown")
|
||||
del blocked_data["blocked_user_info"][str(user_id)]
|
||||
else:
|
||||
username = "Unknown"
|
||||
|
||||
self._save_blocked_users(blocked_data)
|
||||
print(f"✅ User {user_id} ({username}) has been unblocked")
|
||||
return True
|
||||
else:
|
||||
print(f"⚠️ User {user_id} is not blocked")
|
||||
return False
|
||||
except Exception as e:
|
||||
print(f"❌ Failed to unblock user {user_id}: {e}")
|
||||
return False
|
||||
|
||||
def get_blocked_users(self) -> List[dict]:
|
||||
"""Get list of all blocked users"""
|
||||
blocked_data = self._load_blocked_users()
|
||||
result = []
|
||||
|
||||
for user_id in blocked_data.get("blocked_users", []):
|
||||
user_info = blocked_data.get("blocked_user_info", {}).get(str(user_id), {})
|
||||
result.append({
|
||||
"user_id": str(user_id), # String to prevent JS precision loss
|
||||
"username": user_info.get("username", "Unknown"),
|
||||
"blocked_at": user_info.get("blocked_at", "Unknown"),
|
||||
"blocked_by": user_info.get("blocked_by", "admin")
|
||||
})
|
||||
|
||||
return result
|
||||
|
||||
async def log_reaction_add(self, user_id: int, message_id: int, emoji: str, reactor_id: int, reactor_name: str, is_bot_reactor: bool):
|
||||
"""Log when a reaction is added to a message in DMs"""
|
||||
try:
|
||||
logs = self._load_user_logs(user_id)
|
||||
|
||||
# Find the message to add the reaction to
|
||||
for message in logs["conversations"]:
|
||||
if message.get("message_id") == message_id:
|
||||
# Initialize reactions list if it doesn't exist
|
||||
if "reactions" not in message:
|
||||
message["reactions"] = []
|
||||
|
||||
# Check if this exact reaction already exists (shouldn't happen, but just in case)
|
||||
reaction_exists = any(
|
||||
r["emoji"] == emoji and r["reactor_id"] == reactor_id
|
||||
for r in message["reactions"]
|
||||
)
|
||||
|
||||
if not reaction_exists:
|
||||
reaction_entry = {
|
||||
"emoji": emoji,
|
||||
"reactor_id": reactor_id,
|
||||
"reactor_name": reactor_name,
|
||||
"is_bot": is_bot_reactor,
|
||||
"added_at": datetime.now().isoformat()
|
||||
}
|
||||
message["reactions"].append(reaction_entry)
|
||||
self._save_user_logs(user_id, logs)
|
||||
|
||||
reactor_type = "🤖 Miku" if is_bot_reactor else f"👤 {reactor_name}"
|
||||
print(f"➕ Reaction logged: {emoji} by {reactor_type} on message {message_id}")
|
||||
return True
|
||||
else:
|
||||
print(f"⚠️ Reaction {emoji} by {reactor_name} already exists on message {message_id}")
|
||||
return False
|
||||
|
||||
print(f"⚠️ Message {message_id} not found in user {user_id}'s logs")
|
||||
return False
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Failed to log reaction add for user {user_id}, message {message_id}: {e}")
|
||||
return False
|
||||
|
||||
async def log_reaction_remove(self, user_id: int, message_id: int, emoji: str, reactor_id: int):
|
||||
"""Log when a reaction is removed from a message in DMs"""
|
||||
try:
|
||||
logs = self._load_user_logs(user_id)
|
||||
|
||||
# Find the message to remove the reaction from
|
||||
for message in logs["conversations"]:
|
||||
if message.get("message_id") == message_id:
|
||||
if "reactions" in message:
|
||||
# Find and remove the specific reaction
|
||||
original_count = len(message["reactions"])
|
||||
message["reactions"] = [
|
||||
r for r in message["reactions"]
|
||||
if not (r["emoji"] == emoji and r["reactor_id"] == reactor_id)
|
||||
]
|
||||
|
||||
if len(message["reactions"]) < original_count:
|
||||
self._save_user_logs(user_id, logs)
|
||||
print(f"➖ Reaction removed: {emoji} by user/bot {reactor_id} from message {message_id}")
|
||||
return True
|
||||
else:
|
||||
print(f"⚠️ Reaction {emoji} by {reactor_id} not found on message {message_id}")
|
||||
return False
|
||||
else:
|
||||
print(f"⚠️ No reactions on message {message_id}")
|
||||
return False
|
||||
|
||||
print(f"⚠️ Message {message_id} not found in user {user_id}'s logs")
|
||||
return False
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Failed to log reaction remove for user {user_id}, message {message_id}: {e}")
|
||||
return False
|
||||
|
||||
async def delete_conversation(self, user_id: int, conversation_id: str) -> bool:
|
||||
"""Delete a specific conversation/message from both Discord and logs (only bot messages can be deleted)"""
|
||||
try:
|
||||
logs = self._load_user_logs(user_id)
|
||||
|
||||
print(f"🔍 DM Logger: Looking for bot message ID '{conversation_id}' for user {user_id}")
|
||||
print(f"🔍 DM Logger: Searching through {len(logs['conversations'])} conversations")
|
||||
|
||||
# Convert conversation_id to int for comparison if it looks like a Discord message ID
|
||||
conv_id_as_int = None
|
||||
try:
|
||||
conv_id_as_int = int(conversation_id)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
# Find the specific bot message to delete
|
||||
message_to_delete = None
|
||||
for conv in logs["conversations"]:
|
||||
if (conv.get("is_bot_message", False) and
|
||||
(str(conv.get("message_id", "")) == conversation_id or
|
||||
conv.get("message_id", 0) == conv_id_as_int or
|
||||
conv.get("timestamp", "") == conversation_id)):
|
||||
message_to_delete = conv
|
||||
break
|
||||
|
||||
if not message_to_delete:
|
||||
print(f"⚠️ No bot message found with ID {conversation_id} for user {user_id}")
|
||||
return False
|
||||
|
||||
# Try to delete from Discord first
|
||||
discord_deleted = False
|
||||
try:
|
||||
import globals
|
||||
if globals.client and hasattr(globals.client, 'get_user'):
|
||||
# Get the user and their DM channel
|
||||
user = globals.client.get_user(user_id)
|
||||
if user:
|
||||
dm_channel = user.dm_channel
|
||||
if not dm_channel:
|
||||
dm_channel = await user.create_dm()
|
||||
|
||||
# Fetch and delete the message
|
||||
message_id = message_to_delete.get("message_id")
|
||||
if message_id:
|
||||
try:
|
||||
discord_message = await dm_channel.fetch_message(int(message_id))
|
||||
await discord_message.delete()
|
||||
discord_deleted = True
|
||||
print(f"✅ Deleted Discord message {message_id} from DM with user {user_id}")
|
||||
except Exception as e:
|
||||
print(f"⚠️ Could not delete Discord message {message_id}: {e}")
|
||||
# Continue anyway to delete from logs
|
||||
|
||||
except Exception as e:
|
||||
print(f"⚠️ Discord deletion failed: {e}")
|
||||
# Continue anyway to delete from logs
|
||||
|
||||
# Remove from logs regardless of Discord deletion success
|
||||
original_count = len(logs["conversations"])
|
||||
logs["conversations"] = [conv for conv in logs["conversations"]
|
||||
if not (
|
||||
# Match by message_id (as int or string) AND it's a bot message
|
||||
(conv.get("is_bot_message", False) and
|
||||
(str(conv.get("message_id", "")) == conversation_id or
|
||||
conv.get("message_id", 0) == conv_id_as_int or
|
||||
conv.get("timestamp", "") == conversation_id))
|
||||
)]
|
||||
|
||||
deleted_count = original_count - len(logs["conversations"])
|
||||
|
||||
if deleted_count > 0:
|
||||
self._save_user_logs(user_id, logs)
|
||||
if discord_deleted:
|
||||
print(f"🗑️ Deleted bot message from both Discord and logs for user {user_id}")
|
||||
else:
|
||||
print(f"🗑️ Deleted bot message from logs only (Discord deletion failed) for user {user_id}")
|
||||
return True
|
||||
else:
|
||||
print(f"⚠️ No bot message found in logs with ID {conversation_id} for user {user_id}")
|
||||
return False
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Failed to delete conversation {conversation_id} for user {user_id}: {e}")
|
||||
return False
|
||||
|
||||
async def delete_all_conversations(self, user_id: int) -> bool:
|
||||
"""Delete all conversations with a user from both Discord and logs"""
|
||||
try:
|
||||
logs = self._load_user_logs(user_id)
|
||||
conversation_count = len(logs["conversations"])
|
||||
|
||||
if conversation_count == 0:
|
||||
print(f"⚠️ No conversations found for user {user_id}")
|
||||
return False
|
||||
|
||||
# Find all bot messages to delete from Discord
|
||||
bot_messages = [conv for conv in logs["conversations"] if conv.get("is_bot_message", False)]
|
||||
print(f"🔍 Found {len(bot_messages)} bot messages to delete from Discord for user {user_id}")
|
||||
|
||||
# Try to delete all bot messages from Discord
|
||||
discord_deleted_count = 0
|
||||
try:
|
||||
import globals
|
||||
if globals.client and hasattr(globals.client, 'get_user'):
|
||||
# Get the user and their DM channel
|
||||
user = globals.client.get_user(user_id)
|
||||
if user:
|
||||
dm_channel = user.dm_channel
|
||||
if not dm_channel:
|
||||
dm_channel = await user.create_dm()
|
||||
|
||||
# Delete each bot message from Discord
|
||||
for conv in bot_messages:
|
||||
message_id = conv.get("message_id")
|
||||
if message_id:
|
||||
try:
|
||||
discord_message = await dm_channel.fetch_message(int(message_id))
|
||||
await discord_message.delete()
|
||||
discord_deleted_count += 1
|
||||
print(f"✅ Deleted Discord message {message_id} from DM with user {user_id}")
|
||||
except Exception as e:
|
||||
print(f"⚠️ Could not delete Discord message {message_id}: {e}")
|
||||
# Continue with other messages
|
||||
|
||||
except Exception as e:
|
||||
print(f"⚠️ Discord bulk deletion failed: {e}")
|
||||
# Continue anyway to delete from logs
|
||||
|
||||
# Delete all conversations from logs regardless of Discord deletion success
|
||||
logs["conversations"] = []
|
||||
self._save_user_logs(user_id, logs)
|
||||
|
||||
if discord_deleted_count > 0:
|
||||
print(f"🗑️ Deleted {discord_deleted_count} bot messages from Discord and all {conversation_count} conversations from logs for user {user_id}")
|
||||
else:
|
||||
print(f"🗑️ Deleted all {conversation_count} conversations from logs only (Discord deletion failed) for user {user_id}")
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Failed to delete all conversations for user {user_id}: {e}")
|
||||
return False
|
||||
|
||||
def delete_user_completely(self, user_id: int) -> bool:
|
||||
"""Delete user's log file completely"""
|
||||
try:
|
||||
log_file = self._get_user_log_file(user_id)
|
||||
if os.path.exists(log_file):
|
||||
os.remove(log_file)
|
||||
print(f"🗑️ Completely deleted log file for user {user_id}")
|
||||
return True
|
||||
else:
|
||||
print(f"⚠️ No log file found for user {user_id}")
|
||||
return False
|
||||
except Exception as e:
|
||||
print(f"❌ Failed to delete user log file {user_id}: {e}")
|
||||
return False
|
||||
|
||||
# Global instance
|
||||
dm_logger = DMLogger()
|
||||
Reference in New Issue
Block a user