const mangayomiSources = [{ "name": "Novel Updates", "lang": "en", "baseUrl": "https://www.novelupdates.com", "apiUrl": "", "iconUrl": "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/javascript/icon/en.novelupdates.png", "typeSource": "single", "itemType": 2, "version": "0.0.3", "dateFormat": "", "dateFormatLocale": "", "pkgPath": "novel/src/en/novelupdates.js", "appMinVerReq": "0.4.0", "isNsfw": false, "hasCloudflare": true }]; class DefaultExtension extends MProvider { headers = { Referer: this.source.baseUrl, Origin: this.source.baseUrl, Connection: "keep-alive", Accept: "*/*", "Accept-Language": "*", "Sec-Fetch-Mode": "cors", "Accept-Encoding": "gzip, deflate", "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) { throw new Error("getHeaders not implemented"); } mangaListFromPage(res) { const doc = new Document(res.body); const mangaElements = doc.select("div.search_main_box_nu"); const list = []; for (const element of mangaElements) { const name = element.selectFirst(".search_title > a").text; const imageUrl = element.selectFirst("img").getSrc; const link = element.selectFirst(".search_title > a").getHref; list.push({ name, imageUrl, link }); } const hasNextPage = doc.selectFirst("div.digg_pagination > a.next_page").text == " →"; return { list: list, hasNextPage }; } toStatus(status) { if (status.includes("Ongoing")) return 0; else if (status.includes("Completed")) return 1; else if (status.includes("Hiatus")) return 2; else if (status.includes("Dropped")) return 3; else return 5; } async getPopular(page) { const res = await new Client().get( `${this.source.baseUrl}/series-ranking/?rank=popmonth&pg=${page}`, this.headers ); return this.mangaListFromPage(res); } async getLatestUpdates(page) { const res = await new Client().get( `${this.source.baseUrl}/series-finder/?sf=1&sh=&sort=sdate&order=desc&pg=${page}`, this.headers ); return this.mangaListFromPage(res); } async search(query, page, filters) { let url = `${this.source.baseUrl}/series-finder/?sf=1&sh=${query}&pg=${page}`; if (!filters || filters.length == 0) { const res = await new Client().get(url, this.headers); return this.mangaListFromPage(res); } if (filters[0].state.filter(f => f.state == true).length > 0) { const values = filters[0].state.filter(f => f.state == true).map(f => f.value).join(","); url += `&nt=${values}`; } if (filters[1].state.filter(f => f.state == true).length > 0) { const values = filters[1].state.filter(f => f.state == true).map(f => f.value).join(","); url += `&org=${values}`; } if (filters[2].state.filter(f => f.state == 1 || f.state == 2).length > 0) { const including = filters[2].state.filter(f => f.state == 1).map(f => f.value).join(","); const excluding = filters[2].state.filter(f => f.state == 2).map(f => f.value).join(","); if (including.length > 0) url += `&gi=${including}`; if (excluding.length > 0) url += `&ge=${excluding}`; } if (filters[3].state.filter(f => f.state == true).length > 0) { const values = filters[3].state.filter(f => f.state == true).map(f => f.value).join(","); url += `&ss=${values}`; } url += `&sort=${filters[4].values[filters[4].state].value}`; url += `&order=${filters[5].values[filters[5].state].value}`; const res = await new Client().get(url, this.headers); return this.mangaListFromPage(res); } async getDetail(url) { const client = new Client(); const res = await client.get(url, this.headers); const doc = new Document(res.body); const imageUrl = doc.selectFirst(".wpb_wrapper img")?.getSrc; const type = doc.selectFirst("#showtype")?.text.trim(); const description = doc.selectFirst("#editdescription")?.text.trim() + `\n\nType: ${type}`; const author = doc .select("#authtag") .map((el) => el.text.trim()) .join(", "); const artist = doc .select("#artiststag") .map((el) => el.text.trim()) .join(", "); const status = this.toStatus(doc.selectFirst("#editstatus")?.text.trim()); const genre = doc.select("#seriesgenre > a").map((el) => el.text.trim()); const novelId = doc.selectFirst("input#mypostid")?.attr("value"); const link = `https://www.novelupdates.com/wp-admin/admin-ajax.php`; const headers = { "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", ...this.headers, }; const chapters = []; const chapterRes = await client.post(link, headers, { action: "nd_getchapters", mygrr: "0", mypostid: novelId, }); const chapterDoc = new Document(chapterRes.body); const nameReplacements = { v: "Volume ", c: " Chapter ", part: "Part ", ss: "SS", }; const chapterElements = chapterDoc.select("li.sp_li_chp"); for (const el of chapterElements) { let chapterName = el.selectFirst("span").text; for (const name in nameReplacements) { chapterName = chapterName.replace(name, nameReplacements[name]); } chapterName = chapterName.replace(/\b\w/g, (l) => l.toUpperCase()).trim(); const chapterUrl = `https:${el.select("a")[1].getHref}`; const dateUpload = String(Date.now()); chapters.push({ name: chapterName, url: chapterUrl, dateUpload: dateUpload, scanlator: null, }); } chapters.reverse(); return { imageUrl, description, genre, author, artist, status, chapters, }; } async getHtmlContent(url) { const client = await new Client(); const res = await client.get(url, { Priority: "u=0, i", "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", }); return await this.cleanHtmlContent(res.body); } async cleanHtmlContent(html) { const client = await new Client(); const doc = new Document(html); const domain = html; if (domain.includes("anotivereads")) { const title = doc.selectFirst("#comic-nav-name")?.text.trim() || ""; const content = doc.selectFirst("#spliced-comic")?.innerHtml; return `

${title}



${content}`; } if (domain.includes("asuratls")) { const title = doc.selectFirst(".post-body > div > b")?.text.trim() || ""; const content = doc.selectFirst(".post-body")?.innerHtml?.replace(title, ""); return `

${title}



${content}`; } if (domain.includes("daoist")) { const title = doc.selectFirst(".chapter__title")?.text.trim() || ""; const content = doc.selectFirst(".chapter__content")?.innerHtml; return `

${title}



${content}`; } if (domain.includes("darkstartranslations")) { const title = doc.selectFirst("ol.breadcrumb > li")?.text.trim() || ""; const content = doc.selectFirst(".text-left")?.innerHtml?.replace("
", "

"); return `

${title}



${content}`; } if (domain.includes("fictionread")) { const title = doc.selectFirst(".title-image > span")?.text.trim() || ""; const content = doc.selectFirst(".content")?.innerHtml; return `

${title}



${content}`; } if (domain.includes("helscans")) { const title = doc.selectFirst(".entry-title-main")?.text.trim() || ""; const content = doc.selectFirst("#readerarea.rdminimal")?.innerHtml; return `

${title}



${content}`; } if (domain.includes("hiraethtranslation")) { const title = doc.selectFirst("li.active")?.text.trim() || ""; const content = doc.selectFirst(".text-left")?.innerHtml; return `

${title}



${content}`; } if (domain.includes("hostednovel")) { const title = doc.selectFirst("#chapter-title")?.text.trim() || ""; const content = doc.selectFirst("#chapter-content")?.innerHtml; return `

${title}



${content}`; } if (domain.includes("inoveltranslation")) { const content = doc.selectFirst(".styles_content__JHK8G")?.innerHtml; return `${content}`; } if (domain.includes("isotls")) { const title = doc.selectFirst("head > title")?.text.trim() || ""; const content = doc.selectFirst("main > article")?.innerHtml; return `

${title}



${content}`; } if (domain.includes("mirilu")) { const title = doc.selectFirst(".entry-content > p > strong")?.text.trim() || ""; const content = doc.selectFirst(".entry-content")?.innerHtml; return `

${title}



${content}`; } if (domain.includes("novelplex")) { const title = doc.selectFirst(".halChap--jud")?.text.trim() || ""; const content = doc.selectFirst(".halChap--kontenInner")?.innerHtml; return `

${title}



${content}`; } if (domain.includes("novelworldtranslations")) { const title = doc.selectFirst(".entry-title")?.text.trim() || ""; const content = doc.selectFirst(".entry-content")?.innerHtml?.replace(/ /g, '')?.replace(/\n/g, '
'); return `

${title}



${content}`; } if (domain.includes("readingpia")) { const content = doc.selectFirst(".chapter-body")?.innerHtml; return `${content}`; } if (domain.includes("sacredtexttranslations")) { const title = doc.selectFirst(".entry-title")?.text.trim() || ""; const content = doc.selectFirst(".entry-content")?.innerHtml; return `

${title}



${content}`; } if (domain.includes("scribblehub")) { const title = doc.selectFirst(".chapter-title")?.text.trim() || ""; const content = doc.selectFirst(".chp_raw")?.innerHtml; return `

${title}



${content}`; } if (domain.includes("tinytranslation")) { const title = doc.selectFirst(".title-content")?.text.trim() || ""; const content = doc.selectFirst(".content")?.innerHtml; return `

${title}



${content}`; } if (domain.includes("tumblr")) { const content = doc.selectFirst(".post")?.innerHtml; return `${content}`; } if (domain.includes("wattpad")) { const title = doc.selectFirst(".h2")?.text.trim() || ""; const content = doc.selectFirst(".part-content > pre")?.innerHtml; return `

${title}



${content}`; } if (domain.includes("webnovel")) { const title = doc.selectFirst(".cha-tit > .pr > .dib")?.text.trim() || ""; const content = doc.selectFirst(".cha-words")?.innerHtml || doc.selectFirst("._content")?.innerHtml; return `

${title}



${content}`; } if (domain.includes("wetriedtls")) { const content = doc.selectFirst("script:contains(\"p dir=\")")?.innerHtml || doc.selectFirst("script:contains(\"u003c\")")?.innerHtml; if (content) { const jsonString_wetried = content.slice( content.indexOf('.push(') + '.push('.length, content.lastIndexOf(')'), ); return `${JSON.parse(jsonString_wetried)[1]}`; } return "

Failed to parse JSON content!

"; } if (domain.includes("wuxiaworld")) { const title = doc.selectFirst("h4 > span")?.text.trim() || ""; const content = doc.selectFirst(".chapter-content")?.innerHtml; return `

${title}



${content}`; } if (domain.includes("zetrotranslation")) { const title = doc.selectFirst(".text-left h2")?.text.trim() || doc.selectFirst(".active")?.text.trim() || ""; const content = doc.selectFirst(".text-left")?.innerHtml; return `

${title}



${content}`; } if (domain.includes("webnovel")) { const title = doc.selectFirst("#page > .chapter_content > .cha-tit > div > div")?.text.trim() || ""; const content = doc.selectFirst("#page > .chapter_content > .cha-content > .cha-words")?.innerHtml.replaceAll(/.*?<\/i>/gm, ""); return `

${title}



${content}`; } if (domain.includes("re-library")) { const redirectUrl = doc.selectFirst(".entry-content > div > div > p > a").getHref; const redirectRes = await client.get(redirectUrl, { Priority: "u=0, i", "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", }); const redirectDoc = new Document(redirectRes.body); const title = redirectDoc.selectFirst(".entry-header > .entry-title")?.text.trim() || ""; const content = redirectDoc.selectFirst(".entry-content")?.innerHtml.replaceAll(/.*?<\/i>/gm, ""); return `

${title}



${content}`; } const blogspotElements = [ doc.selectFirst("meta[name=\"google-adsense-platform-domain\"]").attr("content"), doc.selectFirst("meta[name=\"generator\"]").attr("content"), ]; const isBlogspot = blogspotElements.some(e => { return e?.toLowerCase().includes("blogspot") || e?.toLowerCase().includes("blogger") }); if (isBlogspot) { const title = doc.selectFirst("h3.post-title")?.text.trim() || doc.selectFirst("h3.entry-title")?.text.trim() || ""; const content = doc.selectFirst("div.post-body")?.innerHtml || doc.selectFirst("div.entry-content")?.innerHtml || doc.selectFirst("div.content-post")?.innerHtml; return `

${title}



${content}`; } const wordpressElements = [ doc.selectFirst("#dcl_comments-js-extra")?.innerHtml, doc.selectFirst("meta[name=\"generator\"]")?.attr("content"), doc.selectFirst(".powered-by")?.text, doc.selectFirst("footer")?.text, ]; let isWordpress = wordpressElements.some(e => { return e?.toLowerCase().includes("wordpress") || e?.toLowerCase().includes("site kit by google") }); let title = doc.selectFirst(".entry-title")?.text.trim() || doc.selectFirst(".entry-title-main")?.text.trim() || doc.selectFirst(".chapter__title")?.text.trim() || doc.selectFirst(".sp-title")?.text.trim() || doc.selectFirst(".title-content")?.text.trim() || doc.selectFirst(".wp-block-post-title")?.text.trim() || doc.selectFirst(".title_story")?.text.trim() || doc.selectFirst(".active")?.text.trim() || doc.selectFirst("head title")?.text.trim() || doc.selectFirst("h1.leading-none ~ h2")?.text.trim() || ""; const subtitle = doc.selectFirst(".cat-series")?.text.trim() || doc.selectFirst("h1.leading-none ~ span")?.text.trim() || ""; if (subtitle && subtitle != "") { title = subtitle; } const content = doc.selectFirst(".rdminimal")?.innerHtml || doc.selectFirst(".entry-content")?.innerHtml || doc.selectFirst(".chapter__content")?.innerHtml || doc.selectFirst(".prevent-select")?.innerHtml || doc.selectFirst(".text_story")?.innerHtml || doc.selectFirst(".contenta")?.innerHtml || doc.selectFirst(".single_post")?.innerHtml || doc.selectFirst(".post-entry")?.innerHtml || doc.selectFirst(".main-content")?.innerHtml || doc.selectFirst(".post-content")?.innerHtml || doc.selectFirst(".content")?.innerHtml || doc.selectFirst(".page-body")?.innerHtml || doc.selectFirst(".td-page-content")?.innerHtml || doc.selectFirst(".reader-content")?.innerHtml || doc.selectFirst("#content")?.innerHtml || doc.selectFirst("#the-content")?.innerHtml || doc.selectFirst("article.post")?.innerHtml; if (isWordpress || domain.includes("etherreads") || domain.includes("soafp")) { return `

${title}



${content}`; } return `

Domain not supported yet. Content might not load properly!


${title}



${content}`; } getFilterList() { return [ { type_name: "GroupFilter", name: "Novel Type", state: [ { type_name: "CheckBox", name: "Web Novel", value: "2444", }, { type_name: "CheckBox", name: "Light Novel", value: "2443", }, { type_name: "CheckBox", name: "Published Novel", value: "26874", }, ], }, { type_name: "GroupFilter", name: "Original Language", state: [ { type_name: "CheckBox", name: "Chinese", value: "495", }, { type_name: "CheckBox", name: "Filipino", value: "9181", }, { type_name: "CheckBox", name: "Indonesian", value: "9179", }, { type_name: "CheckBox", name: "Japanese", value: "496", }, { type_name: "CheckBox", name: "Khmer", value: "18657", }, { type_name: "CheckBox", name: "Korean", value: "497", }, { type_name: "CheckBox", name: "Malaysian", value: "9183", }, { type_name: "CheckBox", name: "Thai", value: "9954", }, { type_name: "CheckBox", name: "Vietnamese", value: "9177", }, ], }, { type_name: "GroupFilter", name: "Genre", state: [ { type_name: "TriState", name: "Action", value: "8", }, { type_name: "TriState", name: "Adventure", value: "13", }, { type_name: "TriState", name: "Comedy", value: "17", }, { type_name: "TriState", name: "Drama", value: "9", }, { type_name: "TriState", name: "Ecchi", value: "292", }, { type_name: "TriState", name: "Fantasy", value: "5", }, { type_name: "TriState", name: "Gender Bender", value: "168", }, { type_name: "TriState", name: "Harem", value: "3", }, { type_name: "TriState", name: "Horror", value: "343", }, { type_name: "TriState", name: "Josei", value: "324", }, { type_name: "TriState", name: "Martial Arts", value: "14", }, { type_name: "TriState", name: "Mature", value: "4", }, { type_name: "TriState", name: "Mecha", value: "10", }, { type_name: "TriState", name: "Mystery", value: "245", }, { type_name: "TriState", name: "Psychological", value: "486", }, { type_name: "TriState", name: "Romance", value: "15", }, { type_name: "TriState", name: "School", value: "6", }, { type_name: "TriState", name: "Sci-Fi", value: "11", }, { type_name: "TriState", name: "Seinen", value: "18", }, { type_name: "TriState", name: "Shoujo", value: "157", }, { type_name: "TriState", name: "Shoujo Ai", value: "851", }, { type_name: "TriState", name: "Shounen", value: "12", }, { type_name: "TriState", name: "Shounen Ai", value: "1692", }, { type_name: "TriState", name: "Slice of Life", value: "7", }, { type_name: "TriState", name: "Smut", value: "281", }, { type_name: "TriState", name: "Sports", value: "1357", }, { type_name: "TriState", name: "Supernatural", value: "16", }, { type_name: "TriState", name: "Tragedy", value: "132", }, { type_name: "TriState", name: "Wuxia", value: "479", }, { type_name: "TriState", name: "Xianxia", value: "480", }, { type_name: "TriState", name: "Xuanhuan", value: "3954", }, { type_name: "TriState", name: "Yaoi", value: "560", }, { type_name: "TriState", name: "Yuri", value: "922", }, ], }, { type_name: "GroupFilter", name: "Status", state: [ { type_name: "CheckBox", name: "All", value: "", }, { type_name: "CheckBox", name: "Completed", value: "2", }, { type_name: "CheckBox", name: "Ongoing", value: "3", }, { type_name: "CheckBox", name: "Hiatus", value: "4", }, ], }, { type_name: "SelectFilter", type: "sort", name: "Sort", state: 0, values: [ { type_name: "SelectOption", name: "Last Updated", value: "sdate", }, { type_name: "SelectOption", name: "Rating", value: "srate", }, { type_name: "SelectOption", name: "Rank", value: "srank", }, { type_name: "SelectOption", name: "Reviews", value: "sreview", }, { type_name: "SelectOption", name: "Chapters", value: "srel", }, { type_name: "SelectOption", name: "Title", value: "abc", }, { type_name: "SelectOption", name: "Readers", value: "sread", }, { type_name: "SelectOption", name: "Frequency", value: "sfrel", }, ], }, { type_name: "SelectFilter", name: "Order", state: 0, values: [ { type_name: "SelectOption", name: "Descending", value: "desc", }, { type_name: "SelectOption", name: "Ascending", value: "asc", }, ], } ]; } getSourcePreferences() { throw new Error("getSourcePreferences not implemented"); } }