🌞晴天融合4.7.30(完全版)

晴天融合4.0

晴天 (8653)2天前

注册地址:https://api.qingtian618.com


4.7.30

修复轻阅读登录问题,69书吧恢复服务器访问(暂时69下载限制)
4.7.23
69书吧本地网络访问+真人验证,如果看69书吧的书,请先在登录手动切换为本地访问模式(需要梯子),然后正常使用,中途可能需要过一到两次真人验证,视频教程看群消息
4.7.22
新增一个服务器,优化登录布局
4.7.20
新增懒人听书(VIP专属)
4.7.19
修复源阅目录获取错误的bug
4.7.18
支持卷名
4.7.16
新增番茄书荒广场(订阅源)点击导入订阅源
4.7.14
修复bug,新增番茄段评、章评回复评论
4.7.13
1.修复了可能会频繁打开段评界面的bug!
2.新增切换服务器不用重新登录账号!
3.修复更新书源后需要重新添加书架的问题
4.修复退出阅读重新进的话,得点图片刷新两遍才能打开段评界面!
5.对原来的书籍URL添加了适配!
6.修复源阅不能切换服务器的bug!
7.源阅新增番茄章评,正文右下角按钮进入
再次感谢@河鹅和.喵~的支持
4.7.12

修复源阅无法切换来源的bug,新增精简简介开关



二维码导入
{
    "bookSourceComment": "更新日志请点击登录,更新书源中查看\n\n兼容正式版阅读app",
    "bookSourceGroup": "晴天聚合",
    "bookSourceName": "🌞晴天融合4.7.30(完全版)",
    "bookSourceType": 0,
    "bookSourceUrl": "晴天融合4.0",
    "bookUrlPattern": "https?:\\\/\\\/(?:[a-zA-Z0-9-]+\\.)*qingtian618\\.com\\\/detail.*",
    "customOrder": 3,
    "enabled": true,
    "enabledCookieJar": true,
    "enabledExplore": true,
    "exploreUrl": "<js>\nfunction setArgument(key, value) {\n    var open_argument = source.getVariable();\n    open_argument = getArguments(open_argument, '') || {};\n    open_argument[key] = value;\n    var result = JSON.stringify(open_argument);\n    source.setVariable(result);\n    return result;\n}\n\nvar open_argument = source.getVariable();\nvar base_url = getArguments(open_argument, 'server') || '';\nvar ms = getArguments(open_argument, 'tone_id') || '';\nvar source_type = getArguments(open_argument, 'source_type') || '男频';\nvar tab = getArguments(open_argument, 'media') || '小说';\nvar sources = getArguments(open_argument, 'source') || '番茄';\n\n\nvar sdtoken;\ntry {\n    var loginInfoMap = source.getLoginInfoMap ? source.getLoginInfoMap() : {};\n    sdtoken = String(loginInfoMap['手动填写番茄token(可不填)'] || '');\n} catch (e) {\n    sdtoken = '';\n}\n\nvar rawCookie = getFanqieCookie() || sdtoken;\nvar match = rawCookie.match(\/sessionid=[^;]+\/);\nvar fqcookie = match ? match[0] : '';\nvar fqssionid = '';\nif (!fqcookie) {\n    java.toast('您还未登陆番茄账号,无法同步数据哦!');\n} else {\n    fqssionid = getSessionId(fqcookie)\n}\nvar fqsjurl = base_url + \"\/bookshelf?page={{page}}&ssionid=\" + fqssionid;\n\nvar groupDatas = [];\nvar infoData = [];\n\nfunction deviceType() {\n    try {\n        return !!java.androidId();\n    } catch (e) {\n        return false;\n    }\n}\n\nvar hasValidCookie = fqcookie.length > 0;\n\nif (hasValidCookie) {\n    function groupQuery() {\n        try {\n            var url = base_url + \"\/group_name?ssionid=\" + fqssionid;\n            var res = java.ajax(url);\n            var response = JSON.parse(res);\n\n            if (!(response && response.data)) {}\n\n            response.data.forEach(function(group) {\n                var keys = Object.keys(group);\n                if (keys.length > 0) {\n                    var key = keys[0];\n                    var value = group[key];\n                    if (value && value.length) {\n                        var option = {\n                            \"method\": \"POST\",\n                            \"body\": {\n                                \"book_ids\": value,\n                                \"page\": \"{{page}}\"\n                            }\n                        };\n                        groupDatas.push({\n                            title: key,\n                            url: base_url + \"\/bookshelf,\" + JSON.stringify(option),\n                            style: {\n                                layout_flexGrow: 1,\n                                layout_flexBasisPercent: 0.45\n                            }\n                        });\n                    }\n                }\n            });\n\n            if (groupDatas.length % 2 !== 0) {\n                groupDatas.push({\n                    title: \"--\",\n                    url: \"\",\n                    style: {\n                        layout_flexGrow: 1,\n                        layout_flexBasisPercent: 0.45\n                    }\n                });\n            }\n        } catch (e) {\n            java.longToast(\"分组获取失败: \" + e.message);\n        }\n    }\n\n    try {\n        java.longToast(\"正在加载分组数据...\");\n        var userUrl = base_url + \"\/fquser?ssionid=\" + fqssionid;\n        var userRes = java.ajax(userUrl);\n        var userData = JSON.parse(userRes);\n\n        var userName = (userData && userData.data && userData.data.name) ? userData.data.name : '未知用户';\n        infoData = [{\n            title: userName + \"个人中心\",\n            url: fqsjurl,\n            style: {\n                layout_flexGrow: 1,\n                layout_flexBasisPercent: 1\n            }\n        }];\n\n        groupQuery();\n    } catch (e) {\n        java.longToast(\"操作失败: \" + e.message);\n    }\n}\n\nvar style_list = [];\ntry {\n    var durl = `${base_url}\/discovestyle?source=${sources}&source_type=${source_type}&tab=${tab}`;\n    var res = java.ajax(durl);\n    var result = JSON.parse(res);\n    style_list = result.data || [];\n    if (result.msg) {\n        java.toast(result.msg);\n    }\n} catch (e) {\n    java.toast(\"发现样式获取失败\");\n}\n\nvar finalData = infoData.concat(groupDatas, style_list);\nJSON.stringify(finalData);\n<\/js>",
    "header": "{ \"User-Agent\":\"Mozilla\/5.0 (Linux; Android 6.0; Nexus 5 Build\/MRA58N) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/138.0.0.0 Mobile Safari\/537.36 Edg\/138.0.0.0\" }",
    "jsLib": "var host = [\n'https:\/\/api.qingtian618.com',\n'https:\/\/apicdn.qingtian618.com'\n\n];\n\nfunction getArguments(open_argument, key) {\n  try {\n    open_argument = JSON.parse(open_argument);\n  } catch (e) {\n    open_argument = {\n      media: \"小说\",\n      tone_id: \"默认音色\",\n      server: host[0],\n      source: \"全部\",\n      source_type: \"男频\",\n    };\n  }\n  if (key) {\n    return open_argument[key];\n  } else {\n    return open_argument;\n  }\n}\n\nfunction setArguments(key, value) {\n\tconst { source } = this;\n\tlet open_argument = source.getVariable();\n\topen_argument = getArguments(open_argument, '');\n\topen_argument[key] = value;\n\topen_argument = JSON.stringify(open_argument);\n\tsource.setVariable(open_argument);\n\treturn open_argument;\n}\n\nfunction decrypt(Text) {\n  return Text;\n}\n\nfunction getComments(content, bid, cid) {\n  const { java, cache, source } = this;\n  try {\n    const base_url = getArguments(source.getVariable(), \"server\");\n    const fqssionid = getArguments(source.getVariable(), \"fqssionid\") || \"\";\n    const apiUrl = `${base_url}\/para_idea?item_id=${cid}&ssionid=${fqssionid}`;\n    const comments = java.ajax(apiUrl);\n\n    const lines = content.split(\"\\n\");\n    const raw = JSON.parse(comments).data.data;\n\n    Object.keys(raw).forEach((x) => {\n      cache.putMemory(`fq-${bid}-${cid}-${x}-text`, lines[x]);\n      let plcolor = getArguments(source.getVariable(), \"plcolor\");\n      if (!plcolor) {\n        plcolor = \"#000000\";\n      }\n      lines[x] += `<img src=\"${this.createSvg(\n        raw[x].count,\n        plcolor,\n        bid,\n        cid,\n        x\n      )}\">`;\n    });\n\n    return lines.join(\"\\n\");\n  } catch (e) {\n    return content;\n  }\n}\n\nfunction createSvg(number, color, bid, cid, para) {\n  const displayText = number > 99 ? \"99+\" : number;\n  const date = String(Date.now()).match(\/(\\d{6}$)\/)[1];\n  this.cache.putMemory(`fq-${bid}-${cid}-${para}`, date);\n  const svg = `<svg width=\"1000\" height=\"800\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n        <rect x=\"25\" y=\"25\" width=\"950\" height=\"750\" rx=\"250\" ry=\"250\" fill=\"none\" stroke=\"${color}\" stroke-width=\"25\"\/>\n        <text x=\"510\" y=\"650\" font-family=\"Arial, sans-serif\" text-anchor=\"middle\" dominant-baseline=\"middle\" font-size=\"30\" fill=\"${color}\">刷新图片查看段评<\/text>\n        <text x=\"510\" y=\"565\" font-family=\"Arial, sans-serif\" text-anchor=\"middle\" dominant-baseline=\"middle\" font-size=\"425\" fill=\"${color}\">${displayText}<\/text>\n    <\/svg>`;\n\n  const encodedSvg = this.java.base64Encode(svg);\n  return `data:image\/svg+xml;base64,${encodedSvg},{\"js\":\"showCmt('${bid}','${cid}','${para}','${date}')\"}`;\n}\n\nfunction showCmt(bid, cid, para, date) {\n  const { java, cache, source } = this;\n  const mname = `fq-${bid}-${cid}-${para}`;\n  const load = String(cache.getFromMemory(mname));\n\n  if (load == date) {\n    cache.deleteMemory(mname);\n    return;\n  }\n  cache.deleteMemory(mname);\n  const base_url = getArguments(source.getVariable(), \"server\");\n  const fqssionid = getArguments(source.getVariable(), \"fqssionid\") || \"\";;\n  const apiUrl = `${base_url}\/get_para_review?item_id=${cid}&book_id=${bid}&para=${para}&ssionid=${fqssionid}`;\n  const title = cache.getFromMemory(mname + \"-text\") || \"段评内容\";\n  if (\n    !cache.getFromMemory(\"fq.bopenat\") ||\n    Date.now() - parseInt(cache.getFromMemory(\"fq.bopenat\")) > 400\n  ) {\n    cache.putMemory(\"fq.bopenat\", String(Date.now()));\n    java.startBrowser(apiUrl, title);\n  }\n}\n\nfunction cleanHTML(html) {\n  let result = html\n    .replace(\/<header[^>]*>[\\s\\S]*?<\\\/header>\/gi, \"\")\n    .replace(\/<div class=\"tt-title\"[^>]*>[\\s\\S]*?<\\\/div>\/gi, \"\")\n    .replace(\/<(?!\\\/?p\\b|\\\/?img\\b)[^>]+>\/gi, \"\");\n  result = result.replace(\/<\\\/?p[^>]*>\/g, \"\\n\");\n  return result.replace(\/\\n+\/g, \"\\n\").trim();\n}\nvar javaImport = new JavaImporter();\njavaImport.importClass(\n  Packages.android.util.Base64,\n  Packages.java.lang.String,\n  Packages.java.net.URL,\n  Packages.okhttp3.HttpUrl\n);\nwith (javaImport) {\n  function btoa(data) {\n    return Base64.encodeToString(String(data).getBytes(\"UTF-8\"), 2);\n  }\n\n  function getSubDomain(url) {\n    let baseUrl = getBaseUrl(url);\n    if (!baseUrl) {\n      return url;\n    }\n    try {\n      let mURL = URL(baseUrl);\n      let host = mURL.host;\n      if (isIPAddress(host)) return host;\n      return HttpUrl.parse(baseUrl).topPrivateDomain() || host;\n    } catch (e) {\n      this.java.log(e);\n      return baseUrl;\n    }\n  }\n\n  function getDomain(url) {\n    let baseUrl = getBaseUrl(url);\n    if (!baseUrl) {\n      return url;\n    }\n    try {\n      return URL(baseUrl).host;\n    } catch (e) {\n      return baseUrl;\n    }\n  }\n  \/**\n   * 移除cookie\n   *\/\n  function removeCookie(url) {\n    const { cookie } = this;\n    cookie.removeCookie(url);\n    let domains = [getDomain(url), getSubDomain(url)];\n    domains.forEach((domain) => {\n      cookie.removeCookie(domain);\n    });\n  }\n}\n\nfunction getBaseUrl(url) {\n  if (!url) {\n    return null;\n  }\n  url = String(url);\n  if (url.match(\/https?:\\\/\\\/\/i)) {\n    var index = url.indexOf(\"\/\", 9);\n    return index == -1 ? url : url.substring(0, index);\n  }\n  return null;\n}\n\nfunction isIPv4Address(ip) {\n  ip = String(ip);\n  let parts = ip.split(\".\");\n  if (parts.length !== 4) return false;\n\n  for (let part of parts) {\n    if (!\/^\\d+$\/.test(part)) return false; \/\/ 必须是数字\n    if (part.length > 1 && part[0] === \"0\") return false; \/\/ 禁止前导零\n    let num = parseInt(part, 10);\n    if (num < 0 || num > 255) return false; \/\/ 范围检查\n  }\n  return true;\n}\n\nfunction isIPv6Address(ip) {\n  ip = String(ip);\n  \/\/ 处理双冒号(最多出现一次)\n  if (ip.includes(\":::\")) return false;\n  let doubleColonCount = (ip.match(\/::\/g) || []).length;\n  if (doubleColonCount > 1) return false;\n\n  \/\/ 分割成组\n  let groups = ip.split(\":\");\n  let validGroupCount = 8;\n  let actualGroupCount = groups.filter((g) => g !== \"\").length;\n\n  \/\/ 验证组数\n  if (doubleColonCount === 1) {\n    if (actualGroupCount > validGroupCount - 1) return false;\n  } else {\n    if (groups.length !== validGroupCount) return false;\n  }\n\n  \/\/ 验证每组内容\n  for (let group of groups) {\n    if (group === \"\") continue; \/\/ 跳过空组(双冒号部分)\n    if (!\/^[0-9a-fA-F]{1,4}$\/.test(group)) return false; \/\/ 1-4位十六进制\n  }\n  return true;\n}\n\nfunction isIPAddress(input) {\n  return isIPv4Address(input) || isIPv6Address(input);\n}\n\nfunction getSessionId(cookieString) {\n    const match = cookieString.match(\/sessionid=([^;]+)\/);\n    return match ? match[1] : null;\n}\n\nfunction getKey(key) {\n  let parts = key.split(\";\");\n  for (let part of parts) {\n    if (part.includes(\"qttoken\")) {\n      return part.split(\"=\")[1];\n    }\n  }\n  return \"\";\n}\n\nfunction getFanqieCookie() {\n\t   const { cookie } = this;\n    try {\n        return String(cookie.getCookie('fanqienovel.com') || java.getCookie('fanqienovel.com') || '');\n    } catch (e) {\n        return '';\n    }\n}",
    "lastUpdateTime": "1753841385299",
    "loginUi": "[{\"name\": \"邮箱\", \"type\": \"text\"},\n        {\"name\": \"密码\", \"type\": \"password\"},\n        {\n            \"name\": \"♥登录书源\",\n            \"type\": \"button\",\n            \"action\": \"login(true)\",\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            \"name\": \"🍅番茄登录\",\n            \"type\": \"button\",\n            \"action\": \"fq_login()\",\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        },\n        {\n            \"name\": \"🏝用户后台\",\n            \"type\": \"button\",\n            \"action\": \"loginqt()\",\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        },\n        {\n            \"name\": \" 🔚 退出登录\",\n            \"type\": \"button\",\n            \"action\": \"logout()\",\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            \"name\": \"🔮 检测登录\",\n            \"type\": \"button\",\n            \"action\": \"checkStatus()\",\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n\n        }, {\n            \"name\": \" 🗑 清除设备\",\n            \"type\": \"button\",\n            \"action\": \"clearDevice()\",\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n\n        }, {\n            \"name\": \"📑更少简介\",\n            \"type\": \"button\",\n            \"action\": \"set_info()\",\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            \"name\": \"📝段评开关\",\n            \"type\": \"button\",\n            \"action\": \"paracomment('fqpara')\",\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            \"name\": \"👨‍🦱男频发现\",\n            \"type\": \"button\",\n            \"action\": \"set_source_type('男频')\",\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            \"name\": \"👩‍🦰女频发现\",\n            \"type\": \"button\",\n            \"action\": \"set_source_type('女频')\",\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            \"name\": \"☕打赏享福利\",\n            \"type\": \"button\",\n            \"action\": \"vip()\",\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            \"name\": \"❇️ 更新书源\",\n            \"type\": \"button\",\n            \"action\": \"renderVersionPage()\",\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        },{\n            \"name\": \"🗂当前模式\",\n            \"type\": \"button\",\n            \"action\": \"get_media()\",\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 1\n            }\n        }, {\n            \"name\": \"📖小说模式\",\n            \"type\": \"button\",\n            \"action\": \"set_media('小说')\",\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            \"name\": \"🔊听书模式\",\n            \"type\": \"button\",\n            \"action\": \"set_media('听书')\",\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            \"name\": \"🏞漫画模式\",\n            \"type\": \"button\",\n            \"action\": \"set_media('漫画')\",\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            \"name\": \"🖲短剧模式\",\n            \"type\": \"button\",\n            \"action\": \"set_media('短剧')\",\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            \"name\": \"🎚切换服务器\",\n            \"type\": \"button\",\n            \"action\": \"set_server(server)\",\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            \"name\": \"🖱当前服务器 \",\n            \"type\": \"button\",\n            \"action\": \"get_server()\",\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            \"name\": \"♻️检测服务器\",\n            \"type\": \"button\",\n            \"action\": \"api()\",\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            \"name\": \"⚕️本地\/服务器 \",\n            \"type\": \"button\",\n            \"action\": \"get_proxy()\",\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            \"name\": \"↓↓下方可切换来源用于搜索\/发现页↓↓\",\n            \"type\": \"button\",\n            \"action\": \"get_media()\",\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 1\n            }\n        }, {\n            \"name\": \"全部\",\n            \"type\": \"button\",\n            \"action\": \"set_source('全部')\",\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            'action': \"set_source('番茄')\",\n            'name': '番茄',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            'action': \"set_source('69书吧')\",\n            'name': '69书吧',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            'action': \"set_source('七猫')\",\n            'name': '七猫',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            'action': \"set_source('百度')\",\n            'name': '百度',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            'action': \"set_source('起点')\",\n            'name': '起点(第三方)',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            'action': \"set_source('得间')\",\n            'name': '得间',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            'action': \"set_source('塔读')\",\n            'name': '塔读',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            'action': \"set_source('书旗')\",\n            'name': '书旗',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            'action': \"set_source('QQ')\",\n            'name': 'QQ',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            'action': \"set_source('猫眼')\",\n            'name': '猫眼',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            'action': \"set_source('搜书神器')\",\n            'name': '搜书神器',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            'action': \"set_source('得奇')\",\n            'name': '得奇',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            'action': \"set_source('伪69')\",\n            'name': '伪69',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            'action': \"set_source('爱下电子书')\",\n            'name': '爱下电子书',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            'action': \"set_source('小米')\",\n            'name': '小米',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            'action': \"set_source('星星小说')\",\n            'name': '星星小说',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            'action': \"set_source('笔趣阁22')\",\n            'name': '笔趣阁22',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            'action': \"set_source('顶点')\",\n            'name': '顶点',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            'action': \"set_source('幻梦轻小说')\",\n            'name': '幻梦轻小说',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            'action': \"set_source('江湖')\",\n            'name': '江湖',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            'action': \"set_source('歪瑞古德')\",\n            'name': '歪瑞古德漫画',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            'action': \"set_source('河马')\",\n            'name': '河马短剧',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }}, {\n            'action': \"set_source('知乎')\",\n            'name': '知乎',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            'action': \"set_source('vip')\",\n            'name': '下方为VIP专属书源(点击此处搜所有vip)',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 1\n            }\n        }, {\n            'action': \"set_source('喜马拉雅')\",\n            'name': '喜马拉雅',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            'action': \"set_source('懒人听书')\",\n            'name': '懒人听书',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            'action': \"set_source('svip')\",\n            'name': '下方为SVIP专属书源(点击此处搜所有svip)',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 1\n            }\n        }, {\n            'action': \"set_source('全本小说')\",\n            'name': '全本小说',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            'action': \"set_source('全本免费小说')\",\n            'name': '全本免费小说',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            'action': \"set_source('神书网')\",\n            'name': '神书网',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            'action': \"set_source('读全本')\",\n            'name': '读全本',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            'action': \"set_source('八一中文网')\",\n            'name': '八一中文网',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            'action': \"set_source('斋书苑')\",\n            'name': '斋书苑',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            'action': \"set_source('101看书')\",\n            'name': '101看书',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            'action': \"set_source('QQ阅读')\",\n            'name': 'QQ阅读',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            'action': \"set_source('晋江文学')\",\n            'name': '晋江文学',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            'action': \"set_source('万相书城')\",\n            'name': '万相书城',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            'action': \"set_source('纵横中文网')\",\n            'name': '纵横中文网',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            'action': \"set_source('轻小说文库')\",\n            'name': '轻小说文库',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            'action': \"set_source('轻之文库')\",\n            'name': '轻之文库',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            'action': \"set_source('中华典藏')\",\n            'name': '中华典藏',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            'action': \"set_source('福利小说')\",\n            'name': '福利小说',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            'action': \"set_source('福利漫画')\",\n            'name': '福利漫画',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            'action': \"set_source('毒舌影视')\",\n            'name': '毒舌影视',\n            'type': 'button',\n            \"style\": {\n                \"layout_flexGrow\": 1,\n                \"layout_flexBasisPercent\": 0.4\n            }\n        }, {\n            \"name\": \"自定义搜索源(多个用英文,分割)\",\n            \"type\": \"text\"\n        }, {\n            \"name\": \"听书Ai音色填写后点击右上角✔\",\n            \"type\": \"text\"\n        }, {\n            \"name\": \"自定义服务器(可不填)\",\n            \"type\": \"text\"\n        }, {\n            \"name\": \"自定义评论颜色(可不填)\",\n            \"type\": \"text\"\n        }, {\n            \"name\": \"手动填写番茄token(可不填)\",\n            \"type\": \"text\"\n        }]\n",
    "loginUrl": "\/\/ 当前书源版本号,切勿修改,否则影响更新的识别\nconst localVersion = '4.7.30';\n\n\nfunction login(flag) {\n\tif (flag == undefined) {\n\t\tresult = JSON.parse(source.getLoginInfo())\n\t} else {\n\t\tjava.longToast(\"\\n\\n💞正在登录中...\")\n\t\tputLoginInfo(JSON.stringify(result))\n\t}\n\tlet base_url = getArgument('server')\n\tlet zdyserver = String(result['自定义服务器(可不填)']);\n\tif (zdyserver.includes('http')) {\n\t\tsetArgument('server', zdyserver);\n\t\tif (getKey(String(cookie.getCookie(base_url)))){\n\t\t\tlet cookies=cookie.getCookie(base_url)\n\t\t\tremoveCookie(base_url)\n\t\t\tcookie.setCookie(zdyserver,cookies)\n\t\t}\n\t\tjava.toast(`\\n\\n当前服务器为自定义服务器\\n${zdyserver}\\n\\n切换服务器请先清空服务器地址中的数据`);\n\t}\n\tlet zdytone_id = String(result['听书Ai音色填写后点击右上角✔'] || '');\n\tif (zdytone_id) {\n\t\tsetArgument('tone_id', zdytone_id);\n\t} else {\n\t\tsetArgument('tone_id', '默认音色');\n\t}\n\tlet plcolor = String(result['自定义评论颜色(可不填)'] || '#000000');\n\tif (plcolor) {\n\t\tsetArgument('plcolor', plcolor);\n\t} else {\n\t\tsetArgument('plcolor', '#000000');\n\t}\n\tlet zdysources = String(result['自定义搜索源(多个用英文,分割)'] || '');\n\tif (zdysources) {\n\t\tsetArgument('source', zdysources);\n\t};\n\tbase_url = getArgument('server')\n\tlet register_email = String(result['邮箱'])\n\tlet password = String(result['密码'])\n\tlet key = String(result['密钥']||'')\n\t\n\t\/\/java.log(cookie.getCookie(base_url))\n\tif ((register_email && password || key)&& !String(getKey(String(cookie.getCookie(base_url))))) {\n\t\tremoveCookie(base_url)\n\t\tlet deviceKey = '';\t\t\n\t  try {\n\t\t\t\tdeviceKey = java.deviceID();\n\t\t\t} catch (e) {\n\t\t\t\tdeviceKey = java.androidId();\n\t\t};\n\tlet deviceId = java.digestHex(deviceKey, \"SHA256\")\n\t\t  if (register_email && password){\n\t\t\tlet options = JSON.stringify({\n\t\t\t\tmethod: 'POST',\n\t\t\t\theaders: {\n\t\t\t\t\t'Content-Type': 'application\/json'\n\t\t\t\t},\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\tregister_email: result['邮箱'],\n\t\t\t\t\tpassword: result['密码']\n\t\t\t\t})\n\t\t\t})\n\t\t\ttry {\n\t\t\t\tlet data = JSON.parse(java.ajax(`${base_url}\/login_api,${options}`))\n\t\t\t\tif (data.code == 0) {\n\t\t\t\t\tjava.toast(\"\\n\\n✅️登录成功\")\n\t\t\t\t\tcookie.setCookie(base_url, `qttoken=${data.key};deviceId=${deviceId}`)\n\t\t\t\t\tresult['密钥']=data.key\n\t\t\t\t\tputLoginInfo(JSON.stringify(result))\n\t\t\t\t} else {\n\t\t\t\t\tjava.toast('\\n\\n💔'+data.msg || \"登录失败,请重试!\")\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\tjava.toast(\"\\n\\n💔登录失败,请重试!\\n\" + e.message)\n\t\t\t}\n\t\t} else {\n\t\t\tcookie.setCookie(base_url, `qttoken=${key};deviceId=${deviceId}`)\n\t\t\tlet res=java.ajax(`${base_url}\/user_api,{\"method\":\"POST\",\"headers\":{\"cookie\":\"${cookie.getCookie(base_url)}\"}}`)\t\t\t\n\t\t\ttry {\n\t\t\t\tres=JSON.parse(res)\n\t\t\t\tif (res.id!=undefined) {\n\t\t\t\t\tjava.toast('\\n\\n密钥登录成功')\n\t\t\t\t\tresult['邮箱'] = res.email\n\t\t\t\t\tputLoginInfo(JSON.stringify(result))\n\t\t\t\t} else {\n\t\t\t\t\tthrow new Error()\n\t\t\t\t}\n\t\t\t} catch(e) {\n\t\t\t\tjava.log(e)\n\t\t\t\tjava.toast(\"\\n\\n💔登录失败\")\n\t\t\t}\n\t\t}\n\t} else if (flag&&String(getKey(String(cookie.getCookie(base_url))))) {\n\t\tjava.toast(\"\\n\\n当前✅️已登录,请🚫退出登录后重新登录\");\n\t\t\/\/checkStatus();\n\t} else if (flag) {\n\t\tjava.toast(\"\\n\\n⛔️请先填写邮箱和密码\");\n\t\t}\n}\n\nfunction checkStatus() {\n\tjava.longToast('\\n\\n♻️检测中...');\n\tlet base_url = getArgument('server')\n\tlet res=java.ajax(`${base_url}\/user_api,{\"method\":\"POST\",\"headers\":{\"cookie\":\"${cookie.getCookie(base_url)}\"}}`)\t\n\ttry {\n\t\t\t\tres=JSON.parse(res)\n\t\t\t\tif (res.id!=undefined) {\n\t\t\t\t\tresult['邮箱'] = res.email\n\t\t\t\t\tputLoginInfo(JSON.stringify(result))\n\t\t\t\t\tlet devices\n\t\t\t\t\ttry {\n\t\t\t\t\t\tdevices = JSON.parse(res.device).length;\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tdevices = res.device ? 1 : 0;\n\t\t\t\t\t}\n\t\t\t\t\tlet isVip;\n\t\t\t\t\tif (res.is_vip==1) {\n\t\t\t\t\t\tisVip = 'VIP';\n\t\t\t\t\t} else if (res.is_vip>=2) {\n\t\t\t\t\t\tisVip = 'SVIP';\n\t\t\t\t\t} else {\n\t\t\t\t\t\tisVip = '普通会员';\n\t\t\t\t\t}\n\t\t\t\t\ttips= `\n┏┅┅┅┅┅┅┱┄┄┄┄┄┄┄┄┄┄┐\n ✉️邮箱    ${res.email.replace(\/(.{3}).*?@\/,\"$1***@\").padEnd(20,\"\\t\")}\n┣┅┅┅┅┅┅╉┄┄┄┄┄┄┄┄┄┄┤\n 🔑密钥    ${(`${res.user_key.substring(0,4)}***${res.user_key.slice(-4)}`).padEnd(20,\"\\t\")}\n┣┅┅┅┅┅┅╉┄┄┄┄┄┄┄┄┄┄┤\n 📅注册时间  ${java.timeFormat(res.register_time*1000).padEnd(20,\"\\t\")}\n┣┅┅┅┅┅┅╉┄┄┄┄┄┄┄┄┄┄┤\n 🗒️今日阅读  ${(java.timeFormat(new Date()).slice(0,10)==java.timeFormat(res.last_read_time * 1000).slice(0,10)?res.day_read_count:0).toString().padEnd(20,\"\\t\")}\n┣┅┅┅┅┅┅╉┄┄┄┄┄┄┄┄┄┄┤\n 📚累计阅读  ${res.all_read_count.toString().padEnd(20,\"\\t\")}\n┣┅┅┅┅┅┅╉┄┄┄┄┄┄┄┄┄┄┤\n 🕓最后阅读  ${(res.last_read_time != 0?java.timeFormat(res.last_read_time * 1000):'未阅读').padEnd(20,\"\\t\")}\n┣┅┅┅┅┅┅╉┄┄┄┄┄┄┄┄┄┄┤\n 📱关联设备  ${devices.toString().padEnd(20,\"\\t\")}\n┣┅┅┅┅┅┅╉┄┄┄┄┄┄┄┄┄┄┤\n 👑会员状态  ${isVip.padEnd(20,\"\\t\")}\n┣┅┅┅┅┅┅╉┄┄┄┄┄┄┄┄┄┄┤\n 🚫封禁状态  ${res.is_banned?'已封禁':'正常 '}       \n┗┅┅┅┅┅┅┹┄┄┄┄┄┄┄┄┄┄┘\n`\n\t\t\t\t\tjava.log(tips)\n\t\t\t\t\tjava.longToast(tips)\n\t\t\t\t} else {\n\t\t\t\t\tthrow new Error(res.msg)\n\t\t\t\t}\n\t\t\t} catch(e) {\n\t\t\t\t\/\/java.log(e)\n\t\t\t\tjava.toast(\"\\n检测登录失败\\n\"+e.message)\n\t\t\t}\n}\n\nfunction clearDevice() {\n\tlet base_url = getArgument('server')\n  let res=java.ajax(`${base_url}\/clear,{\"method\":\"POST\",\"headers\":{\"cookie\":\"${cookie.getCookie(base_url)}\"}}`)\n\tjava.toast(res.code === 0 ? \"\\n\\n📴设备清除成功\" : res.msg)\n\tPackages.java.lang.Thread.sleep(500)\n\tcheckStatus()\n}\n\/\/ 保存登录UI信息\nfunction putLoginInfo(info) {\n\ttry {\n\t\tlet key = java.androidId()\n\t\tlet encodeStr = Packages.android.util.Base64.encodeToString(java.createSymmetricCrypto(\"AES\", key).encrypt(info), 2)\n\t\tcache.put(`userInfo_${source.getKey()}`, encodeStr)\n\t\treturn true\n\t} catch (e) {\n\t\tjava.log(e)\n\t\treturn source.putLoginInfo(info)\n\t}\n}\n\n\/\/ 填写密钥\nfunction loginqt() {\n\tjava.startBrowserAwait(getArgument('server') + '\/login', '登录晴天小说书源');\n}\n\n\/\/登录番茄\nfunction fq_login() {\n\ttry {\n\t\tjava.startBrowserAwait(\"https:\/\/fanqienovel.com\/\", \"登录\")\n\t} catch (e) {\n\t\tjava.toast(e)\n\t}\n\ttry {\n\t\tcookie.removeCookie(\"snssdk.com\")\n\t} catch (e) {}\n\tvar cookies = cookie.getCookie(\"fanqienovel.com\")\n\tif (!cookies || cookies == \"\") {\n\t\tjava.toast(\"登录失败!\")\n\t\treturn false\n\t}\n\tjava.toast(\"登录成功!\")\n\treturn true\n}\n\n\/\/退出登录\nfunction logout() {\n\tcookie.removeCookie(\"fanqienovel.com\");\n\tcookie.removeCookie(\"snssdk.com\");\n\tcookie.removeCookie(\"69shuba.com\");\n\t\/*\n\tlet servers = host\n\tfor (let server of servers) {\n\t\tremoveCookie(server);\n\t}\n\t*\/\n\tremoveCookie(getArgument('server'))\n\tjava.toast(\"退出登录成功\");\n}\n\n\/\/获取参数\nfunction getArgument(key) {\n\tlet open_argument = source.getVariable();\n\topen_argument = getArguments(open_argument, '');\n\treturn open_argument[key];\n}\n\n\/\/设置参数\nfunction setArgument(key, value) {\n\tlet open_argument = source.getVariable();\n\topen_argument = getArguments(open_argument, '');\n\topen_argument[key] = value;\n\topen_argument = JSON.stringify(open_argument);\n\tsource.setVariable(open_argument);\n\treturn open_argument;\n}\n\n\/\/ 设置本地or云端访问\nfunction get_proxy() {\n\tlet proxy = getArgument('proxy');\n\tif (proxy=='本地') {\n\t\tsetArgument('proxy','云端');\n\t\tjava.longToast('\\n所有数据采用\\n\\n服务器网络访问\\n\\n如果发现用不了,请切换本地网络访问,如69书吧');\n\t\t\t\t} else {\n\t\t\tsetArgument('proxy','本地');\n\t\t\tjava.longToast('\\n所有数据采用\\n\\n本地网络访问\\n\\n如果发现用不了,请开启网络代理,如69书吧');\n\t\t\t\t\t\t}\n\t}\n\n\n\/\/设置男女频\nfunction set_source_type(source_type) {\n\tsetArgument(\"source_type\", source_type);\n\tjava.toast(\"\\n发现页已设置为:\" + source_type);\n\t}\n\t\n\/\/首页\nfunction api() {\n\tjava.startBrowserAwait('http:\/\/vip.qingtian618.com', \"首页\");\n}\n\n\/\/打赏\nfunction vip() {\n\tjava.startBrowserAwait(getArgument('server') + '\/coffee', \"喝咖啡\");\n}\n\nvar server = getArgument('server');\n\n\/\/设置搜索媒体\nfunction set_media(media) {\n    const mediaConfig = {\n        '喜马拉雅': ['听书'],\n        '番茄': '*',\n        '福利小说':['小说'],\n        '如漫画':['漫画'],\n        '包子漫画':['漫画'],\n        '九妖漫画':['漫画'],\n        '绅士漫画':['漫画'],\n        '福利漫画':['漫画'],\n        '六月听书':['听书'],\n        '海洋听书':['听书'],\n        '七猫': ['小说', '听书'],\n        '河马': ['短剧'],\n        '歪瑞古德': ['漫画'],\n        '毒舌影视':['短剧'],\n        '全部': '*', \/\/ 允许所有模式\n        '默认': ['小说']\n    };\n    \t\n\tconst source = getArgument('source');\n\tconst allowedModes = mediaConfig[source] || mediaConfig['默认'];\n\tlet targetMedia = mediaConfig['默认'][0]; \n\tlet isAllowed = false;\n\t\n\tif (allowedModes === '*' || allowedModes.includes(media)) {\n\t\ttargetMedia = media;\n\t\tisAllowed = true;\n\t} else if (Array.isArray(allowedModes)) {\n\t\ttargetMedia = allowedModes[0]; \n\t}\n\n\tconst message = isAllowed ?\n\t\t`\\n\\n已切换至:${targetMedia}\\n请重新搜索书籍!` :\n\t\t`\\n\\n目前${source}:不支持【${media}】模式!\\n已自动切换至:${targetMedia}`;\n\n\tsetArgument('media', targetMedia);\n\tjava.toast(message);\n}\n\n\/\/获取搜索媒体\nfunction get_media() {\n\tlet media = getArgument('media');\n\tlet source = getArgument('source');\n\tif (media == '') {\n\t\tmedia = '全部';\n\t}\n\tjava.toast(`\\n\\n当前使用源:${source}-${media}`);\n\n}\n\n\/\/获取服务器\nfunction get_server() {\n\tvar server = getArgument('server');\n\tvar tishi = '\\n\\n当前服务器:' + server\n\tjava.toast(tishi);\n\treturn server\n}\n\n\n\/\/设置服务器\nfunction set_server() {\n\tputLoginInfo(JSON.stringify(result))\n\tlet zdyserver;\n\tlet base_url = getArgument('server')\n\ttry {\n\t\tzdyserver = String(result['自定义服务器(可不填)']);\n\t\tif (zdyserver.includes('http')) {\n\t\t\tsetArgument('server', zdyserver);\n\t\t\tif (getKey(String(cookie.getCookie(base_url)))){\n\t\t\t\tlet cookies=cookie.getCookie(base_url)\n\t\t\t\tremoveCookie(base_url)\n\t\t\t\tcookie.setCookie(zdyserver,cookies)\n\t\t\t}\n\t\t\tjava.toast(`\\n\\n当前服务器为自定义服务器\\n${zdyserver}\\n\\n切换服务器请先清空服务器地址中的数据`);\n\t\t} else {\n\t\t\tzdyserver = '';\n\t\t}\n\t} catch (error) {\n\t\tzdyserver = '';\n\t}\n\tif (!zdyserver) {\n\t\tconst servers = host\n\t\tconst currentServer = getArgument('server') || '';\n\t\tconst currentIndex = servers.indexOf(currentServer);\n\n\t\tconst nextIndex = currentIndex >= 0 ? (currentIndex + 1) % servers.length : 0;\n\t\tconst nextServer = servers[nextIndex];\n\n\t\tsetArgument('server', nextServer);\n\t\tif (getKey(String(cookie.getCookie(currentServer)))){\n\t\t\tlet cookies=cookie.getCookie(currentServer)\n\t\t\tremoveCookie(currentServer)\n\t\t\tcookie.setCookie(nextServer,cookies)\n\t\t}\n\t\tjava.longToast(`\\n\\n当前服务器${nextIndex+1}:${nextServer}`);\n\t}\n}\n\n\/\/获取音色\nvar tone_id = getArgument('tone_id');\n\nfunction get_tone_id(arg) {\n\tvar datadist = {\n\t\t\"0\": \"默认音色\",\n\t\t\"-1\": \"阅读模式\",\n\t\t\"-2\": \"漫画模式\",\n\t\t\"51\": \"多人发音\",\n\t\t\"1\": \"甜美少女\",\n\t\t\"2\": \"清亮青叔\",\n\t\t\"5\": \"开朗青年\",\n\t\t\"6\": \"温柔淑女\",\n\t\t\"4\": \"成熟大叔\",\n\t\t\"74\": \"大叔升级\",\n\t\t\"30\": \"优雅御姐\"\n\t};\n\tvar tone_id = datadist[arg] || arg;\n\tvar tishi = '\\n\\n当前音色:' + tone_id;\n\tjava.toast(tishi);\n}\n\n\/\/设置音色\nfunction set_tone_id(mode, name) {\n\tputLoginInfo(JSON.stringify(result))\n\tlet zdytone_id;\n\ttry {\n\t\tzdytone_id = String(result['其他音色填写后点击右上角✔']);\n\t\tif (zdytone_id) {\n\t\t\tsetArgument('tone_id', zdytone_id);\n\t\t\tjava.toast(`\\n\\n当前音色为自定义音色\\n${zdytone_id}\\n\\n切换音色请先清空音色输入框中的数据`);\n\t\t} else {\n\t\t\tzdytone_id = '';\n\t\t}\n\t} catch (error) {\n\t\tzdytone_id = '';\n\t}\n\tif (!zdytone_id) {\n\t\tlet toast = \"\\n\\n已切换至:\" + name + '\\n\\n切换后需要刷新详情页';\n\t\tsetArgument('tone_id', mode);\n\t\tjava.toast(toast);\n\t}\n}\n\n\/\/设置来源\nfunction set_source(sources) {\n\tlet zdysources = String(result['自定义搜索源(多个用英文,分割)']||'');\n\tif (zdysources.length>1 && zdysources!='undefined') {\n\t\tjava.toast('\\n\\n请先清空自定义源再设置');\n\t} else {\n\t\tsetArgument('source', sources);\n\t\tset_media('小说');\n\t\tjava.toast(`\\n\\n当前来源已切换为:\\n${sources}\\n\\n切换后请重新搜索`);\n\t}\n}\n\n\/\/ 设置简介\nfunction set_info() {\n\tvar info = getArgument('info');\n\tif (info == 'on' ) {\n\t\tsetArgument('info','off');\n\t\tjava.toast('\\n\\n已恢复详情页详细简介');\n\t} else {\n\t\tsetArgument('info','on');\n\t\tjava.toast('\\n\\n已精简详情页简介');\n\t}\n}\n\t\n\/\/ 番茄段评\nfunction paracomment(a) {\n\tlet status = cache.get(a);\n\tif (status == \"on\") {\n\t\tcache.put(a, \"off\");\n\t\tjava.toast(\"\\n段评已关闭\");\n\t} else {\n\t\tcache.put(a, \"on\");\n\t\tjava.longToast(\"段评已开启\\n\\n长按刷新段后面的图片即可\\n\\n如果图片不显示,刷新无反应\\n请更新测试版阅读app\");\n\t}\n}\n\n\/\/ 书源更新\nfunction renderVersionPage() {\n\tlet yd = '';\n  let html = `\n<!DOCTYPE html>\n<html lang=\"zh-CN\">\n<head>\n  <meta charset=\"UTF-8\" \/>\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" \/>\n  <title>书源更新<\/title>\n  <style>\n    body {\n      margin: 0;\n      padding: 1em;\n      font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;\n      background: linear-gradient(135deg, #e0c3fc 0%, #8ec5fc 100%);\n      display: flex;\n      justify-content: center;\n      align-items: center;\n      min-height: 100vh;\n      color: #333;\n    }\n\n    .container {\n      width: 100%;\n      max-width: 480px;\n      background: rgba(255, 255, 255, 0.85);\n      backdrop-filter: blur(10px);\n      border-radius: 16px;\n      padding: 1em;\n      box-shadow: 0 8px 30px rgba(0, 0, 0, 0.1);\n      animation: fadeIn 0.5s ease-in-out;\n      display: none; \n          }\n\n    @keyframes fadeIn {\n      from { opacity: 0; transform: translateY(10px); }\n      to { opacity: 1; transform: translateY(0); }\n    }\n\n    h1 {\n      text-align: center;\n      font-size: 1.6em;\n      margin-bottom: 1em;\n      color: #333;\n    }\n\n    .version-info, .status {\n      text-align: center;\n      margin-bottom: 1em;\n      font-weight: 500;\n    }\n\n    .status {\n      color: #d63384;\n      font-size: 0.9em;\n    }\n\n    .button-group {\n      display: flex;\n      flex-direction: column;\n      gap: 0.75em;\n      margin-bottom: 1.5em;\n    }\n\n    .button {\n      display: block;\n      width: 90%;\n      padding: 0.85em;\n      text-align: center;\n      font-size: 1em;\n      border: none;\n      border-radius: 8px;\n      text-decoration: none;\n      background: linear-gradient(135deg, #42e695 0%, #3bb2b8 100%);\n      color: white;\n      font-weight: bold;\n      transition: all 0.25s ease;\n      box-shadow: 0 4px 14px rgba(0, 0, 0, 0.15);\n    }\n\n    .button:hover {\n      transform: translateY(-2px);\n      box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2);\n    }\n\n    .logs {\n      background: #ffffffcc;\n      padding: 1em;\n      border-radius: 8px;\n      border: 1px solid #ddd;\n      box-shadow: inset 0 1px 3px rgba(0,0,0,0.05);\n    }\n\n    .logs h2 {\n      font-size: 1.2em;\n      margin-bottom: 0.8em;\n      border-bottom: 1px solid #ccc;\n      padding-bottom: 0.3em;\n      color: #222;\n    }\n\n    .log-item {\n      margin-bottom: 0.7em;\n      line-height: 1.5;\n    }\n\n    .log-item-date {\n      font-weight: bold;\n      color: #3b3b3b;\n    }\n\n    .log-item-content {\n      margin-left: 1em;\n      color: #555;\n    }\n\n    .loading {\n      text-align: center;\n      font-size: 1.1em;\n      color: #555;\n      animation: pulse 1.2s infinite;\n    }\n\n    @keyframes pulse {\n      0% { opacity: 1; }\n      50% { opacity: 0.5; }\n      100% { opacity: 1; }\n    }\n    .ad-banner {\n            background: linear-gradient(135deg, #ff9a9e 0%, #fad0c4 100%);\n            color: white;\n            padding: 10px 15px;\n            text-align: center;\n            margin-bottom: 20px;\n            cursor: pointer;\n            border-radius: 8px;\n            border: 1px solid #ddd;\n            box-shadow: inset 0 1px 3px rgba(0,0,0,0.05);\n           }\n\n        .ad-banner:hover {\n            transform: translateY(-2px);\n            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);\n        }\n\n        .ad-banner span {\n            font-weight: 500;\n            font-size: 16px;\n        }\n  <\/style>\n<\/head>\n<body>\n  <div id=\"loading\" class=\"loading\">🔍 正在拼命检查中,请稍候~ 📡<\/div>\n\n  <div class=\"container\" id=\"container\">\n    <h1>📚 书源版本检查<\/h1>\n    <div class=\"ad-banner\" onclick=\"window.location.href='https:\/\/api.qingtian618.com\/phonecardad'\">\n        <span>📱 手机卡充值优惠活动,点击查看详情 →<\/span>\n    <\/div>\n    <div class=\"version-info\" id=\"versionInfo\">加载中...<\/div>\n    <div class=\"status\" id=\"statusText\"><\/div>\n\n    <div class=\"button-group\" id=\"buttonGroup\" style=\"display: none;\">\n          <\/div>\n\n    <div class=\"logs\" id=\"logs\" style=\"display: none;\">\n      <h2>📝 更新日志<\/h2>\n      <div id=\"logList\"><\/div>\n    <\/div>\n  <\/div>\n\n <script>\n(async function() {\n  const loading = document.getElementById('loading');\n  const container = document.getElementById('container');\n  const versionInfo = document.getElementById('versionInfo');\n  const statusText = document.getElementById('statusText');\n  const updateButton = document.getElementById('updateButton');\n  const buttonGroup = document.getElementById('buttonGroup');\n  const logsContainer = document.getElementById('logs');\n  const logList = document.getElementById('logList');\n\nconst localVer = '${String(localVersion)}';\n\/\/ 版本判断逻辑\nfunction compareVersions(vs) {\n  const parts1 = localVer.split('.').map(Number);\n  const parts2 = vs.split('.').map(Number);\n  const maxLength = Math.max(parts1.length, parts2.length);\n  for (let i = 0; i < maxLength; i++) {\n    const num1 = parts1[i] || 0;\n    const num2 = parts2[i] || 0;\n    if (num1 > num2) return 1;\n    if (num1 < num2) return -1;\n  }\n  return 0;\n}\n\nconst encodedEndpoints = [\n  'aHR0cHM6Ly9hcGkucWluZ3RpYW42MTguY29t',     \n  'aHR0cHM6Ly92MS5xaW5ndGlhbjYxOC5jb20=',      \n  'aHR0cHM6Ly92Mi5xaW5ndGlhbjYxOC5jb20=',       \n  'aHR0cHM6Ly92My5xaW5ndGlhbjYxOC5jb20=',      \n  'aHR0cHM6Ly92NC5xaW5ndGlhbjYxOC5jb20=',        \n  'aHR0cHM6Ly92NS5xaW5ndGlhbjYxOC5jb20=',       \n  'aHR0cDovLzExMy40NS4xNzUuMTEyOjg4ODg='        \n];\n\nfunction decodeEndpoint(str) {\n  return atob(str);\n}\n\nasync function fetchVersionData() {\n  for (const b64 of encodedEndpoints) {\n    const url = decodeEndpoint(b64);\n    try {\n      const response = await fetch(url + '\/version', { timeout: 2000 }); \n      if (response.ok) {\n        return await response.json();\n      }\n    } catch (e) {\n      console.warn(\\`接口失败:\\${url}\\`, e);\n    }\n  }\n  throw new Error('所有更新接口都请求失败');\n}\n  try {\n    loading.style.display = 'block';\n\n    const data = await fetchVersionData();\n    const cloudVersion = String(data.version3);\n    const updateLog = data.update_log || {};\n\n    versionInfo.innerHTML = \\`🔖当前版本:v\\${localVer} <br> 🔭最新版本:v\\${cloudVersion}\\`;\n\n    logList.innerHTML = Object.entries(updateLog).map(([date, content]) => \\`\n      <div class=\"log-item\">\n        <div class=\"log-item-date\">\\${date}<\/div>\n        <div class=\"log-item-content\">\\${content}<\/div>\n      <\/div>\n    \\`).join('');\n    logsContainer.style.display = 'block';\n\n    if (compareVersions(cloudVersion) === -1) {\n      statusText.innerHTML = '<span>✨ 有新版本可用,建议立即更新!<br>${yd}<\/span>';\nconst domainMap = {\n  main: 'aHR0cDovL3N5LnFpbmd0aWFuNjE4LmNvbQ==', \n  d1:   'aHR0cHM6Ly9hcGkucWluZ3RpYW42MTguY29t', \n  d2:   'aHR0cHM6Ly92MS5xaW5ndGlhbjYxOC5jb20=',\n  d3:   'aHR0cHM6Ly92Mi5xaW5ndGlhbjYxOC5jb20=',\n  d4:   'aHR0cHM6Ly92My5xaW5ndGlhbjYxOC5jb20=',\n  d5:   'aHR0cHM6Ly92NC5xaW5ndGlhbjYxOC5jb20=',\n  d6:   'aHR0cHM6Ly92NS5xaW5ndGlhbjYxOC5jb20='\n};\n\nfunction decode(b64) {\n  return atob(b64);\n}\n\nconst path = '\/sy\/download\/%E5%AE%89%E5%8D%93%E9%98%85%E8%AF%BBapp-%E6%99%B4%E5%A4%A9%E8%9E%8D%E5%90%884.0(%E5%AE%8C%E5%85%A8%E7%89%88).json';\nconst mainPath = '\/download\/%E5%AE%89%E5%8D%93%E9%98%85%E8%AF%BBapp-%E6%99%B4%E5%A4%A9%E8%9E%8D%E5%90%884.0(%E5%AE%8C%E5%85%A8%E7%89%88).json';\n\nconst routes = [\n  { name: '🚀 主线路', domain: 'main', suffix: mainPath },\n  { name: '📦 备用线路1', domain: 'd1', suffix: path },\n  { name: '🛰️ 备用线路2', domain: 'd2', suffix: path },\n  { name: '🛰️ 备用线路3', domain: 'd3', suffix: path },\n  { name: '🛰️ 备用线路4', domain: 'd4', suffix: path },\n  { name: '🛰️ 备用线路5', domain: 'd5', suffix: path },\n  { name: '🛰️ 备用线路6', domain: 'd6', suffix: path }\n];\n\nbuttonGroup.innerHTML = routes.map(r => {\n  const fullUrl = decode(domainMap[r.domain]) + r.suffix;\n  return \\`<a href=\"yuedu:\/\/booksource\/importonline?src=\\${encodeURIComponent(fullUrl)}\" class=\"button\">\\${r.name}<\/a>\\`;\n}).join('');\n      buttonGroup.style.display = 'flex';\n      } else {\n      statusText.textContent = '✅ 已是最新书源咯~';\n    }\n\n    loading.style.display = 'none';\n    container.style.display = 'block';\n\n  } catch (err) {\n    loading.textContent = '😢 检查失败啦~ 请稍后再试==>'+err;\n    console.error('版本检查失败:', err);\n  }\n})();\n<\/script>\n<\/body>\n<\/html>\n`;\n  java.startBrowser(`data:text\/html;base64,${java.base64Encode(html)}`, '晴天书源更新');\n}",
    "respondTime": 180000,
    "ruleBookInfo": {
        "author": "$.author",
        "canReName": "1",
        "coverUrl": "$.thumb_url",
        "init": "<js>\nif (String(baseUrl).startsWith(\"data:\")) {\n  let res = JSON.parse(java.hexDecodeToString(result));\n  let book_id = res.book_id;\n  let tab = res.tab;\n  let sources = res.sources;\n  let url = res.url;\n  let html = \"\";\n  let proxy = getArguments(source.getVariable(), \"proxy\");\n  if (url != \"\" && proxy == \"本地\") {\n  \tif (sources=='69书吧') {\n  \tlet ck69 = String(cookie.getCookie(url));\n   let headers = {\n                \"Cookie\": ck69\n            };\n            let op = JSON.stringify({\"headers\":headers});\n  \t\thtml = java.ajax(url+','+op);\n  \t\t} else {\n  \t\thtml = java.ajax(url);\n  \t\t}\n                \/\/java.log(html);\n    if (html.includes(\"Just a moment...\") && sources == '69书吧') {\n    \tcookie.removeCookie(url);\nvar x=`https:\/\/www.69shuba.com`;\njava.longToast('需要真人验证,请进入任意书籍详情页过验证');\nvar s=java.startBrowserAwait(x,\"需要真人验证,请进入任意书籍详情页过验证\").body();\n\t\n    let ck69 = String(cookie.getCookie(url));\n   let headers = {\n                \"Cookie\": ck69\n            };\n            let op = JSON.stringify({\"headers\":headers});\n            java.log(op);\n            html = java.ajax(url+','+op);\n            \/\/java.log(html);\n    \t}\n  }\n  let base_url = getArguments(source.getVariable(), \"server\");\n  let op = { method: \"POST\", body: { html: html } };\n  op = JSON.stringify(op);\n  \/\/java.log(op);\n  result = java.ajax(`${base_url}\/detail?book_id=${book_id}&source=${sources}&tab=${tab},${op}`);\n}\nresult\n<\/js>\n$.data",
        "intro": "<js>\nlet {\n  book_id,\n  source: sources,\n  tab,\n  book_tts,\n  tags,\n  role,\n  last_chapter_title,\n  last_chapter_update_time,\n  word_number,\n  status,\n  score,\n  abstract,\n  copyright_info\n} = result;\nlet proxy = getArguments(source.getVariable(), \"proxy\");\nif (proxy == \"本地\") {\n  proxy = \"本地网络\";\n} else {\n  proxy = \"服务器网络\";\n}\njava.put(\"book_detail\", JSON.stringify(result));\n\nlet base_url = getArguments(source.getVariable(), \"server\");\nlet key = \"\";\ntry {\n  let cookieValue =\n    String(cookie.getCookie(base_url)) || String(java.getCookie(base_url));\n  key = getKey(cookieValue);\n} catch (e) {\n  key = \"\";\n}\n\nif (key == \"\") {\n  java.log(\"当前服务器未查询到登录状态,尝试查询其他服务器登录状态...\");\n  let cookieValue;\n  for (let h of host) {\n    try {\n      cookieValue = String(cookie.getCookie(h)) || String(java.getCookie(h));\n      key = getKey(cookieValue);\n    } catch (e) {\n      key = \"\";\n    }\n    if (key) {\n      java.log(`已在${h}登录,退出查询,正在转移登录状态到当前服务${base_url}`);\n      \/\/java.log(cookieValue)\n      removeCookie(h);\n      removeCookie(base_url);\n      cookie.setCookie(base_url, cookieValue);\n      break;\n    }\n  }\n}\n\nif (book.readConfig == null || book.readConfig.useReplaceRule == null) {\n  book.setUseReplaceRule(false);\n}\nlet loginStatus = key ? \"✅ 已登录\" : \"⚠️ 未登录 | 点击右上角 🔖 登录\";\n\nlet lightDivider = \"❇️───────❇️───────❇️\";\nlet heavyDivider = \"&lrm;\\n&lrm;\";\n\nlet isValid = (value) => String(value).length > 1;\n\nlet info = `\n    📡 当前服务:${base_url}\n    🔑 账号状态:${loginStatus}\n    🏷 数据来源:${sources}\n    🔄 当前模式:${tab}\n    ⚙️ 访问模式:${proxy}\n`;\n\nif (tab == \"听书\") {\n  let toneId = getArguments(source.getVariable(), \"tone_id\");\n  if (isValid(book_tts)) {\n    info += `${lightDivider}\n    🎵 音色配置:${toneId}\n    ${book_tts}\n`;\n  }\n}\n\nlet basicInfo = \"\";\nlet addBasicInfo = (value, prefix, icon) => {\n  if (isValid(value)) basicInfo += `    ${icon} ${prefix} ${value}\\n`;\n};\n\naddBasicInfo(tags, \"书籍分类:\", \"🌈\");\naddBasicInfo(role, \"书籍主角:\", \"👑\");\naddBasicInfo(last_chapter_title, \"最新章节:\", \"📚\");\naddBasicInfo(last_chapter_update_time, \"更新时间:\", \"⏳\");\naddBasicInfo(word_number, \"书籍字数:\", \"📊\");\naddBasicInfo(status, \"书籍状态:\", \"🚩\");\naddBasicInfo(score, \"书籍评分:\", \"⭐\");\n\nif (basicInfo) info += `${lightDivider}\\n${basicInfo}`;\n\nif (isValid(abstract)) {\n  let indentedAbstract = abstract\n    .split(\"\\n\")\n    .map((line) => `    ${line}`)\n    .join(\"\\n\");\n  info += `${heavyDivider}\n    📖 书籍简介:\n${indentedAbstract}\n`;\n} else {\n  info += `${heavyDivider}`;\n}\n\nif (isValid(copyright_info)) {\n  info += `${lightDivider}\n    © ${copyright_info}\n`;\n} else {\n  info += `${lightDivider}`;\n}\n\ninfo += `\n${heavyDivider}\n    💠💠💠 数据更新于 ${new Date().toLocaleString()} 💠💠💠\n`;\nlet jjinfo = getArguments(source.getVariable(), \"info\");\n\nif (jjinfo != \"on\") {\n  info = String(info)\n    .split(\"\\n\")\n    .map((line) => line.replace(\/^ {4}\/, \"\"))\n    .join(\"\\n\");\n} else {\n  basicInfo = \"\";\n  addBasicInfo(last_chapter_title, \"最新章节:\", \"📚\");\n  addBasicInfo(last_chapter_update_time, \"更新时间:\", \"⏳\");\n  addBasicInfo(word_number, \"书籍字数:\", \"📊\");\n  addBasicInfo(status, \"书籍状态:\", \"🚩\");\n  addBasicInfo(score, \"书籍评分:\", \"⭐\");\n  if (isValid(abstract)) {\n    let indentedAbstract = abstract\n      .split(\"\\n\")\n      .map((line) => `    ${line}`)\n      .join(\"\\n\");\n    basicInfo += `\n    \\n&lrm;\n    📖 书籍简介:\n${indentedAbstract}\n`;\n  } else {\n    basicInfo += `${heavyDivider}`;\n  }\n  info = `&lrm;\\n🏷 数据来源:${sources}\\n` + basicInfo;\n}\n<\/js>",
        "lastChapter": "{{$.source}} {{$.last_chapter_title}} {{$.last_chapter_update_time}}",
        "name": "$.book_name",
        "tocUrl": "<js>\nlet book_id = result.book_id;\nlet sources = result.source;\nlet tab = result.tab || \"小说\";\nlet url = result.toc_url || \"\";\nvar sdtoken;\ntry {\n    var loginInfoMap = source.getLoginInfoMap ? source.getLoginInfoMap() : {};\n    sdtoken = String(loginInfoMap['手动填写番茄token(可不填)'] || '');\n} catch (e) {\n    sdtoken = '';\n}\nvar rawCookie = getFanqieCookie() || sdtoken;\nvar match = rawCookie.match(\/sessionid=[^;]+\/);\nvar fqcookie = match ? match[0] : '';\nvar fqssionid = '';\nif (fqcookie) {\n    fqssionid = getSessionId(fqcookie);\n};\nsetArguments('fqssionid', fqssionid);\njava.put(\"tab\", tab);\njava.put(\"book_id\", book_id);\nlet qtcatalog = {\n  book_id: book_id,\n  sources: sources,\n  tab: tab,\n  url: url,\n};\nqtcatalog = java.base64Encode(JSON.stringify(qtcatalog));\n`data:;base64,${qtcatalog},{\"type\":\"qingtian2\"}`;\n<\/js>",
        "wordCount": "$.word_number"
    },
    "ruleContent": {
        "content": "<js>\nresult = String(java.hexDecodeToString(result));\nlet res;\nif (result.match(\/晴天融合\/)) {\n  result = result.split(\"晴天融合4\");\n  res = {\n    item_id: result[0],\n    tab: result[1],\n    title: result[2],\n    sources: result[3],\n    url: \"\"\n  };\n} else {\n  res = JSON.parse(result);\n}\n\nlet book_id = java.get(\"book_id\");\nlet item_id = res.item_id;\nlet tab = res.tab;\nlet title = res.title;\nlet sources = res.sources;\nlet url = res.url;\nlet html = \"\";\nlet proxy = getArguments(source.getVariable(), \"proxy\");\nif (url != \"\" && proxy == \"本地\") {\n\tif (sources=='69书吧') {\n  \tlet ck69 = String(cookie.getCookie(url));\n   let headers = {\n                \"Cookie\": ck69\n            };\n            let op = JSON.stringify({\"headers\":headers});\n  \t\thtml = java.ajax(url+','+op);\n  \t\t} else {\n  \t\thtml = java.ajax(url);\n  \t\t}\n                \/\/java.log(html);\n    if (html.includes(\"Just a moment...\") && sources == '69书吧') {\n    \tcookie.removeCookie(url);\nvar x=`https:\/\/www.69shuba.com`;\njava.longToast('需要真人验证,请进入任意书籍详情页过验证');\nvar s=java.startBrowserAwait(x,\"需要真人验证,请进入任意书籍详情页过验证\").body();\n\t\n    let ck69 = String(cookie.getCookie(url));\n   let headers = {\n                \"User-Agent\":      \"Mozilla\/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/138.0.0.0 Safari\/537.36 Edg\/138.0.0.0\",\n                \"Cookie\": ck69\n            };\n            let op = JSON.stringify({\"headers\":headers});\n            java.log(op);\n            html = java.ajax(url+','+op);\n            \/\/java.log(html);\n    \t}\n};\nlet content = \"\";\nlet data;\nlet tone_id = getArguments(source.getVariable(), \"tone_id\");\nlet base_url = getArguments(source.getVariable(), \"server\");\nlet device, device_type;\ntry {\n  device = java.androidId();\n  device_type = \"安卓\";\n} catch (e) {\n  try {\n    device = java.deviceID();\n    device_type = \"苹果\";\n  } catch (e) {\n    device = \"\";\n    device_type = \"安卓\";\n  }\n}\nlet op = {\n  method: \"POST\",\n  body: { html: html },\n  headers: { cookie: cookie.getCookie(base_url) },\n};\nop = JSON.stringify(op);\n\/\/java.log(op);\nlet content_url = `\/content?item_id=${item_id}&source=${sources}&tab=${tab}&tone_id=${tone_id}&version=4.6.29,${op}`;\n\ndata = java.ajax(base_url + content_url);\ntry {\n\tdata = JSON.parse(data);\n  if (data.msg) {\n    java.toast(data.msg);\n  }\n} catch (e) {}\ncontent = data.content;\ncontent = decrypt(content);\nif (sources == \"番茄\" && cache.get(\"fqpara\") == \"on\" && tab == \"小说\") {\n  content = getComments(content, book_id, item_id);\n}\ndata = JSON.stringify({\n  content: content,\n});\nif (device_type == \"安卓\" && (tab == \"短剧\" || tab == \"视频\" || sources == '毒舌影视')) {\n  data = {\n    content: `【右上角刷新】开启播放(下一集请切换下一章刷新)\\n播放直链:\\n${content}`,\n  };\n  data = JSON.stringify(data);\n  if (book.durChapterIndex === chapter.index) {\n  \tlet video_url = `${base_url}\/online_video?book_id=${book_id}&source=${sources}&tab=${tab}`;\n  \tif (sources=='毒舌影视') {\n  \t\tvideo_url = content;\n  \t\t};\n    java.startBrowser(video_url, title);\n    java.toast(\"正在加载视频...\");\n  }\n}\ndata;\n<\/js>\n$.content",
        "imageStyle": "TEXT"
    },
    "ruleExplore": {
        "author": "$.author",
        "bookList": "$.data",
        "bookUrl": "<js>\nlet book_id = result.book_id;\nlet sources = result.source;\nlet tab = result.tab || '小说';\nlet url = result.toc_url || '';\n\nlet qtdetail = {\n\tbook_id:book_id,\n\tsources:sources,\n\ttab:tab,\n\turl:url\n\t}\n\tqtdetail = java.base64Encode(JSON.stringify(qtdetail));\n`data:;base64,${qtdetail},{\"type\":\"qingtian\"}`\n<\/js>",
        "coverUrl": "$.thumb_url",
        "intro": "{{$.source}}\n{{$.abstract}}",
        "kind": "{{$.category}}\n{{$.score}}\n{{$.status}}\n{{$.source}}\n{{$.tags}}",
        "lastChapter": "{{$.last_chapter_title}} • {{$.last_update_time}}",
        "name": "$.book_name",
        "wordCount": "$.word_number"
    },
    "ruleSearch": {
        "author": "$.author",
        "bookList": "$.data",
        "bookUrl": "<js>\nlet book_id = result.book_id;\nlet sources = result.source;\nlet tab = result.tab || '小说';\nlet url = result.toc_url || '';\n\nlet qtdetail = {\n\tbook_id:book_id,\n\tsources:sources,\n\ttab:tab,\n\turl:url\n\t}\n\tqtdetail = java.base64Encode(JSON.stringify(qtdetail));\n`data:;base64,${qtdetail},{\"type\":\"qingtian\"}`\n<\/js>",
        "checkKeyWord": "我的26岁女房客@番茄",
        "coverUrl": "$.thumb_url",
        "intro": "$.abstract",
        "kind": "{{$.status}},{{$.score}},{{$.tags}},{{$.last_chapter_update_time}}",
        "lastChapter": "{{$.source}} {{$.last_chapter_title}}",
        "name": "$.book_name##(别名:.*?)",
        "wordCount": "$.word_number"
    },
    "ruleToc": {
        "chapterList": "<js>\nlet res = JSON.parse(java.hexDecodeToString(result));\nif (res.method) {\n  res = Object.fromEntries(\n    res.body\n      .replace(\"source\", \"sources\")\n      .split(\"&\")\n      .map((query) => query.split(\"=\"))\n  );\n  res.url = \"\";\n}\nlet book_id = res.book_id;\nlet tab = res.tab;\nlet sources = res.sources;\nlet url = res.url;\nlet html = \"\";\nlet proxy = getArguments(source.getVariable(), \"proxy\");\nif (url != \"\" && proxy == \"本地\") {\n\tif (sources=='69书吧') {\n  \tlet ck69 = String(cookie.getCookie(url));\n   let headers = {\n                \"Cookie\": ck69\n            };\n            let op = JSON.stringify({\"headers\":headers});\n  \t\thtml = java.ajax(url+','+op);\n  \t\t} else {\n  \t\thtml = java.ajax(url);\n  \t\t}\n                \/\/java.log(html);\n    if (html.includes(\"Just a moment...\") && sources == '69书吧') {\n    \tcookie.removeCookie(url);\nvar x=`https:\/\/www.69shuba.com`;\njava.longToast('需要真人验证,请进入任意书籍详情页过验证');\nvar s=java.startBrowserAwait(x,\"需要真人验证,请进入任意书籍详情页过验证\").body();\n\t\n    let ck69 = String(cookie.getCookie(url));\n   let headers = {\n                \"Cookie\": ck69\n            };\n            let op = JSON.stringify({\"headers\":headers});\n            java.log(op);\n            html = java.ajax(url+','+op);\n            \/\/java.log(html);\n    \t}\n};\nlet base_url = getArguments(source.getVariable(), \"server\");\nlet op = { method: \"POST\", body: { html: html } };\nop = JSON.stringify(op);\n\/\/java.log(op);\nlet data = java.ajax(\n  `${base_url}\/catalog?book_id=${book_id}&source=${sources}&tab=${tab},${op}`\n);\nlet device;\nlet device_type;\ntry {\n  device = java.androidId();\n  device_type = \"安卓\";\n} catch (e) {\n  device_type = \"苹果\";\n}\n\nif (tab == \"小说\") {\n  if (device_type == \"安卓\") {\n    book.type = 8;\n  } else {\n    book.type = 0;\n  }\n} else if (tab == \"听书\") {\n  if (device_type == \"安卓\") {\n    book.type = 32;\n  } else {\n    book.type = 1;\n  }\n} else if (tab == \"漫画\") {\n  if (device_type == \"安卓\") {\n    book.type = 64;\n  } else {\n    book.type = 2;\n  }\n} else if (tab == \"短剧\") {\n  if (device_type == \"安卓\") {\n    book.type = 8;\n  } else {\n    book.type = 3;\n  }\n} else {\n  if (device_type == \"安卓\") {\n    book.type = 8;\n  } else {\n    book.type = 0;\n  }\n}\ndata;\n<\/js>\n$.data",
        "chapterName": "$.title",
        "chapterUrl": "<js>\nlet tab = result.tab;\nlet sources = result.source;\nlet title = result.title;\nlet item_id = result.item_id;\nlet url = result.toc_url || \"\";\nlet qtcontent = {\n  item_id: item_id,\n  title: title,\n  sources: sources,\n  tab: tab,\n  url: url,\n};\nqtcontent = java.base64Encode(JSON.stringify(qtcontent));\nif (sources=='卷') {\n\tcontent_url = item_id\n\t} else if (sources == \"番茄\" && tab == \"小说\") {\n  book_id = java.get(\"book_id\");\n  java.put(\"book_id\", book_id);\n  var base_url = getArguments(source.getVariable(), \"server\") || \"\";\n  var fqssionid = getArguments(source.getVariable(), \"fqssionid\") || \"\";\n   content_url = `data:;base64,${qtcontent},{\"type\":\"qingtian3\",\"js\":\"book ? result : '${base_url}\/get_review?book_id=${book_id}&item_id=${item_id}&ssionid=${fqssionid}'\"}`;\n} else {\n  content_url = `data:;base64,${qtcontent},{\"type\":\"qingtian3\"}`;\n}\n<\/js>",
        "isVolume": "$.is_volume",
        "preUpdateJs": "if (String(book.tocUrl).startsWith(\"http\")) {\n\tjava.log(\"重新获取书籍信息\")\n\tjava.reGetBook()\n}",
        "updateTime": "$.first_pass_time"
    },
    "searchUrl": "<js>\nlet base_url = getArguments(source.getVariable(),'server');\nlet media;\nlet sources = getArguments(source.getVariable(),'source');\nif (String(key).startsWith(\"m:\")||String(key).startsWith(\"m:\")) {\n  media = \"漫画\"\n  key = key.slice(2)\n  }else if (String(key).startsWith(\"t:\")||String(key).startsWith(\"t:\")) {\n  media = \"听书\"\n  key = key.slice(2)\n} else if (String(key).startsWith(\"d:\")||String(key).startsWith(\"d:\")) {\n  media = \"短剧\"\n  key = key.slice(2)\n} else if (String(key).startsWith(\"x:\")||String(key).startsWith(\"x:\"))  {\n\tmedia = \"小说\"\n  key = key.slice(2)\n\t} else {\n\tmedia = getArguments(source.getVariable(),'media');\n\t}\nif (key.includes('@')) {\n  var parts = key.split('@');\n  key = parts[0];\n  sources = parts[1] || sources;\n}\n\t`${base_url}\/search?title=${key}&tab=${media}&source=${sources}&page={{page}}`\n<\/js>",
    "weight": 60
}
广告