-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathfishhawk.json
53 lines (53 loc) · 12.2 KB
/
fishhawk.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
[
{
"bookSourceComment": "仅支持网络小说(非文库本)\n\n酷安 @吉王义昊\nGitHub:https://github.com/jiwangyihao/source-j-legado\n\n# 关于许可的额外声明(在线版本参见 GitHub,以在线版本为准)\n\n- 当许可证与本声明冲突时,以本声明为准;\n- 对于本仓库中的任意代码片段:按照 `MPL 2.0` 中有关约定执行;\n- 对于本仓库中的某一完整书源的转载或二次开发,需满足以下全部条件:\n - 在[本仓库](https://github.com/jiwangyihao/source-j-legado)的 `issue` 中提出请求并具体说明转载地址、二次开发后的书源开源地址以及其他必要信息;\n - 等待原作者(即本仓库的初始所有者和初始代码贡献者 [@jiwangyihao](https://github.com/jiwangyihao))查看并通过 `issue` 或依据原作者要求更改转载方式或补充更详细的信息。\n - 考虑到本项目弃坑的可能,新 `issue` 开启后超过 20 个工作日原作者没有回复或者原作者回复要求更改的 `issue` 在更改后超过 20 个工作日原作者没有回复即视为原作者通过该 `issue`:\n - 此处的 `issue` 仅包括在[本仓库](https://github.com/jiwangyihao/source-j-legado)开启的,处于「开启状态」的 issue。(也就是说,请不要在已经关闭的 issue 中回复)。\n - 对于此种方式通过的 issue,转载/二次开发者仍应当遵守本声明中已经写明的相关约定。\n - 不得上传至源仓库或整理至`非轻小说专用`的书源合集中并应当避免其他人将转载/二次开发版本上传至源仓库或整理至`非轻小说专用`的书源合集中:\n - 关于轻小说的定义的额外说明:不包括国内的原创网络文学作品(如 `SF 轻小说` 中的原创轻小说以及`起点中文网`中标签包含轻小说的作品)。\n - 轻小说专用的定义:有且仅有想看轻小说的人可能会添加。\n - 必须在转载/二次开发地址的明显位置完整包含本声明的全部内容。\n - 必须保留源注释中原有的更改记录。\n\n2024.4.10\n酷安 @吉王义昊\n处理目录中的卷名\n解决了章节中的引号导致加载目录失败的问题\n2024.5.7\n酷安 @吉王义昊\n支持登录\n支持网站阅读历史\n支持收藏(多收藏夹)\n新增发现\n2024.5.31\n酷安 @吉王义昊\n修正优先级序列模式下意外忽略后续翻译源的问题\n2024.6.21\n酷安 @吉王义昊\n跟进最新 API 更改\n2024.7.8\n酷安 @吉王义昊\n跟进源站发现更改\n2024.7.23\n酷安 @吉王义昊\n跟进源站登录更改\n2024.8.10\n酷安 @吉王义昊\n支持添加网址\n2024.10.28\n酷安 @吉王义昊\n支持「Lordly•阅读」\n支持在正文中加载图片",
"bookSourceGroup": "轻小说,机翻",
"bookSourceName": "轻小说机翻🤖",
"bookSourceType": 0,
"bookSourceUrl": "https://books.fishhawk.top/",
"bookUrlPattern": "https?://books1?.fishhawk.top/(api/)?novel/\\w+/\\w+",
"customOrder": -41330,
"enabled": true,
"enabledCookieJar": true,
"enabledExplore": true,
"exploreUrl": "@js:\nresult=[\n {\n 'title': '>> 个人中心 <<',\n 'url': \"\",\n 'style':{\n layout_flexGrow:1,\n layout_flexBasisPercent:1\n }\n },\n {\n 'title': \"阅读历史\",\n 'url': `/api/user/read-history?page={{page-1}}&pageSize=30`,\n 'style':{\n layout_flexGrow:2,\n layout_flexBasisPercent:0.25\n \t}\n }\n]\nfavored = String(java.ajax(source.bookSourceUrl + \"/api/user/favored\"))\nif (favored.match(\"Token不合法或者过期\")) {\n result[0].title = '>> 个人中心 | 未登录 <<'\n} else {\n favored = JSON.parse(java.ajax(source.bookSourceUrl + \"/api/user/favored\")).favoredWeb\n favored.forEach(favor => {\n result.push({\n 'title': favor.title,\n 'url': `/api/user/favored-web/${favor.id}?page={{page-1}}&pageSize=30&sort=update`,\n 'style':{\n layout_flexGrow:2,\n layout_flexBasisPercent:0.25\n \t}\n })\n })\n}\nString(java.ajax(`https://github.moeyy.xyz/https://raw.githubusercontent.com/FishHawk/auto-novel/main/web/src/pages/layouts/MainLayout.vue, {\n \"headers\": {\n \"Authorization\": \"\"\n }\n}`))\n.match(/label:.?'小说排行'[^\\]]+]/gi)[0]\n.match(/renderLabel\\(.+\\)/gi)\n.forEach((menu,index)=>{\n if (index!=1) {\n title=menu.replace(/renderLabel\\('(.+)',.?'(.+)'\\)/gi, \"$1\")\n href=menu.replace(/renderLabel\\('(.+)',.?'(.+)'\\)/gi, \"$2\")\n result.push({\n 'title': `>> ${title} <<`,\n 'url': \"\",\n 'style':{\n layout_flexGrow:1,\n layout_flexBasisPercent:1\n }\n })\n html = org.jsoup.Jsoup.parse(String(java.webView(null,source.bookSourceUrl + href.replace(/^\\//i,''),null)))\n sorts = html.select(\".n-layout-scroll-container h1 + div.n-flex > .n-flex\")\n sorts[0].select(\".n-flex > .n-flex > .n-flex > span\").forEach(tag => {\n result.push({\n 'title': tag.text(),\n 'url': href.replace(/\\/(.+)\\/(.+)\\/(.+)/gi, \"$3\") != \"2\" ? `/api/novel/rank/${href.replace(/\\/(.+)\\/(.+)\\/(.+)/gi, \"$2\")}?type=${title.replace(/(.+):(.+)/gi,\"$2\").replace(\"异世界转移/转生\", \"异世界转生/转移\")}&genre=${tag.text()}&range=总计&status=全部&page={{page-1}}` : `/api/novel/rank/${href.replace(/\\/(.+)\\/(.+)\\/(.+)/gi, \"$2\")}?type=${title.replace(/(.+):(.+)/gi,\"$2\")}&range=${tag.text()}&status=全部&page={{page-1}}`,\n 'style':{\n layout_flexGrow:2,\n layout_flexBasisPercent:0.4\n \t}\n })\n \t})\n }\n})\nJSON.stringify(result)",
"jsLib": "function getConfig() {\n const { book, source, java } = this\n const config = {\n \t language: \"中日\",\n \t translation: \"SGYB\",\n \t translationArr: []\n \t}\n \tconst languages = [\n \t \"日文\",\n \"中文\",\n \"中日\",\n \"日中\"\n ]\n const translations = {\n \t B: \"baiduParagraphs\",\n \t Y: \"youdaoParagraphs\",\n \t G: \"gptParagraphs\",\n \t S: \"sakuraParagraphs\"\n \t}\n \tfunction applyTran(tranStr) {\n \t config.translation=tranStr\n \t if (tranStr===\"并列\") tranStr=\"SGYB\"\n \t let tranArr = []\n \t for (let i=0; i<tranStr.length; i++) {\n \t \t tranArr.push(translations[tranStr.charAt(i)])\n \t \t}\n \t \tconfig.translationArr=tranArr\n \t}\n \tfunction applyLanguage(lang) {\n \t if (languages.includes(lang))\n \t \t config.language=lang\n \t}\n applyTran(config.translation)\n const sVar = String(source.getVariable()).replace(/\\s/gi, '').split('-')\n if (sVar[0]) applyLanguage(sVar[0])\n if (sVar[1]) applyTran(sVar[1])\n const bVar = String(book.getVariable(\"custom\")).replace(/\\s/gi, '').split('-')\n if (bVar[0]) applyLanguage(bVar[0])\n if (bVar[1]) applyTran(bVar[1])\n return config\n}",
"lastUpdateTime": 1730100786782,
"loginUi": "[\n {\n \"name\": \"账号\",\n \"type\": \"text\"\n },\n {\n \"name\": \"密码\",\n \"type\": \"password\"\n }\n]",
"loginUrl": "@js:\nfunction login() {\n let une = source.getLoginInfoMap().get(\"账号\")\n let pwd = source.getLoginInfoMap().get(\"密码\")\n if (une && pwd) {\n let body = JSON.stringify({\n emailOrUsername: une,\n password: pwd\n })\n let url = source.bookSourceUrl + '/api/auth/sign-in'\n let res = java.post(url, body, {\n \"Content-Type\": \"application/json\"\n })\n if (res.body().match(/错误/gi)) {\n throw(res.body())\n }\n //throw(String(res.body()))\n //result = JSON.parse(res.body())\n \n let header = JSON.stringify({\n \"Authorization\": \"Bearer \" + res.body()\n })\n source.putLoginHeader(header)\n }\n}",
"respondTime": 180000,
"ruleBookInfo": {
"author": "$.authors.*.name",
"init": "@js:\nif (!/api/g.test(book.bookUrl)) {\n book.bookUrl=book.bookUrl.replace(\"novel\",\"api/novel\")\n result=java.ajax(book.bookUrl)\n}\nresult=JSON.parse(result)\nresult.points+=' PT'\nresult.visited+=' 浏览'\nJSON.stringify(result)",
"intro": "当前规则:语言展现形式-{{getConfig().language}},翻译优先级-{{getConfig().translation}}(可在源变量或书籍变量中修改,详情参考变量说明)\n\n{{$.titleJp}}\n总计:{{$.total}} 百度:{{$.baidu}} 有道:{{$.youdao}} GPT:{{$.gpt}} Sakura:{{$.sakura}}\n\n{{$.introductionZh}}\n\n{{$.introductionJp}}",
"kind": "$.attentions&&$.type&&$.points&&$.visited&&$.keywords",
"lastChapter": "{{$.toc[-1].chapterId}} - {{$.toc[-1].titleZh||$.toc[-1].titleJp}}",
"name": "$.titleZh",
"tocUrl": "",
"wordCount": "$.totalCharacters"
},
"ruleContent": {
"content": "@js:\nresult=JSON.parse(result)\nconst config=getConfig()\nconst resultList=[]\nfor (let ip = 0; ip < result.paragraphs.length; ip++) {\n let p = result.paragraphs[ip]\n if (/^<图片>http.+$/.test(p)) {\n p = '<img src=\"'+p.replace(/^<图片>/i, \"\")+'\">'\n resultList.push(p)\n continue\n }\n function generateTran(i) {\n const chars = {\n \t baiduParagraphs: \"ᵇ\",\n \t youdaoParagraphs: \"ʸ\",\n \t gptParagraphs: \"ᵍ\",\n \t sakuraParagraphs: \"ˢ\"\n }\n if (config.translation===\"并列\") {\n const processed=[]\n for (let ii = 0; ii < config.translationArr.length; ii++) {\n let t = config.translationArr[ii]\n if (result[t]) {\n if (/^<图片>http.+$/.test(result[t][i])) {\n let tmp = '<img src=\"'+result[t][i].replace(/^<图片>/i, \"\")+'\">'\n if (!processed.includes(tmp))\n processed.push(tmp)\n \tcontinue\n }\n processed.push((result[t][i]!=\"\" ? chars[t] : \"\") + result[t][i].trim())\n continue\n }\n processed.push(\"\")\n }\n return processed.join(\"\\n\")\n } else {\n for (let tt=0; tt<config.translationArr.length; tt++) {\n let t=config.translationArr[tt]\n if (result[t]) {\n if (/^<图片>http.+$/.test(result[t][i])) {\n let tmp = '<img src=\"'+result[t][i].replace(/^<图片>/i, \"\")+'\">'\n return tmp\n }\n return (result[t][i]!=\"\" ? chars[t] : \"\") + result[t][i].trim()\n }\n }\n }\n \t}\n switch (String(config.language)) {\n \t case \"日文\":\n \t resultList.push(p)\n \t break\n \t case \"中文\":\n \t resultList.push(generateTran(ip))\n \t break\n \t case \"中日\":\n \t resultList.push([generateTran(ip), p.trim()].join(\"\\n\"))\n \t break\n \t case \"日中\":\n \t resultList.push([p, generateTran(ip)].join(\"\\n\"))\n \t break\n \t}\n}\nresultList.join(\"\\n\")"
},
"ruleExplore": {},
"ruleSearch": {
"bookList": "$.items",
"bookUrl": "/api/novel/{{$.providerId}}/{{$.novelId}}",
"checkKeyWord": "驯兽师少女的逃亡日记",
"intro": "{{$.titleJp}}\n总计:{{$.total}} 百度:{{$.baidu}} 有道:{{$.youdao}} GPT:{{$.gpt}} Sakura:{{$.sakura}}",
"kind": "$.attentions&&$.type&&$.keywords",
"lastChapter": "@js:\n`{{$.total}} - ` + new Date(parseInt({{$.updateAt}}) * 1000).toJSON().replace(/T|\\.\\d+Z/gi, ' ')",
"name": "$.titleZh||$.titleJp"
},
"ruleToc": {
"chapterList": "$.toc",
"chapterName": "@js:\n`{{$.chapterId}}` ? `{{$.chapterId}} - {{$.titleZh}}` : `{{$.titleZh}} - {{$.titleJp}}`",
"chapterUrl": "@js:\n`{{$.chapterId}}` ? `{{baseUrl}}/chapter/{{$.chapterId}}` : ''",
"isVolume": "@js:\n!`{{$.chapterId}}`",
"updateTime": "@js:\n`{{$.chapterId}}` ? (`{{$.titleJp}} - ` + (`{{$.createAt}}` ? new Date(parseInt({{$.createAt}}) * 1000).toJSON().replace(/T|\\.\\d+Z/gi, ' ') : '暂无')) : ''"
},
"searchUrl": "/api/novel?page={{page-1}}&pageSize=20&query={{key}}&provider=kakuyomu%2Csyosetu%2Cnovelup%2Chameln%2Cpixiv%2Calphapolis&level=0&type=0&translate=0&sort=0",
"variableComment": "设置正文语言展现形式及翻译优先级\n!错误的设置可能导致书源工作不正常\n格式:语言展现形式 - 翻译优先级\n\n语言展现形式:\n- 日文\n- 中文\n- 中日\n- 日中\n翻译优先级:\n- 并列(展示所有存在的翻译)\n- 优先级序列,写在前面的优先采用,B-百度、Y-有道、G-GPT、S-Sakura,如 `SGYB`\n\n示例(默认值):中日 - SGYB\n示例:中文 - 并列",
"weight": 0
}
]