Merge remote-tracking branch 'upstream/main'

main
FongMi 2 years ago
commit c85a25a1a0
  1. 4
      README.md
  2. 165
      open/13bqg_open.js
  3. 1
      open/bookan_open.js
  4. 16
      open/config_open.json
  5. 204
      open/copymanga_open.js
  6. 7
      open/wrapper/index.js

@ -13,8 +13,8 @@ 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 video&cloud disk&audio book module.
- 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 & txt novel module.
- Not supporting sniffing.
- Basic JS interface support.
- No builtin maccms api support.

@ -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(/<br>|请收藏.*?<\/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,
};
}

@ -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: '',

@ -21,6 +21,12 @@
},
"read": {
"sites": [
{
"key": "13bqg",
"name": "笔趣阁",
"type": 10,
"api": "assets://js/13bqg_open.js"
},
{
"key": "bookan",
"name": "博看听书",
@ -29,6 +35,16 @@
}
]
},
"comic": {
"sites": [
{
"key": "copymanga",
"name": "拷贝漫画",
"type": 20,
"api": "assets://js/copymanga_open.js"
}
]
},
"pan": {
"sites": [
{

@ -0,0 +1,204 @@
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],
});
}
filterObj['c1'].push({
key: 'theme',
name: '',
init: '',
wrap: 1,
value: themeValues,
});
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 || ''}&region=${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,
};
}

@ -387,6 +387,13 @@ globalThis.JSFile = function (path) {
return;
};
/**
* File to sharedBuffer.
*/
this.shared = async function () {
return;
};
/**
* Closes the file descriptor.
*

Loading…
Cancel
Save