const mangayomiSources = [{ "name": "漫画柜", "lang": "zh", "baseUrl": "https://www.manhuagui.com", "apiUrl": "", "iconUrl": "https://www.manhuagui.com/favicon.ico", "typeSource": "single", "isManga": true, "isNsfw": false, "version": "0.0.25", "dateFormat": "", "dateFormatLocale": "", "pkgPath": "manga/src/zh/manhuagui.js" }]; LZString = function() { function o(o, r) { if (!t[o]) { t[o] = {}; for (var n = 0; n < o.length; n++) t[o][o.charAt(n)] = n } return t[o][r] } var r = String.fromCharCode, n = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", e = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$", t = {}, i = { decompressFromBase64: function(r) { return null == r ? "" : "" == r ? null : i._decompress(r.length, 32, function(e) { return o(n, r.charAt(e)) }) }, _decompress: function(o, n, e) { var t, i, s, p, u, c, a, l, f = [], h = 4, d = 4, m = 3, v = "", w = [], A = { val: e(0), position: n, index: 1 }; for (i = 0; 3 > i; i += 1) f[i] = i; for (p = 0, c = Math.pow(2, 2), a = 1; a != c;) u = A.val & A.position, A.position >>= 1, 0 == A.position && (A.position = n, A.val = e(A.index++)), p |= (u > 0 ? 1 : 0) * a, a <<= 1; switch (t = p) { case 0: for (p = 0, c = Math.pow(2, 8), a = 1; a != c;) u = A.val & A.position, A.position >>= 1, 0 == A.position && (A.position = n, A.val = e(A.index++)), p |= (u > 0 ? 1 : 0) * a, a <<= 1; l = r(p); break; case 1: for (p = 0, c = Math.pow(2, 16), a = 1; a != c;) u = A.val & A.position, A.position >>= 1, 0 == A.position && (A.position = n, A.val = e(A.index++)), p |= (u > 0 ? 1 : 0) * a, a <<= 1; l = r(p); break; case 2: return "" } for (f[3] = l, s = l, w.push(l);;) { if (A.index > o) return ""; for (p = 0, c = Math.pow(2, m), a = 1; a != c;) u = A.val & A.position, A.position >>= 1, 0 == A.position && (A.position = n, A.val = e(A.index++)), p |= (u > 0 ? 1 : 0) * a, a <<= 1; switch (l = p) { case 0: for (p = 0, c = Math.pow(2, 8), a = 1; a != c;) u = A.val & A.position, A.position >>= 1, 0 == A.position && (A.position = n, A.val = e(A.index++)), p |= (u > 0 ? 1 : 0) * a, a <<= 1; f[d++] = r(p), l = d - 1, h--; break; case 1: for (p = 0, c = Math.pow(2, 16), a = 1; a != c;) u = A.val & A.position, A.position >>= 1, 0 == A.position && (A.position = n, A.val = e(A.index++)), p |= (u > 0 ? 1 : 0) * a, a <<= 1; f[d++] = r(p), l = d - 1, h--; break; case 2: return w.join("") } if (0 == h && (h = Math.pow(2, m), m++), f[l]) v = f[l]; else { if (l !== d) return null; v = s + s.charAt(0) } w.push(v), f[d++] = s + v.charAt(0), h--, s = v, 0 == h && (h = Math.pow(2, m), m++) } } }; return i }(); function decode(text) { function packed(functionStr, a, c, data) { function e(c) { return String(c < a ? '' : e(Math.floor(c / a))) + String((c % a > 35) ? String.fromCharCode(c % a + 29) : tr(c % a, 36)); } function tr(value, num) { var tmp = itr(value, num); return tmp == '' ? '0' : tmp; } function itr(value, num) { const d = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; return value <= 0 ? '' : itr(Math.floor(value / num), num) + d[value % num]; } c = c - 1; const d = {}; while (c + 1) { d[e(c)] = data[c] == '' ? e(c) : data[c]; c -= 1; } const pieces = functionStr.split(/\b(\w+)\b/); const js = pieces.map(function(x) { return d[x] !== undefined ? d[x] : x; }).join('').replace(/\\'/g, '\''); return JSON.parse(js.match(/^.*\((\{.*\})\).*$/)[1]); } const m = text.match(/^.*\}\(\'(.*)\',(\d*),(\d*),\'([\w|\+|\/|=]*)\'.*$/); return packed(m[1], parseInt(m[2]), parseInt(m[3]), LZString.decompressFromBase64(m[4]).split('|')); } class DefaultExtension extends MProvider { headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36" }; getHeaders(url) { return { Referer: this.source.baseUrl } } async getItems(url, p) { const res = await new Client().get(this.source.baseUrl + url, this.headers); const doc = new Document(res.body); const mangas = []; const elements = doc.select(p); for (const element of elements) { const title = element.selectFirst("a").attr("title"); const url = element.selectFirst("a").attr("href"); var cover = element.selectFirst("img").attr("src"); if (cover == "") { cover = element.selectFirst("img").attr("data-src"); } cover = "https:" + cover; mangas.push({ name: title, imageUrl: cover, link: url }); } return { list: mangas, hasNextPage: true }; } async getPopular(page) { return await this.getItems(`/list/view_p${page}.html`, "ul#contList li"); } async getLatestUpdates(page) { return await this.getItems(`/list/index_p${page}.html`, "ul#contList li"); } async search(query, page, filters) { if (query == "") { var sort, locations, categories, status, reader; for (const filter of filters) { if (filter["type"] == "sort") { sort = filter["values"][filter["state"]]["value"]; } else if (filter["type"] == "locations") { locations = filter["values"][filter["state"]]["value"]; } else if (filter["type"] == "categories") { categories = filter["values"][filter["state"]]["value"]; } else if (filter["type"] == "status") { status = filter["values"][filter["state"]]["value"]; } else if (filter["type"] == "reader") { reader = filter["values"][filter["state"]]["value"]; } } const params = [locations, categories, reader, status]; return await this.getItems(`/list${"/"+params.filter(item => item != "").join("_")}/${sort}_p${page}.html`, "ul#contList li"); } else { return await this.getItems(`/s/${query}_p${page}.html`, "div.book-result li"); } } async getDetail(url) { const res = await new Client().get(this.source.baseUrl + url, this.headers); const doc = new Document(res.body); const title = doc.selectFirst("div.book-title h1").text; const cover = "https:" + doc.selectFirst("p.hcover img").attr("src"); const desc = doc.selectFirst("div#intro-all").text; const info = doc.select("ul.detail-list li")[1].select("span"); const authors = info[1].text.replace("漫画作者:", ""); const genres = info[0].select("a").map(e => e.text); const status_str = doc.selectFirst("li.status span").text; var status; if (status_str == "已完结") { status = 1; } else { status = 0; } const eps = []; var chapter_html; if (res.body.search("请点击此处继续阅读!") == -1) { chapter_html = doc; } else { const text = LZString.decompressFromBase64(doc.selectFirst("input#__VIEWSTATE").attr("value")); chapter_html = new Document(text); } const ch_title = chapter_html.select("h4 span"); const chapters = chapter_html.select("div.chapter-list") var index = 0; for (const chs of ch_title) { const t = chs.text; for (const ch of chapters[index].select("ul")) { const ep_ = []; for (const c of ch.select("a.status0")) { ep_.push({ name: `|${t}|` + c.attr("title"), url: c.attr("href") }); } ep_.reverse(); for (const e of ep_) { eps.push(e); } } index = index + 1; } eps.reverse(); return { name: title, imageUrl: cover, description: desc, genre: genres, author: authors, status: status, episodes: eps }; } async getPageList(url) { const preference = new SharedPreferences(); const image_host = preference.get("imghost"); const res = await new Client().get(this.source.baseUrl + url, this.headers); const datas = decode(res.body); const imgs = []; for (const data of datas["files"]) { imgs.push(`https://${image_host}.hamreus.com` + datas["path"] + data + `?e=${datas["sl"]["e"]}&m=${datas["sl"]["m"]}`); } return imgs; } getFilterList() { return [{ type: "sort", name: "排序", type_name: "SelectFilter", values: [{ type_name: "SelectOption", name: "最新发布", value: "index" }, { type_name: "SelectOption", name: "最新更新", value: "update" }, { type_name: "SelectOption", name: "人气最旺", value: "view" }, { type_name: "SelectOption", name: "评分最高", value: "rate" } ] }, { type: "locations", name: "地区", type_name: "SelectFilter", values: [{ type_name: "SelectOption", name: "全部", value: "" }, { type_name: "SelectOption", name: "日本", value: "japan" }, { type_name: "SelectOption", name: "港台", value: "hongkong" }, { type_name: "SelectOption", name: "其他", value: "other" }, { type_name: "SelectOption", name: "欧美", value: "europe" }, { type_name: "SelectOption", name: "内地", value: "china" }, { type_name: "SelectOption", name: "韩国", value: "korea" } ] }, { type: "categories", name: "剧情", type_name: "SelectFilter", values: [{ type_name: "SelectOption", name: "全部", value: "" }, { type_name: "SelectOption", name: "热血", value: "rexue" }, { type_name: "SelectOption", name: "冒险", value: "maoxian" }, { type_name: "SelectOption", name: "魔幻", value: "mohuan" }, { type_name: "SelectOption", name: "神鬼", value: "shengui" }, { type_name: "SelectOption", name: "搞笑", value: "gaoxiao" }, { type_name: "SelectOption", name: "萌系", value: "mengxi" }, { type_name: "SelectOption", name: "爱情", value: "aiqing" }, { type_name: "SelectOption", name: "科幻", value: "kehuan" }, { type_name: "SelectOption", name: "魔法", value: "mofa" }, { type_name: "SelectOption", name: "格斗", value: "gedou" }, { type_name: "SelectOption", name: "武侠", value: "wuxia" }, { type_name: "SelectOption", name: "机战", value: "jizhan" }, { type_name: "SelectOption", name: "战争", value: "zhanzheng" }, { type_name: "SelectOption", name: "竞技", value: "jingji" }, { type_name: "SelectOption", name: "体育", value: "tiyu" }, { type_name: "SelectOption", name: "校园", value: "xiaoyuan" }, { type_name: "SelectOption", name: "生活", value: "shenghuo" }, { type_name: "SelectOption", name: "励志", value: "lizhi" }, { type_name: "SelectOption", name: "历史", value: "lishi" }, { type_name: "SelectOption", name: "伪娘", value: "weiniang" }, { type_name: "SelectOption", name: "宅男", value: "zhainan" }, { type_name: "SelectOption", name: "腐女", value: "funv" }, { type_name: "SelectOption", name: "耽美", value: "danmei" }, { type_name: "SelectOption", name: "百合", value: "baihe" }, { type_name: "SelectOption", name: "后宫", value: "hougong" }, { type_name: "SelectOption", name: "治愈", value: "zhiyu" }, { type_name: "SelectOption", name: "美食", value: "meishi" }, { type_name: "SelectOption", name: "推理", value: "tuili" }, { type_name: "SelectOption", name: "悬疑", value: "xuanyi" }, { type_name: "SelectOption", name: "恐怖", value: "kongbu" }, { type_name: "SelectOption", name: "四格", value: "sige" }, { type_name: "SelectOption", name: "职场", value: "zhichang" }, { type_name: "SelectOption", name: "侦探", value: "zhentan" }, { type_name: "SelectOption", name: "社会", value: "shehui" }, { type_name: "SelectOption", name: "音乐", value: "yinyue" }, { type_name: "SelectOption", name: "舞蹈", value: "wudao" }, { type_name: "SelectOption", name: "杂志", value: "zazhi" }, { type_name: "SelectOption", name: "黑道", value: "heidao" } ] }, { type: "reader", name: "受众", type_name: "SelectFilter", values: [{ type_name: "SelectOption", name: "全部", value: "" }, { type_name: "SelectOption", name: "少女", value: "shaonv" }, { type_name: "SelectOption", name: "少年", value: "shaonian" }, { type_name: "SelectOption", name: "青年", value: "qingnian" }, { type_name: "SelectOption", name: "儿童", value: "ertong" }, { type_name: "SelectOption", name: "通用", value: "tongyong" } ] }, { type: "status", name: "状态", type_name: "SelectFilter", values: [{ type_name: "SelectOption", name: "全部", value: "" }, { type_name: "SelectOption", name: "连载中", value: "lianzai" }, { type_name: "SelectOption", name: "已完结", value: "wanjie" } ] } ]; } getSourcePreferences() { return [{ "key": "imghost", "listPreference": { "title": "图片服务器", "summary": "", "valueIndex": 0, "entries": ["通用", "欧洲", "美国"], "entryValues": ["i", "eu", "us"], } }]; } }