From 2bdae6ed7ba2a15244c38e2c5fc20af1cbc39907 Mon Sep 17 00:00:00 2001 From: Kinneyzhang Date: Fri, 2 Oct 2026 07:35:44 +0800 Subject: [PATCH] release v0.1.2 --- MANIFEST.json | 8 +- README.md | 3 +- SKILL.md | 86 -------------- VERSION | 2 +- contract.lock.json | 174 --------------------------- interface.json | 289 --------------------------------------------- 6 files changed, 7 insertions(+), 555 deletions(-) delete mode 100644 SKILL.md delete mode 100644 contract.lock.json delete mode 100644 interface.json diff --git a/MANIFEST.json b/MANIFEST.json index aae6f9d..bd26335 100644 --- a/MANIFEST.json +++ b/MANIFEST.json @@ -4,13 +4,13 @@ "summary": "网易云音乐遥控器:一句话对上云里的内容(每日推荐 / 歌单 / 榜单 / 收藏 / FM / 最近 / 播客)并放出来;播放侧管好本机队列现场(快照 / back / 追加)", "tier": 1, "status": "stable", - "version": "fb22dd2", + "version": "fb22dd2.dirty", "source": { "path": "skills/netease-music", "commit": "fb22dd2", "describe": "fb22dd2", - "dirty": false, - "packed_at": "2026-10-01T23:34:48.413Z" + "dirty": true, + "packed_at": "2026-10-01T23:35:43.878Z" }, "platforms": [ "darwin" @@ -327,7 +327,7 @@ { "path": "VERSION", "bytes": 6, - "sha256": "80447316529fc620" + "sha256": "297b50f08386d352" }, { "path": "contract.lock.json", diff --git a/README.md b/README.md index 833cb7a..9ff683c 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,8 @@ 网易云音乐遥控器:一句话对上云里的内容(每日推荐 / 歌单 / 榜单 / 收藏 / FM / 最近 / 播客)并放出来;播放侧管好本机队列现场(快照 / back / 追加) -由 Pi 技能 `netease-music` 发布,当前版本 v0.1.1。命令名是 `netease-music`(仓库名带 `-cli`,命令不带)。 +由 Pi 技能 `netease-music` 发布(同一个源还有技能包那个出口),当前版本 v0.1.2。 +命令名是 `netease-music`:仓库名带 `-cli`,命令不带。 ## 安装 diff --git a/SKILL.md b/SKILL.md deleted file mode 100644 index b41107e..0000000 --- a/SKILL.md +++ /dev/null @@ -1,86 +0,0 @@ ---- -name: netease-music -description: 放网易云音乐并控制播放:直接调接口(搜歌点播、每日推荐、我喜欢的音乐、暂停切歌、音量、歌词、喜欢),不像以前那样模拟鼠标点界面。用户说「放首歌/放每日推荐/换一首/暂停/现在在放什么」时使用。 -platforms: [darwin] ---- - -# 网易云音乐(netease-music) - -**一句话**:`pi-skill netease-music daily` 直接开播每日推荐;`play <关键词>` 想听什么说什么;控制都是毫秒级命令,状态是真值。 - -## 何时用 - -| 用户说的 | 跑这个 | -|---|---| -| 放每日推荐 / 放点歌 | `pi-skill netease-music daily`(`--limit 20` 少放点,`--shuffle` 随机) | -| 放某首歌 / 某个歌手的歌 | `pi-skill netease-music play "<关键词>"` | -| 放某张歌单 | `pi-skill netease-music play "<歌单链接>"`(或 `play playlist:`;id 用 `myplaylists` 查) | -| 放我喜欢的音乐 | `pi-skill netease-music liked` | -| 放某位歌手的热门 | `pi-skill netease-music artist "陈粒"`(`--limit 20` 少放点;也可给歌手 id) | -| 放某张专辑 | `pi-skill netease-music album "自传"`(名字、id、专辑链接都行) | -| 查某歌手有哪些专辑 | `pi-skill netease-music albums "周杰伦"`(只列不播;搜不到正版专辑时用它拿 id) | -| 放别人做的歌单 | `pi-skill netease-music playlist "夜跑"`(名字直接写;`playlists "夜跑"` 只搜不播) | -| 放排行榜 | `pi-skill netease-music chart 飙升榜`(`charts` 列全部 63 个) | -| 放我收藏的歌单 / 专辑 / 歌手 | `pi-skill netease-music myplaylists collected` / `myalbums` / `myartists` | -| 放点没听过的 | `pi-skill netease-music fm`(私人 FM) | -| 刚才那首再放一遍 | `pi-skill netease-music replay`(`recent` 看最近播放) | -| 放播客(订阅的) | `pi-skill netease-music podcasts` → `podcast 黑水公园 --limit 3` | -| 换队列但别丢现场 | 每次换队列会自动留「上一条」:`back` 切回(含位置);`queue-save 名字` / `queue-load 名字` 自己存取的;`queues` 看有哪些 | -| 往队列里加一首 | `pi-skill netease-music add "幻听"`(不动正在放的那首) | -| 把搜索结果整列播放 / 从某首开始 | `pi-skill netease-music play-ids 1000,1001,1002 --start 2`(单个逗号分隔的 ID 参数;按输入顺序,序号从 1 开始) | -| 看队列 / 跳到第几首 | `pi-skill netease-music queue` / `jump 5` | -| 删除队列第几首 / 清空 | `pi-skill netease-music remove 3` / `clear`(当前项删除后选下一首,末尾选上一首,删空停止;保留暂停状态) | -| 单曲循环 / 整列循环 / 关闭循环 | `pi-skill netease-music repeat single` / `repeat list` / `repeat off`(旧 `on` = `list`;状态字段 `repeat_mode`) | -| 换一首 / 回上一首 | `pi-skill netease-music next` / `prev` | -| 暂停 / 继续 | `pi-skill netease-music pause` / `resume`(或 `toggle`) | -| 声音大点 / 小点 | `pi-skill netease-music volume 45`(不带数字=读当前值) | -| 现在在放什么 | `pi-skill netease-music status` | -| 这首歌歌词 | `pi-skill netease-music lyric`(`--all` 全文) | -| 查歌曲封面 / 下载封面 | `pi-skill netease-music cover "<歌曲关键词或id>"`(始终输出 JSON;加 `--download PATH` 下载,覆盖需 `--force`,最多 10 MB = 10,000,000 字节;不改变队列或登录态) | -| 这首好听,收藏 | `pi-skill netease-music like`(`unlike` 取消) | -| 私人 FM 这首不喜欢 | `pi-skill netease-music dislike`(也可 `dislike 1000` 指定歌曲 ID;提交 `fm/trash`,不自动切歌) | -| 查询哪些歌曲已喜欢 | `pi-skill netease-music liked-ids --json`(`{count,total,ids:[数字,...]}` 全表;只读) | -| 只是查有哪些歌 | `pi-skill netease-music search "<关键词>"`(只列不播) | -| 取歌曲 JSON 给播放器 | `node scripts/netease-api.mjs song "<关键词或id>"`(歌曲字段依次为 `id/name/artist/album/ms/vip/cover`;没有封面时为 `""`;接口提供布尔 `liked` 时追加它) | -| 列下一页 | `pi-skill netease-music myplaylists --limit 3 --offset 3`(跳过前 3 条;`--json` 带 `total`,人读样式不变) | - -**分页**:`playlist` / `liked` / `album` / `artist` / `chart` / `search` / `playlists` / `charts` / `myalbums` / `myartists` / `recent` / `podcasts` / `podcast`,以及 `myplaylists` / `albums` / `daily`,都支持 `--limit N --offset N`。`offset` 默认 0,从 0 起跳过 N 条;后端 JSON 的 `count` 是本页条数,`total` 是接口总数(没给总数时用接口返回、尚未本地截取的条数)。翻过末尾返回空列表,具体口径见 `REFERENCE.md`。 - -**封面**:`cover` 查询返回 `{id,name,artist,cover}`,下载返回 `{id,cover,file,bytes}`(`file` 为绝对路径,`bytes` 为实际字节数)。歌曲或封面缺失时报 `notfound` 错误 JSON;下载路径的父目录须已存在。字段来源与大小检查见 `REFERENCE.md` §2.2。 - -**批量与队列**:`play-ids [--start N]` 接收一个无空格、逗号分隔的正整数 ID 参数,保留顺序和重复项;默认从输入列表第 1 首开始。`--start` 指输入列表的 1 基序号;指定歌曲无播放地址或任一歌曲详情缺失时报错并保留旧队列,其他无地址项跳过并计入 `skipped`。它关闭随机,不支持 `--shuffle`。`remove N` 按 `queue` 显示的顺序删除(含随机队列);`clear` 停止、清掉本地队列和地址保活,保留配置及快照。 - -**喜欢状态**:列表、搜索和详情的歌曲对象仅在接口提供布尔值时追加 `liked: true|false`;`liked` 歌曲列表全部为 `true`。缺字段表示未知,可用只读 `liked-ids --json`(或 `node scripts/netease-api.mjs liked-ids`)取得完整 ID 数组后按 ID 补齐;不自动为每首歌增加请求。`dislike [id]` 是私人 FM 的不喜欢,与 `unlike` 分开;只提交 API,播放位置和队列保持原样。 - -**循环状态**:`repeat off|list|single` 同时设置 mpv 的两个循环属性;`on` 和无参数继续表示 `list`。`status` 的 `repeat_mode` 报 `off/list/single`,原 `repeat` 布尔字段仍表示是否整列循环。 - -**首次使用**:`pi-skill netease-music check`(自检依赖与登录态)。没登录就登一次,两条路都行: -`login --sms <手机号>` 收验证码,再 `login --sms <手机号> --sms-code <验证码>`(主力,实测最稳); -或 `login` 出二维码用手机网易云 App 扫(30 秒)。cookie 只存本机。 - -**与音箱配合**:电脑的声音去哪台设备由系统输出决定,要让家里的 EDIFIER 音箱出声就先 `pi-skill edifier-speaker bt`(它会切音箱档位 + 把系统输出接过去)。 - -## 失败 → 动作 - -| 现象 | 动作 | -|---|---| -| `error=auth`(未登录) | `login --sms <手机号>` 两步短信登录;或 `login` 扫码;或 `setup --cookie 'MUSIC_U=…'` 粘浏览器里的 cookie | -| `error=notfound`(搜不到/歌单不存在) | 换个关键词;歌单 id 用 `myplaylists` 查 | -| `error=notfound ... 没有一首能播` | 这首/这张全要 VIP 或没版权:换一个(周杰伦正版目录基本都这样) | -| 歌手/专辑搜到的是翻唱 | 用 `albums <歌手>` 拿正版专辑 id,再 `album `(网易搜索索引会缺正版) | -| `error=deps missing=mpv` | `brew install mpv`(播放器);`qrencode` 只在扫码登录时要 | -| `error=external ... url=null` | 那首要 VIP 或没版权,队列会自己跳过并在 `skipped=` 里报数量 | -| `error=timeout`(扫码超时) | 重新 `login`(二维码 2 分钟过期) | -| 队列有歌但没声音 | 系统输出没指向音箱:`pi-skill edifier-speaker bt`;或 `volume` 太小 | -| 播放卡在旧队列 | `stop` 清空队列再来 | -| `error=notfound 没有上一条可切回` | 还没换过队列;`queues` 看有哪些快照 | -| 换队列后想找回刚才那条 | `back`(回到上一条,含放到哪儿);更早的看 `queues`,或 `queue-load <名字>` | -| `add` 之后没马上听到 | 队列开着随机,新歌在队尾按随机顺序插进来;想顺序放先 `shuffle off` | -| 播客某一期放不出来 | 那期要付费或已下架;换几期:`podcast <播客> --limit 5` | - -## 边界 - -- 只做「播放与控制」,不碰客户端界面;官方客户端开着不受影响,两边互不干扰(各放各的)。 -- 音质默认无损(`quality`,改成 `exhigh` 可省流量)。 -- 歌单每页默认最多取 500 首,每日推荐 40 首(`--limit` 可调);用 `--offset` 接着取下一页,500 不是歌单总量上限。歌手热门默认 50 首、专辑默认 200 首;后端用 `total` 报分页前数量。 -- 能不能播由版权/VIP 决定:拉不到地址的会被跳过(`skipped=` 报数量),整张都拿不到就 `error=notfound`。 diff --git a/VERSION b/VERSION index 17e51c3..d917d3e 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.1.1 +0.1.2 diff --git a/contract.lock.json b/contract.lock.json deleted file mode 100644 index ab1c3f6..0000000 --- a/contract.lock.json +++ /dev/null @@ -1,174 +0,0 @@ -{ - "version": 1, - "skill": "netease-music", - "tier": 1, - "platforms": [ - "darwin" - ], - "commands": { - "add": { - "destructive": false - }, - "album": { - "destructive": false - }, - "albums": { - "destructive": false - }, - "artist": { - "destructive": false - }, - "back": { - "destructive": false - }, - "chart": { - "destructive": false - }, - "charts": { - "destructive": false - }, - "check": { - "destructive": false - }, - "clear": { - "destructive": false - }, - "cover": { - "destructive": false - }, - "daily": { - "destructive": false - }, - "dislike": { - "destructive": false - }, - "episode": { - "destructive": false - }, - "fm": { - "destructive": false - }, - "jump": { - "destructive": false - }, - "like": { - "destructive": false - }, - "liked": { - "destructive": false - }, - "liked-ids": { - "destructive": false - }, - "login": { - "destructive": false - }, - "lyric": { - "destructive": false - }, - "myalbums": { - "destructive": false - }, - "myartists": { - "destructive": false - }, - "myplaylists": { - "destructive": false - }, - "next": { - "destructive": false - }, - "pause": { - "destructive": false - }, - "play": { - "destructive": false - }, - "play-ids": { - "destructive": false - }, - "playlist": { - "destructive": false - }, - "playlists": { - "destructive": false - }, - "podcast": { - "destructive": false - }, - "podcasts": { - "destructive": false - }, - "prev": { - "destructive": false - }, - "queue": { - "destructive": false - }, - "queue-load": { - "destructive": false - }, - "queue-save": { - "destructive": false - }, - "queues": { - "destructive": false - }, - "recent": { - "destructive": false - }, - "remove": { - "destructive": false - }, - "repeat": { - "destructive": false - }, - "replay": { - "destructive": false - }, - "resume": { - "destructive": false - }, - "search": { - "destructive": false - }, - "seek": { - "destructive": false - }, - "setup": { - "destructive": false - }, - "shuffle": { - "destructive": false - }, - "status": { - "destructive": false - }, - "stop": { - "destructive": false - }, - "toggle": { - "destructive": false - }, - "unlike": { - "destructive": false - }, - "volume": { - "destructive": false - } - }, - "errors": [ - "auth", - "deps", - "external", - "internal", - "notfound", - "timeout", - "usage" - ], - "aliases": [ - "netease", - "netease-music" - ], - "adminAliases": [] -} diff --git a/interface.json b/interface.json deleted file mode 100644 index b3080b3..0000000 --- a/interface.json +++ /dev/null @@ -1,289 +0,0 @@ -{ - "summary": "网易云音乐遥控器:一句话对上云里的内容(每日推荐 / 歌单 / 榜单 / 收藏 / FM / 最近 / 播客)并放出来;播放侧管好本机队列现场(快照 / back / 追加)", - "useWhen": "用户要放网易云的音乐(每日推荐、指定歌曲/歌手、我喜欢的音乐)、问现在在放什么,或要暂停/切歌/调音量/看歌词/取歌曲封面时", - "tier": 1, - "entry": { - "path": "scripts/netease-music.sh" - }, - "aliases": [ - "netease", - "netease-music" - ], - "commands": [ - { - "name": "daily", - "summary": "每日推荐分页入队播放(--limit N / --offset N / --shuffle;JSON 带 total)" - }, - { - "name": "play", - "summary": "播一首或一整张:关键词→最匹配一首;歌单 id/链接→整张(--shuffle)" - }, - { - "name": "play-ids", - "summary": "play-ids [--start N]:按输入顺序整列替换,1 基起点默认 1;保留重复项,选中歌不可播则保留旧队列;关闭随机" - }, - { - "name": "search", - "summary": "只搜不播:列出 id/歌名/歌手/时长/是否要 VIP(--limit N / --offset N;JSON 带 total)" - }, - { - "name": "cover", - "summary": "cover <歌曲关键词|id> [--download PATH] [--force]:只读查询封面,JSON 为 id/name/artist/cover;下载为 id/cover/file/bytes,最多 10 MB(10000000 字节),覆盖需 --force;所有原语歌曲对象含字符串 cover(缺失为空)" - }, - { - "name": "artist", - "summary": "歌手热门分页入队播放(名字或 id;--limit N / --offset N;JSON 带 total)" - }, - { - "name": "album", - "summary": "专辑按顺序分页入队播放(名字、id 或专辑链接;--limit N / --offset N;JSON 带 total)" - }, - { - "name": "albums", - "summary": "只列不播:歌手的专辑(含老专辑;--limit N / --offset N;JSON 带 total)" - }, - { - "name": "liked", - "summary": "分页播放「我喜欢的音乐」(--limit N / --offset N;JSON 带 total)" - }, - { - "name": "liked-ids", - "summary": "只读喜欢 ID 全表;--json 为 {count,total,ids:[数字,...]};歌曲 JSON 透传可用的布尔 liked,缺字段时用全表按 id 判定" - }, - { - "name": "myplaylists", - "summary": "我的歌单(自建 + 收藏);--limit N / --offset N 分页,collected/own 筛本页;JSON 带 total" - }, - { - "name": "pause", - "summary": "暂停" - }, - { - "name": "resume", - "summary": "继续播放" - }, - { - "name": "toggle", - "summary": "暂停/继续切换" - }, - { - "name": "next", - "summary": "下一首" - }, - { - "name": "prev", - "summary": "上一首" - }, - { - "name": "stop", - "summary": "停止并清空队列" - }, - { - "name": "clear", - "summary": "停止并清空 mpv 和本地队列,收掉保活;配置和快照保留,可重复调用" - }, - { - "name": "volume", - "summary": "读或设音量(0-130)" - }, - { - "name": "seek", - "summary": "跳进度(相对秒数,如 +30)" - }, - { - "name": "queue", - "summary": "看队列(mpv 真值):每首歌名、时长,标出正在放的那首" - }, - { - "name": "jump", - "summary": "跳到队列第 N 首(从 1 开始),并回读状态确认" - }, - { - "name": "remove", - "summary": "remove :按 queue 显示的 1 基序号删除;当前项选下一首,末尾选上一首,删空停止;同步本地文件" - }, - { - "name": "status", - "summary": "当前曲目/进度/音量/队列位置(mpv 真值);repeat_mode 为 off/list/single" - }, - { - "name": "lyric", - "summary": "当前歌曲歌词(默认只显示当前句与下一句,--all 全文)" - }, - { - "name": "like", - "summary": "把当前这首歌加入「我喜欢的音乐」" - }, - { - "name": "unlike", - "summary": "把当前这首歌移出「我喜欢的音乐」" - }, - { - "name": "shuffle", - "summary": "队列随机开/关" - }, - { - "name": "repeat", - "summary": "repeat off|list|single:关闭/整列/单曲循环;on 和无参数 = list;状态追加 repeat_mode,保留旧 repeat 布尔含义" - }, - { - "name": "login", - "summary": "登录(--sms 手机号+验证码两步为主力;不带参数出二维码扫码),cookie 存本机 config" - }, - { - "name": "setup", - "summary": "写配置(--cookie/--quality);不带参数打印登录办法" - }, - { - "name": "check", - "summary": "只读自检:依赖、登录态、mpv 可用性、默认音质" - }, - { - "name": "playlist", - "summary": "放一张歌单:名字/id/链接都行(--limit N / --offset N;JSON 带 total)" - }, - { - "name": "playlists", - "summary": "搜歌单(只列不播):id / 名字 / 曲目数 / 作者 / 是否已收藏;--limit N / --offset N,JSON 带 total" - }, - { - "name": "charts", - "summary": "列排行榜(只列不播):飙升榜 / 新歌榜 / …;--limit N / --offset N,JSON 带 total" - }, - { - "name": "chart", - "summary": "放某个榜单:名字或 id(--limit N / --offset N;JSON 带 total)" - }, - { - "name": "myalbums", - "summary": "我收藏的专辑(只列不播;--limit N / --offset N;JSON 带 total;id 可喂 album)" - }, - { - "name": "myartists", - "summary": "我收藏的歌手(只列不播;--limit N / --offset N;JSON 带 total;id 可喂 artist)" - }, - { - "name": "fm", - "summary": "私人 FM:没听过的歌,整列入队开播(--limit N)" - }, - { - "name": "dislike", - "summary": "dislike [歌曲id]:私人 FM 不喜欢(fm/trash);省略 id 用当前歌曲,只上报,不自动切歌或改队列" - }, - { - "name": "recent", - "summary": "最近播放(只列不播,一周内,含播放次数;--limit N / --offset N;JSON 带 total)" - }, - { - "name": "replay", - "summary": "再放一次最近第 N 首(默认 1 = 最近那首)" - }, - { - "name": "podcasts", - "summary": "我的播客订阅(只列不播;--recommend 看推荐的;--limit N / --offset N;JSON 带 total)" - }, - { - "name": "podcast", - "summary": "放某播客的节目(--limit N 默认 3;--offset N;名字或 id;JSON 带 total)" - }, - { - "name": "episode", - "summary": "放某一期节目(节目 id 从 podcast 输出里抄)" - }, - { - "name": "queues", - "summary": "看本地队列快照(每次换队列会自动留一条「上一条」)" - }, - { - "name": "queue-save", - "summary": "把当前队列存成命名快照(只存歌曲列表,地址回放时重取)" - }, - { - "name": "queue-load", - "summary": "载入某个命名快照(含当时位置与随机状态)" - }, - { - "name": "back", - "summary": "切回上一条队列(含位置);再 back 一次切回来" - }, - { - "name": "add", - "summary": "把一首加到当前队列尾部,不动正在放的那首" - } - ], - "errors": [ - "usage", - "deps", - "auth", - "notfound", - "timeout", - "external", - "internal" - ], - "requires": [ - { - "kind": "runtime", - "name": "node", - "check": "which node", - "note": "接口客户端与 mpv 控制都是 node 脚本,零 npm 依赖" - }, - { - "kind": "runtime", - "name": "python3", - "check": "which python3" - }, - { - "kind": "binary", - "name": "mpv", - "install": "brew install mpv", - "check": "which mpv", - "note": "真正的播放器(常驻 + unix socket 控制)" - }, - { - "kind": "binary", - "name": "qrencode", - "install": "brew install qrencode", - "check": "which qrencode", - "note": "只在扫码登录时用" - } - ], - "config": [ - { - "key": "cookie", - "desc": "登录 cookie(MUSIC_U=…),由 login 命令扫码写入", - "type": "string", - "secret": true, - "required": true, - "ask": "扫码登录一次:pi-skill netease-music login", - "note": "只存本机 local/skills/netease-music/config.json,不进共享仓库" - }, - { - "key": "quality", - "desc": "音质级别:standard/higher/exhigh/lossless/hires", - "type": "enum", - "values": [ - "standard", - "higher", - "exhigh", - "lossless", - "hires" - ], - "default": "lossless" - } - ], - "helpListsCommands": true, - "probeUnknownCommand": true, - "admin": [ - { - "path": "scripts/install-cli.sh", - "runner": "sh", - "summary": "standalone 安装:不需要 Pi,把入口链接成 netease-music 并检查 node/mpv/python3" - } - ], - "publish": { - "repo": "https://gitea.vhkd.top/geekinney/netease-music-cli.git", - "mirrors": [ - "git@gitea.gklazycat.heiyu.space:geekinney/netease-music-cli.git" - ] - } -}