Pular para o conteúdo

Migrando um App

Um mapa de conceitos para quem já escreveu bot em outra plataforma. Você vai reconhecer o terreno; o código, você reescreve.

Identidade e credencial

AquiO que muda de verdade
ApplicationApp
Bot userO App instaladoLá são duas entidades (application e bot user); aqui é uma. O App instalado num servidor é um membro: aparece na lista, recebe cargos, assina as mensagens que escreve, reage e responde à hierarquia. O que some é o segundo id — o client_id e o "id do bot" viram um número só, o Application ID.
discord.js / biblioteca de comunidade@trivo/sdkOficial e única: não existe "a biblioteca X ou a Y", e um App de produção não é construído por fora dela. Ela sobe junto com o servidor, e o contrato que ela expõe É o contrato.
Bot tokentrivo_app.<AppID>.<segredo>Uma por App, mostrada uma vez, esquema Bearer.
Client secretNão existe — o que existe é a segunda credencialLá ele serve à troca de código por token, e aqui não há o que trocar: não existe delegação de usuário, e o App age sempre como ele mesmo. O que o Trivo tem é uma segunda vaga de credencial do mesmo tipo, para rotacionar sem janela de queda — emita a nova, suba o processo com ela, revogue a velha. Não é um segredo com outro poder, e o nome não finge que é.
SnowflakeId públicoMesma ideia, e a mesma serialização em string.
GuildServidor

Permissões e escopos

AquiO que muda de verdade
Bitfield de permissõesPermissões nomeadasNomes em texto, não bits. Nada de somar potências de dois.
Escopos OAuthEscopos da instalaçãoEles são o teto. E há uma regra que não existe lá: capacidade = cargos ∩ escopos.
Permissão por canalVisibilidade + capacidades do canalSão dois eixos, e não um: ver o canal é lista aditiva de contas e cargos (quem está fora nem recebe os eventos daquele canal), e o que se faz lá dentro é uma escada de capacidades com allow e deny, herdada da categoria. Duas diferenças de lá: deny de cargo nomeado vence allow de outro cargo, e administrador não é curinga dentro do canal. O teto continua valendo: nenhum override amplia um App além dos escopos da instalação.

Gateway

AquiO que muda de verdade
Identify / Hello / ReadyUma requisiçãoBearer no cabeçalho, e o primeiro quadro já é evento. Sem aperto de mão.
Heartbeat com confirmaçãoBatimento do servidor a cada 25 sSentido inverso: não há nada a responder, e quem detecta o silêncio é você.
Sequência de eventoO campo id: do SSEDo protocolo, não nosso.
ResumeLast-Event-IDTambém do protocolo. Janela de 500 eventos ou 120 segundos.
Códigos de fechamentoconnection_closeUm quadro antes do fim, com code, motivo legível e reconnect. Texto, não número.
Bitfield de intents?intents= com nomesAusente entrega o padrão; presente e vazio é recusa que ensina.
Intents privilegiadasNenhuma família é sensível hojeA intent aqui é otimização de banda, e a fronteira é a instalação mais o funil de visibilidade — nunca a declaração do cliente. A sensibilidade é um eixo próprio no desenho, separado de escopo e de permissão; quando a primeira família sensível existir, ela pedirá aprovação num bloco à parte da autorização.
Comandos pelo gatewayNão existemTudo o que o App faz, faz pela REST.
ShardingNão existe

Interações

AquiO que muda de verdade
Deferred responseResposta diferidaPrazo menor, e o marcador "pensando" só quem acionou vê.
FollowupSeguimentoJanela de 10 minutos, teto de 5.
Ephemeral flagResposta privadaNão é mensagem: é evento endereçado, e não persiste.
Interactions endpoint + assinaturaO mesmo conceitoChave pública da plataforma — uma só, não uma por App. Assine sobre o corpo cru, como lá. O que muda: o destinatário está DENTRO do material assinado, e é isso que impede um App de tratar como sua uma interação assinada para outro.
Webhook de entradaNão existe

Comandos e componentes

AquiO que muda de verdade
Slash commandComando de barraRegistrado por app.rest.createCommand(…), e vale na hora: não há a espera de propagação global que você conhece.
Command optionsArgumentosMesmos tetos, por familiaridade. Tipo, obrigatoriedade, faixa e lista fechada.
Subcommand groupGrupo de subcomandoMesma profundidade: um nível.
AutocompleteAutocompletarPrazo bem menor — 1 s, não 3 —, e a resposta é suggest com choices. Nada que você faça ali vira erro na tela de quem digita.
User/message context commandComando sobre pessoa / sobre mensagemNos menus de clique direito que já existem.
Buttons / select menusComponentesVocabulário fechado, e quem renderiza é o cliente. Nada de HTML nem CSS — o catálogo está em Componentes e formulários.
ModalFormulárioA definição viaja na resposta e fica gravada na interação — é contra ela que o envio é conferido.
EmbedComponente cardUm vocabulário rico só no produto inteiro, e não dois: o cartão é o mesmo bloco que a pessoa vê quando alguém compartilha um link.
Monetização, diretório de Apps, Apps de usuário, ActivitiesNão existemE não há data prometida para nenhum deles.

As seis coisas que vão te surpreender

1. Não existe conta de robô — mas existe membro

Não há conta, senha, e-mail nem login — e ainda assim o seu App é membro de verdade do servidor onde foi instalado: aparece na lista, recebe cargos, assina o que escreve e responde à hierarquia como qualquer um.

O selo APP na tela deriva de um booleano que o servidor manda, e não do nome que você escolheu: chamar o seu App de "Fulano" não engana ninguém, e nenhum nome de exibição produz a pílula.

2. Cargo poderoso não amplia credencial

Um admin pode dar administrador ao seu App. Sem o escopo autorizado na instalação, isso não produz nada. É a regra da interseção, e ela existe para que "instalei com escopo pequeno" continue valendo depois que alguém mexe nos cargos.

3. Você não alcança conversa privada. Nunca.

E não é configuração: são três camadas independentes — nenhuma moldura de /api/me/* aceita Bearer, o Gateway roteia DM por id de conta (que App não tem), e a DM é cifrada ponta a ponta. O metadado de quem fala com quem é justamente o que o funil protege.

4. A resposta privada não é uma mensagem

Ela não fica no histórico de ninguém, nem no seu. Não há retenção, não há exclusão de conta que a alcance, não há moderação sobre ela — porque não há linha.

5. O 404 não distingue

"Servidor não existe", "você não está instalado nele" e "o id está torto" respondem a mesma coisa. É anti-oráculo, e é de propósito: distinguir entregaria informação a quem sonda.

6. Se você só responde a comandos, prefira o endpoint HTTP

O Gateway é uma conexão viva num processo só, e são 2 vagas por App — elas são suas, e ninguém as disputa com você. O que é dividido com todo mundo é o teto global de 50 conexões no gateway inteiro. Quem responde a comando não precisa de fluxo aberto: o caminho é Endpoint de interações.

O que esta página NÃO promete

  • Nenhuma tradução automática de payload, nem adaptador de biblioteca.
  • Nenhuma paridade de campo: os nomes são outros, e não vão mudar para se parecer com os de fora.
  • Nenhum cronograma para o que não existe.

O que hoje não existe, e está registrado como decisão e não como esquecimento: monetização, diretório de Apps, Apps instaláveis por usuário, atividades embutidas, webhook de saída, hierarquia de App e verificação de App.

O que existe e ninguém espera encontrar aqui: a moderação da plataforma pode suspender ou banir um App, e pode revogar a credencial dele sem excluí-lo. Nos dois casos o Gateway fecha com reconnect: false APP_SANCTIONED ou CREDENTIAL_REVOKED — e a REST passa a responder 401 igual a token inválido. Trate os dois como "pare e avise um humano".