Skip to main content

music163-playlist

Automate NetEase Cloud Music (网易云音乐) playlist management via reverse-engineered internal Web APIs. Use when the user wants to list playlists, add/remove songs, search tracks, create/delete playlists, manage favorites (red heart), or bulk-import songs from text into NetEase Cloud Music.

الانتقال إلى التثبيت

معلومات المصدر

المستودع
XHXIAIEIN/music163-api
آخر نشاط في المصدر
١٤ أبريل ٢٠٢٦ في ٠٩:٥٤
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٢
التفرعات
٠

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

مستكشف الملفات
2 ملفات

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
music163-playlist
description
Automate NetEase Cloud Music (网易云音乐) playlist management via reverse-engineered internal Web APIs. Use when the user wants to list playlists, add/remove songs, search tracks, create/delete playlists, manage favorites (red heart), or bulk-import songs from text into NetEase Cloud Music.
# NetEase Cloud Music Playlist Automation Manage NetEase Cloud Music playlists through internal Web APIs reverse-engineered from music.163.com. All write APIs use the `/weapi/` encrypted endpoint. Reads can use either `/weapi/` or legacy `/api/`. Auth requires `MUSIC_U` cookie (login credential) and `__csrf` token. ## Authentication Try in priority order, stop on first success: **Strategy A — Auto-extract (when chrome-devtools-mcp is available)** Check if MCP tools `list_pages`, `select_page`, `evaluate_script` exist. If so: 1. `list_pages` → find page with URL containing `music.163.com` 2. If none → `new_page` to open `https://music.163.com` 3. `select_page` to select it 4. `evaluate_script`: ```javascript (async () => { const csrf = (document.cookie.match(/__csrf=([^;]+)/) || [])[1] || ""; if (!csrf) return { error: "Not logged in: no __csrf cookie. Please log in at music.163.com first." }; // MUSIC_U is HttpOnly — JS can't read it, but fetch sends it automatically. // Verify login by calling account API: const resp = await fetch("https://music.163.com/api/nuser/account/get", { method: "POST", credentials: "include", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: "csrf_token=" + csrf }); const data = await resp.json(); if (data.code !== 200 || !data.account) return { error: "Not logged in or session expired. Please log in at music.163.com." }; return { csrf, uid: data.account.id, nickname: data.profile?.nickname, status: "ok" }; })() ``` Note: `MUSIC_U` is `HttpOnly` — JavaScript cannot read it directly, but browser `fetch` with `credentials: 'include'` sends it automatically. Auth verification must be done by calling an API, not by reading cookies. **Strategy B — File / env vars** Check in order: - Env vars `MUSIC_U` and `NCM_UID` - `.env` file in project root (`MUSIC_U=xxx`, `NCM_UID=xxx`) **Strategy C — Ask user (last resort)** Tell the user: open music.163.com → F12 → Application → Cookies → copy `MUSIC_U` value. ## Encryption (weapi) All `/weapi/` requests require encrypted POST body. **Strategy A — Use page's built-in function (preferred):** music.163.com exposes `window.asrsea(text, pubKey, modulus, nonce)` which returns `{encText, encSecKey}`. This is the page's own encryption function — no need to reimplement. ```javascript function encrypt(data) { data.csrf_token = csrf; const enc = window.asrsea(JSON.stringify(data), "010001", "00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7", "0CoJUm6Qyw8W8jud"); return `params=${encodeURIComponent(enc.encText)}&encSecKey=${enc.encSecKey}`; } ``` Check availability: `typeof window.asrsea === 'function'`. If unavailable, page may not be fully loaded — wait or reload. **Strategy B — Manual CryptoJS (fallback for non-browser or if asrsea unavailable):** See reference.md "Encryption Constants" section for the full manual implementation using CryptoJS AES + BigInt RSA. ## How to Call APIs **With browser (Strategy A):** Execute encryption + `fetch` via `evaluate_script` in page context. All fetch calls must include `credentials: 'include'`. **Without browser (Strategy B/C):** Use Python with `pycryptodome` for AES encryption + built-in `pow()` for RSA, then `urllib`/`requests` POST with headers: ``` Cookie: MUSIC_U=<MUSIC_U> Referer: https://music.163.com/ Content-Type: application/x-www-form-urlencoded ``` Note: weapi POST body is `application/x-www-form-urlencoded` (NOT JSON). Send as `params=<encrypted>&encSecKey=<key>`. ## Operations | # | Operation | Endpoint | Type | |---|-----------|----------|------| | 0 | Get account info (uid) | `/weapi/w/nuser/account/get` | Read | | 1 | List user playlists | `/weapi/user/playlist` | Read | | 2 | Get playlist songs | `/weapi/v6/playlist/detail` | Read | | 3 | Add songs to playlist | `/weapi/playlist/manipulate/tracks` | Write | | 4 | Remove songs from playlist | `/weapi/playlist/manipulate/tracks` | Write | | 5 | Create playlist | `/weapi/playlist/create` | Write | | 6 | Delete playlist | `/weapi/playlist/remove` | Write | | 7 | Search songs | `/weapi/search/get` | Read | | 8 | Like / unlike song (red heart) | `/weapi/song/like` | Write | | 9 | Get liked song ID list | `/weapi/song/like/get` | Read | | 10 | Get song details (by ID) | `/weapi/v3/song/detail` | Read | | 11 | Bulk text import (search + add) | Composite workflow | Write | For full API specs, params, and code examples for each operation, read [reference.md](reference.md). ## Key Facts | Topic | Detail | |-------|--------| | `MUSIC_U` vs `__csrf` | `MUSIC_U` = login session token (long-lived, **HttpOnly** — JS cannot read it). `__csrf` = CSRF token (readable from cookie). Both sent automatically by browser fetch with `credentials: 'include'`. Verify login by calling `/api/nuser/account/get`, not by checking cookies. | | Encryption | All `/weapi/` endpoints require double-AES + RSA encrypted body. **Prefer `window.asrsea(text, pubKey, modulus, nonce)`** — the page's own encryption function. Falls back to manual CryptoJS implementation. | | Content-Type | weapi uses `application/x-www-form-urlencoded`, NOT JSON. Body: `params=<enc>&encSecKey=<key>`. | | Favorites playlist | "My Liked Music" (我喜欢的音乐) is the user's first playlist (index 0 in playlist list). Unlike QQ Music, there is NO fixed dirId — get it from the user's playlist list. | | Like (red heart) vs playlist add | Red heart = `/weapi/song/like` with `trackId` (string) + `like` (bool). Adding to favorites playlist = `/weapi/playlist/manipulate/tracks` with the favorites playlist ID. These are DIFFERENT operations. | | Song IDs | NetEase uses numeric `id` (e.g. `347230`). `trackIds` param takes JSON array of IDs: `[347230, 186016]`. | | `window.asrsea` | The page exposes `window.asrsea(text, pubKey, modulus, nonce)` → `{encText, encSecKey}`. Use this instead of manual encryption when in browser context. Check `typeof window.asrsea === 'function'` first. | | `cloudsearch` encrypted response | `/weapi/cloudsearch/get/web` returns encrypted hex in `result` field. Use `/weapi/search/get` instead — returns plain JSON. | | Delete playlist | Use `/weapi/playlist/remove` with `{ids: "[pid]"}`, NOT `/weapi/playlist/delete`. | | `chrome-devtools-mcp` | Required for browser automation. `claude-in-chrome` may block music.163.com. | | CryptoJS fallback | Only needed if `window.asrsea` is unavailable. Inject via CDN: `crypto-js/4.2.0/crypto-js.min.js`. | ## Rate Limits | Operation | Concurrency | Interval | |-----------|-------------|----------| | Read (playlist, search) | 5 parallel | 300ms | | Write (add/remove tracks) | Sequential | 500ms per batch | | Search | Sequential | 300ms per query | | Like/unlike | Sequential | 300ms per call | ## Output Format After each operation, report: - **Operation**: what was done - **Summary**: success / existed / failed counts - **Key data**: playlist ID, song count, batch count - **Errors**: specific error details if any ## Quality Bar - Read current state before writes (list → add → list to verify). - On mid-batch errors, log succeeded vs failed batches. Do not retry the entire operation. - Auth errors (code `301` or `-462`) → re-extract MUSIC_U, retry once. - Network errors → surface to user, let them decide. - Before adding songs, check if they already exist in the target playlist to avoid duplicates. ## Boundaries - Search returns first match; ambiguous song names may mismatch. Confirm with user when in doubt. - Only operates on the **currently logged-in user's** playlists. Cannot modify others' playlists. - Unofficial API — may break if NetEase changes backend. - Unlike QQ Music, NetEase has stricter rate limiting. Respect intervals to avoid IP blocks.
عرض على GitHub