Bluesky.bot

Crea un bot en TypeScript

Esta guía escribe un bot que publica en Bluesky con @atproto/api, el SDK oficial de TypeScript. Funciona con Node.js 20 o posterior.

1. Crea una contraseña de aplicación

Inicia sesión en Bluesky como el bot, abre Ajustes → Privacidad y seguridad → Contraseñas de aplicación y crea una. Un bot inicia sesión con una contraseña de aplicación, nunca con la contraseña principal de la cuenta: puedes revocarla en cualquier momento sin tocar la cuenta.

2. Prepara el proyecto

bash
mkdir my-bot && cd my-bot
npm init -y
npm pkg set type=module
npm install @atproto/api
npm install --save-dev tsx typescript

Mantén las credenciales fuera del código, en variables de entorno:

bash
export BLUESKY_HANDLE="weather.bluesky.bot"
export BLUESKY_APP_PASSWORD="xxxx-xxxx-xxxx-xxxx"

3. Escribe el bot

bot.ts
// bot.ts: publica una vez como el bot. Ejecútalo con `npx tsx bot.ts`.
import { AtpAgent, RichText } from "@atproto/api";

// La propia cuenta del bot, con sesión iniciada con una contraseña de aplicación
// (Ajustes > Privacidad y seguridad > Contraseñas de aplicación),
// nunca con su contraseña principal.
const identifier = process.env.BLUESKY_HANDLE ?? "";
const password = process.env.BLUESKY_APP_PASSWORD ?? "";
if (!identifier || !password) {
  throw new Error("Set BLUESKY_HANDLE and BLUESKY_APP_PASSWORD.");
}

const agent = new AtpAgent({ service: "https://bsky.social" });
await agent.login({ identifier, password });

// RichText encuentra enlaces, menciones y hashtags para hacerlos clicables.
const text = new RichText({
  text: "Today: sunny, 21°C. Forecast at https://example.com #weather",
});
await text.detectFacets(agent);

const { uri } = await agent.post({
  text: text.text,
  facets: text.facets,
  createdAt: new Date().toISOString(),
});
console.log(`Posted ${uri}`);

Qué hace:

  • AtpAgent habla con https://bsky.social, el servidor de las cuentas alojadas por Bluesky. Si el bot vive en otro servidor (un PDS propio), usa la URL de ese servidor.
  • login abre una sesión con el handle y la contraseña de aplicación.
  • RichText y detectFacets convierten el enlace y #weather en facets clicables: un text normal los mostraría como caracteres sin más.
  • post crea el post y devuelve su URI at://.

4. Ejecútalo

bash
npx tsx bot.ts

Errores que conviene gestionar

  • Límites de uso: Bluesky responde 429 cuando una cuenta o un servidor hace demasiado. Espera y vuelve a intentarlo más tarde; consulta las Buenas prácticas.
  • Credenciales caducadas: una contraseña de aplicación revocada hace que login falle. Crea una nueva.
  • Posts largos: un post admite 300 caracteres (grafemas). Recorta el texto más largo o publica un hilo.

Siguientes pasos