This is the full developer documentation for LANrurugi # LANrurugi 文档 > 以漫画为主、也能读 PDF / EPUB 等电子书的自托管书库,以 LANraragi 为起点、用 Rust + React 大幅改造与强化——现有 LANraragi 部署的数据与 API 直接可用。 ## 这个站点里有什么 [Section titled “这个站点里有什么”](#这个站点里有什么) * **[安装(Docker / NAS)](guide/install/)**——把 LANrurugi 跑起来,并让它读到你已有的库。 * **[原生安装](guide/install-native/)**——不用容器,直接在 Linux、Apple Silicon Mac 或 FreeBSD 上运行。 * **[快速开始](guide/quickstart/)**——首次登录、扫描库、导入旧数据。 * **[支持的格式](guide/formats/)**——能放进书库的压缩包和电子书(PDF、EPUB、MOBI/AZW3、DjVu、FB2、TXT),以及各自怎么显示。 * **[用文档站测试 API](guide/api-testing/)**——在浏览器里直接对**你自己的实例**发请求,以及它不生效时的处理方式。 * **[插件开发入门](plugin/getting-started/)**——写一个元数据/登录/下载插件。 * **[API 参考](api/)**——完整的 HTTP API:每个端点、参数、响应,以及可直接复制的命令行。 ## 关于 API 参考 [Section titled “关于 API 参考”](#关于-api-参考) API 参考**不是手写的**。它由 `crates/lanrurugi-api-docgen` 从服务端自己的路由注册里生成,因此: * 服务端提供的每个端点都在里面,**不会**出现“代码里有、文档里没有”; * 它**不会**列出服务端其实不提供的端点; * 与 LANraragi 共有的端点,直接沿用 LANraragi 官方 OpenAPI 文档的字段级描述(路径前缀与鉴权部分除外); * 尚未写清请求/响应结构的端点会被明确标出,而不是被编造出一份看起来很像真的 schema。 CI 会在生成结果与代码不一致时直接失败,所以这份参考不会像手写文档那样慢慢过期。 # API 参考 > 本参考由 `crates/lanrurugi-api-docgen` 从服务端自己的路由注册生成:共 **248** 个端点,分为 **39** 组。每个端点都给出方法、完整路径、参数与响应示例,并带一个请求面板——填入**你自己的实例地址 本参考由 `crates/lanrurugi-api-docgen` 从服务端自己的路由注册生成:共 **248** 个端点,分为 **39** 组。每个端点都给出方法、完整路径、参数与响应示例,并带一个请求面板——填入**你自己的实例地址**即可直接发送,请求由浏览器直接发往该地址。 * [搜索 API](./search/) — 9 * [档案 API](./archives/) — 29 * [数据库 API](./database/) — 14 * [分类 API](./categories/) — 7 * [Tankoubon API](./tankoubons/) — 13 * [图章 API](./stamps/) — 8 * [插件 API](./plugins/) — 12 * [Shinobu API](./shinobu/) — 4 * [Minion API](./minion/) — 3 * [OPDS 目录](./opds/) — 3 * [其他 API](./misc/) — 5 * [活动日志](./activity/) — 6 * [API 令牌](./api-tokens/) — 4 * [档案拆分](./archive-split/) — 5 * [跨域登录](./auth-bridge/) — 4 * [性能基准](./bench/) — 2 * [书签](./bookmarks/) — 13 * [下载队列](./download-queue/) — 21 * [重复检测](./duplicates/) — 3 * [字体模式](./font-pattern/) — 2 * [健康检查](./health/) — 1 * [后台任务](./jobs/) — 3 * [登录](./login/) — 4 * [日志](./logs/) — 1 * [OpenSearch](./opensearch/) — 1 * [插件向导](./plugin-wizard/) — 7 * [偏好设置](./preferences/) — 2 * [推荐](./recommend/) — 1 * [维护脚本](./scripts/) — 3 * [登录设备](./sessions/) — 3 * [设置](./settings/) — 4 * [库统计](./stats/) — 3 * [订阅](./subscriptions/) — 25 * [Tankoubon 分组](./tankoubon-grouping/) — 8 * [术语表](./terminology-glossary/) — 3 * [页面翻译](./translation/) — 6 * [翻译设置](./translation-settings/) — 4 * [版本](./version/) — 1 * [AI 用量](./llm-usage/) — 1 怎么让浏览器能直接请求你自己的实例(跨域、HTTPS、令牌),见[用文档站测试 API](../guide/api-testing/)。 [下载 OpenAPI 文档(JSON)](/openapi.json) # 活动日志 > 6 endpoints. 6 endpoints. ## 删除选中的活动记录 [Section titled “删除选中的活动记录”](#删除选中的活动记录) DELETEhttp\://localhost:3000/api/activity 按 ID 批量删除。仅限会话调用——任何角色的 API 令牌都会被拒绝,因此令牌无法抹掉自己的审计记录。 #### 请求体 application/json #### 响应 200移除了多少条记录。 ``` null ``` 服务器地址http\://localhost:3000 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 列出活动记录 [Section titled “列出活动记录”](#列出活动记录) GEThttp\://localhost:3000/api/activity 一页活动记录,最新的在前,范围限定为调用者有权看到的内容(见本文件头部的说明)。 目标为某个档案的记录会附带该档案是否仍然存在的标注,这样客户端可以显示「此后已被删除」,而不是一个死链接。 权限差异 * **你能看到哪些条目取决于你的身份。** 网页会话能看到全部记录;管理员令牌能看到它自己产生的、以及所有 guest 令牌产生的记录;guest 令牌只能看到它自己产生的记录。所以令牌持有者看到的是完整日志的一个**子集**——返回空不代表什么都没发生。 #### 查询参数 * cursorstring可选 来自上一次响应 `next_cursor` 的不透明分页游标。 * limitinteger · min: 1 · max: 200 · default: 50可选 无论请求多少都会被夹到一个小固定范围内——不设上限的话,单个请求就能强制触发任意大的扫描。 * start_tsinteger可选 只返回该 Unix 秒级时间戳(含)之后的活动记录。 * end_tsinteger可选 只返回该 Unix 秒级时间戳(含)之前的活动记录。 * actorstring可选 逗号分隔的操作者键;多个值是「或」的关系。 * action_typestring可选 逗号分隔的操作类型;多个值是「或」的关系。 * outcomestring可选 逗号分隔的结果;多个值是「或」的关系。 #### 响应 200一页记录。 ``` { "entries": [ {} ], "next_cursor": "", "total_estimate": 0 } ``` 服务器地址http\://localhost:3000API 令牌••••• cursorquerylimitquerystart_tsqueryend_tsqueryactorqueryaction_typequeryoutcomequery 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 删除单条活动记录 [Section titled “删除单条活动记录”](#删除单条活动记录) DELETEhttp\://localhost:3000/api/activity/{id} 按 ID 删除单条记录。仅限会话调用,原因与批量删除相同。 #### 路径参数 * idstring必填 #### 响应 200已删除。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 404没有该 ID 的记录。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000 idpath 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 列出活动记录的筛选项 [Section titled “列出活动记录的筛选项”](#列出活动记录的筛选项) GEThttp\://localhost:3000/api/activity/facets 日志中出现过的操作类型与操作者,各自带计数——这样客户端可以按「实际存在的内容」来构建筛选界面,而不是按一份写死的列表。 与列表端点一样,范围限定为调用者可见的内容:只有当调用者有权读取某操作者的记录时,该操作者才会出现。 #### 响应 200可用的分面。 ``` { "action_types": [ {} ], "actors": [ {} ] } ``` 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 读取活动记录的保留窗口 [Section titled “读取活动记录的保留窗口”](#读取活动记录的保留窗口) GEThttp\://localhost:3000/api/activity/retention 活动记录保留多久,单位为秒。 #### 响应 200当前时间窗口。 ``` { "retention_secs": 0 } ``` 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 设置活动记录的保留窗口 [Section titled “设置活动记录的保留窗口”](#设置活动记录的保留窗口) PUThttp\://localhost:3000/api/activity/retention 修改活动记录的保留时长。仅限会话调用:令牌不能缩短自己留下的痕迹能存活多久。 #### 请求体 application/json #### 响应 200已保存。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # API 令牌 > 4 endpoints. 4 endpoints. ## 列出 API 令牌 [Section titled “列出 API 令牌”](#列出-api-令牌) GEThttp\://localhost:3000/api/tokens 每一个已签发令牌的元数据。令牌密钥本身**绝不**包含在内:它只在下面那个创建调用中返回一次,且不会以可恢复的形式存储。 需要会话 cookie 登录。 #### 响应 200已签发的令牌。 ``` [ { "created_at": 0, "expires_at": 0, "id": "", "last_used_at": 0, "last_used_ip": "", "name": "", "role": "admin" } ] ``` 服务器地址http\://localhost:3000 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 创建 API 令牌 [Section titled “创建 API 令牌”](#创建-api-令牌) POSThttp\://localhost:3000/api/tokens 签发一个新令牌并返回它的密钥——**这是它唯一一次被返回**。请当场保存;之后无法找回,只能替换。 过期时间按服务端自己的时钟计算,而不是采用客户端提供的时间戳,因此时钟不准的客户端无法铸造出比它申请的有效期更长的令牌。 #### 请求体 application/json #### 响应 200该令牌,密钥在 \`data.token\` 下。 ``` null ``` 400名称为空。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 吊销 API 令牌 [Section titled “吊销 API 令牌”](#吊销-api-令牌) DELETEhttp\://localhost:3000/api/tokens/{id} 永久吊销一个令牌。仍在使用它的任何东西会立刻开始失败;令牌无法撤销吊销,只能替换。 需要会话 cookie 登录。 #### 路径参数 * idstring必填 #### 响应 200已吊销。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 404没有该令牌。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000 idpath 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 重命名 API 令牌 [Section titled “重命名 API 令牌”](#重命名-api-令牌) PATCHhttp\://localhost:3000/api/tokens/{id} 修改令牌的标签。需要会话 cookie 登录。 #### 路径参数 * idstring必填 #### 请求体 application/json #### 响应 200重命名后的令牌。 ``` null ``` 404没有该令牌。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000 idpath 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # 档案拆分 > 5 endpoints. 5 endpoints. ## 获取拆分建议 [Section titled “获取拆分建议”](#获取拆分建议) GEThttp\://localhost:3000/api/archives/{id}/split-suggestion 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `get_split_suggestion`,位于 crates/lanrurugi-api/src/archive_split.rs:707。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/archive_split.rs:69 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 手动触发「立即分析该档案」 [Section titled “手动触发「立即分析该档案」”](#手动触发立即分析该档案) POSThttp\://localhost:3000/api/archives/{id}/split-suggestion 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/archive_split.rs:681)的**译文**;原文以源码为准。 手动触发「立即分析该档案」的端点。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/archive_split.rs:69 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 返回档案内部的目录树(`GET /archives/{id}/split-tree`,含嵌套层级) [Section titled “返回档案内部的目录树(GET /archives/{id}/split-tree,含嵌套层级)”](#返回档案内部的目录树get-archivesidsplit-tree含嵌套层级) GEThttp\://localhost:3000/api/archives/{id}/split-tree 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/archive_split.rs:508)的**译文**;原文以源码为准。 `GET /archives/{id}/split-tree`——返回档案内部的目录树,并递归展开其中嵌套的档案。这是只读的浏览用端点:它不调用 LLM,也不生成任何输出 ZIP。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/archive_split.rs:75 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 执行拆分 [Section titled “执行拆分”](#执行拆分) POSThttp\://localhost:3000/api/archives/{id}/split/execute 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `execute_split`,位于 crates/lanrurugi-api/src/archive_split.rs:735。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/archive_split.rs:73 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 拆分进度流 [Section titled “拆分进度流”](#拆分进度流) GEThttp\://localhost:3000/api/archives/{id}/split/stream 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `split_progress_stream`,位于 crates/lanrurugi-api/src/archive_split.rs:793。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/archive_split.rs:74 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # 档案 API > 29 endpoints. 29 endpoints. ## 批量删除档案(`DELETE /archives`,请求体 `{ids: [...]}`) [Section titled “批量删除档案(DELETE /archives,请求体 {ids: \[...\]})”](#批量删除档案delete-archives请求体-ids-) DELETEhttp\://localhost:3000/api/archives 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/archives.rs:618)的**译文**;原文以源码为准。 `DELETE /archives`(issue #63),请求体 `{ids: [...]}`——沿用本代码库已有的「复数资源 + 用 JSON 请求体指明操作对象」这一形态(见 `activity.rs::bulk_delete_activity` 的 `DELETE /activity`),而不是 `POST .../batch-delete` 那种动作式路径;按 RFC 9110,`DELETE` **可以**带请求体(虽然一些较旧的代理/客户端在实践中会静默丢掉它,但 Axum 和本项目自己的前端都处理得很好,而且本仓库已有先例)。Batch 页面自己的「删除档案」操作此前是在前端按选中的档案逐个发 `DELETE /archives/{id}`,就是一个普通的顺序循环(没有原子性,没有统一的审计点,而且——由于每个请求只报告自己的成功/失败——调用方除非在操作前后对比整个书库,否则无法知道*哪些* id 失败了)。这里把同样的逐 id 工作(`delete_one_archive`,与单条删除端点完全相同的清理)放到服务端一个请求里完成,并返回逐 id 的结果列表,让前端能准确展示发生了什么,而不是假定全部成功。 仅限会话调用(`route_policy.csv` 拒绝所有令牌角色以及 `anonymous`)——刻意比本文件里其他所有会修改档案的端点都更严格,那些端点 Token(Admin 或 Guest)都能调用。一个泄露或被写错的 API 令牌就能在一个请求里抹掉任意规模的库内容,其影响范围远大于令牌访问本来就允许的任何一个单目标端点;而本项目对批量删除并不存在像脚本化上传或元数据编辑那样的正当自动化场景——所以这条额外限制不会破坏任何真实工作流。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/archives.rs:209 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 获取全部档案 [Section titled “获取全部档案”](#获取全部档案) GEThttp\://localhost:3000/api/archives 返回数据库中全部档案的列表。按设计不包含 Tankoubon。 这个 JSON 里的 ID 可以用在其他端点上。 权限差异 * **访客和匿名调用者完全不可达。** 这是无范围的列表:它返回书库中的全部档案,不做任何分类范围限制——给访客开放它等于绕过 `/api/search` 强制的那套「访客可见」限制。访客请走 `/api/search`。 #### 响应 200档案数组 ``` [ { "arcid": "28697b96f0ac5858be2614ed10ca47742c9522fd", "extension": "rar", "filename": "Fate GO MEMO", "isnew": false, "lastreadtime": 1337038281, "pagecount": 34, "progress": 3, "size": 1234567, "summary": null, "tags": "parody:fate grand order, group:wadamemo, artist:wada rco, artbook, full color", "title": "Fate GO MEMO", "toc": [ { "name": "Chapter 1", "page": 1 }, { "name": "Chapter 2", "page": 13 }, { "name": "Chapter 3", "page": 25 } ] } ] ``` 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 删除档案 [Section titled “删除档案”](#删除档案) DELETEhttp\://localhost:3000/api/archives/{id} 同时删除档案元数据和服务器上存储的文件。\ 🙏 调用这个端点前请先向用户确认。 #### 路径参数 * idstring · min: 40 · max: 40 · pattern必填 要处理的档案 ID。 #### 响应 200档案已删除的响应 ``` { "filename": "big_chungus.zip", "id": "75d18ce470dc99f83dc355bdad66319d1f33c82b", "operation": "delete_archive", "success": 1 } ``` 400没有档案 ID 的响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 423资源被锁定的响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpath 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 获取档案所属分类 [Section titled “获取档案所属分类”](#获取档案所属分类) GEThttp\://localhost:3000/api/archives/{id}/categories 获取当前引用了该档案 ID 的全部分类。 #### 路径参数 * idstring必填 要处理的档案 ID。 #### 响应 200档案所属分类 ``` { "categories": [ { "archives": [ "0d50858d727723d856d2ab78564bb8e906e65f14", "7f03b8b1f337e1e42b2c2890533c0de7479d41ca" ], "id": "SET_1613080290", "name": "My great category", "pinned": 0, "search": null }, { "archives": [ "0d50858d727723d856d2ab78564bb8e906e65f14", "75d18ce470dc99f83dc355bdad66319d1f33c82b" ], "id": "SET_1613080294", "name": "My other category", "pinned": 1, "search": null } ], "operation": "find_arc_categories", "success": 1 } ``` 400没有档案 ID 的响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpath 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 下载档案 [Section titled “下载档案”](#下载档案) GEThttp\://localhost:3000/api/archives/{id}/download 从服务端下载一个档案。 #### 路径参数 * idstring · min: 40 · max: 40 · pattern必填 要下载的档案 ID。 #### 响应 200档案文件 该响应没有示例数据。 400没有档案 ID 的响应 ``` { "error": "No archive ID specified.", "operation": "download_archive", "success": 0 } ``` 服务器地址http\://localhost:3000API 令牌••••• idpath 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 提取档案 [Section titled “提取档案”](#提取档案) GEThttp\://localhost:3000/api/archives/{id}/files 获取指向档案内各图片的 URL 列表。 如有必要,这个端点还会启动一个后台 Minion 任务来解压该档案,使其可供阅读。 权限差异 * 对**不在访客可见范围内**的档案,这里返回 **404** 而不是 403——刻意与「档案不存在」不可区分,因此这个响应无法被用来探测访客范围之外的档案是否存在。 #### 路径参数 * idstring · min: 40 · max: 40 · pattern必填 要处理的档案 ID。 #### 查询参数 * forceboolean可选 强制在后台完整重新提取该档案。在该档案完全重新提取完成之前,后续的 `/api/archives/:id/page` 调用仍可能用到已有的缓存文件。 #### 响应 200会返回页面 URL,以及后台提取任务的 ID。 ``` { "job": 561, "pages": [ ".\\/api\\/archives\\/28697b96f0ac5858be2614ed10ca47742c9522fd\\/page&path=00.jpg", ".\\/api\\/archives\\/28697b96f0ac5858be2614ed10ca47742c9522fd\\/page&path=01.jpg" ] } ``` 400没有档案 ID 的响应 ``` { "error": "No archive ID specified.", "operation": "get_file_list", "success": 0 } ``` 服务器地址http\://localhost:3000API 令牌••••• idpathforcequery 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 提取页面缩略图 [Section titled “提取页面缩略图”](#提取页面缩略图) POSThttp\://localhost:3000/api/archives/{id}/files/thumbnails 为指定档案的每一页生成缩略图。 这个端点会把缩略图生成排入后台队列。 如果检测到全部缩略图都已存在,调用会返回 HTTP 200。\ 这个端点可以重复调用——如果该 ID 的缩略图任务已经在进行中,它只会把那个进行中任务的 ID 给你。 #### 路径参数 * idstring · min: 40 · max: 40 · pattern必填 要处理的档案 ID。 #### 查询参数 * forceboolean可选 是否强制重新生成全部缩略图,即使它们已经存在。 #### 响应 200缩略图已提取且 \`force=0\` 时 ``` { "message": "No job queued, all thumbnails already exist.", "operation": "generate_page_thumbnails", "success": 1 } ``` 202缩略图已排入提取队列。可以用 \`/api/minion/:jobid\` 跟踪进度,查看 \`notes->progress\` 与 \`notes->pages\`。 ``` { "job": 0, "operation": "", "success": 1 } ``` 400没有档案 ID 的响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpathforcequery 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 清除档案的「新」标记 [Section titled “清除档案的「新」标记”](#清除档案的新标记) DELETEhttp\://localhost:3000/api/archives/{id}/isnew 清除档案上的「新!」标记。 #### 路径参数 * idstring · min: 40 · max: 40 · pattern必填 要处理的档案 ID。 #### 响应 200成功响应 ``` { "id": "d07ff399dddb25a0408385bc75b9ba52709fe2c1", "operation": "clear_new", "success": 0 } ``` 400没有档案 ID 的响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 423资源被锁定的响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpath 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 设置档案的「新」标记 [Section titled “设置档案的「新」标记”](#设置档案的新标记) PUThttp\://localhost:3000/api/archives/{id}/isnew 设置/恢复档案上的「新!」标记。 #### 路径参数 * idstring · min: 40 · max: 40 · pattern必填 要处理的档案 ID。 #### 响应 200成功响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 400没有档案 ID 的响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 423资源被锁定的响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpath 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 获取档案元数据 [Section titled “获取档案元数据”](#获取档案元数据) GEThttp\://localhost:3000/api/archives/{id}/metadata 获取指定档案的元数据(标题、标签)。 权限差异 * 对**不在访客可见范围内**的档案,这里返回 **404** 而不是 403——刻意与「档案不存在」不可区分,因此这个响应无法被用来探测访客范围之外的档案是否存在。 #### 路径参数 * idstring · min: 40 · max: 40 · pattern必填 要处理的档案 ID。 #### 响应 200档案元数据 ``` { "arcid": "28697b96f0ac5858be2614ed10ca47742c9522fd", "extension": "rar", "filename": "Fate GO MEMO", "isnew": false, "lastreadtime": 1337038281, "pagecount": 34, "progress": 3, "size": 1234567, "summary": null, "tags": "parody:fate grand order, group:wadamemo, artist:wada rco, artbook, full color", "title": "Fate GO MEMO", "toc": [ { "name": "Chapter 1", "page": 1 }, { "name": "Chapter 2", "page": 13 }, { "name": "Chapter 3", "page": 25 } ] } ``` 400没有档案 ID 的响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpath 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 更新档案元数据 [Section titled “更新档案元数据”](#更新档案元数据) PUThttp\://localhost:3000/api/archives/{id}/metadata 更新指定档案的标签与标题。\ 通过这个方法提交给服务端的数据会**覆盖**原有数据。 #### 路径参数 * idstring · min: 40 · max: 40 · pattern必填 要处理的档案 ID。 #### 查询参数 * titlestring可选 档案的新标题。 * tagsstring可选 档案的新标签。 * summarystring可选 档案的新摘要。 #### 响应 200档案元数据已更新 ``` { "operation": "update_metadata", "success": 1 } ``` 400没有档案 ID 的响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 423资源被锁定的响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpathtitlequerytagsquerysummaryquery 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 获取档案的某一页 [Section titled “获取档案的某一页”](#获取档案的某一页) GEThttp\://localhost:3000/api/archives/{id}/page 获取档案的某一页。这个调用主要与 `/api/archives/files` 配合使用。 权限差异 * 对**不在访客可见范围内**的档案,这里返回 **404** 而不是 403——刻意与「档案不存在」不可区分,因此这个响应无法被用来探测访客范围之外的档案是否存在。 #### 路径参数 * idstring · min: 40 · max: 40 · pattern必填 要下载的档案 ID。 #### 查询参数 * pathstring必填 图片路径。 #### 响应 200档案页面 该响应没有示例数据。 400没有档案 ID 的响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpathpathquery 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 返回前 `N` 页的自然像素宽高 [Section titled “返回前 N 页的自然像素宽高”](#返回前-n-页的自然像素宽高) GEThttp\://localhost:3000/api/archives/{id}/page-dimensions 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/archives.rs:3688)的**译文**;原文以源码为准。 `GET /archives/{id}/page-dimensions?count=N`——只返回前 `N` 页的自然像素宽高,顺序与 `/files` 自己的 `pages` 数组一致(这样前端可以按下标直接配对,不必再做一次名称匹配)。它是对 `/files` 的**新增**端点,而不是折进 `/files`:`/files` 的既有调用方(第三方兼容的文件列表契约)不该被迫为一次需要逐条解析图片头的档案遍历买单;实际调用这个端点的只有无限滚动阅读视图(唯一真正需要它的调用方——用于在跳到恢复位置之前准确摆好尚未加载的 `` 尺寸;为什么它只限定在跳转前的那些页而不是整个档案,见 `read_page_dimensions` 自身的文档)。 权限差异 * 对**不在访客可见范围内**的档案,这里返回 **404** 而不是 403——刻意与「档案不存在」不可区分,因此这个响应无法被用来探测访客范围之外的档案是否存在。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/archives.rs:228 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 删除补丁(`DELETE /archives/{id}/patch`,删除 `.patch.zip` 旁挂文件并清理相关状态) [Section titled “删除补丁(DELETE /archives/{id}/patch,删除 .patch.zip 旁挂文件并清理相关状态)”](#删除补丁delete-archivesidpatch删除-patchzip-旁挂文件并清理相关状态) DELETEhttp\://localhost:3000/api/archives/{id}/patch 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/archives.rs:1160)的**译文**;原文以源码为准。 `DELETE /archives/{id}/patch`——删除旁挂的 `.patch.zip`(如果有),并清除该档案的 `has_patch` 标记。让用户可以撤销一个补丁——比如在重跑对比流程后换用另一个来源的页面——而不必改动档案本身。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/archives.rs:248 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 更新阅读进度 [Section titled “更新阅读进度”](#更新阅读进度) PUThttp\://localhost:3000/api/archives/{id}/progress/{page} 告诉服务端你当前正在展示/阅读这个档案的第几页,以便它相应地更新内部的阅读进度。\ 这个端点还会用服务端当前时间戳更新该档案的最后阅读时间。 只有在你确认用户确实正在阅读你展示的那一页时才应调用它。\ **不要**在为了预加载图片而请求服务端时使用它。 阅读进度是否允许回退由客户端决定。(网页端在用户开始重读前面的页面时会减小进度值)\ 不过建议在开始更新进度时顺手清掉档案上的「新!」标记——只要新标记还在,网页端就不会显示任何阅读进度。 ⚠ 如果服务端配置为使用客户端进度跟踪,这个 API 调用会返回错误!\ 调用前请务必先用 `/api/info` 确认服务端是否跟踪阅读进度。 #### 路径参数 * idstring · min: 40 · max: 40 · pattern必填 要处理的档案 ID。 * pageinteger必填 要更新到的当前阅读页码。 **必须**是正整数,且不超过该档案的总页数。 #### 响应 200成功响应 ``` { "id": "75d18ce470dc99f83dc355bdad66319d1f33c82b", "lastreadtime": 123943543, "operation": "update_progress", "page": 34, "success": 1 } ``` 400通用错误响应 ``` { "error": "Server-side Progress Tracking is disabled on this instance.", "operation": "update_progress", "success": 0 } ``` 401开启 authprogress 时需要认证 ``` { "error": "This operation requires authentication.", "operation": "update_progress", "success": 0 } ``` 423资源被锁定的响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpathpagepath 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 重命名档案(`PUT /archives/{id}/rename`,新增端点,legacy 没有对应功能) [Section titled “重命名档案(PUT /archives/{id}/rename,新增端点,legacy 没有对应功能)”](#重命名档案put-archivesidrename新增端点legacy-没有对应功能) PUThttp\://localhost:3000/api/archives/{id}/rename 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/archives.rs:1277)的**译文**;原文以源码为准。 `PUT /archives/{id}/rename`——新增端点,legacy 没有对应功能(legacy 根本没有档案重命名功能;已核对 `~/LANraragi/lib/LANraragi/Controller/*.pm` 与 `public/js/edit.js`,任何地方都没有 `rename` 相关引用)。它重命名的是档案在磁盘上的文件(不只是存储的 `title`/`name`),并保持 `Archive::file` 与 `LRR_FILEMAP` 同步——参照 `download_manager::ingest` 自己那套「暂存文件改名进 `archive_dir`」的修正逻辑,那是「档案文件路径变了,要同步更新跟踪它的两处」最接近的既有先例。 旁挂的 `.patch.zip`(它如何被关联见 `delete_patch` 自身的文档——同目录、同主文件名,纯靠文件名约定)会随档案一起改名:把它留在旧主文件名下会静默破坏 `patch::patch_path_for` 之后每一次查找,使一个已存在的补丁变得不可见,既不报错也不删除任何东西——这类「静默接近数据丢失」的 bug,远比让本函数直接拒绝这次改名要糟糕。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/archives.rs:249 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 获取档案所属的 Tankoubon [Section titled “获取档案所属的 Tankoubon”](#获取档案所属的-tankoubon) GEThttp\://localhost:3000/api/archives/{id}/tankoubons 获取当前引用了该档案 ID 的全部 Tankoubon。 #### 路径参数 * idstring · min: 40 · max: 40 · pattern必填 要处理的档案 ID。 #### 响应 200档案所属的 Tankoubon ``` { "operation": "find_arc_tankoubons", "success": 1, "tankoubons": [ "TANK_1688616437", "TANK_1688693913" ] } ``` 400没有档案 ID 的响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpath 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 获取档案缩略图 [Section titled “获取档案缩略图”](#获取档案缩略图) GEThttp\://localhost:3000/api/archives/{id}/thumbnail 获取指定档案的缩略图。如果缩略图尚不存在,这个端点会返回一张占位图。若想把缩略图生成排入后台,可以使用 `no_fallback` 查询参数——这样你会拿到一个后台任务 ID,而不是占位图。 权限差异 * 对**不在访客可见范围内**的档案,这里返回 **404** 而不是 403——刻意与「档案不存在」不可区分,因此这个响应无法被用来探测访客范围之外的档案是否存在。 #### 路径参数 * idstring · min: 40 · max: 40 · pattern必填 要处理的档案 ID #### 查询参数 * no_fallbackstring · enum: true | false可选 关闭占位图,把缩略图排入提取队列,并返回 code 202 的 JSON。图片已存在时该参数不起作用。(无论哪种情况,只要图片已存在就会以 code 200 返回它) * pageinteger · min: 0可选 指定要取哪一页的缩略图,默认为封面,也就是第 1 页。 #### 响应 200如果缩略图已经提取过,会直接返回它。 该响应没有示例数据。 202缩略图已排入提取队列。用 \`/api/minion/:jobid\` 跟踪它何时就绪。 ``` { "job": 0, "operation": "", "success": 1 } ``` 400没有档案 ID 的响应 ``` { "error": "No archive ID specified.", "operation": "serve_thumbnail", "success": 0 } ``` 服务器地址http\://localhost:3000API 令牌••••• idpathno_fallbackquerytruepagequery 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 更新档案缩略图 [Section titled “更新档案缩略图”](#更新档案缩略图) PUThttp\://localhost:3000/api/archives/{id}/thumbnail 更新指定档案的封面缩略图。你可以指定用哪一页作为缩略图,也可以使用默认缩略图。 #### 路径参数 * idstring · min: 40 · max: 40 · pattern必填 要处理的档案 ID。 #### 查询参数 * pageinteger可选 用哪一页生成缩略图,默认第 1 页。 #### 响应 200档案缩略图已更新 ``` { "new_thumbnail": "", "operation": "update_thumbnail", "success": 0 } ``` 400没有档案 ID 的响应 ``` { "error": "No archive ID specified.", "operation": "update_thumbnail", "success": 0 } ``` 服务器地址http\://localhost:3000API 令牌••••• idpathpagequery 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 获取页面缩略图 [Section titled “获取页面缩略图”](#获取页面缩略图) GEThttp\://localhost:3000/api/archives/{id}/thumbnails 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 权限差异 * 对**不在访客可见范围内**的档案,这里返回 **404** 而不是 403——刻意与「档案不存在」不可区分,因此这个响应无法被用来探测访客范围之外的档案是否存在。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/archives.rs:233 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 从档案目录中移除条目 [Section titled “从档案目录中移除条目”](#从档案目录中移除条目) DELETEhttp\://localhost:3000/api/archives/{id}/toc 从指定档案的目录中删除一个条目。 #### 路径参数 * idstring · min: 40 · max: 40 · pattern必填 要处理的档案 ID。 #### 查询参数 * pageinteger必填 要删除的章节页码。 #### 响应 200档案目录已更新 ``` { "operation": "remove_toc", "success": 1, "successMessage": "Removed ToC entry for page 143." } ``` 400没有档案 ID 的响应,或其他错误 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 423资源被锁定的响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpathpagequery 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 向档案目录添加条目 [Section titled “向档案目录添加条目”](#向档案目录添加条目) PUThttp\://localhost:3000/api/archives/{id}/toc 向指定档案的目录添加一个条目。 目录以 JSON 编码的键值数组存储,把页码映射到从该页开始的章节标题。 #### 路径参数 * idstring · min: 40 · max: 40 · pattern必填 要处理的档案 ID。 #### 查询参数 * pageinteger必填 章节的起始页码。 * titlestring必填 章节标题。 #### 响应 200档案目录已更新 ``` { "operation": "update_toc", "success": 1, "successMessage": "Added ToC entry for page 143." } ``` 400没有档案 ID 的响应,或其他错误 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 423资源被锁定的响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpathpagequerytitlequery 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 获取全部未打标签的档案 [Section titled “获取全部未打标签的档案”](#获取全部未打标签的档案) GEThttp\://localhost:3000/api/archives/untagged 获取没有任何标签记录的档案。 规则与批量打标签的筛选一致,因此 parody:、date_added:、series: 或 artist: 这类标签的存在不影响判定。 #### 响应 200档案 ID 数组 ``` [ "d1858d5dc36925aa66be072a97817650d39de166", "c3458d5dc36925da93be072a97817650d39de166", "28697b96f0ac5858be2614ed10ca47742c9522fd" ] ``` 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 上传档案 [Section titled “上传档案”](#上传档案) PUThttp\://localhost:3000/api/archives/upload 把档案上传到服务端。\ 如果附带该档案的 SHA1 校验和,服务端会做一次可选的传输中文件完整性校验,并在服务端算出的校验和不匹配时拒绝这次上传。 #### 请求体 multipart/form-data #### 响应 200档案上传成功 ``` { "id": "d07ff399dddb25a0408385bc75b9ba52709fe2c1", "operation": "upload", "success": 1 } ``` 400请求有误 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 409重复的档案 ``` { "error": "This file already exists in the Library. Enable replace duplicated archive in config to replace old ones.", "id": "0b91b546850e881034833c73375558928ddcec7c", "operation": "upload", "success": 0 } ``` 415不支持的文件 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 417校验和不匹配 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 422无法处理的实体 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 423资源被锁定的响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 500服务端内部错误 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Start or re-attach to a resumable upload [Section titled “Start or re-attach to a resumable upload”](#start-or-re-attach-to-a-resumable-upload) POSThttp\://localhost:3000/api/archives/upload/session Creates a session (an empty staged file plus a sidecar describing it) and returns the id. If `client_key` matches a session that is still alive, that session is returned instead, with the offset its bytes are already at — which is what makes a page refresh resumable rather than restarting the transfer. The returned `offset` is always read from the staged file’s real length, never from the sidecar, so a truncated or edited sidecar cannot make the server believe it holds bytes it does not. Sessions that have not been touched for 24 hours are swept by the operations here; the staged bytes also live in `temp_dir`, so `DELETE /api/tempfolder` reclaims them too. #### 请求体 application/json #### 响应 200A session to upload into. ``` { "created_at": 0, "file_name": "", "file_size": 0, "offset": 0, "operation": "upload", "resumed": false, "success": 1, "updated_at": 0, "upload_id": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Abandon a session [Section titled “Abandon a session”](#abandon-a-session) DELETEhttp\://localhost:3000/api/archives/upload/session/{id} Drops the staged bytes and the sidecar. Safe to call on an unknown id. #### 路径参数 * idstring必填 #### 响应 200The session's bytes are gone (whether or not it existed). 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• idpath 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Upload session status [Section titled “Upload session status”](#upload-session-status) GEThttp\://localhost:3000/api/archives/upload/session/{id} The handshake a resuming client starts from: how many bytes the server actually holds for this session. `404` means unknown, expired, or already completed — in every case the client’s correct move is to start a new session. #### 路径参数 * idstring必填 #### 响应 200The session, with its current offset. ``` { "created_at": 0, "file_name": "", "file_size": 0, "offset": 0, "operation": "upload", "resumed": false, "success": 1, "updated_at": 0, "upload_id": "" } ``` 404Unknown or expired session. ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpath 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Append one chunk [Section titled “Append one chunk”](#append-one-chunk) PUThttp\://localhost:3000/api/archives/upload/session/{id} Appends the request body to the staged file, but only at the position the client claims. `Upload-Offset` is required and must equal the staged file’s real length; the response always reports the authoritative offset, including on failure: * `204` — the chunk was appended; `Upload-Offset` is the new length. * `409` — the client’s offset disagrees with the disk (a lost response, a retried chunk, two tabs); `Upload-Offset` says where to resume from. * `400` — missing or malformed `Upload-Offset`. A connection that dies mid-chunk keeps whatever bytes reached the disk and reports the offset, so a partial chunk is just fewer bytes rather than a corrupt one. The body is bounded at 64 MiB (the one-shot route is deliberately unbounded; a chunk is supposed to be small). #### 路径参数 * idstring必填 #### 请求头 * Upload-Offsetinteger必填 Byte position this chunk starts at; must equal the server's own length. #### 请求体 application/octet-stream #### 响应 204Chunk appended. 该响应没有示例数据。 404Unknown or expired session. ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 409Offset mismatch; resync from the returned \`Upload-Offset\`. 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• idpath 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Finish a session and ingest it [Section titled “Finish a session and ingest it”](#finish-a-session-and-ingest-it) POSThttp\://localhost:3000/api/archives/upload/session/{id}/complete Verifies what landed, hashes it, and hands it to the same ingest the one-shot route uses — including the persistent download-queue row, so a completed upload shows up (and can be removed) exactly like any other queue item. Verification: a `file_size` announced at session creation must equal the staged length (`417` otherwise, and the staged bytes are dropped), and an optional `file_checksum` is compared against the SHA-1 of the finished file (`417` on mismatch). That SHA-1 is computed by reading the staged file once at this point rather than persisting incremental hasher state: a resumed upload’s early chunks were hashed by processes that are long gone, and state that can silently desync from the bytes on disk is a worse trade than one sequential read of an already-local file. After this call the session no longer exists. #### 路径参数 * idstring必填 #### 请求体 application/json #### 响应 200Ingested; the same body the one-shot upload returns. 该响应没有示例数据。 400The session holds no bytes. ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 404Unknown or expired session. ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 417The announced size or the supplied checksum did not match what arrived. ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpath 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # 跨域登录 > 4 endpoints. 4 endpoints. ## 跨域登录回调 [Section titled “跨域登录回调”](#跨域登录回调) GEThttp\://localhost:3000/api/auth/bridge/callback 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `bridge_callback`,位于 crates/lanrurugi-api/src/auth_bridge.rs:599。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/auth_bridge.rs:47 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点不需要认证。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 准备跨域登录 [Section titled “准备跨域登录”](#准备跨域登录) GEThttp\://localhost:3000/api/auth/bridge/prepare 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `prepare_bridge`,位于 crates/lanrurugi-api/src/auth_bridge.rs:402。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/auth_bridge.rs:45 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点不需要认证。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 开始跨域登录 [Section titled “开始跨域登录”](#开始跨域登录) GEThttp\://localhost:3000/api/auth/bridge/start 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `start_bridge`,位于 crates/lanrurugi-api/src/auth_bridge.rs:464。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/auth_bridge.rs:46 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点不需要认证。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 获取认证配置 [Section titled “获取认证配置”](#获取认证配置) GEThttp\://localhost:3000/api/auth/config 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `get_auth_config`,位于 crates/lanrurugi-api/src/auth_bridge.rs:380。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/auth_bridge.rs:44 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点不需要认证。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # 性能基准 > 2 endpoints. 2 endpoints. ## 获取报告 [Section titled “获取报告”](#获取报告) GEThttp\://localhost:3000/api/bench/{reportid} 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `get_report`,位于 crates/lanrurugi-api/src/bench.rs:107。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/bench.rs:21 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 对调用者提供的 legacy/新版端点执行跨系统对比(两端都由调用者给出) [Section titled “对调用者提供的 legacy/新版端点执行跨系统对比(两端都由调用者给出)”](#对调用者提供的-legacy新版端点执行跨系统对比两端都由调用者给出) POSThttp\://localhost:3000/api/bench/run 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/bench.rs:65)的**译文**;原文以源码为准。 对调用者提供的 legacy/新版端点执行跨系统对比(从本 crate 的角度看两者都是外部 HTTP 目标——即使「新版」恰好就是这个正在运行的实例、通过它自己的监听地址访问——所以同一份实现能同等驱动两种情况,与 `lanrurugi-bench-compare` 独立运行时的方式一致)。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/bench.rs:20 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # 书签 > 13 endpoints. 13 endpoints. ## 列出某个档案的书签页(不分页) [Section titled “列出某个档案的书签页(不分页)”](#列出某个档案的书签页不分页) GEThttp\://localhost:3000/api/archives/{id}/bookmarks 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/bookmarks.rs:479)的**译文**;原文以源码为准。 `GET /archives/{id}/bookmarks`——不分页,只返回这一个档案被标记书签的页面(升序,每项附带解析出的文件名)。读者用它判断当前页是否已加书签(那里只关心 `page`),`BookmarkHoverGrid` 也用它(它的标题需要 `page` 和 `filename` 两者,此前要额外发一次 `GET /archives/{id}/files`)。不要求档案存在——与 `remove_bookmark` 的姿态一致:档案不存在就只是没有书签可报告(也没有文件名可解析)。 权限差异 * 对**不在访客可见范围内**的档案,这里返回 **404** 而不是 403——刻意与「档案不存在」不可区分,因此这个响应无法被用来探测访客范围之外的档案是否存在。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/bookmarks.rs:36 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 删除书签(`DELETE /archives/{id}/bookmarks/{page}`,幂等) [Section titled “删除书签(DELETE /archives/{id}/bookmarks/{page},幂等)”](#删除书签delete-archivesidbookmarkspage幂等) DELETEhttp\://localhost:3000/api/archives/{id}/bookmarks/{page} 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/bookmarks.rs:751)的**译文**;原文以源码为准。 `DELETE /archives/{id}/bookmarks/{page}`——幂等,与 `BookmarksRepository::remove` 自身的契约一致;不会先检查档案是否存在,因为为一个已被删除的档案移除书签属于正当清理,不是错误。下面那次活动日志查询只是一次*尽力而为*的标签获取,与上述宽松处理是两回事——档案缺失时移除本身照常进行,只是 `target.label: None`(退化为只有 `target.id`,与任何其他「资源先消失」的操作类型相同)。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/bookmarks.rs:37 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 添加书签(`POST /archives/{id}/bookmarks/{page}`,不校验 `page` 是否超出该档案的页数) [Section titled “添加书签(POST /archives/{id}/bookmarks/{page},不校验 page 是否超出该档案的页数)”](#添加书签post-archivesidbookmarkspage不校验-page-是否超出该档案的页数) POSThttp\://localhost:3000/api/archives/{id}/bookmarks/{page} 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/bookmarks.rs:689)的**译文**;原文以源码为准。 `POST /archives/{id}/bookmarks/{page}`——bookmarks 不拿档案真实的 `pagecount` 去校验 `page`,与 `update_progress`(`archives.rs`)自身的宽松处理一致:唯一的调用方是读者界面,它总是传入自己当前、已经合法的页码。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/bookmarks.rs:37 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 设置或清除该书签自身的名称(`PUT /archives/{id}/bookmarks/{page}/name`) [Section titled “设置或清除该书签自身的名称(PUT /archives/{id}/bookmarks/{page}/name)”](#设置或清除该书签自身的名称put-archivesidbookmarkspagename) PUThttp\://localhost:3000/api/archives/{id}/bookmarks/{page}/name 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/bookmarks.rs:562)的**译文**;原文以源码为准。 `PUT /archives/{id}/bookmarks/{page}/name`——设置或清除该书签自身的名称。书签本身不存在时返回 `404`(名称不能比它所命名的书签活得更久,而在不存在的书签上设置名称会静默留下一个 `NAMES_HASH_KEY` 孤儿条目,任何 `add_bookmark` 调用都不会清理它)——与 `add_stamp`「档案必须先存在」的姿态一致,只是这里检查的是书签存在性而非档案存在性。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/bookmarks.rs:47 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 列出全部书签(`GET /bookmarks`,按档案聚合后依 `sort`/分页参数排序分页) [Section titled “列出全部书签(GET /bookmarks,按档案聚合后依 sort/分页参数排序分页)”](#列出全部书签get-bookmarks按档案聚合后依-sort分页参数排序分页) GEThttp\://localhost:3000/api/bookmarks 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/bookmarks.rs:252)的**译文**;原文以源码为准。 `GET /bookmarks`——全部书签,按档案聚合后依 `sort`/`cursor`/`limit` 排序分页。书签所属的档案已被删除时,它会被静默从结果中剔除,而不是让整个列表报错(与 `BookmarksRepository::list_all` 对个别格式错误条目已有的容忍一致——一个悬空引用不该拖垮其余全部仍然有效的书签)。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/bookmarks.rs:29 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 读取已保存的 `BookmarkHoverGrid` 翻页顺序偏好 [Section titled “读取已保存的 BookmarkHoverGrid 翻页顺序偏好”](#读取已保存的-bookmarkhovergrid-翻页顺序偏好) GEThttp\://localhost:3000/api/bookmarks/hover-page-order 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/bookmarks.rs:984)的**译文**;原文以源码为准。 `GET /bookmarks/hover-page-order`——已保存的 `BookmarkHoverGrid` 翻页顺序偏好(从未设置过时是 `None`;那种情况下前端会套用它自己的默认值 `"pageDesc"`)。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/bookmarks.rs:48 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 写入翻页顺序偏好(不记入活动日志——与 `settings.rs` 对显示类偏好采取的姿态一致) [Section titled “写入翻页顺序偏好(不记入活动日志——与 settings.rs 对显示类偏好采取的姿态一致)”](#写入翻页顺序偏好不记入活动日志与-settingsrs-对显示类偏好采取的姿态一致) PUThttp\://localhost:3000/api/bookmarks/hover-page-order 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/bookmarks.rs:1002)的**译文**;原文以源码为准。 不记入活动日志——属于仅影响显示的偏好,与 `settings.rs` 自己的 `theme` 字段采取的姿态相同(同样没有 `record_manual` 调用)。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/bookmarks.rs:48 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 读取「只显示自身匹配 `q` 的书签」这一已保存偏好 [Section titled “读取「只显示自身匹配 q 的书签」这一已保存偏好”](#读取只显示自身匹配-q-的书签这一已保存偏好) GEThttp\://localhost:3000/api/bookmarks/only-matching 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/bookmarks.rs:1018)的**译文**;原文以源码为准。 `GET /bookmarks/only-matching`——已保存的「只显示自身匹配 `q` 的书签」偏好(从未设置过时为 `false`,与历史上一直显示全部的行为一致)。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/bookmarks.rs:52 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 写入「只显示匹配书签」偏好(不记入活动日志,与翻页顺序偏好姿态一致) [Section titled “写入「只显示匹配书签」偏好(不记入活动日志,与翻页顺序偏好姿态一致)”](#写入只显示匹配书签偏好不记入活动日志与翻页顺序偏好姿态一致) PUThttp\://localhost:3000/api/bookmarks/only-matching 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/bookmarks.rs:1035)的**译文**;原文以源码为准。 不记入活动日志——与 `put_hover_page_order` 相同的「仅影响显示」姿态。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/bookmarks.rs:52 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 列出 Tankoubon 内所有成员档案的书签,并换算成 Tankoubon 全局页码 [Section titled “列出 Tankoubon 内所有成员档案的书签,并换算成 Tankoubon 全局页码”](#列出-tankoubon-内所有成员档案的书签并换算成-tankoubon-全局页码) GEThttp\://localhost:3000/api/tankoubons/{id}/bookmarks 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/bookmarks.rs:877)的**译文**;原文以源码为准。 `GET /tankoubons/{id}/bookmarks`——Tankoubon 内所有成员档案的全部书签,并换算成 Tankoubon 自己的全局页码。不分页,按全局页码升序——与 `list_bookmarks_for_archive` 自身的契约一致(用法也相同,都是给 `BookmarkHoverGrid` 用,只是这里对应 Tankoubon 卡片而不是普通档案卡片)。已不存在的成员档案(或 `pagecount` 为空,例如尚未扫描)会静默不贡献任何内容,而不是让整个请求失败——与 `TankoubonFullResponse` 自身文档所描述的、`full_data` 静默省略缺失成员是同一种容忍。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/bookmarks.rs:64 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 删除 Tankoubon 书签(先换算全局页码再委托给档案级删除) [Section titled “删除 Tankoubon 书签(先换算全局页码再委托给档案级删除)”](#删除-tankoubon-书签先换算全局页码再委托给档案级删除) DELETEhttp\://localhost:3000/api/tankoubons/{id}/bookmarks/{page} 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/bookmarks.rs:832)的**译文**;原文以源码为准。 `DELETE /tankoubons/{id}/bookmarks/{page}`——与 \[`add_tank_bookmark`] 相同的「先换算再委托」形态,委托对象是 \[`remove_bookmark`]。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/bookmarks.rs:68 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 为 Tankoubon 添加书签(把 Tankoubon 全局页码换算到具体成员档案的页码) [Section titled “为 Tankoubon 添加书签(把 Tankoubon 全局页码换算到具体成员档案的页码)”](#为-tankoubon-添加书签把-tankoubon-全局页码换算到具体成员档案的页码) POSThttp\://localhost:3000/api/tankoubons/{id}/bookmarks/{page} 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/bookmarks.rs:817)的**译文**;原文以源码为准。 `POST /tankoubons/{id}/bookmarks/{page}`——把 Tankoubon 全局 `page` 换算到真实的成员档案 + 局部页码(`tankoubons::resolve_tank_page`),然后委托给 \[`add_bookmark`] 自己的逻辑;写入本身仍然落在真实档案 ID 上,与在阅读 Tankoubon 时放置的图章相同(`stamps.rs` 自己的 Tankoubon 路由)——`bookmarks.rs` 底层的 `BookmarksRepository` 没有自己的 `TANK_` 概念,也永远不需要。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/bookmarks.rs:68 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 重命名 Tankoubon 书签(同样是先换算再委托) [Section titled “重命名 Tankoubon 书签(同样是先换算再委托)”](#重命名-tankoubon-书签同样是先换算再委托) PUThttp\://localhost:3000/api/tankoubons/{id}/bookmarks/{page}/name 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/bookmarks.rs:665)的**译文**;原文以源码为准。 `PUT /tankoubons/{id}/bookmarks/{page}/name`——与 `add_tank_bookmark`/`remove_tank_bookmark` 相同的「先换算再委托」形态,委托对象是 \[`rename_bookmark`]。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/bookmarks.rs:72 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # 分类 API > 7 endpoints. 7 endpoints. ## 获取全部分类 [Section titled “获取全部分类”](#获取全部分类) GEThttp\://localhost:3000/api/categories 获取服务端保存的全部分类。 #### 响应 200分类列表 ``` [ { "archives": [ "0d50858d727723d856d2ab78564bb8e906e65f14", "7f03b8b1f337e1e42b2c2890533c0de7479d41ca" ], "id": "SET_1613080290", "name": "My great category", "pinned": 0, "search": null } ] ``` 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 创建分类 [Section titled “创建分类”](#创建分类) PUThttp\://localhost:3000/api/categories 创建一个新分类。 #### 请求体 application/x-www-form-urlencoded, multipart/form-data #### 响应 200成功响应 ``` { "category_id": "SET_1613080290", "operation": "create_category", "success": 0 } ``` 400错误响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 删除分类 [Section titled “删除分类”](#删除分类) DELETEhttp\://localhost:3000/api/categories/{id} 删除一个分类。 #### 响应 200成功响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 423该分类 ID 当前被锁定,无法修改 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 获取单个分类 [Section titled “获取单个分类”](#获取单个分类) GEThttp\://localhost:3000/api/categories/{id} 获取指定分类 ID 的详情。 #### 响应 200分类 ``` { "archives": [ "0d50858d727723d856d2ab78564bb8e906e65f14", "7f03b8b1f337e1e42b2c2890533c0de7479d41ca" ], "id": "SET_1613080290", "name": "My great category", "pinned": 0, "search": null } ``` 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 更新分类 [Section titled “更新分类”](#更新分类) PUThttp\://localhost:3000/api/categories/{id} 修改一个分类。 #### 请求体 application/x-www-form-urlencoded, multipart/form-data #### 响应 200成功响应 ``` { "category_id": "SET_1613080290", "operation": "update_category", "success": 0 } ``` 400错误响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 423该分类当前被锁定,无法修改 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 把档案移出分类 [Section titled “把档案移出分类”](#把档案移出分类) DELETEhttp\://localhost:3000/api/categories/{id}/{archive} 把某个档案 ID 从一个分类中移除。 #### 路径参数 * idstring · min: 14 · max: 14 · pattern必填 要移出的分类 ID。 * archivestring · min: 40 · max: 40 · pattern必填 要移除的档案 ID。 #### 响应 200结果 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 423该分类 ID 当前被锁定,无法修改 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpatharchivepath 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 把档案加入分类 [Section titled “把档案加入分类”](#把档案加入分类) PUThttp\://localhost:3000/api/categories/{id}/{archive} 把指定的档案 ID(见「档案 API」)加入给定分类。 #### 路径参数 * idstring · min: 14 · max: 14 · pattern必填 要加入的分类 ID。 * archivestring · min: 40 · max: 40 · pattern必填 #### 响应 200结果 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 423该分类 ID 当前被锁定,无法修改 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpatharchivepath 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # 数据库 API > 14 endpoints. 14 endpoints. ## 获取备份 JSON [Section titled “获取备份 JSON”](#获取备份-json) GEThttp\://localhost:3000/api/database/backup 扫描整个数据库并以 JSON 形式返回备份。 数据库较大时建议改用 POST 版本——这个基础 GET 端点如果生成备份耗时过长可能会超时。\ 这份备份可以通过「备份与恢复」功能手动重新导入。 #### 响应 200成功响应 ``` { "archives": [ { "arcid": "28697b96f0ac5858be2614ed10ca47742c9522fd", "filename": "FateGOMEMO", "summary": null, "tags": "parody:fate grand order, group:wadamemo, artist:wada rco, artbook, full color, super:test, date_added:1553537258", "thumbhash": "ec2a0ca3a3da67a9390889f0910fe494241faa9a", "title": "Fate GO MEMO" }, { "arcid": "d1858d5dc36925aa66be072a97817650d39de166", "filename": "(Memes)9B789D38B0784C5FBC9D59A9F24D20F2", "summary": null, "tags": "", "thumbhash": "9846bb6d62949b56545c42e88d8010446b65702e", "title": "test title" } ], "categories": [ { "archives": [], "catid": "SET_1749925633", "name": "english", "search": "language:english" } ], "tankoubons": [ { "archives": [ "28697b96f0ac5858be2614ed10ca47742c9522fd", "d1858d5dc36925aa66be072a97817650d39de166" ], "name": "sailor moon", "tankid": "TANK_1749925516" } ] } ``` 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 排入一个备份任务 [Section titled “排入一个备份任务”](#排入一个备份任务) POSThttp\://localhost:3000/api/database/backup 排入一个 Minion 任务来生成备份 JSON 文件。\ 用返回的任务 ID 查看进度,完成后下载该文件。 #### 响应 200已入队的任务 ``` { "job": 42, "operation": "queue_backup", "success": 1 } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 从已完成的任务下载备份 JSON [Section titled “从已完成的任务下载备份 JSON”](#从已完成的任务下载备份-json) GEThttp\://localhost:3000/api/database/backup/{jobid} 下载由已完成的备份任务生成的备份 JSON 文件。 #### 路径参数 * jobidinteger必填 已完成的备份任务 ID。 #### 查询参数 * formatstring · enum: json | file可选 返回的备份格式,默认 `file`。`json` 会以 JSON 响应返回备份。 #### 响应 200备份 JSON 文件 ``` {} ``` 400任务不存在,或尚未完成 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• jobidpathformatqueryjson 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 清理数据库 [Section titled “清理数据库”](#清理数据库) POSThttp\://localhost:3000/api/database/clean 清理数据库:先隐藏、再移除那些文件已不在文件系统上的条目。\ 文件已不存在的条目在第一次清理时只做解除关联,因此不会出现在界面上——之后再跑一次清理才会**删除**这些已解除关联的条目。 #### 响应 200成功响应 ``` { "deleted": 0, "operation": "", "success": 0, "unlinked": 0 } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 清空数据库 [Section titled “清空数据库”](#清空数据库) POSThttp\://localhost:3000/api/database/drop 删除整个数据库,包括用户偏好设置。 这是个相当危险的端点,调用它可能会让你作为客户端被锁在服务端之外! #### 响应 200成功响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 导入调用者直接上传的 LANraragi(或 LANrurugi)备份 JSON 文件——不需要实例在线 [Section titled “导入调用者直接上传的 LANraragi(或 LANrurugi)备份 JSON 文件——不需要实例在线”](#导入调用者直接上传的-lanraragi或-lanrurugi备份-json-文件不需要实例在线) POSThttp\://localhost:3000/api/database/import-legacy 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/database.rs:789)的**译文**;原文以源码为准。 导入调用者直接上传的 LANraragi(或 LANrurugi)备份 JSON 文件——不连接任何远端 Redis 实例(原因见 `lanrurugi_backup::import_legacy` 自身的模块文档:官方 LANraragi Docker 镜像默认从不把它内置的 Redis 暴露到容器外)。与上面的 `queue_restore` 是相同的 multipart 文件上传形态,但这里刻意做成独立的 handler/解析/持久化路径,而不是 `queue_restore` 的一个变体——尽管两者的 JSON 形状表面相似却绝不能共用代码,原因见 `import_legacy` 自身的文档。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/database.rs:44 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 本实例一共执行过多少次 LANraragi 导入——前端在导入前会读它 [Section titled “本实例一共执行过多少次 LANraragi 导入——前端在导入前会读它”](#本实例一共执行过多少次-lanraragi-导入前端在导入前会读它) GEThttp\://localhost:3000/api/database/import-legacy/count 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/database.rs:998)的**译文**;原文以源码为准。 本实例一共执行过多少次 LANraragi 导入——前端在展示导入界面之前会读它,以便在第 2 次及以后的导入时给出提醒(「你之前做过这个——建议先做一次完整备份」),而不必等导入本身完成。只读,与 `queue_import_legacy` 自己的递增(在真实导入完成后发生)分开,与 `ImportSnapshotRepository::import_count` 自身的读/增分离一致。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/database.rs:48 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 导入快照的元数据列表,最新的在前(不含 `document` 内容) [Section titled “导入快照的元数据列表,最新的在前(不含 document 内容)”](#导入快照的元数据列表最新的在前不含-document-内容) GEThttp\://localhost:3000/api/database/import-snapshots 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/database.rs:1025)的**译文**;原文以源码为准。 按时间倒序的元数据列表(不含 `document` 内容——见 `ImportSnapshotRepository::list_metadata` 自身的文档),供备份页面那个「时光机」式回滚点选择器使用。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/database.rs:49 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 删除导入快照 [Section titled “删除导入快照”](#删除导入快照) DELETEhttp\://localhost:3000/api/database/import-snapshots/{id} 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `delete_import_snapshot`,位于 crates/lanrurugi-api/src/database.rs:1067。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/database.rs:50 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 把完整的 `BackupDocument` 内容作为可下载的 JSON 文件返回(与导入时接受的格式相同) [Section titled “把完整的 BackupDocument 内容作为可下载的 JSON 文件返回(与导入时接受的格式相同)”](#把完整的-backupdocument-内容作为可下载的-json-文件返回与导入时接受的格式相同) GEThttp\://localhost:3000/api/database/import-snapshots/{id} 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/database.rs:1045)的**译文**;原文以源码为准。 把完整的 `BackupDocument` 内容作为可下载的 JSON 文件返回——与 `POST /database/restore` 接受的形状相同,因此前端自己的「恢复」流程可以把这个文件原样喂回去,两端都不需要任何格式转换。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/database.rs:50 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 清除全部「新」标记 [Section titled “清除全部「新」标记”](#清除全部新标记) DELETEhttp\://localhost:3000/api/database/isnew 清除全部档案上的「新!」标记。 #### 响应 200成功响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 重建索引 [Section titled “重建索引”](#重建索引) POSThttp\://localhost:3000/api/database/rebuild-index 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `rebuild_index`,位于 crates/lanrurugi-api/src/database.rs:706。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/database.rs:43 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 排入一个恢复任务 [Section titled “排入一个恢复任务”](#排入一个恢复任务) POSThttp\://localhost:3000/api/database/restore 排入一个 Minion 任务,从备份 JSON 文件恢复。\ 用返回的任务 ID 查看进度。 #### 请求体 multipart/form-data #### 响应 200已入队的任务 ``` { "job": 43, "operation": "queue_restore", "success": 1 } ``` 400请求无效 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 获取统计信息 [Section titled “获取统计信息”](#获取统计信息) GEThttp\://localhost:3000/api/database/stats 从数据库获取标签,并附带表示其流行度的数值。 #### 查询参数 * minweightinteger可选 只想取权重不低于给定最小值的标签时传这个参数。 不传时默认为 1,即返回全部标签。 * hide_excluded_namespacesstring可选 设为 true 时,把服务端设置里配置的命名空间从结果中排除。默认返回全部标签。 #### 响应 200成功响应 ``` [ { "namespace": "character", "text": "jeanne alter", "weight": 2 }, { "namespace": "character", "text": "xuanzang", "weight": 2 }, { "namespace": "parody", "text": "fate grand order", "weight": 3 }, { "namespace": null, "text": "artbook", "weight": 3 } ] ``` 服务器地址http\://localhost:3000API 令牌••••• minweightqueryhide_excluded_namespacesquery 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # 下载队列 > 21 endpoints. 21 endpoints. ## 列出队列项 [Section titled “列出队列项”](#列出队列项) GEThttp\://localhost:3000/api/download_queue 下载队列中的每一个项,无论它当前处于什么状态。 需要实时更新时请优先使用 `/download_queue/stream`,它会在状态变化发生时主动推送,而不必轮询。 #### 响应 200队列。 ``` { "items": [ {} ] } ``` 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 向队列添加下载项 [Section titled “向队列添加下载项”](#向队列添加下载项) POSThttp\://localhost:3000/api/download_queue 批量添加。调用者已经自行判断好每个 URL 匹配的是哪个下载插件的 `url_pattern`;这个端点唯一的校验是 `plugin_namespace` 能解析到一个已安装的插件。 无效条目会被**逐条拒绝**,而不是让整批失败,因此粘贴的列表里有一个坏 URL 不会挡住其余的。请检查响应中的 `rejected`。 #### 请求体 application/json #### 响应 200已加入的项,以及未能加入的项。 ``` { "added": [ {} ], "rejected": [ { "reason": "", "url": "" } ] } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 删除一个队列项 [Section titled “删除一个队列项”](#删除一个队列项) DELETEhttp\://localhost:3000/api/download_queue/{id} 从队列中移除一个项。 正在下载中的项会以 409 拒绝——把它的记录从正在运行的后台任务下面抽掉,会让那个任务无处更新,队列里既没有行可以显示进度,也没有办法停止传输。请先停止它。 已经入库的队列项同样会被拒绝;请改为删除由此产生的那份档案。 #### 路径参数 * idstring必填 #### 响应 200已删除。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 409该项正在下载;请先停止再删除。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpath 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 更新一个队列项 [Section titled “更新一个队列项”](#更新一个队列项) PATCHhttp\://localhost:3000/api/download_queue/{id} 部分更新:请求体中省略的字段会保留已存储的值,而不是被清空。约定与 `PUT /plugins/options` 相同。 #### 路径参数 * idstring必填 #### 请求体 Any subset of the item's editable fields. #### 响应 200已更新。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 404没有该队列项。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000 idpath 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## AI 质量对比判断(issue #77,针对某个下载队列项) [Section titled “AI 质量对比判断(issue #77,针对某个下载队列项)”](#ai-质量对比判断issue-77针对某个下载队列项) POSThttp\://localhost:3000/api/download_queue/{id}/compare 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/download_queue.rs:1857)的**译文**;原文以源码为准。 `POST /download_queue/{id}/compare`——issue #77 针对 `PendingFilenameConflict` 的 AI 质量对比判断:把刚暂存下来的下载(`temp_path`,在响应中暴露为 \[`imgcompare::Side::A`])与已经入库、持有同名文件的那个档案(`existing_id` 自己的文件,暴露为 \[`imgcompare::Side::B`])做页面对齐与清晰度比较——只读,自身不解决任何冲突;前端之后仍会根据用户(借助或不借助这次对比)的决定去调用 `.../overwrite` 或 `.../rename`。响应里刻意不把 `A`/`B` 标为「新」/「旧」(见 \[`lanrurugi_imgcompare::Side`] 自身的文档)——是这个 handler 为这个具体调用方赋予了那层含义。 它与下面流式的 \[`compare_queue_item_stream`] 并存(而不是被其取代),作为给不愿使用 SSE 的调用方准备的普通请求/响应降级方案——前端自己的 `ComparisonResultModal` 流程现在改走流式端点(原因见那个 handler 自身的文档)。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/download_queue.rs:44 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 用用户挑选的页面生成 `.patch.zip` [Section titled “用用户挑选的页面生成 .patch.zip”](#用用户挑选的页面生成-patchzip) POSThttp\://localhost:3000/api/download_queue/{id}/compare/export-patch 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/download_queue.rs:2610)的**译文**;原文以源码为准。 `POST /download_queue/{id}/compare/export-patch`——用用户挑选的 A 侧独有页面(`ComparisonResult.a_unmatched_pages`,issue #77 自己的后续设计)构建一个 `.patch.zip`,并返回其原始字节供下载,可直接放到目标档案所在磁盘位置并命名为 `<档案文件名>.patch.zip`(`lanrurugi_scanner::patch`)——这个端点自己不会把它写到那里(已确认的设计:「补丁不需要应用,只要放在漫画目录内」——由用户放置的文件,而不是本服务端未经请求就安装的东西)。目标永远是 B(本次冲突所针对的库中已有档案)——补丁只会在用户保留的那一版之上追加 A 自己的额外页面,绝不会反过来。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/download_queue.rs:61 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 保留书库中已有的那份档案、丢弃新下载的那份 [Section titled “保留书库中已有的那份档案、丢弃新下载的那份”](#保留书库中已有的那份档案丢弃新下载的那份) POSThttp\://localhost:3000/api/download_queue/{id}/compare/keep-b 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/download_queue.rs:2719)的**译文**;原文以源码为准。 `POST /download_queue/{id}/compare/keep-b`——「保留库中已有的档案、丢弃这次下载」这一解决方式(issue #77 自己的后续设计)。它与本文件里其他所有解决动作都不同:那些都会把*暂存的*文件(A)以某种形式入库,要么替换 B(`overwrite_queue_item`),要么与 B 并存(`rename_queue_item`)——这一个则什么都不入库。B 已经在库里,就原样留在那里;实际发生的只有两件事:(1) `insertions`(如果有)会被直接写进 B 自己的旁挂 `.patch.zip`(不像 \[`export_compare_patch`] 那样只是返回给用户自行放置——这个流程的前端在用户*选择*保留 B 的过程中已经引导他挑好了插入点,所以没有「现在去把这个文件放好」这一步留给他做),以及 (2) 该队列项被直接删除,与普通的 `DELETE /download_queue/{id}` 相同——它已经没有东西需要跟踪了(已确认的设计:补丁的存在本身体现在 B 旁边的磁盘文件上,而不是队列项的某个标记)。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/download_queue.rs:65 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 对比视图里某一侧某一页的真实图片 [Section titled “对比视图里某一侧某一页的真实图片”](#对比视图里某一侧某一页的真实图片) GEThttp\://localhost:3000/api/download_queue/{id}/compare/page 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/download_queue.rs:2354)的**译文**;原文以源码为准。 `GET /download_queue/{id}/compare/page?side=a|b&index=N`——`.../compare` 自身响应中某个 `PageComparison` 样本背后的真实页面图片,供前端的叠加/位移切换对比视图使用。`side=a` 读取尚未入库的暂存下载(`temp_path`——此时还不存在档案 ID,所以无法复用 `archives.rs` 自己的 `GET /archives/{id}/page`);`side=b` 读取已有档案自己的文件。`index` 是自然排序下的页位置(与 `lanrurugi_imgcompare::PageComparison` 自己的 `a_page_index`/`b_page_index` 一致),每次调用都用 `list_pages` 现算成条目名,而不是缓存——这个端点每个冲突只会被访问寥寥几次(issue #77 自己确认的样本量为 3–5),为它加缓存不值得。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/download_queue.rs:53 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 列出一侧对比项的真实条目名列表(`GET /download_queue/{id}/compare/pages?side=a|b`) [Section titled “列出一侧对比项的真实条目名列表(GET /download_queue/{id}/compare/pages?side=a|b)”](#列出一侧对比项的真实条目名列表get-download_queueidcomparepagessideab) GEThttp\://localhost:3000/api/download_queue/{id}/compare/pages 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/download_queue.rs:2482)的**译文**;原文以源码为准。 `GET /download_queue/{id}/compare/pages?side=a|b`——对比中某一侧的真实条目名列表,按自然排序(页)顺序给出。前端自己那个「选择把 A 侧未匹配页面插入到哪里」的界面(issue #77 自己的后续设计)需要 B 的真实条目名,以便在 `.../export-patch` 里作为 `after_filename`/`before_filename` 发送——它除此之外只处理数字页码(与 `PageComparison.a_page_index`/`b_page_index` 一致),而 `patch.rs` 自己的 JSON schema 刻意不使用页码(为什么以条目名而非可能因档案重新扫描而漂移的下标作为稳定锚点,见该模块的文档)。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/download_queue.rs:57 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 对比队列项的 SSE 流式版本 [Section titled “对比队列项的 SSE 流式版本”](#对比队列项的-sse-流式版本) GEThttp\://localhost:3000/api/download_queue/{id}/compare/stream 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/download_queue.rs:1988)的**译文**;原文以源码为准。 `GET /download_queue/{id}/compare/stream`——上面 \[`compare_queue_item`] 的 SSE 流式孪生版本,依据 issue #77 自己确认的两阶段设计(完整的阶段一/阶段二拆分见 `lanrurugi_imgcompare::compare_archives_streaming` 自身的文档):开启一条 `EventSource` 兼容的流(用 GET 而非 POST——`EventSource` 无法发送请求体,也无法使用任何其他 HTTP 方法),每当出现一个 `CompareEvent::Sample` 就发出一个 `event: sample`(先粗后精,精确的替换样本随后陆续流入),最后发出一个终止性的 `event: done`,携带 `ComparisonResult` 其余字段——绝不把连接关闭/超时当作隐含的结束信号(「并且sse要有结束标记」)。前端在**第一个** `sample` 事件到达时就打开结果视图,而不是等整个对比完成;对于一对约 200 页的档案,否则会有好几秒的空白等待(「假设有6对结果(粗加工),可以用sse分6次发,发第一对的时候就开始显示modal,这样是一个很大的提速」)。 缓存命中(策略与 `compare_queue_item` 自己的相同)会以一批 `sample` 事件(全部是 `phase: coarse`——缓存结果已经过两个阶段,而前端只关心「这个值是否是最终展示值」,一旦值本身已定,`Coarse` 与 `Precise` 其实没有区别)一次性重放,紧接着发出 `done`,因此重新打开一个已算好的对比依然是瞬时完成的。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/download_queue.rs:49 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 确认保留较旧的版本(回答「是否用旧版本覆盖」这个提问) [Section titled “确认保留较旧的版本(回答「是否用旧版本覆盖」这个提问)”](#确认保留较旧的版本回答是否用旧版本覆盖这个提问) POSThttp\://localhost:3000/api/download_queue/{id}/confirm-older 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/download_queue.rs:707)的**译文**;原文以源码为准。 `POST /download_queue/{id}/confirm-older`——回答当一次下载被判定为比库中已有档案更*旧*的版本时弹出的那个 `AwaitingRevisionConfirmation` 提问(issue #107 的 `warn_then_conflict_menu`)。 `proceed: true` 会把该决定记录到该项上并重新启动它——由于此时 `revision_confirmed` 已置位,重启会直接穿过同一套版本历史检查,而不会再次停在那里。`proceed: false` 会把该项移到 `Cancelled`,那本来就是「用户主动停下的、仍可重启」的状态,因此不需要新的终态。 刻意与 `.../start` 分开:`AwaitingRevisionConfirmation` 不属于 `is_startable`,所以普通的启动按钮不会不小心跳过这个提问。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/download_queue.rs:45 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 「获取元数据」按钮的后端路径 [Section titled “「获取元数据」按钮的后端路径”](#获取元数据按钮的后端路径) POSThttp\://localhost:3000/api/download_queue/{id}/fetch-metadata 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/download_queue.rs:148)的**译文**;原文以源码为准。 `POST /download_queue/{id}/fetch-metadata`——「获取元数据」按钮的后端路径。它跑的是与下载后自动抓取相同的那套插件 `execMetadata` + `metadata_preview` 缓存逻辑(`plugins::ensure_metadata_cached`),因此手动预览与自动抓取共用同一条代码路径(以及同一个 10 分钟 TTL),而不必让前端自己去调用 `POST /plugins/use`。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/download_queue.rs:36 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 用新下载覆盖同名文件,从而解决 `PendingFilenameConflict` [Section titled “用新下载覆盖同名文件,从而解决 PendingFilenameConflict”](#用新下载覆盖同名文件从而解决-pendingfilenameconflict) POSThttp\://localhost:3000/api/download_queue/{id}/overwrite 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/download_queue.rs:1362)的**译文**;原文以源码为准。 `POST /download_queue/{id}/overwrite`——通过删除已有档案(B)并把暂存下载(A)以它原本预期的文件名入库来解决 `PendingFilenameConflict`。 给定 `body.insertions` 时,会把 B 自己独有的页面打包成 `.patch.zip` 交给*新的* A 档案(issue #77 自己的后续设计:即使 A 总体上胜出,B 的某些页面可能仍值得保留)——这必须在调用 `resolve_conflict` **之前**读取 B 的页面并解析 B 自己的分类/标签/进度元数据,因为那次调用在把 A 入库的过程中会删除 B 的文件与记录(`pipeline.rs::delete_existing_archive`)——之后再想读就没有东西可读了。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/download_queue.rs:42 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 把冲突的文件重新命名并入库,从而解决 `PendingFilenameConflict` [Section titled “把冲突的文件重新命名并入库,从而解决 PendingFilenameConflict”](#把冲突的文件重新命名并入库从而解决-pendingfilenameconflict) POSThttp\://localhost:3000/api/download_queue/{id}/rename 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/download_queue.rs:1649)的**译文**;原文以源码为准。 `POST /download_queue/{id}/rename`——通过改为以 `body.filename` 把暂存下载入库来解决 `PendingFilenameConflict`,原文件名的持有者(已有档案)保持不变(成为一个全新的、独立并存的档案)。如果 `filename` 本身也与某个其他档案冲突,该项会得到一个*新的* `PendingFilenameConflict`(仍可解决,只是针对另一个已有档案/文件名),而不是丢掉已经下载好的字节——见 `ingest::resolve_rename` 自身的文档。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/download_queue.rs:43 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 启动一个队列项 [Section titled “启动一个队列项”](#启动一个队列项) POSThttp\://localhost:3000/api/download_queue/{id}/start 解析该项自己的下载插件(用的是它被加入时选定的那个,而不是现在重新选),标记为正在启动,并在后台发起真正的下载。随着传输推进,该项的 `state`、`job_id` 与 `error` 始终保持最新。 #### 路径参数 * idstring必填 #### 响应 200已启动;响应体里带着任务 ID。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 409该项当前不处于可启动状态。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpath 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 停止进行中的队列项(`POST /download_queue/{id}/stop`,用于 `Starting`/`Downloading` 状态的项) [Section titled “停止进行中的队列项(POST /download_queue/{id}/stop,用于 Starting/Downloading 状态的项)”](#停止进行中的队列项post-download_queueidstop用于-startingdownloading-状态的项) POSThttp\://localhost:3000/api/download_queue/{id}/stop 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/download_queue.rs:1253)的**译文**;原文以源码为准。 `POST /download_queue/{id}/stop`——取消一个进行中(`Starting`/`Downloading`)的队列项的下载,并把它退回 `Queued` 以便重新启动。这是协作式而非强制式的:它只是给该项在 `AppState::download_cancellations` 里的令牌发个信号——后台任务自己会在下一次 `tokio::select!` 轮询时察觉(见 `download_manager::stream::download_one`),并在真正结束前自行清理不完整的文件,此时 `start_download` 会把队列项状态改回去(见那里 `cancel_for_task.is_cancelled()` 分支)。没有令牌意味着要么该项其实从未在下载(没什么可停的),要么它恰好在本次请求到达前自己完成了——两者都是 `NotRunning`,并不值得大声报错,因为无论哪种情况,期望的最终状态(「这一项没有在下载」)都已经成立。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/download_queue.rs:41 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 清空已完成项(`POST /download_queue/clear_completed`,删除所有 `Done` 项并返回删除数量) [Section titled “清空已完成项(POST /download_queue/clear_completed,删除所有 Done 项并返回删除数量)”](#清空已完成项post-download_queueclear_completed删除所有-done-项并返回删除数量) POSThttp\://localhost:3000/api/download_queue/clear_completed 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/download_queue.rs:3098)的**译文**;原文以源码为准。 `POST /download_queue/clear_completed`——删除所有 `Done` 状态的项,返回删除数量。刻意排除 `Error`——与 `Done` 不同,出错的项是一个可重试、仍可操作的状态(在本模块其他地方都与 `Queued`/`Cancelled` 归为一类:可选中、有重试按钮、显示自己的错误文本),而不是用户已经看完不想再管的「已完成」工作。想丢弃某个具体失败项的用户,仍可通过 `DELETE /download_queue/{id}` 单独处理(那个端点确实会清理 `pending_filename_conflict` 自己暂存的临时文件——`Done` 项从不带这种文件,所以本 handler 没有同类东西需要操心)。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/download_queue.rs:69 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 删除选中的队列项 [Section titled “删除选中的队列项”](#删除选中的队列项) POSThttp\://localhost:3000/api/download_queue/delete_selected 按 ID 批量删除,语义与 `start_selected` 对齐:不存在或已被删除的 ID 是**静默无操作**,不是错误,所以可以安全地传入一份过期的选择。 正在下载中的 ID 同样是静默无操作——这正是单项删除用 409 表达的同一套安全规则。 #### 请求体 application/json #### 响应 200实际被移除的那些 ID。 ``` { "deleted": [ "" ] } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 启动全部排队项 [Section titled “启动全部排队项”](#启动全部排队项) POSThttp\://localhost:3000/api/download_queue/start_all 并发启动所有处于 `queued` 状态的项。每一项都会派生自己的后台任务;按域名限流与并发限制由下载管理器在下游统一执行,所以这里不再额外限速。 它的范围刻意比单项启动更窄:处于 `error` 或 `cancelled` 的项必须逐个重试,而正在等待版本冲突答复的项**绝不会**被顺带启动——批量启动它等于用沉默回答了它正卡着的那个问题。 #### 响应 200哪些项启动了、哪些被跳过以及原因。 ``` { "skipped": [ { "id": "", "reason": "" } ], "started": [ { "id": "", "job": "" } ] } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 启动选中的队列项 [Section titled “启动选中的队列项”](#启动选中的队列项) POSThttp\://localhost:3000/api/download_queue/start_selected 与 `start_all` 相同,但只作用于给定的那些 ID。 已经进行中、已经完成、或以其他方式无法启动的 ID 是**静默无操作**,不是错误——这样客户端可以直接传入一份选择,而不必先逐个复查当前状态。 #### 请求体 application/json #### 响应 200哪些项启动了、哪些被跳过以及原因。 ``` { "skipped": [ { "id": "", "reason": "" } ], "started": [ { "id": "", "job": "" } ] } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 推送下载队列项状态变化的 SSE 端点(`GET /download_queue/stream`) [Section titled “推送下载队列项状态变化的 SSE 端点(GET /download_queue/stream)”](#推送下载队列项状态变化的-sse-端点get-download_queuestream) GEThttp\://localhost:3000/api/download_queue/stream 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/download_queue.rs:75)的**译文**;原文以源码为准。 `GET /download_queue/stream`——SSE 端点,推送由 `update_queue_item_state` 在每次成功写入 Redis 后广播的队列项增量状态变化。第一个事件是 `full`,携带当前完整列表,使客户端无需另外发一次 HTTP GET 即可完成初始化。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/download_queue.rs:31 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # 重复检测 > 3 endpoints. 3 endpoints. ## 清除重复项(`DELETE /database/duplicates`,对应 legacy 同一页面路由上的 `?delete=1` 参数) [Section titled “清除重复项(DELETE /database/duplicates,对应 legacy 同一页面路由上的 ?delete=1 参数)”](#清除重复项delete-databaseduplicates对应-legacy-同一页面路由上的-delete1-参数) DELETEhttp\://localhost:3000/api/database/duplicates 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/duplicates.rs:228)的**译文**;原文以源码为准。 `DELETE /database/duplicates`——对应 legacy 同一页面路由上的 `?delete=1` 参数。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/duplicates.rs:32 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 读取所有已存储的重复组,把 ID 解析成当前的档案元数据,并剔除已失效的条目 [Section titled “读取所有已存储的重复组,把 ID 解析成当前的档案元数据,并剔除已失效的条目”](#读取所有已存储的重复组把-id-解析成当前的档案元数据并剔除已失效的条目) GEThttp\://localhost:3000/api/database/duplicates 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/duplicates.rs:169)的**译文**;原文以源码为准。 读取所有已存储的重复组,把 ID 解析成当前的档案元数据,并剔除自扫描以来已消失(被删除)的条目——与 legacy 在 `Controller/Duplicates.pm::index` 中的自愈行为一致(若剔除后组成员少于 2 个就丢弃整组,否则只移除消失的 ID 并重写该组)。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/duplicates.rs:32 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 把重复扫描排入后台任务(对应 legacy 的 `/api/minion/find_duplicates/queue`) [Section titled “把重复扫描排入后台任务(对应 legacy 的 /api/minion/find_duplicates/queue)”](#把重复扫描排入后台任务对应-legacy-的-apiminionfind_duplicatesqueue) POSThttp\://localhost:3000/api/database/duplicates/scan 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/duplicates.rs:47)的**译文**;原文以源码为准。 把扫描排入后台任务(对应 legacy 的 `/api/minion/find_duplicates/queue` 是由 Minion 承载而非同步执行),因为对每一对档案做哈希是 O(n²),不该阻塞请求。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/duplicates.rs:36 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # 字体模式 > 2 endpoints. 2 endpoints. ## 获取字体模式 [Section titled “获取字体模式”](#获取字体模式) GEThttp\://localhost:3000/api/volumes/{id}/font-pattern 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `get_font_pattern`,位于 crates/lanrurugi-api/src/font_pattern.rs:35。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/font_pattern.rs:25 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 重置字体模式 [Section titled “重置字体模式”](#重置字体模式) POSThttp\://localhost:3000/api/volumes/{id}/font-pattern/reset 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `reset_font_pattern`,位于 crates/lanrurugi-api/src/font_pattern.rs:52。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/font_pattern.rs:24 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # 健康检查 > 1 endpoint. 1 endpoint. ## 健康检查 [Section titled “健康检查”](#健康检查) GEThttp\://localhost:3000/health 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `health`,位于 crates/lanrurugi-api/src/health.rs:68。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/health.rs:43 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点不需要认证。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # 后台任务 > 3 endpoints. 3 endpoints. ## 清除全部已完成任务 [Section titled “清除全部已完成任务”](#清除全部已完成任务) DELETEhttp\://localhost:3000/api/jobs 移除已到达终止状态的任务——`finished` **或** `failed`。仍在进行中(`queued`、`active`)的任务保持被跟踪;等它们结束后再用单项端点处理。 只接受 `state=finished`。这个名字的含义是「任何处于终止状态的任务」,所以 `failed` 的也会被一并清掉。 #### 查询参数 * statestring · enum: finished必填 只接受 `finished`;缺失或传入其他值会返回 400。 #### 响应 200清除了多少个任务。 ``` null ``` 400\`state\` 缺失,或者不是 \`finished\`。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• statequeryfinished 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 列出正在跟踪的后台任务 [Section titled “列出正在跟踪的后台任务”](#列出正在跟踪的后台任务) GEThttp\://localhost:3000/api/jobs 本实例正在跟踪的每一个任务,最新的在前。 进度与字节数是尽力而为的:无法报告细粒度进度的任务会直接从 0 跳到 1,而不是伪造一个中间值;对于没有传输可报告的任务,字节字段是真正的缺失(而不是 `0`)。 #### 响应 200当前任务列表。 ``` { "jobs": [ { "downloaded_bytes": null, "error": null, "finished_at": null, "id": null, "name": null, "progress": null, "rate_limit_bytes_per_sec": null, "rate_limit_matched_pattern": null, "result": null, "result_truncated": null, "started_at": null, "state": null, "total_bytes": null } ] } ``` 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 清除单个任务 [Section titled “清除单个任务”](#清除单个任务) DELETEhttp\://localhost:3000/api/jobs/{id} 按 ID 清除单个任务,且只在该任务已到达终止状态后进行。 仍处于 `queued` 或 `active` 的任务会返回 409,而不是被悄悄杀掉——一个工作还在跑却报告成功的任务,比一个错误更糟。 #### 路径参数 * idstring必填 #### 响应 200已清除。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 404没有在跟踪该 ID 的任务。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 409该任务仍在排队或执行中;请等它结束或失败后再操作。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpath 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # AI 用量 > 各项 AI 功能的请求次数、token 用量、耗时与失败统计。 各项 AI 功能的请求次数、token 用量、耗时与失败统计。 ## usage [Section titled “usage”](#usage) GEThttp\://localhost:3000/api/llm/usage 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `usage`,位于 crates/lanrurugi-api/src/llm_usage.rs:124。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/llm_usage.rs:19 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # 登录 > 4 endpoints. 4 endpoints. ## 登录 [Section titled “登录”](#登录) POSThttp\://localhost:3000/api/login 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `login`,位于 crates/lanrurugi-api/src/login.rs:236。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/login.rs:39 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点不需要认证。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 查询调用者是否「已登录」(用于权限门控判断,`GET /login/status`) [Section titled “查询调用者是否「已登录」(用于权限门控判断,GET /login/status)”](#查询调用者是否已登录用于权限门控判断get-loginstatus) GEThttp\://localhost:3000/api/login/status 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/login.rs:669)的**译文**;原文以源码为准。 `GET /login/status`——报告调用者就「是否显示仅管理员可见的界面」这一判断而言是否「已登录」,与 legacy 自己的 `userlogged` 模板变量一致(`Controller/Reader.pm`/`Index.pm`:`enable_pass == 0 || session('is_logged')`)。刻意做成自己的端点,而不是在 `/info` 上加一个新字段——`/info` 逐字段镜像 legacy 的第三方 `ServerInfo` OpenAPI schema(宪法原则 II),而 `logged_in` 在那个契约里没有位置。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/login.rs:40 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点不需要认证。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 登出(refresh token 现在是有状态的,所以登出会真正吊销它) [Section titled “登出(refresh token 现在是有状态的,所以登出会真正吊销它)”](#登出refresh-token-现在是有状态的所以登出会真正吊销它) POSThttp\://localhost:3000/api/logout 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/login.rs:751)的**译文**;原文以源码为准。 由于 refresh token 现在是有状态的(`lanrurugi_storage::refresh_tokens`),登出现在会真的吊销——烧掉调用者 access token 所源自的整个 refresh token 家族(与 `rotate` 自己那条重放检测路径采取的补救相同),而不是只清掉浏览器 cookie、然后指望那个已成孤儿的 access token 在接下来几小时里自己安静过期。 它从 *access* token 里读 `fid`(`session::COOKIE_NAME`,`Path=/`),而不是从 refresh cookie 读——这是刻意的,这样 `REFRESH_COOKIE_PATH` 就能继续只限定于 `POST /api/token/refresh`,不必再覆盖本端点。这里用的是 `family_id_ignoring_expiry` 而非平常那个会检查过期的验证器:用户在 access token 已经过期之后(闲置的标签页,还没碰到任何会触发静默刷新的端点)点击「登出」,他的 refresh token 家族仍然必须被真正吊销——一个已过期的 access token 仍能通过其签名证明来源真实,而这正是这里唯一需要的东西。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/login.rs:41 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点不需要认证。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 刷新令牌(`POST /token/refresh`,legacy 没有对应端点) [Section titled “刷新令牌(POST /token/refresh,legacy 没有对应端点)”](#刷新令牌post-tokenrefreshlegacy-没有对应端点) POSThttp\://localhost:3000/api/token/refresh 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/login.rs:404)的**译文**;原文以源码为准。 `POST /token/refresh`——legacy 没有对应端点。用 refresh cookie 换取一个新的 access token + 轮换后的 refresh cookie(轮换/重放检测的语义见 `lanrurugi_storage::refresh_tokens::rotate` 自身的文档)。前端会在任何其他端点返回 401 时透明地调用它(`apps/frontend/src/api/client.ts`),且在此之前不会跳转到 `/login`。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/login.rs:42 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点不需要认证。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # 日志 > 1 endpoint. 1 endpoint. ## 获取日志行 [Section titled “获取日志行”](#获取日志行) GEThttp\://localhost:3000/api/logs/{category} 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `get_log_lines`,位于 crates/lanrurugi-api/src/logs.rs:26。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/logs.rs:18 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # Minion API > 3 endpoints. 3 endpoints. ## 获取 Minion 任务的基本状态 [Section titled “获取 Minion 任务的基本状态”](#获取-minion-任务的基本状态) GEThttp\://localhost:3000/api/minion/{jobid} 给定 Minion 任务 ID,检查它是成功还是失败。\ Minion 任务用于缩略图、缓存预热、处理新进来的文件等各种场合。\ 对部分任务,你可以查看 notes 字段获取进度信息。详见 。 #### 路径参数 * jobidinteger必填 要查询状态的任务 ID。 #### 响应 200任务状态数据 ``` { "error": null, "notes": { "example_note": "This note could contain the name of the upload, for example." }, "state": "finished", "task": "handle_upload" } ``` 服务器地址http\://localhost:3000API 令牌••••• jobidpath 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 获取 Minion 任务的完整状态 [Section titled “获取 Minion 任务的完整状态”](#获取-minion-任务的完整状态) GEThttp\://localhost:3000/api/minion/{jobid}/detail 获取一个 Minion 任务的状态。\ 这个 API 主要供内部使用,但你可以用它来获取插件执行、URL 下载这类任务的详细状态。 #### 路径参数 * jobidinteger必填 #### 响应 200任务详情 ``` { "args": [ "/tmp/QF3UCnKdMr/myfile.zip" ], "attempts": 1, "children": [], "created": 1601145004, "delayed": 1601145004, "expires": null, "finished": 1601145004, "id": 7, "lax": 0, "notes": {}, "parents": [], "priority": 0, "queue": "default", "result": { "id": "75d18ce470dc99f83dc355bdad66319d1f33c82b", "message": "This file already exists in the Library.", "success": 0 }, "retried": null, "retries": 0, "started": 1601145004, "state": "finished", "task": "handle_upload", "time": 1601145005, "worker": 1 } ``` 服务器地址http\://localhost:3000API 令牌••••• jobidpath 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 排入一个 Minion 任务 [Section titled “排入一个 Minion 任务”](#排入一个-minion-任务) POSThttp\://localhost:3000/api/minion/{jobname}/queue 按指定的类型和参数排入一个任务。\ 可用的任务类型及各自所需参数见 LANraragi::Utils::Minion 。 对于某个任务类型在给定服务端版本上是否存在,并没有 API 契约,所以除非你有充分理由,否则不建议使用它。 #### 路径参数 * jobnamestring · enum: thumbnail_task | tank_thumbnail_task | page_thumbnails | regen_all_thumbnails | find_duplicates | build_stat_hashes | handle_upload | download_url | run_plugin必填 要实例化的任务类型。 #### 查询参数 * argsstring必填 参数,以 JSON 数组字符串给出 * priorityinteger · default: 0可选 Minion 任务的优先级。数字越大越优先。 #### 响应 200已入队的任务 ``` { "job": 0, "operation": "", "success": 1 } ``` 服务器地址http\://localhost:3000API 令牌••••• jobnamepaththumbnail_taskargsquerypriorityquery 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # 其他 API > 5 endpoints. 5 endpoints. ## 把 URL 排入下载队列 [Section titled “把 URL 排入下载队列”](#把-url-排入下载队列) POSThttp\://localhost:3000/api/download_url 添加一个 URL,交由服务端下载并加入其书库。 #### 查询参数 * urlstring可选 要下载的 URL * catidstring · min: 14 · max: 14 · pattern可选 把下载到的 URL 加入的分类 ID。 #### 请求体 multipart/form-data #### 响应 200已入队的任务 ``` { "job": 86, "operation": "download_url", "success": 1, "url": "https://example.com" } ``` 400请求有误 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• urlquerycatidquery 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 获取服务端信息 [Section titled “获取服务端信息”](#获取服务端信息) GEThttp\://localhost:3000/api/info 返回这个服务端所运行的 LRR 实例的一些基本信息。 #### 响应 200服务端信息 ``` { "archives_per_page": 100, "authenticated_progress": false, "cache_last_cleared": 1728852701, "debug_mode": true, "excluded_namespaces": [ "source", "date_added" ], "has_password": false, "motd": "aye lads time to read some manga", "name": "LANraragi", "nofun_mode": false, "restart_required": false, "server_resizes_images": false, "server_tracks_progress": true, "total_archives": 104, "total_pages_read": 252, "version": "0.9.30", "version_desc": "I'm under Japanese influence and my honor's at stake!", "version_name": "Law (Earthlings On Fire)" } ``` 服务器地址http\://localhost:3000 该端点不需要认证。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 查询是否已配置 LLM 密钥(`GET /api/llm/key-status`,返回 `{ configured: true/false }`) [Section titled “查询是否已配置 LLM 密钥(GET /api/llm/key-status,返回 { configured: true/false })”](#查询是否已配置-llm-密钥get-apillmkey-status返回--configured-truefalse-) GEThttp\://localhost:3000/api/llm/key-status 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/misc.rs:118)的**译文**;原文以源码为准。 `GET /api/llm/key-status`——返回 `{ configured: true/false }`。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/misc.rs:20 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 重新生成缩略图 [Section titled “重新生成缩略图”](#重新生成缩略图) POSThttp\://localhost:3000/api/regen_thumbs 排入一个 Minion 任务,在服务端重新生成缺失的/全部的缩略图。 #### 查询参数 * forceboolean可选 是生成全部缩略图,还是只生成缺失的那些。 #### 响应 200已入队的任务 ``` { "job": 3, "operation": "regen_thumbnails", "success": 1 } ``` 服务器地址http\://localhost:3000API 令牌••••• forcequery 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 清理临时目录 [Section titled “清理临时目录”](#清理临时目录) DELETEhttp\://localhost:3000/api/tempfolder 清理服务端的临时目录。 #### 响应 200清理结果 ``` { "error": null, "newsize": 0, "operation": "cleantemp", "success": 1 } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # OPDS 目录 > 3 endpoints. 3 endpoints. ## 获取 OPDS 目录 [Section titled “获取 OPDS 目录”](#获取-opds-目录) GEThttp\://localhost:3000/api/opds 以兼容 PSE 1.1 的 OPDS 1.2 目录形式获取档案索引。 #### 查询参数 * categorystring可选 分类 ID。传入后,OPDS 目录会被过滤为只显示该分类下的档案。 #### 响应 200OPDS 目录 XML 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• categoryquery 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 通过 OPDS 获取指定档案 [Section titled “通过 OPDS 获取指定档案”](#通过-opds-获取指定档案) GEThttp\://localhost:3000/api/opds/{id} 以 XML 返回某个特定的 OPDS 条目。结果中只会为该 ID 显示一个 ``,而不是全部档案。 #### 路径参数 * idstring必填 #### 响应 200OPDS 条目 XML 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• idpath 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## OPDS-PSE 分页图片 [Section titled “OPDS-PSE 分页图片”](#opds-pse-分页图片) GEThttp\://localhost:3000/api/opds/{id}/pse 以 XML 返回 OPDS-PSE 的某个具体图片页。 #### 路径参数 * idstring必填 #### 查询参数 * pageinteger可选 #### 响应 200所请求页面的图片文件 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• idpathpagequery 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # OpenSearch > 1 endpoint. 1 endpoint. ## OpenSearch 描述文档 [Section titled “OpenSearch 描述文档”](#opensearch-描述文档) GEThttp\://localhost:3000/opensearch.xml 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `opensearch_xml`,位于 crates/lanrurugi-api/src/opensearch.rs:74。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/opensearch.rs:25 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点不需要认证。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # 插件向导 > 7 endpoints. 7 endpoints. ## 分析登录 [Section titled “分析登录”](#分析登录) POSThttp\://localhost:3000/api/plugin-wizard/analyze-login 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `analyze_login`,位于 crates/lanrurugi-api/src/plugin_wizard/analyze_login.rs:55。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/plugin_wizard/mod.rs:23 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `GET /plugin-wizard/generate/{id}/record` — the whole read surface; no UI [Section titled “GET /plugin-wizard/generate/{id}/record — the whole read surface; no UI”](#get-plugin-wizardgenerateidrecord--the-whole-read-surface-no-ui) GEThttp\://localhost:3000/api/plugin-wizard/generate/{id}/record 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/plugin_wizard/record.rs:118),**逐字引用、未翻译**——它是写给本代码库维护者看的,可能会提到内部标识符。 `GET /plugin-wizard/generate/{id}/record` — the whole read surface; no UI. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/plugin_wizard/mod.rs:35 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 启动插件生成(`POST /plugin-wizard/generate/start`,为何这样设计见该模块自身的顶部文档) [Section titled “启动插件生成(POST /plugin-wizard/generate/start,为何这样设计见该模块自身的顶部文档)”](#启动插件生成post-plugin-wizardgeneratestart为何这样设计见该模块自身的顶部文档) POSThttp\://localhost:3000/api/plugin-wizard/generate/start 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/plugin_wizard/generate.rs:193)的**译文**;原文以源码为准。 `POST /plugin-wizard/generate/start`——为什么生成被拆成这里加 `generate_stream`、而不是一个返回 JSON 的 `POST`,见本模块自身的顶部文档。它把请求体当作原始的 \[`serde_json::Value`] 接收(而不是带类型的 `GenerateRequest`),正是为了让本端点永远不必重复实现 `GenerateRequest` 自己的字段/默认值处理——真正带类型的解析只在 `generate_stream` 时发生一次,针对的是这里原样暂存下来的内容。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/plugin_wizard/mod.rs:27 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 插件生成的 `EventSource` 兼容流式端点(`GET /plugin-wizard/generate/stream/{id}`) [Section titled “插件生成的 EventSource 兼容流式端点(GET /plugin-wizard/generate/stream/{id})”](#插件生成的-eventsource-兼容流式端点get-plugin-wizardgeneratestreamid) GEThttp\://localhost:3000/api/plugin-wizard/generate/stream/{id} 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/plugin_wizard/generate.rs:211)的**译文**;原文以源码为准。 `GET /plugin-wizard/generate/stream/{id}`——真正 `EventSource` 兼容的流式端点;完整的事件序列见本模块自身的顶部文档。`id` 是一次性的(本方法被调用的那一刻就从 `pending_generate_requests` 中移除),因此重放同一个 id(一个过期的书签、一次双击竞态)总会得到 `generation_not_found`,而不会静默重跑一个旧请求。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/plugin_wizard/mod.rs:31 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 查询 [Section titled “查询”](#查询) POSThttp\://localhost:3000/api/plugin-wizard/lookup 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `lookup`,位于 crates/lanrurugi-api/src/plugin_wizard/mod.rs:22。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/plugin_wizard/mod.rs:22 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 保存 [Section titled “保存”](#保存) POSThttp\://localhost:3000/api/plugin-wizard/save 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `save`,位于 crates/lanrurugi-api/src/plugin_wizard/save.rs:71。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/plugin_wizard/mod.rs:40 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 试运行 [Section titled “试运行”](#试运行) POSThttp\://localhost:3000/api/plugin-wizard/trial-run 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `trial_run`,位于 crates/lanrurugi-api/src/plugin_wizard/trial_run.rs:148。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/plugin_wizard/mod.rs:39 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # 插件 API > 12 endpoints. 12 endpoints. ## 列出可用插件 [Section titled “列出可用插件”](#列出可用插件) GEThttp\://localhost:3000/api/plugins/{type} 列出给定类型的全部插件。 #### 路径参数 * typestring · enum: download | login | metadata | script | all必填 要列出的插件类型。传 "all" 可以一次取回所有类型。 #### 响应 200插件数组 ``` [ { "author": "Difegue", "description": "Searches chaika.moe for tags matching your archive.", "icon": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA\\nB3RJTUUH4wYCFQocjU4r+QAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUH\\nAAAEZElEQVQ4y42T3WtTdxzGn/M7J+fk5SRpTk7TxMZkXU84tTbVNrUT3YxO7HA4pdtQZDe7cgx2\\ns8vBRvEPsOwFYTDYGJUpbDI2wV04cGXCGFLonIu1L2ptmtrmxeb1JDkvv121ZKVze66f74eH7/f5\\nMmjRwMCAwrt4/9KDpflMJpPHvyiR2DPcJklJ3TRDDa0xk36cvrm8vDwHAAwAqKrqjjwXecPG205w\\nHBuqa9rk77/d/qJYLD7cCht5deQIIczbgiAEKLVAKXWUiqVV06Tf35q8dYVJJBJem2A7Kwi2nQzD\\nZig1CG93+PO5/KN6tf5NKpVqbsBUVVVFUUxwHJc1TXNBoxojS7IbhrnLMMx9pVJlBqFQKBKPxwcB\\nkJYgjKIo3QCE1nSKoghbfJuKRqN2RVXexMaQzWaLezyeEUEQDjscjk78PxFFUYRkMsltJgGA3t7e\\nyMLCwie6rr8iCILVbDbvMgwzYRjGxe0o4XC4s1AoHPP5fMP5/NNOyzLKAO6Ew+HrDADBbre/Ryk9\\nnzx81FXJNlEpVpF+OqtpWu2MpmnXWmH9/f2umZmZi4cOHXnLbILLzOchhz1YerJAs9m1GwRAg2GY\\nh7GYah488BJYzYW+2BD61AFBlmX/1nSNRqN9//792ujoaIPVRMjOKHoie3DytVGmp2fXCAEAjuMm\\nu7u7Umosho6gjL/u/QHeEgvJZHJ2K/D+/fuL4+PjXyvPd5ldkShy1UXcmb4DnjgQj/fd5gDA6/XS\\nYCAwTwh9oT3QzrS1+VDVi+vd3Tsy26yQVoFF3dAXJVmK96p9EJ0iLNOwKKU3CQCk0+lSOpP5WLDz\\nF9Q9kZqyO0SloOs6gMfbHSU5NLRiUOuax2/HyZPHEOsLw2SbP83eu/fLxrkNp9P554XxCzVa16MC\\n7+BPnTk9cfmH74KJE8nmga7Xy5JkZ8VKifGIHpoBb1VX8hNTd3/t/7lQ3OeXfFPvf/jBRw8ezD/a\\n7M/aWq91cGgnJaZ2VcgSdnV1XRNNd3vAoBVVYusmnEQS65hfgSG6c+zy3Kre7nF/KrukcMW0Zg8O\\nD08DoJutDxxOEb5IPUymwrq8ft1gLKfkFojkkRxemERCAQUACPFWRazYLJcrFGwQhyufbQQ7rFpy\\nLMkCwGZC34qPIuwp+XPOjBFwazQ/txrdFS2GGS/Xuj+pUKLGk1Kjvlded3s72lyGW+PLbGVcmrAA\\ngN0wTk1NWYODg9XOKltGtpazi5GigzroUnHN5nUHG1ylRsG7rDXHmnEpu4CeEtEKkqNc6QqlLc/M\\n8uT5lLH5eq0aGxsju1O7GQB498a5s/0x9dRALPaQEDZnYwnhWJtMCCNrjeb0UP34Z6e/PW22zjPP\\n+vwXBwfPvbw38XnXjk7GsiwKAIQQhjAMMrlsam45d+zLH6/8o6vkWcBcrXbVKQhf6bpucCwLjmUB\\nSmmhXC419eblrbD/TAgAkUjE987xE0c7ZDmk66ajUCnq+cL63fErl25s5/8baQPaWLhx6goAAAAA\\nSUVORK5CYII=", "name": "Chaika.moe", "namespace": "trabant", "oneshot_arg": "Chaika Gallery or Archive URL (Will attach matching tags to your archive)", "origin": "builtin", "parameters": [ { "desc": "ipb_pass_hash cookie", "type": "string" }, { "default_value": 0, "desc": "Force resampled archive download", "name": "forceresampled", "type": "bool" } ], "type": "metadata", "version": "2.1" } ] ``` 服务器地址http\://localhost:3000API 令牌••••• typepathdownload 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 导出插件(`GET /plugins/export?namespace=...`,见 `specs/006-ai-plugin-wizard` FR-028) [Section titled “导出插件(GET /plugins/export?namespace=...,见 specs/006-ai-plugin-wizard FR-028)”](#导出插件get-pluginsexportnamespace见-specs006-ai-plugin-wizard-fr-028) GEThttp\://localhost:3000/api/plugins/export 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/plugins.rs:1038)的**译文**;原文以源码为准。 `GET /plugins/export?namespace=...`(`specs/006-ai-plugin-wizard` FR-028)——把一个已安装的插件(无论是否由向导创建)下载为包含它自己 `.ts` 文件的 `.zip`,文件以该命名空间自身最后一段路径命名(例如 `custom/metadata/foo` → 内含 `foo.ts` 的 `foo.zip`),而不是用完整命名空间,因为命名空间那个以 `/` 分隔的类别前缀在单独解压出来后没有意义。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/plugins.rs:435 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 批量导出插件(`POST /plugins/export-batch`,与单个导出相同,但一次处理多个命名空间) [Section titled “批量导出插件(POST /plugins/export-batch,与单个导出相同,但一次处理多个命名空间)”](#批量导出插件post-pluginsexport-batch与单个导出相同但一次处理多个命名空间) POSThttp\://localhost:3000/api/plugins/export-batch 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/plugins.rs:1109)的**译文**;原文以源码为准。 `POST /plugins/export-batch`——与 \[`export_plugin`] 类似,但一次处理多个命名空间,打包进一个 `.zip`。每个条目以其完整命名空间路径存放(`custom/download/foo.ts`,而不只是 `foo.ts`),因为两个不同的命名空间可以共用同一个文件主名(`custom/download/foo` 与 `custom/metadata/foo`)——把两者都压成 `foo.ts` 会在写 zip 时静默丢掉其中一个。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/plugins.rs:436 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 删除插件选项 [Section titled “删除插件选项”](#删除插件选项) DELETEhttp\://localhost:3000/api/plugins/options 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `delete_plugin_options`,位于 crates/lanrurugi-api/src/plugins.rs:931。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/plugins.rs:437 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 获取插件选项 [Section titled “获取插件选项”](#获取插件选项) GEThttp\://localhost:3000/api/plugins/options 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `get_plugin_options`,位于 crates/lanrurugi-api/src/plugins.rs:785。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/plugins.rs:437 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 写入插件选项 [Section titled “写入插件选项”](#写入插件选项) PUThttp\://localhost:3000/api/plugins/options 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `put_plugin_options`,位于 crates/lanrurugi-api/src/plugins.rs:854。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/plugins.rs:437 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 持久化某个插件 `type` 分组内拖拽排序后的显示顺序(`PUT /plugins/priority`) [Section titled “持久化某个插件 type 分组内拖拽排序后的显示顺序(PUT /plugins/priority)”](#持久化某个插件-type-分组内拖拽排序后的显示顺序put-pluginspriority) POSThttp\://localhost:3000/api/plugins/priority 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/plugins.rs:567)的**译文**;原文以源码为准。 `PUT /plugins/priority`——持久化某个插件 `type` 分组内拖拽排序后的显示顺序(新增端点,legacy 没有对应功能:legacy 的 `plugins.html.tt2` 完全没有这种交互)。它把 `order` 中列出的每个命名空间在其自己的 `LRR_PLUGIN_` 哈希(与 `customargs`/`enabled` 同一处存储)里的 `priority` 字段重写为其在 `order` 中的位置,使后续的 `GET /plugins/{type}` 按此排序。实际类型与 `body.type` 不符的命名空间会被跳过(不写入,也不让整个请求报错)——为什么会有这个检查,见 `PutPluginPriorityBody::kind` 自身的文档。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/plugins.rs:432 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 异步执行插件 [Section titled “异步执行插件”](#异步执行插件) POSThttp\://localhost:3000/api/plugins/queue 执行一个插件并返回与本次执行对应的 Minion 任务 ID。若你想执行耗时较长、用标准端点可能会超时的插件,这个端点很有用。 #### 查询参数 * idstring · min: 40 · max: 40 · pattern可选 要在其上执行插件的档案 ID。只有元数据插件才必须提供。 * priorityinteger · default: 0可选 Minion 任务的优先级。数字越大越优先。 * pluginstring可选 要使用的插件命名空间。 * argstring可选 执行该插件时可选的 One-Shot 参数。 #### 响应 200已入队的任务 ``` { "job": 86, "operation": "queue_plugin_exec", "success": 1 } ``` 服务器地址http\://localhost:3000API 令牌••••• idquerypriorityquerypluginqueryargquery 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 读取插件当前持久化的 `customargs`(`GET /plugins/settings?namespace=...`,按定义补齐/截断) [Section titled “读取插件当前持久化的 customargs(GET /plugins/settings?namespace=...,按定义补齐/截断)”](#读取插件当前持久化的-customargsget-pluginssettingsnamespace按定义补齐截断) GEThttp\://localhost:3000/api/plugins/settings 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/plugins.rs:461)的**译文**;原文以源码为准。 `GET /plugins/settings?namespace=...`——插件当前持久化的 `customargs`(会被补齐/截断到它自己声明的 `parameters.len()` 恰好长度——一个比插件当前声明更长或更短的过期已保存数组,例如插件升级增删过参数之后,会被静默调整到当前形状,而不是作为不匹配暴露出来,与 legacy 在 `get_plugin_parameters` 里「先填默认值再覆盖」的行为一致)以及 `enabled`(legacy 的「自动运行」开关——`is_plugin_enabled`,从未设置时为 `false`,与 legacy 自己那个以 `hexists` 为条件的默认值相同)。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/plugins.rs:422 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 写入插件设置 [Section titled “写入插件设置”](#写入插件设置) PUThttp\://localhost:3000/api/plugins/settings 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `put_plugin_settings`,位于 crates/lanrurugi-api/src/plugins.rs:497。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/plugins.rs:422 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 上传插件 [Section titled “上传插件”](#上传插件) POSThttp\://localhost:3000/api/plugins/upload 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `upload_plugin`,位于 crates/lanrurugi-api/src/plugins.rs:3924。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/plugins.rs:434 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 执行插件 [Section titled “执行插件”](#执行插件) POSThttp\://localhost:3000/api/plugins/use 执行一个插件并返回结果。 如果用的是元数据插件,匹配到的档案不会在数据库中被修改。插件的更多说明见文档中对应的章节。 #### 查询参数 * idstring · min: 40 · max: 40 · pattern可选 要在其上执行插件的档案 ID。只有元数据插件才必须提供。 * pluginstring可选 要使用的插件命名空间。 * argstring可选 执行该插件时可选的 One-Shot 参数。 #### 响应 200插件执行结果 ``` { "data": { "new_tags": "pages:45" }, "operation": "use_plugin", "success": 1, "type": "metadata" } ``` 服务器地址http\://localhost:3000API 令牌••••• idquerypluginqueryargquery 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # 偏好设置 > 2 endpoints. 2 endpoints. ## 读取调用者自己的偏好设置 [Section titled “读取调用者自己的偏好设置”](#读取调用者自己的偏好设置) GEThttp\://localhost:3000/api/preferences 调用者自己的书库视图偏好;任何从未设置过的值都会回落到默认值。未认证的调用者拿到的是默认值——不是别人的设置。 #### 响应 200生效中的偏好设置。 ``` { "library_sortby": "", "library_sortdir": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 更新调用者自己的偏好设置 [Section titled “更新调用者自己的偏好设置”](#更新调用者自己的偏好设置) PUThttp\://localhost:3000/api/preferences 保存调用者的书库视图偏好。请求中省略的字段保持原样。需要已认证的调用者;未认证的调用会被拒绝,而不是悄悄写进一个共享的存储桶。 #### 请求体 application/json #### 响应 200已保存;响应体会回显保存后的值。 ``` { "library_sortby": "", "library_sortdir": "" } ``` 403没有已认证的调用者,无法确定偏好的归属。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # 推荐 > 1 endpoint. 1 endpoint. ## 获取推荐 [Section titled “获取推荐”](#获取推荐) GEThttp\://localhost:3000/api/reader/recommendations/{id} 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `get_recommendations`,位于 crates/lanrurugi-api/src/recommend.rs:438。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/recommend.rs:430 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # 维护脚本 > 3 endpoints. 3 endpoints. ## 修复乱码元数据(`POST /database/scripts/repair-mojibake`) [Section titled “修复乱码元数据(POST /database/scripts/repair-mojibake)”](#修复乱码元数据post-databasescriptsrepair-mojibake) POSThttp\://localhost:3000/api/database/scripts/repair-mojibake 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/scripts.rs:61)的**译文**;原文以源码为准。 `POST /database/scripts/repair-mojibake`——为什么在导入器早已学会修复之后,已存储的记录里仍可能存在双重编码的文本,见 `crate::mojibake` 自身的文档。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/scripts.rs:41 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 按子目录批量建分类(`POST /database/scripts/subfolders-to-categories`,扫描档案目录并为每个子目录建一个分类) [Section titled “按子目录批量建分类(POST /database/scripts/subfolders-to-categories,扫描档案目录并为每个子目录建一个分类)”](#按子目录批量建分类post-databasescriptssubfolders-to-categories扫描档案目录并为每个子目录建一个分类) POSThttp\://localhost:3000/api/database/scripts/subfolders-to-categories 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/scripts.rs:182)的**译文**;原文以源码为准。 `POST /database/scripts/subfolders-to-categories`——扫描档案目录,并为每个直接包含档案的子目录创建一个静态分类(`FolderToCat.pm::run_script`)。 响应里会报告它自己的墙上时钟耗时 `elapsed_ms`(从遍历目录到创建分类,含两端),以便与 `plugins/script/foldertocat.ts` 直接对比——那是一个真实的 `.ts` 脚本插件,自己完成完全相同的目录遍历与分组逻辑(用 `Deno.readDir`,而不是由宿主注入路径——用户要的是真正的正面对比,而不是让插件拿着别人遍历好的数据这种人为构造的场景),用来衡量把这类 I/O 密集的整库扫描放进 Deno 子进程插件沙箱、相对原生 Rust 究竟有多少真实开销。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/scripts.rs:33 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 按子目录批量建 Tankoubon(`POST /database/scripts/subfolders-to-tankoubons`,只扫描**第一层子目录**) [Section titled “按子目录批量建 Tankoubon(POST /database/scripts/subfolders-to-tankoubons,只扫描第一层子目录)”](#按子目录批量建-tankoubonpost-databasescriptssubfolders-to-tankoubons只扫描第一层子目录) POSThttp\://localhost:3000/api/database/scripts/subfolders-to-tankoubons 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/scripts.rs:494)的**译文**;原文以源码为准。 `POST /database/scripts/subfolders-to-tankoubons`——只扫描档案目录的**第一层子目录**,并为每个这样的子目录创建一个 Tankoubon。该第一层子目录下的所有档案(包括更深层嵌套子目录里的)都会被加入同一个 Tankoubon;嵌套子目录不会创建自己的 Tankoubon。允许重名;这是非破坏性操作,绝不会删除或去重已有的 Tankoubon。 配置了 DeepSeek API 密钥时,该端点会尽力用 LLM 推断一个更好的 Tankoubon 名称以及一个 `artist:`/`circle:` 作者标签。没有密钥、或 LLM 调用失败时,它会回退到原始目录名并跳过作者标签。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/scripts.rs:37 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # 搜索 API > 对档案索引执行搜索。 对档案索引执行搜索。 ## 搜索档案 [Section titled “搜索档案”](#搜索档案) GEThttp\://localhost:3000/api/search 搜索档案。这个 JSON 里的 ID 可以用在其他端点上。 权限差异 * 访客(开启访客访问时的未认证访问者)只能看到所属分类被标记为「访客可见」的档案;其他身份能看到整个书库。 #### 查询参数 * categorystring · min: 14 · max: 14 · pattern可选 限定本次搜索范围的分类 ID。 * filterstring可选 搜索查询串。可以在这当中使用下列特殊字符: **双引号 ("...")** 精确字符串搜索。让一个搜索词可以包含空格;一对双引号内的所有内容会被当成单个词条处理。通配符仍然按通配符解释。 **问号 (?)、下划线 (\_)** 通配符,匹配任意单个字符。 **星号 (\*)、百分号 (%)** 通配符,匹配任意长度的字符序列(也可以一个都不匹配)。 **减号 (-)** 排除。放在某个词前面,搜索结果就不会包含该词。 **美元符号 ($)** 加在标签末尾,对该标签做精确搜索,而不是显示所有以该词开头的结果。它只匹配标签,不受搜索参数影响,因此也可以当作排除项,用来在搜索里忽略杂项标签。 * startinteger可选 从结果总数中的第几个档案开始枚举。单页显示的档案数取决于服务端的每页条数偏好。 从 0.8.2 起,这里传 "-1" 可以取到完整的、不分页的数据。 * sortbystring可选 结果排序所依据的命名空间。可用的排序键有: - \*title\*:按标题排序 - \*lastread\*:按上次阅读时间排序(需开启 **服务端进度跟踪** ) (默认值是 title。按 lastread 排序时,从未读过的 ID 会被从搜索结果里移除。) * orderstring可选 排序方向,`asc` 或 `desc`。 * newonlyboolean可选 只搜索未读过的档案。 * untaggedonlyboolean可选 只搜索未打标签的档案。 * hidecompletedboolean可选 隐藏已读到末尾的档案。 * groupby_tanksboolean · default: true可选 启用或关闭 Tankoubon 分组,默认开启。 开启时,搜索结果里会显示 Tankoubon,取代它包含的所有档案 ID。 #### 响应 200搜索结果 ``` { "data": [ { "arcid": "28697b96f0ac5858be2614ed10ca47742c9522fd", "extension": "rar", "filename": "Fate GO MEMO", "isnew": false, "lastreadtime": 1337038281, "pagecount": 34, "progress": 3, "size": 0, "summary": null, "tags": "parody:fate grand order, group:wadamemo, artist:wada rco, artbook, full color", "title": "Fate GO MEMO" }, { "arcid": "28697b96f0ac5858be2614ed10ca47742c9522fd", "extension": "rar", "filename": "Gucc", "isnew": false, "lastreadtime": 1337038281, "pagecount": 34, "progress": 3, "size": 0, "summary": "cool summary", "tags": "parody:jojo's bizarre adventure", "title": "Rohan Kishibe goes to Gucci" } ], "recordsFiltered": 2, "recordsTotal": 2 } ``` 204搜索引擎尚未初始化完成,请稍等几秒。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• categoryqueryfilterquerystartquerysortbyqueryorderquerynewonlyqueryuntaggedonlyqueryhidecompletedquerygroupby_tanksquery 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 原始档案搜索端点(`GET /search/archives`),共用 `/search` 的查询参数,但不会把成员档案折叠进 Tankoubon [Section titled “原始档案搜索端点(GET /search/archives),共用 /search 的查询参数,但不会把成员档案折叠进 Tankoubon”](#原始档案搜索端点get-searcharchives共用-search-的查询参数但不会把成员档案折叠进-tankoubon) GEThttp\://localhost:3000/api/search/archives 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/search.rs:435)的**译文**;原文以源码为准。 新增的原始档案搜索端点(`GET /search/archives`),共用 `/search` 的查询语法、筛选、排序与分页,但绝不把成员档案折叠到 Tankoubon 之后。它刻意是一个独立端点,而不是 `/search` 上的一个新默认行为:既有的分组搜索调用方保持完全一致的行为,而重复项/库成员检查则可以索取底层的档案记录,而不是一个 `TANK_` 聚合体。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/search.rs:200 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 丢弃搜索缓存 [Section titled “丢弃搜索缓存”](#丢弃搜索缓存) DELETEhttp\://localhost:3000/api/search/cache 丢弃存放用户历史搜索的缓存。 #### 响应 200成功响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 400没有档案 ID 的响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Forget one entry [Section titled “Forget one entry”](#forget-one-entry) DELETEhttp\://localhost:3000/api/search/history What the search panel’s `Delete` key calls on a highlighted history row. Removes every occurrence, so a hand-edited list cannot leave a row the reader cannot dismiss. #### 查询参数 * filterstring必填 The exact history entry to forget. #### 响应 200The history after the removal. ``` { "history": [ "" ] } ``` 400No filter to forget was given. ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 403The caller has no account to keep a history for. ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• filterquery 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## The account’s recent searches [Section titled “The account’s recent searches”](#the-accounts-recent-searches) GEThttp\://localhost:3000/api/search/history Newest first, at most 8 entries (the cap the browser-side version kept). With `filter`, only the entries related to it, judged with the engine’s own folding, so `くろ` still offers a stored `クロガネ`; without it, the whole history. A caller with no account (e.g. a read-only token) gets an empty list; guests are denied by the route policy. #### 查询参数 * filterstring可选 What the reader is typing; limits the answer to the related entries. #### 响应 200The (possibly filtered) history. ``` { "history": [ "" ] } ``` 服务器地址http\://localhost:3000API 令牌••••• filterquery 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Remember one applied filter [Section titled “Remember one applied filter”](#remember-one-applied-filter) POSThttp\://localhost:3000/api/search/history Moves the entry to the front, removing any previous occurrence and trimming to the cap, in one atomic pipeline. Called only for a genuinely applied filter. #### 请求体 application/json #### 响应 200The history after the write. ``` { "history": [ "" ] } ``` 400The filter was empty. ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 403The caller has no account to keep a history for. ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 搜索档案 ID [Section titled “搜索档案 ID”](#搜索档案-id) GEThttp\://localhost:3000/api/search/ids 与 `/api/search` 一样搜索档案,但只返回匹配档案 ID 的有序列表,不带随附的元数据。 权限差异 * 作用域与 `/api/search` 相同:访客只会拿到访客可见档案的 ID。 #### 查询参数 * categorystring · min: 14 · max: 14 · pattern可选 限定本次搜索范围的分类 ID。 * filterstring可选 搜索查询串,规则与 `/api/search` 相同。 * startinteger可选 从结果总数中的第几个档案开始枚举。单页显示的档案数取决于服务端的每页条数偏好。 从 0.8.2 起,这里传 "-1" 可以取到完整的、不分页的 ID 列表。 * sortbystring可选 结果排序所依据的命名空间。可用的排序键有: - \*title\*:按标题排序 - \*lastread\*:按上次阅读时间排序(需开启 **服务端进度跟踪** ) (默认值是 title。按 lastread 排序时,从未读过的 ID 会被从搜索结果里移除。) * orderstring可选 排序方向,`asc` 或 `desc`。 * newonlyboolean可选 只搜索未读过的档案。 * untaggedonlyboolean可选 只搜索未打标签的档案。 * hidecompletedboolean可选 隐藏已读到末尾的档案。 * groupby_tanksboolean · default: true可选 启用或关闭 Tankoubon 分组,默认开启。 开启时,搜索结果里会显示 Tankoubon,取代它包含的所有档案 ID。 #### 响应 200搜索结果 ``` { "data": [ "28697b96f0ac5858be2614ed10ca47742c9522fd", "5cf64ec2f3c2c627fb8a64df198af2a8527c4fdb" ], "recordsFiltered": 2, "recordsTotal": 2 } ``` 204搜索引擎尚未初始化完成,请稍等几秒。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• categoryqueryfilterquerystartquerysortbyqueryorderquerynewonlyqueryuntaggedonlyqueryhidecompletedquerygroupby_tanksquery 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 随机搜索档案 [Section titled “随机搜索档案”](#随机搜索档案) GEThttp\://localhost:3000/api/search/random 按给定的筛选条件和/或分类,随机取出一批档案。 权限差异 * 作用域与 `/api/search` 相同:访客只会在访客可见的档案中随机抽取。 #### 查询参数 * categorystring · min: 14 · max: 14 · pattern可选 限定本次搜索范围的分类 ID。 * filterstring可选 搜索查询串,规则与 `/api/search` 相同。 * countinteger · default: 5可选 要随机取多少个档案,默认 5。 如果搜索结果的条数不够你要的数量,就返回全部搜索结果打乱后的结果。 * newonlyboolean可选 只搜索未读过的档案。 * untaggedonlyboolean可选 只搜索未打标签的档案。 * hidecompletedboolean可选 隐藏已读到末尾的档案。 * groupby_tanksboolean · default: true可选 启用或关闭 Tankoubon 分组,默认开启。 开启时,搜索结果里会显示 Tankoubon,取代它包含的所有档案 ID。 #### 响应 200搜索结果 ``` { "data": [ { "arcid": "28697b96f0ac5858be2614ed10ca47742c9522fd", "extension": "rar", "filename": "Gucc", "isnew": false, "lastreadtime": 1337038281, "pagecount": 34, "progress": 3, "size": 0, "summary": "cool summary", "tags": "parody:jojo's bizarre adventure", "title": "Rohan Kishibe goes to Gucci" } ], "recordsTotal": 2 } ``` 服务器地址http\://localhost:3000API 令牌••••• categoryqueryfilterquerycountquerynewonlyqueryuntaggedonlyqueryhidecompletedquerygroupby_tanksquery 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 为书库搜索框的标题自动补全提供数据的轻量端点 [Section titled “为书库搜索框的标题自动补全提供数据的轻量端点”](#为书库搜索框的标题自动补全提供数据的轻量端点) GEThttp\://localhost:3000/api/search/suggest 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/search.rs:603)的**译文**;原文以源码为准。 新增的轻量端点,为书库搜索框的标题自动补全提供数据。与 `/search` 不同,它只返回前几个匹配项中的 `arcid` + `title`——没有标签、进度或体积——因为前端每敲一次键(已做防抖)就会调用它,而一次返回 100 条档案记录的完整 `/search` 页会有几百 KB 的 JSON,建议列表拿到后立刻就丢掉了。查询语法相同、筛选相同、默认的 `title` 排序也相同(这正是建议列表想要的),并且访客范围限制也相同:这里同样应用 `restrict_to_archive_ids`,因此 `guest_visitor` 绝不可能通过这个端点看到一个 `/search` 会拒绝返回的越界标题。 权限差异 * 作用域与 `/api/search` 相同,因此访客不可能看到 `/api/search` 会拒绝返回的档案标题。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/search.rs:202 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # 登录设备 > 3 endpoints. 3 endpoints. ## 列出已登录设备 [Section titled “列出已登录设备”](#列出已登录设备) GEThttp\://localhost:3000/api/sessions 每一个活跃的 refresh token 家族——也就是每一台当前已登录的设备——包括发出本次请求的这一台,它会被标记出来,以免客户端不小心提出吊销自己。 需要会话 cookie 登录。任何角色的 API 令牌都会被拒绝。 #### 响应 200当前活跃的会话。 ``` [ { "auto_name": "", "created_at": 0, "current": false, "custom_name": "", "expires_at": 0, "family_id": "", "idle_expires_at": 0, "ip": "", "last_seen_at": 0, "name": "" } ] ``` 服务器地址http\://localhost:3000 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 吊销一台已登录设备 [Section titled “吊销一台已登录设备”](#吊销一台已登录设备) DELETEhttp\://localhost:3000/api/sessions/{family_id} 通过吊销某个会话的整个 refresh token 家族来结束它,该设备必须重新登录。需要会话 cookie 登录。 #### 路径参数 * family_idstring必填 #### 响应 200已吊销。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 404没有该会话。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000 family_idpath 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 重命名一台已登录设备 [Section titled “重命名一台已登录设备”](#重命名一台已登录设备) PATCHhttp\://localhost:3000/api/sessions/{family_id} 为某个会话设置自定义显示名,这样设备列表读起来是「客厅平板」而不是一串 user-agent。需要会话 cookie 登录。 #### 路径参数 * family_idstring必填 #### 请求体 application/json #### 响应 200已重命名。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 404没有该会话。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000 family_idpath 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # 设置 > 4 endpoints. 4 endpoints. ## 获取设置 [Section titled “获取设置”](#获取设置) GEThttp\://localhost:3000/api/settings 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `get_settings`,位于 crates/lanrurugi-api/src/settings.rs:628。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/settings.rs:59 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 写入设置 [Section titled “写入设置”](#写入设置) PUThttp\://localhost:3000/api/settings 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `put_settings`,位于 crates/lanrurugi-api/src/settings.rs:755。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/settings.rs:59 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 设置新的管理员密码,哈希方式与 legacy 存密码的方式一致(`{CRYPT}$2a$...`) [Section titled “设置新的管理员密码,哈希方式与 legacy 存密码的方式一致({CRYPT}$2a$...)”](#设置新的管理员密码哈希方式与-legacy-存密码的方式一致crypt2a) POSThttp\://localhost:3000/api/settings/password 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/settings.rs:1021)的**译文**;原文以源码为准。 设置新的管理员密码,哈希方式与 legacy 存密码的方式一致(`{CRYPT}$2a$...`——见 `lanrurugi_core::password`),这样共用同一 Redis 的 legacy 实例也仍然接受它。空字符串会清除密码保护的实际效果,但方式与 legacy 配置页「留空则保持当前密码」的约定*不同*——这个端点总是设置提交上来的内容,因此除非用户确实想设一个空密码,前端绝不能提交空字段。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/settings.rs:60 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 读取主题(issue #92:这个响应现在还带着 `language`,不只是 `theme`) [Section titled “读取主题(issue #92:这个响应现在还带着 language,不只是 theme)”](#读取主题issue-92这个响应现在还带着-language不只是-theme) GEThttp\://localhost:3000/api/theme 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/settings.rs:160)的**译文**;原文以源码为准。 issue #92:这个响应现在还带着 `language`,不只是 `theme`——`useApplyTheme`/`useApplySettingsLanguage`(`apps/frontend/src/theme.ts`/`i18n/index.ts`)过去都从完整的、需要鉴权的 `GET /settings` 里读取各自那个字段(该响应还带着 API 密钥和其他确实属于机密的字段,无法公开,因此登录前会 401)——每个在会话存在之前渲染的页面(登录页自己那套特制的 `usePublicTheme` 回退除外)都撞上那个 401,而 `client.ts` 里那个*全局* 401 处理器在每一次上都强制跳转到 `/login`,不管发起调用的 hook 自己是否已经准备好了回退值,从而使 issue #92 自己「留在当前页、不要跳转」的要求对任何在登出状态下渲染的内容都失效(新加的 404 页面尤其如此——实测报告了一次真实的双重跳转:先闪一下 404 内容,然后还是去了 `/login`)。`theme`/`language` 是会话存在之前唯一需要的两个字段,而且两者都完全不机密,所以把 `language` 折进这个已经公开的端点,比为多一个字段再撑起一整套公开设置接口要简单。响应里还带着 `admin_theme`——始终是管理员自己的 `theme`,与访客资格无关——这样即使开启了访客模式、且访客主题是另一套,登录页也能用管理员的主题渲染。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/settings.rs:70 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点不需要认证。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # Shinobu API > 4 endpoints. 4 endpoints. ## 获取 Shinobu 状态 [Section titled “获取 Shinobu 状态”](#获取-shinobu-状态) GEThttp\://localhost:3000/api/shinobu 获取 FileWatcher 的当前状态。 #### 响应 200状态 ``` { "is_alive": 1, "operation": "shinobu_status", "pid": 1608, "success": 1 } ``` 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 重新扫描 filemap 并重启 Shinobu [Section titled “重新扫描 filemap 并重启 Shinobu”](#重新扫描-filemap-并重启-shinobu) POSThttp\://localhost:3000/api/shinobu/rescan 这会删除系统上已扫描文件的内部映射(即「filemap」)并重启 Shinobu,相当于触发一次对文件系统的完整重新扫描。 #### 响应 200结果 ``` { "new_pid": 1727, "operation": "shinobu_rescan", "success": 1 } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 重启 Shinobu [Section titled “重启 Shinobu”](#重启-shinobu) POSThttp\://localhost:3000/api/shinobu/restart 重启 Shinobu 文件监视器 #### 响应 200结果 ``` { "new_pid": 1727, "operation": "shinobu_restart", "success": 1 } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 停止 Shinobu [Section titled “停止 Shinobu”](#停止-shinobu) POSThttp\://localhost:3000/api/shinobu/stop 停止文件监视器。用 `/api/shinobu/restart` 再次启动它。 #### 响应 200结果 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # 图章 API > 8 endpoints. 8 endpoints. ## 获取该档案中至少含有一个图章的页面 [Section titled “获取该档案中至少含有一个图章的页面”](#获取该档案中至少含有一个图章的页面) GEThttp\://localhost:3000/api/archives/{id}/stamps 获取该档案中至少含有一个图章的页面。 权限差异 * 对**不在访客可见范围内**的档案,这里返回 **404** 而不是 403——刻意与「档案不存在」不可区分,因此这个响应无法被用来探测访客范围之外的档案是否存在。 #### 路径参数 * idstring必填 档案 ID。 #### 响应 200成功响应 ``` { "result": [ "" ] } ``` 400错误响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpath 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 获取链接到该页面的图章 [Section titled “获取链接到该页面的图章”](#获取链接到该页面的图章) GEThttp\://localhost:3000/api/archives/{id}/stamps/{index} 获取链接到该页面的图章。 权限差异 * 对**不在访客可见范围内**的档案,这里返回 **404** 而不是 403——刻意与「档案不存在」不可区分,因此这个响应无法被用来探测访客范围之外的档案是否存在。 #### 路径参数 * idstring必填 档案 ID。 * indexinteger必填 档案的页码。 #### 响应 200成功响应 ``` { "result": [ { "content": "Lorem ipsum dolore", "position": "12,34" } ] } ``` 400错误响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpathindexpath 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 添加图章标注 [Section titled “添加图章标注”](#添加图章标注) PUThttp\://localhost:3000/api/archives/{id}/stamps/{index} 在给定坐标处向该页面添加一个新图章。 #### 路径参数 * idstring必填 档案 ID。 * indexinteger必填 档案的页码。 #### 查询参数 * contentstring可选 图章文本。 * positionstring可选 图章在页面中的位置。 #### 响应 200成功响应 ``` { "operation": "add_stamp", "stamp_id": "", "success": 0 } ``` 400错误响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpathindexpathcontentquerypositionquery 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 删除图章 [Section titled “删除图章”](#删除图章) DELETEhttp\://localhost:3000/api/stamps/{id} 从某个档案中移除一个图章。 #### 路径参数 * idstring必填 图章 ID。 #### 响应 200成功响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 400错误响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 423该图章当前被锁定,无法修改 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpath 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 获取图章 [Section titled “获取图章”](#获取图章) GEThttp\://localhost:3000/api/stamps/{id} 从某个档案获取一个图章。 #### 路径参数 * idstring必填 图章 ID。 #### 响应 200成功响应 ``` { "content": "Lorem ipsum dolore", "position": "12,34" } ``` 400错误响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 423该图章当前被锁定,无法修改 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpath 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 更新图章 [Section titled “更新图章”](#更新图章) PUThttp\://localhost:3000/api/stamps/{id} 更新某个档案中的一个图章。 #### 路径参数 * idstring必填 图章 ID。 #### 查询参数 * contentstring可选 图章文本。 * positionstring可选 图章在页面中的位置。 #### 响应 200成功响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 400错误响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 423该图章当前被锁定,无法修改 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpathcontentquerypositionquery 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 获取 Tankoubon 中某页的图章 [Section titled “获取 Tankoubon 中某页的图章”](#获取-tankoubon-中某页的图章) GEThttp\://localhost:3000/api/tankoubons/{id}/stamps/{page} 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `tank_stamps_by_page`,位于 crates/lanrurugi-api/src/stamps.rs:58。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/stamps.rs:52 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 向 Tankoubon 添加图章 [Section titled “向 Tankoubon 添加图章”](#向-tankoubon-添加图章) PUThttp\://localhost:3000/api/tankoubons/{id}/stamps/{page} 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `tank_add_stamp`,位于 crates/lanrurugi-api/src/stamps.rs:72。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/stamps.rs:52 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # 库统计 > 3 endpoints. 3 endpoints. ## The archives behind one bar of one chart [Section titled “The archives behind one bar of one chart”](#the-archives-behind-one-bar-of-one-chart) GEThttp\://localhost:3000/api/stats/bucket A drill-down: given one bucket of one `/stats` chart, the archives in it, for the list the page shows under the chart. Fetched per click rather than folded into `/stats/overview`, which is a whole-library snapshot that would have to carry every bucket’s archive list to support this. Deliberately not expressed as a search query, even though some of these buckets have one: “last read on day X” has no search operator at all, and the progress ladder’s `unread` rung means “never *opened*” (its own `is_read`) while the search’s `read:`/`is:unread` filters key on the `progress` field alone — so they disagree about an archive that was opened without a page turn. Deriving the list from the same classification the chart used is what keeps the list and the bar consistent by construction. Requesting this as a guest is scoped to what that guest may see, matching `/stats/overview`. #### 查询参数 * metricstring · enum: ingest | read | size | rating | progress必填 `ingest`/`read` are time buckets and need `from`+`to`; `size`/`rating`/`progress` are keyed buckets and need `key`. * fromstring可选 `ingest`/`read` only. First day of the bucket, `YYYY-MM-DD`, inclusive. The client sends the span it actually drew rather than a unit+key pair, so no bucket-key-to-span arithmetic has to exist in two languages. * tostring可选 `ingest`/`read` only. Last day of the bucket, `YYYY-MM-DD`, inclusive. * keystring可选 `size` bucket key (`lt_1mb` … `gte_500mb`), a `rating` of `0`-`5` (where `0` is the unrated-or-zero slot, exactly as the chart's own distribution counts it), or a `progress` ladder key (`unread`, `1_20`, `21_40`, `41_60`, `61_80`, `81_99`, `finished`). #### 响应 200The bucket's archives, newest/largest/most-progressed first per metric. ``` { "archives": [ null ], "metric": "ingest", "total": 0, "truncated": false } ``` 400Unknown metric, or a missing/invalid \`from\`/\`to\`/\`key\` for that metric. ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• metricqueryingestfromquerytoquerykeyquery 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Aggregated library statistics [Section titled “Aggregated library statistics”](#aggregated-library-statistics) GEThttp\://localhost:3000/api/stats/overview One snapshot covering: headline totals, archive size distribution, container format/MIME breakdown, ingestion history (by month, by ingestion path, and the newest arrivals), reading history (per-day, progress distribution, ratings, and the most recently/most often read works), and a weighted reading-preference analysis over tags, authors and categories. Requesting this as a guest yields counts and breakdowns restricted to what that guest may actually see, matching `/database/stats`’s own scoping. Weighted preference values are relative rankings, not probabilities or percentages: they are only ever meaningful against each other within one response. #### 响应 200The aggregated snapshot. ``` { "formats": [ null ], "generated_at": 0, "ingest": { "recent": null, "sources": null, "sources_sampled": null, "sources_sampled_only": null }, "note": "no_server_side_reading", "preferences": { "by_namespace": null, "categories": null, "categories_truncated": null, "highlights": null, "namespaces": null, "ratings": null, "read_archives": null }, "reading": { "most_reread": null, "progress": null, "ratings": null, "recent": null }, "size_buckets": [ null ], "totals": { "archives": null, "average_bytes": null, "average_pages": null, "bookmarks": null, "categories": null, "finished": null, "largest_bytes": null, "new": null, "pages": null, "pages_read": null, "rated": null, "reading": null, "storage_bytes": null, "tankoubons": null, "unread": null } } ``` 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## One metric’s daily time series [Section titled “One metric’s daily time series”](#one-metrics-daily-time-series) GEThttp\://localhost:3000/api/stats/timeline The page’s time-series source, kept separate from `/stats/overview` because it is driven interactively: the overview is one expensive snapshot (its preference analysis runs a search per dynamic category), while this endpoint is refetched per range change and re-bucketed entirely client-side. The series is **always daily**, whatever granularity the reader is looking at, so that changing granularity — or zooming and panning — needs no request at all once the range has been fetched once. A request wider than the server’s own cap is clamped to the *newest* days of it, and `available_from` still reports where the data really begins. Requesting this as a guest is scoped to what that guest may see, matching `/stats/overview`. #### 查询参数 * metricstring · enum: ingest | reading必填 `ingest` counts archives added per day (from each archive's own `date_added` tag); `reading` reports page turns and archives-last-read per day. * frominteger可选 Unix seconds. Defaults to the whole available range — which is what the page asks for, so every later zoom is local. Clamped to the library's own data. * tointeger可选 Unix seconds; defaults to now, and is never later than it. #### 响应 200The daily series, oldest first. ``` { "available_from": "", "available_to": "", "from": "", "metric": "ingest", "pages_since": "", "points": [ null ], "to": "" } ``` 400\`metric\` was missing or was neither \`ingest\` nor \`reading\`. ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• metricqueryingestfromquerytoquery 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # 订阅 > 25 endpoints. 25 endpoints. ## 列出预留 [Section titled “列出预留”](#列出预留) GEThttp\://localhost:3000/api/reservations 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `list_reservations`,位于 crates/lanrurugi-api/src/subscriptions/api.rs:1007。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:54 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 放弃预留 [Section titled “放弃预留”](#放弃预留) POSThttp\://localhost:3000/api/reservations/{id}/discard 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `discard_reservation`,位于 crates/lanrurugi-api/src/subscriptions/api.rs:1027。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:55 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 列表 [Section titled “列表”](#列表) GEThttp\://localhost:3000/api/subscriptions 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `list`,位于 crates/lanrurugi-api/src/subscriptions/api.rs:172。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:27 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 创建 [Section titled “创建”](#创建) POSThttp\://localhost:3000/api/subscriptions 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `create`,位于 crates/lanrurugi-api/src/subscriptions/api.rs:249。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:27 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 移除 [Section titled “移除”](#移除) DELETEhttp\://localhost:3000/api/subscriptions/{id} 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `remove`,位于 crates/lanrurugi-api/src/subscriptions/api.rs:352。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:40 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 详情 [Section titled “详情”](#详情) GEThttp\://localhost:3000/api/subscriptions/{id} 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `detail`,位于 crates/lanrurugi-api/src/subscriptions/api.rs:292。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:40 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 更新 [Section titled “更新”](#更新) PUThttp\://localhost:3000/api/subscriptions/{id} 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `update`,位于 crates/lanrurugi-api/src/subscriptions/api.rs:311。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:40 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 用户自己投的反对票:这些作品从此不再被该订阅下载 [Section titled “用户自己投的反对票:这些作品从此不再被该订阅下载”](#用户自己投的反对票这些作品从此不再被该订阅下载) POSThttp\://localhost:3000/api/subscriptions/{id}/block 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/subscriptions/api.rs:644)的**译文**;原文以源码为准。 用户自己投的「不」:这些作品从此不再被该订阅下载。 刻意与「规则拒绝」区分开——规则读取的值会变化,所以拒绝是临时性的,每个周期都重新判定(FR-011i);而这是一个答复,重新判定就等于把用户已经说过的话再问一遍。预览界面按行提供这一操作;`forget_seen` 可以撤销它。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:50 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 立即执行一次真实检查,而不是等排期(FR-024) [Section titled “立即执行一次真实检查,而不是等排期(FR-024)”](#立即执行一次真实检查而不是等排期fr-024) POSThttp\://localhost:3000/api/subscriptions/{id}/check 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/subscriptions/api.rs:846)的**译文**;原文以源码为准。 立即执行一次真实检查,而不是等待排期(FR-024)。 它是派生出去执行的,而不是被 await:一次检查要联系来源,还可能翻页遍历,比一个请求应该保持打开的时间更长。结果会出现在该订阅自己的历史里。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:48 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 停用 [Section titled “停用”](#停用) POSThttp\://localhost:3000/api/subscriptions/{id}/disable 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `disable`,位于 crates/lanrurugi-api/src/subscriptions/api.rs:388。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:45 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 启用 [Section titled “启用”](#启用) POSThttp\://localhost:3000/api/subscriptions/{id}/enable 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `enable`,位于 crates/lanrurugi-api/src/subscriptions/api.rs:378。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:44 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 让某个订阅重新考虑它已经处理过的作品 [Section titled “让某个订阅重新考虑它已经处理过的作品”](#让某个订阅重新考虑它已经处理过的作品) POSThttp\://localhost:3000/api/subscriptions/{id}/forget 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/subscriptions/api.rs:597)的**译文**;原文以源码为准。 让某个订阅重新考虑它已经处理过的作品。 「已看过」在其他情况下是永久性的,这对通常情形是正确的——用户故意删掉的作品绝不能在下次检查时回来。但有两种情况需要撤销它:一次误删,以及一条后来被放宽的规则(在旧规则下被拒绝的作品在被拒绝的那一刻就被记为已看过,所以没有任何东西会重新考虑它们)。 带 `sources` 时只遗忘指定的那些。带 `all: true` 时清空整个集合——它被保留为一个独立的、显式的请求,因为在长期运行的订阅上,它可能一次匹配到全部历史目录,后果的量级不同。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:49 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 预览一次检查会做什么,但不真的执行 [Section titled “预览一次检查会做什么,但不真的执行”](#预览一次检查会做什么但不真的执行) POSThttp\://localhost:3000/api/subscriptions/{id}/preview 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/subscriptions/api.rs:803)的**译文**;原文以源码为准。 预览一次检查会做什么,但不真的执行。 它刻意可以作用于**已停用**的订阅:「这条规则实际会抓到什么」恰恰是在调整一条关掉的规则时问的。不会入队、不会记为已看过、也不会写日志,因此可以安全地反复运行——唯一的代价是向来源发一次请求。 接受一个可选的请求体携带尚未保存的订阅,这样规则可以在提交之前先预览。没有这一点,用户就得先保存一条规则才能知道它做什么。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:47 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 解除系统施加的暂停 [Section titled “解除系统施加的暂停”](#解除系统施加的暂停) POSThttp\://localhost:3000/api/subscriptions/{id}/resume 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/subscriptions/api.rs:400)的**译文**;原文以源码为准。 解除系统施加的暂停。与 `enable` 不同,因为被暂停的订阅是*被系统*停下的,它欠用户一个解释——恢复就是用户对这个解释的回应。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:46 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 用户显式屏蔽过的全部作品,最新的在前 [Section titled “用户显式屏蔽过的全部作品,最新的在前”](#用户显式屏蔽过的全部作品最新的在前) GEThttp\://localhost:3000/api/subscriptions/blocked 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/subscriptions/api.rs:417)的**译文**;原文以源码为准。 用户显式屏蔽过的全部作品,最新的在前,跨所有订阅。 它有自己的端点,而不是在历史记录上加个筛选:屏蔽是一个*答复*——用户对这个作品说了不——而历史是不断被后续周期重写的决策日志(一个先入队后入库的作品在每条记录里都读作 `already_held`)。只有屏蔽列表始终保持在用户留下的样子,这正是它值得单独展示、并从这里撤销的原因。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:53 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 生成 [Section titled “生成”](#生成) POSThttp\://localhost:3000/api/subscriptions/condition/ai 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `generate`,位于 crates/lanrurugi-api/src/subscriptions/ai_condition.rs:301。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:38 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 解析 [Section titled “解析”](#解析) POSThttp\://localhost:3000/api/subscriptions/condition/parse 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `parse`,位于 crates/lanrurugi-api/src/subscriptions/ai_condition.rs:284。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:39 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 全部订阅的近期候选,合并成一条按时间倒序的流 [Section titled “全部订阅的近期候选,合并成一条按时间倒序的流”](#全部订阅的近期候选合并成一条按时间倒序的流) GEThttp\://localhost:3000/api/subscriptions/history 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/subscriptions/api.rs:450)的**译文**;原文以源码为准。 全部订阅的近期候选,合并成一条按时间倒序的流。 按订阅分开的历史已经存在,但它回答的是「*这条*规则做了什么」——而实际被问到的通常是另一个问题:最近来了什么,以及某个预期中的东西为什么没来。那需要把各个订阅交错在一起,而不是逐个读。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:52 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 等待用户确认的已匹配作品 [Section titled “等待用户确认的已匹配作品”](#等待用户确认的已匹配作品) GEThttp\://localhost:3000/api/subscriptions/pending 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/subscriptions/api.rs:859)的**译文**;原文以源码为准。 已匹配、等待用户确认的作品。它之所以可达,仅仅因为 `auto_download` 默认关闭——否则那个默认值会让候选被记录下来却无从答复。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:31 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 批准——这一刻之后,无人值守的匹配才变成要花钱的操作 [Section titled “批准——这一刻之后,无人值守的匹配才变成要花钱的操作”](#批准这一刻之后无人值守的匹配才变成要花钱的操作) POSThttp\://localhost:3000/api/subscriptions/pending/approve 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/subscriptions/api.rs:892)的**译文**;原文以源码为准。 批准就是无人值守的匹配变成有人值守的花钱的时刻——在此之前不消耗任何下载额度。 部分成功会如实上报而不是整体回滚:有多个条目时,其中一个入队失败没有理由把其余的也一并撤销批准,调用方会被告知究竟哪些没能入队。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:32 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 忽略——把每个作品标记为已看过,后续检查就不会再问同样的问题 [Section titled “忽略——把每个作品标记为已看过,后续检查就不会再问同样的问题”](#忽略把每个作品标记为已看过后续检查就不会再问同样的问题) POSThttp\://localhost:3000/api/subscriptions/pending/dismiss 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/subscriptions/api.rs:980)的**译文**;原文以源码为准。 忽略会把每个作品标记为已看过,因此后续检查不会再提出同样的问题。这是用户在回答「不」——与预留不同,后者是系统在报告它*无法*下载某个东西。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:33 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 预览一个还不存在的订阅 [Section titled “预览一个还不存在的订阅”](#预览一个还不存在的订阅) POSThttp\://localhost:3000/api/subscriptions/preview 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/subscriptions/api.rs:744)的**译文**;原文以源码为准。 预览一个还不存在的订阅。 带 id 的路由无法承担这件事:没有记录可读。而恰恰是在创建一个订阅的时候,「这条规则实际会抓到什么」最重要——之后用户就已经把规则定下来了。草稿是按来源当前的状态求值的,无论结果如何都不会存储任何东西。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:36 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 在可能不同的条件下,重新评判一份已抓取的列表 [Section titled “在可能不同的条件下,重新评判一份已抓取的列表”](#在可能不同的条件下重新评判一份已抓取的列表) POSThttp\://localhost:3000/api/subscriptions/preview/judge 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/subscriptions/api.rs:684)的**译文**;原文以源码为准。 在可能不同的条件下,重新评判一份已抓取的列表。 改一个条件并不会改变来源会返回什么——只有 `criteria` 影响请求——所以重新抓取纯属浪费、很慢,而且是对一个有限流的来源又多发一次请求。判断仍然发生在这里而不是浏览器里,因为条件树的第二份实现迟早会与真实的那份产生分歧。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:37 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 哪些来源可以支撑一个订阅,以及各自的间隔上下限——好让界面只提供合法选项 [Section titled “哪些来源可以支撑一个订阅,以及各自的间隔上下限——好让界面只提供合法选项”](#哪些来源可以支撑一个订阅以及各自的间隔上下限好让界面只提供合法选项) GEThttp\://localhost:3000/api/subscriptions/sources 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/subscriptions/api.rs:186)的**译文**;原文以源码为准。 哪些来源可以支撑一个订阅,以及各自的间隔上下限——好让界面只提供可行的来源,并在用户提交*之前*就显示这些上下限,而不是通过一次拒绝来教会用户规则。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:28 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 哪些订阅已经处理过某个作品(按其来源 URL 查) [Section titled “哪些订阅已经处理过某个作品(按其来源 URL 查)”](#哪些订阅已经处理过某个作品按其来源-url-查) GEThttp\://localhost:3000/api/subscriptions/tracking 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/subscriptions/api.rs:555)的**译文**;原文以源码为准。 哪些订阅已经处理过某个作品(按其来源 URL 查)。 在删除档案之前询问,这样删除流程只会为「确实由某个订阅带进来」的档案提供「不要再让它回来」这个选项——对一个手动上传的文件提供该选项等于给了一个没有效果的开关,那比不给选项更糟。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:51 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # Tankoubon 分组 > 8 endpoints. 8 endpoints. ## AI 分组建议 [Section titled “AI 分组建议”](#ai-分组建议) POSThttp\://localhost:3000/api/tankoubons/ai-group-suggestions 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `ai_group_suggestions`,位于 crates/lanrurugi-api/src/tankoubon_grouping.rs:775。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/tankoubon_grouping.rs:97 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 取消忽略某条 AI 分组建议(`DELETE /tankoubons/ai-group-suggestions/ignore`) [Section titled “取消忽略某条 AI 分组建议(DELETE /tankoubons/ai-group-suggestions/ignore)”](#取消忽略某条-ai-分组建议delete-tankoubonsai-group-suggestionsignore) DELETEhttp\://localhost:3000/api/tankoubons/ai-group-suggestions/ignore 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/tankoubon_grouping.rs:1259)的**译文**;原文以源码为准。 `DELETE /tankoubons/ai-group-suggestions/ignore`——重新启用一条此前被忽略的建议(前端「显示已忽略的组合」清单里自己的「取消忽略」按钮)。幂等——取消忽略一个当前并未被忽略的组合是无操作,不是错误。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/tankoubon_grouping.rs:101 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 忽略某条 AI 分组建议(「不要再建议这个组合」) [Section titled “忽略某条 AI 分组建议(「不要再建议这个组合」)”](#忽略某条-ai-分组建议不要再建议这个组合) POSThttp\://localhost:3000/api/tankoubons/ai-group-suggestions/ignore 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/tankoubon_grouping.rs:1216)的**译文**;原文以源码为准。 `POST /tankoubons/ai-group-suggestions/ignore`——对某一条具体建议执行「不要再建议这个」。幂等(忽略一个已被忽略的组合只会覆盖它的 `ignored_at` 时间戳,见 `IgnoredGroupSuggestionsRepository::ignore` 自身的契约)。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/tankoubon_grouping.rs:101 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 列出被忽略的 AI 分组建议(支撑「显示已忽略的组合」) [Section titled “列出被忽略的 AI 分组建议(支撑「显示已忽略的组合」)”](#列出被忽略的-ai-分组建议支撑显示已忽略的组合) GEThttp\://localhost:3000/api/tankoubons/ai-group-suggestions/ignored 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/tankoubon_grouping.rs:1281)的**译文**;原文以源码为准。 `GET /tankoubons/ai-group-suggestions/ignored`——支撑「显示已忽略的组合」清单本身(标题由客户端针对已加载的档案列表解析,用的就是 `AiSmartTankoubonModal.tsx` 已经为主建议卡片构建的那张 `titleById` 映射——这个端点只需要返回原始的已忽略条目,不必在服务端做补全)。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/tankoubon_grouping.rs:105 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `DELETE /tankoubons/ai-group-suggestions/labels` (FR-017) [Section titled “DELETE /tankoubons/ai-group-suggestions/labels (FR-017)”](#delete-tankoubonsai-group-suggestionslabels-fr-017) DELETEhttp\://localhost:3000/api/tankoubons/ai-group-suggestions/labels 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/tankoubon_grouping/labels.rs:197),**逐字引用、未翻译**——它是写给本代码库维护者看的,可能会提到内部标识符。 `DELETE /tankoubons/ai-group-suggestions/labels` (FR-017). #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/tankoubon_grouping.rs:113 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `GET /tankoubons/ai-group-suggestions/labels` [Section titled “GET /tankoubons/ai-group-suggestions/labels”](#get-tankoubonsai-group-suggestionslabels) GEThttp\://localhost:3000/api/tankoubons/ai-group-suggestions/labels 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/tankoubon_grouping/labels.rs:185),**逐字引用、未翻译**——它是写给本代码库维护者看的,可能会提到内部标识符。 `GET /tankoubons/ai-group-suggestions/labels`. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/tankoubon_grouping.rs:113 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `POST /tankoubons/ai-group-suggestions/labels` [Section titled “POST /tankoubons/ai-group-suggestions/labels”](#post-tankoubonsai-group-suggestionslabels) POSThttp\://localhost:3000/api/tankoubons/ai-group-suggestions/labels 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/tankoubon_grouping/labels.rs:128),**逐字引用、未翻译**——它是写给本代码库维护者看的,可能会提到内部标识符。 `POST /tankoubons/ai-group-suggestions/labels`. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/tankoubon_grouping.rs:113 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `POST /tankoubons/ai-group-suggestions/review` — never an HTTP error for a review failure: the [Section titled “POST /tankoubons/ai-group-suggestions/review — never an HTTP error for a review failure: the”](#post-tankoubonsai-group-suggestionsreview--never-an-http-error-for-a-review-failure-the) POSThttp\://localhost:3000/api/tankoubons/ai-group-suggestions/review 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/tankoubon_grouping/review\.rs:489),**逐字引用、未翻译**——它是写给本代码库维护者看的,可能会提到内部标识符。 `POST /tankoubons/ai-group-suggestions/review` — never an HTTP error for a review failure: the card always renders, with the local result when the review could not be had. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/tankoubon_grouping.rs:109 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # Tankoubon API > 13 endpoints. 13 endpoints. ## 获取全部 Tankoubon [Section titled “获取全部 Tankoubon”](#获取全部-tankoubon) GEThttp\://localhost:3000/api/tankoubons 分页获取 Tankoubon 列表。 #### 查询参数 * pageinteger可选 Tankoubon 列表的页码。 每页数量取决于服务端的 `archives_per_page` 设置。 #### 响应 200Tankoubon 列表 ``` { "filtered": 0, "result": [ { "archives": [ "e69e43e1355267f7d32a4f9b7f2fe108d2401ebf", "e69e43e1355267f7d32a4f9b7f2fe108d2401eba" ], "id": "TANK_1749925516", "name": "sailor moon", "progress": 0, "summary": "", "tags": "" } ], "total": 0 } ``` 服务器地址http\://localhost:3000API 令牌••••• pagequery 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 创建 Tankoubon [Section titled “创建 Tankoubon”](#创建-tankoubon) PUThttp\://localhost:3000/api/tankoubons 创建一个新 Tankoubon,或更新已有 Tankoubon 的名称。 #### 请求体 application/x-www-form-urlencoded, multipart/form-data #### 响应 200成功响应 ``` { "operation": "create_tankoubon", "success": 0, "tankoubon_id": "" } ``` 400错误响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 删除 Tankoubon [Section titled “删除 Tankoubon”](#删除-tankoubon) DELETEhttp\://localhost:3000/api/tankoubons/{id} 从服务端移除一个 Tankoubon。这不会删除它底下的档案。 #### 响应 200成功响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 400错误响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 423该 Tankoubon 当前被锁定,无法修改 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 获取单个 Tankoubon [Section titled “获取单个 Tankoubon”](#获取单个-tankoubon) GEThttp\://localhost:3000/api/tankoubons/{id} 获取指定 tankoubon ID 的详情。 #### 响应 200Tankoubon ``` { "archives": [ "" ], "id": "", "name": "", "progress": 0, "summary": "", "tags": "" } ``` 400错误响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 更新 Tankoubon 的元数据与内容 [Section titled “更新 Tankoubon 的元数据与内容”](#更新-tankoubon-的元数据与内容) PUThttp\://localhost:3000/api/tankoubons/{id} 修改 Tankoubon 的完整元数据(名称、摘要、附加标签)或它的内容。\ 如果你只需要改名称,考虑直接用 PUT `/api/tankoubons`。 注意:如果不需要更新 `data` 里某个键对应的内容,就不要发送那个键——否则可能产生非预期的结果。 #### 路径参数 * idstring · min: 15 · max: 15 · pattern必填 要更新的 Tankoubon ID。 #### 请求体 application/json #### 响应 200成功响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 400错误响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 423该 Tankoubon 当前被锁定,无法修改 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpath 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 把档案移出 Tankoubon [Section titled “把档案移出 Tankoubon”](#把档案移出-tankoubon) DELETEhttp\://localhost:3000/api/tankoubons/{id}/{archive} 把某个档案移出一个 Tankoubon。 #### 路径参数 * idstring · min: 15 · max: 15 · pattern必填 要更新的 Tankoubon ID。 * archivestring · min: 40 · max: 40 · pattern必填 要移除的档案 ID。 #### 响应 200结果 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 400错误响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 423该 Tankoubon 当前被锁定,无法修改 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpatharchivepath 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 把档案加入 Tankoubon [Section titled “把档案加入 Tankoubon”](#把档案加入-tankoubon) PUThttp\://localhost:3000/api/tankoubons/{id}/{archive} 把一个档案追加到 Tankoubon 的最后一位。 #### 路径参数 * idstring · min: 15 · max: 15 · pattern必填 要更新的 Tankoubon ID。 * archivestring · min: 40 · max: 40 · pattern必填 要追加的档案 ID。 #### 响应 200成功响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 400错误响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 423该 Tankoubon 当前被锁定,无法修改 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpatharchivepath 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## AI 重命名章节 [Section titled “AI 重命名章节”](#ai-重命名章节) POSThttp\://localhost:3000/api/tankoubons/{id}/ai/rename-chapter 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `ai_rename_chapter`,位于 crates/lanrurugi-api/src/tankoubons.rs:1714。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/tankoubons.rs:106 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## AI 重命名建议 [Section titled “AI 重命名建议”](#ai-重命名建议) POSThttp\://localhost:3000/api/tankoubons/{id}/ai/rename-suggestions 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/tankoubons.rs:1588)的**译文**;原文以源码为准。 把 tankoubon 的标题、成员档案名与顺序发给 DeepSeek,返回 AI 生成的改名建议(tankoubon 名称 + 每个档案的章节名)。必须配置 LLM 密钥;未配置时返回 400。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/tankoubons.rs:102 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 获取单个 Tankoubon 的完整详情 [Section titled “获取单个 Tankoubon 的完整详情”](#获取单个-tankoubon-的完整详情) GEThttp\://localhost:3000/api/tankoubons/{id}/full 获取指定 tankoubon ID 的详情,附带分页的档案元数据。 每页的档案数取决于服务端的 `archives_per_page` 设置。 #### 查询参数 * pageinteger · default: -1可选 档案列表的页码。默认 -1,返回全部档案。 #### 响应 200Tankoubon ``` { "filtered": 0, "result": { "archives": [ "" ], "full_data": [ null ], "id": "", "name": "", "progress": 0, "summary": "", "tags": "" }, "total": 0 } ``` 400错误响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• pagequery 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 更新 Tankoubon 阅读进度 [Section titled “更新 Tankoubon 阅读进度”](#更新-tankoubon-阅读进度) PUThttp\://localhost:3000/api/tankoubons/{id}/progress/{page} 告诉服务端你当前正在阅读这个 Tankoubon 的第几页,以便它相应地更新内部的阅读进度。 页码是在该 tank 内所有档案上全局计数的(如果一个 tank 有两个档案,分别有 20 页和 25 页,那么第 26 页就是第 2 个档案的第 6 页)。 ⚠ 如果服务端配置为使用客户端进度跟踪,这个 API 调用会返回错误! 调用前请务必先用 `/api/info` 确认服务端是否跟踪阅读进度。 #### 路径参数 * idstring · min: 15 · max: 15 · pattern必填 要更新的 Tankoubon ID。 * pageinteger · min: 1必填 要更新到的全局页码,从 1 开始计数。必须是正整数。 #### 响应 200成功响应 ``` { "id": "TANK_1589141306", "lastreadtime": 123943543, "operation": "update_tank_progress", "page": 5, "success": 1 } ``` 400通用错误响应 ``` { "error": "Server-side Progress Tracking is disabled on this instance.", "operation": "update_tank_progress", "success": 0 } ``` 401开启 authprogress 时需要认证 ``` { "error": "This operation requires authentication.", "operation": "update_tank_progress", "success": 0 } ``` 服务器地址http\://localhost:3000API 令牌••••• idpathpagepath 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 获取 Tankoubon 缩略图 [Section titled “获取 Tankoubon 缩略图”](#获取-tankoubon-缩略图) GEThttp\://localhost:3000/api/tankoubons/{id}/thumbnail 获取指定 Tankoubon 的封面缩略图。 默认情况下,缩略图取自第一个档案的第一页。 如果缩略图尚不存在,这个端点会返回一张占位图。 若想把缩略图生成排入后台, 可以使用 `no_fallback` 查询参数。 #### 查询参数 * no_fallbackstring · enum: true | false可选 关闭占位图,把缩略图排入提取队列,并返回 code 202 的 JSON。图片已存在时该参数不起作用。(无论哪种情况,只要图片已存在就会以 code 200 返回它) #### 响应 200如果缩略图已经提取过,会直接返回它。 该响应没有示例数据。 202缩略图已排入提取队列。用 \`/api/minion/:jobid\` 跟踪它何时就绪。 ``` { "job": 0, "operation": "", "success": 1 } ``` 400错误响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• no_fallbackquerytrue 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 更新 Tankoubon 缩略图 [Section titled “更新 Tankoubon 缩略图”](#更新-tankoubon-缩略图) PUThttp\://localhost:3000/api/tankoubons/{id}/thumbnail 用跨该 tank 内所有档案(按顺序)的全局页码,设置指定 Tankoubon 的封面缩略图。全局页码会自动换算到正确的档案与其中的局部页码。 #### 查询参数 * pageinteger · min: 1必填 跨整个 Tankoubon 内所有档案的全局页码,从 1 开始计数。第 1 页就是第一个档案的第一页,依此类推。 #### 响应 200Tankoubon 缩略图已更新 ``` { "new_thumbnail": "", "operation": "update_tankoubon_thumbnail", "success": 0 } ``` 400错误响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• pagequery 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # 术语表 > 3 endpoints. 3 endpoints. ## 获取术语表 [Section titled “获取术语表”](#获取术语表) GEThttp\://localhost:3000/api/volumes/{id}/terminology-glossary 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `get_glossary`,位于 crates/lanrurugi-api/src/terminology_glossary.rs:38。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/terminology_glossary.rs:27 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 删除条目 [Section titled “删除条目”](#删除条目) DELETEhttp\://localhost:3000/api/volumes/{id}/terminology-glossary/{term} 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `delete_entry`,位于 crates/lanrurugi-api/src/terminology_glossary.rs:139。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/terminology_glossary.rs:28 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 编辑单条记录 [Section titled “编辑单条记录”](#编辑单条记录) PUThttp\://localhost:3000/api/volumes/{id}/terminology-glossary/{term} 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/terminology_glossary.rs:59)的**译文**;原文以源码为准。 编辑单条记录。在下一次翻译请求时生效(FR-007d)。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/terminology_glossary.rs:28 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # 页面翻译 > 6 endpoints. 6 endpoints. ## 检测结果,加上浏览器在本地翻译与合成所需的全部数据 [Section titled “检测结果,加上浏览器在本地翻译与合成所需的全部数据”](#检测结果加上浏览器在本地翻译与合成所需的全部数据) GEThttp\://localhost:3000/api/archives/{id}/page/{page}/text-regions 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/translation.rs:406)的**译文**;原文以源码为准。 检测结果,加上浏览器在本地翻译与合成所需的全部数据。 包含云端路径所组装的同一份 `context`,因此本地托管的后端也能获得 FR-007a–e 的一致性收益,尽管它的翻译调用从不经过本服务端。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/translation.rs:45 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 读者的「重新翻译」:丢弃本页的检测缓存、全部已翻译记录与合成结果 [Section titled “读者的「重新翻译」:丢弃本页的检测缓存、全部已翻译记录与合成结果”](#读者的重新翻译丢弃本页的检测缓存全部已翻译记录与合成结果) DELETEhttp\://localhost:3000/api/archives/{id}/page/{page}/translation 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/translation.rs:203)的**译文**;原文以源码为准。 阅读界面的「重新翻译」:丢弃本页的检测缓存、全部已翻译记录以及渲染出的图片,使下一次 `GET .../translation` 重新跑完整的 OCR → 翻译 → 合成流程,而不是复用过期缓存(例如由旧版流程产生的,或区域检测不完整的那一份)。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/translation.rs:41 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 为云端后端路径提供合成好的译文页面(T028) [Section titled “为云端后端路径提供合成好的译文页面(T028)”](#为云端后端路径提供合成好的译文页面t028) GEThttp\://localhost:3000/api/archives/{id}/page/{page}/translation 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/translation.rs:275)的**译文**;原文以源码为准。 为云端后端路径提供合成好的译文页面(T028)。 有缓存渲染结果时直接返回。未命中时它会**触发**真正的编排流程——OCR → 字体路由 → 批量翻译 → 合成 → 写缓存(`translation_pipeline::translate_page`)——覆盖本页及其预读窗口,然后立刻报告「尚未就绪」。 这里刻意不等待该工作完成:一个完整的 OCR + LLM 周期要几十秒,而 FR-012 要求阅读界面在此期间继续显示原图并给出非阻塞的提示。客户端轮询即可;后续某次轮询就能拿到这次触发的缓存条目。阅读永远不应等待翻译(SC-007)。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/translation.rs:41 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 记录浏览器用它自己的本地模型得到的译文(T049a) [Section titled “记录浏览器用它自己的本地模型得到的译文(T049a)”](#记录浏览器用它自己的本地模型得到的译文t049a) POSThttp\://localhost:3000/api/archives/{id}/page/{page}/translation/record 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/translation.rs:591)的**译文**;原文以源码为准。 记录浏览器用它自己的本地模型得到的译文(T049a)。 **这里不会发生任何 LLM 调用**——它只是一次轻量写入。其目的是让本地后端翻译出的名称/术语仍然进入服务端共享的术语表,从而使后续同一卷的云端路径(或其他设备)请求与之保持一致。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/translation.rs:49 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 报告该档案当前是否开启翻译,以及开启的是该档案自身的设置还是它所属 Tankoubon 的 [Section titled “报告该档案当前是否开启翻译,以及开启的是该档案自身的设置还是它所属 Tankoubon 的”](#报告该档案当前是否开启翻译以及开启的是该档案自身的设置还是它所属-tankoubon-的) GEThttp\://localhost:3000/api/archives/{id}/translation/scope 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/translation.rs:118)的**译文**;原文以源码为准。 报告该档案当前是否开启翻译,以及开启的是它自己的设置还是从它所属的 Tankoubon 继承来的——后者是为了让阅读界面能告诉用户「这一项跟随整本书的设置」,而不是把一个只影响本文件的开关呈现得好像切换它会影响到别处。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/translation.rs:53 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 设置当前实际管辖该档案的那个开关(若档案属于某个 Tankoubon,则是该 Tankoubon 的) [Section titled “设置当前实际管辖该档案的那个开关(若档案属于某个 Tankoubon,则是该 Tankoubon 的)”](#设置当前实际管辖该档案的那个开关若档案属于某个-tankoubon则是该-tankoubon-的) PUThttp\://localhost:3000/api/archives/{id}/translation/scope 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/translation.rs:144)的**译文**;原文以源码为准。 设置当前实际管辖该档案的那个开关(若它属于某个 Tankoubon 则是该 Tankoubon 的,否则是该档案自身)——为什么在这里切换只会作用于其中之一、从不两者同时,见 `TranslationScopeRepository::set_enabled` 自身的文档。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/translation.rs:53 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # 翻译设置 > 4 endpoints. 4 endpoints. ## 更新预算 [Section titled “更新预算”](#更新预算) PUThttp\://localhost:3000/api/translation/budget 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `update_budget`,位于 crates/lanrurugi-api/src/translation_settings.rs:335。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/translation_settings.rs:40 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 获取翻译设置 [Section titled “获取翻译设置”](#获取翻译设置) GEThttp\://localhost:3000/api/translation/settings 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `get_translation_settings`,位于 crates/lanrurugi-api/src/translation_settings.rs:118。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/translation_settings.rs:35 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## 更新翻译设置 [Section titled “更新翻译设置”](#更新翻译设置) PUThttp\://localhost:3000/api/translation/settings 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `update_translation_settings`,位于 crates/lanrurugi-api/src/translation_settings.rs:172。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/translation_settings.rs:35 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## FR-014 要求的四个粒度上的当前用量 [Section titled “FR-014 要求的四个粒度上的当前用量”](#fr-014-要求的四个粒度上的当前用量) GEThttp\://localhost:3000/api/translation/usage 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 下面这段是 handler 自己的文档注释(crates/lanrurugi-api/src/translation_settings.rs:277)的**译文**;原文以源码为准。 FR-014 要求的四个粒度上的当前用量。 没有配置计量后端时返回一个全零结果而不是错误——本地托管的后端本来就没有用量可报告。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/translation_settings.rs:39 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # 版本 > 1 endpoint. 1 endpoint. ## 获取版本 [Section titled “获取版本”](#获取版本) GEThttp\://localhost:3000/api/version 尚未在此参考中描述。这个端点会被列出,是因为服务端确实注册了它,但它的请求与响应形状还没有写下来。 对应的 handler 是 `get_version`,位于 crates/lanrurugi-api/src/version.rs:528。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/version.rs:144 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点不需要认证。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # LANrurugi documentation > A self-hosted library for manga first, and for e-books such as PDF and EPUB too, built on LANraragi and extensively reworked and extended in Rust + React — data- and API-compatible with an existing LANraragi deployment. ## What is in here [Section titled “What is in here”](#what-is-in-here) * **[Install (Docker / NAS)](guide/install/)** — get LANrurugi running and pointed at the library you already have. * **[Native install](guide/install-native/)** — run it directly on Linux, an Apple Silicon Mac or FreeBSD, without containers. * **[Quickstart](guide/quickstart/)** — first login, scanning the library, importing existing data. * **[Supported formats](guide/formats/)** — the archives and e-books (PDF, EPUB, MOBI/AZW3, DjVu, FB2, TXT) the library accepts, and how each is shown. * **[Testing the API from these docs](guide/api-testing/)** — send requests from your browser straight to **your own instance**, and what to do when it does not work. * **[Plugin authoring](plugin/getting-started/)** — write a metadata, login, or download plugin. * **[API reference](api/)** — the complete HTTP API: every endpoint, its parameters and responses, and a command line you can copy. ## About the API reference [Section titled “About the API reference”](#about-the-api-reference) The API reference is **not hand-written**. `crates/lanrurugi-api-docgen` generates it from the server’s own route registrations, which means: * Every endpoint the server serves is in it — “in the code but not in the docs” **cannot** happen; * It does **not** list endpoints the server does not actually serve; * For endpoints shared with LANraragi, it carries that project’s field-level descriptions verbatim (apart from the path prefix and the authentication section); * Endpoints whose request/response shapes have not been written down yet are **marked as such**, rather than being given an invented schema that merely looks plausible. CI fails outright when the generated result disagrees with the code, so this reference cannot rot the way a hand-maintained document does. # API Reference > Generated by `crates/lanrurugi-api-docgen` from the server's own route registrations: **248** endpoints in **39** groups Generated by `crates/lanrurugi-api-docgen` from the server’s own route registrations: **248** endpoints in **39** groups. Every endpoint lists its method, full path, parameters and a response example, and carries a request panel — point it at **your own instance** and the request goes straight there from this browser. * [Search API](./search/) — 9 * [Archive API](./archives/) — 29 * [Database API](./database/) — 14 * [Category API](./categories/) — 7 * [Tankoubon API](./tankoubons/) — 13 * [Stamps API](./stamps/) — 8 * [Plugin API](./plugins/) — 12 * [Shinobu API](./shinobu/) — 4 * [Minion API](./minion/) — 3 * [OPDS Catalog](./opds/) — 3 * [Miscellaneous other API](./misc/) — 5 * [Activity Log](./activity/) — 6 * [API Tokens](./api-tokens/) — 4 * [Archive Splitting](./archive-split/) — 5 * [Cross-origin Login](./auth-bridge/) — 4 * [Benchmark](./bench/) — 2 * [Bookmarks](./bookmarks/) — 13 * [Download Queue](./download-queue/) — 21 * [Duplicate Detection](./duplicates/) — 3 * [Font Patterns](./font-pattern/) — 2 * [Health](./health/) — 1 * [Background Jobs](./jobs/) — 3 * [Login](./login/) — 4 * [Logs](./logs/) — 1 * [OpenSearch](./opensearch/) — 1 * [Plugin Wizard](./plugin-wizard/) — 7 * [Preferences](./preferences/) — 2 * [Recommendations](./recommend/) — 1 * [Maintenance Scripts](./scripts/) — 3 * [Signed-in Devices](./sessions/) — 3 * [Settings](./settings/) — 4 * [Library Statistics](./stats/) — 3 * [Subscriptions](./subscriptions/) — 25 * [Tankoubon Grouping](./tankoubon-grouping/) — 8 * [Terminology Glossary](./terminology-glossary/) — 3 * [Page Translation](./translation/) — 6 * [Translation Settings](./translation-settings/) — 4 * [Version](./version/) — 1 * [AI Usage](./llm-usage/) — 1 What the browser needs before it can call your own instance (cross-origin access, HTTPS, a token) is in [Testing the API from these docs](../guide/api-testing/). [Download the OpenAPI document (JSON)](/openapi.json) # Activity Log > 6 endpoints. 6 endpoints. ## Delete selected activity entries [Section titled “Delete selected activity entries”](#delete-selected-activity-entries) DELETEhttp\://localhost:3000/api/activity Bulk delete by ID. Session-only — an API token of either role is refused, so a token cannot erase its own audit trail. #### 请求体 application/json #### 响应 200移除了多少条记录。 ``` null ``` 服务器地址http\://localhost:3000 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## List activity entries [Section titled “List activity entries”](#list-activity-entries) GEThttp\://localhost:3000/api/activity A page of activity entries, newest first, scoped to what the caller is allowed to see (see this file’s header). Entries whose target is an archive are annotated with whether that archive still exists, so a client can render “deleted since” instead of a dead link. 权限差异 * **你能看到哪些条目取决于你的身份。** 网页会话能看到全部记录;管理员令牌能看到它自己产生的、以及所有 guest 令牌产生的记录;guest 令牌只能看到它自己产生的记录。所以令牌持有者看到的是完整日志的一个**子集**——返回空不代表什么都没发生。 #### 查询参数 * cursorstring可选 来自上一次响应 `next_cursor` 的不透明分页游标。 * limitinteger · min: 1 · max: 200 · default: 50可选 无论请求多少都会被夹到一个小固定范围内——不设上限的话,单个请求就能强制触发任意大的扫描。 * start_tsinteger可选 只返回该 Unix 秒级时间戳(含)之后的活动记录。 * end_tsinteger可选 只返回该 Unix 秒级时间戳(含)之前的活动记录。 * actorstring可选 逗号分隔的操作者键;多个值是「或」的关系。 * action_typestring可选 逗号分隔的操作类型;多个值是「或」的关系。 * outcomestring可选 逗号分隔的结果;多个值是「或」的关系。 #### 响应 200一页记录。 ``` { "entries": [ {} ], "next_cursor": "", "total_estimate": 0 } ``` 服务器地址http\://localhost:3000API 令牌••••• cursorquerylimitquerystart_tsqueryend_tsqueryactorqueryaction_typequeryoutcomequery 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Delete one activity entry [Section titled “Delete one activity entry”](#delete-one-activity-entry) DELETEhttp\://localhost:3000/api/activity/{id} Deletes a single entry by ID. Session-only, for the same reason the bulk delete is. #### 路径参数 * idstring必填 #### 响应 200已删除。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 404没有该 ID 的记录。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000 idpath 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## List activity filter facets [Section titled “List activity filter facets”](#list-activity-filter-facets) GEThttp\://localhost:3000/api/activity/facets The distinct action types and actors present in the log, each with a count — so a client can build a filter UI from what is actually there rather than from a hardcoded list. Like the list endpoint, this is scoped to what the caller may see: an actor only appears if the caller could read that actor’s entries. #### 响应 200可用的分面。 ``` { "action_types": [ {} ], "actors": [ {} ] } ``` 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Read the activity retention window [Section titled “Read the activity retention window”](#read-the-activity-retention-window) GEThttp\://localhost:3000/api/activity/retention How long activity entries are kept, in seconds. #### 响应 200当前时间窗口。 ``` { "retention_secs": 0 } ``` 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Set the activity retention window [Section titled “Set the activity retention window”](#set-the-activity-retention-window) PUThttp\://localhost:3000/api/activity/retention Changes how long activity entries are kept. Session-only: a token must not be able to shorten how long its own trail survives. #### 请求体 application/json #### 响应 200已保存。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # API Tokens > 4 endpoints. 4 endpoints. ## List API tokens [Section titled “List API tokens”](#list-api-tokens) GEThttp\://localhost:3000/api/tokens Every issued token’s metadata. The token secret itself is **never** included: it is returned exactly once, by the creation call below, and is not stored in a recoverable form. Requires a session-cookie login. #### 响应 200已签发的令牌。 ``` [ { "created_at": 0, "expires_at": 0, "id": "", "last_used_at": 0, "last_used_ip": "", "name": "", "role": "admin" } ] ``` 服务器地址http\://localhost:3000 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Create an API token [Section titled “Create an API token”](#create-an-api-token) POSThttp\://localhost:3000/api/tokens Issues a new token and returns its secret — **the only time it is ever returned**. Store it then; it cannot be recovered afterwards, only replaced. The expiry is computed from the server’s own clock, not from a client-supplied timestamp, so a client with a skewed clock cannot mint a token that outlives what it asked for. #### 请求体 application/json #### 响应 200该令牌,密钥在 \`data.token\` 下。 ``` null ``` 400名称为空。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Revoke an API token [Section titled “Revoke an API token”](#revoke-an-api-token) DELETEhttp\://localhost:3000/api/tokens/{id} Permanently revokes a token. Anything still using it starts failing immediately; the token cannot be un-revoked, only replaced. Requires a session-cookie login. #### 路径参数 * idstring必填 #### 响应 200已吊销。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 404没有该令牌。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000 idpath 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Rename an API token [Section titled “Rename an API token”](#rename-an-api-token) PATCHhttp\://localhost:3000/api/tokens/{id} Changes a token’s label. Requires a session-cookie login. #### 路径参数 * idstring必填 #### 请求体 application/json #### 响应 200重命名后的令牌。 ``` null ``` 404没有该令牌。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000 idpath 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # Archive Splitting > 5 endpoints. 5 endpoints. ## get_split_suggestion [Section titled “get_split_suggestion”](#get_split_suggestion) GEThttp\://localhost:3000/api/archives/{id}/split-suggestion Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `get_split_suggestion` in crates/lanrurugi-api/src/archive_split.rs:707. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/archive_split.rs:69 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Manual “analyze this archive now” endpoint [Section titled “Manual “analyze this archive now” endpoint”](#manual-analyze-this-archive-now-endpoint) POSThttp\://localhost:3000/api/archives/{id}/split-suggestion Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/archive_split.rs:681), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** Manual “analyze this archive now” endpoint. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/archive_split.rs:69 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `GET /archives/{id}/split-tree` — returns the archive’s internal directory tree with nested [Section titled “GET /archives/{id}/split-tree — returns the archive’s internal directory tree with nested”](#get-archivesidsplit-tree--returns-the-archives-internal-directory-tree-with-nested) GEThttp\://localhost:3000/api/archives/{id}/split-tree Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/archive_split.rs:508), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `GET /archives/{id}/split-tree` — returns the archive’s internal directory tree with nested archives recursively expanded. This is a viewer-only endpoint: it does not call the LLM and does not create any output ZIPs. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/archive_split.rs:75 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## execute_split [Section titled “execute_split”](#execute_split) POSThttp\://localhost:3000/api/archives/{id}/split/execute Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `execute_split` in crates/lanrurugi-api/src/archive_split.rs:735. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/archive_split.rs:73 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## split_progress_stream [Section titled “split_progress_stream”](#split_progress_stream) GEThttp\://localhost:3000/api/archives/{id}/split/stream Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `split_progress_stream` in crates/lanrurugi-api/src/archive_split.rs:793. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/archive_split.rs:74 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # Archive API > 29 endpoints. 29 endpoints. ## `DELETE /archives` (issue #63), body `{ids: [...]}` — same “plural resource, `DELETE` with a [Section titled “DELETE /archives (issue #63), body {ids: \[...\]} — same “plural resource, DELETE with a”](#delete-archives-issue-63-body-ids---same-plural-resource-delete-with-a) DELETEhttp\://localhost:3000/api/archives Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/archives.rs:618), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `DELETE /archives` (issue #63), body `{ids: [...]}` — same “plural resource, `DELETE` with a JSON body carrying which ones” shape `activity.rs::bulk_delete_activity` (`DELETE /activity`) already established in this codebase, not a `POST .../batch-delete` action-style path; `DELETE` *can* carry a request body per RFC 9110 (silently dropped by some older proxies/clients in practice, but Axum and this project’s own frontend both handle it fine, and precedent already exists here). The Batch page’s own “delete archives” operation previously fired `DELETE /archives/{id}` once per selected archive from the frontend as a plain sequential loop (no atomicity, no single audit point, and — since each request only ever reported its own pass/fail — no way for the caller to know *which* ids failed without diffing the library before/after). This does the same per-id work (`delete_one_archive`, identical cleanup to the single-delete endpoint) server-side in one request, and reports a per-id result list so the frontend can show exactly what happened rather than assuming full success. Session-only (`route_policy.csv` denies every token role and `anonymous`) — deliberately stricter than every other archive-mutating endpoint in this file, all of which a Token (Admin or Guest) can call. A single wrong/leaked API token being able to wipe an arbitrary-sized slice of the library in one request is a materially larger blast radius than any one of the single-target endpoints token access already permits, and this project has no legitimate automation use case for bulk deletion the way it does for e.g. scripted uploads or metadata edits — so the extra restriction has no real workflow it breaks. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/archives.rs:209 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Get all Archives [Section titled “Get all Archives”](#get-all-archives) GEThttp\://localhost:3000/api/archives Returns a list of all Archives in the database. This doesn’t include Tankoubons by design. You can use the IDs of this JSON with the other endpoints. 权限差异 * **访客和匿名调用者完全不可达。** 这是无范围的列表:它返回书库中的全部档案,不做任何分类范围限制——给访客开放它等于绕过 `/api/search` 强制的那套「访客可见」限制。访客请走 `/api/search`。 #### 响应 200档案数组 ``` [ { "arcid": "28697b96f0ac5858be2614ed10ca47742c9522fd", "extension": "rar", "filename": "Fate GO MEMO", "isnew": false, "lastreadtime": 1337038281, "pagecount": 34, "progress": 3, "size": 1234567, "summary": null, "tags": "parody:fate grand order, group:wadamemo, artist:wada rco, artbook, full color", "title": "Fate GO MEMO", "toc": [ { "name": "Chapter 1", "page": 1 }, { "name": "Chapter 2", "page": 13 }, { "name": "Chapter 3", "page": 25 } ] } ] ``` 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Delete archive [Section titled “Delete archive”](#delete-archive) DELETEhttp\://localhost:3000/api/archives/{id} Delete both the archive metadata and the file stored on the server.\ 🙏 Please ask your user for confirmation before invoking this endpoint. #### 路径参数 * idstring · min: 40 · max: 40 · pattern必填 要处理的档案 ID。 #### 响应 200档案已删除的响应 ``` { "filename": "big_chungus.zip", "id": "75d18ce470dc99f83dc355bdad66319d1f33c82b", "operation": "delete_archive", "success": 1 } ``` 400没有档案 ID 的响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 423资源被锁定的响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpath 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Get archive categories [Section titled “Get archive categories”](#get-archive-categories) GEThttp\://localhost:3000/api/archives/{id}/categories Get all the Categories which currently refer to this Archive ID. #### 路径参数 * idstring必填 要处理的档案 ID。 #### 响应 200档案所属分类 ``` { "categories": [ { "archives": [ "0d50858d727723d856d2ab78564bb8e906e65f14", "7f03b8b1f337e1e42b2c2890533c0de7479d41ca" ], "id": "SET_1613080290", "name": "My great category", "pinned": 0, "search": null }, { "archives": [ "0d50858d727723d856d2ab78564bb8e906e65f14", "75d18ce470dc99f83dc355bdad66319d1f33c82b" ], "id": "SET_1613080294", "name": "My other category", "pinned": 1, "search": null } ], "operation": "find_arc_categories", "success": 1 } ``` 400没有档案 ID 的响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpath 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Download archive [Section titled “Download archive”](#download-archive) GEThttp\://localhost:3000/api/archives/{id}/download Download an Archive from the server. #### 路径参数 * idstring · min: 40 · max: 40 · pattern必填 要下载的档案 ID。 #### 响应 200档案文件 该响应没有示例数据。 400没有档案 ID 的响应 ``` { "error": "No archive ID specified.", "operation": "download_archive", "success": 0 } ``` 服务器地址http\://localhost:3000API 令牌••••• idpath 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Extract an Archive [Section titled “Extract an Archive”](#extract-an-archive) GEThttp\://localhost:3000/api/archives/{id}/files Get a list of URLs pointing to the images contained in an archive. If necessary, this endpoint also launches a background Minion job to extract the archive so it is ready for reading. 权限差异 * 对**不在访客可见范围内**的档案,这里返回 **404** 而不是 403——刻意与「档案不存在」不可区分,因此这个响应无法被用来探测访客范围之外的档案是否存在。 #### 路径参数 * idstring · min: 40 · max: 40 · pattern必填 要处理的档案 ID。 #### 查询参数 * forceboolean可选 强制在后台完整重新提取该档案。在该档案完全重新提取完成之前,后续的 `/api/archives/:id/page` 调用仍可能用到已有的缓存文件。 #### 响应 200会返回页面 URL,以及后台提取任务的 ID。 ``` { "job": 561, "pages": [ ".\\/api\\/archives\\/28697b96f0ac5858be2614ed10ca47742c9522fd\\/page&path=00.jpg", ".\\/api\\/archives\\/28697b96f0ac5858be2614ed10ca47742c9522fd\\/page&path=01.jpg" ] } ``` 400没有档案 ID 的响应 ``` { "error": "No archive ID specified.", "operation": "get_file_list", "success": 0 } ``` 服务器地址http\://localhost:3000API 令牌••••• idpathforcequery 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Extract page thumbnails [Section titled “Extract page thumbnails”](#extract-page-thumbnails) POSThttp\://localhost:3000/api/archives/{id}/files/thumbnails Create thumbnails for every page of a given Archive. This endpoint will queue generation of the thumbnails in the background. If all thumbnails are detected as already existing, the call will return HTTP code 200.\ This endpoint can be called multiple times – If a thumbnailing job is already in progress for the given ID, it’ll just give you the ID for that ongoing job. #### 路径参数 * idstring · min: 40 · max: 40 · pattern必填 要处理的档案 ID。 #### 查询参数 * forceboolean可选 是否强制重新生成全部缩略图,即使它们已经存在。 #### 响应 200缩略图已提取且 \`force=0\` 时 ``` { "message": "No job queued, all thumbnails already exist.", "operation": "generate_page_thumbnails", "success": 1 } ``` 202缩略图已排入提取队列。可以用 \`/api/minion/:jobid\` 跟踪进度,查看 \`notes->progress\` 与 \`notes->pages\`。 ``` { "job": 0, "operation": "", "success": 1 } ``` 400没有档案 ID 的响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpathforcequery 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Clear Archive New flag [Section titled “Clear Archive New flag”](#clear-archive-new-flag) DELETEhttp\://localhost:3000/api/archives/{id}/isnew Clears the “New!” flag on an archive. #### 路径参数 * idstring · min: 40 · max: 40 · pattern必填 要处理的档案 ID。 #### 响应 200成功响应 ``` { "id": "d07ff399dddb25a0408385bc75b9ba52709fe2c1", "operation": "clear_new", "success": 0 } ``` 400没有档案 ID 的响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 423资源被锁定的响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpath 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Set Archive New flag [Section titled “Set Archive New flag”](#set-archive-new-flag) PUThttp\://localhost:3000/api/archives/{id}/isnew Sets/Restores the “New!” flag on an archive. #### 路径参数 * idstring · min: 40 · max: 40 · pattern必填 要处理的档案 ID。 #### 响应 200成功响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 400没有档案 ID 的响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 423资源被锁定的响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpath 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Get archive metadata [Section titled “Get archive metadata”](#get-archive-metadata) GEThttp\://localhost:3000/api/archives/{id}/metadata Get Metadata (title, tags) for a given Archive. 权限差异 * 对**不在访客可见范围内**的档案,这里返回 **404** 而不是 403——刻意与「档案不存在」不可区分,因此这个响应无法被用来探测访客范围之外的档案是否存在。 #### 路径参数 * idstring · min: 40 · max: 40 · pattern必填 要处理的档案 ID。 #### 响应 200档案元数据 ``` { "arcid": "28697b96f0ac5858be2614ed10ca47742c9522fd", "extension": "rar", "filename": "Fate GO MEMO", "isnew": false, "lastreadtime": 1337038281, "pagecount": 34, "progress": 3, "size": 1234567, "summary": null, "tags": "parody:fate grand order, group:wadamemo, artist:wada rco, artbook, full color", "title": "Fate GO MEMO", "toc": [ { "name": "Chapter 1", "page": 1 }, { "name": "Chapter 2", "page": 13 }, { "name": "Chapter 3", "page": 25 } ] } ``` 400没有档案 ID 的响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpath 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Update archive metadata [Section titled “Update archive metadata”](#update-archive-metadata) PUThttp\://localhost:3000/api/archives/{id}/metadata Update tags and title for the given Archive.\ Data supplied to the server through this method will **overwrite** the previous data. #### 路径参数 * idstring · min: 40 · max: 40 · pattern必填 要处理的档案 ID。 #### 查询参数 * titlestring可选 档案的新标题。 * tagsstring可选 档案的新标签。 * summarystring可选 档案的新摘要。 #### 响应 200档案元数据已更新 ``` { "operation": "update_metadata", "success": 1 } ``` 400没有档案 ID 的响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 423资源被锁定的响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpathtitlequerytagsquerysummaryquery 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Get an archive page [Section titled “Get an archive page”](#get-an-archive-page) GEThttp\://localhost:3000/api/archives/{id}/page Get an archive page. This call is mainly used alongside `/api/archives/files`. 权限差异 * 对**不在访客可见范围内**的档案,这里返回 **404** 而不是 403——刻意与「档案不存在」不可区分,因此这个响应无法被用来探测访客范围之外的档案是否存在。 #### 路径参数 * idstring · min: 40 · max: 40 · pattern必填 要下载的档案 ID。 #### 查询参数 * pathstring必填 图片路径。 #### 响应 200档案页面 该响应没有示例数据。 400没有档案 ID 的响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpathpathquery 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `GET /archives/{id}/page-dimensions?count=N` — natural pixel width/height for the first `N` [Section titled “GET /archives/{id}/page-dimensions?count=N — natural pixel width/height for the first N”](#get-archivesidpage-dimensionscountn--natural-pixel-widthheight-for-the-first-n) GEThttp\://localhost:3000/api/archives/{id}/page-dimensions Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/archives.rs:3688), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `GET /archives/{id}/page-dimensions?count=N` — natural pixel width/height for the first `N` pages only, in the same order as `/files`’s own `pages` array (so the frontend can zip them together by index without a separate name-matching step). Additive to `/files`, not folded into it — existing callers of `/files` (the third-party-compatible file-list contract) shouldn’t have to pay for an archive pass with per-entry image-header parsing they never asked for; only the infinite-scroll reader view (the one caller that actually needs this, to size not-yet-loaded ``s accurately before jumping to a resume position — see `read_page_dimensions`’s own docs for why it’s bounded to just the pages before that jump, not the whole archive) calls this endpoint at all. 权限差异 * 对**不在访客可见范围内**的档案,这里返回 **404** 而不是 403——刻意与「档案不存在」不可区分,因此这个响应无法被用来探测访客范围之外的档案是否存在。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/archives.rs:228 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `DELETE /archives/{id}/patch` — deletes the sidecar `.patch.zip` (if any) and clears the [Section titled “DELETE /archives/{id}/patch — deletes the sidecar .patch.zip (if any) and clears the”](#delete-archivesidpatch--deletes-the-sidecar-patchzip-if-any-and-clears-the) DELETEhttp\://localhost:3000/api/archives/{id}/patch Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/archives.rs:1160), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `DELETE /archives/{id}/patch` — deletes the sidecar `.patch.zip` (if any) and clears the archive’s `has_patch` flag. Lets the user undo a patch — e.g. to replace it with pages from a different source after re-running the comparison flow — without touching the archive itself. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/archives.rs:248 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Update reading progression [Section titled “Update reading progression”](#update-reading-progression) PUThttp\://localhost:3000/api/archives/{id}/progress/{page} Tell the server which page of this Archive you’re currently showing/reading, so that it updates its internal reading progression accordingly.\ This endpoint will also update the date this Archive was last read, using the current server timestamp. You should call this endpoint only when you’re sure the user is currently reading the page you present.\ **Don’t** use it when preloading images off the server. Whether to make reading progression regressible or not is up to the client. (The web client will reduce progression if the user starts reading previous pages)\ Consider however removing the “New!” flag from an archive when you start updating its progress - The web client won’t display any reading progression if the new flag is still set. ⚠ If the server is configured to use clientside progress tracking, this API call will return an error!\ Make sure to check using `/api/info` whether the server tracks reading progression or not before calling this endpoint. #### 路径参数 * idstring · min: 40 · max: 40 · pattern必填 要处理的档案 ID。 * pageinteger必填 要更新到的当前阅读页码。 **必须**是正整数,且不超过该档案的总页数。 #### 响应 200成功响应 ``` { "id": "75d18ce470dc99f83dc355bdad66319d1f33c82b", "lastreadtime": 123943543, "operation": "update_progress", "page": 34, "success": 1 } ``` 400通用错误响应 ``` { "error": "Server-side Progress Tracking is disabled on this instance.", "operation": "update_progress", "success": 0 } ``` 401开启 authprogress 时需要认证 ``` { "error": "This operation requires authentication.", "operation": "update_progress", "success": 0 } ``` 423资源被锁定的响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpathpagepath 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `PUT /archives/{id}/rename` — additive, no legacy equivalent (legacy has no archive-rename [Section titled “PUT /archives/{id}/rename — additive, no legacy equivalent (legacy has no archive-rename”](#put-archivesidrename--additive-no-legacy-equivalent-legacy-has-no-archive-rename) PUThttp\://localhost:3000/api/archives/{id}/rename Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/archives.rs:1277), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `PUT /archives/{id}/rename` — additive, no legacy equivalent (legacy has no archive-rename feature at all; verified via `~/LANraragi/lib/LANraragi/Controller/*.pm` and `public/js/edit.js` having no `rename` reference anywhere). Renames the archive’s on-disk file (not just its stored `title`/`name`), keeping `Archive::file` and `LRR_FILEMAP` in sync — modeled on `download_manager::ingest`’s own staging-file-to-`archive_dir` rename fixup, the closest existing precedent for “the archive’s file path changed, update the two places that track it”. A sidecar `.patch.zip` (see `delete_patch`’s own docs on how it’s associated — same directory, same stem, purely by filename convention) is renamed alongside the archive itself: leaving it under the old stem would silently break `patch::patch_path_for`’s lookup for every future request, making an existing patch invisible without deleting anything or erroring — the kind of silent data-loss-adjacent bug that’s much worse than a rename this function could instead just reject outright. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/archives.rs:249 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Get archive tankoubons [Section titled “Get archive tankoubons”](#get-archive-tankoubons) GEThttp\://localhost:3000/api/archives/{id}/tankoubons Get all the Tankoubons which currently refer to this Archive ID. #### 路径参数 * idstring · min: 40 · max: 40 · pattern必填 要处理的档案 ID。 #### 响应 200档案所属的 Tankoubon ``` { "operation": "find_arc_tankoubons", "success": 1, "tankoubons": [ "TANK_1688616437", "TANK_1688693913" ] } ``` 400没有档案 ID 的响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpath 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Get archive thumbnail [Section titled “Get archive thumbnail”](#get-archive-thumbnail) GEThttp\://localhost:3000/api/archives/{id}/thumbnail Get a Thumbnail image for a given Archive. This endpoint will return a placeholder image if it doesn’t already exist. If you want to queue generation of the thumbnail in the background, you can use the no_fallback query parameter. This will give you a background job ID instead of the placeholder. 权限差异 * 对**不在访客可见范围内**的档案,这里返回 **404** 而不是 403——刻意与「档案不存在」不可区分,因此这个响应无法被用来探测访客范围之外的档案是否存在。 #### 路径参数 * idstring · min: 40 · max: 40 · pattern必填 要处理的档案 ID #### 查询参数 * no_fallbackstring · enum: true | false可选 关闭占位图,把缩略图排入提取队列,并返回 code 202 的 JSON。图片已存在时该参数不起作用。(无论哪种情况,只要图片已存在就会以 code 200 返回它) * pageinteger · min: 0可选 指定要取哪一页的缩略图,默认为封面,也就是第 1 页。 #### 响应 200如果缩略图已经提取过,会直接返回它。 该响应没有示例数据。 202缩略图已排入提取队列。用 \`/api/minion/:jobid\` 跟踪它何时就绪。 ``` { "job": 0, "operation": "", "success": 1 } ``` 400没有档案 ID 的响应 ``` { "error": "No archive ID specified.", "operation": "serve_thumbnail", "success": 0 } ``` 服务器地址http\://localhost:3000API 令牌••••• idpathno_fallbackquerytruepagequery 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Update archive thumbnail [Section titled “Update archive thumbnail”](#update-archive-thumbnail) PUThttp\://localhost:3000/api/archives/{id}/thumbnail Update the cover thumbnail for the given Archive. You can specify a page number to use as the thumbnail, or you can use the default thumbnail. #### 路径参数 * idstring · min: 40 · max: 40 · pattern必填 要处理的档案 ID。 #### 查询参数 * pageinteger可选 用哪一页生成缩略图,默认第 1 页。 #### 响应 200档案缩略图已更新 ``` { "new_thumbnail": "", "operation": "update_thumbnail", "success": 0 } ``` 400没有档案 ID 的响应 ``` { "error": "No archive ID specified.", "operation": "update_thumbnail", "success": 0 } ``` 服务器地址http\://localhost:3000API 令牌••••• idpathpagequery 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## get_page_thumbnails [Section titled “get_page_thumbnails”](#get_page_thumbnails) GEThttp\://localhost:3000/api/archives/{id}/thumbnails Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `get_page_thumbnails` in crates/lanrurugi-api/src/archives.rs:3870. 权限差异 * 对**不在访客可见范围内**的档案,这里返回 **404** 而不是 403——刻意与「档案不存在」不可区分,因此这个响应无法被用来探测访客范围之外的档案是否存在。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/archives.rs:233 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Remove entry from Archive Table of Contents [Section titled “Remove entry from Archive Table of Contents”](#remove-entry-from-archive-table-of-contents) DELETEhttp\://localhost:3000/api/archives/{id}/toc Delete an entry from the Table of Contents of a given Archive. #### 路径参数 * idstring · min: 40 · max: 40 · pattern必填 要处理的档案 ID。 #### 查询参数 * pageinteger必填 要删除的章节页码。 #### 响应 200档案目录已更新 ``` { "operation": "remove_toc", "success": 1, "successMessage": "Removed ToC entry for page 143." } ``` 400没有档案 ID 的响应,或其他错误 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 423资源被锁定的响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpathpagequery 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Add entry to Archive Table of Contents [Section titled “Add entry to Archive Table of Contents”](#add-entry-to-archive-table-of-contents) PUThttp\://localhost:3000/api/archives/{id}/toc Add an entry to the Table of Contents of a given Archive. The ToC is stored as a JSON-encoded key-value array mapping a page to a title for the chapter/section starting at that page. #### 路径参数 * idstring · min: 40 · max: 40 · pattern必填 要处理的档案 ID。 #### 查询参数 * pageinteger必填 章节的起始页码。 * titlestring必填 章节标题。 #### 响应 200档案目录已更新 ``` { "operation": "update_toc", "success": 1, "successMessage": "Added ToC entry for page 143." } ``` 400没有档案 ID 的响应,或其他错误 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 423资源被锁定的响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpathpagequerytitlequery 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Get all untagged archives [Section titled “Get all untagged archives”](#get-all-untagged-archives) GEThttp\://localhost:3000/api/archives/untagged Get Archives that don’t have any tags recorded. This follows the same rules as the Batch Tagging filter and will include Archives that have parody:, date_added:, series: or artist: tags. #### 响应 200档案 ID 数组 ``` [ "d1858d5dc36925aa66be072a97817650d39de166", "c3458d5dc36925da93be072a97817650d39de166", "28697b96f0ac5858be2614ed10ca47742c9522fd" ] ``` 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Upload Archive [Section titled “Upload Archive”](#upload-archive) PUThttp\://localhost:3000/api/archives/upload Upload an Archive to the server.\ If a SHA1 checksum of the Archive is included, the server will perform an optional in-transit, file integrity validation, and reject the upload if the server-side checksum does not match. #### 请求体 multipart/form-data #### 响应 200档案上传成功 ``` { "id": "d07ff399dddb25a0408385bc75b9ba52709fe2c1", "operation": "upload", "success": 1 } ``` 400请求有误 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 409重复的档案 ``` { "error": "This file already exists in the Library. Enable replace duplicated archive in config to replace old ones.", "id": "0b91b546850e881034833c73375558928ddcec7c", "operation": "upload", "success": 0 } ``` 415不支持的文件 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 417校验和不匹配 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 422无法处理的实体 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 423资源被锁定的响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 500服务端内部错误 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Start or re-attach to a resumable upload [Section titled “Start or re-attach to a resumable upload”](#start-or-re-attach-to-a-resumable-upload) POSThttp\://localhost:3000/api/archives/upload/session Creates a session (an empty staged file plus a sidecar describing it) and returns the id. If `client_key` matches a session that is still alive, that session is returned instead, with the offset its bytes are already at — which is what makes a page refresh resumable rather than restarting the transfer. The returned `offset` is always read from the staged file’s real length, never from the sidecar, so a truncated or edited sidecar cannot make the server believe it holds bytes it does not. Sessions that have not been touched for 24 hours are swept by the operations here; the staged bytes also live in `temp_dir`, so `DELETE /api/tempfolder` reclaims them too. #### 请求体 application/json #### 响应 200A session to upload into. ``` { "created_at": 0, "file_name": "", "file_size": 0, "offset": 0, "operation": "upload", "resumed": false, "success": 1, "updated_at": 0, "upload_id": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Abandon a session [Section titled “Abandon a session”](#abandon-a-session) DELETEhttp\://localhost:3000/api/archives/upload/session/{id} Drops the staged bytes and the sidecar. Safe to call on an unknown id. #### 路径参数 * idstring必填 #### 响应 200The session's bytes are gone (whether or not it existed). 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• idpath 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Upload session status [Section titled “Upload session status”](#upload-session-status) GEThttp\://localhost:3000/api/archives/upload/session/{id} The handshake a resuming client starts from: how many bytes the server actually holds for this session. `404` means unknown, expired, or already completed — in every case the client’s correct move is to start a new session. #### 路径参数 * idstring必填 #### 响应 200The session, with its current offset. ``` { "created_at": 0, "file_name": "", "file_size": 0, "offset": 0, "operation": "upload", "resumed": false, "success": 1, "updated_at": 0, "upload_id": "" } ``` 404Unknown or expired session. ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpath 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Append one chunk [Section titled “Append one chunk”](#append-one-chunk) PUThttp\://localhost:3000/api/archives/upload/session/{id} Appends the request body to the staged file, but only at the position the client claims. `Upload-Offset` is required and must equal the staged file’s real length; the response always reports the authoritative offset, including on failure: * `204` — the chunk was appended; `Upload-Offset` is the new length. * `409` — the client’s offset disagrees with the disk (a lost response, a retried chunk, two tabs); `Upload-Offset` says where to resume from. * `400` — missing or malformed `Upload-Offset`. A connection that dies mid-chunk keeps whatever bytes reached the disk and reports the offset, so a partial chunk is just fewer bytes rather than a corrupt one. The body is bounded at 64 MiB (the one-shot route is deliberately unbounded; a chunk is supposed to be small). #### 路径参数 * idstring必填 #### 请求头 * Upload-Offsetinteger必填 Byte position this chunk starts at; must equal the server's own length. #### 请求体 application/octet-stream #### 响应 204Chunk appended. 该响应没有示例数据。 404Unknown or expired session. ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 409Offset mismatch; resync from the returned \`Upload-Offset\`. 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• idpath 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Finish a session and ingest it [Section titled “Finish a session and ingest it”](#finish-a-session-and-ingest-it) POSThttp\://localhost:3000/api/archives/upload/session/{id}/complete Verifies what landed, hashes it, and hands it to the same ingest the one-shot route uses — including the persistent download-queue row, so a completed upload shows up (and can be removed) exactly like any other queue item. Verification: a `file_size` announced at session creation must equal the staged length (`417` otherwise, and the staged bytes are dropped), and an optional `file_checksum` is compared against the SHA-1 of the finished file (`417` on mismatch). That SHA-1 is computed by reading the staged file once at this point rather than persisting incremental hasher state: a resumed upload’s early chunks were hashed by processes that are long gone, and state that can silently desync from the bytes on disk is a worse trade than one sequential read of an already-local file. After this call the session no longer exists. #### 路径参数 * idstring必填 #### 请求体 application/json #### 响应 200Ingested; the same body the one-shot upload returns. 该响应没有示例数据。 400The session holds no bytes. ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 404Unknown or expired session. ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 417The announced size or the supplied checksum did not match what arrived. ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpath 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # Cross-origin Login > 4 endpoints. 4 endpoints. ## bridge_callback [Section titled “bridge_callback”](#bridge_callback) GEThttp\://localhost:3000/api/auth/bridge/callback Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `bridge_callback` in crates/lanrurugi-api/src/auth_bridge.rs:599. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/auth_bridge.rs:47 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点不需要认证。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## prepare_bridge [Section titled “prepare_bridge”](#prepare_bridge) GEThttp\://localhost:3000/api/auth/bridge/prepare Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `prepare_bridge` in crates/lanrurugi-api/src/auth_bridge.rs:402. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/auth_bridge.rs:45 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点不需要认证。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## start_bridge [Section titled “start_bridge”](#start_bridge) GEThttp\://localhost:3000/api/auth/bridge/start Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `start_bridge` in crates/lanrurugi-api/src/auth_bridge.rs:464. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/auth_bridge.rs:46 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点不需要认证。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## get_auth_config [Section titled “get_auth_config”](#get_auth_config) GEThttp\://localhost:3000/api/auth/config Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `get_auth_config` in crates/lanrurugi-api/src/auth_bridge.rs:380. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/auth_bridge.rs:44 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点不需要认证。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # Benchmark > 2 endpoints. 2 endpoints. ## get_report [Section titled “get_report”](#get_report) GEThttp\://localhost:3000/api/bench/{reportid} Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `get_report` in crates/lanrurugi-api/src/bench.rs:107. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/bench.rs:21 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Runs the cross-system comparison against the caller-supplied legacy/new endpoints (both are [Section titled “Runs the cross-system comparison against the caller-supplied legacy/new endpoints (both are”](#runs-the-cross-system-comparison-against-the-caller-supplied-legacynew-endpoints-both-are) POSThttp\://localhost:3000/api/bench/run Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/bench.rs:65), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** Runs the cross-system comparison against the caller-supplied legacy/new endpoints (both are external HTTP targets from this crate’s point of view — even when “new” happens to be this same running instance, reached via its own bind address — so one implementation drives either case identically, matching how `lanrurugi-bench-compare` works standalone). #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/bench.rs:20 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # Bookmarks > 13 endpoints. 13 endpoints. ## `GET /archives/{id}/bookmarks` — unpaginated, just this one archive’s bookmarked pages [Section titled “GET /archives/{id}/bookmarks — unpaginated, just this one archive’s bookmarked pages”](#get-archivesidbookmarks--unpaginated-just-this-one-archives-bookmarked-pages) GEThttp\://localhost:3000/api/archives/{id}/bookmarks Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/bookmarks.rs:479), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `GET /archives/{id}/bookmarks` — unpaginated, just this one archive’s bookmarked pages (ascending, each with its resolved filename). Used by the reader (is the current page bookmarked? — only `page` matters there) and `BookmarkHoverGrid` (needs both `page` and `filename` for its caption, previously a second `GET /archives/{id}/files` call). Doesn’t require the archive to exist — same posture as `remove_bookmark`, a nonexistent archive simply has no bookmarks to report (and no filenames to resolve). 权限差异 * 对**不在访客可见范围内**的档案,这里返回 **404** 而不是 403——刻意与「档案不存在」不可区分,因此这个响应无法被用来探测访客范围之外的档案是否存在。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/bookmarks.rs:36 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `DELETE /archives/{id}/bookmarks/{page}` — idempotent, same as [Section titled “DELETE /archives/{id}/bookmarks/{page} — idempotent, same as”](#delete-archivesidbookmarkspage--idempotent-same-as) DELETEhttp\://localhost:3000/api/archives/{id}/bookmarks/{page} Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/bookmarks.rs:751), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `DELETE /archives/{id}/bookmarks/{page}` — idempotent, same as `BookmarksRepository::remove`’s own contract; doesn’t check archive existence first since removing a bookmark for an already-deleted archive is a legitimate cleanup, not an error. The activity-log lookup below is a *best-effort* label fetch only, separate from that leniency — a missing archive still lets the removal itself proceed, just with `target.label: None` (falls back to `target.id` alone, same as any other action type whose resource vanished first). #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/bookmarks.rs:37 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `POST /archives/{id}/bookmarks/{page}` — bookmarks does not validate `page` against the [Section titled “POST /archives/{id}/bookmarks/{page} — bookmarks does not validate page against the”](#post-archivesidbookmarkspage--bookmarks-does-not-validate-page-against-the) POSThttp\://localhost:3000/api/archives/{id}/bookmarks/{page} Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/bookmarks.rs:689), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `POST /archives/{id}/bookmarks/{page}` — bookmarks does not validate `page` against the archive’s real `pagecount`, matching `update_progress`’s own leniency (`archives.rs`) — the reader is the only caller and always passes its own current, already-valid page. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/bookmarks.rs:37 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `PUT /archives/{id}/bookmarks/{page}/name` — sets or clears this bookmark’s own name [Section titled “PUT /archives/{id}/bookmarks/{page}/name — sets or clears this bookmark’s own name”](#put-archivesidbookmarkspagename--sets-or-clears-this-bookmarks-own-name) PUThttp\://localhost:3000/api/archives/{id}/bookmarks/{page}/name Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/bookmarks.rs:562), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `PUT /archives/{id}/bookmarks/{page}/name` — sets or clears this bookmark’s own name. `404`s if the bookmark itself doesn’t exist yet (a name can’t outlive the bookmark it names, and setting one on a nonexistent bookmark would silently create an orphaned `NAMES_HASH_KEY` entry no `add_bookmark` call ever cleans up) — matches `add_stamp`’s own “archive must exist first” posture, just checking bookmark existence instead of archive existence. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/bookmarks.rs:47 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `GET /bookmarks` — every bookmark, aggregated by archive, sorted and paginated per `sort`/ [Section titled “GET /bookmarks — every bookmark, aggregated by archive, sorted and paginated per sort/”](#get-bookmarks--every-bookmark-aggregated-by-archive-sorted-and-paginated-per-sort) GEThttp\://localhost:3000/api/bookmarks Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/bookmarks.rs:252), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `GET /bookmarks` — every bookmark, aggregated by archive, sorted and paginated per `sort`/ `cursor`/`limit`. A bookmark whose archive has since been deleted is silently dropped from the result rather than erroring the whole list (same tolerance `BookmarksRepository::list_all` already applies to malformed individual entries — one dangling reference shouldn’t take down every other still-valid bookmark). #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/bookmarks.rs:29 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `GET /bookmarks/hover-page-order` — the saved `BookmarkHoverGrid` page-order preference [Section titled “GET /bookmarks/hover-page-order — the saved BookmarkHoverGrid page-order preference”](#get-bookmarkshover-page-order--the-saved-bookmarkhovergrid-page-order-preference) GEThttp\://localhost:3000/api/bookmarks/hover-page-order Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/bookmarks.rs:984), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `GET /bookmarks/hover-page-order` — the saved `BookmarkHoverGrid` page-order preference (`None` when never set; the frontend applies its own default, `"pageDesc"`, in that case). #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/bookmarks.rs:48 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Not recorded to the activity log — a display-only preference, same posture `settings.rs`’s own [Section titled “Not recorded to the activity log — a display-only preference, same posture settings.rs’s own”](#not-recorded-to-the-activity-log--a-display-only-preference-same-posture-settingsrss-own) PUThttp\://localhost:3000/api/bookmarks/hover-page-order Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/bookmarks.rs:1002), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** Not recorded to the activity log — a display-only preference, same posture `settings.rs`’s own `theme` field takes (no `record_manual` call either). #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/bookmarks.rs:48 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `GET /bookmarks/only-matching` — the saved “only show bookmarks that themselves matched `q`” [Section titled “GET /bookmarks/only-matching — the saved “only show bookmarks that themselves matched q””](#get-bookmarksonly-matching--the-saved-only-show-bookmarks-that-themselves-matched-q) GEThttp\://localhost:3000/api/bookmarks/only-matching Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/bookmarks.rs:1018), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `GET /bookmarks/only-matching` — the saved “only show bookmarks that themselves matched `q`” preference (`false` when never set, matching the historical always-show-everything behavior). #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/bookmarks.rs:52 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Not recorded to the activity log — same display-only posture `put_hover_page_order` takes [Section titled “Not recorded to the activity log — same display-only posture put_hover_page_order takes”](#not-recorded-to-the-activity-log--same-display-only-posture-put_hover_page_order-takes) PUThttp\://localhost:3000/api/bookmarks/only-matching Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/bookmarks.rs:1035), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** Not recorded to the activity log — same display-only posture `put_hover_page_order` takes. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/bookmarks.rs:52 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `GET /tankoubons/{id}/bookmarks` — every bookmark across every member archive, translated into [Section titled “GET /tankoubons/{id}/bookmarks — every bookmark across every member archive, translated into”](#get-tankoubonsidbookmarks--every-bookmark-across-every-member-archive-translated-into) GEThttp\://localhost:3000/api/tankoubons/{id}/bookmarks Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/bookmarks.rs:877), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `GET /tankoubons/{id}/bookmarks` — every bookmark across every member archive, translated into the Tankoubon’s own global page numbering. Unpaginated, ascending by global page — matches `list_bookmarks_for_archive`’s own contract (used the same way, by `BookmarkHoverGrid`, just for a Tankoubon card instead of a plain archive card). A member archive that no longer exists (or has an empty `pagecount`, e.g. not yet scanned) contributes nothing, silently, rather than failing the whole request — same tolerance `TankoubonFullResponse`’s own docs describe for `full_data` silently omitting a missing member. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/bookmarks.rs:64 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `DELETE /tankoubons/{id}/bookmarks/{page}` — same resolve-then-delegate shape as [Section titled “DELETE /tankoubons/{id}/bookmarks/{page} — same resolve-then-delegate shape as”](#delete-tankoubonsidbookmarkspage--same-resolve-then-delegate-shape-as) DELETEhttp\://localhost:3000/api/tankoubons/{id}/bookmarks/{page} Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/bookmarks.rs:832), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `DELETE /tankoubons/{id}/bookmarks/{page}` — same resolve-then-delegate shape as \[`add_tank_bookmark`], onto \[`remove_bookmark`]. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/bookmarks.rs:68 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `POST /tankoubons/{id}/bookmarks/{page}` — resolves the Tankoubon-global `page` down to the [Section titled “POST /tankoubons/{id}/bookmarks/{page} — resolves the Tankoubon-global page down to the”](#post-tankoubonsidbookmarkspage--resolves-the-tankoubon-global-page-down-to-the) POSThttp\://localhost:3000/api/tankoubons/{id}/bookmarks/{page} Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/bookmarks.rs:817), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `POST /tankoubons/{id}/bookmarks/{page}` — resolves the Tankoubon-global `page` down to the real member archive + local page (`tankoubons::resolve_tank_page`) and delegates to \[`add_bookmark`]’s own logic; the write itself still lands on the real archive id, same as a stamp placed while reading a Tankoubon (`stamps.rs`’s own Tankoubon routes) — `bookmarks.rs`’s underlying `BookmarksRepository` has no `TANK_` concept of its own and never needs one. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/bookmarks.rs:68 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `PUT /tankoubons/{id}/bookmarks/{page}/name` — same resolve-then-delegate shape as [Section titled “PUT /tankoubons/{id}/bookmarks/{page}/name — same resolve-then-delegate shape as”](#put-tankoubonsidbookmarkspagename--same-resolve-then-delegate-shape-as) PUThttp\://localhost:3000/api/tankoubons/{id}/bookmarks/{page}/name Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/bookmarks.rs:665), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `PUT /tankoubons/{id}/bookmarks/{page}/name` — same resolve-then-delegate shape as `add_tank_bookmark`/`remove_tank_bookmark`, onto \[`rename_bookmark`]. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/bookmarks.rs:72 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # Category API > 7 endpoints. 7 endpoints. ## Get all Categories [Section titled “Get all Categories”](#get-all-categories) GEThttp\://localhost:3000/api/categories Get all the categories saved on the server. #### 响应 200分类列表 ``` [ { "archives": [ "0d50858d727723d856d2ab78564bb8e906e65f14", "7f03b8b1f337e1e42b2c2890533c0de7479d41ca" ], "id": "SET_1613080290", "name": "My great category", "pinned": 0, "search": null } ] ``` 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Create a Category [Section titled “Create a Category”](#create-a-category) PUThttp\://localhost:3000/api/categories Create a new Category. #### 请求体 application/x-www-form-urlencoded, multipart/form-data #### 响应 200成功响应 ``` { "category_id": "SET_1613080290", "operation": "create_category", "success": 0 } ``` 400错误响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Delete Category [Section titled “Delete Category”](#delete-category) DELETEhttp\://localhost:3000/api/categories/{id} #### 响应 200成功响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 423该分类 ID 当前被锁定,无法修改 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Get a single Category [Section titled “Get a single Category”](#get-a-single-category) GEThttp\://localhost:3000/api/categories/{id} Get the details of the specified category ID. #### 响应 200分类 ``` { "archives": [ "0d50858d727723d856d2ab78564bb8e906e65f14", "7f03b8b1f337e1e42b2c2890533c0de7479d41ca" ], "id": "SET_1613080290", "name": "My great category", "pinned": 0, "search": null } ``` 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Update Category [Section titled “Update Category”](#update-category) PUThttp\://localhost:3000/api/categories/{id} Modify a Category. #### 请求体 application/x-www-form-urlencoded, multipart/form-data #### 响应 200成功响应 ``` { "category_id": "SET_1613080290", "operation": "update_category", "success": 0 } ``` 400错误响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 423该分类当前被锁定,无法修改 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Remove an Archive from a Category [Section titled “Remove an Archive from a Category”](#remove-an-archive-from-a-category) DELETEhttp\://localhost:3000/api/categories/{id}/{archive} Remove an Archive ID from a Category. #### 路径参数 * idstring · min: 14 · max: 14 · pattern必填 要移出的分类 ID。 * archivestring · min: 40 · max: 40 · pattern必填 要移除的档案 ID。 #### 响应 200结果 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 423该分类 ID 当前被锁定,无法修改 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpatharchivepath 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Add an Archive to a Category [Section titled “Add an Archive to a Category”](#add-an-archive-to-a-category) PUThttp\://localhost:3000/api/categories/{id}/{archive} Adds the specified Archive ID (see Archive API) to the given Category. #### 路径参数 * idstring · min: 14 · max: 14 · pattern必填 要加入的分类 ID。 * archivestring · min: 40 · max: 40 · pattern必填 #### 响应 200结果 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 423该分类 ID 当前被锁定,无法修改 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpatharchivepath 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # Database API > 14 endpoints. 14 endpoints. ## Get a backup JSON [Section titled “Get a backup JSON”](#get-a-backup-json) GEThttp\://localhost:3000/api/database/backup Scans the entire database and returns a backup in JSON form. Consider using the POST variant if your database is large, as this basic GET endpoint might time out if it takes too long to generate the backup.\ This backup can be reimported manually through the Backup and Restore feature. #### 响应 200成功响应 ``` { "archives": [ { "arcid": "28697b96f0ac5858be2614ed10ca47742c9522fd", "filename": "FateGOMEMO", "summary": null, "tags": "parody:fate grand order, group:wadamemo, artist:wada rco, artbook, full color, super:test, date_added:1553537258", "thumbhash": "ec2a0ca3a3da67a9390889f0910fe494241faa9a", "title": "Fate GO MEMO" }, { "arcid": "d1858d5dc36925aa66be072a97817650d39de166", "filename": "(Memes)9B789D38B0784C5FBC9D59A9F24D20F2", "summary": null, "tags": "", "thumbhash": "9846bb6d62949b56545c42e88d8010446b65702e", "title": "test title" } ], "categories": [ { "archives": [], "catid": "SET_1749925633", "name": "english", "search": "language:english" } ], "tankoubons": [ { "archives": [ "28697b96f0ac5858be2614ed10ca47742c9522fd", "d1858d5dc36925aa66be072a97817650d39de166" ], "name": "sailor moon", "tankid": "TANK_1749925516" } ] } ``` 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Queue a backup job [Section titled “Queue a backup job”](#queue-a-backup-job) POSThttp\://localhost:3000/api/database/backup Queues a Minion job to generate a backup JSON file.\ Use the returned job ID to check progress and download the file once complete. #### 响应 200已入队的任务 ``` { "job": 42, "operation": "queue_backup", "success": 1 } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Download backup JSON from completed job [Section titled “Download backup JSON from completed job”](#download-backup-json-from-completed-job) GEThttp\://localhost:3000/api/database/backup/{jobid} Downloads the backup JSON file generated by a completed backup job. #### 路径参数 * jobidinteger必填 已完成的备份任务 ID。 #### 查询参数 * formatstring · enum: json | file可选 返回的备份格式,默认 `file`。`json` 会以 JSON 响应返回备份。 #### 响应 200备份 JSON 文件 ``` {} ``` 400任务不存在,或尚未完成 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• jobidpathformatqueryjson 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Clean the Database [Section titled “Clean the Database”](#clean-the-database) POSThttp\://localhost:3000/api/database/clean Cleans the Database, hiding then removing entries for files that are no longer on the filesystem.\ Entries that are no longer on the filesystem are only unlinked at first so they don’t appear in the UI – A subsequent run of this cleanup will **delete** unlinked entries. #### 响应 200成功响应 ``` { "deleted": 0, "operation": "", "success": 0, "unlinked": 0 } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Drop the Database [Section titled “Drop the Database”](#drop-the-database) POSThttp\://localhost:3000/api/database/drop Delete the entire database, including user preferences. This is a rather dangerous endpoint, invoking it might lock you out of the server as a client! #### 响应 200成功响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Imports a LANraragi (or LANrurugi) backup JSON file the caller uploads directly — no live [Section titled “Imports a LANraragi (or LANrurugi) backup JSON file the caller uploads directly — no live”](#imports-a-lanraragi-or-lanrurugi-backup-json-file-the-caller-uploads-directly--no-live) POSThttp\://localhost:3000/api/database/import-legacy Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/database.rs:789), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** Imports a LANraragi (or LANrurugi) backup JSON file the caller uploads directly — no live connection to any remote Redis instance (see `lanrurugi_backup::import_legacy`’s own module docs for why: the official LANraragi Docker image never exposes its bundled Redis outside the container by default). Same multipart-file-upload shape as `queue_restore` above, but this is deliberately its own independent handler/parsing/persistence path, not a variant of `queue_restore` — see `import_legacy`’s own docs on why the two must not share code despite superficially similar JSON shapes. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/database.rs:44 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## How many times this instance has ever run a LANraragi import — read by the frontend before [Section titled “How many times this instance has ever run a LANraragi import — read by the frontend before”](#how-many-times-this-instance-has-ever-run-a-lanraragi-import--read-by-the-frontend-before) GEThttp\://localhost:3000/api/database/import-legacy/count Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/database.rs:998), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** How many times this instance has ever run a LANraragi import — read by the frontend before showing the import UI, so it can warn (“you’ve done this before — consider a full backup first”) on a 2nd-or-later import without waiting for the import itself to complete. Read-only, separate from `queue_import_legacy`’s own increment (which happens after a real import finishes), matching `ImportSnapshotRepository::import_count`’s own read/increment split. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/database.rs:48 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Newest-first metadata list (no `document` payload — see [Section titled “Newest-first metadata list (no document payload — see”](#newest-first-metadata-list-no-document-payload--see) GEThttp\://localhost:3000/api/database/import-snapshots Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/database.rs:1025), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** Newest-first metadata list (no `document` payload — see `ImportSnapshotRepository::list_metadata`’s own docs) for the Backup page’s Time-Machine-style rollback-point picker. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/database.rs:49 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## delete_import_snapshot [Section titled “delete_import_snapshot”](#delete_import_snapshot) DELETEhttp\://localhost:3000/api/database/import-snapshots/{id} Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `delete_import_snapshot` in crates/lanrurugi-api/src/database.rs:1067. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/database.rs:50 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Returns the full `BackupDocument` payload as a downloadable JSON file — same shape [Section titled “Returns the full BackupDocument payload as a downloadable JSON file — same shape”](#returns-the-full-backupdocument-payload-as-a-downloadable-json-file--same-shape) GEThttp\://localhost:3000/api/database/import-snapshots/{id} Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/database.rs:1045), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** Returns the full `BackupDocument` payload as a downloadable JSON file — same shape `POST /database/restore` accepts, so the frontend’s own “restore” flow can take this file straight back in with zero format translation on either side. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/database.rs:50 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Clear All “New” flags [Section titled “Clear All “New” flags”](#clear-all-new-flags) DELETEhttp\://localhost:3000/api/database/isnew Clears the “New!” flag on all archives. #### 响应 200成功响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## rebuild_index [Section titled “rebuild_index”](#rebuild_index) POSThttp\://localhost:3000/api/database/rebuild-index Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `rebuild_index` in crates/lanrurugi-api/src/database.rs:706. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/database.rs:43 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Queue a restore job [Section titled “Queue a restore job”](#queue-a-restore-job) POSThttp\://localhost:3000/api/database/restore Queues a Minion job to restore from a backup JSON file.\ Use the returned job ID to check progress. #### 请求体 multipart/form-data #### 响应 200已入队的任务 ``` { "job": 43, "operation": "queue_restore", "success": 1 } ``` 400请求无效 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Get Statistics [Section titled “Get Statistics”](#get-statistics) GEThttp\://localhost:3000/api/database/stats Get tags from the database, with a value symbolizing their prevalence. #### 查询参数 * minweightinteger可选 只想取权重不低于给定最小值的标签时传这个参数。 不传时默认为 1,即返回全部标签。 * hide_excluded_namespacesstring可选 设为 true 时,把服务端设置里配置的命名空间从结果中排除。默认返回全部标签。 #### 响应 200成功响应 ``` [ { "namespace": "character", "text": "jeanne alter", "weight": 2 }, { "namespace": "character", "text": "xuanzang", "weight": 2 }, { "namespace": "parody", "text": "fate grand order", "weight": 3 }, { "namespace": null, "text": "artbook", "weight": 3 } ] ``` 服务器地址http\://localhost:3000API 令牌••••• minweightqueryhide_excluded_namespacesquery 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # Download Queue > 21 endpoints. 21 endpoints. ## List queue items [Section titled “List queue items”](#list-queue-items) GEThttp\://localhost:3000/api/download_queue Every item in the download queue, in whatever state it currently holds. For live updates prefer `/download_queue/stream`, which pushes state changes as they happen rather than requiring a poll. #### 响应 200队列。 ``` { "items": [ {} ] } ``` 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Add items to the queue [Section titled “Add items to the queue”](#add-items-to-the-queue) POSThttp\://localhost:3000/api/download_queue Bulk add. The caller has already decided which download plugin’s `url_pattern` matched each URL; this endpoint’s only validation is that `plugin_namespace` resolves to an installed plugin. Invalid entries are **rejected individually** rather than failing the whole batch, so one bad URL in a pasted list does not block the rest. Check `rejected` in the response. #### 请求体 application/json #### 响应 200已加入的项,以及未能加入的项。 ``` { "added": [ {} ], "rejected": [ { "reason": "", "url": "" } ] } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Delete a queue item [Section titled “Delete a queue item”](#delete-a-queue-item) DELETEhttp\://localhost:3000/api/download_queue/{id} Removes one item from the queue. An item that is currently downloading is refused with a 409 — deleting its record out from under the running background task would leave that task updating nothing, with no queue row left to show progress and no way to stop the transfer. Stop it first. A queue item that has already been ingested into the library is also refused; remove the resulting archive instead. #### 路径参数 * idstring必填 #### 响应 200已删除。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 409该项正在下载;请先停止再删除。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpath 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Update a queue item [Section titled “Update a queue item”](#update-a-queue-item) PATCHhttp\://localhost:3000/api/download_queue/{id} Partial update: a field omitted from the request body keeps its stored value rather than being cleared. Same convention as `PUT /plugins/options`. #### 路径参数 * idstring必填 #### 请求体 Any subset of the item's editable fields. #### 响应 200已更新。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 404没有该队列项。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000 idpath 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `POST /download_queue/{id}/compare` — issue #77’s AI quality-comparison judgment for a [Section titled “POST /download_queue/{id}/compare — issue #77’s AI quality-comparison judgment for a”](#post-download_queueidcompare--issue-77s-ai-quality-comparison-judgment-for-a) POSThttp\://localhost:3000/api/download_queue/{id}/compare Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/download_queue.rs:1857), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `POST /download_queue/{id}/compare` — issue #77’s AI quality-comparison judgment for a `PendingFilenameConflict`: page-aligns and sharpness-compares the freshly-staged download (`temp_path`, exposed to the response as \[`imgcompare::Side::A`]) against the already-cataloged archive that owns the colliding filename (`existing_id`’s own file, exposed as \[`imgcompare::Side::B`]) — read-only, resolves nothing on its own; the frontend still calls `.../overwrite` or `.../rename` afterward based on what the user (with or without this comparison’s help) decides. `A`/`B` are deliberately not labeled “new”/“old” in the response itself (see \[`lanrurugi_imgcompare::Side`]’s own docs) — this handler is what actually assigns that meaning for this specific caller. Kept alongside the streaming \[`compare_queue_item_stream`] below (not replaced by it) as a plain request/response fallback for any caller that doesn’t want SSE — the frontend’s own `ComparisonResultModal` flow now goes through the stream endpoint instead (see that handler’s own docs for why). #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/download_queue.rs:44 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `POST /download_queue/{id}/compare/export-patch` — builds a `.patch.zip` from a user-picked [Section titled “POST /download_queue/{id}/compare/export-patch — builds a .patch.zip from a user-picked”](#post-download_queueidcompareexport-patch--builds-a-patchzip-from-a-user-picked) POSThttp\://localhost:3000/api/download_queue/{id}/compare/export-patch Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/download_queue.rs:2610), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `POST /download_queue/{id}/compare/export-patch` — builds a `.patch.zip` from a user-picked selection of A’s own unique pages (`ComparisonResult.a_unmatched_pages`, issue #77’s own follow-on design) and returns its raw bytes for download, ready to be dropped next to the target archive on disk as `.patch.zip` (`lanrurugi_scanner::patch`) — this endpoint doesn’t write it there itself (confirmed design: “补丁不需要应用,只要放在漫画目录内” — a user-placed file, not one this server installs unprompted). The target is always B (the existing library archive this conflict is against) — a patch only ever adds A’s own extra pages on top of the version the user is keeping, never the other way around. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/download_queue.rs:61 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `POST /download_queue/{id}/compare/keep-b` — the “keep the existing library archive, discard [Section titled “POST /download_queue/{id}/compare/keep-b — the “keep the existing library archive, discard”](#post-download_queueidcomparekeep-b--the-keep-the-existing-library-archive-discard) POSThttp\://localhost:3000/api/download_queue/{id}/compare/keep-b Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/download_queue.rs:2719), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `POST /download_queue/{id}/compare/keep-b` — the “keep the existing library archive, discard this download” resolution (issue #77’s own follow-on design). Distinct from every other resolve action in this file: those all catalogue the *staged* file (A) as some archive, either replacing B (`overwrite_queue_item`) or coexisting with it (`rename_queue_item`) — this one catalogues nothing at all. B is already in the library and stays exactly where it is; the only two things that happen are (1) `insertions`, if any, get written straight to B’s own sidecar `.patch.zip` (not just returned for the user to place themselves, unlike \[`export_compare_patch`] — this flow’s own frontend already walked the user through picking insertion points as part of *choosing* to keep B, so there’s no separate “now go place this file” step left for them to do), and (2) the queue item is deleted outright, same as a plain `DELETE /download_queue/{id}` — there’s nothing left for it to track (confirmed design: a patch’s own existence lives on disk next to B, not as a queue-item flag). #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/download_queue.rs:65 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `GET /download_queue/{id}/compare/page?side=a|b&index=N` — the actual page image behind one [Section titled “GET /download_queue/{id}/compare/page?side=a|b\&index=N — the actual page image behind one”](#get-download_queueidcomparepagesideabindexn--the-actual-page-image-behind-one) GEThttp\://localhost:3000/api/download_queue/{id}/compare/page Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/download_queue.rs:2354), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `GET /download_queue/{id}/compare/page?side=a|b&index=N` — the actual page image behind one `PageComparison` sample from `.../compare`’s own response, for the frontend’s overlay/shift-to-toggle comparison view. `side=a` reads from the still-uncatalogued staged download (`temp_path` — no archive ID exists yet, so this can’t reuse `archives.rs`’s own `GET /archives/{id}/page`); `side=b` reads from the existing archive’s own file. `index` is a natural-sort page position (matching `lanrurugi_imgcompare::PageComparison`’s own `a_page_index`/`b_page_index`), resolved to an entry name via `list_pages` fresh on every call rather than cached — this endpoint is only ever hit a handful of times per conflict (issue #77’s own confirmed sample size of 3-5), so re-listing isn’t worth adding a cache for. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/download_queue.rs:53 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `GET /download_queue/{id}/compare/pages?side=a|b` — the real entry-name list for one side of [Section titled “GET /download_queue/{id}/compare/pages?side=a|b — the real entry-name list for one side of”](#get-download_queueidcomparepagessideab--the-real-entry-name-list-for-one-side-of) GEThttp\://localhost:3000/api/download_queue/{id}/compare/pages Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/download_queue.rs:2482), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `GET /download_queue/{id}/compare/pages?side=a|b` — the real entry-name list for one side of the comparison, in natural-sort (page) order. The frontend’s own “pick where to insert an unmatched A page” UI (issue #77’s own follow-on design) needs B’s real entry names to send as `after_filename`/`before_filename` in `.../export-patch` — it otherwise only ever deals in numeric page indices (matching `PageComparison.a_page_index`/`b_page_index`), which `patch.rs`’s own JSON schema deliberately doesn’t use (see that module’s docs on why an entry name is the stable anchor, not an index that can drift if the archive is re-scanned). #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/download_queue.rs:57 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `GET /download_queue/{id}/compare/stream` — the SSE-streaming twin of \[`compare_queue_item`] [Section titled “GET /download_queue/{id}/compare/stream — the SSE-streaming twin of \[compare_queue_item\]”](#get-download_queueidcomparestream--the-sse-streaming-twin-of-compare_queue_item) GEThttp\://localhost:3000/api/download_queue/{id}/compare/stream Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/download_queue.rs:1988), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `GET /download_queue/{id}/compare/stream` — the SSE-streaming twin of \[`compare_queue_item`] above, per issue #77’s own confirmed two-phase design (see `lanrurugi_imgcompare::compare_archives_streaming`’s own docs for the full phase-1/phase-2 breakdown): opens an `EventSource`-compatible stream (GET, not POST — `EventSource` can’t send a request body or use any other HTTP method) that emits one `event: sample` per `CompareEvent::Sample` (coarse first, precise replacements streamed in afterward) and a single terminal `event: done` carrying the rest of `ComparisonResult`’s own fields — never relies on connection-close/timeout as an implicit end signal (“并且sse要有结束标记”). The frontend opens its result view the moment the FIRST `sample` event arrives rather than waiting for the whole comparison, which for a \~200-page archive pair is otherwise several seconds of dead time (“假设有6对结果(粗加工),可以用sse分6次发,发第一对的时候就开始显示modal,这样是一个很大的提速”). A cache hit (same policy as `compare_queue_item`’s own) is replayed as a single burst of `sample` events (`phase: coarse` for all of them — a cached result has already gone through both phases, and the frontend only cares about “is this a display-final value”, which `Coarse` vs `Precise` doesn’t actually change once the value itself is final) immediately followed by `done`, so re-opening an already-computed comparison is still effectively instant. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/download_queue.rs:49 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `POST /download_queue/{id}/confirm-older` — answers the [Section titled “POST /download_queue/{id}/confirm-older — answers the”](#post-download_queueidconfirm-older--answers-the) POSThttp\://localhost:3000/api/download_queue/{id}/confirm-older Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/download_queue.rs:707), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `POST /download_queue/{id}/confirm-older` — answers the `AwaitingRevisionConfirmation` prompt raised when a download turned out to be an *older* revision than an archive already in the library (issue #107’s `warn_then_conflict_menu`). `proceed: true` records the decision on the item and restarts it — the restart runs straight through the same version-history check instead of parking again, because `revision_confirmed` is now set. `proceed: false` moves the item to `Cancelled`, which is already the “user stopped this on purpose, still restartable” state, so no new terminal state is needed. Deliberately separate from `.../start`: `AwaitingRevisionConfirmation` is not `is_startable`, so the ordinary Start button can’t skip the question by accident. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/download_queue.rs:45 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `POST /download_queue/{id}/fetch-metadata` — the “Fetch Metadata” button’s backend path [Section titled “POST /download_queue/{id}/fetch-metadata — the “Fetch Metadata” button’s backend path”](#post-download_queueidfetch-metadata--the-fetch-metadata-buttons-backend-path) POSThttp\://localhost:3000/api/download_queue/{id}/fetch-metadata Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/download_queue.rs:148), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `POST /download_queue/{id}/fetch-metadata` — the “Fetch Metadata” button’s backend path. Runs the same plugin-`execMetadata` + `metadata_preview`-cache logic the post-download auto-fetch uses (`plugins::ensure_metadata_cached`), so a manual preview and the automatic one share one code path (and one 10-min TTL) instead of the frontend calling `POST /plugins/use` itself. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/download_queue.rs:36 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `POST /download_queue/{id}/overwrite` — resolves a `PendingFilenameConflict` by deleting the [Section titled “POST /download_queue/{id}/overwrite — resolves a PendingFilenameConflict by deleting the”](#post-download_queueidoverwrite--resolves-a-pendingfilenameconflict-by-deleting-the) POSThttp\://localhost:3000/api/download_queue/{id}/overwrite Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/download_queue.rs:1362), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `POST /download_queue/{id}/overwrite` — resolves a `PendingFilenameConflict` by deleting the existing archive (B) and cataloguing the staged download (A) under its originally-intended filename. `body.insertions`, when given, packages B’s own unique pages into a `.patch.zip` for the *new* A archive (issue #77’s own follow-on design: even when A wins overall, some of B’s pages might still be worth keeping) — this has to read B’s pages and resolve B’s own category/tag/progress metadata *before* calling `resolve_conflict`, since that call deletes B’s file and record as part of cataloguing A (`pipeline.rs::delete_existing_archive`) — there’s nothing left to read from afterward. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/download_queue.rs:42 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `POST /download_queue/{id}/rename` — resolves a `PendingFilenameConflict` by cataloguing the [Section titled “POST /download_queue/{id}/rename — resolves a PendingFilenameConflict by cataloguing the”](#post-download_queueidrename--resolves-a-pendingfilenameconflict-by-cataloguing-the) POSThttp\://localhost:3000/api/download_queue/{id}/rename Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/download_queue.rs:1649), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `POST /download_queue/{id}/rename` — resolves a `PendingFilenameConflict` by cataloguing the staged download under `body.filename` instead, leaving the existing archive that owns the original filename untouched (a fresh, separate, coexisting archive). If `filename` itself also collides with some other archive, the item ends up with a *new* `PendingFilenameConflict` (still resolvable, just against a different existing archive/filename) rather than losing the already-downloaded bytes — see `ingest::resolve_rename`’s own docs. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/download_queue.rs:43 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Start one queue item [Section titled “Start one queue item”](#start-one-queue-item) POSThttp\://localhost:3000/api/download_queue/{id}/start Resolves the item’s own download plugin (chosen when it was added, not now), marks it as starting, and launches the real download in the background. The item’s `state`, `job_id` and `error` stay current as the transfer proceeds. #### 路径参数 * idstring必填 #### 响应 200已启动;响应体里带着任务 ID。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 409该项当前不处于可启动状态。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpath 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `POST /download_queue/{id}/stop` — cancels an in-flight (`Starting`/`Downloading`) item’s [Section titled “POST /download_queue/{id}/stop — cancels an in-flight (Starting/Downloading) item’s”](#post-download_queueidstop--cancels-an-in-flight-startingdownloading-items) POSThttp\://localhost:3000/api/download_queue/{id}/stop Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/download_queue.rs:1253), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `POST /download_queue/{id}/stop` — cancels an in-flight (`Starting`/`Downloading`) item’s download and reverts it to `Queued` so it can be restarted. Cooperative, not forceful: this only signals `AppState::download_cancellations`’ token for the item — the background task itself notices at its next `tokio::select!` poll (see `download_manager::stream::download_one`) and does its own partial-file cleanup before actually finishing, at which point `start_download` reverts the queue item’s state (see the `cancel_for_task.is_cancelled()` branch there). No token present means either the item was never actually downloading (nothing to stop) or it already finished on its own just before this request landed — both are `NotRunning`, not an error worth surfacing loudly, since the desired end state (“this item isn’t downloading”) is already true either way. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/download_queue.rs:41 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `POST /download_queue/clear_completed` — deletes every `Done` item, returns the count removed [Section titled “POST /download_queue/clear_completed — deletes every Done item, returns the count removed”](#post-download_queueclear_completed--deletes-every-done-item-returns-the-count-removed) POSThttp\://localhost:3000/api/download_queue/clear_completed Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/download_queue.rs:3098), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `POST /download_queue/clear_completed` — deletes every `Done` item, returns the count removed. Deliberately excludes `Error` — unlike `Done`, an errored item is a restartable, still- actionable state (grouped with `Queued`/`Cancelled` everywhere else in this module: selectable, has a retry button, shows its own error text), not “completed” work a user is done looking at. A user wanting to discard a specific failed item can still do so individually via `DELETE /download_queue/{id}` (which does clean up a `pending_filename_conflict`’s own staged temp file — `Done` items never carry one, so this handler has nothing analogous to worry about). #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/download_queue.rs:69 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Delete selected queue items [Section titled “Delete selected queue items”](#delete-selected-queue-items) POSThttp\://localhost:3000/api/download_queue/delete_selected Bulk delete by ID, mirroring `start_selected`’s semantics: an ID that is missing or already deleted is a **silent no-op**, not an error, so a stale selection can be passed safely. An ID that is currently downloading is likewise a silent no-op — the same safety rule the single-item delete enforces with a 409. #### 请求体 application/json #### 响应 200实际被移除的那些 ID。 ``` { "deleted": [ "" ] } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Start every queued item [Section titled “Start every queued item”](#start-every-queued-item) POSThttp\://localhost:3000/api/download_queue/start_all Starts every item in the `queued` state, concurrently. Each spawns its own background task; per-domain concurrency and rate limiting are enforced downstream by the download manager, so no extra throttling happens here. Deliberately narrower than the single-item start: items in `error` or `cancelled` are retried one at a time on purpose, and an item parked awaiting a version-conflict answer is **never** swept up — bulk-starting it would answer, by omission, the very question it is parked on. #### 响应 200哪些项启动了、哪些被跳过以及原因。 ``` { "skipped": [ { "id": "", "reason": "" } ], "started": [ { "id": "", "job": "" } ] } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Start selected queue items [Section titled “Start selected queue items”](#start-selected-queue-items) POSThttp\://localhost:3000/api/download_queue/start_selected Like `start_all`, filtered to the IDs given. An ID that is already in flight, already finished, or otherwise not startable is a **silent no-op**, not an error — so a client can pass a selection without re-checking each item’s current state first. #### 请求体 application/json #### 响应 200哪些项启动了、哪些被跳过以及原因。 ``` { "skipped": [ { "id": "", "reason": "" } ], "started": [ { "id": "", "job": "" } ] } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `GET /download_queue/stream` — SSE endpoint that pushes incremental queue-item state changes [Section titled “GET /download_queue/stream — SSE endpoint that pushes incremental queue-item state changes”](#get-download_queuestream--sse-endpoint-that-pushes-incremental-queue-item-state-changes) GEThttp\://localhost:3000/api/download_queue/stream Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/download_queue.rs:75), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `GET /download_queue/stream` — SSE endpoint that pushes incremental queue-item state changes broadcast by `update_queue_item_state` after each successful Redis write. The first event is `full` with the current complete list so the client can bootstrap without a separate HTTP GET. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/download_queue.rs:31 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # Duplicate Detection > 3 endpoints. 3 endpoints. ## `DELETE /database/duplicates` — matches legacy’s `?delete=1` param on the same page route [Section titled “DELETE /database/duplicates — matches legacy’s ?delete=1 param on the same page route”](#delete-databaseduplicates--matches-legacys-delete1-param-on-the-same-page-route) DELETEhttp\://localhost:3000/api/database/duplicates Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/duplicates.rs:228), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `DELETE /database/duplicates` — matches legacy’s `?delete=1` param on the same page route. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/duplicates.rs:32 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Reads every stored group, resolving IDs to current archive metadata and pruning entries that [Section titled “Reads every stored group, resolving IDs to current archive metadata and pruning entries that”](#reads-every-stored-group-resolving-ids-to-current-archive-metadata-and-pruning-entries-that) GEThttp\://localhost:3000/api/database/duplicates Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/duplicates.rs:169), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** Reads every stored group, resolving IDs to current archive metadata and pruning entries that have vanished since the scan (deleted archives) — matches legacy’s self-healing behavior in `Controller/Duplicates.pm::index` (drops the whole group if it’d shrink below 2 members, otherwise just removes the vanished ID and rewrites the group). #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/duplicates.rs:32 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Queues the scan as a background job (matches legacy’s `/api/minion/find_duplicates/queue` [Section titled “Queues the scan as a background job (matches legacy’s /api/minion/find_duplicates/queue”](#queues-the-scan-as-a-background-job-matches-legacys-apiminionfind_duplicatesqueue) POSThttp\://localhost:3000/api/database/duplicates/scan Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/duplicates.rs:47), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** Queues the scan as a background job (matches legacy’s `/api/minion/find_duplicates/queue` being Minion-backed rather than synchronous) since hashing every archive pair is O(n²) and shouldn’t block the request. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/duplicates.rs:36 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # Font Patterns > 2 endpoints. 2 endpoints. ## get_font_pattern [Section titled “get_font_pattern”](#get_font_pattern) GEThttp\://localhost:3000/api/volumes/{id}/font-pattern Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `get_font_pattern` in crates/lanrurugi-api/src/font_pattern.rs:35. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/font_pattern.rs:25 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## reset_font_pattern [Section titled “reset_font_pattern”](#reset_font_pattern) POSThttp\://localhost:3000/api/volumes/{id}/font-pattern/reset Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `reset_font_pattern` in crates/lanrurugi-api/src/font_pattern.rs:52. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/font_pattern.rs:24 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # Health > 1 endpoint. 1 endpoint. ## health [Section titled “health”](#health) GEThttp\://localhost:3000/health Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `health` in crates/lanrurugi-api/src/health.rs:68. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/health.rs:43 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点不需要认证。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # Background Jobs > 3 endpoints. 3 endpoints. ## Clear every finished job [Section titled “Clear every finished job”](#clear-every-finished-job) DELETEhttp\://localhost:3000/api/jobs Removes jobs that have reached a terminal state — `finished` **or** `failed`. Jobs still in flight (`queued`, `active`) are left tracked; use the single-job endpoint once they settle. Only `state=finished` is accepted. The name means “any terminal-state job”, which is why `failed` jobs are swept up too. #### 查询参数 * statestring · enum: finished必填 只接受 `finished`;缺失或传入其他值会返回 400。 #### 响应 200清除了多少个任务。 ``` null ``` 400\`state\` 缺失,或者不是 \`finished\`。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• statequeryfinished 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## List tracked background jobs [Section titled “List tracked background jobs”](#list-tracked-background-jobs) GEThttp\://localhost:3000/api/jobs Every job this instance is tracking, most recently created first. Progress and byte counts are best-effort: a job that cannot report granular progress jumps straight from 0 to 1 rather than reporting a fabricated intermediate value, and the byte fields are genuinely absent (not `0`) for jobs that have no transfer to report. #### 响应 200当前任务列表。 ``` { "jobs": [ { "downloaded_bytes": null, "error": null, "finished_at": null, "id": null, "name": null, "progress": null, "rate_limit_bytes_per_sec": null, "rate_limit_matched_pattern": null, "result": null, "result_truncated": null, "started_at": null, "state": null, "total_bytes": null } ] } ``` 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Clear one job [Section titled “Clear one job”](#clear-one-job) DELETEhttp\://localhost:3000/api/jobs/{id} Clears a single job by ID, and only once it has reached a terminal state. A job that is still `queued` or `active` is a 409 rather than being silently killed — a job that reports success while its work is still running would be worse than an error. #### 路径参数 * idstring必填 #### 响应 200已清除。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 404没有在跟踪该 ID 的任务。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 409该任务仍在排队或执行中;请等它结束或失败后再操作。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpath 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # AI Usage > Per-feature AI request counts, token usage, time and failures. Per-feature AI request counts, token usage, time and failures. ## usage [Section titled “usage”](#usage) GEThttp\://localhost:3000/api/llm/usage Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `usage` in crates/lanrurugi-api/src/llm_usage.rs:124. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/llm_usage.rs:19 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # Login > 4 endpoints. 4 endpoints. ## login [Section titled “login”](#login) POSThttp\://localhost:3000/api/login Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `login` in crates/lanrurugi-api/src/login.rs:236. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/login.rs:39 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点不需要认证。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `GET /login/status` — reports whether the caller is “logged in” for the purposes of gating [Section titled “GET /login/status — reports whether the caller is “logged in” for the purposes of gating”](#get-loginstatus--reports-whether-the-caller-is-logged-in-for-the-purposes-of-gating) GEThttp\://localhost:3000/api/login/status Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/login.rs:669), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `GET /login/status` — reports whether the caller is “logged in” for the purposes of gating admin-only UI, matching legacy’s own `userlogged` template variable (`Controller/Reader.pm`/`Index.pm`: `enable_pass == 0 || session('is_logged')`). Deliberately its own endpoint rather than a new field on `/info` — `/info` mirrors legacy’s third-party `ServerInfo` OpenAPI schema field-for-field (constitution Principle II), and `logged_in` has no place in that contract. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/login.rs:40 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点不需要认证。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Now that refresh tokens are stateful (`lanrurugi_storage::refresh_tokens`), logout actually [Section titled “Now that refresh tokens are stateful (lanrurugi_storage::refresh_tokens), logout actually”](#now-that-refresh-tokens-are-stateful-lanrurugi_storagerefresh_tokens-logout-actually) POSThttp\://localhost:3000/api/logout Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/login.rs:751), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** Now that refresh tokens are stateful (`lanrurugi_storage::refresh_tokens`), logout actually revokes — burns the entire refresh-token family the caller’s access token was minted from (same remediation `rotate`’s own reuse-detection path takes), not just clearing the browser’s cookies and hoping the now-orphaned access token quietly expires on its own within the next few hours. Reads `fid` out of the *access* token (`session::COOKIE_NAME`, `Path=/`), not the refresh cookie — deliberately, so `REFRESH_COOKIE_PATH` can stay scoped to only `POST /api/token/refresh` without also needing to cover this endpoint. Uses `family_id_ignoring_expiry` rather than the normal expiry-checking verifier: a user who clicks “log out” after their access token has already expired (idle tab, hasn’t hit any endpoint that would have triggered a silent refresh yet) must still get their refresh-token family actually revoked — an already-expired access token still proves genuine origin via its signature, which is all this needs. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/login.rs:41 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点不需要认证。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `POST /token/refresh` — no legacy equivalent [Section titled “POST /token/refresh — no legacy equivalent”](#post-tokenrefresh--no-legacy-equivalent) POSThttp\://localhost:3000/api/token/refresh Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/login.rs:404), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `POST /token/refresh` — no legacy equivalent. Redeems the refresh cookie for a fresh access token + rotated refresh cookie (see `lanrurugi_storage::refresh_tokens::rotate`’s own docs for the rotation/reuse-detection semantics). The frontend calls this transparently on a 401 from any other endpoint (`apps/frontend/src/api/client.ts`), before ever redirecting to `/login`. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/login.rs:42 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点不需要认证。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # Logs > 1 endpoint. 1 endpoint. ## get_log_lines [Section titled “get_log_lines”](#get_log_lines) GEThttp\://localhost:3000/api/logs/{category} Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `get_log_lines` in crates/lanrurugi-api/src/logs.rs:26. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/logs.rs:18 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # Minion API > 3 endpoints. 3 endpoints. ## Get the basic status of a Minion Job [Section titled “Get the basic status of a Minion Job”](#get-the-basic-status-of-a-minion-job) GEThttp\://localhost:3000/api/minion/{jobid} For a given Minion job ID, check whether it succeeded or failed.\ Minion jobs are ran for various occasions like thumbnails, cache warmup and handling incoming files.\ For some jobs, you can check the notes field for progress information. Look at for more information. #### 路径参数 * jobidinteger必填 要查询状态的任务 ID。 #### 响应 200任务状态数据 ``` { "error": null, "notes": { "example_note": "This note could contain the name of the upload, for example." }, "state": "finished", "task": "handle_upload" } ``` 服务器地址http\://localhost:3000API 令牌••••• jobidpath 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Get the full status of a Minion Job [Section titled “Get the full status of a Minion Job”](#get-the-full-status-of-a-minion-job) GEThttp\://localhost:3000/api/minion/{jobid}/detail Get the status of a Minion Job.\ This API is there for internal usage mostly, but you can use it to get detailed status for jobs like plugin runs or URL downloads. #### 路径参数 * jobidinteger必填 #### 响应 200任务详情 ``` { "args": [ "/tmp/QF3UCnKdMr/myfile.zip" ], "attempts": 1, "children": [], "created": 1601145004, "delayed": 1601145004, "expires": null, "finished": 1601145004, "id": 7, "lax": 0, "notes": {}, "parents": [], "priority": 0, "queue": "default", "result": { "id": "75d18ce470dc99f83dc355bdad66319d1f33c82b", "message": "This file already exists in the Library.", "success": 0 }, "retried": null, "retries": 0, "started": 1601145004, "state": "finished", "task": "handle_upload", "time": 1601145005, "worker": 1 } ``` 服务器地址http\://localhost:3000API 令牌••••• jobidpath 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Queue a Minion job [Section titled “Queue a Minion job”](#queue-a-minion-job) POSThttp\://localhost:3000/api/minion/{jobname}/queue Queue a Job with the specified type and parameters.\ See LANraragi::Utils::Minion for all the available types of jobs and the parameters they require. There’s no API contract in place for whether a Job type exists on a given server version, so I wouldn’t recommend using this unless you have a good reason to. #### 路径参数 * jobnamestring · enum: thumbnail_task | tank_thumbnail_task | page_thumbnails | regen_all_thumbnails | find_duplicates | build_stat_hashes | handle_upload | download_url | run_plugin必填 要实例化的任务类型。 #### 查询参数 * argsstring必填 参数,以 JSON 数组字符串给出 * priorityinteger · default: 0可选 Minion 任务的优先级。数字越大越优先。 #### 响应 200已入队的任务 ``` { "job": 0, "operation": "", "success": 1 } ``` 服务器地址http\://localhost:3000API 令牌••••• jobnamepaththumbnail_taskargsquerypriorityquery 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # Miscellaneous other API > 5 endpoints. 5 endpoints. ## Queue a URL download [Section titled “Queue a URL download”](#queue-a-url-download) POSThttp\://localhost:3000/api/download_url Add a URL to be downloaded by the server and added to its library. #### 查询参数 * urlstring可选 要下载的 URL * catidstring · min: 14 · max: 14 · pattern可选 把下载到的 URL 加入的分类 ID。 #### 请求体 multipart/form-data #### 响应 200已入队的任务 ``` { "job": 86, "operation": "download_url", "success": 1, "url": "https://example.com" } ``` 400请求有误 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• urlquerycatidquery 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Get server info [Section titled “Get server info”](#get-server-info) GEThttp\://localhost:3000/api/info Returns some basic information about the LRR instance this server is running. #### 响应 200服务端信息 ``` { "archives_per_page": 100, "authenticated_progress": false, "cache_last_cleared": 1728852701, "debug_mode": true, "excluded_namespaces": [ "source", "date_added" ], "has_password": false, "motd": "aye lads time to read some manga", "name": "LANraragi", "nofun_mode": false, "restart_required": false, "server_resizes_images": false, "server_tracks_progress": true, "total_archives": 104, "total_pages_read": 252, "version": "0.9.30", "version_desc": "I'm under Japanese influence and my honor's at stake!", "version_name": "Law (Earthlings On Fire)" } ``` 服务器地址http\://localhost:3000 该端点不需要认证。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `GET /api/llm/key-status` — returns `{ configured: true/false }` [Section titled “GET /api/llm/key-status — returns { configured: true/false }”](#get-apillmkey-status--returns--configured-truefalse-) GEThttp\://localhost:3000/api/llm/key-status Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/misc.rs:118), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `GET /api/llm/key-status` — returns `{ configured: true/false }`. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/misc.rs:20 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Regenerate Thumbnails [Section titled “Regenerate Thumbnails”](#regenerate-thumbnails) POSThttp\://localhost:3000/api/regen_thumbs Queue a Minion job to regenerate missing/all thumbnails on the server. #### 查询参数 * forceboolean可选 是生成全部缩略图,还是只生成缺失的那些。 #### 响应 200已入队的任务 ``` { "job": 3, "operation": "regen_thumbnails", "success": 1 } ``` 服务器地址http\://localhost:3000API 令牌••••• forcequery 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Clean the Temporary Folder [Section titled “Clean the Temporary Folder”](#clean-the-temporary-folder) DELETEhttp\://localhost:3000/api/tempfolder Cleans the server’s temporary folder. #### 响应 200清理结果 ``` { "error": null, "newsize": 0, "operation": "cleantemp", "success": 1 } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # OPDS Catalog > 3 endpoints. 3 endpoints. ## Get the OPDS Catalog [Section titled “Get the OPDS Catalog”](#get-the-opds-catalog) GEThttp\://localhost:3000/api/opds Get the Archive Index as an OPDS 1.2 Catalog with PSE 1.1 compatibility. #### 查询参数 * categorystring可选 分类 ID。传入后,OPDS 目录会被过滤为只显示该分类下的档案。 #### 响应 200OPDS 目录 XML 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• categoryquery 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Get a specific archive through OPDS [Section titled “Get a specific archive through OPDS”](#get-a-specific-archive-through-opds) GEThttp\://localhost:3000/api/opds/{id} Returns a specific OPDS item as XML. This will show only one \ for the given ID in the result, instead of all the archives. #### 路径参数 * idstring必填 #### 响应 200OPDS 条目 XML 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• idpath 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## OPDS-PSE [Section titled “OPDS-PSE”](#opds-pse) GEThttp\://localhost:3000/api/opds/{id}/pse Returns a specific image page for OPDS-PSE as XML. #### 路径参数 * idstring必填 #### 查询参数 * pageinteger可选 #### 响应 200所请求页面的图片文件 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• idpathpagequery 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # OpenSearch > 1 endpoint. 1 endpoint. ## opensearch_xml [Section titled “opensearch_xml”](#opensearch_xml) GEThttp\://localhost:3000/opensearch.xml Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `opensearch_xml` in crates/lanrurugi-api/src/opensearch.rs:74. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/opensearch.rs:25 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点不需要认证。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # Plugin Wizard > 7 endpoints. 7 endpoints. ## analyze_login [Section titled “analyze_login”](#analyze_login) POSThttp\://localhost:3000/api/plugin-wizard/analyze-login Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `analyze_login` in crates/lanrurugi-api/src/plugin_wizard/analyze_login.rs:55. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/plugin_wizard/mod.rs:23 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `GET /plugin-wizard/generate/{id}/record` — the whole read surface; no UI [Section titled “GET /plugin-wizard/generate/{id}/record — the whole read surface; no UI”](#get-plugin-wizardgenerateidrecord--the-whole-read-surface-no-ui) GEThttp\://localhost:3000/api/plugin-wizard/generate/{id}/record Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/plugin_wizard/record.rs:118), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `GET /plugin-wizard/generate/{id}/record` — the whole read surface; no UI. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/plugin_wizard/mod.rs:35 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `POST /plugin-wizard/generate/start` — see this module’s own top-level docs for why generation [Section titled “POST /plugin-wizard/generate/start — see this module’s own top-level docs for why generation”](#post-plugin-wizardgeneratestart--see-this-modules-own-top-level-docs-for-why-generation) POSThttp\://localhost:3000/api/plugin-wizard/generate/start Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/plugin_wizard/generate.rs:193), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `POST /plugin-wizard/generate/start` — see this module’s own top-level docs for why generation is split into this plus `generate_stream` rather than one `POST` returning JSON. Accepts the request body as a raw \[`serde_json::Value`] (not a typed `GenerateRequest`) specifically so this endpoint never has to duplicate `GenerateRequest`’s own field/default handling — the real typed parse happens once, at `generate_stream` time, against whatever was stashed here unmodified. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/plugin_wizard/mod.rs:27 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `GET /plugin-wizard/generate/stream/{id}` — the real `EventSource`-compatible streaming [Section titled “GET /plugin-wizard/generate/stream/{id} — the real EventSource-compatible streaming”](#get-plugin-wizardgeneratestreamid--the-real-eventsource-compatible-streaming) GEThttp\://localhost:3000/api/plugin-wizard/generate/stream/{id} Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/plugin_wizard/generate.rs:211), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `GET /plugin-wizard/generate/stream/{id}` — the real `EventSource`-compatible streaming endpoint; see this module’s own top-level docs for the full event sequence. `id` is single-use (removed from `pending_generate_requests` the moment this is called), so replaying the same id (a stale bookmark, a double-click race) always yields `generation_not_found` rather than silently re-running an old request. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/plugin_wizard/mod.rs:31 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## lookup [Section titled “lookup”](#lookup) POSThttp\://localhost:3000/api/plugin-wizard/lookup Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `lookup` in crates/lanrurugi-api/src/plugin_wizard/mod.rs:22. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/plugin_wizard/mod.rs:22 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## save [Section titled “save”](#save) POSThttp\://localhost:3000/api/plugin-wizard/save Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `save` in crates/lanrurugi-api/src/plugin_wizard/save.rs:71. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/plugin_wizard/mod.rs:40 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## trial_run [Section titled “trial_run”](#trial_run) POSThttp\://localhost:3000/api/plugin-wizard/trial-run Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `trial_run` in crates/lanrurugi-api/src/plugin_wizard/trial_run.rs:148. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/plugin_wizard/mod.rs:39 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # Plugin API > 12 endpoints. 12 endpoints. ## List available plugins [Section titled “List available plugins”](#list-available-plugins) GEThttp\://localhost:3000/api/plugins/{type} List all plugins of the given type. #### 路径参数 * typestring · enum: download | login | metadata | script | all必填 要列出的插件类型。传 "all" 可以一次取回所有类型。 #### 响应 200插件数组 ``` [ { "author": "Difegue", "description": "Searches chaika.moe for tags matching your archive.", "icon": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA\\nB3RJTUUH4wYCFQocjU4r+QAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUH\\nAAAEZElEQVQ4y42T3WtTdxzGn/M7J+fk5SRpTk7TxMZkXU84tTbVNrUT3YxO7HA4pdtQZDe7cgx2\\ns8vBRvEPsOwFYTDYGJUpbDI2wV04cGXCGFLonIu1L2ptmtrmxeb1JDkvv121ZKVze66f74eH7/f5\\nMmjRwMCAwrt4/9KDpflMJpPHvyiR2DPcJklJ3TRDDa0xk36cvrm8vDwHAAwAqKrqjjwXecPG205w\\nHBuqa9rk77/d/qJYLD7cCht5deQIIczbgiAEKLVAKXWUiqVV06Tf35q8dYVJJBJem2A7Kwi2nQzD\\nZig1CG93+PO5/KN6tf5NKpVqbsBUVVVFUUxwHJc1TXNBoxojS7IbhrnLMMx9pVJlBqFQKBKPxwcB\\nkJYgjKIo3QCE1nSKoghbfJuKRqN2RVXexMaQzWaLezyeEUEQDjscjk78PxFFUYRkMsltJgGA3t7e\\nyMLCwie6rr8iCILVbDbvMgwzYRjGxe0o4XC4s1AoHPP5fMP5/NNOyzLKAO6Ew+HrDADBbre/Ryk9\\nnzx81FXJNlEpVpF+OqtpWu2MpmnXWmH9/f2umZmZi4cOHXnLbILLzOchhz1YerJAs9m1GwRAg2GY\\nh7GYah488BJYzYW+2BD61AFBlmX/1nSNRqN9//792ujoaIPVRMjOKHoie3DytVGmp2fXCAEAjuMm\\nu7u7Umosho6gjL/u/QHeEgvJZHJ2K/D+/fuL4+PjXyvPd5ldkShy1UXcmb4DnjgQj/fd5gDA6/XS\\nYCAwTwh9oT3QzrS1+VDVi+vd3Tsy26yQVoFF3dAXJVmK96p9EJ0iLNOwKKU3CQCk0+lSOpP5WLDz\\nF9Q9kZqyO0SloOs6gMfbHSU5NLRiUOuax2/HyZPHEOsLw2SbP83eu/fLxrkNp9P554XxCzVa16MC\\n7+BPnTk9cfmH74KJE8nmga7Xy5JkZ8VKifGIHpoBb1VX8hNTd3/t/7lQ3OeXfFPvf/jBRw8ezD/a\\n7M/aWq91cGgnJaZ2VcgSdnV1XRNNd3vAoBVVYusmnEQS65hfgSG6c+zy3Kre7nF/KrukcMW0Zg8O\\nD08DoJutDxxOEb5IPUymwrq8ft1gLKfkFojkkRxemERCAQUACPFWRazYLJcrFGwQhyufbQQ7rFpy\\nLMkCwGZC34qPIuwp+XPOjBFwazQ/txrdFS2GGS/Xuj+pUKLGk1Kjvlded3s72lyGW+PLbGVcmrAA\\ngN0wTk1NWYODg9XOKltGtpazi5GigzroUnHN5nUHG1ylRsG7rDXHmnEpu4CeEtEKkqNc6QqlLc/M\\n8uT5lLH5eq0aGxsju1O7GQB498a5s/0x9dRALPaQEDZnYwnhWJtMCCNrjeb0UP34Z6e/PW22zjPP\\n+vwXBwfPvbw38XnXjk7GsiwKAIQQhjAMMrlsam45d+zLH6/8o6vkWcBcrXbVKQhf6bpucCwLjmUB\\nSmmhXC419eblrbD/TAgAkUjE987xE0c7ZDmk66ajUCnq+cL63fErl25s5/8baQPaWLhx6goAAAAA\\nSUVORK5CYII=", "name": "Chaika.moe", "namespace": "trabant", "oneshot_arg": "Chaika Gallery or Archive URL (Will attach matching tags to your archive)", "origin": "builtin", "parameters": [ { "desc": "ipb_pass_hash cookie", "type": "string" }, { "default_value": 0, "desc": "Force resampled archive download", "name": "forceresampled", "type": "bool" } ], "type": "metadata", "version": "2.1" } ] ``` 服务器地址http\://localhost:3000API 令牌••••• typepathdownload 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `GET /plugins/export?namespace=...` (`specs/006-ai-plugin-wizard` FR-028) — downloads an [Section titled “GET /plugins/export?namespace=... (specs/006-ai-plugin-wizard FR-028) — downloads an”](#get-pluginsexportnamespace-specs006-ai-plugin-wizard-fr-028--downloads-an) GEThttp\://localhost:3000/api/plugins/export Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/plugins.rs:1038), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `GET /plugins/export?namespace=...` (`specs/006-ai-plugin-wizard` FR-028) — downloads an installed plugin (wizard-created or not) as a `.zip` containing its own `.ts` file, named after the namespace’s own last path component (e.g. `custom/metadata/foo` → `foo.zip` containing `foo.ts`) rather than the full namespace, since the namespace’s `/`-separated category prefix isn’t meaningful once extracted standalone. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/plugins.rs:435 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `POST /plugins/export-batch` — like \[`export_plugin`] but for several namespaces at once, [Section titled “POST /plugins/export-batch — like \[export_plugin\] but for several namespaces at once,”](#post-pluginsexport-batch--like-export_plugin-but-for-several-namespaces-at-once) POSThttp\://localhost:3000/api/plugins/export-batch Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/plugins.rs:1109), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `POST /plugins/export-batch` — like \[`export_plugin`] but for several namespaces at once, packed into a single `.zip`. Each entry is stored under its full namespace path (`custom/ download/foo.ts`, not just `foo.ts`) since two different namespaces can share the same file stem (`custom/download/foo` vs `custom/metadata/foo`) — collapsing both to `foo.ts` would silently drop one on zip write. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/plugins.rs:436 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## delete_plugin_options [Section titled “delete_plugin_options”](#delete_plugin_options) DELETEhttp\://localhost:3000/api/plugins/options Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `delete_plugin_options` in crates/lanrurugi-api/src/plugins.rs:931. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/plugins.rs:437 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## get_plugin_options [Section titled “get_plugin_options”](#get_plugin_options) GEThttp\://localhost:3000/api/plugins/options Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `get_plugin_options` in crates/lanrurugi-api/src/plugins.rs:785. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/plugins.rs:437 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## put_plugin_options [Section titled “put_plugin_options”](#put_plugin_options) PUThttp\://localhost:3000/api/plugins/options Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `put_plugin_options` in crates/lanrurugi-api/src/plugins.rs:854. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/plugins.rs:437 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `PUT /plugins/priority` — persists a drag-and-drop reorder of one plugin `type` group’s display [Section titled “PUT /plugins/priority — persists a drag-and-drop reorder of one plugin type group’s display”](#put-pluginspriority--persists-a-drag-and-drop-reorder-of-one-plugin-type-groups-display) POSThttp\://localhost:3000/api/plugins/priority Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/plugins.rs:567), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `PUT /plugins/priority` — persists a drag-and-drop reorder of one plugin `type` group’s display order (additive, no legacy equivalent: legacy’s `plugins.html.tt2` has no such affordance at all). Rewrites every listed namespace’s `priority` field in its own `LRR_PLUGIN_` hash (same storage as `customargs`/`enabled`) to its position in `order`, so a subsequent `GET /plugins/{type}` sorts accordingly. A namespace whose actual type doesn’t match `body.type` is skipped (not written, not erroring the whole request) — see `PutPluginPriorityBody::kind`’s own docs for why this check exists at all. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/plugins.rs:432 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Use a Plugin Asynchronously [Section titled “Use a Plugin Asynchronously”](#use-a-plugin-asynchronously) POSThttp\://localhost:3000/api/plugins/queue Uses a Plugin and returns a Minion Job ID matching the Plugin run. This endpoint is useful if you want to run longer-lived plugins which might timeout if ran with the standard endpoint. #### 查询参数 * idstring · min: 40 · max: 40 · pattern可选 要在其上执行插件的档案 ID。只有元数据插件才必须提供。 * priorityinteger · default: 0可选 Minion 任务的优先级。数字越大越优先。 * pluginstring可选 要使用的插件命名空间。 * argstring可选 执行该插件时可选的 One-Shot 参数。 #### 响应 200已入队的任务 ``` { "job": 86, "operation": "queue_plugin_exec", "success": 1 } ``` 服务器地址http\://localhost:3000API 令牌••••• idquerypriorityquerypluginqueryargquery 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `GET /plugins/settings?namespace=...` — the plugin’s currently persisted `customargs` (padded/ [Section titled “GET /plugins/settings?namespace=... — the plugin’s currently persisted customargs (padded/”](#get-pluginssettingsnamespace--the-plugins-currently-persisted-customargs-padded) GEThttp\://localhost:3000/api/plugins/settings Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/plugins.rs:461), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `GET /plugins/settings?namespace=...` — the plugin’s currently persisted `customargs` (padded/ truncated to exactly its own declared `parameters.len()` — a stale saved array longer/shorter than the plugin’s current declaration, e.g. after the plugin was upgraded to add/remove a parameter, is silently reconciled to the current shape rather than surfaced as a mismatch, matching legacy’s own default-value-fill-then-overwrite behavior in `get_plugin_parameters`) and `enabled` (legacy’s “Run Automatically” toggle — `is_plugin_enabled`, `false` when never set, same as legacy’s own `hexists`-gated default). #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/plugins.rs:422 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## put_plugin_settings [Section titled “put_plugin_settings”](#put_plugin_settings) PUThttp\://localhost:3000/api/plugins/settings Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `put_plugin_settings` in crates/lanrurugi-api/src/plugins.rs:497. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/plugins.rs:422 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## upload_plugin [Section titled “upload_plugin”](#upload_plugin) POSThttp\://localhost:3000/api/plugins/upload Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `upload_plugin` in crates/lanrurugi-api/src/plugins.rs:3924. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/plugins.rs:434 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Use a Plugin [Section titled “Use a Plugin”](#use-a-plugin) POSThttp\://localhost:3000/api/plugins/use Uses a Plugin and returns the result. If using a metadata plugin, the matching archive will not be modified in the database. See more info on Plugins in the matching section of the Docs. #### 查询参数 * idstring · min: 40 · max: 40 · pattern可选 要在其上执行插件的档案 ID。只有元数据插件才必须提供。 * pluginstring可选 要使用的插件命名空间。 * argstring可选 执行该插件时可选的 One-Shot 参数。 #### 响应 200插件执行结果 ``` { "data": { "new_tags": "pages:45" }, "operation": "use_plugin", "success": 1, "type": "metadata" } ``` 服务器地址http\://localhost:3000API 令牌••••• idquerypluginqueryargquery 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # Preferences > 2 endpoints. 2 endpoints. ## Read the caller’s preferences [Section titled “Read the caller’s preferences”](#read-the-callers-preferences) GEThttp\://localhost:3000/api/preferences The caller’s own library-view preferences, falling back to the defaults for any value that has never been set. An unauthenticated caller gets the defaults — not another user’s settings. #### 响应 200生效中的偏好设置。 ``` { "library_sortby": "", "library_sortdir": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Update the caller’s preferences [Section titled “Update the caller’s preferences”](#update-the-callers-preferences) PUThttp\://localhost:3000/api/preferences Stores the caller’s library-view preferences. Fields omitted from the request are left as they are. Requires an authenticated caller; an unauthenticated one is refused rather than silently writing to a shared bucket. #### 请求体 application/json #### 响应 200已保存;响应体会回显保存后的值。 ``` { "library_sortby": "", "library_sortdir": "" } ``` 403没有已认证的调用者,无法确定偏好的归属。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # Recommendations > 1 endpoint. 1 endpoint. ## get_recommendations [Section titled “get_recommendations”](#get_recommendations) GEThttp\://localhost:3000/api/reader/recommendations/{id} Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `get_recommendations` in crates/lanrurugi-api/src/recommend.rs:438. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/recommend.rs:430 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # Maintenance Scripts > 3 endpoints. 3 endpoints. ## `POST /database/scripts/repair-mojibake` — see `crate::mojibake`’s own docs for why stored [Section titled “POST /database/scripts/repair-mojibake — see crate::mojibake’s own docs for why stored”](#post-databasescriptsrepair-mojibake--see-cratemojibakes-own-docs-for-why-stored) POSThttp\://localhost:3000/api/database/scripts/repair-mojibake Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/scripts.rs:61), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `POST /database/scripts/repair-mojibake` — see `crate::mojibake`’s own docs for why stored records can still hold doubly-encoded text long after the importer learned to repair it. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/scripts.rs:41 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `POST /database/scripts/subfolders-to-categories` — scans the archive folder and creates one [Section titled “POST /database/scripts/subfolders-to-categories — scans the archive folder and creates one”](#post-databasescriptssubfolders-to-categories--scans-the-archive-folder-and-creates-one) POSThttp\://localhost:3000/api/database/scripts/subfolders-to-categories Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/scripts.rs:182), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `POST /database/scripts/subfolders-to-categories` — scans the archive folder and creates one static Category per subfolder that directly contains archives (`FolderToCat.pm::run_script`). Reports its own wall-clock `elapsed_ms` in the response (directory walk through category creation, inclusive) so it can be directly compared against `plugins/script/foldertocat.ts` — a real `.ts` script plugin doing the identical directory walk + grouping logic itself (via `Deno.readDir`, not host-injected paths — the user wanted a genuine head-to-head, not a contrived one where the plugin is handed pre-walked data), used to gauge the real overhead of running this kind of I/O-heavy whole-library scan through the Deno-subprocess plugin sandbox versus native Rust. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/scripts.rs:33 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `POST /database/scripts/subfolders-to-tankoubons` — scans only the **first-level subfolders** [Section titled “POST /database/scripts/subfolders-to-tankoubons — scans only the first-level subfolders”](#post-databasescriptssubfolders-to-tankoubons--scans-only-the-first-level-subfolders) POSThttp\://localhost:3000/api/database/scripts/subfolders-to-tankoubons Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/scripts.rs:494), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `POST /database/scripts/subfolders-to-tankoubons` — scans only the **first-level subfolders** of the archive folder and creates one Tankoubon per such subfolder. All archives under that first-level subdirectory (including archives in deeper nested subdirectories) are added to the same Tankoubon; nested subdirectories do not create their own Tankoubons. Duplicate names are allowed; this is a non-destructive action and never deletes or deduplicates existing Tankoubons. When a DeepSeek API key is configured, the endpoint best-effort uses the LLM to infer a better Tankoubon name and an `artist:`/`circle:` author tag. Without a key, or when the LLM call fails, it falls back to the raw folder name and skips the author tag. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/scripts.rs:37 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # Search API > Perform searches against the archive index. Perform searches against the archive index. ## Search Archives [Section titled “Search Archives”](#search-archives) GEThttp\://localhost:3000/api/search Search for Archives. You can use the IDs of this JSON with the other endpoints. 权限差异 * 访客(开启访客访问时的未认证访问者)只能看到所属分类被标记为「访客可见」的档案;其他身份能看到整个书库。 #### 查询参数 * categorystring · min: 14 · max: 14 · pattern可选 限定本次搜索范围的分类 ID。 * filterstring可选 搜索查询串。可以在这当中使用下列特殊字符: **双引号 ("...")** 精确字符串搜索。让一个搜索词可以包含空格;一对双引号内的所有内容会被当成单个词条处理。通配符仍然按通配符解释。 **问号 (?)、下划线 (\_)** 通配符,匹配任意单个字符。 **星号 (\*)、百分号 (%)** 通配符,匹配任意长度的字符序列(也可以一个都不匹配)。 **减号 (-)** 排除。放在某个词前面,搜索结果就不会包含该词。 **美元符号 ($)** 加在标签末尾,对该标签做精确搜索,而不是显示所有以该词开头的结果。它只匹配标签,不受搜索参数影响,因此也可以当作排除项,用来在搜索里忽略杂项标签。 * startinteger可选 从结果总数中的第几个档案开始枚举。单页显示的档案数取决于服务端的每页条数偏好。 从 0.8.2 起,这里传 "-1" 可以取到完整的、不分页的数据。 * sortbystring可选 结果排序所依据的命名空间。可用的排序键有: - \*title\*:按标题排序 - \*lastread\*:按上次阅读时间排序(需开启 **服务端进度跟踪** ) (默认值是 title。按 lastread 排序时,从未读过的 ID 会被从搜索结果里移除。) * orderstring可选 排序方向,`asc` 或 `desc`。 * newonlyboolean可选 只搜索未读过的档案。 * untaggedonlyboolean可选 只搜索未打标签的档案。 * hidecompletedboolean可选 隐藏已读到末尾的档案。 * groupby_tanksboolean · default: true可选 启用或关闭 Tankoubon 分组,默认开启。 开启时,搜索结果里会显示 Tankoubon,取代它包含的所有档案 ID。 #### 响应 200搜索结果 ``` { "data": [ { "arcid": "28697b96f0ac5858be2614ed10ca47742c9522fd", "extension": "rar", "filename": "Fate GO MEMO", "isnew": false, "lastreadtime": 1337038281, "pagecount": 34, "progress": 3, "size": 0, "summary": null, "tags": "parody:fate grand order, group:wadamemo, artist:wada rco, artbook, full color", "title": "Fate GO MEMO" }, { "arcid": "28697b96f0ac5858be2614ed10ca47742c9522fd", "extension": "rar", "filename": "Gucc", "isnew": false, "lastreadtime": 1337038281, "pagecount": 34, "progress": 3, "size": 0, "summary": "cool summary", "tags": "parody:jojo's bizarre adventure", "title": "Rohan Kishibe goes to Gucci" } ], "recordsFiltered": 2, "recordsTotal": 2 } ``` 204搜索引擎尚未初始化完成,请稍等几秒。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• categoryqueryfilterquerystartquerysortbyqueryorderquerynewonlyqueryuntaggedonlyqueryhidecompletedquerygroupby_tanksquery 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Additive raw-archive search endpoint (`GET /search/archives`), sharing `/search`’s query [Section titled “Additive raw-archive search endpoint (GET /search/archives), sharing /search’s query”](#additive-raw-archive-search-endpoint-get-searcharchives-sharing-searchs-query) GEThttp\://localhost:3000/api/search/archives Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/search.rs:435), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** Additive raw-archive search endpoint (`GET /search/archives`), sharing `/search`’s query syntax, filtering, sorting, and pagination but never folding member archives behind a Tankoubon. It is intentionally a separate endpoint rather than a new default on `/search`: existing grouped-search callers keep their exact behavior, while duplicate/library-membership checks can ask for the underlying archive records instead of a `TANK_` aggregate. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/search.rs:200 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Discard Search Cache [Section titled “Discard Search Cache”](#discard-search-cache) DELETEhttp\://localhost:3000/api/search/cache Discard the cache containing previous user searches. #### 响应 200成功响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 400没有档案 ID 的响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Forget one entry [Section titled “Forget one entry”](#forget-one-entry) DELETEhttp\://localhost:3000/api/search/history What the search panel’s `Delete` key calls on a highlighted history row. Removes every occurrence, so a hand-edited list cannot leave a row the reader cannot dismiss. #### 查询参数 * filterstring必填 The exact history entry to forget. #### 响应 200The history after the removal. ``` { "history": [ "" ] } ``` 400No filter to forget was given. ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 403The caller has no account to keep a history for. ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• filterquery 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## The account’s recent searches [Section titled “The account’s recent searches”](#the-accounts-recent-searches) GEThttp\://localhost:3000/api/search/history Newest first, at most 8 entries (the cap the browser-side version kept). With `filter`, only the entries related to it, judged with the engine’s own folding, so `くろ` still offers a stored `クロガネ`; without it, the whole history. A caller with no account (e.g. a read-only token) gets an empty list; guests are denied by the route policy. #### 查询参数 * filterstring可选 What the reader is typing; limits the answer to the related entries. #### 响应 200The (possibly filtered) history. ``` { "history": [ "" ] } ``` 服务器地址http\://localhost:3000API 令牌••••• filterquery 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Remember one applied filter [Section titled “Remember one applied filter”](#remember-one-applied-filter) POSThttp\://localhost:3000/api/search/history Moves the entry to the front, removing any previous occurrence and trimming to the cap, in one atomic pipeline. Called only for a genuinely applied filter. #### 请求体 application/json #### 响应 200The history after the write. ``` { "history": [ "" ] } ``` 400The filter was empty. ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 403The caller has no account to keep a history for. ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Search Archive IDs [Section titled “Search Archive IDs”](#search-archive-ids) GEThttp\://localhost:3000/api/search/ids Search for Archives like `/api/search`, but returns only the ordered list of matching Archive IDs without the accompanying metadata. 权限差异 * 作用域与 `/api/search` 相同:访客只会拿到访客可见档案的 ID。 #### 查询参数 * categorystring · min: 14 · max: 14 · pattern可选 限定本次搜索范围的分类 ID。 * filterstring可选 搜索查询串,规则与 `/api/search` 相同。 * startinteger可选 从结果总数中的第几个档案开始枚举。单页显示的档案数取决于服务端的每页条数偏好。 从 0.8.2 起,这里传 "-1" 可以取到完整的、不分页的 ID 列表。 * sortbystring可选 结果排序所依据的命名空间。可用的排序键有: - \*title\*:按标题排序 - \*lastread\*:按上次阅读时间排序(需开启 **服务端进度跟踪** ) (默认值是 title。按 lastread 排序时,从未读过的 ID 会被从搜索结果里移除。) * orderstring可选 排序方向,`asc` 或 `desc`。 * newonlyboolean可选 只搜索未读过的档案。 * untaggedonlyboolean可选 只搜索未打标签的档案。 * hidecompletedboolean可选 隐藏已读到末尾的档案。 * groupby_tanksboolean · default: true可选 启用或关闭 Tankoubon 分组,默认开启。 开启时,搜索结果里会显示 Tankoubon,取代它包含的所有档案 ID。 #### 响应 200搜索结果 ``` { "data": [ "28697b96f0ac5858be2614ed10ca47742c9522fd", "5cf64ec2f3c2c627fb8a64df198af2a8527c4fdb" ], "recordsFiltered": 2, "recordsTotal": 2 } ``` 204搜索引擎尚未初始化完成,请稍等几秒。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• categoryqueryfilterquerystartquerysortbyqueryorderquerynewonlyqueryuntaggedonlyqueryhidecompletedquerygroupby_tanksquery 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Search random Archives [Section titled “Search random Archives”](#search-random-archives) GEThttp\://localhost:3000/api/search/random Get randomly selected Archives from the given filter and/or category. 权限差异 * 作用域与 `/api/search` 相同:访客只会在访客可见的档案中随机抽取。 #### 查询参数 * categorystring · min: 14 · max: 14 · pattern可选 限定本次搜索范围的分类 ID。 * filterstring可选 搜索查询串,规则与 `/api/search` 相同。 * countinteger · default: 5可选 要随机取多少个档案,默认 5。 如果搜索结果的条数不够你要的数量,就返回全部搜索结果打乱后的结果。 * newonlyboolean可选 只搜索未读过的档案。 * untaggedonlyboolean可选 只搜索未打标签的档案。 * hidecompletedboolean可选 隐藏已读到末尾的档案。 * groupby_tanksboolean · default: true可选 启用或关闭 Tankoubon 分组,默认开启。 开启时,搜索结果里会显示 Tankoubon,取代它包含的所有档案 ID。 #### 响应 200搜索结果 ``` { "data": [ { "arcid": "28697b96f0ac5858be2614ed10ca47742c9522fd", "extension": "rar", "filename": "Gucc", "isnew": false, "lastreadtime": 1337038281, "pagecount": 34, "progress": 3, "size": 0, "summary": "cool summary", "tags": "parody:jojo's bizarre adventure", "title": "Rohan Kishibe goes to Gucci" } ], "recordsTotal": 2 } ``` 服务器地址http\://localhost:3000API 令牌••••• categoryqueryfilterquerycountquerynewonlyqueryuntaggedonlyqueryhidecompletedquerygroupby_tanksquery 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Additive, lightweight endpoint backing the Library search box’s title autocomplete [Section titled “Additive, lightweight endpoint backing the Library search box’s title autocomplete”](#additive-lightweight-endpoint-backing-the-library-search-boxs-title-autocomplete) GEThttp\://localhost:3000/api/search/suggest Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/search.rs:603), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** Additive, lightweight endpoint backing the Library search box’s title autocomplete. Unlike `/search`, it returns only `arcid` + `title` for the first few matches — no tags, progress, or size — because the frontend calls it on every (debounced) keystroke, where a full `/search` page of 100 archive records would be a few hundred KB of JSON that a suggestion list immediately discards. Same query syntax, same filters, and the same default `title` ordering as `/search` (which is exactly what a suggestion list wants), plus the same guest scoping: `restrict_to_archive_ids` is applied here too, so a `guest_visitor` can never be shown an out-of-scope title through this endpoint that `/search` would refuse to return. 权限差异 * 作用域与 `/api/search` 相同,因此访客不可能看到 `/api/search` 会拒绝返回的档案标题。 #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/search.rs:202 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # Signed-in Devices > 3 endpoints. 3 endpoints. ## List signed-in devices [Section titled “List signed-in devices”](#list-signed-in-devices) GEThttp\://localhost:3000/api/sessions Every active refresh-token family — that is, every device currently signed in — including the one making this request, which is marked so a client does not offer to revoke itself by accident. Requires a session-cookie login. An API token of either role is rejected. #### 响应 200当前活跃的会话。 ``` [ { "auto_name": "", "created_at": 0, "current": false, "custom_name": "", "expires_at": 0, "family_id": "", "idle_expires_at": 0, "ip": "", "last_seen_at": 0, "name": "" } ] ``` 服务器地址http\://localhost:3000 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Revoke a signed-in device [Section titled “Revoke a signed-in device”](#revoke-a-signed-in-device) DELETEhttp\://localhost:3000/api/sessions/{family_id} Ends one session by revoking its whole refresh-token family, so the device must sign in again. Requires a session-cookie login. #### 路径参数 * family_idstring必填 #### 响应 200已吊销。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 404没有该会话。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000 family_idpath 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Rename a signed-in device [Section titled “Rename a signed-in device”](#rename-a-signed-in-device) PATCHhttp\://localhost:3000/api/sessions/{family_id} Sets a custom display name for one session, so a device list reads as “living room tablet” rather than as a user-agent string. Requires a session-cookie login. #### 路径参数 * family_idstring必填 #### 请求体 application/json #### 响应 200已重命名。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 404没有该会话。 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000 family_idpath 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # Settings > 4 endpoints. 4 endpoints. ## get_settings [Section titled “get_settings”](#get_settings) GEThttp\://localhost:3000/api/settings Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `get_settings` in crates/lanrurugi-api/src/settings.rs:628. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/settings.rs:59 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## put_settings [Section titled “put_settings”](#put_settings) PUThttp\://localhost:3000/api/settings Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `put_settings` in crates/lanrurugi-api/src/settings.rs:755. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/settings.rs:59 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Sets a new admin password, hashed the same way legacy stores one (`{CRYPT}$2a$...` — see [Section titled “Sets a new admin password, hashed the same way legacy stores one ({CRYPT}$2a$... — see”](#sets-a-new-admin-password-hashed-the-same-way-legacy-stores-one-crypt2a--see) POSThttp\://localhost:3000/api/settings/password Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/settings.rs:1021), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** Sets a new admin password, hashed the same way legacy stores one (`{CRYPT}$2a$...` — see `lanrurugi_core::password`) so a legacy instance sharing this Redis keeps accepting it too. An empty string clears password protection’s practical effect the same way legacy’s own config-page “leave blank to keep current password” convention does *not* work here — this endpoint always sets whatever was submitted, so the frontend must not submit an empty field unless the user explicitly means to set an empty password. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/settings.rs:60 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点**只接受网页会话**(登录本站所用实例后浏览器自动携带的 cookie)。API 令牌会被服务端拒绝,因此这里不提供令牌输入框,上面的命令行也不带 Authorization 头。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## issue #92: this response also carries `language` now, not just `theme` — `useApplyTheme`/ [Section titled “issue #92: this response also carries language now, not just theme — useApplyTheme/”](#issue-92-this-response-also-carries-language-now-not-just-theme--useapplytheme) GEThttp\://localhost:3000/api/theme Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/settings.rs:160), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** issue #92: this response also carries `language` now, not just `theme` — `useApplyTheme`/ `useApplySettingsLanguage` (`apps/frontend/src/theme.ts`/`i18n/index.ts`) both used to read their respective field off the full, auth-gated `GET /settings` (which 401s pre-login, since that response also carries the API key and other genuinely secret fields that can’t be made public) — every page rendered before a session exists (the Login page’s own bespoke `usePublicTheme` fallback aside) hit that 401, and the *global* 401 handler in `client.ts` force-navigates to `/login` on every single one regardless of whether the calling hook itself already had a fallback ready, defeating issue #92’s own “stay on the page, don’t redirect” requirement for anything rendered while logged out (the new 404 page very much included — live-reported as a real double-navigation: the 404 content flashes, then `/login` anyway). `theme`/`language` are the only two fields anything needs before a session exists, and neither is remotely secret, so folding `language` into this already-public endpoint is simpler than standing up a whole second public settings surface for one more field. The response also carries `admin_theme` — always the administrator’s own `theme`, regardless of guest-eligibility — so the Login page can render with the admin theme even when guest mode is on and the guest theme is a different one. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/settings.rs:70 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点不需要认证。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # Shinobu API > 4 endpoints. 4 endpoints. ## Get Shinobu status [Section titled “Get Shinobu status”](#get-shinobu-status) GEThttp\://localhost:3000/api/shinobu Get the current status of the FileWatcher. #### 响应 200状态 ``` { "is_alive": 1, "operation": "shinobu_status", "pid": 1608, "success": 1 } ``` 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Rescan filemap and restart Shinobu [Section titled “Rescan filemap and restart Shinobu”](#rescan-filemap-and-restart-shinobu) POSThttp\://localhost:3000/api/shinobu/rescan This deletes the internal map of scanned files on your system (the “filemap”) and restarts Shinobu, effectively prompting a full rescan of your FS. #### 响应 200结果 ``` { "new_pid": 1727, "operation": "shinobu_rescan", "success": 1 } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Restart Shinobu [Section titled “Restart Shinobu”](#restart-shinobu) POSThttp\://localhost:3000/api/shinobu/restart Restart the Shinobu filewatcher #### 响应 200结果 ``` { "new_pid": 1727, "operation": "shinobu_restart", "success": 1 } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Stop Shinobu [Section titled “Stop Shinobu”](#stop-shinobu) POSThttp\://localhost:3000/api/shinobu/stop Stops the Filewatcher. Use `/api/shinobu/restart` to start it again. #### 响应 200结果 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # Stamps API > 8 endpoints. 8 endpoints. ## Get pages that contain at least one stamp in the archive [Section titled “Get pages that contain at least one stamp in the archive”](#get-pages-that-contain-at-least-one-stamp-in-the-archive) GEThttp\://localhost:3000/api/archives/{id}/stamps Get pages that contain at least one stamp in the archive. 权限差异 * 对**不在访客可见范围内**的档案,这里返回 **404** 而不是 403——刻意与「档案不存在」不可区分,因此这个响应无法被用来探测访客范围之外的档案是否存在。 #### 路径参数 * idstring必填 档案 ID。 #### 响应 200成功响应 ``` { "result": [ "" ] } ``` 400错误响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpath 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Get the stamps linked to the page [Section titled “Get the stamps linked to the page”](#get-the-stamps-linked-to-the-page) GEThttp\://localhost:3000/api/archives/{id}/stamps/{index} Get the stamps linked to the page. 权限差异 * 对**不在访客可见范围内**的档案,这里返回 **404** 而不是 403——刻意与「档案不存在」不可区分,因此这个响应无法被用来探测访客范围之外的档案是否存在。 #### 路径参数 * idstring必填 档案 ID。 * indexinteger必填 档案的页码。 #### 响应 200成功响应 ``` { "result": [ { "content": "Lorem ipsum dolore", "position": "12,34" } ] } ``` 400错误响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpathindexpath 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Add a stamp annotation [Section titled “Add a stamp annotation”](#add-a-stamp-annotation) PUThttp\://localhost:3000/api/archives/{id}/stamps/{index} Add a new Stamp to the page at the given coordinates. #### 路径参数 * idstring必填 档案 ID。 * indexinteger必填 档案的页码。 #### 查询参数 * contentstring可选 图章文本。 * positionstring可选 图章在页面中的位置。 #### 响应 200成功响应 ``` { "operation": "add_stamp", "stamp_id": "", "success": 0 } ``` 400错误响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpathindexpathcontentquerypositionquery 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Delete Stamp [Section titled “Delete Stamp”](#delete-stamp) DELETEhttp\://localhost:3000/api/stamps/{id} Remove a stamp from an Archive. #### 路径参数 * idstring必填 图章 ID。 #### 响应 200成功响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 400错误响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 423该图章当前被锁定,无法修改 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpath 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Get Stamp [Section titled “Get Stamp”](#get-stamp) GEThttp\://localhost:3000/api/stamps/{id} Get a stamp from an Archive. #### 路径参数 * idstring必填 图章 ID。 #### 响应 200成功响应 ``` { "content": "Lorem ipsum dolore", "position": "12,34" } ``` 400错误响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 423该图章当前被锁定,无法修改 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpath 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Update Stamp [Section titled “Update Stamp”](#update-stamp) PUThttp\://localhost:3000/api/stamps/{id} Update a stamp from an Archive. #### 路径参数 * idstring必填 图章 ID。 #### 查询参数 * contentstring可选 图章文本。 * positionstring可选 图章在页面中的位置。 #### 响应 200成功响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 400错误响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 423该图章当前被锁定,无法修改 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpathcontentquerypositionquery 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## tank_stamps_by_page [Section titled “tank_stamps_by_page”](#tank_stamps_by_page) GEThttp\://localhost:3000/api/tankoubons/{id}/stamps/{page} Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `tank_stamps_by_page` in crates/lanrurugi-api/src/stamps.rs:58. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/stamps.rs:52 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## tank_add_stamp [Section titled “tank_add_stamp”](#tank_add_stamp) PUThttp\://localhost:3000/api/tankoubons/{id}/stamps/{page} Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `tank_add_stamp` in crates/lanrurugi-api/src/stamps.rs:72. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/stamps.rs:52 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # Library Statistics > 3 endpoints. 3 endpoints. ## The archives behind one bar of one chart [Section titled “The archives behind one bar of one chart”](#the-archives-behind-one-bar-of-one-chart) GEThttp\://localhost:3000/api/stats/bucket A drill-down: given one bucket of one `/stats` chart, the archives in it, for the list the page shows under the chart. Fetched per click rather than folded into `/stats/overview`, which is a whole-library snapshot that would have to carry every bucket’s archive list to support this. Deliberately not expressed as a search query, even though some of these buckets have one: “last read on day X” has no search operator at all, and the progress ladder’s `unread` rung means “never *opened*” (its own `is_read`) while the search’s `read:`/`is:unread` filters key on the `progress` field alone — so they disagree about an archive that was opened without a page turn. Deriving the list from the same classification the chart used is what keeps the list and the bar consistent by construction. Requesting this as a guest is scoped to what that guest may see, matching `/stats/overview`. #### 查询参数 * metricstring · enum: ingest | read | size | rating | progress必填 `ingest`/`read` are time buckets and need `from`+`to`; `size`/`rating`/`progress` are keyed buckets and need `key`. * fromstring可选 `ingest`/`read` only. First day of the bucket, `YYYY-MM-DD`, inclusive. The client sends the span it actually drew rather than a unit+key pair, so no bucket-key-to-span arithmetic has to exist in two languages. * tostring可选 `ingest`/`read` only. Last day of the bucket, `YYYY-MM-DD`, inclusive. * keystring可选 `size` bucket key (`lt_1mb` … `gte_500mb`), a `rating` of `0`-`5` (where `0` is the unrated-or-zero slot, exactly as the chart's own distribution counts it), or a `progress` ladder key (`unread`, `1_20`, `21_40`, `41_60`, `61_80`, `81_99`, `finished`). #### 响应 200The bucket's archives, newest/largest/most-progressed first per metric. ``` { "archives": [ null ], "metric": "ingest", "total": 0, "truncated": false } ``` 400Unknown metric, or a missing/invalid \`from\`/\`to\`/\`key\` for that metric. ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• metricqueryingestfromquerytoquerykeyquery 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Aggregated library statistics [Section titled “Aggregated library statistics”](#aggregated-library-statistics) GEThttp\://localhost:3000/api/stats/overview One snapshot covering: headline totals, archive size distribution, container format/MIME breakdown, ingestion history (by month, by ingestion path, and the newest arrivals), reading history (per-day, progress distribution, ratings, and the most recently/most often read works), and a weighted reading-preference analysis over tags, authors and categories. Requesting this as a guest yields counts and breakdowns restricted to what that guest may actually see, matching `/database/stats`’s own scoping. Weighted preference values are relative rankings, not probabilities or percentages: they are only ever meaningful against each other within one response. #### 响应 200The aggregated snapshot. ``` { "formats": [ null ], "generated_at": 0, "ingest": { "recent": null, "sources": null, "sources_sampled": null, "sources_sampled_only": null }, "note": "no_server_side_reading", "preferences": { "by_namespace": null, "categories": null, "categories_truncated": null, "highlights": null, "namespaces": null, "ratings": null, "read_archives": null }, "reading": { "most_reread": null, "progress": null, "ratings": null, "recent": null }, "size_buckets": [ null ], "totals": { "archives": null, "average_bytes": null, "average_pages": null, "bookmarks": null, "categories": null, "finished": null, "largest_bytes": null, "new": null, "pages": null, "pages_read": null, "rated": null, "reading": null, "storage_bytes": null, "tankoubons": null, "unread": null } } ``` 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## One metric’s daily time series [Section titled “One metric’s daily time series”](#one-metrics-daily-time-series) GEThttp\://localhost:3000/api/stats/timeline The page’s time-series source, kept separate from `/stats/overview` because it is driven interactively: the overview is one expensive snapshot (its preference analysis runs a search per dynamic category), while this endpoint is refetched per range change and re-bucketed entirely client-side. The series is **always daily**, whatever granularity the reader is looking at, so that changing granularity — or zooming and panning — needs no request at all once the range has been fetched once. A request wider than the server’s own cap is clamped to the *newest* days of it, and `available_from` still reports where the data really begins. Requesting this as a guest is scoped to what that guest may see, matching `/stats/overview`. #### 查询参数 * metricstring · enum: ingest | reading必填 `ingest` counts archives added per day (from each archive's own `date_added` tag); `reading` reports page turns and archives-last-read per day. * frominteger可选 Unix seconds. Defaults to the whole available range — which is what the page asks for, so every later zoom is local. Clamped to the library's own data. * tointeger可选 Unix seconds; defaults to now, and is never later than it. #### 响应 200The daily series, oldest first. ``` { "available_from": "", "available_to": "", "from": "", "metric": "ingest", "pages_since": "", "points": [ null ], "to": "" } ``` 400\`metric\` was missing or was neither \`ingest\` nor \`reading\`. ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• metricqueryingestfromquerytoquery 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # Subscriptions > 25 endpoints. 25 endpoints. ## list_reservations [Section titled “list_reservations”](#list_reservations) GEThttp\://localhost:3000/api/reservations Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `list_reservations` in crates/lanrurugi-api/src/subscriptions/api.rs:1007. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:54 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## discard_reservation [Section titled “discard_reservation”](#discard_reservation) POSThttp\://localhost:3000/api/reservations/{id}/discard Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `discard_reservation` in crates/lanrurugi-api/src/subscriptions/api.rs:1027. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:55 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## list [Section titled “list”](#list) GEThttp\://localhost:3000/api/subscriptions Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `list` in crates/lanrurugi-api/src/subscriptions/api.rs:172. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:27 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## create [Section titled “create”](#create) POSThttp\://localhost:3000/api/subscriptions Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `create` in crates/lanrurugi-api/src/subscriptions/api.rs:249. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:27 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## remove [Section titled “remove”](#remove) DELETEhttp\://localhost:3000/api/subscriptions/{id} Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `remove` in crates/lanrurugi-api/src/subscriptions/api.rs:352. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:40 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## detail [Section titled “detail”](#detail) GEThttp\://localhost:3000/api/subscriptions/{id} Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `detail` in crates/lanrurugi-api/src/subscriptions/api.rs:292. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:40 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## update [Section titled “update”](#update) PUThttp\://localhost:3000/api/subscriptions/{id} Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `update` in crates/lanrurugi-api/src/subscriptions/api.rs:311. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:40 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## The user’s own “no”: these works are never downloaded by this subscription again [Section titled “The user’s own “no”: these works are never downloaded by this subscription again”](#the-users-own-no-these-works-are-never-downloaded-by-this-subscription-again) POSThttp\://localhost:3000/api/subscriptions/{id}/block Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/subscriptions/api.rs:644), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** The user’s own “no”: these works are never downloaded by this subscription again. Distinct from a rule rejection on purpose — a rule reads a value that can change, so a rejection is provisional and decided afresh every cycle (FR-011i), while this is an answer, and re-deciding it would ask again what the user already said. The preview offers it per row; `forget_seen` undoes it. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:50 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Runs a real check now rather than waiting for the schedule (FR-024) [Section titled “Runs a real check now rather than waiting for the schedule (FR-024)”](#runs-a-real-check-now-rather-than-waiting-for-the-schedule-fr-024) POSThttp\://localhost:3000/api/subscriptions/{id}/check Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/subscriptions/api.rs:846), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** Runs a real check now rather than waiting for the schedule (FR-024). Spawned rather than awaited: a check contacts the source and may page through it, which is longer than a request should hold open. The result shows up in the subscription’s own history. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:48 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## disable [Section titled “disable”](#disable) POSThttp\://localhost:3000/api/subscriptions/{id}/disable Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `disable` in crates/lanrurugi-api/src/subscriptions/api.rs:388. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:45 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## enable [Section titled “enable”](#enable) POSThttp\://localhost:3000/api/subscriptions/{id}/enable Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `enable` in crates/lanrurugi-api/src/subscriptions/api.rs:378. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:44 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Makes a subscription reconsider works it has already handled [Section titled “Makes a subscription reconsider works it has already handled”](#makes-a-subscription-reconsider-works-it-has-already-handled) POSThttp\://localhost:3000/api/subscriptions/{id}/forget Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/subscriptions/api.rs:597), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** Makes a subscription reconsider works it has already handled. Being seen is otherwise permanent, which is correct for the ordinary case — a work the user deleted on purpose must not come back on the next check. But two situations need it undone: a deletion made by mistake, and a rule that has since been widened (works rejected under the old rule were recorded as seen at the moment they were rejected, so nothing would reconsider them). With `sources`, forgets exactly those. With `all: true`, clears the set — kept as a separate, explicit request because on a long-running subscription it can match the entire back catalogue at once, which is a different order of consequence. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:49 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## What a check would do, without doing it [Section titled “What a check would do, without doing it”](#what-a-check-would-do-without-doing-it) POSThttp\://localhost:3000/api/subscriptions/{id}/preview Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/subscriptions/api.rs:803), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** What a check would do, without doing it. Deliberately works on a **disabled** subscription: “what would this rule actually catch” is asked precisely while tuning one that is switched off. Nothing is queued, recorded as seen, or logged, so it is safe to run repeatedly — the only cost is one request to the source. Accepts an optional body carrying an unsaved subscription, so a rule can be previewed before it is committed. Without that, a user would have to save a rule to find out what it does. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:47 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Clears a system-applied pause [Section titled “Clears a system-applied pause”](#clears-a-system-applied-pause) POSThttp\://localhost:3000/api/subscriptions/{id}/resume Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/subscriptions/api.rs:400), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** Clears a system-applied pause. Distinct from `enable`, because a paused subscription was stopped *by the system* and owes the user an explanation — resuming is the user answering it. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:46 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Every work the user has explicitly blocked, newest first, across all subscriptions [Section titled “Every work the user has explicitly blocked, newest first, across all subscriptions”](#every-work-the-user-has-explicitly-blocked-newest-first-across-all-subscriptions) GEThttp\://localhost:3000/api/subscriptions/blocked Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/subscriptions/api.rs:417), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** Every work the user has explicitly blocked, newest first, across all subscriptions. Its own endpoint rather than a filter over the history: a block is an *answer* — the user said no to this work — and the history is a log of decisions that keeps being rewritten by later cycles (a work queued and then catalogued reads `already_held` in every record). Only the block list stays exactly as the user left it, which is what makes it worth showing on its own and undoing from there. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:53 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## generate [Section titled “generate”](#generate) POSThttp\://localhost:3000/api/subscriptions/condition/ai Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `generate` in crates/lanrurugi-api/src/subscriptions/ai_condition.rs:301. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:38 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## parse [Section titled “parse”](#parse) POSThttp\://localhost:3000/api/subscriptions/condition/parse Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `parse` in crates/lanrurugi-api/src/subscriptions/ai_condition.rs:284. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:39 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Every subscription’s recent candidates, newest first, as one stream [Section titled “Every subscription’s recent candidates, newest first, as one stream”](#every-subscriptions-recent-candidates-newest-first-as-one-stream) GEThttp\://localhost:3000/api/subscriptions/history Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/subscriptions/api.rs:450), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** Every subscription’s recent candidates, newest first, as one stream. Per-subscription history already exists, but it answers “what did *this* rule do” — the question actually asked is usually the other one: what has arrived lately, and why did something expected not. That needs the subscriptions interleaved rather than read one at a time. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:52 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Matched works waiting for the user’s go-ahead [Section titled “Matched works waiting for the user’s go-ahead”](#matched-works-waiting-for-the-users-go-ahead) GEThttp\://localhost:3000/api/subscriptions/pending Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/subscriptions/api.rs:859), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** Matched works waiting for the user’s go-ahead. Only reachable because `auto_download` defaults off — without this, that default would leave candidates recorded but unanswerable. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:31 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Approving is the moment unattended matching becomes attended spending — nothing before this point [Section titled “Approving is the moment unattended matching becomes attended spending — nothing before this point”](#approving-is-the-moment-unattended-matching-becomes-attended-spending--nothing-before-this-point) POSThttp\://localhost:3000/api/subscriptions/pending/approve Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/subscriptions/api.rs:892), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** Approving is the moment unattended matching becomes attended spending — nothing before this point consumes download credit. Partial success is reported rather than rolled back: with several items, one that fails to queue is no reason to un-approve the rest, and the caller is told exactly which ones did not make it. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:32 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Dismissing marks each work seen, so later checks do not raise the same question again [Section titled “Dismissing marks each work seen, so later checks do not raise the same question again”](#dismissing-marks-each-work-seen-so-later-checks-do-not-raise-the-same-question-again) POSThttp\://localhost:3000/api/subscriptions/pending/dismiss Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/subscriptions/api.rs:980), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** Dismissing marks each work seen, so later checks do not raise the same question again. This is the user answering “no” — distinct from a reservation, which is the system reporting it *could* not download something. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:33 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Previews a subscription that does not exist yet [Section titled “Previews a subscription that does not exist yet”](#previews-a-subscription-that-does-not-exist-yet) POSThttp\://localhost:3000/api/subscriptions/preview Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/subscriptions/api.rs:744), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** Previews a subscription that does not exist yet. The id-bearing route cannot serve this: there is no record to read. Yet a subscription being created is exactly when “what would this actually catch” matters most — afterwards the user has already committed to the rule. The draft is evaluated against the source as it is now, and nothing is stored either way. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:36 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Re-judges a listing already fetched, against possibly-different conditions [Section titled “Re-judges a listing already fetched, against possibly-different conditions”](#re-judges-a-listing-already-fetched-against-possibly-different-conditions) POSThttp\://localhost:3000/api/subscriptions/preview/judge Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/subscriptions/api.rs:684), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** Re-judges a listing already fetched, against possibly-different conditions. Changing a condition changes nothing about what the source would return — only `criteria` shapes the request — so re-fetching would be wasted, slow, and one more hit on a source that rate-limits. The judgment still happens here rather than in the browser, because a second implementation of the condition tree would eventually disagree with the real one. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:37 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Which sources can back a subscription, with their interval bounds — so the UI can offer only [Section titled “Which sources can back a subscription, with their interval bounds — so the UI can offer only”](#which-sources-can-back-a-subscription-with-their-interval-bounds--so-the-ui-can-offer-only) GEThttp\://localhost:3000/api/subscriptions/sources Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/subscriptions/api.rs:186), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** Which sources can back a subscription, with their interval bounds — so the UI can offer only viable sources and show the bounds *before* the user submits, rather than teaching them the rules through a rejection. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:28 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Which subscriptions have already handled a given work, by its source URL [Section titled “Which subscriptions have already handled a given work, by its source URL”](#which-subscriptions-have-already-handled-a-given-work-by-its-source-url) GEThttp\://localhost:3000/api/subscriptions/tracking Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/subscriptions/api.rs:555), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** Which subscriptions have already handled a given work, by its source URL. Asked before deleting an archive, so the delete flow only offers “stop this coming back” for an archive a subscription actually brought in — offering it for a hand-uploaded file would be an option with no effect, which is worse than no option at all. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/subscriptions/api.rs:51 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # Tankoubon Grouping > 8 endpoints. 8 endpoints. ## ai_group_suggestions [Section titled “ai_group_suggestions”](#ai_group_suggestions) POSThttp\://localhost:3000/api/tankoubons/ai-group-suggestions Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `ai_group_suggestions` in crates/lanrurugi-api/src/tankoubon_grouping.rs:775. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/tankoubon_grouping.rs:97 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `DELETE /tankoubons/ai-group-suggestions/ignore` — re-enables a previously-ignored suggestion [Section titled “DELETE /tankoubons/ai-group-suggestions/ignore — re-enables a previously-ignored suggestion”](#delete-tankoubonsai-group-suggestionsignore--re-enables-a-previously-ignored-suggestion) DELETEhttp\://localhost:3000/api/tankoubons/ai-group-suggestions/ignore Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/tankoubon_grouping.rs:1259), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `DELETE /tankoubons/ai-group-suggestions/ignore` — re-enables a previously-ignored suggestion (the frontend’s “Show ignored combinations” checklist’s own “Un-ignore” button). Idempotent — un-ignoring a combination that isn’t currently ignored is a no-op, not an error. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/tankoubon_grouping.rs:101 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `POST /tankoubons/ai-group-suggestions/ignore` — “Don’t suggest this again” for one specific [Section titled “POST /tankoubons/ai-group-suggestions/ignore — “Don’t suggest this again” for one specific”](#post-tankoubonsai-group-suggestionsignore--dont-suggest-this-again-for-one-specific) POSThttp\://localhost:3000/api/tankoubons/ai-group-suggestions/ignore Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/tankoubon_grouping.rs:1216), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `POST /tankoubons/ai-group-suggestions/ignore` — “Don’t suggest this again” for one specific suggestion. Idempotent (ignoring an already-ignored combination just overwrites its `ignored_at` timestamp, per `IgnoredGroupSuggestionsRepository::ignore`’s own contract). #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/tankoubon_grouping.rs:101 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `GET /tankoubons/ai-group-suggestions/ignored` — backs the “Show ignored combinations” [Section titled “GET /tankoubons/ai-group-suggestions/ignored — backs the “Show ignored combinations””](#get-tankoubonsai-group-suggestionsignored--backs-the-show-ignored-combinations) GEThttp\://localhost:3000/api/tankoubons/ai-group-suggestions/ignored Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/tankoubon_grouping.rs:1281), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `GET /tankoubons/ai-group-suggestions/ignored` — backs the “Show ignored combinations” checklist itself (titles are resolved client-side against the already-loaded archive list, the same `titleById` map `AiSmartTankoubonModal.tsx` already builds for the main suggestion cards — this endpoint only needs to return the raw ignored entries, not hydrate them server-side). #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/tankoubon_grouping.rs:105 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `DELETE /tankoubons/ai-group-suggestions/labels` (FR-017) [Section titled “DELETE /tankoubons/ai-group-suggestions/labels (FR-017)”](#delete-tankoubonsai-group-suggestionslabels-fr-017) DELETEhttp\://localhost:3000/api/tankoubons/ai-group-suggestions/labels Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/tankoubon_grouping/labels.rs:197), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `DELETE /tankoubons/ai-group-suggestions/labels` (FR-017). #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/tankoubon_grouping.rs:113 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `GET /tankoubons/ai-group-suggestions/labels` [Section titled “GET /tankoubons/ai-group-suggestions/labels”](#get-tankoubonsai-group-suggestionslabels) GEThttp\://localhost:3000/api/tankoubons/ai-group-suggestions/labels Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/tankoubon_grouping/labels.rs:185), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `GET /tankoubons/ai-group-suggestions/labels`. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/tankoubon_grouping.rs:113 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `POST /tankoubons/ai-group-suggestions/labels` [Section titled “POST /tankoubons/ai-group-suggestions/labels”](#post-tankoubonsai-group-suggestionslabels) POSThttp\://localhost:3000/api/tankoubons/ai-group-suggestions/labels Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/tankoubon_grouping/labels.rs:128), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `POST /tankoubons/ai-group-suggestions/labels`. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/tankoubon_grouping.rs:113 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## `POST /tankoubons/ai-group-suggestions/review` — never an HTTP error for a review failure: the [Section titled “POST /tankoubons/ai-group-suggestions/review — never an HTTP error for a review failure: the”](#post-tankoubonsai-group-suggestionsreview--never-an-http-error-for-a-review-failure-the) POSThttp\://localhost:3000/api/tankoubons/ai-group-suggestions/review Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/tankoubon_grouping/review\.rs:489), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** `POST /tankoubons/ai-group-suggestions/review` — never an HTTP error for a review failure: the card always renders, with the local result when the review could not be had. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/tankoubon_grouping.rs:109 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # Tankoubon API > 13 endpoints. 13 endpoints. ## Get all Tankoubons [Section titled “Get all Tankoubons”](#get-all-tankoubons) GEThttp\://localhost:3000/api/tankoubons Get list of Tankoubons paginated. #### 查询参数 * pageinteger可选 Tankoubon 列表的页码。 每页数量取决于服务端的 `archives_per_page` 设置。 #### 响应 200Tankoubon 列表 ``` { "filtered": 0, "result": [ { "archives": [ "e69e43e1355267f7d32a4f9b7f2fe108d2401ebf", "e69e43e1355267f7d32a4f9b7f2fe108d2401eba" ], "id": "TANK_1749925516", "name": "sailor moon", "progress": 0, "summary": "", "tags": "" } ], "total": 0 } ``` 服务器地址http\://localhost:3000API 令牌••••• pagequery 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Create a Tankoubon [Section titled “Create a Tankoubon”](#create-a-tankoubon) PUThttp\://localhost:3000/api/tankoubons Create a new Tankoubon or update the name of an existing one. #### 请求体 application/x-www-form-urlencoded, multipart/form-data #### 响应 200成功响应 ``` { "operation": "create_tankoubon", "success": 0, "tankoubon_id": "" } ``` 400错误响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Delete Tankoubon [Section titled “Delete Tankoubon”](#delete-tankoubon) DELETEhttp\://localhost:3000/api/tankoubons/{id} Remove a Tankoubon from the server. This doesn’t delete underlying Archives. #### 响应 200成功响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 400错误响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 423该 Tankoubon 当前被锁定,无法修改 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Get a single Tankoubon [Section titled “Get a single Tankoubon”](#get-a-single-tankoubon) GEThttp\://localhost:3000/api/tankoubons/{id} Get the details of the specified tankoubon ID. #### 响应 200Tankoubon ``` { "archives": [ "" ], "id": "", "name": "", "progress": 0, "summary": "", "tags": "" } ``` 400错误响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Update Tankoubon metadata/contents [Section titled “Update Tankoubon metadata/contents”](#update-tankoubon-metadatacontents) PUThttp\://localhost:3000/api/tankoubons/{id} Modify the full metadata (name, summary, additional tags) or the contents of a Tankoubon.\ If you only need to change the name of Tank, consider just using PUT `/api/tankoubons`. Note: If there is no need to update something in one of the `data` keys, do not send the key – This otherwise can result in unwanted results. #### 路径参数 * idstring · min: 15 · max: 15 · pattern必填 要更新的 Tankoubon ID。 #### 请求体 application/json #### 响应 200成功响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 400错误响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 423该 Tankoubon 当前被锁定,无法修改 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpath 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Remove an Archive from a Tankoubon [Section titled “Remove an Archive from a Tankoubon”](#remove-an-archive-from-a-tankoubon) DELETEhttp\://localhost:3000/api/tankoubons/{id}/{archive} #### 路径参数 * idstring · min: 15 · max: 15 · pattern必填 要更新的 Tankoubon ID。 * archivestring · min: 40 · max: 40 · pattern必填 要移除的档案 ID。 #### 响应 200结果 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 400错误响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 423该 Tankoubon 当前被锁定,无法修改 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpatharchivepath 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Add an Archive to a Tankoubon [Section titled “Add an Archive to a Tankoubon”](#add-an-archive-to-a-tankoubon) PUThttp\://localhost:3000/api/tankoubons/{id}/{archive} Append an archive at the final position of a Tankoubon. #### 路径参数 * idstring · min: 15 · max: 15 · pattern必填 要更新的 Tankoubon ID。 * archivestring · min: 40 · max: 40 · pattern必填 要追加的档案 ID。 #### 响应 200成功响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 400错误响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 423该 Tankoubon 当前被锁定,无法修改 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• idpatharchivepath 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## ai_rename_chapter [Section titled “ai_rename_chapter”](#ai_rename_chapter) POSThttp\://localhost:3000/api/tankoubons/{id}/ai/rename-chapter Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `ai_rename_chapter` in crates/lanrurugi-api/src/tankoubons.rs:1714. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/tankoubons.rs:106 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## POST /api/tankoubons/{id}/ai/rename-suggestions [Section titled “POST /api/tankoubons/{id}/ai/rename-suggestions”](#post-apitankoubonsidairename-suggestions) POSThttp\://localhost:3000/api/tankoubons/{id}/ai/rename-suggestions Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/tankoubons.rs:1588), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** POST /api/tankoubons/{id}/ai/rename-suggestions Sends the tankoubon title, member archive names, and order to DeepSeek and returns AI-generated rename suggestions (tankoubon name + per-archive chapter names). The LLM key must be configured; returns 400 if not. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/tankoubons.rs:102 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Get a single Tankoubon with full detail [Section titled “Get a single Tankoubon with full detail”](#get-a-single-tankoubon-with-full-detail) GEThttp\://localhost:3000/api/tankoubons/{id}/full Get the details of the specified tankoubon ID with paginated archive metadata. The amount of archives per page depends on the server `archives_per_page` setting. #### 查询参数 * pageinteger · default: -1可选 档案列表的页码。默认 -1,返回全部档案。 #### 响应 200Tankoubon ``` { "filtered": 0, "result": { "archives": [ "" ], "full_data": [ null ], "id": "", "name": "", "progress": 0, "summary": "", "tags": "" }, "total": 0 } ``` 400错误响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• pagequery 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Update Tankoubon reading progression [Section titled “Update Tankoubon reading progression”](#update-tankoubon-reading-progression) PUThttp\://localhost:3000/api/tankoubons/{id}/progress/{page} Tell the server which page of this Tankoubon you’re currently reading, so that it updates its internal reading progression accordingly. The page number is global across all Archives in the tank (If a tank has two Archives with 20 and 25 pages, page 26 will be page 6 in Archive #2). ⚠ If the server is configured to use clientside progress tracking, this API call will return an error! Make sure to check using `/api/info` whether the server tracks reading progression or not before calling this endpoint. #### 路径参数 * idstring · min: 15 · max: 15 · pattern必填 要更新的 Tankoubon ID。 * pageinteger · min: 1必填 要更新到的全局页码,从 1 开始计数。必须是正整数。 #### 响应 200成功响应 ``` { "id": "TANK_1589141306", "lastreadtime": 123943543, "operation": "update_tank_progress", "page": 5, "success": 1 } ``` 400通用错误响应 ``` { "error": "Server-side Progress Tracking is disabled on this instance.", "operation": "update_tank_progress", "success": 0 } ``` 401开启 authprogress 时需要认证 ``` { "error": "This operation requires authentication.", "operation": "update_tank_progress", "success": 0 } ``` 服务器地址http\://localhost:3000API 令牌••••• idpathpagepath 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Get Tankoubon thumbnail [Section titled “Get Tankoubon thumbnail”](#get-tankoubon-thumbnail) GEThttp\://localhost:3000/api/tankoubons/{id}/thumbnail Get the cover thumbnail for a given Tankoubon. By default, the thumbnail is sourced from the first page of the first archive. This endpoint will return a placeholder image if it doesn’t already exist. If you want to queue generation of the thumbnail in the background, you can use the no_fallback query parameter. #### 查询参数 * no_fallbackstring · enum: true | false可选 关闭占位图,把缩略图排入提取队列,并返回 code 202 的 JSON。图片已存在时该参数不起作用。(无论哪种情况,只要图片已存在就会以 code 200 返回它) #### 响应 200如果缩略图已经提取过,会直接返回它。 该响应没有示例数据。 202缩略图已排入提取队列。用 \`/api/minion/:jobid\` 跟踪它何时就绪。 ``` { "job": 0, "operation": "", "success": 1 } ``` 400错误响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• no_fallbackquerytrue 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Update Tankoubon thumbnail [Section titled “Update Tankoubon thumbnail”](#update-tankoubon-thumbnail) PUThttp\://localhost:3000/api/tankoubons/{id}/thumbnail Set the cover thumbnail for the given Tankoubon using a global page number that spans all archives in the tank (in order). The global page is translated to the correct archive and local page automatically. #### 查询参数 * pageinteger · min: 1必填 跨整个 Tankoubon 内所有档案的全局页码,从 1 开始计数。第 1 页就是第一个档案的第一页,依此类推。 #### 响应 200Tankoubon 缩略图已更新 ``` { "new_thumbnail": "", "operation": "update_tankoubon_thumbnail", "success": 0 } ``` 400错误响应 ``` { "error": "", "operation": "", "success": 0, "successMessage": "" } ``` 服务器地址http\://localhost:3000API 令牌••••• pagequery 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # Terminology Glossary > 3 endpoints. 3 endpoints. ## get_glossary [Section titled “get_glossary”](#get_glossary) GEThttp\://localhost:3000/api/volumes/{id}/terminology-glossary Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `get_glossary` in crates/lanrurugi-api/src/terminology_glossary.rs:38. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/terminology_glossary.rs:27 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## delete_entry [Section titled “delete_entry”](#delete_entry) DELETEhttp\://localhost:3000/api/volumes/{id}/terminology-glossary/{term} Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `delete_entry` in crates/lanrurugi-api/src/terminology_glossary.rs:139. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/terminology_glossary.rs:28 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Edits a single entry [Section titled “Edits a single entry”](#edits-a-single-entry) PUThttp\://localhost:3000/api/volumes/{id}/terminology-glossary/{term} Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/terminology_glossary.rs:59), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** Edits a single entry. Takes effect on the next translation request (FR-007d). #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/terminology_glossary.rs:28 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # Page Translation > 6 endpoints. 6 endpoints. ## Detection output plus everything the browser needs to translate and composite locally [Section titled “Detection output plus everything the browser needs to translate and composite locally”](#detection-output-plus-everything-the-browser-needs-to-translate-and-composite-locally) GEThttp\://localhost:3000/api/archives/{id}/page/{page}/text-regions Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/translation.rs:406), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** Detection output plus everything the browser needs to translate and composite locally. Includes the same `context` the cloud path assembles, so a locally-hosted backend gets FR-007a–e’s consistency benefit even though its translation call never touches this server. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/translation.rs:45 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Reader’s “重新翻译”: drops this page’s detection cache, every translated record and the [Section titled “Reader’s “重新翻译”: drops this page’s detection cache, every translated record and the”](#readers-重新翻译-drops-this-pages-detection-cache-every-translated-record-and-the) DELETEhttp\://localhost:3000/api/archives/{id}/page/{page}/translation Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/translation.rs:203), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** Reader’s “重新翻译”: drops this page’s detection cache, every translated record and the rendered image, so the next `GET .../translation` re-runs the whole OCR -> translate -> composite pipeline instead of reusing a stale cache (e.g. one produced by an old pipeline version, or a partially-detected region set). #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/translation.rs:41 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Serves the composited, translated page for the cloud-backend path (T028) [Section titled “Serves the composited, translated page for the cloud-backend path (T028)”](#serves-the-composited-translated-page-for-the-cloud-backend-path-t028) GEThttp\://localhost:3000/api/archives/{id}/page/{page}/translation Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/translation.rs:275), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** Serves the composited, translated page for the cloud-backend path (T028). Returns the cached rendering when one exists. On a miss it **triggers** the real orchestration — OCR → font routing → batched translation → compositing → cache write (`translation_pipeline::translate_page`) — for this page and its look-ahead window, then reports not-ready immediately. The work is deliberately not awaited here: a full OCR + LLM cycle takes tens of seconds, and FR-012 requires the reader to keep showing the original page with a non-blocking indicator meanwhile. The client polls; a later poll finds the cache entry this triggered. Reading must never wait on translation (SC-007). #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/translation.rs:41 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Records a translation the browser obtained from its own local model (T049a) [Section titled “Records a translation the browser obtained from its own local model (T049a)”](#records-a-translation-the-browser-obtained-from-its-own-local-model-t049a) POSThttp\://localhost:3000/api/archives/{id}/page/{page}/translation/record Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/translation.rs:591), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** Records a translation the browser obtained from its own local model (T049a). **No LLM call happens here** — this is a lightweight write. Its purpose is that a name/term the local backend translated still reaches the shared, server-stored glossary, so later cloud-path (or other-device) requests for the same volume stay consistent with it. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/translation.rs:49 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Reports whether translation is on for this archive, and whether that’s this archive’s own [Section titled “Reports whether translation is on for this archive, and whether that’s this archive’s own”](#reports-whether-translation-is-on-for-this-archive-and-whether-thats-this-archives-own) GEThttp\://localhost:3000/api/archives/{id}/translation/scope Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/translation.rs:118), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** Reports whether translation is on for this archive, and whether that’s this archive’s own setting or inherited from a Tankoubon it belongs to — the latter so the reader can tell the user “this follows the whole book’s setting” rather than presenting it as if toggling here only ever affects this one file. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/translation.rs:53 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Sets the switch for whichever scope actually governs this archive right now (its Tankoubon if [Section titled “Sets the switch for whichever scope actually governs this archive right now (its Tankoubon if”](#sets-the-switch-for-whichever-scope-actually-governs-this-archive-right-now-its-tankoubon-if) PUThttp\://localhost:3000/api/archives/{id}/translation/scope Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/translation.rs:144), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** Sets the switch for whichever scope actually governs this archive right now (its Tankoubon if it has one, else the archive itself) — see `TranslationScopeRepository::set_enabled`’s own docs for why toggling here only ever targets one or the other, never both. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/translation.rs:53 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # Translation Settings > 4 endpoints. 4 endpoints. ## update_budget [Section titled “update_budget”](#update_budget) PUThttp\://localhost:3000/api/translation/budget Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `update_budget` in crates/lanrurugi-api/src/translation_settings.rs:335. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/translation_settings.rs:40 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## get_translation_settings [Section titled “get_translation_settings”](#get_translation_settings) GEThttp\://localhost:3000/api/translation/settings Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `get_translation_settings` in crates/lanrurugi-api/src/translation_settings.rs:118. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/translation_settings.rs:35 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## update_translation_settings [Section titled “update_translation_settings”](#update_translation_settings) PUThttp\://localhost:3000/api/translation/settings Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `update_translation_settings` in crates/lanrurugi-api/src/translation_settings.rs:172. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/translation_settings.rs:35 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 该端点需要**管理员**令牌:访客(只读)令牌会被服务端拒绝。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 ## Current consumption at the four granularities FR-014 requires [Section titled “Current consumption at the four granularities FR-014 requires”](#current-consumption-at-the-four-granularities-fr-014-requires) GEThttp\://localhost:3000/api/translation/usage Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The note below is the handler’s own documentation comment (crates/lanrurugi-api/src/translation_settings.rs:277), quoted verbatim. It is written for maintainers of this codebase and may reference internal identifiers. *** Current consumption at the four granularities FR-014 requires. Returns a zeroed result rather than an error when no metered backend is configured — a locally-hosted backend simply has no usage to report. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/translation_settings.rs:39 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000API 令牌••••• 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # Version > 1 endpoint. 1 endpoint. ## get_version [Section titled “get_version”](#get_version) GEThttp\://localhost:3000/api/version Not yet described in this reference. This endpoint is listed because the server registers it, but its request and response shapes have not been written down yet. The handler is `get_version` in crates/lanrurugi-api/src/version.rs:528. #### 响应 200该端点已响应;其确切结构尚未记录,见 crates/lanrurugi-api/src/version.rs:144 处的 handler。 该响应没有示例数据。 服务器地址http\://localhost:3000 该端点不需要认证。 发送复制为 cURL **请求失败** — 常见原因:实例地址填错或不可达;实例未开启「为客户端 API 启用 CORS」;或者文档站是 HTTPS 而实例是局域网内的纯 HTTP(浏览器按混合内容拦截)。可以用上面的「复制为 cURL」在终端里发同样的请求。 ``` ``` 填写你自己的实例地址,请求由浏览器直接发往该地址。 # Testing the API from these docs > Send requests from your browser straight to your own running LANrurugi instance — preconditions, security boundaries, and what to do when it does not work. Every endpoint in the [API reference](../../api/) has a request panel: enter a server address, enter a token, press send. This page explains exactly where that request goes, what it requires, and how to continue when the browser blocks it. ## Where the request goes [Section titled “Where the request goes”](#where-the-request-goes) **From your browser, straight to the address you type into the panel.** * The address and token you enter below live only in your browser’s local storage, and are sent only to that address. * This project has **no** intermediate server and **no** proxy. There is no path by which a user’s token or internal address reaches this project’s infrastructure. * The one exception is the page itself: the API description document (`openapi.json`) and the JavaScript that renders it are served from this documentation site’s own origin, not a CDN. This feature therefore needs no “public demo instance” — it was always aimed at your own instance. ## Preconditions [Section titled “Preconditions”](#preconditions) ### 1. Your instance must be reachable from this browser [Section titled “1. Your instance must be reachable from this browser”](#1-your-instance-must-be-reachable-from-this-browser) The address you enter must be reachable from **this browser**. If you are running the docs site on one machine and the instance on another, then `localhost` means the machine the browser is running on, not the machine the instance is running on. ### 2. Enable cross-origin access on the instance [Section titled “2. Enable cross-origin access on the instance”](#2-enable-cross-origin-access-on-the-instance) **“Enable CORS for the client API”** in the settings page must be on. It is off by default, and the browser will refuse cross-origin requests while it is. Once enabled, the instance permits the headers a browser needs to preflight — including the `Content-Type` that any JSON-bodied request requires. If your instance is on an older version and calls with a body always fail, that is usually this setting not covering it. ### 3. An HTTPS page can only call HTTPS instances and `http://localhost` [Section titled “3. An HTTPS page can only call HTTPS instances and http://localhost”](#3-an-https-page-can-only-call-https-instances-and-httplocalhost) This rule is enforced by the browser, not by LANrurugi: | Docs site | Instance address you enter | Result | | ----------- | -------------------------- | -------------------------------------------------------- | | `https://…` | `https://lrr.example.com` | ✅ works | | `https://…` | `http://localhost:3000` | ✅ works (browsers treat `localhost` as a trusted origin) | | `https://…` | `http://192.168.1.10:3000` | ❌ blocked as mixed content | | `http://…` | anything | ✅ works (the site itself is HTTP) | A LAN IP does **not** get `localhost`’s exemption. To test a LAN instance from an HTTPS docs site, there are two routes: * **Give the instance HTTPS**: a reverse proxy (Caddy / Traefik / nginx), a Cloudflare Tunnel, or a certificate-bearing entry point inside a VPN. * **Forward the port to localhost**: ```sh ssh -L 3000:127.0.0.1:3000 ``` then enter `http://localhost:3000` in the panel. The browser treats it as a trusted origin and it works directly. ## When the browser will not allow it: use the command line [Section titled “When the browser will not allow it: use the command line”](#when-the-browser-will-not-allow-it-use-the-command-line) **Every endpoint has a copyable command line (cURL)** in its code-sample panel. It is generated from the endpoint itself and depends on neither the browser, CORS, nor HTTPS, so it always works — reach for it whenever sending from the panel fails. ```sh curl -H "Authorization: Bearer " \ "http://192.168.1.10:3000/api/archives?start=0&count=10" ``` ## Reading a panel error [Section titled “Reading a panel error”](#reading-a-panel-error) * **Network error / failed to fetch**: check the three preconditions above first. Most often it is CORS not being enabled, a wrong address, or the mixed-content combination. * **401**: the token is wrong, or it has no permission for this endpoint. * **403**: the token is a guest token and this endpoint is administrator-only. * **404**: the path or the archive ID is wrong. ## Tokens [Section titled “Tokens”](#tokens) Create one under token management in the settings page. The token field in the panel only puts it into an `Authorization: Bearer ` header, stores it in your browser’s local storage, and sends it only to the address you entered. Do not enter a token on somebody else’s documentation site The premise of this page is that the documentation site is a static page. But “static page” is not the same as “trusted page” — only enter a token on a deployment you trust. If you are unsure whether a docs site is an official deployment, use cURL instead. # Supported formats > The archive and e-book formats the library accepts, how each is displayed, and where its table of contents comes from. Every file in the library is an “archive” that you read page by page in the same reader. Besides archives of images, e-books such as PDF and EPUB can be dropped into the library directory or added from the upload page as they are, with no conversion step. ## Archives [Section titled “Archives”](#archives) | Format | Extensions | | -------------------- | -------------------------------------------------------------------------------------------- | | ZIP | `.zip` `.cbz` | | RAR (including RAR5) | `.rar` `.cbr` | | 7-Zip | `.7z` `.cb7` | | TAR | `.tar` `.cbt`, and tar compressed with gzip / bzip2 / xz / lzma (`.gz` `.bz2` `.xz` `.lzma`) | | LZH | `.lzh` `.lha` | Images that can be pages inside an archive: PNG, JPEG (`.jpg` `.jpeg` `.jfif`), GIF, BMP, WebP, AVIF, JPEG XL and HEIF/HEIC. Formats the browser cannot display (such as AVIF, JPEG XL or animated images on some browsers) are converted by the server first; HEIF/HEIC cannot be converted yet and only shows in browsers that support it natively (such as Safari). zstd-compressed files (`.zst`) are not supported yet and are not picked up. ## E-books [Section titled “E-books”](#e-books) | Format | Extensions | How pages are shown | Where the table of contents comes from | | ------------------- | ----------------------------- | ----------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | | PDF | `.pdf` | Scanned pages are the picture stored in the PDF; text and vector pages are rendered | PDF bookmarks | | EPUB (fixed layout) | `.epub` | Each page is the picture stored in the book | The book’s own contents (nav / NCX) | | EPUB (reflowable) | `.epub` | Typeset into pages on the server, illustrations in place | The book’s own contents, down to where each chapter starts | | MOBI / AZW / AZW3 | `.mobi` `.azw` `.azw3` `.prc` | Comics: the stored picture per page; text books: typeset on the server | The book’s contents page or chapter headings | | DjVu | `.djvu` `.djv` | Rendered | DjVu bookmarks | | FB2 | `.fb2` | Typeset on the server, illustrations in place | The book’s sections | | Plain text | `.txt` | Typeset on the server | Chapter lines detected automatically (“Chapter 3”, “Prologue”, 第一章, 第十二回, …) | Notes: * **Pictures are never re-compressed.** Where a page is a picture stored in the book (scanned PDFs, fixed-layout EPUB, comic MOBI/AZW3, FB2 illustrations), the reader gets that exact picture. * **Text books are typeset by the server**, with a Simplified Chinese, Japanese or Korean font chosen by the book’s language; headings, paragraphs and illustrations all land on the page. Only horizontal text is supported for now. * **The table of contents is imported once, on first import**, and only into an archive that has no chapters yet, so chapters you edited are never overwritten. When the book’s own contents are missing or have just one or two entries (a cover or a licence page, say), they are completed from the headings and chapter lines in the text. * **Only `.txt` files of 8 KB or more are picked up**, so readme files and notes next to your archives are not mistaken for books. The encoding is detected automatically (UTF-8, UTF-16, GBK/GB18030, Big5, Shift_JIS, EUC-JP, EUC-KR and others), and text hard-wrapped at a fixed width is joined back into paragraphs. * **The library marks the format.** E-books show a small `PDF`, `EPUB`, … label beside their title, and a PDF can also be opened as-is in the browser from the reader. * Split suggestions only make sense for archives and are not offered for e-books. * Rendered pages of text books and text PDF pages are cached, and count towards the same “Settings → Archive Files → Maximum Reader Cache Size” limit as the reader’s other caches. ## What is not supported [Section titled “What is not supported”](#what-is-not-supported) * **DRM- or password-protected books** (for example store-bought Kindle books whose protection was not removed, or a PDF with an open password) cannot be read. They still appear in the library (with 0 pages); opening one shows why it cannot be read (protected by DRM or a password), and the server log records it too. * **Damaged or incomplete files** likewise report the reason and do not affect the rest of the library. * Kindle’s KFX format and HUFF/CDIC-compressed MOBI files (mostly Kindle dictionaries) are not supported yet. # Install (Docker / NAS) > Deploy LANrurugi on a server or NAS with Docker or Compose. The LANrurugi server is one resident process holding the static frontend, the HTTP API, the file watcher and background jobs; plugins, e-book parsing and AI inference run in subprocesses started on demand. It has its own database and neither reads nor changes LANraragi’s, so the two can run side by side. Moving from LANraragi 1. In LANraragi, go to Settings → Database Backup/Restore → Backup Database and save the JSON. LANraragi can keep running. 2. Start LANrurugi with the same manga directory as its library. Thumbnails and the database need mounts too, but in new directories, not LANraragi’s. The converter on the [homepage](https://lrrg.dev/en/#start) generates this from LANraragi’s deployment command or compose file. 3. Sign in with the default password `kamimamita`; the first-run wizard asks you to change it. 4. Upload the JSON in the wizard’s “Import from a LANraragi backup” step (or later under Settings → Database Backup/Restore). Tags, categories, tankoubons and stamps come back; reading progress is not part of the backup. Prefer not to use containers? There are [native packages](../install-native/) for Linux, macOS (Apple Silicon) and FreeBSD. ## Deploy with Compose (recommended) [Section titled “Deploy with Compose (recommended)”](#deploy-with-compose-recommended) Save the following as `compose.yaml`, change the host directories on the left as the comments describe, then start it: ```yaml services: lanrurugi: image: ghcr.io/thelastfantasy/lanrurugi:latest container_name: lanrurugi ports: - "3000:3000" volumes: # Library — can point straight at LANraragi's content directory - ./data/manga:/home/koyomi/lanrurugi/content # Thumbnail cache - ./data/thumb:/home/koyomi/lanrurugi/thumb # Redis data, LANrurugi only; LANraragi's metadata is imported from its backup JSON - ./data/database:/home/koyomi/lanrurugi/database # Embedding model for recommendations, downloaded on first use - ./data/models:/home/koyomi/lanrurugi/models environment: # Set to true when served over HTTPS through a reverse proxy - LANRURUGI_FORCE_SECURE_COOKIES=false restart: unless-stopped ``` ```sh docker compose up -d # or: podman compose up -d ``` On a NAS (Synology Container Manager, Portainer and the like), create a compose project and paste the same text. Then open `http://:3000` in a browser. Redis is bundled in the image; no separate database container is needed. The four mounted directories: | Host path | Path in the container | Purpose | | ----------------- | --------------------------------- | ----------------------------------------- | | `./data/manga` | `/home/koyomi/lanrurugi/content` | Your library | | `./data/thumb` | `/home/koyomi/lanrurugi/thumb` | Thumbnail cache | | `./data/database` | `/home/koyomi/lanrurugi/database` | Redis data (LANrurugi only) | | `./data/models` | `/home/koyomi/lanrurugi/models` | Embedding model cache for recommendations | To serve it on a domain over HTTPS, see [Reverse proxy](../reverse-proxy/). ## Run it with plain Docker [Section titled “Run it with plain Docker”](#run-it-with-plain-docker) ```sh docker run -d --name lanrurugi -p 3000:3000 \ -v /path/to/library:/home/koyomi/lanrurugi/content \ -v /path/to/thumb:/home/koyomi/lanrurugi/thumb \ -v /path/to/database:/home/koyomi/lanrurugi/database \ ghcr.io/thelastfantasy/lanrurugi:latest ``` ## Where the image is published [Section titled “Where the image is published”](#where-the-image-is-published) The same image, for amd64 and arm64, is published to two registries: | Registry | Image | | --------------------------------------- | ---------------------------------- | | GitHub Container Registry (recommended) | `ghcr.io/thelastfantasy/lanrurugi` | | Docker Hub | `jade913/lanrurugi` | The examples above use GitHub’s registry. Docker Hub limits how often anonymous users can pull; if your NAS panel only searches Docker Hub, or you simply prefer it, use `jade913/lanrurugi` instead. `latest` points at the newest release; a specific version number works too. ## Build the image from source [Section titled “Build the image from source”](#build-the-image-from-source) The repository’s own `compose.yaml` builds from source for a trial run (`network_mode: host`, listening on port 3000): ```sh podman compose up -d --build # or: docker compose up -d --build ``` ## First login [Section titled “First login”](#first-login) The first visit opens the first-run wizard: change the admin password, add a DeepSeek API key for the AI features, and import a LANraragi backup. Every step can be skipped, and the wizard can be rerun from Settings later. A brand-new instance — or one migrated from an old installation whose password was never changed — uses LANraragi’s own default administrator password, **`kamimamita`**. Change the password first thing Change it in the settings page immediately after logging in. Do not leave an instance reachable from outside your local network while it still uses the default password. ## Reading this documentation offline [Section titled “Reading this documentation offline”](#reading-this-documentation-offline) The documentation site, the API reference, the Swagger UI and the plugin SDK reference are all baked into the image and served by the instance itself under `/docs`: ```text http://:3000/docs/ guides and the per-group API reference (Chinese) http://:3000/docs/en/ the same, in English http://:3000/docs/swagger/ Swagger UI, Chinese content (schemas; send requests) http://:3000/docs/swagger/en/ Swagger UI, English content http://:3000/docs/sdk/ plugin SDK reference ``` No internet access is required: even Swagger UI’s JavaScript bundle and the SDK’s search index ship inside the image — nothing is loaded from a CDN. ## Toolchain (building from source) [Section titled “Toolchain (building from source)”](#toolchain-building-from-source) Versions are pinned in `.mise.toml`, and `mise install` reproduces them exactly (Rust, Node, Deno, pnpm, plus `sccache`/`mold`). ```sh # Backend cargo build --release -p lanrurugi-server ./target/release/lanrurugi-server serve --redis-url redis://127.0.0.1:6379 \ --library-path /path/to/existing/library # Frontend dev server (proxies /api to the backend above) pnpm --filter lanrurugi-frontend run dev ``` ### CLI subcommands [Section titled “CLI subcommands”](#cli-subcommands) * `lanrurugi serve` — runs the HTTP API, static frontend, file watcher and plugin pool in one process. * `lanrurugi rebuild-index` — recomputes every archive’s ID with the size-aware algorithm and surfaces files that were historically hidden by a mistaken merge. * `lanrurugi bench` — generates a synthetic library and runs a concurrency/throughput comparison against a running legacy instance. ## Next [Section titled “Next”](#next) * [Quickstart](../quickstart/) * [Testing the API from these docs](../api-testing/) # Native install (Linux / macOS / FreeBSD) > Run LANrurugi directly on Linux, an Apple Silicon Mac or FreeBSD, without containers. Besides the [Docker image](../install/), every release ships native packages for: | Package | Systems | | ------------------------------------------- | ----------------------------------------------------------------------------------- | | `lanrurugi--linux-x86_64.tar.gz` | 64-bit Linux with glibc 2.35 or newer (Debian 12, Ubuntu 22.04, Fedora 36, Arch, …) | | `lanrurugi--linux-aarch64.tar.gz` | ARM64 Linux, same baseline (e.g. Raspberry Pi 5, ARM servers) | | `lanrurugi--macos-arm64.tar.gz` | Apple Silicon Macs, macOS 13 or newer | | `lanrurugi--freebsd-x86_64.tar.gz` | FreeBSD 14 | Download them from the GitHub [Releases](https://github.com/thelastfantasy/LANrurugi/releases) page; `SHA256SUMS` lists every file’s checksum. Docker remains the least work if you would rather not manage dependencies; on Windows, use Docker Desktop. ## 1. Install the prerequisites [Section titled “1. Install the prerequisites”](#1-install-the-prerequisites) The database server, plugin runtime, DjVu tools and fonts come from your system’s package manager and are not in the package: | | Debian / Ubuntu | Fedora | Arch | macOS (Homebrew) | FreeBSD | | --------------------------------- | ------------------------------------ | -------------------------------------------------------------------- | ---------------------------- | -------------------------- | ------------------------------------------------------------------- | | Redis 7.4 or newer | `apt install redis-server` ¹ | `dnf install redis` ² | `pacman -S redis` | `brew install redis` | `pkg install redis` | | Deno (plugins) | [install script](https://deno.com) | [install script](https://deno.com) | `pacman -S deno` | `brew install deno` | `pkg install deno` | | DjVu books | `apt install djvulibre-bin` | `dnf install djvulibre` | `pacman -S djvulibre` | `brew install djvulibre` | `pkg install djvulibre` | | CJK fonts (text books) | `apt install fonts-noto-cjk` | `dnf install google-noto-serif-cjk-fonts google-noto-sans-cjk-fonts` | `pacman -S noto-fonts-cjk` | built in | `pkg install noto-serif-sc noto-sans-sc noto-serif-jp noto-sans-jp` | | Colour emoji font (text books) | `apt install fonts-noto-color-emoji` | `dnf install google-noto-color-emoji-fonts` | `pacman -S noto-fonts-emoji` | built in | `pkg install noto-emoji` | | Archive codecs | built in | built in | built in | `brew install xz lz4 zstd` | `pkg install lz4 zstd` | | PDF books | bundled | bundled | bundled | bundled | `pkg install pdfium` | | OCR, translation, recommendations | bundled | bundled | bundled | bundled | `pkg install onnxruntime` | | CA certificates (HTTPS) | `apt install ca-certificates` ³ | built in | built in | built in | `pkg install ca_root_nss` | ¹ Debian 12 ships Redis 7.0, which is fine for a new library; reusing data from a Docker deployment needs 7.4 or newer (use the redis.io repository). ² Recent Fedora installs Valkey, a Redis-compatible server. It is fine for a new library but cannot open data files written by Redis 7.4. ³ Minimal systems (slim containers, VMs) may lack them. It still runs without: when no system certificates are found, HTTPS falls back to the Mozilla roots built into the binary, which the startup log reports as `tls_roots=bundled`. System certificates follow your OS’s updates and also trust any certificate you add yourself. ## 2. Unpack and start [Section titled “2. Unpack and start”](#2-unpack-and-start) ```sh tar -xzf lanrurugi--.tar.gz cd lanrurugi-- redis-server --daemonize yes # or enable your system's Redis service ./bin/lanrurugi-server serve \ --library-path ~/manga \ --thumb-dir ~/.local/share/lanrurugi/thumb \ --temp-dir ~/.local/share/lanrurugi/temp \ --log-dir ~/.local/share/lanrurugi/log ``` Then open `http://:3000`. The first-run wizard changes the default password, takes the API key for the AI features and can import a LANraragi backup. The web interface, plugins, documentation, bundled libraries and models are found relative to the program itself, so the package works wherever you unpack it. It connects to `redis://127.0.0.1:6379` by default; change that with `--redis-url` or `LANRURUGI_REDIS_URL`. ## 3. Translation models (optional) [Section titled “3. Translation models (optional)”](#3-translation-models-optional) ```sh ./fetch-models.sh # text recognition and removal, several hundred MB ./fetch-models.sh --with-bubbles # also builds the speech-bubble model (needs uv) ``` The library and reader work without them; without the bubble model, translation erases text with rectangles. ## 4. Run as a service [Section titled “4. Run as a service”](#4-run-as-a-service) ```sh sudo ./install-service.sh /var/lib/lanrurugi # Linux (systemd), FreeBSD (rc.d) ./install-service.sh ~/LANrurugi # macOS (launchd, current user) ``` The script creates the data directories and `lanrurugi.env` (library location, Redis URL, port), installs the service definition for your system and prints the command that starts it. Add `--print` to see the generated definition without installing it. ## Moving from a Docker deployment [Section titled “Moving from a Docker deployment”](#moving-from-a-docker-deployment) Reuse the container’s three mounted directories: `content` as the library and `thumb` as the thumbnail directory. Give the `database` directory to a Redis 7.4+ configured like `service/redis.conf.example` (its `dir` pointing there, port 16379), and set `LANRURUGI_REDIS_URL` to `redis://127.0.0.1:16379`. ## Features by platform [Section titled “Features by platform”](#features-by-platform) | Feature | Linux | macOS | FreeBSD | | ----------------------------------------- | -------------------------- | ------- | ---------------------------------------- | | Library, reader, search, archives | ✓ | ✓ | ✓ | | PDF / DjVu / EPUB / MOBI / FB2 / TXT | ✓ | ✓ | ✓ (PDF needs the `pdfium` package) | | Plugins, downloads, subscriptions | ✓ | ✓ | ✓ | | Recommendations, OCR, in-page translation | ✓ | ✓ (CPU) | ✓ (CPU; needs the `onnxruntime` package) | | GPU-accelerated inference | ✓ (as in the Docker image) | — | — | When an optional component is missing the server still starts; its start-up log prints `optional components` and `some features are unavailable on this system`, naming what is missing and which features it affects, and those features report the reason when used. ## Platforms not supported yet [Section titled “Platforms not supported yet”](#platforms-not-supported-yet) * **Windows**: use Docker Desktop. * **Intel Macs, other BSDs, musl distributions (e.g. Alpine)**: no packages; musl distributions can use the Docker image. * **HarmonyOS / OpenHarmony**: not supported. Apps there run in a sandbox with no supported way to keep a server running in the background, and none of Redis, Deno, PDFium or ONNX Runtime has a HarmonyOS build. The realistic route is a separate HarmonyOS reader app that connects to an existing LANrurugi server, rather than running the server on the device. # llms.txt for AI tools > What each llms.txt file on the homepage and the documentation site contains, and which one to give an AI assistant. [llms.txt](https://llmstxt.org/) is a convention: a Markdown file at a site’s root that tells AI tools what a project is and where to read more. LANrurugi’s homepage and this documentation site both publish them. Give an AI assistant the right address and it can answer questions, help you deploy, write scripts against the API or write plugins from the documentation, instead of guessing from whatever it saw in training. ## The files [Section titled “The files”](#the-files) | Address | Contents | Size (approx.) | | -------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | -------------- | | [`lrrg.dev/llms.txt`](https://lrrg.dev/llms.txt) | Entry point: what the project is, the HTTP API and the plugin SDK, and links to the main docs | 3.5 KB | | [`docs.lrrg.dev/llms.txt`](https://docs.lrrg.dev/llms.txt) | Index of this site: links to the files below, plus the API and SDK overview | 3 KB | | [`docs.lrrg.dev/llms-full.txt`](https://docs.lrrg.dev/llms-full.txt) | Every documentation page, in both languages, as one Markdown file | 800 KB | | [`docs.lrrg.dev/llms-small.txt`](https://docs.lrrg.dev/llms-small.txt) | Abridged: guides and plugin authoring only, without the API pages and asides | 80 KB | | [`…/_llms-txt/guides-english.txt`](https://docs.lrrg.dev/_llms-txt/guides-english.txt) | Guides and plugin authoring, English only | 40 KB | | [`…/_llms-txt/guides-simplified-chinese.txt`](https://docs.lrrg.dev/_llms-txt/guides-simplified-chinese.txt) | The same, Simplified Chinese | 40 KB | | [`…/_llms-txt/api-reference-english.txt`](https://docs.lrrg.dev/_llms-txt/api-reference-english.txt) | The API reference, English only, one section per group | 300 KB | | [`…/_llms-txt/api-reference-simplified-chinese.txt`](https://docs.lrrg.dev/_llms-txt/api-reference-simplified-chinese.txt) | The same, Simplified Chinese | 300 KB | Two structured files are linked from the llms.txt files as well: * [`docs.lrrg.dev/openapi.json`](https://docs.lrrg.dev/openapi.json): the complete HTTP API as OpenAPI 3.1. It is generated from the server’s own route registrations, so it lists exactly the endpoints the server serves. * [`sdk.lrrg.dev/plugin-sdk.json`](https://sdk.lrrg.dev/plugin-sdk.json): the plugin SDK reference as JSON, generated by `deno doc` from the TypeScript the plugin runtime loads. All of them are regenerated with every documentation release, from the same source as the pages, so they never drift apart. ## Which one to give an AI [Section titled “Which one to give an AI”](#which-one-to-give-an-ai) | You want the AI to | Give it | | ---------------------------------------------------- | --------------------------------------------------------------------------- | | Explain the project, answer general questions | `lrrg.dev/llms.txt` | | Help you deploy, debug an install or a reverse proxy | One language’s guides (`guides-*.txt`) or `llms-small.txt` | | Write a script or client for the API | `openapi.json`: more precise than the API pages’ Markdown, and fewer tokens | | Write a plugin | [Plugin authoring](../../plugin/getting-started/) plus `plugin-sdk.json` | | Have all the background, with a large enough context | `llms-full.txt` | If you only need a metadata, login or download plugin for one site, the instance’s own **AI Plugin Creation Wizard** fetches the target pages, writes the code and trial-runs it, which is usually less work than having an outside assistant start from nothing. ## How to hand it over [Section titled “How to hand it over”](#how-to-hand-it-over) * **AI tools that can browse** (chat assistants with web reading, coding agents): send the address, for example “Read `https://lrrg.dev/llms.txt` first, then …”. It follows the links inside for the parts it needs. * **Tools without web access**: download the files you need and attach or paste them. * **Coding agents working in a repository**: download `openapi.json` or `plugin-sdk.json` into the project, which is steadier than fetching it every time. # Quickstart > First login, creating an API token, scanning the library, importing existing data. ## 1. Log in [Section titled “1. Log in”](#1-log-in) Open `http://:3000`, log in with the default password `kamimamita`, then **change it in the settings page immediately**. ## 2. Point it at your library [Section titled “2. Point it at your library”](#2-point-it-at-your-library) `--library-path` (or `LANRURUGI_LIBRARY_PATH`) points at the directory holding your archives. It defaults to `./library`; under the Compose deployment that corresponds to the container’s `/home/koyomi/lanrurugi/content`. ## 3. Scan [Section titled “3. Scan”](#3-scan) Trigger a full scan from the settings page. Scanning is concurrent (Rayon) and does **not** delete archive records by itself — “a file disappeared during the scan” only cleans up path bookkeeping. Removing archive records is the separate, explicitly-triggered database cleanup. ## 4. Create an API token [Section titled “4. Create an API token”](#4-create-an-api-token) The request panels throughout the API reference need a token. Create one under token management in the settings page, then: ```sh curl -H "Authorization: Bearer " http://localhost:3000/api/archives ``` Tokens come in two roles, administrator and guest; a guest token can only read. ## 5. Migrating from LANraragi [Section titled “5. Migrating from LANraragi”](#5-migrating-from-lanraragi) LANrurugi has its own database and neither reads nor changes LANraragi’s, so the two can run side by side. The steps are under “Moving from LANraragi” on the [install](../install/) page: mount the same manga directory as the library, give thumbnails and the database new directories, then import LANraragi’s backup JSON in the first-run wizard. The import pairs archives in the backup with the ones LANrurugi scanned by file name, never by ID: LANrurugi’s IDs are a size-aware fingerprint (`hash(first 512KB ++ big-endian u64 file size)`), unlike LANraragi’s `SHA-1(first 512KB)`. When several files share a name nothing is guessed; they count as ambiguous. Let the library scan finish before importing — archives not scanned yet count as skipped with no match. Different files that LANraragi wrongly merged as duplicates because their leading bytes matched show up separately in LANrurugi. ## 6. Try the API [Section titled “6. Try the API”](#6-try-the-api) Open the [API reference](../../api/) and, in the request panel, set the server address to your own instance (it already defaults to `http://localhost:3000`), fill in a token, and send the request. Requests go from your browser straight to your instance, never through this project. When the browser will not allow it (for example, this documentation is served over HTTPS while your instance is plain HTTP on a LAN address), every endpoint also carries a command line you can copy. Details are in [Testing the API from these docs](../api-testing/). # Reverse proxy > Serve LANrurugi on a domain over HTTPS with Nginx, Caddy, Traefik, Apache or Nginx Proxy Manager. LANrurugi itself only speaks HTTP (by default on `0.0.0.0:3000`). To serve it on a domain over HTTPS, put a reverse proxy in front of it. Whichever proxy you use, it has to meet the conditions below. ## What the proxy has to do [Section titled “What the proxy has to do”](#what-the-proxy-has-to-do) * **Serve it at the root of a host.** The frontend requests the API at absolute `/api/...` paths, so mounting it under a sub-path (such as `example.com/lanrurugi/`) is not supported. Use a dedicated domain or subdomain such as `manga.example.com`. * **Forward three headers.** `X-Forwarded-Proto` (whether the request came in over HTTPS), `X-Forwarded-Host` (correct addresses for cross-domain login handoff and OpenSearch) and `X-Forwarded-For` (the real client IP in the activity log). Keep the original `Host` as well. * **Don’t buffer SSE.** Download-queue progress, the AI plugin wizard and archive-split suggestions stream over Server-Sent Events. If the proxy buffers the response, those screens stall and then update all at once when the request ends. The server sends a heartbeat every 15 seconds, so the usual 60-second read timeout is enough — but buffering has to be off. * **Allow large uploads.** Archive uploads are sent in chunks of up to 64 MB, and a legacy data import can be up to 100 MB in one request. The proxy’s body-size limit has to be at least that; the simplest choice is no limit. * **Turn on secure cookies once you’re on HTTPS.** Set `LANRURUGI_FORCE_SECURE_COOKIES=true` in the compose file. The server does not infer this from `X-Forwarded-Proto`: that header can be forged and this service has no trusted-proxy allowlist. Do **not** turn it on over plain HTTP — browsers would drop the login cookies and you could not sign in. WebSockets are not used. The examples assume LANrurugi and the proxy run on the same machine with LANrurugi on `127.0.0.1:3000`; if they share a compose network, use `lanrurugi:3000` instead. ## Nginx [Section titled “Nginx”](#nginx) ```nginx server { listen 443 ssl; http2 on; server_name manga.example.com; ssl_certificate /etc/ssl/manga.example.com/fullchain.pem; ssl_certificate_key /etc/ssl/manga.example.com/privkey.pem; # No upload size limit (chunked uploads send up to 64 MB per chunk) client_max_body_size 0; location / { proxy_pass http://127.0.0.1:3000; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Connection ""; # SSE: no buffering, no timeout on long-lived streams proxy_buffering off; proxy_cache off; proxy_read_timeout 1h; proxy_request_buffering off; } } server { listen 80; server_name manga.example.com; return 301 https://$host$request_uri; } ``` ## Caddy [Section titled “Caddy”](#caddy) Caddy obtains certificates automatically, forwards `X-Forwarded-*` by default and flushes `text/event-stream` responses immediately, so the configuration is as short as it gets: ```caddyfile manga.example.com { reverse_proxy 127.0.0.1:3000 } ``` ## Traefik [Section titled “Traefik”](#traefik) Add labels to the LANrurugi compose service (this assumes Traefik already has an entrypoint named `websecure` and a certificate resolver named `letsencrypt`, on the same Docker network): ```yaml services: lanrurugi: image: ghcr.io/thelastfantasy/lanrurugi:latest # Traefik serves it, so port 3000 no longer needs publishing volumes: - ./data/manga:/home/koyomi/lanrurugi/content - ./data/thumb:/home/koyomi/lanrurugi/thumb - ./data/database:/home/koyomi/lanrurugi/database - ./data/models:/home/koyomi/lanrurugi/models environment: - LANRURUGI_FORCE_SECURE_COOKIES=true labels: - traefik.enable=true - traefik.http.routers.lanrurugi.rule=Host(`manga.example.com`) - traefik.http.routers.lanrurugi.entrypoints=websecure - traefik.http.routers.lanrurugi.tls.certresolver=letsencrypt - traefik.http.services.lanrurugi.loadbalancer.server.port=3000 restart: unless-stopped ``` Traefik forwards `X-Forwarded-*`, doesn’t buffer responses and doesn’t limit request bodies by default, so no extra middleware is needed. ## Apache httpd [Section titled “Apache httpd”](#apache-httpd) Enable `mod_proxy`, `mod_proxy_http`, `mod_headers` and `mod_ssl`: ```apache ServerName manga.example.com SSLEngine on SSLCertificateFile /etc/ssl/manga.example.com/fullchain.pem SSLCertificateKeyFile /etc/ssl/manga.example.com/privkey.pem ProxyPreserveHost On # mod_proxy sets X-Forwarded-For and X-Forwarded-Host itself RequestHeader set X-Forwarded-Proto "https" # flushpackets=on delivers SSE events to the browser immediately ProxyPass / http://127.0.0.1:3000/ flushpackets=on timeout=3600 ProxyPassReverse / http://127.0.0.1:3000/ # No upload size limit LimitRequestBody 0 ``` ## Nginx Proxy Manager [Section titled “Nginx Proxy Manager”](#nginx-proxy-manager) Many NAS users manage certificates with it. Create a Proxy Host: * **Details**: Domain `manga.example.com`, Scheme `http`, Forward Hostname / IP and Port pointing at LANrurugi and `3000`. * **SSL**: request a certificate and tick *Force SSL*. * **Advanced**: paste ```nginx client_max_body_size 0; proxy_buffering off; proxy_request_buffering off; proxy_read_timeout 1h; proxy_set_header X-Forwarded-Host $host; ``` Nginx Proxy Manager already forwards `Host`, `X-Forwarded-Proto` and `X-Forwarded-For` by default. ## Checking the setup [Section titled “Checking the setup”](#checking-the-setup) 1. Open `https://manga.example.com`; you can sign in, and you stay signed in after a refresh. 2. Add a task to the download queue; its progress bar should advance steadily rather than jump to 100% only when it finishes. 3. On the activity log page (`/activity`), sign-ins show your client IP rather than the proxy’s address. # Plugin authoring > Write LANrurugi's metadata / login / download plugins in TypeScript. A LANrurugi plugin is a **single `.ts` file**, placed under `plugins//` or uploaded through the settings page / `POST /api/plugins/upload` (which lands in `plugins/custom//`). It runs in a **separate Deno subprocess** holding only the permissions the plugin itself declares (`--allow-net` / `--allow-read` and so on), with no access to anything in the host process. ## Minimal plugin [Section titled “Minimal plugin”](#minimal-plugin) A plugin file must export exactly two things: 1. `pluginInfo()` — synchronous, side-effect free, returning only the plugin’s own metadata: namespace, name, parameters, declared permissions. The host calls it in a **zero-permission** one-shot subprocess purely to read that metadata, and only then requests the real permissions it declared. 2. The execution function for its category — `execMetadata` (metadata fetching), `execLogin` (login), or `execDownload` (downloading). For the exact signatures, the types, and what every field means, see the **[SDK reference](../sdk/)**: `deno doc` generates it directly from the same TypeScript the runtime loads, so it cannot drift from the real behaviour. ## Permissions [Section titled “Permissions”](#permissions) A plugin has to **declare up front** what it needs, and the host grants exactly that. This is what stops a misbehaving or malicious plugin from taking down the host process or reading files it should not. Any network or file access beyond the declaration fails. ## Debugging [Section titled “Debugging”](#debugging) * The settings page’s plugin list shows each plugin’s `pluginInfo()` result, including its declared permissions. * When a plugin call fails, the host records the subprocess’s stderr alongside it; the logs page can be filtered by category. * HTTP requests are relayed through the host and minimised on demand — plugin requests are proxied by the host, so a plugin needs nothing beyond `--allow-net`, and they can be rate-limited and logged in one place. ## Next [Section titled “Next”](#next) * [SDK reference](../sdk/) — every exported type and function, with its documentation comments. * [API reference](../../api/) — the endpoints under `/api/plugins*` (list, upload, execute, export). # SDK Reference > The API reference for the TypeScript the plugin runtime actually loads. Every type and function a plugin author can use, generated by `deno doc` straight from **the same TypeScript the plugin runtime loads** (`plugin-sdk.ts` and `dispatcher.ts` under `crates/lanrurugi-plugin/dispatcher/`, plus `plugins/legacy-globals.d.ts`) — so it cannot drift from what the host actually does. [Open the SDK reference →](https://sdk.lrrg.dev/) That reference supports symbol search, grouping by type/interface/function, and shows each symbol’s own documentation comment. The same content is also published as machine-readable JSON (`plugin-sdk.json`) for tooling. Why it is not part of this sidebar’s page tree `deno doc --html` produces a **self-contained static site** with its own search, dark mode and symbol index. Re-rendering all of that inside Starlight would mean writing it again rather than reusing it, so it is published as its own site instead (and under `/docs/sdk/` inside the server image). ## Related [Section titled “Related”](#related) * [Plugin authoring intro](../getting-started/) — a minimal plugin, the permission model, debugging. * [API reference](../../api/) — the endpoints under `/api/plugins*`. # 用文档站测试 API > 在浏览器里直接对你自己正在运行的 LANrurugi 实例发请求——前置条件、安全边界,以及它不生效时怎么办。 [API 参考](../../api/) 里每个端点都有一个请求面板:填服务器地址、填令牌、点发送。这一页说明它到底 把请求发到哪里、需要什么前置条件,以及浏览器拦下来的时候怎么继续。 ## 请求发到哪里 [Section titled “请求发到哪里”](#请求发到哪里) **从你的浏览器,直接发到你在面板里填的那个地址。** * 你在下面填的地址与令牌,只存在你浏览器的本地存储里,也只发往那个地址。 * 本项目**没有**中间服务器、**没有**代理。绝不会有一条路径把用户的令牌或内网地址送到本项目的基础设施。 * 唯一的例外是页面本身:API 描述文档(`openapi.json`)和 Scalar 的运行时都由文档站同源提供,不走外部 CDN。 因此这个功能不需要任何“公开 demo 实例”——它的目标从来就是你自己的实例。 ## 前置条件 [Section titled “前置条件”](#前置条件) ### 1. 你的实例要对这个浏览器可达 [Section titled “1. 你的实例要对这个浏览器可达”](#1-你的实例要对这个浏览器可达) 面板里填的地址必须是**当前浏览器**能访问到的。你在这台机器上跑文档站、实例在另一台机器上,那么 `localhost` 指的是浏览器所在的机器,不是实例所在的机器。 ### 2. 在实例上打开跨源访问 [Section titled “2. 在实例上打开跨源访问”](#2-在实例上打开跨源访问) 设置页面里的 **「为客户端 API 启用 CORS」** 必须打开。默认是关闭的,此时浏览器会拒绝跨源请求。 打开之后,实例会允许浏览器预检所需的头——包括带 JSON 请求体时必需的 `Content-Type`。如果你的实例版本较 旧、带请求体的调用总是失败,多半就是这一项没有覆盖到。 ### 3. HTTPS 页面只能调用 HTTPS 实例和 `http://localhost` [Section titled “3. HTTPS 页面只能调用 HTTPS 实例和 http://localhost”](#3-https-页面只能调用-https-实例和-httplocalhost) 这是浏览器强制执行的规则,和 LANrurugi 无关: | 文档站 | 你填的实例地址 | 结果 | | ----------- | -------------------------- | ----------------------------- | | `https://…` | `https://lrr.example.com` | ✅ 可用 | | `https://…` | `http://localhost:3000` | ✅ 可用(浏览器把 `localhost` 当作可信来源) | | `https://…` | `http://192.168.1.10:3000` | ❌ 被当作混合内容拦掉 | | `http://…` | 任意 | ✅ 可用(站点本身也是 HTTP) | 局域网 IP **不**享受 `localhost` 那个豁免。想在 HTTPS 文档站上测试局域网里的实例,两条路: * **给实例配 HTTPS**:反向代理(Caddy / Traefik / nginx)、Cloudflare Tunnel,或者 VPN 里带证书的入口。 * **把端口转发到 localhost**: ```sh ssh -L 3000:127.0.0.1:3000 <跑着实例的机器> ``` 然后在面板里填 `http://localhost:3000`。浏览器把它当作可信来源,直接可用。 ## 浏览器不允许的时候:用命令行 [Section titled “浏览器不允许的时候:用命令行”](#浏览器不允许的时候用命令行) **每个端点都有一份可直接复制的命令行(cURL)**,在代码示例面板里。它由端点本身生成,不依赖浏览器、 不依赖 CORS、不依赖 HTTPS,永远可用——面板里发送失败时,用它。 ```sh curl -H "Authorization: Bearer <你的令牌>" \ "http://192.168.1.10:3000/api/archives?start=0&count=10" ``` ## 面板报错时怎么读 [Section titled “面板报错时怎么读”](#面板报错时怎么读) * **网络错误 / failed to fetch**:先看上面三条前置条件。最常见的是 CORS 没开、地址填错,或者那份「 混合内容」的组合。 * **401**:令牌不对,或者令牌没有这个端点的权限。 * **403**:令牌是访客类型的,而这个端点只允许管理员。 * **404**:路径或档案 ID 不对。 ## 令牌 [Section titled “令牌”](#令牌) 在设置页面的令牌管理里创建。面板里的令牌字段只是把它放进 `Authorization: Bearer ` 头,存在你 浏览器的本地存储里,也只会发往你填的那个地址。 别在别人的文档站上填令牌 这一页的前提是文档站只是个静态页面。但“静态页面”不等于“可信页面”——对你信任的部署再填令牌。如果你不 确定某个文档站是不是官方部署,直接用 cURL。 # 支持的格式 > 能放进书库的压缩包与电子书格式,以及每种格式怎么显示、目录从哪里来。 书库里的每个文件都是一本「档案」,在同一个阅读器里一页一页地读。除了装着图片的压缩包,PDF、EPUB 等 电子书也可以直接放进书库目录或通过上传页加入,不需要先转换。 ## 压缩包 [Section titled “压缩包”](#压缩包) | 格式 | 扩展名 | | ----------- | ----------------------------------------------------------------------------- | | ZIP | `.zip` `.cbz` | | RAR(含 RAR5) | `.rar` `.cbr` | | 7-Zip | `.7z` `.cb7` | | TAR | `.tar` `.cbt`,以及 gzip / bzip2 / xz / lzma 压缩的 tar(`.gz` `.bz2` `.xz` `.lzma`) | | LZH | `.lzh` `.lha` | 压缩包里能作为页面的图片:PNG、JPEG(`.jpg` `.jpeg` `.jfif`)、GIF、BMP、WebP、AVIF、JPEG XL、HEIF/HEIC。 浏览器显示不了的格式(例如部分浏览器上的 AVIF、JPEG XL 和动画图)会由服务端转换后再显示;HEIF/HEIC 目前 无法转换,只有原生支持它的浏览器(例如 Safari)能显示。 用 zstd 压缩的文件(`.zst`)目前不支持,不会被收录。 ## 电子书 [Section titled “电子书”](#电子书) | 格式 | 扩展名 | 页面怎么显示 | 目录从哪里来 | | ----------------- | ----------------------------- | ------------------------------ | ----------------------------------- | | PDF | `.pdf` | 扫描页直接输出 PDF 里存的原图;文字页、矢量页渲染成图片 | PDF 书签 | | EPUB(固定版式) | `.epub` | 每一页输出书里存的原图 | 书自带的目录(nav / NCX) | | EPUB(流式文字) | `.epub` | 服务端排版成页,插图随文排入 | 书自带的目录,精确到章节所在的位置 | | MOBI / AZW / AZW3 | `.mobi` `.azw` `.azw3` `.prc` | 漫画:每页输出原图;文字书:服务端排版 | 书里的目录页或章节标题 | | DjVu | `.djvu` `.djv` | 渲染成图片 | DjVu 书签 | | FB2 | `.fb2` | 服务端排版,插图随文排入 | 书的章节结构 | | 纯文本 | `.txt` | 服务端排版 | 自动识别「第一章」「第十二回」「序章」「Chapter 3」这类章节行 | 几点说明: * **原图不重新压缩。** 书里存的是图片的页面(扫描版 PDF、固定版式 EPUB、漫画 MOBI/AZW3、FB2 插图), 阅读器拿到的就是书里那张图本身。 * **文字书由服务端排版。** 正文按书的语言选用简体中文、日文或韩文字体,标题、段落、插图都会排进页面; 目前只支持横排。 * **目录只在首次入库时导入**,而且只在档案还没有章节目录时才导入,不会覆盖你手动编辑过的目录。书自带的 目录缺失或只有一两条(比如只有封面、版权页)时,会从正文里的标题和章节行补全。 * **TXT 只收录 8 KB 以上的文件**,避免把书库里的说明文件、备注当成书。编码自动识别(UTF-8、UTF-16、 GBK/GB18030、Big5、Shift_JIS、EUC-JP、EUC-KR 等);按固定宽度折行的文本会重新拼回段落。 * **书库里会标出格式。** 电子书在标题旁显示 `PDF`、`EPUB` 之类的小标签;PDF 还可以在阅读页里直接用浏览器 打开原文件。 * 拆包建议只对压缩包有意义,电子书不提供。 * 文字书和 PDF 文字页渲染出的页面会缓存起来,与阅读器的其它缓存一起受 「设置 → 档案文件 → 最大阅读缓存大小」限制。 ## 不支持的情况 [Section titled “不支持的情况”](#不支持的情况) * **带 DRM 或密码保护的书**(例如从商店购买、未去除保护的 Kindle 书,或加了打开密码的 PDF)无法读取。 这类文件仍会出现在书库里(0 页),打开时阅读器会显示无法读取的原因(受 DRM 或密码保护),服务端日志里也会 记录。 * **损坏或不完整的文件**同样会提示具体原因,不影响书库里的其它书。 * Kindle 的 KFX 格式,以及使用 HUFF/CDIC 压缩的 MOBI(多见于 Kindle 词典)暂不支持。 # 安装(Docker / NAS) > 用 Docker 或 Compose 在服务器/NAS 上部署 LANrurugi。 LANrurugi 的服务端是一个常驻进程,前端静态资源、HTTP API、文件监视器和后台任务都在里面;插件、电子书解析和 AI 推理在按需启动的子进程里运行。它有自己的数据库,不读取也不改动 LANraragi 的数据库,两者可以同时运行。 从 LANraragi 迁移 1. 在 LANraragi 的设置 →「Database Backup/Restore」→「Backup Database」下载备份 JSON,LANraragi 可以继续运行。 2. 启动 LANrurugi:书库挂载和 LANraragi 相同的漫画目录;缩略图和数据库也要挂载,但必须用新的目录,不要和 LANraragi 的相同。[主页](https://lrrg.dev/#start)上的转换器能根据 LANraragi 的部署命令或 compose 文件生成。 3. 用默认密码 `kamimamita` 登录,首次运行向导会提示你修改。 4. 在向导的「从 LANraragi 备份导入」一步上传 JSON(之后也能在设置 →「数据库备份/恢复」里导入)。标签、分类、 合集和 stamps 会恢复,阅读进度不在备份里。 不想用容器的话,也可以用 Linux、macOS(Apple Silicon)和 FreeBSD 的[原生安装包](../install-native/)。 ## 用 Compose 部署(推荐) [Section titled “用 Compose 部署(推荐)”](#用-compose-部署推荐) 把下面这段保存为 `compose.yaml`,按注释把左侧的宿主机目录改成你自己的,然后启动: ```yaml services: lanrurugi: image: ghcr.io/thelastfantasy/lanrurugi:latest container_name: lanrurugi ports: - "3000:3000" volumes: # 书库,可以直接指向旧版 LANraragi 的 content 目录 - ./data/manga:/home/koyomi/lanrurugi/content # 缩略图缓存 - ./data/thumb:/home/koyomi/lanrurugi/thumb # Redis 数据,LANrurugi 专用;LANraragi 的元数据通过备份 JSON 导入 - ./data/database:/home/koyomi/lanrurugi/database # 推荐功能的嵌入模型,首次用到时自动下载 - ./data/models:/home/koyomi/lanrurugi/models environment: # 经 HTTPS 反向代理访问时改为 true - LANRURUGI_FORCE_SECURE_COOKIES=false restart: unless-stopped ``` ```sh docker compose up -d # 或 podman compose up -d ``` NAS 上(群晖 Container Manager、Portainer 等)新建一个 compose 项目,粘贴同一段文本即可。 启动后在浏览器打开 `http://<服务器地址>:3000`。镜像自带 Redis,不需要额外的数据库容器。四个挂载目录: | 宿主机路径 | 容器内路径 | 用途 | | ----------------- | --------------------------------- | ---------------------- | | `./data/manga` | `/home/koyomi/lanrurugi/content` | 你的档案库 | | `./data/thumb` | `/home/koyomi/lanrurugi/thumb` | 缩略图缓存 | | `./data/database` | `/home/koyomi/lanrurugi/database` | Redis 数据(LANrurugi 专用) | | `./data/models` | `/home/koyomi/lanrurugi/models` | 推荐功能的嵌入模型缓存 | 要通过域名和 HTTPS 访问,见[反向代理](../reverse-proxy/)。 ## 直接用 Docker 运行 [Section titled “直接用 Docker 运行”](#直接用-docker-运行) ```sh docker run -d --name lanrurugi -p 3000:3000 \ -v /path/to/library:/home/koyomi/lanrurugi/content \ -v /path/to/thumb:/home/koyomi/lanrurugi/thumb \ -v /path/to/database:/home/koyomi/lanrurugi/database \ ghcr.io/thelastfantasy/lanrurugi:latest ``` ## 镜像来源 [Section titled “镜像来源”](#镜像来源) 同一个镜像同时发布在两个仓库,内容完全相同,都包含 amd64 和 arm64 两种架构: | 仓库 | 镜像名 | | ----------------------------- | ---------------------------------- | | GitHub Container Registry(推荐) | `ghcr.io/thelastfantasy/lanrurugi` | | Docker Hub | `jade913/lanrurugi` | 上面的示例用的是 GitHub 的仓库。Docker Hub 对未登录用户有拉取次数限制;如果你的 NAS 面板只能从 Docker Hub 搜索镜像,或者你更习惯用它,把镜像名换成 `jade913/lanrurugi` 即可。`latest` 指向最新的正式版本, 也可以写具体的版本号。 ## 从源码构建镜像 [Section titled “从源码构建镜像”](#从源码构建镜像) 仓库根目录的 `compose.yaml` 用于从源码构建并试运行(`network_mode: host`,监听 3000 端口): ```sh podman compose up -d --build # 或 docker compose up -d --build ``` ## 首次登录 [Section titled “首次登录”](#首次登录) 首次打开时会出现首次运行向导:修改管理员密码、填写 AI 功能用的 DeepSeek API 密钥、从 LANraragi 备份导入 数据,每一步都可以跳过,之后也能在设置页面重新运行。 一个全新实例——或者从一个从未修改过密码的旧版安装迁移过来的实例——使用的是旧版 LANraragi 自身的默认 管理员密码 **`kamimamita`**。 第一件事就是改密码 登录后请立刻在设置页面修改密码。不要让一个还在用默认密码的实例可以从本地网络之外访问。 ## 离线阅读本文档 [Section titled “离线阅读本文档”](#离线阅读本文档) 文档站、API 正文参考、Swagger UI 和插件 SDK 参考都打包在镜像里,由实例自己在 `/docs` 下提供: ```text http://<你的实例地址>:3000/docs/ 指南与按分组的 API 正文参考(中文) http://<你的实例地址>:3000/docs/en/ 同上,英文版 http://<你的实例地址>:3000/docs/swagger/ Swagger UI,中文内容(可看 schema,可试发请求) http://<你的实例地址>:3000/docs/swagger/en/ Swagger UI,英文内容 http://<你的实例地址>:3000/docs/sdk/ 插件 SDK 参考 ``` 不需要外网:连 Swagger UI 的 JS 打包和 SDK 的搜索索引都在镜像里,没有任何资源来自 CDN。 ## 工具链(从源码构建) [Section titled “工具链(从源码构建)”](#工具链从源码构建) 版本固定在 `.mise.toml` 里,`mise install` 会精确复现它们(Rust、Node、Deno、pnpm,以及 `sccache`/`mold`)。 ```sh # 后端 cargo build --release -p lanrurugi-server ./target/release/lanrurugi-server serve --redis-url redis://127.0.0.1:6379 \ --library-path /path/to/existing/library # 前端开发服务器(把 /api 代理到上面的后端) pnpm --filter lanrurugi-frontend run dev ``` ### CLI 子命令 [Section titled “CLI 子命令”](#cli-子命令) * `lanrurugi serve`——在同一个进程里运行 HTTP API、静态前端、文件监视器与插件池。 * `lanrurugi rebuild-index`——用大小感知算法重新计算每个档案的 ID,并发现历史上曾被误判合并而隐藏的 文件。 * `lanrurugi bench`——生成合成库,并针对一个正在运行的旧版实例做并发/吞吐量对比。 ## 下一步 [Section titled “下一步”](#下一步) * [快速开始](../quickstart/) * [用文档站测试 API](../api-testing/) # 原生安装(Linux / macOS / FreeBSD) > 不用容器,直接在 Linux、Apple Silicon Mac 或 FreeBSD 上运行 LANrurugi。 除了 [Docker 镜像](../install/),每个版本还提供以下平台的原生安装包: | 安装包 | 适用系统 | | -------------------------------------- | ------------------------------------------------------------------ | | `lanrurugi-<版本>-linux-x86_64.tar.gz` | 64 位 Linux(glibc 2.35 及以上:Debian 12、Ubuntu 22.04、Fedora 36、Arch 等) | | `lanrurugi-<版本>-linux-aarch64.tar.gz` | ARM64 Linux(同上,例如树莓派 5、ARM 服务器) | | `lanrurugi-<版本>-macos-arm64.tar.gz` | Apple Silicon Mac(macOS 13 及以上) | | `lanrurugi-<版本>-freebsd-x86_64.tar.gz` | FreeBSD 14 | 安装包在 GitHub 的 [Releases](https://github.com/thelastfantasy/LANrurugi/releases) 页面,`SHA256SUMS` 里有每个文件的校验值。 不想管理依赖的话,Docker 仍然是最省事的方式;Windows 用户请使用 Docker Desktop。 ## 1. 安装依赖 [Section titled “1. 安装依赖”](#1-安装依赖) 数据库、插件运行环境、DjVu 工具和字体由系统的包管理器安装,安装包里不附带: | | Debian / Ubuntu | Fedora | Arch | macOS(Homebrew) | FreeBSD | | ---------------- | ------------------------------------ | -------------------------------------------------------------------- | ---------------------------- | -------------------------- | ------------------------------------------------------------------- | | Redis 7.4 及以上 | `apt install redis-server` ¹ | `dnf install redis` ² | `pacman -S redis` | `brew install redis` | `pkg install redis` | | Deno(插件) | [官方安装脚本](https://deno.com) | [官方安装脚本](https://deno.com) | `pacman -S deno` | `brew install deno` | `pkg install deno` | | DjVu 阅读 | `apt install djvulibre-bin` | `dnf install djvulibre` | `pacman -S djvulibre` | `brew install djvulibre` | `pkg install djvulibre` | | 中日韩字体(文字书) | `apt install fonts-noto-cjk` | `dnf install google-noto-serif-cjk-fonts google-noto-sans-cjk-fonts` | `pacman -S noto-fonts-cjk` | 系统自带,无需安装 | `pkg install noto-serif-sc noto-sans-sc noto-serif-jp noto-sans-jp` | | 彩色 emoji 字体(文字书) | `apt install fonts-noto-color-emoji` | `dnf install google-noto-color-emoji-fonts` | `pacman -S noto-fonts-emoji` | 系统自带,无需安装 | `pkg install noto-emoji` | | 压缩包解码库 | 系统自带 | 系统自带 | 系统自带 | `brew install xz lz4 zstd` | `pkg install lz4 zstd` | | PDF 阅读 | 安装包自带 | 安装包自带 | 安装包自带 | 安装包自带 | `pkg install pdfium` | | OCR、翻译、推荐 | 安装包自带 | 安装包自带 | 安装包自带 | 安装包自带 | `pkg install onnxruntime` | | CA 证书(HTTPS) | `apt install ca-certificates` ³ | 系统自带 | 系统自带 | 系统自带 | `pkg install ca_root_nss` | ¹ Debian 12 自带的是 Redis 7.0,用于新书库没有问题;要沿用 Docker 部署留下的数据,需要 7.4 及以上(可使用 redis.io 的软件源)。 ² 较新的 Fedora 实际安装的是兼容 Redis 的 Valkey,用于新书库没有问题,但它读不了 Redis 7.4 写出的数据文件。 ³ 精简系统(最小化容器、虚拟机)可能没有装。不装也能运行:程序找不到系统证书时,HTTPS 会改用内置的 Mozilla 根证书,启动日志里的 `tls_roots=bundled` 表示这种情况。装上系统证书则跟随系统更新,也能识别你自己添加的证书。 ## 2. 解压并启动 [Section titled “2. 解压并启动”](#2-解压并启动) ```sh tar -xzf lanrurugi-<版本>-<平台>.tar.gz cd lanrurugi-<版本>-<平台> redis-server --daemonize yes # 或启用系统自带的 Redis 服务 ./bin/lanrurugi-server serve \ --library-path ~/manga \ --thumb-dir ~/.local/share/lanrurugi/thumb \ --temp-dir ~/.local/share/lanrurugi/temp \ --log-dir ~/.local/share/lanrurugi/log ``` 然后打开 `http://<你的机器>:3000`,首次运行向导会引导你修改默认密码、填写 AI 功能用的 API 密钥、导入 LANraragi 备份。 前端、插件、文档、自带的原生库和模型都按程序自己的位置查找,解压到哪里都可以,不需要再设置其它路径。 默认连接 `redis://127.0.0.1:6379`,用 `--redis-url` 或环境变量 `LANRURUGI_REDIS_URL` 修改。 ## 3. 下载翻译模型(可选) [Section titled “3. 下载翻译模型(可选)”](#3-下载翻译模型可选) ```sh ./fetch-models.sh # 文字识别与擦除模型,几百 MB ./fetch-models.sh --with-bubbles # 另外生成对话框分割模型(需要 uv) ``` 不下载也能正常使用书库和阅读器;没有对话框分割模型时,翻译用矩形框擦除原文。 ## 4. 作为系统服务运行 [Section titled “4. 作为系统服务运行”](#4-作为系统服务运行) ```sh sudo ./install-service.sh /var/lib/lanrurugi # Linux(systemd)、FreeBSD(rc.d) ./install-service.sh ~/LANrurugi # macOS(launchd,当前用户) ``` 脚本会创建数据目录和 `lanrurugi.env`(书库位置、Redis 地址、监听端口),并为当前系统安装服务定义,最后提示启动命令。 只想看生成的服务文件而不安装,加 `--print`。 ## 从 Docker 部署迁移 [Section titled “从 Docker 部署迁移”](#从-docker-部署迁移) 把容器挂载的三个目录直接拿过来用:`content` 作为书库,`thumb` 作为缩略图目录。`database` 目录交给一个按 `service/redis.conf.example` 配置的 Redis(7.4 及以上),它的 `dir` 指向这个目录,端口 16379;再把 `LANRURUGI_REDIS_URL` 设为 `redis://127.0.0.1:16379`。 ## 各平台功能 [Section titled “各平台功能”](#各平台功能) | 功能 | Linux | macOS | FreeBSD | | ------------------------------------ | ---------------- | ------ | ------------------------ | | 书库、阅读、搜索、压缩包 | ✓ | ✓ | ✓ | | PDF / DjVu / EPUB / MOBI / FB2 / TXT | ✓ | ✓ | ✓(PDF 需 `pdfium` 包) | | 插件、下载、订阅 | ✓ | ✓ | ✓ | | 推荐、OCR、页面翻译 | ✓ | ✓(CPU) | ✓(CPU,需 `onnxruntime` 包) | | GPU 加速推理 | ✓(与 Docker 镜像相同) | — | — | 缺少某个可选组件时服务照常启动,启动日志会列出 `optional components` 和 `some features are unavailable on this system`,说明缺了什么、影响哪些功能;用到这些功能时也会显示原因。 ## 尚未支持的平台 [Section titled “尚未支持的平台”](#尚未支持的平台) * **Windows**:请使用 Docker Desktop。 * **Intel Mac、其它 BSD、musl 发行版(如 Alpine)**:没有提供安装包;musl 发行版请使用 Docker 镜像。 * **鸿蒙(HarmonyOS / OpenHarmony)**:暂不支持。鸿蒙系统上的应用运行在沙箱里,不支持长期在后台运行的 服务端程序,LANrurugi 依赖的 Redis、Deno、PDFium、ONNX Runtime 也都没有鸿蒙版本。可行的方向是另做 一个连接现有 LANrurugi 服务端的鸿蒙阅读客户端,而不是在设备上运行服务端。 # 给 AI 工具用的 llms.txt > 项目主页和文档站提供的 llms.txt 系列文件各自包含什么,以及让 AI 助手了解 LANrurugi 时该给它哪一份。 [llms.txt](https://llmstxt.org/) 是一种约定:在站点根目录放一份 Markdown 文件,告诉 AI 工具这个项目是什么、 更详细的内容去哪里读。LANrurugi 的项目主页和文档站都提供了这类文件。把对应的地址交给 AI 助手, 它就能按文档回答问题、帮你部署、写调用 API 的脚本或者写插件,而不必只凭训练时的印象猜。 ## 文件一览 [Section titled “文件一览”](#文件一览) | 地址 | 内容 | 大小(约) | | -------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- | ------ | | [`lrrg.dev/llms.txt`](https://lrrg.dev/llms.txt) | 入口:项目简介、HTTP API 与插件 SDK 的说明,以及主要文档的链接 | 3.5 KB | | [`docs.lrrg.dev/llms.txt`](https://docs.lrrg.dev/llms.txt) | 文档站目录:下面各文件的链接,以及 API 与 SDK 的说明 | 3 KB | | [`docs.lrrg.dev/llms-full.txt`](https://docs.lrrg.dev/llms-full.txt) | 全部文档页,中英两种语言,合成一个 Markdown 文件 | 800 KB | | [`docs.lrrg.dev/llms-small.txt`](https://docs.lrrg.dev/llms-small.txt) | 精简版:只含指南和插件开发,去掉 API 参考页与提示框 | 80 KB | | [`…/_llms-txt/guides-simplified-chinese.txt`](https://docs.lrrg.dev/_llms-txt/guides-simplified-chinese.txt) | 只含中文的指南与插件开发 | 40 KB | | [`…/_llms-txt/guides-english.txt`](https://docs.lrrg.dev/_llms-txt/guides-english.txt) | 同上,英文 | 40 KB | | [`…/_llms-txt/api-reference-simplified-chinese.txt`](https://docs.lrrg.dev/_llms-txt/api-reference-simplified-chinese.txt) | 只含中文的 API 参考,每组一节 | 300 KB | | [`…/_llms-txt/api-reference-english.txt`](https://docs.lrrg.dev/_llms-txt/api-reference-english.txt) | 同上,英文 | 300 KB | 另有两份结构化数据,llms.txt 里也有链接: * [`docs.lrrg.dev/openapi.json`](https://docs.lrrg.dev/openapi.json):完整的 HTTP API,OpenAPI 3.1 格式。它由服务器 自己注册的路由生成,列出的正是服务器实际提供的全部端点。 * [`sdk.lrrg.dev/plugin-sdk.json`](https://sdk.lrrg.dev/plugin-sdk.json):插件 SDK 参考的 JSON 版,由 `deno doc` 从插件运行时实际加载的 TypeScript 生成。 这些文件在每次发布文档时与网页一同重新生成,内容和网页同源,不会各自过时。 ## 该给 AI 哪一份 [Section titled “该给 AI 哪一份”](#该给-ai-哪一份) | 你想让 AI 做什么 | 给它 | | ---------------- | ------------------------------------------------------------ | | 介绍这个项目、回答一般问题 | `lrrg.dev/llms.txt` | | 帮你部署、排查安装与反向代理问题 | 一种语言的指南(`guides-*.txt`)或 `llms-small.txt` | | 写调用 API 的脚本或客户端 | `openapi.json`:比 API 参考页的 Markdown 更精确,也更省 token | | 写插件 | [插件开发入门](../../plugin/getting-started/) 加上 `plugin-sdk.json` | | 需要全部背景、上下文足够大 | `llms-full.txt` | 如果只是想为某个站点生成元数据、登录或下载插件,实例里自带的 **「AI 创建插件」** 会直接抓取目标页面、 生成代码并试运行,通常比让外部 AI 助手从零写更省事。 ## 怎么交给 AI [Section titled “怎么交给 AI”](#怎么交给-ai) * **能联网的 AI 工具**(带网页读取的聊天助手、编程代理等):直接把地址发给它,例如 「先读 `https://lrrg.dev/llms.txt`,再回答……」。它会按里面的链接继续读需要的部分。 * **不能联网的工具**:先下载需要的文件,再作为附件上传或粘贴进对话。 * **编程代理**(在代码仓库里工作的 AI):把 `openapi.json` 或 `plugin-sdk.json` 下载进项目目录,比每次 联网读取更稳定。 # 快速开始 > 首次登录、建立 API 令牌、扫描库、导入旧数据。 ## 1. 登录 [Section titled “1. 登录”](#1-登录) 打开 `http://<你的实例地址>:3000`,用默认密码 `kamimamita` 登录,然后**立刻在设置页面改掉它**。 ## 2. 指向你的库 [Section titled “2. 指向你的库”](#2-指向你的库) `--library-path`(或 `LANRURUGI_LIBRARY_PATH`)指向放档案的目录。默认是 `./library`;Compose 部署里 对应容器的 `/home/koyomi/lanrurugi/content`。 ## 3. 扫描 [Section titled “3. 扫描”](#3-扫描) 在设置页面触发一次全量扫描。扫描是并发的(Rayon),并且**不会**自动删除档案记录——「扫描时发现文件消失」 只会清理路径簿记,档案记录本身归「数据库清理」管,是一个独立的、需要你明确触发的操作。 ## 4. 建立 API 令牌 [Section titled “4. 建立 API 令牌”](#4-建立-api-令牌) API 参考里的「Test it」面板需要令牌。在设置页面的令牌管理里创建一个,然后: ```sh curl -H "Authorization: Bearer <你的令牌>" http://localhost:3000/api/archives ``` 令牌按权限分为管理员与访客两类;访客令牌只能读取。 ## 5. 从旧版 LANraragi 迁移 [Section titled “5. 从旧版 LANraragi 迁移”](#5-从旧版-lanraragi-迁移) LANrurugi 用自己的数据库,不读取也不改动 LANraragi 的数据,两边可以同时运行。步骤见[安装](../install/)页的 「从 LANraragi 迁移」:书库挂载同一个漫画目录,缩略图和数据库用新的目录,再在首次运行向导里导入 LANraragi 的 备份 JSON。 导入按文件名把备份里的档案对应到 LANrurugi 扫描到的档案,不比较档案 ID:LANrurugi 用大小感知指纹 (`hash(前 512KB ++ 大端 u64 文件大小)`)作为 ID,和 LANraragi 的 `SHA-1(前 512KB)` 不同。同名文件有多个时 不会猜测,计入「匹配不唯一」。导入前请等书库扫描完成,还没扫描到的档案会被算作「无匹配而跳过」。 LANraragi 曾把开头字节相同的不同文件误判为重复并合并,这些文件在 LANrurugi 里会各自出现。 ## 6. 试试 API [Section titled “6. 试试 API”](#6-试试-api) 打开 [API 参考](../../api/),在请求面板里把服务器地址改成你自己的实例(默认已经是 `http://localhost:3000`),填上令牌,然后直接发请求。请求从你的浏览器直接到你的实例,不经过本项目。 浏览器不允许的时候(例如文档站是 HTTPS 而你的实例是局域网里的纯 HTTP),每个端点都提供了一份可直接 复制的命令行。 细节见[用文档站测试 API](../api-testing/)。 # 反向代理 > 用 Nginx、Caddy、Traefik、Apache 或 Nginx Proxy Manager 为 LANrurugi 配置域名与 HTTPS。 LANrurugi 本身只提供 HTTP(默认 `0.0.0.0:3000`)。要通过域名和 HTTPS 访问,在它前面放一个反向代理。 无论用哪一种代理,都要满足下面几条。 ## 代理需要满足的条件 [Section titled “代理需要满足的条件”](#代理需要满足的条件) * **挂在域名根路径下。** 前端以绝对路径 `/api/...` 请求接口,不支持挂在子路径(如 `example.com/lanrurugi/`)下。请用独立的域名或子域名,例如 `manga.example.com`。 * **转发三个请求头。** `X-Forwarded-Proto`(判断是否走 HTTPS)、`X-Forwarded-Host`(跨域登录交接与 OpenSearch 生成正确的地址)、`X-Forwarded-For`(活动记录里显示真实客户端 IP)。同时保留原始 `Host`。 * **不要缓冲 SSE。** 下载队列进度、AI 插件向导与拆包建议使用 Server-Sent Events 实时推送。代理一旦缓冲 响应,这些界面就会卡住、直到请求结束才一次性刷新。服务端每 15 秒发送一次心跳,所以默认的读超时 (通常 60 秒)够用,但缓冲必须关闭。 * **放开上传大小。** 档案上传以每片最多 64 MB 分片发送,旧版数据导入单次最多 100 MB。代理的请求体 上限要不小于这个值,最简单的做法是不设上限。 * **走 HTTPS 后打开安全 Cookie。** 在 compose 里设置 `LANRURUGI_FORCE_SECURE_COOKIES=true`。服务端不会 根据 `X-Forwarded-Proto` 自动推断这一项——那个请求头可以被伪造,而本服务没有可信代理白名单。只走 HTTP 时**不要**打开它,否则浏览器会丢弃登录 Cookie,导致无法登录。 不需要 WebSocket。 下面的示例都假设 LANrurugi 与代理在同一台机器上,监听 `127.0.0.1:3000`;如果代理和 LANrurugi 在同一个 compose 网络里,把地址换成 `lanrurugi:3000`。 ## Nginx [Section titled “Nginx”](#nginx) ```nginx server { listen 443 ssl; http2 on; server_name manga.example.com; ssl_certificate /etc/ssl/manga.example.com/fullchain.pem; ssl_certificate_key /etc/ssl/manga.example.com/privkey.pem; # 不限制上传大小(分片上传每片最多 64 MB) client_max_body_size 0; location / { proxy_pass http://127.0.0.1:3000; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Connection ""; # SSE:不缓冲,长连接不超时 proxy_buffering off; proxy_cache off; proxy_read_timeout 1h; proxy_request_buffering off; } } server { listen 80; server_name manga.example.com; return 301 https://$host$request_uri; } ``` ## Caddy [Section titled “Caddy”](#caddy) Caddy 自动申请证书、默认转发 `X-Forwarded-*`,并且会立即刷新 `text/event-stream` 响应,所以配置最短: ```caddyfile manga.example.com { reverse_proxy 127.0.0.1:3000 } ``` ## Traefik [Section titled “Traefik”](#traefik) 在 LANrurugi 的 compose 服务上加 labels(假设 Traefik 已经有名为 `websecure` 的 entrypoint 与名为 `letsencrypt` 的证书解析器,且两者在同一个 Docker 网络里): ```yaml services: lanrurugi: image: ghcr.io/thelastfantasy/lanrurugi:latest # 由 Traefik 对外提供服务时,不需要再发布 3000 端口 volumes: - ./data/manga:/home/koyomi/lanrurugi/content - ./data/thumb:/home/koyomi/lanrurugi/thumb - ./data/database:/home/koyomi/lanrurugi/database - ./data/models:/home/koyomi/lanrurugi/models environment: - LANRURUGI_FORCE_SECURE_COOKIES=true labels: - traefik.enable=true - traefik.http.routers.lanrurugi.rule=Host(`manga.example.com`) - traefik.http.routers.lanrurugi.entrypoints=websecure - traefik.http.routers.lanrurugi.tls.certresolver=letsencrypt - traefik.http.services.lanrurugi.loadbalancer.server.port=3000 restart: unless-stopped ``` Traefik 默认转发 `X-Forwarded-*`、不缓冲响应、不限制请求体大小,无需额外中间件。 ## Apache httpd [Section titled “Apache httpd”](#apache-httpd) 需要启用 `mod_proxy`、`mod_proxy_http`、`mod_headers` 与 `mod_ssl`: ```apache ServerName manga.example.com SSLEngine on SSLCertificateFile /etc/ssl/manga.example.com/fullchain.pem SSLCertificateKeyFile /etc/ssl/manga.example.com/privkey.pem ProxyPreserveHost On # mod_proxy 会自动设置 X-Forwarded-For 与 X-Forwarded-Host RequestHeader set X-Forwarded-Proto "https" # flushpackets=on 让 SSE 事件立即送达浏览器 ProxyPass / http://127.0.0.1:3000/ flushpackets=on timeout=3600 ProxyPassReverse / http://127.0.0.1:3000/ # 不限制上传大小 LimitRequestBody 0 ``` ## Nginx Proxy Manager [Section titled “Nginx Proxy Manager”](#nginx-proxy-manager) 许多 NAS 用户用它管理证书。新建一个 Proxy Host: * **Details**:Domain 填 `manga.example.com`,Scheme 选 `http`,Forward Hostname / IP 与 Port 填 LANrurugi 的地址和 `3000`。 * **SSL**:申请证书,勾选 *Force SSL*。 * **Advanced** 中粘贴: ```nginx client_max_body_size 0; proxy_buffering off; proxy_request_buffering off; proxy_read_timeout 1h; proxy_set_header X-Forwarded-Host $host; ``` Nginx Proxy Manager 默认已经转发 `Host`、`X-Forwarded-Proto` 与 `X-Forwarded-For`。 ## 检查是否配置正确 [Section titled “检查是否配置正确”](#检查是否配置正确) 1. 打开 `https://manga.example.com`,能正常登录且刷新后仍保持登录。 2. 在下载队列里添加一个任务,进度条应当连续推进,而不是在结束时才一次跳到 100%。 3. 活动记录页(`/activity`)里,登录记录显示的是你的客户端 IP,而不是代理的地址。 # 插件开发入门 > 用 TypeScript 写 LANrurugi 的元数据 / 登录 / 下载插件。 LANrurugi 的插件是**单个 `.ts` 文件**,放在 `plugins/<类别>/` 下,或者通过设置页面/`POST /api/plugins/upload` 上传(会上传到 `plugins/custom/<类别>/`)。它在**独立的 Deno 子进程**里运行,只带插件自己声明的权限 (`--allow-net` / `--allow-read` 等),拿不到宿主进程的任何东西。 ## 最小插件 [Section titled “最小插件”](#最小插件) 一个插件文件必须导出恰好两样东西: 1. `pluginInfo()`——同步、无副作用,只返回插件自己的元数据:命名空间、名称、参数、声明的权限。 宿主会用一个**零权限**的一次性子进程调用它,就为了读元数据,然后再按声明去申请真正的权限。 2. 对应类型的执行函数——`execMetadata`(元数据抓取)、`execLogin`(登录)、`execDownload`(下载)。 具体签名、类型与每个字段的含义,见 **[SDK 参考](../sdk/)**:它由 `deno doc` 直接从运行时会加载的那份 TypeScript 源码生成,所以不会和实际行为脱节。 ## 权限 [Section titled “权限”](#权限) 插件必须**预先声明**它需要什么,宿主才会授予什么。这是为了让一个行为异常或者恶意的插件没法拖垮宿主进程, 也没法读它不该读的文件。声明之外的任何网络/文件访问都会失败。 ## 调试 [Section titled “调试”](#调试) * 设置页面的插件列表会显示每个插件的 `pluginInfo()` 结果,包括它声明的权限。 * 插件调用失败时,宿主会把子进程的 stderr 一并记录;日志页面按类别可查。 * HTTP 请求走宿主中继,并按需最小化——插件发出的请求由宿主代理,因此插件不需要 `--allow-net` 之外的东西, 也能被统一限流与记录。 ## 下一步 [Section titled “下一步”](#下一步) * [SDK 参考](../sdk/)——所有导出类型与函数,含文档注释。 * [API 参考](../../api/)——`/api/plugins*` 下的端点(列表、上传、执行、导出)。 # SDK 参考 > 插件运行时实际加载的那份 TypeScript 的 API 参考。 插件作者可用的每个类型与函数,都由 `deno doc` 直接从**插件运行时实际加载的那份 TypeScript** (`crates/lanrurugi-plugin/dispatcher/` 下的 `plugin-sdk.ts`、`dispatcher.ts`,以及 `plugins/legacy-globals.d.ts`)生成,所以它不会和真实行为脱节。 [打开 SDK 参考 →](https://sdk.lrrg.dev/) 那份参考里可以搜索符号、按类型/接口/函数分组浏览,也能看到每个符号自身的文档注释。同一份内容还有一个 机器可读的 JSON 版本(`plugin-sdk.json`),便于工具消费。 为什么它不在这个侧栏的页面体系里 `deno doc --html` 产出的是**自成一体的静态站点**(有自己的搜索、暗色模式和符号索引)。把它塞进 Starlight 的布局里意味着重写一遍这些,而不是复用。所以它作为独立站点发布(服务器镜像里位于 `/docs/sdk/`)。 ## 相关 [Section titled “相关”](#相关) * [插件开发入门](../getting-started/)——最小插件、权限模型、调试。 * [API 参考](../../api/)——`/api/plugins*` 下的端点。