🐱Pixiv小喵
https://app-api.pixiv.net/
AHa-hahahahaha (14320)2天前
在源仓库「🐱Pixiv小喵(自动翻译)」基础上,整合了以下改进:
✅ 翻译引擎全面升级(三引擎切换)
✅ 界面功能按钮优化
✅ 增加私密关注/收藏
✅ 增加章首描述 + 猫猫分割线
✅ 增加注音替换、表情显示、特殊语法补充
✅ 修复翻页报错(127.0.0.1 问题)
🔁 翻译引擎说明
─────────────────────────
本版移植自 laizhiyu 大佬修复的翻译模块,支持三种引擎切换:
1️⃣ 🟢 必应网页接口(默认)
- 最快,免密钥,国内直连
- 效果好,无限制
- ⚠️ 用量太大可能被风控
2️⃣ 🔵 腾讯+微软密钥模式
- 未填微软密钥:走腾讯自有引擎(效果一般,仅兜底)
- 已填微软密钥:走 Azure 官方通道,质量更稳
- 💡 密钥本人未测试,有条件的可自测
3️⃣ 🤖 AI 大模型翻译
- 支持 OpenAI 兼容接口
- 接口地址:填写平台提供的 baseurl
- 密钥:一般需填(部分平台如 OpenCode 免 token)
- AI 模型:选填,默认 gpt-4o-mini
- 填完配置后可点击「🤖翻译测试」验证
- 输出「你好,世界」即为配置成功
📦 新增功能一览
─────────────────────────
🖼️ 图片显示:切换正文插图显示/隐藏
🔢 补充序号:自动为章节名添加序号
📝 简介标签:在书籍简介中显示标签
📄 章首描述:在正文前显示小说前言/简介
🎀 分割线式:循环切换4种猫猫风格分割线
😊 表情显示:将(表情代码)替换为表情图片
🔊 注音替换:将 [[rb:汉字>读音]] 替换为汉字(读音)
📐 特殊语法:支持 [chapter:] [jump:] [[jumpuri:]]
📘 书名标识:在书名前添加 📘 符号
👤 @作者搜索:搜索框输入 @作者名 直达作者作品
🔒 私密关注/收藏:支持私密模式操作
📖 按钮说明:点击查看所有按钮功能
🔁 翻译引擎:三引擎循环切换
🌐 翻译模式:关闭 / 自动识别 / 对照显示
🤖 翻译测试:验证 AI 翻译配置是否连通
📖 翻译说明:查看详细翻译使用说明
🔧 已修复问题
─────────────────────────
❌ 修复翻页报错
❌ 修复书籍详情页作者名含多余 @ 符号问题
❌ 修复翻译功能完全失效(替换为三引擎)
❌ 修复「作者其他书籍」功能无法识别作者名
⚠️ 使用须知
─────────────────────────
· 推荐阅读器版本:3.26(lyc 推荐)
· token:长效账号身份令牌,在登录界面填写
· 获取 token:阅读登录中获取,或从 pixEz 导出
· 翻译配置:填完 AI 配置后必须点击右上角 √ 重新登录
🐱 猫猫碎碎念
─────────────────────────
本喵也不知道自己有没有把 AI 翻译功能移坏
但如果你发现了 bug,可以「反馈」给本喵哦~
(虽然本喵没留联系方式,嘻嘻~)
不过嘛~本喵心善
只要你把这个书源丢给 AI,本喵自然会出现~ ฅ(^ω^ฅ)
❤️ 感谢所有为开源做出贡献的大佬们
────────────────────────
AI还是挺好用的
不用我打字了
{
"bookSourceComment": "✨ 本喵基于以下版本整合而来:\n\n⭐ 洛娅橙原版:Pixiv 小说书源的早期基础版本。\n\n⭐ 添加翻译功能的版本:由不知名人士在洛娅橙原版基础上添加了微软翻译功能,后来又被加入了商业推广广告(虽说本喵感觉是一个人干的,但本喵也没有证据嘛~)。\n\n⭐ laizhiyu 大佬修复版:修复了网络直连问题,并替换为三引擎翻译模块(必应\/腾讯\/AI),彻底解决翻译失效问题。感谢 laizhiyu 大佬的辛勤付出!\n\n⭐ 猫猫黛西(由 DeepSeek 全程代劳):基于以上版本,去除所有广告,进行了界面优化和功能调整。\n\n⚠️ 使用3.26版本,推荐阅读 lyc。\n\n🐱 本喵也不知道自己有没有把 AI 翻译功能搞坏,但你要是发现了 bug,可以反馈给本喵哦~\n 不过嘛~本喵没有留下任何联系方式,嘻嘻~\n 哎呀~本喵还是心善的啦~只要你把这个书源丢给 AI,本喵自然就会出现~ ฅ(^ω^ฅ)\n\n\n感谢所有为开源做出贡献的大佬们!(ฅ´ω`ฅ)",
"bookSourceGroup": "Pixiv",
"bookSourceName": "🐱Pixiv小喵",
"bookSourceType": 0,
"bookSourceUrl": "https:\/\/app-api.pixiv.net\/",
"bookUrlPattern": "http:\/\/localhost\/|https:\/\/www.pixiv.net\/novel\/series\/\\d{3,}",
"concurrentRate": "3\/2000",
"customButton": false,
"customOrder": -3,
"enabled": false,
"enabledCookieJar": true,
"enabledExplore": true,
"eventListener": false,
"exploreUrl": "@js:\nlet banben=\"1.1.9\";\nvar obj = {\n '动态': {\n \"url\": `{{\n if (page == 1) {\n url = 'https:\/\/app-api.pixiv.net\/v1\/novel\/follow?restrict=public';\n } else {url = source.get('nurl');}\n url=gethd(url);\n }}`,\n \"fb\": 0.2 },\n '推荐': {\n \"url\": `{{\n if (page == 1) {\n url = 'https:\/\/app-api.pixiv.net\/v1\/novel\/recommended?include_privacy_policy=true&filter=for_android&include_ranking_novels=true';\n } else {url = source.get('nurl');}\n url=gethd(url);\n }}`,\n \"fb\": 0.2 },\n '追更': {\n \"url\": `{{\n if (page == 1) {\n url = 'https:\/\/app-api.pixiv.net\/v1\/watchlist\/novel';\n } else {url = source.get('nurl');}\n url=gethd(url);\n }}`,\n \"fb\": 0.2 },\n '收藏·公开': {\n \"url\": `{{\n if (page == 1) {\n let id = source.getLoginInfoMap().get('id');\n url = 'https:\/\/app-api.pixiv.net\/v1\/user\/bookmarks\/novel?user_id='+id+'&restrict=public';\n } else {url = source.get('nurl');}\n url=gethd(url);\n }}`,\n \"wb\": 1,\n \"fb\": 0.4 },\n '收藏·私密': {\n \"url\": `{{\n if (page == 1) {\n let id = source.getLoginInfoMap().get('id');\n url = 'https:\/\/app-api.pixiv.net\/v1\/user\/bookmarks\/novel?user_id='+id+'&restrict=private';\n } else {url = source.get('nurl');}\n url=gethd(url);\n }}`,\n \"fb\": 0.4 },\n 'R-18·日': {\n \"url\": `{{\n if (page == 1) {\n url = 'https:\/\/app-api.pixiv.net\/v1\/novel\/ranking?filter=for_android&mode=day_r18';\n } else {url = source.get('nurl');}\n url=gethd(url);\n }}`,\n \"wb\": 1,\n \"fb\": 0.2 },\n 'R-18·AI': {\n \"url\": `{{\n if (page == 1) {\n url = 'https:\/\/app-api.pixiv.net\/v1\/novel\/ranking?filter=for_android&mode=week_ai_r18';\n } else {url = source.get('nurl');}\n url=gethd(url);\n }}`,\n \"fb\": 0.2 },\n 'R-18·周': {\n \"url\": `{{\n if (page == 1) {\n url = 'https:\/\/app-api.pixiv.net\/v1\/novel\/ranking?filter=for_android&mode=week_r18';\n } else {url = source.get('nurl');}\n url=gethd(url);\n }}`,\n \"fb\": 0.2 }\n}\n\nvar sort = [];\npush = (title, url, fg, wrap, fb) => sort.push({\n \"title\": title,\n \"url\": url,\n \"style\": {\n layout_flexGrow: fg || 1,\n layout_flexBasisPercent: fb||-1,\n layout_wrapBefore: wrap ? true : false\n }\n });\n\nfor (x in obj) {\npush(x, obj[x].url, obj[x].fg, obj[x].wb, obj[x].fb);\n}\nJSON.stringify(sort);",
"header": "@js:\n(()=>{\n\tlet headers = gethd();\n\treturn JSON.stringify(headers);\n})();",
"jsLib": "sleep = Packages.java.lang.Thread.sleep;\nua = 'PixivAndroidApp\/5.0.166 (Android 14; RMX3366)';\nappv = '5.0.166';\na_l = 'zh-CN';\nBUA = 'Mozilla\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/131.0.0.0 Safari\/537.36';\n\nbiaoq = new RegExp('^(?:NTR|NTL|修仙|奇幻|后宫|纯爱|隐奸|乱伦|乱交|母女.?|母子|父女|幼女|姐弟|人妻|正太|足交|口交|肛交|丝袜|催眠|系统|原创|续写|软饭流|修罗场|规则怪谈|女性视角|性开放世界|奸尸|冰恋|.?重口)$','i');\n\nfunction timemd5(time) {\n\tvar saltStr = time + '28c1fdd170a5204386cb1313c7077b34f83e4aaf4aa829ce78c231e05b0bae2c';\n\ttry {\n\t\tvar jv = this.java || (typeof java !== 'undefined' ? java : null);\n\t\tif (jv && jv.md5Encode) return jv.md5Encode(saltStr);\n\t} catch(e) {}\n\tvar md = Packages.java.security.MessageDigest.getInstance(\"MD5\");\n\tmd.update(new Packages.java.lang.String(saltStr).getBytes(\"UTF-8\"));\n\tvar dg = md.digest();\n\tvar hx = '';\n\tfor (var di = 0; di < dg.length; di++) {\n\t\tvar bv = dg[di] & 0xFF;\n\t\thx += (bv < 16 ? '0' : '') + bv.toString(16);\n\t}\n\treturn hx;\n}\n\nfunction gethd(url='',ck='') {\n\t\/\/ 修复:遇到 127.0.0.1(翻页结束标记)直接返回空数据,避免报错\n\tif (url && url.startsWith('http:\/\/127.')) return 'data:;base64,';\n\tconst {java, source} = this;\nlet time = java.timeFormatUTC(Date.now(),\"yyyy-MM-dd'T'HH:mm:ss'+00:00'\",8*60*60*1000);\nlet hash = this.timemd5(time);\nlet atk = source.getLoginHeader()||'';\nif(atk) atk = String('Bearer '+atk);\nlet headers = {\n 'x-client-time': time,\n \t'User-Agent': ua,\n \t'accept-language': a_l,\n \t'authorization': atk,\n \t'app-os': 'Android',\n \t'app-os-version': 'Android 14',\n \t'app-version': appv,\n 'x-client-hash': hash,\n 'cookie': ''\n \t }\nck!='' && (headers['cookie']=ck);\nurl=url.replace(\"app-api.pixiv.net\",\"210.140.139.155\");\nurl && (headers['host']='app-api.pixiv.net');\nif (url=='') return headers;\nelse if (url.startsWith('data')) return url;\nelse {\n\tdelete headers['x-client-time'];\n\tdelete headers['x-client-hash'];\n\treturn url + ',' + JSON.stringify({'headers':headers});}\n};\n\nfunction leng(str) {\n\tlet length = 0;\n\tconst fuhao = ',.?!:;()[]\"';\n\tconst fuhao2 = '📘';\n\tfor (let char of str) {\n\t\tif (fuhao.includes(char) ) length += 0.5;\n\t\telse if (fuhao2.includes(char) ) length += 2;\n\t\telse length += 1;\n\t\t}\n\t\treturn length;\n}\n\nfunction gethdi(url='') {\turl=url.replace(\"i.pximg.net\",\"210.140.139.133\");\nlet imgoptions = {\n headers: {\n 'User-Agent': 'PixivIOSApp\/5.8.0',\n 'accept-encoding': 'gzip, br',\n 'referer': 'https:\/\/app-api.pixiv.net\/',\n 'host': 'i.pximg.net'\n }\n };\n return url+','+JSON.stringify(imgoptions);\n }\n \nfunction copy(txt) {\n\tlet htm = `data:text\/html;charset=utf-8,<html>\n<head>\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<style>\nbody {\n\tdisplay: flex;\n\tflex-direction: column;\n\tjustify-content: center;\n\talign-items: center;\n\theight: 60vh;}\n<\/style>\n<\/head>\n<body>\n<textarea id=\"copyt\" rows=\"3\">${txt}<\/textarea>\n<br>\n<button id=\"btn1\" onclick=\"copy()\">复制<\/button>\n<script>\ndocument.addEventListener(\"DOMContentLoaded\", function () {\nconst textarea = document.getElementById(\"copyt\");\ntextarea.style.height = \"auto\";\ntextarea.style.height = textarea.scrollHeight + \"px\";});\nfunction copy() {\nconst cpt = document.getElementById(\"copyt\");\ncpt.select();\ndocument.execCommand(\"copy\");}\n<\/script>\n<\/body><\/html>`;\nthis.java.startBrowser(htm,'复制');\n\t}\n\nfunction lookc(lyc) {\nconst [title,uid,unm,uim,tags,caption,cdate,xh,sc,gk,sTitle,id,ugz] = lyc;\n\tlet htm = `<html>\n<head>\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<style>\ntable {\n\twidth: 100%;\n\ttable-layout: fixed;\n\ttext-align: center;\n\tmargin: 0 auto;\n\tword-break: break-all;\n\t}\ntd img {\n\twidth: 100%;\n\theight: 100%;\n\tobject-fit: contain;\n\t}\n.cap {\n\t text-align: left;\n\t text-indent: 2em;\n\t}\na {text-decoration: none;}\np {margin: 0.2em auto;}\n<\/style>\n<\/head>\n<body>\n<table border=\"1\" cellspacing=\"0\">\n<tr>\n<th colspan=\"6\">标题:<a href=\"https:\/\/www.pixiv.net\/novel\/show.php?id=${id}\">${title}<\/a><\/th>\n<\/tr>\n<tr>\n<td colspan=\"4\">\n作者:<a href=\"https:\/\/www.pixiv.net\/users\/${uid}\">${unm}<\/a>\n${ugz=='true' ? '<span style=\"font-size: 0.7em;\"> (已关注)<\/span>' : ''}\n<\/td>\n<td colspan=\"2\"><img src=\"${uim}\"><\/td>\n<\/tr>\n${sTitle!='' ? ('<tr><td colspan=\"6\">小说:《'+sTitle+'》'+'<\/td><\/tr>') : ''}\n<tr>\n<td>喜欢<\/td>\n<td>${xh}<\/td>\n<td>收藏<\/td>\n<td>${sc}<\/td>\n<td>观看<\/td>\n<td>${gk}<\/td>\n<\/tr>\n<tr>\n<td>时间<\/td>\n<td colspan=\"5\">${cdate}<\/td>\n<\/tr>\n<td>标签<\/td>\n<td colspan=\"5\">${tags}<\/td>\n<\/tr>\n${caption!='' ? ('<tr><td>简介<\/td><td class=\"cap\" colspan=\"5\">'+caption+'<\/td><\/tr>') : ''}\n<\/table>\n<br>\n<script>\n<\/script>\n<\/body><\/html>`;\nthis.java.startBrowser(`data:text\/html;charset=utf-8,${encodeURIComponent(htm)}`,'信息');\n}\n\n\/\/ ============================================================\n\/\/ 🤖 三引擎翻译模块(移植自 laizhiyu 的 Pixiv 小喵自动翻译版)\n\/\/ 引擎:🟢必应网页版(免密钥·国内直连) \/ 🔵腾讯TranSmart \/ 🤖AI大模型(OpenAI兼容)\n\/\/ ============================================================\n\nvar util={open(url,title,msg){if(msg){this.java.longToast(\"\\n\"+msg);this.sleep(300)}url&&this.java.startBrowser(url,title||\"\")},getMaxLen(texts,max){max=max||5E4;for(var len=0,all=0;len<texts.length;len++)if(len>1E3||(all+=texts[len].Text.length)>max){len--;break}return len},splitByMaxLenAdjustLines(str,maxLen){const parts=[];let remaining=str;maxLen=maxLen||5E4;while(remaining.length>maxLen){let part=remaining.slice(0,maxLen);let rest=remaining.slice(maxLen);let lastNewlineIndex=part.lastIndexOf(\"\\n\");if(lastNewlineIndex===\n-1){parts.push(part);remaining=rest}else{let firstPart=part.slice(0,lastNewlineIndex+1);let movedPart=part.slice(lastNewlineIndex+1);parts.push(firstPart);remaining=movedPart+rest}}remaining.length>0&&parts.push(remaining);return parts},api:{auth:\"https:\/\/edge.microsoft.com\/translate\/auth\",translate:\"https:\/\/api.cognitive.microsofttranslator.com\/translate?from\\x3d{from}\\x26to\\x3d{to}\\x26api-version\\x3d3.0\"},isJa:(str,n)=>\/[\\u30a1-\\u30f6\\u3041-\\u3093\\uff66-\\uff9d\\uff9e\\uff9f][\\u30a1-\\u9fa5]\/.test((n=\nn||100)>0?String(str).substring(0,n):str),isEn:(str,n)=>!\/[\\u30a1-\\u30f6\\u3041-\\u3093\\uff66-\\uff9d\\uff9e\\uff9f\\u4e00-\\u9fa5]{2}\/.test((n=n||100)>0?String(str).substring(0,n):str),noZh:(k,n)=>{n=n||100;if(util.isJa(k,n)){util.lang_zh=\"\\u65e5\\u8bed\";util.lang=\"ja\";return true}else if(util.isEn(k,n)){util.lang_zh=\"\\u82f1\\u8bed\";util.lang=\"en\";return true}else return false},fixImg(str){let obj={\"\\uff1a\":\":\",\"\\uff0c\":\",\",\"\\u201c\":'\"',\"\\u201d\":'\"'};return str.replace(\/<img .+>\/g,$=>$.replace(\/[\\u201c\\u201d\\uff1a\\uff0c]\/g,\nx=>obj[x]))},objfy:(x,y,z)=>JSON.stringify(x,y||null,z||2),getAuth(isNew){const {cache,java}=this;if(!isNew){var auth=cache.getFromMemory(\"auth\");if(auth){let t=+auth.slice(0,13),k=auth.slice(14);if(k&&Date.now()-t<6E5)return k}}auth=java.ajax(util.api.auth)+\"\";cache.putMemory(\"auth\",`${Date.now()}#${auth}`);return auth},filterReg:\/^[\\x00-@\\[-`{-~\\uff01-\\uff20]+$|^\\s*[\\x00-\\u2e7f]\\s*$\/,logProp(ox){let obj={};Object.keys(ox).forEach(x=>{let v=ox[x];if(typeof v===\"function\"){v=v.toString();try{obj[x]=\n[v,ox[x]()]}catch{obj[x]=v}}else obj[x]=v});this.java.log(JSON.stringify(obj,null,2))},\n\/\/ 🟢 必应网页版翻译(免注册免密钥):GET cn.bing.com\/translator 取IG+key+token,POST ttranslatev3逐段翻译,token失效自动重取\nbingCred(){const{java}=this;let h=String(java.get(\"https:\/\/cn.bing.com\/translator\",{\"User-Agent\":BUA}).body());let ig=h.match(\/IG:\"([A-Za-z0-9]{32})\"\/),ap=h.match(\/params_AbusePreventionHelper\\s*=\\s*\\[([^\\]]+)\\]\/);if(!ig||!ap)throw\"必应凭据获取失败\";let p=ap[1].split(\",\");return{ig:ig[1],key:p[0].replace(\/[\"\\s]\/g,\"\"),tk:p[1].replace(\/[\"\\s]\/g,\"\")}},bingT(texts,from){const{java}=this;let c=util.bingCred.call(this),out=[];for(let i=0;i<texts.length;i++){var tx=\"\";if(texts[i])for(let t=0;t<2&&!tx;t++){try{tx=JSON.parse(String(java.post(\"https:\/\/cn.bing.com\/ttranslatev3?isVertical=1&&IG=\"+c.ig+\"&IID=translator.5027\",\"fromLang=\"+((from||util.lang)===\"en\"?\"en\":\"ja\")+\"&to=zh-Hans&text=\"+encodeURIComponent(texts[i])+\"&token=\"+c.tk+\"&key=\"+c.key+\"&tryFetchingGenderDebiasedTranslations=true\",{\"content-type\":\"application\/x-www-form-urlencoded\",\"referer\":\"https:\/\/cn.bing.com\/translator\",\"x-requested-with\":\"XMLHttpRequest\",\"User-Agent\":BUA}).body()))[0].translations[0].text}catch(e){tx=\"\"}if(!tx){if(t)tx=texts[i];else{sleep(700);c=util.bingCred.call(this)}}}out.push(tx||texts[i]);if(i<texts.length-1)sleep(120)}return out},\n\/\/ 🔵 腾讯TranSmart:填微软密钥走Azure官方;未填走腾讯自有引擎+MyMemory兜底\ntxT(texts,from){const{java,source}=this;let lgm=source.getLoginInfoMap(),msKey=util.lgKey(lgm,\"微软密钥\").replace(\/\\s\/g,\"\");let to=\"zh\";if(msKey.length>10){let result=[];for(let i=0;i<texts.length;){let batch=[];let total=0;while(i<texts.length&&batch.length<50&&(total+=texts[i].length)<=20000){batch.push({Text:texts[i]});i++}let reqBody=JSON.stringify(batch);let r=java.post(\"https:\/\/api.cognitive.microsofttranslator.com\/translate?api-version=3.0&to=\"+to,reqBody,{\"content-type\":\"application\/json\",\"Ocp-Apim-Subscription-Key\":msKey});let j=JSON.parse(String(r.body()));for(let k=0;k<j.length;k++)result.push(j[k].translations[0].text)}return result}let result=[];for(let i=0;i<texts.length;){let batch=[];let total=0;while(i<texts.length&&batch.length<8&&(total+=texts[i].length)<=4000){batch.push(texts[i]);i++}let reqBody=JSON.stringify({header:{fn:\"auto_translation\",session:\"\",client_key:\"browser-chromium-131.0.0.0\"},type:\"plain\",model_category:1,text_domain:0,source:{lang:(from||\"ja\"),text_list:batch},target:{lang:\"zh\"}});let r=java.post(\"https:\/\/transmart.qq.com\/api\/imt\",reqBody,{\"content-type\":\"application\/json\",\"referer\":\"https:\/\/transmart.qq.com\/\"});let j=JSON.parse(String(r.body()));if(j.header.ret_code==\"succ\"&&j.auto_translation&&j.auto_translation.length==batch.length){result=result.concat(j.auto_translation)}else{for(let k=0;k<batch.length;k++){let mm=java.ajax(\"https:\/\/api.mymemory.translated.net\/get?q=\"+encodeURIComponent(batch[k])+\"&langpair=\"+((from||util.lang)===\"en\"?\"en\":\"ja\")+\"|zh-CN\");let mj=JSON.parse(mm);result.push(mj.responseData?mj.responseData.translatedText:batch[k])}}}return result},\n\/\/ 🤖 AI大模型翻译(OpenAI兼容)\naiT(texts,from){const{java,source}=this;let m=source.getLoginInfoMap(),au=util.lgKey(m,\"AI接口地址\"),ak=util.lgKey(m,\"AI密钥\"),am=util.lgKey(m,\"AI模型\");if(!au)throw\"AI翻译未配置:请先在登录界面填写「AI接口地址」,再点「AI翻译测试」验证\";if(!ak)java.toast(\"@⚠️未填写AI密钥:部分平台(如opencode)无需token可直接使用,若你的平台需要凭据请到登录界面填写「AI密钥」\");if(!am)am=\"gpt-4o-mini\";let u=au.replace(\/\\\/+$\/,\"\");if(!\/\\\/chat\\\/completions$\/.test(u))u+=\/\\\/v\\d+$\/.test(u)?\"\/chat\/completions\":\"\/v1\/chat\/completions\";let srcLang=(from||util.lang)===\"en\"?\"英语\":\"日语\",out=[];for(let i=0;i<texts.length;i++){var tx=\"\";if(texts[i])for(let t=0;t<2&&!tx;t++){try{let body=JSON.stringify({model:am,temperature:0.2,messages:[{role:\"system\",content:\"你是专业的小说翻译引擎。用户提供的文本是\"+srcLang+\"原文,请精准翻译成**简体中文**。严格规则:(1)只输出简体中文译文本身;(2)禁止任何解释、注释、拼音、原文片段或引号包装;(3)必须保留原文的换行与段落结构;(4)若原文已是中文则原样返回;(5)禁止把目标语言写成日文\/英文\/任何非中文语言。\"},{role:\"user\",content:texts[i]}]});let hd={\"content-type\":\"application\/json\",\"User-Agent\":\"Mozilla\/5.0 (Linux; Android 14)\"};if(ak)hd.authorization=\"Bearer \"+ak;let j=JSON.parse(String(java.post(u,body,hd,120000).body()));let c=j.choices&&j.choices[0]&&j.choices[0].message&&j.choices[0].message.content;tx=c?String(c).replace(\/^\\s+|\\s+$\/g,\"\"):\"\";if(!tx)throw j.error&&j.error.message||\"空响应\";var _k=(tx.match(\/[\\u3040-\\u309f\\u30a0-\\u30ff]\/g)||[]).length;if(srcLang===\"日语\"&&_k>0&&_k\/tx.length>0.25){java.log(\"AI译文仍以日文为主(\"+_k+\"\/\"+tx.length+\"):\"+tx.substring(0,40));throw \"译文中日文占比过高\"}}catch(e){tx=\"\";if(t)java.log(\"AI翻译第\"+(i+1)+\"段失败:\"+e);else sleep(900)}}out.push(tx||texts[i]);if(i<texts.length-1)sleep(150)}return out},\n\/\/ 🤖 AI翻译测试(优化文案排版)\naiTest(){try{let r=util.aiT.call(this,[\"これはAI翻訳の接続テストです。こんにちは、世界。\"],\"ja\");this.java.longToast(\"🤖 翻译测试成功!\\n\\n\" + r[0])}catch(e){this.java.longToast(\"❌ 翻译测试失败\\n\\n原因:\" + e + \"\\n\\n排查:\\n① AI接口地址 如 https:\/\/api.deepseek.com (无需\/v1,自动补全)\\n② AI密钥 sk-开头(可选:需凭据的平台才填,opencode等免token平台留空)\\n③ AI模型名如 gpt-4o-mini \/ deepseek-chat\\n④ 手机网络能否直连该服务\")}},\n\/\/ 翻译引擎主入口:根据 source.get('teng') 选择 必应\/腾讯\/AI\ntranslateTexts(_texts,option){const {java,source}=this;try{option=option||{};let {from,to}=option;var texts=_texts;if(typeof texts===\"string\"){if(texts.length<10&&!util.filterReg.test(texts))return[texts];texts=util.splitByMaxLenAdjustLines(texts,2000)}if(!(texts&&texts.length))throw\"Invalid input!\";to=(to==\"zh-hans\"||to==\"zh-CN\"||to==\"zh\"||!to)?\"zh\":to;var teng=source.get(\"teng\")+\"\";if(teng===\"ai\")return util.aiT.call(this,texts,from);if(teng===\"tx\")return util.txT.call(this,texts,from);return util.bingT.call(this,texts,from)}catch(e){e=\"@\\u7ffb\\u8bd1\\u5931\\u8d25\\uff1a\\n\"+e;java.log(e);java.toast(e);return typeof _texts===\"string\"?[_texts]:(_texts&&_texts.length?_texts.slice():[])}},\n\/\/ 辅助:从登录信息Map中按前缀取Key\nlgKey(m,pre){try{if(!m)return\"\";var ks=null;try{if(m.keySet){var it=m.keySet().iterator();ks=[];while(it.hasNext())ks.push(String(it.next()))}else ks=Object.keys(m)}catch(e){ks=Object.keys(m)}if(!ks||!ks.length)return\"\";for(var i=0;i<ks.length;i++){var k=String(ks[i]);if(k.indexOf(pre)===0){var v=\"\";try{v=String(m.get?(m.get(k)||\"\"):(m[k]||\"\"))}catch(e2){v=String(m[k]||\"\")}v=v.replace(\/^\\s+|\\s+$\/g,\"\");if(v)return v}}}catch(e){}return\"\"},\n\/\/ 翻译模式(关闭\/自动\/对照)\nxq_trans(){const {java,book}=this;let val=this.getTrans();if(val!==0){let needTag=this.source.get(\"bq\")==1;let intro=needTag?String(book.intro).replace(\/^\\s*#.*\\n\\s*\/,\"\"):book.intro+\"\";let ks=intro.split(\/\\n\\s*\/);if(needTag){var tags=(java.get(\"tags\")+\"\").replace(\/^\\[|\\]$\/g,\"\").split(\/,\\s*\/).join(\"\\uff0c\");ks.unshift(tags)}ks.unshift(book.name,book.author);if(util.noZh(intro+book.name)){let start=needTag?3:2;let arr=this.translate(ks,{start:start});let tagStr=needTag?`\\u6807\\u7b7e(\\u8bd1)\\uff1a#${arr[2].replace(\/\\uff0c\/g,\" #\")}\\n\\u539f\\u6807\\u7b7e\\uff1a#${tags.replace(\/\\uff0c\/g,\" #\")}\\n`:\"\";book.name=arr[0];book.intro=`\\u3000\\u3000\\u7ffb\\u8bd1\\uff1a\\u6a21\\u5f0f${val}\\u3001${util.lang_zh}\\n\\u539f\\u6807\\u9898\\uff1a${ks[0]}\\n\\u4f5c\\u8005(\\u8bd1)\\uff1a${arr[1]}\\n${tagStr}${\"\\u2014\".repeat(24)}\\n${arr.slice(start).join(\"\\n\").replace(\/\\uff1a\\\/\/g,\":\/\")}`.replace(\/\\n\\s*\/g,\"$\\x26\\u3000\\u3000\");java.put(\"lang\",util.lang)}}},\nmulu_trans(list){list=list||this.result;const {java}=this;if(java.get(\"sid\")!=\"\\ud83c\\udde8\\ud83c\\uddf3\"&&java.get(\"lang\")+\"\")if(list.length>0){let titles=Array.from(list,x=>x.title);let ts=this.translate(titles,{forced:1});Array.from(list,(x,i)=>{x.title=ts[i]||x.title})}return list},noImg(v){this.source.put(\"noImg\",v=v?1:\"\");this.java.longToast(v?\"\\n\\u4e0d\\u52a0\\u8f7d\\u6b63\\u6587\\u4e2d\\u56fe\\u7247\\uff0c\\u663e\\u793a\\u5176url\\uff0c\\u56fe\\u7247\\u4f1a\\u5f71\\u54cd\\u6b63\\u6587\\u52a0\\u8f7d\\u901f\\u5ea6\\uff0c\\u6b63\\u6587\\u4e00\\u76f4\\u4e3a\\u7a7a\\u767d\\u65f6\\u5efa\\u8bae\\u5f00\\u542f\":\n\"\\n\\u52a0\\u8f7d\\u6b63\\u6587\\u4e2d\\u56fe\\u7247\\uff08\\u9ed8\\u8ba4\\uff09\\uff0c\\u8f83\\u591a\\u56fe\\u7247\\u4f1a\\u4e25\\u91cd\\u5f71\\u54cd\\u6b63\\u6587\\u52a0\\u8f7d\\u901f\\u5ea6\")},tihuan_trans(str){str=str||this.result;str=util.noZh(str)?util.fixImg(this.translate(str)):str;if(this.source.get(\"noImg\")==1)str=str.replace(\/<img src=\"(.+?),.*?>\/g,\"$1\");return str}};\n\nfunction translate(str,option){str=str||this.result;let val=this.getTrans();let isStr=!!str.split;let fn=util.translateTexts.bind(this);if(option&&option.forced||val==1)var res=fn(str,option);else if(val==0)return isStr?str:str.join(\"\\n\");else if(val==2){let arr=isStr?str.split(\"\\n\"):str;res=fn(arr,option);for(let i=option&&option.start||0,n=res.length;i<n;i++){let x=res[i];res[i]=\/^<img .+>$\/.test(x)?arr[i]:`${arr[i]}${x.length>6?\"\\n\":\"\"}\\ud83d\\udd04\\ufe0f${x}`}}return isStr?res.join(\"\\n\"):res}\n\nfunction getTrans(){let s=this.source.get(\"trans\")+\"\";if(s===\"\"){this.source.put(\"trans\",1);return 1}return isNaN(s=+s)?1:s}\n\n\/\/ ============================================================\n\/\/ 🐱 原有功能:检测过度访问\n\/\/ ============================================================\n\nfunction checkOverAccess() {\n const {java, cache, source} = this;\n let lastCheck = cache.get('overAccessCheckTime');\n let now = Date.now();\n if (lastCheck && (now - lastCheck) < 4*60*60*1000) return;\n cache.put('overAccessCheckTime', now);\n try {\n let url = 'https:\/\/www.pixiv.net\/rpc\/index.php?mode=latest_message_threads2&num=5&lang=zh';\n let resp = java.ajax(gethd(url));\n if (!resp) return;\n let data = JSON.parse(resp);\n if (data.error) return;\n let threads = data.body.message_threads || [];\n let msg = threads.find(item => item.thread_name === 'pixiv事務局');\n if (msg && (now - msg.modified_at*1000) < 3*24*60*60*1000) {\n let time = new Date(msg.modified_at*1000);\n let timeStr = time.toLocaleString();\n java.longToast(`⚠️ 您于 ${timeStr} 触发 Pixiv 过度访问,请修改密码并重新登录。`);\n }\n } catch(e) {\n \/\/ 静默忽略\n }\n}\n\n\/\/ ============================================================\n\/\/ 🐱 原有功能:Pixiv OAuth 登录\n\/\/ ============================================================\n\nfunction pxOauth(postBody) {\n\tconst {java} = this;\n\tlet time = java.timeFormatUTC(Date.now(),\"yyyy-MM-dd'T'HH:mm:ss'+00:00'\",8*60*60*1000);\n\tlet hash = timemd5(time);\n\tlet req = 'POST \/auth\/token HTTP\/1.1\\r\\nHost: oauth.secure.pixiv.net\\r\\n'\n\t\t+'User-Agent: '+ua+'\\r\\n'\n\t\t+'content-type: application\/x-www-form-urlencoded\\r\\n'\/*--- 🎉 小彩蛋:推荐小说《说好低调发育,全服公告什么鬼?》作者:稀粥西洲 🎉 --- *\/\n\t\t+'x-client-time: '+time+'\\r\\nx-client-hash: '+hash+'\\r\\n'\n\t\t+'accept-language: '+a_l+'\\r\\napp-os: Android\\r\\napp-os-version: Android 14\\r\\napp-version: '+appv+'\\r\\n'\n\t\t+'Content-Length: '+postBody.length+'\\r\\nConnection: close\\r\\n\\r\\n'+postBody;\n\tlet sf = Packages.javax.net.ssl.SSLSocketFactory.getDefault();\n\tlet ips = ['210.140.139.155','210.140.139.152','210.140.139.158','210.140.139.161'];\n\tlet sock = null, lastErr = '';\n\tfor (let i = 0; i < ips.length; i++) {\n\t\ttry {\n\t\t\tlet addr = Packages.java.net.InetAddress.getByName(ips[i]);\n\t\t\tsock = sf.createSocket(addr, 443);\n\t\t\tsock.setSoTimeout(12000);\n\t\t\tlet os = sock.getOutputStream();\n\t\t\tos.write(new Packages.java.lang.String(req).getBytes('UTF-8'));\n\t\t\tos.flush();\n\t\t\tlet rd = new Packages.java.io.BufferedReader(new Packages.java.io.InputStreamReader(sock.getInputStream(),'UTF-8'));\n\t\t\tlet sb = new Packages.java.lang.StringBuilder();\n\t\t\tlet line;\n\t\t\twhile ((line = rd.readLine()) != null) { sb.append(line); sb.append('\\n'); }\n\t\t\treturn String(sb.toString());\n\t\t} catch(e) {\n\t\t\tlastErr = e;\n\t\t\ttry { if (sock != null) sock.close(); } catch(e2) {}\n\t\t}\n\t}\n\tthrow lastErr == '' ? 'oauth直连失败:无可用IP' : lastErr;\n}",
"lastUpdateTime": "1788113914866",
"loginCheckJs": "\/\/java.toast('登录检查:'+result);\n\nif (result.code() == 400) {\n\tsource.login();\n\tsleep(500);\n\tlet url = gethd(result.url());\n\tresult = java.connect(url);\n\t}\nif (result.code() == 200) {\n checkOverAccess();\n}\nresult",
"loginUi": "[ \n {\n name: \"下载pixEz(支持插画、回复评论等)\",\n type: \"button\",\n action: \"https:\/\/gh-proxy.org\/https:\/\/github.com\/Notsfsssf\/pixez-flutter\",\n \"style\": {\n \"layout_flexGrow\": 1,\n \"layout_flexBasisPercent\": 1\n }\n },\n {\n name: \"token\",\n type: \"text\"\n },\n {\n name: \"token说明\",\n type: \"button\",\n action: \"java.longToast(`\ntoken说明:\n填写该值后点击右上角√进行登录\n可以通过获取token按钮得到(不需要跳转app)\n阅读正式版无法支持获取token功能`);\",\n style: {\n \"layout_flexGrow\": 1,\n \"layout_flexBasisPercent\": 0.4\n }\n },\n {\n name: \"获取token\",\n type: \"button\",\n action: \"Login()\",\n style: {\n \"layout_flexGrow\": 1,\n \"layout_flexBasisPercent\": 0.4\n }\n },\n {\n name: \"id\",\n type: \"text\"\n },\n {\n name: \"id说明\",\n type: \"button\",\n action: \"java.longToast(`\nid说明:\n登录时该值为空会自动填写该值,这是登录账号的ID(可手动更改)。\n发现页的收藏分类加载的该ID的收藏`);\",\n style: {\n \"layout_flexGrow\": 1,\n \"layout_flexBasisPercent\": 0.2\n }\n },\n {\n name: \"搜索说明\",\n type: \"button\",\n action: \"java.longToast(`\n搜索说明:\n默认使用关键词搜索\n输入小说id号显示对应的小说\n输入“正文@许斌”搜索正文含许斌的小说\n输入“作者@69559022”搜索指定id作者的书\n输入“@作者名”搜索该作者的作品(无需数字ID)`);\",\n style: {\n \"layout_flexGrow\": 1,\n \"layout_flexBasisPercent\": 0.2\n }\n },\n {\n name: \"书名\",\n type: \"text\"\n },\n {\n name: \"↑追更该书\",\n type: \"button\",\n action: \"scz(3)\",\n style: {\n \"layout_flexGrow\": 1,\n \"layout_flexBasisPercent\": -1\n }\n },\n {\n name: \"复制id\",\n type: \"button\",\n action: \"fuzhi(2)\",\n style: {\n \"layout_flexGrow\": 1,\n \"layout_flexBasisPercent\": 0.2\n }\n },\n {\n name: \"取消追更\",\n type: \"button\",\n action: \"scz(30)\",\n style: {\n \"layout_flexGrow\": 1,\n \"layout_flexBasisPercent\": -1\n }\n },\n {\n name: \"章节\",\n type: \"text\"\n },\n {\n name: \"↑收藏该章\",\n type: \"button\",\n action: \"scz(1,'public')\",\n \"style\": {\n \"layout_flexGrow\": 1,\n \"layout_flexBasisPercent\": 0.4\n }\n },\n {\n name: \"取消收藏\",\n type: \"button\",\n action: \"scz(10)\",\n style: {\n \"layout_flexGrow\": 1,\n \"layout_flexBasisPercent\": 0.4\n }\n },\n {\n name: \"↑私密收藏\",\n type: \"button\",\n action: \"scz(1,'private')\",\n style: {\n \"layout_flexGrow\": 1,\n \"layout_flexBasisPercent\": 0.4\n }\n },\n {\n name: \"详情\",\n type: \"button\",\n action: \"caption()\",\n style: {\n \"layout_flexGrow\": 1,\n \"layout_flexBasisPercent\": 0.4\n }\n },\n {\n name: \"作者\",\n type: \"text\"\n },\n {\n name: \"↑关注作者\",\n type: \"button\",\n action: \"scz(2)\",\n style: {\n \"layout_flexGrow\": 1,\n \"layout_flexBasisPercent\": 0.4\n }\n },\n {\n name: \"取消关注\",\n type: \"button\",\n action: \"scz(20)\",\n style: {\n \"layout_flexGrow\": 1,\n \"layout_flexBasisPercent\": 0.4\n }\n },\n {\n name: \"↑私密关注\",\n type: \"button\",\n action: \"scz(2,'private')\",\n style: {\n \"layout_flexGrow\": 1,\n \"layout_flexBasisPercent\": 0.4,\n \"layout_wrapBefore\": true\n }\n },\n {\n name: \"复制id\",\n type: \"button\",\n action: \"fuzhi(1)\",\n style: {\n \"layout_flexGrow\": 1,\n \"layout_flexBasisPercent\": 0.4\n }\n },\n {\n name: \"购买token\",\n type: \"button\",\n action: \"java.longToast('喵~购买链接被本喵挠掉啦!请勿轻信任何购买渠道,保护好你的小钱钱(๑•̀ㅂ•́)و✧')\",\n \"style\": {\n \"layout_flexGrow\": 1,\n \"layout_flexBasisPercent\": 1\n }\n },\n {\n name: \"查看设置\",\n type: \"button\",\n action: \"showSettings()\",\n \"style\": {\n \"layout_flexGrow\": 1,\n \"layout_flexBasisPercent\": 0.4\n }\n },\n {\n name: \"(ฅ´ω`ฅ)\",\n type: \"button\",\n action: \"showCatBlessing()\",\n \"style\": {\n \"layout_flexGrow\": 1,\n \"layout_flexBasisPercent\": 0.4\n }\n },\n {\n name: \"🖼️图片显示\",\n type: \"button\",\n action: \"toggleImg()\",\n \"style\": {\n \"layout_flexGrow\": 1,\n \"layout_flexBasisPercent\": 0.4\n }\n },\n \t{\n name: \"🔢补充序号\",\n type: \"button\",\n action: \"xvhao()\",\n style: {\n \"layout_flexGrow\": 1,\n \"layout_flexBasisPercent\": 0.4\n }\n },\n \t{\n name: \"📝简介标签\",\n type: \"button\",\n action: \"biaoqian()\",\n \"style\": {\n \"layout_flexGrow\": 1,\n \"layout_flexBasisPercent\": 0.4\n }\n },\n {\n name: \"📄章首描述\",\n type: \"button\",\n action: \"toggleCaption()\",\n \"style\": {\n \"layout_flexGrow\": 1,\n \"layout_flexBasisPercent\": 0.4\n }\n },\n {\n name: \"🎀分割线式\",\n type: \"button\",\n action: \"cycleDividerStyle()\",\n \"style\": {\n \"layout_flexGrow\": 1,\n \"layout_flexBasisPercent\": 0.4\n }\n },\n {\n name: \"😊表情显示\",\n type: \"button\",\n action: \"toggleEmoji()\",\n \"style\": {\n \"layout_flexGrow\": 1,\n \"layout_flexBasisPercent\": 0.4\n }\n },\n {\n name: \"🔊注音替换\",\n type: \"button\",\n action: \"toggleRuby()\",\n \"style\": {\n \"layout_flexGrow\": 1,\n \"layout_flexBasisPercent\": 0.4\n }\n },\n {\n name: \"📐特殊语法\",\n type: \"button\",\n action: \"toggleSyntax()\",\n \"style\": {\n \"layout_flexGrow\": 1,\n \"layout_flexBasisPercent\": 0.4\n }\n },\n \t{\n name: \"📘书名标识\",\n type: \"button\",\n action: \"gongcun()\",\n style: {\n \"layout_flexGrow\": 1,\n \"layout_flexBasisPercent\": 0.4\n }\n },\n {\n name: \"📖按钮说明\",\n type: \"button\",\n action: \"showButtonHelp()\",\n \"style\": {\n \"layout_flexGrow\": 1,\n \"layout_flexBasisPercent\": 0.4\n }\n },\n \t{\n name: \"书源介绍\",\n type: \"button\",\n action: \"showSourceIntro()\",\n \"style\": {\n \"layout_flexGrow\": 1,\n \"layout_flexBasisPercent\": 0.4\n }\n },\n {\n name: \"微软密钥(Azure·仅腾讯模式生效)\",\n type: \"text\"\n },\n {\n name: \"AI接口地址(OpenAI兼容)\",\n type: \"text\"\n },\n {\n name: \"AI密钥(OpenAI兼容·可选)\",\n type: \"text\"\n },\n {\n name: \"AI模型(OpenAI兼容·选填)\",\n type: \"text\"\n },\n \t{\n name: \"🌐翻译模式\",\n type: \"button\",\n action: \"changeTrans()\",\n \"style\": {\n \"layout_flexGrow\": 1,\n \"layout_flexBasisPercent\": 0.4\n }\n },\n \t{\n name: \"🤖翻译测试\",\n type: \"button\",\n action: \"util.aiTest.call(this)\",\n \"style\": {\n \"layout_flexGrow\": 1,\n \"layout_flexBasisPercent\": 0.4\n }\n },\n \t{\n name: \"🔁翻译引擎\",\n type: \"button\",\n action: \"changeEng()\",\n \"style\": {\n \"layout_flexGrow\": 1,\n \"layout_flexBasisPercent\": 0.4\n }\n },\n \t{\n name: \"📖翻译说明\",\n type: \"button\",\n action: \"java.longToast(`\\n自动翻译日语\/英语为简体中文。\\n\\n【模式】点「🌐翻译模式」循环切换:关闭 → 自动识别(默认) → 对照显示。\\n\\n【引擎】点「🔁翻译引擎」循环切换:\\n🟢必应翻译:免密钥、国内直连,开箱即用;\\n🔵腾讯TranSmart:填了「微软密钥」就走 Azure 官方通道,质量更稳;没填密钥则走腾讯自有引擎(失败自动降级 MyMemory);\\n🤖AI大模型:OpenAI 兼容接口,需填「AI接口地址」(如 https:\/\/api.deepseek.com ,\/v1 自动补全),「AI密钥」可选(部分平台免token),「AI模型」选填默认 gpt-4o-mini。\\n\\n填完 AI 配置请点「🤖翻译测试」验证连通性。\\n\\n本喵不知道ai翻译功能被没被咱搞坏 \\n╮(︶﹏︶)╭`)\",\n \"style\": {\n \"layout_flexGrow\": 1,\n \"layout_flexBasisPercent\": 0.4\n }\n },\n {\n name: \"屏蔽标签\",\n type: \"text\"\n }\n]",
"loginUrl": "function gongcun() {\nlet gc = source.get('gc');\nif(gc!=1) {source.put('gc',1);java.toast('🟢已开启\\n书名开头会有📘符号');}\nelse {source.put('gc',0);java.toast('⚫已关闭\\n不会添加📘');}\n\t}\nfunction xvhao() {\nlet xh = source.get('xh');\nif(xh!=1) {source.put('xh',1);java.toast('🟢已开启\\n会自动补充章节名序号');}\nelse {source.put('xh',0);java.toast('⚫已关闭\\n不会补充序号');}\n\t}\nfunction biaoqian() {\nlet bq = source.get('bq');\nif(bq!=1) {source.put('bq',1);java.toast('🟢已开启\\n会在简介显示作品标签');}\nelse {source.put('bq',0);java.toast('⚫已关闭\\n不会显示简介标签');}\n\t}\n\nfunction toggleImg() {\n let noImg = source.get('noImg');\n if (noImg == 1) {\n source.put('noImg', 0);\n java.toast('🟢 已开启显示插图');\n } else {\n source.put('noImg', 1);\n java.toast('⚫ 已关闭插图显示(仅显示链接)');\n }\n java.reLoginView();\n}\n\n\/\/ ---- 章首描述开关 ----\nfunction toggleCaption() {\n let val = source.get('showCaption');\n if (val == 1) {\n source.put('showCaption', 0);\n java.toast('⚫ 已关闭章首描述');\n } else {\n source.put('showCaption', 1);\n java.toast('🟢 已开启章首描述');\n }\n java.reLoginView();\n}\n\n\/\/ ---- 注音替换开关 ----\nfunction toggleRuby() {\n let val = source.get('rubyReplace');\n if (val == 1) {\n source.put('rubyReplace', 0);\n java.toast('⚫ 已关闭注音替换。\\n本喵也不知道有什么用哦~ 想看效果的话,再点一次开启就好啦!');\n } else {\n source.put('rubyReplace', 1);\n java.toast('🟢 已开启注音替换(显示为括号)。\\n本喵也不知道有什么用哦~ 你自己试试看就知道啦!(ฅ´ω`ฅ)');\n }\n java.reLoginView();\n}\n\n\/\/ ---- 表情\/印章显示开关 ----\nfunction toggleEmoji() {\n let val = source.get('showEmoji');\n if (val == 1) {\n source.put('showEmoji', 0);\n java.toast('⚫ 已关闭表情\/印章显示。\\n本喵也不知道有什么用哦~ 想看效果的话,再点一次开启就好啦!');\n } else {\n source.put('showEmoji', 1);\n java.toast('🟢 已开启表情\/印章显示。\\n本喵也不知道有什么用哦~ 你自己试试看就知道啦!(ฅ´ω`ฅ)');\n }\n java.reLoginView();\n}\n\n\/\/ ---- 特殊语法补充开关 ----\nfunction toggleSyntax() {\n let val = source.get('showSyntax');\n if (val == 1) {\n source.put('showSyntax', 0);\n java.toast('⚫ 已关闭特殊语法补充。\\n本喵也不知道有什么用哦~ 想看效果的话,再点一次开启就好啦!');\n } else {\n source.put('showSyntax', 1);\n java.toast('🟢 已开启特殊语法补充([chapter:][jump:][[jumpuri:]]等)。\\n本喵也不知道有什么用哦~ 你自己试试看就知道啦!(ฅ´ω`ฅ)');\n }\n java.reLoginView();\n}\n\n\/\/ ---- 分割线样式循环 ----\nfunction cycleDividerStyle() {\n let mode = parseInt(source.get('dividerMode')) || 0;\n let styles = [\n '',\n '━━━━━━━━━━━━━━━━',\n '━━━ (=^・^=) ━━━ ( =^・^= ) ━━━',\n '━━━ ฅ(^ω^ฅ) ━━━ ฅ(^ω^ฅ) ━━━',\n '—— 这 · 里 · 是 · 分 · 割 · 线 ——'\n ];\n mode = (mode + 1) % 5;\n source.put('dividerMode', mode);\n if (mode == 0) {\n java.toast('🎀 分割线式\\n已关闭');\n } else {\n java.toast('🎀 分割线式\\n' + styles[mode]);\n }\n}\n\nfunction showSettings() {\n let gc = source.get('gc') == 1 ? '🟢开启' : '⚫关闭';\n let xh = source.get('xh') == 1 ? '🟢开启' : '⚫关闭';\n let bq = source.get('bq') == 1 ? '🟢开启' : '⚫关闭';\n let noImg = source.get('noImg') == 1 ? '⚫隐藏' : '🟢显示';\n let trans = source.get('trans') || '1';\n let transMap = {'0':'⚫关闭','1':'🟢自动识别(默认)','2':'🟢对照显示'};\n let transStr = transMap[trans] || trans;\n let showCaption = source.get('showCaption') == 1 ? '🟢开启' : '⚫关闭';\n let rubyReplace = source.get('rubyReplace') == 1 ? '🟢开启' : '⚫关闭';\n let showEmoji = source.get('showEmoji') == 1 ? '🟢开启' : '⚫关闭';\n let showSyntax = source.get('showSyntax') == 1 ? '🟢开启' : '⚫关闭';\n let dividerMode = parseInt(source.get('dividerMode')) || 0;\n let modeNames = ['⚫关闭', '━━━━━━━━━', '━(=^・^=)━', '━ฅ(^ω^ฅ)━', '——分割线——'];\n let modeDisplay = modeNames[dividerMode] || modeNames[0];\n let teng = source.get('teng') + '';\n let tengMap = {'bing':'🟢必应翻译(免密钥)','tx':'🔵腾讯TranSmart','ai':'🤖AI大模型(OpenAI兼容)'};\n let tengStr = tengMap[teng] || '🟢必应翻译(免密钥)';\n let msg = '\\n🖼️图片显示:' + noImg +\n '\\n🔢补充序号:' + xh +\n '\\n📝简介标签:' + bq +\n '\\n📄章首描述:' + showCaption +\n '\\n😊表情显示:' + showEmoji +\n '\\n🔊注音替换:' + rubyReplace +\n '\\n📐特殊语法:' + showSyntax +\n '\\n📘书名标识:' + gc +\n '\\n🌐翻译模式:' + transStr +\n '\\n🔁翻译引擎:' + tengStr +\n '\\n🎀分割线式:' + modeDisplay;\n java.longToast(msg);\n}\n\n\/\/ ---- 📖书源介绍 ----\nfunction showSourceIntro() {\n let intro = '📖 本小说书源基于以下版本合并修改:\\n\\n' +\n '✨ 洛娅橙原版:\\n' +\n ' Pixiv 小说书源的早期基础版本。\\n\\n' +\n '✨ 添加翻译功能的版本:\\n' +\n ' 由不知名人士在洛娅橙原版基础上添加了微软翻译功能,\\n' +\n ' 后来又被加入了商业推广广告。\\n\\n' +\n '✨ laizhiyu 修复版:\\n' +\n ' 修复了网络直连问题,并替换为三引擎翻译模块\\n' +\n ' (必应\/腾讯\/AI),彻底解决翻译失效问题。\\n\\n' +\n '✨ 猫猫黛西(由 DeepSeek 全程代劳):\\n' +\n ' 基于以上版本,去除所有广告,\\n' +\n ' 进行了界面优化和功能调整。\\n\\n' +\n '感谢所有为开源做出贡献的大佬们!(ฅ´ω`ฅ)';\n java.longToast(intro);\n}\n\n\/\/ ---- 📖按钮说明 ----\nfunction showButtonHelp() {\n let msg = '📖 按钮功能说明\\n\\n' +\n '本喵也不知道咱加的按钮有没有用,但你可以点开试试~\\n\\n' +\n '🖼️ 图片显示:切换正文中插图的显示\/隐藏\\n' +\n '🔢 补充序号:自动为章节名添加序号\\n' +\n '📝 简介标签:在书籍简介中显示标签\\n' +\n '📄 章首描述:在正文前显示小说前言\/简介\\n' +\n '🎀 分割线式:循环切换4种小猫风格分割线\\n' +\n '😊 表情显示:将(表情代码)替换为表情图片\\n' +\n '🔊 注音替换:将[[rb:汉字>读音]]替换为汉字(读音)\\n' +\n '📐 特殊语法:支持[chapter:][jump:][[jumpuri:]]等\\n' +\n '📘 书名标识:在书名前添加📘符号\\n' +\n '🌐 翻译模式:关闭\/自动识别\/对照显示 三态循环\\n' +\n '🔁 翻译引擎:必应\/腾讯\/AI 三引擎循环切换\\n' +\n '🤖 翻译测试:验证AI翻译配置是否连通\\n' +\n '📖 翻译说明:查看详细的翻译使用说明';\n java.longToast(msg);\n}\n\n\/\/ ---- 🌐翻译模式 ----\nfunction changeTrans(){\n let n = this.getTrans();\n let v = n > 1 ? 0 : n + 1;\n this.source.put('trans', v);\n let modeDesc = v == 0 ? '⚫ 关闭' : (v == 1 ? '🟢 自动识别(默认)' : '🟢 对照显示');\n java.toast('🌐 翻译模式:' + modeDesc);\n}\n\n\/\/ ---- 🔁翻译引擎 ----\nfunction changeEng(){\n var c = this.source.get('teng') + '';\n if (c !== 'tx' && c !== 'ai') c = 'bing';\n var v = c === 'bing' ? 'tx' : (c === 'tx' ? 'ai' : 'bing');\n this.source.put('teng', v);\n var engMap = {\n 'bing': '🟢 必应翻译(免密钥·国内直连)',\n 'tx': '🔵 腾讯TranSmart(微软密钥走Azure官方)',\n 'ai': '🤖 AI大模型(OpenAI兼容,AI密钥可选)'\n };\n java.toast('🔁 翻译引擎:\\n' + engMap[v]);\n}\n\nfunction login() {\nlet Info = source.getLoginInfoMap();\ntry {\nlet tk = Info.token;\nif (!tk || tk == '') throw 'TOKEN为空,请先填写';\nlet body = `client_id=MOBrBDS8blbauoSck0ZfDbtuzpyT&client_secret=lsACyCD94FhDUtGTXi3QzcFE2uU1hqtDaKeqrdwj&grant_type=refresh_token&refresh_token=${tk}&include_policy=true`;\nlet rr;\ntry {\nrr = pxOauth(body);\n} catch(err) {\njava.log('px oauth直连失败,回退常规请求:'+err);\nlet time2 = java.timeFormatUTC(Date.now(),\"yyyy-MM-dd'T'HH:mm:ss'+00:00'\",8*60*60*1000);\nlet headers = {\n 'User-Agent': ua,\n 'content-type': 'application\/x-www-form-urlencoded',\n 'x-client-hash': timemd5(time2),\n 'accept-language': a_l,\n 'app-version': appv,\n 'app-os-version': 'Android 6.0',\n 'x-client-time': time2,\n 'app-os': 'Android',\n 'host': 'oauth.secure.pixiv.net'\n };\nlet url = 'https:\/\/oauth.secure.pixiv.net\/auth\/token';\nurl = url.replace(\"oauth.secure.pixiv.net\",\"210.140.139.155\");\nrr = String(java.post(url,body,headers).body());\n}\nif (rr.indexOf('{') >= 0) rr = rr.substring(rr.indexOf('{'));\nlet atk = rr.match(\/\"access_token\"[:\\s\"]+([^\"]+)\/)[1];\nsource.putLoginHeader(atk);\nif (Info.id=='') {\n\tInfo.id = com.jayway.jsonpath.JsonPath.read(rr, \"$.user.id\");}\nsource.putLoginInfo(JSON.stringify(Info));\n} catch(err) {\n\tjava.toast('\\n💔登录失败');\n\tjava.log('px登录失败:'+err);\n \tsleep(600);}\n}\n\nfunction scz(x, restrict) {\n\tlet headers = gethd();\n\tlet url = \"https:\/\/210.140.139.155\/\";\n\tlet body,nm,tt,ttt;\n\tif (x==1) {\n\t url += 'v2\/novel\/bookmark\/add';\n\t \tlet id = cache.get('pxid');\n\t \tif (id=='') ttt='请刷新章节';\n\t \tbody = 'novel_id='+id+'&restrict=' + (restrict || 'public');\n\t \tnm = source.getLoginInfoMap().get('章节');\n\t \ttt= (restrict=='private'? '私密收藏' : '公开收藏');\n\t } else if(x==2) {\n\t \turl += 'v1\/user\/follow\/add';\n\t \tlet uid = cache.get('pxuid');\n\t \tif (uid=='') ttt='请刷新章节或详情页';\n\t \tbody = 'user_id='+uid+'&restrict=' + (restrict || 'public');\n\t \tnm = source.getLoginInfoMap().get('作者');\n\t \ttt= (restrict=='private'? '私密关注' : '公开关注');\n\t \t} else if(x==10) {\n\t \turl += 'v1\/novel\/bookmark\/delete';\n\t \tlet id = String(cache.get('pxid'));\n\t \tbody = id ? 'novel_id='+id : '';\n\t \tnm = source.getLoginInfoMap().get('章节');\n\t \ttt='取消收藏';\n\t \t} else if(x==20) {\n\t \turl += 'v1\/user\/follow\/delete';\n\t \tlet uid = String(cache.get('pxuid'));\n\t \tbody = uid ? 'user_id='+uid : '';\n\t \tnm = source.getLoginInfoMap().get('作者');\n\t \ttt='取消关注';\n\t \t} else if(x==3) {\n\t \turl += 'v1\/watchlist\/novel\/add';\n\t \tlet sid = cache.get('pxsid');\n\t \tif (sid=='') ttt='请刷新详情页';\n\t \tbody = 'series_id='+sid;\n\t \tnm = source.getLoginInfoMap().get('书名');\n\t \ttt='追更';\n\t \t} else if(x==30) {\n\t \turl += 'v1\/watchlist\/novel\/delete';\n\t \tlet sid = String(cache.get('pxsid'));\n\t \tbody = sid ? 'series_id='+sid : '';\n\t \tnm = source.getLoginInfoMap().get('书名');\n\t \ttt='取消追更';\n\t \t}\n\n\ttry {\n\t\tif (ttt) {java.longToast(ttt);throw 't空';}\n\t\tif (!body) throw 'b空';\n\t\theaders['host']='app-api.pixiv.net';\n\t\tlet jg = java.post(url,body,headers).statusCode();\n\t\tif (jg!=200) throw tt+'响应码异常';\n\t\telse java.longToast(`\\n已${tt}:\\n${nm}`);\n\t\t} catch(e) {\n\t\t\tif (!ttt) java.toast(`\\n${tt}失败`);\n\t\t\tjava.log(e);}\n\t}\n\nfunction reck() {\nsource.removeLoginHeader();\ncookie.removeCookie('https:\/\/accounts.pixiv.net');\ncookie.removeCookie('https:\/\/accounts.google.com');\ncookie.removeCookie('https:\/\/api.weibo.com');\n\t}\n\nfunction Login() {\nlet rkey = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~';\nlet cv='';\nfor (let i = 0; i < 128; i++) {\n\tlet ra = Math.floor(Math.random()*rkey.length);\n\tcv+=rkey.charAt(ra);}\n\nlet aly = new JavaImporter(\nPackages.cn.hutool.crypto.digest.Digester,\nPackages.cn.hutool.core.codec.Base64,\nPackages.cn.hutool.crypto.digest.DigestAlgorithm);\nwith (aly) {\n\tlet asBs = Packages.java.lang.String(cv).getBytes(\"US-ASCII\");\n\tlet digester = new Digester(DigestAlgorithm.SHA256);\n\tlet hashBs = digester.digest(asBs);\n\tvar codeChallenge = Base64.encodeUrlSafe(hashBs);\n}\n\nlet urllg =`https:\/\/app-api.pixiv.net\/web\/v1\/login?code_challenge=${codeChallenge}&code_challenge_method=S256&client=pixiv-android`;\nreck();\n\nlet wbua=java.getWebViewUA().replaceAll(\"; wv| Version\\\/4.0\",'')+'';\nif (\/HUA\\s*WEI\/i.test(wbua))\nwbua=\"Mozilla\/5.0 (Linux; Android 14; RMX3366 Build\/UKQ1.230924.001) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/135.0.7049.100 Mobile Safari\/537.36\";\n\nlet bb=java.startBrowserAwait(urllg+`,{\n\"headers\":{\n\t\"User-Agent\": \"${wbua}\"\n\t}}`,'登录',false).body();\nlet code;\nif (bb.includes('<title>Online com')) {\nsleep(600);\njava.toast('稍等');\nlet over = java.webViewGetOverrideUrl(bb,'https:\/\/app-api.pixiv.net\/','','pixiv:.*');\ncode = over.match(\/code=([^&]+)\/);\n}\nreck();\n\nlet token;\nif (code) {\nlet tkurl = 'https:\/\/oauth.secure.pixiv.net\/auth\/token';\nlet headers = gethd();\nlet body = `code_verifier=${cv}&code=${code[1]}&grant_type=authorization_code&redirect_uri=https:\/\/app-api.pixiv.net\/web\/v1\/users\/auth\/pixiv\/callback&client_id=MOBrBDS8blbauoSck0ZfDbtuzpyT&client_secret=lsACyCD94FhDUtGTXi3QzcFE2uU1hqtDaKeqrdwj&include_policy=true`;\nlet tkr = java.post(tkurl,body,headers);\ntoken = tkr.body().match(\/refresh_token\":\"([^\"]+)\/);\n}\n\nif (token) {\nlet htm = `data:text\/html;charset=utf-8,<html>\n<head>\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><style>\nh2 {\n\ttext-align: center;\n\tline-height: 6;}\ntextarea {\n\tfont-size: 12px;\n\twidth: 96%;\n\tmargin: 10px 2%;\n\tpadding: 6px;}\n.ann {\n\tdisplay: flex;\n\tjustify-content: center;\n\talign-items: center;\n\theight: 50vh;}\nbutton {\n\tbackground-color: rgb(76,175,80);\n\tcolor: white;\n\tborder: none;\n\tborder-radius: 4px;\n\theight: 6vh;\n\twidth: 30vw;\n\toverflow: hidden;\n\ttransition: font-size 0.3s;\n\tfont-size: 16px;}\n.an-s {\n\tfont-size: 12px;}\n.alert-overlay {\n\tposition: fixed;\n\ttop: 0;\n\tleft: 0;\n\twidth: 100%;\n\theight: 100%;\n\tbackground: rgba(0, 0, 0, 0.6);\n\tdisplay: none;\n\tjustify-content: center;\n\talign-items: center;\n\tz-index: 9999;}\n.alert-box {\n\tbackground: rgb(232,234,246);\n\tpadding: 10px;\n\tborder-radius: 12px;\n\tbox-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);\n\tmin-width: 100px;\n\ttext-align: center;}\n<\/style><\/head>\n<body>\n<div class=\"alert-overlay\" id=\"alertO\">\n <div class=\"alert-box\">\n <p>已复制到剪贴板:<\/p>\n <p id=\"alertM\" style=\"font-size: 12px;\"><\/p>\n <\/div>\n<\/div>\n<h2>Token获取成功🥳<\/h2>\n<textarea readonly id=\"copyt\" rows=\"3\">${token[1]}<\/textarea>\n<p style=\"font-size: 12px;\">请复制粘贴到登录界面的token框,然后点击√进行登录<\/p>\n<div class=\"ann\">\n<button id=\"btn1\" onclick=\"copy()\">复制<\/button>\n<\/div>\n<script>\nfunction showAlert(txt, time) {\nconst overlay = document.getElementById('alertO');\nconst message = document.getElementById('alertM');\nmessage.textContent = txt;\noverlay.style.display = 'flex';\nif (time > 0) {\n\tsetTimeout(() => {\n\t\toverlay.style.display = 'none';\n\t\t}, time);\n\t}\n}\nfunction copy() {\nconst btn = document.getElementById('btn1');\nbtn.classList.add('an-s');\nconst cpt = document.getElementById(\"copyt\");\ncpt.select();\ntry {\n const cpy = document.execCommand(\"copy\");\n if (cpy.length<9) throw '异常';\n showAlert(cpt.value, 1000);\n } catch (e) {alert(\"复制失败,请手动复制\");}\nsetTimeout(() => {\n\tbtn.classList.remove('an-s');\n\t}, 450);\n}\n<\/script>\n<\/body><\/html>`;\n\njava.startBrowser(htm,'获取token');\njava.log(token[1]);\n\t} else {sleep(700);java.toast('获取失败😭');}\n}\n\nfunction fuzhi(x) {\n\tif (x==1) {\n\tlet uid = cache.get('pxuid');\n\tcopy(uid);}\n\tif (x==2) {\n\tlet sid = cache.get('pxsid');\n\tcopy(sid);}\n\t}\n\nfunction caption() {\n\tlet lyc=cache.getFromMemory('pxcjj');\n\tif (lyc) lookc(lyc);\n\telse java.longToast('请刷新正文');\n\t}\n\nfunction showCatBlessing() {\n var catBlessings = [\n '猫猫祝你今天心情超好~ 多笑笑,好运自然来喵!(ฅ´ω`ฅ)',\n '愿猫猫的柔软治愈你~ 今天也要好好吃饭、好好休息喵!',\n '猫猫保佑你嘎嘎!今天更容易发现生活中的小确幸哦~',\n '愿你像猫猫一样慵懒又幸福,鱼干自由,阳光满屋喵!',\n '猫猫说:你今天超棒的!继续保持,好运正在路上喵~',\n '愿你今天眼睛亮亮的,发现更多美好,烦恼统统退散喵!',\n '猫猫赐你一天好心情buff!不易低落,不易烦躁,开心一整天喵!',\n '愿你今天皮肤光滑、心情愉悦,像猫猫一样优雅又自在喵!',\n '猫猫觉得你很有眼缘~ 今天运气会变好,惊喜等着你喵!',\n '愿你今天精神饱满,做事顺顺利利,猫猫在背后保佑你喵!',\n '哈!(ᗒᗣᗕ)՞',\n '愿你今天说话都特别顺溜,好运buff已到位,冲鸭!'\n ];\n var idx = Math.floor(Math.random() * catBlessings.length);\n java.longToast('猫猫黛西:' + catBlessings[idx]);\n}",
"respondTime": 180705,
"ruleBookInfo": {
"author": "$.novel_series_detail.user.name\n<js>\nlet uid = java.get('uid');\nlet auth = result || String(book.author).replace(\/[@\\u200b]+\/,'');\nif (uid == '') {uid = java.getString('$.novel_series_detail.user.id');}\nlet Info=source.getLoginInfoMap();\nInfo['作者'] = '@' + auth;\ncache.put('pxuid',uid);\nsource.putLoginInfo(JSON.stringify(Info));\n'@' + auth\n<\/js>",
"canReName": "1",
"init": "<js>\nvar sid = java.get('sid');\nlet i = String(book.bookUrl).includes('https:\/');\nif (i) { sid = String(book.bookUrl).match(\/\\d{3,}$\/);}\n\ncache.deleteMemory('pxcjj');\nif (sid == '🇨🇳') {\n\tlet Info=source.getLoginInfoMap();\n\tlet bkn = String(book.name);\n\tlet id = java.hexDecodeToString(result).match(\/\\d+$\/)[0];\n\tInfo['书名'] = '';\n\tcache.put('pxsid','');\n\tInfo['章节'] = bkn;\n\tcache.put('pxid',id);\n\tsource.putLoginInfo(JSON.stringify(Info));\n\tlet length = leng(bkn);\t\nbook.intro = (source.get('bq')==1?String(java.get('tags')).replace(\/, \/g,' #').replace('[',' #').replace(']','\\n '):'') + (length>18?('《'+book.name+'》\\n'):'') + java.get('jianjie');\n\trr='1';\n\n} else {\nlet url = 'https:\/\/app-api.pixiv.net\/v2\/novel\/series?series_id=' + sid;\nbook.bookUrl = `data:;base64,${java.base64Encode(url)},{\"type\":\"px\"}`;\n\ntry {\n\njg = java.connect(gethd(url));\nrr = jg.body();\nif (jg.code() == 400) {\n\tsource.login();\n\tPackages.java.lang.Thread.sleep(500);\n\trr = java.ajax(gethd(url));\n\t}\n\n} catch(err) {\n\trr={};\n\tjava.toast('详情页链接加载失败'+sid);\n\t}\n\njava.setContent(rr);\n\ntry {\nlet tm = java.getString('$.novel_series_latest_novel.create_date');\nlet d = new Date(tm);\nd = java.timeFormatUTC(d,'yy\/MM\/dd',8*60*60*1000);\nbook.kind = String(book.kind).replace(\/\\d+\\\/\\d+\\\/\\d+|$\/,d).replace('null','');\n} catch(err) {java.toast('详情页内容错误');}\n\nlet bkn = String(java.getString('$.novel_series_detail.title')).replace(\/^《(.+)》$\/,'$1');\nbook.name = bkn.replace(\/[((].{0,9}((?:仙侠|纯爱|后宫|萝莉).?){3,}.{0,9}[))](?=\\s*[一-ꀀ])\/,'');\n\nif (book.name == '') {\n\tlet txte = java.getString('$..user_message',rr);\n\tjava.longToast('\\n未获取到书名\\n'+txte);\n\t} else {\n\t\n\tlet Info=source.getLoginInfoMap();\n\tInfo['书名'] = book.name;\n\tcache.put('pxsid',sid);\n\tInfo['章节'] = '';\n\tcache.put('pxid','');\n\tsource.putLoginInfo(JSON.stringify(Info));\n\t\n\tif (source.get('gc') == 1) book.name='📘'+book.name;\n\t}\n\nif (book.coverUrl == null) {\n\tlet img = java.getString('$.novel_series_latest_novel.image_urls.large');\n\tbook.coverUrl = gethdi(img);\n}\n\nlet length = leng(String(book.name));\nif (length > 18) length= '《'+String(book.name).replace(\/^📘\/,'')+'》\\n';\nelse length = '';\nlet jianjie = java.getString('$.novel_series_detail.caption');\nbook.intro = (source.get('bq')==1?String(java.get('tags')).replace(\/, \/g,' #').replace('[',' #').replace(']','\\n '):'') + length + java.get('jianjie');\njava.put('jianjie',jianjie);\njava.put(\"bookr\",rr);\n}\nutil.xq_trans.call(this);\nrr\n<\/js>",
"lastChapter": "$.novel_series_latest_novel.title##[【《]?{{book.name}}[》】]?",
"tocUrl": "@js:book.bookUrl",
"wordCount": "$.novel_series_detail.total_character_count"
},
"ruleContent": {
"content": "script.0@html\n<js>\nlet rr = result.match(\/novel:\\s*({.+})\/)[1];\nlet id = String(chapter.url).match(\/\\d+(?=$|,)\/)[0];\n\nlet bin = book.durChapterIndex;\nlet cin = chapter.index;\nlet inn = cin - bin;\nif (inn==0) {\nlet rra = result.match(\/authorDetails:\\s*({.+})\/)[1];\nlet uid = java.getString('$..userId',rra);\nlet unm = java.getString('$..userName',rra);\nlet uim = java.getString('$..url',rra);\nuim = uim.replace('i.pximg.net','pximg.hakurei.cc');\nlet ugz = java.getString('$..isFollowed',rra);\nlet tags = java.getStringList('$..tags[*]',rr);\ntags = Array.from(tags).map(x => `#${x}`).join(' ');\nlet caption = String(java.getString('$..caption',rr));\ncaption = caption ? '<p>'+caption.replace(\/(?:<br \\\/>)+\/g, '<\/p><p>')+'<\/p>' : '';\nlet cdate = java.getString('$..cdate',rr);\nlet xh = java.getString('$..rating.like',rr);\nlet sc = java.getString('$..rating.bookmark',rr);\nlet gk = java.getString('$..rating.view',rr);\nlet title = java.getString('$.title',rr);\nlet sTitle = java.getString('$.seriesTitle',rr);\ncache.putMemory('pxcjj',[title,uid,unm,uim,tags,caption,cdate,xh,sc,gk,sTitle,id,ugz]);\ncache.put('pxuid',uid);\ncache.put('pxid',id);\nlet Info=source.getLoginInfoMap();\n\nlet sid = java.get('sid');\nif (sid != '🇨🇳') {\n\tInfo['书名']=String(book.name).replace(\/^📘\/,'');\n\tcache.put('pxsid',sid);} else {\n\tInfo['书名']='';\n\tcache.put('pxsid','');}\n\nInfo['章节'] = chapter.title;\nInfo['作者'] = book.author;\nsource.putLoginInfo(JSON.stringify(Info));\n}\n\nlet urls = java.getString('$..urls',rr);\nlet tt = String(java.getString('$.text',rr));\n\n\/\/ ---- 图片处理 ----\nlet img1 = tt.match(\/\\[uploadedimage\\:\\d+\\]\/g)||'';\nlet img2 = tt.match(\/\\[pixivimage\\:[\\d\\-]+\\]\/g)||'';\nfor (x of img1) {\n\tlet id = x.match(\/\\d+\/)[0];\n\tlet url = java.getString('$..'+id+'.urls.original',rr);\n\tlet re = new RegExp('\\\\[uploadedimage\\\\:'+id+'\\\\]');\n\ttt = tt.replace(re,'<img src=\"'+gethdi(url)+'\"\/>');\n\t}\nfor (x of img2) {\n\tlet id = x.match(\/[\\d\\-]+\/)[0];\n\tlet url = java.getString('$..'+id+'..images.original',rr);\n\tif (url=='null') url = java.getString('$..'+id+'..images.medium',rr);\n\tlet re = new RegExp('\\\\[pixivimage\\\\:'+id+'\\\\]');\n\ttt = tt.replace(re,'<img src=\"'+gethdi(url)+'\"\/>');\n\t}\n\n\/\/ ---- 基础替换 ----\ntt = tt.replaceAll('[newpage]','\\n—换页符—\\n');\ntt = tt.replace(\/\\[\\[jumpuri\\:(.+)\\>(.+)\\]\\]\/g, '🖇️$1($2)');\n\n\/\/ ---- 表情\/印章显示 ----\nif (source.get('showEmoji') == 1) {\n let emojiMap = {\n 'normal': 101, 'surprise': 102, 'series': 103, 'heaven': 104, 'happy': 105,\n 'excited': 106, 'sing': 107, 'cry': 108, 'normal2': 201, 'shame2': 202,\n 'love2': 203, 'interesting2': 204, 'blush2': 205, 'fire2': 206, 'angry2': 207,\n 'shine2': 208, 'panic2': 209, 'normal3': 301, 'satisfaction3': 302, 'surprise3': 303,\n 'smile3': 304, 'shock3': 305, 'gaze3': 306, 'wink3': 307, 'happy3': 308,\n 'excited3': 309, 'love3': 310, 'normal4': 401, 'surprise4': 402, 'series4': 403,\n 'love4': 404, 'shine4': 405, 'sweet4': 406, 'shame4': 407, 'sleep4': 408,\n 'heart': 501, 'teardrop': 502, 'star': 503\n };\n tt = tt.replace(\/\\(([a-zA-Z0-9_]+)\\)\/g, function(match, key) {\n if (emojiMap.hasOwnProperty(key)) {\n let imgUrl = 'https:\/\/s.pximg.net\/common\/images\/emoji\/' + emojiMap[key] + '.png';\n return '<img src=\"' + imgUrl + '\" style=\"width:1.2em;height:1.2em;vertical-align:middle;\"\/>';\n }\n return match;\n });\n}\n\n\/\/ ---- 特殊语法补充 ----\nif (source.get('showSyntax') == 1) {\n tt = tt.replace(\/\\[chapter:(.*?)\\]\/g, '<h3>$1<\/h3>');\n tt = tt.replace(\/\\[jump:(\\d+)\\]\/g, '跳转至第 $1 节');\n}\n\n\/\/ ---- 章首描述 & 分割线 ----\nif (source.get('showCaption') == 1) {\n let cap = String(java.getString('$.caption',rr));\n if (cap) {\n let capHtml = cap.replace(\/(?:<br \\\/>)+\/g, '<\/p><p>');\n let mode = parseInt(source.get('dividerMode')) || 0;\n let divider = '';\n if (mode > 0) {\n let styles = [\n '',\n '<p>━━━━━━━━━━━━━━━━<\/p>',\n '<p>━━━ (=^・^=) ━━━ ( =^・^= ) ━━━<\/p>',\n '<p>━━━ ฅ(^ω^ฅ) ━━━ ฅ(^ω^ฅ) ━━━<\/p>',\n '<p>—— 这 · 里 · 是 · 分 · 割 · 线 ——<\/p>'\n ];\n divider = styles[mode] || '';\n }\n tt = '<p>' + capHtml + '<\/p>' + divider + tt;\n }\n}\n\n\/\/ ---- 注音替换 ----\nif (source.get('rubyReplace') == 1) {\n tt = tt.replace(\/\\[\\[rb:(.*?)>(.*?)\\]\\]\/g, '$1($2)');\n}\n\ntt\n<\/js>",
"replaceRegex": "@js:util.tihuan_trans.call(this);"
},
"ruleExplore": {
"author": "@js:\nlet uid = java.getString('$.user.id');\njava.put('uid',uid);\n'@' + java.getString('$.user.name');",
"bookList": "<js>\nif (baseUrl.startsWith('http:\/\/127.') || baseUrl === 'data:;base64,') {\n\trr = [{}];\n\t} else {\nlet nurl = java.getString('$.next_url');\nif (nurl == '') {\n\tjava.toast('发现页到底了');\n\tsource.put('nurl','http:\/\/127.0.0.1');\n\t}\nelse {\n\tsource.put('nurl',nurl);\n\t}\nif (baseUrl.includes('\/watchlist\/novel') ) {\n\trr = java.getElement(\"$.series\");\n\t} else { rr = java.getElement(\"$.novels\");}\n\n}\nrr\n<\/js>",
"bookUrl": "<js>\nlet id = java.getString('$.id');\nlet sid = java.getString('$.series.id');\nlet rr = 'https:\/\/app-api.pixiv.net\/webview\/v2\/novel?id=' + id;\n\nif (baseUrl.includes('\/watchlist\/novel') ) {\n\tsid = id;\n\tif (source.get('gc')=='1') book.name='📘'+book.name;\n}\nelse if (sid=='') {sid='🇨🇳';}\nelse {\n\tlet jj = java.get('jianjie');\n\tjava.put('jianjie',book.name+'\\n'+jj);\n}\njava.put('sid',sid);\n`data:;base64,${java.base64Encode(rr)},{\"type\":\"px\"}`\n<\/js>",
"coverUrl": "<js>\nif (baseUrl.includes('\/watchlist\/novel') ) {url = java.getString('$.url');}\nelse {url = java.getString('$.image_urls.large');}\ngethdi(url);\n<\/js>",
"intro": "<js>\nlet jj = java.get('jianjie');\nlet rr = '\\n' + java.getString('$.caption');\nlet rs = java.htmlFormat(rr);\njava.put('jianjie',rs);\njj + rs\n<\/js>",
"kind": "@js:\nif (baseUrl.includes('\/watchlist\/novel') ) {\n\trrr = '';\n\tjava.put('tags','');\n\ttm = java.getString('$.last_published_content_datetime');\n\t} else {\n\t\tlet tags=java.get('tags');\n\t\trr=String(tags).slice(1,-1).split(', ');\n\t\trrr = rr.filter(i => biaoq.test(i) );\n\t\trr.forEach(x=>{\n\t\t\tif (x=='萝莉') {\n\t\t\t\tif (!rrr.includes('幼女')) rrr.unshift(x);}\n\t\t\telse if (['熟女','淫妻'].includes(x)) {\n\t\t\t\tif (!rrr.includes('人妻')) rrr.unshift(x);}\n\t\t\telse if (['仙侠','古风','武侠'].includes(x) && !rrr.some(y=>\/[修仙古风武侠]{2}\/.test(y))) {\n\t\t\t\t\trrr.unshift(x);}\n\t});\n\t\ttm = java.getString('$.create_date');\n}\nlet d=new Date(tm);\nd=java.timeFormatUTC(d,'yy\/MM\/dd',8*60*60*1000);\n\nrrr.toString()+','+d",
"name": "@js:\nresult = String(java.getString('$.title'));\nlet bookn = String(java.getString('$.series.title')).replace(\/^《(.+)》$\/,'$1');\nif (bookn != '') {\n\tjava.put('jianjie', '《'+bookn+'》\\n');\n\tresult = result.replace(bookn,'♸').replace(\/[《【]?♸[】》]?\/,'')||result;\n\t}\nresult = result.replace(\/[((].{0,9}((?:仙侠|纯爱|后宫|萝莉).?){3,}.{0,9}[))](?=\\s*[一-ꀀ])\/,'').replace(\/《(.+)》\/,'$1');\n\nlet tags = java.getStringList('$.tags..name');\njava.put('tags',tags);\ntags=String(tags).slice(1,-1).split(\/, |\\\/\/);\nlet bptag=source.getLoginInfoMap()['屏蔽标签']||'';\nif (bptag!='') {\n\tbptag = String(bptag).split(\/[,\\|]\/).map(x=>x.replace('#',''))\nfor (let char of tags)\nif (bptag.includes(char)) result=''\n}\nresult",
"wordCount": "$.text_length"
},
"ruleSearch": {
"author": "<js>\n{{(source.ruleExplore.author).replace('@js:','')}}\n<\/js>",
"bookList": "<js>\npage=cache.getFromMemory('pxpage');\ncache.deleteMemory('pxpage');\nif (baseUrl.startsWith('http:\/\/127.') || baseUrl === 'data:;base64,') {rr = [{}];}\n\nelse {\nrr = java.getElement('$.novels');\nnurl = java.getString('$.next_url');\nif (rr.length<6&&page==1&&nurl!='') {\n\tsleep(500);\n\trs = java.ajax(gethd(nurl));\n\tjava.setContent(rs)\n\trrr = java.getElement('$.novels');\n\trr.addAll(rrr);\n\tnurl = java.getString('$.next_url');\n}\n\nif (nurl == '') {\n\tjava.toast('搜索页到底了');\n\tsource.put('nurls','http:\/\/127.0.0.1');\n\t} else {source.put('nurls',nurl);}\n\n}\nrr\n<\/js>",
"bookUrl": "<js>\nlet id = java.getString('$.id');\nlet sid = java.getString('$.series.id');\nif (sid=='') {\n\tsid='🇨🇳';\n\t} else {\n\tlet jj = java.get('jianjie');\n\tjava.put('jianjie',book.name+'\\n'+jj);\n\t}\nlet rr = 'https:\/\/app-api.pixiv.net\/webview\/v2\/novel?id=' + id;\njava.put('sid',sid);\n`data:;base64,${java.base64Encode(rr)},{\"type\":\"px\"}`\n<\/js>",
"coverUrl": "$.image_urls.large\n<js>\ngethdi(result);\n<\/js>",
"intro": "<js>\nlet jj = java.get('jianjie');\nlet rr = '\\n' + java.getString('$.caption');\nlet rs = java.htmlFormat(rr);\njava.put('jianjie',rs);\njj + rs\n<\/js>",
"kind": "<js>\n{{(source.ruleExplore.kind).replace('@js:','')}}\n<\/js>",
"name": "<js>\n{{(source.ruleExplore.name).replace('@js:','')}}\n<\/js>",
"wordCount": "$.text_length"
},
"ruleToc": {
"chapterList": "<js>\nlet sid = java.get('sid');\nif (sid == '🇨🇳') {result=[result];}\nelse {\n\ttry {\n\t\tlet url = java.hexDecodeToString(result);\nlet bookr=java.get('bookr')+'';\nif (!bookr) {\n\tlet rs=java.connect(gethd(url));\n\tif (rs.code() == 400) {\n\t\tsource.login();\n\t\tsleep(500);\n\t\trs=java.connect(gethd(url));}\nbookr=rs.body();}\n\t\tjava.setContent(bookr);\n\t\tjava.put('bookr','');\n\t\t} catch(e){}\nresult = java.getElement('$.novels');\n}\nutil.mulu_trans.call(this);\nresult\n<\/js>",
"chapterName": "<js>\nlet sid = java.get('sid');\nif (sid == '🇨🇳') {cc=book.name;}\nelse {\nlet title = java.getString('$.title');\ntitle = String(title).replace(\/[((].{0,9}((?:仙侠|纯爱|后宫|萝莉).?){3,}.{0,9}[))](?=\\s*[一-ꀀ])\/,'');\nlet bkn=String(book.name).replace(\/^📘|[。?!]+$\/g,'');\ncc = title.replace(bkn,'♸').replace(\/[《【]♸[。?!]*[】》]\\s*|♸[。?!\\s]*\/,'')||title;\n\t}\nif (source.get('xh')==1) {\n\tcc='▫️'+cc;\n}\n\tcc\n<\/js>",
"chapterUrl": "<js>\nlet sid = java.get('sid');\nif (sid == '🇨🇳') {\n\t\tuu=java.hexDecodeToString(result);\n\t\tbook.putCustomVariable('这是单贴,链接:'+uu);\n\t}\nelse {\nlet id = java.getString('$.id');\nuu='https:\/\/app-api.pixiv.net\/webview\/v2\/novel?id=' + id;\n}\ngethd(uu);\n<\/js>",
"formatJs": "title.replace(\/^▫️(?![第序]|#?第?[\\d零一二三四五六七八九十百千]+[章回])\/,'第'+index+'章 ').replace(\/^▫️\/,'');",
"nextTocUrl": "$.next_url\n<js>\nif (result!='[]') {\nresult=gethd(result[0]);\n}else{result=[];}\nresult\n<\/js>",
"updateTime": "$.create_date\n<js>\nif (result) {\nlet d=new Date(result);\nupt=java.timeFormatUTC(d,\"yyyy\/MM\/dd HH:mm\",8*60*60*1000);\n}\nelse '';\n<\/js>"
},
"searchUrl": "<js>\nif (page == 1) {\ncache.putMemory('pxpage',page);\n if (\/^\\u200b\/.test(key)) {\n let uid = cache.getFromMemory('pxuid');\n if (uid=='') java.longToast('\\n请刷新书籍');\n else url = 'https:\/\/app-api.pixiv.net\/v1\/user\/novels?filter=for_android&user_id=' + uid;}\n else if (key.startsWith('@')) {\n let name = key.slice(1).trim();\n if (!name) { java.longToast('\\n请输入作者名'); url = 'http:\/\/127.0.0.1'; }\n else {\n try {\n let searchUserUrl = 'https:\/\/app-api.pixiv.net\/v1\/search\/user?word=' + encodeURIComponent(name);\n let resp = java.ajax(gethd(searchUserUrl));\n let data = JSON.parse(resp);\n let users = data.user_previews || [];\n if (users.length == 0) {\n java.longToast('\\n未找到该作者:' + name);\n url = 'http:\/\/127.0.0.1';\n } else {\n let uid = users[0].user.id;\n url = 'https:\/\/app-api.pixiv.net\/v1\/user\/novels?filter=for_android&user_id=' + uid;\n java.longToast('\\n找到作者:' + users[0].user.name + ' (ID:' + uid + ')' );\n }\n } catch(e) {\n java.longToast('\\n搜索作者失败:' + e);\n url = 'http:\/\/127.0.0.1';\n }\n }\n }\n else if (key.startsWith('作者@')) {\n let uid = key.slice(3);\n if (!\/^\\d{3,}$\/.test(uid)) java.longToast('\\n请输入正确的id');\n else url = 'https:\/\/app-api.pixiv.net\/v1\/user\/novels?filter=for_android&user_id='+uid;\t}\n else if (\/\\d{5,}$\/.test(key) ) {\n let sid = key.match(\/\\d+$\/)[0];\n java.put('sid',sid);\n if (key.startsWith('作者')) java.longToast('\\n请输入正确的搜索格式');\n else url = `data:;base64,${java.base64Encode(sid)},{\"type\":\"\"}`;}\n else if (key.startsWith('正文@')) {\n url = 'https:\/\/app-api.pixiv.net\/v1\/search\/novel?filter=for_android&merge_plain_keyword_results=true&sort=date_desc&search_target=text&word='+key.slice(3);}\n else { url = 'https:\/\/app-api.pixiv.net\/v1\/search\/novel?filter=for_android&merge_plain_keyword_results=true&word='+key;}\nsource.put('nurls','http:\/\/127.0.0.1');\n\n} else {url = source.get('nurls');}\ngethd(url)\n<\/js>",
"weight": 0
}