笔趣阁
https://m.qidian.com
yang-huan-52 (15288)11/04 23:29
该用户很懒,什么介绍也没有写!
{
"bookSourceGroup": "笔趣阁",
"bookSourceName": "笔趣阁",
"bookSourceType": 0,
"bookSourceUrl": "https:\/\/m.qidian.com",
"customButton": false,
"customOrder": -2,
"enabled": true,
"enabledCookieJar": true,
"enabledExplore": true,
"eventListener": false,
"exploreUrl": "<js>(function(){\nvar _H = (typeof _dpSrv === 'function') ? _dpSrv() : 'http:\/\/43.139.147.103:8070';\nvar FALLBACK = [{\"title\":\"请选择平台\",\"type\":\"select\",\"chars\": [\"📖 综合\", \"🌙 得奇小说\", \"圣墟小说网\", \"提书网(tishu)\", \"思兔阅读(sto66)\", \"2K小说\", \"同人小说(trxs123)\", \"黑岩阅读\", \"🍅 番茄小说\", \"思路客\", \"夜伴书屋\",\"错层小说\", \"STV镜像\", \"笔下文学网(bxwx9)\", \"笔趣阁小说网(biquguo)\", \"37阅读网(37yue)\", \"大唐小说\", \"小说屋\",\"笔趣阁(bqgooo.cc)\", \"书旗小说\", \"米读小说\", \"七猫小说\", \"武侠小说网(wuxiayue)\", \"爱下电子书(ixdzs8) ✨优质\", \"🌙 顶点小说·APP接口 ✨优质\", \"📖 读知阁\" ],\"default\":\"📖 综合\",\"action\":\"show(infoMap['请选择平台'],'dpsrc')\",\"style\":{\"layout_flexGrow\":1,\"layout_flexBasisPercent\":1}},{\"title\":\"≡ 综合分类(多源合并)≡\",\"url\":\"\",\"style\":{\"layout_flexGrow\":1,\"layout_flexBasisPercent\":1}},{\"title\":\"玄幻\",\"url\":_H+\"\/api\/discover\/unified_list\/0?page={{page}}\",\"style\":{\"layout_flexGrow\":1,\"layout_flexBasisPercent\":0.25}},{\"title\":\"仙侠\",\"url\":_H+\"\/api\/discover\/unified_list\/1?page={{page}}\",\"style\":{\"layout_flexGrow\":1,\"layout_flexBasisPercent\":0.25}},{\"title\":\"都市\",\"url\":_H+\"\/api\/discover\/unified_list\/2?page={{page}}\",\"style\":{\"layout_flexGrow\":1,\"layout_flexBasisPercent\":0.25}},{\"title\":\"历史\",\"url\":_H+\"\/api\/discover\/unified_list\/3?page={{page}}\",\"style\":{\"layout_flexGrow\":1,\"layout_flexBasisPercent\":0.25}},{\"title\":\"科幻\",\"url\":_H+\"\/api\/discover\/unified_list\/4?page={{page}}\",\"style\":{\"layout_flexGrow\":1,\"layout_flexBasisPercent\":0.25}},{\"title\":\"悬疑\",\"url\":_H+\"\/api\/discover\/unified_list\/5?page={{page}}\",\"style\":{\"layout_flexGrow\":1,\"layout_flexBasisPercent\":0.25}},{\"title\":\"游戏\",\"url\":_H+\"\/api\/discover\/unified_list\/6?page={{page}}\",\"style\":{\"layout_flexGrow\":1,\"layout_flexBasisPercent\":0.25}},{\"title\":\"言情\",\"url\":_H+\"\/api\/discover\/unified_list\/7?page={{page}}\",\"style\":{\"layout_flexGrow\":1,\"layout_flexBasisPercent\":0.25}},{\"title\":\"完本\",\"url\":_H+\"\/api\/discover\/unified_list\/8?page={{page}}\",\"style\":{\"layout_flexGrow\":1,\"layout_flexBasisPercent\":0.25}},{\"title\":\"最新\",\"url\":_H+\"\/api\/discover\/unified_list\/9?page={{page}}\",\"style\":{\"layout_flexGrow\":1,\"layout_flexBasisPercent\":0.25}},{\"title\":\"排行\",\"url\":_H+\"\/api\/discover\/unified_list\/10?page={{page}}\",\"style\":{\"layout_flexGrow\":1,\"layout_flexBasisPercent\":0.25}},{\"title\":\"--\",\"url\":\"\",\"style\":{\"layout_flexGrow\":1,\"layout_flexBasisPercent\":0.25}}];\ntry{\nvar _p=_dpExplorePage(java, cache, FALLBACK);\nif(_p){return _p;}\n}catch(e){}\nreturn JSON.stringify(FALLBACK);\n})()<\/js>",
"header": "{\"User-Agent\": \"Mozilla\/5.0 (Linux; Android 13; SM-S918B) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/120.0.0.0 Mobile Safari\/537.36\", \"Accept-Language\": \"zh-CN,zh;q=0.9\"}",
"jsLib": "var _DP_JV = null, _DP_BK = null, _DP_CH = null;\nvar _DP_ILLU_DIAG = ''; \nfunction _dpSetCtx(jv, bk, ch) {\n try { if (jv) _DP_JV = jv; } catch (e1) {}\n try { if (bk) _DP_BK = bk; } catch (e2) {}\n try { if (ch) _DP_CH = ch; } catch (e3) {}\n return _DP_JV;\n}\nfunction _dpScopeChapter() {\n try { if (typeof chapter !== 'undefined' && chapter) return chapter; } catch (e1) {}\n try { if (_DP_CH) return _DP_CH; } catch (e2) {}\n return null;\n}\nfunction _dpJv(jv) {\n if (jv) return jv;\n if (_DP_JV) return _DP_JV;\n try { if (typeof java !== 'undefined' && java) return java; } catch (e1) {}\n try { if (typeof source !== 'undefined' && source) return source; } catch (e2) {}\n return null;\n}\n\nvar _DP_UA = 'Mozilla\/5.0 (Linux; Android 12; Redmi K40 Build\/SKQ1.220213.001; wv) AppleWebKit\/537.36 (KHTML, like Gecko) Version\/4.0 Chrome\/110.0.0.0 Mobile Safari\/537.36';\nvar _DP_LANG = 'zh-CN,zh;q=0.9';\nvar _DP_QD_DIAG = '';\nvar _DP_DEBUG = true; \nvar _DP_DEBUG_OK = false; \nvar _DP_NET_ERR = ''; \nvar _DP_CSRF = ''; \nvar _DP_LAST_FAIL = ''; \nvar _DP_HOT_EMPTY = false;\nvar _DP_HOT_DIAG = '';\nvar _DP_IMG_VH = 55;\n\nvar _DP_SERVER = 'http:\/\/43.139.147.103:8070'; \n\nfunction _dpSrv() {\n try {\n var sc = _dpSrcOf(_dpJv());\n if (sc && typeof sc.get === 'function') {\n var v = String(sc.get('agg_server') || '').replace(\/\\\/+$\/, '');\n if (v) return v;\n }\n } catch (e0) {}\n return _DP_SERVER;\n}\nvar _dpBidCache = {}; \nvar _dpCatCache = {}; \n\nfunction _dpFlat(s) {\n try { s = String(s == null ? '' : s); } catch (e0) { s = ''; }\n try { s = s.split('').join(''); } catch (e1) {}\n return s;\n}\nfunction _dpFlatHd(hd) {\n var out = {};\n try { for (var k in hd) { out[_dpFlat(k)] = _dpFlat(hd[k]); } } catch (e) { return hd; }\n return out;\n}\n\nfunction _dpToast(jav, msg) {\n if (!_DP_DEBUG) return;\n try { jav.toast(msg); } catch (e) {}\n}\n\nfunction _dpT2S(jav, s) {\n var v = String(s == null ? '' : s);\n if (!v) return v;\n try { var r = jav.t2s(v); if (r) return String(r); } catch (e) {}\n return v;\n}\nfunction _dpGetJson(jav, url, headers) {\n try {\n var r = jav.get(url, headers);\n var body = String(r.body() || '');\n if (!body) return null;\n return JSON.parse(body);\n } catch (e) { _DP_NET_ERR = String(e); return null; }\n}\nfunction _dpIsHtmlBlock(t) {\n return \/<(p|br|div|h[1-6])[\\s>\\\/]\/i.test(String(t == null ? '' : t));\n}\n\nfunction _dpPlainText(s) {\n return String(s == null ? '' : s)\n .replace(\/<script[\\s\\S]*?<\\\/script>\/gi, '')\n .replace(\/<style[\\s\\S]*?<\\\/style>\/gi, '')\n .replace(\/<br\\s*\\\/?>\/gi, '\\n')\n .replace(\/<\\\/p>\/gi, '\\n')\n .replace(\/<\\\/div>\/gi, '\\n')\n .replace(\/<[^>]*>\/g, '')\n .replace(\/ \/gi, ' ')\n .replace(\/“\/gi, '“').replace(\/”\/gi, '”')\n .replace(\/…\/gi, '…').replace(\/—\/gi, '—')\n .replace(\/&\/gi, '&').replace(\/<\/gi, '<')\n .replace(\/>\/gi, '>').replace(\/"\/gi, '\"')\n .replace(\/&#\\d+;\/g, ' ');\n}\nfunction _dpInjectServer(t, nm, au, cn, jav) {\n try {\n var plain = _dpIsHtmlBlock(t) ? _dpPlainText(t) : t;\n var body = 'name=' + encodeURIComponent(nm)\n + '&author=' + encodeURIComponent(au)\n + '&chapter=' + encodeURIComponent(cn)\n + '&text=' + encodeURIComponent(plain)\n + '&hot=' + ((_dpSegCardOn(jav) || _dpEndCardOn(jav)) ? '1' : '0')\n + '&bubble=' + (_dpBubbleOn(jav) ? '1' : '0')\n + '&segcard=' + (_dpSegCardOn(jav) ? '1' : '0')\n + '&endcard=' + (_dpEndCardOn(jav) ? '1' : '0')\n + '&theme=' + _dpTheme(jav);\n var r = '';\n try {\n var _resp = jav.post(_dpSrv() + '\/qqdp\/inline', body,\n {\"Content-Type\": \"application\/x-www-form-urlencoded;charset=utf-8\"});\n r = String(_resp.body() || '');\n } catch (e4) {\n try {\n r = String(jav.post(_dpSrv() + '\/qqdp\/inline', body, {}).body() || '');\n } catch (e5) { r = ''; }\n }\n if (r.length > 80 && r.indexOf('qqShowCmt(') >= 0) {\n var n = (r.match(\/qqShowCmt\\(\/g) || []).length;\n if (_DP_DEBUG_OK) _dpToast(jav, '段评:服务器通道' + n + '个');\n return r;\n }\n if (!_DP_LAST_FAIL) {\n _DP_LAST_FAIL = '服务器:未注入(len=' + r.length\n + (plain && r === plain ? ' 原样返回' : '') + ')';\n }\n return '';\n } catch (e) {\n if (!_DP_LAST_FAIL) _DP_LAST_FAIL = '服务器:异常 ' + e;\n return '';\n }\n}\n\nfunction __dpInject(txt, nm, au, cn, jav, ck, bko, chapter) {\n var t = String(txt == null ? '' : txt);\n function _reIllu(x) {\n try { return __dpIllu(x, bko, chapter, jav); } catch (eI2) { return x; }\n }\n try {\n t = _dpFitImgs(t);\n try { t = __dpIllu(t, bko, chapter, jav); } catch (eIllu) {} \n _dpSetCtx(jav, bko, _dpScopeChapter());\n var bubbleOn = true, segCardOn = true, endCardOn = true;\n try { bubbleOn = _dpBubbleOn(jav); } catch (eSO) {}\n try { segCardOn = _dpSegCardOn(jav); } catch (eSO2) {}\n try { endCardOn = _dpEndCardOn(jav); } catch (eHO2) {}\n if (bko && nm) { try { _dpRegBook(_dpSrcOf(jav), nm, bko.bookUrl ? String(bko.bookUrl) : ''); } catch (eR0) {} }\n if (!bubbleOn && !segCardOn && !endCardOn) { return t; }\n if (t.length < 80) return t;\n if (t.indexOf('qqShowCmt(') >= 0) return t;\n if (t.indexOf('<\/p>') < 0 && \/<p[\\s>]\/i.test(t)) {\n t = t.replace(\/<p([^>]*)>\/gi, '<\/p><p$1>').replace(\/^(<\\\/p>)+\/i, '') + '<\/p>';\n }\n nm = _dpT2S(jav, nm);\n au = _dpT2S(jav, au);\n cn = _dpT2S(jav, cn);\n if (!cn) {\n try {\n var mm = t.replace(\/^[\\s\\u3000]+\/, '').match(\/^(第[0-9一二三四五六七八九十百千两零]{1,12}[章节回卷集篇][^\\n]{0,24})\/);\n if (mm) cn = mm[1];\n } catch (e0) {}\n }\n if (!nm || !cn) { _dpToast(jav, '段评:缺名 nm=' + nm + ' cn=' + cn); return t; }\n\n _DP_NET_ERR = '';\n var srv = _dpInjectServer(t, nm, au, cn, jav);\n if (srv) return _reIllu(srv);\n\n _dpToast(jav, '段评:服务器未取到(' + _DP_LAST_FAIL + ')');\n return _reIllu(t);\n } catch (e) { _dpToast(jav, '段评:异常 ' + e); return txt; }\n}\n\n\nvar _JJ_SERVER = 'http:\/\/43.139.147.103:8070'; \nfunction _dpDpSrv(ovr){\n try {\n var s = _dpSrcOf(_dpJv());\n if (s && typeof s.get === 'function') {\n var v = String(s.get(ovr || 'jj_server') || '');\n if (v) return v.replace(\/\\\/+$\/, '');\n }\n } catch (e) {}\n return _JJ_SERVER;\n}\nfunction _dpDpShow(jv, url) {\n var cfg = JSON.stringify({\n \"expandedCornersRadius\": 20, \"dismissOnTouchOutside\": true, \"isDraggable\": true,\n \"shouldDimBackground\": true, \"backgroundDimAmount\": 0.5, \"hardwareAccelerated\": true,\n \"isNestedScrollingEnabled\": true, \"isGestureInsetBottomIgnored\": true,\n \"setFitToContents\": true, \"isHideable\": true, \"heightPercentage\": 0.8\n });\n var html = '';\n try { html = String(jv.ajax(url) || ''); } catch (eA) {}\n if (html && html.indexOf('<!DOCTYPE html>') >= 0) {\n try { jv.showBrowser(url, html, '', cfg); return true; } catch (eB) {}\n }\n try { jv.showBrowser(url, null, null, cfg); return true; } catch (eB2) {}\n try { jv.startBrowser(url, '段评'); } catch (eC) {}\n return false;\n}\nfunction _jjSrv() {\n try { return _dpDpSrv('jj_server'); } catch (e) { return _JJ_SERVER; }\n}\nfunction jjShowCmt(nid, cid, para, cnt, pt64) {\n var jv = null;\n try { if (this && this.java) jv = this.java; } catch (e) {}\n if (!jv) jv = _dpJv();\n if (!jv) return;\n try {\n nid = _dpFlat(nid); cid = _dpFlat(cid); para = _dpFlat(para);\n if (!nid || !cid) { try { jv.toast('段评参数缺失'); } catch (e0) {} return; }\n if (!para) para = '1';\n var tq = '';\n try { tq = encodeURIComponent(_dpFlat(pt64)); } catch (eT) {}\n var host = _JJ_SERVER;\n try { host = _jjSrv(); } catch (eH) {}\n _dpDpShow(jv, host + '\/jj\/review?nid=' + encodeURIComponent(nid) +\n '&cid=' + encodeURIComponent(cid) +\n '¶=' + encodeURIComponent(para) +\n '&size=50&fmt=html' + (tq ? '&pt=' + tq : ''));\n } catch (eAll) {\n try { jv.toast('段评打开失败:' + eAll); } catch (eT2) {}\n }\n}\nfunction sqShowCmt(bid, cid, para, cnt, pt64) {\n var jv = null;\n try { if (this && this.java) jv = this.java; } catch (e) {}\n if (!jv) jv = _dpJv();\n if (!jv) return;\n bid = _dpFlat(bid); cid = _dpFlat(cid); para = _dpFlat(para);\n if (!bid || !cid) { try { jv.toast('段评参数缺失'); } catch (e0) {} return; }\n if (!para) para = 'p001';\n var pq = encodeURIComponent(para);\n var tq = '';\n try { tq = encodeURIComponent(_dpFlat(pt64)); } catch (eT) {}\n _dpDpShow(jv, _JJ_SERVER + '\/shuqi\/review?bid=' + encodeURIComponent(bid) +\n '&cid=' + encodeURIComponent(cid) +\n '&pid=' + pq + '¶=' + pq + '&size=50&fmt=html' +\n (tq ? '&pt=' + tq : ''));\n}\n\nfunction qqShowCmt(bid, cid, segId, csrf, q, qdBid, qdCid, name, author, ch) {\n var jv = null;\n try { if (this && this.java) jv = this.java; } catch (e) {}\n if (!jv) jv = _dpJv(); \n if (!jv) return;\n bid = _dpFlat(bid); cid = _dpFlat(cid); segId = _dpFlat(segId); csrf = _dpFlat(csrf);\n q = _dpFlat(q); qdBid = _dpFlat(qdBid); qdCid = _dpFlat(qdCid);\n name = _dpFlat(name); author = _dpFlat(author); ch = _dpFlat(ch);\n if (arguments.length >= 10) { _dpShowServer(jv, bid, cid, segId, csrf, q, qdBid, qdCid, name, author, ch); }\n else if (arguments.length >= 6) { _dpShowServer(jv, bid, cid, segId, csrf, q, qdBid, qdCid, '', '', ''); }\n else { _dpShowServer(jv, '0', '0', segId, csrf, '', bid, cid, '', '', ''); }\n}\n\nfunction _dpFailCode() {\n var d = '';\n try { d = _dpFlat(_DP_QD_DIAG || ''); } catch (e1) {}\n if (d) return d.replace(\/\\s+\/g, ' ').slice(0, 70);\n try { if (_DP_NET_ERR) return ('网络 ' + _dpFlat(_DP_NET_ERR)).replace(\/\\s+\/g, ' ').slice(0, 70); } catch (e2) {}\n try { if (!_DP_CSRF) return '未拿到 csrf'; } catch (e3) {}\n return '本章无数据返回';\n}\n\nfunction _dpShowServer(jv, bid, cid, para, uuid, q, qdBid, qdCid, name, author, ch) {\n var url = _dpSrv() + '\/qqdp\/para?bid=' + bid + '&cid=' + cid + '&offset=' + para;\n if (uuid) { url += '&uuid=' + uuid; }\n if (q) { url += '&q=' + encodeURIComponent(q); }\n if (qdBid && qdCid) { url += '&qd_bid=' + qdBid + '&qd_cid=' + qdCid; }\n if (name) { url += '&name=' + name; }\n if (author) { url += '&author=' + author; }\n if (ch) { url += '&ch=' + ch; }\n var html = '';\n try { html = String(jv.ajax(url) || ''); } catch (eA) {}\n if (html) {\n try {\n var cfg = JSON.stringify({\n \"expandedCornersRadius\": 20,\n \"dismissOnTouchOutside\": true,\n \"isDraggable\": true,\n \"shouldDimBackground\": true,\n \"backgroundDimAmount\": 0.5,\n \"hardwareAccelerated\": true,\n \"isNestedScrollingEnabled\": true,\n \"isGestureInsetBottomIgnored\": true,\n \"setFitToContents\": true,\n \"isHideable\": true,\n \"heightPercentage\": 0.8\n });\n jv.showBrowser(url, html, '', cfg);\n return;\n } catch (eB) {}\n }\n try { jv.startBrowser(url, '段评'); } catch (eC) {\n try { jv.toast('段评加载失败: ' + _dpFailCode()); } catch (eD) {}\n }\n}\nvar _DP3_SRVS = ['http:\/\/43.139.147.103:8070', 'http:\/\/43.139.147.103'];\ntry {\n var _dpSrvV = _dpSrv();\n if (_dpSrvV) {\n _DP3_SRVS = [_dpSrvV];\n if (_dpSrvV.indexOf(':8070') < 0) _DP3_SRVS.push('http:\/\/43.139.147.103:8070');\n }\n} catch (eSrv) {}\nvar _DP3_SRV_OK = '';\nvar _DP3_CACHE = {};\nvar _DP3_BAD = null;\nvar _DP3_TTL = 3600 * 1000;\nvar _DP3_MISS_TTL = 6 * 3600 * 1000;\nvar _DP3_BUDGET = 45000; \nvar _DP3_MAX_TRY = 3; \nvar _DP3_TO_SEARCH = 20000; \nvar _DP3_TO_BOOK = 15000; \nvar _DP3_TO_TOC = 40000; \nvar _DP3_TO_CHAPTER = 35000; \n\nfunction _dp3Try(jav, path, src, to) {\n var order = [], i;\n if (_DP3_SRV_OK) order.push(_DP3_SRV_OK);\n for (i = 0; i < _DP3_SRVS.length; i++) {\n if (_DP3_SRVS[i] !== _DP3_SRV_OK) order.push(_DP3_SRVS[i]);\n }\n for (i = 0; i < order.length; i++) {\n var body = '';\n try {\n var r = jav.get(order[i] + path, null, to || 8000); \n if (r) body = String(r.body() || '');\n } catch (e0) { body = ''; }\n if (!body) { try { body = String(jav.ajax(order[i] + path) || ''); } catch (e1) { body = ''; } }\n if (!body || body.length < 2) continue;\n try {\n var j = JSON.parse(body);\n if (j) { _DP3_SRV_OK = order[i]; return j; }\n } catch (e2) { }\n }\n return null;\n}\n\nfunction _dp3TryUrl(jav, url, to) {\n var body = '';\n try {\n var r = jav.get(url, null, to || 8000); \n if (r) body = String(r.body() || '');\n } catch (e0) { body = ''; }\n if (!body) { try { body = String(jav.ajax(url) || ''); } catch (e1) { body = ''; } }\n if ((!body || body.length < 3) && _DP3_SRV_OK) {\n var alt = String(url).replace(\/^https?:\\\/\\\/[^\\\/]+\/, _DP3_SRV_OK);\n try { body = String(jav.ajax(alt) || ''); } catch (e2) { body = ''; }\n }\n if (!body) return null;\n try { return JSON.parse(body); } catch (e3) { return null; }\n}\n\nfunction _dp3Norm(s) {\n return String(s == null ? '' : s)\n .replace(\/[\\s\\u3000]+\/g, '')\n .replace(\/[::,,。.、!!??;;()()《》〈〉【】\\[\\]\"\"''—\\-_|]\/g, '')\n .toLowerCase();\n}\n\nfunction _dp3Cn2int(s) {\n var D = { '零': 0, '〇': 0, '一': 1, '壹': 1, '二': 2, '两': 2, '贰': 2, '三': 3, '叁': 3,\n '四': 4, '肆': 4, '五': 5, '伍': 5, '六': 6, '陆': 6, '七': 7, '柒': 7, '八': 8, '捌': 8,\n '九': 9, '玖': 9 };\n var U = { '十': 10, '拾': 10, '百': 100, '佰': 100, '千': 1000, '仟': 1000, '万': 10000 };\n var total = 0, section = 0, num = -1, seen = false;\n for (var i = 0; i < s.length; i++) {\n var c = s.charAt(i);\n if (D[c] !== undefined) { num = D[c]; seen = true; }\n else if (U[c] !== undefined) {\n var u = U[c];\n if (u >= 10000) { section = (section + (num < 0 ? 0 : num)) * u; total += section; section = 0; num = -1; }\n else { section += (num < 0 ? 1 : num) * u; num = -1; }\n seen = true;\n } else { return NaN; }\n }\n if (!seen) return NaN;\n return total + section + (num < 0 ? 0 : num);\n}\n\nfunction _dp3Seq(name) {\n var s = String(name == null ? '' : name).replace(\/[\\s\\u3000]+\/g, '');\n var m = s.match(\/第\\s*([0-9]{1,10})\\s*[章节回节话]\/);\n if (m) return parseInt(m[1], 10);\n m = s.match(\/第\\s*([零〇一壹二两贰三叁四肆五伍六陆七柒八捌九玖十拾百佰千仟万]{1,12})\\s*[章节回节话]\/);\n if (m) { var v = _dp3Cn2int(m[1]); if (!isNaN(v)) return v; }\n m = s.match(\/^\\s*([0-9]{1,10})[\\.、,,::]\/);\n if (m) return parseInt(m[1], 10);\n return NaN;\n}\n\n\n\n\n\n\n\n\nfunction _dp3Get(src, k) {\n if (!src) return null;\n try { var v = src.get(k); if (v !== undefined && v !== null && String(v) !== '') return String(v); } catch (e) {}\n try {\n var all = src.getVariable();\n if (all) {\n var o = JSON.parse(String(all));\n if (o && o[k] !== undefined && o[k] !== null && String(o[k]) !== '') return String(o[k]);\n }\n } catch (e2) {}\n return null;\n}\nfunction _dp3Put(src, k, v) {\n if (!src) return;\n try { src.put(k, String(v)); return; } catch (e) {}\n try { src.putVariable(k, String(v)); } catch (e2) {}\n}\n\n\nfunction _dpBody(raw) {\n var h = String(raw == null ? '' : raw);\n if (!h || h.length < 200) return h;\n try {\n var mm = h.match(\/<script id=\"vite-plugin-ssr_pageContext\"[^>]*>([\\s\\S]*?)<\\\/script>\/i);\n if (mm) {\n var ci = null;\n try { ci = JSON.parse(mm[1]).pageContext.pageProps.pageData.chapterInfo; } catch (eJ) {}\n var ct = ci ? String(ci.content == null ? '' : ci.content) : '';\n if (_dpTxtLen(ct) > 60) return ct;\n }\n } catch (e1) {}\n try {\n var pi = h.search(\/<div[^>]*class=\"[^\"]*\\bprint\\b[^\"]*\"[^>]*>\/i);\n if (pi >= 0) {\n var seg = h.slice(pi).replace(\/^<div[^>]*>\/i, '');\n seg = _dpCutDiv(seg)\n .replace(\/<script[\\s\\S]*?<\\\/script>\/gi, '')\n .replace(\/<style[\\s\\S]*?<\\\/style>\/gi, '')\n .replace(\/<h1[^>]*>[\\s\\S]*?<\\\/h1>\/i, '');\n if (_dpTxtLen(seg) > 60) return seg;\n }\n } catch (e2) {}\n return h;\n}\n\nfunction _dpFitImgs(t) {\n var s = String(t == null ? '' : t);\n if (!s || s.indexOf('<img') < 0) return s;\n var vh = _DP_IMG_VH;\n try {\n if (!vh) vh = 55;\n var v = _dp3Get(_dpSrcOf(_dpJv()), 'dpimgvh');\n if (v) { var n = parseInt(v, 10); if (!isNaN(n) && n >= 15 && n <= 100) vh = n; }\n } catch (e0) {}\n var css = 'max-width:100%;height:auto;max-height:' + vh + 'vh;object-fit:contain;';\n try {\n return s.replace(\/<img\\b([^>]*)>\/gi, function (m0, a) {\n if (\/max-height\\s*:\/i.test(a)) return m0;\n if (\/\\sstyle\\s*=\\s*\"\/i.test(a)) {\n return '<img' + a.replace(\/(\\sstyle\\s*=\\s*\")([^\"]*)\"\/i, '$1$2;' + css + '\"') + '>';\n }\n return '<img' + a + ' style=\"' + css + '\">';\n });\n } catch (e1) { return s; }\n}\n\nfunction _dpTxtLen(s) {\n try { return String(s == null ? '' : s).replace(\/<[^>]*>\/g, '').replace(\/[\\s\\u3000]\/g, '').length; }\n catch (e) { return 0; }\n}\n\nfunction _dpCutDiv(s) {\n var d = 0, re = \/<div\\b[^>]*>|<\\\/div\\s*>\/gi, m;\n while ((m = re.exec(s)) !== null) {\n if (m[0].charAt(1) === '\/') { d--; if (d <= 0) return s.slice(0, m.index); }\n else d++;\n }\n return s;\n}\n\n\nfunction _dpMeta(h, prop) {\n try {\n var re = \/<meta\\b[^>]*>\/gi, m;\n while ((m = re.exec(String(h))) !== null) {\n var tag = m[0];\n if (tag.indexOf(prop) < 0) continue;\n var c = tag.match(\/content\\s*=\\s*([\"'])([\\s\\S]*?)\\1\/i);\n if (c) return c[2];\n }\n } catch (e) {}\n return '';\n}\n\nfunction _dpBookIntro(h, baseUrl, jav, bko) {\n _dpSetCtx(jav, bko, _dpScopeChapter());\n var o = _dpMeta(h, 'og:description');\n if (!o) {\n try {\n var m = String(h).match(\/<p[^>]*class=\"[^\"]*summary__content[^\"]*\"[^>]*>([\\s\\S]*?)<\\\/p>\/i);\n if (m) o = _dpPlainText(m[1]).replace(\/[\\s\\u3000]+\/g, ' ').replace(\/^ | $\/g, '');\n } catch (e1) {}\n }\n if (!o) {\n o = _dpMeta(h, 'name=\"description\"');\n if (o) o = o.replace(\/^[^,]*?,已更新\\s*\\d+\\s*章[、,::]?\\s*最新章节[::]?\/, '');\n }\n return o;\n}\n\nfunction _dpBooks(src) {\n try {\n var v = _dp3Get(src, 'dp3books');\n if (v) { var a = JSON.parse(String(v)); if (a && a.length) return a; }\n } catch (e) {}\n return [];\n}\n\nfunction _dpBid(u) {\n try { var m = String(u || '').match(\/\\\/book\\\/(\\d+)\/); if (m) return m[1]; } catch (e) {}\n return '';\n}\n\nfunction _dpRegBook(src, name, bookUrl) {\n if (!src || !name) return;\n try {\n var bid = _dpBid(bookUrl), old = _dpBooks(src), out = [{ n: String(name), b: bid }], i;\n for (i = 0; i < old.length && out.length < 40; i++) {\n if (String(old[i].n) === String(name)) continue;\n out.push({ n: String(old[i].n), b: String(old[i].b || '') });\n }\n if (old.length && String(old[0].n) === String(name) && String(old[0].b || '') === bid) return;\n _dp3Put(src, 'dp3books', JSON.stringify(out));\n } catch (e) {}\n}\n\nfunction _dpExploreFill(r) {\n try {\n if (!r || r.u) return r;\n var bid = String(r.bid == null ? '' : r.bid);\n var q = String(r.dp3q == null ? '' : r.dp3q);\n r.u = 'https:\/\/m.qidian.com\/book\/' + bid + '\/?dp3q=' + q;\n r.c = 'https:\/\/bookcover.yuewen.com\/qdbimg\/349573\/' + bid + '\/180';\n } catch (e0) {}\n return r;\n}\n\nfunction _dpExploreList(baseUrl, result, jav) {\n var body = String(result == null ? '' : result);\n try { _dpSetCtx(jav, null, null); } catch (eS0) {}\n try {\n if (String(baseUrl || '').indexOf('dp3panel') >= 0) {\n return JSON.stringify({ data: { records: [] } });\n }\n } catch (e1) {}\n try {\n var jd = JSON.parse(body);\n if (jd && jd.disc === true) {\n return JSON.stringify({ data: { records: (jd.records || []) } });\n }\n } catch (eD) {}\n try {\n var j = JSON.parse(body);\n var r = j && j.data && j.data.records;\n if (r && r.length) {\n var keep = [];\n for (var i = 0; i < r.length; i++) {\n if (!r[i]) continue;\n if (r[i].dp3q === undefined) r[i].dp3q = '';\n if (String(r[i].bAuth || '') === 'VIP补章源') continue; \n _dpExploreFill(r[i]); \n keep.push(r[i]);\n }\n return JSON.stringify({ data: { records: keep } });\n }\n } catch (e2) {}\n return body;\n}\n\n\n\n\n\n\n\nfunction _dpGradeIsAdult(src) {\n return false;\n}\nfunction _dpGradeSet(jav, on) {\n on = false;\n try { _dp3Put(_dpSrcOf(jav), 'dp_adult', '0'); } catch (e) {}\n var upd = {};\n upd[\"lu_grade_n\"] = (on ? \"○ \" : \"◉ \") + \"📖 正常小说\";\n upd[\"lu_grade_a\"] = (on ? \"◉ \" : \"○ \") + \"🔞 成人小说\";\n try { jav.upLoginData(upd); } catch (eU) {}\n try {\n jav.toast('📖 已切回正常小说(成人内容已迁至独立入口)');\n } catch (e2) {}\n try { jav.refreshExplore(); } catch (e4) {}\n return '已切换:📖 正常小说(成人内容已迁至独立入口)';\n}\nfunction _dpGradeRows(jav) {\n return [];\n}\nfunction _dpGradePick(v) {\n var jv = null;\n try { if (this && this.java) jv = this.java; } catch (e0) {}\n if (!jv) { try { if (typeof java !== 'undefined' && java) jv = java; } catch (e1) {} }\n var on = String(v == null ? '' : v).indexOf('成人') >= 0;\n return _dpGradeSet(jv, on);\n}\n\nfunction _dpLuRow(name, label, action, dynLabel, basis) {\n var r = {\n name: name, type: \"button\",\n style: {\n layout_flexGrow: 1,\n layout_flexBasisPercent: (basis == null ? 0.45 : basis)\n }\n };\n r.viewName = dynLabel ? String(label) : (\"'\" + String(label).replace(\/'\/g, \"\") + \"'\");\n if (action) r.action = action;\n return r;\n}\n\n\n\nfunction _dpSegOn(jav) {\n var src = _dpSrcOf(jav);\n var v = _dp3Get(src, 'dp_seg_on');\n if (v === null) return true;\n return v !== '0';\n}\nfunction _dpHotOn(jav) {\n var src = _dpSrcOf(jav);\n var v = _dp3Get(src, 'dp_hot_on');\n if (v === null) return true;\n return v !== '0';\n}\nfunction _dpFineGet(jav, key, legacy) {\n var src = _dpSrcOf(jav);\n var v = _dp3Get(src, key);\n if (v !== null && v !== '') return v !== '0';\n return legacy;\n}\nfunction _dpBubbleOn(jav) { return _dpFineGet(jav, 'dp_bubble_on', _dpSegOn(jav)); }\nfunction _dpSegCardOn(jav) { return _dpFineGet(jav, 'dp_segcard_on', _dpSegOn(jav) && _dpHotOn(jav)); }\nfunction _dpEndCardOn(jav) { return _dpFineGet(jav, 'dp_endcard_on', _dpHotOn(jav)); }\n\nfunction _dpSwMark(on) { return (on ? \"◉ \" : \"○ \"); }\nfunction _dpBubbleLabel(on) { return _dpSwMark(on) + \"💬 段评气泡\"; }\nfunction _dpSegCardLabel(on) { return _dpSwMark(on) + \"🔥 段神评卡\"; }\nfunction _dpEndCardLabel(on) { return _dpSwMark(on) + \"📌 章末大卡\"; }\nfunction _dpSwMigrate(jav) {\n try {\n var src = _dpSrcOf(jav);\n var b = _dp3Get(src, 'dp_bubble_on'), s = _dp3Get(src, 'dp_segcard_on'), e = _dp3Get(src, 'dp_endcard_on');\n if (b !== null && b !== '' && s !== null && s !== '' && e !== null && e !== '') return;\n _dp3Put(src, 'dp_bubble_on', _dpBubbleOn(jav) ? '1' : '0');\n _dp3Put(src, 'dp_segcard_on', _dpSegCardOn(jav) ? '1' : '0');\n _dp3Put(src, 'dp_endcard_on', _dpEndCardOn(jav) ? '1' : '0');\n } catch (eM) {}\n}\nfunction _dpSwAllOn(jav) {\n try { return (_dpBubbleOn(jav) && _dpSegCardOn(jav) && _dpEndCardOn(jav)) ? true : false; }\n catch (e) { return true; }\n}\nfunction _dpToggleOne(jav, key, name, onGet, labelFn, onMsg, offMsg) {\n _dpSwMigrate(jav);\n var src = _dpSrcOf(jav);\n var on = onGet(jav);\n _dp3Put(src, key, on ? '0' : '1');\n var upd = {};\n upd[name] = labelFn(!on);\n _dpLuDone(jav, on ? offMsg : onMsg, upd);\n return String(on ? offMsg : onMsg).split('(')[0];\n}\nfunction _dpToggleBubbleSw(jav) {\n return _dpToggleOne(jav, 'dp_bubble_on', 'tog_bubble', _dpBubbleOn, _dpBubbleLabel,\n '已开启段评气泡(正文段尾小气泡),重新打开本章生效',\n '已关闭段评气泡(热评卡不受影响),重新打开本章生效');\n}\nfunction _dpToggleSegCardSw(jav) {\n return _dpToggleOne(jav, 'dp_segcard_on', 'tog_segcard', _dpSegCardOn, _dpSegCardLabel,\n '已开启段神评卡(段内热评大卡),重新打开本章生效',\n '已关闭段神评卡(气泡不受影响),重新打开本章生效');\n}\nfunction _dpToggleEndCardSw(jav) {\n return _dpToggleOne(jav, 'dp_endcard_on', 'tog_endcard', _dpEndCardOn, _dpEndCardLabel,\n '已开启章末大卡(本章说\/神评论),重新打开本章生效',\n '已关闭章末大卡(气泡不受影响),重新打开本章生效');\n}\nvar _DP_CARD_THEMES = ['white', 'night', 'black', 'jade', 'kraft', 'wood'];\nvar _DP_CARD_THEME_LABEL = {\n white: '☀️ 白露', night: '🌙 夜间', black: '⚫ 纯黑',\n jade: '🍃 青竹', kraft: '📜 牛皮纸', wood: '🪵 木纹'\n};\nfunction _dpCardThemeNorm(v) {\n var t = String(v == null ? '' : v).replace(\/^\\s+|\\s+$\/g, '').toLowerCase();\n if (t === 'light') return 'white'; \n if (t === 'dark') return 'night';\n for (var i = 0; i < _DP_CARD_THEMES.length; i++) {\n if (_DP_CARD_THEMES[i] === t) return t;\n }\n return 'white'; \n}\nfunction _dpCardThemeLabel(t) {\n return _DP_CARD_THEME_LABEL[_dpCardThemeNorm(t)] || _DP_CARD_THEME_LABEL.white;\n}\nfunction _dpTheme(jav) {\n try {\n var src = _dpSrcOf(jav);\n var v = _dp3Get(src, 'dp_card_theme');\n if (v !== null && String(v) !== '') return _dpCardThemeNorm(v);\n var old = _dp3Get(src, 'dp_theme');\n if (old !== null && String(old) !== '') return _dpCardThemeNorm(old);\n return 'white';\n } catch (eT) { return 'white'; }\n}\nfunction _dpToggleTheme(jav) {\n var src = _dpSrcOf(jav);\n var now = _dpTheme(jav);\n var idx = 0;\n for (var i = 0; i < _DP_CARD_THEMES.length; i++) {\n if (_DP_CARD_THEMES[i] === now) { idx = i; break; }\n }\n var next = _DP_CARD_THEMES[(idx + 1) % _DP_CARD_THEMES.length];\n _dp3Put(src, 'dp_card_theme', next);\n _dp3Put(src, 'dp_theme', next);\n var upd = {};\n upd[\"tog_theme\"] = \"◉ 🎨 卡片配色:\" + _dpCardThemeLabel(next);\n _dpLuDone(jav, '卡片配色:' + _dpCardThemeLabel(next) + '(重新打开本章生效)', upd);\n return '卡片配色:' + _dpCardThemeLabel(next);\n}\n\n\nfunction _dpDpSrcGet(jav) {\n try {\n var s = _dpSrcOf(jav);\n var v = String(_dp3Get(s, 'dp_dpsrc') || '').toLowerCase();\n return (v === 'qq') ? 'qq' : 'qd';\n } catch (e) { return 'qd'; }\n}\nfunction _dpDpSrcLabel(k) {\n return (String(k) === 'qq') ? 'QQ阅读段评' : '起点段评';\n}\nfunction _dpDpSrcRows(jav) {\n var cur = _dpDpSrcGet(jav);\n return [\n _dpLuRow(\"tog_dp_head\", \"↓ 段评通道 ↓\", null, false, 1),\n _dpLuRow(\"tog_dpsrc\", \"◉ 🔄 段评切换:\" + _dpDpSrcLabel(cur), \"_dpToggleDpSrc(java)\", false, 1)\n ];\n}\nfunction _dpToggleDpSrc(jav) {\n var s = _dpSrcOf(jav);\n var now = _dpDpSrcGet(jav);\n var next = (now === 'qq') ? 'qd' : 'qq';\n _dp3Put(s, 'dp_dpsrc', next);\n var got = next;\n try {\n var r = String(jav.ajax(_dpSrv() + '\/qqdp\/dpsrc?src=' + next) || '');\n var o = JSON.parse(r);\n if (o && o.pref) { got = String(o.pref); }\n } catch (e1) {}\n if (got !== next) { _dp3Put(s, 'dp_dpsrc', got); }\n var upd = {};\n upd[\"tog_dpsrc\"] = \"◉ 🔄 段评切换:\" + _dpDpSrcLabel(got);\n _dpLuDone(jav, '段评已切换到:' + _dpDpSrcLabel(got), upd);\n return '';\n}\n\nfunction _dpSegHotRows(jav) {\n var rows = [];\n rows.push(_dpLuRow(\"tog_head\", \"↓ 段评 ↓\", null, false, 1));\n rows.push(_dpLuRow(\"tog_bubble\", _dpBubbleLabel(_dpBubbleOn(jav)), \"_dpToggleBubbleSw(java)\", false, 1));\n rows.push(_dpLuRow(\"tog_segcard\", _dpSegCardLabel(_dpSegCardOn(jav)), \"_dpToggleSegCardSw(java)\", false, 1));\n rows.push(_dpLuRow(\"tog_endcard\", _dpEndCardLabel(_dpEndCardOn(jav)), \"_dpToggleEndCardSw(java)\", false, 1));\n rows.push(_dpLuRow(\"tog_theme\", \"◉ 🎨 卡片配色:\" + _dpCardThemeLabel(_dpTheme(jav)),\n \"_dpToggleTheme(java)\", false, 1));\n try {\n var _dpRows = _dpDpSrcRows(jav);\n for (var _dpi = 0; _dpi < _dpRows.length; _dpi++) rows.push(_dpRows[_dpi]);\n } catch (eDP) {}\n return rows;\n}\n\nfunction _dpLuFallback() {\n try {\n return JSON.stringify([\n _dpLuRow(\"lu_hint\", \"↓ 账号登录 ↓\", null, false, 1),\n _dpLuRow(\"lu_fqweb\", \"🍅 番茄账号登录\", \"_dpFqWebLogin(java, (typeof cookie!==\\\"undefined\\\"?cookie:null))\", false, 0.45),\n _dpLuRow(\"lu_login\", \"📖 起点网页登录\", \"_dpLuLogin(java, \\\"\\\")\", false, 0.45),\n _dpLuRow(\"lu_tip\", \"部分设置暂不可用,账号登录仍可继续\", null, false, 1)\n ]);\n } catch (e) { return \"[]\"; }\n}\n\n\n\nfunction _dpLuDone(jav, msg, upd) {\n try { jav.toast(msg); } catch (e) {}\n if (upd) { try { jav.upLoginData(upd); } catch (e0) {} }\n try { jav.refreshContent(); } catch (e2) {}\n}\n\n\n\n\n\n\n\n\nfunction _dpLuLogin(jav, url) {\n try {\n var jv = _dpJv(jav);\n var u = String(url || '');\n if (!u) { try { var s = _dpSrcOf(jv); if (s && s.loginUrl) u = String(s.loginUrl); } catch (e0) {} }\n if (!u) u = 'https:\/\/ptlogin.qidian.com\/login';\n try { jv.startBrowser(u, '登录起点'); return ''; } catch (e1) {}\n try { if (jv && jv.showBrowser) jv.showBrowser(u); } catch (e2) {}\n } catch (e) { try { jav.toast('打开登录页失败:' + (e && e.message ? e.message : e)); } catch (e3) {} }\n return '';\n}\n\nfunction _dpFqAuthBase(jav) {\n try { if (_DP3_SRV_OK) return String(_DP3_SRV_OK).replace(\/\\\/+$\/, ''); } catch (e0) {}\n try { if (_DP3_SRVS && _DP3_SRVS.length) return String(_DP3_SRVS[0]).replace(\/\\\/+$\/, ''); } catch (e1) {}\n return _dpSrv();\n}\n\n\n\nfunction _dpFqAuthLogin(jav) {\n try {\n var jv = _dpJv(jav);\n var u = _dpFqAuthBase(jv) + '\/fq\/auth\/login';\n try { jv.startBrowser(u, '番茄登录\/续期'); return ''; } catch (e1) {}\n try { if (jv && jv.showBrowser) jv.showBrowser(u); } catch (e2) {}\n } catch (e) { try { jav.toast('打开番茄登录页失败:' + (e && e.message ? e.message : e)); } catch (e3) {} }\n return '';\n}\n\n\n\nvar _DP_FQ_GRAB_CHAN = '';\n\nfunction _dpFqCookieGet(jv, tag, ckObj) {\n var v = '';\n try {\n if (ckObj && typeof ckObj.getCookie === 'function') v = String(ckObj.getCookie(tag) || '');\n } catch (e0) { v = ''; }\n if (!v) {\n try {\n if (typeof cookie !== 'undefined' && cookie && typeof cookie.getCookie === 'function') {\n v = String(cookie.getCookie(tag) || '');\n }\n } catch (e1) { v = ''; }\n }\n if (!v && jv) {\n try { if (typeof jv.getCookie === 'function') v = String(jv.getCookie(tag) || ''); } catch (e2) { v = ''; }\n }\n if (!v && jv) {\n try {\n if (typeof jv.getCookieStore === 'function') {\n var st = jv.getCookieStore();\n if (st && typeof st.getCookie === 'function') v = String(st.getCookie('https:\/\/' + tag + '\/') || '');\n }\n } catch (e3) { v = ''; }\n }\n return v;\n}\n\nfunction _dpFqGrabCookie(jav, ckObj) {\n var jv = _dpJv(jav);\n var PREF = ['fanqienovel.com', 'www.fanqienovel.com', 'm.fanqienovel.com'];\n var REST = ['fqnovel.com', 'reading.snssdk.com', 'snssdk.com', 'bytedance.com'];\n var chan = [];\n var SESS = \/(?:^|;\\s*)(?:sessionid|sessionid_ss|sid_guard|sid_tt|sid_ucp_v1|ssid_ucp_v1)=\/;\n\n function merge(list) {\n var bag = {}, order = [], i, j, m;\n for (i = 0; i < list.length; i++) {\n var c = _dpFqCookieGet(jv, list[i], ckObj);\n if (!c) continue;\n chan.push(list[i] + '(' + c.length + ')');\n var parts = c.split(';');\n for (j = 0; j < parts.length; j++) {\n var kv = String(parts[j]).replace(\/^\\s+|\\s+$\/g, '');\n if (!kv || kv.indexOf('=') < 0) continue;\n var k = kv.split('=')[0];\n if (k && !bag[k]) { bag[k] = kv; order.push(k); }\n }\n }\n var out = [];\n for (m = 0; m < order.length; m++) out.push(bag[order[m]]);\n return out.join('; ');\n }\n\n var s1 = merge(PREF);\n if (SESS.test(s1)) {\n try { _DP_FQ_GRAB_CHAN = chan.join(', '); } catch (eA) {}\n return s1;\n }\n var s2 = merge(REST);\n var all = (s1 && s2) ? (s1 + '; ' + s2) : (s1 || s2);\n try { _DP_FQ_GRAB_CHAN = chan.join(', ') || '(空)'; } catch (eB) {}\n return SESS.test(all) ? all : '';\n}\n\nfunction _dpFqGrabSave(jav, ckObj) {\n try {\n var jv = _dpJv(jav);\n var ck = _dpFqGrabCookie(jv, ckObj);\n if (!ck) {\n try { jv.toast('❌ 没抓到登录态 Cookie —— 已打开诊断页'); } catch (e0) {}\n try { _dpFqDiag(jv); } catch (eD) {}\n return '';\n }\n var base = _dpFqAuthBase(jv);\n var txt = '', how = '';\n var tries = [];\n\n try {\n var enc = '';\n try { enc = encodeURIComponent(ck); } catch (eE) { enc = ck; }\n var u = base + '\/fq\/auth\/setq?switch=1&ck=' + enc;\n txt = String(jv.ajax(u, 20000) || '');\n how = 'S1 GET \/fq\/auth\/setq';\n } catch (e1) { txt = ''; tries.push('S1:' + (e1 && e1.message ? e1.message : e1)); }\n\n if (!txt) {\n try {\n var p2 = JSON.stringify({ Cookie: ck });\n txt = String(jv.post(base + '\/fq\/auth\/set', p2,\n { 'Content-Type': 'application\/json;charset=utf-8' }, 20000).body() || '');\n how = 'S2 POST \/fq\/auth\/set';\n } catch (e2) { txt = ''; tries.push('S2:' + (e2 && e2.message ? e2.message : e2)); }\n }\n\n if (!txt) {\n try {\n var p3 = JSON.stringify({ Cookie: ck });\n txt = String(jv.post(base + '\/fq\/auth\/set', p3, {}, 20000).body() || '');\n how = 'S3 POST(空headers)';\n } catch (e3) { txt = ''; tries.push('S3:' + (e3 && e3.message ? e3.message : e3)); }\n }\n\n var ok = false, msg = '', tail = '';\n try {\n var o = JSON.parse(txt);\n ok = !!o.ok;\n if (ok) {\n msg = o.user || o.probe || '';\n var stt = o.status || {};\n var dl = (stt.days_left === null || stt.days_left === undefined) ? null : stt.days_left;\n if (dl !== null) tail = '(剩 ' + dl + ' 天)';\n } else {\n msg = o.err || '';\n }\n } catch (e4) {}\n try { jv.toast(ok ? ('✅ 番茄凭证已保存 · ' + msg + tail) : ('❌ 保存失败:' + (msg || '服务器无响应'))); } catch (e5) {}\n if (ok) {\n try { if (jv.refreshContent) jv.refreshContent(); } catch (e7) {}\n } else {\n try {\n var d = _dpFqDiagText(jv);\n d += '\\n\\n--- 本次上传 ---\\n抓取通道: ' + String(_DP_FQ_GRAB_CHAN || '(无)')\n + '\\nCookie 长度: ' + ck.length\n + '\\n上传策略: ' + (how || '(三条全失败)')\n + '\\n策略报错: ' + (tries.join(' | ') || '(无)')\n + '\\n服务器返回: ' + (txt || '(空)');\n _dpFqShowDiag(jv, '❌ 保存失败 · 诊断', d);\n } catch (e8) {}\n }\n } catch (e) { try { jav.toast('抓取失败:' + (e && e.message ? e.message : e)); } catch (e9) {} }\n return '';\n}\n\nfunction _dpFqWebLogin(jav, ckObj) {\n var jv = _dpJv(jav);\n var opened = false;\n try {\n if (jv && typeof jv.startBrowserAwait === 'function') {\n jv.startBrowserAwait('https:\/\/fanqienovel.com\/', '番茄登录(登录完成后返回)');\n opened = true;\n }\n } catch (e1) { opened = false; }\n if (!opened) {\n try { return _dpFqAuthLogin(jv); } catch (e2) {}\n try { if (jv && jv.toast) jv.toast('无法打开番茄登录页,请检查书源服务器连接'); } catch (e3) {}\n return '';\n }\n try { return _dpFqGrabSave(jv, ckObj); } catch (e4) { return ''; }\n}\n\nfunction _dpFqCookieHosts() {\n return [\n 'https:\/\/fanqienovel.com', 'https:\/\/fanqienovel.com\/',\n 'https:\/\/www.fanqienovel.com', 'https:\/\/www.fanqienovel.com\/',\n 'https:\/\/m.fanqienovel.com', 'https:\/\/m.fanqienovel.com\/',\n 'https:\/\/reading.snssdk.com', 'https:\/\/reading.snssdk.com\/',\n 'https:\/\/api5-normal-sinfonlineb.fqnovel.com', 'https:\/\/api5-normal-sinfonlineb.fqnovel.com\/',\n 'https:\/\/api.fqnovel.com', 'https:\/\/api.fqnovel.com\/',\n 'https:\/\/fqnovel.com', 'https:\/\/fqnovel.com\/',\n 'https:\/\/sso.snssdk.com', 'https:\/\/sso.snssdk.com\/',\n 'https:\/\/passport.snssdk.com', 'https:\/\/passport.snssdk.com\/',\n 'https:\/\/snssdk.com', 'https:\/\/snssdk.com\/',\n 'https:\/\/sso.bytedance.com', 'https:\/\/sso.bytedance.com\/',\n 'https:\/\/bytedance.com', 'https:\/\/bytedance.com\/',\n 'https:\/\/www.bytedance.com', 'https:\/\/www.bytedance.com\/'\n ];\n}\n\nfunction _dpFqShowDiag(jav, title, lines) {\n var jv = _dpJv(jav);\n var esc = String(lines == null ? '' : lines)\n .replace(\/&\/g, '&').replace(\/<\/g, '<').replace(\/>\/g, '>');\n var html = '<!DOCTYPE html><html><head><meta charset=\"utf-8\">'\n + '<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">'\n + '<style>body{background:#f5f6f8;color:#1f2328;margin:0;padding:14px;'\n + 'font:14px\/1.6 -apple-system,\"PingFang SC\",\"Microsoft YaHei\",sans-serif}'\n + 'h2{font-size:17px;margin:0 0 10px}pre{background:#1f2328;color:#e8eaed;padding:12px;'\n + 'border-radius:9px;font-size:11.5px;line-height:1.55;white-space:pre-wrap;word-break:break-all}<\/style>'\n + '<\/head><body><h2>' + title + '<\/h2><pre>' + esc + '<\/pre><\/body><\/html>';\n try { jv.startBrowser('https:\/\/fanqienovel.com\/', title, html); return true; } catch (e0) {}\n try { if (jv.showBrowser) { jv.showBrowser('https:\/\/fanqienovel.com\/', html, '', ''); return true; } } catch (e1) {}\n return false;\n}\n\nfunction _dpFqDiagText(jav) {\n var jv = _dpJv(jav), L = [], ck = null, err = '', i;\n L.push('java 对象 : ' + (jv ? 'OK' : 'NULL'));\n L.push('java.getCookieStore: ' + !!(jv && jv.getCookieStore)\n + ' ← Legado JS 里没有这个 API,false 是正常的,不是故障');\n try { ck = (jv && jv.getCookieStore) ? jv.getCookieStore() : null; } catch (e0) { err = String(e0 && e0.message ? e0.message : e0); }\n L.push('CookieStore 实例 : ' + (ck ? 'OK' : 'NULL') + (err ? (' err=' + err) : ''));\n L.push('java.getCookie() : ' + !!(jv && typeof jv.getCookie === 'function'));\n L.push('store.getCookie() : ' + !!(ck && typeof ck.getCookie === 'function'));\n L.push('store.getKey() : ' + !!(ck && typeof ck.getKey === 'function'));\n L.push('');\n L.push('--- 各域名 Cookie(最多显示 180 字)---');\n var hosts = _dpFqCookieHosts(), nonEmpty = 0;\n for (i = 0; i < hosts.length; i++) {\n var v = '';\n try { v = String(ck && ck.getCookie ? (ck.getCookie(hosts[i]) || '') : ''); } catch (e2) { v = 'ERR:' + (e2 && e2.message); }\n if (v && v.indexOf('ERR:') !== 0) nonEmpty++;\n L.push((v ? '[有] ' : '[空] ') + hosts[i] + ' => ' + (v ? (v.length + ' 字符 ' + v.slice(0, 180)) : ''));\n }\n L.push('');\n L.push('非空域名数: ' + nonEmpty + ' \/ ' + hosts.length);\n var merged = _dpFqGrabCookie(jv);\n L.push('合并后长度: ' + merged.length);\n L.push('合并内容 : ' + (merged || '(空)'));\n L.push('');\n L.push('--- 服务端 ---');\n var base = _dpFqAuthBase(jv);\n L.push('base = ' + base);\n var st = null;\n try { st = _dp3Try(jv, '\/fq\/auth\/status?test=1', null, 8000); } catch (e3) {}\n L.push('status = ' + (st ? JSON.stringify(st) : '(取不到)'));\n return L.join('\\n');\n}\n\nfunction _dpFqDiag(jav) {\n try {\n var jv = _dpJv(jav);\n var txt = _dpFqDiagText(jv);\n if (!_dpFqShowDiag(jv, '🔍 番茄凭证抓取诊断', txt)) {\n try { jv.toast(txt.slice(0, 400)); } catch (e1) {}\n }\n } catch (e) { try { jav.toast('诊断失败:' + (e && e.message ? e.message : e)); } catch (e2) {} }\n return '';\n}\n\n\n\n\n\nfunction _dpLuList(bko, jav) {\n var rows = [];\n jav = _dpJv(jav);\n try {\n rows.push(_dpLuRow(\"lu_login_head\", \"↓ 账号登录 ↓\", null, false, 1));\n rows.push(_dpLuRow(\"lu_fqweb\", \"🍅 番茄账号登录\", \"_dpFqWebLogin(java, (typeof cookie!==\\\"undefined\\\"?cookie:null))\", false, 0.45));\n rows.push(_dpLuRow(\"lu_login\", \"📖 起点网页登录\", \"_dpLuLogin(java, \\\"\\\")\", false, 0.45));\n try { rows = rows.concat(_dpGradeRows(jav)); } catch (eG0) {}\n try { rows = rows.concat(_dpSegHotRows(jav)); } catch (eS0) {}\n return JSON.stringify(rows);\n } catch (e) {\n try { return _dpLuFallback(); } catch (e2) { return \"[]\"; }\n }\n}\n\n\n\n\n\n\n\nfunction __qpCsrf(jav, ck, src) {\n var K = 'qp_csrf', TTL = 12 * 3600 * 1000, tok = '';\n var now = 0; try { now = new Date().getTime(); } catch (e) { now = 0; }\n try { if (_QP_CSRF && _QP_CSRF.t && (now - _QP_CSRF.t) < TTL) return _QP_CSRF.v; } catch (e0) {}\n try {\n var raw = src ? String(src.get(K) || '') : '';\n if (raw) {\n var o = JSON.parse(raw);\n if (o && o.t && (now - o.t) < TTL && o.v) return String(o.v);\n }\n } catch (e1) {}\n try { tok = String(ck.getKey('https:\/\/qidian.com', '_csrfToken') || ''); } catch (e2) { tok = ''; }\n if (!tok) {\n var urls = ['https:\/\/m.qidian.com\/rank\/', 'https:\/\/m.qidian.com\/free\/', 'https:\/\/m.qidian.com\/'];\n for (var i = 0; i < urls.length && !tok; i++) {\n var r = null;\n try { r = jav.get(urls[i], null, 15000); } catch (e3) { r = null; }\n if (!r) continue;\n try { tok = String(r.cookie('_csrfToken') || ''); } catch (e4) { tok = ''; }\n if (!tok) {\n var hh = '';\n try { hh = String(r.headers() || ''); } catch (e5) { hh = ''; }\n try { hh += '|' + String(r.headers().values('Set-Cookie').join('|') || ''); } catch (e5b) { hh = ''; }\n var m1 = hh.match(\/_csrfToken=([0-9a-fA-F\\-]{16,})\/);\n if (m1) tok = m1[1];\n }\n if (!tok) {\n var bd = '';\n try { bd = String(r.body() || ''); } catch (e6) { bd = ''; }\n var m2 = bd.match(\/_csrfToken[\"']?\\s*[:=]\\s*[\"']?([0-9a-fA-F\\-]{16,})\/);\n if (m2) tok = m2[1];\n }\n }\n }\n if (tok) {\n try { _QP_CSRF = { t: now, v: tok }; } catch (e7) {}\n try { if (src) src.put(K, JSON.stringify({ t: now, v: tok })); } catch (e8) {}\n }\n return tok;\n}\nvar _QP_CSRF = null;\n\n\n\n\nfunction _dpCtx() {\n var o = { java: null, book: null, chapter: null };\n try { if (typeof java !== 'undefined' && java) o.java = java; } catch (e1) {}\n try { if (typeof book !== 'undefined' && book) o.book = book; } catch (e2) {}\n try { if (typeof chapter !== 'undefined' && chapter) o.chapter = chapter; } catch (e3) {}\n try { if (!o.java && this && this.java) o.java = this.java; } catch (e4) {}\n try { if (!o.book && this && this.book) o.book = this.book; } catch (e5) {}\n try { if (!o.chapter && this && this.chapter) o.chapter = this.chapter; } catch (e6) {}\n if (!o.java) o.java = _dpJv();\n try { if (!o.book && _DP_BK) o.book = _DP_BK; } catch (e7) {}\n try { if (!o.chapter && _DP_CH) o.chapter = _DP_CH; } catch (e8) {}\n return o;\n}\n\nfunction _dpBookName(b) {\n try { if (b && b.name) return String(b.name).trim(); } catch (e) {}\n return '';\n}\n\nfunction _dpBGet(b, k) {\n if (!b || typeof b.getVariable !== 'function') return '';\n try { var v = b.getVariable(k); return (v === undefined || v === null) ? '' : String(v); } catch (e) {}\n return '';\n}\nfunction _dpBPut(b, k, v) {\n if (!b || typeof b.putVariable !== 'function') return;\n try { b.putVariable(k, String(v == null ? '' : v)); } catch (e) {}\n}\n\nfunction _dpSrcOf(jv) {\n try {\n if (jv) {\n var s = null;\n try { if (typeof jv.getSource === 'function') s = jv.getSource(); } catch (e0) {}\n if (s && typeof s.get === 'function') return s;\n if (typeof jv.get === 'function' && typeof jv.put === 'function') return jv;\n }\n } catch (e) {}\n return null;\n}\n\nfunction _dpCandKey() { return 'dp3cands_'; }\nfunction _dpCandGet(b, src) {\n var k = _dpCandKey() + _dpBookName(b);\n var s = src ? (_dp3Get(src, k) || '') : '';\n if (!s) s = _dpBGet(b, 'dp3cands');\n if (!s) return null;\n try { var a = JSON.parse(String(s)); if (a && a.length) return a; } catch (e) {}\n return null;\n}\nfunction _dpCandSet(b, src, arr) {\n var s = '';\n try { s = JSON.stringify(arr); } catch (e1) { return; }\n _dpBPut(b, 'dp3cands', s);\n if (src) { try { _dp3Put(src, _dpCandKey() + _dpBookName(b), s); } catch (e2) {} }\n}\n\nfunction _dpPickGet(b) {\n var s = _dpBGet(b, 'dp3pick');\n if (!s) return null;\n try { var o = JSON.parse(s); if (o && o.i) return o; } catch (e) {}\n return null;\n}\nfunction _dpPickSave(c, it) {\n var b = c.book, jv = c.java, k = _dpBookName(b);\n var o = { i: it.i, u: it.u, n: it.n || '' };\n _dpBPut(b, 'dp3pick', JSON.stringify(o));\n _dpBPut(b, 'dp3cur', String(o.n || ''));\n _dpBPut(b, 'dp3err', '');\n var s = _dpSrcOf(jv);\n if (s) { try { _dp3Put(s, 'dp3_' + k, JSON.stringify({ i: o.i, u: o.u })); } catch (e4) {} }\n _dpBPut(b, 'dp3miss_' + k, '');\n if (s) { try { _dp3Put(s, 'dp3miss_' + k, ''); } catch (e6) {} }\n try { delete _DP3_CACHE['dp3miss_' + k]; } catch (e7) {}\n try { if (k) _DP3_CACHE[k] = { i: o.i, u: o.u }; } catch (e5) {}\n return o;\n}\nfunction _dpPickClear(c) {\n var b = c.book, jv = c.java, k = _dpBookName(b);\n _dpBPut(b, 'dp3pick', '');\n _dpBPut(b, 'dp3cur', '');\n _dpBPut(b, 'dp3err', '');\n var s = _dpSrcOf(jv);\n if (s) {\n try { _dp3Put(s, 'dp3_' + k, ''); } catch (e1) {}\n try { _dp3Put(s, 'dp3miss_' + k, ''); } catch (e2) {}\n }\n try { delete _DP3_CACHE['dp3miss_' + k]; } catch (e3) {}\n}\n\nfunction _dp3SrcName(r) {\n try {\n var t = String(r.intro || '');\n var m = t.match(\/来自\\s*[::]\\s*([^\\]\\s|]+)\/);\n if (m && m[1]) return String(m[1]).trim();\n var lc = String(r.lastChapter || '');\n var p = lc.split(\/[::]\/);\n if (p.length > 1 && p[0] && p[0].length <= 12) return String(p[0]).trim();\n var bu = String(r.bookUrl || '');\n var mu = bu.match(\/[?&]u=([^&]+)\/);\n if (mu) {\n var u = decodeURIComponent(mu[1]);\n var md = u.match(\/^https?:\\\/\\\/([^\\\/]+)\/);\n if (md) return md[1];\n }\n } catch (e) {}\n return '';\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nfunction _dpAggHost() {\n try { if (_DP3_SRV_OK) return _DP3_SRV_OK; } catch (e0) {}\n try { if (_DP3_SRVS && _DP3_SRVS.length) return _DP3_SRVS[0]; } catch (e1) {}\n return _dpSrv();\n}\n\nfunction __dpIllu(txt, book, chapter, jav) {\n var t = String(txt == null ? '' : txt);\n try {\n function _dec(s) {\n s = String(s == null ? '' : s);\n try { return decodeURIComponent(s); } catch (e) { return s; }\n }\n\n var ch = chapter;\n if (!ch) { try { ch = _dpCtx().chapter; } catch (eCtx) {} }\n if (!ch) { try { ch = _DP_CH; } catch (eCh) {} }\n var bk = book;\n if (!bk) { try { bk = _dpCtx().book; } catch (eBk) {} }\n\n var bid = '';\n try {\n var bu = _dec(bk && bk.bookUrl ? String(bk.bookUrl) : '');\n var m0 = bu.match(\/book\\\/(\\d+)\/) || bu.match(\/[?&]bid=(\\d+)\/)\n || bu.match(\/bookId=(\\d+)\/);\n if (m0) bid = m0[1];\n } catch (eB) {}\n var cid = '';\n try {\n var cu = _dec(ch && (ch.url || ch.chapterUrl) ? String(ch.url || ch.chapterUrl) : '');\n var m1 = cu.match(\/chapter\\\/(\\d+)\\\/(\\d+)\/)\n || cu.match(\/chapterId=(\\d+)\/)\n || cu.match(\/(\\d{6,})\\\/?$\/)\n || cu.match(\/\\\/(\\d{5,})\\\/?$\/);\n if (m1) cid = m1.length > 2 ? m1[2] : m1[1];\n if (!cid) {\n var m2 = cu.match(\/\\\/(\\d{6,})(?:\\\/|$)\/g);\n if (m2 && m2.length) {\n var last = m2[m2.length - 1].replace(\/\\\/\/g, '');\n if (last && last !== bid) cid = last;\n }\n }\n } catch (eC) {}\n if (!cid && t) {\n try {\n var m3 = t.match(\/chapterId[\"'\\s:=]+(\\d{6,})\/);\n if (m3) cid = m3[1];\n } catch (eS) {}\n }\n if (!bid || !cid) {\n try {\n var _aq = (__dpIllu._aggQd || {})[String(_dpAggCur(ch, ''))];\n if (_aq) { if (!bid) bid = _aq.bid; if (!cid) cid = _aq.cid; }\n } catch (eAq) {}\n }\n if (!cid) {\n try { _DP_ILLU_DIAG = 'no-cid'; } catch (eD) {}\n return t;\n }\n var kk = (bid || '?') + '_' + cid;\n try { if (__dpIllu._seen === undefined) __dpIllu._seen = {}; } catch (eInit) {}\n\n if (t.indexOf('class=\"dp-illu\"') >= 0) {\n try { _DP_ILLU_DIAG = 'skip: already injected'; } catch (eD1) {}\n return t;\n }\n\n var payload = null;\n if (__dpIllu._seen[kk] !== undefined) {\n payload = __dpIllu._seen[kk];\n } else {\n var host = _dpAggHost();\n var url = host + '\/api\/illu?bid=' + encodeURIComponent(bid)\n + '&cid=' + encodeURIComponent(cid);\n var body = '', _netOK = false;\n try {\n var _r1 = jav.get(url, {}, 25000);\n if (_r1) { body = String(_r1.body() || ''); _netOK = true; }\n } catch (e0) {\n try {\n var _r2 = jav.get(url, {}, 25000);\n if (_r2) { body = String(_r2.body() || ''); _netOK = true; }\n } catch (e1) { _netOK = false; }\n }\n body = String(body || '').replace(\/^\\s+|\\s+$\/g, '');\n if (body && body.charAt(0) === '{') {\n try { payload = JSON.parse(body); } catch (eJ) { payload = null; }\n }\n if (!payload) {\n payload = { ok: false, hit: false, items: [] };\n }\n if (_netOK) { try { __dpIllu._seen[kk] = payload; } catch (eS0) {} }\n }\n var items = (payload && payload.items) ? payload.items : [];\n try {\n _DP_ILLU_DIAG = 'bid=' + bid + ' cid=' + cid + ' items=' + items.length;\n } catch (eD2) {}\n if (!items.length) return t;\n\n function _norm(s) {\n return String(s == null ? '' : s)\n .replace(\/[\\s\\u3000]+\/g, '')\n .replace(\/[\\u2018\\u2019\\u201c\\u201d\\u300c\\u300d\\u300e\\u300f]\/g, '\"')\n .replace(\/[\\u2026]+\/g, '\\u2026')\n .replace(\/[\\u2014\\u2015]+\/g, '\\u2014');\n }\n var txtN = '', srcArr = [];\n (function () {\n var i = 0, n = t.length;\n while (i < n) {\n var c = t.charAt(i);\n if (c === '\\u2026') {\n var j1 = i; while (j1 < n && t.charAt(j1) === '\\u2026') j1++;\n txtN += '\\u2026'; srcArr.push(i); i = j1; continue;\n }\n if (c === '\\u2014' || c === '\\u2015') {\n var j2 = i; while (j2 < n && (t.charAt(j2) === '\\u2014' || t.charAt(j2) === '\\u2015')) j2++;\n txtN += '\\u2014'; srcArr.push(i); i = j2; continue;\n }\n if (\/[\\s\\u3000]\/.test(c)) { i++; continue; }\n if (\/[\\u2018\\u2019\\u201c\\u201d\\u300c\\u300d\\u300e\\u300f]\/.test(c)) {\n txtN += '\"'; srcArr.push(i); i++; continue;\n }\n txtN += c; srcArr.push(i); i++;\n }\n })();\n\n function _posOf(endNorm) {\n var posRaw = srcArr[endNorm];\n if (posRaw === undefined) return -1;\n var ch0 = t.charAt(posRaw);\n if (ch0 === '\\u2026') {\n var jj = posRaw; while (jj < t.length && t.charAt(jj) === '\\u2026') jj++;\n posRaw = jj - 1;\n } else if (ch0 === '\\u2014' || ch0 === '\\u2015') {\n var jj2 = posRaw; while (jj2 < t.length && (t.charAt(jj2) === '\\u2014' || t.charAt(jj2) === '\\u2015')) jj2++;\n posRaw = jj2 - 1;\n }\n var pos = posRaw + 1; \n var TAILCH = '\\u3002\\uff01\\uff1f\\uff1b\\uff0c\\u2026\\u2014\"\\'\\u201d\\u2019)\\uff09]\\u3011\\u300b\\u300d\\u300f}> \\t\\r\\n\\u3000';\n while (pos < t.length && TAILCH.indexOf(t.charAt(pos)) >= 0) pos++;\n if (t.substr(pos, 4) === '<\/p>') pos += 4;\n return pos;\n }\n function _endsOf(anchorBefore) {\n var a = _norm(anchorBefore), res = [], from = 0, guard = 0;\n if (a.length < 4) return res; \n while (guard++ < 64) {\n var ip = txtN.indexOf(a, from);\n if (ip < 0) break;\n var p = _posOf(ip + a.length - 1);\n if (p >= 0) res.push(p);\n from = ip + 1;\n }\n if (!res.length) {\n var tail = a.slice(-8), tp = txtN.indexOf(tail);\n if (tp >= 0) { var q1 = _posOf(tp + tail.length - 1); if (q1 >= 0) res.push(q1); }\n }\n if (!res.length) {\n var head = a.slice(0, 8), hp = txtN.indexOf(head);\n if (hp >= 0) { var q2 = _posOf(hp + head.length - 1); if (q2 >= 0) res.push(q2); }\n }\n return res;\n }\n function _findEnd(anchorBefore, refRaw) {\n var res = _endsOf(anchorBefore);\n if (!res.length) return -1;\n if (refRaw >= 0 && res.length > 1) {\n var best = res[0], bd = Math.abs(res[0] - refRaw);\n for (var i = 1; i < res.length; i++) {\n var d = Math.abs(res[i] - refRaw);\n if (d < bd) { bd = d; best = res[i]; }\n }\n return best;\n }\n return res[0];\n }\n\n var _AD_RE = \/下载本站免费小说阅读器|手机浏览器扫码下载|随时随地免费看小说|本章有错误|推荐本书|加入书架|投推荐票|收藏本站|手机浏览器访问|打开手机阅读|返回书架|最新网址|浏览器打开|点击安装|继续阅读|作者的话|作者有话说|作者感言|先更后改|求月票|求推荐票|求订阅|求票|ps[::]|PS[::]\/;\n function _segBounds() {\n var bs = [], re = \/<p[^>]*>|<\\\/p\\s*>|\\r?\\n\/g, m2;\n var cur = 0;\n while ((m2 = re.exec(t)) !== null) {\n bs.push({ start: cur, end: m2.index });\n cur = m2.index + m2[0].length;\n }\n bs.push({ start: cur, end: t.length });\n return bs;\n }\n function _findByParaEnd(n) {\n if (!(n > 0)) return -1;\n var bs = _segBounds(), cnt = 0;\n for (var i = 0; i < bs.length; i++) {\n var s = t.slice(bs[i].start, bs[i].end)\n .replace(\/<[^>]*>\/g, '').replace(\/ \/g, ' ');\n s = s.replace(\/^\\s+|\\s+$\/g, '');\n if (!s) continue;\n if (s.length >= 4 && _AD_RE.test(s)) continue;\n cnt++;\n if (cnt === n) return bs[i].end;\n }\n return -1;\n }\n\n var plan = [];\n for (var ii = 0; ii < items.length; ii++) {\n var it = items[ii] || {};\n var anc = it.anchor || {};\n var at = -1;\n var paraRef = (anc.para > 0) ? _findByParaEnd(anc.para) : -1;\n if (anc.before) at = _findEnd(anc.before, paraRef);\n if (at < 0 && anc.after) {\n var an = _norm(anc.after), ap = -1, from2 = 0, g2 = 0;\n while (g2++ < 64) {\n var h2 = txtN.indexOf(an, from2);\n if (h2 < 0) break;\n var p3 = srcArr[h2];\n if (p3 !== undefined && (ap < 0\n || (paraRef >= 0 && Math.abs(p3 - paraRef) < Math.abs(ap - paraRef)))) {\n ap = p3;\n }\n if (ap >= 0 && paraRef < 0) break;\n from2 = h2 + 1;\n }\n at = ap;\n }\n if (at < 0) at = paraRef;\n if (at < 0) {\n try { _DP_ILLU_DIAG += ' drop@' + ii; } catch (eDd) {}\n continue;\n }\n plan.push({ at: at, html: it.html });\n }\n if (!plan.length) {\n return t;\n }\n\n plan.sort(function (a, b) { return a.at - b.at; });\n var out = '', last = 0;\n for (var pi = 0; pi < plan.length; pi++) {\n var p = plan[pi];\n var cut = (p.at < last) ? last : p.at;\n var seg = t.slice(last, cut);\n if (seg && !\/[\\r\\n]$\/.test(seg)) seg += '\\n';\n out += seg;\n out += '<div class=\"dp-illu\">' + p.html + '<\/div>';\n last = cut;\n }\n var rest = t.slice(last);\n if (rest && !\/^[\\r\\n]\/.test(rest) && !\/^\\s*$\/.test(rest)) {\n out += '\\n';\n }\n out += rest;\n return out;\n } catch (e) {\n try { _DP_ILLU_DIAG = 'err ' + (e && e.message ? e.message : String(e)); } catch (eD3) {}\n return t;\n }\n}\n\nfunction _dpIsAgg(u) {\n return \/\\\/api\\\/(?:book|toc|chapter)\\?\/i.test(String(u == null ? '' : u));\n}\nfunction _dpAggI(u) { var m = String(u == null ? '' : u).match(\/[?&]i=(\\d+)\/); return m ? m[1] : ''; }\nfunction _dpAggU(u) { var m = String(u == null ? '' : u).match(\/[?&]u=([^&]+)\/); return m ? decodeURIComponent(m[1]) : ''; }\nfunction _dpAggSwUrl(url, jav) {\n var b = true, s = true, e = true, t = 'white';\n try { b = _dpBubbleOn(jav); } catch (e0) {}\n try { s = _dpSegCardOn(jav); } catch (e1) {}\n try { e = _dpEndCardOn(jav); } catch (e2) {}\n try { t = _dpTheme(jav); } catch (e3) {}\n return url + (url.indexOf('?') >= 0 ? '&' : '?')\n + 'bubble=' + (b ? '1' : '0')\n + '&segcard=' + (s ? '1' : '0')\n + '&endcard=' + (e ? '1' : '0')\n + '&theme=' + t;\n}\nfunction _dpAggApi(kind, i, u) {\n return _dpAggHost() + '\/api\/' + kind + '?i=' + i + '&u=' + encodeURIComponent(u);\n}\nfunction _dpAggCur(chapter, baseUrl) {\n var a = '';\n try { a = chapter ? String(chapter.url || '') : ''; } catch (e0) {}\n if (!_dpIsAgg(a)) { try { a = chapter ? String(chapter.baseUrl || '') : ''; } catch (e1) {} }\n if (!_dpIsAgg(a)) { try { a = String(baseUrl || ''); } catch (e2) {} }\n return a;\n}\nfunction _dpAggWant(chapter, baseUrl) { return _dpIsAgg(_dpAggCur(chapter, baseUrl)); }\nfunction _dpAggStripIntro(s) {\n return String(s == null ? '' : s).replace(\/^\\s*\\[来自\\s*[::][^\\]]*\\]\\s*\/, '').trim();\n}\nfunction _dpStripTags(s) {\n return String(s == null ? '' : s).replace(\/<[^>]*>\/g, '').replace(\/ \/g, ' ').trim();\n}\n\nfunction _dpQdSearchItems(h) {\n var out = [], i, parts = String(h == null ? '' : h).split('<div class=\"y-list__item\"');\n for (i = 1; i < parts.length; i++) {\n var seg = parts[i];\n var mb = seg.match(\/data-bid=\"(\\d+)\"\/);\n if (!mb) continue;\n var mn = seg.match(\/<h2[^>]*class=\"[^\"]*_searchBookName[^\"]*\"[^>]*>([\\s\\S]*?)<\\\/h2>\/i);\n var name = mn ? _dpStripTags(mn[1]) : '';\n if (!name) { var mt = seg.match(\/\\btitle=\"([^\"]*?)在线阅读\"\/); if (mt) name = mt[1]; }\n if (!name) continue;\n var ma = seg.match(\/<p[^>]*class=\"[^\"]*_searchBookAuthor[^\"]*\"[^>]*>([\\s\\S]*?)<\\\/p>\/i);\n var mi = seg.match(\/<p[^>]*class=\"[^\"]*_searchBookDesc[^\"]*\"[^>]*>([\\s\\S]*?)<\\\/p>\/i);\n var mk = seg.match(\/<div[^>]*class=\"[^\"]*_tags[^\"]*\"[^>]*>([\\s\\S]*?)<\\\/div>\/i);\n var mc = seg.match(\/<img[^>]*class=\"[^\"]*_bookImg[^\"]*\"[^>]*>\/i);\n var cover = '';\n if (mc) { var md = mc[0].match(\/data-src=\"([^\"]+)\"\/); if (md) cover = md[1]; }\n if (cover.indexOf('\/\/') === 0) cover = 'https:' + cover;\n var kindTxt = mk ? _dpStripTags(mk[1]) : '';\n var wcTxt = '';\n if (mk) {\n try {\n var mws = String(mk[1]).match(\/([\\d]+(?:\\.[\\d]+)?)\\s*(万)?字\/);\n if (mws) {\n wcTxt = mws[1] + (mws[2] ? '万' : '') + '字';\n kindTxt = kindTxt.replace(\/[\\d]+(?:\\.[\\d]+)?\\s*万?字\/g, '')\n .replace(\/\\s{2,}\/g, ' ').replace(\/^\\s+|\\s+$\/g, '');\n }\n } catch (eW) { }\n }\n out.push({\n name: name,\n author: ma ? _dpStripTags(ma[1]) : '',\n intro: mi ? _dpStripTags(mi[1]) : '',\n kind: kindTxt,\n coverUrl: cover,\n lastChapter: '',\n wordCount: wcTxt,\n bookUrl: 'https:\/\/m.qidian.com\/book\/' + mb[1] + '\/'\n });\n }\n return out;\n}\n\nfunction _dpAggRows(rows, key) {\n var agg = [], seen = {}, i;\n for (i = 0; i < rows.length; i++) {\n var r = rows[i]; if (!r) continue;\n var bu = String(r.bookUrl || ''); if (!bu) continue;\n var isQd = \/qidian\\.com\\\/book\\\/\/.test(bu);\n var mi = bu.match(\/[?&]i=(\\d+)\/);\n if (!isQd && !mi) continue;\n var nm = String(r.name || '').replace(\/^\\s+|\\s+$\/g, ''); if (!nm) continue;\n var _au = String(r.author || '').replace(\/^\\s+|\\s+$\/g, '');\n var kk = (isQd ? 'qd' : mi[1]) + '|' + _dp3Norm(nm) + '|' + _dp3Norm(_au);\n if (seen[kk]) continue;\n seen[kk] = 1;\n var kd = String(r.kind || ''), sn = '';\n if (isQd) {\n if (kd.indexOf('起点') !== 0) kd = '起点|' + kd;\n sn = '起点';\n } else {\n try { sn = _dp3SrcName(r); } catch (eS) { }\n if (!sn) sn = '源' + (mi ? mi[1] : '?');\n if (kd.indexOf('〔') !== 0) kd = '〔' + sn + '〕' + (kd ? ' ' + kd : '');\n }\n var lc = String(r.lastChapter || '').replace(\/^\\s+|\\s+$\/g, '');\n agg.push({\n name: nm,\n author: String(r.author || ''),\n intro: _dpAggStripIntro(r.intro),\n kind: kd,\n coverUrl: String(r.coverUrl || ''),\n lastChapter: lc,\n wordCount: String(r.wordCount || ''),\n bookUrl: bu\n });\n }\n return agg.slice(0, 60);\n}\n\n\nfunction _dpSearchRows(raw, key, jav, src) {\n var out = [], i;\n var _k0 = '';\n try { _k0 = (typeof key === 'undefined' || key == null) ? '' : String(key); } catch (eK0) { _k0 = ''; }\n _k0 = _k0.replace(\/^\\s+|\\s+$\/g, '');\n try {\n var _j0 = JSON.parse(String(raw == null ? '' : raw));\n var _a0 = null;\n if (Object.prototype.toString.call(_j0) === '[object Array]') _a0 = _j0;\n else if (_j0 && Object.prototype.toString.call(_j0.list) === '[object Array]') _a0 = _j0.list;\n else if (_j0 && Object.prototype.toString.call(_j0.data) === '[object Array]') _a0 = _j0.data;\n if (_a0 && _a0.length) return _dpAggRows(_a0, _k0);\n } catch (eJ0) { }\n try { out = _dpQdSearchItems(raw); } catch (eQ) { out = []; }\n try {\n if (!_k0) return out;\n var rows = _dp3Try(jav, '\/api\/search?key=' + encodeURIComponent(_k0) + '&type=novel', src, _DP3_TO_SEARCH);\n if (!rows || !rows.length) return out;\n var agg = _dpAggRows(rows, _k0);\n for (i = 0; i < agg.length; i++) out.push(agg[i]);\n } catch (e1) { }\n return out;\n}\n\n\nfunction _dpInfoFallback(book, field) {\n try {\n if (!book) return '';\n if (field === 'name') return String(book.name || '');\n if (field === 'author') return String(book.author || '');\n if (field === 'coverUrl') return String(book.coverUrl || '');\n if (field === 'kind') return String(book.kind || '');\n } catch (e) { }\n return '';\n}\nfunction _dpEpubHit() {\n for (var i = 0; i < arguments.length; i++) {\n var s = String(arguments[i] == null ? '' : arguments[i]);\n if (!s) continue;\n if (\/\\.epub([?#]|$)\/i.test(s)) return s.slice(0, 60);\n if (\/(^|[\\s,,;;|\/])epub([\\s,,;;|\/]|$)\/i.test(s)) return s.slice(0, 60);\n }\n return '';\n}\nfunction _dpQdWordCount(h) {\n var s = String(h == null ? '' : h);\n if (!s) return '';\n try {\n var i = s.indexOf('总字数');\n if (i > 0) {\n var seg = s.slice(Math.max(0, i - 400), i);\n var mv = seg.match(\/class=\"[^\"]*value[^\"]*\"[^>]*>\\s*([\\d.]+)\\s*<\/g);\n if (mv && mv.length) {\n var lastHtml = mv[mv.length - 1];\n var mv2 = lastHtml.match(\/>\\s*([\\d.]+)\\s*<$\/);\n var val = mv2 ? mv2[1] : '';\n var after = seg.slice(seg.lastIndexOf(lastHtml) + lastHtml.length);\n var mu = after.match(\/class=\"[^\"]*unit[^\"]*\"[^>]*>\\s*([^<]*?)\\s*<\/);\n var u = mu ? mu[1].replace(\/\\s\/g, '') : '字';\n if (val) return val + u;\n }\n }\n var m2 = s.match(\/([\\d]+(?:\\.[\\d]+)?)\\s*(万)?字\/);\n if (m2) return m2[1] + (m2[2] ? '万' : '') + '字';\n } catch (e) { }\n return '';\n}\n\nfunction _dpInfoField(baseUrl, result, jav, book, field) {\n var u = String(baseUrl == null ? '' : baseUrl);\n var s = String(result == null ? '' : result);\n if (_dpIsAgg(u)) {\n var j = null;\n try { j = JSON.parse(s); } catch (e0) { j = null; }\n if (!j || typeof j !== 'object') { try { j = _dp3TryUrl(jav, u, _DP3_TO_BOOK); } catch (e1) { j = null; } }\n if (!j) return _dpInfoFallback(book, field);\n var ep = '';\n try {\n ep = _dpEpubHit(j.kind, j.format, j.intro, j.downloadUrl, j.lastChapter, j.url);\n } catch (eE) { ep = ''; }\n if (ep) { throw new Error('该源返回的是 EPUB 电子书(' + ep + '),不支持在线阅读,请换源'); }\n if (field === 'intro') {\n var _bd = _dpAggStripIntro(j.intro) || _dpInfoFallback(book, field);\n var _sn = '';\n try { _sn = _dp3SrcName(j); } catch (eS3) { _sn = ''; }\n return _sn ? ('📖 来源:' + _sn + '\\n\\n' + _bd) : _bd;\n }\n var v0 = (j[field] == null ? '' : String(j[field]));\n return v0 || _dpInfoFallback(book, field);\n }\n try {\n if (field === 'name') {\n return _dpMeta(s, 'og:title')\n || _dpStripTags((s.match(\/<h1[^>]*>([\\s\\S]*?)<\\\/h1>\/i) || [, ''])[1])\n || _dpInfoFallback(book, 'name');\n }\n if (field === 'author') {\n var a = _dpMeta(s, 'og:novel:author');\n if (!a) { var m1 = s.match(\/<a[^>]*class=\"[^\"]*author-link[^\"]*\"[^>]*>([\\s\\S]*?)<\\\/a>\/i); a = m1 ? _dpStripTags(m1[1]) : ''; }\n return a || _dpInfoFallback(book, 'author');\n }\n if (field === 'kind') return _dpMeta(s, 'og:novel:category') || _dpInfoFallback(book, 'kind');\n if (field === 'coverUrl') return _dpMeta(s, 'og:image') || _dpInfoFallback(book, 'coverUrl');\n if (field === 'lastChapter') return _dpMeta(s, 'og:novel:latest_chapter_name');\n if (field === 'wordCount') return _dpQdWordCount(s);\n if (field === 'intro') return _dpBookIntro(s, u, jav, book) || _dpInfoFallback(book, 'intro');\n } catch (e2) {}\n return '';\n}\n\nfunction _dpTocUrl(baseUrl, result) {\n var u = String(baseUrl == null ? '' : baseUrl);\n if (_dpIsAgg(u)) {\n try {\n var j = JSON.parse(String(result == null ? '' : result));\n var t = (j && j.tocUrl) ? String(j.tocUrl) : '';\n if (t && \/\\\/api\\\/toc\\?\/.test(t)) return t;\n } catch (eT) { }\n return _dpAggApi('toc', _dpAggI(u), _dpAggU(u));\n }\n try { return u.split('?')[0].split('#')[0].replace(\/\\\/+$\/, '') + '\/catalog\/'; } catch (e) { return u; }\n}\nfunction _dpQdTocItems(html) {\n var out = [], re = \/<a\\b([^>]*)>([\\s\\S]*?)<\\\/a>\/gi, m, onlyChapter = true, pass;\n for (pass = 0; pass < 2; pass++) {\n onlyChapter = (pass === 0);\n re.lastIndex = 0;\n out = [];\n while ((m = re.exec(String(html))) !== null) {\n var attrs = String(m[1] || ''), inner = String(m[2] || '');\n var mc = attrs.match(\/data-cid=\"(\\d+)\"\/);\n if (!mc) continue;\n if (\/_secondHeader|_lastChapterCN|_lastChapterUT\/.test(attrs)) continue;\n if (\/_lastChapterCN\/.test(inner)) continue;\n var cm = attrs.match(\/class=\"([^\"]*)\"\/);\n var cls = cm ? cm[1] : '';\n if (onlyChapter && cls.indexOf('_chapterItem') < 0) continue;\n var mn = inner.match(\/<h([23])[^>]*>([\\s\\S]*?)<\\\/h\\1>\/i);\n if (!mn) continue;\n var n = _dpStripTags(mn[2]);\n if (!n) continue;\n out.push({ name: n, cid: mc[1], cls: cls });\n }\n if (out.length) break; \n }\n return out;\n}\nfunction _dpTocRows(baseUrl, raw, jav) {\n var u = String(baseUrl == null ? '' : baseUrl);\n var s = String(raw == null ? '' : raw);\n var out = [], i;\n if (_dpIsAgg(u)) {\n var arr = null;\n try { arr = JSON.parse(s); } catch (e0) { arr = null; }\n if ((!arr || !arr.length) && jav) { try { arr = _dp3TryUrl(jav, u, _DP3_TO_TOC); } catch (e1) { arr = null; } }\n if (!arr || !arr.length) return out;\n var _epCnt = 0, _epSmp = '';\n for (var _ei = 0; _ei < arr.length; _ei++) {\n var _eu = String((arr[_ei] && arr[_ei].url) || '');\n if (\/\\.epub([?#]|$)\/i.test(_eu)) { _epCnt++; if (!_epSmp) _epSmp = _eu.slice(0, 60); }\n }\n if (_epCnt > 0) { throw new Error('目录含 ' + _epCnt + ' 个 EPUB 文件直链(' + _epSmp + '),不支持在线阅读,请换源'); }\n for (i = 0; i < arr.length; i++) {\n if (arr[i] && arr[i].name) out.push({ name: String(arr[i].name), url: String(arr[i].url || '') });\n }\n try {\n var q1 = _dp3Seq(out[0].name), q2 = _dp3Seq(out[out.length - 1].name);\n if (!isNaN(q1) && !isNaN(q2) && q1 > q2) out.reverse();\n } catch (e2) {}\n return out;\n }\n var bid = (_dpBid(u) || '');\n var items = [];\n try { items = _dpQdTocItems(s); } catch (e3) { items = []; }\n for (i = 0; i < items.length; i++) {\n out.push({ name: items[i].name, url: '\/chapter\/' + bid + '\/' + items[i].cid + '\/' });\n }\n if (bid && jav && out.length) {\n try {\n var _bhost = _dpAggHost();\n var _burl = _bhost + '\/qqdp\/blocks?bid=' + encodeURIComponent(bid);\n var _bb = '';\n try { _bb = String(jav.get(_burl, null, 8000).body() || ''); }\n catch (eB1) { try { _bb = String(jav.get(_burl, null, 8000).body() || ''); } catch (eB2) { _bb = ''; } }\n if (!_bb) { try { _bb = String(jav.ajax(_burl) || ''); } catch (eB3) { _bb = ''; } }\n var _bj = null;\n if (_bb && _bb.charAt(0) === '{') { try { _bj = JSON.parse(_bb); } catch (eB4) { _bj = null; } }\n if (_bj && _bj.blocks && _bj.blocks.length) {\n var _bs = {}, _bi;\n for (_bi = 0; _bi < _bj.blocks.length; _bi++) _bs[String(_bj.blocks[_bi])] = 1;\n for (_bi = 0; _bi < out.length; _bi++) {\n var _bm = String(out[_bi].url || '').match(\/\\\/chapter\\\/\\d+\\\/(\\d+)\\\/\/);\n if (_bm && _bs[_bm[1]] && String(out[_bi].name).indexOf('📺') < 0) {\n out[_bi].name = '📺 ' + out[_bi].name;\n }\n }\n }\n } catch (eB0) {}\n }\n return out;\n}\n\n\n\nfunction _dpAggBody(raw, chapter, baseUrl, jav) {\n var url = _dpAggCur(chapter, baseUrl);\n var s = String(raw == null ? '' : raw);\n var j = null;\n try { j = JSON.parse(s); } catch (e0) { j = null; }\n var _isAgg = _dpIsAgg(url);\n var _swAllOn = (_dpSwAllOn(jav) && _dpTheme(jav) === 'white');\n if (!j || typeof j !== 'object') {\n var _u = (_isAgg && !_swAllOn) ? _dpAggSwUrl(url, jav) : url;\n try { j = _dp3TryUrl(jav, _u, _DP3_TO_CHAPTER); } catch (e1) { j = null; }\n } else if (_isAgg && !_swAllOn) {\n var _j2 = null;\n try { _j2 = _dp3TryUrl(jav, _dpAggSwUrl(url, jav), _DP3_TO_CHAPTER); } catch (eSw) { _j2 = null; }\n if (_j2 && typeof _j2 === 'object' && _j2.content) { j = _j2; }\n }\n try {\n if (j && j.qd_bid && j.qd_cid) {\n if (!__dpIllu._aggQd) __dpIllu._aggQd = {};\n __dpIllu._aggQd[String(url)] = { bid: String(j.qd_bid), cid: String(j.qd_cid) };\n }\n } catch (eQd) {}\n var ct = (j && j.content) ? String(j.content) : '';\n return ct;\n}\n\nvar _DP_EX_TTL = 10 * 60 * 1000; \n\nfunction _dpExIn(arr, v) {\n for (var i = 0; i < (arr ? arr.length : 0); i++) { if (arr[i] === v) return true; }\n return false;\n}\n\nfunction show(k, v) {\n var jv = null, ck = null;\n try { if (this && this.java) jv = this.java; } catch (e0) {}\n try { if (this && this.cache) ck = this.cache; } catch (e1) {}\n if (!jv) { try { if (typeof java !== 'undefined' && java) jv = java; } catch (e2) {} }\n if (!ck) { try { if (typeof cache !== 'undefined' && cache) ck = cache; } catch (e3) {} }\n try { if (ck) ck.put(String(v), String(k)); } catch (e4) {}\n try { if (jv) jv.refreshExplore(); } catch (e5) {}\n}\n\nfunction create(k, chars, defaultV, v, size) {\n return {\n title: k,\n type: 'select',\n chars: chars,\n default: defaultV,\n action: \"show(infoMap['\" + k + \"'],'\" + v + \"')\",\n style: { layout_flexGrow: 1, layout_flexBasisPercent: size }\n };\n}\n\nfunction _dpExTab(jav) {\n var ck = _DP3_CACHE['dpex'], now = 0;\n try { now = new Date().getTime(); } catch (eN) { now = 0; }\n if (ck && ck.v && ck.v.length && (now - ck.t) < _DP_EX_TTL) return ck.v;\n var j = null;\n try { j = _dp3Try(jav, '\/api\/discover\/tabs', null, 15000); } catch (e0) { j = null; }\n var v = (j && j.sources && j.sources.length) ? j.sources : null;\n if (v) { try { _DP3_CACHE['dpex'] = { t: now, v: v }; } catch (e1) {} return v; }\n return (ck && ck.v && ck.v.length) ? ck.v : null;\n}\n\nfunction _dpExCatsRaw(jav) {\n var ck = _DP3_CACHE['dpexc_raw'], now = 0;\n try { now = new Date().getTime(); } catch (eN) { now = 0; }\n if (ck && ck.v && (now - ck.t) < _DP_EX_TTL) return ck.v;\n var j = null;\n try { j = _dp3Try(jav, '\/api\/discover\/cats', null, 15000); } catch (e0) { j = null; }\n if (j) { try { _DP3_CACHE['dpexc_raw'] = { t: now, v: j }; } catch (e1) {} return j; }\n return (ck && ck.v) ? ck.v : null;\n}\n\nfunction _dpExCats(jav, adult, chan) {\n var j = _dpExCatsRaw(jav);\n if (!j) return null;\n if (!adult) return (j.novel && j.novel.length) ? j.novel : null;\n if (chan === '漫画') return (j.comic && j.comic.length) ? j.comic : null;\n if (chan === '视频') return (j.video && j.video.length) ? j.video : null;\n return (j.adult && j.adult.length) ? j.adult : null;\n}\n\nfunction _dpChanPick(v) {\n var jv = null, ck = null;\n try { if (this && this.java) jv = this.java; } catch (e0) {}\n try { if (this && this.cache) ck = this.cache; } catch (e1) {}\n if (!jv) { try { if (typeof java !== 'undefined' && java) jv = java; } catch (e2) {} }\n if (!ck) { try { if (typeof cache !== 'undefined' && cache) ck = cache; } catch (e3) {} }\n try {\n var _wv = String(v == null ? '' : v);\n if (_wv.indexOf('漫画') >= 0 || _wv.indexOf('视频') >= 0) {\n var _ad = false;\n try { _ad = _dpGradeIsAdult(_dpSrcOf(jv)); } catch (eA) { _ad = false; }\n if (!_ad) {\n var _mh = (_wv.indexOf('漫画') >= 0);\n try { if (jv) jv.toast(_mh\n ? '📚 浏览漫画时请在编辑页切换类型到图片'\n : '🎬 浏览视频时请在编辑页切换类型到视频'); } catch (eT) {}\n try { if (jv) jv.refreshExplore(); } catch (eR) {}\n return ''; \n }\n }\n } catch (eG) {}\n try { if (ck) ck.put('dpchan', String(v)); } catch (e4) {}\n try { if (ck) ck.put('dpsrc', ''); } catch (e5) {}\n try { if (jv) jv.refreshExplore(); } catch (e6) {}\n return '';\n}\n\nfunction _dpAppendSearchBar(out, cur, map, wantType, ADULT) {\n var host = '';\n try { host = _dpAggHost(); } catch (e0) { host = ''; }\n if (!host) return;\n var KWKEY = '单源搜索';\n var idx = -1, nm = cur;\n try {\n if (map && map[cur] && typeof map[cur].i === 'number') idx = map[cur].i;\n } catch (e1) { idx = -1; }\n var _pos = 0;\n try {\n for (var _i = 0; _i < out.length; _i++) {\n var _it = out[_i] || {};\n if (String(_it.title || '').indexOf('≡') >= 0 && String(_it.url || '') === '') { _pos = _i; break; }\n }\n } catch (eP) { _pos = 0; }\n var _textItem = {\n title: KWKEY, type: 'text',\n viewName: \"'输入关键词'\",\n style: { layout_flexGrow: 1, layout_flexBasisPercent: 0.62 }\n };\n var js = \"(function(){\"\n + \"var _kw='';try{_kw=String((infoMap&&infoMap['\" + KWKEY + \"'])||'');}catch(eK){}\"\n + \"var _nm='';try{_nm=String((infoMap&&infoMap['请选择平台'])||'');}catch(eN){}\"\n + \"return '\" + host + \"\/api\/discover\/srcsearch?src=\" + idx + \"&type=\" + wantType + \"&adult=\" + (ADULT ? 1 : 0) + \"&key='\"\n + \"+encodeURIComponent(_kw)+'&page={{page}}&name='+encodeURIComponent(_nm);\"\n + \"})()\";\n var _urlItem = {\n title: '🔍 单源搜索', type: 'url',\n url: '<js>' + js + '<\/js>',\n style: { layout_flexGrow: 1, layout_flexBasisPercent: 0.38 }\n };\n out.splice(_pos, 0, _textItem, _urlItem);\n}\n\n\nfunction _dpStripCh(t) {\n var s = String(t == null ? '' : t);\n var pf = ['\\uD83D\\uDCD6 ', '\\uD83D\\uDCDA ', '\\uD83C\\uDFAC ', '\\uD83D\\uDD1E '];\n for (var i = 0; i < pf.length; i++) {\n if (s.indexOf(pf[i]) === 0) return s.slice(pf[i].length);\n }\n return s;\n}\nfunction _dpExplorePage(jav, cacheObj, fallback) {\n var srcs = null;\n try { srcs = _dpExTab(jav); } catch (e0) { srcs = null; }\n if (!srcs || !srcs.length) return null;\n\n function _g(k, d) {\n var v = '';\n try {\n v = String(cacheObj && cacheObj.get ? (cacheObj.get(k) || '') : '');\n } catch (e) { v = ''; }\n return v || d;\n }\n var ADULT = false;\n try { ADULT = _dpGradeIsAdult(_dpSrcOf(jav)); } catch (eGA) { ADULT = false; }\n var chanRaw = _g('dpchan', '📖 小说');\n var chan = (chanRaw.indexOf('漫画') >= 0) ? '漫画'\n : (chanRaw.indexOf('视频') >= 0) ? '视频' : '小说';\n if (!ADULT) chan = '小说'; \n var wantType = (chan === '漫画') ? 2 : (chan === '视频') ? 4 : 0;\n\n var i, nm, names = [], map = {};\n for (i = 0; i < srcs.length; i++) {\n if (!srcs[i]) continue;\n if (!!srcs[i].adult !== ADULT) continue;\n if (srcs[i].type !== wantType) continue; \n nm = String((srcs[i].em || '') + (srcs[i].name || ('源' + srcs[i].i)));\n if (_dpExIn(names, nm)) nm = nm + '·' + srcs[i].i; \n names.push(nm);\n map[nm] = srcs[i];\n }\n var AGG = '📖 综合';\n names.unshift(AGG);\n\n var cur = '';\n try { cur = String(cacheObj && cacheObj.get ? (cacheObj.get('dpsrc') || '') : ''); } catch (e1) { cur = ''; }\n if (!cur || !_dpExIn(names, cur)) cur = AGG; \n\n var out = [];\n function _fin(o) {\n try { _dpAppendSearchBar(o, cur, map, wantType, ADULT); } catch (eSB) {}\n return JSON.stringify(o);\n }\n out.push({\n title: '内容分级', type: 'select',\n chars: ['📖 正常'],\n default: '📖 正常',\n action: \"_dpGradePick(infoMap['内容分级'])\",\n style: { layout_flexGrow: 1, layout_flexBasisPercent: 0.5 }\n });\n out.push({\n title: '频道', type: 'select',\n chars: (ADULT ? ['📖 小说', '📚 漫画', '🎬 视频'] : ['📖 小说']), \n default: '📖 ' + chan,\n action: \"_dpChanPick(infoMap['频道'])\",\n style: { layout_flexGrow: 1, layout_flexBasisPercent: 0.5 }\n });\n out.push(create('请选择平台', names, cur, 'dpsrc', 1));\n\n if (cur === AGG) {\n var _cats = null;\n try { _cats = _dpExCats(jav, ADULT, chan); } catch (eC0) { _cats = null; }\n if (_cats && _cats.length) {\n out.push({\n title: '≡ ' + cur + ' 分类(多源合并)≡', url: '',\n style: { layout_flexGrow: 1, layout_flexBasisPercent: 1 }\n });\n for (var _c2 = 0; _c2 < _cats.length; _c2++) {\n out.push({\n title: _dpStripCh(String(_cats[_c2].title || '')),\n url: String(_cats[_c2].url || ''),\n style: { layout_flexGrow: 1, layout_flexBasisPercent: 0.25 }\n });\n }\n return _fin(out);\n }\n var fb = [];\n if (!ADULT && fallback && fallback.length) {\n for (var fi = 0; fi < fallback.length; fi++) {\n if (fallback[fi] && fallback[fi].url) fb.push(fallback[fi]);\n }\n }\n return _fin(out.concat(fb));\n }\n\n var s = map[cur];\n if (!s || !s.cats || !s.cats.length) {\n out.push({\n title: '「' + cur + '」暂无分类数据', url: '',\n style: { layout_flexGrow: 1, layout_flexBasisPercent: 1 }\n });\n return _fin(out);\n }\n\n out.push({\n title: '≡ ' + cur + ' ≡', url: '',\n style: { layout_flexGrow: 1, layout_flexBasisPercent: 1 }\n });\n\n var base = _dpAggHost(), cnt = 0, one;\n for (i = 0; i < s.cats.length; i++) {\n one = String(s.cats[i]);\n out.push({\n title: _dpStripCh(one),\n url: base + '\/api\/discover\/list?i=' + s.i + '&cat='\n + encodeURIComponent(one) + '&page={{page}}',\n style: { layout_flexGrow: 1, layout_flexBasisPercent: 0.25 }\n });\n cnt++;\n if (cnt >= 2) cnt = 0;\n }\n while (cnt > 0 && cnt < 2) { \n out.push({\n title: '--', url: '',\n style: { layout_flexGrow: 1, layout_flexBasisPercent: 0.25 }\n });\n cnt++;\n }\n return _fin(out);\n}\n\nfunction fqShowCmt(a, b, c) {\n var jv = null, bid = '', iid = '';\n if (a && typeof a === 'object') { jv = a; bid = String(b || ''); iid = String(c || ''); }\n else { bid = String(a || ''); iid = String(b || ''); }\n if (!jv) { try { if (this && this.java) jv = this.java; } catch (e0) {} }\n if (!jv) { try { jv = _dpJv(); } catch (e1) {} }\n if (!bid || !iid) { try { jv.toast('fqShowCmt 参数缺失'); } catch (e9) {} return; }\n var host = '';\n try { host = _dpAggHost(); } catch (e1) { host = _dpSrv(); }\n var url = host + '\/fq\/review?item_id=' + encodeURIComponent(iid)\n + '&book_id=' + encodeURIComponent(bid);\n var cfg = '{\"heightPercentage\":0.72}';\n var html = '';\n try { html = String(jv.ajax(url) || ''); } catch (eA) { html = ''; }\n var _ok = false;\n try { if (jv.showBrowser) { jv.showBrowser(url, (html && html.length > 200) ? html : null, null, cfg); _ok = true; } } catch (e2) {}\n if (_ok) { return; }\n try { jv.startBrowser(url, '本章评论'); return; } catch (e3) {}\n try { jv.toast('本章评论:' + url); } catch (e4) {}\n}\nfunction fqShowPara(a, b, c, dd) {\n var jv = null, bid = '', iid = '', para = '';\n if (a && typeof a === 'object') { jv = a; bid = String(b || ''); iid = String(c || ''); para = String(dd || ''); }\n else { bid = String(a || ''); iid = String(b || ''); para = String(c || ''); }\n if (!jv) { try { if (this && this.java) jv = this.java; } catch (e0) {} }\n if (!jv) { try { jv = _dpJv(); } catch (e1) {} }\n if (!bid || !iid || para === '') { try { jv.toast('fqShowPara 参数缺失'); } catch (e9) {} return; }\n var host = '';\n try { host = _dpAggHost(); } catch (e1) { host = _dpSrv(); }\n var url = host + '\/fq\/review?item_id=' + encodeURIComponent(iid)\n + '&book_id=' + encodeURIComponent(bid) + '¶=' + encodeURIComponent(para);\n var cfg = '{\"heightPercentage\":0.72}';\n var html = '';\n try { html = String(jv.ajax(url) || ''); } catch (eA) { html = ''; }\n var _ok = false;\n try { if (jv.showBrowser) { jv.showBrowser(url, (html && html.length > 200) ? html : null, null, cfg); _ok = true; } } catch (e2) {}\n if (_ok) { return; }\n try { jv.startBrowser(url, '段评'); return; } catch (e3) {}\n try { jv.toast('段评:' + url); } catch (e4) {}\n}\n\nfunction _tdJv() {\n try { if (this && this.java) return this.java; } catch (e) {}\n try { if (typeof java !== 'undefined' && java) return java; } catch (e) {}\n return null;\n}\nfunction _tdEsc(s) {\n return String(s == null ? '' : s)\n .replace(\/&\/g, '&').replace(\/<\/g, '<')\n .replace(\/>\/g, '>').replace(\/\"\/g, '"');\n}\nfunction _taduShow(bid, cid, seg) {\n var jv = _tdJv.call(this);\n if (!jv) { try { jv = java; } catch (e) {} }\n var html = '';\n try {\n seg = Number(seg || 0);\n var base = 'http:\/\/43.139.147.103:8070';\n var u = base + '\/tadu\/seg?bid=' + encodeURIComponent(bid)\n + '&cid=' + encodeURIComponent(cid) + '&seg=' + seg;\n var raw = '';\n try { raw = String(jv.ajax(u) || ''); } catch (e) { raw = ''; }\n var d = {};\n try { d = (JSON.parse(raw) || {}).data || {}; } catch (e) { d = {}; }\n var cs = d.comments || [];\n var items = '';\n for (var i = 0; i < cs.length; i++) {\n var c = cs[i] || {};\n var txt = String(c.text || '');\n if (txt.length > 300) txt = txt.slice(0, 300) + '…';\n var av = String(c.avatar || '');\n var nick = String(c.user || '读者');\n var segTag = (c.seg && seg <= 0) ? '<span class=\"ip\">第' + c.seg + '段<\/span>' : '';\n var meta = [];\n if (Number(c.like || 0) > 0) meta.push(Number(c.like) + ' 赞');\n if (Number(c.reply || 0) > 0) meta.push(Number(c.reply) + ' 回复');\n if (c.time) meta.push(_tdEsc(String(c.time)));\n var avatarHtml = av\n ? '<img class=\"av\" src=\"' + _tdEsc(av) + '\" onerror=\"this.style.display=\\'none\\'\"\/>'\n : '<div class=\"av ph\">' + _tdEsc(nick.charAt(0)) + '<\/div>';\n items += '<div class=\"card\">' + avatarHtml + '<div class=\"main\">'\n + '<div class=\"nick\">' + _tdEsc(nick) + segTag + '<\/div>'\n + '<div class=\"txt\">' + _tdEsc(txt) + '<\/div>'\n + (meta.length ? '<div class=\"meta\">' + _tdEsc(meta.join(' · ')) + '<\/div>' : '')\n + '<\/div><\/div>';\n }\n if (!items) items = '<div class=\"empty\">该段落暂无段评<\/div>';\n var head = d.content ? String(d.content)\n : (seg > 0 ? ('第 ' + seg + ' 段') : '本书段评');\n if (head.length > 120) head = head.slice(0, 120) + '…';\n html = '<!doctype html><html><head><meta charset=\"utf-8\">'\n + '<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\"><style>'\n + 'body{margin:0;background:#f8f8f8;color:#1f2329;'\n + 'font-family:-apple-system,\"PingFang SC\",\"Microsoft YaHei\",Arial,sans-serif}'\n + '.topbar{display:flex;justify-content:space-between;padding:12px 16px;background:#fff;border-bottom:1px solid #eee}'\n + '.topbar span:first-child{font-size:13px;color:#666}'\n + '.topbar span:last-child{font-size:15px;font-weight:600;color:#111}'\n + '.wrap{padding:12px}'\n + '.head{margin:0 0 12px;padding:14px 16px;background:#fff;border:1px solid #eaeaea;border-radius:12px}'\n + '.sub{color:#111;font-size:15px;line-height:1.6;word-break:break-all}'\n + '.card{display:flex;gap:9px;margin:0 0 10px;padding:14px;background:#fff;border:1px solid #e2e5ea;border-radius:14px}'\n + '.av{width:38px;height:38px;border-radius:50%;object-fit:cover;flex:0 0 38px;background:#eee}'\n + '.av.ph{display:flex;align-items:center;justify-content:center;color:#fff;background:#4A90E2;font-size:15px}'\n + '.main{flex:1;min-width:0}'\n + '.nick{font-size:13px;color:#333;font-weight:600;margin-bottom:5px}'\n + '.ip{font-size:11px;color:#999;font-weight:400;margin-left:6px}'\n + '.txt{font-size:15px;line-height:1.7;word-break:break-word}'\n + '.meta{font-size:12px;color:#999;margin-top:7px}'\n + '.empty{color:#999;text-align:center;padding:40px 0}'\n + '<\/style><\/head><body>'\n + '<div class=\"topbar\"><span>共 ' + cs.length + ' 条段评<\/span><span>段评详情<\/span><\/div>'\n + '<div class=\"wrap\"><div class=\"head\"><div class=\"sub\">' + _tdEsc(head) + '<\/div><\/div>'\n + items + '<\/div><\/body><\/html>';\n var cfg = JSON.stringify({ isHideable: true, expandedCornersRadius: 16,\n skipCollapsed: true, heightPercentage: 0.82 });\n jv.showBrowser(base, html, '', cfg);\n } catch (e) {\n try { jv.toast('段评加载失败: ' + e); } catch (e2) {}\n try { jv.startBrowser('data:text\/html;base64,'\n + jv.base64Encode(html || '<html><body>段评加载失败<\/body><\/html>'), '段评'); } catch (e3) {}\n }\n}",
"lastUpdateTime": "1793806190671",
"loginUi": "@js:(function(){try{return _dpAqUi(book, java);}catch(e){return _dpLuFallback();}})()",
"loginUrl": "@js:\n\nvar AQ_DEFAULT_BASE = 'http:\/\/43.139.147.103:8070'; \n\nfunction _aqBase() {\n var b = '';\n try { b = String(source.get('agg_server') || ''); } catch (e) {}\n b = b.replace(\/\\\/+$\/, '');\n return b || AQ_DEFAULT_BASE;\n}\n\nfunction _aqV(name) {\n try {\n if (typeof result !== 'undefined' && result) {\n if (typeof result.get === 'function') {\n var g = result.get(name);\n if (g != null && String(g) !== '') return String(g);\n } else if (result[name] != null && String(result[name]) !== '') {\n return String(result[name]);\n }\n }\n } catch (e) {}\n try {\n if (typeof source !== 'undefined' && source && source.getLoginInfoMap) {\n var m = source.getLoginInfoMap();\n if (m) {\n var v = (typeof m.get === 'function') ? m.get(name) : m[name];\n if (v != null) return String(v);\n }\n }\n } catch (e2) {}\n return '';\n}\n\nfunction aqDev() {\n var d = '';\n try { d = String(source.get('aq_dev') || ''); } catch (e) {}\n d = d.replace(\/[^0-9a-f]\/gi, '').toLowerCase();\n if (!\/^[a-f0-9]{32}$\/.test(d)) {\n d = '';\n try { d = String(java.deviceID() || ''); } catch (e1) {}\n if (!d) { try { d = String(java.androidId() || ''); } catch (e2) {} }\n d = d.replace(\/[^0-9a-f]\/gi, '').toLowerCase();\n if (!\/^[a-f0-9]{16,64}$\/.test(d)) {\n d = '';\n for (var i = 0; i < 32; i++) {\n d += '0123456789abcdef'.charAt(Math.floor(Math.random() * 16));\n }\n }\n if (d.length > 64) d = d.substring(0, 64);\n try { source.put('aq_dev', d); } catch (e3) {}\n }\n return d;\n}\n\nfunction _aqPost(path, obj) {\n var base = _aqBase();\n var body = JSON.stringify(obj);\n var hd = { 'Content-Type': 'application\/json' };\n var resp = '';\n try {\n var r = java.post(base + path, body, hd, 15000);\n if (r) { try { resp = String(r.body ? r.body() : r); } catch (e1) { resp = String(r); } }\n } catch (e2) { resp = ''; }\n if (!resp) {\n var opt = JSON.stringify({ method: 'POST', headers: hd, body: body });\n try { resp = String(java.ajax(base + path + ',' + opt) || ''); } catch (e3) { resp = ''; }\n }\n resp = _aqTidy(resp);\n var c0 = resp.charAt(0);\n if (c0 !== '{' && c0 !== '[') { return null; }\n try { return JSON.parse(resp); } catch (e4) { return null; }\n}\n\nfunction _aqGet(path) {\n var base = _aqBase();\n var resp = '';\n try {\n var r = java.get(base + path, {}, 12000);\n if (r) { try { resp = String(r.body ? r.body() : r); } catch (e1) { resp = String(r); } }\n } catch (e2) { resp = ''; }\n if (!resp) {\n try { resp = String(java.ajax(base + path) || ''); } catch (e3) { resp = ''; }\n }\n resp = _aqTidy(resp);\n var c0 = resp.charAt(0);\n if (c0 !== '{' && c0 !== '[') { return null; }\n try { return JSON.parse(resp); } catch (e4) { return null; }\n}\n\nfunction _aqTidy(s) {\n s = String(s == null ? '' : s);\n try { s = s.replace(\/^\\uFEFF\/, ''); } catch (e) {}\n return s.replace(\/^\\s+|\\s+$\/g, '');\n}\n\nfunction _aqToast(s) {\n try { java.toast(String(s)); } catch (e) {}\n}\n\nvar _AQ_IMPORT_URL = 'http:\/\/43.139.147.103:8070\/fq\/bookSource.json';\n\nvar _AQ_SELF_VER = '20261102-3';\n\nfunction _dpSrcLocalVer() {\n var v = '';\n try { v = String(source.get('aq_src_ver') || ''); } catch (e0) {}\n if (!v) { v = _AQ_SELF_VER; }\n return v;\n}\n\nfunction _dpSrcFetchVer() {\n var base = _aqBase();\n var resp = '';\n try {\n var r = java.get(base + '\/fq\/version.json', {}, 12000);\n if (r) { try { resp = String(r.body ? r.body() : r); } catch (e1) { resp = String(r); } }\n } catch (e2) { resp = ''; }\n if (!resp) {\n try { resp = String(java.ajax(base + '\/fq\/version.json') || ''); } catch (e3) { resp = ''; }\n }\n resp = _aqTidy(resp);\n if (resp.charAt(0) !== '{') { return null; }\n try { return JSON.parse(resp); } catch (e4) { return null; }\n}\n\nfunction _dpSrcVerText() {\n var remote = null;\n try { remote = _dpSrcFetchVer(); } catch (e0) {}\n var local = _dpSrcLocalVer();\n if (remote && remote.version) {\n if (local && local === String(remote.version)) {\n return '📦 已是最新版 ' + local;\n }\n var tip = '📦 本地 ' + (local || '未知') + ' → 最新 ' + remote.version;\n if (remote.requireImport === false) { tip += '(服务端升级,无需导入)'; }\n return tip;\n }\n if (local) { return '📦 当前版本 ' + local + '(服务端版本未知)'; }\n return '📦 版本未知(点下方按钮检查)';\n}\n\nfunction _dpSrcUpd() {\n try {\n var remote = _dpSrcFetchVer();\n if (!remote || !remote.version) {\n _aqToast('检查失败:网络错误,请稍后重试');\n return '';\n }\n var local = _dpSrcLocalVer();\n var ver = String(remote.version);\n if (local && local === ver) {\n _aqToast('✅ 已是最新版 ' + ver + ',无需更新');\n try { java.upLoginData({ 'aq_ver': '📦 已是最新版 ' + ver }); } catch (eU) {}\n return '';\n }\n try {\n java.upLoginData({ 'aq_ver': '📦 本地 ' + (local || '未知') + ' → 最新 ' + ver });\n } catch (eU2) {}\n var needImport = remote.requireImport !== false;\n if (!needImport) {\n try { source.put('aq_src_ver', ver); } catch (eS) {}\n _aqToast('服务端已升级到 ' + ver + ',无需重新导入,直接使用即可');\n return '';\n }\n var msg = '有新版:' + (local ? local + ' → ' : '') + ver;\n var ch = [];\n if (Object.prototype.toString.call(remote.changes) === '[object Array]') { ch = remote.changes; }\n var shown = ch.slice(0, 5);\n if (shown.length) { msg += '\\n' + shown.join('\\n'); }\n if (ch.length > 5) { msg += '\\n…共 ' + ch.length + ' 条,详情可看更新日志页'; }\n var notice = '';\n try { if (remote.notice != null) { notice = String(remote.notice); } } catch (eN) {}\n if (notice) { msg += '\\n📢 ' + notice; }\n msg += '\\n即将打开导入确认页…';\n _aqToast(msg);\n var deep = 'legado:\/\/import\/bookSource?src=' + encodeURIComponent(_AQ_IMPORT_URL);\n var okDeep = false;\n try { java.openUrl(deep); okDeep = true; } catch (eO) {}\n if (!okDeep) {\n _aqToast('唤起导入页失败\\n请手动:书源管理 → 网络 → 粘贴 ' + _AQ_IMPORT_URL);\n }\n } catch (e) {\n _aqToast('更新出错:' + (e && e.message ? e.message : e));\n }\n return '';\n}\n\nfunction aqVer() {\n try {\n var t = _dpSrcVerText();\n try { java.upLoginData({ 'aq_ver': t }); } catch (e0) {}\n return '';\n } catch (e) { return ''; }\n}\n\nfunction login(force) {\n try {\n var email = _aqV('邮箱');\n var pw = _aqV('密码');\n if (!email || !pw) { _aqToast('请填写邮箱和密码'); return ''; }\n var j = _aqPost('\/user\/auth\/login', {\n email: email, password: pw, device: aqDev()\n });\n if (!j) { _aqToast('网络错误,请重试'); return ''; }\n if (j.code === 0) {\n try {\n var sess = String(j.session || '');\n if (sess && typeof cookie !== 'undefined' && cookie) {\n cookie.setCookie(_aqBase(), 'rq_session=' + sess);\n }\n } catch (e1) {}\n try { java.upLoginData({ 'aq_quota_line': _aqQuotaText() }); } catch (eQ) {}\n try { source.put('aq_email', String(email)); } catch (eM) {}\n _aqToast('登录成功');\n try { java.refreshContent(); } catch (e2) {}\n } else if (j.code === 429) {\n _aqToast((j.message || '登录设备数已达上限') + '\\n点「🚪 下线其它设备」可腾出名额');\n } else {\n _aqToast(j.message || '登录失败');\n }\n } catch (e) {\n _aqToast('登录出错:' + (e && e.message ? e.message : e));\n }\n return '';\n}\n\nfunction register() {\n try {\n var code = _aqV('注册码');\n var email = _aqV('邮箱');\n var pw = _aqV('密码');\n if (!code) { _aqToast('请先点「🎫 领取注册码」拿到注册码'); return ''; }\n if (!email || !pw) { _aqToast('请填写邮箱和密码'); return ''; }\n var j = _aqPost('\/user\/auth\/register', {\n code: code, email: email, password: pw, device: aqDev()\n });\n if (!j) { _aqToast('网络错误,请重试'); return ''; }\n if (j.code === 0) {\n try {\n var sess = String(j.session || '');\n if (sess && typeof cookie !== 'undefined' && cookie) {\n cookie.setCookie(_aqBase(), 'rq_session=' + sess);\n }\n } catch (e1) {}\n try { source.put('aq_email', String(email)); } catch (eM) {}\n _aqToast('注册成功');\n try { java.upLoginData({ '注册码': '' }); } catch (eC) {}\n try { java.upLoginData({ 'aq_quota_line': _aqQuotaText() }); } catch (eQ) {}\n try { java.refreshContent(); } catch (e2) {}\n } else {\n _aqToast(j.message || '注册失败');\n }\n } catch (e) {\n _aqToast('注册出错:' + (e && e.message ? e.message : e));\n }\n return '';\n}\n\nfunction aqIssue() {\n try {\n var st = _aqGet('\/user\/code\/state');\n if (st && st.selfCodeEnabled === false) {\n _aqToast('管理员已暂停发码');\n return '';\n }\n if (st && st.pool_exhausted === true) {\n _aqToast('注册码已发完(剩 0 \/ ' + (st.pool_total == null ? '?' : st.pool_total)\n + ' 个名额)\\n请等待释放或联系管理员');\n return '';\n }\n var email = _aqV('邮箱');\n if (!email) {\n _aqToast('请先在上方「邮箱」栏填好邮箱,再点「领取注册码」\\n邮箱用于以后找回注册码,务必填对');\n return '';\n }\n var j = _aqPost('\/user\/code\/issue', { device: aqDev(), email: email });\n if (!j) { _aqToast('网络错误,请重试'); return ''; }\n if (j.code === 0) {\n var c = String(j.reg_code || '');\n try { java.upLoginData({ '注册码': c }); } catch (e1) {}\n var left = (j.remaining_today != null) ? ('|今日还可发 ' + j.remaining_today + ' 个') : '';\n var poolLeft = (j.remaining_pool != null && j.pool_total != null)\n ? ('\\n余额:剩 ' + j.remaining_pool + ' \/ ' + j.pool_total + ' 个名额') : '';\n try { java.upLoginData({ 'aq_stock': _aqCodeStockText(j) }); } catch (eSk) {}\n _aqToast('已领取:' + c + left + poolLeft + '\\n请立即点「📝 注册」完成注册');\n } else if (j.code_existing) {\n try { java.upLoginData({ '注册码': String(j.code_existing) }); } catch (e2) {}\n _aqToast('本机已领过:' + j.code_existing + '\\n如需更换请先「♻️ 解绑当前设备」');\n } else {\n _aqToast(j.message || '领取失败');\n }\n } catch (e) {\n _aqToast('领码出错:' + (e && e.message ? e.message : e));\n }\n return '';\n}\n\nfunction aqRelease() {\n try {\n var j = _aqPost('\/user\/code\/release', { device: aqDev() });\n if (!j) { _aqToast('网络错误,请重试'); return ''; }\n if (j.code === 0) {\n if (j.already_released) {\n _aqToast(j.note || '当前没有生效的注册码,可直接点「🎫 领取注册码」');\n } else {\n try { java.upLoginData({ '注册码': '' }); } catch (e1) {}\n if (j.code_revoked) {\n _aqToast('已解绑,可重新领取');\n } else {\n _aqToast('已解绑。该码已用于注册,换机请直接用邮箱密码登录');\n }\n }\n } else {\n _aqToast(j.message || '解绑失败');\n }\n } catch (e) {\n _aqToast('解绑出错:' + (e && e.message ? e.message : e));\n }\n return '';\n}\n\nfunction aqFind() {\n try {\n var email = _aqV('邮箱');\n if (!email) { _aqToast('请先填写邮箱(领码时用的那个)'); return ''; }\n var j = _aqPost('\/user\/code\/find', { email: email, device: aqDev() });\n if (!j) { _aqToast('网络错误,请重试'); return ''; }\n if (j.code === 0 && j.codes && j.codes.length) {\n var unused = null;\n for (var i = 0; i < j.codes.length; i++) {\n if (j.codes[i].status === 'unused') { unused = j.codes[i].code; break; }\n }\n if (unused) {\n try { java.upLoginData({ '注册码': unused }); } catch (e1) {}\n _aqToast('已找回:' + unused);\n } else {\n _aqToast('本机领的码已失效(过期\/已作废\/已用于注册)\\n直接点「🎫 领取注册码」换一张新码');\n }\n } else {\n _aqToast(j.message || '该邮箱没有领码记录');\n }\n } catch (e) {\n _aqToast('找回出错:' + (e && e.message ? e.message : e));\n }\n return '';\n}\n\nfunction _aqLimitSrcText(q) {\n var s = String((q && q.source) || '');\n if (s === 'exempt') return '豁免·不限';\n if (s === 'custom') return '单独设的额度';\n if (s === 'default') return '默认额度';\n return '来源未知';\n}\n\nfunction _aqCodeStockText(st) {\n try {\n var a = st || _aqGet('\/user\/auth\/status');\n if (a) {\n var tot = a.pool_total;\n var left = a.remaining_pool;\n if (a.pool_exhausted === true) {\n return '🎟 注册码余额:0 个名额(已发完,等释放)';\n }\n if (left != null && tot != null) {\n var t = '🎟 注册码余额:剩 ' + left + ' \/ ' + tot + ' 个名额可注册';\n if (a.low_stock === true) { t += ' · 库存偏低'; }\n if (a.remaining_today != null) { t += '|今日还可发 ' + a.remaining_today; }\n return t;\n }\n }\n } catch (eS) {}\n return '🎟 注册码余额:读取失败 · 点这里重试';\n}\n\nfunction _aqQuotaText(st) {\n try {\n var a = st || _aqGet('\/user\/auth\/status');\n if (a && a.code === 0 && a.loggedIn && a.quota) {\n var q = a.quota;\n var lim = (q.limit == null) ? '不限' : q.limit;\n var t = '📊 今日已读 ' + q.used + ' \/ ' + lim + ' 章';\n if (q.remaining != null) { t += '(剩 ' + q.remaining + ')'; }\n if (q.bypass) { t += ' · 暂不计限'; }\n t += '|' + _aqLimitSrcText(q);\n return t;\n }\n if (a && a.loggedIn === false) {\n return '📊 未登录 · 登录后这里显示今日额度';\n }\n } catch (e) {}\n return '📊 额度获取失败 · 点这里重试';\n}\n\nfunction _aqWhoText(st) {\n try {\n var a = st || _aqGet('\/user\/auth\/status');\n if (!a) return '🔌 状态未知 · 点这里重试';\n if (a.code === 0 && a.loggedIn) {\n var em = '';\n try { em = String((a.user && a.user.email) || ''); } catch (eE) {}\n var q = a.quota || {};\n var lim = (q.limit == null) ? '不限' : (q.limit + ' 章');\n return '✅ 已登录' + (em ? ':' + em : '') + '|今日 ' + q.used + ' \/ ' + lim\n + '(' + _aqLimitSrcText(q) + ')';\n }\n if (a.code === 401 || a.loggedIn === false) {\n return '❌ 未登录 · 会话已失效,填邮箱密码再点登录';\n }\n } catch (e) {}\n return '⚠ 登录状态读取失败 · 点这里重试';\n}\n\nfunction aqStock() {\n try {\n var a = _aqGet('\/user\/auth\/status');\n if (!a) { _aqToast('网络错误,请重试'); return ''; }\n var t = _aqCodeStockText(a);\n try { java.upLoginData({ 'aq_stock': t }); } catch (e1) {}\n var more = '';\n if (a.remaining_pool != null && a.pool_total != null) {\n more = '\\n已发 ' + (a.pool_total - a.remaining_pool) + ' \/ ' + a.pool_total + ' 个名额';\n }\n _aqToast(t + more);\n } catch (e) { _aqToast('查询出错'); }\n return '';\n}\n\nfunction aqCheck() {\n try {\n var a = _aqGet('\/user\/auth\/status');\n if (!a) { _aqToast('网络错误,请重试'); return ''; }\n var t = _aqWhoText(a);\n _aqToast(t);\n try { java.upLoginData({ 'aq_who': t }); } catch (e1) {}\n try { java.upLoginData({ 'aq_quota_line': _aqQuotaText(a) }); } catch (e2) {}\n if (a.code === 0 && a.loggedIn) {\n try {\n var em = String((a.user && a.user.email) || '');\n if (em) {\n java.upLoginData({ '邮箱': em });\n source.put('aq_email', em); \n }\n } catch (e3) {}\n }\n } catch (e) {\n _aqToast('检测出错:' + (e && e.message ? e.message : e));\n }\n return '';\n}\n\nfunction aqQuota() {\n try {\n var j = _aqGet('\/user\/api\/quota');\n if (!j) { _aqToast('网络错误,请重试'); return ''; }\n if (j.code !== 0) {\n _aqToast(j.message || '未登录');\n try { java.upLoginData({ 'aq_quota_line': '📊 未登录 · 登录后这里显示今日额度' }); } catch (e0) {}\n return '';\n }\n var lim = (j.limit == null) ? '不限' : j.limit;\n var t = '📊 今日已读 ' + j.used + ' \/ ' + lim + ' 章';\n if (j.remaining != null) { t += '(剩 ' + j.remaining + ')'; }\n if (j.bypass) { t += ' · 暂不计限'; }\n try { java.upLoginData({ 'aq_quota_line': t }); } catch (e1) {}\n _aqToast(t + '\\n重读同一章不重复计 · 每日本地 0 点重置');\n } catch (e) {\n _aqToast('查询出错');\n }\n return '';\n}\n\nfunction aqKickOthers() {\n try {\n var d = _aqGet('\/user\/api\/devices');\n if (!d || d.code !== 0) { _aqToast('请先登录'); return ''; }\n var list = d.devices || [];\n var n = 0, names = [];\n for (var i = 0; i < list.length; i++) {\n var it = list[i];\n if (it.current || !it.active) { continue; }\n if (!it.device) { continue; } \n names.push((it.device_label || '?') + '(' + it.active + ')');\n var j = _aqPost('\/user\/api\/devices\/kick', { device: it.device });\n if (j && j.code === 0) { n += (j.kicked || 0); }\n }\n if (!n) { _aqToast('没有其它在线设备(共 ' + list.length + ' 台)'); return ''; }\n _aqToast('已下线 ' + n + ' 个会话:' + names.join('、'));\n } catch (e) {\n _aqToast('操作出错:' + (e && e.message ? e.message : e));\n }\n return '';\n}\n\nfunction aqLogout() {\n try {\n _aqPost('\/user\/auth\/logout', {});\n try { cookie.removeCookie(_aqBase()); } catch (e1) {}\n try { java.upLoginData({ 'aq_quota_line': _aqQuotaText() }); } catch (e2) {}\n _aqToast('已退出登录');\n try { java.refreshContent(); } catch (e3) {}\n } catch (e) {}\n return '';\n}\n\nfunction _dpLuRow(name, label, action, dynLabel, basis) {\n var r = {\n name: name, type: 'button',\n style: {\n layout_flexGrow: 1,\n layout_flexBasisPercent: (basis == null ? 0.45 : basis)\n }\n };\n r.viewName = dynLabel ? String(label) : JSON.stringify(String(label));\n if (action) r.action = action;\n return r;\n}\n\nfunction _dpLuFallback() {\n try {\n return JSON.stringify([\n _dpLuRow('lu_hint', '↓ 账号登录 ↓', null, false, 1),\n _dpLuRow('lu_login', '🔑 登录', 'login(true)', false, 0.45),\n _dpLuRow('lu_reg', '📝 注册', 'register()', false, 0.45),\n _dpLuRow('lu_tip', '每日 100 章 · 重读不重复计 · 未登录无法阅读', null, false, 1)\n ]);\n } catch (e) { return '[]'; }\n}\n\nfunction _dpAqRows() {\n var r = [];\n var hint = '点「🎫 领取注册码」自助领码:一机一码,换机先解绑';\n var st = _aqGet('\/user\/code\/state');\n if (st && st.code === 0) {\n if (st.codeHint) {\n var parts = String(st.codeHint).split('\\n');\n hint = parts[0];\n }\n if (st.selfCodeEnabled === false) {\n r.push(_dpLuRow('aq_off', '⛔ 管理员已暂停发码', null, false, 1));\n }\n }\n var _st = null;\n try { _st = _aqGet('\/user\/auth\/status'); } catch (eSt) {}\n var qtext = '📊 今日额度加载中…';\n try { qtext = _aqQuotaText(_st); } catch (eq) {}\n r.push(_dpLuRow('aq_quota_line', qtext, 'aqQuota()', false, 1));\n var whoText = '🔌 登录状态检测中…';\n try { whoText = _aqWhoText(_st); } catch (ew) {}\n r.push(_dpLuRow('aq_who', whoText, 'aqCheck()', false, 1));\n r.push(_dpLuRow('aq_head', '↓ 注册码登录(阅读额度) ↓', null, false, 1));\n var stockText = '🎟 注册码余额加载中…';\n try { stockText = _aqCodeStockText(_st); } catch (eSk) {}\n r.push(_dpLuRow('aq_stock', stockText, 'aqStock()', false, 1));\n r.push({ name: '注册码', type: 'text', default: '' });\n var _mail = '';\n try { _mail = String(source.get('aq_email') || ''); } catch (eM) {}\n r.push({ name: '邮箱', type: 'text', default: _mail });\n r.push({ name: '密码', type: 'password', default: '' });\n r.push(_dpLuRow('aq_check', '🔄 检测登录状态', 'aqCheck()', false, 1));\n r.push(_dpLuRow('aq_login', '🔑 登录', 'login(true)', false, 0.45));\n r.push(_dpLuRow('aq_reg', '📝 注册', 'register()', false, 0.45));\n r.push(_dpLuRow('aq_issue', '🎫 领取注册码', 'aqIssue()', false, 0.45));\n r.push(_dpLuRow('aq_release', '♻️ 解绑当前设备', 'aqRelease()', false, 0.45));\n r.push(_dpLuRow('aq_find', '🔍 找回注册码', 'aqFind()', false, 0.45));\n r.push(_dpLuRow('aq_kick', '🚪 下线其它设备', 'aqKickOthers()', false, 0.45));\n r.push(_dpLuRow('aq_logout', '⏏️ 退出登录', 'aqLogout()', false, 1));\n r.push(_dpLuRow('aq_ver', '📦 版本检查中…', 'aqVer()', false, 1));\n r.push(_dpLuRow('aq_upd', '⟳ 检查书源更新', '_dpSrcUpd()', false, 1));\n var tip = hint;\n if (st && st.code === 0) {\n if (st.pool_exhausted === true) {\n tip += '|注册码已发完,等待释放';\n } else if (st.remaining_today != null) {\n tip += '|今日还可发 ' + st.remaining_today + ' 个';\n }\n tip += '|每日 ' + (st.dailyLimit == null ? 100 : st.dailyLimit) + ' 章';\n }\n r.push(_dpLuRow('aq_tip', tip, null, false, 1));\n return r;\n}\n\nfunction _dpAqUi(bko, jav) {\n try {\n var rows = _dpAqRows();\n try {\n if (typeof _dpLuList === 'function') {\n var rest = JSON.parse(_dpLuList(bko, jav));\n if (rest && rest.length) rows = rows.concat(rest);\n }\n } catch (eB) {}\n return JSON.stringify(rows);\n } catch (e) { return '[]'; }\n}\n",
"respondTime": 180000,
"ruleBookInfo": {
"author": "@js:_dpInfoField(baseUrl, result, java, book, 'author')",
"coverUrl": "@js:_dpInfoField(baseUrl, result, java, book, 'coverUrl')",
"intro": "@js:_dpInfoField(baseUrl, result, java, book, 'intro')",
"kind": "@js:_dpInfoField(baseUrl, result, java, book, 'kind')",
"lastChapter": "@js:_dpInfoField(baseUrl, result, java, book, 'lastChapter')",
"name": "@js:_dpInfoField(baseUrl, result, java, book, 'name')",
"tocUrl": "@js:_dpTocUrl(baseUrl, result)",
"wordCount": "@js:_dpInfoField(baseUrl, result, java, book, 'wordCount')"
},
"ruleContent": {
"content": "<js>(function(){\nfunction _ILLU(x){try{return __dpIllu(String(x==null?\"\":x),book,chapter,java);}catch(eI){return x;}}\nif((typeof _dpAggWant===\"function\")&&_dpAggWant(chapter,baseUrl)){\n try{_dpSetCtx(java,book,chapter);}catch(eS){}\n return _ILLU(_dpAggBody(result,chapter,baseUrl,java));\n}\nreturn _ILLU(_dpBody(String(result==null?\"\":result)));\n})()<\/js>\n@js:(function(){if((typeof _dpAggWant==='function')&&_dpAggWant(chapter,baseUrl))return result;return __dpInject(result, book ? String(book.name || '') : '', book ? String(book.author || '') : '', chapter ? String(chapter.title || '') : '', java, cookie, book, chapter);})()"
},
"ruleExplore": {
"author": "$.bAuth",
"bookList": "<js>var _h=(typeof src!=='undefined'&&src!=null)?String(src):String(result==null?'':result);result=_dpExploreList(baseUrl,_h,java);<\/js>\n$.data.records||$.dp3.records",
"bookUrl": "$.u",
"coverUrl": "$.c",
"intro": "$.desc",
"kind": "$.subCat||$.cat",
"name": "$.bName",
"wordCount": "$.cnt"
},
"ruleSearch": {
"author": "$.author",
"bookList": "<js>var _h=(typeof src!=='undefined'&&src!=null)?String(src):String(result==null?'':result); var _r=[];try{_r=_dpSearchRows(_h,'',java,source)||[];}catch(eS0){_r=[];}result=JSON.stringify({list:_r});<\/js>\n$.list",
"bookUrl": "$.bookUrl",
"coverUrl": "$.coverUrl",
"intro": "$.intro",
"kind": "$.kind",
"lastChapter": "$.lastChapter",
"name": "$.name",
"wordCount": "$.wordCount"
},
"ruleToc": {
"chapterList": "<js>var _h=(typeof src!=='undefined'&&src!=null)?String(src):String(result==null?'':result);var _r=[];try{_r=_dpTocRows(baseUrl,_h,java)||[];}catch(eT0){_r=[];}result=JSON.stringify({list:_r});<\/js>\n$.list",
"chapterName": "$.name",
"chapterUrl": "$.url"
},
"searchUrl": "@js:\nvar _g='';\ntry { _g=String(source.get('dp_adult')||''); } catch(e1){}\nif(!_g){ try { _g=String(source.get('dpgrade')||''); } catch(e2){} }\nif(!_g){ try { _g=String(cache.get('dpgrade')||''); } catch(e3){} }\nvar _a=((String(_g)==='1')||String(_g).indexOf('成人')>=0)?'1':'0';\n_dpAggHost() + '\/api\/search?key={{key}}&page={{page}}&type=novel&adult='+_a+'&all_src=1&batch=0&budget=25&sv=1';\n",
"weight": 0
}