Repository navigation
Releases: Dresteam/MisMiss
Release list
v1.6.0
🚀 MisMiss v1.6.0 — 临期会提醒,备注能写清
安全加固 · 开播临期提示 · 账户备注与昵称 · 直播间信息插件
v1.6.0 把「安全」和「日常使用」一起补了一轮:修掉一批能把面板凭据读走、
把插件装到账户目录之外、把消息接收循环打死的问题;同时加上开播临期提醒、
账户备注/昵称编辑,以及一个新的「直播间信息」插件。
🔐 安全修复
- 插件 zip 解压的 Zip Slip:解压改为逐成员校验,tar 走
filter="data";
安全路径实现收敛到核心层唯一一份,路由层不再各写一套。 - 插件名目录穿越:
metadata.yaml的name与 API 传入的插件名统一白名单,
安装/更新/卸载/数据目录全部经realpath + commonpath断言,../../不再能
删改账户目录之外的文件。 - 面板静态兜底目录穿越:SPA 的
full_path先resolve()再断言仍在
web/frontend/dist内,../../../data/panel.json这类匿名读取被拒绝。 - 认证接口角色越权:
/api/auth/change-password只认管理员令牌;
匿名可触达的skip-first-login改为自行校验管理员令牌。 - 未 join 的直播间不再 500:
/api/accounts/{id}/live读主播 ID 时兜住
CoreApiException,平台风控期间账户详情页不会整页挂掉。 - WebSocket 断线补发方向修正:重连时补的是
last_seq之后的日志,而不是
更早的旧日志。 - 插件重载不再丢启用状态:
reload_plugin在卸载前读取was_enabled。 - 异常隔离:单个事件处理器抛错不再中断同事件的其他监听器;指令缺参只记
warning,不会再把该账户的弹幕接收循环打死。
⏳ 开播临期提示
直播间开播的瞬间检查账户剩余有效期:不足 3 天时,自动在直播间发一条
续期提醒。默认开启,同一场直播只提醒一次,下播后再开播可再次提醒。
- 开关存在账户级偏好
expiry_notice_enabled,管理员与账户本人都能关; - 老账户没有这个字段时按「开启」处理,功能上线即生效;
- 位置:账户概览「订阅」卡片、账户端首页「账户偏好」、管理端「编辑账户资料」。
🏷️ 账户备注与昵称
- 管理端可为每个账户写独立备注(仅面板可见,不参与登录、不发给平台),
总览卡片与详情页展示,搜索框也能按备注命中。 - 管理端可直接修改账户昵称;登录用户名保持不变,仍走「重置登录凭据」。
- 新增「编辑账户资料」弹窗,昵称、备注、临期提示开关一处置齐。
🔌 新插件:直播间信息
发送 直播间(别名 直播数据)输出实时数据卡片,默认仅房管/主播可用:
@触发人
直播间数据:
🎤分区:情感-闲聊
⏰直播时长:02:07:17
👪累计人数:42
💗关注数:576
☀️热度:2146
👩超粉:0
🍁贵宾:1
🏅️小时榜:暂无
💰小时榜差值/距离上榜:2015
📛勋章:z野玫瑰
数据走猫耳公开接口,分区/时长/人数/热度/超粉/贵宾/小时榜/勋章均为真实字段;
平台没有提供的分区排名、热度排名、Banner 位、推荐位、福星榜、PK 胜率
直接不输出。支持冷却、缓存、超长按行拆分,以及房管白名单。
🚦 出站节流与面板体验
- 出站请求改为双车道:交互消息降速不停,后台轮询在平台限流时直接让路;
- 新增在途并发上限与退避升档冷却,压住「限流 → 更多请求 → 更紧限流」的正反馈;
- 日志页、账户筛选、更新页与移动端排版的一批改进同步进入本版本。
🧪 测试
test/ 下 36 个脚本全部通过,其中新增:
test_security_fixes.py— 目录穿越、Zip Slip、认证角色、WS 补发等回归;test_expiry_notice.py— 临期判定、同场去重、开关与边界;test_account_remark.py/test_account_profile_api.py— 备注、昵称、偏好接口;test_room_info_plugin.py— 数据解析、输出格式、权限/冷却、消息拆分。
⚠️ 已知限制
- 面板保存设置仍会用
yaml.dump整表重写config.yml,注释会丢失; - 「直播间信息」插件不输出猫耳公开接口没有的排名/推荐位/福星榜/PK 胜率字段。
MisMiss v1.6.0 — 该提醒的提醒,该藏好的藏好 🚀
v1.5.3-alpha.2
这是一个内部测试版本,请不要下载
v1.5.2
🧭 MisMiss v1.5.2 — 有指引了
账户端的操作指引 · 创建账户后弹出凭据 · 账号卡片带编号
v1.5.2 的主角是操作指引:账户持有者第一次登录会走一遍,之后侧栏一直留着入口。
🧭 操作指引
指引教账户持有者怎么用面板:看账户状态、绑定与连接直播间、换 Cookie、装插件、配插件。
它不另画一套界面,而是直接在真实页面上浮一层蒙版。 这一点是刻意的:最早几版
指引自己抄了一份「模拟界面」,主页一改样式、一加字段,抄的那份不会跟着变,
用户看到的指引和真实面板对不上。现在高亮的就是真实元素本身 —— 主页怎么变,
指引自动跟着变。
几条规矩:
- 内容区点不动。 蒙版盖住整屏,被高亮的按钮同样点不动 —— 兑换码、Bot 启停
这类点一下就真作用到账户上,不能在指引里被误触 - 切页自己点。 从一页到下一页由你点左侧导航完成,指引只把该点的那一项圈出来 ——
这趟要教的正是「怎么切」 - 该动手的地方才放行。 少数几步(切 Cookie 来源、装插件)要先点一下才能往下走,
这时只放行被高亮的那一个按钮,做完自动翻到下一步 - 手机同样能走。 手机端左栏是抽屉,指引会跟着抽屉走
- 版本化。 指引改版后,看过的账户下次登录会再走一遍新的
- 只有点「跳过」或「完成」才算看过。 从侧栏溜走不算,下次登录仍会进来。
「完成」和「跳过」都会回到「概览」
演示数据
讲到直播间和插件时,面板会摆一份演示数据(虚拟直播间、演示插件清单),
这样即便账户还没绑直播间、一个插件都没装,这几步也有东西可讲、可点。
演示数据都带明显的「演示用」标记,怎么点都不会影响你的账户。「装插件」那一步
会把一个带插件主页的演示插件「装」进去,好让你接着看插件详情、配置和插件主页 ——
全程只是演示,不会真的安装任何东西。
🔑 创建账户后的凭据窗口
面板只保存密码的哈希,不存明文(「重置凭据」也不会返回新密码),所以「在卡片上
放个复制密码的按钮」是做不到的 —— 对改过密码的账户,面板根本无从得知。
现在抓住唯一能拿到明文的时机:创建完成那一刻。创建成功后不再只弹个提示条,
而是列出账户、用户名、密码、登录网址,配一个「复制信息」按钮,整段格式化成便于
转发给对方的文本。
窗口里如实写明:关闭后就看不到了,请现在复制。创建时密码留空(后端随机生成、
连创建方也不知道)的情况也单独注明,并指向「重置凭据」。
🗂 账户与插件卡片
- 账户卡片右上角显示编号
#xx,编号也纳入搜索(写成#12而不是12,
带不带井号两种输入都能命中)—— 排查「为什么跳号」这类问题时好定位 - 未绑定直播间的账户,卡片上的按钮从「绑定」改成「绑定直播间」,说清楚点它
要干什么 - 插件卡片的「插件主页」标签带上文字:原来只有一个外链图标,看不出点进去是什么
- 桌面端四组筛选排进同一行:四组胶囊加起来的宽度已经很贴近容器上限,字体度量
稍有出入就会翻到第二行。把容器放宽到max-w-7xl、桌面端不许换行、胶囊内边距收窄一档
⚠️ 已知问题
面板保存设置会丢掉 config.yml 里的注释——保存走的是 yaml.dump 整表重写,
YAML 注释不在数据模型里,重写即丢失。功能不受影响,但注释里的说明需要另行留存。
MisMiss v1.5.2 — 第一次用也知道该点哪儿 🧭
What's Changed
- origin/main by @dikxingmengya in #8
Full Changelog: v1.5.1...v1.5.2
v1.5.1
📱 MisMiss v1.5.1 — 手机上好用了
移动端全面适配 · 面板不再整页打不开 · 修掉几处「看起来能用其实在坏」的问题
v1.5.1 以移动端适配为主,另修了几个线上真实踩到的坑。桌面端的布局基本未动。
📱 移动端
手机上此前有不少「能显示,但没法用」的地方,这版逐条收拾:
- 账户详情页的 Tab 不再折成两行——六个 Tab 均分窄屏后每个只剩 60px 上下,
「图标 + 四字标签」放不下,标签自己折行了。移动端隐去图标,把宽度让给文字 - 插件日志弹窗——每行原本是「时间 / 级别 / 来源 / 消息」四列横排,光前三个
固定列就占掉 300px,而窄屏减去内边距只剩 310px,消息(日志的主角)几乎
分不到宽度。窄屏改为消息独占一行 - 插件卡片整卡可点进入插件主页,取代原来混在一排小图标里的
ExternalLink
按钮;没有插件主页的插件点了没反应,不做成「看着能点却没响应」的样子 - 筛选区:四组各补齐为四项(新增「即将过期 / Bot 异常 / 未绑定」等),
窄屏默认折叠成一个「筛选」按钮并显示生效数量;日志页与账户页共用同一套开关 - 日志级别在窄屏显示缩写(
SUCCESS→SUC、WARNING→WARN、CRITICAL→CRT),
短的那些(INFO/ERROR/DEBUG)保持原样——它们本来就不占地方 - 开关按钮全站收敛成一份实现,尺寸、过渡、焦点环、保存中的转圈位置统一
🐛 修掉的问题
面板整页 500,三个接口一起挂
CoreApiException: 直播间尚未初始化,请先调用 join()
MissevanLivestream.creator 在直播间未 join 时直接抛异常,而
creator_name 等字段都是它的转发属性。账户列表 / 总览 / 服务状态共用的那条
聚合路径裸读了它——一个没就绪的账户就能让整页打不开。
平时账户都能正常启动所以看不出来;v1.5.0 部署后平台风控导致账户集体起不来,
正好把它踩出来。现已统一走安全取值(同一条链上的「主播简介」早就是这个写法,
只是当初没覆盖到其它字段)。
插件库显示「为空」,但插件其实都在
页面用 Promise.all([插件库, 账户列表]) 把两个互不依赖的请求绑死,再配
一个静默的 catch {}。账户接口 500 → 插件列表也变成空 → 错误被吞 →
界面显示「插件库为空」。真实情况是「另一个接口挂了」,界面却说「你没装插件」,
排查时被这个假象带偏过一轮。改为各自独立结算,并且如实报错。
加入直播间的欢迎语发得很晚
事件是实时的、消息却迟迟不来。根因在出站闸门:它把平台正常应答但业务拒绝
(如给未开播房间发消息返回的「主播休息」)也算作了「限流失败」。32 个账户的
定时消息 8 次就攒满阈值,闸门于是反复进入 30 秒全局退避,把欢迎语这类
实时消息一并压后——而弹幕/进入事件走 WebSocket、不经过闸门,所以「事件到了、
消息没发」。
现在只有确实表明被限流的才计入失败。
悬浮提示与提示条
- Toast 在窄屏左端跑出屏幕:宽度用了
w-full(视口宽 100%),而容器只锚在
右侧 16px、没有左侧约束,屏宽不足 400px 时左边缘被顶到 −16px - Toast 压住顶栏菜单:它距顶仅 16px,而移动端顶栏占 0~48px
- 按钮的悬浮提示被视口边缘裁掉,靠近顶部时还会盖住顶栏;现在贴边会自动
夹回屏内、贴近顶部会自动翻到下方 - 长提示超过屏幕宽度时改为换行,而不是硬撑着一行被切掉
切 Tab 时页面宽度抖动
全局滚动条宽 6px 且占布局宽度:内容矮的 Tab 没有滚动条、内容高的有,
可用宽度差 6px,均分宽度的 Tab 栏就跟着缩一下。已常驻预留滚动条位置。
图标不在正中间
Button 把 children 多包了一层 <span>,而调用方普遍写成
<span className="hidden sm:inline">刷新</span>——内层虽然 display:none,
外层仍是个空 flex item,gap 照常在它与图标之间生效,图标被挤偏。
(原注释「display:none 的元素不占 flex 间距」推理是对的,被这层包装破坏了。)
⚙️ 其它
- Docker 构建:Docker CLI 与 compose 插件下载源默认改走清华镜像
(download.docker.com在国内会传输中途被重置),curl补上
--retry-all-errors——默认的--retry对连接重置完全不重试 - 健康检查放宽
start_period:启动会按账户数错峰(32 个账户约 50 秒),
镜像里默认的 15 秒撑不过去,会让 compose 判定不健康并放弃启动 nginx,
表现为更新完面板打不开
⚠️ 已知问题
面板保存设置会丢掉 config.yml 里的注释——保存走的是 yaml.dump 整表重写,
YAML 注释不在数据模型里,重写即丢失。如果你在 config.yml 里写了注释,
保存过一次面板设置后就没了。功能不受影响,但注释里的说明需要另行留存。
MisMiss v1.5.1 — 手机上终于能顺利用 🎧
What's Changed
- dev by @dikxingmengya in #6
Full Changelog: v1.4.3...v1.5.1
v1.4.3
🎉 MisMiss v1.4.3 — 私有 Cookie 可以自助获取了
账户门户新增「获取 Cookie」 · 账户与插件列表支持搜索筛选 · 手机端可用性修复
v1.4.3 是目前改动面最大的一次:给私有 Cookie 账户补上自助取 Cookie 的完整链路,
并把账户、插件两个列表从「一长条平铺」改成了可查可筛。
🎉 新功能
私有 Cookie 自助获取
私有 Cookie 账户原本只能由用户从浏览器开发者工具里手动复制 Cookie,对非技术用户门槛很高。
现在 Bot 页的「自定义 Cookie」区块里有两种获取方式:
- 书签助手 —— 把按钮拖到书签栏,在猫耳页面点一下,Cookie 自动传回面板
- 手动获取 —— 书签只把 Cookie 弹出来,自己复制粘贴
取到 Cookie 后会自动把账户切换为自定义模式,不必再手动切一次。
账户与插件的搜索筛选
- 账户总览:关键词搜索覆盖直播间名称 / 用户名 / 主播名 / 直播间简介 / 主播简介,
外加账户名、Bot 名与房间 ID;另有状态(正常 / 已过期)与 Bot 模式(公共 / 私有)两组筛选,
以及分页(每页 12 个) - 账户插件 / 账户插件库:按名称、作者、简介搜索;插件库另有「已安装 / 未安装」筛选
- 面板插件库:关键词搜索 + 「默认插件 / 使用中」筛选
筛选胶囊都带实时计数,筛完没结果会给一个「清除筛选条件」的出口。
账户卡片上的运行时快捷开关
账户卡片新增 Bot 启停、直播间连断两个快捷按钮,省去点进详情页。
两者都会先弹二次确认——它们会改变线上行为,误点代价不小。
时长管理合并
「续期 / 设置剩余天数 / 兑换授权码 / 设为永久」合并进同一个对话框,弹窗顶部可自由切换;
另新增「设为过期停用」,一键把账户置为过期状态(到期时间置为过去并立刻停用)。
🐛 Bug 修复
切到公共 Cookie 会丢掉自定义 Cookie
之前点「公共 Cookie」会直接用面板 Cookie 覆盖掉账户自己的那串,切回来就得重新去浏览器里翻一遍。
现在切走时会把自有 Cookie 留存,切回时给一个「填入上次保存的 Cookie」按钮一键取回。
顺带修掉一条绕过路径:走 PATCH /api/panel/accounts/{id} 切公共模式时没有强制降级权限,
有完整权限的账户切过去会继续握着完整权限却跑着面板的共享 Cookie。
创建账户时,直播间 ID 和登录密码被浏览器自动填充
浏览器(实测 Edge)会把密码框前面那个文本框当成「用户名」配对,于是它把保存的账号
灌进了直播间 ID、把密码灌进了登录密码——一打开弹窗,两个框里就躺着别人的账号密码。
默认用户名会跳号
原本按账户 id 取名,删过账户就会跳号(3 个账户可能默认出 user_7)。改成按账户总数 + 1,
并跳过已占用的名字。
🔧 改进优化
手机端触摸适配
Switch开关视觉仍是 36×20,但点击热区扩到 52×44——手机上 20px 高的目标按不准- 筛选胶囊、标签按钮统一抬到 32px 高
- 日志行改为整行可点展开全文,并加了 ▼/▲ 指示。此前只有正文那一小条能点,
而且看不出可点——手机上又没有 hover - 账户卡片的房间名在手机上换行显示,不再被省略号吞掉
仍在使用默认密码的账户须先改密
默认密码 user123 人人皆知,留着等于没设防。用它登录后会强制先改密才能进面板。
⚠️ 升级注意
- 书签回传需要面板走 HTTPS。 HTTPS 的猫耳页面无法向 http 地址发请求,
本地开发环境(http://localhost)用不了这条路径 - 手机端需要手动新建书签:手机上无法拖拽,面板里给了分平台的逐步说明
(电脑 / iPhone / iPad / Android / 其他浏览器) - 微信、QQ 等内置浏览器装不了书签,需要先「在浏览器打开」换到系统浏览器
- 除以上外无需任何配置或部署层面配合
📌 为什么没有「面板代登录」
早期实现过一版由面板后端代发的短信登录,实测一律失败,代码已移除。
对照浏览器抓包,猫耳的登录接口有三道服务端伪造不了的门槛:
Content-Type: application/x-www-form-urlencoded(body 却仍是 JSON 文本)- 每个请求带
X-M-DeviceSign—— 由猫耳的指纹库算出visitorId再对 URL 签名,
天生要求请求方是个有真实指纹的浏览器 - 一整套登录页访客会话 Cookie(
FM_SESS/FM_SESS.sig/MSESSID…),
其中FM_SESS.sig还是签过名的,验证码多半就绑在它上面
书签之所以可行,是因为它运行在用户自己的浏览器、猫耳自己的页面上,
用的是这个人真实的指纹与会话,没有冒充谁。这也是唯一可行的形态。
MisMiss v1.4.3 — 把 Cookie 这件事交给用户自己 ✨
v1.4.2
🐛 MisMiss v1.4.2 — Docker 下终于存得下设置
单文件挂载写配置不再 EBUSY · 补偿复选框不再崩 · 输入法回车不再误提交
v1.4.2 以修复为主,另带两处插件弹窗的体验改进。
- Docker 部署保存设置终于能用了——上版本去掉只读挂载只解决了「没权限写」,
还没解决「挂载点不能被重命名替换」,这次补齐 - 批量补偿的复选框点一下就崩,已修
- 插件的操作弹窗现在支持多行文本;用中文输入法时,确认候选词的回车不再
被当成提交
🐛 Bug 修复
Docker 部署下面板保存设置仍然失败(Device or resource busy)
这是 v1.4.1 那个修复的遗留半截:
- v1.4.1 去掉了
config.yml挂载的:ro,解决了「没权限写」 - 但没解决
rename():Docker 把config.yml以单文件方式挂进容器时,
/app/config.yml本身是一个挂载点,而「先写临时文件、再重命名替换」这个
保证原子性的写法里,重命名到挂载点上内核必然返回EBUSY
于是更新源设置 / 更新提示消息 / 日志等级 / 端口这四个入口在 Docker 下依然全部失败,
报错是 配置文件不可写(/app/config.yml):[Errno 16] Device or resource busy。
现在改为分情况处理:
- 能原子替换就原子替换——普通(非 Docker)安装的行为完全不变,写一半崩溃
仍然不会毁掉原文件 - 替换不了(目标是挂载点)就退回直接覆写——牺牲原子性换取可用性,
否则这个文件在 Docker 下根本写不进去
批量补偿的复选框点一下就崩
把补偿改成「默认全选、用选项排除」时,状态变量改了名,但「逐个查看」里那个
复选框的处理函数漏改了一处 —— 点它会直接抛 ReferenceError,不是显示错乱,
是功能完全不可用。已修正。
全局消息的请求体类型不正确
面板「全局消息」发出的请求体在类型上不符合浏览器 fetch 的要求。运行时本来
无碍(客户端有兜底转换),但它会让发布构建直接失败,影响后续打包。已修正。
🔧 改进优化
插件操作弹窗:多行文本与输入法
- 新增多行文本字段——插件的
_ui_schema.json动作字段可用
input_type: "textarea"声明多行输入(rows指定行数,默认 3)。
回车换行、Ctrl / Cmd + Enter 提交,占位符里也写了这条提示 - 输入法回车不再误提交——用中文输入法打字时,按回车是「确认候选词」,
但此前会被当成「提交」而把半截内容发出去。现在会识别输入法的组合状态
(isComposing),确认候选词的回车不再触发提交(所有回车提交的输入框都修了) - 列表项里的回车不再冒泡——在多值字段的条目里换行,不会再去触发外层的提交
⚠️ 升级注意
- 如果你在 v1.4.1 上遇到过「配置文件不可写(…):
[Errno 16] Device or resource busy」,
本版本修的就是它。保存设置失败不影响在线更新——更新流程本身不写config.yml
(它会跳过这个文件),所以可以直接在线升级到本版本 - 无需再改动
docker-compose.yml——挂载层面的:ro在 v1.4.1 已经去掉,
本版本是从代码侧补齐「挂载点写不了」的兼容。两步都到位后才能正常保存设置:- 从 v1.4.0 及更早升级:
docker-compose.yml的:ro要去掉(v1.4.1 的更新包会自动带上),
再加上本版本的代码修复 - 从 v1.4.1 升级:只需要本版本
- 从 v1.4.0 及更早升级:
MisMiss v1.4.2 — 让「保存」真的保存下来 🔧
v1.4.1
🔧 MisMiss v1.4.1 — 直播间看得见 · 补偿发得动 · 面板存得下
总览直接看开播状态 · 一键跳进直播间 · 批量补偿时长 · Docker 保存设置不再 500
v1.4.1 是一次补齐直播间与账户运维的版本:
- 开播状态修好了——此前「主播已开播」和「显示未开播」经常对不上,得手动刷新才同步;
现在总览页就能直接看到每个直播间是否在播 - 跳转与绑定直播间——一键跳到猫耳直播间页面;绑定/更换时可以直接粘贴直播间链接
- 批量补偿时长——按条件筛账户,一次给一批人补天数
- Docker 部署的「保存设置」不再报 500
- 还有全局消息、批量补偿、多选日志筛选、自绘下拉框若干
✨ 新增功能
直播间
- 总览显示开播状态——账户卡片上「开播中 / 未开播」与「已连接 / 未连接」并列显示。
两者不是一回事:连着但没开播是常态 - 跳转直播间——总览卡片与账户详情页各有一个入口,一键在猫耳打开
https://fm.missevan.com/live/<直播间 ID> - 按链接绑定/更换——绑定与更换直播间的输入框现在直接粘贴直播间链接即可
(带协议头、www、结尾斜杠、查询串、参数都行),当然也仍然接受裸数字
账户
- 批量补偿时长——账户总览的「批量补偿」:默认全选,用选项排除不想要的
(排除已过期 / 排除未过期 / 排除剩余天数多于 N 天 / 逐个取消勾选)。
走「预览 → 二次确认列出将要补谁 → 执行」,确认前能看到完整的受影响名单 - 创建账户的默认凭据——用户名默认
user_<账户号>、密码默认user123,两者都还能改
面板
- 全局消息——「服务器设置」页新增卡片,用各账户的机器人向所有已启用且正在开播
的直播间广播一条自定义消息(与更新提示走同一条通道) - 日志按账户多选筛选——日志页的账户筛选从只能选一个改为多选,可同时看几个账户;
长按不再需要来回切换 - 自绘下拉框——全站下拉不再使用系统原生控件,展开列表跟随应用主题(深色界面里
不再弹出亮色一块)
🐛 Bug 修复
- 「未开播」与「主播离线」状态不同步——开播/下播由平台通过 WebSocket 明确告知,
但此前只异步去查一次房间信息接口,而「主播在线」是同步改的:于是出现「主播已开播
但仍显示未开播」,要等接口回来才对上;接口一旦失败就永远停在旧值,只有手动刷新
才对得上。现改为收到开播/下播通知时同步更新状态,房间信息接口只负责补齐人数、
封面等展示字段 - Docker 部署下面板的设置根本存不下来——
docker-compose.yml把config.yml
以只读(:ro)方式挂载,而「更新源设置 / 更新提示消息 / 日志等级 / 端口」四个端点
都要写回这个文件;写入抛出的PermissionError没有被捕获,面板只看到无信息的 500,
用户无从判断是自己填错了还是部署方式不对。现改为读写挂载(更新流程本身会跳过覆盖
config.yml,容器可写不会被发布包冲掉用户配置),并让写入失败的端点返回带文件路径
与处理办法的可读报错。顺带堵掉一个数据丢失隐患:原先读取配置失败会退回空字典再写回,
等于把文件里其余配置全部抹掉,现在改为报错中止 - 「安装后自动启用」的控件形态不一致——它是复选框,而全站其它「点了立即生效」的
设置都是开关按钮,容易让人以为改完还要再点保存。现统一为开关(行为本来就是即时的:
拨动即通过接口落盘,失败会回滚)
🔧 改进优化
- 手机上不再三行按钮——插件库头部原来标题被压成四行、五个操作排三行;现窄屏下
标题与操作分行、次要操作只留图标,压到一行。日志页同理:级别筛选、账户筛选、
三个操作、搜索原本各占一行,现折叠为「搜索 + 筛选」一行,筛选区一点即开 - 更新提示开关点击即生效——不再需要额外点一次保存
⚠️ 升级注意
- Docker 部署需要用上新的
docker-compose.yml——若你此前保存设置遇到 500,
根因是config.yml被只读挂载。在线升级到本版本会自动带上修正后的 compose 文件,
并在重建容器时生效;想立刻恢复也可以自己在宿主机把config.yml那行末尾的:ro
去掉,再执行一次docker compose up -d - 「开播状态」是新字段,与「已连接」含义不同——
room_streaming表示主播是否在播,
room_connected表示机器人是否连上了直播间。连着但没开播属正常状态 - 批量补偿只处理非永久账户——永久账户加天数没有意义,会被自动排除并计入「跳过」,
在确认弹窗里能看到原因
MisMiss v1.4.1 — 让直播间的状态一眼可见 🎧
Full Changelog: v1.4.0...v1.4.1
v1.4.0
📢 MisMiss v1.4.0 — 更新先打招呼 · 日志只留重点
更新前先告诉直播间 · 日志默认不再刷屏 · 机器人不再被自己触发
v1.4.0 是一次以可运维性为主的版本:
- 更新提示消息——程序更新时可以用机器人在各直播间先发一条自定义消息,
更新完成后再发一条,让观众知道机器人只是去升级了 - 日志大幅降噪——默认级别改为 INFO,插件扫描、状态同步这类天天刷屏的日志降到
DEBUG;需要排查时在「设置」里一键切回,细节一条不少 - 机器人不再被自己的弹幕触发——修掉了「回复内容含关键词 → 再次触发 → 再回复」的死循环
- 插件自定义界面新增多值字段,可增删条目、编辑已有条目时自动预填
✨ 新增功能
更新提示消息
面板「更新 MisMiss」页新增「更新提示消息」卡片:
| 配置项 | 默认文案 | 发送时机 |
|---|---|---|
| 更新前提示 | 机器人即将更新,稍后自动恢复 | 更新包下载完成、覆盖程序文件之前 |
| 更新后提示 | 机器人已更新完成,已恢复正常 | 新版本启动完成之后 |
- 只发给已启用且正在开播的直播间;未绑定 / 未启用 / 未开播 / 已过期的账户自动跳过
- 单个账户发送失败不影响其余账户,也不阻断更新本身
- 单条上限 80 字符(直播弹幕有长度限制),超出截断;留空则跳过对应阶段
- 「更新前」消息发送后会等消息队列真正排空——否则覆盖程序文件触发的进程重启
会把它连同未发出的消息一起掐掉 - 「更新后」消息由新版本启动后补发,只发一次;更新包解压失败会撤销待发标记,
普通重启不会误发
插件自定义界面:多值字段
_ui_schema.json 的动作字段新增 input_type: "list":
- 每个条目一个文本框,配「+ 添加」与逐条删除按钮,提交前自动过滤空项
- 新增
item_label/item_placeholder定制添加按钮文案与输入框占位符 - 新增
body_template,支持{{row.字段}}占位符,编辑已有条目时自动带入原值 - 弹窗在含多值字段时自动加宽、限高并滚动,条目多也不会溢出屏幕
🐛 Bug 修复
- 机器人会被自己的弹幕触发——平台会把本连接发出的弹幕回推,插件回复内容如果
包含触发关键词(如「喵」→「喵喵喵~」)就会形成「回复 → 再次触发 → 再回复」的
死循环。现在本房弹幕与跨房弹幕都会先过滤掉机器人自己发的消息 - 跨房幸运礼物不计入榜单——跨房礼物包此前把幸运值写死为
None,
导致礼物感谢插件的幸运值榜单看不到任何跨房贡献,现按与「本房礼物」相同的方式解析 - 插件库卡片被拉高——卡片底部罗列使用账户徽标时会自动换行,行数随账户数增长,
而同排卡片在 CSS grid 下会被拉齐到最高的那个。徽标改为固定单行(前 3 个 + 「+N」),
页脚高度恒定;「+N」可点开完整账户列表 - 插件刷新逐账户刷屏——刷新插件库会扇出到每个账户的 PluginManager,
此前每个账户都打一条「插件刷新完成」;现合并为结束时的一条汇总
🔧 改进优化
日志
- 默认级别改为 INFO——由
config.yml的logging.level统一驱动
(core.logging.init()、面板实时日志流、设置页调试开关读写同一项,
切换即时生效、无需重启)。想看细节就在设置里打开调试 - 日志按账户标记与筛选——格式变为「时间 | 级别 | [账户名] 类名:函数 | 消息」,
面板日志页可按账户筛选(也可只看面板级日志) - 插件加载 / 启停日志带版本号——统一显示为「名称 v版本 by 作者」
- 高频噪声日志降级为 DEBUG(默认不再显示,切到 DEBUG 仍可查):
插件目录扫描与逐插件发现、插件已加载,跳过、Bot 未启用,插件标记已恢复、
服务器启动中 / 关闭中、Livestream 已恢复、插件刷新完成、
插件首次加载分配默认权限、多 worker 的 state 同步细节等 - 批量操作只打汇总:插件库刷新从「每账户一条」改为一条总计;
扫描到新插件时才补一条 INFO
实测:一次完整启动 + 插件库刷新(3 个账户、15 个插件),
面板默认可见日志由 106 条降到 13 条。
⚠️ 升级注意
- 日志默认级别由 DEBUG 改为 INFO——「设置」页的调试开关默认关闭。
排查插件加载、多 worker 状态同步等问题时请先打开它,
或直接改config.yml的logging.level为DEBUG - 更新提示消息默认关闭——需要在「更新 MisMiss」页打开开关并确认文案后才会发送;
仅对已启用且正在开播的直播间生效 - 插件多值字段需要插件侧适配——
input_type: "list"与body_template
是对_ui_schema.json的扩展,未使用的插件渲染与之前完全一致
MisMiss v1.4.0 — 更新之前,先跟直播间说一声 🎧
v1.3.0
🚀 MisMiss v1.3.0 — 统一登录 · 事件编排 · 专属昵称
一个域名登录 · 插件事件可编排 · 观众可设专属昵称 · 更新后自动告知
v1.3.0 是一次以体验与可扩展性为主的版本:
- 登录入口统一——不再区分
user.<域名>子域名,管理端与账户端共用一个登录页,
登录后按角色进入各自界面 - 更新日志弹窗——服务器更新后,账户再次登录会自动看到本版本的更新日志
- 事件可编排——插件监听支持优先级、可取消传播、可改写事件参数
- 专属昵称插件——观众给自己设一个昵称,之后所有涉及他的事件里都会用这个昵称
- 顺带修掉了一个永不过期的账户一旦续期就变成限期的缺陷
✨ 新增功能
登录与更新提示
- 统一登录入口——管理端与账户端不再用不同子域名区分,
同一个登录页按登录凭据决定进入哪个界面 - 更新日志弹窗——服务器更新后账户再次登录自动弹出该版本日志,每个账户每个版本只弹一次;
日志随部署包一同分发,无需联网
事件系统
插件的事件监听现在具备三项能力:
| 能力 | 用法 |
|---|---|
| 优先级 | @event_handler(priority=N),值越大越先收到事件;不写则顺序与旧版完全一致 |
| 取消传播 | 用户内容类事件(弹幕 / 礼物 / 进入 / 关注 / 提问 / 跨房)可调用 event.cancel() 阻止继续传给后续插件 |
| 改写参数 | 事件的属性可直接赋值,改动对后续插件可见;event.user.display_name 可覆盖用户名 |
插件
- 专属昵称插件(新)——观众发送
昵称 xxx设置专属昵称,之后所有涉及他的事件中
用户名都会被替换(欢迎、礼物感谢、签到等插件的文案自动跟随);昵称查看、重置昵称取消 - 插件配置分组——配置页按「常用 / 文案 / 高级」折叠;未标注分组的插件渲染与之前完全一致
- 插件批量推送与默认插件——面板可按插件或一次性把库版本推到各账户
(自动跳过已是最新的);点亮星标设为默认插件后,新建账户会自动安装并启用 - 一键更新——账户插件页一键把「副本落后于库」的插件全部更新到库版本
- 卸载数据分类——卸载时可分别选择删除配置 / 插件数据 / 持久化数据,三项默认都不勾选
- 安装插件自动启用——账户级偏好,默认关闭;开启后从插件库安装插件会随即启用
- 插件日志弹窗——只显示插件相关日志(插件自身代码与框架的插件生命周期),
可由插件库页的常驻入口、或插件卡上的「初始化失败」徽标打开
直播间与账户
- 跨房事件——连麦时对方直播间的弹幕、大厅中送给其他麦的礼物现在有独立事件,
监听本房弹幕 / 礼物的插件不会被对方直播间的事件打扰 - 直播间失联提示——区分「未绑定」与「绑定了但加载失败」,后者给出提示并支持重试加载
- 设为永久——账户概览按当前状态显示「设为永久」或「改为限时」
🐛 Bug 修复
- 永不过期的账户一续期就变成限期——叠加续期把「永久」当成了「已过期」来起算,
永久 + N 天被算成了now + N 天。修复后永久账户叠加续期会保持永久并给出提示;
永久账户兑换授权码会被拒绝,且不会消耗掉那个码 - 面板上看不到插件失败的完整报错——异常堆栈此前只写进日志文件,面板上只有一行摘要;
现在完整堆栈会进入面板与插件日志弹窗 - 「删除配置文件」勾了不生效——删除路径写成了目录而实际是文件,且失败被静默吞掉
- 插件库的「有更新日志」标记判断错误
- 插件安装 / 更新流程的版本校验——版本拒绝(409)曾被前端误当成「确认覆盖」信号,
且确认后会绕过校验降级覆盖 - 插件配置分组点击无法展开、账户详情的插件页偶发白屏
- 服务器页的插件数含义不对——原为各账户已启用插件数之和,现为插件库中的插件总数
🔧 改进优化
- 账户卡片整卡可点——删掉了作用完全重复的「管理」与「账户设置」两个按钮,
改为点击卡片任意位置进入管理;键盘操作、中键新标签页打开也都支持 - 批量操作二次确认——四处批量入口统一改为「预览 → 确认 → 执行」,
确认弹窗可展开列出「将要影响哪些账户 / 插件」;无事可做时直接提示,不弹空确认框 - 插件初始化失败的处理——移除「加载失败的插件」列表,
改为插件卡上的红色「初始化失败」徽标 + 插件日志弹窗 - 礼物感谢:跨房感谢默认开启——大厅中观众送给其他麦的礼物现在默认也会感谢
(此前需手动开启);同一礼物送给多人时会按礼物名合并成一行,
受赠主播以顿号接在行尾、超过 5 人折叠为「等 N 人」,
不再出现多行看起来重复的礼物记录
⚠️ 升级注意
- 子域名入口取消——原本用
user.<域名>访问账户门户的方式不再区分,
管理端与账户端统一使用同一个域名与登录页。若反向代理本来只转发了主域名,无需改动;
若单独配了user.子域名,可以撤掉了 - 昵称指令不带方括号——专属昵称插件的指令是
昵称 xxx/昵称/重置昵称,
原来的[昵称 xxx]写法不再生效 - 「加载失败的插件」列表移除——插件初始化失败改为在卡片上显示红色徽标,
点击徽标查看插件日志;不再提供「重试 / 放弃」按钮,重新启用该插件即可重试 - 插件不再自带启停开关——
timer_messages的enabled配置项已移除,
插件的启用与停用统一由账户插件页的开关管理。
若你此前把该配置设为关闭,请在账户插件页把该插件停用 - 账户插件副本需更新——本次随发行更新了
gift_thanks(v1.3.4)、nickname与
timer_messages。各账户的副本不会自动跟随,请在账户插件页点「一键更新」或逐个点「更新」 - 礼物感谢的旧配置会自动迁移——插件加载时会把「仍是历史默认值」的配置项迁移为
新默认值(cross_gift_enabled改为开启、跨房标注改为行内后缀→ {targets}),
你自己改过的值不会被覆盖,无需手动调整
MisMiss v1.3.0 — 一个入口,一套可编排的事件,一个属于你的昵称 🎧
v1.2.0
🚀 MisMiss v1.2.0 — 安全加固 · 插件副本隔离修复 · 插件定时消息体系
面板鉴权收紧 · 插件消息与普通消息分类 · 账户副本真正生效 · 插件生命周期补齐
v1.2.0 是一次以修缺陷 + 补能力为主的版本:
- 收紧了面板的四处认证绕过(其中三处可直接导致 RCE / SSRF / 信息泄露)
- 修复了 v1.1.0 引入的账户插件副本从未被加载——「副本隔离」此前只对配置/权限/数据成立,对代码不成立
- 建立了插件定时消息体系:与面板添加的普通消息分类管理,不落盘、不可改删、轮转置顶
- 补齐插件生命周期:
on_livestream_bound钩子,插件不再需要靠弹幕事件兜底重试
🔒 安全修复
面板中间件此前把若干前缀整段设为公开,导致以下端点无需登录即可调用:
| 端点 | 风险 | 修复 |
|---|---|---|
POST /api/config/pip-install |
任意 pip install → 任意代码执行 |
要求管理员登录;拒绝 - 开头的包名(阻断 --target / -r 参数注入),限长并加 --no-input |
POST /api/plugin/install* |
上传 zip + 裸 extractall → Zip Slip |
要求管理员登录;逐成员校验路径,拒绝绝对路径 / .. 段 / 盘符 |
GET /api/proxy/image |
无限制 → SSRF / 开放代理 | 域名白名单(可在 config.yml 的 proxy.allowed_hosts 扩展)+ 内网地址拦截 + 重定向逐跳校验 + 10MB 上限 |
WS /api/ws |
无鉴权 → 日志泄露 | 要求管理员 token(浏览器 WebSocket 无法设置 header,故走查询参数);鉴权失败以关闭码 4401 断开,前端据此停止重连 |
- 图片代理保持匿名可访问(前端
<img>无法携带 Authorization header),改以「白名单 + 内网拦截」限制目标 - token 现在来自查询参数(外部可控),
_load_token增加 64 位十六进制格式校验,堵住文件路径穿越
✨ 新增功能
插件定时消息体系
插件注册的定时消息与面板添加的消息分类管理:
| 维度 | 普通消息 | 插件消息 |
|---|---|---|
| 注册途径 | 面板「定时消息」页 | Plugin.register_timer_message() |
| 持久化 | 写入账户 state 文件 | 不写入 |
| 编辑 / 删除 / 排序 | 允许 | 禁止(但可「跳过」「立即发送」) |
| 轮转位置 | 队列中段 | 置顶 |
| 执行指针 | 与插件消息共用同一个 | 同左 |
| 开播条件 | 无 | 可声明 only_when_live=True |
| 生命周期 | 由面板管理 | 插件停用 / 挂起 / 卸载 / 重载时由框架自动清理 |
- 插件消息不落盘,因此插件即使异常终止(
terminate未执行)后重新启用,也不会累积出重复消息 - 框架在插件激活前与停用/挂起/卸载时按插件名强制回收,不依赖插件自觉
- 插件消息增删时自动补偿轮转指针,始终指向原来那条消息
插件生命周期:on_livestream_bound
Plugin 新增 on_livestream_bound(livestream) 钩子,在账户新绑定直播间时触发;
插件被启用/重新启用时若账户已绑定,框架会补发一次。
两条路径都覆盖,插件不再需要靠弹幕事件兜底重试注册。
面板
- 统计区分:账户总览卡片与账户门户概览分别展示「普通 N · 插件 M」
- 来源筛选:定时消息页可按 全部 / 普通 / 插件 筛选(筛选只影响展示,指针位置按后端索引计算,不会错位)
- 插件消息在列表中带「插件」徽标,编辑 / 删除 / 排序按钮置灰
🐛 Bug 修复
- 账户插件副本从未被加载(关键):模块以
import plugins.<dir>.<mod>导入,而账户目录下的
plugins/是插件数据目录,plugins又是命名空间包——仓库的plugins/被合并进来并抢先命中,
于是账户永远执行插件库的源码,installed_plugins/下的副本形同虚设,面板「可更新」徽标也失去意义。
改为按副本绝对路径加载并取唯一模块名,磁盘布局无需迁移 - 插件异常终止后重复注册定时消息:插件消息此前会随 state 落盘,崩溃后残留 + 重新启用再注册 = 重复条目
Server.enable_plugin复刻了一份PluginManager的分支逻辑,导致启用前清理与绑定通知都被跳过
(表现为禁用后再启用,插件定时消息不再恢复)。改为委托,消除重复实现- 合并轮转缓存失效不完整:
move_timer_message是原地交换源列表,缓存持有的是拼接副本不会同步更新 _install_lock形同虚设:在StreamingResponse返回前即释放,并发安装互斥失效;改为在生成器内部持锁,
并给/install、/install/update一并加上- 嵌套结构的 zip 安装报 500:版本比较按固定根路径读
metadata.yaml,而插件名是递归查找的 - 插件元数据缺
name时返回字符串'None'(真值)导致后续判断失真 - 无 token 时前端发出字面量
"Bearer null" - CHANGELOG 存在性判断错误(3 处):其中一处按
module_path字符串反推目录,依赖旧的模块命名格式;
改为在PluginMetadata上记录changelog_path(与既有readme_path同款) - 日志环形缓冲区容量与文档不符(实例化为 2000,类默认值与文档均为 10000),统一为 10000
🔧 改进优化
- WebSocket 重连改为真正的指数退避(2/4/8/16/32s)——此前实现为线性,与文档描述不符
- 合并轮转缓存:
_combined_cycle结果按直播间缓存,避免每次调用新建拼接列表 - 术语统一:「人工消息」全面更名为「普通消息」(代码 / 文档 / 测试)
- 死代码清理:3 个无引用的前端组件(
InstallModal/RoomSelect/ReadmeModal)、重复定义的路由函数、
3 个无用 schema、InlineLoader、TYPE_CHECKING空块、_delete_token、残留的dashboard.pyc - 插件编写约束放宽:各账户插件模块现为独立加载,模块级变量不再跨账户共享;
原「禁止模块级可写状态」的硬约束改为建议(同一账户内重载仍会重新执行模块代码)
📝 文档
README.md— 按多账户模型重写:架构图、事件树(补LiveQuestionEvent/LiveStatisticsEvent)、
插件库与账户副本、_ui_schema.json、Docker 部署包与在线更新、实际项目结构docs/TASKS.md— 校正状态(Question 实体、测试体系等已完成;路径统一为src/core/...)docs/web/README.md— 按实际路由 / 页面 / API 重写,补充认证与授权模型docs/interfaces/interface.md— 定时消息语义更新为三类队列 + 两类消息docs/plugin/PLUGIN_DEV_GUIDE.md— 定时消息章节重写(on_livestream_bound时机、only_when_live)、
生命周期钩子表补齐、副本隔离约束修正- 5 个插件的
metadata.yaml与 3 个插件 README 去除已废弃能力的描述
🧪 测试
新增两组回归测试(与既有测试脚本一样保留在本地开发目录,不随仓库发布):
- 插件定时消息:不落盘、置顶、不可改删移动、按插件清理互不影响、
指针共用与增删补偿、基类接口、账户未绑定直播间返回空串、
异常终止后重新启用不产生重复、仅开播时发送条件、计数区分 - 插件副本隔离:加载账户副本而非插件库源码、副本内相对导入可用、
各账户独立模块对象、卸载后清理模块缓存
另以 HTTP 端到端复核:未登录访问敏感端点被拒、图片代理拦截内网与非法域名、
插件消息的编辑/删除/移动返回 400 而跳过返回 200、账户插件安装与更新全程加载副本。
既有回归(账户管理 / API 集成 / 授权码 / 跨 worker 状态同步 / 定时持久化)全部保持通过。
⚠️ 升级注意
- 插件副本开始生效:此前账户实际执行的是插件库源码,升级后会转而执行
data/accounts/{id}/installed_plugins/下的副本。若某账户的副本比插件库旧,
该账户行为会回退到旧版本——请在账户插件页逐个点「更新」(卡片上有「可更新」徽标) - 日志 WebSocket 需要 token:未登录时不再推送,前端会显示「未授权」并停止重连
- pip 安装与插件上传需要登录(面板用户无需额外操作)
- 插件定时消息不再写入
server_state.json,历史遗留的插件消息条目在下次保存时自然消失
MisMiss v1.2.0 — 门关严了,副本也真跑起来了 🎧