[{"articleStyle":1,"cacheFirst":false,"customOrder":-10100159,"enableJs":true,"enabled":true,"enabledCookieJar":true,"header":"{\"User-Agent\":\"Mozilla\/5.0 (Linux; U; Android 13; zh-Hans-CN; PFJM10 Build\/TP1A.220905.001) AppleWebKit\/537.36 (KHTML, like Gecko) Version\/4.0 Chrome\/135.0.4896.58 Quark\/6.13.6.581 Mobile Safari\/537.36\",\"Accept-Language\":\"zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7\"}","jsLib":"function getData() {\nvar Data = this.source.getVariable();\nif (Data == \"\" || Data == undefined) {\nreturn {};\n}\ntry {\nreturn JSON.parse(String(Data));\n} catch (e) {\nreturn {};\n}\n}\nfunction getPage() {\nvar data = getData.call(this);\nvar startPage = (data.page == \"\" || data.page == undefined) ? '' : parseInt(data.page)-1;\nreturn startPage;\n}\nfunction getUrl2() {\nvar url2=String(this.source.key).replace(\/\\\/$\/,'');\nreturn url2;\n}\n\n\/\/ ===== 91PORN 线路注入（261107 新增）=====\n\/\/ BaseSource.evalJS 每次把 jsLib 注入脚本作用域，source 绑定可用；\n\/\/ PN_base() 在 sortUrl \/ searchUrl 的 {{}} 内联 JS 里「请求时」求值，\n\/\/ 因此登录面板切了 pnLine 后，下一次拉列表\/搜索立即落在新线路，\n\/\/ 不受 sortUrls() 的 ACache 缓存影响（@js: 整段脚本方案会被缓存坑住）。\n\/\/ ===== 261108 三轮修复：线路变量走 this.source.getVariable() =====\n\/\/ 诊断实锤：{{}} 的 jsLib 共享 scope 里裸 source\/cache\/java\/baseUrl 全部不可用，\n\/\/ 但 this.source.getVariable() 可用（与既有 getData() 同通道）。\nfunction PN_var() {\n  var o = {};\n  try {\n    var v = '';\n    try { v = String(this.source.getVariable() || ''); } catch (e0) { v = ''; }\n    if (v) o = JSON.parse(v) || {};\n  } catch (e) { o = {}; }\n  return o;\n}\n\/\/ 写线路到 variable（保留起始页码 page，绝不写死页码上限）\nfunction PN_setVarLine(line) {\n  var o = PN_var.call(this);\n  if (!o.page) o.page = '1';\n  o.pnLine = String(line || '');\n  try { this.source.setVariable(JSON.stringify(o)); } catch (e) {}\n  return o;\n}\nfunction PN_base() {\n  var ok = function (v) {\n    var s = '';\n    try { s = String(v); } catch (e) { return ''; }\n    return (s && s !== 'null' && s !== 'undefined' && s.indexOf('http') === 0) ? s : '';\n  };\n  var d = '';\n  \/\/ ① 主通道：variable.pnLine（this.source 在 {{}} 共享 scope 可用，诊断版4 实锤）\n  try { d = ok(PN_var.call(this).pnLine); } catch (e) { d = ''; }\n  \/\/ ② 面板原生 source.put 通道（部分版本可用）\n  if (!d) { try { d = ok(source.get('pnLine')); } catch (e2) { d = ''; } }\n  \/\/ ③ CacheManager 精确键（需要 cache 绑定；缺失则跳过）\n  if (!d) {\n    try {\n      var key = '';\n      try { key = String(this.source.key || ''); } catch (e3) { key = ''; }\n      if (!key) { try { key = String(source.sourceUrl || ''); } catch (e4) {} }\n      if (!key) key = 'https:\/\/418.sol148.com\/index.php';\n      d = ok(cache.get('v_' + key + '_pnLine'));\n    } catch (e5) { d = ''; }\n  }\n  \/\/ ④ java.get 兜底\n  if (!d) { try { d = ok(java.get('pnLine')); } catch (e6) { d = ''; } }\n  if (!d) d = 'https:\/\/a.26702.app';\n  return d.replace(\/\\\/+$\/, '');\n}\n","lastUpdateTime":1794139497524,"loadWithBaseUrl":true,"loginUi":"[{\"name\": \"起始页码\",\"type\": \"text\",\"viewName\": \"'起始页码(默认1)'\",\"style\": {\"layout_flexBasisPercent\": 0.48,\"layout_flexGrow\": 1}},{\"name\": \"发布页\",\"type\": \"text\",\"viewName\": \"'发布页地址'\",\"style\": {\"layout_flexBasisPercent\": 0.48,\"layout_flexGrow\": 1}},{\"name\": \"应用发布页\",\"type\": \"button\",\"action\": \"PN_pubFrom(result)\",\"viewName\": \"'💾 应用发布页地址'\",\"style\": {\"layout_flexBasisPercent\": 0.48,\"layout_flexGrow\": 1}},{\"name\": \"更新书源\",\"type\": \"button\",\"action\": \"PN_update()\",\"viewName\": \"'🎁 更新书源'\",\"style\": {\"layout_flexBasisPercent\": 0.48,\"layout_flexGrow\": 1}},{\"name\": \"获取路线\",\"type\": \"button\",\"action\": \"PN_fetchPub()\",\"viewName\": \"'🧭 一键从发布页获取网址路线'\",\"style\": {\"layout_flexBasisPercent\": 1,\"layout_wrapBefore\": true}},{\"name\": \"测试延时\",\"type\": \"button\",\"action\": \"PN_testAll()\",\"viewName\": \"'⏱ 检测路线延迟(ms写入路线按钮)'\",\"style\": {\"layout_flexBasisPercent\": 0.48,\"layout_flexGrow\": 1}},{\"name\": \"检查登录状态\",\"type\": \"button\",\"action\": \"PN_checkLogin()\",\"viewName\": \"'🔍 检查登录状态\/路线可用性'\",\"style\": {\"layout_flexBasisPercent\": 0.48,\"layout_flexGrow\": 1}},{\"name\": \"打开网站\",\"type\": \"button\",\"action\": \"PN_web()\",\"viewName\": \"'🌐 打开网站(登录)'\",\"style\": {\"layout_flexBasisPercent\": 0.48,\"layout_flexGrow\": 1}},{\"name\": \"显示线路\",\"type\": \"button\",\"action\": \"PN_toast(PN_found().map(PN_host).join(' \/ '))\",\"viewName\": \"'📋 显示当前全部路线'\",\"style\": {\"layout_flexBasisPercent\": 0.48,\"layout_flexGrow\": 1}},{\"name\": \"当前线路\",\"type\": \"label\",\"viewName\": \"PN_curLineText()\",\"style\": {\"layout_flexBasisPercent\": 1,\"layout_wrapBefore\": true}},{\"name\": \"路线列表\",\"type\": \"button\",\"action\": \"\",\"viewName\": \"'━━━ 点击切换路线（延时见按钮名）━━━'\",\"style\": {\"layout_flexBasisPercent\": 1,\"layout_wrapBefore\": true}},{\"name\": \"路线1\",\"type\": \"button\",\"action\": \"PN_switch(1)\",\"viewName\": \"PN_lineBtn(1)\",\"style\": {\"layout_flexBasisPercent\": 0.48,\"layout_flexGrow\": 1}},{\"name\": \"路线2\",\"type\": \"button\",\"action\": \"PN_switch(2)\",\"viewName\": \"PN_lineBtn(2)\",\"style\": {\"layout_flexBasisPercent\": 0.48,\"layout_flexGrow\": 1}},{\"name\": \"路线3\",\"type\": \"button\",\"action\": \"PN_switch(3)\",\"viewName\": \"PN_lineBtn(3)\",\"style\": {\"layout_flexBasisPercent\": 0.48,\"layout_flexGrow\": 1}},{\"name\": \"路线4\",\"type\": \"button\",\"action\": \"PN_switch(4)\",\"viewName\": \"PN_lineBtn(4)\",\"style\": {\"layout_flexBasisPercent\": 0.48,\"layout_flexGrow\": 1}},{\"name\": \"路线5\",\"type\": \"button\",\"action\": \"PN_switch(5)\",\"viewName\": \"PN_lineBtn(5)\",\"style\": {\"layout_flexBasisPercent\": 0.48,\"layout_flexGrow\": 1}},{\"name\": \"路线6\",\"type\": \"button\",\"action\": \"PN_switch(6)\",\"viewName\": \"PN_lineBtn(6)\",\"style\": {\"layout_flexBasisPercent\": 0.48,\"layout_flexGrow\": 1}}]","loginUrl":"\/\/ ==================== 91PORN(订阅) · 发布页\/线路管理面板 ====================\n\/\/ 用途（全部函数挂在 loginUrl，SourceLoginDialog 把 \"$loginJS\\n$action\" 一起 eval）：\n\/\/   ① 发布页输入框：用户可改发布页地址（默认 91p676.com，meta refresh 到 a.26702.app\/1.php）\n\/\/   ② 🧭 一键从发布页获取网址路线：抓 meta refresh \/ 302 Location，解析出线路域名池\n\/\/   ③ ⏱ 检测路线延迟(ms)：java.connect 逐线路请求 \/index.php，callTime() 取 ms，\n\/\/      写入 pnDelay0..N，由 PN_lineBtn 动态 viewName 显示在各路线按钮上\n\/\/   ④ 各路线按钮：点按切换 pnLine；sortUrl\/searchUrl 的 {{PN_base()}} 在请求时\n\/\/      读取 pnLine（绕过 @js: sortUrl 的 ACache 缓存），切换后即时生效\n\/\/   ⑤ 🔍 检查登录状态\/线路可用性 + 🌐 打开网站(登录)（保留原功能）\n\/\/ 兼容 LegadoTeam(LT) + legado-E：V1 静态 loginUi；text 输入值由 getLoginData()\n\/\/ 注入为 result Map（键=行 name），按钮 action 用 PN_pubFrom(result) 读取；\n\/\/ viewName 动态表达式在 evalUiJs 环境无 java 绑定，故只读 source\/cache，不调用 java。\nvar PN_MAX = 6;\nvar PN_PUB_DEFAULT = 'http:\/\/91p676.com';\nvar PN_LINE_DEFAULT = 'https:\/\/a.26702.app';\nvar PN_UA = 'Mozilla\/5.0 (Linux; Android 13; Pixel 7) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/124.0.0.0 Mobile Safari\/537.36';\n\/\/ 内置兜底线路（均来自源注释\/发布页实测，不含写死页码上限）：\n\/\/ 发布页 host 本身即完整站点；其余为历史镜像，供测速对比。\nvar PN_FALLBACK = [\n  'https:\/\/a.26702.app',\n  'https:\/\/418.sol148.com',\n  'https:\/\/a1019.9p58b.com',\n  'https:\/\/f1011.a2507app.com',\n  'https:\/\/902.9p234.com'\n];\n\nfunction PN_toast(t) {\n  try { java.longToast(String(t)); } catch (e) { try { java.toast(String(t)); } catch (e2) {} }\n}\nfunction PN_gv(k, def) {\n  var v = '';\n  try { v = String(source.get(k)); } catch (e) { v = ''; }\n  if (v === '' || v === 'null' || v === 'undefined') v = def || '';\n  return v;\n}\nfunction PN_norm(u) {\n  var s = String(u || '').trim().replace(\/\\\/+$\/, '');\n  if (s === '') return '';\n  if (s.indexOf('http') !== 0) s = 'https:\/\/' + s;\n  \/\/ 只保留 scheme:\/\/host[:port]，丢掉路径（发布页\/线路域名都按根站使用）\n  var m = \/^(https?:\\\/\\\/[^\/]+)\/.exec(s);\n  if (m) s = m[1];\n  return s;\n}\nfunction PN_host(u) {\n  var m = \/^https?:\\\/\\\/([^\/]+)\/.exec(String(u));\n  return m ? m[1] : String(u);\n}\nfunction PN_hdr() { return JSON.stringify({ 'User-Agent': PN_UA, 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8' }); }\n\n\/\/ ---------- 发布页输入框 ----------\nfunction PN_pub() {\n  var p = PN_gv('pnPub', PN_PUB_DEFAULT);\n  p = PN_norm(p);\n  return p === '' ? PN_PUB_DEFAULT : p;\n}\n\/\/ action 环境 result = getLoginData(rowUis)（Java MutableMap<行name, 输入框文本>）\nfunction PN_pubFrom(r) {\n  var v = '';\n  try { if (r && r.get) v = String(r.get('发布页') || ''); } catch (e0) { v = ''; }\n  if (!v) { try { v = String(r['发布页'] || ''); } catch (eA) { v = ''; } }\n  if (!v) { try { if (result && result.get) v = String(result.get('发布页') || ''); } catch (e1) {} }\n  if (!v) { try { if (result) v = String(result['发布页'] || ''); } catch (eB) {} }\n  if (!v || !v.trim()) v = PN_PUB_DEFAULT;\n  var p = PN_norm(v);\n  source.put('pnPub', p);\n  PN_toast('✅ 发布页已设为：' + PN_host(p) + '（点「🧭 一键从发布页获取网址路线」生效）');\n  PN_refresh();\n}\nfunction PN_pubHint() {\n  return \"'发布页(默认91p676.com)'\";\n}\n\n\/\/ ---------- 线路池持久化 ----------\nfunction PN_setFound(list) {\n  var out = [], i, u;\n  for (i = 0; i < list.length && out.length < PN_MAX; i++) {\n    u = PN_norm(list[i]);\n    if (u && out.indexOf(u) < 0) out.push(u);\n  }\n  if (!out.length) out = PN_FALLBACK.slice(0);\n  source.put('pnFound', out.join(' '));\n  for (i = 0; i < PN_MAX; i++) source.put('pnDelay' + i, '');\n  return out;\n}\nfunction PN_found() {\n  var s = PN_gv('pnFound', '');\n  if (!s) return PN_setFound(PN_FALLBACK);\n  var a = s.split(\/\\s+\/), out = [], i;\n  for (i = 0; i < a.length && out.length < PN_MAX; i++) {\n    var u = PN_norm(a[i]);\n    if (u.indexOf('http') === 0 && out.indexOf(u) < 0) out.push(u);\n  }\n  return out.length ? out : PN_setFound(PN_FALLBACK);\n}\n\/\/ 统一写线路：source.put + variable 双写（PN_base 走 getVariable 读取）\nfunction PN_writeLine(line) {\n  var L = String(line || '');\n  try { source.put('pnLine', L); } catch (e0) {}\n  try { source.put('pnLineHost', L.replace(\/^https?:\\\/\\\/\/, '').replace(\/\\\/.*$\/, '')); } catch (e1) {}\n  try {\n    if (typeof PN_setVarLine === 'function') PN_setVarLine.call(source, L);\n    else {\n      var o = {}, v = '';\n      try { v = String(source.getVariable() || ''); } catch (e2) { v = ''; }\n      try { o = v ? (JSON.parse(v) || {}) : {}; } catch (e3) { o = {}; }\n      if (!o.page) o.page = '1';\n      o.pnLine = L;\n      source.setVariable(JSON.stringify(o));\n    }\n  } catch (e4) {}\n  return L;\n}\nfunction PN_line() {\n  var d = PN_norm(PN_gv('pnLine', PN_LINE_DEFAULT));\n  return d.indexOf('http') === 0 ? d : PN_LINE_DEFAULT;\n}\nfunction PN_absUrl(u, base) {\n  var s = String(u || '').trim();\n  if (!s) return '';\n  if (s.indexOf('http') === 0) return PN_norm(s);\n  if (s.indexOf('\/\/') === 0) return PN_norm('https:' + s);\n  var b = PN_norm(base).replace(\/\\\/+$\/, '');\n  if (s.charAt(0) !== '\/') s = '\/' + s;\n  return PN_norm(b + s);\n}\n\n\/\/ ---------- 🧭 一键从发布页获取网址路线 ----------\n\/\/ 发布页 91p676.com：200 + <META HTTP-EQUIV=Refresh CONTENT=\"0; URL=https:\/\/a.26702.app\/1.php\">\n\/\/ 二级 a.26702.app\/1.php：302 Location: https:\/\/902.9p234.com（当前官方线路）\n\/\/ 解析策略：抓 meta refresh → GET 目标 → 若 302 取 Location；同时把发布页 host\n\/\/ 本身（完整站点）加入池，历史上已记录的同源镜像一并纳入，按去重建最多 PN_MAX 条。\n\/\/  meta refresh \/ 302 Location 解析（★不削路径：\/1.php 才是发布页跳转入口，\n\/\/  削成根域会命中 18+ 入口页 200 而拿不到 Location）\nfunction PN_fetchPub() {\n  var pub = PN_pub();\n  PN_toast('🧭 开始获取：正在打开发布页 ' + PN_host(pub));\n  var raw = '', err = '';\n  try {\n    var r0 = java.connect(pub + '\/', PN_hdr(), 15000);\n    raw = String(r0.body());\n    if (r0.code && r0.code() !== 200) err = 'HTTP ' + r0.code();\n  } catch (e) { err = String(e).substring(0, 90); }\n  if (err === '' && (raw.length < 20 || raw.indexOf('Exception') === 0)) err = '发布页内容异常';\n  if (err !== '') {\n    PN_toast('⚠ 发布页抓取失败(' + err + ')，载入内置 ' + PN_FALLBACK.length + ' 条兜底线路');\n    PN_setFound(PN_FALLBACK);\n    PN_toast('✅ 已载入内置线路，请点「⏱ 检测路线延迟」');\n    PN_refresh(); return;\n  }\n  PN_toast('🔓 发布页已获取(' + raw.length + 'B)，正在解析跳转…');\n  var lines = [], i, u;\n  \/\/ ① meta refresh 目标（保留 \/1.php 路径，交给 java.head 取 302 Location）\n  var meta = \/URL\\s*=\\s*['\"]?([^'\"\\s>]+)\/i.exec(raw);\n  var next = '';\n  if (meta) next = PN_absUrl(meta[1], pub);\n  if (next) {\n    PN_toast('↪ 发布页跳转 → ' + PN_host(next));\n    \/\/ 「发布页 host」本身是完整站点（a.26702.app\/index.php 实测可访问），先入池\n    var nh = PN_norm(next);\n    if (nh && lines.indexOf(nh) < 0) lines.push(nh);\n    var loc = '';\n    try {\n      var h = java.head(next, PN_hdr(), 12000);\n      var sc = Number(h.statusCode ? h.statusCode() : 0);\n      if (sc === 301 || sc === 302 || sc === 307 || sc === 308) {\n        try { loc = String(h.header('Location') || ''); } catch (eL) { loc = ''; }\n      }\n    } catch (e2) { loc = ''; }\n    if (loc) {\n      u = PN_absUrl(loc, next);\n      if (u && lines.indexOf(u) < 0) lines.push(u);\n    }\n  }\n  \/\/ ② 发布页正文里出现的同族镜像域名（排除 CDN\/图床\/统计信标）\n  var re = \/https?:\\\/\\\/([a-z0-9][a-z0-9.\\-]*\\.[a-z]{2,})\/gi, m, hn;\n  var BAD = \/(cloudflare|cloudfront|google|gstatic|alicdn|cdn77|w3\\.org|beacon|insights|liongege|91selfie|ganyiwanghe|china-goon|gcfang|sjhf120|zhongpinwenhua|hpv112|googletagmanager)\/i;\n  while ((m = re.exec(raw)) !== null) {\n    u = PN_norm(m[0]); hn = PN_host(u);\n    if (BAD.test(hn)) continue;\n    if (\/^[a-z0-9]+\\.[a-z0-9]+\\.(com|net|app|cc|xyz|rest)$\/i.test(hn) ||\n        hn.indexOf('9p') > -1 || hn.indexOf('sol') > -1 ||\n        hn.indexOf('a2507') > -1 || hn.indexOf('26702') > -1) {\n      if (lines.indexOf(u) < 0) lines.push(u);\n    }\n  }\n  \/\/ ③ 内置兜底补齐（保证按钮始终有可切换对象；站点以后加数据也自动跟随）\n  for (i = 0; i < PN_FALLBACK.length && lines.length < PN_MAX; i++) {\n    if (lines.indexOf(PN_FALLBACK[i]) < 0) lines.push(PN_FALLBACK[i]);\n  }\n  var got = PN_setFound(lines);\n  \/\/ 取路线后同步一次 variable（避免 pnLine 只存在于 put 通道而 PN_base 读不到）\n  try { PN_writeLine(PN_line()); } catch (eW) {}\n  PN_toast('✅ 共获取 ' + got.length + ' 条路线：' + got.map(PN_host).join(' \/ '));\n  PN_toast('已写入各路线按钮；请点「⏱ 检测路线延迟」把 ms 写进按钮名');\n  PN_refresh();\n}\n\n\/\/ ---------- ⏱ 检测路线延迟（ms 写入各路线按钮） ----------\n\/\/ 判活三判据：code 200-399 + body 非异常堆栈 + body 含站点特征。\n\/\/ 注意 java.ajax\/connect 失败时返回异常堆栈串而非抛异常（源码 runCatching 包 body），\n\/\/ 因此必须显式排除 'Exception'\/'timeout' 且长度过短的堆栈串。\nfunction PN_testAll() {\n  var list = PN_found();\n  PN_toast('⏱ 开始测速：共 ' + list.length + ' 条线路，逐个请求 \/index.php（约 ' + (list.length * 3) + ' 秒）…');\n  var i, r, b, ms, tag, best = -1, bestMs = 999999;\n  for (i = 0; i < list.length; i++) {\n    ms = -1; tag = '✗ 不可达';\n    try {\n      r = java.connect(list[i] + '\/index.php', PN_hdr(), 10000);\n      b = String(r.body());\n      if (b.indexOf('Exception') > -1 || b.indexOf('timeout') > -1) {\n        \/\/ java.connect 失败时不抛异常，而是 code=200 + 异常堆栈串当 body\n        \/\/ （JsExtensionsAndroid runCatching 包 body）⇒ 明确标成「不可达」而非 HTTP\/200\n        tag = '✗ 不可达';\n      } else if (r.code && (r.code() < 200 || r.code() >= 400)) {\n        tag = '✗ HTTP\/' + r.code();\n      } else if (b.length < 500) {\n        tag = '✗ 内容异常';\n      } else {\n        \/\/ callTime() 是 StrResponse 真机计时（毫秒）；缺失时退化为本地计时\n        ms = r.callTime ? Number(r.callTime()) : -1;\n        if (ms < 0 || isNaN(ms)) ms = 0;\n        tag = ms + 'ms';\n        if (ms < bestMs) { bestMs = ms; best = i; }\n      }\n    } catch (e) { tag = '✗ ' + String(e).substring(0, 36); }\n    source.put('pnDelay' + i, tag);\n    PN_toast('  [' + (i + 1) + '\/' + list.length + '] ' + PN_host(list[i]) + ' → ' + tag);\n  }\n  if (best >= 0) {\n    source.put('pnDelay' + best, '⚡' + bestMs + 'ms');\n    PN_toast('🏁 测速完成：最快 ' + PN_host(list[best]) + ' ' + bestMs + 'ms（点对应路线按钮切换）');\n  } else {\n    PN_toast('⚠ 测速完成：暂无可用线路，可点「🧭 一键从发布页获取网址路线」刷新后重试');\n  }\n  PN_refresh();\n}\n\n\/\/ ---------- 🔍 检查登录状态 \/ 线路可用性 ----------\nfunction PN_checkLogin() {\n  var d = PN_line();\n  PN_toast('🔍 正在检查当前线路：' + PN_host(d));\n  var b = '', code = 0;\n  try {\n    var r = java.connect(d + '\/index.php', PN_hdr(), 15000);\n    b = String(r.body());\n    try { code = r.code ? r.code() : 0; } catch (eC) { code = 0; }\n  } catch (e) { PN_toast('❌ 检查失败：' + String(e).substring(0, 90)); return; }\n  if (b.indexOf('Exception') > -1 || (code && (code < 200 || code >= 400)) || b.length < 5000) {\n    PN_toast('❌ 当前线路不可用(' + (b.indexOf('Exception') > -1 ? '连接异常' : 'HTTP ' + code + ', ' + b.length + 'B') + ')，建议测速后切换线路'); return;\n  }\n  var needLogin = \/(请先登录|登录后查看|需要登录|会员专享|VIP专属)\/.test(b);\n  var hasUser = \/(logout|退出登录|signout)\/i.test(b);\n  PN_toast('✅ 线路正常(' + b.length + 'B)；' + (needLogin ? '⚠ 检测到登录墙' : '列表页可访问') + (hasUser ? '；已检测到登录态' : '；当前为游客态') + '；点「🌐 打开网站」可登录');\n}\n\n\/\/ ---------- 各路线按钮：动态文字 + 切换 ----------\n\/\/ 当前线路动态文本（loginUi 里 label 的 viewName 每次渲染重跑；必须返回纯文本）\nfunction PN_curLineText() {\n  var l = PN_line();\n  var dl = '';\n  try { dl = String(PN_gv('pnDelay' + PN_found().indexOf(l), '')); } catch (e) {}\n  return '📍 当前线路：' + PN_host(l) + (dl ? '（' + dl + '）' : '') + '｜点下方按钮切换';\n}\nfunction PN_lineBtn(n) {\n  var list = PN_found(), i = Number(n) - 1;\n  if (i < 0 || i >= list.length) return '━━ 路线' + n + ' 未获取 ━━';\n  var cur = PN_line(), mark = (list[i] === cur) ? '▶ ' : '　 ';\n  var dl = PN_gv('pnDelay' + i, '');\n  if (dl) mark += dl + ' ';\n  \/\/ ★动态 viewName 求值结果被直接设成按钮文字（E 版 evalUiJs 仅 .toString()，\n  \/\/   LT 版 normalizeJsResult 也不剥引号）⇒ 必须返回纯文本，绝不能自带外层单引号。\n  return mark + PN_host(list[i]);\n}\nfunction PN_switch(n) {\n  var list = PN_found(), i = Number(n) - 1;\n  if (i < 0 || i >= list.length) { PN_toast('⚠ 路线 ' + n + ' 尚未获取，请先点「🧭 一键从发布页获取网址路线」'); return; }\n  var old = PN_line(), nw = list[i];\n  PN_writeLine(nw);\n  \/\/ {{PN_base()}} 在每次请求时读 pnLine，切换后下一次拉列表\/搜索即时落在新线路；\n  \/\/ ruleLink 的 @js 同源重写也读同一个 PN_base() ⇒ 文章链接不再钉死旧域。\n  \/\/ pnSortRev 仅作为运维标记（供排查「是否已切换」），不再是缓存失效的手段。\n  PN_bumpRev();\n  PN_toast('🔄 已切换：' + PN_host(old) + ' → ' + PN_host(nw));\n  PN_toast('✅ 列表\/搜索\/文章链接\/正文全部跟随新线路；请回到订阅页下拉刷新');\n  PN_toast('📍 当前线路：' + PN_host(PN_line()));\n  PN_refresh();\n}\nfunction PN_bumpRev() {\n  var v = 0;\n  try { v = parseInt(PN_gv('pnSortRev', '0'), 10) || 0; } catch (e) { v = 0; }\n  source.put('pnSortRev', String(v + 1));\n}\nfunction PN_refresh() {\n  var ok = false;\n  try { java.reLoginView(); ok = true; } catch (e) {\n    try { java.reLoginView(false); ok = true; } catch (e2) { ok = false; }\n  }\n  if (!ok) PN_toast('ℹ 按钮文字可能未即时刷新：重新打开本面板即可看到「📍 当前线路」与 ▶ 标记');\n}\n\n\/\/ ---------- 保留原功能：起始页码 \/ 打开网站 \/ 更新书源 ----------\n\/\/ 原 jsLib 的 getData\/getPage\/getUrl2 用 this.source，登录面板的 loginUrl 环境里\n\/\/ 这些函数仍挂在 source.evalJS 的共享作用域，但为稳妥这里不依赖 jsLib。\nfunction PN_getPage() {\n  var v = '{}';\n  try { v = String(source.getVariable() || '{}'); } catch (e) { v = '{}'; }\n  var data = {};\n  try { data = JSON.parse(v) || {}; } catch (e2) { data = {}; }\n  var p = (data.page === '' || data.page == undefined) ? '' : parseInt(data.page, 10) - 1;\n  return isNaN(p) ? '' : p;\n}\nfunction PN_getUrl2() {\n  \/\/ 保留原 getUrl2 语义：当前 key（订阅源登录面板里 baseUrl = sourceUrl）\n  var u = '';\n  try { u = String(source.key || ''); } catch (e) { u = ''; }\n  if (!u) u = PN_line();\n  return String(u).replace(\/\\\/$\/, '');\n}\nfunction PN_web() {\n  var d = PN_line();\n  java.startBrowser(d + '\/index.php', d);\n  PN_toast('\\n🌐 已打开 ' + PN_host(d));\n}\nfunction PN_update() {\n  java.openUrl('https:\/\/pc.sysbbs.com\/thread-72602-1-1.html');\n}\n\n\/\/ loginUrl 必须定义 login()，否则点右上角 √ 抛 Function login not implements\n\/\/ login() 同时承担「起始页码」持久化（原 loginUrl 的逻辑），绝不写死页码上限。\nfunction login(e) {\n  if (e != undefined) { PN_toast(String(e)); return; }\n  var info = {};\n  try { info = source.getLoginInfoMap() || {}; } catch (e1) { info = {}; }\n  var pageInput = '';\n  \/\/ login() 的 result 是 Java MutableMap（getLoginData），下标访问在部分 Rhino 桥接下为 undefined\n  try { if (result && result.get) pageInput = String(result.get('起始页码') || ''); } catch (e0) { pageInput = ''; }\n  if (!pageInput) { try { pageInput = String(result['起始页码'] || ''); } catch (eA) { pageInput = ''; } }\n  if (!pageInput || pageInput == 'null' || pageInput == 'undefined') {\n    try { pageInput = String(info['起始页码'] || ''); } catch (e3) { pageInput = ''; }\n  }\n  if (!pageInput || pageInput == 'null' || pageInput == 'undefined') pageInput = '1';\n  try { info['起始页码'] = pageInput; source.putLoginInfo(JSON.stringify(info)); } catch (e4) {}\n  \/\/ ★ 保留起始页码 + 当前线路（PN_base 从 getVariable 读 pnLine）\n  var varObj = { 'page': pageInput };\n  try {\n    var prev = String(source.getVariable() || '');\n    if (prev) { var po = JSON.parse(prev) || {}; if (po.pnLine) varObj.pnLine = po.pnLine; }\n  } catch (eV) {}\n  if (!varObj.pnLine) varObj.pnLine = PN_line();\n  source.setVariable(JSON.stringify(varObj));\n  \/\/ 发布页输入框的值也在 result 里，顺手持久化（用户不点「应用」也能生效）\n  try {\n    var pb = '';\n    try { if (result && result.get) pb = String(result.get('发布页') || '').trim(); } catch (eP0) { pb = ''; }\n    if (!pb) { try { pb = String(result['发布页'] || '').trim(); } catch (eP1) { pb = ''; } }\n    if (pb) source.put('pnPub', PN_norm(pb));\n  } catch (e5) {}\n  PN_bumpRev();\n  PN_toast('91PORN · 线路面板已保存｜起始页码 ' + pageInput + '｜当前线路 ' + PN_host(PN_line()));\n}\n","preload":false,"ruleArticles":"@js:\nvar a=java.getElements('.col-xs-12');\nvar b=parseInt(java.getString('.page_number@value'));\n\/\/java.log(b);\nvar c=parseInt(String(java.getString('.pagingnav@form@a.-2@text')));\n\/\/java.log(c);\nif (baseUrl.match(\/search_id\/)) {\na;\n} else {\njava.toast('\\n📚 第'+b+'\/'+c+'页');\na;\n}","ruleContent":"<js>\nvar step1 = java.base64Decode('PGpzPgp2YXIgYT1zb3VyY2Uuc291cmNlQ29tbWVudDsKdmFyIGQ9amF2YS5iYXNlNjREZWNvZGUoJzVMMmM2SUNGNzd5YTVhU2M1cGlPNTZtNkNpOHY1cnFRNTZTKzVZeTY3N3lhYUhSMGNITTZMeTl3WXk1emVYTmlZbk11WTI5dEN1S2FvTys0aitTNHBlZW1nZVdJaHVTNnErT0FnZVdBa3VXTmx1V1BpdVM3dStTOWxlaS9uZWF6bGVpaGpPUzR1dSs4Z2VTOXYrZVVxT2lBaGVpSHF1aWhqT2FKdithTGhlbWpqdW1acWVTNGp1aTBvK1M3dXdvOEwrV2pzT2FZamo0PScpOwppZihhLmluY2x1ZGVzKGQpKXsKdmFyIGNvbnQgPQpqYXZhLmJhc2U2NERlY29kZSgnUEdwelBncDJZWElnYUhSdGJDQTlJRk4wY21sdVp5aHlaWE4xYkhRZ2ZId2djM0pqSUh4OElDY25LVHNLZG1GeUlIVnliQ0E5SUNjbk93b3ZMeURpa2FBZ01qWXhNVEEzSU9hVXVlZUppT1M0dStXOW91YUFnZSs4bW5aaGNpQjJZa1l3UFhOMGNtVnVZMjlrWlRJb0lpVXpZeVUzTXlVMlppNHVMaUlwQ25aaGNpQnRJRDBnYUhSdGJDNXRZWFJqYUNndmMzUnlaVzVqYjJSbE1sd29XeUluWFNoYlhpSW5YU3NwV3lJblhWd3BMeWs3Q21sbUlDaHRLU0I3Q2lBZ2RISjVJSHNLSUNBZ0lIWmhjaUJrWldNZ1BTQmtaV052WkdWVlVrbERiMjF3YjI1bGJuUW9iVnN4WFNrN0NpQWdJQ0IyWVhJZ2N5QTlJR1JsWXk1dFlYUmphQ2d2YzNKalhITXFQVnh6S2xzaUoxMG9XMTRpSjEwcktWc2lKMTB2S1RzS0lDQWdJR2xtSUNoeklDWW1JSE5iTVYwcElIVnliQ0E5SUhOYk1WMDdDaUFnZlNCallYUmphQ0FvWlNrZ2UzMEtmUW92THlEbWw2Zm1xS0htbmIvbGhaemx1cFh2dkpwa2IyTjFiV1Z1ZEM1M2NtbDBaU2h6ZEhKbGJtTnZaR1V5S0NjdUxpNG5LU2tnNUxpTzVMaUs2WjJpNVpDTTVMaUE1cTJqNVlpWjViZXk2S2FHNTV1Vzc3eU01cGVnNlp5QTZZZU41YVNONVlpRzVwU3ZDaTh2SU9LUm9TQXZkbXhyTG5Cb2NDRG1qSWZudXJucGdKcnBnWlB2dklqcG9iWHBuYUxtbDZEbm03VHBrNzdtbDdidnZJa0thV1lnS0NGMWNtd2dKaVlnZEhsd1pXOW1JR3BoZG1FdWNHOXpkQ0E5UFQwZ0oyWjFibU4wYVc5dUp5a2dld29nSUhSeWVTQjdDaUFnSUNCMllYSWdaeUE5SUNob2RHMXNMbTFoZEdOb0tDOTJZa2RjY3lvOVhITXFXeUluWFNoYk1DMDVZUzE2UVMxYVhYczRMSDBwV3lJblhTOHBJSHg4SUZ0ZEtWc3hYU0I4ZkNBbkp6c0tJQ0FnSUhaaGNpQjBJRDBnS0doMGJXd3ViV0YwWTJnb0wzWmlSMVJjY3lvOVhITXFXeUluWFNoYk1DMDVZUzE2UVMxYVhYczRMSDBwV3lJblhTOHBJSHg4SUZ0ZEtWc3hYU0I4ZkNBbkp6c0tJQ0FnSUhaaGNpQnZjbWxuYVc0Z1BTQlRkSEpwYm1jb1ltRnpaVlZ5YkNCOGZDQW5KeWt1Y21Wd2JHRmpaU2d2WGlob2RIUndjejg2WEM5Y0wxdGVYQzlkS3lrdUtpUXZMQ0FuSkRFbktUc0tJQ0FnSUdsbUlDaHZjbWxuYVc0cElIc0tJQ0FnSUNBZ2RtRnlJSEJoZVd4dllXUWdQU0JLVTA5T0xuTjBjbWx1WjJsbWVTaDdaenBuTEhRNmRDeGxkam9uY0c5cGJuUmxjbVJ2ZDI0bkxHOXdPakUxTUN4dFl6b3lMSFJqT2pFc0NpQWdJQ0FnSUNBZ2MyTTZNQ3hyWXpvd0xIZGtPakFzWjJ3NkowRmtjbVZ1YnlBb1ZFMHBJRFkwTUNjc2MyYzZNQ3h1WXpvd0xIQnNPakFzYkdjNk1peHZkem8wTVRJc2IyZzZPVEUxZlNrN0NpQWdJQ0FnSUhaaGNpQnlJRDBnYW1GMllTNXdiM04wS0c5eWFXZHBiaUFySUNjdmRteHJMbkJvY0Njc0lIQmhlV3h2WVdRc0lDZDdJa052Ym5SbGJuUXRWSGx3WlNJNkluUmxlSFF2Y0d4aGFXNGlmU2NwT3dvZ0lDQWdJQ0IyWVhJZ2FpQTlJRXBUVDA0dWNHRnljMlVvVTNSeWFXNW5LSEl1WW05a2VTZ3BLU2s3Q2lBZ0lDQWdJR2xtSUNocUlDWW1JR291ZFNrZ2RYSnNJRDBnVTNSeWFXNW5LR291ZFNrN0NpQWdJQ0I5Q2lBZ2ZTQmpZWFJqYUNBb1pTa2dlMzBLZlFvdkx5RGlrYUlnNXBpTzVwYUhJRHh6YjNWeVkyVWdjM0pqUHUrOGlPYVhxZWFjbithb29lYWR2eUF2SU9tRHFPV0lodW1Wbk9XRGorKzhpUXBwWmlBb0lYVnliQ2tnZXdvZ0lIWmhjaUJ6TWlBOUlHaDBiV3d1YldGMFkyZ29Menh6YjNWeVkyVmJYajVkSzNOeVl6MWJJaWRkS0Z0ZUlpZGRLMXd1YlhBMFcxNGlKMTBxS1ZzaUoxMHZhU2s3Q2lBZ2FXWWdLSE15SUNZbUlITXlXekZkS1NCMWNtd2dQU0J6TWxzeFhUc0tmUXBwWmlBb0lYVnliQ0I4ZkNBaEwxNW9kSFJ3Y3o4NlhDOWNMeTh1ZEdWemRDaDFjbXdwS1NCN0NpQWdkSEo1SUhzZ2FtRjJZUzUwYjJGemRDZ240cHFnSURreFVFOVNUdSs4bXVhdG8rYVdoK2VidE9tVHZ1YWNxdVdQbHVXSXNPKzhqT2VybWVlQ3VlV1ByK2lEdmVXR2plYXNvZWFVdWVlSmlDY3BPeUI5SUdOaGRHTm9JQ2hsS1NCN2ZRb2dJQ2NuT3dwOUlHVnNjMlVnZXdvZ0lDOHZJT0tZaFNEa3VJM2xobzNsaVpUcG1hUWdKbVk5Nzd5YTVhNmU1cldMNWJpbTU2Mis1WkNOSURJd01DQjJhV1JsYnk5dGNEVHZ2SXpsaVpUcG1hVGxrSTRnTXpBeUlIUmxlSFF2YUhSdGJBb2dJSFZ5YkRzS2ZRbzhMMnB6UGc9PScpOwpyZXN1bHQgPSBqYXZhLmdldFN0cmluZyhjb250KTsKfSBlbHNlIHsKZXJyb3I9amF2YS5iYXNlNjREZWNvZGUoJzRwcWc3N2lQSU9hamdPYTFpK1dJc09TNXB1YTZrT2lpcSthQnR1YUVqK2V2b2VhVXVRcmlyWkFnNksrMzVZbU41YjZBNUwyYzZJQ0Y1TGk3NmFHMTVwdTA1cGF3NUxtbTVycVFLT1dGcyttWHJlV0hnT1dNbHVhWXZ1ZWt1dW1UdnVhT3BTbnZ2Sm9LYUhSMGNITTZMeTl0TG5ONWMySmljeTVqYjIwSzRxMlFJT2FRbk9lMG91ZVVxT2FJdCtXUWplKzhtdVdrbk9hWWp1ZXB1Zz09Jyk7CnJlc3VsdD1qYXZhLmxvbmdUb2FzdCgnXG4nK2Vycm9yKTsKcmVzdWx0PSdcbiZscm07XG4nK2Vycm9yOwp9CnJlc3VsdAo8L2pzPg==');\nvar step2 = java.getString(step1);\nresult = step2\n<\/js>","ruleImage":"tag.img.0@src||tag.img.0@data-src","ruleLink":"@js:\nvar u = String(java.getString('a@href') || '');\nif (!u) { ''; } else {\n  var base = '';\n  try { base = String(PN_base()); } catch (e) { base = String(baseUrl || '').replace(\/^(https?:\\\/\\\/[^\/]+).*$\/, '$1'); }\n  var out = '';\n  if (u.indexOf('http') === 0) {\n    \/\/ 绝对链接：把页面写死的 host 换成当前线路（站点换域后链接不再钉死旧域）\n    var p = u.replace(\/^https?:\\\/\\\/[^\/]+\/, '');\n    out = (base || 'https:\/\/a.26702.app').replace(\/\\\/+$\/, '') + p;\n  } else if (u.indexOf('\/\/') === 0) {\n    out = 'https:' + u;\n  } else if (u.charAt(0) === '\/') {\n    out = (base || String(baseUrl || '').replace(\/^(https?:\\\/\\\/[^\/]+).*$\/, '$1')) + u;\n  } else {\n    out = u;   \/\/ 站方若给相对路径，交给 loadWithBaseUrl 处理\n  }\n  out;\n}","ruleNextPage":"page","rulePubDate":"<js>\nvar html = String(java.getString('.well@text'));\nvar resultParts = [];\nvar time=java.getString('.duration@text');\nresultParts.push('🔁' + time);\n\nvar data = html.replace(\/.*添加时间:([^作者]+)作者.*\/, '$1').replace(\/\\s*\/g, '');\nif (data && data.trim() !== '' && data !== html) {\nresultParts.push('⏰' + data);\n}\nvar author = html.replace(\/.*作者:([^热度]+)热度.*\/, '$1');\nif (author && author.trim() !== '' && author !== html) {\nresultParts.push('👤' + author);\n}\nvar hotMatch = html.match(\/.*热度:([^收藏]+)收藏.*\/);\nif (hotMatch && hotMatch[1]) {\nvar hot = parseInt(hotMatch[1].trim());\nif (!isNaN(hot) && hot !== 0) {\nresultParts.push('🔥' + hot);\n}\n}\nresultParts.join(' ')\n<\/js>","ruleTitle":".video-title@text","searchUrl":"{{PN_base()}}\/search_result.php?viewtype=basic&search_type=search_videos&search_id={{key}}&min_duration=10&page={{page}}","showWebLog":false,"singleUrl":false,"sortUrl":"最新::{{PN_base()}}\/v.php?next=watch&page=<{{page+getPage()}}>\n91原创::{{PN_base()}}\/v.php?category=ori&viewtype=basic&page=<{{page+getPage()}}>\n当前最热::{{PN_base()}}\/v.php?category=hot&viewtype=basic&page=<{{page+getPage()}}>\n本月最热::{{PN_base()}}\/v.php?category=top&viewtype=basic&page=<{{page+getPage()}}>\n10分钟以上::{{PN_base()}}\/v.php?category=long&viewtype=basic&page=<{{page+getPage()}}>\n20分钟以上::{{PN_base()}}\/v.php?category=longer&viewtype=basic&page=<{{page+getPage()}}>\n本月收藏::{{PN_base()}}\/v.php?category=tf&viewtype=basic&page=<{{page+getPage()}}>\n最近加精::{{PN_base()}}\/v.php?category=rf&viewtype=basic&page=<{{page+getPage()}}>\n高清::{{PN_base()}}\/v.php?category=hd&viewtype=basic&page=<{{page+getPage()}}>\n每月最热::{{PN_base()}}\/v.php?category=top&m=-1&viewtype=basic&page=<{{page+getPage()}}>\n本月讨论::{{PN_base()}}\/v.php?category=md&viewtype=basic&page=<{{page+getPage()}}>\n收藏最多::{{PN_base()}}\/v.php?category=mf&viewtype=basic&page=<{{page+getPage()}}>","sourceComment":"\/\/疑似永久域名：http:\/\/91p676.com\n\/\/同类：\nhttps:\/\/a1019.9p58b.com\/index.php\nhttps:\/\/f1011.a2507app.com\/index.php\n作者：夜明空\n\/\/源社区：https:\/\/pc.sysbbs.com\n⚠️严禁分享、倒卖及任何违法行为！使用者自行承担风险与责任\n<\/声明>","sourceGroup":"视频,R18","sourceIcon":"http:\/\/img95.699pic.com\/xsj\/1r\/73\/9i.jpg","sourceName":"91PORN","sourceUrl":"https:\/\/418.sol148.com\/index.php","type":2,"variableComment":"❌ 请勿修改此处内容，请自行查看源注释"}]