From bc8fc6c05013c13962c2f35d5c7971603ad2e876 Mon Sep 17 00:00:00 2001 From: catvod <88956744+catvod@users.noreply.github.com> Date: Sat, 13 Jan 2024 11:58:22 +0800 Subject: [PATCH 01/12] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 600860d..e241730 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Not being maintained and uncertain whether they will be updated. ### **Limits** -- Only local `assets://`, `github://`, `gitee://` config is supported, and http config is not available. +- Only local `assets://`, `github://`, `gitee://`, `http(s)://user:pwd@xxx` config is supported, and http config without basic auth is not available. - Only video&cloud disk&audio book module. - Not supporting sniffing. - Basic JS interface support. From 881e53953073c4c0884a0bc07ea6aab9e546c57c Mon Sep 17 00:00:00 2001 From: catvod <88956744+catvod@users.noreply.github.com> Date: Mon, 15 Jan 2024 15:12:27 +0800 Subject: [PATCH 02/12] Create copymanga.js --- open/copymanga.js | 207 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 207 insertions(+) create mode 100644 open/copymanga.js diff --git a/open/copymanga.js b/open/copymanga.js new file mode 100644 index 0000000..1b0bf38 --- /dev/null +++ b/open/copymanga.js @@ -0,0 +1,207 @@ +import { Crypto, _, load } from './lib/cat.js'; + +let key = 'copymanga'; +let url = 'https://www.copymanga.tv'; + +let siteKey = ''; +let siteType = 0; + +const PC_UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36'; + +async function request(reqUrl) { + let resp = await req(reqUrl, { + headers: { + 'User-Agent': PC_UA, + }, + }); + return resp.content; +} + +// cfg = {skey: siteKey, ext: extend} +async function init(cfg) { + siteKey = cfg.skey; + siteType = cfg.stype; +} + +async function home(filter) { + var html = await request(url + '/comics'); + const $ = load(html); + let filterObj = {}; + + let region = { + key: 'region', + name: '地區', + init: '', + }; + let regionValues = []; + regionValues.push({ n: '全部', v: '' }); + regionValues.push({ n: '日漫', v: '0' }); + regionValues.push({ n: '韓漫', v: '1' }); + regionValues.push({ n: '美漫', v: '2' }); + region['value'] = regionValues; + + let ordering = { + key: 'ordering', + name: '排序', + init: '-datetime_updated', + }; + let orderingValues = []; + orderingValues.push({ n: '更新時間↓', v: '-datetime_updated' }); + orderingValues.push({ n: '更新時間↑', v: 'datetime_updated' }); + orderingValues.push({ n: '熱門↓', v: '-popular' }); + orderingValues.push({ n: '熱門↑', v: 'popular' }); + ordering['value'] = orderingValues; + + let status = { + key: 'sort', + name: '狀態', + init: '', + }; + let statusValues = []; + statusValues.push({ n: '全部', v: '' }); + statusValues.push({ n: '連載中', v: '0' }); + statusValues.push({ n: '已完結', v: '1' }); + statusValues.push({ n: '短篇', v: '2' }); + status['value'] = statusValues; + + filterObj['c1'] = []; + + let themeValues = [{ n: '全部', v: '' }]; + for (const a of $('div.classify-right>a[href*="theme="]')) { + themeValues.push({ + n: $(a).text().trim(), + v: a.attribs.href.match(/.*?theme=(.*)&/)[1], + }); + } + + _.each(_.chunk(themeValues, 11), (vals) => { + let theme = { + key: 'theme', + name: '', + init: '', + value: vals, + }; + filterObj['c1'].push(theme); + }); + + filterObj['c1'].push(region); + filterObj['c1'].push(status); + filterObj['c1'].push(ordering); + + return { + class: [{ type_name: 'all', type_id: 'c1' }], + filters: filterObj, + }; +} + +async function category(tid, pg, filter, extend) { + if (pg == 0) pg = 1; + let link = url + `/comics?theme=${extend.theme || ''}®ion=${extend.region || ''}&status=${extend.status || ''}&ordering=${extend.ordering || '-datetime_updated'}`; + if (pg > 1) { + link += '&offset=' + (pg - 1) * 50 + '&limit=50'; + } + var html = await request(link); + const $ = load(html); + const list = eval($('div[class="row exemptComic-box"]')[0].attribs.list); + let books = []; + for (const book of list) { + books.push({ + book_id: book.path_word, + book_name: book.name, + book_pic: book.cover, + book_remarks: book.author ? book.author[0].name : '', + }); + } + return { + page: pg, + pagecount: list.length == 50 ? pg + 1 : pg, + list: books, + }; +} + +async function detail(id) { + var html = await request(url + `/comic/${id}`); + const $ = load(html); + let book = { + book_name: $('h6').text().trim(), + book_director: _.map($('span.comicParticulars-right-txt>a[href*="/author/"]'), (a) => $(a).text().trim()).join('/'), + book_content: $('p.intro').text().trim(), + }; + + const data = JSON.parse(await request(url + `/comicdetail/${id}/chapters`)).results; + var key = Crypto.enc.Utf8.parse('xxxmanga.woo.key'); + var iv = Crypto.enc.Utf8.parse(data.substr(0, 16)); + var src = Crypto.enc.Hex.parse(data.substr(16)); + var dst = Crypto.AES.decrypt({ ciphertext: src }, key, { iv: iv, padding: Crypto.pad.Pkcs7 }); + dst = Crypto.enc.Utf8.stringify(dst); + + const groups = JSON.parse(dst).groups; + + let urls = _.map(groups.default.chapters, (c) => { + return c.name + '$' + id + '|' + c.id; + }).join('#'); + book.volumes = '默認'; + book.urls = urls; + + return { + list: [book], + }; +} + +async function play(flag, id, flags) { + try { + var info = id.split('|'); + var html = await request(url + `/comic/${info[0]}/chapter/${info[1]}`); + const $ = load(html); + const data = $('div.imageData')[0].attribs.contentkey; + var key = Crypto.enc.Utf8.parse('xxxmanga.woo.key'); + var iv = Crypto.enc.Utf8.parse(data.substr(0, 16)); + var src = Crypto.enc.Hex.parse(data.substr(16)); + var dst = Crypto.AES.decrypt({ ciphertext: src }, key, { iv: iv, padding: Crypto.pad.Pkcs7 }); + dst = Crypto.enc.Utf8.stringify(dst); + const list = JSON.parse(dst); + var content = []; + for (let index = 0; index < list.length; index++) { + const element = list[index]; + content[index] = element.url; + } + return { + content: content, + }; + } catch (e) { + return { + content: '', + }; + } +} + +async function search(wd, quick, pg) { + if (pg == 0) pg = 1; + const link = `${url}/api/kb/web/searcha/comics?offset=${pg > 1 ? ((pg - 1) * 12).toString() : ''}&platform=2&limit=12&q=${wd}&q_type=`; + var list = JSON.parse(await request(link)).results.list; + const books = []; + for (const book of list) { + books.push({ + book_id: book.path_word, + book_name: book.name, + book_pic: book.cover, + book_remarks: book.author ? book.author[0].name : '', + }); + } + return { + page: pg, + pagecount: list.length == 12 ? pg + 1 : pg, + list: books, + }; +} + +export function __jsEvalReturn() { + return { + init: init, + home: home, + category: category, + detail: detail, + play: play, + search: search, + }; +} From c33366dca5938b027bd09d47d3d3a6f0eb376156 Mon Sep 17 00:00:00 2001 From: catvod <88956744+catvod@users.noreply.github.com> Date: Mon, 15 Jan 2024 15:12:58 +0800 Subject: [PATCH 03/12] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e241730..51fe729 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Not being maintained and uncertain whether they will be updated. ### **Limits** - Only local `assets://`, `github://`, `gitee://`, `http(s)://user:pwd@xxx` config is supported, and http config without basic auth is not available. -- Only video&cloud disk&audio book module. +- Only video & cloud disk & audio book & comic module. - Not supporting sniffing. - Basic JS interface support. - No builtin maccms api support. From aa84f1063fdde164ed6ee0535d0419478fe0f113 Mon Sep 17 00:00:00 2001 From: catvod <88956744+catvod@users.noreply.github.com> Date: Mon, 15 Jan 2024 15:14:26 +0800 Subject: [PATCH 04/12] Update config_open.json --- open/config_open.json | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/open/config_open.json b/open/config_open.json index 0065324..e7101a2 100644 --- a/open/config_open.json +++ b/open/config_open.json @@ -29,6 +29,16 @@ } ] }, + "comic": { + "sites": [ + { + "key": "copymanga", + "name": "拷贝漫画", + "type": 20, + "api": "assets://js/copymanga.js" + } + ] + }, "pan": { "sites": [ { From 7c8fe83aa3670c67f88e207996b7449aca630cc6 Mon Sep 17 00:00:00 2001 From: catvod <88956744+catvod@users.noreply.github.com> Date: Mon, 15 Jan 2024 15:14:37 +0800 Subject: [PATCH 05/12] Update config_open.json --- open/config_open.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/open/config_open.json b/open/config_open.json index e7101a2..ed747d5 100644 --- a/open/config_open.json +++ b/open/config_open.json @@ -35,7 +35,7 @@ "key": "copymanga", "name": "拷贝漫画", "type": 20, - "api": "assets://js/copymanga.js" + "api": "assets://js/copymanga_open.js" } ] }, From 2a9ce7d785278a238af7be372b3e5e4c9baceaab Mon Sep 17 00:00:00 2001 From: catvod <88956744+catvod@users.noreply.github.com> Date: Mon, 15 Jan 2024 15:15:02 +0800 Subject: [PATCH 06/12] Rename copymanga.js to copymanga_open.js --- open/{copymanga.js => copymanga_open.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename open/{copymanga.js => copymanga_open.js} (100%) diff --git a/open/copymanga.js b/open/copymanga_open.js similarity index 100% rename from open/copymanga.js rename to open/copymanga_open.js From 701305db2fe15b70a6f8ea68875fd30c27943b4c Mon Sep 17 00:00:00 2001 From: catvod <88956744+catvod@users.noreply.github.com> Date: Mon, 15 Jan 2024 15:16:41 +0800 Subject: [PATCH 07/12] Update bookan_open.js --- open/bookan_open.js | 1 + 1 file changed, 1 insertion(+) diff --git a/open/bookan_open.js b/open/bookan_open.js index 21999fb..b348b92 100644 --- a/open/bookan_open.js +++ b/open/bookan_open.js @@ -64,6 +64,7 @@ async function detail(id) { let data = JSON.parse(content).data; let book = { + audio: 1, book_id: id, type_name: '', book_year: '', From 79b57af9c067ed275e97835a114c60cc95a173c4 Mon Sep 17 00:00:00 2001 From: catvod <88956744+catvod@users.noreply.github.com> Date: Fri, 19 Jan 2024 14:26:45 +0800 Subject: [PATCH 08/12] Create 13bqg_open.js --- open/13bqg_open.js | 165 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 open/13bqg_open.js diff --git a/open/13bqg_open.js b/open/13bqg_open.js new file mode 100644 index 0000000..b26dc33 --- /dev/null +++ b/open/13bqg_open.js @@ -0,0 +1,165 @@ +import { _, load } from './lib/cat.js'; + +let key = '13bqg'; +let url = 'https://m.13bqg.com'; +let siteKey = ''; +let siteType = 0; + +const MOBILE_UA = 'Mozilla/5.0 (Linux; Android 11; M2007J3SC Build/RKQ1.200826.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045714 Mobile Safari/537.36'; + +async function request(reqUrl) { + let resp = await req(reqUrl, { + headers: { + 'Accept-Language': 'zh-CN,zh;q=0.8', + 'User-Agent': MOBILE_UA, + }, + }); + return resp.content; +} + +// cfg = {skey: siteKey, ext: extend} +async function init(cfg) { + siteKey = cfg.skey; + siteType = cfg.stype; +} + +async function home(filter) { + var html = await request(url); + const $ = load(html); + let classes = []; + for (const a of $('div.nav > ul > li > a[href!="/"]')) { + classes.push({ + type_id: a.attribs.href.replace(/\//g, ''), + type_name: a.children[0].data.trim(), + tline: 2, + }); + } + return { + class: classes, + }; +} + +async function category(tid, pg, filter, extend) { + if (pg == 0) pg = 1; + var html = await request(url + `/${tid}/${pg}.html`); + const $ = load(html); + let books = []; + for (const item of $('div.item')) { + const a = $(item).find('a:first')[0]; + const img = $(a).find('img:first')[0]; + const span = $(item).find('span:first')[0]; + books.push({ + book_id: a.attribs.href, + book_name: img.attribs.alt, + book_pic: img.attribs.src, + book_remarks: span.children[0].data.trim(), + }); + } + return { + page: pg, + pagecount: $('div.page > a:contains(>)').length > 0 ? pg + 1 : pg, + list: books, + }; +} + +async function detail(id) { + var html = await request(url + id); + var $ = load(html); + let book = { + book_name: $('[property$=book_name]')[0].attribs.content, + book_year: $('[property$=update_time]')[0].attribs.content, + book_director: $('[property$=author]')[0].attribs.content, + book_content: $('[property$=description]')[0].attribs.content, + }; + html = await request(url + id + `list.html`); + $ = load(html); + let urls = []; + const links = $('dl>dd>a[href*="/html/"]'); + for (const l of links) { + var name = $(l).text().trim(); + var link = l.attribs.href; + urls.push(name + '$' + link); + } + book.volumes = '全卷'; + book.urls = urls.join('#'); + + return { + list: [book], + }; +} + +async function play(flag, id, flags) { + try { + var content = ''; + while (true) { + var html = await request(url + id); + var $ = load(html); + content += $('#chaptercontent') + .html() + .replace(/
|请收藏.*?<\/p>/g, '\n') + .trim(); + id = $('a.Readpage_down')[0].attribs.href; + if (id.indexOf('_') < 0) break; + } + return { + content: content + '\n\n', + }; + } catch (e) { + return { + content: '', + }; + } +} + +async function search(wd, quick, pg) { + const cook = await req(`${url}/user/hm.html?q=${encodeURIComponent(wd)}`, { + headers: { + accept: 'application/json', + 'User-Agent': MOBILE_UA, + Referer: `${url}/s?q=${encodeURIComponent(wd)}`, + }, + }); + const set_cookie = _.isArray(cook.headers['set-cookie']) ? cook.headers['set-cookie'].join(';;;') : cook.headers['set-cookie']; + const cks = set_cookie.split(';;;'); + const cookie = {}; + for (const c of cks) { + const tmp = c.trim(); + const idx = tmp.indexOf('='); + const k = tmp.substr(0, idx); + const v = tmp.substr(idx + 1, tmp.indexOf(';') - idx - 1); + cookie[k] = v; + } + const resp = await req(`${url}/user/search.html?q=${encodeURIComponent(wd)}&so=undefined`, { + headers: { + accept: 'application/json', + 'User-Agent': MOBILE_UA, + cookie: 'hm=' + cookie['hm'], + Referer: `${url}/s?q=${encodeURIComponent(wd)}`, + }, + }); + var data = JSON.parse(resp.content); + let books = []; + for (const book of data) { + books.push({ + book_id: book.url_list, + book_name: book.articlename, + book_pic: book.url_img, + book_remarks: book.author, + }); + } + return { + tline: 2, + list: books, + }; +} + +export function __jsEvalReturn() { + return { + init: init, + home: home, + category: category, + detail: detail, + play: play, + search: search, + }; +} From ff3f3a071d188dfa0dea271418b73d6288e7688c Mon Sep 17 00:00:00 2001 From: catvod <88956744+catvod@users.noreply.github.com> Date: Fri, 19 Jan 2024 14:27:36 +0800 Subject: [PATCH 09/12] Update config_open.json --- open/config_open.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/open/config_open.json b/open/config_open.json index ed747d5..2cad3cc 100644 --- a/open/config_open.json +++ b/open/config_open.json @@ -21,6 +21,12 @@ }, "read": { "sites": [ + { + "key": "13bqg", + "name": "笔趣阁", + "type": 10, + "api": "assets://js/13bqg_open.js" + }, { "key": "bookan", "name": "博看听书", From 3b8b157f001416c5c06526ca31e78cf2a060c2e3 Mon Sep 17 00:00:00 2001 From: catvod <88956744+catvod@users.noreply.github.com> Date: Fri, 19 Jan 2024 14:29:37 +0800 Subject: [PATCH 10/12] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 51fe729..fa7cd41 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Not being maintained and uncertain whether they will be updated. ### **Limits** - Only local `assets://`, `github://`, `gitee://`, `http(s)://user:pwd@xxx` config is supported, and http config without basic auth is not available. -- Only video & cloud disk & audio book & comic module. +- Only video & cloud disk & audio book & comic & txt novel module. - Not supporting sniffing. - Basic JS interface support. - No builtin maccms api support. From 85d6241a2d9c6a23e422cdc4f3e8f42422ebc0c1 Mon Sep 17 00:00:00 2001 From: catvod <88956744+catvod@users.noreply.github.com> Date: Tue, 23 Jan 2024 11:52:16 +0800 Subject: [PATCH 11/12] Update copymanga_open.js --- open/copymanga_open.js | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/open/copymanga_open.js b/open/copymanga_open.js index 1b0bf38..f3445ce 100644 --- a/open/copymanga_open.js +++ b/open/copymanga_open.js @@ -73,15 +73,12 @@ async function home(filter) { v: a.attribs.href.match(/.*?theme=(.*)&/)[1], }); } - - _.each(_.chunk(themeValues, 11), (vals) => { - let theme = { - key: 'theme', - name: '', - init: '', - value: vals, - }; - filterObj['c1'].push(theme); + filterObj['c1'].push({ + key: 'theme', + name: '', + init: '', + wrap: 1, + value: themeValues, }); filterObj['c1'].push(region); From 5a1cc7bd664d242437d5e1ad531128ad8d62e718 Mon Sep 17 00:00:00 2001 From: catvod <88956744+catvod@users.noreply.github.com> Date: Tue, 23 Jan 2024 11:59:41 +0800 Subject: [PATCH 12/12] Update index.js --- open/wrapper/index.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/open/wrapper/index.js b/open/wrapper/index.js index 2a599b2..ff2cb30 100644 --- a/open/wrapper/index.js +++ b/open/wrapper/index.js @@ -386,6 +386,13 @@ globalThis.JSFile = function (path) { this.flush = async function () { return; }; + + /** + * File to sharedBuffer. + */ + this.shared = async function () { + return; + }; /** * Closes the file descriptor.