Como Fazer um Bot do Discord Usar Postgres para Persistência
🔍 WiseChecker

Como Fazer um Bot do Discord Usar Postgres para Persistência

Executar um bot do Discord que reinicia ou escala em várias instâncias requer um banco de dados confiável para armazenar dados de usuários, configurações de servidor e histórico de comandos. Sem persistência, todos os dados são perdidos quando o bot fica offline. O SQLite funciona para bots pequenos, mas sofre com gravações simultâneas e conjuntos de dados maiores. Este artigo explica como conectar seu bot do Discord a um banco de dados PostgreSQL para armazenar dados permanentemente, mesmo após reinicializações ou falhas.

Principais Conclusões: Conectando um Bot do Discord ao PostgreSQL

  • Biblioteca psycopg2 ou asyncpg: A biblioteca Python que permite que seu bot se comunique com um banco Postgres.
  • CREATE TABLE IF NOT EXISTS: Comando SQL que cria uma tabela apenas se ela não existir, evitando erros na reinicialização.
  • cursor.execute vs await connection.execute: A diferença entre consultas síncronas e assíncronas ao banco de dados no código do seu bot.

O Que é Persistência com Postgres e Por Que Seu Bot Precisa Dela

PostgreSQL é um banco de dados relacional de código aberto que armazena dados em tabelas com esquemas rígidos. Para um bot do Discord, persistência significa que dados como XP do usuário, prefixos do servidor e logs de moderação sobrevivem a reinicializações do bot. Sem um banco de dados, seu bot armazena tudo na memória, e uma única reinicialização apaga todos os dados.

O Postgres oferece várias vantagens sobre armazenamento baseado em arquivos como JSON ou SQLite:

  • Conexões simultâneas de várias instâncias do bot sem corrupção.
  • Consultas avançadas com JOINs, índices e busca em texto completo.
  • Controle de acesso baseado em funções para gerenciamento seguro de dados.

Antes de começar, você precisa de um servidor PostgreSQL em execução. Você pode instalá-lo localmente ou usar um provedor de nuvem como Amazon RDS, Google Cloud SQL ou Railway. Você também precisa do token do seu bot do Discord e da biblioteca Python discord.py instalada.

Pré-requisitos

  • Python 3.8 ou superior instalado no seu sistema.
  • Um bot do Discord criado no Portal do Desenvolvedor do Discord com um token.
  • PostgreSQL instalado e em execução. A porta padrão é 5432.
  • Nome do banco de dados, nome de usuário e senha para o Postgres.

Passos para Conectar Seu Bot do Discord ao PostgreSQL

Os passos a seguir usam a biblioteca asyncpg, que é assíncrona e funciona bem com discord.py. Se preferir uma abordagem síncrona, use psycopg2. Os passos assumem que você tem um arquivo de bot básico chamado bot.py.

  1. Instale a biblioteca asyncpg
    Abra seu terminal e execute: pip install asyncpg. Se planeja usar psycopg2, execute pip install psycopg2-binary.
  2. Crie um banco de dados e um usuário no Postgres
    Conecte-se ao seu servidor Postgres usando um cliente como pgAdmin ou a linha de comando. Execute: CREATE DATABASE discord_bot; e CREATE USER bot_user WITH PASSWORD 'sua_senha';. Em seguida, conceda todos os privilégios no banco de dados para esse usuário.
  3. Importe asyncpg no código do seu bot
    No topo do seu arquivo bot.py, adicione: import asyncpg. Se estiver usando psycopg2, adicione: import psycopg2.
  4. Crie um pool de conexões na inicialização do bot
    Dentro do evento on_ready, crie um pool de conexões. Exemplo de código:
    async def on_ready():
        bot.db_pool = await asyncpg.create_pool(
            user='bot_user',
            password='sua_senha',
            database='discord_bot',
            host='localhost',
            port=5432
        )
        print('Conectado ao Postgres')
  5. Crie uma tabela para seus dados
    Use uma instrução CREATE TABLE IF NOT EXISTS para garantir que a tabela exista em toda inicialização. Exemplo:
    async with bot.db_pool.acquire() as conn:
        await conn.execute('''
            CREATE TABLE IF NOT EXISTS user_xp (
                user_id BIGINT PRIMARY KEY,
                xp INTEGER DEFAULT 0,
                level INTEGER DEFAULT 1
            )
        ''')
  6. Escreva um comando que armazene dados
    Crie um comando de barra ou comando de prefixo que insira ou atualize dados. Exemplo:
    @bot.tree.command(name='add_xp')
    async def add_xp(interaction: discord.Interaction, user: discord.User, amount: int):
        async with bot.db_pool.acquire() as conn:
            await conn.execute('''
                INSERT INTO user_xp (user_id, xp)
                VALUES ($1, $2)
                ON CONFLICT (user_id)
                DO UPDATE SET xp = user_xp.xp + $2
            ''', user.id, amount)
        await interaction.response.send_message('XP adicionado')
  7. Leia dados do banco de dados
    Para recuperar dados, use uma consulta SELECT. Exemplo:
    async with bot.db_pool.acquire() as conn:
        row = await conn.fetchrow('SELECT xp, level FROM user_xp WHERE user_id = $1', user.id)
        if row:
            xp = row['xp']
            level = row['level']

Usando psycopg2 em vez de asyncpg

Se seu bot não for assíncrono ou você preferir uma configuração mais simples, use psycopg2. A principal diferença é que você chama cursor.execute() em vez de await connection.execute(). Exemplo:

import psycopg2

conn = psycopg2.connect(
    user='bot_user',
    password='sua_senha',
    database='discord_bot',
    host='localhost',
    port=5432
)
cursor = conn.cursor()
cursor.execute('SELECT * FROM user_xp')
rows = cursor.fetchall()

Lembre-se de chamar conn.commit() após operações INSERT, UPDATE ou DELETE, e cursor.close() e conn.close() quando terminar.

Erros Comuns e Como Evitá-los

Tempo Limite de Conexão ao Iniciar o Bot

Se seu bot falhar ao conectar ao Postgres, verifique se o servidor de banco de dados está em execução e aceitando conexões. Verifique o host e a porta. Se estiver usando um banco de dados remoto, certifique-se de que o endereço IP está na lista de permissões nas configurações de firewall do provedor de nuvem.

Erros de Chave Duplicada ao Inserir

Ao inserir dados para um usuário que já existe, você obtém um erro de chave duplicada. Use ON CONFLICT DO UPDATE (UPSERT) para atualizar a linha existente em vez de falhar. O exemplo no passo 6 mostra esse padrão.

Bot Falha Após Consulta ao Banco de Dados

Uma exceção não tratada durante uma consulta ao banco de dados pode derrubar seu bot. Envolva todas as operações de banco de dados em blocos try-except. Use async with bot.db_pool.acquire() as conn: para garantir que as conexões sejam retornadas ao pool mesmo em caso de erro.

Dados Não Salvos Após Reinicialização

Se você usar psycopg2 e esquecer de chamar conn.commit(), as alterações não serão salvas no banco de dados. Sempre faça commit após operações de escrita. Para asyncpg, os commits ocorrem automaticamente dentro do método execute.

Opções de Banco de Dados para Bot do Discord: PostgreSQL vs SQLite vs JSON

Item PostgreSQL SQLite Arquivo JSON
Conexões simultâneas Ilimitadas Um escritor, vários leitores Não suportado
Integridade dos dados Compatível com ACID Compatível com ACID Sem integridade embutida
Linguagem de consulta SQL completo SQL completo Nenhuma linguagem de consulta
Complexidade de configuração Requer instalação de servidor Baseado em arquivo, sem servidor Sem configuração
Melhor para Bots grandes, múltiplas instâncias Bots pequenos de instância única Protótipos e testes

PostgreSQL é a melhor escolha para bots de produção que precisam lidar com muitos usuários e comandos sem perda de dados. SQLite funciona para bots pessoais pequenos. Arquivos JSON são adequados apenas para testes rápidos, pois não conseguem lidar com gravações simultâneas e são lentos para grandes conjuntos de dados.

Agora seu bot do Discord pode armazenar dados permanentemente usando PostgreSQL. Comece executando o bot com a conexão ao banco de dados e teste o comando /add_xp. Em seguida, adicione mais tabelas para configurações de servidor ou logs de moderação. Para desempenho avançado, considere usar pool de conexões com tamanhos mínimo e máximo para lidar com alto tráfego.