• Ronana

    现在比较晚了,我打算早上再折腾一下好好写一下这篇文章

    不过我做了个演示站可以看看

    Demo user name: [[email protected]](https://feedbbs.com/cdn-cgi/l/email-protection)

    Demo user password: Demo@Acgbyte2026

    站点在这里,后续会关闭并清空:https://leilei.xyz/

    目前还有不完善的地方在继续做继续完善。

    先来讲讲目前做了什么:

    1.恢复原有的捐赠版功能(这个不必再说)

    2.新增API接口,这个接口并不是根据原本的接口做的,他是独立于原本的接口,管理员可以在后台配置是否开启全站的API权限,用户侧才能够正常使用,网页端可以做的事情我全部都引出了接口,使用jwt鉴权。

    3.引出主题接口,前两天写komari主题上头了,我觉得还是需要完善的一些针对于前端样式的接口,并且格式要求比较严格,不允许夹带私货(虽然减少了可玩性,但我感觉还行)可以直接上传主题包(这玩意儿最大的作用就是替换掉原本的登录页,我已经不想吐槽原本的登录页修改起来很麻烦了)另外一种则是直接上传css

    4.原本的离线下载就是一个aria2,但我不满意,把qBittorrent也加进去了。

    5.忘了,好像弄了不少的东西,总之先这样吧,丢几个开发文档放这里先看看

    Acgbyte 公共 API 开发文档

    公共 API 是独立兼容层,不会替代网页和客户端使用的 /api/v3 接口。

    一、开启公共 API

    管理员进入:

    管理控制台 -> 站点设置 -> 用户与验证码 -> 启用公共 API 与 JWT 令牌

    关闭总开关后,所有 /api/open/v1/* 请求和新的令牌创建都会返回 CodeFeatureNotEnabled。已有令牌不会删除,重新开启后继续可用。

    二、创建令牌

    登录网页后进入:

    账户设置 -> API 令牌

    创建请求:```
    POST /api/v3/user/setting/api-token
    Content-Type: application/json

    {
    "name": "自动化任务",
    "expires_days": 30
    }

    ```令牌值只返回一次。服务端保存 SHA-256 哈希,可单个撤销。

    三、认证```
    Authorization: Bearer <jwt>

    ``示例:``
    curl \
    -H "Authorization: Bearer $ACGBYTE_TOKEN" \
    https://example.com/api/open/v1/user/storage

    ```服务端会校验:

    - Bearer 方案,大小写不敏感。

    - HS256 签名算法。

    - JWT issuer。

    - 令牌是否过期、是否撤销。

    - 令牌哈希是否匹配。

    四、接口范围

    公共 API 会复用网页接口的权限检查和业务逻辑:

    - GET /api/open/v1/site/config

    - GET /api/open/v1/site/themes

    - GET /api/open/v1/user/storage

    - GET /api/open/v1/user/setting

    - GET /api/open/v1/user/setting/policies

    - PATCH /api/open/v1/user/setting/policy

    - GET|PUT|PATCH|DELETE /api/open/v1/directory*

    - GET|POST|PUT|PATCH|DELETE /api/open/v1/object*

    - GET|POST|PUT|PATCH|DELETE /api/open/v1/file*

    - GET|POST|PUT|PATCH|DELETE /api/open/v1/share*

    - GET|POST|PUT|PATCH|DELETE /api/open/v1/vas*

    - GET|POST|PUT|PATCH|DELETE /api/open/v1/webdav*

    - GET|POST|PUT|PATCH|DELETE /api/open/v1/aria2*

    管理接口、从机接口、回调接口、WOPI 内部接口和验证码验证接口不会开放。

    五、示例

    列出根目录:```
    curl \
    -H "Authorization: Bearer $ACGBYTE_TOKEN" \
    "https://example.com/api/open/v1/directory/&quot;

    ``创建目录:``
    curl -X PUT \
    -H "Authorization: Bearer $ACGBYTE_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"path":"/API/Projects"}' \
    https://example.com/api/open/v1/directory

    ``创建文本文件:``
    curl -X POST \
    -H "Authorization: Bearer $ACGBYTE_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"path":"/API/Projects/readme.txt"}' \
    https://example.com/api/open/v1/file/create

    ``添加离线下载任务:``
    curl -X POST \
    -H "Authorization: Bearer $ACGBYTE_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"url":["magnet:?xt=urn:btih:..."],"dst":"/Downloads"}' \
    https://example.com/api/open/v1/aria2/url

    ``查询会员商品并购买:``
    curl \
    -H "Authorization: Bearer $ACGBYTE_TOKEN" \
    https://example.com/api/open/v1/vas/product

    curl -X POST \
    -H "Authorization: Bearer $ACGBYTE_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"action":"pack","method":"score","id":1,"num":1}' \
    https://example.com/api/open/v1/vas/order

    ```六、完整主题桥接

    沙箱主题通过 postMessage 使用同一组允许路径,不需要也不应该获取 JWT。完整协议见 THEME_DEVELOPMENT.md。

    七、安全规则

    - 令牌继承用户组权限和存储策略权限。

    - 请求路径会被规范化,编码目录穿越、反斜杠、空字节和未知路径会被拒绝。

    - 管理接口永远不会被代理。

    - 撤销令牌后,下一次请求立即失效。

    - 不要把令牌写入前端源码、日志、截图或公开地址。

    Acgbyte 主题开发文档

    Acgbyte 支持两类主题包:

    - tokens:CSS 变量主题,扩展内置 Vue 界面。

    - bundle:完整 HTML/CSS/JavaScript 主题,在隔离 iframe 中运行,并通过受控消息桥调用允许的前台 API。

    一、主题包目录

    仓库内附带了可直接上传的测试包:theme-packages/。其中包括变量主题、完整应用主题、登录文案主题和仅登录页主题。

    变量主题```
    theme.zip
    ├── theme.json
    ├── theme.css
    └── assets/
    ├── preview.webp
    └── custom-font.woff2

    ```theme.json 示例:```
    {
    "id": "my-theme",
    "name": "我的主题",
    "version": "1.0.0",
    "author": "作者",
    "description": "主题说明",
    "mode": "light",
    "type": "tokens",
    "preview": "assets/preview.webp",
    "copy": {
    "brand.tagline": "Acgbyte Cloud",
    "hero.title": "让文件协作更从容",
    "form.title": "登录你的空间",
    "form.submit": "进入空间"
    }
    }

    ``完整页面主题``
    full-theme.zip
    ├── theme.json
    ├── theme.css
    ├── index.html
    ├── theme.js
    └── assets/
    └── cover.webp
    ```theme.json 示例:```
    {
    "id": "full-theme",
    "name": "完整页面主题",
    "version": "1.0.0",
    "author": "作者",
    "description": "独立前端主题",
    "mode": "dark",
    "type": "bundle",
    "entry": "index.html",
    "surfaces": ["app", "login"]
    }
    ```二、包格式与校验规则

    - id 只能使用小写字母、数字和连字符,匹配 [a-z][a-z0-9-]{1,39}。

    - tech、anime、minimal 是内置主题 ID,不能覆盖。

    - mode 可为 light、dark 或 auto。

    - type 可为 tokens 或 bundle。

    - tokens 必须包含 theme.json 和 theme.css。

    - bundle 还必须包含入口 HTML,默认入口为 index.html。

    - 静态资源必须位于 assets/ 下,允许 PNG、JPG、JPEG、WEBP、SVG、WOFF、WOFF2、TTF、JSON。

    - ZIP 最大 8 MB,解压后最大 24 MB,最多 64 个文件。

    - CSS 不允许 @import、外链 HTTP/HTTPS、javascript:、expression()、behavior:、-moz-binding。

    三、登录页文案接口

    内置登录页提供稳定的语义钩子:```
    <main data-page="login" data-surface="login" data-theme-id="my-theme">
    <span data-theme-copy="hero.title">...</span>
    </main>
    ``变量主题可以在 theme.json 的 copy` 中覆盖以下文案:

    文案键 |
    用途 |

    brand.tagline |
    品牌副标题 |

    hero.badge |
    登录主标题上方标签 |

    hero.title |
    登录主标题 |

    hero.description |
    登录介绍 |

    feature.security.title |
    安全功能标题 |

    feature.security.description |
    安全功能说明 |

    feature.login.title |
    登录功能标题 |

    feature.login.description |
    登录功能说明 |

    feature.transfer.title |
    传输功能标题 |

    feature.transfer.description |
    传输功能说明 |

    form.title |
    登录表单标题 |

    form.description |
    登录表单说明 |

    form.emailLabel |
    邮箱字段标题 |

    form.emailPlaceholder |
    邮箱占位文字 |

    form.passwordLabel |
    密码字段标题 |

    form.passwordPlaceholder |
    密码占位文字 |

    form.captchaLabel |
    人机验证字段标题 |

    form.captchaReady |
    验证完成文案 |

    form.captchaRequired |
    待验证文案 |

    form.submit |
    登录按钮 |

    form.forgotPassword |
    找回密码链接 |

    form.noAccount |
    注册提示 |

    form.createAccount |
    注册链接 |

    form.twoFactorTitle |
    两步验证标题 |

    form.twoFactorDescription |
    两步验证说明 |

    form.twoFactorPlaceholder |
    两步验证码占位文字 |

    form.twoFactorSubmit |
    两步验证提交按钮 |

    form.twoFactorBack |
    返回密码登录 |

    footer.brand |
    桌面端页脚品牌文字 |

    文案只能使用纯文本,不能包含控制字符;未知键或超长内容会被拒绝。

    四、CSS 变量接口

    主题 CSS 应作用在主题 ID 上:```
    [data-app-theme="my-theme"] {
    --background: #f5f7ff;
    --foreground: #172033;
    --surface: #ffffff;
    --surface-muted: #eef1fa;
    --surface-raised: #ffffff;
    --muted: #68708a;
    --border: #dce1ef;
    --primary: #3157d5;
    --primary-strong: #2446b8;
    --primary-foreground: #ffffff;
    --accent: #ef6c5a;
    --accent-soft: #fff0ed;
    --danger: #c63e4a;
    --danger-soft: #fff0f2;
    --success: #2f8a63;
    --warning: #a77924;
    --ring: rgba(49, 87, 213, 0.24);
    --shadow-sm: 0 1px 2px rgba(15, 24, 52, 0.06);
    --shadow-md: 0 20px 48px rgba(15, 24, 52, 0.12);
    --radius: 0.75rem;
    --page-background: #f5f7ff;
    --panel-texture: none;
    --display-font: "Noto Sans SC", sans-serif;
    }
    ``动画变量:``
    [data-app-theme="my-theme"] {
    --motion-fast: 150ms;
    --motion-normal: 240ms;
    --ease-standard: cubic-bezier(0.2, 0.8, 0.2, 1);
    --ease-emphasized: cubic-bezier(0.16, 1, 0.3, 1);
    }
    ``主题资源地址:``
    [data-app-theme="my-theme"] .theme-panel {
    background-image: url("/api/v3/site/theme-asset/my-theme/assets/texture.webp");
    }
    ```五、完整主题运行环境

    surfaces 控制主题接管范围:

    - app:登录后的应用页面。

    - login:登录、注册、找回密码和重置密码页面。

    管理控制台始终使用内置界面,不会加载完整主题。

    完整主题 iframe 使用:```
    sandbox="allow-scripts allow-forms allow-modals"
    ```主题不能读取 Cookie、localStorage、父页面 DOM,也不能直接发起外部网络请求。服务端同时下发 CSP、禁止对象嵌入和顶部跳转。

    六、主题消息桥

    主题脚本发送 ready:```
    parent.postMessage({ source: "acgbyte-theme", type: "ready" }, "*");
    ``宿主会发送 context,包含 siteConfig、user、storage 和 theme。上下文也会在 iframe load` 时发送。

    调用允许的前台接口:```
    const requestId = crypto.randomUUID();

    window.addEventListener("message", (event) => {
    if (
    event.data?.source === "acgbyte-host" &&
    event.data?.type === "response" &&
    event.data.requestId === requestId
    ) {
    const response = event.data.data;
    console.log(response?.data ?? response);
    }
    });

    parent.postMessage({
    source: "acgbyte-theme",
    type: "request",
    requestId,
    method: "GET",
    path: "/site/config"
    }, "*");
    ``桥接响应保留普通 /api/v3 响应结构。读取 code 判断状态,读取 data` 获取业务数据。

    允许的接口前缀:

    - /site/

    - /user/

    - /directory

    - /object/

    - /file/

    - /share/

    - /vas/

    - /webdav/

    - /aria2/

    管理接口、从机接口、回调接口、验证码验证接口和内部接口始终禁止访问。桥接会拒绝外部地址、编码目录穿越、反斜杠、空字节和过大的请求体。

    主题页面导航:```
    parent.postMessage({
    source: "acgbyte-theme",
    type: "navigate",
    path: "/home"
    }, "*");
    ```七、管理接口

    - GET /api/v3/site/themes:已安装主题和当前默认主题。

    - GET /api/v3/site/theme.css?id=my-theme:读取变量主题 CSS。

    - GET /api/v3/site/theme-bundle/:id/:path:读取完整主题文件。

    - GET /api/v3/admin/themes:后台主题列表。

    - POST /api/v3/admin/theme/upload:上传 ZIP,字段名 file。

    - PATCH /api/v3/admin/theme/activate/:id:设为默认主题。

    - DELETE /api/v3/admin/theme/:id:删除上传主题。

    八、安装主题

    进入 管理控制台 -> 站点设置 -> 主题与视图 -> 主题包,上传 ZIP,然后选择 设为默认。内置主题始终保留,不能删除。

    主楼
  • 祈雪于凛冬

    ^-^

    #1
  • isyv

    bd

    #2
  • 活在梦里怎么了

    ^-^

    #3
  • Ronana
  • Ronana

    bug确实还有不少,还在折腾

    #5
  • Ronana

    图片

    不过我是真的喜欢这种风格,以及这个dock栏

    #6

发表回复

登录后回复