Skip to content

Releases: Dresteam/MisMiss

v1.6.0

Choose a tag to compare

@dikxingmengya dikxingmengya released this 23 Oct 01:42

🚀 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.3-alpha.2 Pre-release
Pre-release

Choose a tag to compare

@dikxingmengya dikxingmengya released this 06 Oct 00:38

这是一个内部测试版本,请不要下载

v1.5.2

Choose a tag to compare

@dikxingmengya dikxingmengya released this 04 Oct 06:23

🧭 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

Full Changelog: v1.5.1...v1.5.2

v1.5.1

Choose a tag to compare

@dikxingmengya dikxingmengya released this 04 Oct 01:22

📱 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

Full Changelog: v1.4.3...v1.5.1

v1.4.3

Choose a tag to compare

@dikxingmengya dikxingmengya released this 30 Sep 10:05

🎉 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 等内置浏览器装不了书签,需要先「在浏览器打开」换到系统浏览器
  • 除以上外无需任何配置或部署层面配合

📌 为什么没有「面板代登录」

早期实现过一版由面板后端代发的短信登录,实测一律失败,代码已移除。
对照浏览器抓包,猫耳的登录接口有三道服务端伪造不了的门槛:

  1. Content-Type: application/x-www-form-urlencoded(body 却仍是 JSON 文本)
  2. 每个请求带 X-M-DeviceSign —— 由猫耳的指纹库算出 visitorId 再对 URL 签名,
    天生要求请求方是个有真实指纹的浏览器
  3. 一整套登录页访客会话 Cookie(FM_SESS / FM_SESS.sig / MSESSID …),
    其中 FM_SESS.sig 还是签过名的,验证码多半就绑在它上面

书签之所以可行,是因为它运行在用户自己的浏览器、猫耳自己的页面上,
用的是这个人真实的指纹与会话,没有冒充谁。这也是唯一可行的形态。


MisMiss v1.4.3 — 把 Cookie 这件事交给用户自己 ✨

v1.4.2

Choose a tag to compare

@dikxingmengya dikxingmengya released this 26 Sep 05:31

🐛 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 升级:只需要本版本

MisMiss v1.4.2 — 让「保存」真的保存下来 🔧

v1.4.1

Choose a tag to compare

@dikxingmengya dikxingmengya released this 23 Sep 09:20

🔧 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

Choose a tag to compare

@dikxingmengya dikxingmengya released this 21 Sep 10:12

📢 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

Choose a tag to compare

@dikxingmengya dikxingmengya released this 18 Sep 05:03

🚀 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

Choose a tag to compare

@dikxingmengya dikxingmengya released this 13 Sep 04:56

🚀 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 — 门关严了,副本也真跑起来了 🎧