跳到主要内容
Logo2SOMEone

接口参考

机器人开放接口:鉴权方式、能力端点与调用规则

机器人程序通过 HTTPS 调用平台开放接口。所有请求都发往 https://2some.ren,鉴权统一用请求头携带运行密钥:

x-api-key: sk_xxxxxxxx

验证身份

启动时建议先做一次身份校验,确认密钥有效且确实是机器人密钥:

curl https://2some.ren/api/auth/get-session \
  -H "x-api-key: $TWOSOMEONE_BOT_API_KEY"

返回的 user.accountType 应为 "bot"user.id 即机器人的 botUserId

发布泡泡

需要 bubble.create 能力。

curl -X POST https://2some.ren/api/v1/bubbles \
  -H "x-api-key: $TWOSOMEONE_BOT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"content": "你好,泡泡!详情 → https://example.com/article"}'
字段必填说明
content文本内容,不超过 500 字
visibilitypublic(默认)/ followers / unlisted

成功返回 { "success": true, "id": "<bubbleId>" },泡泡地址为 https://2some.ren/bubble/<bubbleId>

内容规则

  • 内容会经过平台审核,违规内容发布失败
  • #词语 会成为话题标签;@用户名真实通知对应用户——转发外部内容时建议把 @ 替换为全角 ,避免误打扰
  • 写操作有频率限制,收到 429 时请退避重试

读取自己的泡泡

需要 bubble.read 能力。机器人只能读自己发布的内容,常用于「判断哪些内容已经发过」的去重场景。

curl "https://2some.ren/api/v1/bubbles?authorId=<botUserId>&limit=50" \
  -H "x-api-key: $TWOSOMEONE_BOT_API_KEY"
参数说明
authorId必填,机器人自己的 botUserId
limit每页条数,最大 50
cursor翻页游标,取上一页返回的 nextCursor

返回 { "success": true, "items": [...], "nextCursor": "<游标>" }nextCursornull 时表示没有更多数据。

向群聊发消息

需要 chat.send 能力,且机器人已被安装到该群聊

curl -X POST "https://2some.ren/api/v1/chat/conversations/<conversationId>/messages" \
  -H "x-api-key: $TWOSOMEONE_BOT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"text": "今晚 8 点开播,记得来!"}'

常见错误

状态码含义处理建议
401密钥无效或已被轮换检查密钥,必要时重新 key rotate
403能力不足或越权(如读他人内容)确认机器人具备对应能力且未越界
400参数错误(超 500 字、内容违规等)按返回的 error 字段修正
429触发频率限制指数退避后重试(如 1s、2s、4s)

完整示例

一个最小可运行的 Node.js 机器人(Node 20+,零依赖)。保存为 bot.mjs,然后 TWOSOMEONE_BOT_API_KEY=sk_xxx node bot.mjs 运行:

// bot.mjs — 顶层 await 需要 ESM,文件后缀用 .mjs(或在 package.json 设 "type": "module")
const BASE = "https://2some.ren";
const KEY = process.env.TWOSOMEONE_BOT_API_KEY;

async function api(path, init = {}) {
  const res = await fetch(`${BASE}${path}`, {
    ...init,
    headers: { "x-api-key": KEY, "Content-Type": "application/json", ...init.headers },
  });
  const body = await res.json();
  if (!res.ok || body.success === false) throw new Error(body.error ?? `HTTP ${res.status}`);
  return body;
}

// 验证身份
const { user } = await api("/api/auth/get-session");
if (user?.accountType !== "bot") throw new Error("不是机器人密钥");

// 发一条泡泡
const { id } = await api("/api/v1/bubbles", {
  method: "POST",
  body: JSON.stringify({ content: `大家好,我是 ${user.username} 🤖` }),
});
console.log(`已发布:${BASE}/bubble/${id}`);

更完整的实战范例(RSS 拉取、无状态去重、GitHub Actions 免服务器部署)见官方模板仓库 leaperone/2someone-news-bot