from __future__ import annotations from fastapi import APIRouter, Request from fastapi.responses import HTMLResponse router = APIRouter() def _build_docs_html(*, base_url: str) -> str: base = (base_url or "").rstrip("/") if not base: base = "" def u(path: str) -> str: path_norm = (path or "").strip() if not path_norm.startswith("/"): path_norm = "/" + path_norm return f"{base}{path_norm}" examples = { "img_default": u("/random"), "img_proxy_cat": u("/random?proxy=i-pixiv-cat"), "img_pixiv_cat": u("/random?pixiv_cat=1"), "img_pixiv_re": u("/random?pixiv_cat=1&pximg_mirror_host=re"), "img_redirect": u("/random?redirect=1"), "rec_tune": u( "/random?strategy=quality&rec_pick_mode=weighted&rec_temperature=1" "&rec_w_freshness=2&rec_fresh_half_life_days=14" "&rec_w_bookmark_velocity=2&rec_velocity_smooth_days=2" ), "status": u("/status"), "status_json": u("/status.json"), "wtf": u("/wtf"), "wtf_r18": u("/wtf?r18=1"), "json_full": u("/random?format=json"), "json_simple": u("/random?format=simple_json"), "r18_only": u("/random?r18=1"), "safe_only": u("/random?r18=0"), "any_r18": u("/random?r18=2"), "portrait": u("/random?orientation=portrait"), "landscape": u("/random?orientation=landscape"), "adaptive": u("/random?adaptive=1"), "tag_loli": u("/random?included_tags=loli"), "pure_random": u("/random?strategy=random"), "quality_strong": u( "/random?strategy=quality&quality_samples=200&min_pixels=2000000&min_bookmarks=100&illust_type=illust&ai_type=0" ), "complex": u("/random?r18=1&illust_type=illust&orientation=portrait&min_pixels=2500000&min_bookmarks=2&min_comments=5&included_tags=loli"), "tags_api": u("/tags"), "authors_api": u("/authors"), "swagger": u("/api/docs"), "openapi": u("/openapi.json"), } return f""" Random Mage Docs

Random Mage · 随机图片 API

质量优先随机 + 强力筛选,支持标签/热度/分辨率/R18/AI/作品类型等组合查询。

1) 最常用(直接出图)

默认返回图片(不是 JSON)。想要稳定 URL 可加 redirect=1 跳转到本站缓存/代理路径。

{examples["img_default"]}
{examples["img_pixiv_cat"]}
{examples["img_pixiv_re"]}
{examples["img_redirect"]}

2) JSON / 调试信息

format=json 返回完整数据(含 tags / debug);format=simple_json 更轻量。

{examples["json_full"]}
{examples["json_simple"]}

3) R18 / 作品类型 / AI

R18 用 r18 控制:0=仅全年龄(默认),1=仅R18,2=都可。

{examples["safe_only"]}
{examples["r18_only"]}
{examples["any_r18"]}
提示:如果你库里有不少作品还没补全 x_restrict,且你想“更容易命中”,可用 r18=0&r18_strict=0(允许未知的 x_restrict)。

4) 横竖图 / 自适应

orientation 支持:any / portrait / landscape / square。自适应用 adaptive=1:移动端默认竖图+更低像素门槛,PC 默认横图+更高门槛(不会覆盖你显式传入的过滤条件)。

{examples["portrait"]}
{examples["landscape"]}
{examples["adaptive"]}

5) 状态页 / 瀑布流

/status 为公开仪表盘:展示 API 状态、图库概览、/random 请求统计;/status.json 为机器可读 JSON。

{examples["status"]}
{examples["status_json"]}

/wtf 为瀑布流:支持 /random 的全部过滤参数(例如 r18/标签/分辨率/热度/排除标签等),默认会补上 adaptive=1 以更适合不同屏幕。

/wtf 额外支持布局参数:view=single|masonry|tiles,以及 wtf_mcols/wtf_mgap/wtf_tcols/wtf_tgap/wtf_tratio(仅影响页面布局)。另有 wtf_gender=girls|boys 与概要标签 @male/@female(仅 /wtf 端展开,用于快速“只看女生/只看男生”)。

{examples["wtf"]}
{examples["wtf_r18"]}

筛选语法速记

标签 AND / OR 速记: AND 用“重复参数”(例如 included_tags=a&included_tags=b), OR 用同一参数里的 |(例如 included_tags=a|b)。 如果你的客户端不方便输入 |,也可以写成 %7C。
参数 说明
strategy 随机策略:quality(默认,质量优先) / random(纯随机)。
quality 会先抽样 N 张候选再按热度/分辨率打分选图。
proxy 指定本次请求的图片上游镜像(优先级最高)。会隐式开启第三方镜像(等价于 pixiv_cat=1),并覆盖地区自动选择。
内置值:cat/re/nl,也支持 pixiv-cat/i-pixiv-cat 等写法。
自定义镜像:可填写你自建镜像域名(需在管理端“自定义镜像白名单”允许)。
示例:{examples["img_proxy_cat"]}
pixiv_cat 0/1:强制使用第三方反向代理拉取图片上游(即使全局未开启)。
上游可为 i.pixiv.cat / i.pixiv.re / i.pixiv.nl。
未指定 pximg_mirror_host 时:大陆访问优先 i.pixiv.re,非大陆默认 i.pixiv.cat。
仅影响服务端拉图的上游域名,客户端仍访问本站域名。
pximg_mirror_host 指定镜像域名(可选):i.pixiv.cat / i.pixiv.re / i.pixiv.nl,也支持简写 cat/re/nl。
示例:{examples["img_pixiv_re"]}
quality_samples 质量抽样数量(1–1000)。越大越“挑剔”,但 DB 开销也更高。
示例:{examples["quality_strong"]}
included_tags 必须包含的标签:参数之间是 AND,单个参数内用 | 表示 OR。
例:included_tags=girl|boy&included_tags=white|black 表示 (girl OR boy) AND (white OR black)。
提示:URL 里的 & 是“参数分隔符”,要写 AND 就重复参数;要写 OR 就在同一参数里用 |。
示例:{examples["tag_loli"]}
excluded_tags 必须不包含的标签:任意命中即排除。可重复传参:excluded_tags=a&excluded_tags=b。
excluded_tags=a|b 等价于排除 a 或 b(效果同上)。
min_width
min_height
min_pixels
分辨率门槛:宽/高/像素数(例如 2000000 ≈ 2MP)。
min_bookmarks
min_views
min_comments
热度门槛:收藏/浏览/评论(需要补全元数据后更准确)。
ai_type any / 0(非AI) / 1(AI)。
illust_type any / illust / manga / ugoira。
user_id 只返回某个作者的作品(Pixiv 用户 ID)。
created_from
created_to
按发布时间筛选(ISO8601,例如 2024-01-01T00:00:00Z)。
seed 固定随机种子(同参数 + 同 seed 更容易复现)。
attempts 上游失败时重试次数(1–10)。
推荐策略 URL 覆盖(rec_*)
这些参数仅影响本次请求,不需要登录,也不会修改后台默认配置:
  • rec_pick_mode: best / weighted
  • rec_temperature: 随机温度(越小越“挑最高分”)
  • rec_w_*: 覆盖 score_weights(如 rec_w_bookmark / rec_w_freshness)
  • rec_m_*: 覆盖 multipliers(如 rec_m_ai / rec_m_manga)
  • rec_fresh_half_life_days: 新鲜度半衰期(天)
  • rec_velocity_smooth_days: 增长率平滑(天)
示例:{examples["rec_tune"]}

复杂示例(组合查询)

示例:R18 + 插画 + 竖图 + 250万像素以上 + 收藏≥2 + 评论≥5 + 标签包含 loli(直接出图)。

{examples["complex"]}

6) 管理端导入(可选)

管理端支持从文件批量导入图片链接:.txt(每行一个 URL)或 PixivBatchDownloader 导出的 .json。

""" @router.get("/docs", include_in_schema=False) async def docs_page(request: Request) -> HTMLResponse: html = _build_docs_html(base_url=str(getattr(request, "base_url", "") or "").rstrip("/")) return HTMLResponse(content=html, status_code=200, headers={"Cache-Control": "no-store"})