聚合音源

聚合音源

Simwoodone (12535)09/27 21:43

该用户很懒,什么介绍也没有写!
二维码导入(APP尚未完成该功能)
{
    "bookSourceUrl": "聚合音源",
    "bookSourceName": "聚合音源",
    "enabledExplore": true,
    "enabled": true,
    "bookSourceGroup": "",
    "author": "",
    "help": true,
    "html": "<!DOCTYPE html>\r\n<html lang=\"zh-CN\" data-page-node-id=\"XQbVule4SKKfDw7Pu1K0dQ\">\r\n<head data-page-node-id=\"qpekIZcCGsOtsu2MotypIg\">\r\n  <meta charset=\"UTF-8\" data-page-node-id=\"A0awshuGDXr7pXstYwPY6R\">\r\n  <title>聚合音源(轻悦时光版)<\/title>\r\n<\/head>\r\n<body data-page-node-id=\"ipewB01HcTUxTTeFUa2qVv\">\r\n\r\n<\/body>\r\n<script>\r\n  var isCookieJar = true;\r\n  class FlutterJSBridge {\r\n    constructor() { this.init(); }\r\n    init() {\r\n      if (window.flutter_inappwebview) { this.isReady = true; this.CookieJar(); }\r\n      else { window.addEventListener('flutterInAppWebViewPlatformReady', () => { this.isReady = true; this.CookieJar(); }); }\r\n    }\r\n    async CookieJar() { try { await window.flutter_inappwebview.callHandler('CookieJar', isCookieJar); } catch (e) {} }\r\n    async log(str) { try { return await window.flutter_inappwebview.callHandler('log', str); } catch (e) { return false; } }\r\n    async text(type, str) { try { return await window.flutter_inappwebview.callHandler('text', type, str); } catch (e) { return false; } }\r\n    async showToast(str) { try { return await window.flutter_inappwebview.callHandler('showToast', str); } catch (e) { return false; } }\r\n    async showLongToast(str) { try { return await window.flutter_inappwebview.callHandler('showLongToast', str); } catch (e) { return false; } }\r\n    async openurlwithMimeType(url, mimeType) { try { return await window.flutter_inappwebview.callHandler('openurl', url, mimeType); } catch (e) { return false; } }\r\n    async openurl(url) { try { return await window.flutter_inappwebview.callHandler('openurl', url, \"\"); } catch (e) { return false; } }\r\n    async base64encode(str) { try { return await window.flutter_inappwebview.callHandler('base64encode', str); } catch (e) { return \"\"; } }\r\n    async base64decode(str) { try { return await window.flutter_inappwebview.callHandler('base64decode', str); } catch (e) { return \"\"; } }\r\n    async getsearch() { try { return await window.flutter_inappwebview.callHandler('getsearch'); } catch (e) { return -1; } }\r\n  }\r\n\r\n  class Http {\r\n    constructor() {\r\n      this.open = false;\r\n      this.requestTimestamps = [];\r\n      this.rateLimit = 5;\r\n      this.rateLimitWindow = 1000;\r\n    }\r\n    async checkRateLimit() {\r\n      if (!this.open) return;\r\n      const now = Date.now();\r\n      this.requestTimestamps = this.requestTimestamps.filter(t => now - t < this.rateLimitWindow);\r\n      if (this.requestTimestamps.length >= this.rateLimit) {\r\n        const oldest = this.requestTimestamps[0];\r\n        await new Promise(r => setTimeout(r, this.rateLimitWindow - (now - oldest)));\r\n        return this.checkRateLimit();\r\n      }\r\n      this.requestTimestamps.push(now);\r\n    }\r\n    async Get(url, headers, followRedirects) {\r\n      try {\r\n        await this.checkRateLimit();\r\n        return await window.flutter_inappwebview.callHandler('http', \"get\", url, \"\", JSON.stringify(headers || {}), followRedirects === false ? false : true, \"\");\r\n      } catch (e) { return null; }\r\n    }\r\n    async Post(url, headers, body, contenttype, followRedirects) {\r\n      try {\r\n        await this.checkRateLimit();\r\n        return await window.flutter_inappwebview.callHandler('http', \"post\", url, body, JSON.stringify(headers || {}), followRedirects === false ? false : true, contenttype || \"\");\r\n      } catch (e) { return null; }\r\n    }\r\n  }\r\n\r\n  class Cache {\r\n    async get(key) { try { return await window.flutter_inappwebview.callHandler('cache.get', key); } catch (e) { return null; } }\r\n    async set(key, value) { try { return await window.flutter_inappwebview.callHandler('cache.set', key, value); } catch (e) { return null; } }\r\n    async remove(key) { try { return await window.flutter_inappwebview.callHandler('cache.remove', key); } catch (e) { return null; } }\r\n    async allget(key) { try { return await window.flutter_inappwebview.callHandler('cache.allget', key); } catch (e) { return null; } }\r\n    async allset(key, value) { try { return await window.flutter_inappwebview.callHandler('cache.allset', key, value); } catch (e) { return null; } }\r\n    async putLyric(bookUrl, index, lyric) { try { return await window.flutter_inappwebview.callHandler('putLyric', bookUrl, index, lyric); } catch (e) { return null; } }\r\n  }\r\n<\/script>\r\n<script>\r\n  const flutterBridge = new FlutterJSBridge();\r\n  const cache = new Cache();\r\n  const http = new Http();\r\n\r\n  \/\/ ================= 配置 =================\r\n  const UA = \"Mozilla\/5.0 (Linux; Android 13; Pixel 7) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/120.0.0.0 Mobile Safari\/537.36\";\r\n  const GDS_API = \"https:\/\/music-api.gdstudio.xyz\/api.php\";\r\n  const GDS_HEADERS = { \"User-Agent\": UA, \"Referer\": \"https:\/\/music.gdstudio.xyz\/\", \"Accept\": \"application\/json\" };\r\n  const SUYIN_KUWO_API = \"https:\/\/oiapi.net\/api\/Kuwo\";\r\n  const LINGCHUAN_API = \"https:\/\/lc.guoyue2010.top\/api\/music\";\r\n  const NeteaseHeaders = { \"User-Agent\": \"Mozilla\/5.0 (Windows NT 10.0; Win64; x64) Chrome\/120.0.0.0\", \"Referer\": \"https:\/\/music.163.com\/\" };\r\n\r\n  \/\/ 音质档位(章节):br 对应 gdstudio 的码率参数\r\n  const QUALITIES = [\r\n    { br: \"128\", name: \"标准音质 128K\", kwBr: \"7\" },\r\n    { br: \"320\", name: \"高品音质 320K\", kwBr: \"5\" },\r\n    { br: \"740\", name: \"无损音质 FLAC\", kwBr: \"1\" },\r\n    { br: \"999\", name: \"Hi-Res 音质\", kwBr: \"1\" }\r\n  ];\r\n\r\n  \/\/ 发现页榜单(网易官方免加密接口)\r\n  const BOARDS = [\r\n    { id: \"3779629\", name: \"🔥 热歌榜\" },\r\n    { id: \"3778678\", name: \"🎵 新歌榜\" },\r\n    { id: \"19723756\", name: \"🚀 飙升榜\" },\r\n    { id: \"745956260\", name: \"✍️ 原创榜\" },\r\n    { id: \"10520166\", name: \"🎧 电音榜\" },\r\n    { id: \"60198\", name: \"🎹 轻音乐榜\" }\r\n  ];\r\n  const PAGE_SIZE = 30;\r\n\r\n  \/\/ ================= 工具函数 =================\r\n  function sleep(ms) { return new Promise(r => setTimeout(r, ms)); }\r\n\r\n  \/\/ UTF-8 安全 base64url(不用 flutterBridge,本地 harness 也能跑)\r\n  function utf8Bytes(str) {\r\n    const out = [];\r\n    for (let i = 0; i < str.length; i++) {\r\n      let c = str.codePointAt(i);\r\n      if (c > 0xffff) i++;\r\n      if (c < 0x80) out.push(c);\r\n      else if (c < 0x800) { out.push(0xc0 | (c >> 6), 0x80 | (c & 63)); }\r\n      else if (c < 0x10000) { out.push(0xe0 | (c >> 12), 0x80 | ((c >> 6) & 63), 0x80 | (c & 63)); }\r\n      else { out.push(0xf0 | (c >> 18), 0x80 | ((c >> 12) & 63), 0x80 | ((c >> 6) & 63), 0x80 | (c & 63)); }\r\n    }\r\n    return out;\r\n  }\r\n  function bytesToB64(bytes) {\r\n    let bin = \"\";\r\n    for (const b of bytes) bin += String.fromCharCode(b);\r\n    return btoa(bin);\r\n  }\r\n  function b64urlEncode(str) {\r\n    return bytesToB64(utf8Bytes(str)).replace(\/\\+\/g, \"-\").replace(\/\\\/\/g, \"_\").replace(\/=+$\/, \"\");\r\n  }\r\n  function b64urlDecode(s) {\r\n    s = s.replace(\/-\/g, \"+\").replace(\/_\/g, \"\/\");\r\n    while (s.length % 4) s += \"=\";\r\n    const bin = atob(s);\r\n    const bytes = [];\r\n    for (let i = 0; i < bin.length; i++) bytes.push(bin.charCodeAt(i));\r\n    let out = \"\";\r\n    let i = 0;\r\n    while (i < bytes.length) {\r\n      const b = bytes[i];\r\n      if (b < 0x80) { out += String.fromCharCode(b); i++; }\r\n      else if (b < 0xe0) { out += String.fromCharCode(((b & 31) << 6) | (bytes[i + 1] & 63)); i += 2; }\r\n      else if (b < 0xf0) { out += String.fromCharCode(((b & 15) << 12) | ((bytes[i + 1] & 63) << 6) | (bytes[i + 2] & 63)); i += 3; }\r\n      else {\r\n        const cp = ((b & 7) << 18) | ((bytes[i + 1] & 63) << 12) | ((bytes[i + 2] & 63) << 6) | (bytes[i + 3] & 63);\r\n        out += String.fromCodePoint(cp); i += 4;\r\n      }\r\n    }\r\n    return out;\r\n  }\r\n\r\n  function respText(res) {\r\n    if (!res) return \"\";\r\n    if (typeof res.data === \"string\") return res.data;\r\n    if (res.data && typeof res.data === \"object\") { try { return JSON.stringify(res.data); } catch (e) { return \"\"; } }\r\n    if (typeof res.body === \"string\") return res.body;\r\n    return \"\";\r\n  }\r\n  function respJson(res) {\r\n    const t = respText(res);\r\n    if (!t) return null;\r\n    \/\/ 兼容原生通道直接回对象\r\n    if (res.data && typeof res.data === \"object\" && !Array.isArray(res.data) && Object.keys(res.data).length) return res.data;\r\n    try { return JSON.parse(t); } catch (e) { return null; }\r\n  }\r\n\r\n  \/\/ gdstudio 请求(CF 随机 503 → 重试)\r\n  async function gdGet(params, retries) {\r\n    const qs = Object.keys(params).map(k => encodeURIComponent(k) + \"=\" + encodeURIComponent(params[k])).join(\"&\");\r\n    const url = GDS_API + \"?\" + qs;\r\n    const n = retries || 4;\r\n    let lastErr = \"\";\r\n    for (let i = 0; i < n; i++) {\r\n      try {\r\n        const res = await http.Get(url, GDS_HEADERS, true);\r\n        const txt = respText(res);\r\n        if (txt && txt.indexOf(\"503 Service\") === -1 && txt.trim().startsWith(\"{\")) {\r\n          const j = JSON.parse(txt);\r\n          if (j && (j.url || j.lyric || j.detail === undefined)) return j;\r\n          lastErr = j.detail || \"empty\";\r\n        } else if (txt.trim().startsWith(\"[\")) {\r\n          return JSON.parse(txt);\r\n        } else {\r\n          lastErr = \"503\/empty\";\r\n        }\r\n      } catch (e) { lastErr = e.message || String(e); }\r\n      if (i < n - 1) await sleep(600 * (i + 1));\r\n    }\r\n    throw new Error(\"星海API失败: \" + lastErr);\r\n  }\r\n\r\n  \/\/ 统一音质规格化\r\n  function normSong(raw, fallbackSource) {\r\n    const artists = Array.isArray(raw.artist) ? raw.artist.join(\"\/\") : (raw.artist || raw.artists || \"未知歌手\");\r\n    return {\r\n      id: String(raw.id || raw.url_id || \"\"),\r\n      name: raw.name || \"未知歌曲\",\r\n      singer: artists,\r\n      album: raw.album || \"\",\r\n      picId: String(raw.pic_id || raw.picId || \"\"),\r\n      lyricId: String(raw.lyric_id || raw.id || \"\"),\r\n      source: raw.source || fallbackSource || \"netease\"\r\n    };\r\n  }\r\n\r\n  function makeBookUrl(s) {\r\n    const meta = [s.name, s.singer, s.album, s.picId, s.lyricId, s.source].join(\"|\");\r\n    return \"klv:\" + s.id + \":\" + b64urlEncode(meta);\r\n  }\r\n  function parseBookUrl(u) {\r\n    const p = String(u).split(\":\");\r\n    if (p.length < 3 || p[0] !== \"klv\") return null;\r\n    const meta = b64urlDecode(p.slice(2).join(\":\"));\r\n    const f = meta.split(\"|\");\r\n    return { id: p[1], name: f[0] || \"\", singer: f[1] || \"\", album: f[2] || \"\", picId: f[3] || \"\", lyricId: f[4] || \"\", source: f[5] || \"netease\" };\r\n  }\r\n\r\n  \/\/ ================= 核心函数 =================\r\n  async function search(key, page, env) {\r\n    if (!key || !key.trim()) return \"[]\";\r\n    const p = Math.max(1, Number(page) || 1);\r\n    try {\r\n      const list = await gdGet({ types: \"search\", source: \"netease\", name: key.trim(), count: PAGE_SIZE, pages: p });\r\n      if (!Array.isArray(list) || !list.length) return \"[]\";\r\n      const books = list.map(raw => {\r\n        const s = normSong(raw, \"netease\");\r\n        return {\r\n          bookUrl: makeBookUrl(s),\r\n          name: s.name,\r\n          author: s.singer,\r\n          kind: \"音乐\",\r\n          type: 1,\r\n          coverUrl: \"\",\r\n          intro: s.album ? \"专辑:\" + s.album : \"网易云 · 裤佬聚合解析\"\r\n        };\r\n      });\r\n      return JSON.stringify(books);\r\n    } catch (e) {\r\n      await flutterBridge.log(\"[裤佬]搜索失败: \" + e.message);\r\n      if (p > 1) return \"[]\";\r\n      return JSON.stringify([{ bookUrl: \"klv:err:err\", type: 1, name: \"搜索失败(\" + e.message + \")\", author: \"裤佬\", intro: \"点开详情重试或稍后再搜\" }]);\r\n    }\r\n  }\r\n\r\n  async function info(bookurl) {\r\n    const s = parseBookUrl(bookurl);\r\n    if (!s) return JSON.stringify({ name: \"解析失败\", author: \"\", intro: \"bookUrl 无法识别: \" + bookurl });\r\n    let cover = \"\";\r\n    let intro = \"\";\r\n    if (s.album) intro += \"专辑:\" + s.album + \"\\n\";\r\n    intro += \"平台:网易云音乐 · 裤佬多线路解析\\n\";\r\n    \/\/ 封面\r\n    if (s.picId) {\r\n      try {\r\n        const pic = await gdGet({ types: \"pic\", source: s.source, id: s.picId, size: \"300\" });\r\n        if (pic && pic.url) cover = pic.url;\r\n      } catch (e) { await flutterBridge.log(\"[]封面失败: \" + e.message); }\r\n    }\r\n    \/\/ 歌词预览\r\n    let lyricText = \"\";\r\n    try {\r\n      const ly = await gdGet({ types: \"lyric\", source: s.source, id: s.lyricId });\r\n      if (ly && ly.lyric) {\r\n        lyricText = String(ly.lyric).replace(\/\\[\\d+:\\d+[.:]\\d+\\]\/g, \"\").replace(\/\\n{2,}\/g, \"\\n\").trim();\r\n        const lines = lyricText.split(\"\\n\").filter(l => l.trim()).slice(0, 12);\r\n        intro += \"\\n歌词预览:\\n\" + lines.join(\"\\n\");\r\n      }\r\n    } catch (e) { \/* 歌词失败不影响详情 *\/ }\r\n    intro += \"\\n\\n目录中的音质档位 = 章节,点击即播。\\n解析失败时自动降档并切换酷我线路。\";\r\n    return JSON.stringify({\r\n      name: s.name,\r\n      author: s.singer,\r\n      coverUrl: cover,\r\n      intro: intro,\r\n      kind: \"音乐\",\r\n      type: 1\r\n    });\r\n  }\r\n\r\n  async function chapter(tocUrl, bookurl) {\r\n    const chapters = QUALITIES.map((q, i) => ({\r\n      title: q.name,\r\n      url: \"play:\" + q.br + \":\" + i\r\n    }));\r\n    return JSON.stringify(chapters);\r\n  }\r\n\r\n  \/\/ 溯音酷我:关键词搜索型直链(fallback),带歌名\/歌手匹配校验\r\n  async function suyinKuwoUrl(s, kwBr) {\r\n    const kw = (s.name + \" \" + s.singer).trim();\r\n    const url = SUYIN_KUWO_API + \"?msg=\" + encodeURIComponent(kw) + \"&n=1&br=\" + kwBr;\r\n    const res = await http.Get(url, { \"User-Agent\": UA, \"Referer\": \"https:\/\/oiapi.net\/\" }, true);\r\n    const j = respJson(res);\r\n    if (!j) throw new Error(\"溯音酷我无响应\");\r\n    let link = \"\";\r\n    if (j.data && j.data.url) link = j.data.url;\r\n    else if (j.message) {\r\n      const m = String(j.message).match(\/音乐链接[::](\\S+)\/);\r\n      if (m) link = m[1];\r\n    }\r\n    if (!link) throw new Error(\"溯音酷我未返回链接\");\r\n    \/\/ 匹配校验:歌名必须能对上\r\n    if (j.data && j.data.song) {\r\n      const a = String(j.data.song).replace(\/\\s+\/g, \"\").toLowerCase();\r\n      const b = String(s.name).replace(\/\\s+\/g, \"\").toLowerCase();\r\n      if (a.indexOf(b) === -1 && b.indexOf(a) === -1) throw new Error(\"溯音酷我匹配到其他歌曲(\" + j.data.song + \")\");\r\n    }\r\n    return link;\r\n  }\r\n\r\n  \/\/ gdstudio 取链(当前档 → 向下降档重试)\r\n  async function gdPlayUrl(s, br) {\r\n    const order = [\"999\", \"740\", \"320\", \"128\"];\r\n    let idx = order.indexOf(String(br));\r\n    if (idx < 0) idx = order.length - 1;\r\n    let lastErr = null;\r\n    for (let i = idx; i < order.length; i++) {\r\n      try {\r\n        const j = await gdGet({ types: \"url\", source: s.source || \"netease\", id: s.id, br: order[i] }, 3);\r\n        if (j && j.url && \/^https?:\\\/\\\/\/.test(j.url)) return j.url;\r\n        lastErr = new Error(j && j.detail ? j.detail : \"未返回URL\");\r\n      } catch (e) { lastErr = e; }\r\n    }\r\n    throw lastErr || new Error(\"全部档位失败\");\r\n  }\r\n\r\n  \/\/ 聆川线路(裤佬特有;当前服务器时通时断,失败自动跳过)\r\n  async function lingchuanUrl(s, br) {\r\n    const brMap = { \"999\": \"flac24bit\", \"740\": \"flac\", \"320\": \"320k\", \"128\": \"128k\" };\r\n    const q = brMap[String(br)] || \"320k\";\r\n    const url = LINGCHUAN_API + \"\/url?source=\" + encodeURIComponent(s.source || \"wy\") + \"&songId=\" + encodeURIComponent(s.id) + \"&quality=\" + encodeURIComponent(q);\r\n    const res = await http.Get(url, { \"User-Agent\": UA, \"Referer\": \"https:\/\/lc.guoyue2010.top\/\" }, true);\r\n    const j = respJson(res);\r\n    if (!j || Number(j.code) !== 200 || !j.url) throw new Error(\"聆川\" + (j ? \"code=\" + j.code : \"无响应\"));\r\n    return j.url;\r\n  }\r\n\r\n  async function content(url, bookurl) {\r\n    const p = String(url).split(\":\");\r\n    const br = p[1] || \"320\";\r\n    const idx = Number(p[2] || 0);\r\n    const s = parseBookUrl(bookurl);\r\n    if (!s) return \"bookUrl 解析失败,请刷新书籍\";\r\n    \/\/ 歌词(听书歌词通道)\r\n    try {\r\n      const ly = await gdGet({ types: \"lyric\", source: s.source, id: s.lyricId }, 2);\r\n      if (ly && ly.lyric) await cache.putLyric(bookurl, idx, String(ly.lyric));\r\n    } catch (e) { \/* 歌词失败不阻断播放 *\/ }\r\n    const errs = [];\r\n    \/\/ 线路1: 星海主API(gdstudio) 降档重试\r\n    try {\r\n      const u = await gdPlayUrl(s, br);\r\n      return u;\r\n    } catch (e1) {\r\n      errs.push(\"星海: \" + e1.message);\r\n      await flutterBridge.log(\"[裤佬]星海线路失败: \" + e1.message);\r\n      \/\/ 线路2: 聆川(裤佬特有备用)\r\n      try {\r\n        const u0 = await lingchuanUrl(s, br);\r\n        return u0;\r\n      } catch (e0) {\r\n        errs.push(\"聆川: \" + e0.message);\r\n        \/\/ 线路3: 溯音酷我(按音质档映射 br)\r\n        try {\r\n          const q = QUALITIES.find(x => x.br === br) || QUALITIES[0];\r\n          const u2 = await suyinKuwoUrl(s, q.kwBr);\r\n          return u2;\r\n        } catch (e2) {\r\n          errs.push(\"酷我: \" + e2.message);\r\n          await flutterBridge.log(\"[裤佬]酷我线路失败: \" + e2.message);\r\n          return \"解析失败:\\n· \" + errs.join(\"\\n· \") + \"\\n\\n建议稍后重试(星海API有Cloudflare随机拦截,重试常可成功)\";\r\n        }\r\n      }\r\n    }\r\n  }\r\n\r\n  \/\/ ================= 发现页 =================\r\n  async function getfinds() {\r\n    return JSON.stringify(BOARDS.map(b => ({\r\n      title: b.name,\r\n      url: \"board:\" + b.id + \":page{{page}}\"\r\n    })));\r\n  }\r\n\r\n  async function find(url, page) {\r\n    const p = Math.max(1, Number(page) || 1);\r\n    const parts = String(url).split(\":\");\r\n    if (parts[0] !== \"board\") return \"[]\";\r\n    const boardId = parts[1];\r\n    if (p > 4) return \"[]\"; \/\/ 榜单 100 首 \/ 每页 30 = 4 页\r\n    const res = await http.Get(\"https:\/\/music.163.com\/api\/playlist\/detail?id=\" + boardId, NeteaseHeaders, true);\r\n    const j = respJson(res);\r\n    if (!j || !j.result || !Array.isArray(j.result.tracks)) return \"[]\";\r\n    const tracks = j.result.tracks.slice((p - 1) * PAGE_SIZE, p * PAGE_SIZE);\r\n    const books = tracks.map(t => {\r\n      const artists = Array.isArray(t.artists) ? t.artists.map(a => a.name).join(\"\/\") : \"未知歌手\";\r\n      const s = {\r\n        id: String(t.id), name: t.name, singer: artists,\r\n        album: t.album ? t.album.name : \"\", picId: \"\", lyricId: String(t.id), source: \"netease\"\r\n      };\r\n      return {\r\n        bookUrl: makeBookUrl(s),\r\n        name: s.name,\r\n        author: s.singer,\r\n        kind: \"音乐\",\r\n        type: 1,\r\n        coverUrl: t.album && t.album.picUrl ? t.album.picUrl + \"?param=200y200\" : \"\",\r\n        intro: s.album ? \"专辑:\" + s.album : \"\"\r\n      };\r\n    });\r\n    return JSON.stringify(books);\r\n  }\r\n\r\n  \/\/ 外部播放器:详情页按钮调用(解析当前最高可用档直链 → 交给系统播放器)\r\n  async function extPlay(bookurl) {\r\n    try {\r\n      const s = parseBookUrl(bookurl);\r\n      if (!s) { await flutterBridge.showLongToast(\"bookUrl 解析失败\"); return; }\r\n      const u = await gdPlayUrl(s, \"999\");\r\n      await flutterBridge.openurlwithMimeType(u, \"audio\/*\");\r\n    } catch (e) {\r\n      await flutterBridge.showLongToast(\"外部播放解析失败: \" + e.message);\r\n    }\r\n  }\r\n\r\n  async function filter() { return \"\"; }\r\n  async function findfilter(url) { return \"\"; }\r\n  async function gethelp() {\r\n    return \"@html:<h3>聚合音源(轻悦时光版)<\/h3><p>移植自洛雪音源「SVIP音源(解密版) v0721」。<\/p><ul><li><b>搜索<\/b>:星海API(网易云)聚合搜索<\/li><li><b>播放<\/b>:星海主线路 → 聆川线路 → 溯音酷我线路 兜底(自动降档)<\/li><li><b>音质<\/b>:128K\/320K\/FLAC\/Hi-Res 四档,音质即章节<\/li><li><b>发现页<\/b>:网易官方六大榜单<\/li><li><b>歌词<\/b>:自动加载(播放时)<\/li><li>星海API有Cloudflare随机拦截,失败重试通常可恢复;聆川线路当前不稳定,恢复后自动生效<\/li><\/ul><p>外部播放:详情页按钮,交给 MX Player\/VLC\/SenPlayer 等系统播放器。<\/p>\";\r\n  }\r\n<\/script>\r\n<\/html>\r\n",
    "login": false,
    "customButton": true,
    "eventListener": true,
    "lastUpdateTime": "1790516607087"
}
广告