> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ghosting.fun/llms.txt
> Use this file to discover all available pages before exploring further.

# Bot Discord: consulte perfis Ghosting com Discord.js v14

> Crie um slash command /ghosting no Discord.js v14 que consulta perfis da API Ghosting. Inclui tratamento de perfis ativos, suspensos e não encontrados.

Este guia mostra como criar um slash command `/ghosting` em Discord.js v14 que consulta a API pública Ghosting e exibe o perfil como embed. O exemplo trata os três cenários possíveis: perfil ativo, perfil suspenso (que retorna `HTTP 200 OK`) e perfil não encontrado.

**1. Instale as dependências**

Seu projeto precisa de Discord.js v14 e Node.js 18+ (para `fetch` nativo).

```bash theme={null}
npm install discord.js
```

**2. Crie o slash command**

Salve o arquivo abaixo em `commands/ghosting.js` (ou o caminho equivalente na sua estrutura de bot).

```javascript commands/ghosting.js theme={null}
const { SlashCommandBuilder, EmbedBuilder } = require("discord.js");

module.exports = {
  data: new SlashCommandBuilder()
    .setName("ghosting")
    .setDescription("Consulta informações de um usuário no Ghosting")
    .addStringOption(opt =>
      opt.setName("usuario")
        .setDescription("Nome de usuário no Ghosting (ex: ghosting)")
        .setRequired(true)
    ),

  async execute(interaction) {
    await interaction.deferReply();

    const rawUsername = interaction.options.getString("usuario");
    const username = rawUsername.trim().replace(/^@/, "");

    try {
      const res = await fetch(`https://ghosting.fun/api/v1/users/${username}`);
      const body = await res.json();

      if (!body.success || !body.data) {
        return interaction.editReply({
          content: `❌ O usuário **@${username}** não foi encontrado no Ghosting.`
        });
      }

      const user = body.data;

      // Tratamento especial para perfil suspenso (retorna 200 OK)
      if (user.status === "suspended") {
        const banEmbed = new EmbedBuilder()
          .setTitle(`⚠️ @${user.username} — Perfil Suspenso`)
          .setURL(user.pageUrl)
          .setColor("#ef4444")
          .setThumbnail(user.avatarUrl)
          .setDescription(
            `Este perfil foi suspenso pela moderação do Ghosting.\n\n` +
            `**Motivo:** ${user.banInfo?.reason || "Violação das Diretrizes da Comunidade"}\n` +
            `**Data:** ${user.banInfo?.bannedAt ? new Date(user.banInfo.bannedAt).toLocaleDateString("pt-BR") : "N/A"}`
          )
          .setFooter({ text: "Ghosting Moderação • API Pública" });

        return interaction.editReply({ embeds: [banEmbed] });
      }

      // Perfil ativo
      const embed = new EmbedBuilder()
        .setTitle(`${user.displayName} (@${user.username})`)
        .setURL(user.pageUrl)
        .setThumbnail(user.avatarUrl)
        .setDescription(user.bio || "*Nenhuma biografia informada.*")
        .setColor(user.badges.isOfficial ? "#22c55e" : "#3b82f6")
        .addFields(
          { name: "Visualizações", value: user.views.toLocaleString("pt-BR"), inline: true },
          { name: "Dias Ativo", value: `${user.accountAgeDays} dias`, inline: true },
          { name: "Verificado", value: user.badges.isVerified ? "✅ Sim" : "❌ Não", inline: true }
        )
        .setFooter({ text: "Ghosting API v1 • ghosting.fun" });

      if (user.avatarDecoration?.url) {
        embed.setAuthor({
          name: `Moldura: ${user.avatarDecoration.name}`,
          iconURL: user.avatarDecoration.url
        });
      }

      return interaction.editReply({ embeds: [embed] });

    } catch (err) {
      console.error("Erro no comando /ghosting:", err);
      return interaction.editReply({
        content: "❌ Ocorreu um erro interno ao consultar a API do Ghosting."
      });
    }
  },
};
```

**3. Registre e teste**

Registre o comando no Discord (guild ou global) usando o script de deploy que já faz parte do seu bot, e teste digitando `/ghosting usuario:ghosting` em qualquer canal.

> [!NOTE]
>
> O bloco de código verifica `user.status === "suspended"` porque a API retorna `HTTP 200 OK` mesmo para perfis suspensos. Não use apenas `res.ok` para decidir se o perfil está acessível. Veja [Arquitetura de moderação](/guias/moderacao.md) para detalhes.

> [!TIP]
>
> Se preferir exibir o motivo formatado, use `user.banInfo.message` em vez de `user.banInfo.reason`. O campo `message` já vem com uma frase pronta para exibição em interfaces públicas.

## Próximos passos

> **[Exemplos de código](/guias/exemplos-codigo.md)**
>
> Snippets em outras linguagens (Python, cURL, Axios).

> **[Schema User](/schemas/user.md)**
>
> Todos os campos do objeto de perfil.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.