diff --git a/javascript/icon/zh.manhuadb.png b/javascript/icon/zh.manhuadb.png new file mode 100644 index 00000000..3c4a76b7 Binary files /dev/null and b/javascript/icon/zh.manhuadb.png differ diff --git a/javascript/manga/src/zh/77mh.js b/javascript/manga/src/zh/77mh.js index 6edec437..47a8f139 100644 --- a/javascript/manga/src/zh/77mh.js +++ b/javascript/manga/src/zh/77mh.js @@ -1,258 +1,259 @@ const mangayomiSources = [{ - "name": "新新漫画", - "lang": "zh", - "baseUrl": "https://www.77mh.nl", - "apiUrl": "", - "iconUrl": "https://www.77mh.nl/favicon.ico", - "typeSource": "single", - "isManga": true, - "isNsfw": false, - "version": "0.0.1", - "apiUrl": "", - "dateFormat": "", - "dateFormatLocale": "", - "pkgName": "manga/src/zh/77mh.js" - }]; - - class DefaultExtension extends MProvider { - StringResolve1(p, a, c, k, e, d) { - e = function(c) { - return c.toString(36) - }; - if (!''.replace(/^/, String)) { - while (c--) { - d[c.toString(a)] = k[c] || c.toString(a) - } - k = [function(e) { - return d[e] - }]; - e = function() { - return '\\w+' - }; - c = 1 - }; + "name": "新新漫画", + "lang": "zh", + "baseUrl": "https://www.77mh.nl", + "apiUrl": "", + "iconUrl": "https://www.77mh.nl/favicon.ico", + "typeSource": "single", + "isManga": true, + "isNsfw": false, + "version": "0.0.1", + "apiUrl": "", + "dateFormat": "", + "dateFormatLocale": "", + "pkgName": "manga/src/zh/77mh.js" +}]; + +class DefaultExtension extends MProvider { + StringResolve1(p, a, c, k, e, d) { + e = function(c) { + return c.toString(36) + }; + if (!''.replace(/^/, String)) { while (c--) { - if (k[c]) { - p = p.replace(new RegExp('\\b' + e(c) + '\\b', 'g'), k[c]) - } + d[c.toString(a)] = k[c] || c.toString(a) + } + k = [function(e) { + return d[e] + }]; + e = function() { + return '\\w+' + }; + c = 1 + }; + while (c--) { + if (k[c]) { + p = p.replace(new RegExp('\\b' + e(c) + '\\b', 'g'), k[c]) } - return p } - - StringResolve2(p, a, c, k, e, d) { - e = function(c) { - return (c < a ? '' : e(parseInt(c / a))) + ((c = c % a) > 35 ? String.fromCharCode(c + 29) : c.toString(36)) - }; - if (!''.replace(/^/, String)) { - while (c--) { - d[e(c)] = k[c] || e(c) - } - k = [function(e) { - return d[e] - }]; - e = function() { - return '\\w+' - }; - c = 1 - }; + return p + } + + StringResolve2(p, a, c, k, e, d) { + e = function(c) { + return (c < a ? '' : e(parseInt(c / a))) + ((c = c % a) > 35 ? String.fromCharCode(c + 29) : c.toString(36)) + }; + if (!''.replace(/^/, String)) { while (c--) { - if (k[c]) { - p = p.replace(new RegExp('\\b' + e(c) + '\\b', 'g'), k[c]) - } + d[e(c)] = k[c] || e(c) } - return p - } - - async getIndex1(url) { - const res = await new Client().get(url); - const doc = new Document(res.body); - const elements = doc.select("div.ar_list_co li"); - const mangas = []; - for (const element of elements) { - const title = element.selectFirst("span a").text; - const url = element.selectFirst("span a").attr("href"); - const cover = element.selectFirst("img").attr("src"); - mangas.push({ - name: title, - link: url, - imageUrl: cover - }); - } - return { - list: mangas, - hasNextPage: true + k = [function(e) { + return d[e] + }]; + e = function() { + return '\\w+' }; - - } - - async getIndex2(url) { - const res = await new Client().get(url); - const doc = new Document(res.body); - const elements = doc.select("div.ar_list_co dl"); - const mangas = []; - for (const element of elements) { - const title = element.selectFirst("h1 a").text.replace("", "").replace("", ""); - const url = element.selectFirst("h1 a").attr("href"); - const cover = element.selectFirst("img").attr("src"); - mangas.push({ - name: title, - link: url, - imageUrl: cover - }); + c = 1 + }; + while (c--) { + if (k[c]) { + p = p.replace(new RegExp('\\b' + e(c) + '\\b', 'g'), k[c]) } - return { - list: mangas, - hasNextPage: true - }; - } - - async getPopular(page) { - return await this.getIndex1(this.source.baseUrl + "/new_coc.html"); - } - - async getLatestUpdates(page) { - return await this.getIndex1(`${this.source.baseUrl}/lianzai/index_${page - 1}.html`); - } - - async search(query, page, filters) { - var url; - if (query == "") { - url = `${this.source.baseUrl}${filters[0]["values"][filters[0]["state"]]["value"]}/index_${page-1}.html` - } else { - url = `${this.source.baseUrl.replace("www","so")}/k.php?k=${query}&p=${page}`; - } - return await this.getIndex2(url); - } - - async getDetail(url) { - const res = await new Client().get(this.source.baseUrl + url); - const doc = new Document(res.body); - const info = doc.selectFirst("div.ar_list_coc"); - const cover = info.selectFirst("img").attr("src"); - const title = info.selectFirst("h1").text; - const info_other = info.selectFirst("ul.ar_list_coc"); - const author = info_other.selectFirst("a").text; - const status_str = info_other.select("a")[1].text; - var status; - if (status_str == "已完结") { - status = 1; - } else { - status = 0; - } - const desc = info.selectFirst("i#det").text; - const elements = doc.select("ul.ar_rlos_bor li a"); - const chapters = []; - for (const element of elements) { - chapters.push({ - name: element.text, - url: element.attr("href") - }); - } - return { + return p + } + + async getIndex1(url) { + const res = await new Client().get(url); + const doc = new Document(res.body); + const elements = doc.select("div.ar_list_co li"); + const mangas = []; + for (const element of elements) { + const title = element.selectFirst("span a").text; + const url = element.selectFirst("span a").attr("href"); + const cover = element.selectFirst("img").attr("src"); + mangas.push({ name: title, - imageUrl: cover, - description: desc, - author: author, - status: status, - episodes: chapters - }; + link: url, + imageUrl: cover + }); } + return { + list: mangas, + hasNextPage: true + }; + + } + + async getIndex2(url) { + const res = await new Client().get(url); + const doc = new Document(res.body); + const elements = doc.select("div.ar_list_co dl"); + const mangas = []; + for (const element of elements) { + const title = element.selectFirst("h1 a").text.replace("", "").replace("", ""); + const url = element.selectFirst("h1 a").attr("href"); + const cover = element.selectFirst("img").attr("src"); + mangas.push({ + name: title, + link: url, + imageUrl: cover + }); + } + return { + list: mangas, + hasNextPage: true + }; + + } - async getPageList(url) { - const preference = new SharedPreferences(); - const image_host = preference.get("imghost"); - const res = await new Client().get(this.source.baseUrl + url); - const strs = res.body.match(/return p}\('(.*?)'.split\('/)[1].split(','); - var result; - try { - result = this.StringResolve1(strs[0], strs[1], strs[2], strs[3].split('|'), 0, {}).replaceAll("'", ""); - } catch { - result = this.StringResolve2(strs[0], strs[1], strs[2], strs[3].split('|'), 0, {}).replaceAll("'", ""); - } - const url_part = result.match(/var img_s=(.*?);var preLink_b/)[1]; - const urls = result.match(/var msg=(.*?);var maxPage/)[1].replaceAll("\\", "").split('|'); - const pages = []; - for (const url of urls) { - pages.push(image_host + `/h${url_part}/` + url); - } - return pages; + async getPopular(page) { + return await this.getIndex1(this.source.baseUrl + "/new_coc.html"); + } + + async getLatestUpdates(page) { + return await this.getIndex1(`${this.source.baseUrl}/lianzai/index_${page - 1}.html`); + } + + async search(query, page, filters) { + var url; + if (query == "") { + url = `${this.source.baseUrl}${filters[0]["values"][filters[0]["state"]]["value"]}/index_${page-1}.html` + } else { + url = `${this.source.baseUrl.replace("www","so")}/k.php?k=${query}&p=${page}`; } - - getFilterList() { - return [{ - type: "category", - name: "分类", - type_name: "SelectFilter", - values: [{ - value: "/rexue", - name: "热血机战", - type_name: "SelectOption" - }, - { - value: "/kehuan", - name: "科幻未来", - type_name: "SelectOption" - }, - { - value: "/kongbu", - name: "恐怖惊悚", - type_name: "SelectOption" - }, - { - value: "/xuanyi", - name: "推理悬疑", - type_name: "SelectOption" - }, - { - value: "/gaoxiao", - name: "滑稽搞笑", - type_name: "SelectOption" - }, - { - value: "/love", - name: "恋爱生活", - type_name: "SelectOption" - }, - { - value: "/danmei", - name: "耽美人生", - type_name: "SelectOption" - }, - { - value: "/tiyu", - name: "体育竞技", - type_name: "SelectOption" - }, - { - value: "/chunqing", - name: "纯情少女", - type_name: "SelectOption" - }, - { - value: "/qihuan", - name: "魔法奇幻", - type_name: "SelectOption" - }, - { - value: "/wuxia", - name: "武侠经典", - type_name: "SelectOption" - } - ] - }]; + return await this.getIndex2(url); + } + + async getDetail(url) { + const res = await new Client().get(this.source.baseUrl + url); + const doc = new Document(res.body); + const info = doc.selectFirst("div.ar_list_coc"); + const cover = info.selectFirst("img").attr("src"); + const title = info.selectFirst("h1").text; + const info_other = info.selectFirst("ul.ar_list_coc"); + const author = info_other.selectFirst("a").text; + const status_str = info_other.select("a")[1].text; + var status; + if (status_str == "已完结") { + status = 1; + } else { + status = 0; } + const desc = info.selectFirst("i#det").text; + const elements = doc.select("ul.ar_rlos_bor li a"); + const chapters = []; + for (const element of elements) { + chapters.push({ + name: element.text, + url: element.attr("href") + }); + } + chapters.reverse(); + return { + name: title, + imageUrl: cover, + description: desc, + author: author, + status: status, + episodes: chapters + }; + } + + async getPageList(url) { + const preference = new SharedPreferences(); + const image_host = preference.get("imghost"); + const res = await new Client().get(this.source.baseUrl + url); + const strs = res.body.match(/return p}\('(.*?)'.split\('/)[1].split(','); + var result; + try { + result = this.StringResolve1(strs[0], strs[1], strs[2], strs[3].split('|'), 0, {}).replaceAll("'", ""); + } catch { + result = this.StringResolve2(strs[0], strs[1], strs[2], strs[3].split('|'), 0, {}).replaceAll("'", ""); + } + const url_part = result.match(/var img_s=(.*?);var preLink_b/)[1]; + const urls = result.match(/var msg=(.*?);var maxPage/)[1].replaceAll("\\", "").split('|'); + const pages = []; + for (const url of urls) { + pages.push(image_host + `/h${url_part}/` + url); + } + return pages; + } - getSourcePreferences() { - return [{ - "key": "imghost", - "listPreference": { - "title": "图片服务器", - "summary": "", - "valueIndex": 0, - "entries": ["服务器1", "服务器2"], - "entryValues": ["https://picsh.77dm.top", "https://imgsh.dm365.top"], + getFilterList() { + return [{ + type: "category", + name: "分类", + type_name: "SelectFilter", + values: [{ + value: "/rexue", + name: "热血机战", + type_name: "SelectOption" + }, + { + value: "/kehuan", + name: "科幻未来", + type_name: "SelectOption" + }, + { + value: "/kongbu", + name: "恐怖惊悚", + type_name: "SelectOption" + }, + { + value: "/xuanyi", + name: "推理悬疑", + type_name: "SelectOption" + }, + { + value: "/gaoxiao", + name: "滑稽搞笑", + type_name: "SelectOption" + }, + { + value: "/love", + name: "恋爱生活", + type_name: "SelectOption" + }, + { + value: "/danmei", + name: "耽美人生", + type_name: "SelectOption" + }, + { + value: "/tiyu", + name: "体育竞技", + type_name: "SelectOption" + }, + { + value: "/chunqing", + name: "纯情少女", + type_name: "SelectOption" + }, + { + value: "/qihuan", + name: "魔法奇幻", + type_name: "SelectOption" + }, + { + value: "/wuxia", + name: "武侠经典", + type_name: "SelectOption" } - }]; - } + ] + }]; + } + + getSourcePreferences() { + return [{ + "key": "imghost", + "listPreference": { + "title": "图片服务器", + "summary": "", + "valueIndex": 0, + "entries": ["服务器1", "服务器2"], + "entryValues": ["https://picsh.77dm.top", "https://imgsh.dm365.top"], + } + }]; + } } \ No newline at end of file diff --git a/javascript/manga/src/zh/manhuadb.js b/javascript/manga/src/zh/manhuadb.js index 80dcb4b2..496b1095 100644 --- a/javascript/manga/src/zh/manhuadb.js +++ b/javascript/manga/src/zh/manhuadb.js @@ -1,668 +1,668 @@ const mangayomiSources = [{ - "name": "漫画DB", - "lang": "zh", - "baseUrl": "https://www.manhuadb.com", - "apiUrl": "", - "iconUrl": "https://www.manhuadb.com/assets/www/img/favicon.png", - "typeSource": "single", - "isManga": true, - "isNsfw": false, - "version": "0.0.1", - "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 + "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.1", + "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) } - - coverUrlConvert(cover_url) { - if (cover_url.search("com") == -1) { - return this.source.baseUrl + cover_url; - } - return cover_url; + return out + } + + coverUrlConvert(cover_url) { + if (cover_url.search("com") == -1) { + return this.source.baseUrl + cover_url; } - - async getMangas(url, search) { - const res = await new Client().get(this.source.baseUrl + url); - const doc = new Document(res.body); - var str; + 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) { - str = "div.comicbook-index"; + title = item.selectFirst("a.d-block").attr("title"); } else { - str = "div.media"; + title = item.selectFirst("a.d-block img").attr("alt"); + title = title.replace("的封面图", ""); } - 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; - } - return { + const url = item.selectFirst("a.d-block").attr("href"); + mangas.push({ name: title, - imageUrl: cover, - description: desc, - episodes: episodes, - genre: tags, - author: author, - status: status - }; + link: url, + imageUrl: cover + }); } - - 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(/