comic-book-dl
Version:
238 lines (237 loc) • 8.36 kB
JavaScript
import got from '../../../../node_modules/got/dist/source/index.js';
import { load } from 'cheerio';
import { UA, fixPathName } from '../../../utils/index.js';
import { Base } from '../../../lib/parse/base/index.js';
import { ApiV4ChapterImageParse, ApiV4ChapterListParse, ApiV4Decrypt } from './crypto.js';
const api = {
v4Chapter: 'https://nnv4api.dmzj.com/comic/chapter/',
v3Chapter: 'https://m.idmzj.com/chapinfo/',
v3Api: 'https://api.dmzj.com',
v4Api: 'https://nnv4api.dmzj.com'
};
export class Dmzj extends Base {
constructor() {
super(...arguments);
this.type = 'Dmzj';
}
async parseBookInfo() {
const url = this.bookUrl;
const rawUrl = url;
let response;
try {
response = await got.get(url, this.genReqOptions());
}
catch (e) {
return false;
}
if (!response || response.statusCode !== 200) {
return false;
}
const isMobile = /m\.idmzj/.test(url);
let parseResult;
if (isMobile) {
parseResult = this.mSite(url, response.body);
}
else {
parseResult = await this.pcSite(url, response.body);
}
if (!parseResult)
return false;
const name = parseResult?.name;
const author = parseResult?.author;
const desc = parseResult?.desc;
const coverUrl = parseResult?.coverUrl;
let chapters = parseResult?.chapters || [];
if (!name || chapters.length === 0) {
return false;
}
chapters = chapters.reverse();
chapters = chapters.map((item, index) => {
const newItem = { ...item };
if (index !== 0) {
newItem.preChapter = {
name: chapters[index - 1].name,
rawName: chapters[index - 1].rawName,
href: chapters[index - 1].href,
index: chapters[index - 1].index
};
}
if (index !== chapters.length - 1) {
newItem.nextChapter = {
name: chapters[index + 1].name,
rawName: chapters[index + 1].rawName,
href: chapters[index + 1].href,
index: chapters[index + 1].index
};
}
return newItem;
});
return {
name,
pathName: fixPathName(name),
author,
desc,
coverUrl,
coverPath: '',
chapters,
url,
language: '简体',
rawUrl
};
}
async getImgList(url) {
const urlPath = /.*view\/(.*).html/g.exec(url)?.[1];
if (!urlPath)
return [];
const response = await got(`${api.v4Chapter}${urlPath}`, this.genReqOptions());
let imgList = [];
try {
const data = ApiV4ChapterImageParse(ApiV4Decrypt(response.body));
imgList = data?.Images ?? [];
imgList = imgList.map(img => decodeURIComponent(img));
}
catch (e) {
const response = await got(`${api.v3Chapter}${urlPath}.html`, this.genReqOptions());
let data = {};
try {
data = JSON.parse(response.body);
}
catch (e) {
console.log(e);
}
imgList = data['page_url'];
}
return imgList;
}
mSite(url, body) {
const $ = load(body);
const name = $('#comicName').text().trim();
const desc = $('.txtDesc.autoHeight').text().trim();
const author = $('.introName').toArray().map(el => $(el).text()).join('/').trim();
const coverUrl = $('#Cover img').attr('src')?.trim() ?? '';
const chaptersReg = /initIntroData\((.*?)\)/gm;
const chaptersJSONstr = chaptersReg.exec(body)?.[1] ?? '';
let tempChapters = [];
try {
tempChapters = JSON.parse(chaptersJSONstr);
}
catch (e) {
return null;
}
if (!Array.isArray(tempChapters))
tempChapters = [];
tempChapters = tempChapters.map((item) => item?.data ?? null);
tempChapters = tempChapters.flat();
const chapters = [];
const { origin } = new URL(url);
tempChapters.forEach((item, index) => {
const chapterIndex = item['chapter_order'] ?? index;
chapters.push({
name: `${chapterIndex}_${fixPathName(item['chapter_name'])}`,
rawName: item['chapter_name'],
href: `${origin}/view/${item['comic_id']}/${item.id}.html`,
imageList: [],
imageListPath: [],
index: chapterIndex,
other: item
});
});
return {
name,
author,
desc,
coverUrl,
chapters,
};
}
async pcSite(url, body) {
const reg = /.*\/(.*?)$/;
const params = {};
let comicName = url.match(reg)?.[1] ?? '';
comicName = comicName.replace(/\.html/, '');
params['comic_py'] = comicName;
const api = 'https://www.idmzj.com/api/v1/comic1/comic/detail';
const nuxtDataStr = body.match(/window\.__NUXT__=\((.*)\)/gm)?.[0] ?? '';
const fieldGroup = ['channel', 'app_name', 'version', 'timestamp'];
fieldGroup.forEach((field, i) => {
const fieldReg = new RegExp(`${field}:(.*?),`);
const key = fieldGroup[i];
params[key] = nuxtDataStr.match(fieldReg)?.[1] ?? '';
});
const queryStr = new URLSearchParams(params).toString();
const response = await got.get(`${api}?${queryStr}`, this.genReqOptions());
let resJSON = null;
try {
resJSON = JSON.parse(response.body);
resJSON = resJSON?.data?.comicInfo || {};
}
catch (e) {
console.log(e);
return null;
}
const author = resJSON?.authorInfo?.authorName || '';
const name = resJSON?.title || '';
const desc = resJSON?.description || '';
const coverUrl = resJSON?.cover || '';
const chapters = [];
let tempChapters = resJSON?.chapterList || [];
if (tempChapters.length <= 0) {
const comicId = resJSON?.id;
tempChapters = await this.commonFetchChaptersList(comicId);
}
else {
tempChapters = tempChapters.map((item) => item?.data ?? null);
tempChapters = tempChapters.flat();
}
tempChapters.forEach((item, index) => {
const chapterIndex = item['chapter_order'] ?? index;
chapters.push({
name: `${chapterIndex}_${fixPathName(item['chapter_title'])}`,
rawName: item['chapter_title'],
href: `https://m.idmzj.com/view/${resJSON?.id}/${item['chapter_id']}.html`,
imageList: [],
imageListPath: [],
index: chapterIndex,
other: item
});
});
return {
name,
author,
desc,
coverUrl,
chapters,
};
}
async commonFetchChaptersList(id) {
if (!id)
return [];
const url = `${api.v4Api}/comic/detail/${id}?uid=2665531`;
const response = await got.get(url, this.genReqOptions());
let chapterList = [];
try {
const data = ApiV4ChapterListParse(ApiV4Decrypt(response.body));
const tempChapterList = data?.Chapters ?? [];
const dataFieldList = tempChapterList.map(item => item.Data);
chapterList = dataFieldList.flat().map(item => {
return {
['chapter_order']: item.ChapterOrder,
['chapter_title']: item.ChapterTitle,
['chapter_id']: item.ChapterId
};
});
}
catch (e) {
return [];
}
return chapterList.reverse();
}
genReqOptions() {
return {
headers: {
'user-agent': UA
},
http2: true
};
}
}