签到机器人接入说明
面向站外开发者。读完本文即可实现一个每日签到机器人,无需阅读本站源码。
本文是签到接口的唯一对外口径。字段、错误码、语义均照实抄录, 若与源码不符以源码为准(但也请提 issue —— 那就是本文过期了)。
0. 一句话说清
POST /api/checkin —— 一个请求签一次到,固定领 3 条小鱼干,每人每天一次。
没有第二步:建签到记录与发鱼干在服务端的同一个事务里完成,要么都成、要么都没有。
三个前置条件(都满足才签得动):① 账号是 core+;② 名下至少有一篇未删除的文章;③ 未被禁言。
第二个是 2026-10 加的,见 §1.1。不满足时 POST 一律 403,GET 会用 can_check_in: false 告诉你。
⚠️ 2026-09 起,「两步式(签到 → 翻牌定命)」已废除。 若你手上是旧版本文档 / 旧代码,它描述的是:先
POST /api/checkin建记录,再POST /api/checkin/claim翻一张牌,牌面数字(1–5)决定当天拿多少鱼干。那一步连同chosenIndex、fortune_value/fortune_label/fortune_pending/total_fortune/show_fortune全部下线,POST /api/checkin/claim现在返回 404。旧代码通常不会炸得很响:按
fortune_pending分支的写法会静默跳过第二步 (字段不存在 →undefined→ 假),结果正好是对的(一步式下签完就到账)。 但请把调用 claim 的那段删掉 —— 它现在只会拿到 404。
📌 本文自包含。账号准备(注册 / 提权)与鉴权(cookie)是全部机器人共用的前置步骤, 三份完整口径见
docs/bot/chat-bot.md§2 与 §3 —— 本文 §2 只给最小可跑的部分。
1. 能力边界(先读这段)
| 范围 | 能读 | 能写 | 说明 |
|---|---|---|---|
| 签到领鱼干 | —— | ✅ | 需 core+,每人每天一次,固定 3 条 |
| 查自己今天的签到状态 | ✅ | ❌ | GET /api/checkin |
| 查别人的签到 | ❌ | ❌ | 没有这类接口(排行榜是另一回事,见 §6.2) |
| 补签 / 撤销 / 重签 | ❌ | ❌ | 没有这类接口,签了就是签了 |
⚠️ 签到是 core+ 专属。 非核心账号(
user)不但拿不到鱼干, 连签到接口都进不去(403 需要核心用户权限)—— 本站的鱼干是 core+ 体系的报酬, 全站没有「注册就有鱼干」的渠道。这是刻意的,别指望用脚本刷出来。
⚠️ 机器人享受不到任何豁免:它同样会被禁言、同样受每日一次的限制约束。 禁言期间不开放新的鱼干赚取,签到 POST 返回
403 你已被禁言,暂时无法签到, GET 仍可读取状态,但can_check_in: false。禁言到期后按通常门槛恢复。
1.1 还得发布过文章(2026-10 起)
名下必须至少有一篇未删除的文章,否则签不了。判断口径:
- 「文章」指你以作者身份发布过的任意一篇博客,任何可见性档(仅站内 / 链接可读 / 公开)都算;
- 发过又全部删除 = 没发过 —— 判据只看此刻还活着的文章,不看历史。删掉的不算数。
💡 对机器人的含义:先发文,再签到。发文接口见
docs/bot/chat-bot.md对应章节 (核心用户即可发布)。新号从注册到能签到,中间要跨过「发表一篇」这一步。
⚠️ 这是刻意的门槛,为的是抬高批量空号的成本。别指望用一堆只签到、从不产出的号 刷鱼干 —— 那种号现在连门都进不去。
2. 准备账号与鉴权
签到接口全部需要 core+ 且登录。注册出来是 user,要提权一次:
- 注册时带有效邀请码 → 直接是 core(推荐,全自动);
- 让站长在服务器上执行:
npm run cli -- promote-core mybot
完整流程(注册字段、人机验证、错误码)见 docs/bot/chat-bot.md §2。
然后以这个账号发布一篇文章 —— 这是签到的第二个前置条件(§1.1)。发文接口见
docs/bot/chat-bot.md。跳过这一步,签到会一直 403 发布过文章后才能签到。
登录换 cookie:
POST /api/auth/login
Content-Type: application/json
{ "username": "mybot", "password": "********" }
响应会 Set-Cookie: raricy_session=<JWT>(HttpOnly、SameSite=Lax、30 天)。
之后每个请求带上 Cookie: raricy_session=<JWT> 即可。
⚠️ 写请求会校验来源,跨站会被拦成
403 跨源请求被拒绝 (CSRF)。 非浏览器客户端本来就不发Origin/Referer,天然通过 —— 不要自作主张伪造一个。
会话失效(改密、被强制下线、被禁言 / 重置密码)后一律
401 请先登录—— 当成「重新登录」的信号,而不是重试。⚠️ 被降权(core → user)不属于会话失效 —— 会话仍有效,只是签到接口改回
403 需要核心用户权限。重登解决不了这个(那是档位问题,不是登录问题)。
3. 「今天」是本站时区的今天
签到按 UTC+8 的零点切分,不是 UTC 零点,也不是你机器的本地时区。
响应里的 today 就是服务端认的那个日期("2026-09-27")。
✅ 一步式之后没有「跨午夜作废」这种坑了。 旧版两步式有:23:59 签了到、 00:00 之后才去翻牌 —— 翻牌按「今天」查不到那条记录,那一天的奖励就丢了。 现在「签到」与「发鱼干」是同一个请求里的一件事, 你按下请求的那一刻,要么今天已经签过、要么这一次签成了,不存在中间态。
📌 另外,鱼干流水里的时间戳是「UTC+8 墙上时间贴
Z标签」的假 Z, 口径与其他接口一致,见docs/bot/comment-bot.md§5。
4. 签到
POST /api/checkin
Cookie: raricy_session=<JWT>
没有请求体。成功:
{
"code": 200,
"message": "签到成功!获得 3 条小鱼干",
"total_count": 37,
"reward_fish": 3,
"today_fish": 3,
"dried_fish": 41.5
}
| 字段 | 说明 |
|---|---|
total_count |
累计签到天数(含今天) |
reward_fish |
这一次发了多少 —— 固定 3,直接照这个字段用,别在代码里写死 |
today_fish |
今天到手的签到鱼干(正常就等于 reward_fish) |
dried_fish |
当前鱼干余额(省掉一次余额查询) |
4.1 今天已经签过了
注意:已签到返回的是 400,不是 200。
{
"code": 400,
"message": "今天已签到",
"already_checked": true,
"total_count": 37,
"reward_fish": 3,
"today_fish": 3,
"dried_fish": 41.5
}
⚠️ 这是本站少见的「错误码里带数据」的接口 —— 除了
code/message, 它还给了already_checked与当前状态。看到already_checked: true不要重试: 它是终态,今天那 3 条早就到账了(today_fish就是它)。
📌 靠「签到返回 400」来判断今天签过没有是可以的,但那会让每天的正常运行 都带一条错误日志。更干净的做法是先
GET /api/checkin(§5)看checked_in。
4.2 会被拒绝的情形
| 情形 | 返回 |
|---|---|
| 未登录 / Cookie 失效 | 401 请先登录 |
| 账号不是 core+ | 403 需要核心用户权限 |
| 账号被禁言 | 403 你已被禁言,暂时无法签到 |
| 名下没有未删除的文章 | 403 发布过文章后才能签到(带 can_check_in: false,见 §1.1) |
| 今天已签到 | 400 今天已签到(带数据,见上) |
| 服务端故障 | 500 服务器开小差了,请稍后再试 —— 事务整体回滚,重发一次即可;若它其实已经成功,重发会拿到 400 今天已签到(照 §4.1 处理,别当成失败) |
| 旧版调用 | POST /api/checkin/claim → 404 —— 翻牌那一步已下线(§0) |
5. 查今天的状态
GET /api/checkin
Cookie: raricy_session=<JWT>
适合当每日任务的第一个请求 —— 用它决定今天要不要签。
{
"code": 200,
"message": "ok",
"checked_in": true,
"can_check_in": true,
"total_count": 37,
"today": "2026-09-27",
"reward_fish": 3,
"today_fish": 3,
"dried_fish": 41.5
}
| 字段 | 说明 |
|---|---|
checked_in |
今天签了没有 |
can_check_in |
够不够格签(core+、名下有一篇未删除的文章且未被禁言)。false 时 POST 必被拒—— 先去看前置条件,别重试 |
today |
服务端认的「今天」(UTC+8) |
reward_fish |
现在签一次给多少(当前的奖励数额,可能随站长调整而变) |
today_fish |
今天已经到手的签到鱼干;没签到是 0 |
dried_fish |
当前鱼干余额 |
⚠️
today_fish可以小于reward_fish(今天签到之前奖励是另一个数,或者更早年代的 历史行)。要用「今天到底到账多少」,读today_fish;要预估「现在签能拿多少」, 读reward_fish。 别拿一个去当另一个。
6. 鱼干这件事
6.1 每天固定 3 条,无其他签到收益
签到给的就是 reward_fish(当前是 3)条鱼干,没有「连续签到加成」「首签奖励」
这类东西。total_count(累计天数)只是统计,不参与结算。
⚠️ 数额以响应里的
reward_fish为准 —— 站长可能调整它,而调完之后同一份文档 描述的所有机器人都会照旧工作(只要你不把 3 写死在自己的代码里)。
⚠️ 签到是鱼干的来源之一,不是转账。 想给别人鱼干请走
docs/bot/fish-bot.md的转账接口 —— 签到没有任何「送给别人」的参数。
6.2 想看排名
GET /api/fish/leaderboard —— 免登录,返回小鱼干余额榜:按当前余额倒序,
字段 rank / user_id / username / avatar_path / balance。只读,与签到是两回事。
7. 失败只有两种,都不会「账记了一半」
签到是鱼干写路径:建记录、发鱼干、写流水在同一个事务里提交 —— 要么都生效、 要么都不存在。所以不存在「本地记了账、别处没记」这种没人知道的状态, 也没有「稍后会自己变好」的暂态。
📌 对机器人的含义,按状态码分两类:
4xx= 业务拒绝(400 今天已签到/403 需要核心用户权限/403 发布过文章后才能签到)—— 原样重试无用,要么改输入,要么先去补齐前置条件;500= 本站故障,事务已整体回滚,今天等于还没签 —— 原样重发即可; 若重发时这次其实已经成功过,你会拿到400 今天已签到(照 §4.1 处理)。两类都别写成循环:失败不会「多试几次就成」。
8. 限频
签到域没有任何 RULES 配额 —— 它是「每天一次」的自然节流:一天能成功的只有一次,
重复请求只会拿到 already_checked 的幂等响应。
⚠️ 但别拿它当心跳刷。它每天每账号最多产生 1 行记录 + 1 笔发鱼, 刷它除了浪费你自己的时间没有任何收益。
📌 别的域(点赞、投喂、转账…)各有各的配额,用哪个域就去读那份接入文档的 「限频」一节 —— 这里没有配额不代表那里也没有。
9. 礼仪与约定
- 签到是给自己签的,不产生任何通知、不影响别人。这大概是全站最不需要 「礼仪」的一段 —— 但同样别用多账号刷(那是在伪造 core+ 体系的报酬)。
- 机器人也不该替人签到。 本站没有「代签」接口,一个账号一份凭据; 拿别人的密码去签等于替他做了决定,且凭据泄露的后果由他承担。
10. 排错速查
| 现象 | 多半是 |
|---|---|
403 需要核心用户权限 |
账号还是 user,需要站长提权一次(§2) |
403 发布过文章后才能签到 |
名下没有未删除的文章 —— 先发一篇;发过又全删了也算没有(§1.1) |
403 你已被禁言,暂时无法签到 |
禁言期间不能签到,解除或到期后恢复 |
400 今天已签到 |
终态,别重试。那天的鱼干早已到账(§4.1) |
404 且路径是 /api/checkin/claim |
翻牌那一步已下线 —— 删掉你代码里的第二步(§0) |
reward_fish 不是我预期的数 |
以响应为准:奖励数额由站长调整,别写死在你的代码里(§6.1) |
签到成功但 today_fish 比 reward_fish 小 |
那是当天早些时候按旧数额发的(§5),不是漏发 |
500 |
本站故障(不是你的输入问题):事务已整体回滚,等于没签过,原样重发即可(§7) |
| 余额涨了但流水里没有 | 不可能:发鱼一定伴随流水。对账请走 docs/bot/fish-bot.md §3.3 的游标模式 |
| 时间差 8 小时 | 假的 Z,见 §3 |
11. 最小可用流程
const BASE = 'https://raricy.com';
const cookie = 'raricy_session=<JWT>'; // 登录见 chat-bot.md §3
// 先看今天的状态(省掉一次必然失败的 POST)
const st = await (await fetch(`${BASE}/api/checkin`, { headers: { cookie } })).json();
if (st.can_check_in === false) {
// 前置条件没满足(多为「名下没有未删除的文章」)—— 先去发一篇,重试无意义(§1.1)
console.warn('还不能签到:检查文章门槛和禁言状态');
} else if (!st.checked_in) {
const res = await fetch(`${BASE}/api/checkin`, { method: 'POST', headers: { cookie } });
const out = await res.json();
if (res.ok) {
console.log(`签到成功:+${out.reward_fish},今日共 ${out.today_fish},余额 ${out.dried_fish}`);
} else if (out.already_checked) {
// 并发 / 重复提交:今天早就签过了,终态
console.log(`今天已签到,今日到手 ${out.today_fish}`);
} else if (res.status === 500) {
// 本站故障,事务已整体回滚 —— 等于没签过,隔一会儿原样重发
} else {
console.error('签到失败', out.code, out.message);
}
}
断线 / 401 → 重新登录。429 → 签到域不会出现,但转账会遇到,见 docs/bot/fish-bot.md §4。