{{ crumb.t }}
{{ crumb.s }}
{{ h.kind }}
{{ h.title }}{{ h.sub }}
没有匹配「{{ gq }}」的内容
{{ disk ? fmtSize(disk.free) : '…' }}空闲
{{ hasFfmpeg ? 'ffmpeg' : '无ffmpeg' }}
{{ appVer ? 'v'+appVer.versionName : '未发布' }}
{{ a.t }}{{ a.s }}
{{ a.label }}
线路配置
{{ lines.length }}条
使用中 {{ onLines.length }} · 已停用 {{ lines.length - onLines.length }} · 检测异常 {{ badChecks.length }}
爬虫代码
{{ codes.length }}个
未被线路引用 {{ unusedCodes.length }} · 所属线路已停用 {{ disabledCodes.length }}
本地视频
{{ videos.length }}个
剧集 {{ epGroups.length }} 部 · 共 {{ totalVidSize }} · 未分类 {{ uncatVids.length }}
磁盘可用
{{ fmtSize(disk.free) }}
—
{{ disk ? '共 '+fmtSize(disk.total)+' · 已用 '+diskUse+'% · '+(hasFfmpeg?'ffmpeg 就绪':'未装 ffmpeg') : '读取中…' }}
线上 App 版本
v{{ appVer.versionName }}
未发布
{{ appVer ? appVer.filename + ' · ' + fmtSize(appVer.size) : 'App 端检测不到更新' }}
线路健康管理全部线路 →
还没有线路文件
{{ f.name }}
{{ f.note || '无备注' }} · {{ checks[f.name] ? checks[f.name].msg : '未检测' }}
最近上传进入视频库 →
还没有上传过视频
本地媒体线路
{{ info.line || '—' }}
TVBox 系 / 桌面版 / 闭原版通用 · 上传视频自动更新 · 当前收录 {{ info.count || 0 }} 个视频
红果取址刷新
代理模块(手机)
{{ relay ? (relay.agent_alive ? '在线 · 心跳 ' + relay.agent_age + ' 秒前' : '离线 · 超过 15 秒无心跳') : '读取中…' }}
签名机 APK
{{ relay ? (relay.signer_alive ? '在线 · ' + relay.signer_age + ' 秒前活跃' : '离线') : '读取中…' }}
今日取址成功 {{ relay.ok_count }} 次 · 失败 {{ relay.fail_count }} · agent 配额 {{ relay.quota_used }}/{{ relay.quota_cap }} · 健康 {{ relay.health }}{{ relay.why ? '(' + relay.why + ')' : '' }}
快捷操作
线路
上传视频
新建文件
重建线路
下载备份
回收站
{{ hasFfmpeg ? "ffmpeg 已就绪: 支持自动截帧封面 / 720p 压缩" : "未检测到 ffmpeg: 截帧封面与 720p 压缩不可用" }}
| 线路 / 备注 | 类型 | 启用 | 连通检测 | 大小 / 修改 | 操作 | |
|---|---|---|---|---|---|---|
|
{{ f.name }}
{{ f.url }}
{{ f.note || '+ 添加备注' }}
|
{{ f.auto ? '系统' : ext(f.name) }} | {{ f.enabled ? '使用中' : '已停用' }} | {{ checks[f.name].msg }} |
{{ fmtSize(f.size) }}
{{ fmtTime(f.mtime) }}
|
|
没有符合当前筛选条件的线路(关键词「{{ lineQ }}」)
还没有线路文件,点击右上角「+ 新建线路」创建
● 未保存
● 已保存, 待重启生效
{{ cur }} · Ctrl+S 保存{{ srcMode ? ' (需口令, 重启才生效)' : '' }}
{{ srcPending.length }} 个文件已存盘但未生效{{ srcPending.join('、') }} —— 进程里还是旧代码,点右上「重启服务生效」才会换过来
保存 = 语法检查(编译不执行) + 备份到 backups/src/(每个模块留最近 20 份),都要再输一次登录口令。
语法错会被拦下,运行时的错拦不住 —— 重启前先在本地把这条模块跑通。
| 模块 | 作用 | 大小 | 修改时间 | 操作 |
|---|---|---|---|---|
| {{ f.name }} | {{ f.desc }} 已保存未生效 这台机器没有 在跑 | {{ f.exists ? fmtSize(f.size) : '—' }} | {{ f.exists ? fmtTime(f.mtime) : '—' }} |
|
正在读取模块清单…
上一个包没装上{{ pkg.bad }}
知道了
这台机器没有 uvpy 线路包装依赖改走系统 python 的 venv + pip,一样能装、只是慢一些;装上 uv 会快很多。js 线路包不受影响
py 包没隔离{{ pkg.sandbox.why }} —— 这台机器上的包能互相读代码,也能读到瓶子的口令;要收别人上传的包,先按提示把隔离开起来
{{ pkgName ? pkgName : '把线路包拖到这里,或点一下选文件' }}
{{ fmtSize(pkgSize) }} · 移除
.zip · 最大 {{ fmtSize(pkg.cap) }} · 装好立刻生效,不用重启服务
给别人开放上传
{{ apiKeys.length ? (apiKeys.length + ' 把 API Key 已生成') : '还没生成 API Key' }}
系统只有你一个管理员,装包直接拖进来即可。要把上传权限发给别人,去「OpenAPI」生成 API Key,他拿 Key 调开放接口就能上传线路包,动不了别的管理功能。
| 线路包 / 填进 App 的地址 | 类型 | 版本 | 启用 | 进聚合线路 | 运行状态 | 操作 |
|---|---|---|---|---|---|---|
|
{{ p.name }}
{{ pkgAddr(p) }}
挂载 {{ p.mount.join(' ') }}
{{ p.desc }}
|
{{ p.kind.toUpperCase() }} | {{ p.version }} | {{ p.enabled ? '使用中' : '已停用' }} | {{ !p.enabled ? '未生效' : (p.in_line ? '已进' : '未进') }} |
{{ pkgRun(p).text }}
{{ pkgRun(p).msg }}
|
|
包结构: plugin.json(清单: id / kind=js|py / name / line / 版本) + 线路配置 + 爬虫。
一个包只能带自己的爬虫: 站点 api 指向别人的服务器、带 jar、混第二条线路,装的时候一律拒绝。
js 包整份下发到 App 里跑 —— 谁拿到线路都能把代码抄走,想防抄就用 py 包(爬虫留在服务器上,App 只拿到壳)。
包默认只发给拿到这个地址的人。想让用这台机器的所有人都拿到它,再单独勾「进聚合线路」;不勾就谁传上来的包都不会变成你分发的线路。
js 包整份下发到 App 里跑 —— 谁拿到线路都能把代码抄走,想防抄就用 py 包(爬虫留在服务器上,App 只拿到壳)。
包默认只发给拿到这个地址的人。想让用这台机器的所有人都拿到它,再单独勾「进聚合线路」;不勾就谁传上来的包都不会变成你分发的线路。
| 代码文件 | 被这些线路引用 | 大小 | 修改时间 | 操作 |
|---|---|---|---|---|
| {{ c.name }} | {{ u }} 未被线路引用 所属线路已停用 | {{ fmtSize(c.size) }} | {{ fmtTime(c.mtime) }} |
|
没有符合当前筛选条件的代码文件
暂无代码文件,点击右上角「+ 新建代码」创建
官方线路地址(TVBox 系 / 桌面版 通用,点击复制)
{{ linksLine }}
| 并入的线路 json | 站点 | 操作 |
|---|---|---|
| {{ j.name }} | {{ j.sites.length }} 个 · {{ jJar(j) }} 个 jar 源(电脑端跑不了) |
|
| 名称 | 视频链接 | 所属剧集 | 分类 | 操作 |
|---|---|---|---|---|
| {{ x.name }} | {{ x.url }} | {{ x.group || '—' }}{{ x.ep ? ' · 第' + x.ep + '集' : '' }} | {{ x.cat || '—' }} |
|
没有符合筛选条件的链接
官方线路还是空的 — 点右上角「+ 添加链接」粘贴视频直链, 或粘贴一条别人的线路 json, App 里点开即播
瓶子只做分发, 直链要播放器自己能连上; 需要代理请自带 js 源
瓶子只做分发, 直链要播放器自己能连上; 需要代理请自带 js 源
公告下发地址(客户端免登录 GET,?end=android / pc / tv;不带 end 回全部)
{{ noticeFeed }}
| 标题 / 正文 | 发到哪些端 | 启用 | 更新 | 操作 |
|---|---|---|---|---|
|
{{ n.title }}
{{ n.body }}
|
{{ noticeEndName(e) }} | {{ n.enabled ? '下发中' : '已停用' }} | {{ fmtTime(n.updated) }} |
|
还没有公告 — 点右上角「+ 发布公告」写一封,勾选要发给哪几个端,手机端/PC端/TV版 启动后各弹一次
同一封弹过就不再弹;改了正文或停用过再启用,「更新时刻」变、客户端才会当成新的一次再弹
同一封弹过就不再弹;改了正文或停用过再启用,「更新时刻」变、客户端才会当成新的一次再弹
松开鼠标, 上传视频文件
将打开上传设置弹窗
本地媒体线路地址(TVBox 系 / 桌面版 / 闭原版 通用,点击复制)
{{ info.line }}
当前条件命中 {{ filtVideos.length }} 个视频 · 分类「{{ activeCat }}」 · 关键词「{{ videoQ }}」
▶
荐
{{ c.v.name }}
▶
共{{ c.eps.length }}集
{{ c.name }}
{{ c.cat }}
{{ c.eps.length }} 集 · 点击管理
封面片名 / 文件名分类
所属剧集大小修改时间操作
没有符合当前条件的视频
视频库为空,点击右上角「上传视频」添加第一个视频
也可以直接把视频文件拖到这里
支持 mp4 / mkv / webm / mov / avi / ts
当前线上版本(App 启动后自动检测, 无需任何配置)
v{{ appVer.versionName }}
{{ appVer.filename }} · {{ fmtSize(appVer.size) }}
· {{ appVer.note }}
尚未发布版本,App 端检测不到更新
PC 桌面版(桌面端启动后自动检测, 设置里可手动检查)
v{{ pcVer.versionName }}
{{ pcVer.filename }} · {{ fmtSize(pcVer.size) }}
· {{ pcVer.note }}
这条版本线还没发包,桌面版检测不到更新
命名规则: 文件名需含版本号, 如 MyApp_v2.1.44.apk、MyApp_v2.0.1.exe(版本号从文件名自动解析, 上传即覆盖旧版本)。
App 端零配置: 启动后自动比对线路源版本号, 有新版本弹窗提示下载安装; 「我的 → 检查更新」可手动检测。
PC 端: 上传 Inno Setup 安装包 (.exe), 桌面版启动后自动检测, 有新版本在设置页提示下载并静默安装。
App 端零配置: 启动后自动比对线路源版本号, 有新版本弹窗提示下载安装; 「我的 → 检查更新」可手动检测。
PC 端: 上传 Inno Setup 安装包 (.exe), 桌面版启动后自动检测, 有新版本在设置页提示下载并静默安装。
还没有 API Key右边生成一把, 发给要上传线路包的人; 他拿 Key 调开放接口就能传包, 动不了别的管理功能。
给别人开放上传
系统只有你一个管理员, 自己装包去「线路包」页拖进来就行, 用不着任何口令。
要让别人也能传包: 生成一把 API Key 发给他, 他拿 Key 调
要让别人也能传包: 生成一把 API Key 发给他, 他拿 Key 调
POST /openapi/pkgUpload 传 .zip 即可, 装好立刻生效 ——
除了传包什么都干不了, Key 随时可以吊销。
curl -X POST '{{ apiBase }}/openapi/pkgUpload' \
-H 'X-API-Key: 你的Key' \
-F 'file=@线路包.zip'
接口文档(免登录, 可直接发给别人看):{{ apiBase }}/openapi/docs
生成新的 API Key
完整 Key 只显示一次, 生成后立即复制
| 备注 | Key(掩码) | 创建时间 | 最近使用 | 操作 |
|---|---|---|---|---|
| {{ k.name || '未命名' }} | {{ k.key_mask }} | {{ fmtTime(k.created) }} | {{ k.last_used ? fmtTime(k.last_used) : '从未使用' }} |
还没有密钥 —— 上面生成一把就有了
用户管理
在线客户端
注册账号
按客户端 IP(设备)统计 —— App 不登录时, 服务端能认的唯一身份就是 TCP 对端地址; 同一个 WiFi 下的多个人会算成一个用户。
同一台机器上并存的几个端(手机短剧接口 / 播放器 / PC)按 UA 分开计数, 不再被最后一条请求抹掉。
这一维是 App「我的」页里注册的账号: 看它登在几台设备、存了多少历史收藏, 能踢下线、停用、删号。
停用会让它手上没吊销的登录当场失效, 恢复后这些设备不用重新登录。
当前 {{ onlineCount }} 个在线 · 5 分钟内有请求算在线 · 页面每 5 秒自动刷新
共 {{ accStats.users }} 个账号 · 有效登录 {{ accStats.devices }} 台 · 存了 {{ accStats.items }} 条数据 · {{ accStats.comments }} 条评论 · 停用中 {{ accStats.banned }} 个
封禁名单({{ onlineBanned.length }})
封掉后对方请求线路直接 403(含线路包自己挂载的取址口), 后台管理端不受影响。
{{ b }}
还没有封任何人
停用中的账号({{ accBanned.length }})
停用不改密码也不删数据, 恢复后设备上的登录接着能用。
{{ a.nick || a.name }}
没有在停用的账号
| 客户端 | 当前线路 | 状态 | 几个端在用它 | 最近请求 | 最近活跃 | 请求数 | 操作 |
|---|---|---|---|---|---|---|---|
| {{ u.ip }}
见于 {{ fmtTime(u.first_seen) }} |
{{ u.line || u.top_line || '—' }} | 已封禁 在线 离线 | {{ tag }} ×{{ n }} — |
{{ u.last_path || '—' }}
{{ Object.entries(u.api).slice(0,3).map(kv => kv[0] + '×' + kv[1]).join(' · ') }}
|
{{ fmtIdle(u.idle) }} | {{ u.reqs }} |
{{ onlineAll ? '最近 24 小时没有客户端请求过线路' : '当前没有在线客户端 —— 5 分钟内有请求就会出现在这里(服务重启前记过的客户端也从磁盘读回来了)' }}
| 账号 | 状态 | 设备 | 最后活跃 | 注册于 | 存了什么 | 操作 |
|---|---|---|---|---|---|---|
| {{ a.nick || a.name }}
登录名 {{ a.name }} · uid {{ a.uid }} |
已停用 正常 | {{ a.devices }} 台 | {{ a.active_at ? fmtIdle(nowSec() - a.active_at) : '没登录过' }} | {{ fmtTime(a.created) }} | {{ kindName(k) }} {{ n }} |
{{ accQ ? '没有匹配「' + accQ + '」的账号' : '还没有人注册账号 —— App 里「我的」页注册了才会出现在这里' }}