const mangayomiSources = [{ "name": "漫画DB", "lang": "zh", "baseUrl": "https://www.manhuadb.com", "apiUrl": "", "iconUrl": "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/javascript/icon/zh.manhuadb.png", "typeSource": "single", "isManga": true, "isNsfw": false, "version": "0.0.25", "dateFormat": "", "dateFormatLocale": "", "pkgPath": "manga/src/zh/manhuadb.js" }]; class DefaultExtension extends MProvider { base64decode(str) { var base64DecodeChars = new Array(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 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, -1, -1, -1, -1, -1, -1, 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, -1, -1, -1, -1, -1); var c1, c2, c3, c4; var i, len, out; len = str.length; i = 0; out = ""; while (i < len) { do { c1 = base64DecodeChars[str.charCodeAt(i++) & 0xff] } while (i < len && c1 == -1); if (c1 == -1) break; do { c2 = base64DecodeChars[str.charCodeAt(i++) & 0xff] } while (i < len && c2 == -1); if (c2 == -1) break; out += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4)); do { c3 = str.charCodeAt(i++) & 0xff; if (c3 == 61) return out; c3 = base64DecodeChars[c3] } while (i < len && c3 == -1); if (c3 == -1) break; out += String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2)); do { c4 = str.charCodeAt(i++) & 0xff; if (c4 == 61) return out; c4 = base64DecodeChars[c4] } while (i < len && c4 == -1); if (c4 == -1) break; out += String.fromCharCode(((c3 & 0x03) << 6) | c4) } return out } coverUrlConvert(cover_url) { if (cover_url.search("com") == -1) { return this.source.baseUrl + cover_url; } return cover_url; } async getMangas(url, search) { const res = await new Client().get(this.source.baseUrl + url); const doc = new Document(res.body); var str; if (search) { str = "div.comicbook-index"; } else { str = "div.media"; } const items = doc.select(str); const mangas = []; for (const item of items) { const cover = this.coverUrlConvert(item.selectFirst("a.d-block img").attr("src")); var title; if (search) { title = item.selectFirst("a.d-block").attr("title"); } else { title = item.selectFirst("a.d-block img").attr("alt"); title = title.replace("的封面图", ""); } const url = item.selectFirst("a.d-block").attr("href"); mangas.push({ name: title, link: url, imageUrl: cover }); } return { list: mangas, hasNextPage: true } } async getPopular(page) { const res = await new Client().get(this.source.baseUrl); const doc = new Document(res.body); const items = doc.select("div.comicbook-index"); var mangas = []; for (let item of items) { const cover = this.coverUrlConvert(item.selectFirst("a img").attr("src")); const title = item.selectFirst("a img").attr("alt"); const url = item.selectFirst("a").attr("href") mangas.push({ name: title.replace("封面", ""), link: url, imageUrl: cover }); } return { list: mangas, hasNextPage: false }; } async getLatestUpdates(page) { return await this.getMangas(`/manhua/list-page-${page}.html`, false); } async search(query, page, filters) { if (query == "") { var locations, readers, status, categories; for (const filter of filters) { if (filter["type"] == "locations") { locations = filter["values"][filter["state"]]["value"]; } else if (filter["type"] == "readers") { readers = filter["values"][filter["state"]]["value"]; } else if (filter["type"] == "status") { status = filter["values"][filter["state"]]["value"]; } else if (filter["type"] == "categories") { categories = filter["values"][filter["state"]]["value"]; } } const url = `/manhua/list${locations}${readers}${status}${categories}-page-${page}.html`; return await this.getMangas(url.replaceAll("all", ""), false); } else { return await this.getMangas(`/search?q=${query}&p=${page}`, true); } } async getDetail(url) { const res = await new Client().get(this.source.baseUrl + url); const doc = new Document(res.body); const title = doc.selectFirst("h1.comic-title").text; const cover = this.coverUrlConvert(doc.selectFirst("td.comic-cover img").attr("src")); const desc = doc.selectFirst("p.comic_story").text; const author = doc.selectFirst("ul.creators a").text; var tags = doc.select("ul.tags a").map(e => e.text); var status = 5; if (tags[0] == "已完结") { status = 1; tags.shift(); } if (tags[0] == "连载中") { status = 0; tags.shift(); } const items = doc.select("ol.links-of-books"); const episodes = []; const ep_names = doc.select("span.h3"); const ep_titles = []; for (const ep_name of ep_names) { ep_titles.push(ep_name.text); } var index = 0; for (const lists of items) { const chapters = lists.select("li"); for (const chapter of chapters) { const name = chapter.selectFirst("a").attr("title"); const url = chapter.selectFirst("a").attr("href"); episodes.push({ name: `[[${ep_titles[index]}]]${name}`, url: url }); } index = index + 1; } episodes.reverse(); return { name: title, imageUrl: cover, description: desc, episodes: episodes, genre: tags, author: author, status: status }; } async getPageList(url) { const res = await new Client().get(this.source.baseUrl + url); const html = res.body; const doc = new Document(html); const urls = []; var script_str = html.match(/