🗨️ 轻之国度

https://api.lightnovel.fun

t2157111 (9598)10/01 21:28

v26.10.01 [阅读书源] 轻之国度API源

轻之国度(魔王轻文学社区)新版 API 源 
// 上一版书源对完整重写,官方已更换接口 
// 2026/10/01 首版作者 By sjshb57 内容如下:
· 搜索/详情/目录/正文均走新版 /proxy/api 接口,目录复用详情数据、分卷并发拉取
· 公开章节无需登录;勇者/付费章节标 🔒,付费章节显示试读并提示价格
· 登录页「花费轻币」开启后,打开付费章节时自动解锁
· 自动清理旧帖迁移的论坛代码与正文残留标签
· 登录页:登录、登录状态、退出、花费轻币、繁转简
· 发现页:分类实时读取官方接口并缓存,支持频道/排序/状态筛选

强烈推荐搭配使用主包制作的legado数字标题!!非常智能!代码已开源↓

推推:https://github.com/sjshb57/legado-57

直链:
https://shuyuan.nyasama.net/shuyuan/35acc89e34bb6515359ac12df563b59d.json
二维码导入
{
    "bookSourceComment": "轻之国度(魔王轻文学社区)新版 API 源 \n\/\/ 上一版书源对完整重写,官方已更换接口 \n\/\/ 2026\/10\/01 首版作者 By sjshb57 制作内容如下:\n· 搜索\/详情\/目录\/正文均走新版 \/proxy\/api 接口,目录复用详情数据、分卷并发拉取\n· 公开章节无需登录;勇者\/付费章节标 🔒,付费章节显示试读并提示价格\n· 登录页「花费轻币」开启后,打开付费章节时自动解锁\n· 自动清理旧帖迁移的论坛代码与正文残留标签\n· 登录页:登录、登录状态、退出、花费轻币、繁转简\n· 发现页:分类实时读取官方接口并缓存,支持频道\/排序\/状态筛选",
    "bookSourceGroup": "🗨️ 轻文",
    "bookSourceName": "🗨️ 轻之国度",
    "bookSourceType": 0,
    "bookSourceUrl": "https:\/\/api.lightnovel.fun",
    "customButton": false,
    "customOrder": 5,
    "enabled": true,
    "enabledCookieJar": false,
    "enabledExplore": true,
    "eventListener": false,
    "exploreUrl": "@js:\nvar cfg = {};\ntry { cfg = JSON.parse(String(source.getVariable() || '{}')) || {}; } catch (e) {}\n\nvar tax = cfg.fast && cfg.tax;\nif (!tax) {\n    tax = null;\n    try {\n        var tab = (JSON.parse(java.ajax(lkTaxonomy())).data.tabs || [])[0] || {};\n        tax = {\n            ch: (tab.channels || []).map(function (c) {\n                return [String(c.label), String((c.filter_payload && c.filter_payload.work_type) || c.code)];\n            }),\n            groups: (tab.groups || []).filter(function (g) {\n                return String(g.title).indexOf('热门') < 0;\n            }).map(function (g) {\n                var items = [];\n                (g.sections || []).forEach(function (sec) {\n                    (sec.tag_items || []).forEach(function (t) {\n                        items.push([String(t.title), t.filter_payload || {q: '', primary_tag: String(t.title)}]);\n                    });\n                });\n                return [String(g.title), items];\n            }).filter(function (g) { return g[1].length; })\n        };\n        if (tax.groups.length) cfg.tax = tax;\n    } catch (e) {}\n    tax = tax || {ch: [], groups: []};\n}\ndelete cfg.fast;\nsource.setVariable(JSON.stringify(cfg));\n\nvar CH = [['全部', '', 'all']].concat(tax.ch.map(function (c) { return [c[0], c[1], c[1]]; }));\nvar ch = CH.filter(function (c) { return c[1] == cfg.ch; })[0] || CH[0];\nvar open = cfg.open || {};\nvar sort = cfg.sort || 'relevance', status = cfg.st || 'all';\n\nvar SORT = [['默认排序', 'relevance'], ['最新', 'new'], ['评分', 'score'], ['字数', 'words']];\nvar STATUS = [['全部状态', 'all'], ['完结', 'completed'], ['连载', 'serializing']];\nfunction label(opts, v) { return (opts.filter(function (o) { return o[1] == v; })[0] || opts[0])[0]; }\n\nvar LAYOUT = {gap: 0.042, pad: 0.068, ch: 0.0368, shortMax: 3.3};\n\nfunction textWidth(t) {\n    var w = 0;\n    for (var i = 0; i < t.length; i++) {\n        var c = t.charCodeAt(i);\n        if (c == 32) w += 0.32;\n        else if (c < 128) w += 0.65;\n        else if (c == 0xB7) w += 0.5;\n        else if (c == 0x25CF) w += 0.9;\n        else w += 1;\n    }\n    return w;\n}\n\nvar s = [];\n\nfunction pack(items, cols) {\n    cols = cols || 4;\n    var g = LAYOUT.gap, cell = (1 - g * (cols - 1)) \/ cols;\n    var fit = (cell - LAYOUT.pad) \/ LAYOUT.ch;\n    var queue = items.map(function (it) {\n        return {it: it, span: Math.min(cols, Math.ceil(textWidth(it.title) \/ fit) || 1)};\n    });\n    while (queue.length) {\n        var row = [], left = cols;\n        while (queue.length && left > 0) {\n            var k = 0;\n            while (k < queue.length && queue[k].span > left) k++;\n            if (k == queue.length) break;\n            var x = queue.splice(k, 1)[0];\n            row.push(x); left -= x.span;\n        }\n        for (; left > 0; left--) row.push({it: {title: ' ', url: ''}, span: 1});\n        row.forEach(function (x, i) {\n            var st = {layout_flexGrow: x.span, layout_flexBasisPercent: Math.round((x.span \/ (cols + 1) + (x.span - 1) * g) * 1e4) \/ 1e4};\n            if (i == 0) st.layout_wrapBefore = true;\n            x.it.style = st;\n            s.push(x.it);\n        });\n    }\n}\n\nfunction action(js) {\n    return \"(function(){var c={};try{c=JSON.parse(String(source.getVariable()||'{}'))||{};}catch(e){}\"\n        + js + \"c.fast=1;source.setVariable(JSON.stringify(c));java.refreshExplore();})()\";\n}\nfunction button(title, js) {\n    return {title: title, type: 'button', action: action(js)};\n}\nfunction bar(title, js) {\n    var b = button(title, js);\n    b.style = {layout_flexGrow: 1, layout_flexBasisPercent: 1, layout_wrapBefore: true};\n    s.push(b);\n}\nfunction optionRow(key, opts, cur) {\n    pack(opts.map(function (o) {\n        return button((o[1] == cur ? '● ' : '') + o[0], 'c[' + JSON.stringify(key) + ']=' + JSON.stringify(o[1]) + ';');\n    }), 3);\n}\n\nfunction listUrl(payload) {\n    return \"{{lkList('\" + encodeURIComponent(JSON.stringify(payload)) + \"',page,'\" + ch[1] + \"','\" + sort + \"','\" + status + \"')}}\";\n}\n\nfunction group(name, defOpen, count, build) {\n    var isOpen = name in open ? !!open[name] : defOpen;\n    bar((isOpen ? '▾ ' : '▸ ') + name + '(' + count + ')',\n        'var o=c.open||{};o[' + JSON.stringify(name) + ']=' + (isOpen ? 0 : 1) + ';c.open=o;');\n    if (isOpen) build();\n}\n\npack(CH.map(function (c) {\n    return button((c[1] == ch[1] ? '● ' : '') + c[0], 'c.ch=' + JSON.stringify(c[1]) + ';');\n}), 3);\n\nbar('⚙ 筛选:' + label(SORT, sort) + ' · ' + label(STATUS, status) + (cfg.filt ? ' ▾' : ' ▸'), 'c.filt=!c.filt;');\nif (cfg.filt) {\n    optionRow('sort', SORT, sort);\n    optionRow('st', STATUS, status);\n}\n\ngroup('书库', true, 3, function () {\n    pack([\n        {title: '最近更新', url: listUrl({q: '最近更新'})},\n        {title: '日榜', url: \"{{lkRank('daily_\" + ch[2] + \"',page)}}\"},\n        {title: '周榜', url: \"{{lkRank('weekly_\" + ch[2] + \"',page)}}\"}\n    ], 3);\n});\n\nif (!tax.groups.length) s.push({title: '⚠ 分类加载失败', url: '', style: {layout_flexGrow: 1, layout_flexBasisPercent: 1, layout_wrapBefore: true}});\ntax.groups.forEach(function (g, gi) {\n    group(g[0], gi == 0, g[1].length, function () {\n        var short = [], long = [];\n        g[1].forEach(function (t) {\n            var it = {title: t[0], url: listUrl(t[1])};\n            (textWidth(t[0]) > LAYOUT.shortMax ? long : short).push(it);\n        });\n        pack(short, 4);\n        pack(long, 3);\n    });\n});\n\nJSON.stringify(s);\n",
    "header": "{\"User-Agent\": \"Dart\/3.11 (dart:io)\"}",
    "jsLib": "var LK_API = 'https:\/\/api.lightnovel.fun\/proxy\/api';\nvar LK_HEADERS = {'User-Agent': 'Dart\/3.11 (dart:io)', 'Content-Type': 'application\/json'};\n\nfunction lkUrl(path, d, key, fresh) {\n    d = d || {};\n    d.security_key = key || '';\n    var b = {is_encrypted: 0, platform: 'android', client: 'app', gz: 0, d: d};\n    if (fresh) {\n        b.ts = Math.floor(Date.now() \/ 1000);\n        b.nonce = (Math.random().toString(36) + Math.random().toString(36)).replace(\/0\\.\/g, '').slice(0, 12);\n    }\n    var body = JSON.stringify(b);\n    return LK_API + path + ',' + JSON.stringify({method: 'POST', body: body, headers: LK_HEADERS});\n}\n\nfunction lkKey(source) {\n    try { return String(source.get('lk_key') || ''); } catch (e) { return ''; }\n}\n\nfunction lkZhOn(source) {\n    try { return String(source.get('lk_zh') || '') == '1'; } catch (e) { return false; }\n}\n\nfunction lkCoinOn(source) {\n    try { return String(source.get('lk_coin') || '') == '1'; } catch (e) { return false; }\n}\n\nfunction lkSearch(q, page) {\n    return lkUrl('\/bff\/apk-search-result-v1', {page: page - 1, pageSize: 20, q: String(q), source: 'manual', sort: 'relevance'});\n}\n\nfunction lkList(payload, page, work, sort, status) {\n    var d = {};\n    try { d = JSON.parse(decodeURIComponent(payload)) || {}; } catch (e) {}\n    d.page = page - 1;\n    d.pageSize = 20;\n    d.source = 'category_tag';\n    d.sort = sort || 'relevance';\n    if (d.q == null) d.q = '';\n    if (work) d.work_type = work;\n    if (status && status != 'all') d.status_bucket = status;\n    return lkUrl('\/bff\/apk-search-result-v1', d);\n}\n\nfunction lkTaxonomy() {\n    return lkUrl('\/bff\/apk-search-taxonomy-v1', {});\n}\n\nfunction lkRank(scene, page) {\n    return lkUrl('\/bff\/book-rank-list-v1', {page: page - 1, pageSize: 20, rank_scene: scene});\n}\n\nfunction lkDetail(id) {\n    return lkUrl('\/new-content-read\/get-book-detail', {book_id: parseInt(id)});\n}\n\nfunction lkChapter(id, key) {\n    return lkUrl('\/new-content-read\/get-chapter-detail', {chapter_id: parseInt(id), with_body: 1}, key);\n}\n\nfunction lkStatus(o) {\n    if (o.serial_status == 'completed' || o.is_completed == 1) return '已完结';\n    if (o.serial_status == 'serializing') return '连载中';\n    return '';\n}\n\nfunction lkTags(o) {\n    var r = [];\n    (o.tags || []).forEach(function (t) {\n        t = String(typeof t == 'string' ? t : (t.name || t.tag_name || ''));\n        if (t && r.indexOf(t) < 0) r.push(t);\n    });\n    return r;\n}\n\nfunction lkKind(o) {\n    var r = [];\n    if (o.work_type && o.work_type.text) r.push(o.work_type.text);\n    var st = lkStatus(o);\n    if (st) r.push(st.replace('已', '').replace('中', ''));\n    return r.concat(lkTags(o)).join(',');\n}\n\nfunction lkBbcode(t) {\n    t = String(t)\n        .replace(\/\\[input_pos\\][\\s\\S]*?\\[\\\/input_pos\\]\/gi, '')\n        .replace(\/\\[i=s\\][\\s\\S]*?\\[\\\/i\\]\/gi, '')\n        .replace(\/\\[img\\]\\s*(https?:\\\/\\\/[^\\[\\s]+?)\\s*\\[\\\/img\\]\/gi, '<img src=\"$1\">');\n    ['justify', 'left', 'right', 'center', 'align', 'font', 'size', 'color', 'backcolor',\n     'b', 'i', 'u', 's', 'indent', 'float', 'quote', 'code', 'url', 'email',\n     'list', 'table', 'tr', 'td', 'p', 'ruby', 'rp', 'rt', 'media', 'attach'].forEach(function (n) {\n        t = t.replace(new RegExp('\\\\[' + n + '=[^\\\\]\\\\n]{1,80}\\\\]', 'gi'), '');\n        if (new RegExp('\\\\[\\\\\/' + n + '\\\\]', 'i').test(t)) {\n            t = t.replace(new RegExp('\\\\[\\\\\/?' + n + '\\\\]', 'gi'), '');\n        }\n    });\n    return t;\n}\n\nfunction lkIntro(o) {\n    var t = lkBbcode(String(o.summary || o.summary_short || '').replace(\/\\\\n\/g, '\\n').replace(\/\\r\/g, ''))\n        .replace(\/[—-\\-_=]{5,}\/g, '')\n        .replace(\/[ \\t\\u3000]*\\n[\\s\\u3000]*\/g, '\\n')\n        .trim();\n    return \/^[\\s.…]*$\/.test(t) ? '' : t;\n}\n\nfunction lkTime(t) {\n    return String(t || '').replace(\/:\\d\\d$\/, '');\n}\n\nfunction lkInfo(o) {\n    var uniq = function (v, i, a) { return v && a.indexOf(v) == i; };\n    var words = parseInt(o.word_count) || 0;\n    var ws = words >= 10000 ? (words \/ 10000).toFixed(1) + '万字' : (words ? words + '字' : '');\n    var size = (o.volume_count ? o.volume_count + '卷' : '') + (o.chapter_count ? o.chapter_count + '章' : '');\n    var posters = (o.poster_users || (o.poster_user ? [o.poster_user] : [])).map(function (u) { return String(u.nickname || ''); }).filter(uniq);\n    var rating = o.rating_displayable == 1 && o.rating_score_10 ? o.rating_score_10 + '(' + o.rating_count + '人评分)' : '';\n    var L = [];\n    var add = function (icon, label, val) { if (val) L.push('\\u3000\\u3000' + icon + ' ' + label + ':' + val); };\n    add('📕', '书名', String(o.title || ''));\n    add('👤', '作者', String(o.author_name || ''));\n    add('📤', '发布', posters.join(' · '));\n    add('🗂️', '类型', o.work_type && o.work_type.text);\n    add('📊', '字数', [ws, lkStatus(o), size].filter(uniq).join(' · '));\n    add('🔖', '标签', lkTags(o).join(' · '));\n    add('⭐', '评分', rating);\n    add('👀', '在读', o.active_reader_count ? o.active_reader_count + '人' : '');\n    add('🕐', '更新', lkTime(o.updated_at));\n    var desc = lkIntro(o);\n    if (desc) {\n        L.push('\\u3000\\u3000\\u200b');\n        L.push('\\u3000\\u3000📜 简介:');\n        L.push('\\u3000\\u3000' + desc.replace(\/\\n\/g, '\\n\\u3000\\u3000'));\n    }\n    L.push('\\u3000\\u3000\\u200b');\n    L.push('\\u3000\\u3000📍 书籍状态:正常');\n    return L.join('\\n');\n}\n\nfunction lkBook(o, full) {\n    return JSON.stringify({\n        name: String(o.title || ''),\n        author: String(o.author_name || ''),\n        kind: lkKind(o),\n        intro: full ? lkInfo(o) : (lkIntro(o) || '暂无简介'),\n        cover: String(o.cover_url || ''),\n        words: String(o.word_count || ''),\n        last: o.updated_at ? '更新于 ' + String(o.updated_at).slice(0, 10) : '',\n        url: lkDetail(o.book_id)\n    });\n}\n\nfunction lkLockTip(d, loggedIn, coinOn, err) {\n    var L = [];\n    if (d.brave_required == 1 || d.access_type == 'brave') {\n        L.push('🔒 本章需要「勇者」身份才能阅读。');\n    } else if (d.access_type == 'coin') {\n        var pct = parseInt(d.preview_percent || d.free_node) || 0;\n        L.push('🔒 本章为付费章节' + (d.coin_price > 0 ? ',需 ' + d.coin_price + ' 轻币解锁' : '') + '。');\n        if (pct) L.push('以上为试读内容(约 ' + pct + '%)。');\n        if (err) L.push('自动解锁失败:' + err);\n        else if (!loggedIn) L.push('请先在书源登录页登录,并开启「花费轻币」后重新加载本章。');\n        else if (!coinOn) L.push('可在书源登录页开启「花费轻币」后重新加载本章。');\n    } else {\n        L.push('🔒 本章暂时无法阅读(' + (d.access_type || '未知原因') + ')。');\n        if (!loggedIn) L.push('当前未登录,可在书源登录页登录后重试。');\n    }\n    return L.map(function (x) { return '<p>' + x + '<\/p>'; }).join('\\n');\n}\n\nfunction lkHtml(d) {\n    var html = String((d.body_snapshot && d.body_snapshot.body_html) || (d.render_preview && d.render_preview.body_html) || '');\n    html = html.replace(\/<p[^>]*>\/gi, '<p>').replace(\/<\\\/?span[^>]*>\/gi, '')\n        .replace(\/&lt;\\\/?p(?:\\s[\\s\\S]*?)?&gt;\/gi, '')\n        .replace(\/<p>\\s*\\*\\*\/g, '<p>').replace(\/\\*\\*\\s*<\\\/p>\/g, '<\/p>');\n    html = html.replace(\/<a\\b[^>]*?href=\"([^\"]+)\"[^>]*>([\\s\\S]*?)<\\\/a>\/gi, function (m, url, label) {\n        var t = label.replace(\/<[^>]+>\/g, '').trim();\n        return !t || t == url ? url : t + ':' + url;\n    });\n    return lkBbcode(html).replace(\/<p>[\\s\\u3000\\u00a0]*<\\\/p>\/g, '').trim();\n}\n",
    "lastUpdateTime": "1790861312577",
    "loginUi": "[\n  {\n    \"name\": \"账号\",\n    \"type\": \"text\"\n  },\n  {\n    \"name\": \"密码\",\n    \"type\": \"password\"\n  },\n  {\n    \"name\": \"🔑 登录\",\n    \"type\": \"button\",\n    \"action\": \"login()\",\n    \"style\": {\n      \"layout_flexGrow\": 1,\n      \"layout_flexBasisPercent\": 1\n    }\n  },\n  {\n    \"name\": \"ℹ️ 登录状态\",\n    \"type\": \"button\",\n    \"action\": \"lkStatus()\",\n    \"style\": {\n      \"layout_flexGrow\": 1,\n      \"layout_flexBasisPercent\": 0.4\n    }\n  },\n  {\n    \"name\": \"🚪 退出登录\",\n    \"type\": \"button\",\n    \"action\": \"lkLogout()\",\n    \"style\": {\n      \"layout_flexGrow\": 1,\n      \"layout_flexBasisPercent\": 0.4\n    }\n  },\n  {\n    \"name\": \"💰 花费轻币\",\n    \"type\": \"button\",\n    \"action\": \"lkToggleCoin()\",\n    \"style\": {\n      \"layout_flexGrow\": 1,\n      \"layout_flexBasisPercent\": 0.4\n    }\n  },\n  {\n    \"name\": \"🈶 繁转简\",\n    \"type\": \"button\",\n    \"action\": \"lkToggleZh()\",\n    \"style\": {\n      \"layout_flexGrow\": 1,\n      \"layout_flexBasisPercent\": 0.4\n    }\n  }\n]",
    "loginUrl": "@js:\nfunction login() {\n    var info = source.getLoginInfoMap() || {};\n    var u = info.get ? info.get('账号') : info['账号'];\n    var p = info.get ? info.get('密码') : info['密码'];\n    if (!u || !p) throw new Error('请先填写账号和密码');\n    var r = JSON.parse(java.ajax(lkUrl('\/bff\/auth-password-login-v1', {username: String(u), password: String(p)})));\n    if (r.code == 0 && r.data && r.data.auth && r.data.auth.security_key) {\n        source.put('lk_key', String(r.data.auth.security_key));\n        java.toast('✅ 登录成功:' + ((r.data.user && r.data.user.nickname) || r.data.auth.uid));\n        return;\n    }\n    throw new Error(r.code == 2 ? '账号或密码错误' : '登录失败 code:' + r.code);\n}\n\nfunction lkStatus() {\n    var key = lkKey(source);\n    if (!key) { java.toast('⚪ 未登录'); return; }\n    var r = JSON.parse(java.ajax(lkUrl('\/bff\/auth-session-v1', {}, key)));\n    if (r.code == 0 && r.data && r.data.logged_in == 1) {\n        var u = r.data.user || {};\n        java.toast('✅ 已登录:' + (u.nickname || u.uid) + (u.level ? '(' + u.level.name + ')' : ''));\n    } else {\n        java.toast('⚠️ 登录已失效,请重新登录');\n    }\n}\n\nfunction lkLogout() {\n    source.put('lk_key', '');\n    java.toast('🚪 已退出登录');\n}\n\nfunction lkToggleCoin() {\n    var on = !lkCoinOn(source);\n    source.put('lk_coin', on ? '1' : '');\n    java.toast(on ? '💰 花费轻币:已开启(打开付费章节时自动解锁)' : '💰 花费轻币:已关闭');\n}\n\nfunction lkToggleZh() {\n    var on = !lkZhOn(source);\n    source.put('lk_zh', on ? '1' : '');\n    java.toast(on ? '🈶 繁转简:已开启(刷新目录后生效)' : '🈶 繁转简:已关闭');\n}\n",
    "respondTime": 180000,
    "ruleBookInfo": {
        "author": "$.author",
        "coverUrl": "$.cover",
        "init": "@js:lkBook(JSON.parse(result).data || {}, true)",
        "intro": "$.intro",
        "kind": "$.kind",
        "lastChapter": "$.last",
        "name": "$.name",
        "tocUrl": "$.url",
        "wordCount": "$.words"
    },
    "ruleContent": {
        "content": "@js:\nvar d = JSON.parse(result).data || {};\nvar key = lkKey(source);\nvar coinOn = lkCoinOn(source);\nvar err = '';\nfunction reload() {\n    try { d = JSON.parse(java.ajax(lkChapter(d.chapter_id, key))).data || d; } catch (e) {}\n}\nif (d.locked == 1 && key) {\n    reload();\n    if (d.locked == 1 && d.access_type == 'coin' && coinOn) {\n        try {\n            var u = JSON.parse(java.ajax(lkUrl('\/new-content-read\/unlock-chapter', {chapter_id: d.chapter_id}, key, true)));\n            if (u.code == 0) reload();\n            else err = String((u.data && u.data.message) || u.message || 'code ' + u.code);\n        } catch (e) { err = String(e); }\n    }\n}\nvar out = lkHtml(d);\nif (d.locked == 1) out = (out ? out + '\\n' : '') + lkLockTip(d, !!key, coinOn, err);\nelse if (!out) out = '⚠️ 本章暂无内容';\nif (lkZhOn(source)) out = String(java.t2s(out));\nout;\n",
        "imageStyle": "FULL"
    },
    "ruleExplore": {
        "author": "$.author",
        "bookList": "@js:(JSON.parse(result).data.list || []).map(function (o) { return lkBook(o); })",
        "bookUrl": "$.url",
        "coverUrl": "$.cover",
        "intro": "$.intro",
        "kind": "$.kind",
        "lastChapter": "$.last",
        "name": "$.name",
        "wordCount": "$.words"
    },
    "ruleSearch": {
        "author": "$.author",
        "bookList": "@js:(JSON.parse(result).data.list || []).map(function (o) { return lkBook(o); })",
        "bookUrl": "$.url",
        "coverUrl": "$.cover",
        "intro": "$.intro",
        "kind": "$.kind",
        "lastChapter": "$.last",
        "name": "$.name",
        "wordCount": "$.words"
    },
    "ruleToc": {
        "chapterList": "@js:\nvar key = lkKey(source);\nvar zh = lkZhOn(source);\nvar d = JSON.parse(result).data || {};\nvar vols = d.volumes || [];\nif (vols.length < (d.volume_count || 0)) {\n    vols = [];\n    for (var p = 1, pages = 1; p <= pages; p++) {\n        var r = JSON.parse(java.ajax(lkUrl('\/new-content-read\/get-book-volumes', {book_id: d.book_id, page: p, page_size: 50}, key))).data || {};\n        pages = (r.pagination && r.pagination.page_count) || 1;\n        vols = vols.concat(r.list || []);\n    }\n}\n\nvar BATCH = 4;\nvar pages = {};\nvar queue = vols.map(function (v, i) { return [i, 1]; });\nwhile (queue.length) {\n    var batch = queue.splice(0, BATCH);\n    var res = java.ajaxAll(batch.map(function (t) {\n        return lkUrl('\/new-content-read\/get-volume-chapters', {volume_id: vols[t[0]].volume_id, page: t[1], page_size: 50}, key);\n    }));\n    batch.forEach(function (t, j) {\n        var body = String(res[j].body());\n        var r;\n        try { r = JSON.parse(body).data || {}; } catch (e) { throw new Error('目录获取失败:' + body.slice(0, 60)); }\n        pages[t[0] + ':' + t[1]] = r.list || [];\n        var count = (r.pagination && r.pagination.page_count) || 1;\n        if (t[1] == 1) for (var n = 2; n <= count; n++) queue.push([t[0], n]);\n    });\n}\n\nvar out = [];\nvols.forEach(function (v, i) {\n    var vt = String(v.title || '');\n    out.push(JSON.stringify({title: zh ? String(java.t2s(vt)) : vt, url: '', volume: 'true', vip: '', time: ''}));\n    for (var n = 1; pages[i + ':' + n]; n++) {\n        pages[i + ':' + n].forEach(function (c) {\n            var t = String(c.title || '');\n            if (zh) t = String(java.t2s(t));\n            var lock = c.locked == 1;\n            out.push(JSON.stringify({\n                title: (lock ? '🔒 ' : '') + t,\n                url: lkChapter(c.chapter_id),\n                volume: '',\n                vip: lock ? 'true' : '',\n                time: String(c.published_at || '')\n            }));\n        });\n    }\n});\nout;\n",
        "chapterName": "$.title",
        "chapterUrl": "$.url",
        "isVip": "$.vip",
        "isVolume": "$.volume",
        "updateTime": "$.time"
    },
    "searchUrl": "@js:lkSearch(key, page)",
    "weight": 0
}
广告