Pular para conteúdo

DISCORD_SEND_FILE - Enviar Arquivos e Mídias no Discord

O que é este Node?

O DISCORD_SEND_FILE é o node responsável por enviar arquivos, imagens, PDFs e documentos para canais do Discord, permitindo compartilhar mídias ricas junto com mensagens.

Por que este Node existe?

Compartilhamento de arquivos é essencial para colaboração e documentação em equipes. O DISCORD_SEND_FILE existe para:

  1. Compartilhar Documentos: Enviar PDFs, relatórios, spreadsheets para equipe
  2. Enviar Imagens: Postar screenshots, gráficos, diagramas automaticamente
  3. Backup e Arquivamento: Salvar arquivos importantes em canais dedicados
  4. Notificações com Comprovantes: Anexar recibos, comprovantes, faturas em notificações

Como funciona internamente?

Quando o DISCORD_SEND_FILE é executado, o sistema:

  1. Valida Autenticação: Verifica webhook URL ou bot token + channel ID
  2. Valida Files Array: Garante que pelo menos um arquivo foi especificado
  3. Cria FormData: Prepara multipart/form-data para upload
  4. Baixa Arquivos: Faz download de cada arquivo das URLs especificadas
  5. Anexa Streams: Adiciona streams de arquivo ao FormData com nomes corretos
  6. Adiciona Payload JSON: Inclui content, username, avatar se especificados
  7. Envia Upload: POST com headers multipart/form-data
  8. Retorna Resposta: Devolve mensagem com array de attachments

Código interno (discord-executor.service.ts:330-377):

private async sendFile(data: DiscordNodeData): Promise<any> {
  const form = new FormData();

  // Add message content
  if (data.content) {
    form.append('payload_json', JSON.stringify({
      content: data.content,
      username: data.username,
      avatar_url: data.avatarUrl
    }));
  }

  // Download and attach files
  for (let i = 0; i < data.files!.length; i++) {
    const file = data.files![i];
    try {
      const fileResponse = await axios.get(file.url, { responseType: 'stream' });
      form.append(`file${i}`, fileResponse.data, {
        filename: file.name,
        contentType: fileResponse.headers['content-type']
      });
    } catch (error) {
      this.logger.error(`Failed to download file from ${file.url}:`, error.message);
      throw new Error(`Failed to download file: ${file.name}`);
    }
  }

  if (data.authType === 'webhook') {
    const response: AxiosResponse = await axios.post(data.webhookUrl!, form, {
      headers: {
        ...form.getHeaders()
      }
    });
    return response.data;
  } else {
    const response: AxiosResponse = await axios.post(
      `${this.DISCORD_API_BASE}/channels/${data.channelId}/messages`,
      form,
      {
        headers: {
          'Authorization': `Bot ${data.botToken}`,
          ...form.getHeaders()
        }
      }
    );
    return response.data;
  }
}

Quando você DEVE usar este Node?

Use DISCORD_SEND_FILE sempre que precisar de envio de arquivos e mídias:

Casos de uso

  1. Relatórios Automáticos: "Gerar PDF de relatório mensal e enviar para canal de gestão"
  2. Screenshots de Erros: "Capturar screenshot de erro e postar em canal de bugs"
  3. Backups Diários: "Exportar dados como CSV e enviar para canal de backups"
  4. Comprovantes de Pagamento: "Enviar fatura PDF quando pagamento for confirmado"
  5. Gráficos e Visualizações: "Gerar gráfico de métricas e compartilhar com equipe"

Quando NÃO usar DISCORD_SEND_FILE

  • Mensagens Simples: Use DISCORD_SEND_MESSAGE para texto sem arquivos
  • Embeds Formatados: Use DISCORD_SEND_EMBED para conteúdo estruturado sem arquivos
  • Arquivos Muito Grandes: Discord limita a 8MB (Nitro: 100MB) - use serviço de storage
  • Múltiplas Mensagens: Limite de 10 arquivos por mensagem - divida se necessário

Parâmetros Detalhados

operation (string, obrigatório)

O que é: Define a operação como envio de arquivo.

Valor: "send_file"

Flow completo para testar:

{
  "name": "Teste Discord - Send File",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "discord_1",
      "type": "discord",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Enviar Arquivo",
        "parameters": {
          "operation": "send_file",
          "authType": "webhook",
          "webhookUrl": "https://discord.com/api/webhooks/SEU_WEBHOOK",
          "content": "Arquivo de teste enviado!",
          "files": [
            {
              "name": "imagem.png",
              "url": "https://i.imgur.com/exemplo.png"
            }
          ]
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Confirmar",
        "parameters": {
          "message": "Arquivo enviado com sucesso!"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 700, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "discord_1" },
    { "source": "discord_1", "target": "message_1" },
    { "source": "message_1", "target": "end_1" }
  ]
}

Teste: Execute o flow e verifique se a imagem foi enviada no Discord.

files (array, obrigatório)

O que é: Array de objetos com informações dos arquivos a serem enviados.

Estrutura:

{
  "name": "nome-do-arquivo.ext",
  "url": "https://url-publica-do-arquivo.com/arquivo.ext",
  "description": "Descrição opcional do arquivo"
}

Limite: 10 arquivos por mensagem, 8MB por arquivo (100MB com Nitro)

Flow completo para testar:

{
  "name": "Teste Discord - Files Array",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "discord_1",
      "type": "discord",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Enviar Múltiplos Arquivos",
        "parameters": {
          "operation": "send_file",
          "authType": "webhook",
          "webhookUrl": "https://discord.com/api/webhooks/SEU_WEBHOOK",
          "content": "📎 Relatório mensal com anexos:",
          "files": [
            {
              "name": "relatorio-janeiro.pdf",
              "url": "https://example.com/relatorio-janeiro.pdf",
              "description": "Relatório completo de Janeiro"
            },
            {
              "name": "grafico-vendas.png",
              "url": "https://example.com/grafico.png",
              "description": "Gráfico de vendas"
            },
            {
              "name": "dados.csv",
              "url": "https://example.com/dados.csv",
              "description": "Dados brutos exportados"
            }
          ]
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Confirmar",
        "parameters": {
          "message": "3 arquivos enviados com sucesso!"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 700, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "discord_1" },
    { "source": "discord_1", "target": "message_1" },
    { "source": "message_1", "target": "end_1" }
  ]
}

Teste: Três arquivos serão enviados juntos na mesma mensagem.

content (string, opcional)

O que é: Mensagem de texto que acompanha os arquivos.

Limite: 2000 caracteres

Flow completo para testar:

{
  "name": "Teste Discord - File Content",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "input_1",
      "type": "input",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Descrição do Arquivo",
        "parameters": {
          "message": "Digite uma descrição para o arquivo:",
          "variableName": "descricao"
        }
      }
    },
    {
      "id": "discord_1",
      "type": "discord",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Enviar com Descrição",
        "parameters": {
          "operation": "send_file",
          "authType": "webhook",
          "webhookUrl": "https://discord.com/api/webhooks/SEU_WEBHOOK",
          "content": "📄 **Novo Documento**\n\n{{descricao}}\n\n*Enviado automaticamente pelo sistema*",
          "files": [
            {
              "name": "documento.pdf",
              "url": "https://example.com/documento.pdf"
            }
          ]
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Confirmar",
        "parameters": {
          "message": "Arquivo enviado com descrição personalizada!"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 900, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "input_1" },
    { "source": "input_1", "target": "discord_1" },
    { "source": "discord_1", "target": "message_1" },
    { "source": "message_1", "target": "end_1" }
  ]
}

Teste: Digite uma descrição e verifique se aparece junto com o arquivo no Discord.

username (string, opcional - apenas webhook)

O que é: Nome customizado que aparecerá como remetente. Só funciona com webhooks.

Flow completo para testar:

{
  "name": "Teste Discord - File Username",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "discord_1",
      "type": "discord",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Enviar como Bot Backup",
        "parameters": {
          "operation": "send_file",
          "authType": "webhook",
          "webhookUrl": "https://discord.com/api/webhooks/SEU_WEBHOOK",
          "content": "💾 Backup diário gerado com sucesso",
          "username": "Sistema de Backup",
          "files": [
            {
              "name": "backup-2025-01-15.zip",
              "url": "https://example.com/backup.zip"
            }
          ]
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 500, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "discord_1" },
    { "source": "discord_1", "target": "end_1" }
  ]
}

Teste: Arquivo aparecerá como enviado por "Sistema de Backup".

avatarUrl (string, opcional - apenas webhook)

O que é: URL da imagem do avatar customizado. Só funciona com webhooks.

Flow completo para testar:

{
  "name": "Teste Discord - File Avatar",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "discord_1",
      "type": "discord",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Enviar com Avatar",
        "parameters": {
          "operation": "send_file",
          "authType": "webhook",
          "webhookUrl": "https://discord.com/api/webhooks/SEU_WEBHOOK",
          "content": "📊 Relatório semanal anexado",
          "username": "Bot Relatórios",
          "avatarUrl": "https://i.imgur.com/report-bot-icon.png",
          "files": [
            {
              "name": "relatorio-semanal.pdf",
              "url": "https://example.com/relatorio.pdf"
            }
          ]
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 500, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "discord_1" },
    { "source": "discord_1", "target": "end_1" }
  ]
}

Teste: Arquivo será enviado com avatar customizado no perfil.

Parâmetros

Campo Tipo Obrigatório Descrição
operation string Sim Deve ser "send_file"
authType string Sim "webhook" ou "bot"
webhookUrl string Sim (webhook) URL do webhook Discord
botToken string Sim (bot) Token do bot Discord
channelId string Sim (bot) ID do canal Discord
files array Sim Array de objetos
content string Não Mensagem de texto com os arquivos
username string Não Nome customizado (webhook only)
avatarUrl string Não Avatar URL (webhook only)

Exemplo 1: Envio Automático de Relatório PDF

Objetivo: Gerar e enviar relatório PDF diário para canal de gestão.

JSON para Importar

{
  "name": "Discord - Relatório PDF Diário",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "variable_1",
      "type": "variable",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Data",
        "parameters": {
          "name": "data",
          "value": "15/01/2025"
        }
      }
    },
    {
      "id": "variable_2",
      "type": "variable",
      "position": { "x": 300, "y": 200 },
      "data": {
        "label": "URL do Relatório",
        "parameters": {
          "name": "pdfUrl",
          "value": "https://storage.lumina.app.br/relatorios/2025-01-15.pdf"
        }
      }
    },
    {
      "id": "variable_3",
      "type": "variable",
      "position": { "x": 300, "y": 300 },
      "data": {
        "label": "Total Vendas",
        "parameters": {
          "name": "totalVendas",
          "value": "R$ 45.890,00"
        }
      }
    },
    {
      "id": "discord_1",
      "type": "discord",
      "position": { "x": 500, "y": 200 },
      "data": {
        "label": "Enviar Relatório",
        "parameters": {
          "operation": "send_file",
          "authType": "webhook",
          "webhookUrl": "https://discord.com/api/webhooks/SEU_WEBHOOK",
          "content": "📊 **RELATÓRIO DIÁRIO - {{data}}**\n\n💰 Total em vendas: **{{totalVendas}}**\n📈 152 pedidos processados\n👥 23 novos clientes\n\n📎 Relatório completo em PDF anexado abaixo.",
          "username": "Sistema de Relatórios",
          "avatarUrl": "https://i.imgur.com/report-icon.png",
          "files": [
            {
              "name": "relatorio-{{data}}.pdf",
              "url": "{{pdfUrl}}",
              "description": "Relatório completo de vendas e métricas"
            }
          ]
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 700, "y": 200 },
      "data": {
        "label": "Confirmar",
        "parameters": {
          "message": "✅ Relatório de {{data}} enviado para equipe!"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 900, "y": 200 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "variable_1" },
    { "source": "variable_1", "target": "variable_2" },
    { "source": "variable_2", "target": "variable_3" },
    { "source": "variable_3", "target": "discord_1" },
    { "source": "discord_1", "target": "message_1" },
    { "source": "message_1", "target": "end_1" }
  ]
}

Saída esperada no Discord:

[Avatar: ícone de relatório]
Sistema de Relatórios

📊 RELATÓRIO DIÁRIO - 15/01/2025

💰 Total em vendas: R$ 45.890,00
📈 152 pedidos processados
👥 23 novos clientes

📎 Relatório completo em PDF anexado abaixo.

[Anexo: relatorio-15/01/2025.pdf - 2.3 MB]

Exemplo 2: Screenshot de Erro Automático

Objetivo: Capturar e enviar screenshot de erro para canal de debugging.

JSON para Importar

{
  "name": "Discord - Screenshot de Erro",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "variable_1",
      "type": "variable",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Erro ID",
        "parameters": {
          "name": "errorId",
          "value": "ERR-2025-001"
        }
      }
    },
    {
      "id": "variable_2",
      "type": "variable",
      "position": { "x": 300, "y": 200 },
      "data": {
        "label": "Mensagem Erro",
        "parameters": {
          "name": "errorMsg",
          "value": "Database connection timeout"
        }
      }
    },
    {
      "id": "variable_3",
      "type": "variable",
      "position": { "x": 300, "y": 300 },
      "data": {
        "label": "Screenshot URL",
        "parameters": {
          "name": "screenshotUrl",
          "value": "https://storage.lumina.app.br/errors/screenshot-001.png"
        }
      }
    },
    {
      "id": "discord_1",
      "type": "discord",
      "position": { "x": 500, "y": 200 },
      "data": {
        "label": "Reportar Erro",
        "parameters": {
          "operation": "send_file",
          "authType": "bot",
          "botToken": "SEU_BOT_TOKEN",
          "channelId": "ID_CANAL_BUGS",
          "content": "🚨 **ERRO CRÍTICO DETECTADO**\n\n🆔 ID: `{{errorId}}`\n❌ Erro: `{{errorMsg}}`\n⏰ Timestamp: <t:1705329000:F>\n🖥️ Servidor: prod-server-01\n\n📸 Screenshot anexado para análise.\n\n@here",
          "files": [
            {
              "name": "error-{{errorId}}.png",
              "url": "{{screenshotUrl}}",
              "description": "Screenshot do erro capturado"
            }
          ]
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 700, "y": 200 },
      "data": {
        "label": "Confirmar",
        "parameters": {
          "message": "Erro {{errorId}} reportado para equipe de dev!"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 900, "y": 200 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "variable_1" },
    { "source": "variable_1", "target": "variable_2" },
    { "source": "variable_2", "target": "variable_3" },
    { "source": "variable_3", "target": "discord_1" },
    { "source": "discord_1", "target": "message_1" },
    { "source": "message_1", "target": "end_1" }
  ]
}

Saída esperada no Discord:

🚨 ERRO CRÍTICO DETECTADO

🆔 ID: ERR-2025-001
❌ Erro: Database connection timeout
⏰ Timestamp: 15 de janeiro de 2025 às 14:30
🖥️ Servidor: prod-server-01

📸 Screenshot anexado para análise.

@here

[Anexo: error-ERR-2025-001.png - 456 KB]
[Preview da imagem renderizado inline]

Exemplo 3: Backup com Múltiplos Arquivos

Objetivo: Enviar múltiplos arquivos de backup para canal de arquivamento.

JSON para Importar

{
  "name": "Discord - Backup Múltiplos Arquivos",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "variable_1",
      "type": "variable",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Timestamp",
        "parameters": {
          "name": "timestamp",
          "value": "2025-01-15-14h30"
        }
      }
    },
    {
      "id": "discord_1",
      "type": "discord",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Enviar Backup",
        "parameters": {
          "operation": "send_file",
          "authType": "webhook",
          "webhookUrl": "https://discord.com/api/webhooks/SEU_WEBHOOK",
          "content": "💾 **BACKUP COMPLETO - {{timestamp}}**\n\n✅ Backup realizado com sucesso\n📦 3 arquivos anexados:\n\n• Database dump (PostgreSQL)\n• Uploads e mídias\n• Configurações do sistema\n\n🔐 Todos os arquivos estão criptografados",
          "username": "Sistema de Backup",
          "avatarUrl": "https://i.imgur.com/backup-icon.png",
          "files": [
            {
              "name": "database-{{timestamp}}.sql.gz",
              "url": "https://storage.lumina.app.br/backups/db.sql.gz",
              "description": "Dump completo do banco de dados"
            },
            {
              "name": "uploads-{{timestamp}}.zip",
              "url": "https://storage.lumina.app.br/backups/uploads.zip",
              "description": "Arquivos de upload dos usuários"
            },
            {
              "name": "config-{{timestamp}}.tar.gz",
              "url": "https://storage.lumina.app.br/backups/config.tar.gz",
              "description": "Configurações e variáveis de ambiente"
            }
          ]
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Confirmar",
        "parameters": {
          "message": "Backup {{timestamp}} arquivado com sucesso! 💾"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 900, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "variable_1" },
    { "source": "variable_1", "target": "discord_1" },
    { "source": "discord_1", "target": "message_1" },
    { "source": "message_1", "target": "end_1" }
  ]
}

Saída esperada no Discord:

[Avatar: ícone de backup]
Sistema de Backup

💾 BACKUP COMPLETO - 2025-01-15-14h30

✅ Backup realizado com sucesso
📦 3 arquivos anexados:

• Database dump (PostgreSQL)
• Uploads e mídias
• Configurações do sistema

🔐 Todos os arquivos estão criptografados

[Anexo 1: database-2025-01-15-14h30.sql.gz - 45.2 MB]
[Anexo 2: uploads-2025-01-15-14h30.zip - 128.7 MB]
[Anexo 3: config-2025-01-15-14h30.tar.gz - 1.2 MB]

Resposta do Node

{
  "id": "1234567890123456789",
  "channel_id": "987654321098765432",
  "author": {
    "username": "Sistema de Backup",
    "avatar": "abc123"
  },
  "content": "💾 BACKUP COMPLETO...",
  "attachments": [
    {
      "id": "111111111111111111",
      "filename": "database-2025-01-15-14h30.sql.gz",
      "size": 47447040,
      "url": "https://cdn.discordapp.com/.../database.sql.gz",
      "proxy_url": "https://media.discordapp.net/.../database.sql.gz",
      "content_type": "application/gzip"
    },
    {
      "id": "222222222222222222",
      "filename": "uploads-2025-01-15-14h30.zip",
      "size": 134963200,
      "url": "https://cdn.discordapp.com/.../uploads.zip",
      "proxy_url": "https://media.discordapp.net/.../uploads.zip",
      "content_type": "application/zip"
    }
  ],
  "timestamp": "2025-01-15T14:30:00.000Z"
}

Boas Práticas

SIM:

  • Valide que URLs de arquivos são públicas e acessíveis
  • Use nomes descritivos com extensão correta (arquivo.pdf, not arquivo)
  • Inclua contexto na mensagem (o que é o arquivo, por que foi enviado)
  • Comprima arquivos grandes antes de enviar (ZIP, GZ)
  • Verifique tamanho antes de enviar (limite 8MB sem Nitro)
  • Use HTTPS para URLs de arquivos (nunca HTTP)
  • Adicione descrições úteis em cada arquivo
  • Organize backups em canais dedicados
  • Use webhooks para automações simples de arquivos
  • Combine com embed para contexto visual rico

NÃO:

  • Não tente enviar arquivos maiores que 8MB (100MB Nitro)
  • Não envie mais de 10 arquivos por mensagem
  • Não use URLs privadas/protegidas (download falhará)
  • Não hardcode URLs de storage (use variáveis)
  • Não esqueça extensões dos arquivos
  • Não envie arquivos sem contexto (sempre adicione content)
  • Não abuse do canal (respeite rate limits)
  • Não envie arquivos sensíveis sem criptografia
  • Não use URLs expiráveis sem validar antes
  • Não ignore erros de download de arquivos

Dicas

💡 Dica 1: O sistema faz download do arquivo da URL e então upload para Discord. Certifique-se que a URL é pública e não expira rapidamente.

💡 Dica 2: Imagens (PNG, JPG, GIF) são renderizadas inline no Discord. Outros tipos (PDF, ZIP) aparecem como download.

💡 Dica 3: Use serviços de storage (AWS S3, Google Cloud Storage) para hospedar arquivos antes de enviar ao Discord.

💡 Dica 4: Content-Type é detectado automaticamente do header da URL. Garanta que seu servidor responde corretamente.

💡 Dica 5: Para múltiplos arquivos, considere criar ZIP único se ultrapassar limite de 10 arquivos.

💡 Dica 6: Webhooks não têm rate limit tão rigoroso quanto bots para file upload.

💡 Dica 7: Use FORMATTER node para preparar array de files dinamicamente antes de enviar.

Próximo Node

DISCORD_SEND_MESSAGE - Enviar mensagens de texto simples → DISCORD_SEND_EMBED - Enviar embeds formatados → DISCORD_EDIT_MESSAGE - Editar mensagens existentes → DISCORD_DELETE_MESSAGE - Deletar mensagens