Repository navigation
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
给插件 API 加两个能力。动机是我想写一个与网易云官方「一起听」房间互通的控制插件(插件本体不在这个 PR 里,只作动机说明):让 SPlayer-Next 作为对等参与者进官方房间,和手机端 App / 官方电脑端听同一首歌。写的过程中撞到两个 API 缺口,所以一并提上来。
1.
player.playTrack(track)—— 播放指定曲目(低风险)PluginPlayerApi目前只有play / pause / next / prev / seek / setVolume / getPosition,没有任何办法让插件指定一首歌。需要按外部状态切歌的插件(一起听、远程遥控、定时电台、歌单自动切换)都会卡在这里。改动很小,且落在已有的实现上:
shared/types/plugin.ts:PluginPlayerApi加playTrack(track: Track): void,HostCallMethod加"player.playTrack"electron/main/plugins/host.ts:加一个case,落到playerControl.playTrack()—— MCP 的play_track工具本来就在用它,不是新逻辑electron/main/plugins/host.worker.ts:splayer.player加对应方法权限沿用现有的
control(host 的门控是method.startsWith("player.")),不新增门控。2.
splayer.netease.request(path, data)—— 以用户账号身份发请求(安全敏感,请重点审)让插件借应用已登录的网易云会话调
/api/接口:宿主代发,插件拿不到 cookie 本身。动机:插件沙箱读不到应用存在 SQLite(
account_sessions表)里的登录态,也读不到 Chromium cookie jar(应用的网易云客户端走undici,不走net.fetch)。所以任何要用网易云账号的插件,都得让用户再扫一次码、或者把 cookie 明文粘进插件设置。这个能力可以消掉这一步。实现上是复用应用自己的请求层(
createRequest的crypto: "api"明文模式),因此 cookie 注入、客户端身份字段(osver/appver/versioncode…)、系统代理都是白拿的;新增的只是electron/main/plugins/neteaseProxy.ts这一层薄包装。这部分的收敛措施:
netease,没有挂在network下。 理由:network是对所有音源插件自动授予的,如果挂在它下面,等于任何音源插件都能悄无声息地以用户账号身份操作网易云。独立权限是显式 opt-in,用户能在插件详情里直接看到「网易云账号」这一项。/api/路径,weapi/eapi等加密入口不开放。PLUGIN_NOT_LOGGED_IN失败。3.
hostRequest改用credentials: "omit"—— 修一个静默失效(建议优先看这条)写插件的过程中发现
splayer.request有一个静默失效,与上面两个新能力无关,但影响所有设置Cookie头的插件:默认 session 的 cookie jar 里只要存有该域名的 cookie,Chromium 就会用 jar 里的那份覆盖插件通过
headers.Cookie设的值——插件设置的认证信息被静默丢弃。我用一个不需要任何账号的实验钉死了它(同一个 session,往 jar 里预置
JARONLY):Cookie: EXPLICIT=…JARONLY,EXPLICIT不见了credentials: "omit"EXPLICIT✅Cookie头JARONLY(符合预期)这会形成一个自锁死循环:
对用户表现为「我明明填对了 cookie,插件一直说登录失效」。
修法是
net.ts里的一行:credentials: "omit",关掉 cookie store 参与,让splayer.request只发插件显式设置的头。这也更符合文档里「网络只能经splayer.request发起」的语义——插件的请求应当是确定的,不该受宿主 Chromium 会话的隐式状态影响。我知道这个 PR 有争议,把风险写在明面上:
netease.request实质扩大了插件的攻击面。 它把「以用户账号身份发请求」开放给了插件。虽然做了权限隔离和路径限制,但一个声明了@grant netease的插件仍可在用户不知情时操作其网易云账号(发评论、改收藏、退房间等)。现有插件模型是「安装即信任」,这个能力把误信一个插件的代价显著提高了——这一点我无法靠技术手段消除,只能靠权限名让它在安装时可见。明文
/api/是社区实践路径,官方客户端走 weapi / eapi。这类接口的通断与风控策略由服务端决定,将来可能变化。我在真机上验证过listen/together/*、song/detail、qrcode/unikey等接口当前可用,但不保证长期稳定。HOST_API_LEVEL3 → 4。 对存量插件是纯新增,老插件声明 ≤3 照常加载、行为不变;只有用到新能力的插件才需要声明 4。我不了解项目对插件 API 的演进规划。这套改动可能和既定的方向不一致,或者你们本来就不打算开放这类能力。
我个人作为插件作者的态度
这个 PR 完全按需处理,不需要照顾我的感受。
如果维护者认为它:
netease.request这部分;请直接关闭这个 PR,我不会觉得被冒犯。 我只是把撞到的缺口提上来,判断权在维护者。
另外,这两个能力可以干净地拆开:
playTracknetease.requestneteaseProxy.ts、PLUGIN_GRANTS里一个词、host 里一段门控如果只想要前者,我可以立刻把
netease.request撤掉重提。验证
pnpm typecheck(tsc+vue-tsc)全部通过playTrack缺失时降级到 MCP 回退,netease.request缺失时降级到插件自带 cookie主要涉及文件