o bot não está mantendo a persistencia, pois apos reiniciar e deletar as mensagens, as interações permaneceram gravadas na database, como se a ID da mensagem depois que reiniciou o bot não fosse util para deletar as interações

import json
import discord
from discord import app_commands
from dotenv import load_dotenv
import os
from commands import setup_commands
from model import setup_model, generate_response
from error_handler import handle_error, log_error
import asyncio
import time
import aiofiles
import aiosqlite
import datetime

# Load environment variables
load_dotenv()

TOKEN = os.getenv('DISCORD_TOKEN')
GEMINI_API_KEY = os.getenv('GEMINI_API_KEY')

intents = discord.Intents.default()
intents.message_content = True
client = discord.Client(intents=intents)
tree = app_commands.CommandTree(client)

# Default configurations
DEFAULT_CONFIG = {
    "temperature": 1.0,
    "top_p": 0.95,
    "top_k": 64,
    "max_output_tokens": 1024,
    "system_instruction": "You are a helpful, gentle, and friendly AI bot called 'Alicia,' developed by 'HikariTheAngel.' Your purpose is to assist in immersive role-playing (RP) sessions and provide helpful responses while maintaining a consistent and coherent narrative. You are powered by an advanced AI model called 'Gemini'. \n\n### GENERAL GUIDELINES:\n\n1. **Respectful and Polite Communication**: Always interact with the user in a polite, gentle, and respectful manner, maintaining a friendly and helpful tone at all times.\n\n2. **Language Consistency**: Always speak in the same language as the user. Adapt to the user's language and style of communication. If the user switches languages, follow their lead without hesitation.\n\n3. **Main Rule on Links**: If the user sends a link, **do not replicate or share it in the chat unless explicitly requested by the user**. Ensure that this rule is strictly followed to avoid unnecessary link sharing.\n\n4. **Roleplay-Specific Rules**: When engaging in RP, follow the guidelines below strictly, ensuring a seamless and immersive experience for the user. Always speak normally when giving instructions **before the RP begins**, but once the RP starts, adhere to the RP tone and context.",
    "max_history": 10000,
    "first_time": True,
    "safety_settings": {
        "HARM_CATEGORY_SEXUALLY_EXPLICIT": "BLOCK_ONLY_HIGH",
        "HARM_CATEGORY_HATE_SPEECH": "BLOCK_ONLY_HIGH",
        "HARM_CATEGORY_HARASSMENT": "BLOCK_ONLY_HIGH",
        "HARM_CATEGORY_DANGEROUS_CONTENT": "BLOCK_ONLY_HIGH"
    },
    "allowed_channels": [],
    "require_mention": False,
    "model_name": "gemini-1.5-flash",
    "rp_mode_enabled": False
}

# Dictionary to store configurations per guild
guild_configs = {}
dm_error_sent = {}

# Helper functions
async def load_guild_configs():
    try:
        async with aiofiles.open('guild_configs.json', 'r') as f:
            return json.loads(await f.read())
    except FileNotFoundError:
        return {}

async def save_guild_configs():
    async with aiofiles.open('guild_configs.json', 'w') as f:
        await f.write(json.dumps(guild_configs, indent=4))

def get_guild_config(guild_id):
    if guild_id not in guild_configs:
        guild_configs[guild_id] = DEFAULT_CONFIG.copy()
    return guild_configs[guild_id]

# SQLite-based guild history functions
async def initialize_db(db_path):
    async with aiosqlite.connect(db_path) as db:
        await db.execute('''
            CREATE TABLE IF NOT EXISTS messages (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                message_id TEXT UNIQUE,
                role TEXT,
                content TEXT,
                timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
            )
        ''')
        await db.commit()

async def get_guild_history(guild_id):
    db_path = f'memories/{guild_id}_histories.sqlite'
    if not os.path.exists(db_path):
        await initialize_db(db_path)
    async with aiosqlite.connect(db_path) as db:
        async with db.execute('SELECT message_id, role, content FROM messages ORDER BY timestamp') as cursor:
            return [{"message_id": row[0], "content": {"role": row[1], "parts": [row[2]]}} for row in await cursor.fetchall()]

async def update_guild_history(guild_id, message, message_id):
    db_path = f'memories/{guild_id}_histories.sqlite'
    if not os.path.exists(db_path):
        await initialize_db(db_path)
    async with aiosqlite.connect(db_path) as db:
        await db.execute('''
            INSERT OR REPLACE INTO messages (message_id, role, content, timestamp)
            VALUES (?, ?, ?, ?)
        ''', (message_id, message['role'], message['parts'][0], datetime.datetime.now()))
        await db.commit()

async def remove_message_from_history(guild_id, message_id):
    db_path = f'memories/{guild_id}_histories.sqlite'
    if os.path.exists(db_path):
        async with aiosqlite.connect(db_path) as db:
            await db.execute('DELETE FROM messages WHERE message_id = ?', (message_id,))
            await db.commit()

async def clear_guild_history(guild_id):
    db_path = f'memories/{guild_id}_histories.sqlite'
    if os.path.exists(db_path):
        async with aiosqlite.connect(db_path) as db:
            await db.execute('DELETE FROM messages')
            await db.commit()

# New function to split long messages
def split_message(message, max_length=2000):
    if len(message) <= max_length:
        return [message]
    
    parts = []
    while len(message) > max_length:
        split_index = message.rfind(' ', 0, max_length)
        if split_index == -1:
            split_index = max_length
        parts.append(message[:split_index])
        message = message[split_index:].lstrip()
    
    if message:
        parts.append(message)
    
    return parts

# Bot initialization
@client.event
async def on_ready():
    global guild_configs
    guild_configs = await load_guild_configs()
    setup_model(GEMINI_API_KEY)
    setup_commands(tree, get_guild_config, save_guild_configs, get_guild_history, update_guild_history, remove_message_from_history, clear_guild_history)
    try:
        await tree.sync()
        print("Commands Synced!")
    except discord.errors.HTTPException as e:
        print(f"Error syncing commands: {e}")
    print(f'{client.user} has connected to Discord!')

# Message event to interact with the Gemini model
@client.event
async def on_message(message):
    if message.author == client.user:
        return

    # Check if the message is a DM
    if isinstance(message.channel, discord.DMChannel):
        # Check if the user has already received the error message
        if message.author.id not in dm_error_sent:
            await message.channel.send("Sorry, Alicia is not available for use in direct messages")
            dm_error_sent[message.author.id] = True
        return

    guild_config = get_guild_config(str(message.guild.id))
    
    if message.channel.id not in guild_config["allowed_channels"]:
        return

    if guild_config["require_mention"] and client.user not in message.mentions:
        return

    # Add user's message to history
    await update_guild_history(
        str(message.guild.id),
        {"role": "user", "parts": [f"{message.author.display_name}: {message.content}"]},
        str(message.id)
    )

    start_time = time.time()
    max_retry_time = 60  # 1 minute

    while time.time() - start_time < max_retry_time:
        try:
            response = await generate_response(message, message.guild.id, get_guild_config, get_guild_history)
            
            # Split the response if it's too long
            response_parts = split_message(response)
            bot_messages = []
            
            for part in response_parts:
                bot_message = await message.channel.send(part)
                bot_messages.append(bot_message)
            
            # Add bot's response to history with its message ID(s)
            full_response = {"role": "model", "parts": [response]}
            for bot_message in bot_messages:
                await update_guild_history(str(message.guild.id), full_response, str(bot_message.id))
            
            return
        except Exception as e:
            log_error(e)
            error_result = await handle_error(e, message.channel)
            if error_result is not None:  # If it's not an InternalServerError, stop retrying
                return
            await asyncio.sleep(5)  # Wait for 5 second before retrying

    # If we've exhausted all retries
    await message.channel.send(embed=discord.Embed(title="Error", description="I'm sorry, but I couldn't get a response after trying for a minute. Please try again later.", color=discord.Color.red()))

@client.event
async def on_message_edit(before, after):
    if after.author == client.user:
        return
    
    guild_config = get_guild_config(str(after.guild.id))
    if after.channel.id not in guild_config["allowed_channels"]:
        return

    await update_guild_history(
        str(after.guild.id),
        {"role": "user", "parts": [f"{after.author.display_name}: {after.content}"]},
        str(after.id)
    )

@client.event
async def on_message_delete(message):
    guild_config = get_guild_config(str(message.guild.id))
    if message.channel.id not in guild_config["allowed_channels"]:
        return

    await remove_message_from_history(str(message.guild.id), str(message.id))

# Start the bot
client.run(TOKEN)