diff --git a/dist/LNReader/plugins.json b/.dist/LNReader/plugins.json
similarity index 100%
rename from dist/LNReader/plugins.json
rename to .dist/LNReader/plugins.json
diff --git a/dist/LNReader/plugins.min.json b/.dist/LNReader/plugins.min.json
similarity index 100%
rename from dist/LNReader/plugins.min.json
rename to .dist/LNReader/plugins.min.json
diff --git a/.dist/k1ngfish3r/plugins.json b/.dist/k1ngfish3r/plugins.json
new file mode 100644
index 0000000..a5889a9
--- /dev/null
+++ b/.dist/k1ngfish3r/plugins.json
@@ -0,0 +1,486 @@
+{
+ "العربية": [
+ {
+ "id": "ar-mtl",
+ "name": "ArMTL[madara]",
+ "site": "https://ar-mtl.club/",
+ "lang": "العربية",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/arabic/ArMTL[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/armtl.png"
+ },
+ {
+ "id": "arnovel",
+ "name": "ArNovel[madara]",
+ "site": "https://arnovel.me/",
+ "lang": "العربية",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/arabic/ArNovel[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/arnovel.png"
+ },
+ {
+ "id": "hizomanga",
+ "name": "HizoManga[madara]",
+ "site": "https://hizomanga.com/",
+ "lang": "العربية",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/arabic/HizoManga[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/hizomanga.png"
+ },
+ {
+ "id": "kolnovel",
+ "name": "KolNovel",
+ "site": "https://kolnovel.lol/",
+ "lang": "العربية",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/arabic/kolnovel.js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/wpmangastream/icons/kolnovel.png"
+ },
+ {
+ "id": "novel4up",
+ "name": "Novel4Up[madara]",
+ "site": "https://novel4up.com/",
+ "lang": "العربية",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/arabic/Novel4Up[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/novel4up.png"
+ },
+ {
+ "id": "riwyat",
+ "name": "Riwyat[madara]",
+ "site": "https://riwyat.com/",
+ "lang": "العربية",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/arabic/Riwyat[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/riwyat.png"
+ },
+ {
+ "id": "teamxnovel",
+ "name": "TeamXNovel[madara]",
+ "site": "https://teamxnovel.com/",
+ "lang": "العربية",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/arabic/TeamXNovel[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/teamxnovel.png"
+ }
+ ],
+ "中文, 汉语, 漢語": [
+ {
+ "id": "linovelib",
+ "name": "Linovelib",
+ "site": "https://w.linovelib.com",
+ "lang": "中文, 汉语, 漢語",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/chinese/linovelib.js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/src/cn/linovelib/icon.png"
+ }
+ ],
+ "English": [
+ {
+ "id": "1stkissnovel",
+ "name": "FirstKissNovel[madara]",
+ "site": "https://1stkissnovel.org/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/FirstKissNovel[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/firstkissnovel.png"
+ },
+ {
+ "id": "BLN.com",
+ "name": "BestLightNovel",
+ "site": "https://bestlightnovel.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/bestlightnovel.js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/src/en/bestlightnovel/icon.png"
+ },
+ {
+ "id": "boxnovel",
+ "name": "BoxNovel[madara]",
+ "site": "https://boxnovel.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/BoxNovel[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/boxnovel.png"
+ },
+ {
+ "id": "clicknovel",
+ "name": "ClickNovel[madara]",
+ "site": "https://clicknovel.net/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/ClickNovel[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/clicknovel.png"
+ },
+ {
+ "id": "cratenovel",
+ "name": "CrateNovel[madara]",
+ "site": "https://cratenovel.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/CrateNovel[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/cratenovel.png"
+ },
+ {
+ "id": "daonovel",
+ "name": "DaoNovel[madara]",
+ "site": "https://daonovel.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/DaoNovel[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/daonovel.png"
+ },
+ {
+ "id": "fanTLS",
+ "name": "Fans Translations[madara]",
+ "site": "https://fanstranslations.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/FansTranslations[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/fanstranslations.png"
+ },
+ {
+ "id": "freenovel.me",
+ "name": "FreeNovelMe[madara]",
+ "site": "https://freenovel.me/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/FreeNovelMe[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/freenovelme.png"
+ },
+ {
+ "id": "guavaread",
+ "name": "Guavaread[madara]",
+ "site": "https://guavaread.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/Guavaread[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/guavaread.png"
+ },
+ {
+ "id": "lnheaven",
+ "name": "LightNovelHeaven[madara]",
+ "site": "https://lightnovelheaven.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/LightNovelHeaven[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/lightnovelheaven.png"
+ },
+ {
+ "id": "lunarletters",
+ "name": "LunarLetters[madara]",
+ "site": "https://www.lunarletters.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/LunarLetters[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/lunarletters.png"
+ },
+ {
+ "id": "mostnovel",
+ "name": "MostNovel[madara]",
+ "site": "https://mostnovel.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/MostNovel[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/mostnovel.png"
+ },
+ {
+ "id": "mtl-novel",
+ "name": "MTL-Novel[madara]",
+ "site": "https://mtl-novel.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/MTLNovel[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/mtl-novel.png"
+ },
+ {
+ "id": "mtlnovel.club",
+ "name": "MTLNovel.Club[madara]",
+ "site": "https://mtlnovel.club/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/MTLNovelClub[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/mtlnovel.club.png"
+ },
+ {
+ "id": "mysticalmerries",
+ "name": "MysticalSeries[madara]",
+ "site": "https://mysticalmerries.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/MysticalSeries[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/mysticalseries.png"
+ },
+ {
+ "id": "neosekaiTLS",
+ "name": "NeoSekai Translations[madara]",
+ "site": "https://www.neosekaitranslations.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/NeoSekaiTranslations[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/neosekaitranslations.png"
+ },
+ {
+ "id": "noblemtl",
+ "name": "NobleMTL",
+ "site": "https://noblemtl.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/nobleMTL.js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/src/en/noblemtl/icon.png"
+ },
+ {
+ "id": "nocturneTLS",
+ "name": "Nocturne Translations[madara]",
+ "site": "https://nocturnetls.net/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/NocturneTranslations[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/nocturnetranslations.png"
+ },
+ {
+ "id": "noobchanTL",
+ "name": "Noobchan Translation[madara]",
+ "site": "https://noobchan.xyz/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/NoobchanTranslation[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/noobchantranslation.png"
+ },
+ {
+ "id": "novelmultiverse",
+ "name": "NovelMultiverse[madara]",
+ "site": "https://www.novelmultiverse.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/NovelMultiverse[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/novelmultiverse.png"
+ },
+ {
+ "id": "novelr18",
+ "name": "NovelR18[madara]",
+ "site": "https://novelr18.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/NovelR18[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/novelr18.png"
+ },
+ {
+ "id": "novelroom",
+ "name": "Novelroom.net[madara]",
+ "site": "https://novelroom.net/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/Novelroomnet[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/novelroom.net.png"
+ },
+ {
+ "id": "novelstic",
+ "name": "Novelstic[madara]",
+ "site": "https://novelstic.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/Novelstic[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/novelstic.png"
+ },
+ {
+ "id": "novelTL",
+ "name": "NovelTranslate[madara]",
+ "site": "https://noveltranslate.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/NovelTranslate[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/noveltranslate.png"
+ },
+ {
+ "id": "onlymtl",
+ "name": "OnlyMTL[madara]",
+ "site": "https://www.onlymtl.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/OnlyMTL[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/onlymtl.png"
+ },
+ {
+ "id": "pandamtl",
+ "name": "PandaMTL",
+ "site": "https://pandamtl.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/pandaMTL.js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/src/en/wordpress/icon.png"
+ },
+ {
+ "id": "readwebnovels",
+ "name": "ReadWebNovels[madara]",
+ "site": "https://readwebnovels.net/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/ReadWebNovels[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/readwebnovels.png"
+ },
+ {
+ "id": "sleeptTLS",
+ "name": "SleepyTranslations[madara]",
+ "site": "https://sleepytranslations.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/SleepyTranslations[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/sleepytranslations.png"
+ },
+ {
+ "id": "sonicmtl",
+ "name": "SonicMTL[madara]",
+ "site": "https://www.sonicmtl.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/SonicMTL[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/sonicmtl.png"
+ },
+ {
+ "id": "sugarbbscan",
+ "name": "Sugar Babies[madara]",
+ "site": "https://sugarbbscan.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/SugarBabies[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/sugarbabies.png"
+ },
+ {
+ "id": "sweetEscapeTL",
+ "name": "Sweet Escape Translations[madara]",
+ "site": "https://sweetescapetranslations.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/SweetEscapeTranslations[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/sweetescapetranslations.png"
+ },
+ {
+ "id": "webnovelover",
+ "name": "WebNovelLover[madara]",
+ "site": "https://www.webnovelover.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/WebNovelLover[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/webnovellover.png"
+ },
+ {
+ "id": "wuxiaworld.site",
+ "name": "WuxiaWorld.Site[madara]",
+ "site": "https://wuxiaworld.site/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/WuxiaWorldSite[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/wuxiaworld.site.png"
+ },
+ {
+ "id": "zetroTL",
+ "name": "Zetro Translation[madara]",
+ "site": "https://zetrotranslation.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/ZetroTranslation[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/zetrotranslation.png"
+ },
+ {
+ "id": "zinnovel",
+ "name": "ZinnNovel[madara]",
+ "site": "https://zinnovel.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/ZinnNovel[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/zinnnovel.png"
+ }
+ ],
+ "Bahasa Indonesia": [
+ {
+ "id": "meionovel",
+ "name": "MeioNovel[madara]",
+ "site": "https://meionovel.id/",
+ "lang": "Bahasa Indonesia",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/indonesian/MeioNovel[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/meionovel.png"
+ },
+ {
+ "id": "morenovel",
+ "name": "MoreNovel[madara]",
+ "site": "https://morenovel.net/",
+ "lang": "Bahasa Indonesia",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/indonesian/MoreNovel[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/morenovel.png"
+ },
+ {
+ "id": "wbnovel",
+ "name": "WBNovel[madara]",
+ "site": "https://wbnovel.com/",
+ "lang": "Bahasa Indonesia",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/indonesian/WBNovel[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/wbnovel.png"
+ }
+ ],
+ "Português": [
+ {
+ "id": "lightnovelbrasil",
+ "name": "Light Novel Brasil",
+ "site": "https://lightnovelbrasil.com/",
+ "lang": "Português",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/portuguese/lightnovelbrasil.js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/wpmangastream/icons/lightnovelbrasil.png"
+ }
+ ],
+ "español, castellano": [
+ {
+ "id": "tunovelaligera",
+ "name": "TuNovelaLigera",
+ "site": "https://tunovelaligera.com/",
+ "lang": "español, castellano",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/spanish/tunovelaligera.js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/src/es/tunovelaligera/icon.png"
+ }
+ ],
+ "Türkçe": [
+ {
+ "id": "lshnovel",
+ "name": "Liebe Schnee Hiver Novel",
+ "site": "https://lshnovel.com/",
+ "lang": "Türkçe",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/turkish/lshnovel.js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/wpmangastream/icons/lshnovel.png"
+ },
+ {
+ "id": "turkcelightnovels",
+ "name": "TurkceLightNovels[madara]",
+ "site": "https://turkcelightnovels.com/",
+ "lang": "Türkçe",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/turkish/TurkceLightNovels[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/turkcelightnovels.png"
+ },
+ {
+ "id": "webnoveloku",
+ "name": "WebNovelOku [madara]",
+ "site": "https://www.webnoveloku.com/",
+ "lang": "Türkçe",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/turkish/WebNovelOku[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/webnoveloku.png"
+ }
+ ],
+ "Tiếng Việt": [
+ {
+ "id": "ln.hako",
+ "name": "Hako",
+ "site": "https://ln.hako.vn",
+ "lang": "Tiếng Việt",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/vietnamese/LNHako.js",
+ "iconUrl": "https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/src/vi/hakolightnovel/icon.png"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.dist/k1ngfish3r/plugins.min.json b/.dist/k1ngfish3r/plugins.min.json
new file mode 100644
index 0000000..d8959db
--- /dev/null
+++ b/.dist/k1ngfish3r/plugins.min.json
@@ -0,0 +1 @@
+{"العربية":[{"id":"ar-mtl","name":"ArMTL[madara]","site":"https://ar-mtl.club/","lang":"العربية","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/arabic/ArMTL[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/armtl.png"},{"id":"arnovel","name":"ArNovel[madara]","site":"https://arnovel.me/","lang":"العربية","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/arabic/ArNovel[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/arnovel.png"},{"id":"hizomanga","name":"HizoManga[madara]","site":"https://hizomanga.com/","lang":"العربية","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/arabic/HizoManga[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/hizomanga.png"},{"id":"kolnovel","name":"KolNovel","site":"https://kolnovel.lol/","lang":"العربية","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/arabic/kolnovel.js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/wpmangastream/icons/kolnovel.png"},{"id":"novel4up","name":"Novel4Up[madara]","site":"https://novel4up.com/","lang":"العربية","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/arabic/Novel4Up[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/novel4up.png"},{"id":"riwyat","name":"Riwyat[madara]","site":"https://riwyat.com/","lang":"العربية","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/arabic/Riwyat[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/riwyat.png"},{"id":"teamxnovel","name":"TeamXNovel[madara]","site":"https://teamxnovel.com/","lang":"العربية","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/arabic/TeamXNovel[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/teamxnovel.png"}],"中文, 汉语, 漢語":[{"id":"linovelib","name":"Linovelib","site":"https://w.linovelib.com","lang":"中文, 汉语, 漢語","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/chinese/linovelib.js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/src/cn/linovelib/icon.png"}],"English":[{"id":"1stkissnovel","name":"FirstKissNovel[madara]","site":"https://1stkissnovel.org/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/FirstKissNovel[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/firstkissnovel.png"},{"id":"BLN.com","name":"BestLightNovel","site":"https://bestlightnovel.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/bestlightnovel.js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/src/en/bestlightnovel/icon.png"},{"id":"boxnovel","name":"BoxNovel[madara]","site":"https://boxnovel.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/BoxNovel[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/boxnovel.png"},{"id":"clicknovel","name":"ClickNovel[madara]","site":"https://clicknovel.net/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/ClickNovel[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/clicknovel.png"},{"id":"cratenovel","name":"CrateNovel[madara]","site":"https://cratenovel.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/CrateNovel[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/cratenovel.png"},{"id":"daonovel","name":"DaoNovel[madara]","site":"https://daonovel.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/DaoNovel[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/daonovel.png"},{"id":"fanTLS","name":"Fans Translations[madara]","site":"https://fanstranslations.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/FansTranslations[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/fanstranslations.png"},{"id":"freenovel.me","name":"FreeNovelMe[madara]","site":"https://freenovel.me/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/FreeNovelMe[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/freenovelme.png"},{"id":"guavaread","name":"Guavaread[madara]","site":"https://guavaread.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/Guavaread[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/guavaread.png"},{"id":"lnheaven","name":"LightNovelHeaven[madara]","site":"https://lightnovelheaven.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/LightNovelHeaven[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/lightnovelheaven.png"},{"id":"lunarletters","name":"LunarLetters[madara]","site":"https://www.lunarletters.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/LunarLetters[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/lunarletters.png"},{"id":"mostnovel","name":"MostNovel[madara]","site":"https://mostnovel.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/MostNovel[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/mostnovel.png"},{"id":"mtl-novel","name":"MTL-Novel[madara]","site":"https://mtl-novel.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/MTLNovel[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/mtl-novel.png"},{"id":"mtlnovel.club","name":"MTLNovel.Club[madara]","site":"https://mtlnovel.club/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/MTLNovelClub[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/mtlnovel.club.png"},{"id":"mysticalmerries","name":"MysticalSeries[madara]","site":"https://mysticalmerries.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/MysticalSeries[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/mysticalseries.png"},{"id":"neosekaiTLS","name":"NeoSekai Translations[madara]","site":"https://www.neosekaitranslations.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/NeoSekaiTranslations[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/neosekaitranslations.png"},{"id":"noblemtl","name":"NobleMTL","site":"https://noblemtl.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/nobleMTL.js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/src/en/noblemtl/icon.png"},{"id":"nocturneTLS","name":"Nocturne Translations[madara]","site":"https://nocturnetls.net/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/NocturneTranslations[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/nocturnetranslations.png"},{"id":"noobchanTL","name":"Noobchan Translation[madara]","site":"https://noobchan.xyz/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/NoobchanTranslation[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/noobchantranslation.png"},{"id":"novelmultiverse","name":"NovelMultiverse[madara]","site":"https://www.novelmultiverse.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/NovelMultiverse[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/novelmultiverse.png"},{"id":"novelr18","name":"NovelR18[madara]","site":"https://novelr18.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/NovelR18[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/novelr18.png"},{"id":"novelroom","name":"Novelroom.net[madara]","site":"https://novelroom.net/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/Novelroomnet[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/novelroom.net.png"},{"id":"novelstic","name":"Novelstic[madara]","site":"https://novelstic.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/Novelstic[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/novelstic.png"},{"id":"novelTL","name":"NovelTranslate[madara]","site":"https://noveltranslate.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/NovelTranslate[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/noveltranslate.png"},{"id":"onlymtl","name":"OnlyMTL[madara]","site":"https://www.onlymtl.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/OnlyMTL[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/onlymtl.png"},{"id":"pandamtl","name":"PandaMTL","site":"https://pandamtl.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/pandaMTL.js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/src/en/wordpress/icon.png"},{"id":"readwebnovels","name":"ReadWebNovels[madara]","site":"https://readwebnovels.net/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/ReadWebNovels[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/readwebnovels.png"},{"id":"sleeptTLS","name":"SleepyTranslations[madara]","site":"https://sleepytranslations.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/SleepyTranslations[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/sleepytranslations.png"},{"id":"sonicmtl","name":"SonicMTL[madara]","site":"https://www.sonicmtl.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/SonicMTL[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/sonicmtl.png"},{"id":"sugarbbscan","name":"Sugar Babies[madara]","site":"https://sugarbbscan.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/SugarBabies[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/sugarbabies.png"},{"id":"sweetEscapeTL","name":"Sweet Escape Translations[madara]","site":"https://sweetescapetranslations.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/SweetEscapeTranslations[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/sweetescapetranslations.png"},{"id":"webnovelover","name":"WebNovelLover[madara]","site":"https://www.webnovelover.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/WebNovelLover[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/webnovellover.png"},{"id":"wuxiaworld.site","name":"WuxiaWorld.Site[madara]","site":"https://wuxiaworld.site/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/WuxiaWorldSite[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/wuxiaworld.site.png"},{"id":"zetroTL","name":"Zetro Translation[madara]","site":"https://zetrotranslation.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/ZetroTranslation[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/zetrotranslation.png"},{"id":"zinnovel","name":"ZinnNovel[madara]","site":"https://zinnovel.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/english/ZinnNovel[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/zinnnovel.png"}],"Bahasa Indonesia":[{"id":"meionovel","name":"MeioNovel[madara]","site":"https://meionovel.id/","lang":"Bahasa Indonesia","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/indonesian/MeioNovel[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/meionovel.png"},{"id":"morenovel","name":"MoreNovel[madara]","site":"https://morenovel.net/","lang":"Bahasa Indonesia","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/indonesian/MoreNovel[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/morenovel.png"},{"id":"wbnovel","name":"WBNovel[madara]","site":"https://wbnovel.com/","lang":"Bahasa Indonesia","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/indonesian/WBNovel[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/wbnovel.png"}],"Português":[{"id":"lightnovelbrasil","name":"Light Novel Brasil","site":"https://lightnovelbrasil.com/","lang":"Português","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/portuguese/lightnovelbrasil.js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/wpmangastream/icons/lightnovelbrasil.png"}],"español, castellano":[{"id":"tunovelaligera","name":"TuNovelaLigera","site":"https://tunovelaligera.com/","lang":"español, castellano","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/spanish/tunovelaligera.js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/src/es/tunovelaligera/icon.png"}],"Türkçe":[{"id":"lshnovel","name":"Liebe Schnee Hiver Novel","site":"https://lshnovel.com/","lang":"Türkçe","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/turkish/lshnovel.js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/wpmangastream/icons/lshnovel.png"},{"id":"turkcelightnovels","name":"TurkceLightNovels[madara]","site":"https://turkcelightnovels.com/","lang":"Türkçe","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/turkish/TurkceLightNovels[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/turkcelightnovels.png"},{"id":"webnoveloku","name":"WebNovelOku [madara]","site":"https://www.webnoveloku.com/","lang":"Türkçe","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/turkish/WebNovelOku[madara].js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/multisrc/madara/icons/webnoveloku.png"}],"Tiếng Việt":[{"id":"ln.hako","name":"Hako","site":"https://ln.hako.vn","lang":"Tiếng Việt","version":"1.0.0","url":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/.js/plugins/vietnamese/LNHako.js","iconUrl":"https://raw.githubusercontent.com/k1ngfish3r/plugins/classes/icons/src/vi/hakolightnovel/icon.png"}]}
\ No newline at end of file
diff --git a/.dist/nyagami/plugins.json b/.dist/nyagami/plugins.json
new file mode 100644
index 0000000..16c821d
--- /dev/null
+++ b/.dist/nyagami/plugins.json
@@ -0,0 +1,464 @@
+{
+ "العربية": [
+ {
+ "id": "ar-mtl",
+ "name": "ArMTL[madara]",
+ "site": "https://ar-mtl.club/",
+ "lang": "العربية",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/arabic/ArMTL[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/armtl.png"
+ },
+ {
+ "id": "arnovel",
+ "name": "ArNovel[madara]",
+ "site": "https://arnovel.me/",
+ "lang": "العربية",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/arabic/ArNovel[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/arnovel.png"
+ },
+ {
+ "id": "hizomanga",
+ "name": "HizoManga[madara]",
+ "site": "https://hizomanga.com/",
+ "lang": "العربية",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/arabic/HizoManga[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/hizomanga.png"
+ },
+ {
+ "id": "kolnovel",
+ "name": "KolNovel",
+ "site": "https://kolnovel.lol/",
+ "lang": "العربية",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/arabic/kolnovel.js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/wpmangastream/icons/kolnovel.png"
+ },
+ {
+ "id": "novel4up",
+ "name": "Novel4Up[madara]",
+ "site": "https://novel4up.com/",
+ "lang": "العربية",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/arabic/Novel4Up[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/novel4up.png"
+ },
+ {
+ "id": "riwyat",
+ "name": "Riwyat[madara]",
+ "site": "https://riwyat.com/",
+ "lang": "العربية",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/arabic/Riwyat[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/riwyat.png"
+ },
+ {
+ "id": "teamxnovel",
+ "name": "TeamXNovel[madara]",
+ "site": "https://teamxnovel.com/",
+ "lang": "العربية",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/arabic/TeamXNovel[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/teamxnovel.png"
+ }
+ ],
+ "English": [
+ {
+ "id": "1stkissnovel",
+ "name": "FirstKissNovel[madara]",
+ "site": "https://1stkissnovel.org/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/FirstKissNovel[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/firstkissnovel.png"
+ },
+ {
+ "id": "BLN.com",
+ "name": "BestLightNovel",
+ "site": "https://bestlightnovel.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/bestlightnovel.js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/src/en/bestlightnovel/icon.png"
+ },
+ {
+ "id": "boxnovel",
+ "name": "BoxNovel[madara]",
+ "site": "https://boxnovel.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/BoxNovel[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/boxnovel.png"
+ },
+ {
+ "id": "clicknovel",
+ "name": "ClickNovel[madara]",
+ "site": "https://clicknovel.net/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/ClickNovel[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/clicknovel.png"
+ },
+ {
+ "id": "cratenovel",
+ "name": "CrateNovel[madara]",
+ "site": "https://cratenovel.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/CrateNovel[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/cratenovel.png"
+ },
+ {
+ "id": "daonovel",
+ "name": "DaoNovel[madara]",
+ "site": "https://daonovel.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/DaoNovel[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/daonovel.png"
+ },
+ {
+ "id": "fanTLS",
+ "name": "Fans Translations[madara]",
+ "site": "https://fanstranslations.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/FansTranslations[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/fanstranslations.png"
+ },
+ {
+ "id": "freenovel.me",
+ "name": "FreeNovelMe[madara]",
+ "site": "https://freenovel.me/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/FreeNovelMe[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/freenovelme.png"
+ },
+ {
+ "id": "guavaread",
+ "name": "Guavaread[madara]",
+ "site": "https://guavaread.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/Guavaread[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/guavaread.png"
+ },
+ {
+ "id": "lnheaven",
+ "name": "LightNovelHeaven[madara]",
+ "site": "https://lightnovelheaven.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/LightNovelHeaven[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/lightnovelheaven.png"
+ },
+ {
+ "id": "lunarletters",
+ "name": "LunarLetters[madara]",
+ "site": "https://www.lunarletters.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/LunarLetters[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/lunarletters.png"
+ },
+ {
+ "id": "mostnovel",
+ "name": "MostNovel[madara]",
+ "site": "https://mostnovel.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/MostNovel[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/mostnovel.png"
+ },
+ {
+ "id": "mtl-novel",
+ "name": "MTL-Novel[madara]",
+ "site": "https://mtl-novel.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/MTLNovel[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/mtl-novel.png"
+ },
+ {
+ "id": "mtlnovel.club",
+ "name": "MTLNovel.Club[madara]",
+ "site": "https://mtlnovel.club/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/MTLNovelClub[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/mtlnovel.club.png"
+ },
+ {
+ "id": "mysticalmerries",
+ "name": "MysticalSeries[madara]",
+ "site": "https://mysticalmerries.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/MysticalSeries[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/mysticalseries.png"
+ },
+ {
+ "id": "neosekaiTLS",
+ "name": "NeoSekai Translations[madara]",
+ "site": "https://www.neosekaitranslations.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/NeoSekaiTranslations[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/neosekaitranslations.png"
+ },
+ {
+ "id": "noblemtl",
+ "name": "NobleMTL",
+ "site": "https://noblemtl.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/nobleMTL.js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/src/en/noblemtl/icon.png"
+ },
+ {
+ "id": "nocturneTLS",
+ "name": "Nocturne Translations[madara]",
+ "site": "https://nocturnetls.net/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/NocturneTranslations[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/nocturnetranslations.png"
+ },
+ {
+ "id": "noobchanTL",
+ "name": "Noobchan Translation[madara]",
+ "site": "https://noobchan.xyz/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/NoobchanTranslation[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/noobchantranslation.png"
+ },
+ {
+ "id": "novelmultiverse",
+ "name": "NovelMultiverse[madara]",
+ "site": "https://www.novelmultiverse.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/NovelMultiverse[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/novelmultiverse.png"
+ },
+ {
+ "id": "novelr18",
+ "name": "NovelR18[madara]",
+ "site": "https://novelr18.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/NovelR18[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/novelr18.png"
+ },
+ {
+ "id": "novelroom",
+ "name": "Novelroom.net[madara]",
+ "site": "https://novelroom.net/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/Novelroomnet[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/novelroom.net.png"
+ },
+ {
+ "id": "novelstic",
+ "name": "Novelstic[madara]",
+ "site": "https://novelstic.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/Novelstic[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/novelstic.png"
+ },
+ {
+ "id": "novelTL",
+ "name": "NovelTranslate[madara]",
+ "site": "https://noveltranslate.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/NovelTranslate[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/noveltranslate.png"
+ },
+ {
+ "id": "onlymtl",
+ "name": "OnlyMTL[madara]",
+ "site": "https://www.onlymtl.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/OnlyMTL[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/onlymtl.png"
+ },
+ {
+ "id": "pandamtl",
+ "name": "PandaMTL",
+ "site": "https://pandamtl.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/pandaMTL.js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/src/en/wordpress/icon.png"
+ },
+ {
+ "id": "readwebnovels",
+ "name": "ReadWebNovels[madara]",
+ "site": "https://readwebnovels.net/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/ReadWebNovels[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/readwebnovels.png"
+ },
+ {
+ "id": "sleeptTLS",
+ "name": "SleepyTranslations[madara]",
+ "site": "https://sleepytranslations.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/SleepyTranslations[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/sleepytranslations.png"
+ },
+ {
+ "id": "sonicmtl",
+ "name": "SonicMTL[madara]",
+ "site": "https://www.sonicmtl.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/SonicMTL[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/sonicmtl.png"
+ },
+ {
+ "id": "sugarbbscan",
+ "name": "Sugar Babies[madara]",
+ "site": "https://sugarbbscan.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/SugarBabies[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/sugarbabies.png"
+ },
+ {
+ "id": "sweetEscapeTL",
+ "name": "Sweet Escape Translations[madara]",
+ "site": "https://sweetescapetranslations.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/SweetEscapeTranslations[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/sweetescapetranslations.png"
+ },
+ {
+ "id": "webnovelover",
+ "name": "WebNovelLover[madara]",
+ "site": "https://www.webnovelover.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/WebNovelLover[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/webnovellover.png"
+ },
+ {
+ "id": "wuxiaworld.site",
+ "name": "WuxiaWorld.Site[madara]",
+ "site": "https://wuxiaworld.site/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/WuxiaWorldSite[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/wuxiaworld.site.png"
+ },
+ {
+ "id": "zetroTL",
+ "name": "Zetro Translation[madara]",
+ "site": "https://zetrotranslation.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/ZetroTranslation[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/zetrotranslation.png"
+ },
+ {
+ "id": "zinnovel",
+ "name": "ZinnNovel[madara]",
+ "site": "https://zinnovel.com/",
+ "lang": "English",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/ZinnNovel[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/zinnnovel.png"
+ }
+ ],
+ "Bahasa Indonesia": [
+ {
+ "id": "meionovel",
+ "name": "MeioNovel[madara]",
+ "site": "https://meionovel.id/",
+ "lang": "Bahasa Indonesia",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/indonesian/MeioNovel[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/meionovel.png"
+ },
+ {
+ "id": "morenovel",
+ "name": "MoreNovel[madara]",
+ "site": "https://morenovel.net/",
+ "lang": "Bahasa Indonesia",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/indonesian/MoreNovel[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/morenovel.png"
+ },
+ {
+ "id": "wbnovel",
+ "name": "WBNovel[madara]",
+ "site": "https://wbnovel.com/",
+ "lang": "Bahasa Indonesia",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/indonesian/WBNovel[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/wbnovel.png"
+ }
+ ],
+ "Português": [
+ {
+ "id": "lightnovelbrasil",
+ "name": "Light Novel Brasil",
+ "site": "https://lightnovelbrasil.com/",
+ "lang": "Português",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/portuguese/lightnovelbrasil.js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/wpmangastream/icons/lightnovelbrasil.png"
+ }
+ ],
+ "Türkçe": [
+ {
+ "id": "lshnovel",
+ "name": "Liebe Schnee Hiver Novel",
+ "site": "https://lshnovel.com/",
+ "lang": "Türkçe",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/turkish/lshnovel.js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/wpmangastream/icons/lshnovel.png"
+ },
+ {
+ "id": "turkcelightnovels",
+ "name": "TurkceLightNovels[madara]",
+ "site": "https://turkcelightnovels.com/",
+ "lang": "Türkçe",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/turkish/TurkceLightNovels[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/turkcelightnovels.png"
+ },
+ {
+ "id": "webnoveloku",
+ "name": "WebNovelOku [madara]",
+ "site": "https://www.webnoveloku.com/",
+ "lang": "Türkçe",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/turkish/WebNovelOku[madara].js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/webnoveloku.png"
+ }
+ ],
+ "Tiếng Việt": [
+ {
+ "id": "ln.hako",
+ "name": "Hako",
+ "site": "https://ln.hako.vn",
+ "lang": "Tiếng Việt",
+ "version": "1.0.0",
+ "url": "https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/vietnamese/LNHako.js",
+ "iconUrl": "https://raw.githubusercontent.com/nyagami/plugins/classes/icons/src/vi/hakolightnovel/icon.png"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.dist/nyagami/plugins.min.json b/.dist/nyagami/plugins.min.json
new file mode 100644
index 0000000..526e5f3
--- /dev/null
+++ b/.dist/nyagami/plugins.min.json
@@ -0,0 +1 @@
+{"العربية":[{"id":"ar-mtl","name":"ArMTL[madara]","site":"https://ar-mtl.club/","lang":"العربية","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/arabic/ArMTL[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/armtl.png"},{"id":"arnovel","name":"ArNovel[madara]","site":"https://arnovel.me/","lang":"العربية","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/arabic/ArNovel[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/arnovel.png"},{"id":"hizomanga","name":"HizoManga[madara]","site":"https://hizomanga.com/","lang":"العربية","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/arabic/HizoManga[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/hizomanga.png"},{"id":"kolnovel","name":"KolNovel","site":"https://kolnovel.lol/","lang":"العربية","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/arabic/kolnovel.js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/wpmangastream/icons/kolnovel.png"},{"id":"novel4up","name":"Novel4Up[madara]","site":"https://novel4up.com/","lang":"العربية","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/arabic/Novel4Up[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/novel4up.png"},{"id":"riwyat","name":"Riwyat[madara]","site":"https://riwyat.com/","lang":"العربية","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/arabic/Riwyat[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/riwyat.png"},{"id":"teamxnovel","name":"TeamXNovel[madara]","site":"https://teamxnovel.com/","lang":"العربية","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/arabic/TeamXNovel[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/teamxnovel.png"}],"English":[{"id":"1stkissnovel","name":"FirstKissNovel[madara]","site":"https://1stkissnovel.org/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/FirstKissNovel[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/firstkissnovel.png"},{"id":"BLN.com","name":"BestLightNovel","site":"https://bestlightnovel.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/bestlightnovel.js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/src/en/bestlightnovel/icon.png"},{"id":"boxnovel","name":"BoxNovel[madara]","site":"https://boxnovel.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/BoxNovel[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/boxnovel.png"},{"id":"clicknovel","name":"ClickNovel[madara]","site":"https://clicknovel.net/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/ClickNovel[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/clicknovel.png"},{"id":"cratenovel","name":"CrateNovel[madara]","site":"https://cratenovel.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/CrateNovel[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/cratenovel.png"},{"id":"daonovel","name":"DaoNovel[madara]","site":"https://daonovel.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/DaoNovel[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/daonovel.png"},{"id":"fanTLS","name":"Fans Translations[madara]","site":"https://fanstranslations.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/FansTranslations[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/fanstranslations.png"},{"id":"freenovel.me","name":"FreeNovelMe[madara]","site":"https://freenovel.me/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/FreeNovelMe[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/freenovelme.png"},{"id":"guavaread","name":"Guavaread[madara]","site":"https://guavaread.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/Guavaread[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/guavaread.png"},{"id":"lnheaven","name":"LightNovelHeaven[madara]","site":"https://lightnovelheaven.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/LightNovelHeaven[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/lightnovelheaven.png"},{"id":"lunarletters","name":"LunarLetters[madara]","site":"https://www.lunarletters.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/LunarLetters[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/lunarletters.png"},{"id":"mostnovel","name":"MostNovel[madara]","site":"https://mostnovel.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/MostNovel[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/mostnovel.png"},{"id":"mtl-novel","name":"MTL-Novel[madara]","site":"https://mtl-novel.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/MTLNovel[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/mtl-novel.png"},{"id":"mtlnovel.club","name":"MTLNovel.Club[madara]","site":"https://mtlnovel.club/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/MTLNovelClub[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/mtlnovel.club.png"},{"id":"mysticalmerries","name":"MysticalSeries[madara]","site":"https://mysticalmerries.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/MysticalSeries[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/mysticalseries.png"},{"id":"neosekaiTLS","name":"NeoSekai Translations[madara]","site":"https://www.neosekaitranslations.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/NeoSekaiTranslations[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/neosekaitranslations.png"},{"id":"noblemtl","name":"NobleMTL","site":"https://noblemtl.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/nobleMTL.js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/src/en/noblemtl/icon.png"},{"id":"nocturneTLS","name":"Nocturne Translations[madara]","site":"https://nocturnetls.net/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/NocturneTranslations[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/nocturnetranslations.png"},{"id":"noobchanTL","name":"Noobchan Translation[madara]","site":"https://noobchan.xyz/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/NoobchanTranslation[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/noobchantranslation.png"},{"id":"novelmultiverse","name":"NovelMultiverse[madara]","site":"https://www.novelmultiverse.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/NovelMultiverse[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/novelmultiverse.png"},{"id":"novelr18","name":"NovelR18[madara]","site":"https://novelr18.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/NovelR18[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/novelr18.png"},{"id":"novelroom","name":"Novelroom.net[madara]","site":"https://novelroom.net/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/Novelroomnet[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/novelroom.net.png"},{"id":"novelstic","name":"Novelstic[madara]","site":"https://novelstic.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/Novelstic[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/novelstic.png"},{"id":"novelTL","name":"NovelTranslate[madara]","site":"https://noveltranslate.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/NovelTranslate[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/noveltranslate.png"},{"id":"onlymtl","name":"OnlyMTL[madara]","site":"https://www.onlymtl.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/OnlyMTL[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/onlymtl.png"},{"id":"pandamtl","name":"PandaMTL","site":"https://pandamtl.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/pandaMTL.js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/src/en/wordpress/icon.png"},{"id":"readwebnovels","name":"ReadWebNovels[madara]","site":"https://readwebnovels.net/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/ReadWebNovels[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/readwebnovels.png"},{"id":"sleeptTLS","name":"SleepyTranslations[madara]","site":"https://sleepytranslations.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/SleepyTranslations[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/sleepytranslations.png"},{"id":"sonicmtl","name":"SonicMTL[madara]","site":"https://www.sonicmtl.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/SonicMTL[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/sonicmtl.png"},{"id":"sugarbbscan","name":"Sugar Babies[madara]","site":"https://sugarbbscan.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/SugarBabies[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/sugarbabies.png"},{"id":"sweetEscapeTL","name":"Sweet Escape Translations[madara]","site":"https://sweetescapetranslations.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/SweetEscapeTranslations[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/sweetescapetranslations.png"},{"id":"webnovelover","name":"WebNovelLover[madara]","site":"https://www.webnovelover.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/WebNovelLover[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/webnovellover.png"},{"id":"wuxiaworld.site","name":"WuxiaWorld.Site[madara]","site":"https://wuxiaworld.site/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/WuxiaWorldSite[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/wuxiaworld.site.png"},{"id":"zetroTL","name":"Zetro Translation[madara]","site":"https://zetrotranslation.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/ZetroTranslation[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/zetrotranslation.png"},{"id":"zinnovel","name":"ZinnNovel[madara]","site":"https://zinnovel.com/","lang":"English","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/english/ZinnNovel[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/zinnnovel.png"}],"Bahasa Indonesia":[{"id":"meionovel","name":"MeioNovel[madara]","site":"https://meionovel.id/","lang":"Bahasa Indonesia","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/indonesian/MeioNovel[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/meionovel.png"},{"id":"morenovel","name":"MoreNovel[madara]","site":"https://morenovel.net/","lang":"Bahasa Indonesia","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/indonesian/MoreNovel[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/morenovel.png"},{"id":"wbnovel","name":"WBNovel[madara]","site":"https://wbnovel.com/","lang":"Bahasa Indonesia","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/indonesian/WBNovel[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/wbnovel.png"}],"Português":[{"id":"lightnovelbrasil","name":"Light Novel Brasil","site":"https://lightnovelbrasil.com/","lang":"Português","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/portuguese/lightnovelbrasil.js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/wpmangastream/icons/lightnovelbrasil.png"}],"Türkçe":[{"id":"lshnovel","name":"Liebe Schnee Hiver Novel","site":"https://lshnovel.com/","lang":"Türkçe","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/turkish/lshnovel.js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/wpmangastream/icons/lshnovel.png"},{"id":"turkcelightnovels","name":"TurkceLightNovels[madara]","site":"https://turkcelightnovels.com/","lang":"Türkçe","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/turkish/TurkceLightNovels[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/turkcelightnovels.png"},{"id":"webnoveloku","name":"WebNovelOku [madara]","site":"https://www.webnoveloku.com/","lang":"Türkçe","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/turkish/WebNovelOku[madara].js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/multisrc/madara/icons/webnoveloku.png"}],"Tiếng Việt":[{"id":"ln.hako","name":"Hako","site":"https://ln.hako.vn","lang":"Tiếng Việt","version":"1.0.0","url":"https://raw.githubusercontent.com/nyagami/plugins/classes/.js/plugins/vietnamese/LNHako.js","iconUrl":"https://raw.githubusercontent.com/nyagami/plugins/classes/icons/src/vi/hakolightnovel/icon.png"}]}
\ No newline at end of file
diff --git a/.github/workflows/updatejson.yml b/.github/workflows/updatejson.yml
index 8097fe7..9ff5b84 100644
--- a/.github/workflows/updatejson.yml
+++ b/.github/workflows/updatejson.yml
@@ -19,8 +19,8 @@ jobs:
- name: Clean up current dist
run: |
- rm -rf dist
- mkdir dist
+ rm -rf .dist
+ mkdir .dist
cat > config.json << EOF
{
"githubUsername": "LNReader",
@@ -32,7 +32,7 @@ jobs:
id: json
run: |
npm run json
- changes="$(git diff --staged dist)"
+ changes="$(git diff --staged .dist)"
if [ "$changes" ]
then
changes=1
diff --git a/.gitignore b/.gitignore
index 3365c9d..7c3b280 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,8 +1,8 @@
-node_modules/**/*
+node_modules
.vscode
.env
config.json
# ignore TS translation folder but keep plugins folder
-js/*
-!js/plugins
+.js/*
+!.js/plugins
diff --git a/.js/plugins/arabic/ArMTL[madara].js b/.js/plugins/arabic/ArMTL[madara].js
new file mode 100644
index 0000000..7c30562
--- /dev/null
+++ b/.js/plugins/arabic/ArMTL[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "ar-mtl", "sourceSite": "https://ar-mtl.club/", "sourceName": "ArMTL", "filters": [], "options": { "useNewChapterEndpoint": true, "lang": "Arabic" } });
+exports.default = plugin;
diff --git a/.js/plugins/arabic/ArNovel[madara].js b/.js/plugins/arabic/ArNovel[madara].js
new file mode 100644
index 0000000..9d4d9a5
--- /dev/null
+++ b/.js/plugins/arabic/ArNovel[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "arnovel", "sourceSite": "https://arnovel.me/", "sourceName": "ArNovel", "filters": [{ "key": "sort", "label": "الترتيب حسب", "values": [{ "label": "A-Z", "value": "alphabet" }, { "label": "الآخير", "value": "latest" }, { "label": "الأكثر مشاهدة", "value": "views" }, { "label": "التقييم", "value": "rating" }, { "label": "جديد", "value": "new-manga" }, { "label": "شائع", "value": "trending" }], "inputType": "Picker" }, { "key": "genres", "label": "التصنيفات", "values": [{ "label": "أكشن", "value": "%d8%a3%d9%83%d8%b4%d9%86" }, { "label": "إتشي", "value": "%d8%a5%d8%aa%d8%b4%d9%80%d9%8a" }, { "label": "بالغ", "value": "%d8%a8%d8%a7%d9%84%d8%ba" }, { "label": "تاريخي", "value": "%d8%aa%d8%a7%d8%b1%d9%8a%d8%ae%d9%8a" }, { "label": "تراجدي", "value": "%d8%aa%d8%b1%d8%a7%d8%ac%d8%af%d9%8a" }, { "label": "جوسي", "value": "%d8%ac%d9%88%d8%b3%d9%8a" }, { "label": "حريم", "value": "%d8%ad%d8%b1%d9%8a%d9%85" }, { "label": "حياة مدرسية", "value": "%d8%ad%d9%8a%d8%a7%d8%a9-%d9%85%d8%af%d8%b1%d8%b3%d9%8a%d8%a9" }, { "label": "خارق لطبيعية", "value": "%d8%ae%d8%a7%d8%b1%d9%82-%d9%84%d8%b7%d8%a8%d9%8a%d8%b9%d9%8a%d8%a9" }, { "label": "خيال", "value": "%d8%ae%d9%8a%d8%a7%d9%84" }, { "label": "خيال علمي", "value": "%d8%ae%d9%8a%d8%a7%d9%84-%d8%b9%d9%84%d9%85%d9%8a" }, { "label": "دراما", "value": "%d8%af%d8%b1%d8%a7%d9%85%d8%a7" }, { "label": "راشد", "value": "%d8%b1%d8%a7%d8%b4%d8%af" }, { "label": "رعب", "value": "%d8%b1%d8%b9%d8%a8" }, { "label": "رومنسي", "value": "%d8%b1%d9%88%d9%85%d9%86%d8%b3%d9%8a" }, { "label": "رياضي", "value": "%d8%b1%d9%8a%d8%a7%d8%b6%d9%8a" }, { "label": "سينين", "value": "%d8%b3%d9%8a%d9%86%d9%8a%d9%86" }, { "label": "شريحة من الحياة", "value": "%d8%b4%d8%b1%d9%8a%d8%ad%d8%a9-%d9%85%d9%86-%d8%a7%d9%84%d8%ad%d9%8a%d8%a7%d8%a9" }, { "label": "شوجو", "value": "%d8%b4%d9%88%d8%ac%d9%88" }, { "label": "شونين", "value": "%d8%b4%d9%88%d9%86%d9%8a%d9%86" }, { "label": "غموض", "value": "%d8%ba%d9%85%d9%88%d8%b6" }, { "label": "فنون قتال", "value": "%d9%81%d9%86%d9%88%d9%86-%d9%82%d8%aa%d8%a7%d9%84" }, { "label": "كوميديا", "value": "%d9%83%d9%88%d9%85%d9%8a%d8%af%d9%8a%d8%a7" }, { "label": "مغامرات", "value": "%d9%85%d8%ba%d8%a7%d9%85%d8%b1%d8%a7%d8%aa" }, { "label": "منتهية", "value": "%d9%85%d9%86%d8%aa%d9%87%d9%8a%d8%a9" }, { "label": "ميكا", "value": "%d9%85%d9%8a%d9%83%d8%a7" }, { "label": "نفسي", "value": "%d9%86%d9%81%d8%b3%d9%8a" }], "inputType": "Picker" }], "options": { "path": { "genres": "home/novel-genre" }, "useNewChapterEndpoint": true, "lang": "Arabic" } });
+exports.default = plugin;
diff --git a/.js/plugins/arabic/HizoManga[madara].js b/.js/plugins/arabic/HizoManga[madara].js
new file mode 100644
index 0000000..c70d234
--- /dev/null
+++ b/.js/plugins/arabic/HizoManga[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "hizomanga", "sourceSite": "https://hizomanga.com/", "sourceName": "HizoManga", "filters": [{ "key": "sort", "label": "ترتيب حسب", "values": [{ "label": "A-Z", "value": "alphabet" }, { "label": "New", "value": "new-manga" }, { "label": "الأحدث", "value": "latest" }, { "label": "الأكثر مشاهدة", "value": "views" }, { "label": "التقييم", "value": "rating" }, { "label": "الرائج", "value": "trending" }], "inputType": "Picker" }, { "key": "genres", "label": "التصنيفات", "values": [{ "label": "آلات", "value": "mechanisms" }, { "label": "أكشن", "value": "action" }, { "label": "إثارة", "value": "excitement" }, { "label": "إيسكاي", "value": "%d8%a5%d9%8a%d8%b3%d9%83%d8%a7%d9%8a" }, { "label": "الحياة اليومية", "value": "slice-of-life" }, { "label": "الحياة مدرسية", "value": "school-life" }, { "label": "تاريخي", "value": "historical" }, { "label": "تراجيدي", "value": "tragic" }, { "label": "جريمة", "value": "%d8%ac%d8%b1%d9%8a%d9%85%d8%a9" }, { "label": "جندر بندر", "value": "%d8%ac%d9%86%d8%af%d8%b1-%d8%a8%d9%86%d8%af%d8%b1" }, { "label": "جوسي", "value": "josei" }, { "label": "حريم", "value": "harem" }, { "label": "خارق للطبيعة", "value": "supernatural" }, { "label": "خيال", "value": "fantasy" }, { "label": "خيال علمي", "value": "sci-fi" }, { "label": "دراما", "value": "drama" }, { "label": "دموي", "value": "%d8%af%d9%85%d9%88%d9%8a" }, { "label": "راشد", "value": "mature" }, { "label": "رعب", "value": "horror" }, { "label": "رومانسي", "value": "romance" }, { "label": "رياضة", "value": "sports" }, { "label": "زمنكاني", "value": "my-time" }, { "label": "زومبي", "value": "%d8%b2%d9%88%d9%85%d8%a8%d9%8a" }, { "label": "سينين", "value": "seinen" }, { "label": "شريحة من الحياة", "value": "%d8%b4%d8%b1%d9%8a%d8%ad%d8%a9-%d9%85%d9%86-%d8%a7%d9%84%d8%ad%d9%8a%d8%a7%d8%a9" }, { "label": "شوجو", "value": "shoujo" }, { "label": "شونين", "value": "shounen" }, { "label": "طبي", "value": "%d8%b7%d8%a8%d9%8a" }, { "label": "غموض", "value": "ambiguity" }, { "label": "فنون قتالية", "value": "martial-arts" }, { "label": "قوة خارقة", "value": "superpower" }, { "label": "كوميدي", "value": "comedy" }, { "label": "مغامرات", "value": "adventure" }, { "label": "نفسي", "value": "psychological" }], "inputType": "Picker" }], "options": { "path": { "novels": "serie", "novel": "serie", "chapter": "serie", "genres": "manga-genre" }, "useNewChapterEndpoint": true, "lang": "Arabic" } });
+exports.default = plugin;
diff --git a/.js/plugins/arabic/Novel4Up[madara].js b/.js/plugins/arabic/Novel4Up[madara].js
new file mode 100644
index 0000000..6747ac8
--- /dev/null
+++ b/.js/plugins/arabic/Novel4Up[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "novel4up", "sourceSite": "https://novel4up.com/", "sourceName": "Novel4Up", "filters": [{ "key": "sort", "label": "ترتيب حسب:", "values": [{ "label": "أ-ي", "value": "alphabet" }, { "label": "الأحدث", "value": "latest" }, { "label": "الأكثر مشاهدة", "value": "views" }, { "label": "التقييم", "value": "rating" }, { "label": "الجديد", "value": "new-manga" }, { "label": "الشائع", "value": "trending" }], "inputType": "Picker" }, { "key": "genres", "label": "التصنيفات", "values": [{ "label": "أكشن", "value": "action" }, { "label": "الخارق للطبيعة", "value": "supernatural" }, { "label": "تاريخي", "value": "historical" }, { "label": "تحقيق", "value": "detective" }, { "label": "تراجيديا", "value": "tragedy" }, { "label": "حريم", "value": "harem" }, { "label": "حياة مدرسية", "value": "school-life" }, { "label": "خيال علمي", "value": "sci-fi" }, { "label": "دراما", "value": "drama" }, { "label": "رعب", "value": "horror" }, { "label": "رومانسي", "value": "romance" }, { "label": "رياضة", "value": "sports" }, { "label": "سحر", "value": "magic" }, { "label": "شريحة من الحياة", "value": "slice-of-life" }, { "label": "شوانهوا", "value": "xuanhuan" }, { "label": "شوجو", "value": "shoujo" }, { "label": "شونين", "value": "shounen" }, { "label": "غموض", "value": "mystery" }, { "label": "فانتازيا", "value": "fantasy" }, { "label": "فنون قتال", "value": "martial-arts" }, { "label": "كوميديا", "value": "comedy" }, { "label": "مغامرة", "value": "adventure" }, { "label": "ميكا", "value": "mecha" }, { "label": "نفسي", "value": "psychological" }, { "label": "ون شوت", "value": "one-shot" }, { "label": "ووشيا", "value": "wuxia" }], "inputType": "Picker" }], "options": { "lang": "Arabic" } });
+exports.default = plugin;
diff --git a/.js/plugins/arabic/Riwyat[madara].js b/.js/plugins/arabic/Riwyat[madara].js
new file mode 100644
index 0000000..d61243c
--- /dev/null
+++ b/.js/plugins/arabic/Riwyat[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "riwyat", "sourceSite": "https://riwyat.com/", "sourceName": "Riwyat", "filters": [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": "Picker" }, { "key": "genres", "label": "GENRES", "values": [{ "label": "أكشن", "value": "%d8%a3%d9%83%d8%b4%d9%86" }, { "label": "أيتشي", "value": "%d8%a3%d9%8a%d8%aa%d8%b4%d9%8a" }, { "label": "استراتجي", "value": "%d8%a7%d8%b3%d8%aa%d8%b1%d8%a7%d8%aa%d8%ac%d9%8a" }, { "label": "العصر الحديث", "value": "%d8%a7%d9%84%d8%b9%d8%b5%d8%b1-%d8%a7%d9%84%d8%ad%d8%af%d9%8a%d8%ab" }, { "label": "انتقام", "value": "%d8%a7%d9%86%d8%aa%d9%82%d8%a7%d9%85" }, { "label": "بالغ", "value": "%d8%a8%d8%a7%d9%84%d8%ba" }, { "label": "بناء مملكة", "value": "%d8%a8%d9%86%d8%a7%d8%a1-%d9%85%d9%85%d9%84%d9%83%d8%a9" }, { "label": "بوليسي", "value": "%d8%a8%d9%88%d9%84%d9%8a%d8%b3%d9%8a" }, { "label": "تاريخي", "value": "%d8%aa%d8%a7%d8%b1%d9%8a%d8%ae%d9%8a" }, { "label": "جوسي", "value": "%d8%ac%d9%88%d8%b3%d9%8a" }, { "label": "حريم", "value": "%d8%ad%d8%b1%d9%8a%d9%85" }, { "label": "حياة يومية", "value": "%d8%ad%d9%8a%d8%a7%d8%a9-%d9%8a%d9%88%d9%85%d9%8a%d8%a9" }, { "label": "خيال", "value": "%d8%ae%d9%8a%d8%a7%d9%84" }, { "label": "خيال علمي", "value": "%d8%ae%d9%8a%d8%a7%d9%84-%d8%b9%d9%84%d9%85%d9%8a" }, { "label": "دراما", "value": "%d8%af%d8%b1%d8%a7%d9%85%d8%a7" }, { "label": "رعب", "value": "%d8%b1%d8%b9%d8%a8" }, { "label": "رومانسية", "value": "%d8%b1%d9%88%d9%85%d8%a7%d9%86%d8%b3%d9%8a%d8%a9" }, { "label": "رياضي", "value": "%d8%b1%d9%8a%d8%a7%d8%b6%d9%8a" }, { "label": "زيانشيا", "value": "xianxia" }, { "label": "سنين", "value": "%d8%b3%d9%86%d9%8a%d9%86" }, { "label": "شريحة حياة", "value": "%d8%b4%d8%b1%d9%8a%d8%ad%d8%a9-%d8%ad%d9%8a%d8%a7%d8%a9" }, { "label": "شوانهوان", "value": "xuanhuan" }, { "label": "شوجو", "value": "%d8%b4%d9%88%d8%ac%d9%88" }, { "label": "شونين", "value": "%d8%b4%d9%88%d9%86%d9%8a%d9%86" }, { "label": "شيانشيا", "value": "%d8%b4%d9%8a%d8%a7%d9%86%d8%b4%d9%8a%d8%a7" }, { "label": "عسكري", "value": "%d8%b9%d8%b3%d9%83%d8%b1%d9%8a" }, { "label": "غموض", "value": "%d8%ba%d9%85%d9%88%d8%b6" }, { "label": "فانتازيا", "value": "%d9%81%d8%a7%d9%86%d8%aa%d8%a7%d8%b2%d9%8a%d8%a7" }, { "label": "فنون قتالية", "value": "%d9%81%d9%86%d9%88%d9%86-%d9%82%d8%aa%d8%a7%d9%84%d9%8a%d8%a9" }, { "label": "قوى خارقة", "value": "%d9%82%d9%88%d9%89-%d8%ae%d8%a7%d8%b1%d9%82%d8%a9" }, { "label": "كوميديا", "value": "%d9%83%d9%88%d9%85%d9%8a%d8%af%d9%8a%d8%a7" }, { "label": "كوميك", "value": "%d9%83%d9%88%d9%85%d9%8a%d9%83" }, { "label": "للكبار", "value": "%d9%84%d9%84%d9%83%d8%a8%d8%a7%d8%b1" }, { "label": "مأساة", "value": "%d9%85%d8%a3%d8%b3%d8%a7%d8%a9" }, { "label": "مانجا", "value": "%d9%85%d8%a7%d9%86%d8%ac%d8%a7" }, { "label": "مانها", "value": "%d9%85%d8%a7%d9%86%d9%87%d8%a7" }, { "label": "مانهوا", "value": "%d9%85%d8%a7%d9%86%d9%87%d9%88%d8%a7" }, { "label": "مدرسي", "value": "%d9%85%d8%af%d8%b1%d8%b3%d9%8a" }, { "label": "مصاصي دماء", "value": "%d9%85%d8%b5%d8%a7%d8%b5%d9%8a-%d8%af%d9%85%d8%a7%d8%a1" }, { "label": "مغامرة", "value": "%d9%85%d8%ba%d8%a7%d9%85%d8%b1%d8%a9" }, { "label": "مكتملة", "value": "%d9%85%d9%83%d8%aa%d9%85%d9%84%d8%a9" }, { "label": "نفسي", "value": "%d9%86%d9%81%d8%b3%d9%8a" }, { "label": "نهاية العالم", "value": "%d9%86%d9%87%d8%a7%d9%8a%d8%a9-%d8%a7%d9%84%d8%b9%d8%a7%d9%84%d9%85" }, { "label": "واب تون", "value": "%d9%88%d8%a7%d8%a8-%d8%aa%d9%88%d9%86" }, { "label": "وان شوت", "value": "%d9%88%d8%a7%d9%86-%d8%b4%d9%88%d8%aa" }], "inputType": "Picker" }], "options": { "useNewChapterEndpoint": true, "lang": "Arabic" } });
+exports.default = plugin;
diff --git a/.js/plugins/arabic/TeamXNovel[madara].js b/.js/plugins/arabic/TeamXNovel[madara].js
new file mode 100644
index 0000000..1ce5d3d
--- /dev/null
+++ b/.js/plugins/arabic/TeamXNovel[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "teamxnovel", "sourceSite": "https://teamxnovel.com/", "sourceName": "TeamXNovel", "filters": [], "options": { "useNewChapterEndpoint": true, "lang": "Arabic" } });
+exports.default = plugin;
diff --git a/.js/plugins/arabic/kolnovel.js b/.js/plugins/arabic/kolnovel.js
new file mode 100644
index 0000000..c57ae46
--- /dev/null
+++ b/.js/plugins/arabic/kolnovel.js
@@ -0,0 +1,333 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var cheerio_1 = require("cheerio");
+var fetch_1 = require("@libs/fetch");
+var filterInputs_1 = require("@libs/filterInputs");
+var KolNovel = /** @class */ (function () {
+ function KolNovel() {
+ this.id = "kolnovel";
+ this.name = "KolNovel";
+ this.icon = "multisrc/wpmangastream/icons/kolnovel.png";
+ this.site = "https://kolnovel.lol/";
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.filters = [
+ {
+ key: "order",
+ label: "ترتيب حسب",
+ values: [
+ { label: "الإعداد الأولي", value: "" },
+ { label: "A-Z", value: "title" },
+ { label: "Z-A", value: "titlereverse" },
+ { label: "أخر التحديثات", value: "update" },
+ { label: "أخر ما تم إضافته", value: "latest" },
+ { label: "الرائجة", value: "popular" },
+ ],
+ inputType: filterInputs_1.FilterInputs.Picker,
+ },
+ {
+ key: "status",
+ label: "الحالة",
+ values: [
+ { label: "All", value: "" },
+ { label: "Ongoing", value: "ongoing" },
+ { label: "Hiatus", value: "hiatus" },
+ { label: "Completed", value: "completed" },
+ ],
+ inputType: filterInputs_1.FilterInputs.Picker,
+ },
+ {
+ key: "type",
+ label: "النوع",
+ values: [
+ { label: "إنجليزية", value: "english" },
+ { label: "روايةلايت", value: "light-novel" },
+ { label: "روايةويب", value: "web-novel" },
+ { label: "صينية", value: "chinese" },
+ { label: "عربية", value: "arabic" },
+ { label: "كورية", value: "korean" },
+ { label: "يابانية", value: "japanese" },
+ ],
+ inputType: filterInputs_1.FilterInputs.Checkbox,
+ },
+ {
+ key: "genres",
+ label: "تصنيف",
+ values: [
+ { label: "Wuxia", value: "wuxia" },
+ { label: "Xianxia", value: "xianxia" },
+ { label: "XUANHUAN", value: "xuanhuan" },
+ { label: "أكشن", value: "action" },
+ { label: "إثارة", value: "excitement" },
+ { label: "إنتقالالىعالمأخر", value: "isekai" },
+ { label: "إيتشي", value: "etchi" },
+ { label: "الخيالالعلمي", value: "sci-fi" },
+ { label: "بوليسي", value: "policy" },
+ { label: "تاريخي", value: "historical" },
+ { label: "تحقيقات", value: "%d8%aa%d8%ad%d9%82%d9%8a%d9%82" },
+ { label: "تقمصشخصيات", value: "rpg" },
+ { label: "جريمة", value: "crime" },
+ { label: "جوسى", value: "josei" },
+ { label: "حريم", value: "harem" },
+ { label: "حياةمدرسية", value: "school-life" },
+ { label: "خيالي(فانتازيا)", value: "fantasy" },
+ { label: "دراما", value: "drama" },
+ { label: "رعب", value: "horror" },
+ { label: "رومانسي", value: "romantic" },
+ { label: "سحر", value: "magic" },
+ { label: "سينن", value: "senen" },
+ { label: "شريحةمنالحياة", value: "slice-of-life" },
+ { label: "شوجو", value: "shojo" },
+ { label: "شونين", value: "shonen" },
+ { label: "طبي", value: "medical" },
+ { label: "ظواهرخارقةللطبيعة", value: "supernatural" },
+ { label: "غموض", value: "mysteries" },
+ { label: "فنونالقتال", value: "martial-arts" },
+ { label: "قوىخارقة", value: "superpower" },
+ { label: "كوميدي", value: "comedy" },
+ { label: "مأساوي", value: "tragedy" },
+ { label: "مابعدالكارثة", value: "after-the-disaster" },
+ { label: "مغامرة", value: "adventure" },
+ { label: "ميكا", value: "mechanical" },
+ { label: "ناضج", value: "mature" },
+ { label: "نفسي", value: "psychological" },
+ ],
+ inputType: filterInputs_1.FilterInputs.Checkbox,
+ },
+ ];
+ }
+ KolNovel.prototype.popularNovels = function (pageNo, _a) {
+ var filters = _a.filters;
+ return __awaiter(this, void 0, void 0, function () {
+ var link, headers, body, loadedCheerio, novels;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ link = "".concat(this.site, "series/?page=").concat(pageNo);
+ if (filters) {
+ if (Array.isArray(filters.genres) && filters.genres.length) {
+ link += filters.genres.map(function (i) { return "&genre[]=".concat(i); }).join("");
+ }
+ if (Array.isArray(filters.type) && filters.type.length)
+ link += filters.type.map(function (i) { return "&lang[]=".concat(i); }).join("");
+ }
+ link += "&status=" + ((filters === null || filters === void 0 ? void 0 : filters.status) ? filters.status : "");
+ link += "&order=" + ((filters === null || filters === void 0 ? void 0 : filters.order) ? filters.order : "popular");
+ headers = new Headers();
+ if (this.cookieString) {
+ headers.append("cookie", this.cookieString);
+ }
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(link, { headers: headers }).then(function (result) {
+ return result.text();
+ })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ novels = [];
+ loadedCheerio("article.maindet").each(function () {
+ var novelName = loadedCheerio(this).find("h2").text();
+ var image = loadedCheerio(this).find("img");
+ var novelCover = image.attr("data-src") || image.attr("src");
+ var novelUrl = loadedCheerio(this).find("h2 a").attr("href");
+ if (!novelUrl)
+ return;
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ KolNovel.prototype.parseNovelAndChapters = function (novelUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var url, headers, result, body, loadedCheerio, novel, chapter;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ url = novelUrl;
+ headers = new Headers();
+ if (this.cookieString) {
+ headers.append("cookie", this.cookieString);
+ }
+ return [4 /*yield*/, fetch(url, { headers: headers })];
+ case 1:
+ result = _a.sent();
+ return [4 /*yield*/, result.text()];
+ case 2:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ novel = {
+ url: url,
+ chapters: [],
+ };
+ novel.name = loadedCheerio("h1.entry-title").text();
+ novel.cover =
+ loadedCheerio("img.wp-post-image").attr("data-src") ||
+ loadedCheerio("img.wp-post-image").attr("src");
+ loadedCheerio("div.serl:nth-child(3) > span").each(function () {
+ var detailName = loadedCheerio(this).text().trim();
+ var detail = loadedCheerio(this).next().text().trim();
+ switch (detailName) {
+ case "الكاتب":
+ case "Author":
+ novel.author = detail;
+ break;
+ }
+ });
+ novel.status = loadedCheerio("div.sertostat > span").attr("class");
+ novel.genres = loadedCheerio(".sertogenre")
+ .children("a")
+ .map(function (i, el) { return loadedCheerio(el).text(); })
+ .toArray()
+ .join(",");
+ novel.summary = loadedCheerio(".sersys")
+ .find("br")
+ .replaceWith("\n")
+ .end()
+ .text();
+ chapter = [];
+ loadedCheerio(".eplister")
+ .find("li")
+ .each(function () {
+ var chapterName = loadedCheerio(this).find(".epl-num").text() +
+ " - " +
+ loadedCheerio(this).find(".epl-title").text();
+ var releaseDate = loadedCheerio(this)
+ .find(".epl-date")
+ .text()
+ .trim();
+ var chapterUrl = loadedCheerio(this).find("a").attr("href");
+ if (!chapterUrl)
+ return;
+ chapter.push({
+ name: chapterName,
+ releaseTime: releaseDate,
+ url: chapterUrl,
+ });
+ });
+ novel.chapters = chapter.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ KolNovel.prototype.parseChapter = function (chapterUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var headers, result, body, loadedCheerio, ignore, chapterText;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ headers = new Headers();
+ if (this.cookieString) {
+ headers.append("cookie", this.cookieString);
+ }
+ return [4 /*yield*/, fetch(chapterUrl, { headers: headers })];
+ case 1:
+ result = _b.sent();
+ return [4 /*yield*/, result.text()];
+ case 2:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.epcontent > div, i').remove();
+ ignore = loadedCheerio('article > style').text().trim().split(',');
+ ignore.push.apply(ignore, (((_a = ignore.pop()) === null || _a === void 0 ? void 0 : _a.match(/^\.\w+/)) || []));
+ ignore.map(function (tag) { return loadedCheerio("p".concat(tag)).remove(); });
+ chapterText = loadedCheerio('.epcontent').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ KolNovel.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var url, headers, result, body, loadedCheerio, novels;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ url = "".concat(this.site, "?s=").concat(searchTerm);
+ headers = new Headers();
+ if (this.cookieString) {
+ headers.append("cookie", this.cookieString);
+ }
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url, { headers: headers })];
+ case 1:
+ result = _a.sent();
+ return [4 /*yield*/, result.text()];
+ case 2:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ novels = [];
+ loadedCheerio("article.maindet").each(function () {
+ var novelName = loadedCheerio(this).find("h2").text();
+ var image = loadedCheerio(this).find("img");
+ var novelCover = image.attr("data-src") || image.attr("src");
+ var novelUrl = loadedCheerio(this).find("h2 a").attr("href");
+ if (!novelUrl)
+ return;
+ novels.push({
+ name: novelName,
+ url: novelUrl,
+ cover: novelCover,
+ });
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ KolNovel.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url)];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return KolNovel;
+}());
+exports.default = new KolNovel();
diff --git a/.js/plugins/chinese/linovelib.js b/.js/plugins/chinese/linovelib.js
new file mode 100644
index 0000000..9266697
--- /dev/null
+++ b/.js/plugins/chinese/linovelib.js
@@ -0,0 +1,525 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var cheerio_1 = require("cheerio");
+var fetch_1 = require("@libs/fetch");
+var filterInputs_1 = require("@libs/filterInputs");
+var showToast_1 = require("@libs/showToast");
+var Linovelib = /** @class */ (function () {
+ function Linovelib() {
+ this.id = "linovelib";
+ this.name = "Linovelib";
+ this.icon = "src/cn/linovelib/icon.png";
+ this.site = "https://w.linovelib.com";
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.filters = [
+ {
+ key: "sort",
+ label: "Sort By",
+ values: [
+ { label: "月点击榜", value: "monthvisit" },
+ { label: "周点击榜", value: "weekvisit" },
+ { label: "月推荐榜", value: "monthvote" },
+ { label: "周推荐榜", value: "weekvote" },
+ { label: "月鲜花榜", value: "monthflower" },
+ { label: "周鲜花榜", value: "weekflower" },
+ { label: "月鸡蛋榜", value: "monthegg" },
+ { label: "周鸡蛋榜", value: "weekegg" },
+ { label: "最近更新", value: "lastupdate" },
+ { label: "最新入库", value: "postdate" },
+ { label: "收藏榜", value: "goodnum" },
+ { label: "新书榜", value: "newhot" },
+ ],
+ inputType: filterInputs_1.FilterInputs.Picker,
+ },
+ ];
+ }
+ Linovelib.prototype.popularNovels = function (pageNo, _a) {
+ var filters = _a.filters;
+ return __awaiter(this, void 0, void 0, function () {
+ var link, headers, body, loadedCheerio, novels;
+ var _this = this;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ link = "".concat(this.site, "/top/");
+ link += ((filters === null || filters === void 0 ? void 0 : filters.sort) ? filters.sort : "monthvisit");
+ link += "/".concat(pageNo, ".html");
+ headers = new Headers();
+ if (this.cookieString) {
+ headers.append("cookie", this.cookieString);
+ }
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(link, { headers: headers }).then(function (result) {
+ return result.text();
+ })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ novels = [];
+ loadedCheerio(".module-rank-booklist .book-layout").each(function (i, el) {
+ var url = loadedCheerio(el).attr('href');
+ var novelName = loadedCheerio(el).find('.book-title').text();
+ var novelCover = loadedCheerio(el)
+ .find('img.book-cover')
+ .attr('data-src');
+ var novelUrl = _this.site + url;
+ if (!url)
+ return;
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ ;
+ Linovelib.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var url, headers, result, body, loadedCheerio, novel, chapter, idPattern, novelId, chaptersUrl, chaptersResult, chaptersBody, chaptersLoadedCheerio, volumeName, chapterId;
+ var _this = this;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ url = novelUrl;
+ headers = new Headers();
+ if (this.cookieString) {
+ headers.append("cookie", this.cookieString);
+ }
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url, { headers: headers })];
+ case 1:
+ result = _b.sent();
+ return [4 /*yield*/, result.text()];
+ case 2:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ novel = {
+ url: url,
+ chapters: [],
+ };
+ novel.name = loadedCheerio('#bookDetailWrapper .book-title').text();
+ novel.cover = loadedCheerio('#bookDetailWrapper img.book-cover').attr('src');
+ novel.summary = loadedCheerio('#bookSummary content').text();
+ novel.author = loadedCheerio('#bookDetailWrapper .book-rand-a a').text();
+ // TODO: Need some regex and dirty selector to get it
+ // Need to look into how to translate that message
+ novel.status = undefined;
+ novel.genres = loadedCheerio('.tag-small.red')
+ .children("a")
+ .map(function (i, el) { return loadedCheerio(el).text(); })
+ .toArray()
+ .join(",");
+ chapter = [];
+ idPattern = /\/(\d+)\.html/;
+ novelId = (_a = url.match(idPattern)) === null || _a === void 0 ? void 0 : _a[1];
+ chaptersUrl = this.site + loadedCheerio('#btnReadBook').attr('href');
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(chaptersUrl, { headers: headers })];
+ case 3:
+ chaptersResult = _b.sent();
+ return [4 /*yield*/, chaptersResult.text()];
+ case 4:
+ chaptersBody = _b.sent();
+ chaptersLoadedCheerio = (0, cheerio_1.load)(chaptersBody);
+ chaptersLoadedCheerio('#volumes .chapter-li').each(function (i, el) {
+ if (chaptersLoadedCheerio(el).hasClass('chapter-bar')) {
+ volumeName = chaptersLoadedCheerio(el).text();
+ }
+ else {
+ var urlPart = chaptersLoadedCheerio(el)
+ .find('.chapter-li-a')
+ .attr('href');
+ var chapterIdMatch = urlPart === null || urlPart === void 0 ? void 0 : urlPart.match(idPattern);
+ // Sometimes the href attribute does not contain the url, but javascript:cid(0).
+ // Increment the previous chapter ID should result in the right URL
+ if (chapterIdMatch) {
+ chapterId = +chapterIdMatch[1];
+ }
+ else {
+ chapterId++;
+ }
+ }
+ var chapterUrl = "".concat(_this.site, "/novel/").concat(novelId, "/").concat(chapterId, ".html");
+ var chapterName = volumeName +
+ ' — ' +
+ chaptersLoadedCheerio(el).find('.chapter-index').text().trim();
+ var releaseDate = null;
+ if (!chapterId)
+ return;
+ chapter.push({
+ name: chapterName,
+ releaseTime: releaseDate,
+ url: chapterUrl,
+ });
+ });
+ novel.chapters = chapter;
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ Linovelib.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var headers, chapterName, chapterText, hasNextPage, pageHasNextPage, pageText, pageNumber, skillgg, addPage, loadPage, url, page;
+ var _this = this;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ headers = new Headers();
+ if (this.cookieString) {
+ headers.append("cookie", this.cookieString);
+ }
+ chapterText = "", pageText = "";
+ pageNumber = 1;
+ skillgg = {
+ '\u201c': '\u300c',
+ '\u201d': '\u300d',
+ '\u2018': '\u300e',
+ '\u2019': '\u300f',
+ '\ue82c': '\u7684',
+ '\ue852': '\u4e00',
+ '\ue82d': '\u662f',
+ '\ue819': '\u4e86',
+ '\ue856': '\u6211',
+ '\ue857': '\u4e0d',
+ '\ue816': '\u4eba',
+ '\ue83c': '\u5728',
+ '\ue830': '\u4ed6',
+ '\ue82e': '\u6709',
+ '\ue836': '\u8fd9',
+ '\ue859': '\u4e2a',
+ '\ue80a': '\u4e0a',
+ '\ue855': '\u4eec',
+ '\ue842': '\u6765',
+ '\ue858': '\u5230',
+ '\ue80b': '\u65f6',
+ '\ue81f': '\u5927',
+ '\ue84a': '\u5730',
+ '\ue853': '\u4e3a',
+ '\ue81e': '\u5b50',
+ '\ue822': '\u4e2d',
+ '\ue813': '\u4f60',
+ '\ue85b': '\u8bf4',
+ '\ue807': '\u751f',
+ '\ue818': '\u56fd',
+ '\ue810': '\u5e74',
+ '\ue812': '\u7740',
+ '\ue851': '\u5c31',
+ '\ue801': '\u90a3',
+ '\ue80c': '\u548c',
+ '\ue815': '\u8981',
+ '\ue84c': '\u5979',
+ '\ue840': '\u51fa',
+ '\ue848': '\u4e5f',
+ '\ue835': '\u5f97',
+ '\ue800': '\u91cc',
+ '\ue826': '\u540e',
+ '\ue863': '\u81ea',
+ '\ue861': '\u4ee5',
+ '\ue854': '\u4f1a',
+ '\ue827': '\u5bb6',
+ '\ue83b': '\u53ef',
+ '\ue85d': '\u4e0b',
+ '\ue84d': '\u800c',
+ '\ue862': '\u8fc7',
+ '\ue81c': '\u5929',
+ '\ue81d': '\u53bb',
+ '\ue860': '\u80fd',
+ '\ue843': '\u5bf9',
+ '\ue82f': '\u5c0f',
+ '\ue802': '\u591a',
+ '\ue831': '\u7136',
+ '\ue84b': '\u4e8e',
+ '\ue837': '\u5fc3',
+ '\ue829': '\u5b66',
+ '\ue85e': '\u4e48',
+ '\ue83a': '\u4e4b',
+ '\ue832': '\u90fd',
+ '\ue808': '\u597d',
+ '\ue841': '\u770b',
+ '\ue821': '\u8d77',
+ '\ue845': '\u53d1',
+ '\ue803': '\u5f53',
+ '\ue828': '\u6ca1',
+ '\ue81b': '\u6210',
+ '\ue83e': '\u53ea',
+ '\ue820': '\u5982',
+ '\ue84e': '\u4e8b',
+ '\ue85a': '\u628a',
+ '\ue806': '\u8fd8',
+ '\ue83f': '\u7528',
+ '\ue833': '\u7b2c',
+ '\ue811': '\u6837',
+ '\ue804': '\u9053',
+ '\ue814': '\u60f3',
+ '\ue80f': '\u4f5c',
+ '\ue84f': '\u79cd',
+ '\ue80e': '\u5f00',
+ '\ue823': '\u7f8e',
+ '\ue849': '\u4e73',
+ '\ue805': '\u9634',
+ '\ue809': '\u6db2',
+ '\ue81a': '\u830e',
+ '\ue844': '\u6b32',
+ '\ue847': '\u547b',
+ '\ue850': '\u8089',
+ '\ue824': '\u4ea4',
+ '\ue85f': '\u6027',
+ '\ue817': '\u80f8',
+ '\ue85c': '\u79c1',
+ '\ue838': '\u7a74',
+ '\ue82a': '\u6deb',
+ '\ue83d': '\u81c0',
+ '\ue82b': '\u8214',
+ '\ue80d': '\u5c04',
+ '\ue839': '\u8131',
+ '\ue834': '\u88f8',
+ '\ue846': '\u9a9a',
+ '\ue825': '\u5507',
+ };
+ addPage = function (pageCheerio) { return __awaiter(_this, void 0, void 0, function () {
+ var formatPage;
+ var _this = this;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ formatPage = function () { return __awaiter(_this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ // Remove JS
+ pageCheerio('#ccacontent .cgo').remove();
+ // Load lazyloaded images
+ pageCheerio('#ccacontent img.imagecontent').each(function (i, el) {
+ // Sometimes images are either in data-src or src
+ var imgSrc = pageCheerio(el).attr('data-src') || pageCheerio(el).attr('src');
+ if (imgSrc) {
+ // The original CDN URL is locked behind a CF-like challenge, switch the URL to bypass that
+ // There are no react-native-url-polyfill lib, can't use URL API
+ var regex = /\/\/.+\.com\//;
+ var imgUrl = imgSrc.replace(regex, '//img.linovelib.com/');
+ // Clean up img element
+ pageCheerio(el)
+ .attr('src', imgUrl)
+ .removeAttr('data-src')
+ .removeClass('lazyload');
+ }
+ });
+ // Recover the original character
+ pageText = pageCheerio('#ccacontent').html() || "";
+ pageText = pageText.replace(/./g, function (char) { return skillgg[char] || char; });
+ return [2 /*return*/, Promise.resolve()];
+ });
+ }); };
+ return [4 /*yield*/, formatPage()];
+ case 1:
+ _a.sent();
+ chapterName =
+ pageCheerio('#atitle + h3').text() +
+ ' — ' +
+ pageCheerio('#atitle').text();
+ if (chapterText === "") {
+ chapterText = '
' + chapterName + '
';
+ }
+ chapterText += pageText;
+ return [2 /*return*/];
+ }
+ });
+ }); };
+ loadPage = function (url) { return __awaiter(_this, void 0, void 0, function () {
+ var result, body, pageCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(url, { headers: headers })];
+ case 1:
+ result = _a.sent();
+ return [4 /*yield*/, result.text()];
+ case 2:
+ body = _a.sent();
+ pageCheerio = (0, cheerio_1.load)(body);
+ return [4 /*yield*/, addPage(pageCheerio)];
+ case 3:
+ _a.sent();
+ pageHasNextPage =
+ pageCheerio('#footlink a:last').text() === '下一页' ? true : false;
+ return [2 /*return*/, { pageCheerio: pageCheerio, pageHasNextPage: pageHasNextPage }];
+ }
+ });
+ }); };
+ url = chapterUrl;
+ _a.label = 1;
+ case 1: return [4 /*yield*/, loadPage(url)];
+ case 2:
+ page = _a.sent();
+ hasNextPage = page.pageHasNextPage;
+ if (hasNextPage === true) {
+ pageNumber++;
+ url = chapterUrl.replace(/\.html/gi, "_".concat(pageNumber) + '.html');
+ }
+ _a.label = 3;
+ case 3:
+ if (hasNextPage === true) return [3 /*break*/, 1];
+ _a.label = 4;
+ case 4: return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ Linovelib.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var searchUrl, Term, headers, NextPage, NoNextPage, DeadEnd, novels, addPage, loadPage, url, page;
+ var _this = this;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ searchUrl = "".concat(this.site, "/search/");
+ Term = encodeURI(searchTerm);
+ headers = new Headers();
+ if (this.cookieString) {
+ headers.append("cookie", this.cookieString);
+ }
+ pageNo = 1;
+ novels = [];
+ addPage = function (pageCheerio, redirect) { return __awaiter(_this, void 0, void 0, function () {
+ var loadSearchResults, novelResults, novelName, novelCover, novelUrl;
+ var _this = this;
+ var _a;
+ return __generator(this, function (_b) {
+ loadSearchResults = function () {
+ pageCheerio('.book-ol .book-layout').each(function (i, el) {
+ var nUrl = pageCheerio(el).attr('href');
+ var novelName = pageCheerio(el).find('.book-title').text();
+ var novelCover = pageCheerio(el)
+ .find('img.book-cover')
+ .attr('data-src');
+ var novelUrl = _this.site + nUrl;
+ if (!nUrl)
+ return;
+ novels.push({
+ name: novelName,
+ url: novelUrl,
+ cover: novelCover,
+ });
+ });
+ };
+ novelResults = pageCheerio('.book-ol a.book-layout');
+ if (novelResults.length === 0) {
+ (0, showToast_1.showToast)('Bypass check by searching in Webview');
+ }
+ else {
+ loadSearchResults();
+ }
+ if (redirect.length) {
+ novels.length = 0;
+ novelName = pageCheerio('#bookDetailWrapper .book-title').text();
+ novelCover = pageCheerio('#bookDetailWrapper img.book-cover').attr('src');
+ novelUrl = this.site +
+ ((_a = pageCheerio('#btnReadBook').attr('href')) === null || _a === void 0 ? void 0 : _a.slice(0, -8)) +
+ '.html';
+ novels.push({
+ name: novelName,
+ url: novelUrl,
+ cover: novelCover,
+ });
+ }
+ return [2 /*return*/];
+ });
+ }); };
+ loadPage = function (url) { return __awaiter(_this, void 0, void 0, function () {
+ var result, body, pageCheerio, redirect;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(url, { headers: headers })];
+ case 1:
+ result = _a.sent();
+ return [4 /*yield*/, result.text()];
+ case 2:
+ body = _a.sent();
+ pageCheerio = (0, cheerio_1.load)(body);
+ redirect = pageCheerio('div.book-layout').text();
+ return [4 /*yield*/, addPage(pageCheerio, redirect)];
+ case 3:
+ _a.sent();
+ NextPage = pageCheerio('.next').attr('href');
+ if (!NextPage) {
+ NoNextPage === true;
+ }
+ else {
+ NoNextPage = NextPage === '#' ? true : false;
+ }
+ return [2 /*return*/, { pageCheerio: pageCheerio, NoNextPage: NoNextPage }];
+ }
+ });
+ }); };
+ url = "".concat(searchUrl).concat(Term, "_").concat(pageNo, ".html");
+ _a.label = 1;
+ case 1: return [4 /*yield*/, loadPage(url)];
+ case 2:
+ page = _a.sent();
+ DeadEnd = page.NoNextPage;
+ if (DeadEnd === false) {
+ pageNo++;
+ url = "".concat(searchUrl).concat(Term, "_").concat(pageNo, ".html");
+ }
+ _a.label = 3;
+ case 3:
+ if (DeadEnd === false) return [3 /*break*/, 1];
+ _a.label = 4;
+ case 4: return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ ;
+ Linovelib.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url)];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return Linovelib;
+}());
+exports.default = new Linovelib();
diff --git a/.js/plugins/english/BoxNovel[madara].js b/.js/plugins/english/BoxNovel[madara].js
new file mode 100644
index 0000000..f8b862d
--- /dev/null
+++ b/.js/plugins/english/BoxNovel[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "boxnovel", "sourceSite": "https://boxnovel.com/", "sourceName": "BoxNovel", "filters": [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": "Picker" }, { "key": "genres", "label": "GENRES", "values": [{ "label": "Action", "value": "action" }, { "label": "Adventure", "value": "adventure" }, { "label": "Comedy", "value": "comedy" }, { "label": "Drama", "value": "drama" }, { "label": "Ecchi", "value": "ecchi" }, { "label": "Fantasy", "value": "fantasy" }, { "label": "Gender Bender", "value": "gender-bender" }, { "label": "Harem", "value": "harem" }, { "label": "Historical", "value": "historical" }, { "label": "Horror", "value": "horror" }, { "label": "Josei", "value": "josei" }, { "label": "Martial Arts", "value": "martial-arts" }, { "label": "Mature", "value": "mature" }, { "label": "Mecha", "value": "mecha" }, { "label": "Mystery", "value": "mystery" }, { "label": "Psychological", "value": "psychological" }, { "label": "Romance", "value": "romance" }, { "label": "School Life", "value": "school-life" }, { "label": "Sci-fi", "value": "sci-fi" }, { "label": "Seinen", "value": "seinen" }, { "label": "Shoujo", "value": "shoujo" }, { "label": "Shounen", "value": "shounen" }, { "label": "Slice of Life", "value": "slice-of-life" }, { "label": "Smut", "value": "smut" }, { "label": "Sports", "value": "sports" }, { "label": "Supernatural", "value": "supernatural" }, { "label": "Tragedy", "value": "tragedy" }, { "label": "Wuxia", "value": "wuxia" }, { "label": "Xianxia", "value": "xianxia" }, { "label": "Xuanhuan", "value": "xuanhuan" }, { "label": "Yaoi", "value": "yaoi" }], "inputType": "Picker" }], "options": { "path": { "genres": "manga-genre" }, "useNewChapterEndpoint": true, "lang": "English" } });
+exports.default = plugin;
diff --git a/.js/plugins/english/ClickNovel[madara].js b/.js/plugins/english/ClickNovel[madara].js
new file mode 100644
index 0000000..c766349
--- /dev/null
+++ b/.js/plugins/english/ClickNovel[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "clicknovel", "sourceSite": "https://clicknovel.net/", "sourceName": "ClickNovel", "filters": [], "options": { "lang": "English" } });
+exports.default = plugin;
diff --git a/.js/plugins/english/CrateNovel[madara].js b/.js/plugins/english/CrateNovel[madara].js
new file mode 100644
index 0000000..c8c7bd7
--- /dev/null
+++ b/.js/plugins/english/CrateNovel[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "cratenovel", "sourceSite": "https://cratenovel.com/", "sourceName": "CrateNovel", "filters": [], "options": { "useNewChapterEndpoint": true, "lang": "English" } });
+exports.default = plugin;
diff --git a/.js/plugins/english/DaoNovel[madara].js b/.js/plugins/english/DaoNovel[madara].js
new file mode 100644
index 0000000..b6b9db3
--- /dev/null
+++ b/.js/plugins/english/DaoNovel[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "daonovel", "sourceSite": "https://daonovel.com/", "sourceName": "DaoNovel", "filters": [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": "Picker" }], "options": { "path": { "novels": "novels-list", "novel": "novels", "chapter": "novels" }, "useNewChapterEndpoint": true, "lang": "English" } });
+exports.default = plugin;
diff --git a/.js/plugins/english/FansTranslations[madara].js b/.js/plugins/english/FansTranslations[madara].js
new file mode 100644
index 0000000..8b57d94
--- /dev/null
+++ b/.js/plugins/english/FansTranslations[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "fanTLS", "sourceSite": "https://fanstranslations.com/", "sourceName": "Fans Translations", "filters": [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": "Picker" }], "options": { "useNewChapterEndpoint": true, "lang": "English" } });
+exports.default = plugin;
diff --git a/.js/plugins/english/FirstKissNovel[madara].js b/.js/plugins/english/FirstKissNovel[madara].js
new file mode 100644
index 0000000..1329250
--- /dev/null
+++ b/.js/plugins/english/FirstKissNovel[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "1stkissnovel", "sourceSite": "https://1stkissnovel.org/", "sourceName": "FirstKissNovel", "filters": [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": "Picker" }, { "key": "genres", "label": "GENRES", "values": [{ "label": "Action", "value": "action" }, { "label": "Adult", "value": "adult" }, { "label": "Adventure", "value": "adventure" }, { "label": "Anime", "value": "anime" }, { "label": "Apocalypse", "value": "apocalypse" }, { "label": "Boy's Love", "value": "boys-love" }, { "label": "Comedy", "value": "comedy" }, { "label": "Completed", "value": "completed" }, { "label": "Cooking", "value": "cooking" }, { "label": "Demons", "value": "demons" }, { "label": "Detective", "value": "detective" }, { "label": "Drama", "value": "drama" }, { "label": "Ecchi", "value": "ecchi" }, { "label": "Fan-Fiction", "value": "fan-fiction" }, { "label": "Fantasy", "value": "fantasy" }, { "label": "Food", "value": "food" }, { "label": "Game", "value": "game" }, { "label": "Gender Bender", "value": "gender-bender" }, { "label": "Girls Love", "value": "girls-love" }, { "label": "Harem", "value": "harem" }, { "label": "Historical", "value": "historical" }, { "label": "Horror", "value": "horror" }, { "label": "Humor", "value": "humor" }, { "label": "Isekai", "value": "isekai" }, { "label": "Josei", "value": "josei" }, { "label": "Magic", "value": "magic" }, { "label": "Magical", "value": "magical" }, { "label": "Manhua", "value": "manhua" }, { "label": "Manhwa", "value": "manhwa" }, { "label": "Martial Arts", "value": "martial-arts" }, { "label": "Mature", "value": "mature" }, { "label": "Mecha", "value": "mecha" }, { "label": "Medical", "value": "medical" }, { "label": "Military", "value": "military" }, { "label": "Moder", "value": "moder" }, { "label": "Modern", "value": "modern" }, { "label": "Murim", "value": "murim" }, { "label": "Music", "value": "music" }, { "label": "Mystery", "value": "mystery" }, { "label": "Psychological", "value": "psychological" }, { "label": "Reverse", "value": "reverse" }, { "label": "Reverse harem", "value": "reverse-harem" }, { "label": "Romance", "value": "romance" }, { "label": "School Life", "value": "school-life" }, { "label": "Sci-fi", "value": "sci-fi" }, { "label": "Seinen", "value": "seinen" }, { "label": "Shoujo", "value": "shoujo" }, { "label": "Shoujo Ai", "value": "shoujo-ai" }, { "label": "Shounen", "value": "shounen" }, { "label": "Shounen Ai", "value": "shounen-ai" }, { "label": "Slice of Life", "value": "slice-of-life" }, { "label": "Smut", "value": "smut" }, { "label": "Sports", "value": "sports" }, { "label": "Super power", "value": "super-power" }, { "label": "Superhero", "value": "superhero" }, { "label": "Supernatural", "value": "supernatural" }, { "label": "Thriller", "value": "thriller" }, { "label": "Tragedy", "value": "tragedy" }, { "label": "Urban Life", "value": "urban-life" }, { "label": "Vampire", "value": "vampire" }, { "label": "Webtoons", "value": "webtoons" }, { "label": "Wuxia", "value": "wuxia" }, { "label": "Xianxia", "value": "xianxia" }, { "label": "Xuanhuan", "value": "xuanhuan" }, { "label": "Yaoi", "value": "yaoi" }, { "label": "Yuri", "value": "yuri" }], "inputType": "Picker" }], "options": { "useNewChapterEndpoint": true, "lang": "English" } });
+exports.default = plugin;
diff --git a/.js/plugins/english/FreeNovelMe[madara].js b/.js/plugins/english/FreeNovelMe[madara].js
new file mode 100644
index 0000000..d4ad448
--- /dev/null
+++ b/.js/plugins/english/FreeNovelMe[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "freenovel.me", "sourceSite": "https://freenovel.me/", "sourceName": "FreeNovelMe", "filters": [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": "Picker" }, { "key": "genres", "label": "GENRES", "values": [{ "label": "Action", "value": "action" }, { "label": "Adult", "value": "adult" }, { "label": "Adventure", "value": "adventure" }, { "label": "Cartoon", "value": "cartoon" }, { "label": "Comedy", "value": "comedy" }, { "label": "Cooking", "value": "cooking" }, { "label": "Detective", "value": "detective" }, { "label": "Drama", "value": "drama" }, { "label": "Fantasy", "value": "fantasy" }, { "label": "Game", "value": "game" }, { "label": "Gender Bender", "value": "gender-bender" }, { "label": "Historical", "value": "historical" }, { "label": "History", "value": "history" }, { "label": "Horror", "value": "horror" }, { "label": "Josei", "value": "josei" }, { "label": "Live action", "value": "live-action" }, { "label": "Martial", "value": "martial" }, { "label": "Martial Arts", "value": "martial-arts" }, { "label": "Mature", "value": "mature" }, { "label": "Mecha", "value": "mecha" }, { "label": "Mystery", "value": "mystery" }, { "label": "One shot", "value": "one-shot" }, { "label": "Premium", "value": "premium" }, { "label": "Psychological", "value": "psychological" }, { "label": "Reincarnation", "value": "reincarnation" }, { "label": "Romance", "value": "romance" }, { "label": "School Life", "value": "school-life" }, { "label": "Sci-fi", "value": "sci-fi" }, { "label": "Slice of Life", "value": "slice-of-life" }, { "label": "Smut", "value": "smut" }, { "label": "Sports", "value": "sports" }, { "label": "Supernatural", "value": "supernatural" }, { "label": "Tragedy", "value": "tragedy" }, { "label": "Wuxia", "value": "wuxia" }, { "label": "Xianxia", "value": "xianxia" }, { "label": "Xuanhuan", "value": "xuanhuan" }], "inputType": "Picker" }], "options": { "lang": "English" } });
+exports.default = plugin;
diff --git a/.js/plugins/english/Guavaread[madara].js b/.js/plugins/english/Guavaread[madara].js
new file mode 100644
index 0000000..81a00aa
--- /dev/null
+++ b/.js/plugins/english/Guavaread[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "guavaread", "sourceSite": "https://guavaread.com/", "sourceName": "Guavaread", "filters": [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": "Picker" }, { "key": "genres", "label": "GENRES", "values": [{ "label": "Action", "value": "action" }, { "label": "Adult", "value": "adult" }, { "label": "Adventure", "value": "adventure" }, { "label": "Comedy", "value": "comedy" }, { "label": "Complete", "value": "complete" }, { "label": "Cooking", "value": "cooking" }, { "label": "Detective", "value": "detective" }, { "label": "Drama", "value": "drama" }, { "label": "Dropped", "value": "dropped" }, { "label": "Ecchi", "value": "ecchi" }, { "label": "Fantasy", "value": "fantasy" }, { "label": "Gender Bender", "value": "gender-bender" }, { "label": "Historical", "value": "historical" }, { "label": "Horror", "value": "horror" }, { "label": "Josei", "value": "josei" }, { "label": "Mature", "value": "mature" }, { "label": "Mystery", "value": "mystery" }, { "label": "Original Story", "value": "original-story" }, { "label": "Pilot", "value": "pilot" }, { "label": "Psychological", "value": "psychological" }, { "label": "R-15", "value": "r-15" }, { "label": "R-19", "value": "r-19" }, { "label": "Reverse Harem", "value": "reverse-harem" }, { "label": "Romance", "value": "romance" }, { "label": "School Life", "value": "school-life" }, { "label": "Sci-fi", "value": "sci-fi" }, { "label": "Shoujo", "value": "shoujo" }, { "label": "Slice of Life", "value": "slice-of-life" }, { "label": "Smut", "value": "smut" }, { "label": "Supernatural", "value": "supernatural" }, { "label": "Tragedy", "value": "tragedy" }], "inputType": "Picker" }], "options": { "useNewChapterEndpoint": true, "lang": "English" } });
+exports.default = plugin;
diff --git a/.js/plugins/english/LightNovelHeaven[madara].js b/.js/plugins/english/LightNovelHeaven[madara].js
new file mode 100644
index 0000000..75b392c
--- /dev/null
+++ b/.js/plugins/english/LightNovelHeaven[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "lnheaven", "sourceSite": "https://lightnovelheaven.com/", "sourceName": "LightNovelHeaven", "filters": [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": "Picker" }], "options": { "path": { "novels": "series", "novel": "series", "chapter": "series" }, "useNewChapterEndpoint": true, "lang": "English" } });
+exports.default = plugin;
diff --git a/.js/plugins/english/LunarLetters[madara].js b/.js/plugins/english/LunarLetters[madara].js
new file mode 100644
index 0000000..9187e6c
--- /dev/null
+++ b/.js/plugins/english/LunarLetters[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "lunarletters", "sourceSite": "https://www.lunarletters.com/", "sourceName": "LunarLetters", "filters": [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": "Picker" }], "options": { "path": { "novels": "series", "novel": "series", "chapter": "series" }, "useNewChapterEndpoint": true, "lang": "English" } });
+exports.default = plugin;
diff --git a/.js/plugins/english/MTLNovelClub[madara].js b/.js/plugins/english/MTLNovelClub[madara].js
new file mode 100644
index 0000000..e178575
--- /dev/null
+++ b/.js/plugins/english/MTLNovelClub[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "mtlnovel.club", "sourceSite": "https://mtlnovel.club/", "sourceName": "MTLNovel.Club", "filters": [], "options": { "useNewChapterEndpoint": true, "lang": "English" } });
+exports.default = plugin;
diff --git a/.js/plugins/english/MTLNovel[madara].js b/.js/plugins/english/MTLNovel[madara].js
new file mode 100644
index 0000000..fef3caa
--- /dev/null
+++ b/.js/plugins/english/MTLNovel[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "mtl-novel", "sourceSite": "https://mtl-novel.com/", "sourceName": "MTL-Novel", "filters": [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": "Picker" }, { "key": "genres", "label": "GENRES", "values": [{ "label": "Action", "value": "action" }, { "label": "Adult", "value": "adult" }, { "label": "Adventure", "value": "adventure" }, { "label": "Chinese", "value": "chinese" }, { "label": "Comedy", "value": "comedy" }, { "label": "Conan", "value": "conan" }, { "label": "Drama", "value": "drama" }, { "label": "Erciyuan", "value": "erciyuan" }, { "label": "Fairy Tail", "value": "fairy-tail" }, { "label": "Faloo", "value": "faloo" }, { "label": "Fan-Fiction", "value": "fan-fiction" }, { "label": "Fantasy", "value": "fantasy" }, { "label": "FoodWars!", "value": "foodwars" }, { "label": "Game", "value": "game" }, { "label": "Gender Bender", "value": "gender-bender" }, { "label": "Harem", "value": "harem" }, { "label": "Historical", "value": "historical" }, { "label": "Horror", "value": "horror" }, { "label": "Hunter x Hunter", "value": "hunter-x-hunter" }, { "label": "Japanese", "value": "japanese" }, { "label": "Jojo", "value": "jojo" }, { "label": "Josei", "value": "josei" }, { "label": "Korean", "value": "korean" }, { "label": "Martial Arts", "value": "martial-arts" }, { "label": "Marvel", "value": "marvel" }, { "label": "Mature", "value": "mature" }, { "label": "Mecha", "value": "mecha" }, { "label": "Military", "value": "military" }, { "label": "Mystery", "value": "mystery" }, { "label": "Naruto", "value": "naruto" }, { "label": "One piece", "value": "one-piece" }, { "label": "Pokemon", "value": "pokemon" }, { "label": "Psychological", "value": "psychological" }, { "label": "Romance", "value": "romance" }, { "label": "School Life", "value": "school-life" }, { "label": "Sci-fi", "value": "sci-fi" }, { "label": "Seinen", "value": "seinen" }, { "label": "Shoujo", "value": "shoujo" }, { "label": "Shoujo Ai", "value": "shoujo-ai" }, { "label": "Shounen Ai", "value": "shounen-ai" }, { "label": "Slice of Life", "value": "slice-of-life" }, { "label": "Smut", "value": "smut" }, { "label": "Sport", "value": "sport" }, { "label": "Sports", "value": "sports" }, { "label": "Supernatural", "value": "supernatural" }, { "label": "System", "value": "system" }, { "label": "Tragedy", "value": "tragedy" }, { "label": "Urban", "value": "urban" }, { "label": "Urban Life", "value": "urban-life" }, { "label": "Wuxia", "value": "wuxia" }, { "label": "Xianxia", "value": "xianxia" }, { "label": "Xuanhuan", "value": "xuanhuan" }, { "label": "Yaoi", "value": "yaoi" }, { "label": "Yuri", "value": "yuri" }], "inputType": "Picker" }], "options": { "path": { "genres": "manga-genre" }, "useNewChapterEndpoint": true, "lang": "English" } });
+exports.default = plugin;
diff --git a/.js/plugins/english/MostNovel[madara].js b/.js/plugins/english/MostNovel[madara].js
new file mode 100644
index 0000000..95263f5
--- /dev/null
+++ b/.js/plugins/english/MostNovel[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "mostnovel", "sourceSite": "https://mostnovel.com/", "sourceName": "MostNovel", "filters": [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": "Picker" }, { "key": "genres", "label": "GENRES", "values": [{ "label": "ACG", "value": "acg" }, { "label": "Action", "value": "action" }, { "label": "Adult", "value": "adult" }, { "label": "Adventure", "value": "adventure" }, { "label": "AGA", "value": "aga" }, { "label": "Anime", "value": "anime" }, { "label": "Anime & Comics", "value": "anime-comics" }, { "label": "Bender", "value": "bender" }, { "label": "BL", "value": "bl" }, { "label": "Cartoon", "value": "cartoon" }, { "label": "Comedy", "value": "comedy" }, { "label": "Comic", "value": "comic" }, { "label": "Contemporary Romance", "value": "contemporary-romance" }, { "label": "Cooking", "value": "cooking" }, { "label": "Cultivation", "value": "cultivation" }, { "label": "Detective", "value": "detective" }, { "label": "Doujinshi", "value": "doujinshi" }, { "label": "Drama", "value": "drama" }, { "label": "Eastern Fantasy", "value": "eastern-fantasy" }, { "label": "Ecchi", "value": "ecchi" }, { "label": "Fantasy", "value": "fantasy" }, { "label": "Gender Bender", "value": "gender-bender" }, { "label": "Harem", "value": "harem" }, { "label": "Historical", "value": "historical" }, { "label": "Horror", "value": "horror" }, { "label": "Horror&Thriller", "value": "horrorthriller" }, { "label": "Josei", "value": "josei" }, { "label": "Live action", "value": "live-action" }, { "label": "Magical Realism", "value": "magical-realism" }, { "label": "Manga", "value": "manga" }, { "label": "Manhua", "value": "manhua" }, { "label": "Manhwa", "value": "manhwa" }, { "label": "Martial Arts", "value": "martial-arts" }, { "label": "Mature", "value": "mature" }, { "label": "Mecha", "value": "mecha" }, { "label": "Modern", "value": "modern" }, { "label": "Movies", "value": "movies" }, { "label": "Mystery", "value": "mystery" }, { "label": "One shot", "value": "one-shot" }, { "label": "Psychological", "value": "psychological" }, { "label": "Romance", "value": "romance" }, { "label": "School Life", "value": "school-life" }, { "label": "Sci-fi", "value": "sci-fi" }, { "label": "Seinen", "value": "seinen" }, { "label": "Shoujo", "value": "shoujo" }, { "label": "Shoujo Ai", "value": "shoujo-ai" }, { "label": "Shounen", "value": "shounen" }, { "label": "Shounen Ai", "value": "shounen-ai" }, { "label": "Slice of Life", "value": "slice-of-life" }, { "label": "Smart MC", "value": "smart-mc" }, { "label": "Smut", "value": "smut" }, { "label": "Soft Yaoi", "value": "soft-yaoi" }, { "label": "Soft Yuri", "value": "soft-yuri" }, { "label": "Sports", "value": "sports" }, { "label": "Supernatural", "value": "supernatural" }, { "label": "Tragedy", "value": "tragedy" }, { "label": "Urban Life", "value": "urban-life" }, { "label": "Video Games", "value": "video-games" }, { "label": "Webtoon", "value": "webtoon" }, { "label": "Wuxia", "value": "wuxia" }, { "label": "Xianxia", "value": "xianxia" }, { "label": "Xuanhuan", "value": "xuanhuan" }, { "label": "Yaoi", "value": "yaoi" }, { "label": "Yuri", "value": "yuri" }], "inputType": "Picker" }], "options": { "path": { "novels": "manga", "novel": "manga", "chapter": "manga", "genres": "manga-genre" }, "lang": "English" } });
+exports.default = plugin;
diff --git a/.js/plugins/english/MysticalSeries[madara].js b/.js/plugins/english/MysticalSeries[madara].js
new file mode 100644
index 0000000..829e1fb
--- /dev/null
+++ b/.js/plugins/english/MysticalSeries[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "mysticalmerries", "sourceSite": "https://mysticalmerries.com/", "sourceName": "MysticalSeries", "filters": [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": "Picker" }, { "key": "genres", "label": "GENRES", "values": [{ "label": "Action", "value": "action" }, { "label": "Adaptation", "value": "adaptation" }, { "label": "Adventure", "value": "adventure" }, { "label": "bilibili", "value": "bilibili" }, { "label": "Chinese Novel", "value": "chinese-novel" }, { "label": "Comedy", "value": "comedy" }, { "label": "Crossdressing", "value": "crossdressing" }, { "label": "Drama", "value": "drama" }, { "label": "Dropped", "value": "dropped" }, { "label": "Family", "value": "family" }, { "label": "Fantasy", "value": "fantasy" }, { "label": "Gender Bender", "value": "gender-bender" }, { "label": "Historical", "value": "historical" }, { "label": "Horror", "value": "horror" }, { "label": "Isekai", "value": "isekai" }, { "label": "Korean Novel", "value": "korean-novell" }, { "label": "Manga", "value": "manga" }, { "label": "Manhua", "value": "manhua" }, { "label": "Manhwa", "value": "manhwa" }, { "label": "Modern Romance", "value": "modern-romance" }, { "label": "Mystery", "value": "mystery" }, { "label": "Office Workers", "value": "office-workers" }, { "label": "One shot", "value": "one-shot" }, { "label": "Pilot Novel", "value": "pilot-novel" }, { "label": "R15", "value": "r15" }, { "label": "R19", "value": "r19" }, { "label": "Regression", "value": "regression" }, { "label": "Reincarnation", "value": "reincarnation" }, { "label": "Reverse Harem", "value": "reverse-harem" }, { "label": "Romance Fantasy", "value": "romance-fantasy" }, { "label": "School Life", "value": "school-life" }, { "label": "Sci-fi", "value": "sci-fi" }, { "label": "Slice of Life", "value": "slice-of-life" }, { "label": "Smut", "value": "smut" }, { "label": "Supernatural", "value": "supernatural" }, { "label": "Violence", "value": "violence" }], "inputType": "Picker" }], "options": { "path": { "novels": "series", "novel": "series", "chapter": "series", "genres": "genre" }, "useNewChapterEndpoint": true, "lang": "English" } });
+exports.default = plugin;
diff --git a/.js/plugins/english/NeoSekaiTranslations[madara].js b/.js/plugins/english/NeoSekaiTranslations[madara].js
new file mode 100644
index 0000000..2264b0f
--- /dev/null
+++ b/.js/plugins/english/NeoSekaiTranslations[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "neosekaiTLS", "sourceSite": "https://www.neosekaitranslations.com/", "sourceName": "NeoSekai Translations", "filters": [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": "Picker" }, { "key": "genres", "label": "GENRES", "values": [{ "label": "Action", "value": "action" }, { "label": "Adventure", "value": "adventure" }, { "label": "Comedy", "value": "comedy" }, { "label": "Drama", "value": "drama" }, { "label": "Fantasy", "value": "fantasy" }, { "label": "Harem", "value": "harem" }, { "label": "Horror", "value": "horror" }, { "label": "Mature", "value": "mature" }, { "label": "Mecha", "value": "mecha" }, { "label": "Mystery", "value": "mystery" }, { "label": "Psychological", "value": "psychological" }, { "label": "Romance", "value": "romance" }, { "label": "School Life", "value": "school-life" }, { "label": "Sci-Fi", "value": "sci-fi" }, { "label": "Slice of Life", "value": "slice-of-life" }], "inputType": "Picker" }], "options": { "lang": "English" } });
+exports.default = plugin;
diff --git a/.js/plugins/english/NocturneTranslations[madara].js b/.js/plugins/english/NocturneTranslations[madara].js
new file mode 100644
index 0000000..b096667
--- /dev/null
+++ b/.js/plugins/english/NocturneTranslations[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "nocturneTLS", "sourceSite": "https://nocturnetls.net/", "sourceName": "Nocturne Translations", "filters": [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": "Picker" }, { "key": "genres", "label": "GENRES", "values": [{ "label": "Action", "value": "action" }, { "label": "Adult", "value": "adult" }, { "label": "Adventure", "value": "adventure" }, { "label": "Anime", "value": "anime" }, { "label": "Cartoon", "value": "cartoon" }, { "label": "Comedy", "value": "comedy" }, { "label": "Comic", "value": "comic" }, { "label": "Cooking", "value": "cooking" }, { "label": "Detective", "value": "detective" }, { "label": "Doujinshi", "value": "doujinshi" }, { "label": "Drama", "value": "drama" }, { "label": "Ecchi", "value": "ecchi" }, { "label": "Fantasy", "value": "fantasy" }, { "label": "Gender Bender", "value": "gender-bender" }, { "label": "Harem", "value": "harem" }, { "label": "Historical", "value": "historical" }, { "label": "Horror", "value": "horror" }, { "label": "Josei", "value": "josei" }, { "label": "Live action", "value": "live-action" }, { "label": "Manga", "value": "manga" }, { "label": "Manhua", "value": "manhua" }, { "label": "Manhwa", "value": "manhwa" }, { "label": "Martial Arts", "value": "martial-arts" }, { "label": "Mature", "value": "mature" }, { "label": "Mecha", "value": "mecha" }, { "label": "Mystery", "value": "mystery" }, { "label": "One shot", "value": "one-shot" }, { "label": "Psychological", "value": "psychological" }, { "label": "Romance", "value": "romance" }, { "label": "School Life", "value": "school-life" }, { "label": "Sci-fi", "value": "sci-fi" }, { "label": "Seinen", "value": "seinen" }, { "label": "Shoujo", "value": "shoujo" }, { "label": "Shoujo Ai", "value": "shoujo-ai" }, { "label": "Shounen", "value": "shounen" }, { "label": "Shounen Ai", "value": "shounen-ai" }, { "label": "Slice of Life", "value": "slice-of-life" }, { "label": "Smut", "value": "smut" }, { "label": "Soft Yaoi", "value": "soft-yaoi" }, { "label": "Soft Yuri", "value": "soft-yuri" }, { "label": "Sports", "value": "sports" }, { "label": "Supernatural", "value": "supernatural" }, { "label": "Tragedy", "value": "tragedy" }, { "label": "Webtoon", "value": "webtoon" }, { "label": "Yaoi", "value": "yaoi" }, { "label": "Yuri", "value": "yuri" }], "inputType": "Picker" }], "options": { "path": { "novels": "novels", "novel": "novels", "chapter": "novels", "genres": "manga-genre" }, "lang": "English" } });
+exports.default = plugin;
diff --git a/.js/plugins/english/NoobchanTranslation[madara].js b/.js/plugins/english/NoobchanTranslation[madara].js
new file mode 100644
index 0000000..d9aa474
--- /dev/null
+++ b/.js/plugins/english/NoobchanTranslation[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "noobchanTL", "sourceSite": "https://noobchan.xyz/", "sourceName": "Noobchan Translation", "filters": [], "options": { "useNewChapterEndpoint": true, "lang": "English" } });
+exports.default = plugin;
diff --git a/.js/plugins/english/NovelMultiverse[madara].js b/.js/plugins/english/NovelMultiverse[madara].js
new file mode 100644
index 0000000..545d558
--- /dev/null
+++ b/.js/plugins/english/NovelMultiverse[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "novelmultiverse", "sourceSite": "https://www.novelmultiverse.com/", "sourceName": "NovelMultiverse", "filters": [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": "Picker" }, { "key": "genres", "label": "GENRES", "values": [{ "label": "Action", "value": "action" }, { "label": "Adult", "value": "adult" }, { "label": "Adventure", "value": "adventure" }, { "label": "Anime", "value": "anime" }, { "label": "Cartoon", "value": "cartoon" }, { "label": "Comedy", "value": "comedy" }, { "label": "Comic", "value": "comic" }, { "label": "Cooking", "value": "cooking" }, { "label": "Detective", "value": "detective" }, { "label": "Doujinshi", "value": "doujinshi" }, { "label": "Drama", "value": "drama" }, { "label": "Ecchi", "value": "ecchi" }, { "label": "Fantasy", "value": "fantasy" }, { "label": "Gender Bender", "value": "gender-bender" }, { "label": "Harem", "value": "harem" }, { "label": "Historical", "value": "historical" }, { "label": "Horror", "value": "horror" }, { "label": "Josei", "value": "josei" }, { "label": "Live action", "value": "live-action" }, { "label": "Manga", "value": "manga" }, { "label": "Manhua", "value": "manhua" }, { "label": "Manhwa", "value": "manhwa" }, { "label": "Martial Arts", "value": "martial-arts" }, { "label": "Mature", "value": "mature" }, { "label": "Mecha", "value": "mecha" }, { "label": "Mystery", "value": "mystery" }, { "label": "One shot", "value": "one-shot" }, { "label": "Original", "value": "original" }, { "label": "Psychological", "value": "psychological" }, { "label": "Romance", "value": "romance" }, { "label": "School Life", "value": "school-life" }, { "label": "Sci-fi", "value": "sci-fi" }, { "label": "Seinen", "value": "seinen" }, { "label": "Shoujo", "value": "shoujo" }, { "label": "Shoujo Ai", "value": "shoujo-ai" }, { "label": "Shounen", "value": "shounen" }, { "label": "Shounen Ai", "value": "shounen-ai" }, { "label": "Slice of Life", "value": "slice-of-life" }, { "label": "Smut", "value": "smut" }, { "label": "Soft Yaoi", "value": "soft-yaoi" }, { "label": "Soft Yuri", "value": "soft-yuri" }, { "label": "Sports", "value": "sports" }, { "label": "Supernatural", "value": "supernatural" }, { "label": "Tragedy", "value": "tragedy" }, { "label": "Translation", "value": "translation" }, { "label": "Webtoon", "value": "webtoon" }, { "label": "Wuxia", "value": "wuxia" }, { "label": "Xianxia", "value": "xianxia" }, { "label": "Xuanhuan", "value": "xuanhuan" }, { "label": "Yaoi", "value": "yaoi" }, { "label": "Yuri", "value": "yuri" }], "inputType": "Picker" }], "options": { "lang": "English" } });
+exports.default = plugin;
diff --git a/.js/plugins/english/NovelR18[madara].js b/.js/plugins/english/NovelR18[madara].js
new file mode 100644
index 0000000..b322c38
--- /dev/null
+++ b/.js/plugins/english/NovelR18[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "novelr18", "sourceSite": "https://novelr18.com/", "sourceName": "NovelR18", "filters": [{ "key": "sort", "label": "Sort by :", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest Update", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "Newly Added Novels", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": "Picker" }], "options": { "path": { "novels": "novel", "novel": "manga", "chapter": "manga" }, "useNewChapterEndpoint": true, "lang": "English" } });
+exports.default = plugin;
diff --git a/.js/plugins/english/NovelTranslate[madara].js b/.js/plugins/english/NovelTranslate[madara].js
new file mode 100644
index 0000000..3abed76
--- /dev/null
+++ b/.js/plugins/english/NovelTranslate[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "novelTL", "sourceSite": "https://noveltranslate.com/", "sourceName": "NovelTranslate", "filters": [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": "Picker" }, { "key": "genres", "label": "GENRES", "values": [{ "label": "Action", "value": "action" }, { "label": "Adult", "value": "adult" }, { "label": "Adventure", "value": "adventure" }, { "label": "Bleach", "value": "bleach" }, { "label": "Chinese", "value": "chinese" }, { "label": "Comedy", "value": "comedy" }, { "label": "Conan", "value": "conan" }, { "label": "cooking", "value": "cooking" }, { "label": "Dragon Ball", "value": "dragon-ball" }, { "label": "Drama", "value": "drama" }, { "label": "Ecchi", "value": "ecchi" }, { "label": "Erciyuan", "value": "erciyuan" }, { "label": "Fairy Tail", "value": "fairy-tail" }, { "label": "Faloo", "value": "faloo" }, { "label": "Fan-Fiction", "value": "fan-fiction" }, { "label": "Fantasy", "value": "fantasy" }, { "label": "FoodWars!", "value": "foodwars" }, { "label": "Game", "value": "game" }, { "label": "Gender Bender", "value": "gender-bender" }, { "label": "Harem", "value": "harem" }, { "label": "Historical", "value": "historical" }, { "label": "Horror", "value": "horror" }, { "label": "Hunter x Hunter", "value": "hunter-x-hunter" }, { "label": "Isekai", "value": "isekai" }, { "label": "Japanese", "value": "japanese" }, { "label": "Jojo", "value": "jojo" }, { "label": "Josei", "value": "josei" }, { "label": "Korean", "value": "korean" }, { "label": "Martial Arts", "value": "martial-arts" }, { "label": "Marvel", "value": "marvel" }, { "label": "Mature", "value": "mature" }, { "label": "Mecha", "value": "mecha" }, { "label": "Military", "value": "military" }, { "label": "Mystery", "value": "mystery" }, { "label": "Naruto", "value": "naruto" }, { "label": "One piece", "value": "one-piece" }, { "label": "Pokemon", "value": "pokemon" }, { "label": "Political", "value": "political" }, { "label": "Psychological", "value": "psychological" }, { "label": "Romance", "value": "romance" }, { "label": "School Life", "value": "school-life" }, { "label": "Sci-fi", "value": "sci-fi" }, { "label": "Seinen", "value": "seinen" }, { "label": "Shoujo", "value": "shoujo" }, { "label": "Shoujo Ai", "value": "shoujo-ai" }, { "label": "Shounen", "value": "shounen" }, { "label": "Shounen Ai", "value": "shounen-ai" }, { "label": "Slice of Life", "value": "slice-of-life" }, { "label": "Smut", "value": "smut" }, { "label": "Sport", "value": "sport" }, { "label": "Sports", "value": "sports" }, { "label": "Supernatural", "value": "supernatural" }, { "label": "System", "value": "system" }, { "label": "Toriko", "value": "toriko" }, { "label": "Tragedy", "value": "tragedy" }, { "label": "Urban", "value": "urban" }, { "label": "Urban Life", "value": "urban-life" }, { "label": "Wuxia", "value": "wuxia" }, { "label": "Xianxia", "value": "xianxia" }, { "label": "Xuanhuan", "value": "xuanhuan" }, { "label": "Yaoi", "value": "yaoi" }, { "label": "Yuri", "value": "yuri" }], "inputType": "Picker" }], "options": { "path": { "novels": "all-novels", "novel": "manga", "chapter": "manga", "genres": "manga-genre" }, "lang": "English" } });
+exports.default = plugin;
diff --git a/.js/plugins/english/Novelroomnet[madara].js b/.js/plugins/english/Novelroomnet[madara].js
new file mode 100644
index 0000000..8b5455e
--- /dev/null
+++ b/.js/plugins/english/Novelroomnet[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "novelroom", "sourceSite": "https://novelroom.net/", "sourceName": "Novelroom.net", "filters": [], "options": { "path": { "novels": "manga", "novel": "manga", "chapter": "manga" }, "lang": "English" } });
+exports.default = plugin;
diff --git a/.js/plugins/english/Novelstic[madara].js b/.js/plugins/english/Novelstic[madara].js
new file mode 100644
index 0000000..2e9f9a5
--- /dev/null
+++ b/.js/plugins/english/Novelstic[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "novelstic", "sourceSite": "https://novelstic.com/", "sourceName": "Novelstic", "filters": [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": "Picker" }], "options": { "useNewChapterEndpoint": true, "lang": "English" } });
+exports.default = plugin;
diff --git a/.js/plugins/english/OnlyMTL[madara].js b/.js/plugins/english/OnlyMTL[madara].js
new file mode 100644
index 0000000..eb7513f
--- /dev/null
+++ b/.js/plugins/english/OnlyMTL[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "onlymtl", "sourceSite": "https://www.onlymtl.com/", "sourceName": "OnlyMTL", "filters": [], "options": { "useNewChapterEndpoint": true, "lang": "English" } });
+exports.default = plugin;
diff --git a/.js/plugins/english/ReadWebNovels[madara].js b/.js/plugins/english/ReadWebNovels[madara].js
new file mode 100644
index 0000000..f93ae3f
--- /dev/null
+++ b/.js/plugins/english/ReadWebNovels[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "readwebnovels", "sourceSite": "https://readwebnovels.net/", "sourceName": "ReadWebNovels", "filters": [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": "Picker" }], "options": { "lang": "English" } });
+exports.default = plugin;
diff --git a/.js/plugins/english/SleepyTranslations[madara].js b/.js/plugins/english/SleepyTranslations[madara].js
new file mode 100644
index 0000000..0f60e4e
--- /dev/null
+++ b/.js/plugins/english/SleepyTranslations[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "sleeptTLS", "sourceSite": "https://sleepytranslations.com/", "sourceName": "SleepyTranslations", "filters": [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": "Picker" }], "options": { "path": { "novels": "series", "novel": "series", "chapter": "series" }, "useNewChapterEndpoint": true, "lang": "English" } });
+exports.default = plugin;
diff --git a/.js/plugins/english/SonicMTL[madara].js b/.js/plugins/english/SonicMTL[madara].js
new file mode 100644
index 0000000..b975609
--- /dev/null
+++ b/.js/plugins/english/SonicMTL[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "sonicmtl", "sourceSite": "https://www.sonicmtl.com/", "sourceName": "SonicMTL", "filters": [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": "Picker" }, { "key": "genres", "label": "GENRES", "values": [{ "label": "Action", "value": "action" }, { "label": "Adult", "value": "adult" }, { "label": "Adventure", "value": "adventure" }, { "label": "Comedy", "value": "comedy" }, { "label": "Cooking", "value": "cooking" }, { "label": "Detective", "value": "detective" }, { "label": "Doujinshi", "value": "doujinshi" }, { "label": "Drama", "value": "drama" }, { "label": "Ecchi", "value": "ecchi" }, { "label": "Fan-Fiction", "value": "fan-fiction" }, { "label": "Fantasy", "value": "fantasy" }, { "label": "Gender Bender", "value": "gender-bender" }, { "label": "Harem", "value": "harem" }, { "label": "Historical", "value": "historical" }, { "label": "Horror", "value": "horror" }, { "label": "Josei", "value": "josei" }, { "label": "Live action", "value": "live-action" }, { "label": "Manga", "value": "manga" }, { "label": "Manhua", "value": "manhua" }, { "label": "Manhwa", "value": "manhwa" }, { "label": "Martial Arts", "value": "martial-arts" }, { "label": "Mature", "value": "mature" }, { "label": "Mecha", "value": "mecha" }, { "label": "Mystery", "value": "mystery" }, { "label": "One shot", "value": "one-shot" }, { "label": "Psychological", "value": "psychological" }, { "label": "Romance", "value": "romance" }, { "label": "School Life", "value": "school-life" }, { "label": "Sci-fi", "value": "sci-fi" }, { "label": "Seinen", "value": "seinen" }, { "label": "Shoujo", "value": "shoujo" }, { "label": "Shoujo Ai", "value": "shoujo-ai" }, { "label": "Shounen", "value": "shounen" }, { "label": "Shounen Ai", "value": "shounen-ai" }, { "label": "Slice of Life", "value": "slice-of-life" }, { "label": "Smut", "value": "smut" }, { "label": "Soft Yaoi", "value": "soft-yaoi" }, { "label": "Soft Yuri", "value": "soft-yuri" }, { "label": "Sports", "value": "sports" }, { "label": "Supernatural", "value": "supernatural" }, { "label": "Tragedy", "value": "tragedy" }, { "label": "Urban Life", "value": "urban-life" }, { "label": "Wuxia", "value": "wuxia" }, { "label": "Xianxia", "value": "xianxia" }, { "label": "Xuanhuan", "value": "xuanhuan" }, { "label": "Yaoi", "value": "yaoi" }, { "label": "Yuri", "value": "yuri" }], "inputType": "Picker" }], "options": { "useNewChapterEndpoint": true, "lang": "English" } });
+exports.default = plugin;
diff --git a/.js/plugins/english/SugarBabies[madara].js b/.js/plugins/english/SugarBabies[madara].js
new file mode 100644
index 0000000..fa1a338
--- /dev/null
+++ b/.js/plugins/english/SugarBabies[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "sugarbbscan", "sourceSite": "https://sugarbbscan.com/", "sourceName": "Sugar Babies", "filters": [], "options": { "path": { "novels": "series", "novel": "series", "chapter": "series" }, "lang": "English" } });
+exports.default = plugin;
diff --git a/.js/plugins/english/SweetEscapeTranslations[madara].js b/.js/plugins/english/SweetEscapeTranslations[madara].js
new file mode 100644
index 0000000..917ffd3
--- /dev/null
+++ b/.js/plugins/english/SweetEscapeTranslations[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "sweetEscapeTL", "sourceSite": "https://sweetescapetranslations.com/", "sourceName": "Sweet Escape Translations", "filters": [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": "Picker" }, { "key": "genres", "label": "GENRES", "values": [{ "label": "Action", "value": "action" }, { "label": "Adult", "value": "adult" }, { "label": "Comedy", "value": "comedy" }, { "label": "Drama", "value": "drama" }, { "label": "Fantasy", "value": "fantasy" }, { "label": "Gender Bender", "value": "gender-bender" }, { "label": "Mature", "value": "mature" }, { "label": "Modern", "value": "modern" }, { "label": "Mystery", "value": "mystery" }, { "label": "R-15", "value": "r-15" }, { "label": "Romance", "value": "romance" }, { "label": "Slice of Life", "value": "slice-of-life" }], "inputType": "Picker" }], "options": { "path": { "novels": "manga", "novel": "manga", "chapter": "manga", "genres": "manga-genre" }, "useNewChapterEndpoint": false, "lang": "English" } });
+exports.default = plugin;
diff --git a/.js/plugins/english/WebNovelLover[madara].js b/.js/plugins/english/WebNovelLover[madara].js
new file mode 100644
index 0000000..44fffb0
--- /dev/null
+++ b/.js/plugins/english/WebNovelLover[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "webnovelover", "sourceSite": "https://www.webnovelover.com/", "sourceName": "WebNovelLover", "filters": [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": "Picker" }, { "key": "genres", "label": "GENRES", "values": [{ "label": "Action", "value": "action" }, { "label": "Adapted into drama", "value": "adapted-into-drama" }, { "label": "Adventure", "value": "adventure" }, { "label": "Comedy", "value": "comedy" }, { "label": "Completed", "value": "completed" }, { "label": "Drama", "value": "drama" }, { "label": "English Novel", "value": "english-novel" }, { "label": "Fantasy", "value": "fantasy" }, { "label": "Gender Bender", "value": "gender-bender" }, { "label": "Harem", "value": "harem" }, { "label": "Historical", "value": "historical" }, { "label": "Horror", "value": "horror" }, { "label": "Indo Novel", "value": "indo-novel" }, { "label": "Josei", "value": "josei" }, { "label": "Martial Arts", "value": "martial-arts" }, { "label": "Mature", "value": "mature" }, { "label": "Mystery", "value": "mystery" }, { "label": "Rebirth", "value": "rebirth" }, { "label": "Reincarnation", "value": "reincarnation" }, { "label": "Romance", "value": "romance" }, { "label": "Sci-fi", "value": "sci-fi" }, { "label": "Shoujo", "value": "shoujo" }, { "label": "Shounen", "value": "shounen" }, { "label": "Slice of Life", "value": "slice-of-life" }, { "label": "Spiritual", "value": "spiritual" }, { "label": "Supernatural", "value": "supernatural" }, { "label": "Tragedy", "value": "tragedy" }, { "label": "Transmigration", "value": "transmigration" }, { "label": "University", "value": "university" }, { "label": "Wuxia", "value": "wuxia" }, { "label": "Xianxia", "value": "xianxia" }, { "label": "Xuanhuan", "value": "xuanhuan" }, { "label": "Youth", "value": "youth" }], "inputType": "Picker" }], "options": { "lang": "English" } });
+exports.default = plugin;
diff --git a/.js/plugins/english/WuxiaWorldSite[madara].js b/.js/plugins/english/WuxiaWorldSite[madara].js
new file mode 100644
index 0000000..db9b9bd
--- /dev/null
+++ b/.js/plugins/english/WuxiaWorldSite[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "wuxiaworld.site", "sourceSite": "https://wuxiaworld.site/", "sourceName": "WuxiaWorld.Site", "filters": [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": "Picker" }], "options": { "useNewChapterEndpoint": true, "lang": "English" } });
+exports.default = plugin;
diff --git a/.js/plugins/english/ZetroTranslation[madara].js b/.js/plugins/english/ZetroTranslation[madara].js
new file mode 100644
index 0000000..aa2b9cf
--- /dev/null
+++ b/.js/plugins/english/ZetroTranslation[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "zetroTL", "sourceSite": "https://zetrotranslation.com/", "sourceName": "Zetro Translation", "filters": [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": "Picker" }, { "key": "genres", "label": "GENRES", "values": [{ "label": "Action", "value": "action" }, { "label": "Adventure", "value": "adventure" }, { "label": "Comedy", "value": "comedy" }, { "label": "Dark Elf", "value": "dark-elf" }, { "label": "Drama", "value": "drama" }, { "label": "Ecchi", "value": "ecchi" }, { "label": "Fantasy", "value": "fantasy" }, { "label": "Harem", "value": "harem" }, { "label": "Horror", "value": "horror" }, { "label": "Isekai", "value": "isekai" }, { "label": "Mecha", "value": "mecha" }, { "label": "Mystery", "value": "mystery" }, { "label": "NTR", "value": "ntr" }, { "label": "Original Works", "value": "original-works" }, { "label": "Rom-Com", "value": "rom-com" }, { "label": "Romance", "value": "romance" }, { "label": "School", "value": "school" }, { "label": "Shoujo", "value": "shoujo" }, { "label": "Slice of Life", "value": "slice-of-life" }, { "label": "Villain", "value": "villain" }, { "label": "Yuri", "value": "yuri" }], "inputType": "Picker" }], "options": { "path": { "genres": "genre" }, "lang": "English" } });
+exports.default = plugin;
diff --git a/.js/plugins/english/ZinnNovel[madara].js b/.js/plugins/english/ZinnNovel[madara].js
new file mode 100644
index 0000000..9e42f1e
--- /dev/null
+++ b/.js/plugins/english/ZinnNovel[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "zinnovel", "sourceSite": "https://zinnovel.com/", "sourceName": "ZinnNovel", "filters": [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": "Picker" }, { "key": "genres", "label": "GENRES", "values": [{ "label": "Action", "value": "action" }, { "label": "Adult", "value": "adult" }, { "label": "Adventure", "value": "adventure" }, { "label": "Anime", "value": "anime" }, { "label": "Cartoon", "value": "cartoon" }, { "label": "Comedy", "value": "comedy" }, { "label": "Comic", "value": "comic" }, { "label": "Cooking", "value": "cooking" }, { "label": "Detective", "value": "detective" }, { "label": "Doujinshi", "value": "doujinshi" }, { "label": "Drama", "value": "drama" }, { "label": "Ecchi", "value": "ecchi" }, { "label": "Fantasy", "value": "fantasy" }, { "label": "Game", "value": "game" }, { "label": "Gender Bender", "value": "gender-bender" }, { "label": "Harem", "value": "harem" }, { "label": "Historical", "value": "historical" }, { "label": "Horror", "value": "horror" }, { "label": "Isekai", "value": "isekai" }, { "label": "Josei", "value": "josei" }, { "label": "Live action", "value": "live-action" }, { "label": "Lolicon", "value": "lolicon" }, { "label": "Magical Realism", "value": "magical-realism" }, { "label": "Manga", "value": "manga" }, { "label": "Manhua", "value": "manhua" }, { "label": "Manhwa", "value": "manhwa" }, { "label": "Martial Arts", "value": "martial-arts" }, { "label": "Mature", "value": "mature" }, { "label": "Mecha", "value": "mecha" }, { "label": "Mystery", "value": "mystery" }, { "label": "One shot", "value": "one-shot" }, { "label": "Psychological", "value": "psychological" }, { "label": "Reincarnation", "value": "reincarnation" }, { "label": "Romance", "value": "romance" }, { "label": "School Life", "value": "school-life" }, { "label": "Sci-fi", "value": "sci-fi" }, { "label": "Seinen", "value": "seinen" }, { "label": "Shoujo", "value": "shoujo" }, { "label": "Shoujo Ai", "value": "shoujo-ai" }, { "label": "Shounen", "value": "shounen" }, { "label": "Shounen Ai", "value": "shounen-ai" }, { "label": "Slice of Life", "value": "slice-of-life" }, { "label": "Smut", "value": "smut" }, { "label": "Soft Yaoi", "value": "soft-yaoi" }, { "label": "Soft Yuri", "value": "soft-yuri" }, { "label": "Sports", "value": "sports" }, { "label": "Supernatural", "value": "supernatural" }, { "label": "Tragedy", "value": "tragedy" }, { "label": "Video Games", "value": "video-games" }, { "label": "Webtoon", "value": "webtoon" }, { "label": "Wuxia", "value": "wuxia" }, { "label": "Xianxia", "value": "xianxia" }, { "label": "Xuanhuan", "value": "xuanhuan" }, { "label": "Yaoi", "value": "yaoi" }, { "label": "Yuri", "value": "yuri" }], "inputType": "Picker" }], "options": { "path": { "novels": "manga", "novel": "manga", "chapter": "manga", "genres": "manga-genre" }, "lang": "English" } });
+exports.default = plugin;
diff --git a/.js/plugins/english/bestlightnovel.js b/.js/plugins/english/bestlightnovel.js
new file mode 100644
index 0000000..25af43d
--- /dev/null
+++ b/.js/plugins/english/bestlightnovel.js
@@ -0,0 +1,231 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var fetch_1 = require("@libs/fetch");
+var novelStatus_1 = require("@libs/novelStatus");
+var BLN = /** @class */ (function () {
+ function BLN() {
+ this.id = "BLN.com";
+ this.name = "BestLightNovel";
+ this.icon = "src/en/bestlightnovel/icon.png";
+ this.site = "https://bestlightnovel.com/";
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ }
+ BLN.prototype.popularNovels = function (pageNo, options) {
+ return __awaiter(this, void 0, void 0, function () {
+ var url, result, _a, _b, body, loadedCheerio, novels;
+ return __generator(this, function (_c) {
+ switch (_c.label) {
+ case 0:
+ url = this.site + "novel_list?type=topview&category=all&state=all&page=1" + pageNo;
+ return [4 /*yield*/, fetch(url)];
+ case 1:
+ result = _c.sent();
+ if (!!result.ok) return [3 /*break*/, 3];
+ _b = (_a = console).error;
+ return [4 /*yield*/, result.text()];
+ case 2:
+ _b.apply(_a, [_c.sent()]);
+ // TODO: Cloudflare protection or other error
+ return [2 /*return*/, []];
+ case 3: return [4 /*yield*/, result.text()];
+ case 4:
+ body = _c.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ novels = [];
+ loadedCheerio(".update_item.list_category").each(function () {
+ var novelName = loadedCheerio(this).find("h3 > a").text();
+ var novelCover = loadedCheerio(this).find("img").attr("src");
+ var novelUrl = loadedCheerio(this).find("h3 > a").attr("href");
+ if (!novelUrl) {
+ // TODO: Handle error
+ console.error("No novel url!");
+ return;
+ }
+ var novel = {
+ name: novelName,
+ url: novelUrl,
+ cover: novelCover,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ BLN.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a, _b, _c;
+ return __awaiter(this, void 0, void 0, function () {
+ var url, result, _d, _e, body, loadedCheerio, novel, status, novelChapters;
+ return __generator(this, function (_f) {
+ switch (_f.label) {
+ case 0:
+ url = novelUrl;
+ return [4 /*yield*/, fetch(url)];
+ case 1:
+ result = _f.sent();
+ if (!!result.ok) return [3 /*break*/, 3];
+ _e = (_d = console).error;
+ return [4 /*yield*/, result.text()];
+ case 2:
+ _e.apply(_d, [_f.sent()]);
+ // TODO: Cloudflare protection
+ return [2 /*return*/, { url: url, chapters: [] }];
+ case 3: return [4 /*yield*/, result.text()];
+ case 4:
+ body = _f.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ novel = {
+ url: url,
+ name: "",
+ cover: "",
+ author: "",
+ status: novelStatus_1.NovelStatus.Unknown,
+ genres: "",
+ summary: "",
+ chapters: [],
+ };
+ novel.name = loadedCheerio(".truyen_info_right h1").text().trim();
+ novel.cover =
+ loadedCheerio(".info_image img").attr("src") || defaultCover_1.defaultCover;
+ novel.summary = (_a = loadedCheerio("#noidungm").text()) === null || _a === void 0 ? void 0 : _a.trim();
+ novel.author = (_b = loadedCheerio("#main_body > div.cotgiua > div.truyen_info_wrapper > div.truyen_info > div.entry-header > div.truyen_if_wrap > ul > li:nth-child(2) > a")
+ .text()) === null || _b === void 0 ? void 0 : _b.trim();
+ status = (_c = loadedCheerio("#main_body > div.cotgiua > div.truyen_info_wrapper > div.truyen_info > div.entry-header > div.truyen_if_wrap > ul > li:nth-child(4) > a")
+ .text()) === null || _c === void 0 ? void 0 : _c.trim();
+ novel.status =
+ status === "ONGOING"
+ ? novelStatus_1.NovelStatus.Ongoing
+ : status === "COMPLETED"
+ ? novelStatus_1.NovelStatus.Completed
+ : novelStatus_1.NovelStatus.Unknown;
+ novelChapters = [];
+ loadedCheerio(".chapter-list div.row").each(function () {
+ var chapterName = loadedCheerio(this).find("a").text().trim();
+ var releaseDate = loadedCheerio(this)
+ .find("span:nth-child(2)")
+ .text()
+ .trim();
+ var chapterUrl = loadedCheerio(this).find("a").attr("href");
+ if (!chapterUrl) {
+ // TODO: Handle error
+ console.error("No chapter url!");
+ return;
+ }
+ novelChapters.push({
+ name: chapterName,
+ releaseTime: releaseDate,
+ url: chapterUrl,
+ });
+ });
+ novel.chapters = novelChapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ BLN.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var url, result, body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ url = chapterUrl;
+ return [4 /*yield*/, fetch(url)];
+ case 1:
+ result = _a.sent();
+ return [4 /*yield*/, result.text()];
+ case 2:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio("#vung_doc").html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ BLN.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var url, result, body, loadedCheerio, novels;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ url = "".concat(this.site, "search_novels/").concat(searchTerm);
+ return [4 /*yield*/, fetch(url)];
+ case 1:
+ result = _a.sent();
+ return [4 /*yield*/, result.text()];
+ case 2:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ novels = [];
+ loadedCheerio(".update_item.list_category").each(function () {
+ var novelName = loadedCheerio(this).find("h3 > a").text();
+ var novelCover = loadedCheerio(this).find("img").attr("src");
+ var novelUrl = loadedCheerio(this).find("h3 > a").attr("href");
+ if (!novelUrl) {
+ // TODO: Handle error
+ console.error("No novel url!");
+ return;
+ }
+ var novel = { name: novelName, cover: novelCover, url: novelUrl };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ BLN.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url)];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return BLN;
+}());
+exports.default = new BLN();
diff --git a/.js/plugins/english/nobleMTL.js b/.js/plugins/english/nobleMTL.js
new file mode 100644
index 0000000..db22d5b
--- /dev/null
+++ b/.js/plugins/english/nobleMTL.js
@@ -0,0 +1,377 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var cheerio_1 = require("cheerio");
+var fetch_1 = require("@libs/fetch");
+var filterInputs_1 = require("@libs/filterInputs");
+var NobleMTL = /** @class */ (function () {
+ function NobleMTL() {
+ this.id = "noblemtl";
+ this.name = "NobleMTL";
+ this.icon = "src/en/noblemtl/icon.png";
+ this.site = "https://noblemtl.com/";
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.filters = [
+ {
+ key: "order",
+ label: "Sort By",
+ values: [
+ { label: "Default", value: "" },
+ { label: "A-Z", value: "title" },
+ { label: "Z-A", value: "titlereverse" },
+ { label: "Latest Update", value: "update" },
+ { label: "Latest Added", value: "latest" },
+ { label: "Popular", value: "popular" },
+ ],
+ inputType: filterInputs_1.FilterInputs.Picker,
+ },
+ {
+ key: "status",
+ label: "Status",
+ values: [
+ { label: "All", value: "" },
+ { label: "Ongoing", value: "ongoing" },
+ { label: "Hiatus", value: "hiatus" },
+ { label: "Completed", value: "completed" },
+ ],
+ inputType: filterInputs_1.FilterInputs.Picker,
+ },
+ {
+ key: "type",
+ label: "Type",
+ values: [
+ { label: "Chinese novel", value: "chinese-novel" },
+ { label: "habyeol", value: "habyeol" },
+ { label: "korean novel", value: "korean-novel" },
+ { label: "Web Novel", value: "web-novel" },
+ { label: "삼심", value: "%ec%82%bc%ec%8b%ac" },
+ { label: "호곡", value: "%ed%98%b8%ea%b3%a1" },
+ ],
+ inputType: filterInputs_1.FilterInputs.Checkbox,
+ },
+ {
+ key: "genres",
+ label: "Genres",
+ values: [
+ { label: "A.I", value: "a.i" },
+ { label: "Academy", value: "academy" },
+ { label: "Action", value: "action" },
+ { label: "Adult", value: "adult" },
+ { label: "Adventure", value: "adventure" },
+ { label: "Alternative History", value: "alternative-history" },
+ { label: "Another World", value: "another-world" },
+ { label: "Apocalypse", value: "apocalypse" },
+ { label: "Bromance", value: "bromance" },
+ { label: "Comedy", value: "comedy" },
+ { label: "Dark fantasy", value: "dark-fantasy" },
+ { label: "Demons", value: "demons" },
+ { label: "Drama", value: "drama" },
+ { label: "Dystopia", value: "dystopia" },
+ { label: "Ecchi", value: "ecchi" },
+ { label: "Entertainment", value: "entertainment" },
+ { label: "Exhaustion", value: "exhaustion" },
+ { label: "Fanfiction", value: "fanfiction" },
+ { label: "fantasy", value: "fantasy" },
+ { label: "finance", value: "finance" },
+ { label: "Full color", value: "full-color" },
+ { label: "Game", value: "game" },
+ { label: "Gender Bender", value: "gender-bender" },
+ { label: "Genius", value: "genius" },
+ { label: "Harem", value: "harem" },
+ { label: "Hero", value: "hero" },
+ { label: "Historical", value: "historical" },
+ { label: "Hunter", value: "hunter" },
+ { label: "korean novel", value: "korean-novel" },
+ { label: "Light Novel", value: "light-novel" },
+ {
+ label: "List Adventure Manga Genres",
+ value: "list-adventure-manga-genres",
+ },
+ { label: "Long Strip", value: "long-strip" },
+ { label: "Love comedy", value: "love-comedy" },
+ { label: "magic", value: "magic" },
+ { label: "Manhua", value: "manhua" },
+ { label: "Martial Arts", value: "martial-arts" },
+ { label: "Mature", value: "mature" },
+ { label: "Medieval", value: "medieval" },
+ { label: "Misunderstanding", value: "misunderstanding" },
+ { label: "Modern", value: "modern" },
+ { label: "modern fantasy", value: "modern-fantasy" },
+ { label: "music", value: "music" },
+ { label: "Mystery", value: "mystery" },
+ { label: "Necromancy", value: "necromancy" },
+ { label: "No Romance", value: "no-romance" },
+ { label: "NTL", value: "ntl" },
+ { label: "o", value: "o" },
+ { label: "Obsession", value: "obsession" },
+ { label: "Politics", value: "politics" },
+ { label: "Possession", value: "possession" },
+ { label: "Programming", value: "programming" },
+ { label: "Psychological", value: "psychological" },
+ { label: "Pure Love", value: "pure-love" },
+ { label: "Redemption", value: "redemption" },
+ { label: "Regression", value: "regression" },
+ { label: "Regret", value: "regret" },
+ { label: "Reincarnation", value: "reincarnation" },
+ { label: "Revenge", value: "revenge" },
+ { label: "Romance", value: "romance" },
+ { label: "Romance Fanrasy", value: "romance-fanrasy" },
+ { label: "Salvation", value: "salvation" },
+ { label: "School Life", value: "school-life" },
+ { label: "Sci-fi", value: "sci-fi" },
+ { label: "Science fiction", value: "science-fiction" },
+ { label: "Seinen", value: "seinen" },
+ { label: "Shounen", value: "shounen" },
+ { label: "Slice of Life", value: "slice-of-life" },
+ { label: "Soft yandere", value: "soft-yandere" },
+ { label: "Sports", value: "sports" },
+ { label: "Supernatural", value: "supernatural" },
+ { label: "Survival", value: "survival" },
+ { label: "system", value: "system" },
+ { label: "Time limit", value: "time-limit" },
+ { label: "Tragedy", value: "tragedy" },
+ { label: "Transmigration", value: "transmigration" },
+ { label: "TS", value: "ts" },
+ { label: "Tsundere", value: "tsundere" },
+ { label: "Unique", value: "unique" },
+ { label: "Wholesome", value: "wholesome" },
+ { label: "Wuxia", value: "wuxia" },
+ { label: "Xuanhuan", value: "xuanhuan" },
+ { label: "Yandere", value: "yandere" },
+ { label: "Yuri", value: "yuri" },
+ ],
+ inputType: filterInputs_1.FilterInputs.Checkbox,
+ },
+ ];
+ }
+ NobleMTL.prototype.popularNovels = function (pageNo, _a) {
+ var filters = _a.filters;
+ return __awaiter(this, void 0, void 0, function () {
+ var link, headers, body, loadedCheerio, novels;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ link = "".concat(this.site, "series/?page=").concat(pageNo);
+ if (filters) {
+ if (Array.isArray(filters.genres) && filters.genres.length) {
+ link += filters.genres.map(function (i) { return "&genre[]=".concat(i); }).join("");
+ }
+ if (Array.isArray(filters.type) && filters.type.length)
+ link += filters.type.map(function (i) { return "&lang[]=".concat(i); }).join("");
+ }
+ link += "&status=" + ((filters === null || filters === void 0 ? void 0 : filters.status) ? filters.status : "");
+ link += "&order=" + ((filters === null || filters === void 0 ? void 0 : filters.order) ? filters.order : "popular");
+ headers = new Headers();
+ if (this.cookieString) {
+ headers.append("cookie", this.cookieString);
+ }
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(link, { headers: headers }).then(function (result) {
+ return result.text();
+ })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ novels = [];
+ loadedCheerio("article.bs").each(function () {
+ var novelName = loadedCheerio(this).find(".ntitle").text().trim();
+ var image = loadedCheerio(this).find("img");
+ var novelCover = image.attr("data-src") || image.attr("src");
+ var novelUrl = loadedCheerio(this).find("a").attr("href");
+ if (!novelUrl)
+ return;
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ ;
+ NobleMTL.prototype.parseNovelAndChapters = function (novelUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var url, headers, result, body, loadedCheerio, novel, chapter;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ url = novelUrl;
+ headers = new Headers();
+ if (this.cookieString) {
+ headers.append("cookie", this.cookieString);
+ }
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url, { headers: headers })];
+ case 1:
+ result = _a.sent();
+ return [4 /*yield*/, result.text()];
+ case 2:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ novel = {
+ url: url,
+ chapters: [],
+ };
+ novel.name = loadedCheerio(".entry-title").text();
+ novel.cover =
+ loadedCheerio("img.wp-post-image").attr("data-src") ||
+ loadedCheerio("img.wp-post-image").attr("src");
+ loadedCheerio("div.spe > span").each(function () {
+ var detailName = loadedCheerio(this).find("b").text().trim();
+ var detail = loadedCheerio(this).find('b').remove().end().text().trim();
+ switch (detailName) {
+ case "Author:":
+ novel.author = detail;
+ break;
+ case "Status:":
+ novel.status = detail;
+ break;
+ }
+ });
+ novel.genres = loadedCheerio(".genxed")
+ .text()
+ .trim()
+ .replace(/\s/g, ",");
+ loadedCheerio('div[itemprop="description"] h3,p.a,strong').remove();
+ novel.summary = loadedCheerio('div[itemprop="description"]')
+ .find("br")
+ .replaceWith("\n")
+ .end()
+ .text();
+ chapter = [];
+ loadedCheerio(".eplister")
+ .find("li")
+ .each(function () {
+ var chapterName = loadedCheerio(this).find(".epl-num").text() +
+ " - " +
+ loadedCheerio(this).find(".epl-title").text();
+ var releaseDate = loadedCheerio(this)
+ .find(".epl-date")
+ .text()
+ .trim();
+ var chapterUrl = loadedCheerio(this).find("a").attr("href");
+ if (!chapterUrl)
+ return;
+ chapter.push({
+ name: chapterName,
+ releaseTime: releaseDate,
+ url: chapterUrl,
+ });
+ });
+ novel.chapters = chapter.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ NobleMTL.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var headers, result, body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ headers = new Headers();
+ if (this.cookieString) {
+ headers.append("cookie", this.cookieString);
+ }
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl, { headers: headers })];
+ case 1:
+ result = _a.sent();
+ return [4 /*yield*/, result.text()];
+ case 2:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio(".epcontent").html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ NobleMTL.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var url, headers, result, body, loadedCheerio, novels;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ url = "".concat(this.site, "?s=").concat(searchTerm);
+ headers = new Headers();
+ if (this.cookieString) {
+ headers.append("cookie", this.cookieString);
+ }
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url, { headers: headers })];
+ case 1:
+ result = _a.sent();
+ return [4 /*yield*/, result.text()];
+ case 2:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ novels = [];
+ loadedCheerio("article.bs").each(function () {
+ var novelName = loadedCheerio(this).find(".ntitle").text().trim();
+ var novelCover = loadedCheerio(this).find("img").attr("src");
+ var novelUrl = loadedCheerio(this).find("a").attr("href");
+ if (!novelUrl)
+ return;
+ novels.push({
+ name: novelName,
+ url: novelUrl,
+ cover: novelCover,
+ });
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ NobleMTL.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url)];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return NobleMTL;
+}());
+exports.default = new NobleMTL();
diff --git a/.js/plugins/english/pandaMTL.js b/.js/plugins/english/pandaMTL.js
new file mode 100644
index 0000000..50d8b18
--- /dev/null
+++ b/.js/plugins/english/pandaMTL.js
@@ -0,0 +1,304 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var cheerio_1 = require("cheerio");
+var fetch_1 = require("@libs/fetch");
+var filterInputs_1 = require("@libs/filterInputs");
+var PandaMTL = /** @class */ (function () {
+ function PandaMTL() {
+ this.id = "pandamtl";
+ this.name = "PandaMTL";
+ this.icon = "src/en/wordpress/icon.png";
+ this.site = "https://pandamtl.com/";
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.filters = [
+ {
+ key: "order",
+ label: "Sort By",
+ values: [
+ { label: "Default", value: "" },
+ { label: "A-Z", value: "title" },
+ { label: "Z-A", value: "titlereverse" },
+ { label: "Latest Update", value: "update" },
+ { label: "Latest Added", value: "latest" },
+ { label: "Popular", value: "popular" },
+ ],
+ inputType: filterInputs_1.FilterInputs.Picker,
+ },
+ {
+ key: "status",
+ label: "Status",
+ values: [
+ { label: "All", value: "" },
+ { label: "Ongoing", value: "ongoing" },
+ { label: "Hiatus", value: "hiatus" },
+ { label: "Completed", value: "completed" },
+ ],
+ inputType: filterInputs_1.FilterInputs.Picker,
+ },
+ {
+ key: "type",
+ label: "Type",
+ values: [
+ { label: "Light Novel (KR)", value: "light-novel-kr" },
+ { label: "Web Novel", value: "web-novel" },
+ ],
+ inputType: filterInputs_1.FilterInputs.Checkbox,
+ },
+ {
+ key: "genres",
+ label: "Genres",
+ values: [
+ { label: "Action", value: "action" },
+ { label: "Adult", value: "adult" },
+ { label: "Adventure", value: "adventure" },
+ { label: "Comedy", value: "comedy" },
+ { label: "Ecchi", value: "ecchi" },
+ { label: "Fantasy", value: "fantasy" },
+ { label: "Harem", value: "harem" },
+ { label: "Josei", value: "josei" },
+ { label: "Martial Arts", value: "martial-arts" },
+ { label: "Mature", value: "mature" },
+ { label: "Romance", value: "romance" },
+ { label: "School Life", value: "school-life" },
+ { label: "Sci-fi", value: "sci-fi" },
+ { label: "Seinen", value: "seinen" },
+ { label: "Slice of Life", value: "slice-of-life" },
+ { label: "Smut", value: "smut" },
+ { label: "Sports", value: "sports" },
+ { label: "Supernatural", value: "supernatural" },
+ { label: "Tragedy", value: "tragedy" },
+ ],
+ inputType: filterInputs_1.FilterInputs.Checkbox,
+ },
+ ];
+ }
+ PandaMTL.prototype.popularNovels = function (pageNo, _a) {
+ var filters = _a.filters;
+ return __awaiter(this, void 0, void 0, function () {
+ var link, headers, body, loadedCheerio, novels;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ link = "".concat(this.site, "series/?page=").concat(pageNo);
+ if (filters) {
+ if (Array.isArray(filters.genres) && filters.genres.length) {
+ link += filters.genres.map(function (i) { return "&genre[]=".concat(i); }).join("");
+ }
+ if (Array.isArray(filters.type) && filters.type.length)
+ link += filters.type.map(function (i) { return "&lang[]=".concat(i); }).join("");
+ }
+ link += "&status=" + ((filters === null || filters === void 0 ? void 0 : filters.status) ? filters.status : "");
+ link += "&order=" + ((filters === null || filters === void 0 ? void 0 : filters.order) ? filters.order : "popular");
+ headers = new Headers();
+ if (this.cookieString) {
+ headers.append("cookie", this.cookieString);
+ }
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(link, { headers: headers }).then(function (result) {
+ return result.text();
+ })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ novels = [];
+ loadedCheerio("article.maindet").each(function () {
+ var novelName = loadedCheerio(this).find("h2").text();
+ var image = loadedCheerio(this).find("img");
+ var novelCover = image.attr("data-src") || image.attr("src");
+ var novelUrl = loadedCheerio(this).find("h2 a").attr("href");
+ if (!novelUrl)
+ return;
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ PandaMTL.prototype.parseNovelAndChapters = function (novelUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var url, headers, result, body, loadedCheerio, novel, chapter;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ url = novelUrl;
+ headers = new Headers();
+ if (this.cookieString) {
+ headers.append("cookie", this.cookieString);
+ }
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url, { headers: headers })];
+ case 1:
+ result = _a.sent();
+ return [4 /*yield*/, result.text()];
+ case 2:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ novel = {
+ url: url,
+ chapters: [],
+ };
+ novel.name = loadedCheerio("h1.entry-title").text();
+ novel.cover =
+ loadedCheerio("img.wp-post-image").attr("data-src") ||
+ loadedCheerio("img.wp-post-image").attr("src");
+ loadedCheerio(".serl:nth-child(3) > span").each(function () {
+ var detailName = loadedCheerio(this).text().trim();
+ var detail = loadedCheerio(this).next().text().trim();
+ switch (detailName) {
+ case "Author":
+ novel.author = detail;
+ break;
+ }
+ });
+ novel.status = loadedCheerio(".sertostat > span").attr("class");
+ novel.genres = loadedCheerio(".sertogenre")
+ .children("a")
+ .map(function (i, el) { return loadedCheerio(el).text(); })
+ .toArray()
+ .join(",");
+ novel.summary = loadedCheerio(".sersys")
+ .find("br")
+ .replaceWith("\n")
+ .end()
+ .text();
+ chapter = [];
+ loadedCheerio(".eplister")
+ .find("li")
+ .each(function () {
+ var chapterName = loadedCheerio(this).find(".epl-num").text() +
+ " - " +
+ loadedCheerio(this).find(".epl-title").text();
+ var releaseDate = loadedCheerio(this)
+ .find(".epl-date")
+ .text()
+ .trim();
+ var chapterUrl = loadedCheerio(this).find("a").attr("href");
+ if (!chapterUrl)
+ return;
+ chapter.push({
+ name: chapterName,
+ releaseTime: releaseDate,
+ url: chapterUrl,
+ });
+ });
+ novel.chapters = chapter.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ PandaMTL.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var headers, result, body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ headers = new Headers();
+ if (this.cookieString) {
+ headers.append("cookie", this.cookieString);
+ }
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl, { headers: headers })];
+ case 1:
+ result = _a.sent();
+ return [4 /*yield*/, result.text()];
+ case 2:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio(".epcontent").html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ PandaMTL.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var url, headers, result, body, loadedCheerio, novels;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ url = "".concat(this.site, "?s=").concat(searchTerm);
+ headers = new Headers();
+ if (this.cookieString) {
+ headers.append("cookie", this.cookieString);
+ }
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url, { headers: headers })];
+ case 1:
+ result = _a.sent();
+ return [4 /*yield*/, result.text()];
+ case 2:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ novels = [];
+ loadedCheerio("article.maindet").each(function () {
+ var novelName = loadedCheerio(this).find("h2").text();
+ var image = loadedCheerio(this).find("img");
+ var novelCover = image.attr("data-src") || image.attr("src");
+ var novelUrl = loadedCheerio(this).find("h2 a").attr("href");
+ if (!novelUrl)
+ return;
+ novels.push({
+ name: novelName,
+ url: novelUrl,
+ cover: novelCover,
+ });
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ PandaMTL.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url)];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return PandaMTL;
+}());
+exports.default = new PandaMTL();
diff --git a/.js/plugins/indonesian/MeioNovel[madara].js b/.js/plugins/indonesian/MeioNovel[madara].js
new file mode 100644
index 0000000..00bb961
--- /dev/null
+++ b/.js/plugins/indonesian/MeioNovel[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "meionovel", "sourceSite": "https://meionovel.id/", "sourceName": "MeioNovel", "filters": [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": "Picker" }, { "key": "genres", "label": "GENRES", "values": [{ "label": "Action", "value": "action" }, { "label": "Adventure", "value": "adventure" }, { "label": "Comedy", "value": "comedy" }, { "label": "Cooking", "value": "cooking" }, { "label": "Drama", "value": "drama" }, { "label": "Ecchi", "value": "ecchi" }, { "label": "Fanfiction", "value": "fanfiction" }, { "label": "Fantasy", "value": "fantasy" }, { "label": "Gender Bender", "value": "gender-bender" }, { "label": "Harem", "value": "harem" }, { "label": "Historical", "value": "historical" }, { "label": "Horror", "value": "horror" }, { "label": "Isekai", "value": "isekai" }, { "label": "Josei", "value": "josei" }, { "label": "Magic", "value": "magic" }, { "label": "Martial Arts", "value": "martial-arts" }, { "label": "Mature", "value": "mature" }, { "label": "Mecha", "value": "mecha" }, { "label": "Mystery", "value": "mystery" }, { "label": "One shot", "value": "one-shot" }, { "label": "Psychological", "value": "psychological" }, { "label": "Reverse Harem", "value": "reverse-harem" }, { "label": "Romance", "value": "romance" }, { "label": "School Life", "value": "school-life" }, { "label": "Sci-fi", "value": "sci-fi" }, { "label": "Seinen", "value": "seinen" }, { "label": "Shoujo", "value": "shoujo" }, { "label": "Shoujo Ai", "value": "shoujo-ai" }, { "label": "Shounen", "value": "shounen" }, { "label": "Shounen Ai", "value": "shounen-ai" }, { "label": "Slice of Life", "value": "slice-of-life" }, { "label": "Smut", "value": "smut" }, { "label": "Sports", "value": "sports" }, { "label": "Supernatural", "value": "supernatural" }, { "label": "Tragedy", "value": "tragedy" }, { "label": "Virtual Reality", "value": "virtual-reality" }, { "label": "Wuxia", "value": "wuxia" }, { "label": "Xianxia", "value": "xianxia" }, { "label": "Xuanhuan", "value": "xuanhuan" }, { "label": "Yuri", "value": "yuri" }], "inputType": "Picker" }], "options": { "useNewChapterEndpoint": true, "lang": "Indonesian" } });
+exports.default = plugin;
diff --git a/.js/plugins/indonesian/MoreNovel[madara].js b/.js/plugins/indonesian/MoreNovel[madara].js
new file mode 100644
index 0000000..ce9c9ee
--- /dev/null
+++ b/.js/plugins/indonesian/MoreNovel[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "morenovel", "sourceSite": "https://morenovel.net/", "sourceName": "MoreNovel", "filters": [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": "Picker" }, { "key": "genres", "label": "GENRES", "values": [{ "label": "Action", "value": "action" }, { "label": "Adventure", "value": "adventure" }, { "label": "Comedy", "value": "comedy" }, { "label": "Drama", "value": "drama" }, { "label": "Ecchi", "value": "ecchi" }, { "label": "Fantasy", "value": "fantasy" }, { "label": "Gender Bender", "value": "gender-bender" }, { "label": "Harem", "value": "harem" }, { "label": "Historical", "value": "historical" }, { "label": "Horror", "value": "horror" }, { "label": "Josei", "value": "josei" }, { "label": "Martial Arts", "value": "martial-arts" }, { "label": "Mature", "value": "mature" }, { "label": "Mecha", "value": "mecha" }, { "label": "Mystery", "value": "mystery" }, { "label": "Psychological", "value": "psychological" }, { "label": "Romance", "value": "romance" }, { "label": "School Life", "value": "school-life" }, { "label": "Sci-fi", "value": "sci-fi" }, { "label": "Seinen", "value": "seinen" }, { "label": "Shoujo", "value": "shoujo" }, { "label": "Shoujo Ai", "value": "shoujo-ai" }, { "label": "Shounen", "value": "shounen" }, { "label": "Shounen Ai", "value": "shounen-ai" }, { "label": "Slice of Life", "value": "slice-of-life" }, { "label": "Sports", "value": "sports" }, { "label": "Supernatural", "value": "supernatural" }, { "label": "Tragedy", "value": "tragedy" }, { "label": "Wuxia", "value": "wuxia" }, { "label": "Xianxia", "value": "xianxia" }, { "label": "Xuanhuan", "value": "xuanhuan" }, { "label": "Yaoi", "value": "yaoi" }, { "label": "Yuri", "value": "yuri" }], "inputType": "Picker" }], "options": { "useNewChapterEndpoint": true, "lang": "Indonesian" } });
+exports.default = plugin;
diff --git a/.js/plugins/indonesian/WBNovel[madara].js b/.js/plugins/indonesian/WBNovel[madara].js
new file mode 100644
index 0000000..405c815
--- /dev/null
+++ b/.js/plugins/indonesian/WBNovel[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "wbnovel", "sourceSite": "https://wbnovel.com/", "sourceName": "WBNovel", "filters": [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": "Picker" }, { "key": "genres", "label": "GENRES", "values": [{ "label": "Action", "value": "action" }, { "label": "Adventure", "value": "adventure" }, { "label": "Alchemy", "value": "alchemy" }, { "label": "Comedy", "value": "comedy" }, { "label": "Crafting", "value": "crafting" }, { "label": "Cultivation", "value": "cultivation" }, { "label": "Drama", "value": "drama" }, { "label": "Dungeon Crawling", "value": "dungeon-crawling" }, { "label": "Eci", "value": "eci" }, { "label": "Fantasy", "value": "fantasy" }, { "label": "Game", "value": "game" }, { "label": "Harem", "value": "harem" }, { "label": "Horror", "value": "horror" }, { "label": "Josei", "value": "josei" }, { "label": "Kingdom Building", "value": "kingdom-building" }, { "label": "Martial Arts", "value": "martial-arts" }, { "label": "Mature", "value": "mature" }, { "label": "Mecha", "value": "mecha" }, { "label": "Modern Setting", "value": "modern-setting" }, { "label": "Mystery", "value": "mystery" }, { "label": "Pets", "value": "pets" }, { "label": "Psychological", "value": "psychological" }, { "label": "Reincarnator", "value": "reincarnator" }, { "label": "Romance", "value": "romance" }, { "label": "School Life", "value": "school-life" }, { "label": "Sci-fi", "value": "sci-fi" }, { "label": "Seinen", "value": "seinen" }, { "label": "Shounen", "value": "shounen" }, { "label": "Slice of Life", "value": "slice-of-life" }, { "label": "Sports", "value": "sports" }, { "label": "Supernatural", "value": "supernatural" }, { "label": "Tragedy", "value": "tragedy" }, { "label": "Transmigration", "value": "transmigration" }, { "label": "Virtual Reality", "value": "virtual-reality" }, { "label": "Wuxia", "value": "wuxia" }, { "label": "Xianxia", "value": "xianxia" }, { "label": "Xuanhuan", "value": "xuanhuan" }], "inputType": "Picker" }], "options": { "lang": "Indonesian" } });
+exports.default = plugin;
diff --git a/.js/plugins/portuguese/lightnovelbrasil.js b/.js/plugins/portuguese/lightnovelbrasil.js
new file mode 100644
index 0000000..33c26e5
--- /dev/null
+++ b/.js/plugins/portuguese/lightnovelbrasil.js
@@ -0,0 +1,378 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var cheerio_1 = require("cheerio");
+var fetch_1 = require("@libs/fetch");
+var filterInputs_1 = require("@libs/filterInputs");
+var LightNovelBrasil = /** @class */ (function () {
+ function LightNovelBrasil() {
+ this.id = "lightnovelbrasil";
+ this.name = "Light Novel Brasil";
+ this.icon = "multisrc/wpmangastream/icons/lightnovelbrasil.png";
+ this.site = "https://lightnovelbrasil.com/";
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.filters = [
+ {
+ key: "order",
+ label: "Sort By",
+ values: [
+ { label: "Default", value: "" },
+ { label: "A-Z", value: "title" },
+ { label: "Z-A", value: "titlereverse" },
+ { label: "Latest Update", value: "update" },
+ { label: "Latest Added", value: "latest" },
+ { label: "Popular", value: "popular" },
+ ],
+ inputType: filterInputs_1.FilterInputs.Picker,
+ },
+ {
+ key: "status",
+ label: "Status",
+ values: [
+ { label: "All", value: "" },
+ { label: "Ongoing", value: "ongoing" },
+ { label: "Hiatus", value: "hiatus" },
+ { label: "Completed", value: "completed" },
+ ],
+ inputType: filterInputs_1.FilterInputs.Picker,
+ },
+ {
+ key: "type",
+ label: "Type",
+ values: [
+ { label: "Chinese novel", value: "chinese-novel" },
+ { label: "habyeol", value: "habyeol" },
+ { label: "korean novel", value: "korean-novel" },
+ { label: "Web Novel", value: "web-novel" },
+ { label: "삼심", value: "%ec%82%bc%ec%8b%ac" },
+ { label: "호곡", value: "%ed%98%b8%ea%b3%a1" },
+ ],
+ inputType: filterInputs_1.FilterInputs.Checkbox,
+ },
+ {
+ key: "genres",
+ label: "Genres",
+ values: [
+ { label: "A.I", value: "a.i" },
+ { label: "Academy", value: "academy" },
+ { label: "Action", value: "action" },
+ { label: "Adult", value: "adult" },
+ { label: "Adventure", value: "adventure" },
+ { label: "Alternative History", value: "alternative-history" },
+ { label: "Another World", value: "another-world" },
+ { label: "Apocalypse", value: "apocalypse" },
+ { label: "Bromance", value: "bromance" },
+ { label: "Comedy", value: "comedy" },
+ { label: "Dark fantasy", value: "dark-fantasy" },
+ { label: "Demons", value: "demons" },
+ { label: "Drama", value: "drama" },
+ { label: "Dystopia", value: "dystopia" },
+ { label: "Ecchi", value: "ecchi" },
+ { label: "Entertainment", value: "entertainment" },
+ { label: "Exhaustion", value: "exhaustion" },
+ { label: "Fanfiction", value: "fanfiction" },
+ { label: "fantasy", value: "fantasy" },
+ { label: "finance", value: "finance" },
+ { label: "Full color", value: "full-color" },
+ { label: "Game", value: "game" },
+ { label: "Gender Bender", value: "gender-bender" },
+ { label: "Genius", value: "genius" },
+ { label: "Harem", value: "harem" },
+ { label: "Hero", value: "hero" },
+ { label: "Historical", value: "historical" },
+ { label: "Hunter", value: "hunter" },
+ { label: "korean novel", value: "korean-novel" },
+ { label: "Light Novel", value: "light-novel" },
+ {
+ label: "List Adventure Manga Genres",
+ value: "list-adventure-manga-genres",
+ },
+ { label: "Long Strip", value: "long-strip" },
+ { label: "Love comedy", value: "love-comedy" },
+ { label: "magic", value: "magic" },
+ { label: "Manhua", value: "manhua" },
+ { label: "Martial Arts", value: "martial-arts" },
+ { label: "Mature", value: "mature" },
+ { label: "Medieval", value: "medieval" },
+ { label: "Misunderstanding", value: "misunderstanding" },
+ { label: "Modern", value: "modern" },
+ { label: "modern fantasy", value: "modern-fantasy" },
+ { label: "music", value: "music" },
+ { label: "Mystery", value: "mystery" },
+ { label: "Necromancy", value: "necromancy" },
+ { label: "No Romance", value: "no-romance" },
+ { label: "NTL", value: "ntl" },
+ { label: "o", value: "o" },
+ { label: "Obsession", value: "obsession" },
+ { label: "Politics", value: "politics" },
+ { label: "Possession", value: "possession" },
+ { label: "Programming", value: "programming" },
+ { label: "Psychological", value: "psychological" },
+ { label: "Pure Love", value: "pure-love" },
+ { label: "Redemption", value: "redemption" },
+ { label: "Regression", value: "regression" },
+ { label: "Regret", value: "regret" },
+ { label: "Reincarnation", value: "reincarnation" },
+ { label: "Revenge", value: "revenge" },
+ { label: "Romance", value: "romance" },
+ { label: "Romance Fanrasy", value: "romance-fanrasy" },
+ { label: "Salvation", value: "salvation" },
+ { label: "School Life", value: "school-life" },
+ { label: "Sci-fi", value: "sci-fi" },
+ { label: "Science fiction", value: "science-fiction" },
+ { label: "Seinen", value: "seinen" },
+ { label: "Shounen", value: "shounen" },
+ { label: "Slice of Life", value: "slice-of-life" },
+ { label: "Soft yandere", value: "soft-yandere" },
+ { label: "Sports", value: "sports" },
+ { label: "Supernatural", value: "supernatural" },
+ { label: "Survival", value: "survival" },
+ { label: "system", value: "system" },
+ { label: "Time limit", value: "time-limit" },
+ { label: "Tragedy", value: "tragedy" },
+ { label: "Transmigration", value: "transmigration" },
+ { label: "TS", value: "ts" },
+ { label: "Tsundere", value: "tsundere" },
+ { label: "Unique", value: "unique" },
+ { label: "Wholesome", value: "wholesome" },
+ { label: "Wuxia", value: "wuxia" },
+ { label: "Xuanhuan", value: "xuanhuan" },
+ { label: "Yandere", value: "yandere" },
+ { label: "Yuri", value: "yuri" },
+ ],
+ inputType: filterInputs_1.FilterInputs.Checkbox,
+ },
+ ];
+ }
+ LightNovelBrasil.prototype.popularNovels = function (pageNo, _a) {
+ var filters = _a.filters;
+ return __awaiter(this, void 0, void 0, function () {
+ var link, headers, body, loadedCheerio, novels;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ link = "".concat(this.site, "series/?page=").concat(pageNo);
+ if (filters) {
+ if (Array.isArray(filters.genres) && filters.genres.length) {
+ link += filters.genres.map(function (i) { return "&genre[]=".concat(i); }).join("");
+ }
+ if (Array.isArray(filters.type) && filters.type.length)
+ link += filters.type.map(function (i) { return "&lang[]=".concat(i); }).join("");
+ }
+ link += "&status=" + ((filters === null || filters === void 0 ? void 0 : filters.status) ? filters.status : "");
+ link += "&order=" + ((filters === null || filters === void 0 ? void 0 : filters.order) ? filters.order : "popular");
+ headers = new Headers();
+ if (this.cookieString) {
+ headers.append("cookie", this.cookieString);
+ }
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(link, { headers: headers }).then(function (result) {
+ return result.text();
+ })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ novels = [];
+ loadedCheerio("article.bs").each(function () {
+ var novelName = loadedCheerio(this).find(".ntitle").text().trim();
+ var image = loadedCheerio(this).find("img");
+ var novelCover = image.attr("data-src") || image.attr("src");
+ var novelUrl = loadedCheerio(this).find("a").attr("href");
+ if (!novelUrl)
+ return;
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ ;
+ LightNovelBrasil.prototype.parseNovelAndChapters = function (novelUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var url, headers, result, body, loadedCheerio, novel, chapter;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ url = novelUrl;
+ headers = new Headers();
+ if (this.cookieString) {
+ headers.append("cookie", this.cookieString);
+ }
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url, { headers: headers })];
+ case 1:
+ result = _a.sent();
+ return [4 /*yield*/, result.text()];
+ case 2:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ novel = {
+ url: url,
+ chapters: [],
+ };
+ novel.name = loadedCheerio(".entry-title").text();
+ novel.cover =
+ loadedCheerio("img.wp-post-image").attr("data-src") ||
+ loadedCheerio("img.wp-post-image").attr("src");
+ loadedCheerio("div.spe > span").each(function () {
+ var detailName = loadedCheerio(this).find("b").text().trim();
+ var detail = loadedCheerio(this).find('b').remove().end().text().trim();
+ switch (detailName) {
+ case "Autor:":
+ case "Author:":
+ novel.author = detail;
+ break;
+ case "Status:":
+ novel.status = detail;
+ break;
+ }
+ });
+ novel.genres = loadedCheerio(".genxed")
+ .text()
+ .trim()
+ .replace(/\s/g, ",");
+ loadedCheerio('div[itemprop="description"] h3,p.a,strong').remove();
+ novel.summary = loadedCheerio('div[itemprop="description"]')
+ .find("br")
+ .replaceWith("\n")
+ .end()
+ .text();
+ chapter = [];
+ loadedCheerio(".eplister")
+ .find("li")
+ .each(function () {
+ var chapterName = loadedCheerio(this).find(".epl-num").text() +
+ " - " +
+ loadedCheerio(this).find(".epl-title").text();
+ var releaseDate = loadedCheerio(this)
+ .find(".epl-date")
+ .text()
+ .trim();
+ var chapterUrl = loadedCheerio(this).find("a").attr("href");
+ if (!chapterUrl)
+ return;
+ chapter.push({
+ name: chapterName,
+ releaseTime: releaseDate,
+ url: chapterUrl,
+ });
+ });
+ novel.chapters = chapter.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ LightNovelBrasil.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var headers, result, body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ headers = new Headers();
+ if (this.cookieString) {
+ headers.append("cookie", this.cookieString);
+ }
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl, { headers: headers })];
+ case 1:
+ result = _a.sent();
+ return [4 /*yield*/, result.text()];
+ case 2:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio(".epcontent").html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ LightNovelBrasil.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var url, headers, result, body, loadedCheerio, novels;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ url = "".concat(this.site, "?s=").concat(searchTerm);
+ headers = new Headers();
+ if (this.cookieString) {
+ headers.append("cookie", this.cookieString);
+ }
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url, { headers: headers })];
+ case 1:
+ result = _a.sent();
+ return [4 /*yield*/, result.text()];
+ case 2:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ novels = [];
+ loadedCheerio("article.bs").each(function () {
+ var novelName = loadedCheerio(this).find(".ntitle").text().trim();
+ var novelCover = loadedCheerio(this).find("img").attr("src");
+ var novelUrl = loadedCheerio(this).find("a").attr("href");
+ if (!novelUrl)
+ return;
+ novels.push({
+ name: novelName,
+ url: novelUrl,
+ cover: novelCover,
+ });
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ LightNovelBrasil.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url)];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return LightNovelBrasil;
+}());
+exports.default = new LightNovelBrasil();
diff --git a/.js/plugins/spanish/tunovelaligera.js b/.js/plugins/spanish/tunovelaligera.js
new file mode 100644
index 0000000..be932e5
--- /dev/null
+++ b/.js/plugins/spanish/tunovelaligera.js
@@ -0,0 +1,416 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var cheerio_1 = require("cheerio");
+var fetch_1 = require("@libs/fetch");
+var filterInputs_1 = require("@libs/filterInputs");
+var showToast_1 = require("@libs/showToast");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var TuNovelaLigera = /** @class */ (function () {
+ function TuNovelaLigera() {
+ this.id = "tunovelaligera";
+ this.name = "TuNovelaLigera";
+ this.icon = "src/es/tunovelaligera/icon.png";
+ this.site = "https://tunovelaligera.com/";
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.filters = [
+ {
+ key: "order",
+ label: "Ordenado por",
+ values: [
+ { label: "Lo mas reciente", value: "?m_orderby=latest" },
+ { label: "A-Z", value: "?m_orderby=alphabet" },
+ { label: "Clasificación", value: "?m_orderby=rating" },
+ { label: "Trending", value: "?m_orderby=trending" },
+ { label: "Mas visto", value: "?m_orderby=views" },
+ { label: "Nuevo", value: "?m_orderby=new-manga" },
+ ],
+ inputType: filterInputs_1.FilterInputs.Picker,
+ },
+ {
+ key: "genres",
+ label: "Generos",
+ values: [
+ { label: "Acción", value: "accion" },
+ { label: "Adulto", value: "adulto" },
+ { label: "Artes Marciales", value: "artes-marciales" },
+ { label: "Aventura", value: "aventura" },
+ { label: "Ciencia Ficción", value: "ciencia-ficcion" },
+ { label: "Comedia", value: "comedia" },
+ { label: "Deportes", value: "deportes" },
+ { label: "Drama", value: "drama" },
+ { label: "Eastern Fantasy", value: "eastern-fantasy" },
+ { label: "Ecchi", value: "ecchi" },
+ { label: "FanFiction", value: "fan-fiction" },
+ { label: "Fantasía", value: "fantasia" },
+ { label: "Fantasía oriental", value: "fantasia-oriental" },
+ { label: "Ficción Romántica", value: "ficcion-romantica" },
+ { label: "Gender Bender", value: "gender-bender" },
+ { label: "Harem", value: "harem" },
+ { label: "Histórico", value: "historico" },
+ { label: "Horror", value: "horror" },
+ { label: "Josei", value: "josei" },
+ { label: "Maduro", value: "maduro" },
+ { label: "Mecha", value: "mecha" },
+ { label: "Misterio", value: "misterio" },
+ { label: "Novela China", value: "novela-china" },
+ { label: "Novela FanFiction", value: "novela-fanfiction" },
+ { label: "Novela Japonesa", value: "novela-japonesa" },
+ { label: "Novela Koreana", value: "novela-koreana" },
+ { label: "Novela ligera", value: "novela-ligera" },
+ { label: "Novela original", value: "novela-original" },
+ { label: "Novela Web", value: "web-novel" },
+ { label: "Psicológico", value: "psicologico" },
+ { label: "Realismo Mágico", value: "realismo-magico" },
+ { label: "Recuento de vida", value: "recuento-de-vida" },
+ { label: "Romance", value: "romance" },
+ { label: "Romance contemporáneo", value: "romance-contemporaneo" },
+ { label: "Romance Moderno", value: "romance-moderno" },
+ { label: "Seinen", value: "seinen" },
+ { label: "Shoujo", value: "shoujo" },
+ { label: "Shounen", value: "shounen" },
+ { label: "Sobrenatural", value: "sobrenatural" },
+ { label: "Tragedia", value: "tragedia" },
+ { label: "Vampiros", value: "vampiros" },
+ { label: "Vida Escolar", value: "vida-escolar" },
+ { label: "Western Fantasy", value: "western-fantasy" },
+ { label: "Wuxia", value: "wuxia" },
+ { label: "Xianxia", value: "xianxia" },
+ { label: "Xuanhuan", value: "xuanhuan" },
+ { label: "Yaoi", value: "yaoi" },
+ ],
+ inputType: filterInputs_1.FilterInputs.Picker,
+ },
+ ];
+ }
+ TuNovelaLigera.prototype.popularNovels = function (pageNo, _a) {
+ var filters = _a.filters;
+ return __awaiter(this, void 0, void 0, function () {
+ var link, headers, result, body, loadedCheerio, novels;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ link = "".concat(this.site);
+ link += ((filters === null || filters === void 0 ? void 0 : filters.genres) ? "genero/" + filters.genres : "novelas");
+ link += "/page/".concat(pageNo);
+ link += ((filters === null || filters === void 0 ? void 0 : filters.order) ? filters.order : "?m_orderby=rating");
+ headers = new Headers();
+ if (this.cookieString) {
+ headers.append("cookie", this.cookieString);
+ }
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(link, { headers: headers })];
+ case 1:
+ result = _b.sent();
+ return [4 /*yield*/, result.text()];
+ case 2:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ novels = [];
+ loadedCheerio(".page-item-detail").each(function (i, el) {
+ var novelName = loadedCheerio(el).find(".h5 > a").text();
+ var novelCover = loadedCheerio(el).find("img").attr("src");
+ var novelUrl = loadedCheerio(el).find(".h5 > a").attr("href");
+ if (!novelUrl)
+ return;
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ ;
+ TuNovelaLigera.prototype.parseNovelAndChapters = function (novelUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var url, headers, result, body, loadedCheerio, novel, novelCover, chapter, delay, lastPage, getChapters, getPageChapters, _a, _b;
+ var _this = this;
+ return __generator(this, function (_c) {
+ switch (_c.label) {
+ case 0:
+ url = novelUrl;
+ headers = new Headers();
+ if (this.cookieString) {
+ headers.append("cookie", this.cookieString);
+ }
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url, { headers: headers })];
+ case 1:
+ result = _c.sent();
+ return [4 /*yield*/, result.text()];
+ case 2:
+ body = _c.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ novel = {
+ url: url,
+ chapters: [],
+ };
+ loadedCheerio(".manga-title-badges").remove();
+ novel.name = loadedCheerio(".post-title > h1").text().trim();
+ novelCover = loadedCheerio(".summary_image > a > img");
+ novel.cover =
+ novelCover.attr("data-src") ||
+ novelCover.attr("src") ||
+ novelCover.attr('data-cfsrc') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio(".post-content_item").each(function () {
+ var detailName = loadedCheerio(this)
+ .find(".summary-heading > h5")
+ .text()
+ .trim();
+ var detail = loadedCheerio(this)
+ .find(".summary-content")
+ .text()
+ .trim();
+ switch (detailName) {
+ case "Generos":
+ novel.genres = detail.replace(/, /g, ",");
+ break;
+ case "Autores":
+ novel.author = detail;
+ break;
+ case "Estado":
+ novel.status =
+ detail.includes("OnGoing") ||
+ detail.includes("Updating")
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ novel.summary = loadedCheerio("div.summary__content > p").text().trim();
+ chapter = [];
+ delay = function (ms) { return new Promise(function (res) { return setTimeout(res, ms); }); };
+ lastPage = 1;
+ lastPage = +loadedCheerio('.lcp_paginator li:last').prev().text();
+ getChapters = function () { return __awaiter(_this, void 0, void 0, function () {
+ var n, novelName, formData, result, text;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ n = url.split('/');
+ novelName = n[4];
+ (0, showToast_1.showToast)('Cargando desde Archivo...');
+ formData = new FormData();
+ formData.append("action", "madara_load_more");
+ formData.append("page", "0");
+ formData.append("template", "html/loop/content");
+ formData.append("vars[category_name]", novelName);
+ formData.append("vars[posts_per_page]", "10000");
+ return [4 /*yield*/, (0, fetch_1.fetchApi)("".concat(this.site, "wp-admin/admin-ajax.php"), {
+ method: "POST",
+ body: formData,
+ headers: headers
+ })];
+ case 1:
+ result = _a.sent();
+ return [4 /*yield*/, result.text()];
+ case 2:
+ text = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(text);
+ loadedCheerio('.heading').each(function (i, el) {
+ var chapterName = loadedCheerio(el)
+ .text()
+ .replace(/[\t\n]/g, '')
+ .trim();
+ var releaseDate = null;
+ var chapterUrl = loadedCheerio(el).find('a').attr('href') || "";
+ chapter.push({
+ name: chapterName,
+ url: chapterUrl,
+ releaseTime: releaseDate,
+ });
+ });
+ return [2 /*return*/, chapter.reverse()];
+ }
+ });
+ }); };
+ getPageChapters = function () { return __awaiter(_this, void 0, void 0, function () {
+ var _loop_1, i;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ _loop_1 = function (i) {
+ var chaptersUrl, result_1, chaptersHTML, chapterCheerio;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ chaptersUrl = "".concat(novelUrl, "?lcp_page0=").concat(i);
+ (0, showToast_1.showToast)("Cargando desde la p\u00E1gina ".concat(i, "/").concat(lastPage, "..."));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(chaptersUrl, { headers: headers })];
+ case 1:
+ result_1 = _b.sent();
+ return [4 /*yield*/, result_1.text()];
+ case 2:
+ chaptersHTML = _b.sent();
+ chapterCheerio = (0, cheerio_1.load)(chaptersHTML);
+ chapterCheerio('.lcp_catlist li').each(function (i, el) {
+ var chapterName = chapterCheerio(el)
+ .find('a')
+ .text()
+ .replace(/[\t\n]/g, '')
+ .trim();
+ var releaseDate = chapterCheerio(el)
+ .find('span')
+ .text()
+ .trim();
+ var chapterUrl = chapterCheerio(el).find('a').attr('href') || "";
+ chapter.push({
+ name: chapterName,
+ releaseTime: releaseDate,
+ url: chapterUrl,
+ });
+ });
+ return [4 /*yield*/, delay(1000)];
+ case 3:
+ _b.sent();
+ return [2 /*return*/];
+ }
+ });
+ };
+ i = 1;
+ _a.label = 1;
+ case 1:
+ if (!(i <= lastPage)) return [3 /*break*/, 4];
+ return [5 /*yield**/, _loop_1(i)];
+ case 2:
+ _a.sent();
+ _a.label = 3;
+ case 3:
+ i++;
+ return [3 /*break*/, 1];
+ case 4: return [2 /*return*/, chapter.reverse()];
+ }
+ });
+ }); };
+ _a = novel;
+ return [4 /*yield*/, getChapters()];
+ case 3:
+ _a.chapters = _c.sent();
+ if (!!novel.chapters.length) return [3 /*break*/, 6];
+ (0, showToast_1.showToast)('¡Archivo no encontrado!');
+ return [4 /*yield*/, delay(1000)];
+ case 4:
+ _c.sent();
+ _b = novel;
+ return [4 /*yield*/, getPageChapters()];
+ case 5:
+ _b.chapters = _c.sent();
+ _c.label = 6;
+ case 6: return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ TuNovelaLigera.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var headers, result, body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ headers = new Headers();
+ if (this.cookieString) {
+ headers.append("cookie", this.cookieString);
+ }
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl)];
+ case 1:
+ result = _a.sent();
+ return [4 /*yield*/, result.text()];
+ case 2:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio("#hola_siguiente").next().find('div').remove();
+ chapterText = loadedCheerio("#hola_siguiente").next().html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ ;
+ TuNovelaLigera.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var url, result, body, loadedCheerio, novels;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ url = "".concat(this.site, "?s=").concat(searchTerm, "&post_type=wp-manga");
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url)];
+ case 1:
+ result = _a.sent();
+ return [4 /*yield*/, result.text()];
+ case 2:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ novels = [];
+ loadedCheerio(".c-tabs-item__content").each(function (i, el) {
+ var novelName = loadedCheerio(el).find(".h4 > a").text();
+ var novelCover = loadedCheerio(el).find("img").attr("src");
+ var novelUrl = loadedCheerio(el).find(".h4 > a").attr("href");
+ if (!novelUrl)
+ return;
+ novels.push({
+ name: novelName,
+ url: novelUrl,
+ cover: novelCover,
+ });
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ ;
+ TuNovelaLigera.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url)];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return TuNovelaLigera;
+}());
+exports.default = new TuNovelaLigera();
diff --git a/.js/plugins/turkish/TurkceLightNovels[madara].js b/.js/plugins/turkish/TurkceLightNovels[madara].js
new file mode 100644
index 0000000..dc6ea8b
--- /dev/null
+++ b/.js/plugins/turkish/TurkceLightNovels[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "turkcelightnovels", "sourceSite": "https://turkcelightnovels.com/", "sourceName": "TurkceLightNovels", "filters": [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": "Picker" }], "options": { "path": { "novels": "light-novel", "novel": "light-novel", "chapter": "light-novel" }, "lang": "Turkish" } });
+exports.default = plugin;
diff --git a/.js/plugins/turkish/WebNovelOku[madara].js b/.js/plugins/turkish/WebNovelOku[madara].js
new file mode 100644
index 0000000..122c9c0
--- /dev/null
+++ b/.js/plugins/turkish/WebNovelOku[madara].js
@@ -0,0 +1,269 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var fetch_1 = require("@libs/fetch");
+var cheerio_1 = require("cheerio");
+var defaultCover_1 = require("@libs/defaultCover");
+var novelStatus_1 = require("@libs/novelStatus");
+var parseMadaraDate_1 = require("@libs/parseMadaraDate");
+var dayjs_1 = __importDefault(require("dayjs"));
+var MadaraDefaultPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+};
+var MadaraPlugin = /** @class */ (function () {
+ function MadaraPlugin(metadata) {
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ var iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = "multisrc/madara/icons/".concat(iconFileName, ".png");
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
+ }
+ MadaraPlugin.prototype.popularNovels = function (pageNo, _a) {
+ var _b, _c, _d, _e, _f, _g;
+ var filters = _a.filters, showLatestNovels = _a.showLatestNovels;
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_h) {
+ switch (_h.label) {
+ case 0:
+ novels = [];
+ url = this.site;
+ if ((filters === null || filters === void 0 ? void 0 : filters.genres) && ((_c = (_b = this.options) === null || _b === void 0 ? void 0 : _b.path) === null || _c === void 0 ? void 0 : _c.genres)) {
+ url += ((_e = (_d = this.options) === null || _d === void 0 ? void 0 : _d.path) === null || _e === void 0 ? void 0 : _e.genres) + filters.genres + '/';
+ }
+ else {
+ url += ((_g = (_f = this.options) === null || _f === void 0 ? void 0 : _f.path) === null || _g === void 0 ? void 0 : _g.novels) ? this.options.path.novels : MadaraDefaultPath.novels;
+ }
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _h.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges').remove();
+ loadedCheerio('.page-item-detail').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ var _a;
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, body, loadedCheerio, html, novelId, formData, chapters;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover_1.defaultCover;
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ var detailName = loadedCheerio(this).find('h5').text().trim();
+ var detail = loadedCheerio(this).find('.summary-content').text().trim();
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? novelStatus_1.NovelStatus.Ongoing
+ : novelStatus_1.NovelStatus.Completed;
+ break;
+ }
+ });
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+ if (!(((_a = this.options) === null || _a === void 0 ? void 0 : _a.useNewChapterEndpoint) !== true)) return [3 /*break*/, 3];
+ novelId = loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+ formData = new FormData();
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(this.site + 'wp-admin/admin-ajax.php', {
+ method: 'POST',
+ body: formData,
+ })
+ .then(function (res) { return res.text(); })];
+ case 2:
+ html = _b.sent();
+ return [3 /*break*/, 5];
+ case 3: return [4 /*yield*/, (0, fetch_1.fetchApi)(novelUrl + 'ajax/chapters/', { method: 'POST' })
+ .then(function (res) { return res.text(); })];
+ case 4:
+ html = _b.sent();
+ _b.label = 5;
+ case 5:
+ if (html !== '0') {
+ loadedCheerio = (0, cheerio_1.load)(html);
+ }
+ chapters = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ var chapterName = loadedCheerio(this).find('a').text().trim();
+ var releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+ if (releaseDate) {
+ releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
+ }
+ else {
+ /**
+ * Insert current date
+ */
+ releaseDate = (0, dayjs_1.default)().format('LL');
+ }
+ var chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+ novel.chapters = chapters.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novels, url, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novels = [];
+ url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url).then(function (res) { return res.text(); })];
+ case 1:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ var novelName = loadedCheerio(this).find('.post-title').text().trim();
+ var image = loadedCheerio(this).find('img');
+ var novelCover = image.attr('data-src') || image.attr('src');
+ var novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ MadaraPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url, {})];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return MadaraPlugin;
+}());
+var plugin = new MadaraPlugin({ "id": "webnoveloku", "sourceSite": "https://www.webnoveloku.com/", "sourceName": "WebNovelOku ", "filters": [{ "key": "sort", "label": "Sırala", "values": [{ "label": "A-Z", "value": "alphabet" }, { "label": "En Son", "value": "latest" }, { "label": "Görüntülenme", "value": "views" }, { "label": "Popülarite", "value": "trending" }, { "label": "Reyting", "value": "rating" }, { "label": "Yeni", "value": "new-manga" }], "inputType": "Picker" }], "options": { "lang": "Turkish" } });
+exports.default = plugin;
diff --git a/.js/plugins/turkish/lshnovel.js b/.js/plugins/turkish/lshnovel.js
new file mode 100644
index 0000000..21807e0
--- /dev/null
+++ b/.js/plugins/turkish/lshnovel.js
@@ -0,0 +1,324 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var cheerio_1 = require("cheerio");
+var fetch_1 = require("@libs/fetch");
+var filterInputs_1 = require("@libs/filterInputs");
+var LSHNovel = /** @class */ (function () {
+ function LSHNovel() {
+ this.id = "lshnovel";
+ this.name = "Liebe Schnee Hiver Novel";
+ this.icon = "multisrc/wpmangastream/icons/lshnovel.png";
+ this.site = "https://lshnovel.com/";
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.filters = [
+ {
+ key: "order",
+ label: "Önerilen",
+ values: [
+ { label: "Varsayılan", value: "" },
+ { label: "A-Z", value: "title" },
+ { label: "Z-A", value: "titlereverse" },
+ { label: "Son Yüklemeler", value: "update" },
+ { label: "Son Eklenenler", value: "latest" },
+ { label: "Bestimiz", value: "popular" },
+ ],
+ inputType: filterInputs_1.FilterInputs.Picker,
+ },
+ {
+ key: "status",
+ label: "Statü",
+ values: [
+ { label: "Tümü", value: "" },
+ { label: "Ongoing", value: "ongoing" },
+ { label: "Hiatus", value: "hiatus" },
+ { label: "Completed", value: "completed" },
+ ],
+ inputType: filterInputs_1.FilterInputs.Picker,
+ },
+ {
+ key: "type",
+ label: "Tür",
+ values: [
+ { label: "Çeviri Novel", value: "ceviri-novel" },
+ { label: "Liz-Chan", value: "liz-chan" },
+ { label: "Manhwa", value: "manhwa" },
+ { label: "Orijinal Novel", value: "orijinal-novel" },
+ { label: "Web Novel", value: "web-novel" },
+ ],
+ inputType: filterInputs_1.FilterInputs.Checkbox,
+ },
+ {
+ key: "genres",
+ label: "Kategori",
+ values: [
+ { label: "+18", value: "18" },
+ { label: "Action", value: "action" },
+ { label: "Adult", value: "adult" },
+ { label: "Aksiyon", value: "aksiyon" },
+ { label: "BL", value: "bl" },
+ { label: "Comedy", value: "comedy" },
+ { label: "Doğaüstü", value: "dogaustu" },
+ { label: "Dram", value: "dram" },
+ { label: "Drama", value: "drama" },
+ { label: "Ecchi", value: "ecchi" },
+ { label: "Fantastik", value: "fantastik" },
+ { label: "Fantasy", value: "fantasy" },
+ { label: "Gizem", value: "gizem" },
+ { label: "Harem", value: "harem" },
+ { label: "Historical", value: "historical" },
+ { label: "Josei", value: "josei" },
+ { label: "Macera", value: "macera" },
+ { label: "Manhwa", value: "manhwa" },
+ { label: "Martial Arts", value: "martial-arts" },
+ { label: "Mature", value: "mature" },
+ { label: "Novel", value: "novel" },
+ { label: "Okul", value: "okul" },
+ { label: "Psikolojik", value: "psikolojik" },
+ { label: "Psychological", value: "psychological" },
+ { label: "Reverse Harem", value: "reverse-harem" },
+ { label: "Romance", value: "romance" },
+ { label: "Romantik", value: "romantik" },
+ { label: "Shoujo", value: "shoujo" },
+ { label: "Slice Of Life", value: "slice-of-life" },
+ { label: "Smut", value: "smut" },
+ { label: "Supernatural", value: "supernatural" },
+ { label: "Tarihi", value: "tarihi" },
+ { label: "Tragedy", value: "tragedy" },
+ { label: "Yaoi", value: "yaoi" },
+ ],
+ inputType: filterInputs_1.FilterInputs.Checkbox,
+ },
+ ];
+ }
+ LSHNovel.prototype.popularNovels = function (pageNo, _a) {
+ var filters = _a.filters;
+ return __awaiter(this, void 0, void 0, function () {
+ var link, headers, body, loadedCheerio, novels;
+ return __generator(this, function (_b) {
+ switch (_b.label) {
+ case 0:
+ link = "".concat(this.site, "series/?page=").concat(pageNo);
+ if (filters) {
+ if (Array.isArray(filters.genres) && filters.genres.length) {
+ link += filters.genres.map(function (i) { return "&genre[]=".concat(i); }).join("");
+ }
+ if (Array.isArray(filters.type) && filters.type.length)
+ link += filters.type.map(function (i) { return "&lang[]=".concat(i); }).join("");
+ }
+ link += "&status=" + ((filters === null || filters === void 0 ? void 0 : filters.status) ? filters.status : "");
+ link += "&order=" + ((filters === null || filters === void 0 ? void 0 : filters.order) ? filters.order : "popular");
+ headers = new Headers();
+ if (this.cookieString) {
+ headers.append("cookie", this.cookieString);
+ }
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(link, { headers: headers }).then(function (result) {
+ return result.text();
+ })];
+ case 1:
+ body = _b.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ novels = [];
+ loadedCheerio("article.bs").each(function () {
+ var novelName = loadedCheerio(this).find(".ntitle").text().trim();
+ var image = loadedCheerio(this).find("img");
+ var novelCover = image.attr("data-src") || image.attr("src");
+ var novelUrl = loadedCheerio(this).find("a").attr("href");
+ if (!novelUrl)
+ return;
+ var novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+ novels.push(novel);
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ ;
+ LSHNovel.prototype.parseNovelAndChapters = function (novelUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var url, headers, result, body, loadedCheerio, novel, chapter;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ url = novelUrl;
+ headers = new Headers();
+ if (this.cookieString) {
+ headers.append("cookie", this.cookieString);
+ }
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url, { headers: headers })];
+ case 1:
+ result = _a.sent();
+ return [4 /*yield*/, result.text()];
+ case 2:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ novel = {
+ url: url,
+ chapters: [],
+ };
+ novel.name = loadedCheerio(".entry-title").text();
+ novel.cover =
+ loadedCheerio("img.wp-post-image").attr("data-src") ||
+ loadedCheerio("img.wp-post-image").attr("src");
+ loadedCheerio("div.spe > span").each(function () {
+ var detailName = loadedCheerio(this).find("b").text().trim();
+ var detail = loadedCheerio(this).find('b').remove().end().text().trim();
+ switch (detailName) {
+ case "Yazar:":
+ novel.author = detail;
+ break;
+ case "Seviye:":
+ novel.status = detail;
+ break;
+ }
+ });
+ novel.genres = loadedCheerio(".genxed")
+ .text()
+ .trim()
+ .replace(/\s/g, ",");
+ loadedCheerio('div[itemprop="description"] h3,p.a,strong').remove();
+ novel.summary = loadedCheerio('div[itemprop="description"]')
+ .find("br")
+ .replaceWith("\n")
+ .end()
+ .text();
+ chapter = [];
+ loadedCheerio(".eplister")
+ .find("li")
+ .each(function () {
+ var chapterName = loadedCheerio(this).find(".epl-num").text() +
+ " - " +
+ loadedCheerio(this).find(".epl-title").text();
+ var releaseDate = loadedCheerio(this)
+ .find(".epl-date")
+ .text()
+ .trim();
+ var chapterUrl = loadedCheerio(this).find("a").attr("href");
+ if (!chapterUrl)
+ return;
+ chapter.push({
+ name: chapterName,
+ releaseTime: releaseDate,
+ url: chapterUrl,
+ });
+ });
+ novel.chapters = chapter.reverse();
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ LSHNovel.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var headers, result, body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ headers = new Headers();
+ if (this.cookieString) {
+ headers.append("cookie", this.cookieString);
+ }
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(chapterUrl, { headers: headers })];
+ case 1:
+ result = _a.sent();
+ return [4 /*yield*/, result.text()];
+ case 2:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio(".epcontent").html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ LSHNovel.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var url, headers, result, body, loadedCheerio, novels;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ url = "".concat(this.site, "?s=").concat(searchTerm);
+ headers = new Headers();
+ if (this.cookieString) {
+ headers.append("cookie", this.cookieString);
+ }
+ return [4 /*yield*/, (0, fetch_1.fetchApi)(url, { headers: headers })];
+ case 1:
+ result = _a.sent();
+ return [4 /*yield*/, result.text()];
+ case 2:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ novels = [];
+ loadedCheerio("article.bs").each(function () {
+ var novelName = loadedCheerio(this).find(".ntitle").text().trim();
+ var novelCover = loadedCheerio(this).find("img").attr("src");
+ var novelUrl = loadedCheerio(this).find("a").attr("href");
+ if (!novelUrl)
+ return;
+ novels.push({
+ name: novelName,
+ url: novelUrl,
+ cover: novelCover,
+ });
+ });
+ return [2 /*return*/, novels];
+ }
+ });
+ });
+ };
+ LSHNovel.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, (0, fetch_1.fetchFile)(url)];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return LSHNovel;
+}());
+exports.default = new LSHNovel();
diff --git a/.js/plugins/vietnamese/LNHako.js b/.js/plugins/vietnamese/LNHako.js
new file mode 100644
index 0000000..2133d02
--- /dev/null
+++ b/.js/plugins/vietnamese/LNHako.js
@@ -0,0 +1,219 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var cheerio_1 = require("cheerio");
+var fetch_1 = require("@libs/fetch");
+var isAbsoluteUrl_1 = require("@libs/isAbsoluteUrl");
+var HakoPlugin = /** @class */ (function () {
+ function HakoPlugin() {
+ this.id = "ln.hako";
+ this.name = "Hako";
+ this.icon = "src/vi/hakolightnovel/icon.png";
+ this.site = "https://ln.hako.vn";
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ }
+ HakoPlugin.prototype.parseNovels = function (loadedCheerio) {
+ var _this = this;
+ var novels = [];
+ loadedCheerio(".row > .thumb-item-flow").each(function (index, ele) {
+ var url = loadedCheerio(ele)
+ .find("div.thumb_attr.series-title > a")
+ .attr("href");
+ if (url && !(0, isAbsoluteUrl_1.isUrlAbsolute)(url)) {
+ url = _this.site + url;
+ }
+ if (url) {
+ var name_1 = loadedCheerio(ele)
+ .find(".series-title")
+ .text()
+ .trim();
+ var cover = loadedCheerio(ele)
+ .find(".img-in-ratio")
+ .attr("data-bg");
+ if (cover && !(0, isAbsoluteUrl_1.isUrlAbsolute)(cover)) {
+ cover = _this.site + cover;
+ }
+ var novel = { name: name_1, url: url, cover: cover };
+ novels.push(novel);
+ }
+ });
+ return novels;
+ };
+ HakoPlugin.prototype.popularNovels = function (pageNo, options) {
+ return __awaiter(this, void 0, void 0, function () {
+ var link, result, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ link = this.site + "/danh-sach?truyendich=1&sapxep=topthang&page=" + pageNo;
+ return [4 /*yield*/, fetch(link)];
+ case 1:
+ result = _a.sent();
+ return [4 /*yield*/, result.text()];
+ case 2:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ return [2 /*return*/, this.parseNovels(loadedCheerio)];
+ }
+ });
+ });
+ };
+ HakoPlugin.prototype.parseNovelAndChapters = function (novelUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var novel, result, body, loadedCheerio, background, novelCover, chapters;
+ var _this = this;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ novel = {
+ url: novelUrl,
+ };
+ return [4 /*yield*/, fetch(novelUrl)];
+ case 1:
+ result = _a.sent();
+ return [4 /*yield*/, result.text()];
+ case 2:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ novel.name = loadedCheerio(".series-name").text();
+ background = loadedCheerio(".series-cover > .a6-ratio > div").attr("style") || "";
+ novelCover = background.substring(background.indexOf("http"), background.length - 2);
+ novel.cover = novelCover
+ ? (0, isAbsoluteUrl_1.isUrlAbsolute)(novelCover)
+ ? novelCover
+ : this.site + novelCover
+ : "";
+ novel.summary = loadedCheerio(".summary-content").text().trim();
+ novel.author = loadedCheerio("#mainpart > div:nth-child(2) > div > div:nth-child(1) > section > main > div.top-part > div > div.col-12.col-md-9 > div.series-information > div:nth-child(2) > span.info-value > a")
+ .text()
+ .trim();
+ novel.genres = loadedCheerio(".series-gernes")
+ .text()
+ .trim()
+ .replace(/ +/g, " ")
+ .split("\n")
+ .filter(function (e) { return e.trim(); })
+ .join(", ");
+ novel.status = loadedCheerio("#mainpart > div:nth-child(2) > div > div:nth-child(1) > section > main > div.top-part > div > div.col-12.col-md-9 > div.series-information > div:nth-child(4) > span.info-value > a")
+ .text()
+ .trim();
+ chapters = [];
+ loadedCheerio(".list-chapters li").each(function (index, ele) {
+ var chapterUrl = loadedCheerio(ele).find("a").attr("href");
+ if (chapterUrl && !(0, isAbsoluteUrl_1.isUrlAbsolute)(chapterUrl)) {
+ chapterUrl = _this.site + chapterUrl;
+ }
+ if (chapterUrl) {
+ var chapterName = loadedCheerio(ele)
+ .find(".chapter-name")
+ .text()
+ .trim();
+ var releaseTime = loadedCheerio(ele)
+ .find(".chapter-time")
+ .text();
+ var chapter = {
+ name: chapterName,
+ releaseTime: releaseTime,
+ url: chapterUrl,
+ };
+ chapters.push(chapter);
+ }
+ });
+ novel.chapters = chapters;
+ return [2 /*return*/, novel];
+ }
+ });
+ });
+ };
+ HakoPlugin.prototype.parseChapter = function (chapterUrl) {
+ return __awaiter(this, void 0, void 0, function () {
+ var result, body, loadedCheerio, chapterText;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, fetch(chapterUrl)];
+ case 1:
+ result = _a.sent();
+ return [4 /*yield*/, result.text()];
+ case 2:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ chapterText = loadedCheerio("#chapter-content").html() || "";
+ return [2 /*return*/, chapterText];
+ }
+ });
+ });
+ };
+ HakoPlugin.prototype.searchNovels = function (searchTerm, pageNo) {
+ return __awaiter(this, void 0, void 0, function () {
+ var url, result, body, loadedCheerio;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ url = this.site + "/tim-kiem?keywords=" + searchTerm;
+ return [4 /*yield*/, fetch(url)];
+ case 1:
+ result = _a.sent();
+ return [4 /*yield*/, result.text()];
+ case 2:
+ body = _a.sent();
+ loadedCheerio = (0, cheerio_1.load)(body);
+ return [2 /*return*/, this.parseNovels(loadedCheerio)];
+ }
+ });
+ });
+ };
+ HakoPlugin.prototype.fetchImage = function (url) {
+ return __awaiter(this, void 0, void 0, function () {
+ var headers;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0:
+ headers = {
+ Referer: "https://ln.hako.vn",
+ };
+ return [4 /*yield*/, (0, fetch_1.fetchFile)(url, { headers: headers })];
+ case 1: return [2 /*return*/, _a.sent()];
+ }
+ });
+ });
+ };
+ return HakoPlugin;
+}());
+exports.default = new HakoPlugin();
diff --git a/README.md b/README.md
index c070119..5a73cd8 100644
--- a/README.md
+++ b/README.md
@@ -11,16 +11,15 @@
Repository to host plugins and related issues, and requests for [LNReader](https://github.com/LNReader/lnreader).
+## Prerequisites
+- Nodejs >= 18
+## Contributing
-## Contributing
-
-1. Please use this [template](./template.ts) or [template.min](./template.min.ts)
-
-2. Choose your language in [./plugins](./plugins)
+1. Choose your language in [plugins/](./plugins)
+ If your language doenst exist or you need some other packages, please request us. We will add it soon.
-3. Write your scripts
+2. Write your scripts
+ See example: [Hako](./plugins/vietnamese/LNHako.ts)
diff --git a/icons/src/cn/linovelib/icon.png b/icons/src/cn/linovelib/icon.png
new file mode 100644
index 0000000..ee97ed6
Binary files /dev/null and b/icons/src/cn/linovelib/icon.png differ
diff --git a/index.ts b/index.ts
index ecd1b5f..f3a9cc3 100644
--- a/index.ts
+++ b/index.ts
@@ -20,6 +20,10 @@ app.get("/all_plugins", (req, res) => {
const allPlugins = pluginApi.all_plugins();
res.json(allPlugins);
});
+app.post("/filters", async (req, res) => {
+ const filters = await pluginApi.getFilter(req.body['pluginRequirePath']);
+ res.json(filters || []);
+})
app.post("/popularNovels/", async (req, res) => {
const filters = req.body["filters"] || {};
const showLatestNovels = req.body["showLatestNovels"] || false;
diff --git a/js/plugins/arabic/ArMTL[madara].js b/js/plugins/arabic/ArMTL[madara].js
deleted file mode 100644
index 86d9c38..0000000
--- a/js/plugins/arabic/ArMTL[madara].js
+++ /dev/null
@@ -1,178 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "ar-mtl";
-exports.name = "ArMTL [madara]";
-exports.icon = "multisrc/madara/icons/armtl.png";
-exports.version = "1.0.0";
-exports.site = "https://ar-mtl.club/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "novel-genre/" + filters.genres + '/';
- }
- else {
- url += "novel/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (true) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [];
diff --git a/js/plugins/arabic/ArNovel[madara].js b/js/plugins/arabic/ArNovel[madara].js
deleted file mode 100644
index b501a08..0000000
--- a/js/plugins/arabic/ArNovel[madara].js
+++ /dev/null
@@ -1,179 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const filterInputs_1 = require("@libs/filterInputs");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "arnovel";
-exports.name = "ArNovel [madara]";
-exports.icon = "multisrc/madara/icons/arnovel.png";
-exports.version = "1.0.0";
-exports.site = "https://arnovel.me/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "home/novel-genre/" + filters.genres + '/';
- }
- else {
- url += "novel/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (true) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [{ "key": "sort", "label": "الترتيب حسب", "values": [{ "label": "A-Z", "value": "alphabet" }, { "label": "الآخير", "value": "latest" }, { "label": "الأكثر مشاهدة", "value": "views" }, { "label": "التقييم", "value": "rating" }, { "label": "جديد", "value": "new-manga" }, { "label": "شائع", "value": "trending" }], "inputType": filterInputs_1.FilterInputs.Picker }, { "key": "genres", "label": "التصنيفات", "values": [{ "label": "أكشن", "value": "%d8%a3%d9%83%d8%b4%d9%86" }, { "label": "إتشي", "value": "%d8%a5%d8%aa%d8%b4%d9%80%d9%8a" }, { "label": "بالغ", "value": "%d8%a8%d8%a7%d9%84%d8%ba" }, { "label": "تاريخي", "value": "%d8%aa%d8%a7%d8%b1%d9%8a%d8%ae%d9%8a" }, { "label": "تراجدي", "value": "%d8%aa%d8%b1%d8%a7%d8%ac%d8%af%d9%8a" }, { "label": "جوسي", "value": "%d8%ac%d9%88%d8%b3%d9%8a" }, { "label": "حريم", "value": "%d8%ad%d8%b1%d9%8a%d9%85" }, { "label": "حياة مدرسية", "value": "%d8%ad%d9%8a%d8%a7%d8%a9-%d9%85%d8%af%d8%b1%d8%b3%d9%8a%d8%a9" }, { "label": "خارق لطبيعية", "value": "%d8%ae%d8%a7%d8%b1%d9%82-%d9%84%d8%b7%d8%a8%d9%8a%d8%b9%d9%8a%d8%a9" }, { "label": "خيال", "value": "%d8%ae%d9%8a%d8%a7%d9%84" }, { "label": "خيال علمي", "value": "%d8%ae%d9%8a%d8%a7%d9%84-%d8%b9%d9%84%d9%85%d9%8a" }, { "label": "دراما", "value": "%d8%af%d8%b1%d8%a7%d9%85%d8%a7" }, { "label": "راشد", "value": "%d8%b1%d8%a7%d8%b4%d8%af" }, { "label": "رعب", "value": "%d8%b1%d8%b9%d8%a8" }, { "label": "رومنسي", "value": "%d8%b1%d9%88%d9%85%d9%86%d8%b3%d9%8a" }, { "label": "رياضي", "value": "%d8%b1%d9%8a%d8%a7%d8%b6%d9%8a" }, { "label": "سينين", "value": "%d8%b3%d9%8a%d9%86%d9%8a%d9%86" }, { "label": "شريحة من الحياة", "value": "%d8%b4%d8%b1%d9%8a%d8%ad%d8%a9-%d9%85%d9%86-%d8%a7%d9%84%d8%ad%d9%8a%d8%a7%d8%a9" }, { "label": "شوجو", "value": "%d8%b4%d9%88%d8%ac%d9%88" }, { "label": "شونين", "value": "%d8%b4%d9%88%d9%86%d9%8a%d9%86" }, { "label": "غموض", "value": "%d8%ba%d9%85%d9%88%d8%b6" }, { "label": "فنون قتال", "value": "%d9%81%d9%86%d9%88%d9%86-%d9%82%d8%aa%d8%a7%d9%84" }, { "label": "كوميديا", "value": "%d9%83%d9%88%d9%85%d9%8a%d8%af%d9%8a%d8%a7" }, { "label": "مغامرات", "value": "%d9%85%d8%ba%d8%a7%d9%85%d8%b1%d8%a7%d8%aa" }, { "label": "منتهية", "value": "%d9%85%d9%86%d8%aa%d9%87%d9%8a%d8%a9" }, { "label": "ميكا", "value": "%d9%85%d9%8a%d9%83%d8%a7" }, { "label": "نفسي", "value": "%d9%86%d9%81%d8%b3%d9%8a" }], "inputType": filterInputs_1.FilterInputs.Picker }];
diff --git a/js/plugins/arabic/HizoManga[madara].js b/js/plugins/arabic/HizoManga[madara].js
deleted file mode 100644
index e04ed71..0000000
--- a/js/plugins/arabic/HizoManga[madara].js
+++ /dev/null
@@ -1,179 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const filterInputs_1 = require("@libs/filterInputs");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "hizomanga";
-exports.name = "HizoManga [madara]";
-exports.icon = "multisrc/madara/icons/hizomanga.png";
-exports.version = "1.0.0";
-exports.site = "https://hizomanga.com/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "manga-genre/" + filters.genres + '/';
- }
- else {
- url += "serie/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (true) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "serie" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [{ "key": "sort", "label": "ترتيب حسب", "values": [{ "label": "A-Z", "value": "alphabet" }, { "label": "New", "value": "new-manga" }, { "label": "الأحدث", "value": "latest" }, { "label": "الأكثر مشاهدة", "value": "views" }, { "label": "التقييم", "value": "rating" }, { "label": "الرائج", "value": "trending" }], "inputType": filterInputs_1.FilterInputs.Picker }, { "key": "genres", "label": "التصنيفات", "values": [{ "label": "آلات", "value": "mechanisms" }, { "label": "أكشن", "value": "action" }, { "label": "إثارة", "value": "excitement" }, { "label": "إيسكاي", "value": "%d8%a5%d9%8a%d8%b3%d9%83%d8%a7%d9%8a" }, { "label": "الحياة اليومية", "value": "slice-of-life" }, { "label": "الحياة مدرسية", "value": "school-life" }, { "label": "تاريخي", "value": "historical" }, { "label": "تراجيدي", "value": "tragic" }, { "label": "جريمة", "value": "%d8%ac%d8%b1%d9%8a%d9%85%d8%a9" }, { "label": "جندر بندر", "value": "%d8%ac%d9%86%d8%af%d8%b1-%d8%a8%d9%86%d8%af%d8%b1" }, { "label": "جوسي", "value": "josei" }, { "label": "حريم", "value": "harem" }, { "label": "خارق للطبيعة", "value": "supernatural" }, { "label": "خيال", "value": "fantasy" }, { "label": "خيال علمي", "value": "sci-fi" }, { "label": "دراما", "value": "drama" }, { "label": "دموي", "value": "%d8%af%d9%85%d9%88%d9%8a" }, { "label": "راشد", "value": "mature" }, { "label": "رعب", "value": "horror" }, { "label": "رومانسي", "value": "romance" }, { "label": "رياضة", "value": "sports" }, { "label": "زمنكاني", "value": "my-time" }, { "label": "زومبي", "value": "%d8%b2%d9%88%d9%85%d8%a8%d9%8a" }, { "label": "سينين", "value": "seinen" }, { "label": "شريحة من الحياة", "value": "%d8%b4%d8%b1%d9%8a%d8%ad%d8%a9-%d9%85%d9%86-%d8%a7%d9%84%d8%ad%d9%8a%d8%a7%d8%a9" }, { "label": "شوجو", "value": "shoujo" }, { "label": "شونين", "value": "shounen" }, { "label": "طبي", "value": "%d8%b7%d8%a8%d9%8a" }, { "label": "غموض", "value": "ambiguity" }, { "label": "فنون قتالية", "value": "martial-arts" }, { "label": "قوة خارقة", "value": "superpower" }, { "label": "كوميدي", "value": "comedy" }, { "label": "مغامرات", "value": "adventure" }, { "label": "نفسي", "value": "psychological" }], "inputType": filterInputs_1.FilterInputs.Picker }];
diff --git a/js/plugins/arabic/Novel4Up[madara].js b/js/plugins/arabic/Novel4Up[madara].js
deleted file mode 100644
index 17abe7b..0000000
--- a/js/plugins/arabic/Novel4Up[madara].js
+++ /dev/null
@@ -1,179 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const filterInputs_1 = require("@libs/filterInputs");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "novel4up";
-exports.name = "Novel4Up [madara]";
-exports.icon = "multisrc/madara/icons/novel4up.png";
-exports.version = "1.0.0";
-exports.site = "https://novel4up.com/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "novel-genre/" + filters.genres + '/';
- }
- else {
- url += "novel/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (false) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [{ "key": "sort", "label": "ترتيب حسب:", "values": [{ "label": "أ-ي", "value": "alphabet" }, { "label": "الأحدث", "value": "latest" }, { "label": "الأكثر مشاهدة", "value": "views" }, { "label": "التقييم", "value": "rating" }, { "label": "الجديد", "value": "new-manga" }, { "label": "الشائع", "value": "trending" }], "inputType": filterInputs_1.FilterInputs.Picker }, { "key": "genres", "label": "التصنيفات", "values": [{ "label": "أكشن", "value": "action" }, { "label": "الخارق للطبيعة", "value": "supernatural" }, { "label": "تاريخي", "value": "historical" }, { "label": "تحقيق", "value": "detective" }, { "label": "تراجيديا", "value": "tragedy" }, { "label": "حريم", "value": "harem" }, { "label": "حياة مدرسية", "value": "school-life" }, { "label": "خيال علمي", "value": "sci-fi" }, { "label": "دراما", "value": "drama" }, { "label": "رعب", "value": "horror" }, { "label": "رومانسي", "value": "romance" }, { "label": "رياضة", "value": "sports" }, { "label": "سحر", "value": "magic" }, { "label": "شريحة من الحياة", "value": "slice-of-life" }, { "label": "شوانهوا", "value": "xuanhuan" }, { "label": "شوجو", "value": "shoujo" }, { "label": "شونين", "value": "shounen" }, { "label": "غموض", "value": "mystery" }, { "label": "فانتازيا", "value": "fantasy" }, { "label": "فنون قتال", "value": "martial-arts" }, { "label": "كوميديا", "value": "comedy" }, { "label": "مغامرة", "value": "adventure" }, { "label": "ميكا", "value": "mecha" }, { "label": "نفسي", "value": "psychological" }, { "label": "ون شوت", "value": "one-shot" }, { "label": "ووشيا", "value": "wuxia" }], "inputType": filterInputs_1.FilterInputs.Picker }];
diff --git a/js/plugins/arabic/Riwyat[madara].js b/js/plugins/arabic/Riwyat[madara].js
deleted file mode 100644
index 23e6154..0000000
--- a/js/plugins/arabic/Riwyat[madara].js
+++ /dev/null
@@ -1,179 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const filterInputs_1 = require("@libs/filterInputs");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "riwyat";
-exports.name = "Riwyat [madara]";
-exports.icon = "multisrc/madara/icons/riwyat.png";
-exports.version = "1.0.0";
-exports.site = "https://riwyat.com/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "novel-genre/" + filters.genres + '/';
- }
- else {
- url += "novel/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (true) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": filterInputs_1.FilterInputs.Picker }, { "key": "genres", "label": "GENRES", "values": [{ "label": "أكشن", "value": "%d8%a3%d9%83%d8%b4%d9%86" }, { "label": "أيتشي", "value": "%d8%a3%d9%8a%d8%aa%d8%b4%d9%8a" }, { "label": "استراتجي", "value": "%d8%a7%d8%b3%d8%aa%d8%b1%d8%a7%d8%aa%d8%ac%d9%8a" }, { "label": "العصر الحديث", "value": "%d8%a7%d9%84%d8%b9%d8%b5%d8%b1-%d8%a7%d9%84%d8%ad%d8%af%d9%8a%d8%ab" }, { "label": "انتقام", "value": "%d8%a7%d9%86%d8%aa%d9%82%d8%a7%d9%85" }, { "label": "بالغ", "value": "%d8%a8%d8%a7%d9%84%d8%ba" }, { "label": "بناء مملكة", "value": "%d8%a8%d9%86%d8%a7%d8%a1-%d9%85%d9%85%d9%84%d9%83%d8%a9" }, { "label": "بوليسي", "value": "%d8%a8%d9%88%d9%84%d9%8a%d8%b3%d9%8a" }, { "label": "تاريخي", "value": "%d8%aa%d8%a7%d8%b1%d9%8a%d8%ae%d9%8a" }, { "label": "جوسي", "value": "%d8%ac%d9%88%d8%b3%d9%8a" }, { "label": "حريم", "value": "%d8%ad%d8%b1%d9%8a%d9%85" }, { "label": "حياة يومية", "value": "%d8%ad%d9%8a%d8%a7%d8%a9-%d9%8a%d9%88%d9%85%d9%8a%d8%a9" }, { "label": "خيال", "value": "%d8%ae%d9%8a%d8%a7%d9%84" }, { "label": "خيال علمي", "value": "%d8%ae%d9%8a%d8%a7%d9%84-%d8%b9%d9%84%d9%85%d9%8a" }, { "label": "دراما", "value": "%d8%af%d8%b1%d8%a7%d9%85%d8%a7" }, { "label": "رعب", "value": "%d8%b1%d8%b9%d8%a8" }, { "label": "رومانسية", "value": "%d8%b1%d9%88%d9%85%d8%a7%d9%86%d8%b3%d9%8a%d8%a9" }, { "label": "رياضي", "value": "%d8%b1%d9%8a%d8%a7%d8%b6%d9%8a" }, { "label": "زيانشيا", "value": "xianxia" }, { "label": "سنين", "value": "%d8%b3%d9%86%d9%8a%d9%86" }, { "label": "شريحة حياة", "value": "%d8%b4%d8%b1%d9%8a%d8%ad%d8%a9-%d8%ad%d9%8a%d8%a7%d8%a9" }, { "label": "شوانهوان", "value": "xuanhuan" }, { "label": "شوجو", "value": "%d8%b4%d9%88%d8%ac%d9%88" }, { "label": "شونين", "value": "%d8%b4%d9%88%d9%86%d9%8a%d9%86" }, { "label": "شيانشيا", "value": "%d8%b4%d9%8a%d8%a7%d9%86%d8%b4%d9%8a%d8%a7" }, { "label": "عسكري", "value": "%d8%b9%d8%b3%d9%83%d8%b1%d9%8a" }, { "label": "غموض", "value": "%d8%ba%d9%85%d9%88%d8%b6" }, { "label": "فانتازيا", "value": "%d9%81%d8%a7%d9%86%d8%aa%d8%a7%d8%b2%d9%8a%d8%a7" }, { "label": "فنون قتالية", "value": "%d9%81%d9%86%d9%88%d9%86-%d9%82%d8%aa%d8%a7%d9%84%d9%8a%d8%a9" }, { "label": "قوى خارقة", "value": "%d9%82%d9%88%d9%89-%d8%ae%d8%a7%d8%b1%d9%82%d8%a9" }, { "label": "كوميديا", "value": "%d9%83%d9%88%d9%85%d9%8a%d8%af%d9%8a%d8%a7" }, { "label": "كوميك", "value": "%d9%83%d9%88%d9%85%d9%8a%d9%83" }, { "label": "للكبار", "value": "%d9%84%d9%84%d9%83%d8%a8%d8%a7%d8%b1" }, { "label": "مأساة", "value": "%d9%85%d8%a3%d8%b3%d8%a7%d8%a9" }, { "label": "مانجا", "value": "%d9%85%d8%a7%d9%86%d8%ac%d8%a7" }, { "label": "مانها", "value": "%d9%85%d8%a7%d9%86%d9%87%d8%a7" }, { "label": "مانهوا", "value": "%d9%85%d8%a7%d9%86%d9%87%d9%88%d8%a7" }, { "label": "مدرسي", "value": "%d9%85%d8%af%d8%b1%d8%b3%d9%8a" }, { "label": "مصاصي دماء", "value": "%d9%85%d8%b5%d8%a7%d8%b5%d9%8a-%d8%af%d9%85%d8%a7%d8%a1" }, { "label": "مغامرة", "value": "%d9%85%d8%ba%d8%a7%d9%85%d8%b1%d8%a9" }, { "label": "مكتملة", "value": "%d9%85%d9%83%d8%aa%d9%85%d9%84%d8%a9" }, { "label": "نفسي", "value": "%d9%86%d9%81%d8%b3%d9%8a" }, { "label": "نهاية العالم", "value": "%d9%86%d9%87%d8%a7%d9%8a%d8%a9-%d8%a7%d9%84%d8%b9%d8%a7%d9%84%d9%85" }, { "label": "واب تون", "value": "%d9%88%d8%a7%d8%a8-%d8%aa%d9%88%d9%86" }, { "label": "وان شوت", "value": "%d9%88%d8%a7%d9%86-%d8%b4%d9%88%d8%aa" }], "inputType": filterInputs_1.FilterInputs.Picker }];
diff --git a/js/plugins/arabic/TeamXNovel[madara].js b/js/plugins/arabic/TeamXNovel[madara].js
deleted file mode 100644
index 1f1a49d..0000000
--- a/js/plugins/arabic/TeamXNovel[madara].js
+++ /dev/null
@@ -1,178 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "teamxnovel";
-exports.name = "TeamXNovel [madara]";
-exports.icon = "multisrc/madara/icons/teamxnovel.png";
-exports.version = "1.0.0";
-exports.site = "https://teamxnovel.com/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "novel-genre/" + filters.genres + '/';
- }
- else {
- url += "novel/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (true) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [];
diff --git a/js/plugins/arabic/kolnovel.js b/js/plugins/arabic/kolnovel.js
deleted file mode 100644
index b5456f3..0000000
--- a/js/plugins/arabic/kolnovel.js
+++ /dev/null
@@ -1,244 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.icon = exports.version = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const filterInputs_1 = require("@libs/filterInputs");
-exports.id = "kolnovel";
-exports.name = "KolNovel";
-exports.version = "1.0.0";
-exports.icon = "multisrc/wpmangastream/icons/kolnovel.png";
-exports.site = "https://kolnovel.com/";
-const pluginId = exports.id;
-const baseUrl = exports.site;
-const popularNovels = function (page, { filters }) {
- return __awaiter(this, void 0, void 0, function* () {
- let link = `${baseUrl}series/?page=${page}`;
- if (filters) {
- if (Array.isArray(filters.genres) && filters.genres.length) {
- link += filters.genres.map((i) => `&genre[]=${i}`).join("");
- }
- if (Array.isArray(filters.type) && filters.type.length)
- link += filters.type.map((i) => `&lang[]=${i}`).join("");
- }
- link += "&status=" + ((filters === null || filters === void 0 ? void 0 : filters.status) ? filters.status : "");
- link += "&order=" + ((filters === null || filters === void 0 ? void 0 : filters.order) ? filters.order : "popular");
- const body = yield (0, fetch_1.fetchApi)(link, {}, pluginId).then((result) => result.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const novels = [];
- loadedCheerio("article.maindet").each(function () {
- const novelName = loadedCheerio(this).find("h2").text();
- let image = loadedCheerio(this).find("img");
- const novelCover = image.attr("data-src") || image.attr("src");
- const novelUrl = loadedCheerio(this).find("h2 a").attr("href");
- if (!novelUrl)
- return;
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function parseNovelAndChapters(novelUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = novelUrl;
- const result = yield (0, fetch_1.fetchApi)(url, {}, pluginId);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- const novel = {
- url,
- chapters: [],
- };
- novel.name = loadedCheerio("h1.entry-title").text();
- novel.cover =
- loadedCheerio("img.wp-post-image").attr("data-src") ||
- loadedCheerio("img.wp-post-image").attr("src");
- loadedCheerio("div.serl:nth-child(3) > span").each(function () {
- const detailName = loadedCheerio(this).text().trim();
- const detail = loadedCheerio(this).next().text().trim();
- switch (detailName) {
- case "الكاتب":
- case "Author":
- novel.author = detail;
- break;
- }
- });
- novel.status = loadedCheerio("div.sertostat > span").attr("class");
- novel.genres = loadedCheerio(".sertogenre")
- .children("a")
- .map((i, el) => loadedCheerio(el).text())
- .toArray()
- .join(",");
- novel.summary = loadedCheerio(".sersys")
- .find("br")
- .replaceWith("\n")
- .end()
- .text();
- let chapter = [];
- loadedCheerio(".eplister")
- .find("li")
- .each(function () {
- const chapterName = loadedCheerio(this).find(".epl-num").text() +
- " - " +
- loadedCheerio(this).find(".epl-title").text();
- const releaseDate = loadedCheerio(this)
- .find(".epl-date")
- .text()
- .trim();
- const chapterUrl = loadedCheerio(this).find("a").attr("href");
- if (!chapterUrl)
- return;
- chapter.push({
- name: chapterName,
- releaseTime: releaseDate,
- url: chapterUrl,
- });
- });
- novel.chapters = chapter.reverse();
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function parseChapter(chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const result = yield (0, fetch_1.fetchApi)(chapterUrl, {}, pluginId);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- let ignore = loadedCheerio(".epcontent > p").next().attr("class");
- loadedCheerio(`p.${ignore}`).remove();
- let chapterText = loadedCheerio(".epcontent").html();
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function searchNovels(searchTerm) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = `${baseUrl}?s=${searchTerm}`;
- const result = yield (0, fetch_1.fetchApi)(url, {}, pluginId);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- const novels = [];
- loadedCheerio("article.maindet").each(function () {
- const novelName = loadedCheerio(this).find("h2").text();
- let image = loadedCheerio(this).find("img");
- const novelCover = image.attr("data-src") || image.attr("src");
- const novelUrl = loadedCheerio(this).find("h2 a").attr("href");
- if (!novelUrl)
- return;
- novels.push({
- name: novelName,
- url: novelUrl,
- cover: novelCover,
- });
- });
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-const fetchImage = function fetchImage(url) {
- return __awaiter(this, void 0, void 0, function* () {
- const headers = {
- Referer: baseUrl,
- };
- return yield (0, fetch_1.fetchFile)(url, { headers: headers });
- });
-};
-exports.fetchImage = fetchImage;
-exports.filters = [
- {
- key: "order",
- label: "ترتيب حسب",
- values: [
- { label: "الإعداد الأولي", value: "" },
- { label: "A-Z", value: "title" },
- { label: "Z-A", value: "titlereverse" },
- { label: "أخر التحديثات", value: "update" },
- { label: "أخر ما تم إضافته", value: "latest" },
- { label: "الرائجة", value: "popular" },
- ],
- inputType: filterInputs_1.FilterInputs.Picker,
- },
- {
- key: "status",
- label: "الحالة",
- values: [
- { label: "All", value: "" },
- { label: "Ongoing", value: "ongoing" },
- { label: "Hiatus", value: "hiatus" },
- { label: "Completed", value: "completed" },
- ],
- inputType: filterInputs_1.FilterInputs.Picker,
- },
- {
- key: "type",
- label: "النوع",
- values: [
- { label: "إنجليزية", value: "english" },
- { label: "روايةلايت", value: "light-novel" },
- { label: "روايةويب", value: "web-novel" },
- { label: "صينية", value: "chinese" },
- { label: "عربية", value: "arabic" },
- { label: "كورية", value: "korean" },
- { label: "يابانية", value: "japanese" },
- ],
- inputType: filterInputs_1.FilterInputs.Checkbox,
- },
- {
- key: "genres",
- label: "تصنيف",
- values: [
- { label: "Wuxia", value: "wuxia" },
- { label: "Xianxia", value: "xianxia" },
- { label: "XUANHUAN", value: "xuanhuan" },
- { label: "أكشن", value: "action" },
- { label: "إثارة", value: "excitement" },
- { label: "إنتقالالىعالمأخر", value: "isekai" },
- { label: "إيتشي", value: "etchi" },
- { label: "الخيالالعلمي", value: "sci-fi" },
- { label: "بوليسي", value: "policy" },
- { label: "تاريخي", value: "historical" },
- { label: "تحقيقات", value: "%d8%aa%d8%ad%d9%82%d9%8a%d9%82" },
- { label: "تقمصشخصيات", value: "rpg" },
- { label: "جريمة", value: "crime" },
- { label: "جوسى", value: "josei" },
- { label: "حريم", value: "harem" },
- { label: "حياةمدرسية", value: "school-life" },
- { label: "خيالي(فانتازيا)", value: "fantasy" },
- { label: "دراما", value: "drama" },
- { label: "رعب", value: "horror" },
- { label: "رومانسي", value: "romantic" },
- { label: "سحر", value: "magic" },
- { label: "سينن", value: "senen" },
- { label: "شريحةمنالحياة", value: "slice-of-life" },
- { label: "شوجو", value: "shojo" },
- { label: "شونين", value: "shonen" },
- { label: "طبي", value: "medical" },
- { label: "ظواهرخارقةللطبيعة", value: "supernatural" },
- { label: "غموض", value: "mysteries" },
- { label: "فنونالقتال", value: "martial-arts" },
- { label: "قوىخارقة", value: "superpower" },
- { label: "كوميدي", value: "comedy" },
- { label: "مأساوي", value: "tragedy" },
- { label: "مابعدالكارثة", value: "after-the-disaster" },
- { label: "مغامرة", value: "adventure" },
- { label: "ميكا", value: "mechanical" },
- { label: "ناضج", value: "mature" },
- { label: "نفسي", value: "psychological" },
- ],
- inputType: filterInputs_1.FilterInputs.Checkbox,
- },
-];
diff --git a/js/plugins/english/BoxNovel[madara].js b/js/plugins/english/BoxNovel[madara].js
deleted file mode 100644
index 257fad8..0000000
--- a/js/plugins/english/BoxNovel[madara].js
+++ /dev/null
@@ -1,179 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const filterInputs_1 = require("@libs/filterInputs");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "boxnovel";
-exports.name = "BoxNovel [madara]";
-exports.icon = "multisrc/madara/icons/boxnovel.png";
-exports.version = "1.0.0";
-exports.site = "https://boxnovel.com/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "manga-genre/" + filters.genres + '/';
- }
- else {
- url += "novel/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (true) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": filterInputs_1.FilterInputs.Picker }, { "key": "genres", "label": "GENRES", "values": [{ "label": "Action", "value": "action" }, { "label": "Adventure", "value": "adventure" }, { "label": "Comedy", "value": "comedy" }, { "label": "Drama", "value": "drama" }, { "label": "Ecchi", "value": "ecchi" }, { "label": "Fantasy", "value": "fantasy" }, { "label": "Gender Bender", "value": "gender-bender" }, { "label": "Harem", "value": "harem" }, { "label": "Historical", "value": "historical" }, { "label": "Horror", "value": "horror" }, { "label": "Josei", "value": "josei" }, { "label": "Martial Arts", "value": "martial-arts" }, { "label": "Mature", "value": "mature" }, { "label": "Mecha", "value": "mecha" }, { "label": "Mystery", "value": "mystery" }, { "label": "Psychological", "value": "psychological" }, { "label": "Romance", "value": "romance" }, { "label": "School Life", "value": "school-life" }, { "label": "Sci-fi", "value": "sci-fi" }, { "label": "Seinen", "value": "seinen" }, { "label": "Shoujo", "value": "shoujo" }, { "label": "Shounen", "value": "shounen" }, { "label": "Slice of Life", "value": "slice-of-life" }, { "label": "Smut", "value": "smut" }, { "label": "Sports", "value": "sports" }, { "label": "Supernatural", "value": "supernatural" }, { "label": "Tragedy", "value": "tragedy" }, { "label": "Wuxia", "value": "wuxia" }, { "label": "Xianxia", "value": "xianxia" }, { "label": "Xuanhuan", "value": "xuanhuan" }, { "label": "Yaoi", "value": "yaoi" }], "inputType": filterInputs_1.FilterInputs.Picker }];
diff --git a/js/plugins/english/ClickNovel[madara].js b/js/plugins/english/ClickNovel[madara].js
deleted file mode 100644
index c70ec04..0000000
--- a/js/plugins/english/ClickNovel[madara].js
+++ /dev/null
@@ -1,178 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "clicknovel";
-exports.name = "ClickNovel [madara]";
-exports.icon = "multisrc/madara/icons/clicknovel.png";
-exports.version = "1.0.0";
-exports.site = "https://clicknovel.net/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "novel-genre/" + filters.genres + '/';
- }
- else {
- url += "novel/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (false) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [];
diff --git a/js/plugins/english/CrateNovel[madara].js b/js/plugins/english/CrateNovel[madara].js
deleted file mode 100644
index 7e684fe..0000000
--- a/js/plugins/english/CrateNovel[madara].js
+++ /dev/null
@@ -1,178 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "cratenovel";
-exports.name = "CrateNovel [madara]";
-exports.icon = "multisrc/madara/icons/cratenovel.png";
-exports.version = "1.0.0";
-exports.site = "https://cratenovel.com/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "novel-genre/" + filters.genres + '/';
- }
- else {
- url += "novel/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (true) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [];
diff --git a/js/plugins/english/DaoNovel[madara].js b/js/plugins/english/DaoNovel[madara].js
deleted file mode 100644
index 9fe4fa1..0000000
--- a/js/plugins/english/DaoNovel[madara].js
+++ /dev/null
@@ -1,179 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const filterInputs_1 = require("@libs/filterInputs");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "daonovel";
-exports.name = "DaoNovel [madara]";
-exports.icon = "multisrc/madara/icons/daonovel.png";
-exports.version = "1.0.0";
-exports.site = "https://daonovel.com/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "novel-genre/" + filters.genres + '/';
- }
- else {
- url += "novels-list/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (true) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "novels" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": filterInputs_1.FilterInputs.Picker }];
diff --git a/js/plugins/english/FansTranslations[madara].js b/js/plugins/english/FansTranslations[madara].js
deleted file mode 100644
index 80e7d3e..0000000
--- a/js/plugins/english/FansTranslations[madara].js
+++ /dev/null
@@ -1,179 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const filterInputs_1 = require("@libs/filterInputs");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "fanTLS";
-exports.name = "Fans Translations [madara]";
-exports.icon = "multisrc/madara/icons/fanstranslations.png";
-exports.version = "1.0.0";
-exports.site = "https://fanstranslations.com/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "novel-genre/" + filters.genres + '/';
- }
- else {
- url += "novel/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (true) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": filterInputs_1.FilterInputs.Picker }];
diff --git a/js/plugins/english/FirstKissNovel[madara].js b/js/plugins/english/FirstKissNovel[madara].js
deleted file mode 100644
index adac694..0000000
--- a/js/plugins/english/FirstKissNovel[madara].js
+++ /dev/null
@@ -1,179 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const filterInputs_1 = require("@libs/filterInputs");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "1stkissnovel";
-exports.name = "FirstKissNovel [madara]";
-exports.icon = "multisrc/madara/icons/firstkissnovel.png";
-exports.version = "1.0.0";
-exports.site = "https://1stkissnovel.org/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "novel-genre/" + filters.genres + '/';
- }
- else {
- url += "novel/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (true) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": filterInputs_1.FilterInputs.Picker }, { "key": "genres", "label": "GENRES", "values": [{ "label": "Action", "value": "action" }, { "label": "Adult", "value": "adult" }, { "label": "Adventure", "value": "adventure" }, { "label": "Anime", "value": "anime" }, { "label": "Apocalypse", "value": "apocalypse" }, { "label": "Boy's Love", "value": "boys-love" }, { "label": "Comedy", "value": "comedy" }, { "label": "Completed", "value": "completed" }, { "label": "Cooking", "value": "cooking" }, { "label": "Demons", "value": "demons" }, { "label": "Detective", "value": "detective" }, { "label": "Drama", "value": "drama" }, { "label": "Ecchi", "value": "ecchi" }, { "label": "Fan-Fiction", "value": "fan-fiction" }, { "label": "Fantasy", "value": "fantasy" }, { "label": "Food", "value": "food" }, { "label": "Game", "value": "game" }, { "label": "Gender Bender", "value": "gender-bender" }, { "label": "Girls Love", "value": "girls-love" }, { "label": "Harem", "value": "harem" }, { "label": "Historical", "value": "historical" }, { "label": "Horror", "value": "horror" }, { "label": "Humor", "value": "humor" }, { "label": "Isekai", "value": "isekai" }, { "label": "Josei", "value": "josei" }, { "label": "Magic", "value": "magic" }, { "label": "Magical", "value": "magical" }, { "label": "Manhua", "value": "manhua" }, { "label": "Manhwa", "value": "manhwa" }, { "label": "Martial Arts", "value": "martial-arts" }, { "label": "Mature", "value": "mature" }, { "label": "Mecha", "value": "mecha" }, { "label": "Medical", "value": "medical" }, { "label": "Military", "value": "military" }, { "label": "Moder", "value": "moder" }, { "label": "Modern", "value": "modern" }, { "label": "Murim", "value": "murim" }, { "label": "Music", "value": "music" }, { "label": "Mystery", "value": "mystery" }, { "label": "Psychological", "value": "psychological" }, { "label": "Reverse", "value": "reverse" }, { "label": "Reverse harem", "value": "reverse-harem" }, { "label": "Romance", "value": "romance" }, { "label": "School Life", "value": "school-life" }, { "label": "Sci-fi", "value": "sci-fi" }, { "label": "Seinen", "value": "seinen" }, { "label": "Shoujo", "value": "shoujo" }, { "label": "Shoujo Ai", "value": "shoujo-ai" }, { "label": "Shounen", "value": "shounen" }, { "label": "Shounen Ai", "value": "shounen-ai" }, { "label": "Slice of Life", "value": "slice-of-life" }, { "label": "Smut", "value": "smut" }, { "label": "Sports", "value": "sports" }, { "label": "Super power", "value": "super-power" }, { "label": "Superhero", "value": "superhero" }, { "label": "Supernatural", "value": "supernatural" }, { "label": "Thriller", "value": "thriller" }, { "label": "Tragedy", "value": "tragedy" }, { "label": "Urban Life", "value": "urban-life" }, { "label": "Vampire", "value": "vampire" }, { "label": "Webtoons", "value": "webtoons" }, { "label": "Wuxia", "value": "wuxia" }, { "label": "Xianxia", "value": "xianxia" }, { "label": "Xuanhuan", "value": "xuanhuan" }, { "label": "Yaoi", "value": "yaoi" }, { "label": "Yuri", "value": "yuri" }], "inputType": filterInputs_1.FilterInputs.Picker }];
diff --git a/js/plugins/english/FreeNovelMe[madara].js b/js/plugins/english/FreeNovelMe[madara].js
deleted file mode 100644
index 46a40d1..0000000
--- a/js/plugins/english/FreeNovelMe[madara].js
+++ /dev/null
@@ -1,179 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const filterInputs_1 = require("@libs/filterInputs");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "freenovel.me";
-exports.name = "FreeNovelMe [madara]";
-exports.icon = "multisrc/madara/icons/freenovelme.png";
-exports.version = "1.0.0";
-exports.site = "https://freenovel.me/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "novel-genre/" + filters.genres + '/';
- }
- else {
- url += "novel/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (false) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": filterInputs_1.FilterInputs.Picker }, { "key": "genres", "label": "GENRES", "values": [{ "label": "Action", "value": "action" }, { "label": "Adult", "value": "adult" }, { "label": "Adventure", "value": "adventure" }, { "label": "Cartoon", "value": "cartoon" }, { "label": "Comedy", "value": "comedy" }, { "label": "Cooking", "value": "cooking" }, { "label": "Detective", "value": "detective" }, { "label": "Drama", "value": "drama" }, { "label": "Fantasy", "value": "fantasy" }, { "label": "Game", "value": "game" }, { "label": "Gender Bender", "value": "gender-bender" }, { "label": "Historical", "value": "historical" }, { "label": "History", "value": "history" }, { "label": "Horror", "value": "horror" }, { "label": "Josei", "value": "josei" }, { "label": "Live action", "value": "live-action" }, { "label": "Martial", "value": "martial" }, { "label": "Martial Arts", "value": "martial-arts" }, { "label": "Mature", "value": "mature" }, { "label": "Mecha", "value": "mecha" }, { "label": "Mystery", "value": "mystery" }, { "label": "One shot", "value": "one-shot" }, { "label": "Premium", "value": "premium" }, { "label": "Psychological", "value": "psychological" }, { "label": "Reincarnation", "value": "reincarnation" }, { "label": "Romance", "value": "romance" }, { "label": "School Life", "value": "school-life" }, { "label": "Sci-fi", "value": "sci-fi" }, { "label": "Slice of Life", "value": "slice-of-life" }, { "label": "Smut", "value": "smut" }, { "label": "Sports", "value": "sports" }, { "label": "Supernatural", "value": "supernatural" }, { "label": "Tragedy", "value": "tragedy" }, { "label": "Wuxia", "value": "wuxia" }, { "label": "Xianxia", "value": "xianxia" }, { "label": "Xuanhuan", "value": "xuanhuan" }], "inputType": filterInputs_1.FilterInputs.Picker }];
diff --git a/js/plugins/english/Guavaread[madara].js b/js/plugins/english/Guavaread[madara].js
deleted file mode 100644
index 17b2363..0000000
--- a/js/plugins/english/Guavaread[madara].js
+++ /dev/null
@@ -1,179 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const filterInputs_1 = require("@libs/filterInputs");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "guavaread";
-exports.name = "Guavaread [madara]";
-exports.icon = "multisrc/madara/icons/guavaread.png";
-exports.version = "1.0.0";
-exports.site = "https://guavaread.com/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "novel-genre/" + filters.genres + '/';
- }
- else {
- url += "novel/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (true) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": filterInputs_1.FilterInputs.Picker }, { "key": "genres", "label": "GENRES", "values": [{ "label": "Action", "value": "action" }, { "label": "Adult", "value": "adult" }, { "label": "Adventure", "value": "adventure" }, { "label": "Comedy", "value": "comedy" }, { "label": "Complete", "value": "complete" }, { "label": "Cooking", "value": "cooking" }, { "label": "Detective", "value": "detective" }, { "label": "Drama", "value": "drama" }, { "label": "Dropped", "value": "dropped" }, { "label": "Ecchi", "value": "ecchi" }, { "label": "Fantasy", "value": "fantasy" }, { "label": "Gender Bender", "value": "gender-bender" }, { "label": "Historical", "value": "historical" }, { "label": "Horror", "value": "horror" }, { "label": "Josei", "value": "josei" }, { "label": "Mature", "value": "mature" }, { "label": "Mystery", "value": "mystery" }, { "label": "Original Story", "value": "original-story" }, { "label": "Pilot", "value": "pilot" }, { "label": "Psychological", "value": "psychological" }, { "label": "R-15", "value": "r-15" }, { "label": "R-19", "value": "r-19" }, { "label": "Reverse Harem", "value": "reverse-harem" }, { "label": "Romance", "value": "romance" }, { "label": "School Life", "value": "school-life" }, { "label": "Sci-fi", "value": "sci-fi" }, { "label": "Shoujo", "value": "shoujo" }, { "label": "Slice of Life", "value": "slice-of-life" }, { "label": "Smut", "value": "smut" }, { "label": "Supernatural", "value": "supernatural" }, { "label": "Tragedy", "value": "tragedy" }], "inputType": filterInputs_1.FilterInputs.Picker }];
diff --git a/js/plugins/english/LightNovelHeaven[madara].js b/js/plugins/english/LightNovelHeaven[madara].js
deleted file mode 100644
index ea176fb..0000000
--- a/js/plugins/english/LightNovelHeaven[madara].js
+++ /dev/null
@@ -1,179 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const filterInputs_1 = require("@libs/filterInputs");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "lnheaven";
-exports.name = "LightNovelHeaven [madara]";
-exports.icon = "multisrc/madara/icons/lightnovelheaven.png";
-exports.version = "1.0.0";
-exports.site = "https://lightnovelheaven.com/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "novel-genre/" + filters.genres + '/';
- }
- else {
- url += "series/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (true) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "series" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": filterInputs_1.FilterInputs.Picker }];
diff --git a/js/plugins/english/LightNovelReader.js b/js/plugins/english/LightNovelReader.js
deleted file mode 100644
index dfba272..0000000
--- a/js/plugins/english/LightNovelReader.js
+++ /dev/null
@@ -1,138 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const isAbsoluteUrl_1 = require("@libs/isAbsoluteUrl");
-const fetch_1 = require("@libs/fetch");
-exports.id = "LNR.org";
-exports.name = "LightNovelReader";
-exports.icon = "src/en/lightnovelreader/icon.png";
-exports.version = "1.0.0";
-exports.site = "https://lightnovelreader.org";
-const baseUrl = exports.site;
-const popularNovels = function (page) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = baseUrl + "/ranking/top-rated/" + page;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- const novels = [];
- loadedCheerio(".category-items.ranking-category.cm-list > ul > li").each(function () {
- let novelUrl = loadedCheerio(this).find("a").attr("href");
- if (novelUrl && !(0, isAbsoluteUrl_1.isUrlAbsolute)(novelUrl)) {
- novelUrl = baseUrl + novelUrl;
- }
- if (novelUrl) {
- const novelName = loadedCheerio(this)
- .find(".category-name a")
- .text()
- .trim();
- let novelCover = loadedCheerio(this)
- .find(".category-img img")
- .attr("src");
- if (novelCover && !(0, isAbsoluteUrl_1.isUrlAbsolute)(novelCover)) {
- novelCover = baseUrl + novelCover;
- }
- const novel = {
- url: novelUrl,
- name: novelName,
- cover: novelCover,
- };
- novels.push(novel);
- }
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = novelUrl;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- const novel = {
- url: novelUrl,
- chapters: [],
- };
- novel.name = loadedCheerio(".section-header-title > h2").text();
- let novelCover = loadedCheerio(".novels-detail img").attr("src");
- novel.cover = novelCover
- ? (0, isAbsoluteUrl_1.isUrlAbsolute)(novelCover)
- ? novelCover
- : baseUrl + novelCover
- : undefined;
- novel.summary = loadedCheerio("div.container > div > div.col-12.col-xl-9 > div > div:nth-child(5) > div")
- .text()
- .trim();
- novel.author = loadedCheerio("div.novels-detail-right > ul > li:nth-child(6) > .novels-detail-right-in-right > a")
- .text()
- .trim();
- novel.genres = loadedCheerio("body > section:nth-child(4) > div > div > div.col-12.col-xl-9 > div > div:nth-child(2) > div > div.novels-detail-right > ul > li:nth-child(3) > div.novels-detail-right-in-right")
- .text()
- .trim();
- novel.status = loadedCheerio("div.novels-detail-right > ul > li:nth-child(2) > .novels-detail-right-in-right")
- .text()
- .trim();
- loadedCheerio(".cm-tabs-content > ul > li").each(function () {
- var _a;
- let chapterUrl = loadedCheerio(this).find("a").attr("href");
- if (chapterUrl && !(0, isAbsoluteUrl_1.isUrlAbsolute)(chapterUrl)) {
- chapterUrl = baseUrl + chapterUrl;
- }
- if (chapterUrl) {
- const chapterName = loadedCheerio(this).find("a").text().trim();
- const releaseDate = null;
- const chapter = {
- name: chapterName,
- releaseTime: releaseDate,
- url: chapterUrl,
- };
- (_a = novel.chapters) === null || _a === void 0 ? void 0 : _a.push(chapter);
- }
- });
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = chapterUrl;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio("#chapterText").html() || "";
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = baseUrl + `/search/autocomplete?dataType=json&query=${searchTerm}`;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.json();
- const novels = [];
- body.results.forEach((item) => novels.push({
- url: item.link,
- name: item.original_title,
- cover: item.image,
- }));
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-const fetchImage = function (url) {
- return __awaiter(this, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url, {});
- });
-};
-exports.fetchImage = fetchImage;
diff --git a/js/plugins/english/Ltnovelcom[readwn].js b/js/plugins/english/Ltnovelcom[readwn].js
deleted file mode 100644
index a77c065..0000000
--- a/js/plugins/english/Ltnovelcom[readwn].js
+++ /dev/null
@@ -1,163 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-// import dayjs from 'dayjs';
-const fetch_1 = require("@libs/fetch");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-// import { isUrlAbsolute } from '@libs/isAbsoluteUrl';
-// import { showToast } from "@libs/showToast";
-const filterInputs_1 = require("@libs/filterInputs");
-// import { NovelStatus } from '@libs/novelStatus';
-// import { defaultCover } from "@libs/defaultCover";
-exports.id = "Ltnovel.com";
-exports.name = "Ltnovel.com";
-exports.icon = "multisrc/readwn/icons/ltnovel.png";
-exports.version = "1.0.0";
-exports.site = "https://www.ltnovel.com/";
-const popularNovels = function (page, { filters, showLatestNovels }) {
- return __awaiter(this, void 0, void 0, function* () {
- const novels = [];
- const pageNo = page - 1;
- let url = exports.site + 'list/';
- url += ((filters === null || filters === void 0 ? void 0 : filters.genres) || 'all') + '/';
- url += ((filters === null || filters === void 0 ? void 0 : filters.status) || 'all') + '-';
- url += (showLatestNovels ? 'lastdotime' : (filters === null || filters === void 0 ? void 0 : filters.sort) || 'newstime') + '-';
- url += pageNo + '.html';
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('li.novel-item').each(function () {
- const novelName = loadedCheerio(this).find('h4').text();
- const novelUrl = exports.site + loadedCheerio(this).find('a').attr('href');
- const coverUri = loadedCheerio(this)
- .find('.novel-cover > img')
- .attr('data-src');
- const novelCover = exports.site + coverUri;
- const novel = { name: novelName, cover: novelCover, url: novelUrl };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const result = yield (0, fetch_1.fetchApi)(novelUrl);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- const novel = {
- url: novelUrl,
- chapters: [],
- };
- novel.name = loadedCheerio('h1.novel-title').text();
- const coverUri = loadedCheerio('figure.cover > img').attr('data-src');
- novel.cover = exports.site + coverUri;
- novel.summary = loadedCheerio('.summary')
- .text()
- .replace('Summary', '')
- .trim();
- novel.genres = '';
- loadedCheerio('div.categories > ul > li').each(function () {
- novel.genres += loadedCheerio(this).text().trim() + ',';
- });
- loadedCheerio('div.header-stats > span').each(function () {
- if (loadedCheerio(this).find('small').text() === 'Status') {
- novel.status = loadedCheerio(this).find('strong').text();
- }
- });
- novel.genres = novel.genres.slice(0, -1);
- novel.author = loadedCheerio('span[itemprop=author]').text();
- let novelChapters = [];
- const novelId = novelUrl.replace('.html', '').replace(exports.site, '');
- const latestChapterNo = parseInt(loadedCheerio('.header-stats')
- .find('span > strong')
- .first()
- .text()
- .trim());
- let lastChapterNo = 1;
- loadedCheerio('.chapter-list li').each(function () {
- var _a;
- const chapterName = loadedCheerio(this)
- .find('a .chapter-title')
- .text()
- .trim();
- const chapterUrl = exports.site + ((_a = loadedCheerio(this).find('a').attr('href')) === null || _a === void 0 ? void 0 : _a.trim());
- const releaseDate = loadedCheerio(this)
- .find('a .chapter-update')
- .text()
- .trim();
- lastChapterNo = parseInt(loadedCheerio(this).find('a .chapter-no').text().trim());
- const chapter = { name: chapterName, releaseTime: (0, parseMadaraDate_1.parseMadaraDate)(releaseDate), url: chapterUrl };
- novelChapters.push(chapter);
- });
- // Itterate once more before loop to finish off
- lastChapterNo++;
- for (let i = lastChapterNo; i <= latestChapterNo; i++) {
- const chapterName = 'Chapter ' + i;
- const chapterUrl = exports.site + novelId + '_' + i + '.html';
- const releaseDate = null;
- const chapter = { name: chapterName, releaseTime: releaseDate, url: chapterUrl };
- novelChapters.push(chapter);
- }
- novel.chapters = novelChapters;
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const result = yield (0, fetch_1.fetchApi)(chapterUrl);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.chapter-content').html();
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const searchUrl = exports.site + 'e/search/index.php';
- const result = yield (0, fetch_1.fetchApi)(searchUrl, {
- headers: {
- 'Content-Type': 'application/x-www-form-urlencoded',
- Referer: exports.site + 'search.html',
- Origin: exports.site,
- 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36',
- },
- method: 'POST',
- body: JSON.stringify({
- show: 'title',
- tempid: 1,
- tbname: 'news',
- keyboard: searchTerm,
- }),
- });
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('li.novel-item').each(function () {
- const novelName = loadedCheerio(this).find('h4').text();
- const novelUrl = exports.site + loadedCheerio(this).find('a').attr('href');
- const coverUri = exports.site + loadedCheerio(this).find('img').attr('data-src');
- const novelCover = exports.site + coverUri;
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-exports.fetchImage = fetch_1.fetchFile;
-exports.filters = [{ "key": "sort", "label": "Sort By", "values": [{ "label": "New", "value": "newstime" }, { "label": "Popular", "value": "onclick" }, { "label": "Updates", "value": "lastdotime" }], "inputType": filterInputs_1.FilterInputs.Picker }, { "key": "status", "label": "Status", "values": [{ "label": "All", "value": "all" }, { "label": "Completed", "value": "Completed" }, { "label": "Ongoing", "value": "Ongoing" }], "inputType": filterInputs_1.FilterInputs.Picker }, { "key": "genres", "label": "Genre / Category", "values": [{ "label": "All", "value": "all" }, { "label": "Action", "value": "action" }, { "label": "Adult", "value": "adult" }, { "label": "Adventure", "value": "adventure" }, { "label": "Comedy", "value": "comedy" }, { "label": "Contemporary Romance", "value": "contemporary-romance" }, { "label": "Drama", "value": "drama" }, { "label": "Eastern Fantasy", "value": "eastern-fantasy" }, { "label": "Ecchi", "value": "ecchi" }, { "label": "Fantasy", "value": "fantasy" }, { "label": "Fantasy Romance", "value": "fantasy-romance" }, { "label": "Game", "value": "game" }, { "label": "Gender Bender", "value": "gender-bender" }, { "label": "Harem", "value": "harem" }, { "label": "Historical", "value": "historical" }, { "label": "Horror", "value": "horror" }, { "label": "Josei", "value": "josei" }, { "label": "Lolicon", "value": "lolicon" }, { "label": "Magical Realism", "value": "magical-realism" }, { "label": "Martial Arts", "value": "martial-arts" }, { "label": "Mature", "value": "mature" }, { "label": "Mecha", "value": "mecha" }, { "label": "Mystery", "value": "mystery" }, { "label": "Psychological", "value": "psychological" }, { "label": "Romance", "value": "romance" }, { "label": "School Life", "value": "school-life" }, { "label": "Sci-fi", "value": "sci-fi" }, { "label": "Seinen", "value": "seinen" }, { "label": "Shoujo", "value": "shoujo" }, { "label": "Shounen", "value": "shounen" }, { "label": "Shounen Ai", "value": "shounen-ai" }, { "label": "Slice of Life", "value": "slice-of-life" }, { "label": "Smut", "value": "smut" }, { "label": "Sports", "value": "sports" }, { "label": "Supernatural", "value": "supernatural" }, { "label": "Tragedy", "value": "tragedy" }, { "label": "Video Games", "value": "video-games" }, { "label": "Wuxia", "value": "wuxia" }, { "label": "Xianxia", "value": "xianxia" }, { "label": "Xuanhuan", "value": "xuanhuan" }, { "label": "Yaoi", "value": "yaoi" }], "inputType": filterInputs_1.FilterInputs.Picker }];
diff --git a/js/plugins/english/LunarLetters[madara].js b/js/plugins/english/LunarLetters[madara].js
deleted file mode 100644
index cced74e..0000000
--- a/js/plugins/english/LunarLetters[madara].js
+++ /dev/null
@@ -1,179 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const filterInputs_1 = require("@libs/filterInputs");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "lunarletters";
-exports.name = "LunarLetters [madara]";
-exports.icon = "multisrc/madara/icons/lunarletters.png";
-exports.version = "1.0.0";
-exports.site = "https://www.lunarletters.com/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "novel-genre/" + filters.genres + '/';
- }
- else {
- url += "series/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (true) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "series" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": filterInputs_1.FilterInputs.Picker }];
diff --git a/js/plugins/english/MTLNovelClub[madara].js b/js/plugins/english/MTLNovelClub[madara].js
deleted file mode 100644
index a4def16..0000000
--- a/js/plugins/english/MTLNovelClub[madara].js
+++ /dev/null
@@ -1,178 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "mtlnovel.club";
-exports.name = "MTLNovel.Club [madara]";
-exports.icon = "multisrc/madara/icons/mtlnovel.club.png";
-exports.version = "1.0.0";
-exports.site = "https://mtlnovel.club/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "novel-genre/" + filters.genres + '/';
- }
- else {
- url += "novel/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (true) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [];
diff --git a/js/plugins/english/MTLNovel[madara].js b/js/plugins/english/MTLNovel[madara].js
deleted file mode 100644
index 06cf5f5..0000000
--- a/js/plugins/english/MTLNovel[madara].js
+++ /dev/null
@@ -1,179 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const filterInputs_1 = require("@libs/filterInputs");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "mtl-novel";
-exports.name = "MTL-Novel [madara]";
-exports.icon = "multisrc/madara/icons/mtl-novel.png";
-exports.version = "1.0.0";
-exports.site = "https://mtl-novel.com/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "manga-genre/" + filters.genres + '/';
- }
- else {
- url += "novel/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (true) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": filterInputs_1.FilterInputs.Picker }, { "key": "genres", "label": "GENRES", "values": [{ "label": "Action", "value": "action" }, { "label": "Adult", "value": "adult" }, { "label": "Adventure", "value": "adventure" }, { "label": "Chinese", "value": "chinese" }, { "label": "Comedy", "value": "comedy" }, { "label": "Conan", "value": "conan" }, { "label": "Drama", "value": "drama" }, { "label": "Erciyuan", "value": "erciyuan" }, { "label": "Fairy Tail", "value": "fairy-tail" }, { "label": "Faloo", "value": "faloo" }, { "label": "Fan-Fiction", "value": "fan-fiction" }, { "label": "Fantasy", "value": "fantasy" }, { "label": "FoodWars!", "value": "foodwars" }, { "label": "Game", "value": "game" }, { "label": "Gender Bender", "value": "gender-bender" }, { "label": "Harem", "value": "harem" }, { "label": "Historical", "value": "historical" }, { "label": "Horror", "value": "horror" }, { "label": "Hunter x Hunter", "value": "hunter-x-hunter" }, { "label": "Japanese", "value": "japanese" }, { "label": "Jojo", "value": "jojo" }, { "label": "Josei", "value": "josei" }, { "label": "Korean", "value": "korean" }, { "label": "Martial Arts", "value": "martial-arts" }, { "label": "Marvel", "value": "marvel" }, { "label": "Mature", "value": "mature" }, { "label": "Mecha", "value": "mecha" }, { "label": "Military", "value": "military" }, { "label": "Mystery", "value": "mystery" }, { "label": "Naruto", "value": "naruto" }, { "label": "One piece", "value": "one-piece" }, { "label": "Pokemon", "value": "pokemon" }, { "label": "Psychological", "value": "psychological" }, { "label": "Romance", "value": "romance" }, { "label": "School Life", "value": "school-life" }, { "label": "Sci-fi", "value": "sci-fi" }, { "label": "Seinen", "value": "seinen" }, { "label": "Shoujo", "value": "shoujo" }, { "label": "Shoujo Ai", "value": "shoujo-ai" }, { "label": "Shounen Ai", "value": "shounen-ai" }, { "label": "Slice of Life", "value": "slice-of-life" }, { "label": "Smut", "value": "smut" }, { "label": "Sport", "value": "sport" }, { "label": "Sports", "value": "sports" }, { "label": "Supernatural", "value": "supernatural" }, { "label": "System", "value": "system" }, { "label": "Tragedy", "value": "tragedy" }, { "label": "Urban", "value": "urban" }, { "label": "Urban Life", "value": "urban-life" }, { "label": "Wuxia", "value": "wuxia" }, { "label": "Xianxia", "value": "xianxia" }, { "label": "Xuanhuan", "value": "xuanhuan" }, { "label": "Yaoi", "value": "yaoi" }, { "label": "Yuri", "value": "yuri" }], "inputType": filterInputs_1.FilterInputs.Picker }];
diff --git a/js/plugins/english/MostNovel[madara].js b/js/plugins/english/MostNovel[madara].js
deleted file mode 100644
index 01e2c17..0000000
--- a/js/plugins/english/MostNovel[madara].js
+++ /dev/null
@@ -1,179 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const filterInputs_1 = require("@libs/filterInputs");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "mostnovel";
-exports.name = "MostNovel [madara]";
-exports.icon = "multisrc/madara/icons/mostnovel.png";
-exports.version = "1.0.0";
-exports.site = "https://mostnovel.com/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "manga-genre/" + filters.genres + '/';
- }
- else {
- url += "manga/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (false) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "manga" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": filterInputs_1.FilterInputs.Picker }, { "key": "genres", "label": "GENRES", "values": [{ "label": "ACG", "value": "acg" }, { "label": "Action", "value": "action" }, { "label": "Adult", "value": "adult" }, { "label": "Adventure", "value": "adventure" }, { "label": "AGA", "value": "aga" }, { "label": "Anime", "value": "anime" }, { "label": "Anime & Comics", "value": "anime-comics" }, { "label": "Bender", "value": "bender" }, { "label": "BL", "value": "bl" }, { "label": "Cartoon", "value": "cartoon" }, { "label": "Comedy", "value": "comedy" }, { "label": "Comic", "value": "comic" }, { "label": "Contemporary Romance", "value": "contemporary-romance" }, { "label": "Cooking", "value": "cooking" }, { "label": "Cultivation", "value": "cultivation" }, { "label": "Detective", "value": "detective" }, { "label": "Doujinshi", "value": "doujinshi" }, { "label": "Drama", "value": "drama" }, { "label": "Eastern Fantasy", "value": "eastern-fantasy" }, { "label": "Ecchi", "value": "ecchi" }, { "label": "Fantasy", "value": "fantasy" }, { "label": "Gender Bender", "value": "gender-bender" }, { "label": "Harem", "value": "harem" }, { "label": "Historical", "value": "historical" }, { "label": "Horror", "value": "horror" }, { "label": "Horror&Thriller", "value": "horrorthriller" }, { "label": "Josei", "value": "josei" }, { "label": "Live action", "value": "live-action" }, { "label": "Magical Realism", "value": "magical-realism" }, { "label": "Manga", "value": "manga" }, { "label": "Manhua", "value": "manhua" }, { "label": "Manhwa", "value": "manhwa" }, { "label": "Martial Arts", "value": "martial-arts" }, { "label": "Mature", "value": "mature" }, { "label": "Mecha", "value": "mecha" }, { "label": "Modern", "value": "modern" }, { "label": "Movies", "value": "movies" }, { "label": "Mystery", "value": "mystery" }, { "label": "One shot", "value": "one-shot" }, { "label": "Psychological", "value": "psychological" }, { "label": "Romance", "value": "romance" }, { "label": "School Life", "value": "school-life" }, { "label": "Sci-fi", "value": "sci-fi" }, { "label": "Seinen", "value": "seinen" }, { "label": "Shoujo", "value": "shoujo" }, { "label": "Shoujo Ai", "value": "shoujo-ai" }, { "label": "Shounen", "value": "shounen" }, { "label": "Shounen Ai", "value": "shounen-ai" }, { "label": "Slice of Life", "value": "slice-of-life" }, { "label": "Smart MC", "value": "smart-mc" }, { "label": "Smut", "value": "smut" }, { "label": "Soft Yaoi", "value": "soft-yaoi" }, { "label": "Soft Yuri", "value": "soft-yuri" }, { "label": "Sports", "value": "sports" }, { "label": "Supernatural", "value": "supernatural" }, { "label": "Tragedy", "value": "tragedy" }, { "label": "Urban Life", "value": "urban-life" }, { "label": "Video Games", "value": "video-games" }, { "label": "Webtoon", "value": "webtoon" }, { "label": "Wuxia", "value": "wuxia" }, { "label": "Xianxia", "value": "xianxia" }, { "label": "Xuanhuan", "value": "xuanhuan" }, { "label": "Yaoi", "value": "yaoi" }, { "label": "Yuri", "value": "yuri" }], "inputType": filterInputs_1.FilterInputs.Picker }];
diff --git a/js/plugins/english/MysticalSeries[madara].js b/js/plugins/english/MysticalSeries[madara].js
deleted file mode 100644
index 7d41355..0000000
--- a/js/plugins/english/MysticalSeries[madara].js
+++ /dev/null
@@ -1,179 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const filterInputs_1 = require("@libs/filterInputs");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "mysticalmerries";
-exports.name = "MysticalSeries [madara]";
-exports.icon = "multisrc/madara/icons/mysticalseries.png";
-exports.version = "1.0.0";
-exports.site = "https://mysticalmerries.com/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "genre/" + filters.genres + '/';
- }
- else {
- url += "series/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (true) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "series" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": filterInputs_1.FilterInputs.Picker }, { "key": "genres", "label": "GENRES", "values": [{ "label": "Action", "value": "action" }, { "label": "Adaptation", "value": "adaptation" }, { "label": "Adventure", "value": "adventure" }, { "label": "bilibili", "value": "bilibili" }, { "label": "Chinese Novel", "value": "chinese-novel" }, { "label": "Comedy", "value": "comedy" }, { "label": "Crossdressing", "value": "crossdressing" }, { "label": "Drama", "value": "drama" }, { "label": "Dropped", "value": "dropped" }, { "label": "Family", "value": "family" }, { "label": "Fantasy", "value": "fantasy" }, { "label": "Gender Bender", "value": "gender-bender" }, { "label": "Historical", "value": "historical" }, { "label": "Horror", "value": "horror" }, { "label": "Isekai", "value": "isekai" }, { "label": "Korean Novel", "value": "korean-novell" }, { "label": "Manga", "value": "manga" }, { "label": "Manhua", "value": "manhua" }, { "label": "Manhwa", "value": "manhwa" }, { "label": "Modern Romance", "value": "modern-romance" }, { "label": "Mystery", "value": "mystery" }, { "label": "Office Workers", "value": "office-workers" }, { "label": "One shot", "value": "one-shot" }, { "label": "Pilot Novel", "value": "pilot-novel" }, { "label": "R15", "value": "r15" }, { "label": "R19", "value": "r19" }, { "label": "Regression", "value": "regression" }, { "label": "Reincarnation", "value": "reincarnation" }, { "label": "Reverse Harem", "value": "reverse-harem" }, { "label": "Romance Fantasy", "value": "romance-fantasy" }, { "label": "School Life", "value": "school-life" }, { "label": "Sci-fi", "value": "sci-fi" }, { "label": "Slice of Life", "value": "slice-of-life" }, { "label": "Smut", "value": "smut" }, { "label": "Supernatural", "value": "supernatural" }, { "label": "Violence", "value": "violence" }], "inputType": filterInputs_1.FilterInputs.Picker }];
diff --git a/js/plugins/english/NeoSekaiTranslations[madara].js b/js/plugins/english/NeoSekaiTranslations[madara].js
deleted file mode 100644
index fd273cd..0000000
--- a/js/plugins/english/NeoSekaiTranslations[madara].js
+++ /dev/null
@@ -1,179 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const filterInputs_1 = require("@libs/filterInputs");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "neosekaiTLS";
-exports.name = "NeoSekai Translations [madara]";
-exports.icon = "multisrc/madara/icons/neosekaitranslations.png";
-exports.version = "1.0.0";
-exports.site = "https://www.neosekaitranslations.com/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "novel-genre/" + filters.genres + '/';
- }
- else {
- url += "novel/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (false) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": filterInputs_1.FilterInputs.Picker }, { "key": "genres", "label": "GENRES", "values": [{ "label": "Action", "value": "action" }, { "label": "Adventure", "value": "adventure" }, { "label": "Comedy", "value": "comedy" }, { "label": "Drama", "value": "drama" }, { "label": "Fantasy", "value": "fantasy" }, { "label": "Harem", "value": "harem" }, { "label": "Horror", "value": "horror" }, { "label": "Mature", "value": "mature" }, { "label": "Mecha", "value": "mecha" }, { "label": "Mystery", "value": "mystery" }, { "label": "Psychological", "value": "psychological" }, { "label": "Romance", "value": "romance" }, { "label": "School Life", "value": "school-life" }, { "label": "Sci-Fi", "value": "sci-fi" }, { "label": "Slice of Life", "value": "slice-of-life" }], "inputType": filterInputs_1.FilterInputs.Picker }];
diff --git a/js/plugins/english/NocturneTranslations[madara].js b/js/plugins/english/NocturneTranslations[madara].js
deleted file mode 100644
index 5c1d516..0000000
--- a/js/plugins/english/NocturneTranslations[madara].js
+++ /dev/null
@@ -1,179 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const filterInputs_1 = require("@libs/filterInputs");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "nocturneTLS";
-exports.name = "Nocturne Translations [madara]";
-exports.icon = "multisrc/madara/icons/nocturnetranslations.png";
-exports.version = "1.0.0";
-exports.site = "https://nocturnetls.net/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "manga-genre/" + filters.genres + '/';
- }
- else {
- url += "novels/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (false) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "novels" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": filterInputs_1.FilterInputs.Picker }, { "key": "genres", "label": "GENRES", "values": [{ "label": "Action", "value": "action" }, { "label": "Adult", "value": "adult" }, { "label": "Adventure", "value": "adventure" }, { "label": "Anime", "value": "anime" }, { "label": "Cartoon", "value": "cartoon" }, { "label": "Comedy", "value": "comedy" }, { "label": "Comic", "value": "comic" }, { "label": "Cooking", "value": "cooking" }, { "label": "Detective", "value": "detective" }, { "label": "Doujinshi", "value": "doujinshi" }, { "label": "Drama", "value": "drama" }, { "label": "Ecchi", "value": "ecchi" }, { "label": "Fantasy", "value": "fantasy" }, { "label": "Gender Bender", "value": "gender-bender" }, { "label": "Harem", "value": "harem" }, { "label": "Historical", "value": "historical" }, { "label": "Horror", "value": "horror" }, { "label": "Josei", "value": "josei" }, { "label": "Live action", "value": "live-action" }, { "label": "Manga", "value": "manga" }, { "label": "Manhua", "value": "manhua" }, { "label": "Manhwa", "value": "manhwa" }, { "label": "Martial Arts", "value": "martial-arts" }, { "label": "Mature", "value": "mature" }, { "label": "Mecha", "value": "mecha" }, { "label": "Mystery", "value": "mystery" }, { "label": "One shot", "value": "one-shot" }, { "label": "Psychological", "value": "psychological" }, { "label": "Romance", "value": "romance" }, { "label": "School Life", "value": "school-life" }, { "label": "Sci-fi", "value": "sci-fi" }, { "label": "Seinen", "value": "seinen" }, { "label": "Shoujo", "value": "shoujo" }, { "label": "Shoujo Ai", "value": "shoujo-ai" }, { "label": "Shounen", "value": "shounen" }, { "label": "Shounen Ai", "value": "shounen-ai" }, { "label": "Slice of Life", "value": "slice-of-life" }, { "label": "Smut", "value": "smut" }, { "label": "Soft Yaoi", "value": "soft-yaoi" }, { "label": "Soft Yuri", "value": "soft-yuri" }, { "label": "Sports", "value": "sports" }, { "label": "Supernatural", "value": "supernatural" }, { "label": "Tragedy", "value": "tragedy" }, { "label": "Webtoon", "value": "webtoon" }, { "label": "Yaoi", "value": "yaoi" }, { "label": "Yuri", "value": "yuri" }], "inputType": filterInputs_1.FilterInputs.Picker }];
diff --git a/js/plugins/english/NoobchanTranslation[madara].js b/js/plugins/english/NoobchanTranslation[madara].js
deleted file mode 100644
index 1e1ced7..0000000
--- a/js/plugins/english/NoobchanTranslation[madara].js
+++ /dev/null
@@ -1,178 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "noobchanTL";
-exports.name = "Noobchan Translation [madara]";
-exports.icon = "multisrc/madara/icons/noobchantranslation.png";
-exports.version = "1.0.0";
-exports.site = "https://noobchan.xyz/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "novel-genre/" + filters.genres + '/';
- }
- else {
- url += "novel/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (true) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [];
diff --git a/js/plugins/english/NovelFullMe.js b/js/plugins/english/NovelFullMe.js
deleted file mode 100644
index 5c2345a..0000000
--- a/js/plugins/english/NovelFullMe.js
+++ /dev/null
@@ -1,131 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.icon = exports.version = exports.site = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-exports.id = "NF.me";
-exports.name = "NovelFull.me";
-exports.site = "https://novelfull.me/";
-exports.version = "1.0.0";
-exports.icon = "src/en/novelfullme/icon.png";
-const baseUrl = exports.site;
-const popularNovels = function (page) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = `${baseUrl}popular?page=${page}`;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio(".book-item").each(function () {
- var _a;
- const novelName = loadedCheerio(this).find(".title").text();
- const novelCover = "https:" + loadedCheerio(this).find("img").attr("data-src");
- const novelUrl = baseUrl +
- ((_a = loadedCheerio(this).find(".title a").attr("href")) === null || _a === void 0 ? void 0 : _a.substring(1));
- const novel = { name: novelName, cover: novelCover, url: novelUrl };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- var _a, _b;
- return __awaiter(this, void 0, void 0, function* () {
- const url = novelUrl;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- let novel = {
- url,
- name: "",
- cover: "",
- author: "",
- status: "",
- genres: "",
- summary: "",
- chapters: [],
- };
- novel.name = loadedCheerio(".name h1").text().trim();
- novel.cover =
- "https:" + loadedCheerio(".img-cover img").attr("data-src");
- novel.summary = loadedCheerio("body > div.layout > div.main-container.book-details > div > div.row.no-gutters > div.col-lg-8 > div.mt-1 > div.section.box.mt-1.summary > div.section-body > p.content")
- .text()
- .trim();
- novel.author = "Unknown";
- novel.status = (_a = loadedCheerio("body > div.layout > div.main-container.book-details > div > div.row.no-gutters > div.col-lg-8 > div.book-info > div.detail > div.meta.box.mt-1.p-10 > p:nth-child(1) > a > span")
- .text()) === null || _a === void 0 ? void 0 : _a.trim();
- novel.genres = (_b = loadedCheerio("body > div.layout > div.main-container.book-details > div > div.row.no-gutters > div.col-lg-8 > div.book-info > div.detail > div.meta.box.mt-1.p-10 > p:nth-child(2)")
- .text()) === null || _b === void 0 ? void 0 : _b.replace("Genres :", "").replace(/[\s\n]+/g, " ").trim();
- let chapters = [];
- const chaptersUrl = novelUrl.replace(baseUrl, "https://novelfull.me/api/novels/") +
- "/chapters?source=detail";
- const chaptersRequest = yield (0, fetch_1.fetchApi)(chaptersUrl);
- const chaptersHtml = yield chaptersRequest.text();
- loadedCheerio = (0, cheerio_1.load)(chaptersHtml);
- loadedCheerio("li").each(function () {
- const chapterName = loadedCheerio(this)
- .find(".chapter-title")
- .text()
- .trim();
- const releaseDate = loadedCheerio(this)
- .find(".chapter-update")
- .text()
- .trim();
- const chapterUrl = loadedCheerio(this).find("a").attr("href");
- if (!chapterUrl)
- return;
- chapters.push({
- name: chapterName,
- releaseTime: releaseDate,
- url: chapterUrl,
- });
- });
- novel.chapters = chapters.reverse();
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = chapterUrl;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio("#listen-chapter").remove();
- loadedCheerio("#google_translate_element").remove();
- const chapterText = loadedCheerio(".chapter__content").html();
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = `${baseUrl}search?status=all&sort=views&q=${searchTerm}`;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio(".book-item").each(function () {
- var _a;
- const novelName = loadedCheerio(this).find(".title").text();
- const novelCover = "https:" + loadedCheerio(this).find("img").attr("data-src");
- const novelUrl = baseUrl +
- ((_a = loadedCheerio(this).find(".title a").attr("href")) === null || _a === void 0 ? void 0 : _a.substring(1));
- const novel = { name: novelName, cover: novelCover, url: novelUrl };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-exports.fetchImage = fetch_1.fetchFile;
diff --git a/js/plugins/english/NovelMultiverse[madara].js b/js/plugins/english/NovelMultiverse[madara].js
deleted file mode 100644
index 47c6c3c..0000000
--- a/js/plugins/english/NovelMultiverse[madara].js
+++ /dev/null
@@ -1,179 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const filterInputs_1 = require("@libs/filterInputs");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "novelmultiverse";
-exports.name = "NovelMultiverse [madara]";
-exports.icon = "multisrc/madara/icons/novelmultiverse.png";
-exports.version = "1.0.0";
-exports.site = "https://www.novelmultiverse.com/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "novel-genre/" + filters.genres + '/';
- }
- else {
- url += "novel/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (false) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": filterInputs_1.FilterInputs.Picker }, { "key": "genres", "label": "GENRES", "values": [{ "label": "Action", "value": "action" }, { "label": "Adult", "value": "adult" }, { "label": "Adventure", "value": "adventure" }, { "label": "Anime", "value": "anime" }, { "label": "Cartoon", "value": "cartoon" }, { "label": "Comedy", "value": "comedy" }, { "label": "Comic", "value": "comic" }, { "label": "Cooking", "value": "cooking" }, { "label": "Detective", "value": "detective" }, { "label": "Doujinshi", "value": "doujinshi" }, { "label": "Drama", "value": "drama" }, { "label": "Ecchi", "value": "ecchi" }, { "label": "Fantasy", "value": "fantasy" }, { "label": "Gender Bender", "value": "gender-bender" }, { "label": "Harem", "value": "harem" }, { "label": "Historical", "value": "historical" }, { "label": "Horror", "value": "horror" }, { "label": "Josei", "value": "josei" }, { "label": "Live action", "value": "live-action" }, { "label": "Manga", "value": "manga" }, { "label": "Manhua", "value": "manhua" }, { "label": "Manhwa", "value": "manhwa" }, { "label": "Martial Arts", "value": "martial-arts" }, { "label": "Mature", "value": "mature" }, { "label": "Mecha", "value": "mecha" }, { "label": "Mystery", "value": "mystery" }, { "label": "One shot", "value": "one-shot" }, { "label": "Original", "value": "original" }, { "label": "Psychological", "value": "psychological" }, { "label": "Romance", "value": "romance" }, { "label": "School Life", "value": "school-life" }, { "label": "Sci-fi", "value": "sci-fi" }, { "label": "Seinen", "value": "seinen" }, { "label": "Shoujo", "value": "shoujo" }, { "label": "Shoujo Ai", "value": "shoujo-ai" }, { "label": "Shounen", "value": "shounen" }, { "label": "Shounen Ai", "value": "shounen-ai" }, { "label": "Slice of Life", "value": "slice-of-life" }, { "label": "Smut", "value": "smut" }, { "label": "Soft Yaoi", "value": "soft-yaoi" }, { "label": "Soft Yuri", "value": "soft-yuri" }, { "label": "Sports", "value": "sports" }, { "label": "Supernatural", "value": "supernatural" }, { "label": "Tragedy", "value": "tragedy" }, { "label": "Translation", "value": "translation" }, { "label": "Webtoon", "value": "webtoon" }, { "label": "Wuxia", "value": "wuxia" }, { "label": "Xianxia", "value": "xianxia" }, { "label": "Xuanhuan", "value": "xuanhuan" }, { "label": "Yaoi", "value": "yaoi" }, { "label": "Yuri", "value": "yuri" }], "inputType": filterInputs_1.FilterInputs.Picker }];
diff --git a/js/plugins/english/NovelOnline.js b/js/plugins/english/NovelOnline.js
deleted file mode 100644
index dc2d8e1..0000000
--- a/js/plugins/english/NovelOnline.js
+++ /dev/null
@@ -1,104 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.fetchImage = exports.parseChapter = exports.popularNovels = exports.parseNovelAndChapters = exports.searchNovels = exports.version = exports.icon = exports.site = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-exports.id = "NO.net";
-exports.name = "novelsOnline";
-exports.site = "https://novelsonline.net";
-exports.icon = "src/coverNotAvailable.jpg";
-exports.version = "1.0.0";
-const pluginId = exports.id;
-const searchNovels = function (searchTerm) {
- return __awaiter(this, void 0, void 0, function* () {
- const result = yield (0, fetch_1.fetchApi)("https://novelsonline.net/sResults.php", {
- headers: {
- Accept: "*/*",
- "Accept-Language": "pl,en-US;q=0.7,en;q=0.3",
- "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
- },
- method: "POST",
- body: "q=" + encodeURIComponent(searchTerm),
- }, pluginId).then((res) => res.text());
- let $ = (0, cheerio_1.load)(result);
- const headers = $("li");
- return headers
- .map((i, h) => {
- const novelName = $(h).text();
- const novelUrl = $(h).find("a").attr("href");
- const novelCover = $(h).find("img").attr("src");
- if (!novelUrl) {
- return null;
- }
- return {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- })
- .get()
- .filter((sr) => sr !== null);
- });
-};
-exports.searchNovels = searchNovels;
-const parseNovelAndChapters = function (novelUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- let novel = {
- url: novelUrl,
- chapters: [],
- };
- const result = yield (0, fetch_1.fetchApi)(novelUrl).then((res) => res.text());
- let $ = (0, cheerio_1.load)(result);
- novel.name = $("h1").text();
- novel.cover = $(".novel-cover").find("a > img").attr("src");
- novel.author = $("div.novel-details > div:nth-child(5) > div.novel-detail-body")
- .find("li")
- .map((_, el) => $(el).text())
- .get()
- .join(", ");
- novel.genres = $("div.novel-details > div:nth-child(2) > div.novel-detail-body")
- .find("li")
- .map((_, el) => $(el).text())
- .get()
- .join(",");
- novel.summary = $("div.novel-right > div > div:nth-child(1) > div.novel-detail-body").text();
- novel.chapters = $("ul.chapter-chs > li > a")
- .map((_, el) => {
- const chapterUrl = $(el).attr("href");
- const chapterName = $(el).text();
- return {
- name: chapterName,
- releaseTime: "",
- url: chapterUrl,
- };
- })
- .get();
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const popularNovels = function (page) {
- return __awaiter(this, void 0, void 0, function* () {
- return []; /** TO DO */
- });
-};
-exports.popularNovels = popularNovels;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const result = yield (0, fetch_1.fetchApi)(chapterUrl).then((res) => res.text());
- let loadedCheerio = (0, cheerio_1.load)(result);
- const chapterText = loadedCheerio("#contentall").html() || "";
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-exports.fetchImage = fetch_1.fetchFile;
diff --git a/js/plugins/english/NovelR18[madara].js b/js/plugins/english/NovelR18[madara].js
deleted file mode 100644
index 0f5fa7c..0000000
--- a/js/plugins/english/NovelR18[madara].js
+++ /dev/null
@@ -1,179 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const filterInputs_1 = require("@libs/filterInputs");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "novelr18";
-exports.name = "NovelR18 [madara]";
-exports.icon = "multisrc/madara/icons/novelr18.png";
-exports.version = "1.0.0";
-exports.site = "https://novelr18.com/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "novel-genre/" + filters.genres + '/';
- }
- else {
- url += "novel/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (true) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "manga" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [{ "key": "sort", "label": "Sort by :", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest Update", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "Newly Added Novels", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": filterInputs_1.FilterInputs.Picker }];
diff --git a/js/plugins/english/NovelTranslate[madara].js b/js/plugins/english/NovelTranslate[madara].js
deleted file mode 100644
index ce55467..0000000
--- a/js/plugins/english/NovelTranslate[madara].js
+++ /dev/null
@@ -1,179 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const filterInputs_1 = require("@libs/filterInputs");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "novelTL";
-exports.name = "NovelTranslate [madara]";
-exports.icon = "multisrc/madara/icons/noveltranslate.png";
-exports.version = "1.0.0";
-exports.site = "https://noveltranslate.com/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "manga-genre/" + filters.genres + '/';
- }
- else {
- url += "all-novels/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (false) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "manga" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": filterInputs_1.FilterInputs.Picker }, { "key": "genres", "label": "GENRES", "values": [{ "label": "Action", "value": "action" }, { "label": "Adult", "value": "adult" }, { "label": "Adventure", "value": "adventure" }, { "label": "Bleach", "value": "bleach" }, { "label": "Chinese", "value": "chinese" }, { "label": "Comedy", "value": "comedy" }, { "label": "Conan", "value": "conan" }, { "label": "cooking", "value": "cooking" }, { "label": "Dragon Ball", "value": "dragon-ball" }, { "label": "Drama", "value": "drama" }, { "label": "Ecchi", "value": "ecchi" }, { "label": "Erciyuan", "value": "erciyuan" }, { "label": "Fairy Tail", "value": "fairy-tail" }, { "label": "Faloo", "value": "faloo" }, { "label": "Fan-Fiction", "value": "fan-fiction" }, { "label": "Fantasy", "value": "fantasy" }, { "label": "FoodWars!", "value": "foodwars" }, { "label": "Game", "value": "game" }, { "label": "Gender Bender", "value": "gender-bender" }, { "label": "Harem", "value": "harem" }, { "label": "Historical", "value": "historical" }, { "label": "Horror", "value": "horror" }, { "label": "Hunter x Hunter", "value": "hunter-x-hunter" }, { "label": "Isekai", "value": "isekai" }, { "label": "Japanese", "value": "japanese" }, { "label": "Jojo", "value": "jojo" }, { "label": "Josei", "value": "josei" }, { "label": "Korean", "value": "korean" }, { "label": "Martial Arts", "value": "martial-arts" }, { "label": "Marvel", "value": "marvel" }, { "label": "Mature", "value": "mature" }, { "label": "Mecha", "value": "mecha" }, { "label": "Military", "value": "military" }, { "label": "Mystery", "value": "mystery" }, { "label": "Naruto", "value": "naruto" }, { "label": "One piece", "value": "one-piece" }, { "label": "Pokemon", "value": "pokemon" }, { "label": "Political", "value": "political" }, { "label": "Psychological", "value": "psychological" }, { "label": "Romance", "value": "romance" }, { "label": "School Life", "value": "school-life" }, { "label": "Sci-fi", "value": "sci-fi" }, { "label": "Seinen", "value": "seinen" }, { "label": "Shoujo", "value": "shoujo" }, { "label": "Shoujo Ai", "value": "shoujo-ai" }, { "label": "Shounen", "value": "shounen" }, { "label": "Shounen Ai", "value": "shounen-ai" }, { "label": "Slice of Life", "value": "slice-of-life" }, { "label": "Smut", "value": "smut" }, { "label": "Sport", "value": "sport" }, { "label": "Sports", "value": "sports" }, { "label": "Supernatural", "value": "supernatural" }, { "label": "System", "value": "system" }, { "label": "Toriko", "value": "toriko" }, { "label": "Tragedy", "value": "tragedy" }, { "label": "Urban", "value": "urban" }, { "label": "Urban Life", "value": "urban-life" }, { "label": "Wuxia", "value": "wuxia" }, { "label": "Xianxia", "value": "xianxia" }, { "label": "Xuanhuan", "value": "xuanhuan" }, { "label": "Yaoi", "value": "yaoi" }, { "label": "Yuri", "value": "yuri" }], "inputType": filterInputs_1.FilterInputs.Picker }];
diff --git a/js/plugins/english/Novelmtcom[readwn].js b/js/plugins/english/Novelmtcom[readwn].js
deleted file mode 100644
index 5b369c6..0000000
--- a/js/plugins/english/Novelmtcom[readwn].js
+++ /dev/null
@@ -1,163 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-// import dayjs from 'dayjs';
-const fetch_1 = require("@libs/fetch");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-// import { isUrlAbsolute } from '@libs/isAbsoluteUrl';
-// import { showToast } from "@libs/showToast";
-const filterInputs_1 = require("@libs/filterInputs");
-// import { NovelStatus } from '@libs/novelStatus';
-// import { defaultCover } from "@libs/defaultCover";
-exports.id = "Novelmt.com";
-exports.name = "Novelmt.com";
-exports.icon = "multisrc/readwn/icons/novelmt.png";
-exports.version = "1.0.0";
-exports.site = "https://www.novelmt.com/";
-const popularNovels = function (page, { filters, showLatestNovels }) {
- return __awaiter(this, void 0, void 0, function* () {
- const novels = [];
- const pageNo = page - 1;
- let url = exports.site + 'list/';
- url += ((filters === null || filters === void 0 ? void 0 : filters.genres) || 'all') + '/';
- url += ((filters === null || filters === void 0 ? void 0 : filters.status) || 'all') + '-';
- url += (showLatestNovels ? 'lastdotime' : (filters === null || filters === void 0 ? void 0 : filters.sort) || 'newstime') + '-';
- url += pageNo + '.html';
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('li.novel-item').each(function () {
- const novelName = loadedCheerio(this).find('h4').text();
- const novelUrl = exports.site + loadedCheerio(this).find('a').attr('href');
- const coverUri = loadedCheerio(this)
- .find('.novel-cover > img')
- .attr('data-src');
- const novelCover = exports.site + coverUri;
- const novel = { name: novelName, cover: novelCover, url: novelUrl };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const result = yield (0, fetch_1.fetchApi)(novelUrl);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- const novel = {
- url: novelUrl,
- chapters: [],
- };
- novel.name = loadedCheerio('h1.novel-title').text();
- const coverUri = loadedCheerio('figure.cover > img').attr('data-src');
- novel.cover = exports.site + coverUri;
- novel.summary = loadedCheerio('.summary')
- .text()
- .replace('Summary', '')
- .trim();
- novel.genres = '';
- loadedCheerio('div.categories > ul > li').each(function () {
- novel.genres += loadedCheerio(this).text().trim() + ',';
- });
- loadedCheerio('div.header-stats > span').each(function () {
- if (loadedCheerio(this).find('small').text() === 'Status') {
- novel.status = loadedCheerio(this).find('strong').text();
- }
- });
- novel.genres = novel.genres.slice(0, -1);
- novel.author = loadedCheerio('span[itemprop=author]').text();
- let novelChapters = [];
- const novelId = novelUrl.replace('.html', '').replace(exports.site, '');
- const latestChapterNo = parseInt(loadedCheerio('.header-stats')
- .find('span > strong')
- .first()
- .text()
- .trim());
- let lastChapterNo = 1;
- loadedCheerio('.chapter-list li').each(function () {
- var _a;
- const chapterName = loadedCheerio(this)
- .find('a .chapter-title')
- .text()
- .trim();
- const chapterUrl = exports.site + ((_a = loadedCheerio(this).find('a').attr('href')) === null || _a === void 0 ? void 0 : _a.trim());
- const releaseDate = loadedCheerio(this)
- .find('a .chapter-update')
- .text()
- .trim();
- lastChapterNo = parseInt(loadedCheerio(this).find('a .chapter-no').text().trim());
- const chapter = { name: chapterName, releaseTime: (0, parseMadaraDate_1.parseMadaraDate)(releaseDate), url: chapterUrl };
- novelChapters.push(chapter);
- });
- // Itterate once more before loop to finish off
- lastChapterNo++;
- for (let i = lastChapterNo; i <= latestChapterNo; i++) {
- const chapterName = 'Chapter ' + i;
- const chapterUrl = exports.site + novelId + '_' + i + '.html';
- const releaseDate = null;
- const chapter = { name: chapterName, releaseTime: releaseDate, url: chapterUrl };
- novelChapters.push(chapter);
- }
- novel.chapters = novelChapters;
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const result = yield (0, fetch_1.fetchApi)(chapterUrl);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.chapter-content').html();
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const searchUrl = exports.site + 'e/search/index.php';
- const result = yield (0, fetch_1.fetchApi)(searchUrl, {
- headers: {
- 'Content-Type': 'application/x-www-form-urlencoded',
- Referer: exports.site + 'search.html',
- Origin: exports.site,
- 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36',
- },
- method: 'POST',
- body: JSON.stringify({
- show: 'title',
- tempid: 1,
- tbname: 'news',
- keyboard: searchTerm,
- }),
- });
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('li.novel-item').each(function () {
- const novelName = loadedCheerio(this).find('h4').text();
- const novelUrl = exports.site + loadedCheerio(this).find('a').attr('href');
- const coverUri = exports.site + loadedCheerio(this).find('img').attr('data-src');
- const novelCover = exports.site + coverUri;
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-exports.fetchImage = fetch_1.fetchFile;
-exports.filters = [{ "key": "sort", "label": "Sort By", "values": [{ "label": "New", "value": "newstime" }, { "label": "Popular", "value": "onclick" }, { "label": "Updates", "value": "lastdotime" }], "inputType": filterInputs_1.FilterInputs.Picker }, { "key": "status", "label": "Status", "values": [{ "label": "All", "value": "all" }, { "label": "Completed", "value": "Completed" }, { "label": "Ongoing", "value": "Ongoing" }], "inputType": filterInputs_1.FilterInputs.Picker }, { "key": "genres", "label": "Genre / Category", "values": [{ "label": "All", "value": "all" }, { "label": "Action", "value": "action" }, { "label": "Adult", "value": "adult" }, { "label": "Adventure", "value": "adventure" }, { "label": "Billionaire", "value": "billionaire" }, { "label": "CEO", "value": "ceo" }, { "label": "Chinese", "value": "chinese" }, { "label": "Comedy", "value": "comedy" }, { "label": "Contemporary Romance", "value": "contemporary-romance" }, { "label": "Drama", "value": "drama" }, { "label": "Eastern Fantasy", "value": "eastern-fantasy" }, { "label": "Ecchi", "value": "ecchi" }, { "label": "Erciyuan", "value": "erciyuan" }, { "label": "Faloo", "value": "faloo" }, { "label": "Fan-Fiction", "value": "fan-fiction" }, { "label": "Fantasy", "value": "fantasy" }, { "label": "Fantasy Romance", "value": "fantasy-romance" }, { "label": "Farming", "value": "farming" }, { "label": "Game", "value": "game" }, { "label": "Games", "value": "games" }, { "label": "Gay Romance", "value": "gay-romance" }, { "label": "Gender Bender", "value": "gender-bender" }, { "label": "Harem", "value": "harem" }, { "label": "Historical", "value": "historical" }, { "label": "Historical Romance", "value": "historical-romance" }, { "label": "Horror", "value": "horror" }, { "label": "Isekai", "value": "isekai" }, { "label": "Japanese", "value": "japanese" }, { "label": "Josei", "value": "josei" }, { "label": "Korean", "value": "korean" }, { "label": "Lolicon", "value": "lolicon" }, { "label": "Magic", "value": "magic" }, { "label": "Magical Realism", "value": "magical-realism" }, { "label": "Martial Arts", "value": "martial-arts" }, { "label": "Mature", "value": "mature" }, { "label": "Mecha", "value": "mecha" }, { "label": "Military", "value": "military" }, { "label": "Modern Life", "value": "modern-life" }, { "label": "Modern Romance", "value": "modern-romance" }, { "label": "Mystery", "value": "mystery" }, { "label": "Psychological", "value": "psychological" }, { "label": "Romance", "value": "romance" }, { "label": "Romantic", "value": "romantic" }, { "label": "School Life", "value": "school-life" }, { "label": "Sci-fi", "value": "sci-fi" }, { "label": "Seinen", "value": "seinen" }, { "label": "Shoujo", "value": "shoujo" }, { "label": "Shoujo Ai", "value": "shoujo-ai" }, { "label": "Shounen", "value": "shounen" }, { "label": "Shounen Ai", "value": "shounen-ai" }, { "label": "Slice of Life", "value": "slice-of-life" }, { "label": "Smut", "value": "smut" }, { "label": "Sports", "value": "sports" }, { "label": "Supernatural", "value": "supernatural" }, { "label": "Tragedy", "value": "tragedy" }, { "label": "Two-dimensional", "value": "two-dimensional" }, { "label": "Urban", "value": "urban" }, { "label": "Urban Life", "value": "urban-life" }, { "label": "Video Games", "value": "video-games" }, { "label": "Virtual Reality", "value": "virtual-reality" }, { "label": "Wuxia", "value": "wuxia" }, { "label": "Xianxia", "value": "xianxia" }, { "label": "Xuanhuan", "value": "xuanhuan" }, { "label": "Yaoi", "value": "yaoi" }, { "label": "Yuri", "value": "yuri" }], "inputType": filterInputs_1.FilterInputs.Picker }];
diff --git a/js/plugins/english/Novelroomnet[madara].js b/js/plugins/english/Novelroomnet[madara].js
deleted file mode 100644
index b48ffab..0000000
--- a/js/plugins/english/Novelroomnet[madara].js
+++ /dev/null
@@ -1,178 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "novelroom";
-exports.name = "Novelroom.net [madara]";
-exports.icon = "multisrc/madara/icons/novelroom.net.png";
-exports.version = "1.0.0";
-exports.site = "https://novelroom.net/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "novel-genre/" + filters.genres + '/';
- }
- else {
- url += "manga/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (false) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "manga" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [];
diff --git a/js/plugins/english/Novelstic[madara].js b/js/plugins/english/Novelstic[madara].js
deleted file mode 100644
index 198324b..0000000
--- a/js/plugins/english/Novelstic[madara].js
+++ /dev/null
@@ -1,179 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const filterInputs_1 = require("@libs/filterInputs");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "novelstic";
-exports.name = "Novelstic [madara]";
-exports.icon = "multisrc/madara/icons/novelstic.png";
-exports.version = "1.0.0";
-exports.site = "https://novelstic.com/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "novel-genre/" + filters.genres + '/';
- }
- else {
- url += "novel/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (true) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": filterInputs_1.FilterInputs.Picker }];
diff --git a/js/plugins/english/OnlyMTL[madara].js b/js/plugins/english/OnlyMTL[madara].js
deleted file mode 100644
index 768c663..0000000
--- a/js/plugins/english/OnlyMTL[madara].js
+++ /dev/null
@@ -1,178 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "onlymtl";
-exports.name = "OnlyMTL [madara]";
-exports.icon = "multisrc/madara/icons/onlymtl.png";
-exports.version = "1.0.0";
-exports.site = "https://www.onlymtl.com/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "novel-genre/" + filters.genres + '/';
- }
- else {
- url += "novel/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (true) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [];
diff --git a/js/plugins/english/ReadWebNovels[madara].js b/js/plugins/english/ReadWebNovels[madara].js
deleted file mode 100644
index e066bb2..0000000
--- a/js/plugins/english/ReadWebNovels[madara].js
+++ /dev/null
@@ -1,179 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const filterInputs_1 = require("@libs/filterInputs");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "readwebnovels";
-exports.name = "ReadWebNovels [madara]";
-exports.icon = "multisrc/madara/icons/readwebnovels.png";
-exports.version = "1.0.0";
-exports.site = "https://readwebnovels.net/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "novel-genre/" + filters.genres + '/';
- }
- else {
- url += "novel/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (false) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": filterInputs_1.FilterInputs.Picker }];
diff --git a/js/plugins/english/Readwncom[readwn].js b/js/plugins/english/Readwncom[readwn].js
deleted file mode 100644
index 84d16a7..0000000
--- a/js/plugins/english/Readwncom[readwn].js
+++ /dev/null
@@ -1,163 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-// import dayjs from 'dayjs';
-const fetch_1 = require("@libs/fetch");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-// import { isUrlAbsolute } from '@libs/isAbsoluteUrl';
-// import { showToast } from "@libs/showToast";
-const filterInputs_1 = require("@libs/filterInputs");
-// import { NovelStatus } from '@libs/novelStatus';
-// import { defaultCover } from "@libs/defaultCover";
-exports.id = "Readwn.com";
-exports.name = "Readwn.com";
-exports.icon = "multisrc/readwn/icons/readwn.png";
-exports.version = "1.0.0";
-exports.site = "https://www.readwn.com/";
-const popularNovels = function (page, { filters, showLatestNovels }) {
- return __awaiter(this, void 0, void 0, function* () {
- const novels = [];
- const pageNo = page - 1;
- let url = exports.site + 'list/';
- url += ((filters === null || filters === void 0 ? void 0 : filters.genres) || 'all') + '/';
- url += ((filters === null || filters === void 0 ? void 0 : filters.status) || 'all') + '-';
- url += (showLatestNovels ? 'lastdotime' : (filters === null || filters === void 0 ? void 0 : filters.sort) || 'newstime') + '-';
- url += pageNo + '.html';
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('li.novel-item').each(function () {
- const novelName = loadedCheerio(this).find('h4').text();
- const novelUrl = exports.site + loadedCheerio(this).find('a').attr('href');
- const coverUri = loadedCheerio(this)
- .find('.novel-cover > img')
- .attr('data-src');
- const novelCover = exports.site + coverUri;
- const novel = { name: novelName, cover: novelCover, url: novelUrl };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const result = yield (0, fetch_1.fetchApi)(novelUrl);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- const novel = {
- url: novelUrl,
- chapters: [],
- };
- novel.name = loadedCheerio('h1.novel-title').text();
- const coverUri = loadedCheerio('figure.cover > img').attr('data-src');
- novel.cover = exports.site + coverUri;
- novel.summary = loadedCheerio('.summary')
- .text()
- .replace('Summary', '')
- .trim();
- novel.genres = '';
- loadedCheerio('div.categories > ul > li').each(function () {
- novel.genres += loadedCheerio(this).text().trim() + ',';
- });
- loadedCheerio('div.header-stats > span').each(function () {
- if (loadedCheerio(this).find('small').text() === 'Status') {
- novel.status = loadedCheerio(this).find('strong').text();
- }
- });
- novel.genres = novel.genres.slice(0, -1);
- novel.author = loadedCheerio('span[itemprop=author]').text();
- let novelChapters = [];
- const novelId = novelUrl.replace('.html', '').replace(exports.site, '');
- const latestChapterNo = parseInt(loadedCheerio('.header-stats')
- .find('span > strong')
- .first()
- .text()
- .trim());
- let lastChapterNo = 1;
- loadedCheerio('.chapter-list li').each(function () {
- var _a;
- const chapterName = loadedCheerio(this)
- .find('a .chapter-title')
- .text()
- .trim();
- const chapterUrl = exports.site + ((_a = loadedCheerio(this).find('a').attr('href')) === null || _a === void 0 ? void 0 : _a.trim());
- const releaseDate = loadedCheerio(this)
- .find('a .chapter-update')
- .text()
- .trim();
- lastChapterNo = parseInt(loadedCheerio(this).find('a .chapter-no').text().trim());
- const chapter = { name: chapterName, releaseTime: (0, parseMadaraDate_1.parseMadaraDate)(releaseDate), url: chapterUrl };
- novelChapters.push(chapter);
- });
- // Itterate once more before loop to finish off
- lastChapterNo++;
- for (let i = lastChapterNo; i <= latestChapterNo; i++) {
- const chapterName = 'Chapter ' + i;
- const chapterUrl = exports.site + novelId + '_' + i + '.html';
- const releaseDate = null;
- const chapter = { name: chapterName, releaseTime: releaseDate, url: chapterUrl };
- novelChapters.push(chapter);
- }
- novel.chapters = novelChapters;
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const result = yield (0, fetch_1.fetchApi)(chapterUrl);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.chapter-content').html();
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const searchUrl = exports.site + 'e/search/index.php';
- const result = yield (0, fetch_1.fetchApi)(searchUrl, {
- headers: {
- 'Content-Type': 'application/x-www-form-urlencoded',
- Referer: exports.site + 'search.html',
- Origin: exports.site,
- 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36',
- },
- method: 'POST',
- body: JSON.stringify({
- show: 'title',
- tempid: 1,
- tbname: 'news',
- keyboard: searchTerm,
- }),
- });
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('li.novel-item').each(function () {
- const novelName = loadedCheerio(this).find('h4').text();
- const novelUrl = exports.site + loadedCheerio(this).find('a').attr('href');
- const coverUri = exports.site + loadedCheerio(this).find('img').attr('data-src');
- const novelCover = exports.site + coverUri;
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-exports.fetchImage = fetch_1.fetchFile;
-exports.filters = [{ "key": "sort", "label": "Sort By", "values": [{ "label": "New", "value": "newstime" }, { "label": "Popular", "value": "onclick" }, { "label": "Updates", "value": "lastdotime" }], "inputType": filterInputs_1.FilterInputs.Picker }, { "key": "status", "label": "Status", "values": [{ "label": "All", "value": "all" }, { "label": "Completed", "value": "Completed" }, { "label": "Ongoing", "value": "Ongoing" }], "inputType": filterInputs_1.FilterInputs.Picker }, { "key": "genres", "label": "Genre / Category", "values": [{ "label": "All", "value": "all" }, { "label": "Action", "value": "action" }, { "label": "Adventure", "value": "adventure" }, { "label": "Chinese", "value": "chinese" }, { "label": "Comedy", "value": "comedy" }, { "label": "Contemporary Romance", "value": "contemporary-romance" }, { "label": "Drama", "value": "drama" }, { "label": "Eastern Fantasy", "value": "eastern-fantasy" }, { "label": "Ecchi", "value": "ecchi" }, { "label": "Erciyuan", "value": "erciyuan" }, { "label": "Faloo", "value": "faloo" }, { "label": "Fan-Fiction", "value": "fan-fiction" }, { "label": "Fantasy", "value": "fantasy" }, { "label": "Fantasy Romance", "value": "fantasy-romance" }, { "label": "Game", "value": "game" }, { "label": "Gender Bender", "value": "gender-bender" }, { "label": "Harem", "value": "harem" }, { "label": "Hentai", "value": "hentai" }, { "label": "Historical", "value": "historical" }, { "label": "Horror", "value": "horror" }, { "label": "Isekai", "value": "isekai" }, { "label": "Japanese", "value": "japanese" }, { "label": "Josei", "value": "josei" }, { "label": "Korean", "value": "korean" }, { "label": "Lolicon", "value": "lolicon" }, { "label": "Magic", "value": "magic" }, { "label": "Magical Realism", "value": "magical-realism" }, { "label": "Martial Arts", "value": "martial-arts" }, { "label": "Mecha", "value": "mecha" }, { "label": "Military", "value": "military" }, { "label": "Mystery", "value": "mystery" }, { "label": "Official Circles", "value": "official_circles" }, { "label": "Psychological", "value": "psychological" }, { "label": "Romance", "value": "romance" }, { "label": "School Life", "value": "school-life" }, { "label": "Sci-fi", "value": "sci-fi" }, { "label": "Science Fiction", "value": "science_fiction" }, { "label": "Seinen", "value": "seinen" }, { "label": "Shoujo", "value": "shoujo" }, { "label": "Shoujo Ai", "value": "shoujo-ai" }, { "label": "Shounen", "value": "shounen" }, { "label": "Shounen Ai", "value": "shounen-ai" }, { "label": "Slice of Life", "value": "slice-of-life" }, { "label": "Sports", "value": "sports" }, { "label": "Supernatural", "value": "supernatural" }, { "label": "Suspense Thriller", "value": "suspense_thriller" }, { "label": "Tragedy", "value": "tragedy" }, { "label": "Travel Through Time", "value": "travel_through_time" }, { "label": "Two-dimensional", "value": "two-dimensional" }, { "label": "Urban", "value": "urban" }, { "label": "Urban Life", "value": "urban-life" }, { "label": "Video Games", "value": "video-games" }, { "label": "Virtual Reality", "value": "virtual-reality" }, { "label": "Wuxia", "value": "wuxia" }, { "label": "Wuxia Xianxia", "value": "wuxia_xianxia" }, { "label": "Xianxia", "value": "xianxia" }, { "label": "Xuanhuan", "value": "xuanhuan" }, { "label": "Yaoi", "value": "yaoi" }, { "label": "Yuri", "value": "yuri" }], "inputType": filterInputs_1.FilterInputs.Picker }];
diff --git a/js/plugins/english/SleepyTranslations[madara].js b/js/plugins/english/SleepyTranslations[madara].js
deleted file mode 100644
index 78a0a1f..0000000
--- a/js/plugins/english/SleepyTranslations[madara].js
+++ /dev/null
@@ -1,179 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const filterInputs_1 = require("@libs/filterInputs");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "sleeptTLS";
-exports.name = "SleepyTranslations [madara]";
-exports.icon = "multisrc/madara/icons/sleepytranslations.png";
-exports.version = "1.0.0";
-exports.site = "https://sleepytranslations.com/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "novel-genre/" + filters.genres + '/';
- }
- else {
- url += "series/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (true) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "series" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": filterInputs_1.FilterInputs.Picker }];
diff --git a/js/plugins/english/SonicMTL[madara].js b/js/plugins/english/SonicMTL[madara].js
deleted file mode 100644
index 62718ae..0000000
--- a/js/plugins/english/SonicMTL[madara].js
+++ /dev/null
@@ -1,179 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const filterInputs_1 = require("@libs/filterInputs");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "sonicmtl";
-exports.name = "SonicMTL [madara]";
-exports.icon = "multisrc/madara/icons/sonicmtl.png";
-exports.version = "1.0.0";
-exports.site = "https://www.sonicmtl.com/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "novel-genre/" + filters.genres + '/';
- }
- else {
- url += "novel/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (true) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": filterInputs_1.FilterInputs.Picker }, { "key": "genres", "label": "GENRES", "values": [{ "label": "Action", "value": "action" }, { "label": "Adult", "value": "adult" }, { "label": "Adventure", "value": "adventure" }, { "label": "Comedy", "value": "comedy" }, { "label": "Cooking", "value": "cooking" }, { "label": "Detective", "value": "detective" }, { "label": "Doujinshi", "value": "doujinshi" }, { "label": "Drama", "value": "drama" }, { "label": "Ecchi", "value": "ecchi" }, { "label": "Fan-Fiction", "value": "fan-fiction" }, { "label": "Fantasy", "value": "fantasy" }, { "label": "Gender Bender", "value": "gender-bender" }, { "label": "Harem", "value": "harem" }, { "label": "Historical", "value": "historical" }, { "label": "Horror", "value": "horror" }, { "label": "Josei", "value": "josei" }, { "label": "Live action", "value": "live-action" }, { "label": "Manga", "value": "manga" }, { "label": "Manhua", "value": "manhua" }, { "label": "Manhwa", "value": "manhwa" }, { "label": "Martial Arts", "value": "martial-arts" }, { "label": "Mature", "value": "mature" }, { "label": "Mecha", "value": "mecha" }, { "label": "Mystery", "value": "mystery" }, { "label": "One shot", "value": "one-shot" }, { "label": "Psychological", "value": "psychological" }, { "label": "Romance", "value": "romance" }, { "label": "School Life", "value": "school-life" }, { "label": "Sci-fi", "value": "sci-fi" }, { "label": "Seinen", "value": "seinen" }, { "label": "Shoujo", "value": "shoujo" }, { "label": "Shoujo Ai", "value": "shoujo-ai" }, { "label": "Shounen", "value": "shounen" }, { "label": "Shounen Ai", "value": "shounen-ai" }, { "label": "Slice of Life", "value": "slice-of-life" }, { "label": "Smut", "value": "smut" }, { "label": "Soft Yaoi", "value": "soft-yaoi" }, { "label": "Soft Yuri", "value": "soft-yuri" }, { "label": "Sports", "value": "sports" }, { "label": "Supernatural", "value": "supernatural" }, { "label": "Tragedy", "value": "tragedy" }, { "label": "Urban Life", "value": "urban-life" }, { "label": "Wuxia", "value": "wuxia" }, { "label": "Xianxia", "value": "xianxia" }, { "label": "Xuanhuan", "value": "xuanhuan" }, { "label": "Yaoi", "value": "yaoi" }, { "label": "Yuri", "value": "yuri" }], "inputType": filterInputs_1.FilterInputs.Picker }];
diff --git a/js/plugins/english/SugarBabies[madara].js b/js/plugins/english/SugarBabies[madara].js
deleted file mode 100644
index 058c420..0000000
--- a/js/plugins/english/SugarBabies[madara].js
+++ /dev/null
@@ -1,178 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "sugarbbscan";
-exports.name = "Sugar Babies [madara]";
-exports.icon = "multisrc/madara/icons/sugarbabies.png";
-exports.version = "1.0.0";
-exports.site = "https://sugarbbscan.com/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "novel-genre/" + filters.genres + '/';
- }
- else {
- url += "series/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (false) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "series" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [];
diff --git a/js/plugins/english/SweetEscapeTranslations[madara].js b/js/plugins/english/SweetEscapeTranslations[madara].js
deleted file mode 100644
index 8feed1b..0000000
--- a/js/plugins/english/SweetEscapeTranslations[madara].js
+++ /dev/null
@@ -1,179 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const filterInputs_1 = require("@libs/filterInputs");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "sweetEscapeTL";
-exports.name = "Sweet Escape Translations [madara]";
-exports.icon = "multisrc/madara/icons/sweetescapetranslations.png";
-exports.version = "1.0.0";
-exports.site = "https://sweetescapetranslations.com/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "manga-genre/" + filters.genres + '/';
- }
- else {
- url += "manga/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (false) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "manga" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": filterInputs_1.FilterInputs.Picker }, { "key": "genres", "label": "GENRES", "values": [{ "label": "Action", "value": "action" }, { "label": "Adult", "value": "adult" }, { "label": "Comedy", "value": "comedy" }, { "label": "Drama", "value": "drama" }, { "label": "Fantasy", "value": "fantasy" }, { "label": "Gender Bender", "value": "gender-bender" }, { "label": "Mature", "value": "mature" }, { "label": "Modern", "value": "modern" }, { "label": "Mystery", "value": "mystery" }, { "label": "R-15", "value": "r-15" }, { "label": "Romance", "value": "romance" }, { "label": "Slice of Life", "value": "slice-of-life" }], "inputType": filterInputs_1.FilterInputs.Picker }];
diff --git a/js/plugins/english/WebNovelLover[madara].js b/js/plugins/english/WebNovelLover[madara].js
deleted file mode 100644
index 0daf7f7..0000000
--- a/js/plugins/english/WebNovelLover[madara].js
+++ /dev/null
@@ -1,179 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const filterInputs_1 = require("@libs/filterInputs");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "webnovelover";
-exports.name = "WebNovelLover [madara]";
-exports.icon = "multisrc/madara/icons/webnovellover.png";
-exports.version = "1.0.0";
-exports.site = "https://www.webnovelover.com/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "novel-genre/" + filters.genres + '/';
- }
- else {
- url += "novel/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (false) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": filterInputs_1.FilterInputs.Picker }, { "key": "genres", "label": "GENRES", "values": [{ "label": "Action", "value": "action" }, { "label": "Adapted into drama", "value": "adapted-into-drama" }, { "label": "Adventure", "value": "adventure" }, { "label": "Comedy", "value": "comedy" }, { "label": "Completed", "value": "completed" }, { "label": "Drama", "value": "drama" }, { "label": "English Novel", "value": "english-novel" }, { "label": "Fantasy", "value": "fantasy" }, { "label": "Gender Bender", "value": "gender-bender" }, { "label": "Harem", "value": "harem" }, { "label": "Historical", "value": "historical" }, { "label": "Horror", "value": "horror" }, { "label": "Indo Novel", "value": "indo-novel" }, { "label": "Josei", "value": "josei" }, { "label": "Martial Arts", "value": "martial-arts" }, { "label": "Mature", "value": "mature" }, { "label": "Mystery", "value": "mystery" }, { "label": "Rebirth", "value": "rebirth" }, { "label": "Reincarnation", "value": "reincarnation" }, { "label": "Romance", "value": "romance" }, { "label": "Sci-fi", "value": "sci-fi" }, { "label": "Shoujo", "value": "shoujo" }, { "label": "Shounen", "value": "shounen" }, { "label": "Slice of Life", "value": "slice-of-life" }, { "label": "Spiritual", "value": "spiritual" }, { "label": "Supernatural", "value": "supernatural" }, { "label": "Tragedy", "value": "tragedy" }, { "label": "Transmigration", "value": "transmigration" }, { "label": "University", "value": "university" }, { "label": "Wuxia", "value": "wuxia" }, { "label": "Xianxia", "value": "xianxia" }, { "label": "Xuanhuan", "value": "xuanhuan" }, { "label": "Youth", "value": "youth" }], "inputType": filterInputs_1.FilterInputs.Picker }];
diff --git a/js/plugins/english/WuxiaWorldSite[madara].js b/js/plugins/english/WuxiaWorldSite[madara].js
deleted file mode 100644
index bb8b570..0000000
--- a/js/plugins/english/WuxiaWorldSite[madara].js
+++ /dev/null
@@ -1,179 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const filterInputs_1 = require("@libs/filterInputs");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "wuxiaworld.site";
-exports.name = "WuxiaWorld.Site [madara]";
-exports.icon = "multisrc/madara/icons/wuxiaworld.site.png";
-exports.version = "1.0.0";
-exports.site = "https://wuxiaworld.site/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "novel-genre/" + filters.genres + '/';
- }
- else {
- url += "novel/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (true) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": filterInputs_1.FilterInputs.Picker }];
diff --git a/js/plugins/english/ZetroTranslation[madara].js b/js/plugins/english/ZetroTranslation[madara].js
deleted file mode 100644
index 6a062f6..0000000
--- a/js/plugins/english/ZetroTranslation[madara].js
+++ /dev/null
@@ -1,179 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const filterInputs_1 = require("@libs/filterInputs");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "zetroTL";
-exports.name = "Zetro Translation [madara]";
-exports.icon = "multisrc/madara/icons/zetrotranslation.png";
-exports.version = "1.0.0";
-exports.site = "https://zetrotranslation.com/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "genre/" + filters.genres + '/';
- }
- else {
- url += "novel/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (false) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": filterInputs_1.FilterInputs.Picker }, { "key": "genres", "label": "GENRES", "values": [{ "label": "Action", "value": "action" }, { "label": "Adventure", "value": "adventure" }, { "label": "Comedy", "value": "comedy" }, { "label": "Dark Elf", "value": "dark-elf" }, { "label": "Drama", "value": "drama" }, { "label": "Ecchi", "value": "ecchi" }, { "label": "Fantasy", "value": "fantasy" }, { "label": "Harem", "value": "harem" }, { "label": "Horror", "value": "horror" }, { "label": "Isekai", "value": "isekai" }, { "label": "Mecha", "value": "mecha" }, { "label": "Mystery", "value": "mystery" }, { "label": "NTR", "value": "ntr" }, { "label": "Original Works", "value": "original-works" }, { "label": "Rom-Com", "value": "rom-com" }, { "label": "Romance", "value": "romance" }, { "label": "School", "value": "school" }, { "label": "Shoujo", "value": "shoujo" }, { "label": "Slice of Life", "value": "slice-of-life" }, { "label": "Villain", "value": "villain" }, { "label": "Yuri", "value": "yuri" }], "inputType": filterInputs_1.FilterInputs.Picker }];
diff --git a/js/plugins/english/ZinnNovel[madara].js b/js/plugins/english/ZinnNovel[madara].js
deleted file mode 100644
index 312e8df..0000000
--- a/js/plugins/english/ZinnNovel[madara].js
+++ /dev/null
@@ -1,179 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const filterInputs_1 = require("@libs/filterInputs");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "zinnovel";
-exports.name = "ZinnNovel [madara]";
-exports.icon = "multisrc/madara/icons/zinnnovel.png";
-exports.version = "1.0.0";
-exports.site = "https://zinnovel.com/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "manga-genre/" + filters.genres + '/';
- }
- else {
- url += "manga/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (false) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "manga" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": filterInputs_1.FilterInputs.Picker }, { "key": "genres", "label": "GENRES", "values": [{ "label": "Action", "value": "action" }, { "label": "Adult", "value": "adult" }, { "label": "Adventure", "value": "adventure" }, { "label": "Anime", "value": "anime" }, { "label": "Cartoon", "value": "cartoon" }, { "label": "Comedy", "value": "comedy" }, { "label": "Comic", "value": "comic" }, { "label": "Cooking", "value": "cooking" }, { "label": "Detective", "value": "detective" }, { "label": "Doujinshi", "value": "doujinshi" }, { "label": "Drama", "value": "drama" }, { "label": "Ecchi", "value": "ecchi" }, { "label": "Fantasy", "value": "fantasy" }, { "label": "Game", "value": "game" }, { "label": "Gender Bender", "value": "gender-bender" }, { "label": "Harem", "value": "harem" }, { "label": "Historical", "value": "historical" }, { "label": "Horror", "value": "horror" }, { "label": "Isekai", "value": "isekai" }, { "label": "Josei", "value": "josei" }, { "label": "Live action", "value": "live-action" }, { "label": "Lolicon", "value": "lolicon" }, { "label": "Magical Realism", "value": "magical-realism" }, { "label": "Manga", "value": "manga" }, { "label": "Manhua", "value": "manhua" }, { "label": "Manhwa", "value": "manhwa" }, { "label": "Martial Arts", "value": "martial-arts" }, { "label": "Mature", "value": "mature" }, { "label": "Mecha", "value": "mecha" }, { "label": "Mystery", "value": "mystery" }, { "label": "One shot", "value": "one-shot" }, { "label": "Psychological", "value": "psychological" }, { "label": "Reincarnation", "value": "reincarnation" }, { "label": "Romance", "value": "romance" }, { "label": "School Life", "value": "school-life" }, { "label": "Sci-fi", "value": "sci-fi" }, { "label": "Seinen", "value": "seinen" }, { "label": "Shoujo", "value": "shoujo" }, { "label": "Shoujo Ai", "value": "shoujo-ai" }, { "label": "Shounen", "value": "shounen" }, { "label": "Shounen Ai", "value": "shounen-ai" }, { "label": "Slice of Life", "value": "slice-of-life" }, { "label": "Smut", "value": "smut" }, { "label": "Soft Yaoi", "value": "soft-yaoi" }, { "label": "Soft Yuri", "value": "soft-yuri" }, { "label": "Sports", "value": "sports" }, { "label": "Supernatural", "value": "supernatural" }, { "label": "Tragedy", "value": "tragedy" }, { "label": "Video Games", "value": "video-games" }, { "label": "Webtoon", "value": "webtoon" }, { "label": "Wuxia", "value": "wuxia" }, { "label": "Xianxia", "value": "xianxia" }, { "label": "Xuanhuan", "value": "xuanhuan" }, { "label": "Yaoi", "value": "yaoi" }, { "label": "Yuri", "value": "yuri" }], "inputType": filterInputs_1.FilterInputs.Picker }];
diff --git a/js/plugins/english/allnovelfull.js b/js/plugins/english/allnovelfull.js
deleted file mode 100644
index da80d22..0000000
--- a/js/plugins/english/allnovelfull.js
+++ /dev/null
@@ -1,177 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.icon = exports.version = exports.site = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-exports.id = "ANF.com";
-exports.name = "AllNovelFull";
-exports.site = "https://allnovelfull.com";
-exports.version = "1.0.0";
-exports.icon = "src/en/allnovelfull/icon.png";
-const popularNovels = function (page) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = `${exports.site}/most-popular?page=${page}`;
- const result = yield (0, fetch_1.fetchApi)(url, {});
- if (!result.ok) {
- console.error("Cloudflare error");
- // console.error(await result.text());
- // TODO: Cloudflare protection or other error
- return [];
- }
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- const novels = [];
- loadedCheerio(".col-truyen-main .list-truyen .row").each(function () {
- const novelName = loadedCheerio(this)
- .find("h3.truyen-title > a")
- .text();
- const novelCover = exports.site + loadedCheerio(this).find("img.cover").attr("src");
- const novelUrl = exports.site + loadedCheerio(this).find("h3.truyen-title > a").attr("href");
- const novel = {
- url: novelUrl,
- name: novelName,
- cover: novelCover,
- };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = novelUrl;
- const result = yield (0, fetch_1.fetchApi)(url);
- if (!result.ok) {
- console.error("Cloudflare error");
- // console.error(await result.text());
- // TODO: Cloudflare protection or other error
- return { url, chapters: [] };
- }
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- let novel = {
- url: novelUrl,
- };
- novel.name = loadedCheerio("div.book > img").attr("alt");
- novel.cover = exports.site + loadedCheerio("div.book > img").attr("src");
- novel.summary = loadedCheerio("div.desc-text").text().trim();
- novel.author = loadedCheerio("div.info > div > h3")
- .filter(function () {
- return loadedCheerio(this).text().trim() === "Author:";
- })
- .siblings()
- .text();
- novel.genres = loadedCheerio("div.info > div")
- .filter(function () {
- return (loadedCheerio(this).find("h3").text().trim() === "Genre:");
- })
- .text()
- .replace("Genre:", "");
- novel.status = loadedCheerio("div.info > div > h3")
- .filter(function () {
- return loadedCheerio(this).text().trim() === "Status:";
- })
- .next()
- .text();
- const novelId = loadedCheerio("#rating").attr("data-novel-id");
- function getChapters(id) {
- return __awaiter(this, void 0, void 0, function* () {
- const chapterListUrl = exports.site + "/ajax/chapter-option?novelId=" + id;
- const data = yield (0, fetch_1.fetchApi)(chapterListUrl);
- if (!data.ok) {
- console.error("Cloudflare error");
- // console.error(await result.text());
- // TODO: Cloudflare protection or other error
- return [];
- }
- const chapters = yield data.text();
- loadedCheerio = (0, cheerio_1.load)(chapters);
- const novelChapters = [];
- loadedCheerio("select > option").each(function () {
- var _a;
- let chapterName = loadedCheerio(this).text();
- let releaseDate = null;
- let chapterUrl = (_a = loadedCheerio(this)
- .attr("value")) === null || _a === void 0 ? void 0 : _a.replace(`/${novelUrl}`, "");
- if (chapterUrl) {
- novelChapters.push({
- name: chapterName,
- releaseTime: releaseDate,
- url: chapterUrl,
- });
- }
- });
- return novelChapters;
- });
- }
- if (novelId) {
- novel.chapters = yield getChapters(novelId);
- }
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = exports.site + chapterUrl;
- const result = yield (0, fetch_1.fetchApi)(url);
- if (!result.ok) {
- console.error("Cloudflare error");
- // console.error(await result.text());
- // TODO: Cloudflare protection or other error
- return "Cloudflare protected site!";
- }
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio("#chapter-content").html() || "";
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = `${exports.site}/search?keyword=${searchTerm}`;
- const result = yield (0, fetch_1.fetchApi)(url);
- if (!result.ok) {
- console.error(yield result.text());
- // TODO: Cloudflare protection or other error
- return [];
- }
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio("div.col-truyen-main > div.list-truyen > .row").each(function () {
- const novelUrl = exports.site +
- loadedCheerio(this).find("h3.truyen-title > a").attr("href");
- const novelName = loadedCheerio(this)
- .find("h3.truyen-title > a")
- .text();
- const novelCover = exports.site + loadedCheerio(this).find("img").attr("src");
- if (novelUrl) {
- novels.push({
- url: novelUrl,
- name: novelName,
- cover: novelCover,
- });
- }
- });
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-const fetchImage = function (url, init) {
- return __awaiter(this, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url, init);
- });
-};
-exports.fetchImage = fetchImage;
diff --git a/js/plugins/english/bestlightnovel.js b/js/plugins/english/bestlightnovel.js
deleted file mode 100644
index 77095ae..0000000
--- a/js/plugins/english/bestlightnovel.js
+++ /dev/null
@@ -1,149 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.icon = exports.version = exports.site = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const defaultCover_1 = require("@libs/defaultCover");
-const fetch_1 = require("@libs/fetch");
-const novelStatus_1 = require("@libs/novelStatus");
-exports.id = "BLN.com";
-exports.name = "BestLightNovel";
-exports.site = "https://bestlightnovel.com/";
-exports.version = "1.0.0";
-exports.icon = "src/en/bestlightnovel/icon.png";
-const popularNovels = function (page) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = exports.site + "novel_list?type=topview&category=all&state=all&page=1" + page;
- const result = yield (0, fetch_1.fetchApi)(url);
- if (!result.ok) {
- console.error(yield result.text());
- // TODO: Cloudflare protection or other error
- return [];
- }
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio(".update_item.list_category").each(function () {
- const novelName = loadedCheerio(this).find("h3 > a").text();
- const novelCover = loadedCheerio(this).find("img").attr("src");
- const novelUrl = loadedCheerio(this).find("h3 > a").attr("href");
- if (!novelUrl) {
- // TODO: Handle error
- console.error("No novel url!");
- return;
- }
- const novel = {
- name: novelName,
- url: novelUrl,
- cover: novelCover,
- };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- var _a, _b, _c;
- return __awaiter(this, void 0, void 0, function* () {
- const url = novelUrl;
- const result = yield (0, fetch_1.fetchApi)(url);
- if (!result.ok) {
- console.error(yield result.text());
- // TODO: Cloudflare protection
- return { url, chapters: [] };
- }
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- let novel = {
- url,
- name: "",
- cover: "",
- author: "",
- status: novelStatus_1.NovelStatus.Unknown,
- genres: "",
- summary: "",
- chapters: [],
- };
- novel.name = loadedCheerio(".truyen_info_right h1").text().trim();
- novel.cover =
- loadedCheerio(".info_image img").attr("src") || defaultCover_1.defaultCover;
- novel.summary = (_a = loadedCheerio("#noidungm").text()) === null || _a === void 0 ? void 0 : _a.trim();
- novel.author = (_b = loadedCheerio("#main_body > div.cotgiua > div.truyen_info_wrapper > div.truyen_info > div.entry-header > div.truyen_if_wrap > ul > li:nth-child(2) > a")
- .text()) === null || _b === void 0 ? void 0 : _b.trim();
- let status = (_c = loadedCheerio("#main_body > div.cotgiua > div.truyen_info_wrapper > div.truyen_info > div.entry-header > div.truyen_if_wrap > ul > li:nth-child(4) > a")
- .text()) === null || _c === void 0 ? void 0 : _c.trim();
- novel.status =
- status === "ONGOING"
- ? novelStatus_1.NovelStatus.Ongoing
- : status === "COMPLETED"
- ? novelStatus_1.NovelStatus.Completed
- : novelStatus_1.NovelStatus.Unknown;
- let novelChapters = [];
- loadedCheerio(".chapter-list div.row").each(function () {
- const chapterName = loadedCheerio(this).find("a").text().trim();
- const releaseDate = loadedCheerio(this)
- .find("span:nth-child(2)")
- .text()
- .trim();
- const chapterUrl = loadedCheerio(this).find("a").attr("href");
- if (!chapterUrl) {
- // TODO: Handle error
- console.error("No chapter url!");
- return;
- }
- novelChapters.push({
- name: chapterName,
- releaseTime: releaseDate,
- url: chapterUrl,
- });
- });
- novel.chapters = novelChapters.reverse();
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = chapterUrl;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio("#vung_doc").html();
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = `${exports.site}search_novels/${searchTerm}`;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio(".update_item.list_category").each(function () {
- const novelName = loadedCheerio(this).find("h3 > a").text();
- const novelCover = loadedCheerio(this).find("img").attr("src");
- const novelUrl = loadedCheerio(this).find("h3 > a").attr("href");
- if (!novelUrl) {
- // TODO: Handle error
- console.error("No novel url!");
- return;
- }
- const novel = { name: novelName, cover: novelCover, url: novelUrl };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-const fetchImage = (...args) => (0, fetch_1.fetchFile)(...args);
-exports.fetchImage = fetchImage;
diff --git a/js/plugins/english/comrademao.js b/js/plugins/english/comrademao.js
deleted file mode 100644
index 1d4fa39..0000000
--- a/js/plugins/english/comrademao.js
+++ /dev/null
@@ -1,146 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.icon = exports.version = exports.site = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "comrademao";
-exports.name = "Comrade Mao";
-exports.site = "https://comrademao.com/";
-exports.version = "1.0.0";
-exports.icon = "src/en/comrademao/icon.png";
-const popularNovels = function (page) {
- return __awaiter(this, void 0, void 0, function* () {
- let url = exports.site + "page/" + page + "/?post_type=novel";
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio(".listupd")
- .find("div.bs")
- .each(function () {
- const novelName = loadedCheerio(this).find(".tt").text().trim();
- const novelCover = loadedCheerio(this).find("img").attr("src");
- const novelUrl = loadedCheerio(this).find("a").attr("href");
- if (!novelUrl) {
- // TODO: Handle error
- console.error("No novel url!");
- return;
- }
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = novelUrl;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- let novel = { url };
- novel.name = loadedCheerio(".entry-title").text().trim();
- novel.cover = loadedCheerio("div.thumbook > div > img").attr("src");
- novel.summary = loadedCheerio("div.infox > div:nth-child(6) > span > p")
- .text()
- .trim();
- novel.genres = loadedCheerio("div.infox > div:nth-child(4) > span")
- .text()
- .replace(/\s/g, "");
- novel.status = loadedCheerio("div.infox > div:nth-child(3) > span")
- .text()
- .trim();
- novel.author = loadedCheerio("div.infox > div:nth-child(2) > span")
- .text()
- .trim();
- let novelChapters = [];
- loadedCheerio("#chapterlist")
- .find("li")
- .each(function () {
- const releaseDate = (0, dayjs_1.default)(loadedCheerio(this).find(".chapterdate").text()).format("LL");
- const chapterName = loadedCheerio(this)
- .find(".chapternum")
- .text();
- const chapterUrl = loadedCheerio(this).find("a").attr("href");
- if (!chapterUrl) {
- // TODO: Handle error
- console.error("No chapter url!");
- return;
- }
- novelChapters.push({
- name: chapterName,
- url: chapterUrl,
- releaseTime: releaseDate,
- });
- });
- novel.chapters = novelChapters.reverse();
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = chapterUrl;
- const result = yield (0, fetch_1.fetchApi)(url);
- if (!result.ok) {
- const err = yield result.text();
- console.error(err);
- // TODO: Cloudflare protection or other error
- return "Error!" + err;
- }
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- let chapterText = loadedCheerio("#chaptercontent").html();
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = exports.site + "?s=" + searchTerm + "&post_type=novel";
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio(".listupd")
- .find("div.bs")
- .each(function () {
- const novelName = loadedCheerio(this).find(".tt").text().trim();
- const novelCover = loadedCheerio(this).find("img").attr("src");
- const novelUrl = loadedCheerio(this).find("a").attr("href");
- if (!novelUrl) {
- // TODO: Handle error
- console.error("No novel url!");
- return;
- }
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-const fetchImage = (...args) => (0, fetch_1.fetchFile)(...args);
-exports.fetchImage = fetchImage;
diff --git a/js/plugins/english/divinedaolibrary.js b/js/plugins/english/divinedaolibrary.js
deleted file mode 100644
index 3309a14..0000000
--- a/js/plugins/english/divinedaolibrary.js
+++ /dev/null
@@ -1,134 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.icon = exports.version = exports.site = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const defaultCover_1 = require("@libs/defaultCover");
-exports.id = "DDL.com";
-exports.name = "Divine Dao Library";
-exports.site = "https://www.divinedaolibrary.com/";
-exports.version = "1.0.0";
-exports.icon = "src/en/divinedaolibrary/icon.png";
-const baseUrl = exports.site;
-const popularNovels = function (page) {
- return __awaiter(this, void 0, void 0, function* () {
- let url = baseUrl + "novels";
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio("#main")
- .find("li")
- .each(function () {
- const novelName = loadedCheerio(this).find("a").text();
- const novelCover = defaultCover_1.defaultCover;
- const novelUrl = loadedCheerio(this).find(" a").attr("href");
- if (!novelUrl)
- return;
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = novelUrl;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- let novel = { url };
- novel.name = loadedCheerio("h1.entry-title").text().trim();
- novel.cover =
- loadedCheerio(".entry-content").find("img").attr("data-ezsrc") ||
- defaultCover_1.defaultCover;
- novel.summary = loadedCheerio("#main > article > div > p:nth-child(6)")
- .text()
- .trim();
- novel.author = loadedCheerio("#main > article > div > h3:nth-child(2)")
- .text()
- .replace(/Author:/g, "")
- .trim();
- let novelChapters = [];
- loadedCheerio("#main")
- .find("li > span > a")
- .each(function () {
- const chapterName = loadedCheerio(this).text().trim();
- const releaseDate = null;
- const chapterUrl = loadedCheerio(this).attr("href");
- if (!chapterUrl)
- return;
- novelChapters.push({
- name: chapterName,
- releaseTime: releaseDate,
- url: chapterUrl,
- });
- });
- novel.chapters = novelChapters;
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = chapterUrl;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- let chapterName = loadedCheerio(".entry-title").text().trim();
- let chapterText = loadedCheerio(".entry-content").html();
- if (!chapterText) {
- chapterText = loadedCheerio(".page-header").html();
- }
- chapterText = `${chapterName}
` + chapterText;
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- return __awaiter(this, void 0, void 0, function* () {
- let url = baseUrl + "novels";
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio("#main")
- .find("li")
- .each(function () {
- const novelName = loadedCheerio(this).find("a").text();
- const novelCover = defaultCover_1.defaultCover;
- const novelUrl = loadedCheerio(this).find(" a").attr("href");
- if (!novelUrl)
- return;
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- novels = novels.filter((novel) => novel.name.toLowerCase().includes(searchTerm.toLowerCase()));
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-const fetchImage = function (url, init) {
- return __awaiter(this, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url, init);
- });
-};
-exports.fetchImage = fetchImage;
diff --git a/js/plugins/english/earlynovel.js b/js/plugins/english/earlynovel.js
deleted file mode 100644
index f39a00c..0000000
--- a/js/plugins/english/earlynovel.js
+++ /dev/null
@@ -1,174 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.icon = exports.version = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const showToast_1 = require("@libs/showToast");
-const defaultCover_1 = require("@libs/defaultCover");
-exports.id = "earlynovel";
-exports.name = "Early Novel";
-exports.version = "1.0.0";
-exports.icon = "multisrc/madara/icons/latestnovel.png";
-exports.site = "https://earlynovel.net/";
-const pluginId = exports.id;
-const baseUrl = exports.site;
-const popularNovels = function (page) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = `${baseUrl}most-popular?page=${page}`;
- const body = yield (0, fetch_1.fetchApi)(url, {}, pluginId).then((r) => r.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio(".col-truyen-main > .list-truyen > .row").each(function () {
- var _a;
- const novelName = loadedCheerio(this)
- .find("h3.truyen-title > a")
- .attr("title");
- const novelCover = loadedCheerio(this).find(".lazyimg").attr("data-desk-image") ||
- loadedCheerio(this).find("img.cover").attr("src");
- const novelUrl = baseUrl +
- ((_a = loadedCheerio(this)
- .find("h3.truyen-title > a")
- .attr("href")) === null || _a === void 0 ? void 0 : _a.slice(1));
- if (!novelUrl || !novelName)
- return;
- const novel = {
- name: novelName,
- cover: novelCover || defaultCover_1.defaultCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- var _a;
- return __awaiter(this, void 0, void 0, function* () {
- (0, showToast_1.showToast)("Early Novel may take 20-30 seconds");
- const url = novelUrl;
- const body = yield (0, fetch_1.fetchApi)(url, {}, pluginId).then((r) => r.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- const name = loadedCheerio(".book > img").attr("alt");
- const cover = loadedCheerio(".book > img").attr("src") || defaultCover_1.defaultCover;
- const summary = loadedCheerio(".desc-text").text().trim();
- const novel = {
- url,
- chapters: [],
- name,
- summary,
- cover,
- };
- loadedCheerio(".info > div > h3").each(function () {
- let detailName = loadedCheerio(this).text();
- let detail = loadedCheerio(this)
- .siblings()
- .map((i, el) => loadedCheerio(el).text())
- .toArray()
- .join(",");
- switch (detailName) {
- case "Author:":
- novel.author = detail;
- break;
- case "Status:":
- novel.status = detail;
- break;
- case "Genre:":
- novel.genres = detail;
- break;
- }
- });
- //! Doesn't work since there are multiple pages and can't find source API
- //# Since cannot find sourceAPI i try similar function to lightnovelpub
- const delay = (ms) => new Promise((res) => setTimeout(res, ms));
- const lastPageStr = (_a = loadedCheerio('a:contains("Last ")')
- .attr("title")) === null || _a === void 0 ? void 0 : _a.match(/(\d+)/g);
- const lastPage = Number((lastPageStr === null || lastPageStr === void 0 ? void 0 : lastPageStr[1]) || "0");
- function getChapters() {
- return __awaiter(this, void 0, void 0, function* () {
- let chapter = [];
- for (let i = 1; i <= lastPage; i++) {
- const chaptersUrl = `${novelUrl}?page=${i}`;
- const chaptersHtml = yield (0, fetch_1.fetchApi)(chaptersUrl, {}, pluginId).then((r) => r.text());
- loadedCheerio = (0, cheerio_1.load)(chaptersHtml);
- loadedCheerio("ul.list-chapter > li").each(function () {
- var _a;
- const chapterName = loadedCheerio(this)
- .find(".chapter-text")
- .text()
- .trim();
- const releaseDate = null;
- const chapterHref = (_a = loadedCheerio(this)
- .find("a")
- .attr("href")) === null || _a === void 0 ? void 0 : _a.slice(1);
- if (!chapterHref)
- return;
- const chapterUrl = baseUrl + chapterHref;
- chapter.push({
- name: chapterName,
- releaseTime: releaseDate,
- url: chapterUrl,
- });
- });
- yield delay(1000);
- }
- return chapter;
- });
- }
- novel.chapters = yield getChapters();
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const body = yield (0, fetch_1.fetchApi)(chapterUrl, {}, pluginId).then((r) => r.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio("#chapter-c").html() || "";
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = `${baseUrl}search?keyword=${searchTerm}`;
- const body = yield (0, fetch_1.fetchApi)(url, {}, pluginId).then((r) => r.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio("div.col-truyen-main > div.list-truyen > .row").each(function () {
- const novelUrl = baseUrl +
- loadedCheerio(this).find("h3.truyen-title > a").attr("href");
- const novelName = loadedCheerio(this)
- .find("h3.truyen-title > a")
- .text();
- const novelCover = baseUrl + loadedCheerio(this).find("img").attr("src");
- if (novelUrl) {
- novels.push({
- url: novelUrl,
- name: novelName,
- cover: novelCover,
- });
- }
- });
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-const fetchImage = function fetchImage(url) {
- return __awaiter(this, void 0, void 0, function* () {
- const headers = {
- Referer: baseUrl,
- };
- return yield (0, fetch_1.fetchFile)(url, { headers: headers });
- });
-};
-exports.fetchImage = fetchImage;
diff --git a/js/plugins/english/fastnovel.js b/js/plugins/english/fastnovel.js
deleted file mode 100644
index 23db36d..0000000
--- a/js/plugins/english/fastnovel.js
+++ /dev/null
@@ -1,152 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.icon = exports.version = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-exports.id = "fastnovel";
-exports.name = "Fast Novel";
-exports.version = "1.0.0";
-exports.icon = "src/en/fastnovel/icon.png";
-exports.site = "https://fastnovel.org/";
-const pluginId = exports.id;
-const baseUrl = exports.site;
-const popularNovels = function (page) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = `${baseUrl}sort/p/?page=${page}`;
- const body = yield (0, fetch_1.fetchApi)(url, {}, pluginId).then((r) => r.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio(".col-novel-main .list-novel .row").each(function () {
- const novelName = loadedCheerio(this).find("h3.novel-title > a").text();
- const novelCover = loadedCheerio(this).find("img.cover").attr("src");
- const novelUrl = loadedCheerio(this)
- .find("h3.novel-title > a")
- .attr("href");
- if (!novelUrl)
- return;
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = novelUrl;
- const body = yield (0, fetch_1.fetchApi)(url, {}, pluginId).then((r) => r.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- const novel = {
- url,
- chapters: [],
- };
- novel.name = loadedCheerio("div.book > img").attr("alt");
- novel.cover = loadedCheerio("div.book > img").attr("src");
- novel.summary = loadedCheerio("div.desc-text").text().trim();
- loadedCheerio("ul.info > li > h3").each(function () {
- let detailName = loadedCheerio(this).text();
- let detail = loadedCheerio(this)
- .siblings()
- .map((i, el) => loadedCheerio(el).text())
- .toArray()
- .join(",");
- switch (detailName) {
- case "Author:":
- novel.author = detail;
- break;
- case "Status:":
- novel.status = detail;
- break;
- case "Genre:":
- novel.genres = detail;
- break;
- }
- });
- const novelId = loadedCheerio("#rating").attr("data-novel-id");
- function getChapters(id) {
- return __awaiter(this, void 0, void 0, function* () {
- const chapterListUrl = baseUrl + "ajax/chapter-archive?novelId=" + id;
- const data = yield (0, fetch_1.fetchApi)(chapterListUrl);
- const chapterdata = yield data.text();
- loadedCheerio = (0, cheerio_1.load)(chapterdata);
- let chapter = [];
- loadedCheerio("ul.list-chapter > li").each(function () {
- const chapterName = loadedCheerio(this).find("a").attr("title");
- const releaseDate = null;
- const chapterUrl = loadedCheerio(this).find("a").attr("href");
- if (!chapterName || !chapterUrl)
- return;
- chapter.push({
- name: chapterName,
- releaseTime: releaseDate,
- url: chapterUrl,
- });
- });
- return chapter;
- });
- }
- if (novelId) {
- novel.chapters = yield getChapters(novelId);
- }
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const body = yield (0, fetch_1.fetchApi)(chapterUrl, {}, pluginId).then((r) => r.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('#chr-content > div,h6,p[style="display: none;"]').remove();
- let chapterText = loadedCheerio("#chr-content").html();
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = `${baseUrl}search/?keyword=${searchTerm}`;
- const body = yield (0, fetch_1.fetchApi)(url, {}, pluginId).then((r) => r.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio("div.col-novel-main > div.list-novel > .row").each(function () {
- const novelUrl = loadedCheerio(this)
- .find("h3.novel-title > a")
- .attr("href");
- const novelName = loadedCheerio(this)
- .find("h3.novel-title > a")
- .text();
- const novelCover = loadedCheerio(this).find("img").attr("src");
- if (novelUrl) {
- novels.push({
- url: novelUrl,
- name: novelName,
- cover: novelCover,
- });
- }
- });
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-const fetchImage = function (url) {
- return __awaiter(this, void 0, void 0, function* () {
- const headers = {
- Referer: baseUrl,
- };
- return yield (0, fetch_1.fetchFile)(url, { headers: headers });
- });
-};
-exports.fetchImage = fetchImage;
diff --git a/js/plugins/english/foxaholic.js b/js/plugins/english/foxaholic.js
deleted file mode 100644
index 3dd859f..0000000
--- a/js/plugins/english/foxaholic.js
+++ /dev/null
@@ -1,154 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.icon = exports.version = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-exports.id = "foxaholic";
-exports.name = "Foxaholic";
-exports.version = "1.0.0";
-exports.icon = "src/en/foxaholic/icon.png";
-exports.site = "https://www.foxaholic.com/";
-const pluginId = exports.id;
-const baseUrl = exports.site;
-const popularNovels = function (page) {
- return __awaiter(this, void 0, void 0, function* () {
- const link = `${baseUrl}novel/page/${page}/?m_orderby=rating`;
- const result = yield (0, fetch_1.fetchApi)(link, {}, pluginId);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- const novels = [];
- loadedCheerio(".page-item-detail").each(function () {
- const novelName = loadedCheerio(this).find(".h5 > a").text();
- const novelCover = loadedCheerio(this).find("img").attr("data-src");
- const novelUrl = loadedCheerio(this).find(".h5 > a").attr("href");
- if (!novelUrl)
- return;
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = novelUrl;
- const result = yield (0, fetch_1.fetchApi)(url, {}, pluginId);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- const novel = {
- url,
- chapters: [],
- };
- novel.name = loadedCheerio(".post-title > h1").text().trim();
- novel.cover = loadedCheerio(".summary_image > a > img").attr("data-src");
- loadedCheerio(".post-content_item").each(function () {
- const detailName = loadedCheerio(this)
- .find(".summary-heading > h5")
- .text()
- .trim();
- const detail = loadedCheerio(this).find(".summary-content").html();
- if (!detail)
- return;
- switch (detailName) {
- case "Genre":
- novel.genres = loadedCheerio(detail)
- .children("a")
- .map((i, el) => loadedCheerio(el).text())
- .toArray()
- .join(",");
- break;
- case "Author":
- novel.author = loadedCheerio(detail)
- .children("a")
- .map((i, el) => loadedCheerio(el).text())
- .toArray()
- .join(", ");
- break;
- case "Novel":
- novel.status = detail === null || detail === void 0 ? void 0 : detail.trim().replace(/G/g, "g");
- break;
- }
- });
- loadedCheerio(".description-summary > div.summary__content > div").remove();
- novel.summary = loadedCheerio(".description-summary > div.summary__content")
- .text()
- .trim();
- let chapter = [];
- loadedCheerio(".wp-manga-chapter").each(function () {
- const chapterName = loadedCheerio(this)
- .find("a")
- .text()
- .replace(/[\t\n]/g, "")
- .trim();
- const releaseDate = loadedCheerio(this).find("span").text().trim();
- const chapterUrl = loadedCheerio(this).find("a").attr("href");
- if (!chapterUrl)
- return;
- chapter.push({
- name: chapterName,
- releaseTime: releaseDate,
- url: chapterUrl,
- });
- });
- novel.chapters = chapter.reverse();
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const result = yield (0, fetch_1.fetchApi)(chapterUrl, {}, pluginId);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio("img").removeAttr("srcset");
- let chapterText = loadedCheerio(".reading-content").html();
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = `${baseUrl}?s=${searchTerm}&post_type=wp-manga`;
- const result = yield (0, fetch_1.fetchApi)(url, {}, pluginId);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- const novels = [];
- loadedCheerio(".c-tabs-item__content").each(function () {
- const novelName = loadedCheerio(this).find(".h4 > a").text();
- const novelCover = loadedCheerio(this).find("img").attr("data-src");
- const novelUrl = loadedCheerio(this).find(".h4 > a").attr("href");
- if (!novelUrl)
- return;
- novels.push({
- name: novelName,
- url: novelUrl,
- cover: novelCover,
- });
- });
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-const fetchImage = function (url) {
- return __awaiter(this, void 0, void 0, function* () {
- const headers = {
- Referer: baseUrl,
- };
- return yield (0, fetch_1.fetchFile)(url, { headers: headers });
- });
-};
-exports.fetchImage = fetchImage;
diff --git a/js/plugins/english/freenovelupdates.js b/js/plugins/english/freenovelupdates.js
deleted file mode 100644
index e37a6e3..0000000
--- a/js/plugins/english/freenovelupdates.js
+++ /dev/null
@@ -1,118 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.icon = exports.version = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const showToast_1 = require("@libs/showToast");
-const isAbsoluteUrl_1 = require("@libs/isAbsoluteUrl");
-exports.id = "freenovelupdates";
-exports.name = "Free Novel Updates (Broken)";
-exports.version = "1.0.0";
-exports.icon = "src/en/freenovelupdates/icon.png";
-exports.site = "https://www.freenovelupdates.com";
-const pluginId = exports.id;
-const baseUrl = exports.site;
-const popularNovels = function (page) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = `${baseUrl}genres/light-novel-1002`;
- const body = yield (0, fetch_1.fetchApi)(url, {}, pluginId).then((r) => r.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio(".books-item").each(function () {
- let novelUrl = loadedCheerio(this).find("a").attr("href");
- if (novelUrl && !(0, isAbsoluteUrl_1.isUrlAbsolute)(novelUrl)) {
- novelUrl = baseUrl + novelUrl;
- }
- if (novelUrl) {
- const novelName = loadedCheerio(this).find(".title").text().trim();
- let novelCover = loadedCheerio(this).find("img").attr("src");
- if (novelCover && !(0, isAbsoluteUrl_1.isUrlAbsolute)(novelCover)) {
- novelCover = baseUrl + novelCover;
- }
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- }
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = novelUrl;
- const body = yield (0, fetch_1.fetchApi)(url, {}, pluginId).then((r) => r.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- const novel = {
- url,
- chapters: [],
- };
- novel.name = loadedCheerio("h1").text();
- let novelCover = loadedCheerio(".img > img").attr("src");
- novel.cover = novelCover
- ? (0, isAbsoluteUrl_1.isUrlAbsolute)(novelCover)
- ? novelCover
- : baseUrl + novelCover
- : undefined;
- novel.summary = loadedCheerio(".description-content").text().trim();
- novel.author = loadedCheerio(".author").text().trim();
- novel.genres = loadedCheerio(".category").text().trim();
- novel.status = loadedCheerio(".status").text().trim();
- loadedCheerio(".chapter").each(function () {
- var _a;
- let chapterUrl = loadedCheerio(this).find("a").attr("href");
- if (chapterUrl && !(0, isAbsoluteUrl_1.isUrlAbsolute)(chapterUrl)) {
- chapterUrl = baseUrl + chapterUrl;
- }
- if (chapterUrl) {
- const chapterName = loadedCheerio(this).find("a").text().trim();
- const releaseDate = null;
- const chapter = {
- name: chapterName,
- releaseTime: releaseDate,
- url: chapterUrl,
- };
- (_a = novel.chapters) === null || _a === void 0 ? void 0 : _a.push(chapter);
- }
- });
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const body = yield (0, fetch_1.fetchApi)(chapterUrl, {}, pluginId).then((r) => r.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio(".content").html() || "";
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- return __awaiter(this, void 0, void 0, function* () {
- (0, showToast_1.showToast)("Search is not available in this source");
- return [];
- });
-};
-exports.searchNovels = searchNovels;
-const fetchImage = function (url) {
- return __awaiter(this, void 0, void 0, function* () {
- const headers = {
- Referer: baseUrl,
- };
- return yield (0, fetch_1.fetchFile)(url, { headers: headers });
- });
-};
-exports.fetchImage = fetchImage;
diff --git a/js/plugins/english/freewebnovel.js b/js/plugins/english/freewebnovel.js
deleted file mode 100644
index 71fee28..0000000
--- a/js/plugins/english/freewebnovel.js
+++ /dev/null
@@ -1,141 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.icon = exports.version = exports.site = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-exports.id = "FWN.com";
-exports.name = "Web NOVEL";
-exports.site = "https://freewebnovel.com/";
-exports.version = "1.0.0";
-exports.icon = "src/en/freewebnovel/icon.png";
-const baseUrl = exports.site;
-const popularNovels = function (page) {
- return __awaiter(this, void 0, void 0, function* () {
- let url = baseUrl + "completed-novel/" + page;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio(".li-row").each(function () {
- const novelName = loadedCheerio(this).find(".tit").text();
- const novelCover = loadedCheerio(this).find("img").attr("src");
- let novelUrl = "https://freewebnovel.com" +
- loadedCheerio(this).find("h3 > a").attr("href");
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = novelUrl;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- let novel = {
- url,
- };
- novel.name = loadedCheerio("h1.tit").text();
- novel.cover = loadedCheerio(".pic > img").attr("src");
- novel.genres = loadedCheerio("[title=Genre]")
- .next()
- .text()
- .replace(/[\t\n]/g, "");
- novel.author = loadedCheerio("[title=Author]")
- .next()
- .text()
- .replace(/[\t\n]/g, "");
- novel.status = loadedCheerio("[title=Status]")
- .next()
- .text()
- .replace(/[\t\n]/g, "");
- let novelSummary = loadedCheerio(".inner").text().trim();
- novel.summary = novelSummary;
- let novelChapters = [];
- let latestChapter;
- loadedCheerio("h3.tit").each(function (res) {
- var _a;
- if (loadedCheerio(this).find("a").text() === novel.name) {
- latestChapter = (_a = loadedCheerio(this)
- .next()
- .find("span.s3")
- .text()
- .match(/(\d+)/)) === null || _a === void 0 ? void 0 : _a[0];
- }
- });
- let prefixUrl = novelUrl.replace(".html", "/");
- for (let i = 1; i <= parseInt(latestChapter || "0", 10); i++) {
- const chapterName = "Chapter " + i;
- const releaseDate = null;
- let chapterUrl = "chapter-" + i;
- chapterUrl = `${prefixUrl}${chapterUrl}.html`;
- const chapter = {
- name: chapterName,
- releaseTime: releaseDate,
- url: chapterUrl,
- };
- novelChapters.push(chapter);
- }
- novel.chapters = novelChapters;
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = chapterUrl;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- let chapterText = loadedCheerio("div.txt").html();
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = baseUrl + "search/";
- const formData = {
- searchkey: searchTerm,
- };
- const result = yield (0, fetch_1.fetchApi)(url, {
- method: "POST",
- body: JSON.stringify(formData),
- });
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio(".li-row > .li > .con").each(function () {
- const novelName = loadedCheerio(this).find(".tit").text();
- const novelCover = loadedCheerio(this)
- .find(".pic > a > img")
- .attr("data-cfsrc");
- let novelUrl = "https://freewebnovel.com" +
- loadedCheerio(this).find("h3 > a").attr("href");
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-exports.fetchImage = fetch_1.fetchFile;
diff --git a/js/plugins/english/lightnovelpub.js b/js/plugins/english/lightnovelpub.js
deleted file mode 100644
index b397d5c..0000000
--- a/js/plugins/english/lightnovelpub.js
+++ /dev/null
@@ -1,171 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.icon = exports.version = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-exports.id = "lightnovelpub";
-exports.name = "LightNovelPub";
-exports.version = "1.0.0";
-exports.icon = "src/en/lightnovelpub/icon.png";
-exports.site = "https://www.lightnovelpub.com/";
-const baseUrl = exports.site;
-const pluginId = exports.id;
-const headers = {
- Accept: "application/json",
- "Content-Type": "application/json",
-};
-const popularNovels = function (page) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = `${baseUrl}browse/all/popular/all/${page}`;
- const body = yield (0, fetch_1.fetchApi)(url, {}, pluginId).then((r) => r.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const novels = [];
- loadedCheerio(".novel-item.ads").remove();
- loadedCheerio(".novel-item").each(function () {
- var _a;
- const novelName = loadedCheerio(this)
- .find(".novel-title")
- .text()
- .trim();
- const novelCover = loadedCheerio(this).find("img").attr("data-src");
- const novelUrl = baseUrl +
- ((_a = loadedCheerio(this)
- .find(".novel-title > a")
- .attr("href")) === null || _a === void 0 ? void 0 : _a.substring(1));
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- var _a;
- return __awaiter(this, void 0, void 0, function* () {
- const url = novelUrl;
- const body = yield (0, fetch_1.fetchApi)(url, {}, pluginId).then((r) => r.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- const novel = {
- url,
- chapters: [],
- };
- novel.name = loadedCheerio("h1.novel-title").text().trim();
- novel.cover = loadedCheerio("figure.cover > img").attr("data-src");
- novel.genres = "";
- loadedCheerio(".categories > ul > li > a").each(function () {
- novel.genres += loadedCheerio(this).text() + ",";
- });
- novel.genres = novel.genres.slice(0, -1);
- loadedCheerio("div.header-stats > span").each(function () {
- if (loadedCheerio(this).find("small").text() === "Status") {
- novel.status = loadedCheerio(this).find("strong").text();
- }
- });
- novel.author = loadedCheerio(".author > a > span").text();
- novel.summary = loadedCheerio(".summary > .content").text().trim();
- const delay = (ms) => new Promise((res) => setTimeout(res, ms));
- let lastPage = 1;
- lastPage = parseInt((_a = loadedCheerio("#novel > header > div.header-body.container > div.novel-info > div.header-stats > span:nth-child(1) > strong")
- .text()) === null || _a === void 0 ? void 0 : _a.trim());
- lastPage = Math.ceil(lastPage / 100);
- function getChapters() {
- return __awaiter(this, void 0, void 0, function* () {
- let chapter = [];
- for (let i = 1; i <= lastPage; i++) {
- const chaptersUrl = `${novelUrl}/chapters/page-${i}`;
- const chaptersHtml = yield (0, fetch_1.fetchApi)(chaptersUrl, { headers: headers }, pluginId).then((r) => r.text());
- loadedCheerio = (0, cheerio_1.load)(chaptersHtml);
- loadedCheerio(".chapter-list li").each(function () {
- var _a;
- const chapterName = loadedCheerio(this)
- .find(".chapter-title")
- .text()
- .trim();
- const releaseDate = loadedCheerio(this)
- .find(".chapter-update")
- .text()
- .trim();
- const chapterUrl = baseUrl +
- ((_a = loadedCheerio(this)
- .find("a")
- .attr("href")) === null || _a === void 0 ? void 0 : _a.substring(1));
- chapter.push({
- name: chapterName,
- releaseTime: releaseDate,
- url: chapterUrl,
- });
- });
- yield delay(1000);
- }
- return chapter;
- });
- }
- novel.chapters = yield getChapters();
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const body = yield (0, fetch_1.fetchApi)(chapterUrl, {}, pluginId).then((r) => r.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- let chapterText = loadedCheerio("#chapter-container").html();
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = `${baseUrl}lnsearchlive`;
- const link = `${baseUrl}search`;
- const response = yield (0, fetch_1.fetchApi)(link, {}, pluginId).then((r) => r.text());
- const token = (0, cheerio_1.load)(response);
- let verifytoken = token("#novelSearchForm > input").attr("value");
- let formData = new FormData();
- formData.append("inputContent", searchTerm);
- const body = yield (0, fetch_1.fetchApi)(url, {
- method: "POST",
- headers: { LNRequestVerifyToken: verifytoken },
- body: formData,
- }, pluginId).then((r) => r.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- let results = JSON.parse(loadedCheerio("body").text());
- loadedCheerio = (0, cheerio_1.load)(results.resultview);
- loadedCheerio(".novel-item").each(function () {
- var _a;
- const novelName = loadedCheerio(this)
- .find("h4.novel-title")
- .text()
- .trim();
- const novelCover = loadedCheerio(this).find("img").attr("src");
- const novelUrl = baseUrl + ((_a = loadedCheerio(this).find("a").attr("href")) === null || _a === void 0 ? void 0 : _a.substring(1));
- novels.push({
- name: novelName,
- url: novelUrl,
- cover: novelCover,
- });
- });
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-const fetchImage = function (url) {
- return __awaiter(this, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url, { headers: headers });
- });
-};
-exports.fetchImage = fetchImage;
diff --git a/js/plugins/english/mtlreader.js b/js/plugins/english/mtlreader.js
deleted file mode 100644
index 06d7285..0000000
--- a/js/plugins/english/mtlreader.js
+++ /dev/null
@@ -1,121 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.icon = exports.version = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-exports.id = "mtlreader";
-exports.name = "MTL Reader";
-exports.version = "1.0.0";
-exports.icon = "src/en/mtlreader/icon.png";
-exports.site = "https://mtlreader.com/";
-const pluginId = exports.id;
-const baseUrl = exports.site;
-const popularNovels = function (page) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = `${baseUrl}novels?page=${page}`;
- const body = yield (0, fetch_1.fetchApi)(url, {}, pluginId).then((r) => r.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio(".col-md-4.col-sm-4").each(function () {
- const novelName = loadedCheerio(this).find("h5").text();
- const novelCover = loadedCheerio(this).find("img").attr("src");
- const novelUrl = loadedCheerio(this).find("h5 > a").attr("href");
- if (!novelUrl)
- return;
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = novelUrl;
- const body = yield (0, fetch_1.fetchApi)(url, {}, pluginId).then((r) => r.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- const novel = {
- url,
- chapters: [],
- };
- novel.name = loadedCheerio(".agent-title").text().trim();
- novel.cover = loadedCheerio(".agent-p-img > img").attr("src");
- novel.summary = loadedCheerio("#editdescription").text().trim();
- novel.author = loadedCheerio("i.fa-user")
- .parent()
- .text()
- .replace("Author: ", "")
- .trim();
- let chapter = [];
- loadedCheerio("tr.spaceUnder").each(function () {
- const chapterName = loadedCheerio(this).find("a").text().trim();
- const releaseDate = null;
- const chapterUrl = loadedCheerio(this).find("a").attr("href");
- if (!chapterUrl)
- return;
- chapter.push({
- name: chapterName,
- releaseTime: releaseDate,
- url: chapterUrl,
- });
- });
- novel.chapters = chapter;
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const body = yield (0, fetch_1.fetchApi)(chapterUrl, {}, pluginId).then((r) => r.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio(".container ins,script,p.mtlreader").remove();
- const chapterText = loadedCheerio(".container").html();
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = `${baseUrl}search?input=${searchTerm}`;
- const body = yield (0, fetch_1.fetchApi)(url, {}, pluginId).then((r) => r.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio(".col-md-4.col-sm-4").each(function () {
- const novelName = loadedCheerio(this).find("h5").text();
- const novelCover = loadedCheerio(this).find("img").attr("src");
- const novelUrl = loadedCheerio(this).find("h5 > a").attr("href");
- if (!novelUrl)
- return;
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-const fetchImage = function (url) {
- return __awaiter(this, void 0, void 0, function* () {
- const headers = {
- Referer: baseUrl,
- };
- return yield (0, fetch_1.fetchFile)(url, { headers: headers });
- });
-};
-exports.fetchImage = fetchImage;
diff --git a/js/plugins/english/nitroscans.js b/js/plugins/english/nitroscans.js
deleted file mode 100644
index 4a9355e..0000000
--- a/js/plugins/english/nitroscans.js
+++ /dev/null
@@ -1,166 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.icon = exports.version = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-exports.id = "nitroscans";
-exports.name = "Nitroscans";
-exports.version = "1.0.0";
-exports.icon = "src/en/nitroscans/icon.png";
-exports.site = "https://nitroscans.com/";
-const baseUrl = exports.site;
-const popularNovels = function (page) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = baseUrl + "wp-admin/admin-ajax.php";
- let formData = new FormData();
- formData.append("action", "madara_load_more");
- formData.append("page", `${Number(page - 1)}`);
- formData.append("template", "madara-core/content/content-archive");
- formData.append("vars[orderby]", "meta_value_num");
- formData.append("vars[post_type]", "wp-manga");
- formData.append("vars[meta_key]", "_wp_manga_views");
- formData.append("vars[wp-manga-genre]", "novels");
- const body = yield (0, fetch_1.fetchApi)(url, {
- method: "POST",
- body: formData,
- }).then((r) => r.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio(".page-item-detail").each(function () {
- const novelName = loadedCheerio(this).find("h3 > a").text();
- const novelCover = loadedCheerio(this).find("img").attr("data-src");
- const novelUrl = loadedCheerio(this).find("h3 > a").attr("href");
- if (!novelUrl)
- return;
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- var _a;
- return __awaiter(this, void 0, void 0, function* () {
- const url = novelUrl;
- const body = yield (0, fetch_1.fetchApi)(url).then((r) => r.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- const novel = {
- url,
- chapters: [],
- };
- loadedCheerio(".manga-title-badges.custom.novel").remove();
- novel.name = loadedCheerio(".post-title > h1").text().trim();
- novel.cover = loadedCheerio(".summary_image")
- .find("img")
- .attr("data-src");
- novel.summary = (_a = loadedCheerio(".summary__content").text()) === null || _a === void 0 ? void 0 : _a.trim();
- novel.genres = loadedCheerio(".genres-content")
- .children("a")
- .map((i, el) => loadedCheerio(el).text())
- .toArray()
- .join(",");
- loadedCheerio(".post-content_item").each(function () {
- const detailName = loadedCheerio(this)
- .find(".summary-heading")
- .text()
- .trim();
- const detail = loadedCheerio(this)
- .find(".summary-content")
- .text()
- .trim();
- switch (detailName) {
- case "Author(s)":
- novel.author = detail;
- break;
- case "Status":
- novel.status = detail.replace(/G/g, "g");
- break;
- }
- });
- let chapter = [];
- let chapterlisturl = novelUrl + "ajax/chapters/";
- const data = yield (0, fetch_1.fetchApi)(chapterlisturl, { method: "POST" });
- const text = yield data.text();
- loadedCheerio = (0, cheerio_1.load)(text);
- loadedCheerio(".wp-manga-chapter").each(function () {
- const chapterName = loadedCheerio(this).find("a").text().trim();
- const releaseDate = loadedCheerio(this).find("span").text().trim();
- const chapterUrl = loadedCheerio(this).find("a").attr("href");
- if (!chapterUrl)
- return;
- chapter.push({
- name: chapterName,
- releaseTime: releaseDate,
- url: chapterUrl,
- });
- });
- novel.chapters = chapter.reverse();
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then((r) => r.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio(".text-left").html();
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = baseUrl + "wp-admin/admin-ajax.php";
- let formData = new FormData();
- formData.append("action", "madara_load_more");
- formData.append("page", `${Number(1 - 1)}`);
- formData.append("template", "madara-core/content/content-search");
- formData.append("vars[s]", searchTerm);
- formData.append("vars[post_type]", "wp-manga");
- formData.append("vars[wp-manga-genre]", "novels");
- const body = yield (0, fetch_1.fetchApi)(url, {
- method: "POST",
- body: formData,
- }).then((r) => r.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio(".c-tabs-item__content").each(function () {
- const novelName = loadedCheerio(this).find("h3 > a").text();
- const novelCover = loadedCheerio(this).find("img").attr("data-src");
- const novelUrl = loadedCheerio(this).find("h3 > a").attr("href");
- if (!novelUrl)
- return;
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-const fetchImage = function (url) {
- return __awaiter(this, void 0, void 0, function* () {
- const headers = {
- Referer: baseUrl,
- };
- return yield (0, fetch_1.fetchFile)(url, { headers: headers });
- });
-};
-exports.fetchImage = fetchImage;
diff --git a/js/plugins/english/nobleMTL.js b/js/plugins/english/nobleMTL.js
deleted file mode 100644
index 5e8a120..0000000
--- a/js/plugins/english/nobleMTL.js
+++ /dev/null
@@ -1,299 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.icon = exports.version = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const filterInputs_1 = require("@libs/filterInputs");
-exports.id = "NobleMTL";
-exports.name = "NobleMTL";
-exports.version = "1.0.0";
-exports.icon = "src/en/noblemtl/icon.png";
-exports.site = "https://www.noblemtl.com/";
-const popularNovels = function (page, { filters }) {
- var _a, _b;
- return __awaiter(this, void 0, void 0, function* () {
- let link = `${exports.site}series/?page=${page}`;
- if ((_a = filters === null || filters === void 0 ? void 0 : filters.genres) === null || _a === void 0 ? void 0 : _a.length) {
- if (Array.isArray(filters.genres))
- link += filters.genres.map((i) => `&genre[]=${i}`).join("");
- }
- if ((_b = filters === null || filters === void 0 ? void 0 : filters.type) === null || _b === void 0 ? void 0 : _b.length) {
- if (Array.isArray(filters.type))
- link += filters.type.map((i) => `&lang[]=${i}`).join("");
- }
- link += "&status=" + ((filters === null || filters === void 0 ? void 0 : filters.status) ? filters === null || filters === void 0 ? void 0 : filters.status : "");
- link += "&order=" + ((filters === null || filters === void 0 ? void 0 : filters.order) ? filters === null || filters === void 0 ? void 0 : filters.order : "popular");
- const body = yield (0, fetch_1.fetchApi)(link).then((result) => result.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const novels = [];
- loadedCheerio("article.bs").each(function () {
- const novelName = loadedCheerio(this).find(".ntitle").text().trim();
- let image = loadedCheerio(this).find("img");
- const novelCover = image.attr("data-src") || image.attr("src");
- const novelUrl = loadedCheerio(this).find("a").attr("href");
- if (!novelUrl)
- return;
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function parseNovelAndChapters(novelUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = novelUrl;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- const novel = {
- url,
- chapters: [],
- };
- novel.name = loadedCheerio(".entry-title").text();
- novel.cover =
- loadedCheerio("img.wp-post-image").attr("data-src") ||
- loadedCheerio("img.wp-post-image").attr("src");
- loadedCheerio("div.spe > span").each(function () {
- const detailName = loadedCheerio(this).find("b").text().trim();
- const detail = loadedCheerio(this)
- .find("b")
- .remove()
- .end()
- .text()
- .trim();
- switch (detailName) {
- case "المؤلف:":
- case "Yazar:":
- case "Autor:":
- case "Author:":
- novel.author = detail;
- break;
- case "Status:":
- case "Seviye:":
- novel.status = detail;
- break;
- }
- });
- novel.genres = loadedCheerio(".genxed")
- .text()
- .trim()
- .replace(/\s/g, ",");
- loadedCheerio('div[itemprop="description"] h3,p.a,strong').remove();
- novel.summary = loadedCheerio('div[itemprop="description"]')
- .find("br")
- .replaceWith("\n")
- .end()
- .text();
- let chapter = [];
- loadedCheerio(".eplister")
- .find("li")
- .each(function () {
- const chapterName = loadedCheerio(this).find(".epl-num").text() +
- " - " +
- loadedCheerio(this).find(".epl-title").text();
- const releaseDate = loadedCheerio(this)
- .find(".epl-date")
- .text()
- .trim();
- const chapterUrl = loadedCheerio(this).find("a").attr("href");
- if (!chapterUrl)
- return;
- chapter.push({
- name: chapterName,
- releaseTime: releaseDate,
- url: chapterUrl,
- });
- });
- novel.chapters = chapter.reverse();
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const result = yield (0, fetch_1.fetchApi)(chapterUrl);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- let chapterText = loadedCheerio("div.epcontent").html();
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = `${exports.site}?s=${searchTerm}`;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- const novels = [];
- loadedCheerio("article.bs").each(function () {
- const novelName = loadedCheerio(this).find(".ntitle").text().trim();
- const novelCover = loadedCheerio(this).find("img").attr("src");
- const novelUrl = loadedCheerio(this).find("a").attr("href");
- if (!novelUrl)
- return;
- novels.push({
- name: novelName,
- url: novelUrl,
- cover: novelCover,
- });
- });
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-const fetchImage = function (url) {
- return __awaiter(this, void 0, void 0, function* () {
- const headers = {
- Referer: exports.site,
- };
- return yield (0, fetch_1.fetchFile)(url, { headers: headers });
- });
-};
-exports.fetchImage = fetchImage;
-exports.filters = [
- {
- key: "order",
- label: "Sort By",
- values: [
- { label: "Default", value: "" },
- { label: "A-Z", value: "title" },
- { label: "Z-A", value: "titlereverse" },
- { label: "Latest Update", value: "update" },
- { label: "Latest Added", value: "latest" },
- { label: "Popular", value: "popular" },
- ],
- inputType: filterInputs_1.FilterInputs.Picker,
- },
- {
- key: "status",
- label: "Status",
- values: [
- { label: "All", value: "" },
- { label: "Ongoing", value: "ongoing" },
- { label: "Hiatus", value: "hiatus" },
- { label: "Completed", value: "completed" },
- ],
- inputType: filterInputs_1.FilterInputs.Picker,
- },
- {
- key: "type",
- label: "Type",
- values: [
- { label: "Chinese novel", value: "chinese-novel" },
- { label: "habyeol", value: "habyeol" },
- { label: "korean novel", value: "korean-novel" },
- { label: "Web Novel", value: "web-novel" },
- { label: "삼심", value: "%ec%82%bc%ec%8b%ac" },
- { label: "호곡", value: "%ed%98%b8%ea%b3%a1" },
- ],
- inputType: filterInputs_1.FilterInputs.Checkbox,
- },
- {
- key: "genres",
- label: "Genres",
- values: [
- { label: "A.I", value: "a.i" },
- { label: "Academy", value: "academy" },
- { label: "Action", value: "action" },
- { label: "Adult", value: "adult" },
- { label: "Adventure", value: "adventure" },
- { label: "Alternative History", value: "alternative-history" },
- { label: "Another World", value: "another-world" },
- { label: "Apocalypse", value: "apocalypse" },
- { label: "Bromance", value: "bromance" },
- { label: "Comedy", value: "comedy" },
- { label: "Dark fantasy", value: "dark-fantasy" },
- { label: "Demons", value: "demons" },
- { label: "Drama", value: "drama" },
- { label: "Dystopia", value: "dystopia" },
- { label: "Ecchi", value: "ecchi" },
- { label: "Entertainment", value: "entertainment" },
- { label: "Exhaustion", value: "exhaustion" },
- { label: "Fanfiction", value: "fanfiction" },
- { label: "fantasy", value: "fantasy" },
- { label: "finance", value: "finance" },
- { label: "Full color", value: "full-color" },
- { label: "Game", value: "game" },
- { label: "Gender Bender", value: "gender-bender" },
- { label: "Genius", value: "genius" },
- { label: "Harem", value: "harem" },
- { label: "Hero", value: "hero" },
- { label: "Historical", value: "historical" },
- { label: "Hunter", value: "hunter" },
- { label: "korean novel", value: "korean-novel" },
- { label: "Light Novel", value: "light-novel" },
- {
- label: "List Adventure Manga Genres",
- value: "list-adventure-manga-genres",
- },
- { label: "Long Strip", value: "long-strip" },
- { label: "Love comedy", value: "love-comedy" },
- { label: "magic", value: "magic" },
- { label: "Manhua", value: "manhua" },
- { label: "Martial Arts", value: "martial-arts" },
- { label: "Mature", value: "mature" },
- { label: "Medieval", value: "medieval" },
- { label: "Misunderstanding", value: "misunderstanding" },
- { label: "Modern", value: "modern" },
- { label: "modern fantasy", value: "modern-fantasy" },
- { label: "music", value: "music" },
- { label: "Mystery", value: "mystery" },
- { label: "Necromancy", value: "necromancy" },
- { label: "No Romance", value: "no-romance" },
- { label: "NTL", value: "ntl" },
- { label: "o", value: "o" },
- { label: "Obsession", value: "obsession" },
- { label: "Politics", value: "politics" },
- { label: "Possession", value: "possession" },
- { label: "Programming", value: "programming" },
- { label: "Psychological", value: "psychological" },
- { label: "Pure Love", value: "pure-love" },
- { label: "Redemption", value: "redemption" },
- { label: "Regression", value: "regression" },
- { label: "Regret", value: "regret" },
- { label: "Reincarnation", value: "reincarnation" },
- { label: "Revenge", value: "revenge" },
- { label: "Romance", value: "romance" },
- { label: "Romance Fanrasy", value: "romance-fanrasy" },
- { label: "Salvation", value: "salvation" },
- { label: "School Life", value: "school-life" },
- { label: "Sci-fi", value: "sci-fi" },
- { label: "Science fiction", value: "science-fiction" },
- { label: "Seinen", value: "seinen" },
- { label: "Shounen", value: "shounen" },
- { label: "Slice of Life", value: "slice-of-life" },
- { label: "Soft yandere", value: "soft-yandere" },
- { label: "Sports", value: "sports" },
- { label: "Supernatural", value: "supernatural" },
- { label: "Survival", value: "survival" },
- { label: "system", value: "system" },
- { label: "Time limit", value: "time-limit" },
- { label: "Tragedy", value: "tragedy" },
- { label: "Transmigration", value: "transmigration" },
- { label: "TS", value: "ts" },
- { label: "Tsundere", value: "tsundere" },
- { label: "Unique", value: "unique" },
- { label: "Wholesome", value: "wholesome" },
- { label: "Wuxia", value: "wuxia" },
- { label: "Xuanhuan", value: "xuanhuan" },
- { label: "Yandere", value: "yandere" },
- { label: "Yuri", value: "yuri" },
- ],
- inputType: filterInputs_1.FilterInputs.Checkbox,
- },
-];
diff --git a/js/plugins/english/novelforest.js b/js/plugins/english/novelforest.js
deleted file mode 100644
index 70fa2d3..0000000
--- a/js/plugins/english/novelforest.js
+++ /dev/null
@@ -1,126 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.icon = exports.version = exports.name = exports.id = void 0;
-const fetch_1 = require("@libs/fetch");
-const cheerio_1 = require("cheerio");
-exports.id = "novelforest";
-exports.name = "Novel Forest (Broken)";
-exports.version = "1.0.0";
-exports.icon = "src/en/novelforest/icon.png";
-exports.site = "https://novelforest.com/";
-const pluginId = exports.id;
-const baseUrl = exports.site;
-const popularNovels = function (page) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = `${baseUrl}popular?page=${page}`;
- const body = yield (0, fetch_1.fetchApi)(url, {}, pluginId).then((r) => r.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio(".book-item").each(function () {
- var _a;
- const novelName = loadedCheerio(this).find(".title").text();
- const novelCover = "https:" + loadedCheerio(this).find("img").attr("data-src");
- const novelUrl = baseUrl +
- ((_a = loadedCheerio(this).find(".title a").attr("href")) === null || _a === void 0 ? void 0 : _a.substring(1));
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- var _a, _b, _c;
- const url = novelUrl;
- const body = yield (0, fetch_1.fetchApi)(url, {}, pluginId).then((r) => r.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- const novel = {
- url,
- chapters: [],
- };
- novel.name = loadedCheerio(".name h1").text().trim();
- novel.cover = "https:" + loadedCheerio(".img-cover img").attr("data-src");
- novel.summary = loadedCheerio("body > div.layout > div.main-container.book-details > div > div.row.no-gutters > div.col-lg-8 > div.mt-1 > div.section.box.mt-1.summary > div.section-body > p.content")
- .text()
- .trim();
- novel.author = (_a = loadedCheerio("body > div.layout > div.main-container.book-details > div > div.row.no-gutters > div.col-lg-8 > div.book-info > div.detail > div.meta.box.mt-1.p-10 > p:nth-child(1) > a > span")
- .text()) === null || _a === void 0 ? void 0 : _a.trim();
- novel.status = (_b = loadedCheerio("body > div.layout > div.main-container.book-details > div > div.row.no-gutters > div.col-lg-8 > div.book-info > div.detail > div.meta.box.mt-1.p-10 > p:nth-child(2) > a > span")
- .text()) === null || _b === void 0 ? void 0 : _b.trim();
- novel.genres = (_c = loadedCheerio("body > div.layout > div.main-container.book-details > div > div.row.no-gutters > div.col-lg-8 > div.book-info > div.detail > div.meta.box.mt-1.p-10 > p:nth-child(3)")
- .text()) === null || _c === void 0 ? void 0 : _c.replace("Genres :", "").replace(/[\s\n]+/g, " ").trim();
- let chapter = [];
- const chaptersUrl = novelUrl.replace(baseUrl, "https://novelforest.com/api/novels/") +
- "/chapters?source=detail";
- const chaptersRequest = yield fetch(chaptersUrl);
- const chaptersHtml = yield chaptersRequest.text();
- loadedCheerio = (0, cheerio_1.load)(chaptersHtml);
- loadedCheerio("li").each(function () {
- var _a;
- const chapterName = loadedCheerio(this)
- .find(".chapter-title")
- .text()
- .trim();
- const releaseDate = loadedCheerio(this)
- .find(".chapter-update")
- .text()
- .trim();
- const chapterUrl = baseUrl + ((_a = loadedCheerio(this).find("a").attr("href")) === null || _a === void 0 ? void 0 : _a.substring(1));
- chapter.push({
- name: chapterName,
- releaseTime: releaseDate,
- url: chapterUrl,
- });
- });
- novel.chapters = chapter;
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const body = yield (0, fetch_1.fetchApi)(chapterUrl, {}, pluginId).then((r) => r.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio("#listen-chapter").remove();
- loadedCheerio("#google_translate_element").remove();
- const chapterText = loadedCheerio(".chapter__content").html();
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = `${baseUrl}search?q=${searchTerm}`;
- const body = yield (0, fetch_1.fetchApi)(url, {}, pluginId).then((r) => r.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio(".book-item").each(function () {
- var _a;
- const novelName = loadedCheerio(this).find(".title").text();
- const novelCover = "https:" + loadedCheerio(this).find("img").attr("data-src");
- const novelUrl = baseUrl +
- ((_a = loadedCheerio(this).find(".title a").attr("href")) === null || _a === void 0 ? void 0 : _a.substring(1));
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-exports.fetchImage = fetch_1.fetchFile;
diff --git a/js/plugins/english/novelfull.js b/js/plugins/english/novelfull.js
deleted file mode 100644
index 0022bbe..0000000
--- a/js/plugins/english/novelfull.js
+++ /dev/null
@@ -1,147 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.icon = exports.version = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-exports.id = "novelfull";
-exports.name = "NovelFull";
-exports.version = "1.0.0";
-exports.icon = "src/en/novelfull/icon.png";
-exports.site = "https://novelfull.com/";
-const baseUrl = exports.site;
-const popularNovels = function (page) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = `${baseUrl}most-popular?page=${page}`;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio(".col-truyen-main .list-truyen .row").each(function () {
- var _a, _b;
- const novelName = loadedCheerio(this)
- .find("h3.truyen-title > a")
- .text();
- const novelCover = baseUrl + ((_a = loadedCheerio(this).find("img").attr("src")) === null || _a === void 0 ? void 0 : _a.slice(1));
- const novelUrl = baseUrl +
- ((_b = loadedCheerio(this)
- .find("h3.truyen-title > a")
- .attr("href")) === null || _b === void 0 ? void 0 : _b.slice(1));
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = novelUrl;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- const novel = {
- url,
- chapters: [],
- };
- novel.name = loadedCheerio("div.book > img").attr("alt");
- novel.cover = baseUrl + loadedCheerio("div.book > img").attr("src");
- novel.summary = loadedCheerio("div.desc-text").text().trim();
- novel.author = loadedCheerio('h3:contains("Author")')
- .parent()
- .contents()
- .text()
- .replace("Author:", "");
- novel.genres = loadedCheerio('h3:contains("Genre")')
- .siblings()
- .map((i, el) => loadedCheerio(el).text())
- .toArray()
- .join(",");
- novel.status = loadedCheerio('h3:contains("Status")').next().text();
- const novelId = loadedCheerio("#rating").attr("data-novel-id");
- function getChapters(id) {
- return __awaiter(this, void 0, void 0, function* () {
- const chapterListUrl = baseUrl + "ajax/chapter-option?novelId=" + id;
- const data = yield (0, fetch_1.fetchApi)(chapterListUrl);
- const chapterlist = yield data.text();
- loadedCheerio = (0, cheerio_1.load)(chapterlist);
- let chapter = [];
- loadedCheerio("select > option").each(function () {
- var _a;
- const chapterName = loadedCheerio(this).text();
- const releaseDate = null;
- const chapterUrl = baseUrl + ((_a = loadedCheerio(this).attr("value")) === null || _a === void 0 ? void 0 : _a.slice(1));
- chapter.push({
- name: chapterName,
- releaseTime: releaseDate,
- url: chapterUrl,
- });
- });
- return chapter;
- });
- }
- novel.chapters = yield getChapters(novelId);
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const result = yield (0, fetch_1.fetchApi)(chapterUrl);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio("#chapter-content div.ads").remove();
- let chapterText = loadedCheerio("#chapter-content").html();
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- return __awaiter(this, void 0, void 0, function* () {
- const searchUrl = `${baseUrl}search?keyword=${searchTerm}`;
- const result = yield (0, fetch_1.fetchApi)(searchUrl);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio(".col-truyen-main .list-truyen .row").each(function () {
- var _a, _b;
- const novelName = loadedCheerio(this)
- .find("h3.truyen-title > a")
- .text();
- const novelCover = baseUrl + ((_a = loadedCheerio(this).find("img").attr("src")) === null || _a === void 0 ? void 0 : _a.slice(1));
- const novelUrl = baseUrl +
- ((_b = loadedCheerio(this)
- .find("h3.truyen-title > a")
- .attr("href")) === null || _b === void 0 ? void 0 : _b.slice(1));
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-const fetchImage = function (url) {
- return __awaiter(this, void 0, void 0, function* () {
- const headers = {
- Referer: baseUrl,
- };
- return yield (0, fetch_1.fetchFile)(url, { headers: headers });
- });
-};
-exports.fetchImage = fetchImage;
diff --git a/js/plugins/english/novelhold.js b/js/plugins/english/novelhold.js
deleted file mode 100644
index 0e10088..0000000
--- a/js/plugins/english/novelhold.js
+++ /dev/null
@@ -1,132 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.icon = exports.version = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-exports.id = "novelhold";
-exports.name = "Novel Hold";
-exports.version = "1.0.0";
-exports.icon = "src/en/novelhold/icon.png";
-exports.site = "https://novelhold.com/";
-const baseUrl = exports.site;
-const popularNovels = function (page) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = `${baseUrl}all-${page}.html`;
- const body = yield (0, fetch_1.fetchApi)(url).then((r) => r.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio("#article_list_content > li").each(function () {
- var _a;
- const novelName = loadedCheerio(this)
- .find("h3")
- .text()
- .replace(/\t+/g, "")
- .replace(/\n/g, " ");
- const novelCover = loadedCheerio(this).find("img").attr("data-src");
- const novelUrl = baseUrl + ((_a = loadedCheerio(this).find("a").attr("href")) === null || _a === void 0 ? void 0 : _a.slice(1));
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- var _a;
- return __awaiter(this, void 0, void 0, function* () {
- const url = novelUrl;
- const body = yield (0, fetch_1.fetchApi)(url).then((r) => r.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- const novel = {
- url,
- chapters: [],
- };
- novel.name = loadedCheerio(".booknav2 > h1").text();
- novel.cover = loadedCheerio('meta[property="og:image"]').attr("content");
- novel.summary = loadedCheerio(".navtxt").text().trim();
- novel.author = loadedCheerio('p:contains("Author")')
- .text()
- .replace("Author:", "")
- .trim();
- novel.status = loadedCheerio('p:contains("Status")')
- .text()
- .replace("Status:", "")
- .replace("Active", "Ongoing")
- .trim();
- novel.genres = (_a = loadedCheerio('p:contains("Genre")')
- .text()) === null || _a === void 0 ? void 0 : _a.replace("Genre:", "").trim();
- let chapter = [];
- loadedCheerio("ul.chapterlist > li").each(function () {
- var _a;
- const chapterName = loadedCheerio(this).find("a").text().trim();
- const releaseDate = null;
- const chapterUrl = baseUrl + ((_a = loadedCheerio(this).find("a").attr("href")) === null || _a === void 0 ? void 0 : _a.slice(1));
- chapter.push({
- name: chapterName,
- releaseTime: releaseDate,
- url: chapterUrl,
- });
- });
- novel.chapters = chapter;
- console.log(novel);
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then((r) => r.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio(".content").html();
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = `${baseUrl}index.php?s=so&module=book&keyword=${searchTerm}`;
- const body = yield (0, fetch_1.fetchApi)(url).then((r) => r.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio("#article_list_content > li").each(function () {
- var _a;
- const novelName = loadedCheerio(this)
- .find("h3")
- .text()
- .replace(/\t+/g, "")
- .replace(/\n/g, " ");
- const novelCover = loadedCheerio(this).find("img").attr("data-src");
- const novelUrl = baseUrl + ((_a = loadedCheerio(this).find("a").attr("href")) === null || _a === void 0 ? void 0 : _a.slice(1));
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-const fetchImage = function (url) {
- return __awaiter(this, void 0, void 0, function* () {
- const headers = {
- Referer: baseUrl,
- };
- return yield (0, fetch_1.fetchFile)(url, { headers: headers });
- });
-};
-exports.fetchImage = fetchImage;
diff --git a/js/plugins/english/novelpub.js b/js/plugins/english/novelpub.js
deleted file mode 100644
index 8266f3b..0000000
--- a/js/plugins/english/novelpub.js
+++ /dev/null
@@ -1,152 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.icon = exports.version = exports.site = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-exports.id = "novelpub.com";
-exports.name = "NovelPub";
-exports.site = "https://www.novelpub.com/";
-exports.version = "1.0.0";
-exports.icon = "src/en/novelpub/icon.png";
-const baseUrl = exports.site;
-const headers = {
- Accept: "application/json",
- "Content-Type": "application/json",
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36",
-};
-const popularNovels = function (page) {
- return __awaiter(this, void 0, void 0, function* () {
- let url = baseUrl + "browse/all/popular/all/" + page;
- const result = yield (0, fetch_1.fetchApi)(url, { method: "GET", headers });
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio(".novel-item.ads").remove();
- loadedCheerio(".novel-item").each(function () {
- var _a;
- const novelName = loadedCheerio(this)
- .find(".novel-title")
- .text()
- .trim();
- const novelCover = loadedCheerio(this).find("img").attr("data-src");
- const novelUrl = baseUrl +
- ((_a = loadedCheerio(this)
- .find(".novel-title > a")
- .attr("href")) === null || _a === void 0 ? void 0 : _a.substring(1));
- const novel = { name: novelName, cover: novelCover, url: novelUrl };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- var _a, _b;
- return __awaiter(this, void 0, void 0, function* () {
- const url = novelUrl;
- const result = yield (0, fetch_1.fetchApi)(url, { method: "GET", headers });
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- let novel = { url, genres: "" };
- novel.name = loadedCheerio("h1.novel-title").text().trim();
- novel.cover = loadedCheerio("figure.cover > img").attr("data-src");
- loadedCheerio("div.categories > ul > li").each(function () {
- novel.genres +=
- loadedCheerio(this)
- .text()
- .replace(/[\t\n]/g, "") + ",";
- });
- loadedCheerio("div.header-stats > span").each(function () {
- if (loadedCheerio(this).find("small").text() === "Status") {
- novel.status = loadedCheerio(this).find("strong").text();
- }
- });
- novel.genres = (_a = novel.genres) === null || _a === void 0 ? void 0 : _a.slice(0, -1);
- novel.author = loadedCheerio(".author > a > span").text();
- novel.summary = loadedCheerio(".summary > .content").text().trim();
- const delay = (ms) => new Promise((res) => setTimeout(res, ms));
- let lastPage = 1;
- lastPage = parseInt((_b = loadedCheerio("#novel > header > div.header-body.container > div.novel-info > div.header-stats > span:nth-child(1) > strong")
- .text()) === null || _b === void 0 ? void 0 : _b.trim());
- lastPage = Math.ceil(lastPage / 100);
- const getChapters = () => __awaiter(this, void 0, void 0, function* () {
- let novelChapters = [];
- for (let i = 1; i <= lastPage; i++) {
- const chaptersUrl = `${novelUrl}/chapters/page-${i}`;
- const chaptersRequest = yield (0, fetch_1.fetchApi)(chaptersUrl, {
- headers,
- });
- const chaptersHtml = yield chaptersRequest.text();
- loadedCheerio = (0, cheerio_1.load)(chaptersHtml);
- loadedCheerio(".chapter-list li").each(function () {
- var _a;
- const chapterName = loadedCheerio(this)
- .find(".chapter-title")
- .text()
- .trim();
- const releaseDate = loadedCheerio(this)
- .find(".chapter-update")
- .text()
- .trim();
- const chapterUrl = baseUrl +
- ((_a = loadedCheerio(this)
- .find("a")
- .attr("href")) === null || _a === void 0 ? void 0 : _a.substring(1));
- novelChapters.push({
- name: chapterName,
- releaseTime: releaseDate,
- url: chapterUrl,
- });
- });
- yield delay(1000);
- }
- return novelChapters;
- });
- novel.chapters = yield getChapters();
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = chapterUrl;
- const result = yield (0, fetch_1.fetchApi)(url, { method: "GET", headers });
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio("#chapter-container").html();
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-// They have API to search, pls update it, im quite lazy xD
-const searchNovels = function (searchTerm) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = `${baseUrl}lnwsearchlive?inputContent=${searchTerm}`;
- const result = yield (0, fetch_1.fetchApi)(url, { method: "GET", headers });
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- // let results = JSON.parse(loadedCheerio('body').text());
- // loadedCheerio = load(results.resultview);
- // loadedCheerio('.novel-item').each(function () {
- // const novelName = loadedCheerio(this).find('.novel-title').text().trim();
- // const novelCover = loadedCheerio(this).find('img').attr('src');
- // const novelUrl =
- // baseUrl + loadedCheerio(this).find('a').attr('href').substring(1);
- // const novel = { name: novelName, cover: novelCover, url: novelUrl };
- // novels.push(novel);
- // });
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-exports.fetchImage = fetch_1.fetchFile;
diff --git a/js/plugins/english/pandaMTL.js b/js/plugins/english/pandaMTL.js
deleted file mode 100644
index 720a6ee..0000000
--- a/js/plugins/english/pandaMTL.js
+++ /dev/null
@@ -1,220 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.icon = exports.version = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const filterInputs_1 = require("@libs/filterInputs");
-exports.id = "PandaMTL";
-exports.name = "PandaMTL";
-exports.version = "1.0.0";
-exports.icon = "src/en/wordpress/icon.png";
-exports.site = "https://www.pandamtl.com/";
-const pluginId = exports.id;
-const baseUrl = exports.site;
-const popularNovels = function (page, { filters }) {
- return __awaiter(this, void 0, void 0, function* () {
- let link = `${baseUrl}series/?page=${page}`;
- if (filters) {
- if (Array.isArray(filters.genres) && filters.genres.length) {
- link += filters.genres.map((i) => `&genre[]=${i}`).join("");
- }
- if (Array.isArray(filters.type) && filters.type.length) {
- link += filters.type.map((i) => `&lang[]=${i}`).join("");
- }
- }
- link += "&status=" + ((filters === null || filters === void 0 ? void 0 : filters.status) ? filters === null || filters === void 0 ? void 0 : filters.status : "");
- link += "&order=" + ((filters === null || filters === void 0 ? void 0 : filters.order) ? filters === null || filters === void 0 ? void 0 : filters.order : "popular");
- const body = yield (0, fetch_1.fetchApi)(link, {}, pluginId).then((result) => result.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const novels = [];
- loadedCheerio("article.maindet").each(function () {
- const novelName = loadedCheerio(this).find("h2").text();
- let image = loadedCheerio(this).find("img");
- const novelCover = image.attr("data-src") || image.attr("src");
- const novelUrl = loadedCheerio(this).find("h2 a").attr("href");
- if (!novelUrl)
- return;
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = novelUrl;
- const result = yield (0, fetch_1.fetchApi)(url, {}, pluginId);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- const novel = {
- url,
- chapters: [],
- };
- novel.name = loadedCheerio("h1.entry-title").text();
- novel.cover =
- loadedCheerio("img.wp-post-image").attr("data-src") ||
- loadedCheerio("img.wp-post-image").attr("src");
- loadedCheerio("div.serl:nth-child(3) > span").each(function () {
- const detailName = loadedCheerio(this).text().trim();
- const detail = loadedCheerio(this).next().text().trim();
- switch (detailName) {
- case "الكاتب":
- case "Author":
- novel.author = detail;
- break;
- }
- });
- novel.status = loadedCheerio("div.sertostat > span").attr("class");
- novel.genres = loadedCheerio(".sertogenre")
- .children("a")
- .map((i, el) => loadedCheerio(el).text())
- .toArray()
- .join(",");
- novel.summary = loadedCheerio(".sersys")
- .find("br")
- .replaceWith("\n")
- .end()
- .text();
- let chapter = [];
- loadedCheerio(".eplister")
- .find("li")
- .each(function () {
- const chapterName = loadedCheerio(this).find(".epl-num").text() +
- " - " +
- loadedCheerio(this).find(".epl-title").text();
- const releaseDate = loadedCheerio(this)
- .find(".epl-date")
- .text()
- .trim();
- const chapterUrl = loadedCheerio(this).find("a").attr("href");
- if (!chapterUrl)
- return;
- chapter.push({
- name: chapterName,
- releaseTime: releaseDate,
- url: chapterUrl,
- });
- });
- novel.chapters = chapter.reverse();
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const result = yield (0, fetch_1.fetchApi)(chapterUrl, {}, pluginId);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- let chapterText = loadedCheerio(".epcontent").html();
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = `${baseUrl}?s=${searchTerm}`;
- const result = yield (0, fetch_1.fetchApi)(url, {}, pluginId);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- const novels = [];
- loadedCheerio("article.maindet").each(function () {
- const novelName = loadedCheerio(this).find("h2").text();
- let image = loadedCheerio(this).find("img");
- const novelCover = image.attr("data-src") || image.attr("src");
- const novelUrl = loadedCheerio(this).find("h2 a").attr("href");
- if (!novelUrl)
- return;
- novels.push({
- name: novelName,
- url: novelUrl,
- cover: novelCover,
- });
- });
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-const fetchImage = function (url) {
- return __awaiter(this, void 0, void 0, function* () {
- const headers = {
- Referer: baseUrl,
- };
- return yield (0, fetch_1.fetchFile)(url, { headers: headers });
- });
-};
-exports.fetchImage = fetchImage;
-exports.filters = [
- {
- key: "order",
- label: "Sort By",
- values: [
- { label: "Default", value: "" },
- { label: "A-Z", value: "title" },
- { label: "Z-A", value: "titlereverse" },
- { label: "Latest Update", value: "update" },
- { label: "Latest Added", value: "latest" },
- { label: "Popular", value: "popular" },
- ],
- inputType: filterInputs_1.FilterInputs.Picker,
- },
- {
- key: "status",
- label: "Status",
- values: [
- { label: "All", value: "" },
- { label: "Ongoing", value: "ongoing" },
- { label: "Hiatus", value: "hiatus" },
- { label: "Completed", value: "completed" },
- ],
- inputType: filterInputs_1.FilterInputs.Picker,
- },
- {
- key: "type",
- label: "Type",
- values: [
- { label: "Light Novel (KR)", value: "light-novel-kr" },
- { label: "Web Novel", value: "web-novel" },
- ],
- inputType: filterInputs_1.FilterInputs.Checkbox,
- },
- {
- key: "genres",
- label: "Genres",
- values: [
- { label: "Action", value: "action" },
- { label: "Adult", value: "adult" },
- { label: "Adventure", value: "adventure" },
- { label: "Comedy", value: "comedy" },
- { label: "Ecchi", value: "ecchi" },
- { label: "Fantasy", value: "fantasy" },
- { label: "Harem", value: "harem" },
- { label: "Josei", value: "josei" },
- { label: "Martial Arts", value: "martial-arts" },
- { label: "Mature", value: "mature" },
- { label: "Romance", value: "romance" },
- { label: "School Life", value: "school-life" },
- { label: "Sci-fi", value: "sci-fi" },
- { label: "Seinen", value: "seinen" },
- { label: "Slice of Life", value: "slice-of-life" },
- { label: "Smut", value: "smut" },
- { label: "Sports", value: "sports" },
- { label: "Supernatural", value: "supernatural" },
- { label: "Tragedy", value: "tragedy" },
- ],
- inputType: filterInputs_1.FilterInputs.Checkbox,
- },
-];
diff --git a/js/plugins/french/chireads.js b/js/plugins/french/chireads.js
deleted file mode 100644
index 9f2e74b..0000000
--- a/js/plugins/french/chireads.js
+++ /dev/null
@@ -1,113 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.icon = exports.version = exports.site = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-exports.id = "chireads.com";
-exports.name = "Chireads";
-exports.site = "https://chireads.com/";
-exports.version = "1.0.0";
-exports.icon = "src/fr/chireads/icon.png";
-const baseUrl = exports.site;
-const popularNovels = function (page) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = `${baseUrl}category/translatedtales/page/${page}/`;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio("#content li").each(function () {
- const novelName = loadedCheerio(this).find(".news-list-tit h5").text();
- const novelCover = loadedCheerio(this).find("img").attr("src");
- const novelUrl = loadedCheerio(this)
- .find(".news-list-tit h5 a")
- .attr("href");
- if (!novelUrl)
- return;
- const novel = { name: novelName, cover: novelCover, url: novelUrl };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = novelUrl;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- let novel = {
- url,
- name: "",
- cover: "",
- author: "",
- status: "",
- genres: "",
- summary: "",
- chapters: [],
- };
- novel.name = loadedCheerio(".inform-title").text().trim();
- novel.cover = loadedCheerio(".inform-product img").attr("src");
- novel.summary = loadedCheerio(".inform-inform-txt").text().trim();
- let chapters = [];
- loadedCheerio(".chapitre-table a").each(function () {
- const chapterName = loadedCheerio(this).text().trim();
- const releaseDate = null;
- const chapterUrl = loadedCheerio(this).attr("href");
- if (!chapterUrl)
- return;
- chapters.push({
- name: chapterName,
- releaseTime: releaseDate,
- url: chapterUrl,
- });
- });
- novel.chapters = chapters;
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = chapterUrl;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio("#content").html();
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = `${baseUrl}search?x=0&y=0&name=${searchTerm}`;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio("#content li").each(function () {
- const novelName = loadedCheerio(this).find(".news-list-tit h5").text();
- const novelCover = loadedCheerio(this).find("img").attr("src");
- const novelUrl = loadedCheerio(this)
- .find(".news-list-tit h5 a")
- .attr("href");
- if (!novelUrl)
- return;
- const novel = { name: novelName, cover: novelCover, url: novelUrl };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-exports.fetchImage = fetch_1.fetchFile;
diff --git a/js/plugins/indonesian/MeioNovel[madara].js b/js/plugins/indonesian/MeioNovel[madara].js
deleted file mode 100644
index f4823f2..0000000
--- a/js/plugins/indonesian/MeioNovel[madara].js
+++ /dev/null
@@ -1,179 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const filterInputs_1 = require("@libs/filterInputs");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "meionovel";
-exports.name = "MeioNovel [madara]";
-exports.icon = "multisrc/madara/icons/meionovel.png";
-exports.version = "1.0.0";
-exports.site = "https://meionovel.id/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "novel-genre/" + filters.genres + '/';
- }
- else {
- url += "novel/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (true) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": filterInputs_1.FilterInputs.Picker }, { "key": "genres", "label": "GENRES", "values": [{ "label": "Action", "value": "action" }, { "label": "Adventure", "value": "adventure" }, { "label": "Comedy", "value": "comedy" }, { "label": "Cooking", "value": "cooking" }, { "label": "Drama", "value": "drama" }, { "label": "Ecchi", "value": "ecchi" }, { "label": "Fanfiction", "value": "fanfiction" }, { "label": "Fantasy", "value": "fantasy" }, { "label": "Gender Bender", "value": "gender-bender" }, { "label": "Harem", "value": "harem" }, { "label": "Historical", "value": "historical" }, { "label": "Horror", "value": "horror" }, { "label": "Isekai", "value": "isekai" }, { "label": "Josei", "value": "josei" }, { "label": "Magic", "value": "magic" }, { "label": "Martial Arts", "value": "martial-arts" }, { "label": "Mature", "value": "mature" }, { "label": "Mecha", "value": "mecha" }, { "label": "Mystery", "value": "mystery" }, { "label": "One shot", "value": "one-shot" }, { "label": "Psychological", "value": "psychological" }, { "label": "Reverse Harem", "value": "reverse-harem" }, { "label": "Romance", "value": "romance" }, { "label": "School Life", "value": "school-life" }, { "label": "Sci-fi", "value": "sci-fi" }, { "label": "Seinen", "value": "seinen" }, { "label": "Shoujo", "value": "shoujo" }, { "label": "Shoujo Ai", "value": "shoujo-ai" }, { "label": "Shounen", "value": "shounen" }, { "label": "Shounen Ai", "value": "shounen-ai" }, { "label": "Slice of Life", "value": "slice-of-life" }, { "label": "Smut", "value": "smut" }, { "label": "Sports", "value": "sports" }, { "label": "Supernatural", "value": "supernatural" }, { "label": "Tragedy", "value": "tragedy" }, { "label": "Virtual Reality", "value": "virtual-reality" }, { "label": "Wuxia", "value": "wuxia" }, { "label": "Xianxia", "value": "xianxia" }, { "label": "Xuanhuan", "value": "xuanhuan" }, { "label": "Yuri", "value": "yuri" }], "inputType": filterInputs_1.FilterInputs.Picker }];
diff --git a/js/plugins/indonesian/MoreNovel[madara].js b/js/plugins/indonesian/MoreNovel[madara].js
deleted file mode 100644
index 47cd615..0000000
--- a/js/plugins/indonesian/MoreNovel[madara].js
+++ /dev/null
@@ -1,179 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const filterInputs_1 = require("@libs/filterInputs");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "morenovel";
-exports.name = "MoreNovel [madara]";
-exports.icon = "multisrc/madara/icons/morenovel.png";
-exports.version = "1.0.0";
-exports.site = "https://morenovel.net/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "novel-genre/" + filters.genres + '/';
- }
- else {
- url += "novel/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (true) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": filterInputs_1.FilterInputs.Picker }, { "key": "genres", "label": "GENRES", "values": [{ "label": "Action", "value": "action" }, { "label": "Adventure", "value": "adventure" }, { "label": "Comedy", "value": "comedy" }, { "label": "Drama", "value": "drama" }, { "label": "Ecchi", "value": "ecchi" }, { "label": "Fantasy", "value": "fantasy" }, { "label": "Gender Bender", "value": "gender-bender" }, { "label": "Harem", "value": "harem" }, { "label": "Historical", "value": "historical" }, { "label": "Horror", "value": "horror" }, { "label": "Josei", "value": "josei" }, { "label": "Martial Arts", "value": "martial-arts" }, { "label": "Mature", "value": "mature" }, { "label": "Mecha", "value": "mecha" }, { "label": "Mystery", "value": "mystery" }, { "label": "Psychological", "value": "psychological" }, { "label": "Romance", "value": "romance" }, { "label": "School Life", "value": "school-life" }, { "label": "Sci-fi", "value": "sci-fi" }, { "label": "Seinen", "value": "seinen" }, { "label": "Shoujo", "value": "shoujo" }, { "label": "Shoujo Ai", "value": "shoujo-ai" }, { "label": "Shounen", "value": "shounen" }, { "label": "Shounen Ai", "value": "shounen-ai" }, { "label": "Slice of Life", "value": "slice-of-life" }, { "label": "Sports", "value": "sports" }, { "label": "Supernatural", "value": "supernatural" }, { "label": "Tragedy", "value": "tragedy" }, { "label": "Wuxia", "value": "wuxia" }, { "label": "Xianxia", "value": "xianxia" }, { "label": "Xuanhuan", "value": "xuanhuan" }, { "label": "Yaoi", "value": "yaoi" }, { "label": "Yuri", "value": "yuri" }], "inputType": filterInputs_1.FilterInputs.Picker }];
diff --git a/js/plugins/indonesian/WBNovel[madara].js b/js/plugins/indonesian/WBNovel[madara].js
deleted file mode 100644
index 83bb96e..0000000
--- a/js/plugins/indonesian/WBNovel[madara].js
+++ /dev/null
@@ -1,179 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const filterInputs_1 = require("@libs/filterInputs");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "wbnovel";
-exports.name = "WBNovel [madara]";
-exports.icon = "multisrc/madara/icons/wbnovel.png";
-exports.version = "1.0.0";
-exports.site = "https://wbnovel.com/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "novel-genre/" + filters.genres + '/';
- }
- else {
- url += "novel/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (false) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": filterInputs_1.FilterInputs.Picker }, { "key": "genres", "label": "GENRES", "values": [{ "label": "Action", "value": "action" }, { "label": "Adventure", "value": "adventure" }, { "label": "Alchemy", "value": "alchemy" }, { "label": "Comedy", "value": "comedy" }, { "label": "Crafting", "value": "crafting" }, { "label": "Cultivation", "value": "cultivation" }, { "label": "Drama", "value": "drama" }, { "label": "Dungeon Crawling", "value": "dungeon-crawling" }, { "label": "Eci", "value": "eci" }, { "label": "Fantasy", "value": "fantasy" }, { "label": "Game", "value": "game" }, { "label": "Harem", "value": "harem" }, { "label": "Horror", "value": "horror" }, { "label": "Josei", "value": "josei" }, { "label": "Kingdom Building", "value": "kingdom-building" }, { "label": "Martial Arts", "value": "martial-arts" }, { "label": "Mature", "value": "mature" }, { "label": "Mecha", "value": "mecha" }, { "label": "Modern Setting", "value": "modern-setting" }, { "label": "Mystery", "value": "mystery" }, { "label": "Pets", "value": "pets" }, { "label": "Psychological", "value": "psychological" }, { "label": "Reincarnator", "value": "reincarnator" }, { "label": "Romance", "value": "romance" }, { "label": "School Life", "value": "school-life" }, { "label": "Sci-fi", "value": "sci-fi" }, { "label": "Seinen", "value": "seinen" }, { "label": "Shounen", "value": "shounen" }, { "label": "Slice of Life", "value": "slice-of-life" }, { "label": "Sports", "value": "sports" }, { "label": "Supernatural", "value": "supernatural" }, { "label": "Tragedy", "value": "tragedy" }, { "label": "Transmigration", "value": "transmigration" }, { "label": "Virtual Reality", "value": "virtual-reality" }, { "label": "Wuxia", "value": "wuxia" }, { "label": "Xianxia", "value": "xianxia" }, { "label": "Xuanhuan", "value": "xuanhuan" }], "inputType": filterInputs_1.FilterInputs.Picker }];
diff --git a/js/plugins/indonesian/indowebnovel.js b/js/plugins/indonesian/indowebnovel.js
deleted file mode 100644
index 956c892..0000000
--- a/js/plugins/indonesian/indowebnovel.js
+++ /dev/null
@@ -1,126 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.version = exports.icon = exports.site = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const defaultCover_1 = require("@libs/defaultCover");
-exports.id = "IDWN.id";
-exports.name = "IndoWebNovel";
-exports.site = "https://indowebnovel.id/id/";
-exports.icon = "src/id/indowebnovel/icon.png";
-exports.version = "1.0.0";
-const baseUrl = exports.site;
-const popularNovels = function (page) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = `${baseUrl}daftar-novel/`;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio(".novellist-blc li").each(function () {
- const novelName = loadedCheerio(this).find("a").text();
- const novelCover = defaultCover_1.defaultCover;
- const novelUrl = loadedCheerio(this).find("a").attr("href");
- if (!novelUrl || !novelName)
- return;
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = novelUrl;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- let novel = {
- url,
- name: "",
- cover: "",
- author: "",
- status: "",
- genres: "",
- summary: "",
- chapters: [],
- };
- novel.name = loadedCheerio(".series-title").text().trim();
- novel.cover = loadedCheerio(".series-thumb > img").attr("src");
- novel.summary = loadedCheerio(".series-synops").text().trim();
- novel.status = loadedCheerio(".status").text().trim();
- const genres = [];
- loadedCheerio(".series-genres").each(function () {
- genres.push(loadedCheerio(this).find("a").text().trim());
- });
- novel.genres = genres.join(",");
- let chapters = [];
- loadedCheerio(".series-chapterlist li").each(function () {
- const chapterName = loadedCheerio(this).find("a").text().trim();
- const releaseDate = null;
- const chapterUrl = loadedCheerio(this).find("a").attr("href");
- if (!chapterUrl)
- return;
- chapters.push({
- name: chapterName,
- releaseTime: releaseDate,
- url: chapterUrl,
- });
- });
- novel.chapters = chapters.reverse();
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = chapterUrl;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio(".reader").html();
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = `${baseUrl}daftar-novel/`;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio(".novellist-blc li").each(function () {
- const novelName = loadedCheerio(this).find("a").text();
- const novelCover = defaultCover_1.defaultCover;
- const novelUrl = loadedCheerio(this).find("a").attr("href");
- if (!novelUrl)
- return;
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- if (novelName.toLowerCase().includes(searchTerm.toLowerCase())) {
- novels.push(novel);
- }
- });
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-exports.fetchImage = fetch_1.fetchFile;
diff --git a/js/plugins/indonesian/novelringan.js b/js/plugins/indonesian/novelringan.js
deleted file mode 100644
index 4b84f3a..0000000
--- a/js/plugins/indonesian/novelringan.js
+++ /dev/null
@@ -1,135 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.version = exports.icon = exports.site = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const novelStatus_1 = require("@libs/novelStatus");
-exports.id = "novelringan.com";
-exports.name = "NovelRingan";
-exports.site = "https://novelringan.com/";
-exports.icon = "src/id/novelringan/icon.png";
-exports.version = "1.0.0";
-const baseUrl = exports.site;
-const coverUriPrefix = "https://i0.wp.com/novelringan.com/wp-content/uploads/";
-const popularNovels = function (page) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = `${baseUrl}/top-novel/page/${page}`;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- const novels = [];
- loadedCheerio("article.post").each(function () {
- var _a;
- const novelName = (_a = loadedCheerio(this)
- .find(".entry-title")
- .text()) === null || _a === void 0 ? void 0 : _a.trim();
- const novelCover = coverUriPrefix + loadedCheerio(this).find("img").attr("data-sxrx");
- const novelUrl = loadedCheerio(this).find("h2 > a").attr("href");
- if (!novelUrl)
- return;
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- var _a;
- return __awaiter(this, void 0, void 0, function* () {
- const url = novelUrl;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- let novel = {
- url,
- name: "",
- cover: "",
- genres: "",
- author: "",
- status: novelStatus_1.NovelStatus.Unknown,
- summary: "",
- chapters: [],
- };
- novel.name = (_a = loadedCheerio(".entry-title").text()) === null || _a === void 0 ? void 0 : _a.trim();
- novel.cover =
- coverUriPrefix +
- loadedCheerio("img.ts-post-image").attr("data-sxrx");
- novel.summary = loadedCheerio("body > div.site-container > div > main > article > div > div.maininfo > span > p").text();
- let genreSelector = loadedCheerio("body > div.site-container > div > main > article > div > div.maininfo > span > ul > li:nth-child(4)").text();
- novel.genres = genreSelector.includes("Genre")
- ? genreSelector.replace("Genre:", "").trim()
- : "";
- let statusSelector = loadedCheerio("body > div.site-container > div > main > article > div > div.maininfo > span > ul > li:nth-child(3)").text();
- novel.status = statusSelector.includes("Status")
- ? statusSelector.replace("Status:", "").trim()
- : novelStatus_1.NovelStatus.Unknown;
- let chapters = [];
- loadedCheerio(".bxcl > ul > li").each(function () {
- const chapterName = loadedCheerio(this).find("a").text();
- const releaseDate = null;
- const chapterUrl = loadedCheerio(this).find("a").attr("href");
- if (!chapterUrl)
- return;
- const chapter = {
- name: chapterName,
- releaseTime: releaseDate,
- url: chapterUrl,
- };
- chapters.push(chapter);
- });
- novel.chapters = chapters.reverse();
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = chapterUrl;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.entry-content div[style="display:none"]').remove();
- const chapterText = loadedCheerio(".entry-content").html();
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = baseUrl + "?s=" + searchTerm;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio("article.post").each(function () {
- const novelName = loadedCheerio(this).find(".entry-title").text();
- const novelCover = coverUriPrefix + loadedCheerio(this).find("img").attr("data-sxrx");
- const novelUrl = loadedCheerio(this).find("h2 > a").attr("href");
- if (!novelUrl)
- return;
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-exports.fetchImage = fetch_1.fetchFile;
diff --git a/js/plugins/indonesian/sakuranovel.js b/js/plugins/indonesian/sakuranovel.js
deleted file mode 100644
index 7913db4..0000000
--- a/js/plugins/indonesian/sakuranovel.js
+++ /dev/null
@@ -1,140 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.version = exports.icon = exports.site = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-exports.id = "sakura.id";
-exports.name = "SakuraNovel";
-exports.site = "https://sakuranovel.id/";
-exports.icon = "src/id/sakuranovel/icon.png";
-exports.version = "1.0.0";
-const pluginId = exports.id;
-const sourceName = exports.name;
-const baseUrl = exports.site;
-const popularNovels = function (page) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = `${baseUrl}advanced-search/page/${page}/?title&author&yearx&status&type&order=rating&country%5B0%5D=china&country%5B1%5D=jepang&country%5B2%5D=unknown`;
- const result = yield (0, fetch_1.fetchApi)(url, {}, pluginId);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio(".flexbox2-item").each(function () {
- const novelName = loadedCheerio(this)
- .find(".flexbox2-title span")
- .first()
- .text();
- const novelCover = loadedCheerio(this).find("img").attr("src");
- const novelUrl = loadedCheerio(this)
- .find(".flexbox2-content > a")
- .attr("href");
- if (!novelUrl)
- return;
- const novel = { name: novelName, cover: novelCover, url: novelUrl };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const result = yield (0, fetch_1.fetchApi)(novelUrl, {}, pluginId);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- let novel = {
- name: sourceName,
- url: novelUrl,
- };
- novel.name = loadedCheerio(".series-title h2").text().trim();
- novel.cover = loadedCheerio(".series-thumb img").attr("src");
- loadedCheerio(".series-infolist > li").each(function () {
- const detailName = loadedCheerio(this).find("b").text().trim();
- const detail = loadedCheerio(this).find("b").next().text().trim();
- switch (detailName) {
- case "Author":
- novel.author = detail;
- break;
- }
- });
- novel.status = loadedCheerio(".status").text().trim();
- novel.genres = loadedCheerio(".series-genres")
- .children("a")
- .map((i, el) => loadedCheerio(el).text())
- .toArray()
- .join(",");
- loadedCheerio(".series-synops div").remove();
- novel.summary = loadedCheerio(".series-synops").text().trim();
- let chapters = [];
- loadedCheerio(".series-chapterlist li").each(function () {
- const chapterName = loadedCheerio(this)
- .find("a span")
- .first()
- .text()
- .replace(/.*?(Chapter.|[0-9])/g, "$1")
- .replace(/Bahasa Indonesia/g, "")
- .replace(/\s+/g, " ")
- .trim();
- const releaseDate = loadedCheerio(this)
- .find("a span")
- .first()
- .next()
- .text();
- const chapterUrl = loadedCheerio(this).find("a").attr("href");
- if (!chapterUrl)
- return;
- chapters.push({
- name: chapterName,
- releaseTime: releaseDate,
- url: chapterUrl,
- });
- });
- novel.chapters = chapters.reverse();
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const result = yield (0, fetch_1.fetchApi)(chapterUrl, {}, pluginId);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio(".readers").html();
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = `${baseUrl}?s=${searchTerm}`;
- const result = yield (0, fetch_1.fetchApi)(url, {}, pluginId);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio(".flexbox2-item").each(function () {
- const novelName = loadedCheerio(this)
- .find(".flexbox2-title span")
- .first()
- .text();
- const novelCover = loadedCheerio(this).find("img").attr("src");
- const novelUrl = loadedCheerio(this)
- .find(".flexbox2-content > a")
- .attr("href");
- if (!novelUrl)
- return;
- const novel = { name: novelName, cover: novelCover, url: novelUrl };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-exports.fetchImage = fetch_1.fetchFile;
diff --git a/js/plugins/japanese/Syosetu.js b/js/plugins/japanese/Syosetu.js
deleted file mode 100644
index 5209189..0000000
--- a/js/plugins/japanese/Syosetu.js
+++ /dev/null
@@ -1,201 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const defaultCover_1 = require("@libs/defaultCover");
-// const novelStatus = require('@libs/novelStatus');
-// const isUrlAbsolute = require('@libs/isAbsoluteUrl');
-// const parseDate = require('@libs/parseDate');
-const pluginId = "yomou.syosetu";
-exports.id = pluginId;
-exports.name = "Syosetu";
-exports.icon = "src/jp/syosetu/icon.png";
-exports.version = "1.0.0";
-exports.site = "https//yomou.syosetu.com/";
-const searchUrl = (pagenum, order) => {
- return `https://yomou.syosetu.com/search.php?order=${order || "hyoka"}${pagenum !== undefined
- ? `&p=${pagenum <= 1 || pagenum > 100 ? "1" : pagenum}` // check if pagenum is between 1 and 100
- : "" // if isn't don't set ?p
- }`;
-};
-const popularNovels = function (pageNo) {
- return __awaiter(this, void 0, void 0, function* () {
- function getNovelsFromPage(pagenumber) {
- return __awaiter(this, void 0, void 0, function* () {
- // load page
- const result = yield (0, fetch_1.fetchApi)(searchUrl(pagenumber));
- const body = yield result.text();
- // Cheerio it!
- const cheerioQuery = (0, cheerio_1.load)(body, { decodeEntities: false });
- let pageNovels = [];
- // find class=searchkekka_box
- cheerioQuery(".searchkekka_box").each(function (i, e) {
- // get div with link and name
- const novelDIV = cheerioQuery(this).find(".novel_h");
- // get link element
- const novelA = novelDIV.children()[0];
- // add new novel to array
- pageNovels.push({
- name: novelDIV.text(),
- url: novelA.attribs.href,
- cover: defaultCover_1.defaultCover,
- });
- });
- // return all novels from this page
- return pageNovels;
- });
- }
- const novels = yield getNovelsFromPage(pageNo);
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- let chapters = [];
- const result = yield (0, fetch_1.fetchApi)(novelUrl);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body, { decodeEntities: false });
- // create novel object
- let novel = {
- url: novelUrl,
- name: loadedCheerio(".novel_title").text(),
- author: loadedCheerio(".novel_writername")
- .text()
- .replace("作者:", ""),
- cover: defaultCover_1.defaultCover,
- };
- // Get all the chapters
- const cqGetChapters = loadedCheerio(".novel_sublist2");
- if (cqGetChapters.length !== 0) {
- // has more than 1 chapter
- novel.summary = loadedCheerio("#novel_ex")
- .text()
- .replace(/<\s*br.*?>/g, "\n");
- cqGetChapters.each(function (i, e) {
- const chapterA = loadedCheerio(this).find("a");
- const [chapterName, releaseDate, chapterUrl] = [
- // set the variables
- chapterA.text(),
- loadedCheerio(this)
- .find("dt") // get title
- .text() // get text
- .replace(/(.)/g, "") // remove "(edited)" mark
- .trim(),
- "https://ncode.syosetu.com" + chapterA.attr("href"),
- ];
- chapters.push({
- name: chapterName,
- releaseTime: releaseDate,
- url: chapterUrl,
- });
- });
- }
- else {
- /**
- * Because there are oneshots on the site, they have to be treated with special care
- * that's what pisses me off in Shosetsu app. They have this extension,
- * but every oneshot is set as "there are no chapters" and all contents are thrown into the description!!
- */
- // get summary for oneshot chapter
- const nameResult = yield (0, fetch_1.fetchApi)(searchUrl() + `&word=${novel.name}`);
- const nameBody = yield nameResult.text();
- const summaryQuery = (0, cheerio_1.load)(nameBody, {
- decodeEntities: false,
- });
- const foundText = summaryQuery(".searchkekka_box")
- .first()
- .find(".ex")
- .text()
- .replace(/\s{2,}/g, "\n");
- novel.summary = foundText;
- // add single chapter
- chapters.push({
- name: "Oneshot",
- releaseTime: loadedCheerio("head")
- .find("meta[name='WWWC']")
- .attr("content"),
- url: novelUrl, // set chapterUrl to oneshot so that chapterScraper knows it's a one-shot,
- });
- }
- novel.chapters = chapters;
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const result = yield (0, fetch_1.fetchApi)(chapterUrl);
- const body = yield result.text();
- // create cheerioQuery
- const cheerioQuery = (0, cheerio_1.load)(body, {
- decodeEntities: false,
- });
- let chapterText = cheerioQuery("#novel_honbun") // get chapter text
- .html();
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- return __awaiter(this, void 0, void 0, function* () {
- let novels = [];
- // returns list of novels from given page
- function getNovelsFromPage(pagenumber) {
- return __awaiter(this, void 0, void 0, function* () {
- // load page
- const result = yield (0, fetch_1.fetchApi)(searchUrl(pagenumber) + `&word=${searchTerm}`);
- const body = yield result.text();
- // Cheerio it!
- const cheerioQuery = (0, cheerio_1.load)(body, { decodeEntities: false });
- let pageNovels = [];
- // find class=searchkekka_box
- cheerioQuery(".searchkekka_box").each(function (i, e) {
- // get div with link and name
- const novelDIV = cheerioQuery(this).find(".novel_h");
- // get link element
- const novelA = novelDIV.children()[0];
- // add new novel to array
- pageNovels.push({
- name: novelDIV.text(),
- url: novelA.attribs.href,
- cover: defaultCover_1.defaultCover,
- });
- });
- // return all novels from this page
- return pageNovels;
- });
- }
- // counter of loaded pages
- // let pagesLoaded = 0;
- // do {
- // // always load first one
- // novels.push(...(await getNovelsFromPage(pagesLoaded + 1)));
- // pagesLoaded++;
- // } while (pagesLoaded < maxPageLoad && isNext); // check if we should load more
- novels = yield getNovelsFromPage(1);
- /** Use
- * novels.push(...(await getNovelsFromPage(pageNumber)))
- * if you want to load more
- */
- // respond with novels!
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-const fetchImage = function (url) {
- return __awaiter(this, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
- });
-};
-exports.fetchImage = fetchImage;
diff --git a/js/plugins/korean/Agitoon.js b/js/plugins/korean/Agitoon.js
deleted file mode 100644
index 48513ef..0000000
--- a/js/plugins/korean/Agitoon.js
+++ /dev/null
@@ -1,141 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.icon = exports.version = exports.site = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-exports.id = "agit.xyz";
-exports.name = "Agitoon";
-exports.site = "https://agit501.xyz/";
-exports.version = "1.0.0";
-exports.icon = "src/kr/agitoon/agit.png";
-const baseUrl = exports.site;
-const popularNovels = function (page) {
- var _a;
- return __awaiter(this, void 0, void 0, function* () {
- const list_limit = 20 * (page - 1);
- const day = new Date().getDay();
- const res = yield (0, fetch_1.fetchApi)(baseUrl + "novel/index.update.php", {
- headers: {
- "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
- },
- body: `mode=get_data_novel_list_p&novel_menu=3&np_day=${day}&np_rank=1&np_distributor=0&np_genre=00&np_order=1&np_genre_ex_1=00&np_genre_ex_2=00&list_limit=${list_limit}&is_query_first=true`,
- method: "POST",
- });
- const resJson = yield res.json();
- const novels = [];
- (_a = resJson === null || resJson === void 0 ? void 0 : resJson.list) === null || _a === void 0 ? void 0 : _a.forEach((novel) => {
- novels.push({
- url: baseUrl + "novel/list/" + novel.wr_id,
- name: novel.wr_subject,
- cover: baseUrl + novel.np_dir + "/thumbnail/" + novel.np_thumbnail,
- });
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- var _a;
- return __awaiter(this, void 0, void 0, function* () {
- const novelId = novelUrl.split("/").reverse()[0];
- // cheerio
- const result = yield (0, fetch_1.fetchApi)(novelUrl);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body, { decodeEntities: false });
- const name = loadedCheerio("h5.pt-2").text();
- const summary = loadedCheerio(".pt-1.mt-1.pb-1.mb-1").text();
- const author = loadedCheerio(".post-item-list-cate-v")
- .first()
- .text()
- .split(" : ")
- .reverse()[0];
- const cover = baseUrl.slice(0, baseUrl.length - 1) +
- loadedCheerio("div.col-5.pr-0.pl-0 img").attr("src");
- const genresTag = loadedCheerio(".col-7 > .post-item-list-cate > span");
- let genres = "";
- genresTag.each((_, element) => {
- genres += loadedCheerio(element).text();
- genres += ", ";
- });
- genres = genres.slice(0, genres.length - 2);
- // normal REST HTTP requests
- let chapters = [];
- const res = yield (0, fetch_1.fetchApi)(baseUrl + "novel/list.update.php", {
- headers: {
- "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
- },
- body: `mode=get_data_novel_list_c&wr_id_p=${novelId}&page_no=1&cnt_list=10000&order_type=Asc`,
- method: "POST",
- });
- const resJson = yield res.json();
- (_a = resJson === null || resJson === void 0 ? void 0 : resJson.list) === null || _a === void 0 ? void 0 : _a.forEach((chapter) => {
- chapters.push({
- name: chapter.wr_subject,
- url: baseUrl + `novel/view/${chapter.wr_id}/2`,
- releaseTime: chapter.wr_datetime,
- });
- });
- const novel = {
- url: novelUrl,
- name,
- cover,
- summary,
- author,
- status: "",
- genres: genres,
- chapters,
- };
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const result = yield (0, fetch_1.fetchApi)(chapterUrl);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- const contentTag = loadedCheerio("#id_wr_content > p");
- let content = "";
- contentTag.each((_, element) => {
- content += loadedCheerio(element).text();
- content += "
";
- });
- // gets rid of the popup thingy
- content = content.replace("팝업메뉴는 빈공간을 더치하거나 스크룰시 사라집니다", "");
- return content;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- var _a;
- return __awaiter(this, void 0, void 0, function* () {
- const rawResults = yield (0, fetch_1.fetchApi)("https://agit501.xyz/novel/search.php", {
- headers: {
- "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
- },
- body: `mode=get_data_novel_list_p_sch&search_novel=${searchTerm}&list_limit=0`,
- method: "POST",
- });
- const resJson = yield rawResults.json();
- const novels = [];
- (_a = resJson === null || resJson === void 0 ? void 0 : resJson.list) === null || _a === void 0 ? void 0 : _a.forEach((novel) => {
- novels.push({
- url: baseUrl + "novel/list/" + novel.wr_id,
- name: novel.wr_subject,
- cover: baseUrl + novel.np_dir + "/thumbnail/" + novel.np_thumbnail,
- });
- });
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-exports.fetchImage = fetch_1.fetchFile;
diff --git a/js/plugins/portuguese/lightnovelbrasil.js b/js/plugins/portuguese/lightnovelbrasil.js
deleted file mode 100644
index b8f806f..0000000
--- a/js/plugins/portuguese/lightnovelbrasil.js
+++ /dev/null
@@ -1,300 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.icon = exports.version = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const filterInputs_1 = require("@libs/filterInputs");
-exports.id = "lightnovelbrasil";
-exports.name = "Light Novel Brasil";
-exports.version = "1.0.0";
-exports.icon = "multisrc/wpmangastream/icons/lightnovelbrasil.png";
-exports.site = "https://lightnovelbrasil.com/";
-const pluginId = exports.id;
-const baseUrl = exports.site;
-const popularNovels = function (page, { filters }) {
- return __awaiter(this, void 0, void 0, function* () {
- let link = `${baseUrl}series/?page=${page}`;
- if (filters) {
- if (Array.isArray(filters.genres) && filters.genres.length) {
- link += filters.genres.map((i) => `&genre[]=${i}`).join("");
- }
- if (Array.isArray(filters.type) && filters.type.length) {
- link += filters.type.map((i) => `&lang[]=${i}`).join("");
- }
- }
- link += "&status=" + ((filters === null || filters === void 0 ? void 0 : filters.status) ? filters === null || filters === void 0 ? void 0 : filters.status : "");
- link += "&order=" + ((filters === null || filters === void 0 ? void 0 : filters.order) ? filters === null || filters === void 0 ? void 0 : filters.order : "popular");
- const body = yield (0, fetch_1.fetchApi)(link, {}, pluginId).then((result) => result.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const novels = [];
- loadedCheerio("article.bs").each(function () {
- const novelName = loadedCheerio(this).find(".ntitle").text().trim();
- let image = loadedCheerio(this).find("img");
- const novelCover = image.attr("data-src") || image.attr("src");
- const novelUrl = loadedCheerio(this).find("a").attr("href");
- if (!novelUrl)
- return;
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = novelUrl;
- const result = yield (0, fetch_1.fetchApi)(url, {}, pluginId);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- const novel = {
- url,
- chapters: [],
- };
- novel.name = loadedCheerio(".entry-title").text();
- novel.cover =
- loadedCheerio("img.wp-post-image").attr("data-src") ||
- loadedCheerio("img.wp-post-image").attr("src");
- loadedCheerio("div.spe > span").each(function () {
- const detailName = loadedCheerio(this).find("b").text().trim();
- const detail = loadedCheerio(this)
- .find("b")
- .remove()
- .end()
- .text()
- .trim();
- switch (detailName) {
- case "المؤلف:":
- case "Yazar:":
- case "Autor:":
- case "Author:":
- novel.author = detail;
- break;
- case "Status:":
- case "Seviye:":
- novel.status = detail;
- break;
- }
- });
- novel.genres = loadedCheerio(".genxed")
- .text()
- .trim()
- .replace(/\s/g, ",");
- loadedCheerio('div[itemprop="description"] h3,p.a,strong').remove();
- novel.summary = loadedCheerio('div[itemprop="description"]')
- .find("br")
- .replaceWith("\n")
- .end()
- .text();
- let chapter = [];
- loadedCheerio(".eplister")
- .find("li")
- .each(function () {
- const chapterName = loadedCheerio(this).find(".epl-num").text() +
- " - " +
- loadedCheerio(this).find(".epl-title").text();
- const releaseDate = loadedCheerio(this)
- .find(".epl-date")
- .text()
- .trim();
- const chapterUrl = loadedCheerio(this).find("a").attr("href");
- if (!chapterUrl)
- return;
- chapter.push({
- name: chapterName,
- releaseTime: releaseDate,
- url: chapterUrl,
- });
- });
- novel.chapters = chapter.reverse();
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const result = yield (0, fetch_1.fetchApi)(chapterUrl, {}, pluginId);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- let chapterText = loadedCheerio("div.epcontent").html();
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = `${baseUrl}?s=${searchTerm}`;
- const result = yield (0, fetch_1.fetchApi)(url, {}, pluginId);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- const novels = [];
- loadedCheerio("article.bs").each(function () {
- const novelName = loadedCheerio(this).find(".ntitle").text().trim();
- const novelCover = loadedCheerio(this).find("img").attr("src");
- const novelUrl = loadedCheerio(this).find("a").attr("href");
- if (!novelUrl)
- return;
- novels.push({
- name: novelName,
- url: novelUrl,
- cover: novelCover,
- });
- });
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-const fetchImage = function (url) {
- return __awaiter(this, void 0, void 0, function* () {
- const headers = {
- Referer: baseUrl,
- };
- return yield (0, fetch_1.fetchFile)(url, { headers: headers });
- });
-};
-exports.fetchImage = fetchImage;
-exports.filters = [
- {
- key: "order",
- label: "Sort By",
- values: [
- { label: "Default", value: "" },
- { label: "A-Z", value: "title" },
- { label: "Z-A", value: "titlereverse" },
- { label: "Latest Update", value: "update" },
- { label: "Latest Added", value: "latest" },
- { label: "Popular", value: "popular" },
- ],
- inputType: filterInputs_1.FilterInputs.Picker,
- },
- {
- key: "status",
- label: "Status",
- values: [
- { label: "All", value: "" },
- { label: "Ongoing", value: "ongoing" },
- { label: "Hiatus", value: "hiatus" },
- { label: "Completed", value: "completed" },
- ],
- inputType: filterInputs_1.FilterInputs.Picker,
- },
- {
- key: "type",
- label: "Type",
- values: [
- { label: "Chinese novel", value: "chinese-novel" },
- { label: "habyeol", value: "habyeol" },
- { label: "korean novel", value: "korean-novel" },
- { label: "Web Novel", value: "web-novel" },
- { label: "삼심", value: "%ec%82%bc%ec%8b%ac" },
- { label: "호곡", value: "%ed%98%b8%ea%b3%a1" },
- ],
- inputType: filterInputs_1.FilterInputs.Checkbox,
- },
- {
- key: "genres",
- label: "Genres",
- values: [
- { label: "A.I", value: "a.i" },
- { label: "Academy", value: "academy" },
- { label: "Action", value: "action" },
- { label: "Adult", value: "adult" },
- { label: "Adventure", value: "adventure" },
- { label: "Alternative History", value: "alternative-history" },
- { label: "Another World", value: "another-world" },
- { label: "Apocalypse", value: "apocalypse" },
- { label: "Bromance", value: "bromance" },
- { label: "Comedy", value: "comedy" },
- { label: "Dark fantasy", value: "dark-fantasy" },
- { label: "Demons", value: "demons" },
- { label: "Drama", value: "drama" },
- { label: "Dystopia", value: "dystopia" },
- { label: "Ecchi", value: "ecchi" },
- { label: "Entertainment", value: "entertainment" },
- { label: "Exhaustion", value: "exhaustion" },
- { label: "Fanfiction", value: "fanfiction" },
- { label: "fantasy", value: "fantasy" },
- { label: "finance", value: "finance" },
- { label: "Full color", value: "full-color" },
- { label: "Game", value: "game" },
- { label: "Gender Bender", value: "gender-bender" },
- { label: "Genius", value: "genius" },
- { label: "Harem", value: "harem" },
- { label: "Hero", value: "hero" },
- { label: "Historical", value: "historical" },
- { label: "Hunter", value: "hunter" },
- { label: "korean novel", value: "korean-novel" },
- { label: "Light Novel", value: "light-novel" },
- {
- label: "List Adventure Manga Genres",
- value: "list-adventure-manga-genres",
- },
- { label: "Long Strip", value: "long-strip" },
- { label: "Love comedy", value: "love-comedy" },
- { label: "magic", value: "magic" },
- { label: "Manhua", value: "manhua" },
- { label: "Martial Arts", value: "martial-arts" },
- { label: "Mature", value: "mature" },
- { label: "Medieval", value: "medieval" },
- { label: "Misunderstanding", value: "misunderstanding" },
- { label: "Modern", value: "modern" },
- { label: "modern fantasy", value: "modern-fantasy" },
- { label: "music", value: "music" },
- { label: "Mystery", value: "mystery" },
- { label: "Necromancy", value: "necromancy" },
- { label: "No Romance", value: "no-romance" },
- { label: "NTL", value: "ntl" },
- { label: "o", value: "o" },
- { label: "Obsession", value: "obsession" },
- { label: "Politics", value: "politics" },
- { label: "Possession", value: "possession" },
- { label: "Programming", value: "programming" },
- { label: "Psychological", value: "psychological" },
- { label: "Pure Love", value: "pure-love" },
- { label: "Redemption", value: "redemption" },
- { label: "Regression", value: "regression" },
- { label: "Regret", value: "regret" },
- { label: "Reincarnation", value: "reincarnation" },
- { label: "Revenge", value: "revenge" },
- { label: "Romance", value: "romance" },
- { label: "Romance Fanrasy", value: "romance-fanrasy" },
- { label: "Salvation", value: "salvation" },
- { label: "School Life", value: "school-life" },
- { label: "Sci-fi", value: "sci-fi" },
- { label: "Science fiction", value: "science-fiction" },
- { label: "Seinen", value: "seinen" },
- { label: "Shounen", value: "shounen" },
- { label: "Slice of Life", value: "slice-of-life" },
- { label: "Soft yandere", value: "soft-yandere" },
- { label: "Sports", value: "sports" },
- { label: "Supernatural", value: "supernatural" },
- { label: "Survival", value: "survival" },
- { label: "system", value: "system" },
- { label: "Time limit", value: "time-limit" },
- { label: "Tragedy", value: "tragedy" },
- { label: "Transmigration", value: "transmigration" },
- { label: "TS", value: "ts" },
- { label: "Tsundere", value: "tsundere" },
- { label: "Unique", value: "unique" },
- { label: "Wholesome", value: "wholesome" },
- { label: "Wuxia", value: "wuxia" },
- { label: "Xuanhuan", value: "xuanhuan" },
- { label: "Yandere", value: "yandere" },
- { label: "Yuri", value: "yuri" },
- ],
- inputType: filterInputs_1.FilterInputs.Checkbox,
- },
-];
diff --git a/js/plugins/russian/Erolate[rulate].js b/js/plugins/russian/Erolate[rulate].js
deleted file mode 100644
index f92f504..0000000
--- a/js/plugins/russian/Erolate[rulate].js
+++ /dev/null
@@ -1,195 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-// import dayjs from 'dayjs';
-const fetch_1 = require("@libs/fetch");
-// import { parseMadaraDate } from "@libs/parseMadaraDate";
-// import { isUrlAbsolute } from '@libs/isAbsoluteUrl';
-// import { showToast } from "@libs/showToast";
-const filterInputs_1 = require("@libs/filterInputs");
-const novelStatus_1 = require("@libs/novelStatus");
-// import { defaultCover } from "@libs/defaultCover";
-exports.id = "erolate";
-exports.name = "Erolate";
-exports.icon = "multisrc/rulate/icons/erolate.png";
-exports.version = "1.0.0";
-exports.site = "https://erolate.com";
-const popularNovels = function (page, { filters, showLatestNovels }) {
- return __awaiter(this, void 0, void 0, function* () {
- let url = exports.site + '/search?t=';
- url += '&cat=' + ((filters === null || filters === void 0 ? void 0 : filters.cat) || '0');
- url += '&s_lang=' + ((filters === null || filters === void 0 ? void 0 : filters.s_lang) || '0');
- url += '&t_lang=' + ((filters === null || filters === void 0 ? void 0 : filters.t_lang) || '0');
- url += '&type=' + ((filters === null || filters === void 0 ? void 0 : filters.type) || '0');
- url += '&sort=' + (showLatestNovels ? '4' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || '6'));
- url += '&atmosphere=' + ((filters === null || filters === void 0 ? void 0 : filters.atmosphere) || '0');
- url += '&adult=' + ((filters === null || filters === void 0 ? void 0 : filters.adult) || '0');
- if ((filters === null || filters === void 0 ? void 0 : filters.genres) instanceof Array) {
- url += filters.genres.map(i => '&genres[]=' + i).join('');
- }
- if ((filters === null || filters === void 0 ? void 0 : filters.genres_ex) instanceof Array) {
- url += filters.genres_ex.map(i => '&genres_ex[]=' + i).join('');
- }
- if ((filters === null || filters === void 0 ? void 0 : filters.tags) instanceof Array) {
- url += filters.tags.map(i => '&tags[]=' + i).join('');
- }
- if ((filters === null || filters === void 0 ? void 0 : filters.tags_ex) instanceof Array) {
- url += filters.tags_ex.map(i => '&tags_ex[]=' + i).join('');
- }
- if ((filters === null || filters === void 0 ? void 0 : filters.fandoms) instanceof Array) {
- url += filters.fandoms.map(i => '&fandoms[]=' + i).join('');
- }
- if ((filters === null || filters === void 0 ? void 0 : filters.fandoms_ex) instanceof Array) {
- url += filters.fandoms_ex.map(i => '&fandoms_ex[]=' + i).join('');
- }
- if ((filters === null || filters === void 0 ? void 0 : filters.trash) instanceof Array) {
- url += filters.trash.map(i => '&' + i + '=1').join('');
- }
- url += '&Book_page=' + page;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- const novels = [];
- loadedCheerio('ul[class="search-results"] > li:not([class="ad_type_catalog"])').each(function () {
- novels.push({
- name: loadedCheerio(this).find('p > a').text(),
- cover: exports.site + loadedCheerio(this).find('img').attr('src'),
- url: exports.site + loadedCheerio(this).find('p > a').attr('href') || '',
- });
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- chapters: [],
- };
- let result = yield (0, fetch_1.fetchApi)(novelUrl);
- if (result.url.includes('mature?path=')) {
- const formData = new FormData();
- formData.append('path', novelUrl);
- formData.append('ok', 'Да');
- yield (0, fetch_1.fetchApi)(result.url, {
- method: 'POST',
- body: formData,
- });
- result = yield (0, fetch_1.fetchApi)(novelUrl);
- }
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- novel.name = loadedCheerio('div[class="container"] > div > div > h1, div.span8:nth-child(1) > h1:nth-child(2)')
- .text()
- .trim();
- novel.cover =
- exports.site + loadedCheerio('div[class="images"] > div img').attr('src');
- novel.summary = loadedCheerio('#Info > div:nth-child(3), .book-description').text();
- novel.author = loadedCheerio('.book-stats-icons_author > span:nth-child(2) > a:nth-child(1)').text();
- let genres = [];
- loadedCheerio('div.span5 > p, .span5 > div:nth-child(2) > p').each(function () {
- switch (loadedCheerio(this).find('strong').text()) {
- case 'Автор:':
- novel.author = loadedCheerio(this).find('em > a').text().trim();
- break;
- case 'Выпуск:':
- novel.status =
- loadedCheerio(this).find('em').text().trim() === 'продолжается'
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- case 'Тэги:':
- loadedCheerio(this)
- .find('em > a')
- .each(function () {
- genres.push(loadedCheerio(this).text());
- });
- break;
- case 'Жанры:':
- loadedCheerio(this)
- .find('em > a')
- .each(function () {
- genres.push(loadedCheerio(this).text());
- });
- break;
- }
- });
- if (genres.length > 0) {
- novel.genres = genres.reverse().join(',');
- }
- const chapters = [];
- loadedCheerio('table > tbody > tr.chapter_row').each(function () {
- var _a;
- const chapterName = loadedCheerio(this)
- .find('td[class="t"] > a')
- .text()
- .trim();
- const releaseDate = (_a = loadedCheerio(this)
- .find('td > span')
- .attr('title')) === null || _a === void 0 ? void 0 : _a.trim();
- const chapterUrl = exports.site + loadedCheerio(this)
- .find('td[class="t"] > a')
- .attr('href');
- if (loadedCheerio(this).find('td > span[class="disabled"]').length < 1 &&
- releaseDate) {
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- }
- });
- novel.chapters = chapters;
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- let result = yield (0, fetch_1.fetchApi)(chapterUrl);
- if (result.url.includes('mature?path=')) {
- const formData = new FormData();
- formData.append('ok', 'Да');
- yield (0, fetch_1.fetchApi)(result.url, {
- method: 'POST',
- body: formData,
- });
- result = yield (0, fetch_1.fetchApi)(chapterUrl);
- }
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.content-text img').each(function () {
- var _a;
- if (!((_a = loadedCheerio(this).attr('src')) === null || _a === void 0 ? void 0 : _a.startsWith('http'))) {
- const src = loadedCheerio(this).attr('src');
- loadedCheerio(this).attr('src', exports.site + src);
- }
- });
- const chapterText = loadedCheerio('.content-text').html();
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const result = yield (0, fetch_1.fetchApi)(exports.site + '/search/autocomplete?query=' + searchTerm);
- let json = yield result.json();
- json.forEach((item) => {
- const novelName = item.title_one + ' / ' + item.title_two;
- const novelCover = exports.site + item.img;
- const novelUrl = exports.site + item.url;
- novels.push({ name: novelName, cover: novelCover, url: novelUrl });
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-;
-exports.fetchImage = fetch_1.fetchFile;
-exports.filters = [{ "key": "cat", "label": "Из раздела каталога:", "values": [{ "label": "Неважно", "value": "0" }, { "label": "Авторские", "value": "12" }, { "label": "Авторские", "value": "35" }, { "label": "Английские", "value": "34" }, { "label": "Игры 18+", "value": "3" }, { "label": "Китайские", "value": "31" }, { "label": "Комиксы", "value": "29" }, { "label": "Корейские", "value": "33" }, { "label": "Манга для взрослых", "value": "30" }, { "label": "Машинный перевод", "value": "38" }, { "label": "Переводы", "value": "15" }, { "label": "Фанфики", "value": "16" }, { "label": "Эротические рассказы", "value": "2" }], "inputType": filterInputs_1.FilterInputs.Picker }, { "key": "s_lang", "label": "Язык оригинала:", "values": [{ "label": "Неважно", "value": "0" }, { "label": "Абхазский", "value": "20" }, { "label": "Аварский", "value": "21" }, { "label": "Азербайджанский", "value": "22" }, { "label": "Аймара", "value": "23" }, { "label": "Акан", "value": "24" }, { "label": "Албанский", "value": "25" }, { "label": "Амхарский", "value": "26" }, { "label": "Английский", "value": "2" }, { "label": "Арабский", "value": "27" }, { "label": "Арагонский", "value": "28" }, { "label": "Арберешский", "value": "29" }, { "label": "Армянский", "value": "30" }, { "label": "Ассамский", "value": "31" }, { "label": "Астурийский", "value": "32" }, { "label": "Афарский", "value": "33" }, { "label": "Африкаанс", "value": "34" }, { "label": "Ацтекский", "value": "35" }, { "label": "Баварский", "value": "36" }, { "label": "Бамбарийский", "value": "37" }, { "label": "Баскский", "value": "39" }, { "label": "Башкирский", "value": "40" }, { "label": "Белорусский", "value": "10" }, { "label": "Бенгальский", "value": "41" }, { "label": "Бирманский", "value": "42" }, { "label": "Бислама", "value": "43" }, { "label": "Бихари", "value": "44" }, { "label": "Болгарский", "value": "45" }, { "label": "Боснийский", "value": "234" }, { "label": "Бретонский", "value": "47" }, { "label": "Валенсийский", "value": "48" }, { "label": "Валлийский", "value": "49" }, { "label": "Валлонский", "value": "50" }, { "label": "Венгерский", "value": "51" }, { "label": "Венда", "value": "52" }, { "label": "Венетский", "value": "53" }, { "label": "Верхнелужицкий", "value": "54" }, { "label": "Волоф", "value": "55" }, { "label": "Вьетнамский", "value": "57" }, { "label": "Гавайский", "value": "58" }, { "label": "Гаитянский", "value": "59" }, { "label": "Галисийский", "value": "60" }, { "label": "Гереро", "value": "61" }, { "label": "Голландский", "value": "62" }, { "label": "Греческий", "value": "63" }, { "label": "Грузинский", "value": "64" }, { "label": "Гуарани", "value": "65" }, { "label": "Гуджарати", "value": "66" }, { "label": "Датский", "value": "19" }, { "label": "Дзонг-кэ", "value": "68" }, { "label": "Древнегреческий", "value": "69" }, { "label": "Западно-фламандский", "value": "70" }, { "label": "Зулу", "value": "71" }, { "label": "Иврит", "value": "15" }, { "label": "Игбо", "value": "72" }, { "label": "Идиш", "value": "73" }, { "label": "Илоко", "value": "74" }, { "label": "Индонезийский", "value": "75" }, { "label": "Интерлингва", "value": "76" }, { "label": "Инуктитут", "value": "77" }, { "label": "Инупиак", "value": "78" }, { "label": "Ирландский", "value": "79" }, { "label": "Исландский", "value": "80" }, { "label": "Испанский", "value": "6" }, { "label": "Итальянский", "value": "5" }, { "label": "Йоруба", "value": "81" }, { "label": "Кабильский", "value": "82" }, { "label": "Казахский", "value": "83" }, { "label": "Калмыцкий", "value": "235" }, { "label": "Каннада", "value": "84" }, { "label": "Кантонский юэ", "value": "85" }, { "label": "Канури", "value": "86" }, { "label": "Каталанский", "value": "87" }, { "label": "Кашмири", "value": "88" }, { "label": "Кечуа", "value": "90" }, { "label": "Кикуйю", "value": "91" }, { "label": "Киньяруанда", "value": "92" }, { "label": "Киргизский", "value": "93" }, { "label": "Китайский", "value": "7" }, { "label": "Клингонский", "value": "94" }, { "label": "Коми", "value": "95" }, { "label": "Конго", "value": "96" }, { "label": "Конкани", "value": "97" }, { "label": "Корейский", "value": "98" }, { "label": "Корсиканский", "value": "100" }, { "label": "Котава", "value": "101" }, { "label": "Кри", "value": "102" }, { "label": "Курдский", "value": "105" }, { "label": "Кхмерский", "value": "107" }, { "label": "Лакский", "value": "233" }, { "label": "Лаосский", "value": "109" }, { "label": "Латынь", "value": "110" }, { "label": "Латышский", "value": "111" }, { "label": "Лезгинский", "value": "112" }, { "label": "Лимбургский", "value": "113" }, { "label": "Лингала", "value": "114" }, { "label": "Литовский", "value": "115" }, { "label": "Луба", "value": "118" }, { "label": "Луганда", "value": "119" }, { "label": "Люксембургский", "value": "120" }, { "label": "Македонский", "value": "121" }, { "label": "Малагасийский", "value": "122" }, { "label": "Малайский", "value": "123" }, { "label": "Мальдивский", "value": "125" }, { "label": "Мальтийский", "value": "126" }, { "label": "Маори", "value": "127" }, { "label": "Марийский", "value": "232" }, { "label": "Маршалльский", "value": "130" }, { "label": "Молдавский", "value": "11" }, { "label": "Монгольский", "value": "133" }, { "label": "Мяо (хмонг)", "value": "209" }, { "label": "Навахо", "value": "135" }, { "label": "Неаполитанский", "value": "139" }, { "label": "Немецкий", "value": "3" }, { "label": "Непальский", "value": "140" }, { "label": "Норвежский", "value": "18" }, { "label": "Осетинский", "value": "147" }, { "label": "Пакистанский", "value": "230" }, { "label": "Пенджабский", "value": "149" }, { "label": "Персидский", "value": "151" }, { "label": "Польский", "value": "152" }, { "label": "Португальский", "value": "153" }, { "label": "Румынский", "value": "158" }, { "label": "Русский", "value": "1" }, { "label": "Санскрит", "value": "163" }, { "label": "Сардинский", "value": "164" }, { "label": "Сербохорватский", "value": "166" }, { "label": "Словацкий", "value": "170" }, { "label": "Словенский", "value": "171" }, { "label": "Сомали", "value": "172" }, { "label": "Старотурецкий", "value": "174" }, { "label": "Суахили", "value": "175" }, { "label": "Сунданский", "value": "176" }, { "label": "Тагальский", "value": "177" }, { "label": "Таджикский", "value": "178" }, { "label": "Таитянский", "value": "179" }, { "label": "Тайваньский", "value": "180" }, { "label": "Тайский", "value": "181" }, { "label": "Тамильский", "value": "182" }, { "label": "Татарский", "value": "12" }, { "label": "Телугу", "value": "184" }, { "label": "Тибетский", "value": "185" }, { "label": "Тигринья", "value": "186" }, { "label": "Ток-писин", "value": "187" }, { "label": "Токи пона", "value": "188" }, { "label": "Тонганский", "value": "189" }, { "label": "Тсвана", "value": "191" }, { "label": "Тсонга", "value": "192" }, { "label": "Турецкий", "value": "193" }, { "label": "Туркменский", "value": "194" }, { "label": "Удмуртский", "value": "196" }, { "label": "Узбекский", "value": "197" }, { "label": "Уйгурский", "value": "198" }, { "label": "Украинский", "value": "9" }, { "label": "Фиджийский", "value": "201" }, { "label": "Филиппинский", "value": "229" }, { "label": "Финский", "value": "17" }, { "label": "Французский", "value": "4" }, { "label": "Фризский", "value": "203" }, { "label": "Фулах", "value": "204" }, { "label": "Хауса", "value": "206" }, { "label": "Хинди", "value": "207" }, { "label": "Хири-моту", "value": "208" }, { "label": "Чеченский", "value": "213" }, { "label": "Чешский", "value": "13" }, { "label": "Чувашский", "value": "217" }, { "label": "Шведский", "value": "16" }, { "label": "Швейцарский немецкий", "value": "218" }, { "label": "Шона", "value": "219" }, { "label": "Шотландский", "value": "67" }, { "label": "Эве", "value": "221" }, { "label": "Эскимосский", "value": "223" }, { "label": "Эсперанто", "value": "14" }, { "label": "Эстонский", "value": "224" }, { "label": "Южно-корейский", "value": "231" }, { "label": "Юкатекский", "value": "225" }, { "label": "Яванский", "value": "227" }, { "label": "Японский", "value": "8" }], "inputType": filterInputs_1.FilterInputs.Picker }, { "key": "t_lang", "label": "Язык перевода:", "values": [{ "label": "Неважно", "value": "0" }, { "label": "Абхазский", "value": "20" }, { "label": "Аварский", "value": "21" }, { "label": "Азербайджанский", "value": "22" }, { "label": "Аймара", "value": "23" }, { "label": "Акан", "value": "24" }, { "label": "Албанский", "value": "25" }, { "label": "Амхарский", "value": "26" }, { "label": "Английский", "value": "2" }, { "label": "Арабский", "value": "27" }, { "label": "Арагонский", "value": "28" }, { "label": "Арберешский", "value": "29" }, { "label": "Армянский", "value": "30" }, { "label": "Ассамский", "value": "31" }, { "label": "Астурийский", "value": "32" }, { "label": "Афарский", "value": "33" }, { "label": "Африкаанс", "value": "34" }, { "label": "Ацтекский", "value": "35" }, { "label": "Баварский", "value": "36" }, { "label": "Бамбарийский", "value": "37" }, { "label": "Баскский", "value": "39" }, { "label": "Башкирский", "value": "40" }, { "label": "Белорусский", "value": "10" }, { "label": "Бенгальский", "value": "41" }, { "label": "Бирманский", "value": "42" }, { "label": "Бислама", "value": "43" }, { "label": "Бихари", "value": "44" }, { "label": "Болгарский", "value": "45" }, { "label": "Боснийский", "value": "234" }, { "label": "Бретонский", "value": "47" }, { "label": "Валенсийский", "value": "48" }, { "label": "Валлийский", "value": "49" }, { "label": "Валлонский", "value": "50" }, { "label": "Венгерский", "value": "51" }, { "label": "Венда", "value": "52" }, { "label": "Венетский", "value": "53" }, { "label": "Верхнелужицкий", "value": "54" }, { "label": "Волоф", "value": "55" }, { "label": "Вьетнамский", "value": "57" }, { "label": "Гавайский", "value": "58" }, { "label": "Гаитянский", "value": "59" }, { "label": "Галисийский", "value": "60" }, { "label": "Гереро", "value": "61" }, { "label": "Голландский", "value": "62" }, { "label": "Греческий", "value": "63" }, { "label": "Грузинский", "value": "64" }, { "label": "Гуарани", "value": "65" }, { "label": "Гуджарати", "value": "66" }, { "label": "Датский", "value": "19" }, { "label": "Дзонг-кэ", "value": "68" }, { "label": "Древнегреческий", "value": "69" }, { "label": "Западно-фламандский", "value": "70" }, { "label": "Зулу", "value": "71" }, { "label": "Иврит", "value": "15" }, { "label": "Игбо", "value": "72" }, { "label": "Идиш", "value": "73" }, { "label": "Илоко", "value": "74" }, { "label": "Индонезийский", "value": "75" }, { "label": "Интерлингва", "value": "76" }, { "label": "Инуктитут", "value": "77" }, { "label": "Инупиак", "value": "78" }, { "label": "Ирландский", "value": "79" }, { "label": "Исландский", "value": "80" }, { "label": "Испанский", "value": "6" }, { "label": "Итальянский", "value": "5" }, { "label": "Йоруба", "value": "81" }, { "label": "Кабильский", "value": "82" }, { "label": "Казахский", "value": "83" }, { "label": "Калмыцкий", "value": "235" }, { "label": "Каннада", "value": "84" }, { "label": "Кантонский юэ", "value": "85" }, { "label": "Канури", "value": "86" }, { "label": "Каталанский", "value": "87" }, { "label": "Кашмири", "value": "88" }, { "label": "Кечуа", "value": "90" }, { "label": "Кикуйю", "value": "91" }, { "label": "Киньяруанда", "value": "92" }, { "label": "Киргизский", "value": "93" }, { "label": "Китайский", "value": "7" }, { "label": "Клингонский", "value": "94" }, { "label": "Коми", "value": "95" }, { "label": "Конго", "value": "96" }, { "label": "Конкани", "value": "97" }, { "label": "Корейский", "value": "98" }, { "label": "Корсиканский", "value": "100" }, { "label": "Котава", "value": "101" }, { "label": "Кри", "value": "102" }, { "label": "Курдский", "value": "105" }, { "label": "Кхмерский", "value": "107" }, { "label": "Лакский", "value": "233" }, { "label": "Лаосский", "value": "109" }, { "label": "Латынь", "value": "110" }, { "label": "Латышский", "value": "111" }, { "label": "Лезгинский", "value": "112" }, { "label": "Лимбургский", "value": "113" }, { "label": "Лингала", "value": "114" }, { "label": "Литовский", "value": "115" }, { "label": "Луба", "value": "118" }, { "label": "Луганда", "value": "119" }, { "label": "Люксембургский", "value": "120" }, { "label": "Македонский", "value": "121" }, { "label": "Малагасийский", "value": "122" }, { "label": "Малайский", "value": "123" }, { "label": "Мальдивский", "value": "125" }, { "label": "Мальтийский", "value": "126" }, { "label": "Маори", "value": "127" }, { "label": "Марийский", "value": "232" }, { "label": "Маршалльский", "value": "130" }, { "label": "Молдавский", "value": "11" }, { "label": "Монгольский", "value": "133" }, { "label": "Мяо (хмонг)", "value": "209" }, { "label": "Навахо", "value": "135" }, { "label": "Неаполитанский", "value": "139" }, { "label": "Немецкий", "value": "3" }, { "label": "Непальский", "value": "140" }, { "label": "Норвежский", "value": "18" }, { "label": "Осетинский", "value": "147" }, { "label": "Пакистанский", "value": "230" }, { "label": "Пенджабский", "value": "149" }, { "label": "Персидский", "value": "151" }, { "label": "Польский", "value": "152" }, { "label": "Португальский", "value": "153" }, { "label": "Румынский", "value": "158" }, { "label": "Русский", "value": "1" }, { "label": "Санскрит", "value": "163" }, { "label": "Сардинский", "value": "164" }, { "label": "Сербохорватский", "value": "166" }, { "label": "Словацкий", "value": "170" }, { "label": "Словенский", "value": "171" }, { "label": "Сомали", "value": "172" }, { "label": "Старотурецкий", "value": "174" }, { "label": "Суахили", "value": "175" }, { "label": "Сунданский", "value": "176" }, { "label": "Тагальский", "value": "177" }, { "label": "Таджикский", "value": "178" }, { "label": "Таитянский", "value": "179" }, { "label": "Тайваньский", "value": "180" }, { "label": "Тайский", "value": "181" }, { "label": "Тамильский", "value": "182" }, { "label": "Татарский", "value": "12" }, { "label": "Телугу", "value": "184" }, { "label": "Тибетский", "value": "185" }, { "label": "Тигринья", "value": "186" }, { "label": "Ток-писин", "value": "187" }, { "label": "Токи пона", "value": "188" }, { "label": "Тонганский", "value": "189" }, { "label": "Тсвана", "value": "191" }, { "label": "Тсонга", "value": "192" }, { "label": "Турецкий", "value": "193" }, { "label": "Туркменский", "value": "194" }, { "label": "Удмуртский", "value": "196" }, { "label": "Узбекский", "value": "197" }, { "label": "Уйгурский", "value": "198" }, { "label": "Украинский", "value": "9" }, { "label": "Фиджийский", "value": "201" }, { "label": "Филиппинский", "value": "229" }, { "label": "Финский", "value": "17" }, { "label": "Французский", "value": "4" }, { "label": "Фризский", "value": "203" }, { "label": "Фулах", "value": "204" }, { "label": "Хауса", "value": "206" }, { "label": "Хинди", "value": "207" }, { "label": "Хири-моту", "value": "208" }, { "label": "Чеченский", "value": "213" }, { "label": "Чешский", "value": "13" }, { "label": "Чувашский", "value": "217" }, { "label": "Шведский", "value": "16" }, { "label": "Швейцарский немецкий", "value": "218" }, { "label": "Шона", "value": "219" }, { "label": "Шотландский", "value": "67" }, { "label": "Эве", "value": "221" }, { "label": "Эскимосский", "value": "223" }, { "label": "Эсперанто", "value": "14" }, { "label": "Эстонский", "value": "224" }, { "label": "Южно-корейский", "value": "231" }, { "label": "Юкатекский", "value": "225" }, { "label": "Яванский", "value": "227" }, { "label": "Японский", "value": "8" }], "inputType": filterInputs_1.FilterInputs.Picker }, { "key": "type", "label": "Тип:", "values": [{ "label": "Неважно", "value": "0" }, { "label": "Только авторские", "value": "2" }, { "label": "Только переводы", "value": "1" }], "inputType": filterInputs_1.FilterInputs.Picker }, { "key": "trash", "label": "Другое:", "values": [{ "label": "Без фэндомов", "value": "fandoms_ex_all" }, { "label": "Готовые на 100%", "value": "ready" }, { "label": "Доступные для перевода", "value": "tr" }, { "label": "Доступные для скачивания", "value": "gen" }, { "label": "Завершённые проекты", "value": "wealth" }, { "label": "Распродажа", "value": "discount" }, { "label": "Только онгоинги", "value": "ongoings" }, { "label": "Убрать машинный", "value": "remove_machinelate" }], "inputType": filterInputs_1.FilterInputs.Checkbox }, { "key": "sort", "label": "Сортировка:", "values": [{ "label": "По рейтингу", "value": "6" }, { "label": "По дате последней активности", "value": "4" }, { "label": "По дате создания", "value": "3" }, { "label": "По кол-ву бесплатных глав", "value": "11" }, { "label": "По кол-ву в закладках", "value": "13" }, { "label": "По кол-ву в избранном", "value": "14" }, { "label": "По кол-ву лайков", "value": "8" }, { "label": "По кол-ву переведённых глав", "value": "7" }, { "label": "По кол-ву рецензий", "value": "12" }, { "label": "По кол-ву страниц", "value": "10" }, { "label": "По названию на языке оригинала", "value": "1" }, { "label": "По названию на языке перевода", "value": "2" }, { "label": "По просмотрам", "value": "5" }, { "label": "По степени готовности", "value": "0" }, { "label": "Случайно", "value": "9" }], "inputType": filterInputs_1.FilterInputs.Picker }, { "key": "genres", "label": "Жанры:", "values": [{ "label": "Анал", "value": "2" }, { "label": "Бдсм", "value": "3" }, { "label": "Большая грудь", "value": "5" }, { "label": "Большая попка", "value": "6" }, { "label": "Большой член", "value": "7" }, { "label": "Бондаж", "value": "8" }, { "label": "В первый раз", "value": "9" }, { "label": "В цвете", "value": "10" }, { "label": "Гарем", "value": "11" }, { "label": "Гендарная интрига", "value": "12" }, { "label": "Групповой секс", "value": "13" }, { "label": "Детектив", "value": "39" }, { "label": "Драма", "value": "14" }, { "label": "Зрелые женщины (milf)", "value": "15" }, { "label": "Измена", "value": "16" }, { "label": "Изнасилование", "value": "17" }, { "label": "Инцест", "value": "18" }, { "label": "Исторический", "value": "19" }, { "label": "Комедия", "value": "20" }, { "label": "Контроль над разумом", "value": "35" }, { "label": "Маленькая грудь", "value": "21" }, { "label": "Мистика", "value": "40" }, { "label": "Научная фантастика", "value": "22" }, { "label": "Нетораре", "value": "23" }, { "label": "Оральный секс", "value": "24" }, { "label": "Повседневность", "value": "41" }, { "label": "Приключения", "value": "38" }, { "label": "Публичный секс", "value": "33" }, { "label": "Романтика", "value": "25" }, { "label": "С изображениями", "value": "36" }, { "label": "Сверхъестественное", "value": "34" }, { "label": "Смат", "value": "37" }, { "label": "Тентакли", "value": "26" }, { "label": "Трагедия", "value": "27" }, { "label": "Ужасы", "value": "28" }, { "label": "Фантастика", "value": "32" }, { "label": "Фэнтези", "value": "29" }, { "label": "Чикан", "value": "30" }, { "label": "Этти", "value": "31" }, { "label": "Ahegao", "value": "1" }], "inputType": filterInputs_1.FilterInputs.Checkbox }, { "key": "tags", "label": "Тэги:", "values": [{ "label": "+18", "value": "141" }, { "label": "18+", "value": "200" }, { "label": "21+", "value": "334" }, { "label": "Адекватные главные герои", "value": "253" }, { "label": "Азартные игры", "value": "210" }, { "label": "Айдолы", "value": "364" }, { "label": "Акула", "value": "53" }, { "label": "Альтернативное развитие событий", "value": "338" }, { "label": "Аморальный главный герой", "value": "219" }, { "label": "Анал", "value": "7" }, { "label": "Анальный секс", "value": "67" }, { "label": "Ангелы", "value": "114" }, { "label": "Антигерой", "value": "226" }, { "label": "Аристократия", "value": "260" }, { "label": "Артефакт", "value": "379" }, { "label": "Афродизиак", "value": "276" }, { "label": "Ахегао", "value": "240" }, { "label": "Бабушка беременна от внука", "value": "393" }, { "label": "Бабушка и внук", "value": "380" }, { "label": "Бдсм", "value": "131" }, { "label": "Беременность", "value": "148" }, { "label": "Бесплатно", "value": "79" }, { "label": "Бесстрашные персонажи", "value": "339" }, { "label": "Библиотека", "value": "265" }, { "label": "Бистиалити", "value": "391" }, { "label": "Битва за трон", "value": "404" }, { "label": "Близнецы", "value": "198" }, { "label": "Блондинка", "value": "91" }, { "label": "Богатые персонажи", "value": "248" }, { "label": "Боги", "value": "115" }, { "label": "Боевик", "value": "252" }, { "label": "Большая грудь", "value": "33" }, { "label": "Большая попка", "value": "328" }, { "label": "Большой член", "value": "76" }, { "label": "Большой член сына", "value": "396" }, { "label": "Босс и подчиненный", "value": "330" }, { "label": "Брак", "value": "182" }, { "label": "Брак по расчёту", "value": "346" }, { "label": "Брат", "value": "29" }, { "label": "Брат и сестра", "value": "30" }, { "label": "Брюнетка", "value": "28" }, { "label": "Бэтмен", "value": "369" }, { "label": "Бэтмен", "value": "170" }, { "label": "В первый раз", "value": "179" }, { "label": "Вагинальный секс", "value": "57" }, { "label": "Вагинальный секс", "value": "171" }, { "label": "Вайурист", "value": "9" }, { "label": "Вампиры", "value": "133" }, { "label": "Ван-пис", "value": "335" }, { "label": "Веб камера", "value": "289" }, { "label": "Ведьмы", "value": "232" }, { "label": "Викинги", "value": "307" }, { "label": "Виртуальная реальность", "value": "382" }, { "label": "Вирус", "value": "203" }, { "label": "Внучка", "value": "189" }, { "label": "Война", "value": "387" }, { "label": "Воспоминания из прошлого", "value": "405" }, { "label": "Враги становятся любовниками", "value": "410" }, { "label": "Время", "value": "81" }, { "label": "Второй шанс", "value": "244" }, { "label": "Вуайеризм", "value": "62" }, { "label": "Выживание", "value": "135" }, { "label": "Гарем", "value": "107" }, { "label": "Гарри поттер", "value": "97" }, { "label": "Гвен", "value": "402" }, { "label": "Гг имба", "value": "87" }, { "label": "Генетические модификации", "value": "314" }, { "label": "Гипноз", "value": "143" }, { "label": "Главная героиня девушка", "value": "147" }, { "label": "Главный герой женщина", "value": "213" }, { "label": "Главный герой извращенец", "value": "116" }, { "label": "Главный герой мужчина", "value": "117" }, { "label": "Глубокое горло", "value": "94" }, { "label": "Гоблины", "value": "230" }, { "label": "Город", "value": "139" }, { "label": "Городское фэнтези", "value": "297" }, { "label": "Грудное молоко", "value": "225" }, { "label": "Групповой секс", "value": "72" }, { "label": "Гэнг-бэнг", "value": "235" }, { "label": "Гяру", "value": "222" }, { "label": "Двойное проникновение", "value": "42" }, { "label": "Двойной анал", "value": "47" }, { "label": "Дворяне", "value": "246" }, { "label": "Деамоны старший школы", "value": "291" }, { "label": "Девственница", "value": "119" }, { "label": "Девушки-монстры", "value": "223" }, { "label": "Демоны", "value": "98" }, { "label": "Детектив", "value": "249" }, { "label": "Дзёсэй", "value": "259" }, { "label": "Доктор", "value": "326" }, { "label": "Дом", "value": "138" }, { "label": "Доминирование", "value": "18" }, { "label": "Дочь", "value": "153" }, { "label": "Дочь беременна от отца", "value": "348" }, { "label": "Древние времена", "value": "383" }, { "label": "Древний китай", "value": "261" }, { "label": "Другой мир", "value": "365" }, { "label": "Дружба", "value": "325" }, { "label": "Друзья детства", "value": "183" }, { "label": "Дядя", "value": "160" }, { "label": "Жена", "value": "70" }, { "label": "Жена и муж", "value": "99" }, { "label": "Жена шлюха", "value": "236" }, { "label": "Женское доминирование", "value": "100" }, { "label": "Жесткий секс", "value": "283" }, { "label": "Жёсткий секс", "value": "101" }, { "label": "Жестокие персонажи", "value": "254" }, { "label": "Жестокий мир", "value": "336" }, { "label": "Жестокость", "value": "123" }, { "label": "Заботливый главный герой", "value": "340" }, { "label": "Зависимость", "value": "370" }, { "label": "Заключение", "value": "196" }, { "label": "Заключённые", "value": "384" }, { "label": "Замок", "value": "140" }, { "label": "Запретная любовь", "value": "273" }, { "label": "Заражение", "value": "206" }, { "label": "Звёздные войны", "value": "120" }, { "label": "Зверодевочки", "value": "158" }, { "label": "Зло", "value": "343" }, { "label": "Золовка", "value": "77" }, { "label": "Золотой дождь", "value": "146" }, { "label": "Зомби апокалипсис", "value": "241" }, { "label": "Зоофилия", "value": "144" }, { "label": "Зрелые женщины", "value": "398" }, { "label": "Игровые элементы", "value": "385" }, { "label": "Извращения", "value": "192" }, { "label": "Измена", "value": "71" }, { "label": "Изменения внешности", "value": "315" }, { "label": "Изменения личности", "value": "316" }, { "label": "Изнасилование", "value": "275" }, { "label": "Изуку мидория", "value": "337" }, { "label": "Ино", "value": "127" }, { "label": "Инопланетяне", "value": "304" }, { "label": "Интересный сюжет", "value": "349" }, { "label": "Интимные сцены", "value": "322" }, { "label": "Интриги и заговоры", "value": "262" }, { "label": "Интроверт", "value": "38" }, { "label": "Инфекция", "value": "207" }, { "label": "Инцест", "value": "35" }, { "label": "Исторический роман", "value": "406" }, { "label": "Камера", "value": "92" }, { "label": "Колледж", "value": "82" }, { "label": "Комикс", "value": "286" }, { "label": "Контроль", "value": "19" }, { "label": "Контроль над разумом", "value": "181" }, { "label": "Контроль разума", "value": "65" }, { "label": "Кончил внутрь", "value": "221" }, { "label": "Королевская семья", "value": "358" }, { "label": "Коррупция", "value": "49" }, { "label": "Космос", "value": "204" }, { "label": "Красивая главная героиня", "value": "255" }, { "label": "Красивые женщины", "value": "321" }, { "label": "Красивый главный герой", "value": "266" }, { "label": "Ксенофилия", "value": "386" }, { "label": "Кулинария", "value": "362" }, { "label": "Культвация", "value": "86" }, { "label": "Кунилингус", "value": "152" }, { "label": "Кушина", "value": "399" }, { "label": "Лактация", "value": "11" }, { "label": "Лесби", "value": "408" }, { "label": "Лишение девственности", "value": "212" }, { "label": "Лоли", "value": "218" }, { "label": "Лунатизм", "value": "279" }, { "label": "Любовь", "value": "89" }, { "label": "Магический мир", "value": "357" }, { "label": "Магия", "value": "80" }, { "label": "Мама", "value": "3" }, { "label": "Мама беременна от сына", "value": "274" }, { "label": "Мама и дочь", "value": "163" }, { "label": "Мама и сын", "value": "1" }, { "label": "Мама супермена", "value": "39" }, { "label": "Манипуляция временем", "value": "292" }, { "label": "Марвел", "value": "290" }, { "label": "Марвел", "value": "173" }, { "label": "Марти стью", "value": "102" }, { "label": "Массаж", "value": "224" }, { "label": "Мастурбация", "value": "63" }, { "label": "Мать", "value": "239" }, { "label": "Мать и дочь", "value": "381" }, { "label": "Мать и сын", "value": "237" }, { "label": "Мафия", "value": "256" }, { "label": "Мачеха", "value": "197" }, { "label": "Мачеха беременна от сына", "value": "395" }, { "label": "Мачеха и сын", "value": "394" }, { "label": "Медсестра", "value": "341" }, { "label": "Межрассовый", "value": "54" }, { "label": "Месть", "value": "306" }, { "label": "Меха", "value": "268" }, { "label": "Ми", "value": "243" }, { "label": "Милф", "value": "34" }, { "label": "Милф", "value": "180" }, { "label": "Минет", "value": "52" }, { "label": "Мистика", "value": "250" }, { "label": "Младшая сестра", "value": "154" }, { "label": "Много спермы", "value": "409" }, { "label": "Модель", "value": "324" }, { "label": "Монстры", "value": "333" }, { "label": "Мошеничество", "value": "44" }, { "label": "Мужская беременность", "value": "363" }, { "label": "Мужчина протагонист", "value": "108" }, { "label": "Музыка", "value": "331" }, { "label": "Мэри съюха", "value": "309" }, { "label": "Наруко", "value": "400" }, { "label": "Наруто", "value": "46" }, { "label": "Насилие", "value": "128" }, { "label": "Насилие и жестокость", "value": "193" }, { "label": "Научный эксперимент", "value": "313" }, { "label": "Нежить", "value": "373" }, { "label": "Некромантия", "value": "298" }, { "label": "Ненормативная лексика", "value": "124" }, { "label": "Нетораре", "value": "69" }, { "label": "Нетори", "value": "284" }, { "label": "Нижнее бельё", "value": "392" }, { "label": "Ниндзя", "value": "296" }, { "label": "Ношеные трусики", "value": "166" }, { "label": "Нудизм", "value": "156" }, { "label": "Няня", "value": "88" }, { "label": "Обмен женами", "value": "78" }, { "label": "Оборотни", "value": "136" }, { "label": "Обратный гарем", "value": "214" }, { "label": "Одержимость", "value": "345" }, { "label": "Омегаверс", "value": "368" }, { "label": "Оплодотворение", "value": "157" }, { "label": "Оральный секс", "value": "10" }, { "label": "Оргия", "value": "356" }, { "label": "Орки", "value": "388" }, { "label": "От слабого к сильному", "value": "351" }, { "label": "Отец", "value": "2" }, { "label": "Отец делится с сыном", "value": "6" }, { "label": "Отец и дочь", "value": "205" }, { "label": "Отец куколд", "value": "272" }, { "label": "Офис", "value": "234" }, { "label": "Падчерица", "value": "271" }, { "label": "Пайзури", "value": "195" }, { "label": "Папа и дочь", "value": "360" }, { "label": "Паразиты", "value": "208" }, { "label": "Параллельный мир", "value": "320" }, { "label": "Пародия", "value": "371" }, { "label": "Первый раз", "value": "159" }, { "label": "Перемещение в другой мир", "value": "347" }, { "label": "Перемещение во времени", "value": "245" }, { "label": "Перерождение", "value": "109" }, { "label": "Перерождение в злодея", "value": "202" }, { "label": "Пирсинг", "value": "145" }, { "label": "Писатель", "value": "267" }, { "label": "Планомерное развитие событий", "value": "350" }, { "label": "Повседневность", "value": "247" }, { "label": "Подглядывание", "value": "280" }, { "label": "Подчинение", "value": "106" }, { "label": "Подчинение и унижение", "value": "211" }, { "label": "Поедание киски", "value": "26" }, { "label": "Покемоны", "value": "132" }, { "label": "Покорная", "value": "8" }, { "label": "Полигамия", "value": "352" }, { "label": "Половое воспитание", "value": "37" }, { "label": "Полулюди", "value": "231" }, { "label": "Попаданец", "value": "103" }, { "label": "Попадание в книгу", "value": "361" }, { "label": "Порка", "value": "20" }, { "label": "Порно", "value": "278" }, { "label": "Постапокалипсис", "value": "332" }, { "label": "Потеря девственности", "value": "142" }, { "label": "Похищение", "value": "161" }, { "label": "Преданные любовный интерес", "value": "407" }, { "label": "Призраки", "value": "412" }, { "label": "Приключения", "value": "134" }, { "label": "Принуждение", "value": "66" }, { "label": "Психология", "value": "238" }, { "label": "Публично", "value": "85" }, { "label": "Публичный секс", "value": "233" }, { "label": "Раб", "value": "353" }, { "label": "Рабы", "value": "308" }, { "label": "Разват", "value": "58" }, { "label": "Разврат", "value": "64" }, { "label": "Райзен", "value": "95" }, { "label": "Раса инопланетных космических лесбиянок", "value": "294" }, { "label": "Религия", "value": "403" }, { "label": "Рестленг", "value": "84" }, { "label": "Риас гремори", "value": "389" }, { "label": "Романтика", "value": "178" }, { "label": "Рыжий", "value": "90" }, { "label": "С", "value": "413" }, { "label": "Сакура", "value": "126" }, { "label": "Самолет", "value": "93" }, { "label": "Санса старк", "value": "277" }, { "label": "Санта", "value": "372" }, { "label": "Свадьба", "value": "73" }, { "label": "Сверхсила", "value": "228" }, { "label": "Сверхъестественное", "value": "319" }, { "label": "Свингеры", "value": "201" }, { "label": "Свободные отношения", "value": "186" }, { "label": "Связывание", "value": "137" }, { "label": "Сёдзе", "value": "264" }, { "label": "Секс", "value": "21" }, { "label": "Секс без проникновения", "value": "68" }, { "label": "Секс втроем", "value": "43" }, { "label": "Секс игрушки", "value": "59" }, { "label": "Секс рабыня", "value": "55" }, { "label": "Секс с монстрами", "value": "56" }, { "label": "Секс с учителем", "value": "184" }, { "label": "Секса будет много", "value": "151" }, { "label": "Сексуальное желание", "value": "209" }, { "label": "Селфцест", "value": "397" }, { "label": "Семья", "value": "5" }, { "label": "Сестра", "value": "31" }, { "label": "Сестра беременна от брата", "value": "355" }, { "label": "Сильный с самого начала", "value": "112" }, { "label": "Симбиоз", "value": "50" }, { "label": "Сирена", "value": "51" }, { "label": "Система", "value": "104" }, { "label": "Сиськи", "value": "285" }, { "label": "Сквирт", "value": "164" }, { "label": "Скрытый секс", "value": "287" }, { "label": "Служанка", "value": "215" }, { "label": "Соб", "value": "281" }, { "label": "Соблазнение", "value": "162" }, { "label": "Современность", "value": "217" }, { "label": "Соколиный Глаз", "value": "176" }, { "label": "Соперничество", "value": "216" }, { "label": "Соседи", "value": "61" }, { "label": "Соседка", "value": "312" }, { "label": "Сперма", "value": "229" }, { "label": "Сперма на лицо", "value": "199" }, { "label": "Спящие", "value": "187" }, { "label": "Старшая сестра", "value": "311" }, { "label": "Стеб", "value": "111" }, { "label": "Студенты", "value": "177" }, { "label": "Суккуб", "value": "390" }, { "label": "Супергерои", "value": "305" }, { "label": "Суперспособности", "value": "300" }, { "label": "Сын", "value": "4" }, { "label": "Твинцест", "value": "188" }, { "label": "Темное фэнтези", "value": "293" }, { "label": "Тентакли", "value": "303" }, { "label": "Тетя", "value": "113" }, { "label": "Тетя беременна от племянника", "value": "376" }, { "label": "Тетя и племянник", "value": "377" }, { "label": "Техника", "value": "302" }, { "label": "Технологии", "value": "301" }, { "label": "Тёща", "value": "270" }, { "label": "Тиран", "value": "310" }, { "label": "Трагическое прошлое", "value": "251" }, { "label": "Трансмиграция", "value": "269" }, { "label": "Трансформация", "value": "317" }, { "label": "Триллер", "value": "344" }, { "label": "Трусики", "value": "165" }, { "label": "Убийства", "value": "258" }, { "label": "Удача", "value": "299" }, { "label": "Ужасы", "value": "375" }, { "label": "Улучшение тела", "value": "288" }, { "label": "Умная главная героиня", "value": "242" }, { "label": "Умные персонажи", "value": "257" }, { "label": "Умный главный герой", "value": "354" }, { "label": "Университет", "value": "323" }, { "label": "Ученик", "value": "83" }, { "label": "Ф", "value": "149" }, { "label": "Фанатичная любовь", "value": "366" }, { "label": "Фанаты", "value": "367" }, { "label": "Фантастика", "value": "295" }, { "label": "Фанфик", "value": "40" }, { "label": "Фелляция", "value": "22" }, { "label": "Ферма", "value": "191" }, { "label": "Фетиш", "value": "60" }, { "label": "Флэш", "value": "121" }, { "label": "Футанария", "value": "150" }, { "label": "Фэнтези", "value": "359" }, { "label": "Хентай", "value": "75" }, { "label": "Хината", "value": "110" }, { "label": "Холодная главная героиня", "value": "263" }, { "label": "Черная вдова", "value": "220" }, { "label": "Черная Вдова", "value": "175" }, { "label": "Черный юмор", "value": "374" }, { "label": "Читерство", "value": "45" }, { "label": "Чтение мыслей", "value": "227" }, { "label": "Чудовища", "value": "378" }, { "label": "Шантаж", "value": "129" }, { "label": "Школа", "value": "118" }, { "label": "Школьная жизнь", "value": "318" }, { "label": "Шлюха", "value": "32" }, { "label": "Шоу-бизнес", "value": "329" }, { "label": "Шоу-бизнес", "value": "172" }, { "label": "Эксгибиционизм", "value": "74" }, { "label": "Элементы бдсм", "value": "185" }, { "label": "Эмма уотсон", "value": "342" }, { "label": "Эмма Уотсон", "value": "169" }, { "label": "Эротика", "value": "36" }, { "label": "Этти", "value": "327" }, { "label": "Юмор", "value": "105" }, { "label": "Яндере", "value": "155" }, { "label": "Bl", "value": "125" }, { "label": "Dc", "value": "411" }, { "label": "Gl", "value": "96" }, { "label": "Harry potter", "value": "190" }, { "label": "Harry potter", "value": "168" }, { "label": "Hentai", "value": "282" }, { "label": "Marvel", "value": "194" }, { "label": "Marvel", "value": "174" }, { "label": "Milf", "value": "167" }, { "label": "Mj", "value": "401" }], "inputType": filterInputs_1.FilterInputs.Checkbox }, { "key": "fandoms", "label": "Фэндом:", "values": [{ "label": "Аватар: Легенда о Корре / Avatar legend of Korra", "value": "46" }, { "label": "Аватар: Легенда об Аанге / Avatar: The Legend of Aang / Avatar: The Last Airbender", "value": "45" }, { "label": "Аладдин / Aladdin", "value": "86" }, { "label": "Алиса в Стране чудес / Alice in Wonderland", "value": "90" }, { "label": "Американский папаша / American Dad", "value": "85" }, { "label": "Атака титанов / Атака на титанов / Attack on Titan", "value": "41" }, { "label": "Блич / Bleach", "value": "58" }, { "label": "Боевой континент", "value": "101" }, { "label": "Большой куш / One Piece", "value": "18" }, { "label": "Боруто: Новое поколение Наруто / Boruto: Naruto Next Generations", "value": "9" }, { "label": "Бэтмен / The Batman", "value": "36" }, { "label": "Ведьмак / The Witcher", "value": "53" }, { "label": "Военная хроника маленькой девочки", "value": "100" }, { "label": "Волейбол / Haikyu!!", "value": "37" }, { "label": "Вселенная Марвел / Marvel Universe", "value": "7" }, { "label": "Вселенная Марвел / Marvel Universe / Marvel Comics", "value": "52" }, { "label": "Вселенная Стивена", "value": "61" }, { "label": "Вселенная DC / DC Universe / DC Comics", "value": "48" }, { "label": "Гарри Поттер / Harry Potter", "value": "4" }, { "label": "Гоэтия / Гоетия / Yοητεία / Ars Goetia", "value": "77" }, { "label": "Демоны старшей школы / High School DxD", "value": "10" }, { "label": "День сурка / Groundhog Day", "value": "3" }, { "label": "Джессика Джонс / Marvel's Jessica Jones", "value": "42" }, { "label": "Дисней / The Walt Disney Company", "value": "74" }, { "label": "Древние свитки: Скайрим / TES: Skyrim", "value": "15" }, { "label": "Дэдпул / Deadpool", "value": "22" }, { "label": "Дэнни-призрак / Danny Phantom", "value": "51" }, { "label": "Железный человек / Iron Man", "value": "19" }, { "label": "Звёздная принцесса и силы зла / Стар против сил зла / Star vs. The Forces of Evil", "value": "50" }, { "label": "Звездные Войны / Star Wars", "value": "43" }, { "label": "Звёздные Войны / Star Wars", "value": "16" }, { "label": "Игра престолов", "value": "78" }, { "label": "Касльвания / Castlevania", "value": "29" }, { "label": "Киберпанк 2077 / Cyberpunk 2077", "value": "6" }, { "label": "Код Гиас / Code Geass", "value": "84" }, { "label": "Кольцо Элдена", "value": "60" }, { "label": "Королевства Сердец / Kingdom Hearts", "value": "93" }, { "label": "Красавица и чудовище / Beauty and the Beast", "value": "91" }, { "label": "Красный, Белый, Черный, Желтый / RWBY", "value": "32" }, { "label": "Кунг фу панда", "value": "81" }, { "label": "Лига Легенд / League of Legends", "value": "5" }, { "label": "Люди Икс / X-Men", "value": "25" }, { "label": "Маг на полную ставку / Quanzhi Fashi", "value": "30" }, { "label": "Мастера меча онлайн / Sword Art Online / SAO", "value": "47" }, { "label": "Мир Тьмы / World of Darkness", "value": "28" }, { "label": "Мой маленький пони / My Little Pony", "value": "72" }, { "label": "Мой маленький пони: Дружба — это чудо / My Little Pony: Friendship is Magic", "value": "71" }, { "label": "Моя геройская академия / Boku no Hero Academia", "value": "8" }, { "label": "Мстители / The Avengers", "value": "20" }, { "label": "Мстители. Эра Альтрона / The Avengers. Age of Ultron", "value": "24" }, { "label": "Мулан / Mulan", "value": "94" }, { "label": "Наруто / Naruto", "value": "2" }, { "label": "Овервотч", "value": "79" }, { "label": "Поднятие уровня в одиночку", "value": "87" }, { "label": "Порновселенная / Porn Universe", "value": "31" }, { "label": "Прототип / Prototype", "value": "44" }, { "label": "Рапунцель: Запутанная история / Tangled", "value": "96" }, { "label": "Розовая пора моей школьной жизни сплошной обман / Yahari Ore no Seishun Love Come wa Machigatteiru", "value": "14" }, { "label": "Русалочка / The Little Mermaid", "value": "97" }, { "label": "Сага о Винланде", "value": "66" }, { "label": "Светлячок / Firefly", "value": "76" }, { "label": "Сильнейший в истории ученик Кэнити / Shijou Saikyou no Deshi Kenichi", "value": "13" }, { "label": "Симпсоны / The Simpsons", "value": "73" }, { "label": "Судьба: Великий Приказ / Fate: Grand Order", "value": "54" }, { "label": "Супергёрл(телесериал, 2015) / Supergirl", "value": "95" }, { "label": "Супермен / Superman", "value": "1" }, { "label": "Теория большого взрыва / The Big Bang Theory", "value": "75" }, { "label": "Тор / Thor", "value": "27" }, { "label": "У Коми-сан проблемы с общением / 古見さんは、コミュ症です / Komi Can't Communicate", "value": "11" }, { "label": "Убийца Акаме / Akame ga Kill", "value": "40" }, { "label": "Уэнздей / Wednesday", "value": "26" }, { "label": "Фантастическая четвёрка / Fantastic Four", "value": "21" }, { "label": "Флэш / The Flash", "value": "17" }, { "label": "Хвост Феи / Fairy Tail", "value": "59" }, { "label": "Холодное сердце / Frozen", "value": "92" }, { "label": "Человек одного удара / Ванпанчмен / One Punch-Man", "value": "39" }, { "label": "Человек-паук / Spider-Man", "value": "23" }, { "label": "Чёрный зверь / Чёрный Пёс / Kuroinu", "value": "35" }, { "label": "Чёрный зверь: Развращение Благородных Воительниц / Black Beast: Corruption of the Noble Warriors", "value": "34" }, { "label": "Школа мертвецов", "value": "67" }, { "label": "Школа строгого режима / Prison School", "value": "12" }, { "label": "Эффект Массы / Mass Effect", "value": "57" }, { "label": "Юные Титаны / Teen Titans", "value": "49" }, { "label": "Ars Goetia | Gods and Demons", "value": "69" }, { "label": "Biohazard", "value": "99" }, { "label": "CL", "value": "70" }, { "label": "Daraku Reijou Hakoiri Ojou-sama Netorare Choukyou Kiroku", "value": "55" }, { "label": "Doom", "value": "64" }, { "label": "Granblue fantasy", "value": "88" }, { "label": "Halo", "value": "80" }, { "label": "Highschool of the Dead/Школа мертвецов", "value": "68" }, { "label": "JK Bitch ni Shiboraretai", "value": "56" }, { "label": "Monogatari Series", "value": "65" }, { "label": "Monster girl quest", "value": "62" }, { "label": "Over", "value": "102" }, { "label": "Rapunzel/Рапунцель", "value": "83" }, { "label": "Resident Evil", "value": "98" }, { "label": "Solo leveling", "value": "63" }, { "label": "Tentacle Locker", "value": "89" }, { "label": "X-COM", "value": "82" }], "inputType": filterInputs_1.FilterInputs.Checkbox }, { "key": "genres_ex", "label": "Исключить жанры:", "values": [{ "label": "Анал", "value": "2" }, { "label": "Бдсм", "value": "3" }, { "label": "Большая грудь", "value": "5" }, { "label": "Большая попка", "value": "6" }, { "label": "Большой член", "value": "7" }, { "label": "Бондаж", "value": "8" }, { "label": "В первый раз", "value": "9" }, { "label": "В цвете", "value": "10" }, { "label": "Гарем", "value": "11" }, { "label": "Гендарная интрига", "value": "12" }, { "label": "Групповой секс", "value": "13" }, { "label": "Детектив", "value": "39" }, { "label": "Драма", "value": "14" }, { "label": "Зрелые женщины (milf)", "value": "15" }, { "label": "Измена", "value": "16" }, { "label": "Изнасилование", "value": "17" }, { "label": "Инцест", "value": "18" }, { "label": "Исторический", "value": "19" }, { "label": "Комедия", "value": "20" }, { "label": "Контроль над разумом", "value": "35" }, { "label": "Маленькая грудь", "value": "21" }, { "label": "Мистика", "value": "40" }, { "label": "Научная фантастика", "value": "22" }, { "label": "Нетораре", "value": "23" }, { "label": "Оральный секс", "value": "24" }, { "label": "Повседневность", "value": "41" }, { "label": "Приключения", "value": "38" }, { "label": "Публичный секс", "value": "33" }, { "label": "Романтика", "value": "25" }, { "label": "С изображениями", "value": "36" }, { "label": "Сверхъестественное", "value": "34" }, { "label": "Смат", "value": "37" }, { "label": "Тентакли", "value": "26" }, { "label": "Трагедия", "value": "27" }, { "label": "Ужасы", "value": "28" }, { "label": "Фантастика", "value": "32" }, { "label": "Фэнтези", "value": "29" }, { "label": "Чикан", "value": "30" }, { "label": "Этти", "value": "31" }, { "label": "Ahegao", "value": "1" }], "inputType": filterInputs_1.FilterInputs.Checkbox }, { "key": "tags_ex", "label": "Исключить тэги:", "values": [{ "label": "+18", "value": "141" }, { "label": "18+", "value": "200" }, { "label": "21+", "value": "334" }, { "label": "Адекватные главные герои", "value": "253" }, { "label": "Азартные игры", "value": "210" }, { "label": "Айдолы", "value": "364" }, { "label": "Акула", "value": "53" }, { "label": "Альтернативное развитие событий", "value": "338" }, { "label": "Аморальный главный герой", "value": "219" }, { "label": "Анал", "value": "7" }, { "label": "Анальный секс", "value": "67" }, { "label": "Ангелы", "value": "114" }, { "label": "Антигерой", "value": "226" }, { "label": "Аристократия", "value": "260" }, { "label": "Артефакт", "value": "379" }, { "label": "Афродизиак", "value": "276" }, { "label": "Ахегао", "value": "240" }, { "label": "Бабушка беременна от внука", "value": "393" }, { "label": "Бабушка и внук", "value": "380" }, { "label": "Бдсм", "value": "131" }, { "label": "Беременность", "value": "148" }, { "label": "Бесплатно", "value": "79" }, { "label": "Бесстрашные персонажи", "value": "339" }, { "label": "Библиотека", "value": "265" }, { "label": "Бистиалити", "value": "391" }, { "label": "Битва за трон", "value": "404" }, { "label": "Близнецы", "value": "198" }, { "label": "Блондинка", "value": "91" }, { "label": "Богатые персонажи", "value": "248" }, { "label": "Боги", "value": "115" }, { "label": "Боевик", "value": "252" }, { "label": "Большая грудь", "value": "33" }, { "label": "Большая попка", "value": "328" }, { "label": "Большой член", "value": "76" }, { "label": "Большой член сына", "value": "396" }, { "label": "Босс и подчиненный", "value": "330" }, { "label": "Брак", "value": "182" }, { "label": "Брак по расчёту", "value": "346" }, { "label": "Брат", "value": "29" }, { "label": "Брат и сестра", "value": "30" }, { "label": "Брюнетка", "value": "28" }, { "label": "Бэтмен", "value": "369" }, { "label": "Бэтмен", "value": "170" }, { "label": "В первый раз", "value": "179" }, { "label": "Вагинальный секс", "value": "57" }, { "label": "Вагинальный секс", "value": "171" }, { "label": "Вайурист", "value": "9" }, { "label": "Вампиры", "value": "133" }, { "label": "Ван-пис", "value": "335" }, { "label": "Веб камера", "value": "289" }, { "label": "Ведьмы", "value": "232" }, { "label": "Викинги", "value": "307" }, { "label": "Виртуальная реальность", "value": "382" }, { "label": "Вирус", "value": "203" }, { "label": "Внучка", "value": "189" }, { "label": "Война", "value": "387" }, { "label": "Воспоминания из прошлого", "value": "405" }, { "label": "Враги становятся любовниками", "value": "410" }, { "label": "Время", "value": "81" }, { "label": "Второй шанс", "value": "244" }, { "label": "Вуайеризм", "value": "62" }, { "label": "Выживание", "value": "135" }, { "label": "Гарем", "value": "107" }, { "label": "Гарри поттер", "value": "97" }, { "label": "Гвен", "value": "402" }, { "label": "Гг имба", "value": "87" }, { "label": "Генетические модификации", "value": "314" }, { "label": "Гипноз", "value": "143" }, { "label": "Главная героиня девушка", "value": "147" }, { "label": "Главный герой женщина", "value": "213" }, { "label": "Главный герой извращенец", "value": "116" }, { "label": "Главный герой мужчина", "value": "117" }, { "label": "Глубокое горло", "value": "94" }, { "label": "Гоблины", "value": "230" }, { "label": "Город", "value": "139" }, { "label": "Городское фэнтези", "value": "297" }, { "label": "Грудное молоко", "value": "225" }, { "label": "Групповой секс", "value": "72" }, { "label": "Гэнг-бэнг", "value": "235" }, { "label": "Гяру", "value": "222" }, { "label": "Двойное проникновение", "value": "42" }, { "label": "Двойной анал", "value": "47" }, { "label": "Дворяне", "value": "246" }, { "label": "Деамоны старший школы", "value": "291" }, { "label": "Девственница", "value": "119" }, { "label": "Девушки-монстры", "value": "223" }, { "label": "Демоны", "value": "98" }, { "label": "Детектив", "value": "249" }, { "label": "Дзёсэй", "value": "259" }, { "label": "Доктор", "value": "326" }, { "label": "Дом", "value": "138" }, { "label": "Доминирование", "value": "18" }, { "label": "Дочь", "value": "153" }, { "label": "Дочь беременна от отца", "value": "348" }, { "label": "Древние времена", "value": "383" }, { "label": "Древний китай", "value": "261" }, { "label": "Другой мир", "value": "365" }, { "label": "Дружба", "value": "325" }, { "label": "Друзья детства", "value": "183" }, { "label": "Дядя", "value": "160" }, { "label": "Жена", "value": "70" }, { "label": "Жена и муж", "value": "99" }, { "label": "Жена шлюха", "value": "236" }, { "label": "Женское доминирование", "value": "100" }, { "label": "Жесткий секс", "value": "283" }, { "label": "Жёсткий секс", "value": "101" }, { "label": "Жестокие персонажи", "value": "254" }, { "label": "Жестокий мир", "value": "336" }, { "label": "Жестокость", "value": "123" }, { "label": "Заботливый главный герой", "value": "340" }, { "label": "Зависимость", "value": "370" }, { "label": "Заключение", "value": "196" }, { "label": "Заключённые", "value": "384" }, { "label": "Замок", "value": "140" }, { "label": "Запретная любовь", "value": "273" }, { "label": "Заражение", "value": "206" }, { "label": "Звёздные войны", "value": "120" }, { "label": "Зверодевочки", "value": "158" }, { "label": "Зло", "value": "343" }, { "label": "Золовка", "value": "77" }, { "label": "Золотой дождь", "value": "146" }, { "label": "Зомби апокалипсис", "value": "241" }, { "label": "Зоофилия", "value": "144" }, { "label": "Зрелые женщины", "value": "398" }, { "label": "Игровые элементы", "value": "385" }, { "label": "Извращения", "value": "192" }, { "label": "Измена", "value": "71" }, { "label": "Изменения внешности", "value": "315" }, { "label": "Изменения личности", "value": "316" }, { "label": "Изнасилование", "value": "275" }, { "label": "Изуку мидория", "value": "337" }, { "label": "Ино", "value": "127" }, { "label": "Инопланетяне", "value": "304" }, { "label": "Интересный сюжет", "value": "349" }, { "label": "Интимные сцены", "value": "322" }, { "label": "Интриги и заговоры", "value": "262" }, { "label": "Интроверт", "value": "38" }, { "label": "Инфекция", "value": "207" }, { "label": "Инцест", "value": "35" }, { "label": "Исторический роман", "value": "406" }, { "label": "Камера", "value": "92" }, { "label": "Колледж", "value": "82" }, { "label": "Комикс", "value": "286" }, { "label": "Контроль", "value": "19" }, { "label": "Контроль над разумом", "value": "181" }, { "label": "Контроль разума", "value": "65" }, { "label": "Кончил внутрь", "value": "221" }, { "label": "Королевская семья", "value": "358" }, { "label": "Коррупция", "value": "49" }, { "label": "Космос", "value": "204" }, { "label": "Красивая главная героиня", "value": "255" }, { "label": "Красивые женщины", "value": "321" }, { "label": "Красивый главный герой", "value": "266" }, { "label": "Ксенофилия", "value": "386" }, { "label": "Кулинария", "value": "362" }, { "label": "Культвация", "value": "86" }, { "label": "Кунилингус", "value": "152" }, { "label": "Кушина", "value": "399" }, { "label": "Лактация", "value": "11" }, { "label": "Лесби", "value": "408" }, { "label": "Лишение девственности", "value": "212" }, { "label": "Лоли", "value": "218" }, { "label": "Лунатизм", "value": "279" }, { "label": "Любовь", "value": "89" }, { "label": "Магический мир", "value": "357" }, { "label": "Магия", "value": "80" }, { "label": "Мама", "value": "3" }, { "label": "Мама беременна от сына", "value": "274" }, { "label": "Мама и дочь", "value": "163" }, { "label": "Мама и сын", "value": "1" }, { "label": "Мама супермена", "value": "39" }, { "label": "Манипуляция временем", "value": "292" }, { "label": "Марвел", "value": "290" }, { "label": "Марвел", "value": "173" }, { "label": "Марти стью", "value": "102" }, { "label": "Массаж", "value": "224" }, { "label": "Мастурбация", "value": "63" }, { "label": "Мать", "value": "239" }, { "label": "Мать и дочь", "value": "381" }, { "label": "Мать и сын", "value": "237" }, { "label": "Мафия", "value": "256" }, { "label": "Мачеха", "value": "197" }, { "label": "Мачеха беременна от сына", "value": "395" }, { "label": "Мачеха и сын", "value": "394" }, { "label": "Медсестра", "value": "341" }, { "label": "Межрассовый", "value": "54" }, { "label": "Месть", "value": "306" }, { "label": "Меха", "value": "268" }, { "label": "Ми", "value": "243" }, { "label": "Милф", "value": "34" }, { "label": "Милф", "value": "180" }, { "label": "Минет", "value": "52" }, { "label": "Мистика", "value": "250" }, { "label": "Младшая сестра", "value": "154" }, { "label": "Много спермы", "value": "409" }, { "label": "Модель", "value": "324" }, { "label": "Монстры", "value": "333" }, { "label": "Мошеничество", "value": "44" }, { "label": "Мужская беременность", "value": "363" }, { "label": "Мужчина протагонист", "value": "108" }, { "label": "Музыка", "value": "331" }, { "label": "Мэри съюха", "value": "309" }, { "label": "Наруко", "value": "400" }, { "label": "Наруто", "value": "46" }, { "label": "Насилие", "value": "128" }, { "label": "Насилие и жестокость", "value": "193" }, { "label": "Научный эксперимент", "value": "313" }, { "label": "Нежить", "value": "373" }, { "label": "Некромантия", "value": "298" }, { "label": "Ненормативная лексика", "value": "124" }, { "label": "Нетораре", "value": "69" }, { "label": "Нетори", "value": "284" }, { "label": "Нижнее бельё", "value": "392" }, { "label": "Ниндзя", "value": "296" }, { "label": "Ношеные трусики", "value": "166" }, { "label": "Нудизм", "value": "156" }, { "label": "Няня", "value": "88" }, { "label": "Обмен женами", "value": "78" }, { "label": "Оборотни", "value": "136" }, { "label": "Обратный гарем", "value": "214" }, { "label": "Одержимость", "value": "345" }, { "label": "Омегаверс", "value": "368" }, { "label": "Оплодотворение", "value": "157" }, { "label": "Оральный секс", "value": "10" }, { "label": "Оргия", "value": "356" }, { "label": "Орки", "value": "388" }, { "label": "От слабого к сильному", "value": "351" }, { "label": "Отец", "value": "2" }, { "label": "Отец делится с сыном", "value": "6" }, { "label": "Отец и дочь", "value": "205" }, { "label": "Отец куколд", "value": "272" }, { "label": "Офис", "value": "234" }, { "label": "Падчерица", "value": "271" }, { "label": "Пайзури", "value": "195" }, { "label": "Папа и дочь", "value": "360" }, { "label": "Паразиты", "value": "208" }, { "label": "Параллельный мир", "value": "320" }, { "label": "Пародия", "value": "371" }, { "label": "Первый раз", "value": "159" }, { "label": "Перемещение в другой мир", "value": "347" }, { "label": "Перемещение во времени", "value": "245" }, { "label": "Перерождение", "value": "109" }, { "label": "Перерождение в злодея", "value": "202" }, { "label": "Пирсинг", "value": "145" }, { "label": "Писатель", "value": "267" }, { "label": "Планомерное развитие событий", "value": "350" }, { "label": "Повседневность", "value": "247" }, { "label": "Подглядывание", "value": "280" }, { "label": "Подчинение", "value": "106" }, { "label": "Подчинение и унижение", "value": "211" }, { "label": "Поедание киски", "value": "26" }, { "label": "Покемоны", "value": "132" }, { "label": "Покорная", "value": "8" }, { "label": "Полигамия", "value": "352" }, { "label": "Половое воспитание", "value": "37" }, { "label": "Полулюди", "value": "231" }, { "label": "Попаданец", "value": "103" }, { "label": "Попадание в книгу", "value": "361" }, { "label": "Порка", "value": "20" }, { "label": "Порно", "value": "278" }, { "label": "Постапокалипсис", "value": "332" }, { "label": "Потеря девственности", "value": "142" }, { "label": "Похищение", "value": "161" }, { "label": "Преданные любовный интерес", "value": "407" }, { "label": "Призраки", "value": "412" }, { "label": "Приключения", "value": "134" }, { "label": "Принуждение", "value": "66" }, { "label": "Психология", "value": "238" }, { "label": "Публично", "value": "85" }, { "label": "Публичный секс", "value": "233" }, { "label": "Раб", "value": "353" }, { "label": "Рабы", "value": "308" }, { "label": "Разват", "value": "58" }, { "label": "Разврат", "value": "64" }, { "label": "Райзен", "value": "95" }, { "label": "Раса инопланетных космических лесбиянок", "value": "294" }, { "label": "Религия", "value": "403" }, { "label": "Рестленг", "value": "84" }, { "label": "Риас гремори", "value": "389" }, { "label": "Романтика", "value": "178" }, { "label": "Рыжий", "value": "90" }, { "label": "С", "value": "413" }, { "label": "Сакура", "value": "126" }, { "label": "Самолет", "value": "93" }, { "label": "Санса старк", "value": "277" }, { "label": "Санта", "value": "372" }, { "label": "Свадьба", "value": "73" }, { "label": "Сверхсила", "value": "228" }, { "label": "Сверхъестественное", "value": "319" }, { "label": "Свингеры", "value": "201" }, { "label": "Свободные отношения", "value": "186" }, { "label": "Связывание", "value": "137" }, { "label": "Сёдзе", "value": "264" }, { "label": "Секс", "value": "21" }, { "label": "Секс без проникновения", "value": "68" }, { "label": "Секс втроем", "value": "43" }, { "label": "Секс игрушки", "value": "59" }, { "label": "Секс рабыня", "value": "55" }, { "label": "Секс с монстрами", "value": "56" }, { "label": "Секс с учителем", "value": "184" }, { "label": "Секса будет много", "value": "151" }, { "label": "Сексуальное желание", "value": "209" }, { "label": "Селфцест", "value": "397" }, { "label": "Семья", "value": "5" }, { "label": "Сестра", "value": "31" }, { "label": "Сестра беременна от брата", "value": "355" }, { "label": "Сильный с самого начала", "value": "112" }, { "label": "Симбиоз", "value": "50" }, { "label": "Сирена", "value": "51" }, { "label": "Система", "value": "104" }, { "label": "Сиськи", "value": "285" }, { "label": "Сквирт", "value": "164" }, { "label": "Скрытый секс", "value": "287" }, { "label": "Служанка", "value": "215" }, { "label": "Соб", "value": "281" }, { "label": "Соблазнение", "value": "162" }, { "label": "Современность", "value": "217" }, { "label": "Соколиный Глаз", "value": "176" }, { "label": "Соперничество", "value": "216" }, { "label": "Соседи", "value": "61" }, { "label": "Соседка", "value": "312" }, { "label": "Сперма", "value": "229" }, { "label": "Сперма на лицо", "value": "199" }, { "label": "Спящие", "value": "187" }, { "label": "Старшая сестра", "value": "311" }, { "label": "Стеб", "value": "111" }, { "label": "Студенты", "value": "177" }, { "label": "Суккуб", "value": "390" }, { "label": "Супергерои", "value": "305" }, { "label": "Суперспособности", "value": "300" }, { "label": "Сын", "value": "4" }, { "label": "Твинцест", "value": "188" }, { "label": "Темное фэнтези", "value": "293" }, { "label": "Тентакли", "value": "303" }, { "label": "Тетя", "value": "113" }, { "label": "Тетя беременна от племянника", "value": "376" }, { "label": "Тетя и племянник", "value": "377" }, { "label": "Техника", "value": "302" }, { "label": "Технологии", "value": "301" }, { "label": "Тёща", "value": "270" }, { "label": "Тиран", "value": "310" }, { "label": "Трагическое прошлое", "value": "251" }, { "label": "Трансмиграция", "value": "269" }, { "label": "Трансформация", "value": "317" }, { "label": "Триллер", "value": "344" }, { "label": "Трусики", "value": "165" }, { "label": "Убийства", "value": "258" }, { "label": "Удача", "value": "299" }, { "label": "Ужасы", "value": "375" }, { "label": "Улучшение тела", "value": "288" }, { "label": "Умная главная героиня", "value": "242" }, { "label": "Умные персонажи", "value": "257" }, { "label": "Умный главный герой", "value": "354" }, { "label": "Университет", "value": "323" }, { "label": "Ученик", "value": "83" }, { "label": "Ф", "value": "149" }, { "label": "Фанатичная любовь", "value": "366" }, { "label": "Фанаты", "value": "367" }, { "label": "Фантастика", "value": "295" }, { "label": "Фанфик", "value": "40" }, { "label": "Фелляция", "value": "22" }, { "label": "Ферма", "value": "191" }, { "label": "Фетиш", "value": "60" }, { "label": "Флэш", "value": "121" }, { "label": "Футанария", "value": "150" }, { "label": "Фэнтези", "value": "359" }, { "label": "Хентай", "value": "75" }, { "label": "Хината", "value": "110" }, { "label": "Холодная главная героиня", "value": "263" }, { "label": "Черная вдова", "value": "220" }, { "label": "Черная Вдова", "value": "175" }, { "label": "Черный юмор", "value": "374" }, { "label": "Читерство", "value": "45" }, { "label": "Чтение мыслей", "value": "227" }, { "label": "Чудовища", "value": "378" }, { "label": "Шантаж", "value": "129" }, { "label": "Школа", "value": "118" }, { "label": "Школьная жизнь", "value": "318" }, { "label": "Шлюха", "value": "32" }, { "label": "Шоу-бизнес", "value": "329" }, { "label": "Шоу-бизнес", "value": "172" }, { "label": "Эксгибиционизм", "value": "74" }, { "label": "Элементы бдсм", "value": "185" }, { "label": "Эмма уотсон", "value": "342" }, { "label": "Эмма Уотсон", "value": "169" }, { "label": "Эротика", "value": "36" }, { "label": "Этти", "value": "327" }, { "label": "Юмор", "value": "105" }, { "label": "Яндере", "value": "155" }, { "label": "Bl", "value": "125" }, { "label": "Dc", "value": "411" }, { "label": "Gl", "value": "96" }, { "label": "Harry potter", "value": "190" }, { "label": "Harry potter", "value": "168" }, { "label": "Hentai", "value": "282" }, { "label": "Marvel", "value": "194" }, { "label": "Marvel", "value": "174" }, { "label": "Milf", "value": "167" }, { "label": "Mj", "value": "401" }], "inputType": filterInputs_1.FilterInputs.Checkbox }, { "key": "fandoms_ex", "label": "Исключить фэндомы:", "values": [{ "label": "Аватар: Легенда о Корре / Avatar legend of Korra", "value": "46" }, { "label": "Аватар: Легенда об Аанге / Avatar: The Legend of Aang / Avatar: The Last Airbender", "value": "45" }, { "label": "Аладдин / Aladdin", "value": "86" }, { "label": "Алиса в Стране чудес / Alice in Wonderland", "value": "90" }, { "label": "Американский папаша / American Dad", "value": "85" }, { "label": "Атака титанов / Атака на титанов / Attack on Titan", "value": "41" }, { "label": "Блич / Bleach", "value": "58" }, { "label": "Боевой континент", "value": "101" }, { "label": "Большой куш / One Piece", "value": "18" }, { "label": "Боруто: Новое поколение Наруто / Boruto: Naruto Next Generations", "value": "9" }, { "label": "Бэтмен / The Batman", "value": "36" }, { "label": "Ведьмак / The Witcher", "value": "53" }, { "label": "Военная хроника маленькой девочки", "value": "100" }, { "label": "Волейбол / Haikyu!!", "value": "37" }, { "label": "Вселенная Марвел / Marvel Universe", "value": "7" }, { "label": "Вселенная Марвел / Marvel Universe / Marvel Comics", "value": "52" }, { "label": "Вселенная Стивена", "value": "61" }, { "label": "Вселенная DC / DC Universe / DC Comics", "value": "48" }, { "label": "Гарри Поттер / Harry Potter", "value": "4" }, { "label": "Гоэтия / Гоетия / Yοητεία / Ars Goetia", "value": "77" }, { "label": "Демоны старшей школы / High School DxD", "value": "10" }, { "label": "День сурка / Groundhog Day", "value": "3" }, { "label": "Джессика Джонс / Marvel's Jessica Jones", "value": "42" }, { "label": "Дисней / The Walt Disney Company", "value": "74" }, { "label": "Древние свитки: Скайрим / TES: Skyrim", "value": "15" }, { "label": "Дэдпул / Deadpool", "value": "22" }, { "label": "Дэнни-призрак / Danny Phantom", "value": "51" }, { "label": "Железный человек / Iron Man", "value": "19" }, { "label": "Звёздная принцесса и силы зла / Стар против сил зла / Star vs. The Forces of Evil", "value": "50" }, { "label": "Звездные Войны / Star Wars", "value": "43" }, { "label": "Звёздные Войны / Star Wars", "value": "16" }, { "label": "Игра престолов", "value": "78" }, { "label": "Касльвания / Castlevania", "value": "29" }, { "label": "Киберпанк 2077 / Cyberpunk 2077", "value": "6" }, { "label": "Код Гиас / Code Geass", "value": "84" }, { "label": "Кольцо Элдена", "value": "60" }, { "label": "Королевства Сердец / Kingdom Hearts", "value": "93" }, { "label": "Красавица и чудовище / Beauty and the Beast", "value": "91" }, { "label": "Красный, Белый, Черный, Желтый / RWBY", "value": "32" }, { "label": "Кунг фу панда", "value": "81" }, { "label": "Лига Легенд / League of Legends", "value": "5" }, { "label": "Люди Икс / X-Men", "value": "25" }, { "label": "Маг на полную ставку / Quanzhi Fashi", "value": "30" }, { "label": "Мастера меча онлайн / Sword Art Online / SAO", "value": "47" }, { "label": "Мир Тьмы / World of Darkness", "value": "28" }, { "label": "Мой маленький пони / My Little Pony", "value": "72" }, { "label": "Мой маленький пони: Дружба — это чудо / My Little Pony: Friendship is Magic", "value": "71" }, { "label": "Моя геройская академия / Boku no Hero Academia", "value": "8" }, { "label": "Мстители / The Avengers", "value": "20" }, { "label": "Мстители. Эра Альтрона / The Avengers. Age of Ultron", "value": "24" }, { "label": "Мулан / Mulan", "value": "94" }, { "label": "Наруто / Naruto", "value": "2" }, { "label": "Овервотч", "value": "79" }, { "label": "Поднятие уровня в одиночку", "value": "87" }, { "label": "Порновселенная / Porn Universe", "value": "31" }, { "label": "Прототип / Prototype", "value": "44" }, { "label": "Рапунцель: Запутанная история / Tangled", "value": "96" }, { "label": "Розовая пора моей школьной жизни сплошной обман / Yahari Ore no Seishun Love Come wa Machigatteiru", "value": "14" }, { "label": "Русалочка / The Little Mermaid", "value": "97" }, { "label": "Сага о Винланде", "value": "66" }, { "label": "Светлячок / Firefly", "value": "76" }, { "label": "Сильнейший в истории ученик Кэнити / Shijou Saikyou no Deshi Kenichi", "value": "13" }, { "label": "Симпсоны / The Simpsons", "value": "73" }, { "label": "Судьба: Великий Приказ / Fate: Grand Order", "value": "54" }, { "label": "Супергёрл(телесериал, 2015) / Supergirl", "value": "95" }, { "label": "Супермен / Superman", "value": "1" }, { "label": "Теория большого взрыва / The Big Bang Theory", "value": "75" }, { "label": "Тор / Thor", "value": "27" }, { "label": "У Коми-сан проблемы с общением / 古見さんは、コミュ症です / Komi Can't Communicate", "value": "11" }, { "label": "Убийца Акаме / Akame ga Kill", "value": "40" }, { "label": "Уэнздей / Wednesday", "value": "26" }, { "label": "Фантастическая четвёрка / Fantastic Four", "value": "21" }, { "label": "Флэш / The Flash", "value": "17" }, { "label": "Хвост Феи / Fairy Tail", "value": "59" }, { "label": "Холодное сердце / Frozen", "value": "92" }, { "label": "Человек одного удара / Ванпанчмен / One Punch-Man", "value": "39" }, { "label": "Человек-паук / Spider-Man", "value": "23" }, { "label": "Чёрный зверь / Чёрный Пёс / Kuroinu", "value": "35" }, { "label": "Чёрный зверь: Развращение Благородных Воительниц / Black Beast: Corruption of the Noble Warriors", "value": "34" }, { "label": "Школа мертвецов", "value": "67" }, { "label": "Школа строгого режима / Prison School", "value": "12" }, { "label": "Эффект Массы / Mass Effect", "value": "57" }, { "label": "Юные Титаны / Teen Titans", "value": "49" }, { "label": "Ars Goetia | Gods and Demons", "value": "69" }, { "label": "Biohazard", "value": "99" }, { "label": "CL", "value": "70" }, { "label": "Daraku Reijou Hakoiri Ojou-sama Netorare Choukyou Kiroku", "value": "55" }, { "label": "Doom", "value": "64" }, { "label": "Granblue fantasy", "value": "88" }, { "label": "Halo", "value": "80" }, { "label": "Highschool of the Dead/Школа мертвецов", "value": "68" }, { "label": "JK Bitch ni Shiboraretai", "value": "56" }, { "label": "Monogatari Series", "value": "65" }, { "label": "Monster girl quest", "value": "62" }, { "label": "Over", "value": "102" }, { "label": "Rapunzel/Рапунцель", "value": "83" }, { "label": "Resident Evil", "value": "98" }, { "label": "Solo leveling", "value": "63" }, { "label": "Tentacle Locker", "value": "89" }, { "label": "X-COM", "value": "82" }], "inputType": filterInputs_1.FilterInputs.Checkbox }, { "key": "atmosphere", "label": "Атмосфера:", "values": [{ "label": "Неважно", "value": "0" }, { "label": "Позитивная", "value": "1" }, { "label": "Dark", "value": "2" }], "inputType": filterInputs_1.FilterInputs.Picker }, { "key": "adult", "label": "Возрастные ограничения:", "values": [{ "label": "Все", "value": "0" }, { "label": "Только 18+", "value": "2" }, { "label": "Убрать 18+", "value": "1" }], "inputType": filterInputs_1.FilterInputs.Picker }];
diff --git a/js/plugins/russian/LitSpace.js b/js/plugins/russian/LitSpace.js
deleted file mode 100644
index 0f0d226..0000000
--- a/js/plugins/russian/LitSpace.js
+++ /dev/null
@@ -1,232 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.fetchImage = exports.filters = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.icon = exports.version = exports.site = exports.name = exports.id = void 0;
-const filterInputs_1 = require("@libs/filterInputs");
-const fetch_1 = require("@libs/fetch");
-const cheerio_1 = require("cheerio");
-exports.id = "freedlit.space";
-exports.name = "LitSpace";
-exports.site = "https://freedlit.space";
-exports.version = "1.0.0";
-exports.icon = "src/ru/freedlit/icon.png";
-const popularNovels = function (page, { showLatestNovels, filters }) {
- return __awaiter(this, void 0, void 0, function* () {
- let url = exports.site + "/books/";
- url += ((filters === null || filters === void 0 ? void 0 : filters.genre) || "all") + "?sort=";
- url += showLatestNovels ? "recent" : (filters === null || filters === void 0 ? void 0 : filters.sort) || "popular";
- url += "&status=" + ((filters === null || filters === void 0 ? void 0 : filters.status) || "all");
- url += "&access=" + ((filters === null || filters === void 0 ? void 0 : filters.access) || "all");
- url += "&adult=" + ((filters === null || filters === void 0 ? void 0 : filters.adult) || "hide");
- url += "&page=" + page;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio("#bookListBlock > div > div").each(function () {
- var _a, _b, _c;
- const name = (_a = loadedCheerio(this).find("div > h4 > a").text()) === null || _a === void 0 ? void 0 : _a.trim();
- const cover = (_b = loadedCheerio(this).find("div > a > img").attr("src")) === null || _b === void 0 ? void 0 : _b.trim();
- const url = (_c = loadedCheerio(this).find("div > h4 > a").attr("href")) === null || _c === void 0 ? void 0 : _c.trim();
- if (!name || !url)
- return;
- novels.push({ name, cover, url });
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- var _a, _b;
- return __awaiter(this, void 0, void 0, function* () {
- const result = yield (0, fetch_1.fetchApi)(novelUrl);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- let novel = {
- url: novelUrl,
- name: loadedCheerio(".book-info > h4").text(),
- cover: (_a = loadedCheerio(".book-cover > div > img").attr("src")) === null || _a === void 0 ? void 0 : _a.trim(),
- summary: (_b = loadedCheerio("#nav-home").text()) === null || _b === void 0 ? void 0 : _b.trim(),
- author: loadedCheerio(".book-info > h5 > a").text(),
- genres: loadedCheerio(".genre-list > a")
- .map((index, element) => loadedCheerio(element).text()).get().join(","),
- };
- let chapters = [];
- loadedCheerio("#nav-contents > div").each(function () {
- const name = loadedCheerio(this).find("a").text();
- const releaseTime = loadedCheerio(this).find('span[class="date"]').text();
- const url = loadedCheerio(this).find("a").attr("href");
- if (!name || !url)
- return;
- chapters.push({ name, releaseTime, url });
- });
- novel.chapters = chapters;
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const result = yield (0, fetch_1.fetchApi)(chapterUrl);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('div[class="standart-block"]').remove();
- loadedCheerio('div[class="mobile-block"]').remove();
- const chapterText = loadedCheerio('div[class="chapter"]').html();
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = `${exports.site}/search?query=${searchTerm}&type=all`;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio("#bookListBlock > div").each(function () {
- var _a, _b, _c;
- const name = (_a = loadedCheerio(this).find("h4 > a").text()) === null || _a === void 0 ? void 0 : _a.trim();
- const cover = (_b = loadedCheerio(this).find("a > img").attr("src")) === null || _b === void 0 ? void 0 : _b.trim();
- const url = (_c = loadedCheerio(this).find("h4 > a").attr("href")) === null || _c === void 0 ? void 0 : _c.trim();
- if (!name || !url)
- return;
- novels.push({ name, cover, url });
- });
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-exports.filters = [
- {
- key: "sort",
- label: "Сортировка:",
- values: [
- { label: "По популярности", value: "popular" },
- { label: "По количеству комментариев", value: "comments" },
- { label: "По количеству лайков", value: "likes" },
- { label: "По новизне", value: "recent" },
- { label: "По просмотрам", value: "views" },
- ],
- inputType: filterInputs_1.FilterInputs.Picker,
- },
- {
- key: "genre",
- label: "Жанры:",
- values: [
- { label: "Любой жанр", value: "all" },
- { label: "Альтернативная история", value: "alternative-history" },
- { label: "Антиутопия", value: "dystopia" },
- { label: "Бизнес-литература", value: "business-literature" },
- { label: "Боевая фантастика", value: "combat-fiction" },
- { label: "Боевик", value: "action" },
- { label: "Боевое фэнтези", value: "combat-fantasy" },
- { label: "Бояръ-Аниме", value: "boyar-anime" },
- { label: "Героическая фантастика", value: "heroic-fiction" },
- { label: "Героическое фэнтези", value: "heroic-fantasy" },
- { label: "Городское фэнтези", value: "urban-fantasy" },
- { label: "Гримдарк", value: "grimdark" },
- { label: "Детектив", value: "mystery" },
- { label: "Детская литература", value: "kids-literature" },
- { label: "Документальная проза", value: "biography" },
- { label: "Историческая проза", value: "historical-fiction" },
- { label: "Исторический детектив", value: "historical-mystery" },
- { label: "Исторический любовный роман", value: "historical-romantic-novel" },
- { label: "Историческое фэнтези", value: "historical-fantasy" },
- { label: "Киберпанк", value: "cyberpunk" },
- { label: "Космическая фантастика", value: "cosmic-fiction" },
- { label: "ЛитРПГ", value: "litrpg" },
- { label: "Лоу / Низкое фэнтези", value: "low-fantasy" },
- { label: "Любовное фэнтези", value: "romantic-fantasy" },
- { label: "Любовный роман", value: "romantic-novel" },
- { label: "Мистика", value: "mystic" },
- { label: "Мистический детектив", value: "mystic-detective" },
- { label: "Научная фантастика", value: "science-fiction" },
- { label: "Подростковая проза", value: "young-adult" },
- { label: "Политический роман", value: "political-romance" },
- { label: "Попаданцы", value: "accidental-travel" },
- { label: "Попаданцы в магические миры", value: "magic-worlds-travel" },
- { label: "Попаданцы во времени", value: "time-travel" },
- { label: "Порнотика", value: "pornotica" },
- { label: "Постапокалипсис", value: "post-apocalypse" },
- { label: "Поэзия", value: "poetry" },
- { label: "Приключения", value: "adventure" },
- { label: "Публицистика", value: "journalism" },
- { label: "Пьеса", value: "play" },
- { label: "Развитие личности", value: "how-to-book" },
- { label: "Разное", value: "other" },
- { label: "Реализм", value: "Realism" },
- { label: "РеалРПГ", value: "realrpg" },
- { label: "Репликация", value: "replication" },
- { label: "Романтическая эротика", value: "romantic-erotic-fiction" },
- { label: "Сказка", value: "fairy-tale" },
- { label: "Слэш", value: "slash" },
- { label: "Современная проза", value: "modern-prose" },
- { label: "Современный любовный роман", value: "modern-romantic-novel" },
- { label: "Социальная фантастика", value: "social-fiction" },
- { label: "Стимпанк", value: "steampunk" },
- { label: "Сценарий", value: "scenario" },
- { label: "Сюаньхуань", value: "xuanhuan" },
- { label: "Сянься", value: "xianxia" },
- { label: "Тёмное фэнтези", value: "dark-fantasy" },
- { label: "Триллер", value: "thriller" },
- { label: "Уся", value: "wuxia" },
- { label: "Фантастика", value: "fiction" },
- { label: "Фантастический детектив", value: "mystery-fiction" },
- { label: "Фанфик", value: "fan-fiction" },
- { label: "Фемслэш", value: "femslash" },
- { label: "Фэнтези", value: "fantasy" },
- { label: "Хоррор", value: "horror" },
- { label: "Шпионский детектив", value: "spy-crime" },
- { label: "Эпическое фэнтези", value: "epic-fantasy" },
- { label: "Эротика", value: "erotic-fiction" },
- { label: "Эротическая фантастика", value: "erotic-fiction" },
- { label: "Эротический фанфик", value: "erotic-fan-fiction" },
- { label: "Эротическое фэнтези", value: "erotic-fantasy" },
- { label: "Этническое фэнтези", value: "ethnic-fantasy" },
- { label: "Юмор", value: "humor" },
- { label: "Юмористическая фантастика", value: "humor-fiction" },
- { label: "Юмористическое фэнтези", value: "humor-fantasy" },
- { label: "RPS", value: "rps" },
- ],
- inputType: filterInputs_1.FilterInputs.Picker,
- },
- {
- key: "status",
- label: "Статус:",
- values: [
- { label: "Любой статус", value: "all" },
- { label: "В процессе", value: "in-process" },
- { label: "Завершено", value: "finished" },
- ],
- inputType: filterInputs_1.FilterInputs.Picker,
- },
- {
- key: "access",
- label: "Доступ:",
- values: [
- { label: "Любой доступ", value: "all" },
- { label: "Бесплатные", value: "free" },
- { label: "Платные", value: "paid" },
- ],
- inputType: filterInputs_1.FilterInputs.Picker,
- },
- {
- key: "adult",
- label: "Возрастные ограничения:",
- values: [
- { label: "Скрыть 18+", value: "hide" },
- { label: "Показать +18", value: "show" },
- ],
- inputType: filterInputs_1.FilterInputs.Picker,
- },
-];
-exports.fetchImage = fetch_1.fetchFile;
diff --git a/js/plugins/russian/Rulate[rulate].js b/js/plugins/russian/Rulate[rulate].js
deleted file mode 100644
index 0743e2c..0000000
--- a/js/plugins/russian/Rulate[rulate].js
+++ /dev/null
@@ -1,195 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-// import dayjs from 'dayjs';
-const fetch_1 = require("@libs/fetch");
-// import { parseMadaraDate } from "@libs/parseMadaraDate";
-// import { isUrlAbsolute } from '@libs/isAbsoluteUrl';
-// import { showToast } from "@libs/showToast";
-const filterInputs_1 = require("@libs/filterInputs");
-const novelStatus_1 = require("@libs/novelStatus");
-// import { defaultCover } from "@libs/defaultCover";
-exports.id = "tl.rulate";
-exports.name = "Rulate";
-exports.icon = "multisrc/rulate/icons/rulate.png";
-exports.version = "1.0.0";
-exports.site = "https://tl.rulate.ru";
-const popularNovels = function (page, { filters, showLatestNovels }) {
- return __awaiter(this, void 0, void 0, function* () {
- let url = exports.site + '/search?t=';
- url += '&cat=' + ((filters === null || filters === void 0 ? void 0 : filters.cat) || '0');
- url += '&s_lang=' + ((filters === null || filters === void 0 ? void 0 : filters.s_lang) || '0');
- url += '&t_lang=' + ((filters === null || filters === void 0 ? void 0 : filters.t_lang) || '0');
- url += '&type=' + ((filters === null || filters === void 0 ? void 0 : filters.type) || '0');
- url += '&sort=' + (showLatestNovels ? '4' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || '6'));
- url += '&atmosphere=' + ((filters === null || filters === void 0 ? void 0 : filters.atmosphere) || '0');
- url += '&adult=' + ((filters === null || filters === void 0 ? void 0 : filters.adult) || '0');
- if ((filters === null || filters === void 0 ? void 0 : filters.genres) instanceof Array) {
- url += filters.genres.map(i => '&genres[]=' + i).join('');
- }
- if ((filters === null || filters === void 0 ? void 0 : filters.genres_ex) instanceof Array) {
- url += filters.genres_ex.map(i => '&genres_ex[]=' + i).join('');
- }
- if ((filters === null || filters === void 0 ? void 0 : filters.tags) instanceof Array) {
- url += filters.tags.map(i => '&tags[]=' + i).join('');
- }
- if ((filters === null || filters === void 0 ? void 0 : filters.tags_ex) instanceof Array) {
- url += filters.tags_ex.map(i => '&tags_ex[]=' + i).join('');
- }
- if ((filters === null || filters === void 0 ? void 0 : filters.fandoms) instanceof Array) {
- url += filters.fandoms.map(i => '&fandoms[]=' + i).join('');
- }
- if ((filters === null || filters === void 0 ? void 0 : filters.fandoms_ex) instanceof Array) {
- url += filters.fandoms_ex.map(i => '&fandoms_ex[]=' + i).join('');
- }
- if ((filters === null || filters === void 0 ? void 0 : filters.trash) instanceof Array) {
- url += filters.trash.map(i => '&' + i + '=1').join('');
- }
- url += '&Book_page=' + page;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- const novels = [];
- loadedCheerio('ul[class="search-results"] > li:not([class="ad_type_catalog"])').each(function () {
- novels.push({
- name: loadedCheerio(this).find('p > a').text(),
- cover: exports.site + loadedCheerio(this).find('img').attr('src'),
- url: exports.site + loadedCheerio(this).find('p > a').attr('href') || '',
- });
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- chapters: [],
- };
- let result = yield (0, fetch_1.fetchApi)(novelUrl);
- if (result.url.includes('mature?path=')) {
- const formData = new FormData();
- formData.append('path', novelUrl);
- formData.append('ok', 'Да');
- yield (0, fetch_1.fetchApi)(result.url, {
- method: 'POST',
- body: formData,
- });
- result = yield (0, fetch_1.fetchApi)(novelUrl);
- }
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- novel.name = loadedCheerio('div[class="container"] > div > div > h1, div.span8:nth-child(1) > h1:nth-child(2)')
- .text()
- .trim();
- novel.cover =
- exports.site + loadedCheerio('div[class="images"] > div img').attr('src');
- novel.summary = loadedCheerio('#Info > div:nth-child(3), .book-description').text();
- novel.author = loadedCheerio('.book-stats-icons_author > span:nth-child(2) > a:nth-child(1)').text();
- let genres = [];
- loadedCheerio('div.span5 > p, .span5 > div:nth-child(2) > p').each(function () {
- switch (loadedCheerio(this).find('strong').text()) {
- case 'Автор:':
- novel.author = loadedCheerio(this).find('em > a').text().trim();
- break;
- case 'Выпуск:':
- novel.status =
- loadedCheerio(this).find('em').text().trim() === 'продолжается'
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- case 'Тэги:':
- loadedCheerio(this)
- .find('em > a')
- .each(function () {
- genres.push(loadedCheerio(this).text());
- });
- break;
- case 'Жанры:':
- loadedCheerio(this)
- .find('em > a')
- .each(function () {
- genres.push(loadedCheerio(this).text());
- });
- break;
- }
- });
- if (genres.length > 0) {
- novel.genres = genres.reverse().join(',');
- }
- const chapters = [];
- loadedCheerio('table > tbody > tr.chapter_row').each(function () {
- var _a;
- const chapterName = loadedCheerio(this)
- .find('td[class="t"] > a')
- .text()
- .trim();
- const releaseDate = (_a = loadedCheerio(this)
- .find('td > span')
- .attr('title')) === null || _a === void 0 ? void 0 : _a.trim();
- const chapterUrl = exports.site + loadedCheerio(this)
- .find('td[class="t"] > a')
- .attr('href');
- if (loadedCheerio(this).find('td > span[class="disabled"]').length < 1 &&
- releaseDate) {
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- }
- });
- novel.chapters = chapters;
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- let result = yield (0, fetch_1.fetchApi)(chapterUrl);
- if (result.url.includes('mature?path=')) {
- const formData = new FormData();
- formData.append('ok', 'Да');
- yield (0, fetch_1.fetchApi)(result.url, {
- method: 'POST',
- body: formData,
- });
- result = yield (0, fetch_1.fetchApi)(chapterUrl);
- }
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.content-text img').each(function () {
- var _a;
- if (!((_a = loadedCheerio(this).attr('src')) === null || _a === void 0 ? void 0 : _a.startsWith('http'))) {
- const src = loadedCheerio(this).attr('src');
- loadedCheerio(this).attr('src', exports.site + src);
- }
- });
- const chapterText = loadedCheerio('.content-text').html();
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const result = yield (0, fetch_1.fetchApi)(exports.site + '/search/autocomplete?query=' + searchTerm);
- let json = yield result.json();
- json.forEach((item) => {
- const novelName = item.title_one + ' / ' + item.title_two;
- const novelCover = exports.site + item.img;
- const novelUrl = exports.site + item.url;
- novels.push({ name: novelName, cover: novelCover, url: novelUrl });
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-;
-exports.fetchImage = fetch_1.fetchFile;
-exports.filters = [{ "key": "cat", "label": "Из раздела каталога:", "values": [{ "label": "Неважно", "value": "0" }, { "label": "Авторские", "value": "18" }, { "label": "Авторские", "value": "35" }, { "label": "Авторские фанфики", "value": "51" }, { "label": "Английские", "value": "28" }, { "label": "Английские", "value": "34" }, { "label": "Английские", "value": "48" }, { "label": "Аниме", "value": "20" }, { "label": "Аудиокниги", "value": "25" }, { "label": "Блич", "value": "42" }, { "label": "Большие игры", "value": "22" }, { "label": "Ван-Пис", "value": "41" }, { "label": "Визуальные новеллы", "value": "8" }, { "label": "Вьетнамские", "value": "39" }, { "label": "Вьетнамские", "value": "49" }, { "label": "Игры", "value": "3" }, { "label": "Китайские", "value": "5" }, { "label": "Китайские", "value": "31" }, { "label": "Китайские", "value": "45" }, { "label": "Книги", "value": "2" }, { "label": "Книги", "value": "14" }, { "label": "Комиксы", "value": "29" }, { "label": "Корейские", "value": "7" }, { "label": "Корейские", "value": "33" }, { "label": "Корейские", "value": "47" }, { "label": "Маленькие игры", "value": "23" }, { "label": "Манга", "value": "16" }, { "label": "Манга", "value": "30" }, { "label": "Марвел", "value": "43" }, { "label": "Машинный перевод", "value": "44" }, { "label": "Наруто", "value": "40" }, { "label": "Новеллы и ранобэ", "value": "12" }, { "label": "Переводы фанфиков", "value": "19" }, { "label": "Психология", "value": "37" }, { "label": "Путешествия", "value": "36" }, { "label": "Статьи", "value": "13" }, { "label": "Субтитры", "value": "15" }, { "label": "Фильмы", "value": "21" }, { "label": "Японские", "value": "6" }, { "label": "Японские", "value": "32" }, { "label": "Японские", "value": "46" }], "inputType": filterInputs_1.FilterInputs.Picker }, { "key": "s_lang", "label": "Язык оригинала:", "values": [{ "label": "Неважно", "value": "0" }, { "label": "Абхазский", "value": "20" }, { "label": "Аварский", "value": "21" }, { "label": "Азербайджанский", "value": "22" }, { "label": "Аймара", "value": "23" }, { "label": "Акан", "value": "24" }, { "label": "Албанский", "value": "25" }, { "label": "Амхарский", "value": "26" }, { "label": "Английский", "value": "2" }, { "label": "Арабский", "value": "27" }, { "label": "Арагонский", "value": "28" }, { "label": "Арберешский", "value": "29" }, { "label": "Армянский", "value": "30" }, { "label": "Ассамский", "value": "31" }, { "label": "Астурийский", "value": "32" }, { "label": "Афарский", "value": "33" }, { "label": "Африкаанс", "value": "34" }, { "label": "Ацтекский", "value": "35" }, { "label": "Баварский", "value": "36" }, { "label": "Бамбарийский", "value": "37" }, { "label": "Баскский", "value": "39" }, { "label": "Башкирский", "value": "40" }, { "label": "Белорусский", "value": "10" }, { "label": "Бенгальский", "value": "41" }, { "label": "Бирманский", "value": "42" }, { "label": "Бислама", "value": "43" }, { "label": "Бихари", "value": "44" }, { "label": "Болгарский", "value": "45" }, { "label": "Боснийский", "value": "234" }, { "label": "Бретонский", "value": "47" }, { "label": "Валенсийский", "value": "48" }, { "label": "Валлийский", "value": "49" }, { "label": "Валлонский", "value": "50" }, { "label": "Венгерский", "value": "51" }, { "label": "Венда", "value": "52" }, { "label": "Венетский", "value": "53" }, { "label": "Верхнелужицкий", "value": "54" }, { "label": "Волоф", "value": "55" }, { "label": "Вьетнамский", "value": "57" }, { "label": "Гавайский", "value": "58" }, { "label": "Гаитянский", "value": "59" }, { "label": "Галисийский", "value": "60" }, { "label": "Гереро", "value": "61" }, { "label": "Голландский", "value": "62" }, { "label": "Греческий", "value": "63" }, { "label": "Грузинский", "value": "64" }, { "label": "Гуарани", "value": "65" }, { "label": "Гуджарати", "value": "66" }, { "label": "Датский", "value": "19" }, { "label": "Дзонг-кэ", "value": "68" }, { "label": "Древнегреческий", "value": "69" }, { "label": "Западно-фламандский", "value": "70" }, { "label": "Зулу", "value": "71" }, { "label": "Иврит", "value": "15" }, { "label": "Игбо", "value": "72" }, { "label": "Идиш", "value": "73" }, { "label": "Илоко", "value": "74" }, { "label": "Индонезийский", "value": "75" }, { "label": "Интерлингва", "value": "76" }, { "label": "Инуктитут", "value": "77" }, { "label": "Инупиак", "value": "78" }, { "label": "Ирландский", "value": "79" }, { "label": "Исландский", "value": "80" }, { "label": "Испанский", "value": "6" }, { "label": "Итальянский", "value": "5" }, { "label": "Йоруба", "value": "81" }, { "label": "Кабильский", "value": "82" }, { "label": "Казахский", "value": "83" }, { "label": "Калмыцкий", "value": "235" }, { "label": "Каннада", "value": "84" }, { "label": "Кантонский юэ", "value": "85" }, { "label": "Канури", "value": "86" }, { "label": "Каталанский", "value": "87" }, { "label": "Кашмири", "value": "88" }, { "label": "Кечуа", "value": "90" }, { "label": "Кикуйю", "value": "91" }, { "label": "Киньяруанда", "value": "92" }, { "label": "Киргизский", "value": "93" }, { "label": "Китайский", "value": "7" }, { "label": "Клингонский", "value": "94" }, { "label": "Коми", "value": "95" }, { "label": "Конго", "value": "96" }, { "label": "Конкани", "value": "97" }, { "label": "Корейский", "value": "98" }, { "label": "Корсиканский", "value": "100" }, { "label": "Котава", "value": "101" }, { "label": "Кри", "value": "102" }, { "label": "Курдский", "value": "105" }, { "label": "Кхмерский", "value": "107" }, { "label": "Лакский", "value": "233" }, { "label": "Лаосский", "value": "109" }, { "label": "Латынь", "value": "110" }, { "label": "Латышский", "value": "111" }, { "label": "Лезгинский", "value": "112" }, { "label": "Лимбургский", "value": "113" }, { "label": "Лингала", "value": "114" }, { "label": "Литовский", "value": "115" }, { "label": "Луба", "value": "118" }, { "label": "Луганда", "value": "119" }, { "label": "Люксембургский", "value": "120" }, { "label": "Македонский", "value": "121" }, { "label": "Малагасийский", "value": "122" }, { "label": "Малайский", "value": "123" }, { "label": "Мальдивский", "value": "125" }, { "label": "Мальтийский", "value": "126" }, { "label": "Маори", "value": "127" }, { "label": "Марийский", "value": "232" }, { "label": "Маршалльский", "value": "130" }, { "label": "Молдавский", "value": "11" }, { "label": "Монгольский", "value": "133" }, { "label": "Мяо (хмонг)", "value": "209" }, { "label": "Навахо", "value": "135" }, { "label": "Неаполитанский", "value": "139" }, { "label": "Немецкий", "value": "3" }, { "label": "Непальский", "value": "140" }, { "label": "Норвежский", "value": "18" }, { "label": "Осетинский", "value": "147" }, { "label": "Пакистанский", "value": "230" }, { "label": "Пенджабский", "value": "149" }, { "label": "Персидский", "value": "151" }, { "label": "Польский", "value": "152" }, { "label": "Португальский", "value": "153" }, { "label": "Румынский", "value": "158" }, { "label": "Русский", "value": "1" }, { "label": "Санскрит", "value": "163" }, { "label": "Сардинский", "value": "164" }, { "label": "Сербохорватский", "value": "166" }, { "label": "Словацкий", "value": "170" }, { "label": "Словенский", "value": "171" }, { "label": "Сомали", "value": "172" }, { "label": "Старотурецкий", "value": "174" }, { "label": "Суахили", "value": "175" }, { "label": "Сунданский", "value": "176" }, { "label": "Тагальский", "value": "177" }, { "label": "Таджикский", "value": "178" }, { "label": "Таитянский", "value": "179" }, { "label": "Тайваньский", "value": "180" }, { "label": "Тайский", "value": "181" }, { "label": "Тамильский", "value": "182" }, { "label": "Татарский", "value": "12" }, { "label": "Телугу", "value": "184" }, { "label": "Тибетский", "value": "185" }, { "label": "Тигринья", "value": "186" }, { "label": "Ток-писин", "value": "187" }, { "label": "Токи пона", "value": "188" }, { "label": "Тонганский", "value": "189" }, { "label": "Тсвана", "value": "191" }, { "label": "Тсонга", "value": "192" }, { "label": "Турецкий", "value": "193" }, { "label": "Туркменский", "value": "194" }, { "label": "Удмуртский", "value": "196" }, { "label": "Узбекский", "value": "197" }, { "label": "Уйгурский", "value": "198" }, { "label": "Украинский", "value": "9" }, { "label": "Фиджийский", "value": "201" }, { "label": "Филиппинский", "value": "229" }, { "label": "Финский", "value": "17" }, { "label": "Французский", "value": "4" }, { "label": "Фризский", "value": "203" }, { "label": "Фулах", "value": "204" }, { "label": "Хауса", "value": "206" }, { "label": "Хинди", "value": "207" }, { "label": "Хири-моту", "value": "208" }, { "label": "Чеченский", "value": "213" }, { "label": "Чешский", "value": "13" }, { "label": "Чувашский", "value": "217" }, { "label": "Шведский", "value": "16" }, { "label": "Швейцарский немецкий", "value": "218" }, { "label": "Шона", "value": "219" }, { "label": "Шотландский", "value": "67" }, { "label": "Эве", "value": "221" }, { "label": "Эскимосский", "value": "223" }, { "label": "Эсперанто", "value": "14" }, { "label": "Эстонский", "value": "224" }, { "label": "Южно-корейский", "value": "231" }, { "label": "Юкатекский", "value": "225" }, { "label": "Яванский", "value": "227" }, { "label": "Японский", "value": "8" }], "inputType": filterInputs_1.FilterInputs.Picker }, { "key": "t_lang", "label": "Язык перевода:", "values": [{ "label": "Неважно", "value": "0" }, { "label": "Абхазский", "value": "20" }, { "label": "Аварский", "value": "21" }, { "label": "Азербайджанский", "value": "22" }, { "label": "Аймара", "value": "23" }, { "label": "Акан", "value": "24" }, { "label": "Албанский", "value": "25" }, { "label": "Амхарский", "value": "26" }, { "label": "Английский", "value": "2" }, { "label": "Арабский", "value": "27" }, { "label": "Арагонский", "value": "28" }, { "label": "Арберешский", "value": "29" }, { "label": "Армянский", "value": "30" }, { "label": "Ассамский", "value": "31" }, { "label": "Астурийский", "value": "32" }, { "label": "Афарский", "value": "33" }, { "label": "Африкаанс", "value": "34" }, { "label": "Ацтекский", "value": "35" }, { "label": "Баварский", "value": "36" }, { "label": "Бамбарийский", "value": "37" }, { "label": "Баскский", "value": "39" }, { "label": "Башкирский", "value": "40" }, { "label": "Белорусский", "value": "10" }, { "label": "Бенгальский", "value": "41" }, { "label": "Бирманский", "value": "42" }, { "label": "Бислама", "value": "43" }, { "label": "Бихари", "value": "44" }, { "label": "Болгарский", "value": "45" }, { "label": "Боснийский", "value": "234" }, { "label": "Бретонский", "value": "47" }, { "label": "Валенсийский", "value": "48" }, { "label": "Валлийский", "value": "49" }, { "label": "Валлонский", "value": "50" }, { "label": "Венгерский", "value": "51" }, { "label": "Венда", "value": "52" }, { "label": "Венетский", "value": "53" }, { "label": "Верхнелужицкий", "value": "54" }, { "label": "Волоф", "value": "55" }, { "label": "Вьетнамский", "value": "57" }, { "label": "Гавайский", "value": "58" }, { "label": "Гаитянский", "value": "59" }, { "label": "Галисийский", "value": "60" }, { "label": "Гереро", "value": "61" }, { "label": "Голландский", "value": "62" }, { "label": "Греческий", "value": "63" }, { "label": "Грузинский", "value": "64" }, { "label": "Гуарани", "value": "65" }, { "label": "Гуджарати", "value": "66" }, { "label": "Датский", "value": "19" }, { "label": "Дзонг-кэ", "value": "68" }, { "label": "Древнегреческий", "value": "69" }, { "label": "Западно-фламандский", "value": "70" }, { "label": "Зулу", "value": "71" }, { "label": "Иврит", "value": "15" }, { "label": "Игбо", "value": "72" }, { "label": "Идиш", "value": "73" }, { "label": "Илоко", "value": "74" }, { "label": "Индонезийский", "value": "75" }, { "label": "Интерлингва", "value": "76" }, { "label": "Инуктитут", "value": "77" }, { "label": "Инупиак", "value": "78" }, { "label": "Ирландский", "value": "79" }, { "label": "Исландский", "value": "80" }, { "label": "Испанский", "value": "6" }, { "label": "Итальянский", "value": "5" }, { "label": "Йоруба", "value": "81" }, { "label": "Кабильский", "value": "82" }, { "label": "Казахский", "value": "83" }, { "label": "Калмыцкий", "value": "235" }, { "label": "Каннада", "value": "84" }, { "label": "Кантонский юэ", "value": "85" }, { "label": "Канури", "value": "86" }, { "label": "Каталанский", "value": "87" }, { "label": "Кашмири", "value": "88" }, { "label": "Кечуа", "value": "90" }, { "label": "Кикуйю", "value": "91" }, { "label": "Киньяруанда", "value": "92" }, { "label": "Киргизский", "value": "93" }, { "label": "Китайский", "value": "7" }, { "label": "Клингонский", "value": "94" }, { "label": "Коми", "value": "95" }, { "label": "Конго", "value": "96" }, { "label": "Конкани", "value": "97" }, { "label": "Корейский", "value": "98" }, { "label": "Корсиканский", "value": "100" }, { "label": "Котава", "value": "101" }, { "label": "Кри", "value": "102" }, { "label": "Курдский", "value": "105" }, { "label": "Кхмерский", "value": "107" }, { "label": "Лакский", "value": "233" }, { "label": "Лаосский", "value": "109" }, { "label": "Латынь", "value": "110" }, { "label": "Латышский", "value": "111" }, { "label": "Лезгинский", "value": "112" }, { "label": "Лимбургский", "value": "113" }, { "label": "Лингала", "value": "114" }, { "label": "Литовский", "value": "115" }, { "label": "Луба", "value": "118" }, { "label": "Луганда", "value": "119" }, { "label": "Люксембургский", "value": "120" }, { "label": "Македонский", "value": "121" }, { "label": "Малагасийский", "value": "122" }, { "label": "Малайский", "value": "123" }, { "label": "Мальдивский", "value": "125" }, { "label": "Мальтийский", "value": "126" }, { "label": "Маори", "value": "127" }, { "label": "Марийский", "value": "232" }, { "label": "Маршалльский", "value": "130" }, { "label": "Молдавский", "value": "11" }, { "label": "Монгольский", "value": "133" }, { "label": "Мяо (хмонг)", "value": "209" }, { "label": "Навахо", "value": "135" }, { "label": "Неаполитанский", "value": "139" }, { "label": "Немецкий", "value": "3" }, { "label": "Непальский", "value": "140" }, { "label": "Норвежский", "value": "18" }, { "label": "Осетинский", "value": "147" }, { "label": "Пакистанский", "value": "230" }, { "label": "Пенджабский", "value": "149" }, { "label": "Персидский", "value": "151" }, { "label": "Польский", "value": "152" }, { "label": "Португальский", "value": "153" }, { "label": "Румынский", "value": "158" }, { "label": "Русский", "value": "1" }, { "label": "Санскрит", "value": "163" }, { "label": "Сардинский", "value": "164" }, { "label": "Сербохорватский", "value": "166" }, { "label": "Словацкий", "value": "170" }, { "label": "Словенский", "value": "171" }, { "label": "Сомали", "value": "172" }, { "label": "Старотурецкий", "value": "174" }, { "label": "Суахили", "value": "175" }, { "label": "Сунданский", "value": "176" }, { "label": "Тагальский", "value": "177" }, { "label": "Таджикский", "value": "178" }, { "label": "Таитянский", "value": "179" }, { "label": "Тайваньский", "value": "180" }, { "label": "Тайский", "value": "181" }, { "label": "Тамильский", "value": "182" }, { "label": "Татарский", "value": "12" }, { "label": "Телугу", "value": "184" }, { "label": "Тибетский", "value": "185" }, { "label": "Тигринья", "value": "186" }, { "label": "Ток-писин", "value": "187" }, { "label": "Токи пона", "value": "188" }, { "label": "Тонганский", "value": "189" }, { "label": "Тсвана", "value": "191" }, { "label": "Тсонга", "value": "192" }, { "label": "Турецкий", "value": "193" }, { "label": "Туркменский", "value": "194" }, { "label": "Удмуртский", "value": "196" }, { "label": "Узбекский", "value": "197" }, { "label": "Уйгурский", "value": "198" }, { "label": "Украинский", "value": "9" }, { "label": "Фиджийский", "value": "201" }, { "label": "Филиппинский", "value": "229" }, { "label": "Финский", "value": "17" }, { "label": "Французский", "value": "4" }, { "label": "Фризский", "value": "203" }, { "label": "Фулах", "value": "204" }, { "label": "Хауса", "value": "206" }, { "label": "Хинди", "value": "207" }, { "label": "Хири-моту", "value": "208" }, { "label": "Чеченский", "value": "213" }, { "label": "Чешский", "value": "13" }, { "label": "Чувашский", "value": "217" }, { "label": "Шведский", "value": "16" }, { "label": "Швейцарский немецкий", "value": "218" }, { "label": "Шона", "value": "219" }, { "label": "Шотландский", "value": "67" }, { "label": "Эве", "value": "221" }, { "label": "Эскимосский", "value": "223" }, { "label": "Эсперанто", "value": "14" }, { "label": "Эстонский", "value": "224" }, { "label": "Южно-корейский", "value": "231" }, { "label": "Юкатекский", "value": "225" }, { "label": "Яванский", "value": "227" }, { "label": "Японский", "value": "8" }], "inputType": filterInputs_1.FilterInputs.Picker }, { "key": "type", "label": "Тип:", "values": [{ "label": "Неважно", "value": "0" }, { "label": "Только авторские", "value": "2" }, { "label": "Только переводы", "value": "1" }], "inputType": filterInputs_1.FilterInputs.Picker }, { "key": "trash", "label": "Другое:", "values": [{ "label": "Без фэндомов", "value": "fandoms_ex_all" }, { "label": "Готовые на 100%", "value": "ready" }, { "label": "Доступные для перевода", "value": "tr" }, { "label": "Доступные для скачивания", "value": "gen" }, { "label": "Завершённые проекты", "value": "wealth" }, { "label": "Распродажа", "value": "discount" }, { "label": "Только онгоинги", "value": "ongoings" }, { "label": "Убрать машинный", "value": "remove_machinelate" }], "inputType": filterInputs_1.FilterInputs.Checkbox }, { "key": "sort", "label": "Сортировка:", "values": [{ "label": "По рейтингу", "value": "6" }, { "label": "По дате последней активности", "value": "4" }, { "label": "По дате создания", "value": "3" }, { "label": "По кол-ву бесплатных глав", "value": "11" }, { "label": "По кол-ву в закладках", "value": "13" }, { "label": "По кол-ву в избранном", "value": "14" }, { "label": "По кол-ву лайков", "value": "8" }, { "label": "По кол-ву переведённых глав", "value": "7" }, { "label": "По кол-ву рецензий", "value": "12" }, { "label": "По кол-ву страниц", "value": "10" }, { "label": "По названию на языке оригинала", "value": "1" }, { "label": "По названию на языке перевода", "value": "2" }, { "label": "По просмотрам", "value": "5" }, { "label": "По степени готовности", "value": "0" }, { "label": "Случайно", "value": "9" }], "inputType": filterInputs_1.FilterInputs.Picker }, { "key": "genres", "label": "Жанры:", "values": [{ "label": "18+", "value": "52" }, { "label": "Арт", "value": "1" }, { "label": "Боевик", "value": "2" }, { "label": "Боевые искусства", "value": "3" }, { "label": "Гаремник", "value": "5" }, { "label": "Героическое фэнтези", "value": "7" }, { "label": "Детектив", "value": "8" }, { "label": "Дзёсэй", "value": "9" }, { "label": "Додзинси", "value": "10" }, { "label": "Драма", "value": "11" }, { "label": "История", "value": "13" }, { "label": "Киберпанк", "value": "46" }, { "label": "Кодомо", "value": "14" }, { "label": "Комедия", "value": "15" }, { "label": "Литрпг", "value": "48" }, { "label": "Махо-сёдзё", "value": "16" }, { "label": "Мелодрама", "value": "49" }, { "label": "Меха", "value": "17" }, { "label": "Мистика", "value": "18" }, { "label": "Научная фантастика", "value": "19" }, { "label": "Повседневность", "value": "20" }, { "label": "Постапокалиптика", "value": "21" }, { "label": "Приключения", "value": "22" }, { "label": "Психология", "value": "23" }, { "label": "Романтика", "value": "24" }, { "label": "Самурайский боевик", "value": "25" }, { "label": "Сверхъестественное", "value": "26" }, { "label": "Сёдзё", "value": "27" }, { "label": "Сёнэн", "value": "29" }, { "label": "Смат", "value": "45" }, { "label": "Спорт", "value": "31" }, { "label": "Сэйнэн", "value": "32" }, { "label": "Сюаньхуа", "value": "44" }, { "label": "Сюаньхуань", "value": "47" }, { "label": "Сянься (XianXia)", "value": "42" }, { "label": "Трагедия", "value": "33" }, { "label": "Триллер", "value": "34" }, { "label": "Ужасы", "value": "35" }, { "label": "Уся (wuxia)", "value": "41" }, { "label": "Фантастика", "value": "36" }, { "label": "Фанфик", "value": "50" }, { "label": "Фэнтези", "value": "37" }, { "label": "Школа", "value": "38" }, { "label": "Этти", "value": "39" }, { "label": "Bl", "value": "43" }, { "label": "Gl", "value": "40" }], "inputType": filterInputs_1.FilterInputs.Checkbox }, { "key": "tags", "label": "Тэги:", "values": [{ "label": "12+", "value": "3316" }, { "label": "16+", "value": "83" }, { "label": "Абсурд", "value": "7973" }, { "label": "Авантюристы", "value": "222" }, { "label": "Автомат", "value": "5272" }, { "label": "Авторский мир", "value": "1062" }, { "label": "Агрессивные персонажи", "value": "3249" }, { "label": "Ад", "value": "2623" }, { "label": "Ад и рай", "value": "817" }, { "label": "Адам дженсен", "value": "1649" }, { "label": "Адаптация произведения", "value": "192" }, { "label": "Адвокат", "value": "6340" }, { "label": "Адекватные главные герои", "value": "1953" }, { "label": "Азартные игры", "value": "5301" }, { "label": "Азгард", "value": "3494" }, { "label": "Азула", "value": "5550" }, { "label": "Аид", "value": "7641" }, { "label": "Айдолы", "value": "4081" }, { "label": "Академия", "value": "316" }, { "label": "Акамэ", "value": "5059" }, { "label": "Аквакинез", "value": "5952" }, { "label": "Акира", "value": "2639" }, { "label": "Акнология", "value": "4634" }, { "label": "Актерское мастерство", "value": "4798" }, { "label": "Актёры", "value": "7506" }, { "label": "Активные герои", "value": "6376" }, { "label": "Акутагава рюноске", "value": "4113" }, { "label": "Аладдин", "value": "6489" }, { "label": "Алая ведьма", "value": "4767" }, { "label": "Алиса", "value": "4761" }, { "label": "Алкоголь", "value": "5508" }, { "label": "Аллегория", "value": "271" }, { "label": "Алукард", "value": "4914" }, { "label": "Алхимики", "value": "1164" }, { "label": "Алхимия", "value": "1473" }, { "label": "Алчность", "value": "6897" }, { "label": "Альбус дамблдор", "value": "5784" }, { "label": "Альтернативное развитие событий", "value": "5330" }, { "label": "Альянсы", "value": "328" }, { "label": "Амбициозный главный герой", "value": "3751" }, { "label": "Америка", "value": "4082" }, { "label": "Амнезия", "value": "2207" }, { "label": "Аморальный герой", "value": "18" }, { "label": "Анбу", "value": "8129" }, { "label": "Ангелы", "value": "857" }, { "label": "Ангелы и демоны", "value": "1327" }, { "label": "Ангст", "value": "4638" }, { "label": "Андроиды", "value": "1993" }, { "label": "Анимализм", "value": "5249" }, { "label": "Аниме", "value": "1294" }, { "label": "Анко митараши", "value": "5768" }, { "label": "Антагонист", "value": "2144" }, { "label": "Антигерой", "value": "7725" }, { "label": "Антиквариат", "value": "3552" }, { "label": "Антимаг", "value": "1348" }, { "label": "Антиутопия", "value": "662" }, { "label": "Апокалипсис", "value": "1498" }, { "label": "Аристократия", "value": "371" }, { "label": "Аристократы", "value": "7338" }, { "label": "Армия", "value": "1723" }, { "label": "Артас", "value": "6700" }, { "label": "Артефакты", "value": "2296" }, { "label": "Археология", "value": "6523" }, { "label": "Асгард", "value": "3635" }, { "label": "Ассасин", "value": "1415" }, { "label": "Асуна", "value": "5044" }, { "label": "Аугментации", "value": "7751" }, { "label": "Ацуши накаджима", "value": "4109" }, { "label": "Аянокоджи киетака", "value": "6862" }, { "label": "Бандиты", "value": "2188" }, { "label": "Басейн", "value": "6847" }, { "label": "Баскетбол", "value": "7933" }, { "label": "Бастарды", "value": "76" }, { "label": "Бедность", "value": "1207" }, { "label": "Без культивации", "value": "668" }, { "label": "Без любовной линий", "value": "2225" }, { "label": "Без перерождений", "value": "262" }, { "label": "Без попаданца", "value": "8065" }, { "label": "Без системы", "value": "747" }, { "label": "Без юмора", "value": "763" }, { "label": "Бездна", "value": "1026" }, { "label": "Безжалостное домашнее животное", "value": "1245" }, { "label": "Безжалостные персонажи", "value": "2986" }, { "label": "Беззаботные персонажи", "value": "3123" }, { "label": "Безответная любовь", "value": "7815" }, { "label": "Безработный", "value": "2202" }, { "label": "Безумие", "value": "37" }, { "label": "Безумные персонажи", "value": "2049" }, { "label": "Бейсбол", "value": "7623" }, { "label": "Беременность", "value": "2122" }, { "label": "Бесконечный поток", "value": "7556" }, { "label": "Беспечные персонажи", "value": "742" }, { "label": "Бесплатно", "value": "8403" }, { "label": "Бессмертные персонажи", "value": "566" }, { "label": "Бесстрашные персонажи", "value": "6921" }, { "label": "Бесстыдные персонажи", "value": "1257" }, { "label": "Бесстыдный главный герой", "value": "8190" }, { "label": "Библиотека", "value": "4210" }, { "label": "Библия", "value": "488" }, { "label": "Бизнес", "value": "704" }, { "label": "Биология", "value": "2220" }, { "label": "Биомехи", "value": "1968" }, { "label": "Биседзе", "value": "777" }, { "label": "Битва за веру", "value": "721" }, { "label": "Битва за трон", "value": "7211" }, { "label": "Битва королевств", "value": "1151" }, { "label": "Битва рас", "value": "6989" }, { "label": "Битвы", "value": "1740" }, { "label": "Благородные персонажи", "value": "2201" }, { "label": "Близнецы", "value": "2931" }, { "label": "Богатство", "value": "6522" }, { "label": "Богатые персонажи", "value": "520" }, { "label": "Боги", "value": "173" }, { "label": "Богини", "value": "30" }, { "label": "Богиня", "value": "8324" }, { "label": "Богоубийца", "value": "1253" }, { "label": "Богохульство", "value": "95" }, { "label": "Боевая академия", "value": "2108" }, { "label": "Большая грудь", "value": "4717" }, { "label": "Борос", "value": "6533" }, { "label": "Борьба", "value": "1925" }, { "label": "Борьба за власть", "value": "8072" }, { "label": "Босс и подчиненный", "value": "7157" }, { "label": "Бояръ", "value": "2307" }, { "label": "Брак", "value": "1558" }, { "label": "Брак по расчету", "value": "1389" }, { "label": "Брат и сестра", "value": "615" }, { "label": "Братский комплекс", "value": "2321" }, { "label": "Броманс", "value": "1103" }, { "label": "Брошенные дети", "value": "2846" }, { "label": "Буддизм", "value": "1871" }, { "label": "Будущее", "value": "1820" }, { "label": "Бывший муж", "value": "8080" }, { "label": "Быстрое развитие", "value": "1443" }, { "label": "Бэтгерл", "value": "2584" }, { "label": "Бэтмен", "value": "4668" }, { "label": "В первый раз", "value": "6212" }, { "label": "В этот же мир", "value": "49" }, { "label": "Ваканда", "value": "8331" }, { "label": "Валькирии", "value": "4047" }, { "label": "Вампиры", "value": "2206" }, { "label": "Веб камера", "value": "5664" }, { "label": "Веб новелла", "value": "2349" }, { "label": "Ведьмак", "value": "843" }, { "label": "Ведьмы", "value": "643" }, { "label": "Везучие персонажи", "value": "1879" }, { "label": "Веном", "value": "3994" }, { "label": "Вестерн", "value": "2131" }, { "label": "Вестерос", "value": "8171" }, { "label": "Взросление", "value": "624" }, { "label": "Взрослый главный герой", "value": "2416" }, { "label": "Видео игры", "value": "2630" }, { "label": "Викинги", "value": "267" }, { "label": "Вино", "value": "6972" }, { "label": "Вирт", "value": "6213" }, { "label": "Виртуальная реальность", "value": "325" }, { "label": "Вирусы", "value": "3327" }, { "label": "Владыка демонов", "value": "555" }, { "label": "Власть", "value": "756" }, { "label": "Влюбленность", "value": "6132" }, { "label": "Внешний вид отличается от личности", "value": "1938" }, { "label": "Внучка", "value": "8399" }, { "label": "Военные", "value": "1096" }, { "label": "Возрождение", "value": "1160" }, { "label": "Воины", "value": "287" }, { "label": "Война", "value": "443" }, { "label": "Войны", "value": "2431" }, { "label": "Воландеморт", "value": "4278" }, { "label": "Волейбол", "value": "6415" }, { "label": "Волки", "value": "1166" }, { "label": "Волшебники", "value": "122" }, { "label": "Волшебные существа", "value": "1689" }, { "label": "Волшебство", "value": "719" }, { "label": "Вор", "value": "1399" }, { "label": "Воровка", "value": "6948" }, { "label": "Ворон", "value": "848" }, { "label": "Воскрешение", "value": "6915" }, { "label": "Воспоминания из другого мира", "value": "1366" }, { "label": "Воспоминания из прошлого", "value": "1372" }, { "label": "Воссоединие семьи", "value": "8130" }, { "label": "Восхождение", "value": "380" }, { "label": "Враги становятся любовниками", "value": "978" }, { "label": "Врата", "value": "40" }, { "label": "Врата в другой мир", "value": "1957" }, { "label": "Врач", "value": "1243" }, { "label": "Временная петля", "value": "2852" }, { "label": "Врмморпг", "value": "2043" }, { "label": "Все дозволено", "value": "96" }, { "label": "Всемогущий главный герой", "value": "1414" }, { "label": "Второй шанс", "value": "2372" }, { "label": "Вуайеризм", "value": "2498" }, { "label": "Выживание", "value": "501" }, { "label": "Вымышленные существа", "value": "3466" }, { "label": "Вынужденный брак", "value": "7705" }, { "label": "Высокие технологии", "value": "653" }, { "label": "Высокомерные персонажи", "value": "3250" }, { "label": "Галустян", "value": "5199" }, { "label": "Гангстеры", "value": "7704" }, { "label": "Гарем", "value": "440" }, { "label": "Гарри поттер", "value": "226" }, { "label": "Геймеры", "value": "2130" }, { "label": "Генетические модификации", "value": "1750" }, { "label": "Гениальный главный герой", "value": "1500" }, { "label": "Гений", "value": "1650" }, { "label": "Гермиона грейнджер", "value": "4280" }, { "label": "Герои", "value": "185" }, { "label": "Гигаполис", "value": "8393" }, { "label": "Гильгамеш", "value": "6031" }, { "label": "Гильдии", "value": "900" }, { "label": "Гильдия авантюристов", "value": "1858" }, { "label": "Гинтама", "value": "4544" }, { "label": "Гипноз", "value": "358" }, { "label": "Главная героиня влюбляется первой", "value": "973" }, { "label": "Главный герой бог", "value": "164" }, { "label": "Главный герой влюбляется первым", "value": "3629" }, { "label": "Главный герой выживальщик", "value": "120" }, { "label": "Главный герой гонг", "value": "7877" }, { "label": "Главный герой девушка", "value": "257" }, { "label": "Главный герой демон", "value": "136" }, { "label": "Главный герой женщина", "value": "7329" }, { "label": "Главный герой жестокий", "value": "1553" }, { "label": "Главный герой извращенец", "value": "94" }, { "label": "Главный герой имба", "value": "2421" }, { "label": "Главный герой киборг", "value": "7780" }, { "label": "Главный герой монстр", "value": "869" }, { "label": "Главный герой мужчина", "value": "1997" }, { "label": "Главный герой на стороне сил зла", "value": "1514" }, { "label": "Главный герой не адекватный", "value": "5" }, { "label": "Главный герой не психопат", "value": "7804" }, { "label": "Главный герой не человек", "value": "2172" }, { "label": "Главный герой не эмоционален", "value": "1150" }, { "label": "Главный герой подросток", "value": "2215" }, { "label": "Главный герой позитивный", "value": "7787" }, { "label": "Главный герой психопат", "value": "7803" }, { "label": "Главный герой ребенок", "value": "2347" }, { "label": "Главный герой русский", "value": "2417" }, { "label": "Главный герой сильный с самого начала", "value": "88" }, { "label": "Главный герой скрывает свою силу", "value": "1059" }, { "label": "Главный герой эгоист", "value": "8326" }, { "label": "Гномы", "value": "1870" }, { "label": "Гоблины", "value": "2029" }, { "label": "Годзилла", "value": "6990" }, { "label": "Големы", "value": "1690" }, { "label": "Голливуд", "value": "7754" }, { "label": "Головоломка", "value": "1697" }, { "label": "Горничные", "value": "8091" }, { "label": "Гробница", "value": "388" }, { "label": "Дазай осаму", "value": "4112" }, { "label": "Даньмэй", "value": "3411" }, { "label": "Даосизм", "value": "258" }, { "label": "Дарк соулс", "value": "6057" }, { "label": "Дарт вейдер", "value": "6826" }, { "label": "Дафна гринграсс", "value": "5192" }, { "label": "Дворяне", "value": "7204" }, { "label": "Девушки", "value": "7668" }, { "label": "Девушки монстры", "value": "2231" }, { "label": "Дедушка и внучка", "value": "8400" }, { "label": "Дейви джонс", "value": "8061" }, { "label": "Действие", "value": "1425" }, { "label": "Демон лорд", "value": "153" }, { "label": "Демонология", "value": "2024" }, { "label": "Демоны", "value": "1406" }, { "label": "Дети", "value": "580" }, { "label": "Джарвис", "value": "933" }, { "label": "Джедай", "value": "4442" }, { "label": "Джин", "value": "4024" }, { "label": "Джокер", "value": "3351" }, { "label": "Джон сноу", "value": "7412" }, { "label": "Джоффри баратеон", "value": "3936" }, { "label": "Дзесэй", "value": "678" }, { "label": "Дин винчестер", "value": "6953" }, { "label": "Династии", "value": "2982" }, { "label": "Динозавры", "value": "3666" }, { "label": "Директор", "value": "1417" }, { "label": "Для девушек", "value": "1441" }, { "label": "Дневник", "value": "298" }, { "label": "Добби", "value": "6762" }, { "label": "Добрый мир", "value": "1685" }, { "label": "Договоры с богами", "value": "2152" }, { "label": "Договоры с демонами", "value": "1922" }, { "label": "Доктор", "value": "1991" }, { "label": "Доктор стрэндж", "value": "7634" }, { "label": "Доминирование", "value": "2054" }, { "label": "Дота", "value": "6965" }, { "label": "Доудзюцу", "value": "7133" }, { "label": "Дочь", "value": "3291" }, { "label": "Драко малфой", "value": "46" }, { "label": "Драконы", "value": "282" }, { "label": "Драконы оборотни", "value": "8082" }, { "label": "Древние времена", "value": "7781" }, { "label": "Древний египет", "value": "7614" }, { "label": "Древний китай", "value": "473" }, { "label": "Древний мир", "value": "4" }, { "label": "Другая вселенная", "value": "39" }, { "label": "Другие планеты", "value": "2371" }, { "label": "Другой мир", "value": "2248" }, { "label": "Дружба", "value": "1903" }, { "label": "Друзья детства", "value": "1153" }, { "label": "Духи", "value": "114" }, { "label": "Духовные силы", "value": "1955" }, { "label": "Души", "value": "1212" }, { "label": "Дьявол", "value": "1094" }, { "label": "Дьявольские фрукты", "value": "1564" }, { "label": "Дэдпул", "value": "4399" }, { "label": "Евнух", "value": "6293" }, { "label": "Европейская атмосфера", "value": "5837" }, { "label": "Египет", "value": "528" }, { "label": "Еда", "value": "2056" }, { "label": "Единороги", "value": "437" }, { "label": "Екаи", "value": "655" }, { "label": "Жалкий главный герой", "value": "97" }, { "label": "Жена", "value": "5729" }, { "label": "Женское доминирование", "value": "4622" }, { "label": "Женщина в теле мужчины", "value": "2748" }, { "label": "Женщина кошка", "value": "7513" }, { "label": "Жестокие персонажи", "value": "3153" }, { "label": "Жестокий мир", "value": "1532" }, { "label": "Жестокость", "value": "7880" }, { "label": "Животные", "value": "7488" }, { "label": "Животные компаньоны", "value": "2061" }, { "label": "Жизнь и смерть", "value": "2014" }, { "label": "Жнец", "value": "6288" }, { "label": "Жойен рид", "value": "3926" }, { "label": "Заботливый главный герой", "value": "338" }, { "label": "Закалка тела", "value": "148" }, { "label": "Заклинания", "value": "558" }, { "label": "Заключенные", "value": "3052" }, { "label": "Занпакто", "value": "1102" }, { "label": "Запретная любовь", "value": "8033" }, { "label": "Запутанный сюжет", "value": "1041" }, { "label": "Захват мира", "value": "315" }, { "label": "Зачарованные", "value": "4169" }, { "label": "Звери", "value": "1638" }, { "label": "Зверодевочки", "value": "2006" }, { "label": "Зверолюди", "value": "1018" }, { "label": "Земля", "value": "82" }, { "label": "Злая организация", "value": "7768" }, { "label": "Зло", "value": "1512" }, { "label": "Злодей", "value": "1060" }, { "label": "Злодейка", "value": "2376" }, { "label": "Злой главный герой", "value": "616" }, { "label": "Злые боги", "value": "7109" }, { "label": "Злые персонажи", "value": "3243" }, { "label": "Змей", "value": "5721" }, { "label": "Знаменитости", "value": "1341" }, { "label": "Знание медицины", "value": "1411" }, { "label": "Золушка", "value": "2980" }, { "label": "Зомби", "value": "1743" }, { "label": "Зомби апокалипсис", "value": "912" }, { "label": "Зона 51", "value": "3051" }, { "label": "Зооморфы", "value": "375" }, { "label": "Зорро", "value": "6736" }, { "label": "Зрелые женщины", "value": "1458" }, { "label": "Игра", "value": "663" }, { "label": "Игра на выживание", "value": "2182" }, { "label": "Игровая система", "value": "384" }, { "label": "Игровые элементы", "value": "720" }, { "label": "Извращения", "value": "651" }, { "label": "Измена", "value": "1874" }, { "label": "Изменение характера", "value": "1113" }, { "label": "Изменения внешности", "value": "259" }, { "label": "Изменения личности", "value": "1080" }, { "label": "Изобретения", "value": "126" }, { "label": "Изуку мидория", "value": "6967" }, { "label": "Император", "value": "867" }, { "label": "Империи", "value": "712" }, { "label": "Империя", "value": "1716" }, { "label": "Инвалидность", "value": "2073" }, { "label": "Инквизитор", "value": "143" }, { "label": "Инкуб", "value": "3264" }, { "label": "Инопланетное вторжение", "value": "209" }, { "label": "Инопланетяне", "value": "866" }, { "label": "Интерактив с читателями", "value": "472" }, { "label": "Интересный сюжет", "value": "7374" }, { "label": "Интернет", "value": "739" }, { "label": "Интимные сцены", "value": "3450" }, { "label": "Интрига", "value": "317" }, { "label": "Интриги и заговоры", "value": "1009" }, { "label": "Иные миры", "value": "35" }, { "label": "Исекай", "value": "2979" }, { "label": "Искусственный интеллект", "value": "1900" }, { "label": "Исследование", "value": "1626" }, { "label": "Исторический роман", "value": "573" }, { "label": "Итачи учиха", "value": "4556" }, { "label": "Ичиго", "value": "7254" }, { "label": "Йода", "value": "6829" }, { "label": "Йоруичи", "value": "6755" }, { "label": "Калипсо", "value": "8062" }, { "label": "Каннибализм", "value": "2249" }, { "label": "Капитан америка", "value": "6301" }, { "label": "Каракура", "value": "7473" }, { "label": "Карточная игра", "value": "1557" }, { "label": "Кастиэль", "value": "6954" }, { "label": "Кафе", "value": "3934" }, { "label": "Кацуки бакуго", "value": "7696" }, { "label": "Квесты", "value": "1707" }, { "label": "Киберспорт", "value": "1984" }, { "label": "Кино", "value": "7126" }, { "label": "Китай", "value": "3762" }, { "label": "Кицунэ", "value": "241" }, { "label": "Кланы", "value": "834" }, { "label": "Клоны", "value": "1624" }, { "label": "Книги", "value": "1068" }, { "label": "Книжный червь", "value": "521" }, { "label": "Колдовство", "value": "2681" }, { "label": "колледж", "value": "5058" }, { "label": "Коллекционер", "value": "2588" }, { "label": "Кольцо", "value": "1628" }, { "label": "Коммунисты", "value": "1042" }, { "label": "Коноха", "value": "2827" }, { "label": "Контракт", "value": "4304" }, { "label": "Контроль разума", "value": "485" }, { "label": "Конфеты", "value": "341" }, { "label": "Корейцы", "value": "6535" }, { "label": "Корея", "value": "2443" }, { "label": "Королевская власть", "value": "55" }, { "label": "Королевская семья", "value": "276" }, { "label": "Королевство", "value": "1695" }, { "label": "Короткий рассказ", "value": "239" }, { "label": "Коррупция", "value": "831" }, { "label": "Космическая опера", "value": "2245" }, { "label": "Космические рейнджеры", "value": "5860" }, { "label": "Космос", "value": "329" }, { "label": "Кот", "value": "5171" }, { "label": "Кража навыков", "value": "1159" }, { "label": "Красивая главная героиня", "value": "186" }, { "label": "Красивые женщины", "value": "66" }, { "label": "Красивые персонажи", "value": "5787" }, { "label": "Красивый главный герой", "value": "895" }, { "label": "Крафт", "value": "1599" }, { "label": "Кроссовер", "value": "75" }, { "label": "Ктулху", "value": "920" }, { "label": "Кузнец", "value": "853" }, { "label": "Кукла", "value": "3085" }, { "label": "Кулинария", "value": "2230" }, { "label": "Культивация", "value": "1901" }, { "label": "Культивирование", "value": "1860" }, { "label": "Курама", "value": "5709" }, { "label": "Курилин", "value": "6134" }, { "label": "Кушина узумаки", "value": "5222" }, { "label": "Лавкрафт", "value": "6063" }, { "label": "Лара крофт", "value": "6435" }, { "label": "Легенда о зельде", "value": "5707" }, { "label": "Ленивый главный герой", "value": "1516" }, { "label": "Леон золдик", "value": "7469" }, { "label": "Лес", "value": "6645" }, { "label": "Лечебная магия", "value": "562" }, { "label": "Локи", "value": "1725" }, { "label": "Лоли", "value": "1576" }, { "label": "Лопата", "value": "4989" }, { "label": "Лорд", "value": "8404" }, { "label": "Лориен", "value": "7397" }, { "label": "Лошади", "value": "6110" }, { "label": "Лунатизм", "value": "3520" }, { "label": "Луффи", "value": "274" }, { "label": "Лучник", "value": "1038" }, { "label": "Любовный интерес влюбляется первым", "value": "7753" }, { "label": "Любовный треугольник", "value": "2109" }, { "label": "Любовь", "value": "2297" }, { "label": "Любовь с первого взгляда", "value": "7748" }, { "label": "Любящие родители", "value": "2699" }, { "label": "Люди", "value": "3572" }, { "label": "Люцифер", "value": "5883" }, { "label": "Маг", "value": "780" }, { "label": "Магазин", "value": "4762" }, { "label": "Маги", "value": "58" }, { "label": "Магическая академия", "value": "6788" }, { "label": "Магические звери", "value": "684" }, { "label": "Магические предметы", "value": "1648" }, { "label": "Магический мир", "value": "578" }, { "label": "Магия", "value": "150" }, { "label": "Магия воды", "value": "6450" }, { "label": "Магия воздуха", "value": "7627" }, { "label": "Магия земли", "value": "7626" }, { "label": "Магия и технология", "value": "107" }, { "label": "Магия крови", "value": "7976" }, { "label": "Магия льда", "value": "1379" }, { "label": "Магия огня", "value": "7625" }, { "label": "Магия призыва", "value": "885" }, { "label": "Магия природы", "value": "6226" }, { "label": "Магия стихий", "value": "7673" }, { "label": "Магия тьмы", "value": "3596" }, { "label": "Мадара", "value": "2929" }, { "label": "Мазохизм", "value": "1961" }, { "label": "Мама", "value": "12" }, { "label": "Мама и дочь", "value": "7894" }, { "label": "Мама и сын", "value": "7895" }, { "label": "Манга", "value": "2464" }, { "label": "Манипуляция временем", "value": "932" }, { "label": "Маньяк", "value": "2026" }, { "label": "Маргери тирелл", "value": "3935" }, { "label": "Марионетки", "value": "3175" }, { "label": "Марс", "value": "4013" }, { "label": "Марти стью", "value": "594" }, { "label": "Мастер на все руки", "value": "3189" }, { "label": "Матриархат", "value": "7197" }, { "label": "Мать и сестры", "value": "7946" }, { "label": "Мафия", "value": "353" }, { "label": "Мачеха", "value": "4664" }, { "label": "Мегаполис", "value": "3322" }, { "label": "Медицина", "value": "441" }, { "label": "Медленная романтика", "value": "8383" }, { "label": "Медленное развитие истории", "value": "7462" }, { "label": "Мелиодас", "value": "7224" }, { "label": "Мелодрама", "value": "1507" }, { "label": "Менеджмент", "value": "368" }, { "label": "Мерлин", "value": "3977" }, { "label": "Месть", "value": "1218" }, { "label": "Меч", "value": "48" }, { "label": "Мечники", "value": "969" }, { "label": "Мечта", "value": "527" }, { "label": "Мизуки", "value": "4269" }, { "label": "Микото", "value": "3862" }, { "label": "Милая главная героиня", "value": "134" }, { "label": "Милф", "value": "1987" }, { "label": "Милый главный герой", "value": "2678" }, { "label": "Мимик", "value": "5706" }, { "label": "Мина ашидо", "value": "7695" }, { "label": "Минато намикадзе", "value": "5223" }, { "label": "Мир будущего", "value": "1770" }, { "label": "Мир земли", "value": "8394" }, { "label": "Мир меча и магии", "value": "1271" }, { "label": "Мистер пропер", "value": "565" }, { "label": "Мифические существа", "value": "1878" }, { "label": "Мифы и легенды", "value": "4463" }, { "label": "Младшая сестра", "value": "1523" }, { "label": "Мморпг", "value": "620" }, { "label": "Много главных героев", "value": "1191" }, { "label": "Много крови", "value": "5318" }, { "label": "Много персонажей", "value": "1539" }, { "label": "Множество королевств", "value": "32" }, { "label": "Модерн", "value": "5457" }, { "label": "Мокутон", "value": "4438" }, { "label": "Молоко", "value": "5469" }, { "label": "Монархия", "value": "3590" }, { "label": "Монстры", "value": "307" }, { "label": "Море", "value": "922" }, { "label": "Моритика ринносукэ", "value": "1142" }, { "label": "Мортал комбат", "value": "5861" }, { "label": "Мошенник", "value": "959" }, { "label": "Мрачный мир", "value": "1" }, { "label": "Мужчина в женском теле", "value": "8405" }, { "label": "Музыка", "value": "1183" }, { "label": "Мультивселенная", "value": "7410" }, { "label": "Мурим", "value": "7342" }, { "label": "Мутанты", "value": "2392" }, { "label": "Мутация", "value": "29" }, { "label": "Мясо", "value": "1503" }, { "label": "На реальных событиях", "value": "26" }, { "label": "Навыки", "value": "415" }, { "label": "Нагато узумаки", "value": "5221" }, { "label": "Наемники", "value": "1668" }, { "label": "Назарик", "value": "5369" }, { "label": "Наивный главный герой", "value": "159" }, { "label": "Наложница", "value": "4867" }, { "label": "Наноботы", "value": "2332" }, { "label": "Наруто", "value": "7177" }, { "label": "Наруто и хината", "value": "5766" }, { "label": "Насилие и жестокость", "value": "1440" }, { "label": "Наука", "value": "2150" }, { "label": "Национализм", "value": "5556" }, { "label": "Нацу", "value": "5826" }, { "label": "Нацуки субару", "value": "6656" }, { "label": "Начальная школа", "value": "3920" }, { "label": "Наши дни", "value": "1814" }, { "label": "Не всесильный главный герой", "value": "42" }, { "label": "Не по канону", "value": "1611" }, { "label": "Неверность", "value": "5735" }, { "label": "Невеста", "value": "6011" }, { "label": "Неджи хьюга", "value": "3099" }, { "label": "Недооценённый главный герой", "value": "43" }, { "label": "Нежить", "value": "1949" }, { "label": "Некромаг", "value": "7441" }, { "label": "Некромант", "value": "1914" }, { "label": "Некромантия", "value": "754" }, { "label": "Ненормативная лексика", "value": "160" }, { "label": "Необычные герои", "value": "67" }, { "label": "Нет людей", "value": "7486" }, { "label": "Нетораре", "value": "403" }, { "label": "Нетори", "value": "5393" }, { "label": "Нефилимы", "value": "7764" }, { "label": "Нецензурная лексика", "value": "4912" }, { "label": "Нечисть", "value": "4559" }, { "label": "Ник фьюри", "value": "6304" }, { "label": "Ниндзюцу", "value": "2354" }, { "label": "Ниндзя", "value": "1330" }, { "label": "Новелла", "value": "2105" }, { "label": "Нэко", "value": "147" }, { "label": "Оби ван кеноби", "value": "6830" }, { "label": "Обито учиха", "value": "2814" }, { "label": "Оборотни", "value": "53" }, { "label": "Обратный гарем", "value": "3303" }, { "label": "Овощ", "value": "6098" }, { "label": "Огнестрельное оружие", "value": "3155" }, { "label": "Одержимость", "value": "708" }, { "label": "Один в поле воин", "value": "6498" }, { "label": "Онлайн игра", "value": "1565" }, { "label": "Ооками теппей", "value": "849" }, { "label": "Оригинальные персонажи", "value": "7741" }, { "label": "Орки", "value": "1597" }, { "label": "Оружие", "value": "125" }, { "label": "Основано на видео игре", "value": "602" }, { "label": "Особые способности", "value": "2904" }, { "label": "От бедности к богатству", "value": "901" }, { "label": "От слабого до сильного", "value": "118" }, { "label": "Отель", "value": "2879" }, { "label": "Отец", "value": "3290" }, { "label": "Отношения", "value": "398" }, { "label": "Отношения человек/нечеловек", "value": "7406" }, { "label": "Офис", "value": "3460" }, { "label": "Охотники", "value": "2263" }, { "label": "Оцуцуки", "value": "5101" }, { "label": "Ошейник", "value": "2362" }, { "label": "Ояш", "value": "8048" }, { "label": "Падчерица", "value": "7023" }, { "label": "Падший ангел", "value": "184" }, { "label": "Палач", "value": "852" }, { "label": "Палочка", "value": "2682" }, { "label": "Пандорум", "value": "4360" }, { "label": "Папа и дочь", "value": "7647" }, { "label": "Паразит", "value": "1213" }, { "label": "Параллельный мир", "value": "2092" }, { "label": "Парень", "value": "619" }, { "label": "Паркур", "value": "3391" }, { "label": "Пародия", "value": "898" }, { "label": "Пасхалки", "value": "455" }, { "label": "Паук", "value": "2209" }, { "label": "Пекарь", "value": "5073" }, { "label": "Первая книга", "value": "269" }, { "label": "Первая любовь", "value": "640" }, { "label": "Первый раз", "value": "1465" }, { "label": "Переводы", "value": "24" }, { "label": "Перевоплощение", "value": "1596" }, { "label": "Перевоплощение в игровом мире", "value": "92" }, { "label": "Перемещение в другой мир", "value": "1288" }, { "label": "Перемещение во времени", "value": "146" }, { "label": "Перерождение", "value": "894" }, { "label": "Перерождение в демона", "value": "1111" }, { "label": "Перерождение в дракона", "value": "6867" }, { "label": "Перерождение в злодейку", "value": "5619" }, { "label": "Перерождение в злодея", "value": "749" }, { "label": "Перерождение в ином мире", "value": "109" }, { "label": "Перерождение в монстра", "value": "917" }, { "label": "Перерождений", "value": "335" }, { "label": "Переселение", "value": "813" }, { "label": "Переселение души", "value": "1864" }, { "label": "Перси джексон", "value": "6329" }, { "label": "Пилот", "value": "5521" }, { "label": "Пилюли", "value": "1531" }, { "label": "Пират", "value": "1579" }, { "label": "Пирог", "value": "80" }, { "label": "Писатель", "value": "734" }, { "label": "Пистолеты", "value": "4916" }, { "label": "Письмо", "value": "840" }, { "label": "Питомцы", "value": "3122" }, { "label": "Планомерное развитие событий", "value": "62" }, { "label": "Племянник", "value": "8303" }, { "label": "Пленница", "value": "4897" }, { "label": "Плети", "value": "4839" }, { "label": "Пляж", "value": "4243" }, { "label": "Повар", "value": "658" }, { "label": "Повествование от первого лица", "value": "1054" }, { "label": "Повествование от разных лиц", "value": "600" }, { "label": "Повествование от третьего лица", "value": "2116" }, { "label": "Подавитель", "value": "497" }, { "label": "Подземелье", "value": "798" }, { "label": "Подростки", "value": "636" }, { "label": "Подруга", "value": "5804" }, { "label": "Подчинение", "value": "8343" }, { "label": "Подчинение и унижение", "value": "4500" }, { "label": "Покемоны", "value": "2840" }, { "label": "Полиамория", "value": "1300" }, { "label": "Полигамия", "value": "1336" }, { "label": "Политика", "value": "1313" }, { "label": "Полицейский", "value": "1907" }, { "label": "Полубог", "value": "7170" }, { "label": "Полукровка", "value": "999" }, { "label": "Полулюди", "value": "2273" }, { "label": "Поношенные трусики", "value": "1204" }, { "label": "Попаданец", "value": "2396" }, { "label": "Попаданец в другой мир", "value": "685" }, { "label": "Попаданец в игру", "value": "6466" }, { "label": "Попадание в книгу", "value": "6957" }, { "label": "Постапокалипсис", "value": "1079" }, { "label": "Похищение", "value": "7452" }, { "label": "Поэзия", "value": "1120" }, { "label": "Правитель", "value": "2261" }, { "label": "Превращения в животных", "value": "3410" }, { "label": "Преданный любовный интерес", "value": "2055" }, { "label": "Предательство", "value": "70" }, { "label": "Президент", "value": "4334" }, { "label": "Преступник", "value": "4049" }, { "label": "Преступный мир", "value": "965" }, { "label": "Призрак", "value": "511" }, { "label": "Призыв", "value": "332" }, { "label": "Призыв в другой мир", "value": "781" }, { "label": "Призыв существ", "value": "412" }, { "label": "Приложение на телефоне", "value": "5345" }, { "label": "Принудительный брак", "value": "2954" }, { "label": "Принуждение", "value": "1442" }, { "label": "Принц", "value": "362" }, { "label": "Принцесса", "value": "2403" }, { "label": "Приручение мостров", "value": "2338" }, { "label": "Прислуга", "value": "5185" }, { "label": "Пришельцы", "value": "273" }, { "label": "Проза", "value": "2012" }, { "label": "Прокачка", "value": "1070" }, { "label": "Проклятия", "value": "1347" }, { "label": "Проработанный мир", "value": "1711" }, { "label": "Пророчество", "value": "7762" }, { "label": "Против наркотиков", "value": "8406" }, { "label": "Псайкеры", "value": "3659" }, { "label": "Псионика", "value": "5216" }, { "label": "Психбольница", "value": "6969" }, { "label": "Психические расстройства", "value": "2445" }, { "label": "Психологические травмы", "value": "3418" }, { "label": "Публичный дом", "value": "7860" }, { "label": "Путешествие в другой мир", "value": "10" }, { "label": "Пух", "value": "4286" }, { "label": "Пушечное мясо", "value": "7234" }, { "label": "Пытки", "value": "1756" }, { "label": "Пьяный мастер", "value": "1655" }, { "label": "Пэнси паркинсон", "value": "7411" }, { "label": "Раб", "value": "977" }, { "label": "Рабы", "value": "1240" }, { "label": "Разведение животных", "value": "3990" }, { "label": "Развитие", "value": "208" }, { "label": "Развитие персонажа", "value": "1780" }, { "label": "Развитие поселения", "value": "7203" }, { "label": "Развитие технологий", "value": "1875" }, { "label": "Раздвоение личности", "value": "2062" }, { "label": "Разные расы", "value": "1188" }, { "label": "Разорванная помолвка", "value": "2057" }, { "label": "Разработчик", "value": "2333" }, { "label": "Ранги", "value": "1568" }, { "label": "Ранобэ", "value": "1764" }, { "label": "Расизм", "value": "3554" }, { "label": "Растение", "value": "407" }, { "label": "Реализм", "value": "1180" }, { "label": "Ребенок", "value": "2881" }, { "label": "Ревность", "value": "293" }, { "label": "Революция", "value": "3996" }, { "label": "Реинкарнация", "value": "1302" }, { "label": "Реинкарнация в другом мире", "value": "2180" }, { "label": "Реинкарнация в игровой мир", "value": "304" }, { "label": "Рейджер", "value": "5147" }, { "label": "Религия", "value": "2184" }, { "label": "Рем", "value": "6655" }, { "label": "Ремесленник", "value": "1483" }, { "label": "Ремонт", "value": "5703" }, { "label": "Репликаторы", "value": "3495" }, { "label": "Ресторан", "value": "7519" }, { "label": "Риас гремори", "value": "6950" }, { "label": "Рим", "value": "612" }, { "label": "Риннеган", "value": "4230" }, { "label": "Ритуал", "value": "1233" }, { "label": "Робот", "value": "4011" }, { "label": "Роботы", "value": "467" }, { "label": "Рок ли", "value": "7002" }, { "label": "Рокси", "value": "7380" }, { "label": "Рон уизли", "value": "4279" }, { "label": "Ророноа зоро", "value": "1590" }, { "label": "Росомаха", "value": "1035" }, { "label": "Российская империя", "value": "2146" }, { "label": "Россия", "value": "4246" }, { "label": "Рудеус", "value": "7379" }, { "label": "Руны", "value": "2393" }, { "label": "Русалки", "value": "3127" }, { "label": "Русь", "value": "2016" }, { "label": "Рыцари", "value": "1902" }, { "label": "Рэо хатаке", "value": "2823" }, { "label": "Сабли", "value": "6136" }, { "label": "Сайян", "value": "6802" }, { "label": "Сакура", "value": "2515" }, { "label": "Самец", "value": "1592" }, { "label": "Самураи", "value": "576" }, { "label": "Санса старк", "value": "3925" }, { "label": "Сарказм", "value": "4658" }, { "label": "Саске", "value": "7237" }, { "label": "Сатира", "value": "215" }, { "label": "Сборник", "value": "7367" }, { "label": "Свадьба", "value": "1524" }, { "label": "Сверхсила", "value": "1055" }, { "label": "Свинцовые книги", "value": "5322" }, { "label": "Связывание", "value": "4506" }, { "label": "Священик", "value": "61" }, { "label": "Северус снейп", "value": "5783" }, { "label": "Сёдзе", "value": "2219" }, { "label": "Секты", "value": "1234" }, { "label": "Сельское хозяйство", "value": "787" }, { "label": "Семейный конфликт", "value": "935" }, { "label": "Семья", "value": "728" }, { "label": "Сенджу", "value": "6069" }, { "label": "Серийный убийца", "value": "261" }, { "label": "Сестра", "value": "2342" }, { "label": "Сила глаза", "value": "1019" }, { "label": "Сильная героиня", "value": "7292" }, { "label": "Сильная главная героиня", "value": "1994" }, { "label": "Сильный главный герой", "value": "570" }, { "label": "Сильфиетта", "value": "7381" }, { "label": "Симбиот", "value": "2648" }, { "label": "Сириус блэк", "value": "7655" }, { "label": "Сирота", "value": "297" }, { "label": "Система", "value": "251" }, { "label": "Система уровней", "value": "2174" }, { "label": "Ситх", "value": "1618" }, { "label": "Сказка", "value": "3570" }, { "label": "Скайрим", "value": "4032" }, { "label": "Скайуокер", "value": "6828" }, { "label": "Сквиб", "value": "4101" }, { "label": "Скелет", "value": "1315" }, { "label": "Скрытые способности", "value": "3417" }, { "label": "Скульптор", "value": "1178" }, { "label": "Слабая главная героиня", "value": "5805" }, { "label": "Слабый главный герой", "value": "731" }, { "label": "Славяне", "value": "2168" }, { "label": "Слизерин", "value": "6979" }, { "label": "Слизь", "value": "1095" }, { "label": "Сломанная игрушка", "value": "8396" }, { "label": "Служанка", "value": "3486" }, { "label": "Смартфон", "value": "457" }, { "label": "Смена сущности", "value": "8391" }, { "label": "Смерть", "value": "1779" }, { "label": "Смерть основного персонажа", "value": "1530" }, { "label": "Собаки", "value": "6109" }, { "label": "Соблазн", "value": "7994" }, { "label": "Соблазнение", "value": "2290" }, { "label": "Современность", "value": "568" }, { "label": "Современные знания", "value": "988" }, { "label": "Сожительство", "value": "3026" }, { "label": "Создание армии", "value": "1992" }, { "label": "Создание королевства", "value": "1497" }, { "label": "Создание пилюль", "value": "816" }, { "label": "Создатель", "value": "1045" }, { "label": "Сокровища", "value": "6521" }, { "label": "Сокрытие истинной личности", "value": "2894" }, { "label": "Сома и эрина", "value": "5737" }, { "label": "Соперничество", "value": "7699" }, { "label": "Соседи", "value": "4075" }, { "label": "Сотрудник", "value": "6339" }, { "label": "Социология", "value": "7618" }, { "label": "Спокойная главная героиня", "value": "236" }, { "label": "Спокойный главный герой", "value": "1656" }, { "label": "Спор", "value": "3484" }, { "label": "Спортивное тело", "value": "8317" }, { "label": "Способность кражи", "value": "7784" }, { "label": "Сражения", "value": "23" }, { "label": "Средневековье", "value": "1022" }, { "label": "Сталкер", "value": "1932" }, { "label": "Становление государства", "value": "111" }, { "label": "Старшая школа", "value": "1658" }, { "label": "Стёб", "value": "454" }, { "label": "Стекло", "value": "7453" }, { "label": "Стеснительный персонаж", "value": "152" }, { "label": "Стимпанк", "value": "1894" }, { "label": "Стихи", "value": "1309" }, { "label": "Стратегия", "value": "569" }, { "label": "Строительство", "value": "921" }, { "label": "Студент", "value": "1464" }, { "label": "Студентка", "value": "7518" }, { "label": "Суккубы", "value": "2662" }, { "label": "Супер зрение", "value": "6574" }, { "label": "Супер удача", "value": "489" }, { "label": "Супергерои", "value": "1481" }, { "label": "Суперзлодеи", "value": "2125" }, { "label": "Супермен", "value": "6997" }, { "label": "Суперсилы", "value": "2276" }, { "label": "Существа", "value": "6033" }, { "label": "Сферы", "value": "1077" }, { "label": "Схемы и заговоры", "value": "7116" }, { "label": "Сценарий", "value": "7489" }, { "label": "Счастливый конец", "value": "3293" }, { "label": "Сын", "value": "3297" }, { "label": "Сэм винчестер", "value": "7461" }, { "label": "Сюаньхуа", "value": "2560" }, { "label": "Сюжетные повороты", "value": "7202" }, { "label": "Таблетки для развития", "value": "589" }, { "label": "Таинственное прошлое", "value": "769" }, { "label": "Тайная личность", "value": "8096" }, { "label": "Тайная любовь", "value": "113" }, { "label": "Тайны", "value": "7481" }, { "label": "Тайные отношения", "value": "7450" }, { "label": "Тайцы", "value": "6413" }, { "label": "Танки", "value": "1787" }, { "label": "Творчество", "value": "20" }, { "label": "Тейлор эберт", "value": "3526" }, { "label": "Телекинез", "value": "2203" }, { "label": "Телепортация", "value": "914" }, { "label": "Телохранитель", "value": "723" }, { "label": "Темари", "value": "4810" }, { "label": "Темная магия", "value": "4788" }, { "label": "Темное фэнтези", "value": "1675" }, { "label": "Темные эльфы", "value": "7198" }, { "label": "Тенсейган", "value": "4367" }, { "label": "Тетя", "value": "4194" }, { "label": "Техномагия", "value": "508" }, { "label": "Тиран", "value": "1174" }, { "label": "Титаны", "value": "3308" }, { "label": "Тодороки шото", "value": "5105" }, { "label": "Токио", "value": "5791" }, { "label": "Том реддл", "value": "6652" }, { "label": "Тони старк", "value": "1338" }, { "label": "Тор", "value": "1800" }, { "label": "Тор и локи", "value": "2645" }, { "label": "Торговля", "value": "1637" }, { "label": "Травничество", "value": "221" }, { "label": "Трагическое прошлое", "value": "644" }, { "label": "Трактир", "value": "1918" }, { "label": "Трансмиграция", "value": "1071" }, { "label": "Трансформация", "value": "156" }, { "label": "Трансформеры", "value": "4616" }, { "label": "Тревор филипс", "value": "5427" }, { "label": "Тройняшки", "value": "7169" }, { "label": "Троли", "value": "4250" }, { "label": "Трудолюбивый главный герой", "value": "248" }, { "label": "Тупой главный герой", "value": "3710" }, { "label": "Тьма", "value": "1919" }, { "label": "Тюрьма", "value": "5597" }, { "label": "Тяжёлое детство", "value": "2253" }, { "label": "Убийства", "value": "378" }, { "label": "Убийцы", "value": "1766" }, { "label": "Убийцы драконов", "value": "1484" }, { "label": "Увечья", "value": "3266" }, { "label": "Удача", "value": "6575" }, { "label": "Узумаки", "value": "7579" }, { "label": "Укротитель", "value": "367" }, { "label": "Умения", "value": "531" }, { "label": "Умная главная героиня", "value": "1381" }, { "label": "Умные персонажи", "value": "2756" }, { "label": "Умный главный герой", "value": "2093" }, { "label": "Университет", "value": "2102" }, { "label": "Унижение", "value": "8342" }, { "label": "Уничтожение мира", "value": "81" }, { "label": "Управление временем", "value": "5648" }, { "label": "Уровни", "value": "8" }, { "label": "Усиление", "value": "3549" }, { "label": "Усопп", "value": "6737" }, { "label": "Устроенный брак", "value": "2223" }, { "label": "Усыновление", "value": "395" }, { "label": "Утопия", "value": "4677" }, { "label": "Уход за детьми", "value": "7609" }, { "label": "Учеба в университете", "value": "2797" }, { "label": "Учебное заведение", "value": "1817" }, { "label": "Ученые", "value": "1843" }, { "label": "Учитель", "value": "845" }, { "label": "Учиха", "value": "5348" }, { "label": "Фамильяры", "value": "1471" }, { "label": "Фанатичная любовь", "value": "6721" }, { "label": "Фанаты", "value": "7739" }, { "label": "Фантастический мир", "value": "2414" }, { "label": "Фармацевт", "value": "1706" }, { "label": "Фашисты", "value": "3118" }, { "label": "Феи", "value": "7185" }, { "label": "Фелляция", "value": "5880" }, { "label": "Феминизм", "value": "6527" }, { "label": "Феникс", "value": "2413" }, { "label": "Фенрир", "value": "2740" }, { "label": "Феодализм", "value": "280" }, { "label": "Ферма", "value": "285" }, { "label": "Фехтовальщик", "value": "4685" }, { "label": "Филиппины", "value": "128" }, { "label": "Философия", "value": "1859" }, { "label": "Флафф", "value": "5048" }, { "label": "Флер делакур", "value": "5191" }, { "label": "Флэш", "value": "4667" }, { "label": "Фокусник", "value": "7602" }, { "label": "Фольклор", "value": "4086" }, { "label": "Фугаку", "value": "6161" }, { "label": "Фурри", "value": "6631" }, { "label": "Футбол", "value": "1121" }, { "label": "Фэнтезийный мир", "value": "1556" }, { "label": "Хакер", "value": "475" }, { "label": "Халк", "value": "1196" }, { "label": "Хан нуньен синг", "value": "4817" }, { "label": "Ханма юджиро", "value": "4369" }, { "label": "Хаос", "value": "3117" }, { "label": "Харизматичный главный герой", "value": "2350" }, { "label": "Хатаке какаши", "value": "2820" }, { "label": "Хиддлстон", "value": "5903" }, { "label": "Химавари", "value": "2583" }, { "label": "Хината", "value": "2513" }, { "label": "Хитрый главный герой", "value": "2036" }, { "label": "Хоббит", "value": "6698" }, { "label": "Хогвартс", "value": "5954" }, { "label": "Холодная главная героиня", "value": "6507" }, { "label": "Холодное оружие", "value": "4889" }, { "label": "Холодный главный герой", "value": "2686" }, { "label": "Храм", "value": "2135" }, { "label": "Христианство", "value": "877" }, { "label": "Художественная литература", "value": "2380" }, { "label": "Художница", "value": "518" }, { "label": "Хулиганы", "value": "854" }, { "label": "Цветок", "value": "902" }, { "label": "Цезарь", "value": "1705" }, { "label": "Целители", "value": "4523" }, { "label": "Церковь", "value": "1980" }, { "label": "Цундере", "value": "1078" }, { "label": "Чакра", "value": "1393" }, { "label": "Чат-система", "value": "8407" }, { "label": "Черный юмор", "value": "2868" }, { "label": "Честная главная героиня", "value": "5855" }, { "label": "Честный главный герой", "value": "129" }, { "label": "Читы", "value": "451" }, { "label": "Шантаж", "value": "7175" }, { "label": "Шаринган", "value": "5165" }, { "label": "Шинигами", "value": "4661" }, { "label": "Шиноби", "value": "1227" }, { "label": "Школьная жизнь", "value": "284" }, { "label": "Школьники", "value": "218" }, { "label": "Школьницы", "value": "5946" }, { "label": "Шлюха", "value": "5822" }, { "label": "Шоу-бизнес", "value": "7119" }, { "label": "Шпионы", "value": "4262" }, { "label": "Эволюция", "value": "2040" }, { "label": "Экзорцизм", "value": "676" }, { "label": "Экономика", "value": "121" }, { "label": "Экспансия", "value": "110" }, { "label": "Эксперименты над людьми", "value": "7408" }, { "label": "Элементальная магия", "value": "1264" }, { "label": "Эльфы", "value": "1362" }, { "label": "Эротика", "value": "2053" }, { "label": "Юмор", "value": "7360" }, { "label": "Яды", "value": "201" }, { "label": "Якудза", "value": "4599" }, { "label": "Яндере", "value": "7111" }, { "label": "Rpg", "value": "90" }, { "label": "Star wars", "value": "1985" }, { "label": "Time skip", "value": "824" }, { "label": "Warrior of light", "value": "5289" }], "inputType": filterInputs_1.FilterInputs.Checkbox }, { "key": "fandoms", "label": "Фэндом:", "values": [{ "label": "19 Дней - Один день / 19 Days - One Day", "value": "838" }, { "label": "47-й / Хитмэн: Агент 47 / Наёмный убийца / Hitman", "value": "589" }, { "label": "Абсолютный дуэт / Absolute Duo", "value": "1029" }, { "label": "Аватар (Короля; об Аанге; об Корре) / Avatar", "value": "1889" }, { "label": "Аватар: Легенда о Корре / Avatar legend of Korra", "value": "351" }, { "label": "Аватар: Легенда об Аанге / Avatar: The Legend of Aang / Avatar: The Last Airbender", "value": "303" }, { "label": "Аватар(Фильм, 2009) / Avatar", "value": "19" }, { "label": "Ад Данте(Данте Алигьери) / Dante's Inferno(Dante Alighieri)", "value": "1502" }, { "label": "Азур Лейн / Azur Lane", "value": "1009" }, { "label": "Айон / Aion", "value": "1005" }, { "label": "Аладдин / Aladdin", "value": "502" }, { "label": "Алиса в Стране чудес / Alice in Wonderland", "value": "616" }, { "label": "Альдноа.Зеро / Aldnoah.Zero", "value": "1799" }, { "label": "Амагами СС / Amagami SS", "value": "900" }, { "label": "Амано Мегуми полна любви! / Amano Megumi wa Sukidarake!", "value": "991" }, { "label": "Американские боги / American Gods", "value": "1843" }, { "label": "Американский папаша! / American Dad", "value": "348" }, { "label": "Ангельские ритмы! / Angel Beats!", "value": "880" }, { "label": "Анлимитед: Хёбу Кёске / Zettai Karen Children: The Unlimited - Hyoubu Kyousuke", "value": "74" }, { "label": "Апостол карточек / The Apostle of Cards", "value": "1504" }, { "label": "Арифурэта: сильнейший ремесленник в мире / Arifureta: From Commonplace to World's Strongest", "value": "62" }, { "label": "Аркан: О Паровых Заводах и Магии Обскуры / Arcanum: Of Steamworks and Magick Obscura", "value": "1495" }, { "label": "Аркейн / Arcane: League of Legends", "value": "1154" }, { "label": "Аркнайтс(Games) / Arknights", "value": "1210" }, { "label": "Армелло(Games) / Armello", "value": "1846" }, { "label": "Астра, затерянная в космосе / Kanata no Astra", "value": "1851" }, { "label": "Атака титанов / Атака на титанов / Attack on Titan", "value": "106" }, { "label": "Атлантида: Затерянный мир / Atlantis: The Lost Empire", "value": "985" }, { "label": "Бакуган Отчаянные бойцы / Bakugan Battle Brawlers", "value": "1069" }, { "label": "Банановая рыба / Banana Fish", "value": "1685" }, { "label": "Баскетбол Куроко / Kuroko no basuke", "value": "582" }, { "label": "Баффи - Истребительница вампиров / Buffy the Vampire Slayer", "value": "115" }, { "label": "Башня Бога / Tower of God", "value": "58" }, { "label": "Бездарная Нана / Munou na Nana", "value": "954" }, { "label": "Бездомный бог / Норагами / Noragami", "value": "1014" }, { "label": "Безумные Мотивы / Looney Tunes", "value": "1140" }, { "label": "Безумный азарт / Kakegurui", "value": "334" }, { "label": "Бейблэйд / Beyblade", "value": "921" }, { "label": "Бен - 10 / Ben 10", "value": "475" }, { "label": "Берсерк / Berserk", "value": "479" }, { "label": "Бесконечное лето / Everlasting Summer", "value": "966" }, { "label": "Бесконечный ужас / Terror Infinity", "value": "381" }, { "label": "Бесподобный Воинственный Бог / Peerless Martial God", "value": "419" }, { "label": "Бессмертный Деревенщина(Games) / Immortal Redneck", "value": "1524" }, { "label": "Бесстыжие / Shameless", "value": "1759" }, { "label": "Био шок(Games) / BioShock", "value": "1095" }, { "label": "Блейд / Blade", "value": "1479" }, { "label": "Блич / Bleach", "value": "7" }, { "label": "Бог войны / God Of War", "value": "352" }, { "label": "Бог из машины / Deus Ex", "value": "612" }, { "label": "Боги поступают плохо / Игры богов / Gods Behaving Badly", "value": "301" }, { "label": "Боевая академия города Астериск / Gakusen Toshi Asterisk", "value": "884" }, { "label": "Боевой континент / Combat Continent / Douluo Dalu", "value": "739" }, { "label": "Боевой молот 40-го тысячелетия / WH40K / Warhammer 40,000", "value": "341" }, { "label": "Боевой молот Фэнтезийная битва / Warhammer Fantasy Battles", "value": "1742" }, { "label": "Боевые машины(Games) / BattleTech", "value": "1667" }, { "label": "Боец Баки / Baki the Grappler", "value": "821" }, { "label": "Божественность II: Эго Дракона(Games) / Divinity II: Ego Draconis", "value": "1538" }, { "label": "Божественные Врата / Divine Gate", "value": "1490" }, { "label": "Большая автомобильная кража 5 / GTA V / Grand Theft Auto V", "value": "1139" }, { "label": "Большая автомобильная кража: Сан-Андреас / GTA: SA / Grand Theft Auto: San Andreas", "value": "820" }, { "label": "Большая разница / Far Cry", "value": "939" }, { "label": "Большой куш / Ван Пис / One Piece", "value": "25" }, { "label": "Боруто: Следующие поколения Наруто / Boruto: Naruto Next Generations", "value": "602" }, { "label": "Брак по договоренности с принцессой красных скорпионов / Arranged marriage to the princess of the Red Scorpions", "value": "1386" }, { "label": "Бэтмен за гранью: Наследие / Batman Beyond: Legacy", "value": "1380" }, { "label": "В другом мире со смартфоном / Isekai wa Smartphone to Tomo ni", "value": "947" }, { "label": "В объятиях шлюхи / JK Bitch ni Shiboraretai", "value": "1283" }, { "label": "В ожидании бедности, я собираюсь стать кузнецом / Expecting to Fall into Ruin, I Aim to Become a Blacksmith", "value": "1475" }, { "label": "В Повелителе как Довакин / In Overlord as a Dovahkiin", "value": "1816" }, { "label": "Вакфу / Wakfu", "value": "814" }, { "label": "ВАЛЛ-И / Wally", "value": "801" }, { "label": "Вампир: Маскарад - Родословные / Vampire: The Masquerade Bloodline", "value": "1212" }, { "label": "Вампирелла / Vampirella", "value": "1214" }, { "label": "Варфрейм / Warframe", "value": "967" }, { "label": "Ведьмак / The Witcher", "value": "278" }, { "label": "Великий из бродячих псов / Bungou Stray Dogs", "value": "75" }, { "label": "Великолепный парк Амаги / Amagi Brilliant Park", "value": "813" }, { "label": "Вельзепуз / Вельзевул / Beelzebub", "value": "765" }, { "label": "Веном / Venom", "value": "978" }, { "label": "Веселая ферма / Fun Farm", "value": "1124" }, { "label": "Вечная история / The Neverending Story", "value": "547" }, { "label": "Вечные(Фильм, 2021) / Eternal", "value": "1234" }, { "label": "Виви: Песнь флюоритового глаза / Vivy: Fluorite Eye's Song", "value": "1819" }, { "label": "Викинги / Vikings", "value": "369" }, { "label": "Владелец ранчо со слизью(Games) / Ранчо слизи / Slime Rancher", "value": "1529" }, { "label": "Властелин колец / Lord of the Ring", "value": "254" }, { "label": "Власть книжного червя / Honzuki no Gekokujou", "value": "1399" }, { "label": "Внук Мудрец / Kenjo no Mago", "value": "1260" }, { "label": "Внук Нурарихёна / Nurarihyon no Mago", "value": "66" }, { "label": "Во всеоружии / Overgeared", "value": "1021" }, { "label": "Во тьме(Games) / The Darkness", "value": "938" }, { "label": "Военная хроника маленькой девочки / Сага о злой Тане / The Saga of Tanya the Evil / \tGekijouban Youjo Senki", "value": "1726" }, { "label": "Возвращение в детские годы / Gaki ni Modotte Yarinaoshi!!!", "value": "1031" }, { "label": "Возрождение Серийного Убийцы / Rebirth Of A Serial Killer", "value": "1358" }, { "label": "Воинственный Бог Асура / Martial God Asura", "value": "771" }, { "label": "Война будущего / The Tomorrow War", "value": "1174" }, { "label": "Война Любовь Снег / War Love Snow", "value": "1417" }, { "label": "Волейбол! / Haikyuu!!", "value": "697" }, { "label": "Волчонок / Teen Wolf", "value": "795" }, { "label": "Волшебная Девушка Спецоперация Аска / Magical Girl Spec-Ops Asuka", "value": "1470" }, { "label": "Волшебник-воин Орфен / Majutsushi Orphen Hagure Tabi: Kimluck-hen", "value": "1128" }, { "label": "Волшебники / The Magicians", "value": "1314" }, { "label": "Волшебный учитель Нэгима! / Negima!: Magister Negi Mag", "value": "1777" }, { "label": "Воля второго цикла мироздания. / Will of the second cycle of the Worldifice.", "value": "1036" }, { "label": "Воспитание хозяина / Yours to Claim", "value": "839" }, { "label": "Восставший против неба / Against the Gods", "value": "957" }, { "label": "Восстание стражей / Хранители снов / Rise of the Guardians", "value": "1488" }, { "label": "Восхождение в Голливуде / I'm in Hollywood", "value": "1237" }, { "label": "Восхождение героя щита / The Rising of the Shield Hero", "value": "103" }, { "label": "Врата Штейна / Steins: Gate", "value": "1044" }, { "label": "Врата: там бьются наши воины / Gate: Jieitai Kanochi nite, Kaku Tatakaeri", "value": "727" }, { "label": "Время / In Time", "value": "542" }, { "label": "Всегда вялый Танака-кун / Tanaka-kun wa Itsumo Kedaruge", "value": "1082" }, { "label": "Всего лишь восьмой сын? Я с этим не смирюсь! / Hachinan tte, Sore wa Nai Deshou! / Eighth son, I don’t think so!", "value": "1473" }, { "label": "Вселенная Марвел / Marvel Universe / Marvel Comics", "value": "6" }, { "label": "Вселенная монстров / Monsterverse / Monster Verse", "value": "905" }, { "label": "Вселенная Стивена / Steven universe", "value": "573" }, { "label": "Вселенная Стрелы / Arrowverse", "value": "488" }, { "label": "Вселенная Тип Луны(Игровая компания) / Universe Type Moon", "value": "1221" }, { "label": "Вселенная DC / DC Universe / DC Comics", "value": "36" }, { "label": "Выпадение радиоактивных осадков / Fallout", "value": "55" }, { "label": "Выращивание онлайн / Cultivation Online", "value": "1252" }, { "label": "Галактическая секс-звезда / Galaxy Sex Star", "value": "1539" }, { "label": "Гало(Games) / Halo", "value": "1338" }, { "label": "Ганц / Gantz", "value": "256" }, { "label": "Гарем рабов в лабиринте другого мира / Slave Harem in the Labyrinth of the Other World", "value": "1853" }, { "label": "Гарри Поттер / Harry Potter", "value": "1" }, { "label": "Гвен-паук / Spider-Gwen", "value": "920" }, { "label": "Генерал маньяк с его сумасшедшей системой / The Maniacal General with his Crazy System", "value": "1356" }, { "label": "Генерал, вы вправе уйти. / General, You May Leave Now", "value": "1385" }, { "label": "Геншин Импакт / Genshin Impact", "value": "689" }, { "label": "Геркулес / Hercules", "value": "721" }, { "label": "Герои и замки / Heroes & Castles", "value": "940" }, { "label": "Герои меча и магии / Heroes of Might and Magic", "value": "1002" }, { "label": "Герои(телесериал) / Heroes", "value": "864" }, { "label": "Гильгамеш / Gilgamesh", "value": "1143" }, { "label": "Гинтама / Gintama", "value": "129" }, { "label": "Глубина(Фильм, 2002) / Below", "value": "1186" }, { "label": "Гнев Асуры / Asura's wrath", "value": "100" }, { "label": "Годзилла / Godzilla", "value": "922" }, { "label": "Голодные игры / The Hunger Games", "value": "859" }, { "label": "Горец / Highlander", "value": "1761" }, { "label": "Горожане(Games) / Townsmen", "value": "1599" }, { "label": "Госпожа Кагуя: в любви как на войне / Kaguya sama: Love is war", "value": "533" }, { "label": "Готика / Gothic", "value": "418" }, { "label": "Готов ли ты влюбиться в извращенку до тех пор, пока она милая? / Hentai demo Suki ni Natte Kuremasu ka", "value": "1383" }, { "label": "Гоэтия / Гоетия / Yοητεία / Ars Goetia", "value": "772" }, { "label": "Гравити Фолз / Gravity Falls", "value": "491" }, { "label": "Граница пустоты / Kara no Kyoukai", "value": "1101" }, { "label": "Гриффины / Family Guy", "value": "349" }, { "label": "Гром над небом / Thunder over the sky", "value": "793" }, { "label": "Гуррен-Лаганн / Tengen Toppa Gurren Lagann", "value": "719" }, { "label": "Да будет благословенен этот прекрасный мир! / Konosuba / Kono Subarashii Sekai ni Shukufuku wo!", "value": "82" }, { "label": "Да Здравствует Призыв! / Long Live Summons!", "value": "948" }, { "label": "Да, я паук, и что с того? / So I'm a Spider, So What? / Kumo Desu ga, Nani ka?", "value": "910" }, { "label": "Данганронпа / Danganronpa", "value": "972" }, { "label": "Две звезды Онмёджи / Sousei no Onmyouji", "value": "1108" }, { "label": "Дворянство / Благородство / Noblesse", "value": "636" }, { "label": "Девочка-волшебница Мадока Магика / Mahou Shoujo Madoka Magica", "value": "1412" }, { "label": "Девочка, которая видит это / Mieruko-chan", "value": "1645" }, { "label": "Декстер(телесериал) / Dexter", "value": "1543" }, { "label": "Демон Бездны всех царств / Abyss Demon of All Realms", "value": "1419" }, { "label": "Демоны старшей школы / High School DxD", "value": "8" }, { "label": "День независимости(Фильм, 1996) / Independence Day", "value": "850" }, { "label": "Детектив Конан / Detective Conan", "value": "1554" }, { "label": "Дети индиго из другого мира / Mondaiji-tachi ga isekai kara kuru sô desu yo", "value": "1484" }, { "label": "Джаггед Альянс 2: Агония Власти(Games) / Jagged Alliance 2", "value": "1668" }, { "label": "Джессика Джонс / Marvel's Jessica Jones", "value": "1817" }, { "label": "Джон Уик / John Wick", "value": "388" }, { "label": "Дисней / The Walt Disney Company", "value": "503" }, { "label": "Для тебя, Бессмертный / Fumetsu no Anata e / To Your Eternity", "value": "1802" }, { "label": "Дневник Будущего / Mirai Nikki", "value": "368" }, { "label": "Дневники вампира / The Vampire Diaries", "value": "160" }, { "label": "Доблесть рыцаря-неудачника / Chivalry of a Failed Knight", "value": "1462" }, { "label": "Добро пожаловать в ад, Ирума / Welcome to Demon School! Iruma-kun", "value": "261" }, { "label": "Добро пожаловать в класс превосходства / Classroom of the Elite", "value": "122" }, { "label": "Добро пожаловать! В лес похотливых эльфов! / Youkoso! Sukebe Elf no Mori e", "value": "1034" }, { "label": "Добывать ремесло / Майнкрафт / Minecraft", "value": "102" }, { "label": "Доктор Кто / Doctor Who", "value": "277" }, { "label": "Доктор Стоун / Dr. Stone", "value": "720" }, { "label": "Доля секунды: скорость / Split - second: velocity", "value": "890" }, { "label": "Дом кролика / Кофейня "Кроличий домик" / Gochuumon wa Usagi Desu ka?", "value": "642" }, { "label": "Домашний очаг / Hearthstone: Heroes of Warcraft / Hearthstone", "value": "934" }, { "label": "Домекано / Domestic Na Kanojo", "value": "632" }, { "label": "Дорогой звёзд / Звёздное преобразование / Stellar Transformation / Xing Chen Bian", "value": "1155" }, { "label": "Доспехи Бога 2: Операция Кондор / Armour of God II: Operation Condor", "value": "1829" }, { "label": "Дота 2 / Dota 2", "value": "1105" }, { "label": "Дофус / Dofus", "value": "817" }, { "label": "Дракенгард / Drakengard / Drag-On Dragoon", "value": "919" }, { "label": "Дракон-горничная госпожи Кобаяси / Kobayashi-san Chi no Maid Dragon", "value": "673" }, { "label": "Дракон-сама из семьи Касумигаока / Dragon-sama of the Kasumigaoka Family", "value": "1458" }, { "label": "Драконий жемчуг Зет / Dragon Ball Z", "value": "307" }, { "label": "Дракониум Онлайн / Draconic Online", "value": "1360" }, { "label": "Дракула / Dracula", "value": "709" }, { "label": "Древнегреческая мифология / Ancient Greek mythology", "value": "1159" }, { "label": "Дре́вние / Первородные / The Originals", "value": "863" }, { "label": "Древние свитки / The Elder Scrolls", "value": "428" }, { "label": "Древние свитки: Скайрим / TES: Skyrim", "value": "337" }, { "label": "Другой мир / Underworld", "value": "480" }, { "label": "Друид с Сеульской станции / Seoul Station Druid", "value": "1178" }, { "label": "Дьявол / Диабло / Diablo", "value": "1787" }, { "label": "Дьявол может плакать / Devil May Cry / DMC", "value": "339" }, { "label": "Дьявол Юраги-су / The Devil of Yuragi-sou", "value": "431" }, { "label": "Дьявол II(Games) / Диабло II / Diablo II", "value": "1055" }, { "label": "Дэдпул / Deadpool", "value": "810" }, { "label": "Дэнни-призрак / Danny Phantom", "value": "109" }, { "label": "Евангелион / Neon Genesis Evangelion", "value": "583" }, { "label": "Единство семи магов / Тринити: Семь Магов / Trinity Seven", "value": "442" }, { "label": "Еженедельный прыжок сёнэн / Weekly Shōnen Jump", "value": "1629" }, { "label": "Ёрмунганд / Jormungand", "value": "77" }, { "label": "Жажда скорости / Need For Speed", "value": "1493" }, { "label": "Железный человек / Iron Man", "value": "710" }, { "label": "Жемчуг дракона / Dragon Ball", "value": "309" }, { "label": "Женщина-Халк(телесериал) / She-Hulk: Attorney at Law", "value": "1593" }, { "label": "Жизнь девушки в игровом мире / A Girl’s Life In A Gaming World", "value": "1406" }, { "label": "Жизнь после / Days Gone", "value": "1279" }, { "label": "За гранью / Beyond the Boundary", "value": "357" }, { "label": "Загипнотизировать Семью / Kyonyuu Kazoku Saimin", "value": "1032" }, { "label": "Закон Уэки / The Law of Ueki", "value": "790" }, { "label": "Закулисье / Backrooms", "value": "1827" }, { "label": "Зачарованные / Charmed", "value": "113" }, { "label": "Защитники / Defenders", "value": "1832" }, { "label": "Защитница Химари / Omamori Himari", "value": "279" }, { "label": "Звёздная принцесса и силы зла\t / Стар против сил зла / Star vs. The Forces of Evil", "value": "782" }, { "label": "Звёздное дитя / Oshi no Ko", "value": "1903" }, { "label": "Звёздное ремесло / StarCraft", "value": "386" }, { "label": "Звездные Войны / Star Wars", "value": "40" }, { "label": "Звёздные войны: Войны клонов - Все типы носителей(мультсериал, 2008) / Star Wars: The Clone Wars", "value": "1182" }, { "label": "Звёздные врата / Stargate", "value": "770" }, { "label": "Звёздные врата: Атлантида / Stargate: Atlantis", "value": "1097" }, { "label": "Звездный путь / Стартрек / Star Trek", "value": "849" }, { "label": "Зверополис / Zootopia", "value": "1449" }, { "label": "Зеленая Жизнь / Green Life", "value": "1196" }, { "label": "Зеленый фонарь / The Green Lantern", "value": "1222" }, { "label": "Зетмен / Zetman", "value": "1191" }, { "label": "Игра в кальмара(телесериал) / Squid game", "value": "1065" }, { "label": "Игра престолов / Game of Thrones", "value": "22" }, { "label": "Игрок / The Gamer", "value": "126" }, { "label": "Идеальная судьба / The Perfect Destiny", "value": "781" }, { "label": "Идолмастер / The Idolmaster", "value": "807" }, { "label": "Иерихон Клайва Баркера / Иерихон / Clive Barker’s Jericho /Jericho", "value": "320" }, { "label": "Извивающийся дракон / Coiling Dragon", "value": "692" }, { "label": "Изгнаные королевства РПГ / Exiled Kingdoms RPG", "value": "1375" }, { "label": "Импульс Валькирии: Сирена / Варукири Дораиву: Сирена / Valkyrie Drive: Mermaid", "value": "1736" }, { "label": "Индекс волшебства / A Certain Magical Index", "value": "68" }, { "label": "Инуяша - Пес-демон / InuYasha", "value": "481" }, { "label": "Искусственный отбор / Triage X", "value": "1037" }, { "label": "Истинный мир боевых искусств / Zhenwu Shijie / True Martial World", "value": "867" }, { "label": "История монстров / Monogatari", "value": "911" }, { "label": "История о второстепенном персонаже который стал игроком в другой игре. / The story is about a minor character who became a player in another game.", "value": "868" }, { "label": "Кабанери железной крепости / Koutetsujou no Kabaneri", "value": "1494" }, { "label": "Каждый раз, когда я сплю, моя душа покидает мое тело / Every Day I Sleep, My Soul Goes Out of My Body", "value": "1048" }, { "label": "Как воспитать героиню из обычной девушки / Saenai Heroine no Sodatekata", "value": "1637" }, { "label": "Как игрок глупой FPS попал в иной мир / Как дурачок из стрелялки в другой мир попал / Manuke na FPS Player ga Isekai e Ochita Baai", "value": "746" }, { "label": "Как приручить дракона / How to Train Your Dragon", "value": "687" }, { "label": "Капитан Америка / Captain America", "value": "1425" }, { "label": "Капитан Марвел(Фильм, 2019) / Captain Marvel", "value": "1594" }, { "label": "Каратель / The Punisher", "value": "387" }, { "label": "Касл / Castle", "value": "389" }, { "label": "Касльвания / Castlevania", "value": "1215" }, { "label": "Катаклизм: Тёмные дни впереди / DDA / Cataclysm: Dark Days Ahead", "value": "680" }, { "label": "Квайзер со Стигматом / Адепт Святого Знака / The Qwaser of Stigmata", "value": "72" }, { "label": "Квартет из альтернативного мира / Isekai Quartet", "value": "1801" }, { "label": "Квест Девушки-монстра / Monster Girl Questt", "value": "928" }, { "label": "Квест титана(Games) / Титанический квест / Titan Quest", "value": "1483" }, { "label": "Кенши(Games) / Kenshi", "value": "1230" }, { "label": "Киберпанк 2077 / Cyberpunk 2077", "value": "416" }, { "label": "Ким Пять-с-плюсом / Kim Possible", "value": "436" }, { "label": "Киру ра Киру / Круши Кромсай / Убей или умри / Kill la Kill", "value": "763" }, { "label": "Класс убийц / Assassination classroom", "value": "610" }, { "label": "Клеймор / Claymore", "value": "110" }, { "label": "Клинок зла / Evil Blade / Übel Blatt", "value": "722" }, { "label": "Клинок королевы / Queen’s Blade", "value": "757" }, { "label": "Клинок Маню: Тайна сисечного свитка / Manyuu Hiken-chou", "value": "501" }, { "label": "Клинок рассекающий демонов / Demon Slayer: Kimetsu no Yaiba", "value": "21" }, { "label": "Клуб Винкс / Winx Club", "value": "397" }, { "label": "Книга джунглей / The Jungle Book", "value": "1688" }, { "label": "Князь тьмы с задней парты / Demon King Daimao / Ichiban Ushiro no Daimaou", "value": "1207" }, { "label": "Код Гиас / Code Geass", "value": "340" }, { "label": "Код Квалидеи / Qualidea Code", "value": "76" }, { "label": "Кольцо Элдена / Elden Ring", "value": "1408" }, { "label": "Комната / The Room", "value": "889" }, { "label": "Конь и клинок: Боевой отряд(Games) / Mount and Blade:Warband", "value": "1477" }, { "label": "Королевства Сердец / Kingdom Hearts", "value": "407" }, { "label": "Короли крестоносцев / Crusader kings", "value": "572" }, { "label": "Король бойцов / The King of Fighters", "value": "1378" }, { "label": "Король лев / The Lion king", "value": "1705" }, { "label": "Король Шаманов / Shaman King", "value": "744" }, { "label": "Корона греха / Guilty Crown", "value": "1007" }, { "label": "Корпорация лоботомии / Lobotomy corporation", "value": "852" }, { "label": "Космические рейнджеры(Games) / Space Rangers", "value": "1508" }, { "label": "Кошечка из Сакурасо / Sakurasou no Pet na Kanojo", "value": "605" }, { "label": "Красавица и чудовище / Beauty and the Beast", "value": "1765" }, { "label": "Красная угроза 3 / Command & Conquer: Red Alert 3", "value": "742" }, { "label": "Красный, Белый, Черный, Желтый / RWBY", "value": "131" }, { "label": "Кредо убийцы / Assassin's Creed", "value": "690" }, { "label": "Кризис / Crysis", "value": "1734" }, { "label": "Крушитель / The Breaker", "value": "1080" }, { "label": "Кунг-фу панда / Kung Fu Panda", "value": "831" }, { "label": "Кэйон! / K-On!", "value": "1785" }, { "label": "Кэнган Асура / Kengan Asura", "value": "726" }, { "label": "Лаборатория Декстера / Dexter Lab", "value": "639" }, { "label": "Лавкрафт / Говард Филлипс Лавкрафт / Howard Phillips Lovecraft", "value": "1259" }, { "label": "Легенда о восьми псах востока / Hakkenden: Touhou Hakken Ibun", "value": "1699" }, { "label": "Легенда о Зельде / The Legend of Zelda", "value": "870" }, { "label": "Легенда о Короле Драконов / Legend of the Dragon King", "value": "623" }, { "label": "Легенда о Легендарных Героях / Densetsu no Yuusha no Densetsu", "value": "193" }, { "label": "Легион Супергероев / The Legion of Super-Heroes", "value": "450" }, { "label": "Леди Баг и Супер-Кот / Miraculous Ladybug", "value": "327" }, { "label": "Летняя сага / Summertime Saga", "value": "1441" }, { "label": "Лига Легенд / League of Legends", "value": "65" }, { "label": "Линия фронта для девочек / Girls' Frontline", "value": "1686" }, { "label": "Литературный клуб Доки Доки / Литературный клуб / Doki Doki literature club!", "value": "819" }, { "label": "Лорд героев(Games) / Lord of Heroes", "value": "1771" }, { "label": "Лорд человечества / Lord of the People", "value": "1896" }, { "label": "Лориенская Сага / Lorien Legacies", "value": "521" }, { "label": "Любимая жена господина генерального директора / Mr.CEO's Beloved Wife", "value": "1389" }, { "label": "Любовные неприятности / To love ru", "value": "353" }, { "label": "Любовь, Деньги, Рок-н-Ролл / Love, Money, Rock'n'Roll", "value": "1890" }, { "label": "Люди в чёрном(Фильм) / Men in Black", "value": "1193" }, { "label": "Люди Икс / X-Men", "value": "371" }, { "label": "Лютер Строуд Сага / The Luther Strode Saga", "value": "1700" }, { "label": "Люцифер(телесериал) / Lucifer", "value": "681" }, { "label": "Маг на полную ставку / Quanzhi Fashi", "value": "291" }, { "label": "Маг смерти не желающий четвертой реинкарнации / The Death Mage Who Doesn’t Want a Fourth Time", "value": "1775" }, { "label": "Маг-целитель: Новый старт / Kaifuku Jutsushi no Yarinaoshi", "value": "1311" }, { "label": "Маги: Волшебный лабиринт / Magi: The Labyrinth of Magic", "value": "1581" }, { "label": "Магистр дьявольского культа / The Grandmaster of Demonic Cultivation", "value": "608" }, { "label": "Магическая академия Атараксия: Гибрид х Сердце / Hybrid x Heart Magias Academy Ataraxia", "value": "1898" }, { "label": "Магическая битва / Magic Battle / Jujutsu Kaisen", "value": "671" }, { "label": "Маленькие кошмары 2 / Little Nightmares 2", "value": "601" }, { "label": "Малефисента / Maleficent", "value": "775" }, { "label": "Мальчик с оленьими рогами / Сладкоежка / Sweet tooth", "value": "1772" }, { "label": "Маска / The mask", "value": "847" }, { "label": "Мастер Урадана / The Master of Uradan", "value": "1395" }, { "label": "Мастера меча онлайн / Sword Art Online / SAO", "value": "324" }, { "label": "Межвидовые Рецензенты / Interspecies Reviewers", "value": "1555" }, { "label": "Менеджер среднего звена Тонэгава / Chuukan Kanriroku Tonegawa", "value": "1084" }, { "label": "Мерлин / Merlin", "value": "486" }, { "label": "Мертвы к Рассвету / Dead by Daylight", "value": "899" }, { "label": "Мертвый или живой / Dead or Alive", "value": "1563" }, { "label": "Мертвый остров / Dead Island", "value": "124" }, { "label": "Месть Масамуне-куна! / Masamune-kun no Revenge", "value": "571" }, { "label": "Метавселенная Рудазова / Rudazov's Metauniverse", "value": "1211" }, { "label": "Метро 2033(Games) / Metro 2033", "value": "1584" }, { "label": "Милый во Франксе / Любимый во Франксе / Darling in the Franxx", "value": "942" }, { "label": "Мир боевых искусств / 武极天下 / Wuji Tianxia / Martial World", "value": "620" }, { "label": "Мир зомби / Zombie World", "value": "1880" }, { "label": "Мир Льда и Пламени / The World of Ice & Fire", "value": "415" }, { "label": "Мир приключений Джеки Чана(мультсериал, 2000) / ackie Chan Adventures", "value": "1544" }, { "label": "Мир танков / WoT Blitz / World of Tanks Blitz", "value": "525" }, { "label": "Мир Тьмы / World of Darkness", "value": "145" }, { "label": "Мир Эрастай / The World of Erasthay", "value": "1836" }, { "label": "Мир Warcraft / World of Warcraft", "value": "89" }, { "label": "Мировая война Z / Война миров Z / World War Z", "value": "1217" }, { "label": "Моана / Moana", "value": "686" }, { "label": "Моб психо 100 / Mob Psycho 100", "value": "866" }, { "label": "Мобильные легенды: Бах-Бах(Games) / Mobile Legends: Bang Bang", "value": "1497" }, { "label": "Могучие рейнджеры / Power Rangers", "value": "1486" }, { "label": "Может, я встречу тебя в подземелье? / DanMachi", "value": "9" }, { "label": "Мой жених сбежал / My Groom Ran Away", "value": "1047" }, { "label": "Мой маленький пони / My Little Pony", "value": "655" }, { "label": "Мой маленький пони: Дружба — это чудо / My Little Pony: Friendship is Magic", "value": "658" }, { "label": "Мой шумный дом(мультсериал, 2016) / The Loud House", "value": "1467" }, { "label": "Монстер Хай / Monster High", "value": "1012" }, { "label": "Моя возлюбленная чпокается со всеми / Kanojo wa Dare to demo Sex Sur", "value": "1274" }, { "label": "Моя геройская академия / Boku no Hero Academia", "value": "69" }, { "label": "Моя девушка - зомби / My Girlfriend is a Zombie", "value": "754" }, { "label": "Моя жена - красивый генеральный директор / My Wife is a Beautiful CEO", "value": "1025" }, { "label": "Моя жена — президент студенческого совета! / My Wife is the Student Council President / Okusama ga Seitokaichou", "value": "241" }, { "label": "Моя Марвел Академия / My marvel academia", "value": "696" }, { "label": "Моя первая модница / Hajimete no Gal", "value": "1835" }, { "label": "Моя Супер-Бывшая / My Super Ex-Girlfriend", "value": "1828" }, { "label": "Мрачный рассвет / Grim Dawn", "value": "1113" }, { "label": "Мстители / The Avengers", "value": "1747" }, { "label": "Мстители. Эра Альтрона / The Avengers. Age of Ultron", "value": "784" }, { "label": "Мулан / Mulan", "value": "706" }, { "label": "Мы не можем учится / Bokutachi wa Benkyou ga Dekinai", "value": "912" }, { "label": "Мэй Гунцин / Mei Gongqing", "value": "753" }, { "label": "Наблюдать / Overwatch", "value": "607" }, { "label": "Надпись / Inscription", "value": "1718" }, { "label": "Нам Ён / Nam Yeon", "value": "1188" }, { "label": "Наруто / Naruto", "value": "3" }, { "label": "Начало после конца / The Beginning After The End", "value": "888" }, { "label": "Не голодай / Don't Starve", "value": "274" }, { "label": "Не издевайся надо мной, Нагаторо / Ijiranaide / Nagatoro-san Don't Toy with Me, Miss Nagatoro", "value": "1041" }, { "label": "Не люблю боль, так что вкачаю все в защиту / Itai no wa Iya nano de Bougyoryoku ni Kyokufuri Shitai to Omoimasu", "value": "517" }, { "label": "Не моя вина, что я непопулярна! / Watashi ga Motenai no wa Dou Kangaetemo Omaera ga Warui", "value": "1381" }, { "label": "Небесный замок Лапута / Tenkuu no Shiro Laputa", "value": "1109" }, { "label": "Невероятные приключения ДжоДжо / JoJo's Bizarre Adventure", "value": "20" }, { "label": "Негодник, которому не снилась девочка-зайка / Rascal Does Not Dream of Bunny Girl Senpai", "value": "1897" }, { "label": "Негодяй спасает мужскую роль / The Villain Saves the Male Lead", "value": "1224" }, { "label": "Неизвестен / Persona", "value": "205" }, { "label": "Некий магический индекс / To Aru Majutsu no Index", "value": "562" }, { "label": "Некий научный акселератор / Toaru Kagaku no Accelerator", "value": "1487" }, { "label": "Ненасытный Берсерк / Boushoku no Berserk: Ore dake Level to Iu Gainen wo Toppa suru the Comic", "value": "1195" }, { "label": "Необъятные небеса / Infinite Stratos / IS", "value": "280" }, { "label": "Необъятный океан / Grand Blue", "value": "531" }, { "label": "Непревзойденная / Master Piece The Animation", "value": "712" }, { "label": "Непризнанный школой владыка демонов / Maou Gakuin no Futekigousha", "value": "1476" }, { "label": "Непутевый ученик в школе магии / Mahouka Koukou No Rettousei", "value": "982" }, { "label": "Непутевый ученик в школе магии / The Irregular at Magic High School", "value": "630" }, { "label": "Несокрушимая механическая кукла / Machine-Doll wa Kizutsukanai", "value": "1030" }, { "label": "Несправедливость / Injustice", "value": "1026" }, { "label": "Нет игры - нет жизни / Без игры жизни нет / No Game No Life", "value": "718" }, { "label": "Неуязвимый / Invincible", "value": "702" }, { "label": "НиоХ(Games) / NioH", "value": "1465" }, { "label": "Новый завет Владыки тьмы / Shinmai Maou no Testament", "value": "1432" }, { "label": "Ну и ну! Земляничные яйца / I My Me! Strawberry Eggs", "value": "1485" }, { "label": "Нулевой Уровень Целомудрия / Teisou Kannen Zero", "value": "1209" }, { "label": "О моём перерождении в меч / Tensei Shitara Ken deshita", "value": "53" }, { "label": "О моём перерождении в слизь / Tensei shitara Slime Datta Ken", "value": "64" }, { "label": "О моя Богиня / Aa! Megami-sama! / Ah! My Goddess", "value": "915" }, { "label": "Обесчещенный(Games) / Dishonored", "value": "1073" }, { "label": "Обитель зла / Resident Evil", "value": "86" }, { "label": "Огненная эмблема / Fire Emblem", "value": "1615" }, { "label": "Огненная эмблема: Пробуждение / Fire Emblem: Awakening", "value": "1616" }, { "label": "Огненная эмблема: Три Дома / Fire Emblem:Three Houses", "value": "1716" }, { "label": "Одинокий рокер! / Bocchi the Rock!", "value": "1904" }, { "label": "Одному лишь Богу ведомый мир / World God Only Knows", "value": "1248" }, { "label": "Она становится гламурной после расторжения помолвки / She gets glamorous after the engagement is annulled", "value": "1404" }, { "label": "Орк-рубака / Orc Grunt", "value": "779" }, { "label": "Освободите эту ведьму / Release that witch", "value": "994" }, { "label": "Острые козырьки(телесериал) / Peaky Blinders", "value": "1177" }, { "label": "От заката до рассвета! / From Dusk till Dawn!", "value": "1416" }, { "label": "Отброс из семьи графа / Trash of counts family", "value": "853" }, { "label": "Отряд самоубийц / The Suicide Squad", "value": "1844" }, { "label": "Отчаянные домохозяйки / Desperate Housewives", "value": "1011" }, { "label": "Отчет о буйстве духов / YuYu Hakusho", "value": "1008" }, { "label": "Охота демонического короля на свою жену / Xie Wang Zhui Qi", "value": "1737" }, { "label": "Охотник х Охотник / Hunter x Hunter", "value": "101" }, { "label": "Охотницы на демонов / Taimanin Asagi", "value": "1463" }, { "label": "Очень приятно Бог! / Kamisama Hajimemashita", "value": "1585" }, { "label": "Очень Странные Дела(телесериал) / Stranger Things", "value": "1834" }, { "label": "ПАЗЛ / PUZZLE", "value": "1762" }, { "label": "Палач Рока / DOOM", "value": "132" }, { "label": "Параграф 78(Фильм) / Paragraph 78", "value": "923" }, { "label": "Паразит: Учение о жизни / Parasyte: The Maxim", "value": "1176" }, { "label": "Пастырь(Фильм, 2011) / Priest", "value": "1173" }, { "label": "Пацаны / The Boys", "value": "133" }, { "label": "Первый детский сад во вселенной / The First Kindergarten in the Universe", "value": "1049" }, { "label": "Перевозчик / Le Transporteur", "value": "365" }, { "label": "Передающийся через кровь / Bloodborne", "value": "229" }, { "label": "Пережить / Outlast", "value": "645" }, { "label": "Перерождение / Rebirth", "value": "550" }, { "label": "Перерождение бессмертного горожанина-культиватора / Rebirth – City Cultivation / Rebirth of the Urban Immortal Cultivator", "value": "843" }, { "label": "Перерождение в монстра / Re:Monster", "value": "85" }, { "label": "Перестрой мир / Sekai O Sai Kochiku / Rebuild World", "value": "961" }, { "label": "Период полураспада(Valve) / Half-Life", "value": "895" }, { "label": "Перси Джексон / Percy Jackson", "value": "308" }, { "label": "Персона 5 / Persona 5", "value": "1614" }, { "label": "Печать ветра / Kaze no Stigma", "value": "845" }, { "label": "Пик боевых искусств / Martial Peak", "value": "414" }, { "label": "Пираты Карибского моря / Pirates of the Caribbean", "value": "932" }, { "label": "Пираты черной лагуны / Black Lagoon", "value": "621" }, { "label": "Пламенная бригада пожарных / Fire Force / Enen no Shouboutai", "value": "841" }, { "label": "Пламя бесчисленых невзгод / I' m really not demon god's lackey", "value": "1452" }, { "label": "Планетарная аннигиляция / Planetary Annihilation", "value": "487" }, { "label": "Плоскостной пейзаж: Мучение / Planescape: Torment", "value": "1768" }, { "label": "По велению адской сестры / The Testament of Sister New Devil", "value": "18" }, { "label": "Поборники тьмы / Darksiders", "value": "1028" }, { "label": "Повар небесной гостиницы / Чем кормят в ином мире / Kakuriyo no Yadomeshi", "value": "998" }, { "label": "Повар-боец Сома / В поисках божественного рецепта / Shokugeki no Souma", "value": "191" }, { "label": "Повелитель тьмы на подработке! / Hataraku Maou-sama!", "value": "674" }, { "label": "Повелитель тьмы: Другая история мира / How Not to Summon a Demon Lord / Isekai Maou to Shoukan Shoujo no Dorei Majutsu", "value": "699" }, { "label": "Повелитель(Куганэ Маруяма) / Overlord", "value": "27" }, { "label": "Повелитель(Games) / Overlord", "value": "1623" }, { "label": "Повесть о Конце Света / Record of Ragnarok", "value": "332" }, { "label": "Повесть о лунной принцессе / Tsukihime: Lunar Legend", "value": "750" }, { "label": "Повесть о Небесных островах / Фэнтези Гранблю / Granblue Fantasy", "value": "808" }, { "label": "Повседневная жизнь бессмертного короля / The Daily Life of the Immortal King / Xian Wang de Richang Shenghuo", "value": "1466" }, { "label": "Повседневная жизнь с девушкой-монстром / Monster Musume", "value": "760" }, { "label": "Пограничье(Games) / Borderlands", "value": "992" }, { "label": "Под лунами Драконьих глаз / Beneath the Dragoneye Moons", "value": "1735" }, { "label": "Подземелья и драконы / Dungeons & Dragons", "value": "81" }, { "label": "Подземная история / Андертейл / Undertale", "value": "390" }, { "label": "Поднявшийся(Games) / Risen", "value": "1273" }, { "label": "Поднятие уровня в одиночку / Solo Leveling", "value": "127" }, { "label": "Подручный Луизы-Нулизы / Zero no Tsukaima", "value": "580" }, { "label": "Пожиратель богов / God Eater", "value": "1321" }, { "label": "Поймай себя ! Моя дорогая жена / Catch You ! My Dear Wife", "value": "1317" }, { "label": "Покемон / Pokemon", "value": "43" }, { "label": "Политическая Хроника Молодой Девушки / A Young Woman's Political Record", "value": "1306" }, { "label": "Полностью пленённые / Totally Captivated", "value": "1086" }, { "label": "Полый Рыцарь(Games) / Hollow Knight", "value": "1198" }, { "label": "Пользователи Силы / Forceusers", "value": "1162" }, { "label": "Поля битвы Неизвестного игрока / ПАБГ / Player Unknown's Battlegrounds / PUBG", "value": "622" }, { "label": "Попытка приручить злого повелителя / Trying to Tame an Evil Overlord", "value": "983" }, { "label": "Поработитель Ада / Helltaker", "value": "776" }, { "label": "Порновселенная / Porn Universe", "value": "1776" }, { "label": "Портал(Valve) / Portal", "value": "800" }, { "label": "Последние из нас / Last Of Us", "value": "1717" }, { "label": "Последний Серафим / Owari no Seraph", "value": "551" }, { "label": "Последняя из рода Блау(Тайга Ри) / The last of the Blau family", "value": "1507" }, { "label": "Последняя фантазия / ファイナルファンタジ / Final Fantasy", "value": "769" }, { "label": "Преподобное безумие / Reverend Insanity", "value": "1280" }, { "label": "Преподобный Гу / Gu Zhen Ren / Daoist Gu", "value": "1464" }, { "label": "Призрачный бегун / Ghostrunner", "value": "613" }, { "label": "Призрачный гонщик / Ghost Rider", "value": "823" }, { "label": "Принц Драконов Хаоса / The Chaos Dragon Prince", "value": "1397" }, { "label": "Принц Персии / Prince of Persia", "value": "1535" }, { "label": "Принцесса монстров / Princess Resurrection", "value": "1304" }, { "label": "Принцесса Цу / Не проиграю! / Maken Ki", "value": "675" }, { "label": "Проект „Восток“ / Touhou Project", "value": "809" }, { "label": "Проект Кей / K Project", "value": "73" }, { "label": "Проклятие: Автоматизация / NieR:Automata", "value": "1496" }, { "label": "Противостояние святого / Renegade Immortal", "value": "926" }, { "label": "Прототип / Prototype", "value": "54" }, { "label": "Пуленепробиваемый / Bang-Tan / BTS", "value": "520" }, { "label": "Путешествие на Запад / Journey to the West", "value": "1833" }, { "label": "Пять невест / Go-Toubun no Hanayome", "value": "713" }, { "label": "Пять ночей у Фредди / Five nights at freddy's", "value": "930" }, { "label": "Рагнарёк Онлайн / Ragnarok Online", "value": "953" }, { "label": "Радуга 6: Осада / Rainbow Six: Siege", "value": "421" }, { "label": "Развращение Дочери / Daraku Reijou Hakoiri Ojou-sama Netorare Choukyou Kiroku", "value": "1284" }, { "label": "Рай Грисайи / Эдем в серых тонах / Grisaia no Rakuen", "value": "584" }, { "label": "Рандеву с жизнью / Date A live", "value": "851" }, { "label": "Ранма ½ / Ranma ½", "value": "1192" }, { "label": "Рапунцель: Запутанная история / Tangled", "value": "773" }, { "label": "Расколотая битвой синева небес / Battle Through the Heavens", "value": "927" }, { "label": "Рассказ служанки / The Handmaid's Tale", "value": "1135" }, { "label": "Расхитительница гробниц / Tomb Raider", "value": "988" }, { "label": "Резатель / Лангриссер / Langrisser", "value": "792" }, { "label": "Реинкарнация безработного / Mushoku Tensei", "value": "569" }, { "label": "Реинкарнация Богини / Megami Tensei", "value": "1161" }, { "label": "Репликант НиеР / NieR Replicant / NieR Gestalt", "value": "1299" }, { "label": "Рецеттия: Повесть о магазине предметов / Recettear: An Item Shop's Tale", "value": "858" }, { "label": "Ривердэйл / Riverdale", "value": "637" }, { "label": "Рик и Морти / Rick and Morty", "value": "315" }, { "label": "Розарий и Вампир / Rosario+Vampire", "value": "83" }, { "label": "Розовая пора моей школьной жизни сплошной обман / Yahari Ore no Seishun Love Come wa Machigatteiru", "value": "856" }, { "label": "Рок шоу! / Show By Rock!!", "value": "344" }, { "label": "Русалочка / The Little Mermaid", "value": "892" }, { "label": "Рыцарь и маг / Knight's & Magic", "value": "1491" }, { "label": "Сага о Винланде / Vinland Saga", "value": "1200" }, { "label": "Садистская смесь / Blend S", "value": "1120" }, { "label": "Сайт волшебниц / Mahou Shoujo Site", "value": "909" }, { "label": "Сверхъестественное(телесериал) / Supernatural", "value": "916" }, { "label": "Связь принцесс: повторное погружение / Princess Connect! Re:Dive", "value": "1481" }, { "label": "Святые / Saints Row", "value": "1390" }, { "label": "Сейлор Мун / Sailor Moon", "value": "114" }, { "label": "Секире: Тени Умирают Дважды / Sekiro: Shadows Die Twice", "value": "1076" }, { "label": "Семь смертных грехов / Nanatsu no Taizai", "value": "61" }, { "label": "Семья шпиона / Spy x Family", "value": "1646" }, { "label": "Сердца Пандоры / Pandora Hearts", "value": "497" }, { "label": "Серия Метроидов / Metroid Series", "value": "1612" }, { "label": "Серый человек / Ди: Гурэйман / D.Gray-man", "value": "367" }, { "label": "Си Тянь Гуань / Si Tian Guan", "value": "1189" }, { "label": "Сильнейший в истории ученик Кэнити / Shijou Saikyou no Deshi Kenichi", "value": "242" }, { "label": "Сильнейший в истории ученик Кэнъити / KenIchi: The Mightiest Disciple", "value": "745" }, { "label": "Сильнейший магнат / The Strongest Tycoon", "value": "1340" }, { "label": "Сильнейший мудрец низшей эмблемы / Shikkakumon no Saikyou Kenja", "value": "1472" }, { "label": "Симпсоны / The Simpsons", "value": "1461" }, { "label": "Симс / The Sims", "value": "654" }, { "label": "Симфония морской стали / Aoki Hagane no Arpeggio", "value": "958" }, { "label": "Сингулярность(Games) / Singularity", "value": "1793" }, { "label": "Синий Архив / Blue Archive", "value": "1411" }, { "label": "Синий экзорцист / Blue Exorcist", "value": "312" }, { "label": "Синяя Тюрьма: Блю Лок / Blue Lock", "value": "1792" }, { "label": "Система Богов и Демонов / God and Devil World", "value": "1648" }, { "label": "Система Спаси-Себя-Сам / The Scum Villain's Self-Saving System: Ren Zha Fanpai Zijiu Xitong", "value": "1505" }, { "label": "Система: Восьмой уровень(Д. Серебряков) / System: Eighth level", "value": "1175" }, { "label": "Сисястая Принцесса под гипнозом / Kyonyuu Princess Saimin", "value": "1618" }, { "label": "Сказание о Демонах и Богах / Tales of Demons and Gods", "value": "59" }, { "label": "Сказание о Тёмном Рыцаре ~ Призван, чтобы одолеть Героя ~ / Tale of Dark Knight~Summoned to Defeat The Hero~", "value": "1647" }, { "label": "Сказки хранителей(Games) / Guardian tales", "value": "1068" }, { "label": "Скрытая Похотливая Натура Моих Русских Сестренок и Мачехи / Muttsuri do Sukebe ro Gibo Shimai", "value": "1282" }, { "label": "Скуби-Ду / Scooby-Doo", "value": "638" }, { "label": "Скучный мир, где не существует самой идеи похабных шуток / Shimoneta to Iu Gainen ga Sonzai Shinai Taikutsu na Sekai", "value": "830" }, { "label": "Сладкая жизнь / Happy Sugar Life", "value": "1099" }, { "label": "Сладкий флирт / Amour Sucré / Sweet Crush", "value": "495" }, { "label": "Сладости и Сигареты / Candy & Cigarettes", "value": "778" }, { "label": "Следопыт Гнев Праведников / Pathfinder Wrath Of The Righteous", "value": "1077" }, { "label": "Следопыт: Творец королей / Pathfinder: Kingmaker", "value": "1770" }, { "label": "Смертельная битва / Мортал Комбат / Mortal Kombat", "value": "806" }, { "label": "Смертельный укус", "value": "1902" }, { "label": "Созданный в бездне / Made in Abyss", "value": "952" }, { "label": "Сок джунглей", "value": "1901" }, { "label": "Сокрушитель: Новые волны / The Breaker: New Waves", "value": "1500" }, { "label": "Соник еж / Sonic the hedgehog", "value": "1052" }, { "label": "Сорвиголова / Daredevil", "value": "1690" }, { "label": "Сотня / Hundred", "value": "885" }, { "label": "Спаун / Spawn", "value": "1254" }, { "label": "Спецагент Арчер / Archer", "value": "624" }, { "label": "Специалист по апгрейду из другого мира / Endless Sea of Clouds ESC", "value": "1499" }, { "label": "Спираль / Удзумаки / Uzumaki", "value": "1164" }, { "label": "СТАЛКЕР / STALKER / S.T.A.L.K.E.R", "value": "677" }, { "label": "Стальная тревога / Full Metal Panic! The Second Raid", "value": "1489" }, { "label": "Стальной алхимик / Fullmetal Alchemist", "value": "1123" }, { "label": "Стальной Гигант / The Iron Giant", "value": "1241" }, { "label": "Становление богом / Bai Lian Cheng Shen", "value": "1315" }, { "label": "Старгерл / Stargirl", "value": "1137" }, { "label": "Стелларис / Stellaris", "value": "1098" }, { "label": "Сторожевые Псы / Watch Dogs", "value": "1886" }, { "label": "Стражи Галактики / Guardians of the Galaxy", "value": "1426" }, { "label": "Страна Самоцветов / Houseki no Kuni", "value": "1305" }, { "label": "Страна чудес смертников / Зона-парк смертников / Deadman Wonderland", "value": "857" }, { "label": "Страношары / Кантриболз / Countryballs", "value": "1895" }, { "label": "Студии 20-й век / 20th Century Studios", "value": "1715" }, { "label": "Судьба / Fate", "value": "1740" }, { "label": "Судьба: Апокриф / Fate: Apocrypha", "value": "231" }, { "label": "Судьба: Великий Орден / Fate: Grand Order", "value": "60" }, { "label": "Судьба: Девочка волшебница Илия / Fate: Kaleid Liner Prisma", "value": "789" }, { "label": "Судьба: Истоки / Fate: Zero", "value": "230" }, { "label": "Судьба: Ночь схватки / Fate: Stay Night", "value": "536" }, { "label": "Сумерки / Twilight", "value": "471" }, { "label": "Супер ген бога / Super God Gene", "value": "316" }, { "label": "Супер Марио / Super Mario", "value": "1661" }, { "label": "Супергёрл(телесериал, 2015) / Supergirl", "value": "1088" }, { "label": "Супермедицинский ниндзя / Super medical ninja", "value": "1391" }, { "label": "Суперсемейка / The Incredibles", "value": "306" }, { "label": "Сэкирэй / Sekirei", "value": "111" }, { "label": "Тада не может влюбиться! / Tada-kun wa koi wo shinai!", "value": "1905" }, { "label": "Тайны Смолвиля / Smallville", "value": "449" }, { "label": "Танец клинка Элементалиста / Seireitsukai no Blade Dance", "value": "1498" }, { "label": "Твоя апрельская ложь / Your lie in april", "value": "532" }, { "label": "Те, кто охотятся на эльфов / エルフを狩るモノたち / Those Who Hunt Elves", "value": "1168" }, { "label": "Темнейшее подземелье / Darkest dungeon", "value": "1405" }, { "label": "Темные Души / Dark Souls", "value": "200" }, { "label": "Темный Ангел / Dark Angel", "value": "1010" }, { "label": "Тёмный Дворецкий / Kuroshitsuj / Dark Butler", "value": "411" }, { "label": "Темный дворецкий / Kuroshitsuji", "value": "1043" }, { "label": "Темный призыватель Апокалипсиса / The Dark Summoner of the Apocalypse", "value": "1407" }, { "label": "Тень ежа / Ёж Шэдоу / Shadow the hedgehog", "value": "796" }, { "label": "Терминатор / The Terminator", "value": "759" }, { "label": "Террарий / Terraria", "value": "805" }, { "label": "Тетрадь смерти / Death Note", "value": "78" }, { "label": "Тибериумные войны / Tiberium Wars", "value": "1893" }, { "label": "Титаник / Titanic", "value": "1842" }, { "label": "Тихий Холм / Сайлент Хилл / Silent Hill", "value": "848" }, { "label": "Тихоокеанский рубеж / Pacific Rim", "value": "832" }, { "label": "Тогайну но Чи ~Потерял кровь~(Games) / Togainu no Chi ~Lost Blood~", "value": "1540" }, { "label": "Токийские вороны / Tokyo Ravens", "value": "836" }, { "label": "Токийские мстители / Tokyo Revengers", "value": "1064" }, { "label": "Токийский Гуль / Tokyo Ghoul", "value": "271" }, { "label": "Тор / Thor", "value": "764" }, { "label": "Торико / Toriko", "value": "342" }, { "label": "Точка зрения Всеведущего читателя / Omniscient Reader’s Viewpoint", "value": "1872" }, { "label": "Трансформеры / Transformers", "value": "117" }, { "label": "Трес Наварра / Tres Navarre", "value": "1197" }, { "label": "Три Икса / xXx", "value": "364" }, { "label": "Трон: Восстание / Tron: Uprising", "value": "1887" }, { "label": "Тропико / Tropico", "value": "694" }, { "label": "Ты единственная, кто любит Великого Меня / Ore wo Suki nano wa Omae dake ka yo", "value": "1818" }, { "label": "Ты же любишь мамочку, удары которой бьют по площади двойным уроном? / Tsuujou Kougeki ga Zentai Kougeki de Ni-kai Kougeki no Okaasan wa Suki Desu ka?", "value": "333" }, { "label": "Тэнти - лишний! / Tenchi Muyo", "value": "1316" }, { "label": "У Коми-сан проблемы с общением / 古見さんは、コミュ症です / Komi Can't Communicate", "value": "591" }, { "label": "У меня мало друзей / Boku wa Tomodachi ga Sukunai", "value": "1506" }, { "label": "Убийца Акаме / Akame ga Kill", "value": "30" }, { "label": "Убийца Брайан / Carl Robert Brown", "value": "1092" }, { "label": "Убийца гоблинов / Goblin slayer", "value": "803" }, { "label": "Удар крови / Very AU strike the blood", "value": "1255" }, { "label": "Уж не зомби ли это? / Kore wa Zombie Desu ka?", "value": "725" }, { "label": "Уличный боец(Games) / Суторито Фаита / Street Fighter", "value": "1203" }, { "label": "Ультрафиолет / Ultraviolet", "value": "1831" }, { "label": "Усио и Тора / Ushio and Tora", "value": "1501" }, { "label": "Утраченное небесами / Sora no Otoshimoto / Lost Property of the Sky", "value": "627" }, { "label": "Ученик Мудреца / Kenja no Deshi wo Nanoru Kenja", "value": "1474" }, { "label": "Ученик чародея / The Sorcerer's Apprentice", "value": "862" }, { "label": "Ученики(Games) / Disciples", "value": "1478" }, { "label": "Учитель Хокаге / Hokage Master", "value": "1319" }, { "label": "Учитель-мафиози Реборн! / Katekyo Hitman Reborn!", "value": "134" }, { "label": "Ушастые Друзья / Kemono Friends", "value": "578" }, { "label": "Фальшивая любовь / Nisekoi", "value": "1103" }, { "label": "Фантастическая четвёрка / Fantastic Four", "value": "625" }, { "label": "Фантастические твари и где они обитают / Fantastic Beasts and Where to Find Them", "value": "246" }, { "label": "Финес и Ферб / Phineas and Ferb", "value": "898" }, { "label": "Флотская коллекция / Kantai Collection", "value": "1194" }, { "label": "Флэш / The Flash", "value": "1136" }, { "label": "Фонд SCP / SCP / SCP Foundation", "value": "822" }, { "label": "Форма голоса / A Silent Voice", "value": "1100" }, { "label": "Форсаж / The Fast and the Furious", "value": "363" }, { "label": "Фронт кровавой блокады / Кровавый круг - линия фронта / Kekkai Sensen / Blood Blockade Battlefront", "value": "794" }, { "label": "Футадом мир / Futadom world", "value": "984" }, { "label": "Халк / Hulk", "value": "973" }, { "label": "Хвост Феи / Fairy Tail", "value": "13" }, { "label": "Хеллбой / Hellboy", "value": "1171" }, { "label": "Хеллсинг: Война с нечистью / Hellsing", "value": "116" }, { "label": "Хикару и го / Hikaru no Go", "value": "1121" }, { "label": "Хищник / Predator", "value": "747" }, { "label": "Хоббит(Дж. Р. Р. Толкина) / The Hobbit(John R.R. Tolkien)", "value": "1127" }, { "label": "Ходячие мертвецы / The Walking Dead", "value": "704" }, { "label": "Холодное сердце / Frozen", "value": "633" }, { "label": "Хонкай удар / Honkai impact", "value": "1332" }, { "label": "Хранители Пандоры / The guardians of Pandora", "value": "1187" }, { "label": "Хранитель вечности / UQ Holder", "value": "1469" }, { "label": "Хроники Акаши / Rokudenashi Majutsu Koushi to Akashic Records", "value": "1166" }, { "label": "Хроники Ксенобладания / Дзэнобурэйдо / Xenoblade Chronicles", "value": "1110" }, { "label": "Хроники Миров(Е. Лукин) / Chronicles of the Worlds(E. Lukin)", "value": "346" }, { "label": "Хроники расхитителей гробниц / Даому Биджи / Grave Robbery Note / Dao Mu Bi Ji / Daomu Biji", "value": "724" }, { "label": "Хроники Ренегата / The Renegade Chronicles", "value": "1225" }, { "label": "Царь Горы / The Gog of the Highschool", "value": "1285" }, { "label": "Чародейки / W.I.T.C.H.", "value": "118" }, { "label": "Человек — бензопила / Chainsaw Man", "value": "797" }, { "label": "Человек — летучая мышь / Бэтмен / Bat-man / Batman", "value": "440" }, { "label": "Человек одного удара / Ванпанчмен / One Punch-Man", "value": "70" }, { "label": "Человек-паук / Spider-Man", "value": "326" }, { "label": "Чемпион! / Campione!", "value": "534" }, { "label": "Червь(Джон Маккрей) / Worm(John C. McCrae(Wildbow))", "value": "700" }, { "label": "Черная Пантера(Фильм, 2018) / Black Panther", "value": "1605" }, { "label": "Черновик(С.Лукьяненко) / Draft", "value": "1023" }, { "label": "Чернокнижник в Мире Магов / Варлок / Warlock", "value": "635" }, { "label": "Чёрные души / Black Souls", "value": "1439" }, { "label": "Чёрный зверь / Чёрный Пёс / Kuroinu", "value": "755" }, { "label": "Чёрный зверь: Развращение Благородных Воительниц / Black Beast: Corruption of the Noble Warriors", "value": "1733" }, { "label": "Чёрный клевер / Black Clover", "value": "11" }, { "label": "Что такое настоящий мир? / What is real peace?", "value": "1336" }, { "label": "Чудачества любви не помеха! / Chuunibyou Demo Koi ga Shitai!", "value": "1719" }, { "label": "Чужой / Чужие / Aliens", "value": "1791" }, { "label": "Чужой / Alien", "value": "748" }, { "label": "Чума инкорпорейтед / Plague Inc", "value": "125" }, { "label": "Шазам! / Shazam!", "value": "1560" }, { "label": "Шальной последний босс появился! / A Wild Last Boss Appeared!", "value": "968" }, { "label": "Шальные девчонки / Girl the Wild's", "value": "965" }, { "label": "Шан Чи и легенда десяти колец / Shang-Chi and the Legend of the Ten Rings", "value": "1424" }, { "label": "Шарлотта / Charlotte", "value": "71" }, { "label": "Шерлок (ВВС) / Sherlock", "value": "492" }, { "label": "Шестерни войны / Gears of War", "value": "1346" }, { "label": "Школа мертвецов / Highschool of the Dead", "value": "98" }, { "label": "Школа строгого режима / Prison School", "value": "676" }, { "label": "Школьные воины / Сила тысячи / Ikki Tosen", "value": "818" }, { "label": "Шрек(мультфильм) / Шрэк / Shrek", "value": "1586" }, { "label": "Шухер, у нас новый студент / Transfer Student The Storm Bringer", "value": "628" }, { "label": "Эволюционировать(Games) / Evolve", "value": "1789" }, { "label": "Эволюция. Естественный Отбор / Game Evolution", "value": "287" }, { "label": "Эльсворд: Эль-ий Йоин / Elsword", "value": "199" }, { "label": "Эльфийская песнь / Elfen Lied", "value": "1899" }, { "label": "Эпоха Драконов / Dragon Age", "value": "253" }, { "label": "Эр Ген Я запечатаю небеса / ISSTH / Er Gen I shall seal the heavens", "value": "1170" }, { "label": "Эрагон(Кристофер Паолини) / Eragon", "value": "417" }, { "label": "Эроманга-сэнсэй / Ero-manga Sensei", "value": "1094" }, { "label": "Эстетика заблудшего героя / Hagure Yuusha no Aesthetica", "value": "1310" }, { "label": "Эта гяру будет встречаться с отаку через 100 дней. / 100-nichigo ni Otaku-kun to Tsukiau Gal", "value": "1246" }, { "label": "Эта фарфоровая кукла влюбилась / Sono Bisque Doll wa Koi wo Suru My Dress-Up Darling", "value": "1335" }, { "label": "Это не Гарри Поттер / This is not Harry Potter", "value": "1219" }, { "label": "Этот герой неуязвим, но очень осторожен / This Hero Is Invincible but Too Cautious", "value": "1276" }, { "label": "Эффект массы / Mass Effect", "value": "213" }, { "label": "Эхо пули / Bullet Echo", "value": "1523" }, { "label": "Югио: Дуэльные монстры / Yu-Gi-Oh", "value": "1814" }, { "label": "Югио! Вреинс / Yu-Gi-Oh! VRAINS", "value": "1888" }, { "label": "Юна из гостиницы Юраги / Yuuna of Yuragi Manor", "value": "493" }, { "label": "Юная Лига Справедливости / Young Justice", "value": "1020" }, { "label": "Юные Титаны / Teen Titans", "value": "420" }, { "label": "Я - Четвертый / I Am Number Four", "value": "590" }, { "label": "Я Король-Волшебник / I Am The Sorcerer King", "value": "1292" }, { "label": "Я мачеха, но моя дочь слишком милая / I'm stepmother but daughter is too cute", "value": "777" }, { "label": "Я не родился счастливчиком / I Wasn’t Born Lucky", "value": "996" }, { "label": "Я получил читерские способности в другом мире и стал экстраординарным в реальном мире / I Got a Cheat Skill in Another World and Became Unrivaled in The Real World, Too", "value": "1900" }, { "label": "Я стала потерянной дочерью злодея / I Became the Villain’s Lost Daughter", "value": "1387" }, { "label": "Ядерный трон / Nuclear Throne", "value": "1456" }, { "label": "Ярость [Пересмотрено] / Rage [Revised]", "value": "1337" }, { "label": "Ящик предложений Мэдаки / Medaka box", "value": "874" }, { "label": "Cказка для Дьявола / Tale For Satan", "value": "1271" }, { "label": "D&D стиль / D&D style", "value": "1289" }, { "label": "Dying Light 2: Stay Human", "value": "1906" }, { "label": "Fallout: Нью-Вегас / Fallout: New Vegas", "value": "1249" }, { "label": "Re: Жизнь в альтернативном мире с нуля / Re: Zero, Starting Life in Another World", "value": "57" }, { "label": "Re:Zero Начало жизни в другом мире / Re:Zero Starting Life in Another World", "value": "1531" }, { "label": "Rimworld", "value": "1894" }, { "label": "The Second Coming of Gluttony / The Second Coming of Avarice", "value": "1236" }, { "label": "Vfhdbk", "value": "1884" }, { "label": "XCOM: Враг внутри / XCOM: Enemy Unknown", "value": "476" }, { "label": "Xenus: Точка кипения / Boiling point: Road To Hell / Xenus: Boiling Point", "value": "695" }], "inputType": filterInputs_1.FilterInputs.Checkbox }, { "key": "genres_ex", "label": "Исключить жанры:", "values": [{ "label": "18+", "value": "52" }, { "label": "Арт", "value": "1" }, { "label": "Боевик", "value": "2" }, { "label": "Боевые искусства", "value": "3" }, { "label": "Гаремник", "value": "5" }, { "label": "Героическое фэнтези", "value": "7" }, { "label": "Детектив", "value": "8" }, { "label": "Дзёсэй", "value": "9" }, { "label": "Додзинси", "value": "10" }, { "label": "Драма", "value": "11" }, { "label": "История", "value": "13" }, { "label": "Киберпанк", "value": "46" }, { "label": "Кодомо", "value": "14" }, { "label": "Комедия", "value": "15" }, { "label": "Литрпг", "value": "48" }, { "label": "Махо-сёдзё", "value": "16" }, { "label": "Мелодрама", "value": "49" }, { "label": "Меха", "value": "17" }, { "label": "Мистика", "value": "18" }, { "label": "Научная фантастика", "value": "19" }, { "label": "Повседневность", "value": "20" }, { "label": "Постапокалиптика", "value": "21" }, { "label": "Приключения", "value": "22" }, { "label": "Психология", "value": "23" }, { "label": "Романтика", "value": "24" }, { "label": "Самурайский боевик", "value": "25" }, { "label": "Сверхъестественное", "value": "26" }, { "label": "Сёдзё", "value": "27" }, { "label": "Сёнэн", "value": "29" }, { "label": "Смат", "value": "45" }, { "label": "Спорт", "value": "31" }, { "label": "Сэйнэн", "value": "32" }, { "label": "Сюаньхуа", "value": "44" }, { "label": "Сюаньхуань", "value": "47" }, { "label": "Сянься (XianXia)", "value": "42" }, { "label": "Трагедия", "value": "33" }, { "label": "Триллер", "value": "34" }, { "label": "Ужасы", "value": "35" }, { "label": "Уся (wuxia)", "value": "41" }, { "label": "Фантастика", "value": "36" }, { "label": "Фанфик", "value": "50" }, { "label": "Фэнтези", "value": "37" }, { "label": "Школа", "value": "38" }, { "label": "Этти", "value": "39" }, { "label": "Bl", "value": "43" }, { "label": "Gl", "value": "40" }], "inputType": filterInputs_1.FilterInputs.Checkbox }, { "key": "tags_ex", "label": "Исключить тэги:", "values": [{ "label": "12+", "value": "3316" }, { "label": "16+", "value": "83" }, { "label": "Абсурд", "value": "7973" }, { "label": "Авантюристы", "value": "222" }, { "label": "Автомат", "value": "5272" }, { "label": "Авторский мир", "value": "1062" }, { "label": "Агрессивные персонажи", "value": "3249" }, { "label": "Ад", "value": "2623" }, { "label": "Ад и рай", "value": "817" }, { "label": "Адам дженсен", "value": "1649" }, { "label": "Адаптация произведения", "value": "192" }, { "label": "Адвокат", "value": "6340" }, { "label": "Адекватные главные герои", "value": "1953" }, { "label": "Азартные игры", "value": "5301" }, { "label": "Азгард", "value": "3494" }, { "label": "Азула", "value": "5550" }, { "label": "Аид", "value": "7641" }, { "label": "Айдолы", "value": "4081" }, { "label": "Академия", "value": "316" }, { "label": "Акамэ", "value": "5059" }, { "label": "Аквакинез", "value": "5952" }, { "label": "Акира", "value": "2639" }, { "label": "Акнология", "value": "4634" }, { "label": "Актерское мастерство", "value": "4798" }, { "label": "Актёры", "value": "7506" }, { "label": "Активные герои", "value": "6376" }, { "label": "Акутагава рюноске", "value": "4113" }, { "label": "Аладдин", "value": "6489" }, { "label": "Алая ведьма", "value": "4767" }, { "label": "Алиса", "value": "4761" }, { "label": "Алкоголь", "value": "5508" }, { "label": "Аллегория", "value": "271" }, { "label": "Алукард", "value": "4914" }, { "label": "Алхимики", "value": "1164" }, { "label": "Алхимия", "value": "1473" }, { "label": "Алчность", "value": "6897" }, { "label": "Альбус дамблдор", "value": "5784" }, { "label": "Альтернативное развитие событий", "value": "5330" }, { "label": "Альянсы", "value": "328" }, { "label": "Амбициозный главный герой", "value": "3751" }, { "label": "Америка", "value": "4082" }, { "label": "Амнезия", "value": "2207" }, { "label": "Аморальный герой", "value": "18" }, { "label": "Анбу", "value": "8129" }, { "label": "Ангелы", "value": "857" }, { "label": "Ангелы и демоны", "value": "1327" }, { "label": "Ангст", "value": "4638" }, { "label": "Андроиды", "value": "1993" }, { "label": "Анимализм", "value": "5249" }, { "label": "Аниме", "value": "1294" }, { "label": "Анко митараши", "value": "5768" }, { "label": "Антагонист", "value": "2144" }, { "label": "Антигерой", "value": "7725" }, { "label": "Антиквариат", "value": "3552" }, { "label": "Антимаг", "value": "1348" }, { "label": "Антиутопия", "value": "662" }, { "label": "Апокалипсис", "value": "1498" }, { "label": "Аристократия", "value": "371" }, { "label": "Аристократы", "value": "7338" }, { "label": "Армия", "value": "1723" }, { "label": "Артас", "value": "6700" }, { "label": "Артефакты", "value": "2296" }, { "label": "Археология", "value": "6523" }, { "label": "Асгард", "value": "3635" }, { "label": "Ассасин", "value": "1415" }, { "label": "Асуна", "value": "5044" }, { "label": "Аугментации", "value": "7751" }, { "label": "Ацуши накаджима", "value": "4109" }, { "label": "Аянокоджи киетака", "value": "6862" }, { "label": "Бандиты", "value": "2188" }, { "label": "Басейн", "value": "6847" }, { "label": "Баскетбол", "value": "7933" }, { "label": "Бастарды", "value": "76" }, { "label": "Бедность", "value": "1207" }, { "label": "Без культивации", "value": "668" }, { "label": "Без любовной линий", "value": "2225" }, { "label": "Без перерождений", "value": "262" }, { "label": "Без попаданца", "value": "8065" }, { "label": "Без системы", "value": "747" }, { "label": "Без юмора", "value": "763" }, { "label": "Бездна", "value": "1026" }, { "label": "Безжалостное домашнее животное", "value": "1245" }, { "label": "Безжалостные персонажи", "value": "2986" }, { "label": "Беззаботные персонажи", "value": "3123" }, { "label": "Безответная любовь", "value": "7815" }, { "label": "Безработный", "value": "2202" }, { "label": "Безумие", "value": "37" }, { "label": "Безумные персонажи", "value": "2049" }, { "label": "Бейсбол", "value": "7623" }, { "label": "Беременность", "value": "2122" }, { "label": "Бесконечный поток", "value": "7556" }, { "label": "Беспечные персонажи", "value": "742" }, { "label": "Бесплатно", "value": "8403" }, { "label": "Бессмертные персонажи", "value": "566" }, { "label": "Бесстрашные персонажи", "value": "6921" }, { "label": "Бесстыдные персонажи", "value": "1257" }, { "label": "Бесстыдный главный герой", "value": "8190" }, { "label": "Библиотека", "value": "4210" }, { "label": "Библия", "value": "488" }, { "label": "Бизнес", "value": "704" }, { "label": "Биология", "value": "2220" }, { "label": "Биомехи", "value": "1968" }, { "label": "Биседзе", "value": "777" }, { "label": "Битва за веру", "value": "721" }, { "label": "Битва за трон", "value": "7211" }, { "label": "Битва королевств", "value": "1151" }, { "label": "Битва рас", "value": "6989" }, { "label": "Битвы", "value": "1740" }, { "label": "Благородные персонажи", "value": "2201" }, { "label": "Близнецы", "value": "2931" }, { "label": "Богатство", "value": "6522" }, { "label": "Богатые персонажи", "value": "520" }, { "label": "Боги", "value": "173" }, { "label": "Богини", "value": "30" }, { "label": "Богиня", "value": "8324" }, { "label": "Богоубийца", "value": "1253" }, { "label": "Богохульство", "value": "95" }, { "label": "Боевая академия", "value": "2108" }, { "label": "Большая грудь", "value": "4717" }, { "label": "Борос", "value": "6533" }, { "label": "Борьба", "value": "1925" }, { "label": "Борьба за власть", "value": "8072" }, { "label": "Босс и подчиненный", "value": "7157" }, { "label": "Бояръ", "value": "2307" }, { "label": "Брак", "value": "1558" }, { "label": "Брак по расчету", "value": "1389" }, { "label": "Брат и сестра", "value": "615" }, { "label": "Братский комплекс", "value": "2321" }, { "label": "Броманс", "value": "1103" }, { "label": "Брошенные дети", "value": "2846" }, { "label": "Буддизм", "value": "1871" }, { "label": "Будущее", "value": "1820" }, { "label": "Бывший муж", "value": "8080" }, { "label": "Быстрое развитие", "value": "1443" }, { "label": "Бэтгерл", "value": "2584" }, { "label": "Бэтмен", "value": "4668" }, { "label": "В первый раз", "value": "6212" }, { "label": "В этот же мир", "value": "49" }, { "label": "Ваканда", "value": "8331" }, { "label": "Валькирии", "value": "4047" }, { "label": "Вампиры", "value": "2206" }, { "label": "Веб камера", "value": "5664" }, { "label": "Веб новелла", "value": "2349" }, { "label": "Ведьмак", "value": "843" }, { "label": "Ведьмы", "value": "643" }, { "label": "Везучие персонажи", "value": "1879" }, { "label": "Веном", "value": "3994" }, { "label": "Вестерн", "value": "2131" }, { "label": "Вестерос", "value": "8171" }, { "label": "Взросление", "value": "624" }, { "label": "Взрослый главный герой", "value": "2416" }, { "label": "Видео игры", "value": "2630" }, { "label": "Викинги", "value": "267" }, { "label": "Вино", "value": "6972" }, { "label": "Вирт", "value": "6213" }, { "label": "Виртуальная реальность", "value": "325" }, { "label": "Вирусы", "value": "3327" }, { "label": "Владыка демонов", "value": "555" }, { "label": "Власть", "value": "756" }, { "label": "Влюбленность", "value": "6132" }, { "label": "Внешний вид отличается от личности", "value": "1938" }, { "label": "Внучка", "value": "8399" }, { "label": "Военные", "value": "1096" }, { "label": "Возрождение", "value": "1160" }, { "label": "Воины", "value": "287" }, { "label": "Война", "value": "443" }, { "label": "Войны", "value": "2431" }, { "label": "Воландеморт", "value": "4278" }, { "label": "Волейбол", "value": "6415" }, { "label": "Волки", "value": "1166" }, { "label": "Волшебники", "value": "122" }, { "label": "Волшебные существа", "value": "1689" }, { "label": "Волшебство", "value": "719" }, { "label": "Вор", "value": "1399" }, { "label": "Воровка", "value": "6948" }, { "label": "Ворон", "value": "848" }, { "label": "Воскрешение", "value": "6915" }, { "label": "Воспоминания из другого мира", "value": "1366" }, { "label": "Воспоминания из прошлого", "value": "1372" }, { "label": "Воссоединие семьи", "value": "8130" }, { "label": "Восхождение", "value": "380" }, { "label": "Враги становятся любовниками", "value": "978" }, { "label": "Врата", "value": "40" }, { "label": "Врата в другой мир", "value": "1957" }, { "label": "Врач", "value": "1243" }, { "label": "Временная петля", "value": "2852" }, { "label": "Врмморпг", "value": "2043" }, { "label": "Все дозволено", "value": "96" }, { "label": "Всемогущий главный герой", "value": "1414" }, { "label": "Второй шанс", "value": "2372" }, { "label": "Вуайеризм", "value": "2498" }, { "label": "Выживание", "value": "501" }, { "label": "Вымышленные существа", "value": "3466" }, { "label": "Вынужденный брак", "value": "7705" }, { "label": "Высокие технологии", "value": "653" }, { "label": "Высокомерные персонажи", "value": "3250" }, { "label": "Галустян", "value": "5199" }, { "label": "Гангстеры", "value": "7704" }, { "label": "Гарем", "value": "440" }, { "label": "Гарри поттер", "value": "226" }, { "label": "Геймеры", "value": "2130" }, { "label": "Генетические модификации", "value": "1750" }, { "label": "Гениальный главный герой", "value": "1500" }, { "label": "Гений", "value": "1650" }, { "label": "Гермиона грейнджер", "value": "4280" }, { "label": "Герои", "value": "185" }, { "label": "Гигаполис", "value": "8393" }, { "label": "Гильгамеш", "value": "6031" }, { "label": "Гильдии", "value": "900" }, { "label": "Гильдия авантюристов", "value": "1858" }, { "label": "Гинтама", "value": "4544" }, { "label": "Гипноз", "value": "358" }, { "label": "Главная героиня влюбляется первой", "value": "973" }, { "label": "Главный герой бог", "value": "164" }, { "label": "Главный герой влюбляется первым", "value": "3629" }, { "label": "Главный герой выживальщик", "value": "120" }, { "label": "Главный герой гонг", "value": "7877" }, { "label": "Главный герой девушка", "value": "257" }, { "label": "Главный герой демон", "value": "136" }, { "label": "Главный герой женщина", "value": "7329" }, { "label": "Главный герой жестокий", "value": "1553" }, { "label": "Главный герой извращенец", "value": "94" }, { "label": "Главный герой имба", "value": "2421" }, { "label": "Главный герой киборг", "value": "7780" }, { "label": "Главный герой монстр", "value": "869" }, { "label": "Главный герой мужчина", "value": "1997" }, { "label": "Главный герой на стороне сил зла", "value": "1514" }, { "label": "Главный герой не адекватный", "value": "5" }, { "label": "Главный герой не психопат", "value": "7804" }, { "label": "Главный герой не человек", "value": "2172" }, { "label": "Главный герой не эмоционален", "value": "1150" }, { "label": "Главный герой подросток", "value": "2215" }, { "label": "Главный герой позитивный", "value": "7787" }, { "label": "Главный герой психопат", "value": "7803" }, { "label": "Главный герой ребенок", "value": "2347" }, { "label": "Главный герой русский", "value": "2417" }, { "label": "Главный герой сильный с самого начала", "value": "88" }, { "label": "Главный герой скрывает свою силу", "value": "1059" }, { "label": "Главный герой эгоист", "value": "8326" }, { "label": "Гномы", "value": "1870" }, { "label": "Гоблины", "value": "2029" }, { "label": "Годзилла", "value": "6990" }, { "label": "Големы", "value": "1690" }, { "label": "Голливуд", "value": "7754" }, { "label": "Головоломка", "value": "1697" }, { "label": "Горничные", "value": "8091" }, { "label": "Гробница", "value": "388" }, { "label": "Дазай осаму", "value": "4112" }, { "label": "Даньмэй", "value": "3411" }, { "label": "Даосизм", "value": "258" }, { "label": "Дарк соулс", "value": "6057" }, { "label": "Дарт вейдер", "value": "6826" }, { "label": "Дафна гринграсс", "value": "5192" }, { "label": "Дворяне", "value": "7204" }, { "label": "Девушки", "value": "7668" }, { "label": "Девушки монстры", "value": "2231" }, { "label": "Дедушка и внучка", "value": "8400" }, { "label": "Дейви джонс", "value": "8061" }, { "label": "Действие", "value": "1425" }, { "label": "Демон лорд", "value": "153" }, { "label": "Демонология", "value": "2024" }, { "label": "Демоны", "value": "1406" }, { "label": "Дети", "value": "580" }, { "label": "Джарвис", "value": "933" }, { "label": "Джедай", "value": "4442" }, { "label": "Джин", "value": "4024" }, { "label": "Джокер", "value": "3351" }, { "label": "Джон сноу", "value": "7412" }, { "label": "Джоффри баратеон", "value": "3936" }, { "label": "Дзесэй", "value": "678" }, { "label": "Дин винчестер", "value": "6953" }, { "label": "Династии", "value": "2982" }, { "label": "Динозавры", "value": "3666" }, { "label": "Директор", "value": "1417" }, { "label": "Для девушек", "value": "1441" }, { "label": "Дневник", "value": "298" }, { "label": "Добби", "value": "6762" }, { "label": "Добрый мир", "value": "1685" }, { "label": "Договоры с богами", "value": "2152" }, { "label": "Договоры с демонами", "value": "1922" }, { "label": "Доктор", "value": "1991" }, { "label": "Доктор стрэндж", "value": "7634" }, { "label": "Доминирование", "value": "2054" }, { "label": "Дота", "value": "6965" }, { "label": "Доудзюцу", "value": "7133" }, { "label": "Дочь", "value": "3291" }, { "label": "Драко малфой", "value": "46" }, { "label": "Драконы", "value": "282" }, { "label": "Драконы оборотни", "value": "8082" }, { "label": "Древние времена", "value": "7781" }, { "label": "Древний египет", "value": "7614" }, { "label": "Древний китай", "value": "473" }, { "label": "Древний мир", "value": "4" }, { "label": "Другая вселенная", "value": "39" }, { "label": "Другие планеты", "value": "2371" }, { "label": "Другой мир", "value": "2248" }, { "label": "Дружба", "value": "1903" }, { "label": "Друзья детства", "value": "1153" }, { "label": "Духи", "value": "114" }, { "label": "Духовные силы", "value": "1955" }, { "label": "Души", "value": "1212" }, { "label": "Дьявол", "value": "1094" }, { "label": "Дьявольские фрукты", "value": "1564" }, { "label": "Дэдпул", "value": "4399" }, { "label": "Евнух", "value": "6293" }, { "label": "Европейская атмосфера", "value": "5837" }, { "label": "Египет", "value": "528" }, { "label": "Еда", "value": "2056" }, { "label": "Единороги", "value": "437" }, { "label": "Екаи", "value": "655" }, { "label": "Жалкий главный герой", "value": "97" }, { "label": "Жена", "value": "5729" }, { "label": "Женское доминирование", "value": "4622" }, { "label": "Женщина в теле мужчины", "value": "2748" }, { "label": "Женщина кошка", "value": "7513" }, { "label": "Жестокие персонажи", "value": "3153" }, { "label": "Жестокий мир", "value": "1532" }, { "label": "Жестокость", "value": "7880" }, { "label": "Животные", "value": "7488" }, { "label": "Животные компаньоны", "value": "2061" }, { "label": "Жизнь и смерть", "value": "2014" }, { "label": "Жнец", "value": "6288" }, { "label": "Жойен рид", "value": "3926" }, { "label": "Заботливый главный герой", "value": "338" }, { "label": "Закалка тела", "value": "148" }, { "label": "Заклинания", "value": "558" }, { "label": "Заключенные", "value": "3052" }, { "label": "Занпакто", "value": "1102" }, { "label": "Запретная любовь", "value": "8033" }, { "label": "Запутанный сюжет", "value": "1041" }, { "label": "Захват мира", "value": "315" }, { "label": "Зачарованные", "value": "4169" }, { "label": "Звери", "value": "1638" }, { "label": "Зверодевочки", "value": "2006" }, { "label": "Зверолюди", "value": "1018" }, { "label": "Земля", "value": "82" }, { "label": "Злая организация", "value": "7768" }, { "label": "Зло", "value": "1512" }, { "label": "Злодей", "value": "1060" }, { "label": "Злодейка", "value": "2376" }, { "label": "Злой главный герой", "value": "616" }, { "label": "Злые боги", "value": "7109" }, { "label": "Злые персонажи", "value": "3243" }, { "label": "Змей", "value": "5721" }, { "label": "Знаменитости", "value": "1341" }, { "label": "Знание медицины", "value": "1411" }, { "label": "Золушка", "value": "2980" }, { "label": "Зомби", "value": "1743" }, { "label": "Зомби апокалипсис", "value": "912" }, { "label": "Зона 51", "value": "3051" }, { "label": "Зооморфы", "value": "375" }, { "label": "Зорро", "value": "6736" }, { "label": "Зрелые женщины", "value": "1458" }, { "label": "Игра", "value": "663" }, { "label": "Игра на выживание", "value": "2182" }, { "label": "Игровая система", "value": "384" }, { "label": "Игровые элементы", "value": "720" }, { "label": "Извращения", "value": "651" }, { "label": "Измена", "value": "1874" }, { "label": "Изменение характера", "value": "1113" }, { "label": "Изменения внешности", "value": "259" }, { "label": "Изменения личности", "value": "1080" }, { "label": "Изобретения", "value": "126" }, { "label": "Изуку мидория", "value": "6967" }, { "label": "Император", "value": "867" }, { "label": "Империи", "value": "712" }, { "label": "Империя", "value": "1716" }, { "label": "Инвалидность", "value": "2073" }, { "label": "Инквизитор", "value": "143" }, { "label": "Инкуб", "value": "3264" }, { "label": "Инопланетное вторжение", "value": "209" }, { "label": "Инопланетяне", "value": "866" }, { "label": "Интерактив с читателями", "value": "472" }, { "label": "Интересный сюжет", "value": "7374" }, { "label": "Интернет", "value": "739" }, { "label": "Интимные сцены", "value": "3450" }, { "label": "Интрига", "value": "317" }, { "label": "Интриги и заговоры", "value": "1009" }, { "label": "Иные миры", "value": "35" }, { "label": "Исекай", "value": "2979" }, { "label": "Искусственный интеллект", "value": "1900" }, { "label": "Исследование", "value": "1626" }, { "label": "Исторический роман", "value": "573" }, { "label": "Итачи учиха", "value": "4556" }, { "label": "Ичиго", "value": "7254" }, { "label": "Йода", "value": "6829" }, { "label": "Йоруичи", "value": "6755" }, { "label": "Калипсо", "value": "8062" }, { "label": "Каннибализм", "value": "2249" }, { "label": "Капитан америка", "value": "6301" }, { "label": "Каракура", "value": "7473" }, { "label": "Карточная игра", "value": "1557" }, { "label": "Кастиэль", "value": "6954" }, { "label": "Кафе", "value": "3934" }, { "label": "Кацуки бакуго", "value": "7696" }, { "label": "Квесты", "value": "1707" }, { "label": "Киберспорт", "value": "1984" }, { "label": "Кино", "value": "7126" }, { "label": "Китай", "value": "3762" }, { "label": "Кицунэ", "value": "241" }, { "label": "Кланы", "value": "834" }, { "label": "Клоны", "value": "1624" }, { "label": "Книги", "value": "1068" }, { "label": "Книжный червь", "value": "521" }, { "label": "Колдовство", "value": "2681" }, { "label": "колледж", "value": "5058" }, { "label": "Коллекционер", "value": "2588" }, { "label": "Кольцо", "value": "1628" }, { "label": "Коммунисты", "value": "1042" }, { "label": "Коноха", "value": "2827" }, { "label": "Контракт", "value": "4304" }, { "label": "Контроль разума", "value": "485" }, { "label": "Конфеты", "value": "341" }, { "label": "Корейцы", "value": "6535" }, { "label": "Корея", "value": "2443" }, { "label": "Королевская власть", "value": "55" }, { "label": "Королевская семья", "value": "276" }, { "label": "Королевство", "value": "1695" }, { "label": "Короткий рассказ", "value": "239" }, { "label": "Коррупция", "value": "831" }, { "label": "Космическая опера", "value": "2245" }, { "label": "Космические рейнджеры", "value": "5860" }, { "label": "Космос", "value": "329" }, { "label": "Кот", "value": "5171" }, { "label": "Кража навыков", "value": "1159" }, { "label": "Красивая главная героиня", "value": "186" }, { "label": "Красивые женщины", "value": "66" }, { "label": "Красивые персонажи", "value": "5787" }, { "label": "Красивый главный герой", "value": "895" }, { "label": "Крафт", "value": "1599" }, { "label": "Кроссовер", "value": "75" }, { "label": "Ктулху", "value": "920" }, { "label": "Кузнец", "value": "853" }, { "label": "Кукла", "value": "3085" }, { "label": "Кулинария", "value": "2230" }, { "label": "Культивация", "value": "1901" }, { "label": "Культивирование", "value": "1860" }, { "label": "Курама", "value": "5709" }, { "label": "Курилин", "value": "6134" }, { "label": "Кушина узумаки", "value": "5222" }, { "label": "Лавкрафт", "value": "6063" }, { "label": "Лара крофт", "value": "6435" }, { "label": "Легенда о зельде", "value": "5707" }, { "label": "Ленивый главный герой", "value": "1516" }, { "label": "Леон золдик", "value": "7469" }, { "label": "Лес", "value": "6645" }, { "label": "Лечебная магия", "value": "562" }, { "label": "Локи", "value": "1725" }, { "label": "Лоли", "value": "1576" }, { "label": "Лопата", "value": "4989" }, { "label": "Лорд", "value": "8404" }, { "label": "Лориен", "value": "7397" }, { "label": "Лошади", "value": "6110" }, { "label": "Лунатизм", "value": "3520" }, { "label": "Луффи", "value": "274" }, { "label": "Лучник", "value": "1038" }, { "label": "Любовный интерес влюбляется первым", "value": "7753" }, { "label": "Любовный треугольник", "value": "2109" }, { "label": "Любовь", "value": "2297" }, { "label": "Любовь с первого взгляда", "value": "7748" }, { "label": "Любящие родители", "value": "2699" }, { "label": "Люди", "value": "3572" }, { "label": "Люцифер", "value": "5883" }, { "label": "Маг", "value": "780" }, { "label": "Магазин", "value": "4762" }, { "label": "Маги", "value": "58" }, { "label": "Магическая академия", "value": "6788" }, { "label": "Магические звери", "value": "684" }, { "label": "Магические предметы", "value": "1648" }, { "label": "Магический мир", "value": "578" }, { "label": "Магия", "value": "150" }, { "label": "Магия воды", "value": "6450" }, { "label": "Магия воздуха", "value": "7627" }, { "label": "Магия земли", "value": "7626" }, { "label": "Магия и технология", "value": "107" }, { "label": "Магия крови", "value": "7976" }, { "label": "Магия льда", "value": "1379" }, { "label": "Магия огня", "value": "7625" }, { "label": "Магия призыва", "value": "885" }, { "label": "Магия природы", "value": "6226" }, { "label": "Магия стихий", "value": "7673" }, { "label": "Магия тьмы", "value": "3596" }, { "label": "Мадара", "value": "2929" }, { "label": "Мазохизм", "value": "1961" }, { "label": "Мама", "value": "12" }, { "label": "Мама и дочь", "value": "7894" }, { "label": "Мама и сын", "value": "7895" }, { "label": "Манга", "value": "2464" }, { "label": "Манипуляция временем", "value": "932" }, { "label": "Маньяк", "value": "2026" }, { "label": "Маргери тирелл", "value": "3935" }, { "label": "Марионетки", "value": "3175" }, { "label": "Марс", "value": "4013" }, { "label": "Марти стью", "value": "594" }, { "label": "Мастер на все руки", "value": "3189" }, { "label": "Матриархат", "value": "7197" }, { "label": "Мать и сестры", "value": "7946" }, { "label": "Мафия", "value": "353" }, { "label": "Мачеха", "value": "4664" }, { "label": "Мегаполис", "value": "3322" }, { "label": "Медицина", "value": "441" }, { "label": "Медленная романтика", "value": "8383" }, { "label": "Медленное развитие истории", "value": "7462" }, { "label": "Мелиодас", "value": "7224" }, { "label": "Мелодрама", "value": "1507" }, { "label": "Менеджмент", "value": "368" }, { "label": "Мерлин", "value": "3977" }, { "label": "Месть", "value": "1218" }, { "label": "Меч", "value": "48" }, { "label": "Мечники", "value": "969" }, { "label": "Мечта", "value": "527" }, { "label": "Мизуки", "value": "4269" }, { "label": "Микото", "value": "3862" }, { "label": "Милая главная героиня", "value": "134" }, { "label": "Милф", "value": "1987" }, { "label": "Милый главный герой", "value": "2678" }, { "label": "Мимик", "value": "5706" }, { "label": "Мина ашидо", "value": "7695" }, { "label": "Минато намикадзе", "value": "5223" }, { "label": "Мир будущего", "value": "1770" }, { "label": "Мир земли", "value": "8394" }, { "label": "Мир меча и магии", "value": "1271" }, { "label": "Мистер пропер", "value": "565" }, { "label": "Мифические существа", "value": "1878" }, { "label": "Мифы и легенды", "value": "4463" }, { "label": "Младшая сестра", "value": "1523" }, { "label": "Мморпг", "value": "620" }, { "label": "Много главных героев", "value": "1191" }, { "label": "Много крови", "value": "5318" }, { "label": "Много персонажей", "value": "1539" }, { "label": "Множество королевств", "value": "32" }, { "label": "Модерн", "value": "5457" }, { "label": "Мокутон", "value": "4438" }, { "label": "Молоко", "value": "5469" }, { "label": "Монархия", "value": "3590" }, { "label": "Монстры", "value": "307" }, { "label": "Море", "value": "922" }, { "label": "Моритика ринносукэ", "value": "1142" }, { "label": "Мортал комбат", "value": "5861" }, { "label": "Мошенник", "value": "959" }, { "label": "Мрачный мир", "value": "1" }, { "label": "Мужчина в женском теле", "value": "8405" }, { "label": "Музыка", "value": "1183" }, { "label": "Мультивселенная", "value": "7410" }, { "label": "Мурим", "value": "7342" }, { "label": "Мутанты", "value": "2392" }, { "label": "Мутация", "value": "29" }, { "label": "Мясо", "value": "1503" }, { "label": "На реальных событиях", "value": "26" }, { "label": "Навыки", "value": "415" }, { "label": "Нагато узумаки", "value": "5221" }, { "label": "Наемники", "value": "1668" }, { "label": "Назарик", "value": "5369" }, { "label": "Наивный главный герой", "value": "159" }, { "label": "Наложница", "value": "4867" }, { "label": "Наноботы", "value": "2332" }, { "label": "Наруто", "value": "7177" }, { "label": "Наруто и хината", "value": "5766" }, { "label": "Насилие и жестокость", "value": "1440" }, { "label": "Наука", "value": "2150" }, { "label": "Национализм", "value": "5556" }, { "label": "Нацу", "value": "5826" }, { "label": "Нацуки субару", "value": "6656" }, { "label": "Начальная школа", "value": "3920" }, { "label": "Наши дни", "value": "1814" }, { "label": "Не всесильный главный герой", "value": "42" }, { "label": "Не по канону", "value": "1611" }, { "label": "Неверность", "value": "5735" }, { "label": "Невеста", "value": "6011" }, { "label": "Неджи хьюга", "value": "3099" }, { "label": "Недооценённый главный герой", "value": "43" }, { "label": "Нежить", "value": "1949" }, { "label": "Некромаг", "value": "7441" }, { "label": "Некромант", "value": "1914" }, { "label": "Некромантия", "value": "754" }, { "label": "Ненормативная лексика", "value": "160" }, { "label": "Необычные герои", "value": "67" }, { "label": "Нет людей", "value": "7486" }, { "label": "Нетораре", "value": "403" }, { "label": "Нетори", "value": "5393" }, { "label": "Нефилимы", "value": "7764" }, { "label": "Нецензурная лексика", "value": "4912" }, { "label": "Нечисть", "value": "4559" }, { "label": "Ник фьюри", "value": "6304" }, { "label": "Ниндзюцу", "value": "2354" }, { "label": "Ниндзя", "value": "1330" }, { "label": "Новелла", "value": "2105" }, { "label": "Нэко", "value": "147" }, { "label": "Оби ван кеноби", "value": "6830" }, { "label": "Обито учиха", "value": "2814" }, { "label": "Оборотни", "value": "53" }, { "label": "Обратный гарем", "value": "3303" }, { "label": "Овощ", "value": "6098" }, { "label": "Огнестрельное оружие", "value": "3155" }, { "label": "Одержимость", "value": "708" }, { "label": "Один в поле воин", "value": "6498" }, { "label": "Онлайн игра", "value": "1565" }, { "label": "Ооками теппей", "value": "849" }, { "label": "Оригинальные персонажи", "value": "7741" }, { "label": "Орки", "value": "1597" }, { "label": "Оружие", "value": "125" }, { "label": "Основано на видео игре", "value": "602" }, { "label": "Особые способности", "value": "2904" }, { "label": "От бедности к богатству", "value": "901" }, { "label": "От слабого до сильного", "value": "118" }, { "label": "Отель", "value": "2879" }, { "label": "Отец", "value": "3290" }, { "label": "Отношения", "value": "398" }, { "label": "Отношения человек/нечеловек", "value": "7406" }, { "label": "Офис", "value": "3460" }, { "label": "Охотники", "value": "2263" }, { "label": "Оцуцуки", "value": "5101" }, { "label": "Ошейник", "value": "2362" }, { "label": "Ояш", "value": "8048" }, { "label": "Падчерица", "value": "7023" }, { "label": "Падший ангел", "value": "184" }, { "label": "Палач", "value": "852" }, { "label": "Палочка", "value": "2682" }, { "label": "Пандорум", "value": "4360" }, { "label": "Папа и дочь", "value": "7647" }, { "label": "Паразит", "value": "1213" }, { "label": "Параллельный мир", "value": "2092" }, { "label": "Парень", "value": "619" }, { "label": "Паркур", "value": "3391" }, { "label": "Пародия", "value": "898" }, { "label": "Пасхалки", "value": "455" }, { "label": "Паук", "value": "2209" }, { "label": "Пекарь", "value": "5073" }, { "label": "Первая книга", "value": "269" }, { "label": "Первая любовь", "value": "640" }, { "label": "Первый раз", "value": "1465" }, { "label": "Переводы", "value": "24" }, { "label": "Перевоплощение", "value": "1596" }, { "label": "Перевоплощение в игровом мире", "value": "92" }, { "label": "Перемещение в другой мир", "value": "1288" }, { "label": "Перемещение во времени", "value": "146" }, { "label": "Перерождение", "value": "894" }, { "label": "Перерождение в демона", "value": "1111" }, { "label": "Перерождение в дракона", "value": "6867" }, { "label": "Перерождение в злодейку", "value": "5619" }, { "label": "Перерождение в злодея", "value": "749" }, { "label": "Перерождение в ином мире", "value": "109" }, { "label": "Перерождение в монстра", "value": "917" }, { "label": "Перерождений", "value": "335" }, { "label": "Переселение", "value": "813" }, { "label": "Переселение души", "value": "1864" }, { "label": "Перси джексон", "value": "6329" }, { "label": "Пилот", "value": "5521" }, { "label": "Пилюли", "value": "1531" }, { "label": "Пират", "value": "1579" }, { "label": "Пирог", "value": "80" }, { "label": "Писатель", "value": "734" }, { "label": "Пистолеты", "value": "4916" }, { "label": "Письмо", "value": "840" }, { "label": "Питомцы", "value": "3122" }, { "label": "Планомерное развитие событий", "value": "62" }, { "label": "Племянник", "value": "8303" }, { "label": "Пленница", "value": "4897" }, { "label": "Плети", "value": "4839" }, { "label": "Пляж", "value": "4243" }, { "label": "Повар", "value": "658" }, { "label": "Повествование от первого лица", "value": "1054" }, { "label": "Повествование от разных лиц", "value": "600" }, { "label": "Повествование от третьего лица", "value": "2116" }, { "label": "Подавитель", "value": "497" }, { "label": "Подземелье", "value": "798" }, { "label": "Подростки", "value": "636" }, { "label": "Подруга", "value": "5804" }, { "label": "Подчинение", "value": "8343" }, { "label": "Подчинение и унижение", "value": "4500" }, { "label": "Покемоны", "value": "2840" }, { "label": "Полиамория", "value": "1300" }, { "label": "Полигамия", "value": "1336" }, { "label": "Политика", "value": "1313" }, { "label": "Полицейский", "value": "1907" }, { "label": "Полубог", "value": "7170" }, { "label": "Полукровка", "value": "999" }, { "label": "Полулюди", "value": "2273" }, { "label": "Поношенные трусики", "value": "1204" }, { "label": "Попаданец", "value": "2396" }, { "label": "Попаданец в другой мир", "value": "685" }, { "label": "Попаданец в игру", "value": "6466" }, { "label": "Попадание в книгу", "value": "6957" }, { "label": "Постапокалипсис", "value": "1079" }, { "label": "Похищение", "value": "7452" }, { "label": "Поэзия", "value": "1120" }, { "label": "Правитель", "value": "2261" }, { "label": "Превращения в животных", "value": "3410" }, { "label": "Преданный любовный интерес", "value": "2055" }, { "label": "Предательство", "value": "70" }, { "label": "Президент", "value": "4334" }, { "label": "Преступник", "value": "4049" }, { "label": "Преступный мир", "value": "965" }, { "label": "Призрак", "value": "511" }, { "label": "Призыв", "value": "332" }, { "label": "Призыв в другой мир", "value": "781" }, { "label": "Призыв существ", "value": "412" }, { "label": "Приложение на телефоне", "value": "5345" }, { "label": "Принудительный брак", "value": "2954" }, { "label": "Принуждение", "value": "1442" }, { "label": "Принц", "value": "362" }, { "label": "Принцесса", "value": "2403" }, { "label": "Приручение мостров", "value": "2338" }, { "label": "Прислуга", "value": "5185" }, { "label": "Пришельцы", "value": "273" }, { "label": "Проза", "value": "2012" }, { "label": "Прокачка", "value": "1070" }, { "label": "Проклятия", "value": "1347" }, { "label": "Проработанный мир", "value": "1711" }, { "label": "Пророчество", "value": "7762" }, { "label": "Против наркотиков", "value": "8406" }, { "label": "Псайкеры", "value": "3659" }, { "label": "Псионика", "value": "5216" }, { "label": "Психбольница", "value": "6969" }, { "label": "Психические расстройства", "value": "2445" }, { "label": "Психологические травмы", "value": "3418" }, { "label": "Публичный дом", "value": "7860" }, { "label": "Путешествие в другой мир", "value": "10" }, { "label": "Пух", "value": "4286" }, { "label": "Пушечное мясо", "value": "7234" }, { "label": "Пытки", "value": "1756" }, { "label": "Пьяный мастер", "value": "1655" }, { "label": "Пэнси паркинсон", "value": "7411" }, { "label": "Раб", "value": "977" }, { "label": "Рабы", "value": "1240" }, { "label": "Разведение животных", "value": "3990" }, { "label": "Развитие", "value": "208" }, { "label": "Развитие персонажа", "value": "1780" }, { "label": "Развитие поселения", "value": "7203" }, { "label": "Развитие технологий", "value": "1875" }, { "label": "Раздвоение личности", "value": "2062" }, { "label": "Разные расы", "value": "1188" }, { "label": "Разорванная помолвка", "value": "2057" }, { "label": "Разработчик", "value": "2333" }, { "label": "Ранги", "value": "1568" }, { "label": "Ранобэ", "value": "1764" }, { "label": "Расизм", "value": "3554" }, { "label": "Растение", "value": "407" }, { "label": "Реализм", "value": "1180" }, { "label": "Ребенок", "value": "2881" }, { "label": "Ревность", "value": "293" }, { "label": "Революция", "value": "3996" }, { "label": "Реинкарнация", "value": "1302" }, { "label": "Реинкарнация в другом мире", "value": "2180" }, { "label": "Реинкарнация в игровой мир", "value": "304" }, { "label": "Рейджер", "value": "5147" }, { "label": "Религия", "value": "2184" }, { "label": "Рем", "value": "6655" }, { "label": "Ремесленник", "value": "1483" }, { "label": "Ремонт", "value": "5703" }, { "label": "Репликаторы", "value": "3495" }, { "label": "Ресторан", "value": "7519" }, { "label": "Риас гремори", "value": "6950" }, { "label": "Рим", "value": "612" }, { "label": "Риннеган", "value": "4230" }, { "label": "Ритуал", "value": "1233" }, { "label": "Робот", "value": "4011" }, { "label": "Роботы", "value": "467" }, { "label": "Рок ли", "value": "7002" }, { "label": "Рокси", "value": "7380" }, { "label": "Рон уизли", "value": "4279" }, { "label": "Ророноа зоро", "value": "1590" }, { "label": "Росомаха", "value": "1035" }, { "label": "Российская империя", "value": "2146" }, { "label": "Россия", "value": "4246" }, { "label": "Рудеус", "value": "7379" }, { "label": "Руны", "value": "2393" }, { "label": "Русалки", "value": "3127" }, { "label": "Русь", "value": "2016" }, { "label": "Рыцари", "value": "1902" }, { "label": "Рэо хатаке", "value": "2823" }, { "label": "Сабли", "value": "6136" }, { "label": "Сайян", "value": "6802" }, { "label": "Сакура", "value": "2515" }, { "label": "Самец", "value": "1592" }, { "label": "Самураи", "value": "576" }, { "label": "Санса старк", "value": "3925" }, { "label": "Сарказм", "value": "4658" }, { "label": "Саске", "value": "7237" }, { "label": "Сатира", "value": "215" }, { "label": "Сборник", "value": "7367" }, { "label": "Свадьба", "value": "1524" }, { "label": "Сверхсила", "value": "1055" }, { "label": "Свинцовые книги", "value": "5322" }, { "label": "Связывание", "value": "4506" }, { "label": "Священик", "value": "61" }, { "label": "Северус снейп", "value": "5783" }, { "label": "Сёдзе", "value": "2219" }, { "label": "Секты", "value": "1234" }, { "label": "Сельское хозяйство", "value": "787" }, { "label": "Семейный конфликт", "value": "935" }, { "label": "Семья", "value": "728" }, { "label": "Сенджу", "value": "6069" }, { "label": "Серийный убийца", "value": "261" }, { "label": "Сестра", "value": "2342" }, { "label": "Сила глаза", "value": "1019" }, { "label": "Сильная героиня", "value": "7292" }, { "label": "Сильная главная героиня", "value": "1994" }, { "label": "Сильный главный герой", "value": "570" }, { "label": "Сильфиетта", "value": "7381" }, { "label": "Симбиот", "value": "2648" }, { "label": "Сириус блэк", "value": "7655" }, { "label": "Сирота", "value": "297" }, { "label": "Система", "value": "251" }, { "label": "Система уровней", "value": "2174" }, { "label": "Ситх", "value": "1618" }, { "label": "Сказка", "value": "3570" }, { "label": "Скайрим", "value": "4032" }, { "label": "Скайуокер", "value": "6828" }, { "label": "Сквиб", "value": "4101" }, { "label": "Скелет", "value": "1315" }, { "label": "Скрытые способности", "value": "3417" }, { "label": "Скульптор", "value": "1178" }, { "label": "Слабая главная героиня", "value": "5805" }, { "label": "Слабый главный герой", "value": "731" }, { "label": "Славяне", "value": "2168" }, { "label": "Слизерин", "value": "6979" }, { "label": "Слизь", "value": "1095" }, { "label": "Сломанная игрушка", "value": "8396" }, { "label": "Служанка", "value": "3486" }, { "label": "Смартфон", "value": "457" }, { "label": "Смена сущности", "value": "8391" }, { "label": "Смерть", "value": "1779" }, { "label": "Смерть основного персонажа", "value": "1530" }, { "label": "Собаки", "value": "6109" }, { "label": "Соблазн", "value": "7994" }, { "label": "Соблазнение", "value": "2290" }, { "label": "Современность", "value": "568" }, { "label": "Современные знания", "value": "988" }, { "label": "Сожительство", "value": "3026" }, { "label": "Создание армии", "value": "1992" }, { "label": "Создание королевства", "value": "1497" }, { "label": "Создание пилюль", "value": "816" }, { "label": "Создатель", "value": "1045" }, { "label": "Сокровища", "value": "6521" }, { "label": "Сокрытие истинной личности", "value": "2894" }, { "label": "Сома и эрина", "value": "5737" }, { "label": "Соперничество", "value": "7699" }, { "label": "Соседи", "value": "4075" }, { "label": "Сотрудник", "value": "6339" }, { "label": "Социология", "value": "7618" }, { "label": "Спокойная главная героиня", "value": "236" }, { "label": "Спокойный главный герой", "value": "1656" }, { "label": "Спор", "value": "3484" }, { "label": "Спортивное тело", "value": "8317" }, { "label": "Способность кражи", "value": "7784" }, { "label": "Сражения", "value": "23" }, { "label": "Средневековье", "value": "1022" }, { "label": "Сталкер", "value": "1932" }, { "label": "Становление государства", "value": "111" }, { "label": "Старшая школа", "value": "1658" }, { "label": "Стёб", "value": "454" }, { "label": "Стекло", "value": "7453" }, { "label": "Стеснительный персонаж", "value": "152" }, { "label": "Стимпанк", "value": "1894" }, { "label": "Стихи", "value": "1309" }, { "label": "Стратегия", "value": "569" }, { "label": "Строительство", "value": "921" }, { "label": "Студент", "value": "1464" }, { "label": "Студентка", "value": "7518" }, { "label": "Суккубы", "value": "2662" }, { "label": "Супер зрение", "value": "6574" }, { "label": "Супер удача", "value": "489" }, { "label": "Супергерои", "value": "1481" }, { "label": "Суперзлодеи", "value": "2125" }, { "label": "Супермен", "value": "6997" }, { "label": "Суперсилы", "value": "2276" }, { "label": "Существа", "value": "6033" }, { "label": "Сферы", "value": "1077" }, { "label": "Схемы и заговоры", "value": "7116" }, { "label": "Сценарий", "value": "7489" }, { "label": "Счастливый конец", "value": "3293" }, { "label": "Сын", "value": "3297" }, { "label": "Сэм винчестер", "value": "7461" }, { "label": "Сюаньхуа", "value": "2560" }, { "label": "Сюжетные повороты", "value": "7202" }, { "label": "Таблетки для развития", "value": "589" }, { "label": "Таинственное прошлое", "value": "769" }, { "label": "Тайная личность", "value": "8096" }, { "label": "Тайная любовь", "value": "113" }, { "label": "Тайны", "value": "7481" }, { "label": "Тайные отношения", "value": "7450" }, { "label": "Тайцы", "value": "6413" }, { "label": "Танки", "value": "1787" }, { "label": "Творчество", "value": "20" }, { "label": "Тейлор эберт", "value": "3526" }, { "label": "Телекинез", "value": "2203" }, { "label": "Телепортация", "value": "914" }, { "label": "Телохранитель", "value": "723" }, { "label": "Темари", "value": "4810" }, { "label": "Темная магия", "value": "4788" }, { "label": "Темное фэнтези", "value": "1675" }, { "label": "Темные эльфы", "value": "7198" }, { "label": "Тенсейган", "value": "4367" }, { "label": "Тетя", "value": "4194" }, { "label": "Техномагия", "value": "508" }, { "label": "Тиран", "value": "1174" }, { "label": "Титаны", "value": "3308" }, { "label": "Тодороки шото", "value": "5105" }, { "label": "Токио", "value": "5791" }, { "label": "Том реддл", "value": "6652" }, { "label": "Тони старк", "value": "1338" }, { "label": "Тор", "value": "1800" }, { "label": "Тор и локи", "value": "2645" }, { "label": "Торговля", "value": "1637" }, { "label": "Травничество", "value": "221" }, { "label": "Трагическое прошлое", "value": "644" }, { "label": "Трактир", "value": "1918" }, { "label": "Трансмиграция", "value": "1071" }, { "label": "Трансформация", "value": "156" }, { "label": "Трансформеры", "value": "4616" }, { "label": "Тревор филипс", "value": "5427" }, { "label": "Тройняшки", "value": "7169" }, { "label": "Троли", "value": "4250" }, { "label": "Трудолюбивый главный герой", "value": "248" }, { "label": "Тупой главный герой", "value": "3710" }, { "label": "Тьма", "value": "1919" }, { "label": "Тюрьма", "value": "5597" }, { "label": "Тяжёлое детство", "value": "2253" }, { "label": "Убийства", "value": "378" }, { "label": "Убийцы", "value": "1766" }, { "label": "Убийцы драконов", "value": "1484" }, { "label": "Увечья", "value": "3266" }, { "label": "Удача", "value": "6575" }, { "label": "Узумаки", "value": "7579" }, { "label": "Укротитель", "value": "367" }, { "label": "Умения", "value": "531" }, { "label": "Умная главная героиня", "value": "1381" }, { "label": "Умные персонажи", "value": "2756" }, { "label": "Умный главный герой", "value": "2093" }, { "label": "Университет", "value": "2102" }, { "label": "Унижение", "value": "8342" }, { "label": "Уничтожение мира", "value": "81" }, { "label": "Управление временем", "value": "5648" }, { "label": "Уровни", "value": "8" }, { "label": "Усиление", "value": "3549" }, { "label": "Усопп", "value": "6737" }, { "label": "Устроенный брак", "value": "2223" }, { "label": "Усыновление", "value": "395" }, { "label": "Утопия", "value": "4677" }, { "label": "Уход за детьми", "value": "7609" }, { "label": "Учеба в университете", "value": "2797" }, { "label": "Учебное заведение", "value": "1817" }, { "label": "Ученые", "value": "1843" }, { "label": "Учитель", "value": "845" }, { "label": "Учиха", "value": "5348" }, { "label": "Фамильяры", "value": "1471" }, { "label": "Фанатичная любовь", "value": "6721" }, { "label": "Фанаты", "value": "7739" }, { "label": "Фантастический мир", "value": "2414" }, { "label": "Фармацевт", "value": "1706" }, { "label": "Фашисты", "value": "3118" }, { "label": "Феи", "value": "7185" }, { "label": "Фелляция", "value": "5880" }, { "label": "Феминизм", "value": "6527" }, { "label": "Феникс", "value": "2413" }, { "label": "Фенрир", "value": "2740" }, { "label": "Феодализм", "value": "280" }, { "label": "Ферма", "value": "285" }, { "label": "Фехтовальщик", "value": "4685" }, { "label": "Филиппины", "value": "128" }, { "label": "Философия", "value": "1859" }, { "label": "Флафф", "value": "5048" }, { "label": "Флер делакур", "value": "5191" }, { "label": "Флэш", "value": "4667" }, { "label": "Фокусник", "value": "7602" }, { "label": "Фольклор", "value": "4086" }, { "label": "Фугаку", "value": "6161" }, { "label": "Фурри", "value": "6631" }, { "label": "Футбол", "value": "1121" }, { "label": "Фэнтезийный мир", "value": "1556" }, { "label": "Хакер", "value": "475" }, { "label": "Халк", "value": "1196" }, { "label": "Хан нуньен синг", "value": "4817" }, { "label": "Ханма юджиро", "value": "4369" }, { "label": "Хаос", "value": "3117" }, { "label": "Харизматичный главный герой", "value": "2350" }, { "label": "Хатаке какаши", "value": "2820" }, { "label": "Хиддлстон", "value": "5903" }, { "label": "Химавари", "value": "2583" }, { "label": "Хината", "value": "2513" }, { "label": "Хитрый главный герой", "value": "2036" }, { "label": "Хоббит", "value": "6698" }, { "label": "Хогвартс", "value": "5954" }, { "label": "Холодная главная героиня", "value": "6507" }, { "label": "Холодное оружие", "value": "4889" }, { "label": "Холодный главный герой", "value": "2686" }, { "label": "Храм", "value": "2135" }, { "label": "Христианство", "value": "877" }, { "label": "Художественная литература", "value": "2380" }, { "label": "Художница", "value": "518" }, { "label": "Хулиганы", "value": "854" }, { "label": "Цветок", "value": "902" }, { "label": "Цезарь", "value": "1705" }, { "label": "Целители", "value": "4523" }, { "label": "Церковь", "value": "1980" }, { "label": "Цундере", "value": "1078" }, { "label": "Чакра", "value": "1393" }, { "label": "Чат-система", "value": "8407" }, { "label": "Черный юмор", "value": "2868" }, { "label": "Честная главная героиня", "value": "5855" }, { "label": "Честный главный герой", "value": "129" }, { "label": "Читы", "value": "451" }, { "label": "Шантаж", "value": "7175" }, { "label": "Шаринган", "value": "5165" }, { "label": "Шинигами", "value": "4661" }, { "label": "Шиноби", "value": "1227" }, { "label": "Школьная жизнь", "value": "284" }, { "label": "Школьники", "value": "218" }, { "label": "Школьницы", "value": "5946" }, { "label": "Шлюха", "value": "5822" }, { "label": "Шоу-бизнес", "value": "7119" }, { "label": "Шпионы", "value": "4262" }, { "label": "Эволюция", "value": "2040" }, { "label": "Экзорцизм", "value": "676" }, { "label": "Экономика", "value": "121" }, { "label": "Экспансия", "value": "110" }, { "label": "Эксперименты над людьми", "value": "7408" }, { "label": "Элементальная магия", "value": "1264" }, { "label": "Эльфы", "value": "1362" }, { "label": "Эротика", "value": "2053" }, { "label": "Юмор", "value": "7360" }, { "label": "Яды", "value": "201" }, { "label": "Якудза", "value": "4599" }, { "label": "Яндере", "value": "7111" }, { "label": "Rpg", "value": "90" }, { "label": "Star wars", "value": "1985" }, { "label": "Time skip", "value": "824" }, { "label": "Warrior of light", "value": "5289" }], "inputType": filterInputs_1.FilterInputs.Checkbox }, { "key": "fandoms_ex", "label": "Исключить фэндомы:", "values": [{ "label": "19 Дней - Один день / 19 Days - One Day", "value": "838" }, { "label": "47-й / Хитмэн: Агент 47 / Наёмный убийца / Hitman", "value": "589" }, { "label": "Абсолютный дуэт / Absolute Duo", "value": "1029" }, { "label": "Аватар (Короля; об Аанге; об Корре) / Avatar", "value": "1889" }, { "label": "Аватар: Легенда о Корре / Avatar legend of Korra", "value": "351" }, { "label": "Аватар: Легенда об Аанге / Avatar: The Legend of Aang / Avatar: The Last Airbender", "value": "303" }, { "label": "Аватар(Фильм, 2009) / Avatar", "value": "19" }, { "label": "Ад Данте(Данте Алигьери) / Dante's Inferno(Dante Alighieri)", "value": "1502" }, { "label": "Азур Лейн / Azur Lane", "value": "1009" }, { "label": "Айон / Aion", "value": "1005" }, { "label": "Аладдин / Aladdin", "value": "502" }, { "label": "Алиса в Стране чудес / Alice in Wonderland", "value": "616" }, { "label": "Альдноа.Зеро / Aldnoah.Zero", "value": "1799" }, { "label": "Амагами СС / Amagami SS", "value": "900" }, { "label": "Амано Мегуми полна любви! / Amano Megumi wa Sukidarake!", "value": "991" }, { "label": "Американские боги / American Gods", "value": "1843" }, { "label": "Американский папаша! / American Dad", "value": "348" }, { "label": "Ангельские ритмы! / Angel Beats!", "value": "880" }, { "label": "Анлимитед: Хёбу Кёске / Zettai Karen Children: The Unlimited - Hyoubu Kyousuke", "value": "74" }, { "label": "Апостол карточек / The Apostle of Cards", "value": "1504" }, { "label": "Арифурэта: сильнейший ремесленник в мире / Arifureta: From Commonplace to World's Strongest", "value": "62" }, { "label": "Аркан: О Паровых Заводах и Магии Обскуры / Arcanum: Of Steamworks and Magick Obscura", "value": "1495" }, { "label": "Аркейн / Arcane: League of Legends", "value": "1154" }, { "label": "Аркнайтс(Games) / Arknights", "value": "1210" }, { "label": "Армелло(Games) / Armello", "value": "1846" }, { "label": "Астра, затерянная в космосе / Kanata no Astra", "value": "1851" }, { "label": "Атака титанов / Атака на титанов / Attack on Titan", "value": "106" }, { "label": "Атлантида: Затерянный мир / Atlantis: The Lost Empire", "value": "985" }, { "label": "Бакуган Отчаянные бойцы / Bakugan Battle Brawlers", "value": "1069" }, { "label": "Банановая рыба / Banana Fish", "value": "1685" }, { "label": "Баскетбол Куроко / Kuroko no basuke", "value": "582" }, { "label": "Баффи - Истребительница вампиров / Buffy the Vampire Slayer", "value": "115" }, { "label": "Башня Бога / Tower of God", "value": "58" }, { "label": "Бездарная Нана / Munou na Nana", "value": "954" }, { "label": "Бездомный бог / Норагами / Noragami", "value": "1014" }, { "label": "Безумные Мотивы / Looney Tunes", "value": "1140" }, { "label": "Безумный азарт / Kakegurui", "value": "334" }, { "label": "Бейблэйд / Beyblade", "value": "921" }, { "label": "Бен - 10 / Ben 10", "value": "475" }, { "label": "Берсерк / Berserk", "value": "479" }, { "label": "Бесконечное лето / Everlasting Summer", "value": "966" }, { "label": "Бесконечный ужас / Terror Infinity", "value": "381" }, { "label": "Бесподобный Воинственный Бог / Peerless Martial God", "value": "419" }, { "label": "Бессмертный Деревенщина(Games) / Immortal Redneck", "value": "1524" }, { "label": "Бесстыжие / Shameless", "value": "1759" }, { "label": "Био шок(Games) / BioShock", "value": "1095" }, { "label": "Блейд / Blade", "value": "1479" }, { "label": "Блич / Bleach", "value": "7" }, { "label": "Бог войны / God Of War", "value": "352" }, { "label": "Бог из машины / Deus Ex", "value": "612" }, { "label": "Боги поступают плохо / Игры богов / Gods Behaving Badly", "value": "301" }, { "label": "Боевая академия города Астериск / Gakusen Toshi Asterisk", "value": "884" }, { "label": "Боевой континент / Combat Continent / Douluo Dalu", "value": "739" }, { "label": "Боевой молот 40-го тысячелетия / WH40K / Warhammer 40,000", "value": "341" }, { "label": "Боевой молот Фэнтезийная битва / Warhammer Fantasy Battles", "value": "1742" }, { "label": "Боевые машины(Games) / BattleTech", "value": "1667" }, { "label": "Боец Баки / Baki the Grappler", "value": "821" }, { "label": "Божественность II: Эго Дракона(Games) / Divinity II: Ego Draconis", "value": "1538" }, { "label": "Божественные Врата / Divine Gate", "value": "1490" }, { "label": "Большая автомобильная кража 5 / GTA V / Grand Theft Auto V", "value": "1139" }, { "label": "Большая автомобильная кража: Сан-Андреас / GTA: SA / Grand Theft Auto: San Andreas", "value": "820" }, { "label": "Большая разница / Far Cry", "value": "939" }, { "label": "Большой куш / Ван Пис / One Piece", "value": "25" }, { "label": "Боруто: Следующие поколения Наруто / Boruto: Naruto Next Generations", "value": "602" }, { "label": "Брак по договоренности с принцессой красных скорпионов / Arranged marriage to the princess of the Red Scorpions", "value": "1386" }, { "label": "Бэтмен за гранью: Наследие / Batman Beyond: Legacy", "value": "1380" }, { "label": "В другом мире со смартфоном / Isekai wa Smartphone to Tomo ni", "value": "947" }, { "label": "В объятиях шлюхи / JK Bitch ni Shiboraretai", "value": "1283" }, { "label": "В ожидании бедности, я собираюсь стать кузнецом / Expecting to Fall into Ruin, I Aim to Become a Blacksmith", "value": "1475" }, { "label": "В Повелителе как Довакин / In Overlord as a Dovahkiin", "value": "1816" }, { "label": "Вакфу / Wakfu", "value": "814" }, { "label": "ВАЛЛ-И / Wally", "value": "801" }, { "label": "Вампир: Маскарад - Родословные / Vampire: The Masquerade Bloodline", "value": "1212" }, { "label": "Вампирелла / Vampirella", "value": "1214" }, { "label": "Варфрейм / Warframe", "value": "967" }, { "label": "Ведьмак / The Witcher", "value": "278" }, { "label": "Великий из бродячих псов / Bungou Stray Dogs", "value": "75" }, { "label": "Великолепный парк Амаги / Amagi Brilliant Park", "value": "813" }, { "label": "Вельзепуз / Вельзевул / Beelzebub", "value": "765" }, { "label": "Веном / Venom", "value": "978" }, { "label": "Веселая ферма / Fun Farm", "value": "1124" }, { "label": "Вечная история / The Neverending Story", "value": "547" }, { "label": "Вечные(Фильм, 2021) / Eternal", "value": "1234" }, { "label": "Виви: Песнь флюоритового глаза / Vivy: Fluorite Eye's Song", "value": "1819" }, { "label": "Викинги / Vikings", "value": "369" }, { "label": "Владелец ранчо со слизью(Games) / Ранчо слизи / Slime Rancher", "value": "1529" }, { "label": "Властелин колец / Lord of the Ring", "value": "254" }, { "label": "Власть книжного червя / Honzuki no Gekokujou", "value": "1399" }, { "label": "Внук Мудрец / Kenjo no Mago", "value": "1260" }, { "label": "Внук Нурарихёна / Nurarihyon no Mago", "value": "66" }, { "label": "Во всеоружии / Overgeared", "value": "1021" }, { "label": "Во тьме(Games) / The Darkness", "value": "938" }, { "label": "Военная хроника маленькой девочки / Сага о злой Тане / The Saga of Tanya the Evil / \tGekijouban Youjo Senki", "value": "1726" }, { "label": "Возвращение в детские годы / Gaki ni Modotte Yarinaoshi!!!", "value": "1031" }, { "label": "Возрождение Серийного Убийцы / Rebirth Of A Serial Killer", "value": "1358" }, { "label": "Воинственный Бог Асура / Martial God Asura", "value": "771" }, { "label": "Война будущего / The Tomorrow War", "value": "1174" }, { "label": "Война Любовь Снег / War Love Snow", "value": "1417" }, { "label": "Волейбол! / Haikyuu!!", "value": "697" }, { "label": "Волчонок / Teen Wolf", "value": "795" }, { "label": "Волшебная Девушка Спецоперация Аска / Magical Girl Spec-Ops Asuka", "value": "1470" }, { "label": "Волшебник-воин Орфен / Majutsushi Orphen Hagure Tabi: Kimluck-hen", "value": "1128" }, { "label": "Волшебники / The Magicians", "value": "1314" }, { "label": "Волшебный учитель Нэгима! / Negima!: Magister Negi Mag", "value": "1777" }, { "label": "Воля второго цикла мироздания. / Will of the second cycle of the Worldifice.", "value": "1036" }, { "label": "Воспитание хозяина / Yours to Claim", "value": "839" }, { "label": "Восставший против неба / Against the Gods", "value": "957" }, { "label": "Восстание стражей / Хранители снов / Rise of the Guardians", "value": "1488" }, { "label": "Восхождение в Голливуде / I'm in Hollywood", "value": "1237" }, { "label": "Восхождение героя щита / The Rising of the Shield Hero", "value": "103" }, { "label": "Врата Штейна / Steins: Gate", "value": "1044" }, { "label": "Врата: там бьются наши воины / Gate: Jieitai Kanochi nite, Kaku Tatakaeri", "value": "727" }, { "label": "Время / In Time", "value": "542" }, { "label": "Всегда вялый Танака-кун / Tanaka-kun wa Itsumo Kedaruge", "value": "1082" }, { "label": "Всего лишь восьмой сын? Я с этим не смирюсь! / Hachinan tte, Sore wa Nai Deshou! / Eighth son, I don’t think so!", "value": "1473" }, { "label": "Вселенная Марвел / Marvel Universe / Marvel Comics", "value": "6" }, { "label": "Вселенная монстров / Monsterverse / Monster Verse", "value": "905" }, { "label": "Вселенная Стивена / Steven universe", "value": "573" }, { "label": "Вселенная Стрелы / Arrowverse", "value": "488" }, { "label": "Вселенная Тип Луны(Игровая компания) / Universe Type Moon", "value": "1221" }, { "label": "Вселенная DC / DC Universe / DC Comics", "value": "36" }, { "label": "Выпадение радиоактивных осадков / Fallout", "value": "55" }, { "label": "Выращивание онлайн / Cultivation Online", "value": "1252" }, { "label": "Галактическая секс-звезда / Galaxy Sex Star", "value": "1539" }, { "label": "Гало(Games) / Halo", "value": "1338" }, { "label": "Ганц / Gantz", "value": "256" }, { "label": "Гарем рабов в лабиринте другого мира / Slave Harem in the Labyrinth of the Other World", "value": "1853" }, { "label": "Гарри Поттер / Harry Potter", "value": "1" }, { "label": "Гвен-паук / Spider-Gwen", "value": "920" }, { "label": "Генерал маньяк с его сумасшедшей системой / The Maniacal General with his Crazy System", "value": "1356" }, { "label": "Генерал, вы вправе уйти. / General, You May Leave Now", "value": "1385" }, { "label": "Геншин Импакт / Genshin Impact", "value": "689" }, { "label": "Геркулес / Hercules", "value": "721" }, { "label": "Герои и замки / Heroes & Castles", "value": "940" }, { "label": "Герои меча и магии / Heroes of Might and Magic", "value": "1002" }, { "label": "Герои(телесериал) / Heroes", "value": "864" }, { "label": "Гильгамеш / Gilgamesh", "value": "1143" }, { "label": "Гинтама / Gintama", "value": "129" }, { "label": "Глубина(Фильм, 2002) / Below", "value": "1186" }, { "label": "Гнев Асуры / Asura's wrath", "value": "100" }, { "label": "Годзилла / Godzilla", "value": "922" }, { "label": "Голодные игры / The Hunger Games", "value": "859" }, { "label": "Горец / Highlander", "value": "1761" }, { "label": "Горожане(Games) / Townsmen", "value": "1599" }, { "label": "Госпожа Кагуя: в любви как на войне / Kaguya sama: Love is war", "value": "533" }, { "label": "Готика / Gothic", "value": "418" }, { "label": "Готов ли ты влюбиться в извращенку до тех пор, пока она милая? / Hentai demo Suki ni Natte Kuremasu ka", "value": "1383" }, { "label": "Гоэтия / Гоетия / Yοητεία / Ars Goetia", "value": "772" }, { "label": "Гравити Фолз / Gravity Falls", "value": "491" }, { "label": "Граница пустоты / Kara no Kyoukai", "value": "1101" }, { "label": "Гриффины / Family Guy", "value": "349" }, { "label": "Гром над небом / Thunder over the sky", "value": "793" }, { "label": "Гуррен-Лаганн / Tengen Toppa Gurren Lagann", "value": "719" }, { "label": "Да будет благословенен этот прекрасный мир! / Konosuba / Kono Subarashii Sekai ni Shukufuku wo!", "value": "82" }, { "label": "Да Здравствует Призыв! / Long Live Summons!", "value": "948" }, { "label": "Да, я паук, и что с того? / So I'm a Spider, So What? / Kumo Desu ga, Nani ka?", "value": "910" }, { "label": "Данганронпа / Danganronpa", "value": "972" }, { "label": "Две звезды Онмёджи / Sousei no Onmyouji", "value": "1108" }, { "label": "Дворянство / Благородство / Noblesse", "value": "636" }, { "label": "Девочка-волшебница Мадока Магика / Mahou Shoujo Madoka Magica", "value": "1412" }, { "label": "Девочка, которая видит это / Mieruko-chan", "value": "1645" }, { "label": "Декстер(телесериал) / Dexter", "value": "1543" }, { "label": "Демон Бездны всех царств / Abyss Demon of All Realms", "value": "1419" }, { "label": "Демоны старшей школы / High School DxD", "value": "8" }, { "label": "День независимости(Фильм, 1996) / Independence Day", "value": "850" }, { "label": "Детектив Конан / Detective Conan", "value": "1554" }, { "label": "Дети индиго из другого мира / Mondaiji-tachi ga isekai kara kuru sô desu yo", "value": "1484" }, { "label": "Джаггед Альянс 2: Агония Власти(Games) / Jagged Alliance 2", "value": "1668" }, { "label": "Джессика Джонс / Marvel's Jessica Jones", "value": "1817" }, { "label": "Джон Уик / John Wick", "value": "388" }, { "label": "Дисней / The Walt Disney Company", "value": "503" }, { "label": "Для тебя, Бессмертный / Fumetsu no Anata e / To Your Eternity", "value": "1802" }, { "label": "Дневник Будущего / Mirai Nikki", "value": "368" }, { "label": "Дневники вампира / The Vampire Diaries", "value": "160" }, { "label": "Доблесть рыцаря-неудачника / Chivalry of a Failed Knight", "value": "1462" }, { "label": "Добро пожаловать в ад, Ирума / Welcome to Demon School! Iruma-kun", "value": "261" }, { "label": "Добро пожаловать в класс превосходства / Classroom of the Elite", "value": "122" }, { "label": "Добро пожаловать! В лес похотливых эльфов! / Youkoso! Sukebe Elf no Mori e", "value": "1034" }, { "label": "Добывать ремесло / Майнкрафт / Minecraft", "value": "102" }, { "label": "Доктор Кто / Doctor Who", "value": "277" }, { "label": "Доктор Стоун / Dr. Stone", "value": "720" }, { "label": "Доля секунды: скорость / Split - second: velocity", "value": "890" }, { "label": "Дом кролика / Кофейня "Кроличий домик" / Gochuumon wa Usagi Desu ka?", "value": "642" }, { "label": "Домашний очаг / Hearthstone: Heroes of Warcraft / Hearthstone", "value": "934" }, { "label": "Домекано / Domestic Na Kanojo", "value": "632" }, { "label": "Дорогой звёзд / Звёздное преобразование / Stellar Transformation / Xing Chen Bian", "value": "1155" }, { "label": "Доспехи Бога 2: Операция Кондор / Armour of God II: Operation Condor", "value": "1829" }, { "label": "Дота 2 / Dota 2", "value": "1105" }, { "label": "Дофус / Dofus", "value": "817" }, { "label": "Дракенгард / Drakengard / Drag-On Dragoon", "value": "919" }, { "label": "Дракон-горничная госпожи Кобаяси / Kobayashi-san Chi no Maid Dragon", "value": "673" }, { "label": "Дракон-сама из семьи Касумигаока / Dragon-sama of the Kasumigaoka Family", "value": "1458" }, { "label": "Драконий жемчуг Зет / Dragon Ball Z", "value": "307" }, { "label": "Дракониум Онлайн / Draconic Online", "value": "1360" }, { "label": "Дракула / Dracula", "value": "709" }, { "label": "Древнегреческая мифология / Ancient Greek mythology", "value": "1159" }, { "label": "Дре́вние / Первородные / The Originals", "value": "863" }, { "label": "Древние свитки / The Elder Scrolls", "value": "428" }, { "label": "Древние свитки: Скайрим / TES: Skyrim", "value": "337" }, { "label": "Другой мир / Underworld", "value": "480" }, { "label": "Друид с Сеульской станции / Seoul Station Druid", "value": "1178" }, { "label": "Дьявол / Диабло / Diablo", "value": "1787" }, { "label": "Дьявол может плакать / Devil May Cry / DMC", "value": "339" }, { "label": "Дьявол Юраги-су / The Devil of Yuragi-sou", "value": "431" }, { "label": "Дьявол II(Games) / Диабло II / Diablo II", "value": "1055" }, { "label": "Дэдпул / Deadpool", "value": "810" }, { "label": "Дэнни-призрак / Danny Phantom", "value": "109" }, { "label": "Евангелион / Neon Genesis Evangelion", "value": "583" }, { "label": "Единство семи магов / Тринити: Семь Магов / Trinity Seven", "value": "442" }, { "label": "Еженедельный прыжок сёнэн / Weekly Shōnen Jump", "value": "1629" }, { "label": "Ёрмунганд / Jormungand", "value": "77" }, { "label": "Жажда скорости / Need For Speed", "value": "1493" }, { "label": "Железный человек / Iron Man", "value": "710" }, { "label": "Жемчуг дракона / Dragon Ball", "value": "309" }, { "label": "Женщина-Халк(телесериал) / She-Hulk: Attorney at Law", "value": "1593" }, { "label": "Жизнь девушки в игровом мире / A Girl’s Life In A Gaming World", "value": "1406" }, { "label": "Жизнь после / Days Gone", "value": "1279" }, { "label": "За гранью / Beyond the Boundary", "value": "357" }, { "label": "Загипнотизировать Семью / Kyonyuu Kazoku Saimin", "value": "1032" }, { "label": "Закон Уэки / The Law of Ueki", "value": "790" }, { "label": "Закулисье / Backrooms", "value": "1827" }, { "label": "Зачарованные / Charmed", "value": "113" }, { "label": "Защитники / Defenders", "value": "1832" }, { "label": "Защитница Химари / Omamori Himari", "value": "279" }, { "label": "Звёздная принцесса и силы зла\t / Стар против сил зла / Star vs. The Forces of Evil", "value": "782" }, { "label": "Звёздное дитя / Oshi no Ko", "value": "1903" }, { "label": "Звёздное ремесло / StarCraft", "value": "386" }, { "label": "Звездные Войны / Star Wars", "value": "40" }, { "label": "Звёздные войны: Войны клонов - Все типы носителей(мультсериал, 2008) / Star Wars: The Clone Wars", "value": "1182" }, { "label": "Звёздные врата / Stargate", "value": "770" }, { "label": "Звёздные врата: Атлантида / Stargate: Atlantis", "value": "1097" }, { "label": "Звездный путь / Стартрек / Star Trek", "value": "849" }, { "label": "Зверополис / Zootopia", "value": "1449" }, { "label": "Зеленая Жизнь / Green Life", "value": "1196" }, { "label": "Зеленый фонарь / The Green Lantern", "value": "1222" }, { "label": "Зетмен / Zetman", "value": "1191" }, { "label": "Игра в кальмара(телесериал) / Squid game", "value": "1065" }, { "label": "Игра престолов / Game of Thrones", "value": "22" }, { "label": "Игрок / The Gamer", "value": "126" }, { "label": "Идеальная судьба / The Perfect Destiny", "value": "781" }, { "label": "Идолмастер / The Idolmaster", "value": "807" }, { "label": "Иерихон Клайва Баркера / Иерихон / Clive Barker’s Jericho /Jericho", "value": "320" }, { "label": "Извивающийся дракон / Coiling Dragon", "value": "692" }, { "label": "Изгнаные королевства РПГ / Exiled Kingdoms RPG", "value": "1375" }, { "label": "Импульс Валькирии: Сирена / Варукири Дораиву: Сирена / Valkyrie Drive: Mermaid", "value": "1736" }, { "label": "Индекс волшебства / A Certain Magical Index", "value": "68" }, { "label": "Инуяша - Пес-демон / InuYasha", "value": "481" }, { "label": "Искусственный отбор / Triage X", "value": "1037" }, { "label": "Истинный мир боевых искусств / Zhenwu Shijie / True Martial World", "value": "867" }, { "label": "История монстров / Monogatari", "value": "911" }, { "label": "История о второстепенном персонаже который стал игроком в другой игре. / The story is about a minor character who became a player in another game.", "value": "868" }, { "label": "Кабанери железной крепости / Koutetsujou no Kabaneri", "value": "1494" }, { "label": "Каждый раз, когда я сплю, моя душа покидает мое тело / Every Day I Sleep, My Soul Goes Out of My Body", "value": "1048" }, { "label": "Как воспитать героиню из обычной девушки / Saenai Heroine no Sodatekata", "value": "1637" }, { "label": "Как игрок глупой FPS попал в иной мир / Как дурачок из стрелялки в другой мир попал / Manuke na FPS Player ga Isekai e Ochita Baai", "value": "746" }, { "label": "Как приручить дракона / How to Train Your Dragon", "value": "687" }, { "label": "Капитан Америка / Captain America", "value": "1425" }, { "label": "Капитан Марвел(Фильм, 2019) / Captain Marvel", "value": "1594" }, { "label": "Каратель / The Punisher", "value": "387" }, { "label": "Касл / Castle", "value": "389" }, { "label": "Касльвания / Castlevania", "value": "1215" }, { "label": "Катаклизм: Тёмные дни впереди / DDA / Cataclysm: Dark Days Ahead", "value": "680" }, { "label": "Квайзер со Стигматом / Адепт Святого Знака / The Qwaser of Stigmata", "value": "72" }, { "label": "Квартет из альтернативного мира / Isekai Quartet", "value": "1801" }, { "label": "Квест Девушки-монстра / Monster Girl Questt", "value": "928" }, { "label": "Квест титана(Games) / Титанический квест / Titan Quest", "value": "1483" }, { "label": "Кенши(Games) / Kenshi", "value": "1230" }, { "label": "Киберпанк 2077 / Cyberpunk 2077", "value": "416" }, { "label": "Ким Пять-с-плюсом / Kim Possible", "value": "436" }, { "label": "Киру ра Киру / Круши Кромсай / Убей или умри / Kill la Kill", "value": "763" }, { "label": "Класс убийц / Assassination classroom", "value": "610" }, { "label": "Клеймор / Claymore", "value": "110" }, { "label": "Клинок зла / Evil Blade / Übel Blatt", "value": "722" }, { "label": "Клинок королевы / Queen’s Blade", "value": "757" }, { "label": "Клинок Маню: Тайна сисечного свитка / Manyuu Hiken-chou", "value": "501" }, { "label": "Клинок рассекающий демонов / Demon Slayer: Kimetsu no Yaiba", "value": "21" }, { "label": "Клуб Винкс / Winx Club", "value": "397" }, { "label": "Книга джунглей / The Jungle Book", "value": "1688" }, { "label": "Князь тьмы с задней парты / Demon King Daimao / Ichiban Ushiro no Daimaou", "value": "1207" }, { "label": "Код Гиас / Code Geass", "value": "340" }, { "label": "Код Квалидеи / Qualidea Code", "value": "76" }, { "label": "Кольцо Элдена / Elden Ring", "value": "1408" }, { "label": "Комната / The Room", "value": "889" }, { "label": "Конь и клинок: Боевой отряд(Games) / Mount and Blade:Warband", "value": "1477" }, { "label": "Королевства Сердец / Kingdom Hearts", "value": "407" }, { "label": "Короли крестоносцев / Crusader kings", "value": "572" }, { "label": "Король бойцов / The King of Fighters", "value": "1378" }, { "label": "Король лев / The Lion king", "value": "1705" }, { "label": "Король Шаманов / Shaman King", "value": "744" }, { "label": "Корона греха / Guilty Crown", "value": "1007" }, { "label": "Корпорация лоботомии / Lobotomy corporation", "value": "852" }, { "label": "Космические рейнджеры(Games) / Space Rangers", "value": "1508" }, { "label": "Кошечка из Сакурасо / Sakurasou no Pet na Kanojo", "value": "605" }, { "label": "Красавица и чудовище / Beauty and the Beast", "value": "1765" }, { "label": "Красная угроза 3 / Command & Conquer: Red Alert 3", "value": "742" }, { "label": "Красный, Белый, Черный, Желтый / RWBY", "value": "131" }, { "label": "Кредо убийцы / Assassin's Creed", "value": "690" }, { "label": "Кризис / Crysis", "value": "1734" }, { "label": "Крушитель / The Breaker", "value": "1080" }, { "label": "Кунг-фу панда / Kung Fu Panda", "value": "831" }, { "label": "Кэйон! / K-On!", "value": "1785" }, { "label": "Кэнган Асура / Kengan Asura", "value": "726" }, { "label": "Лаборатория Декстера / Dexter Lab", "value": "639" }, { "label": "Лавкрафт / Говард Филлипс Лавкрафт / Howard Phillips Lovecraft", "value": "1259" }, { "label": "Легенда о восьми псах востока / Hakkenden: Touhou Hakken Ibun", "value": "1699" }, { "label": "Легенда о Зельде / The Legend of Zelda", "value": "870" }, { "label": "Легенда о Короле Драконов / Legend of the Dragon King", "value": "623" }, { "label": "Легенда о Легендарных Героях / Densetsu no Yuusha no Densetsu", "value": "193" }, { "label": "Легион Супергероев / The Legion of Super-Heroes", "value": "450" }, { "label": "Леди Баг и Супер-Кот / Miraculous Ladybug", "value": "327" }, { "label": "Летняя сага / Summertime Saga", "value": "1441" }, { "label": "Лига Легенд / League of Legends", "value": "65" }, { "label": "Линия фронта для девочек / Girls' Frontline", "value": "1686" }, { "label": "Литературный клуб Доки Доки / Литературный клуб / Doki Doki literature club!", "value": "819" }, { "label": "Лорд героев(Games) / Lord of Heroes", "value": "1771" }, { "label": "Лорд человечества / Lord of the People", "value": "1896" }, { "label": "Лориенская Сага / Lorien Legacies", "value": "521" }, { "label": "Любимая жена господина генерального директора / Mr.CEO's Beloved Wife", "value": "1389" }, { "label": "Любовные неприятности / To love ru", "value": "353" }, { "label": "Любовь, Деньги, Рок-н-Ролл / Love, Money, Rock'n'Roll", "value": "1890" }, { "label": "Люди в чёрном(Фильм) / Men in Black", "value": "1193" }, { "label": "Люди Икс / X-Men", "value": "371" }, { "label": "Лютер Строуд Сага / The Luther Strode Saga", "value": "1700" }, { "label": "Люцифер(телесериал) / Lucifer", "value": "681" }, { "label": "Маг на полную ставку / Quanzhi Fashi", "value": "291" }, { "label": "Маг смерти не желающий четвертой реинкарнации / The Death Mage Who Doesn’t Want a Fourth Time", "value": "1775" }, { "label": "Маг-целитель: Новый старт / Kaifuku Jutsushi no Yarinaoshi", "value": "1311" }, { "label": "Маги: Волшебный лабиринт / Magi: The Labyrinth of Magic", "value": "1581" }, { "label": "Магистр дьявольского культа / The Grandmaster of Demonic Cultivation", "value": "608" }, { "label": "Магическая академия Атараксия: Гибрид х Сердце / Hybrid x Heart Magias Academy Ataraxia", "value": "1898" }, { "label": "Магическая битва / Magic Battle / Jujutsu Kaisen", "value": "671" }, { "label": "Маленькие кошмары 2 / Little Nightmares 2", "value": "601" }, { "label": "Малефисента / Maleficent", "value": "775" }, { "label": "Мальчик с оленьими рогами / Сладкоежка / Sweet tooth", "value": "1772" }, { "label": "Маска / The mask", "value": "847" }, { "label": "Мастер Урадана / The Master of Uradan", "value": "1395" }, { "label": "Мастера меча онлайн / Sword Art Online / SAO", "value": "324" }, { "label": "Межвидовые Рецензенты / Interspecies Reviewers", "value": "1555" }, { "label": "Менеджер среднего звена Тонэгава / Chuukan Kanriroku Tonegawa", "value": "1084" }, { "label": "Мерлин / Merlin", "value": "486" }, { "label": "Мертвы к Рассвету / Dead by Daylight", "value": "899" }, { "label": "Мертвый или живой / Dead or Alive", "value": "1563" }, { "label": "Мертвый остров / Dead Island", "value": "124" }, { "label": "Месть Масамуне-куна! / Masamune-kun no Revenge", "value": "571" }, { "label": "Метавселенная Рудазова / Rudazov's Metauniverse", "value": "1211" }, { "label": "Метро 2033(Games) / Metro 2033", "value": "1584" }, { "label": "Милый во Франксе / Любимый во Франксе / Darling in the Franxx", "value": "942" }, { "label": "Мир боевых искусств / 武极天下 / Wuji Tianxia / Martial World", "value": "620" }, { "label": "Мир зомби / Zombie World", "value": "1880" }, { "label": "Мир Льда и Пламени / The World of Ice & Fire", "value": "415" }, { "label": "Мир приключений Джеки Чана(мультсериал, 2000) / ackie Chan Adventures", "value": "1544" }, { "label": "Мир танков / WoT Blitz / World of Tanks Blitz", "value": "525" }, { "label": "Мир Тьмы / World of Darkness", "value": "145" }, { "label": "Мир Эрастай / The World of Erasthay", "value": "1836" }, { "label": "Мир Warcraft / World of Warcraft", "value": "89" }, { "label": "Мировая война Z / Война миров Z / World War Z", "value": "1217" }, { "label": "Моана / Moana", "value": "686" }, { "label": "Моб психо 100 / Mob Psycho 100", "value": "866" }, { "label": "Мобильные легенды: Бах-Бах(Games) / Mobile Legends: Bang Bang", "value": "1497" }, { "label": "Могучие рейнджеры / Power Rangers", "value": "1486" }, { "label": "Может, я встречу тебя в подземелье? / DanMachi", "value": "9" }, { "label": "Мой жених сбежал / My Groom Ran Away", "value": "1047" }, { "label": "Мой маленький пони / My Little Pony", "value": "655" }, { "label": "Мой маленький пони: Дружба — это чудо / My Little Pony: Friendship is Magic", "value": "658" }, { "label": "Мой шумный дом(мультсериал, 2016) / The Loud House", "value": "1467" }, { "label": "Монстер Хай / Monster High", "value": "1012" }, { "label": "Моя возлюбленная чпокается со всеми / Kanojo wa Dare to demo Sex Sur", "value": "1274" }, { "label": "Моя геройская академия / Boku no Hero Academia", "value": "69" }, { "label": "Моя девушка - зомби / My Girlfriend is a Zombie", "value": "754" }, { "label": "Моя жена - красивый генеральный директор / My Wife is a Beautiful CEO", "value": "1025" }, { "label": "Моя жена — президент студенческого совета! / My Wife is the Student Council President / Okusama ga Seitokaichou", "value": "241" }, { "label": "Моя Марвел Академия / My marvel academia", "value": "696" }, { "label": "Моя первая модница / Hajimete no Gal", "value": "1835" }, { "label": "Моя Супер-Бывшая / My Super Ex-Girlfriend", "value": "1828" }, { "label": "Мрачный рассвет / Grim Dawn", "value": "1113" }, { "label": "Мстители / The Avengers", "value": "1747" }, { "label": "Мстители. Эра Альтрона / The Avengers. Age of Ultron", "value": "784" }, { "label": "Мулан / Mulan", "value": "706" }, { "label": "Мы не можем учится / Bokutachi wa Benkyou ga Dekinai", "value": "912" }, { "label": "Мэй Гунцин / Mei Gongqing", "value": "753" }, { "label": "Наблюдать / Overwatch", "value": "607" }, { "label": "Надпись / Inscription", "value": "1718" }, { "label": "Нам Ён / Nam Yeon", "value": "1188" }, { "label": "Наруто / Naruto", "value": "3" }, { "label": "Начало после конца / The Beginning After The End", "value": "888" }, { "label": "Не голодай / Don't Starve", "value": "274" }, { "label": "Не издевайся надо мной, Нагаторо / Ijiranaide / Nagatoro-san Don't Toy with Me, Miss Nagatoro", "value": "1041" }, { "label": "Не люблю боль, так что вкачаю все в защиту / Itai no wa Iya nano de Bougyoryoku ni Kyokufuri Shitai to Omoimasu", "value": "517" }, { "label": "Не моя вина, что я непопулярна! / Watashi ga Motenai no wa Dou Kangaetemo Omaera ga Warui", "value": "1381" }, { "label": "Небесный замок Лапута / Tenkuu no Shiro Laputa", "value": "1109" }, { "label": "Невероятные приключения ДжоДжо / JoJo's Bizarre Adventure", "value": "20" }, { "label": "Негодник, которому не снилась девочка-зайка / Rascal Does Not Dream of Bunny Girl Senpai", "value": "1897" }, { "label": "Негодяй спасает мужскую роль / The Villain Saves the Male Lead", "value": "1224" }, { "label": "Неизвестен / Persona", "value": "205" }, { "label": "Некий магический индекс / To Aru Majutsu no Index", "value": "562" }, { "label": "Некий научный акселератор / Toaru Kagaku no Accelerator", "value": "1487" }, { "label": "Ненасытный Берсерк / Boushoku no Berserk: Ore dake Level to Iu Gainen wo Toppa suru the Comic", "value": "1195" }, { "label": "Необъятные небеса / Infinite Stratos / IS", "value": "280" }, { "label": "Необъятный океан / Grand Blue", "value": "531" }, { "label": "Непревзойденная / Master Piece The Animation", "value": "712" }, { "label": "Непризнанный школой владыка демонов / Maou Gakuin no Futekigousha", "value": "1476" }, { "label": "Непутевый ученик в школе магии / Mahouka Koukou No Rettousei", "value": "982" }, { "label": "Непутевый ученик в школе магии / The Irregular at Magic High School", "value": "630" }, { "label": "Несокрушимая механическая кукла / Machine-Doll wa Kizutsukanai", "value": "1030" }, { "label": "Несправедливость / Injustice", "value": "1026" }, { "label": "Нет игры - нет жизни / Без игры жизни нет / No Game No Life", "value": "718" }, { "label": "Неуязвимый / Invincible", "value": "702" }, { "label": "НиоХ(Games) / NioH", "value": "1465" }, { "label": "Новый завет Владыки тьмы / Shinmai Maou no Testament", "value": "1432" }, { "label": "Ну и ну! Земляничные яйца / I My Me! Strawberry Eggs", "value": "1485" }, { "label": "Нулевой Уровень Целомудрия / Teisou Kannen Zero", "value": "1209" }, { "label": "О моём перерождении в меч / Tensei Shitara Ken deshita", "value": "53" }, { "label": "О моём перерождении в слизь / Tensei shitara Slime Datta Ken", "value": "64" }, { "label": "О моя Богиня / Aa! Megami-sama! / Ah! My Goddess", "value": "915" }, { "label": "Обесчещенный(Games) / Dishonored", "value": "1073" }, { "label": "Обитель зла / Resident Evil", "value": "86" }, { "label": "Огненная эмблема / Fire Emblem", "value": "1615" }, { "label": "Огненная эмблема: Пробуждение / Fire Emblem: Awakening", "value": "1616" }, { "label": "Огненная эмблема: Три Дома / Fire Emblem:Three Houses", "value": "1716" }, { "label": "Одинокий рокер! / Bocchi the Rock!", "value": "1904" }, { "label": "Одному лишь Богу ведомый мир / World God Only Knows", "value": "1248" }, { "label": "Она становится гламурной после расторжения помолвки / She gets glamorous after the engagement is annulled", "value": "1404" }, { "label": "Орк-рубака / Orc Grunt", "value": "779" }, { "label": "Освободите эту ведьму / Release that witch", "value": "994" }, { "label": "Острые козырьки(телесериал) / Peaky Blinders", "value": "1177" }, { "label": "От заката до рассвета! / From Dusk till Dawn!", "value": "1416" }, { "label": "Отброс из семьи графа / Trash of counts family", "value": "853" }, { "label": "Отряд самоубийц / The Suicide Squad", "value": "1844" }, { "label": "Отчаянные домохозяйки / Desperate Housewives", "value": "1011" }, { "label": "Отчет о буйстве духов / YuYu Hakusho", "value": "1008" }, { "label": "Охота демонического короля на свою жену / Xie Wang Zhui Qi", "value": "1737" }, { "label": "Охотник х Охотник / Hunter x Hunter", "value": "101" }, { "label": "Охотницы на демонов / Taimanin Asagi", "value": "1463" }, { "label": "Очень приятно Бог! / Kamisama Hajimemashita", "value": "1585" }, { "label": "Очень Странные Дела(телесериал) / Stranger Things", "value": "1834" }, { "label": "ПАЗЛ / PUZZLE", "value": "1762" }, { "label": "Палач Рока / DOOM", "value": "132" }, { "label": "Параграф 78(Фильм) / Paragraph 78", "value": "923" }, { "label": "Паразит: Учение о жизни / Parasyte: The Maxim", "value": "1176" }, { "label": "Пастырь(Фильм, 2011) / Priest", "value": "1173" }, { "label": "Пацаны / The Boys", "value": "133" }, { "label": "Первый детский сад во вселенной / The First Kindergarten in the Universe", "value": "1049" }, { "label": "Перевозчик / Le Transporteur", "value": "365" }, { "label": "Передающийся через кровь / Bloodborne", "value": "229" }, { "label": "Пережить / Outlast", "value": "645" }, { "label": "Перерождение / Rebirth", "value": "550" }, { "label": "Перерождение бессмертного горожанина-культиватора / Rebirth – City Cultivation / Rebirth of the Urban Immortal Cultivator", "value": "843" }, { "label": "Перерождение в монстра / Re:Monster", "value": "85" }, { "label": "Перестрой мир / Sekai O Sai Kochiku / Rebuild World", "value": "961" }, { "label": "Период полураспада(Valve) / Half-Life", "value": "895" }, { "label": "Перси Джексон / Percy Jackson", "value": "308" }, { "label": "Персона 5 / Persona 5", "value": "1614" }, { "label": "Печать ветра / Kaze no Stigma", "value": "845" }, { "label": "Пик боевых искусств / Martial Peak", "value": "414" }, { "label": "Пираты Карибского моря / Pirates of the Caribbean", "value": "932" }, { "label": "Пираты черной лагуны / Black Lagoon", "value": "621" }, { "label": "Пламенная бригада пожарных / Fire Force / Enen no Shouboutai", "value": "841" }, { "label": "Пламя бесчисленых невзгод / I' m really not demon god's lackey", "value": "1452" }, { "label": "Планетарная аннигиляция / Planetary Annihilation", "value": "487" }, { "label": "Плоскостной пейзаж: Мучение / Planescape: Torment", "value": "1768" }, { "label": "По велению адской сестры / The Testament of Sister New Devil", "value": "18" }, { "label": "Поборники тьмы / Darksiders", "value": "1028" }, { "label": "Повар небесной гостиницы / Чем кормят в ином мире / Kakuriyo no Yadomeshi", "value": "998" }, { "label": "Повар-боец Сома / В поисках божественного рецепта / Shokugeki no Souma", "value": "191" }, { "label": "Повелитель тьмы на подработке! / Hataraku Maou-sama!", "value": "674" }, { "label": "Повелитель тьмы: Другая история мира / How Not to Summon a Demon Lord / Isekai Maou to Shoukan Shoujo no Dorei Majutsu", "value": "699" }, { "label": "Повелитель(Куганэ Маруяма) / Overlord", "value": "27" }, { "label": "Повелитель(Games) / Overlord", "value": "1623" }, { "label": "Повесть о Конце Света / Record of Ragnarok", "value": "332" }, { "label": "Повесть о лунной принцессе / Tsukihime: Lunar Legend", "value": "750" }, { "label": "Повесть о Небесных островах / Фэнтези Гранблю / Granblue Fantasy", "value": "808" }, { "label": "Повседневная жизнь бессмертного короля / The Daily Life of the Immortal King / Xian Wang de Richang Shenghuo", "value": "1466" }, { "label": "Повседневная жизнь с девушкой-монстром / Monster Musume", "value": "760" }, { "label": "Пограничье(Games) / Borderlands", "value": "992" }, { "label": "Под лунами Драконьих глаз / Beneath the Dragoneye Moons", "value": "1735" }, { "label": "Подземелья и драконы / Dungeons & Dragons", "value": "81" }, { "label": "Подземная история / Андертейл / Undertale", "value": "390" }, { "label": "Поднявшийся(Games) / Risen", "value": "1273" }, { "label": "Поднятие уровня в одиночку / Solo Leveling", "value": "127" }, { "label": "Подручный Луизы-Нулизы / Zero no Tsukaima", "value": "580" }, { "label": "Пожиратель богов / God Eater", "value": "1321" }, { "label": "Поймай себя ! Моя дорогая жена / Catch You ! My Dear Wife", "value": "1317" }, { "label": "Покемон / Pokemon", "value": "43" }, { "label": "Политическая Хроника Молодой Девушки / A Young Woman's Political Record", "value": "1306" }, { "label": "Полностью пленённые / Totally Captivated", "value": "1086" }, { "label": "Полый Рыцарь(Games) / Hollow Knight", "value": "1198" }, { "label": "Пользователи Силы / Forceusers", "value": "1162" }, { "label": "Поля битвы Неизвестного игрока / ПАБГ / Player Unknown's Battlegrounds / PUBG", "value": "622" }, { "label": "Попытка приручить злого повелителя / Trying to Tame an Evil Overlord", "value": "983" }, { "label": "Поработитель Ада / Helltaker", "value": "776" }, { "label": "Порновселенная / Porn Universe", "value": "1776" }, { "label": "Портал(Valve) / Portal", "value": "800" }, { "label": "Последние из нас / Last Of Us", "value": "1717" }, { "label": "Последний Серафим / Owari no Seraph", "value": "551" }, { "label": "Последняя из рода Блау(Тайга Ри) / The last of the Blau family", "value": "1507" }, { "label": "Последняя фантазия / ファイナルファンタジ / Final Fantasy", "value": "769" }, { "label": "Преподобное безумие / Reverend Insanity", "value": "1280" }, { "label": "Преподобный Гу / Gu Zhen Ren / Daoist Gu", "value": "1464" }, { "label": "Призрачный бегун / Ghostrunner", "value": "613" }, { "label": "Призрачный гонщик / Ghost Rider", "value": "823" }, { "label": "Принц Драконов Хаоса / The Chaos Dragon Prince", "value": "1397" }, { "label": "Принц Персии / Prince of Persia", "value": "1535" }, { "label": "Принцесса монстров / Princess Resurrection", "value": "1304" }, { "label": "Принцесса Цу / Не проиграю! / Maken Ki", "value": "675" }, { "label": "Проект „Восток“ / Touhou Project", "value": "809" }, { "label": "Проект Кей / K Project", "value": "73" }, { "label": "Проклятие: Автоматизация / NieR:Automata", "value": "1496" }, { "label": "Противостояние святого / Renegade Immortal", "value": "926" }, { "label": "Прототип / Prototype", "value": "54" }, { "label": "Пуленепробиваемый / Bang-Tan / BTS", "value": "520" }, { "label": "Путешествие на Запад / Journey to the West", "value": "1833" }, { "label": "Пять невест / Go-Toubun no Hanayome", "value": "713" }, { "label": "Пять ночей у Фредди / Five nights at freddy's", "value": "930" }, { "label": "Рагнарёк Онлайн / Ragnarok Online", "value": "953" }, { "label": "Радуга 6: Осада / Rainbow Six: Siege", "value": "421" }, { "label": "Развращение Дочери / Daraku Reijou Hakoiri Ojou-sama Netorare Choukyou Kiroku", "value": "1284" }, { "label": "Рай Грисайи / Эдем в серых тонах / Grisaia no Rakuen", "value": "584" }, { "label": "Рандеву с жизнью / Date A live", "value": "851" }, { "label": "Ранма ½ / Ranma ½", "value": "1192" }, { "label": "Рапунцель: Запутанная история / Tangled", "value": "773" }, { "label": "Расколотая битвой синева небес / Battle Through the Heavens", "value": "927" }, { "label": "Рассказ служанки / The Handmaid's Tale", "value": "1135" }, { "label": "Расхитительница гробниц / Tomb Raider", "value": "988" }, { "label": "Резатель / Лангриссер / Langrisser", "value": "792" }, { "label": "Реинкарнация безработного / Mushoku Tensei", "value": "569" }, { "label": "Реинкарнация Богини / Megami Tensei", "value": "1161" }, { "label": "Репликант НиеР / NieR Replicant / NieR Gestalt", "value": "1299" }, { "label": "Рецеттия: Повесть о магазине предметов / Recettear: An Item Shop's Tale", "value": "858" }, { "label": "Ривердэйл / Riverdale", "value": "637" }, { "label": "Рик и Морти / Rick and Morty", "value": "315" }, { "label": "Розарий и Вампир / Rosario+Vampire", "value": "83" }, { "label": "Розовая пора моей школьной жизни сплошной обман / Yahari Ore no Seishun Love Come wa Machigatteiru", "value": "856" }, { "label": "Рок шоу! / Show By Rock!!", "value": "344" }, { "label": "Русалочка / The Little Mermaid", "value": "892" }, { "label": "Рыцарь и маг / Knight's & Magic", "value": "1491" }, { "label": "Сага о Винланде / Vinland Saga", "value": "1200" }, { "label": "Садистская смесь / Blend S", "value": "1120" }, { "label": "Сайт волшебниц / Mahou Shoujo Site", "value": "909" }, { "label": "Сверхъестественное(телесериал) / Supernatural", "value": "916" }, { "label": "Связь принцесс: повторное погружение / Princess Connect! Re:Dive", "value": "1481" }, { "label": "Святые / Saints Row", "value": "1390" }, { "label": "Сейлор Мун / Sailor Moon", "value": "114" }, { "label": "Секире: Тени Умирают Дважды / Sekiro: Shadows Die Twice", "value": "1076" }, { "label": "Семь смертных грехов / Nanatsu no Taizai", "value": "61" }, { "label": "Семья шпиона / Spy x Family", "value": "1646" }, { "label": "Сердца Пандоры / Pandora Hearts", "value": "497" }, { "label": "Серия Метроидов / Metroid Series", "value": "1612" }, { "label": "Серый человек / Ди: Гурэйман / D.Gray-man", "value": "367" }, { "label": "Си Тянь Гуань / Si Tian Guan", "value": "1189" }, { "label": "Сильнейший в истории ученик Кэнити / Shijou Saikyou no Deshi Kenichi", "value": "242" }, { "label": "Сильнейший в истории ученик Кэнъити / KenIchi: The Mightiest Disciple", "value": "745" }, { "label": "Сильнейший магнат / The Strongest Tycoon", "value": "1340" }, { "label": "Сильнейший мудрец низшей эмблемы / Shikkakumon no Saikyou Kenja", "value": "1472" }, { "label": "Симпсоны / The Simpsons", "value": "1461" }, { "label": "Симс / The Sims", "value": "654" }, { "label": "Симфония морской стали / Aoki Hagane no Arpeggio", "value": "958" }, { "label": "Сингулярность(Games) / Singularity", "value": "1793" }, { "label": "Синий Архив / Blue Archive", "value": "1411" }, { "label": "Синий экзорцист / Blue Exorcist", "value": "312" }, { "label": "Синяя Тюрьма: Блю Лок / Blue Lock", "value": "1792" }, { "label": "Система Богов и Демонов / God and Devil World", "value": "1648" }, { "label": "Система Спаси-Себя-Сам / The Scum Villain's Self-Saving System: Ren Zha Fanpai Zijiu Xitong", "value": "1505" }, { "label": "Система: Восьмой уровень(Д. Серебряков) / System: Eighth level", "value": "1175" }, { "label": "Сисястая Принцесса под гипнозом / Kyonyuu Princess Saimin", "value": "1618" }, { "label": "Сказание о Демонах и Богах / Tales of Demons and Gods", "value": "59" }, { "label": "Сказание о Тёмном Рыцаре ~ Призван, чтобы одолеть Героя ~ / Tale of Dark Knight~Summoned to Defeat The Hero~", "value": "1647" }, { "label": "Сказки хранителей(Games) / Guardian tales", "value": "1068" }, { "label": "Скрытая Похотливая Натура Моих Русских Сестренок и Мачехи / Muttsuri do Sukebe ro Gibo Shimai", "value": "1282" }, { "label": "Скуби-Ду / Scooby-Doo", "value": "638" }, { "label": "Скучный мир, где не существует самой идеи похабных шуток / Shimoneta to Iu Gainen ga Sonzai Shinai Taikutsu na Sekai", "value": "830" }, { "label": "Сладкая жизнь / Happy Sugar Life", "value": "1099" }, { "label": "Сладкий флирт / Amour Sucré / Sweet Crush", "value": "495" }, { "label": "Сладости и Сигареты / Candy & Cigarettes", "value": "778" }, { "label": "Следопыт Гнев Праведников / Pathfinder Wrath Of The Righteous", "value": "1077" }, { "label": "Следопыт: Творец королей / Pathfinder: Kingmaker", "value": "1770" }, { "label": "Смертельная битва / Мортал Комбат / Mortal Kombat", "value": "806" }, { "label": "Смертельный укус", "value": "1902" }, { "label": "Созданный в бездне / Made in Abyss", "value": "952" }, { "label": "Сок джунглей", "value": "1901" }, { "label": "Сокрушитель: Новые волны / The Breaker: New Waves", "value": "1500" }, { "label": "Соник еж / Sonic the hedgehog", "value": "1052" }, { "label": "Сорвиголова / Daredevil", "value": "1690" }, { "label": "Сотня / Hundred", "value": "885" }, { "label": "Спаун / Spawn", "value": "1254" }, { "label": "Спецагент Арчер / Archer", "value": "624" }, { "label": "Специалист по апгрейду из другого мира / Endless Sea of Clouds ESC", "value": "1499" }, { "label": "Спираль / Удзумаки / Uzumaki", "value": "1164" }, { "label": "СТАЛКЕР / STALKER / S.T.A.L.K.E.R", "value": "677" }, { "label": "Стальная тревога / Full Metal Panic! The Second Raid", "value": "1489" }, { "label": "Стальной алхимик / Fullmetal Alchemist", "value": "1123" }, { "label": "Стальной Гигант / The Iron Giant", "value": "1241" }, { "label": "Становление богом / Bai Lian Cheng Shen", "value": "1315" }, { "label": "Старгерл / Stargirl", "value": "1137" }, { "label": "Стелларис / Stellaris", "value": "1098" }, { "label": "Сторожевые Псы / Watch Dogs", "value": "1886" }, { "label": "Стражи Галактики / Guardians of the Galaxy", "value": "1426" }, { "label": "Страна Самоцветов / Houseki no Kuni", "value": "1305" }, { "label": "Страна чудес смертников / Зона-парк смертников / Deadman Wonderland", "value": "857" }, { "label": "Страношары / Кантриболз / Countryballs", "value": "1895" }, { "label": "Студии 20-й век / 20th Century Studios", "value": "1715" }, { "label": "Судьба / Fate", "value": "1740" }, { "label": "Судьба: Апокриф / Fate: Apocrypha", "value": "231" }, { "label": "Судьба: Великий Орден / Fate: Grand Order", "value": "60" }, { "label": "Судьба: Девочка волшебница Илия / Fate: Kaleid Liner Prisma", "value": "789" }, { "label": "Судьба: Истоки / Fate: Zero", "value": "230" }, { "label": "Судьба: Ночь схватки / Fate: Stay Night", "value": "536" }, { "label": "Сумерки / Twilight", "value": "471" }, { "label": "Супер ген бога / Super God Gene", "value": "316" }, { "label": "Супер Марио / Super Mario", "value": "1661" }, { "label": "Супергёрл(телесериал, 2015) / Supergirl", "value": "1088" }, { "label": "Супермедицинский ниндзя / Super medical ninja", "value": "1391" }, { "label": "Суперсемейка / The Incredibles", "value": "306" }, { "label": "Сэкирэй / Sekirei", "value": "111" }, { "label": "Тада не может влюбиться! / Tada-kun wa koi wo shinai!", "value": "1905" }, { "label": "Тайны Смолвиля / Smallville", "value": "449" }, { "label": "Танец клинка Элементалиста / Seireitsukai no Blade Dance", "value": "1498" }, { "label": "Твоя апрельская ложь / Your lie in april", "value": "532" }, { "label": "Те, кто охотятся на эльфов / エルフを狩るモノたち / Those Who Hunt Elves", "value": "1168" }, { "label": "Темнейшее подземелье / Darkest dungeon", "value": "1405" }, { "label": "Темные Души / Dark Souls", "value": "200" }, { "label": "Темный Ангел / Dark Angel", "value": "1010" }, { "label": "Тёмный Дворецкий / Kuroshitsuj / Dark Butler", "value": "411" }, { "label": "Темный дворецкий / Kuroshitsuji", "value": "1043" }, { "label": "Темный призыватель Апокалипсиса / The Dark Summoner of the Apocalypse", "value": "1407" }, { "label": "Тень ежа / Ёж Шэдоу / Shadow the hedgehog", "value": "796" }, { "label": "Терминатор / The Terminator", "value": "759" }, { "label": "Террарий / Terraria", "value": "805" }, { "label": "Тетрадь смерти / Death Note", "value": "78" }, { "label": "Тибериумные войны / Tiberium Wars", "value": "1893" }, { "label": "Титаник / Titanic", "value": "1842" }, { "label": "Тихий Холм / Сайлент Хилл / Silent Hill", "value": "848" }, { "label": "Тихоокеанский рубеж / Pacific Rim", "value": "832" }, { "label": "Тогайну но Чи ~Потерял кровь~(Games) / Togainu no Chi ~Lost Blood~", "value": "1540" }, { "label": "Токийские вороны / Tokyo Ravens", "value": "836" }, { "label": "Токийские мстители / Tokyo Revengers", "value": "1064" }, { "label": "Токийский Гуль / Tokyo Ghoul", "value": "271" }, { "label": "Тор / Thor", "value": "764" }, { "label": "Торико / Toriko", "value": "342" }, { "label": "Точка зрения Всеведущего читателя / Omniscient Reader’s Viewpoint", "value": "1872" }, { "label": "Трансформеры / Transformers", "value": "117" }, { "label": "Трес Наварра / Tres Navarre", "value": "1197" }, { "label": "Три Икса / xXx", "value": "364" }, { "label": "Трон: Восстание / Tron: Uprising", "value": "1887" }, { "label": "Тропико / Tropico", "value": "694" }, { "label": "Ты единственная, кто любит Великого Меня / Ore wo Suki nano wa Omae dake ka yo", "value": "1818" }, { "label": "Ты же любишь мамочку, удары которой бьют по площади двойным уроном? / Tsuujou Kougeki ga Zentai Kougeki de Ni-kai Kougeki no Okaasan wa Suki Desu ka?", "value": "333" }, { "label": "Тэнти - лишний! / Tenchi Muyo", "value": "1316" }, { "label": "У Коми-сан проблемы с общением / 古見さんは、コミュ症です / Komi Can't Communicate", "value": "591" }, { "label": "У меня мало друзей / Boku wa Tomodachi ga Sukunai", "value": "1506" }, { "label": "Убийца Акаме / Akame ga Kill", "value": "30" }, { "label": "Убийца Брайан / Carl Robert Brown", "value": "1092" }, { "label": "Убийца гоблинов / Goblin slayer", "value": "803" }, { "label": "Удар крови / Very AU strike the blood", "value": "1255" }, { "label": "Уж не зомби ли это? / Kore wa Zombie Desu ka?", "value": "725" }, { "label": "Уличный боец(Games) / Суторито Фаита / Street Fighter", "value": "1203" }, { "label": "Ультрафиолет / Ultraviolet", "value": "1831" }, { "label": "Усио и Тора / Ushio and Tora", "value": "1501" }, { "label": "Утраченное небесами / Sora no Otoshimoto / Lost Property of the Sky", "value": "627" }, { "label": "Ученик Мудреца / Kenja no Deshi wo Nanoru Kenja", "value": "1474" }, { "label": "Ученик чародея / The Sorcerer's Apprentice", "value": "862" }, { "label": "Ученики(Games) / Disciples", "value": "1478" }, { "label": "Учитель Хокаге / Hokage Master", "value": "1319" }, { "label": "Учитель-мафиози Реборн! / Katekyo Hitman Reborn!", "value": "134" }, { "label": "Ушастые Друзья / Kemono Friends", "value": "578" }, { "label": "Фальшивая любовь / Nisekoi", "value": "1103" }, { "label": "Фантастическая четвёрка / Fantastic Four", "value": "625" }, { "label": "Фантастические твари и где они обитают / Fantastic Beasts and Where to Find Them", "value": "246" }, { "label": "Финес и Ферб / Phineas and Ferb", "value": "898" }, { "label": "Флотская коллекция / Kantai Collection", "value": "1194" }, { "label": "Флэш / The Flash", "value": "1136" }, { "label": "Фонд SCP / SCP / SCP Foundation", "value": "822" }, { "label": "Форма голоса / A Silent Voice", "value": "1100" }, { "label": "Форсаж / The Fast and the Furious", "value": "363" }, { "label": "Фронт кровавой блокады / Кровавый круг - линия фронта / Kekkai Sensen / Blood Blockade Battlefront", "value": "794" }, { "label": "Футадом мир / Futadom world", "value": "984" }, { "label": "Халк / Hulk", "value": "973" }, { "label": "Хвост Феи / Fairy Tail", "value": "13" }, { "label": "Хеллбой / Hellboy", "value": "1171" }, { "label": "Хеллсинг: Война с нечистью / Hellsing", "value": "116" }, { "label": "Хикару и го / Hikaru no Go", "value": "1121" }, { "label": "Хищник / Predator", "value": "747" }, { "label": "Хоббит(Дж. Р. Р. Толкина) / The Hobbit(John R.R. Tolkien)", "value": "1127" }, { "label": "Ходячие мертвецы / The Walking Dead", "value": "704" }, { "label": "Холодное сердце / Frozen", "value": "633" }, { "label": "Хонкай удар / Honkai impact", "value": "1332" }, { "label": "Хранители Пандоры / The guardians of Pandora", "value": "1187" }, { "label": "Хранитель вечности / UQ Holder", "value": "1469" }, { "label": "Хроники Акаши / Rokudenashi Majutsu Koushi to Akashic Records", "value": "1166" }, { "label": "Хроники Ксенобладания / Дзэнобурэйдо / Xenoblade Chronicles", "value": "1110" }, { "label": "Хроники Миров(Е. Лукин) / Chronicles of the Worlds(E. Lukin)", "value": "346" }, { "label": "Хроники расхитителей гробниц / Даому Биджи / Grave Robbery Note / Dao Mu Bi Ji / Daomu Biji", "value": "724" }, { "label": "Хроники Ренегата / The Renegade Chronicles", "value": "1225" }, { "label": "Царь Горы / The Gog of the Highschool", "value": "1285" }, { "label": "Чародейки / W.I.T.C.H.", "value": "118" }, { "label": "Человек — бензопила / Chainsaw Man", "value": "797" }, { "label": "Человек — летучая мышь / Бэтмен / Bat-man / Batman", "value": "440" }, { "label": "Человек одного удара / Ванпанчмен / One Punch-Man", "value": "70" }, { "label": "Человек-паук / Spider-Man", "value": "326" }, { "label": "Чемпион! / Campione!", "value": "534" }, { "label": "Червь(Джон Маккрей) / Worm(John C. McCrae(Wildbow))", "value": "700" }, { "label": "Черная Пантера(Фильм, 2018) / Black Panther", "value": "1605" }, { "label": "Черновик(С.Лукьяненко) / Draft", "value": "1023" }, { "label": "Чернокнижник в Мире Магов / Варлок / Warlock", "value": "635" }, { "label": "Чёрные души / Black Souls", "value": "1439" }, { "label": "Чёрный зверь / Чёрный Пёс / Kuroinu", "value": "755" }, { "label": "Чёрный зверь: Развращение Благородных Воительниц / Black Beast: Corruption of the Noble Warriors", "value": "1733" }, { "label": "Чёрный клевер / Black Clover", "value": "11" }, { "label": "Что такое настоящий мир? / What is real peace?", "value": "1336" }, { "label": "Чудачества любви не помеха! / Chuunibyou Demo Koi ga Shitai!", "value": "1719" }, { "label": "Чужой / Чужие / Aliens", "value": "1791" }, { "label": "Чужой / Alien", "value": "748" }, { "label": "Чума инкорпорейтед / Plague Inc", "value": "125" }, { "label": "Шазам! / Shazam!", "value": "1560" }, { "label": "Шальной последний босс появился! / A Wild Last Boss Appeared!", "value": "968" }, { "label": "Шальные девчонки / Girl the Wild's", "value": "965" }, { "label": "Шан Чи и легенда десяти колец / Shang-Chi and the Legend of the Ten Rings", "value": "1424" }, { "label": "Шарлотта / Charlotte", "value": "71" }, { "label": "Шерлок (ВВС) / Sherlock", "value": "492" }, { "label": "Шестерни войны / Gears of War", "value": "1346" }, { "label": "Школа мертвецов / Highschool of the Dead", "value": "98" }, { "label": "Школа строгого режима / Prison School", "value": "676" }, { "label": "Школьные воины / Сила тысячи / Ikki Tosen", "value": "818" }, { "label": "Шрек(мультфильм) / Шрэк / Shrek", "value": "1586" }, { "label": "Шухер, у нас новый студент / Transfer Student The Storm Bringer", "value": "628" }, { "label": "Эволюционировать(Games) / Evolve", "value": "1789" }, { "label": "Эволюция. Естественный Отбор / Game Evolution", "value": "287" }, { "label": "Эльсворд: Эль-ий Йоин / Elsword", "value": "199" }, { "label": "Эльфийская песнь / Elfen Lied", "value": "1899" }, { "label": "Эпоха Драконов / Dragon Age", "value": "253" }, { "label": "Эр Ген Я запечатаю небеса / ISSTH / Er Gen I shall seal the heavens", "value": "1170" }, { "label": "Эрагон(Кристофер Паолини) / Eragon", "value": "417" }, { "label": "Эроманга-сэнсэй / Ero-manga Sensei", "value": "1094" }, { "label": "Эстетика заблудшего героя / Hagure Yuusha no Aesthetica", "value": "1310" }, { "label": "Эта гяру будет встречаться с отаку через 100 дней. / 100-nichigo ni Otaku-kun to Tsukiau Gal", "value": "1246" }, { "label": "Эта фарфоровая кукла влюбилась / Sono Bisque Doll wa Koi wo Suru My Dress-Up Darling", "value": "1335" }, { "label": "Это не Гарри Поттер / This is not Harry Potter", "value": "1219" }, { "label": "Этот герой неуязвим, но очень осторожен / This Hero Is Invincible but Too Cautious", "value": "1276" }, { "label": "Эффект массы / Mass Effect", "value": "213" }, { "label": "Эхо пули / Bullet Echo", "value": "1523" }, { "label": "Югио: Дуэльные монстры / Yu-Gi-Oh", "value": "1814" }, { "label": "Югио! Вреинс / Yu-Gi-Oh! VRAINS", "value": "1888" }, { "label": "Юна из гостиницы Юраги / Yuuna of Yuragi Manor", "value": "493" }, { "label": "Юная Лига Справедливости / Young Justice", "value": "1020" }, { "label": "Юные Титаны / Teen Titans", "value": "420" }, { "label": "Я - Четвертый / I Am Number Four", "value": "590" }, { "label": "Я Король-Волшебник / I Am The Sorcerer King", "value": "1292" }, { "label": "Я мачеха, но моя дочь слишком милая / I'm stepmother but daughter is too cute", "value": "777" }, { "label": "Я не родился счастливчиком / I Wasn’t Born Lucky", "value": "996" }, { "label": "Я получил читерские способности в другом мире и стал экстраординарным в реальном мире / I Got a Cheat Skill in Another World and Became Unrivaled in The Real World, Too", "value": "1900" }, { "label": "Я стала потерянной дочерью злодея / I Became the Villain’s Lost Daughter", "value": "1387" }, { "label": "Ядерный трон / Nuclear Throne", "value": "1456" }, { "label": "Ярость [Пересмотрено] / Rage [Revised]", "value": "1337" }, { "label": "Ящик предложений Мэдаки / Medaka box", "value": "874" }, { "label": "Cказка для Дьявола / Tale For Satan", "value": "1271" }, { "label": "D&D стиль / D&D style", "value": "1289" }, { "label": "Dying Light 2: Stay Human", "value": "1906" }, { "label": "Fallout: Нью-Вегас / Fallout: New Vegas", "value": "1249" }, { "label": "Re: Жизнь в альтернативном мире с нуля / Re: Zero, Starting Life in Another World", "value": "57" }, { "label": "Re:Zero Начало жизни в другом мире / Re:Zero Starting Life in Another World", "value": "1531" }, { "label": "Rimworld", "value": "1894" }, { "label": "The Second Coming of Gluttony / The Second Coming of Avarice", "value": "1236" }, { "label": "Vfhdbk", "value": "1884" }, { "label": "XCOM: Враг внутри / XCOM: Enemy Unknown", "value": "476" }, { "label": "Xenus: Точка кипения / Boiling point: Road To Hell / Xenus: Boiling Point", "value": "695" }], "inputType": filterInputs_1.FilterInputs.Checkbox }, { "key": "atmosphere", "label": "Атмосфера:", "values": [{ "label": "Неважно", "value": "0" }, { "label": "Позитивная", "value": "1" }, { "label": "Dark", "value": "2" }], "inputType": filterInputs_1.FilterInputs.Picker }, { "key": "adult", "label": "Возрастные ограничения:", "values": [{ "label": "Все", "value": "0" }, { "label": "Только 18+", "value": "2" }, { "label": "Убрать 18+", "value": "1" }], "inputType": filterInputs_1.FilterInputs.Picker }];
diff --git a/js/plugins/russian/authortoday.js b/js/plugins/russian/authortoday.js
deleted file mode 100644
index 926268a..0000000
--- a/js/plugins/russian/authortoday.js
+++ /dev/null
@@ -1,327 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.icon = exports.version = exports.site = exports.name = exports.id = void 0;
-const filterInputs_1 = require("@libs/filterInputs");
-const defaultCover_1 = require("@libs/defaultCover");
-const fetch_1 = require("@libs/fetch");
-const novelStatus_1 = require("@libs/novelStatus");
-const cheerio_1 = require("cheerio");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "AT";
-exports.name = "Автор Тудей";
-exports.site = "https://author.today";
-exports.version = "1.0.0";
-exports.icon = "src/ru/authortoday/icon.png";
-const apiUrl = "https://api.author.today/";
-const token = "Bearer guest";
-const popularNovels = function (page, { showLatestNovels, filters }) {
- var _a;
- return __awaiter(this, void 0, void 0, function* () {
- let url = apiUrl + "v1/catalog/search?page=" + page;
- if (filters === null || filters === void 0 ? void 0 : filters.genre) {
- url += "&genre=" + filters.genre;
- }
- url +=
- "&sorting=" + (showLatestNovels ? "recent" : (filters === null || filters === void 0 ? void 0 : filters.sort) || "popular");
- url += "&form=" + ((filters === null || filters === void 0 ? void 0 : filters.form) || "any");
- url += "&state=" + ((filters === null || filters === void 0 ? void 0 : filters.state) || "any");
- url += "&series=" + ((filters === null || filters === void 0 ? void 0 : filters.series) || "any");
- url += "&access=" + ((filters === null || filters === void 0 ? void 0 : filters.access) || "any");
- url += "&promo=" + ((filters === null || filters === void 0 ? void 0 : filters.promo) || "hide");
- const result = yield (0, fetch_1.fetchApi)(url, {
- headers: {
- Authorization: token,
- },
- });
- const json = (yield result.json());
- if ((json === null || json === void 0 ? void 0 : json.code) === "NotFound") {
- return [];
- }
- let novels = [];
- (_a = json === null || json === void 0 ? void 0 : json.searchResults) === null || _a === void 0 ? void 0 : _a.forEach((novel) => novels.push({
- name: novel.title,
- cover: (novel === null || novel === void 0 ? void 0 : novel.coverUrl)
- ? "https://cm.author.today/content/" + novel.coverUrl
- : defaultCover_1.defaultCover,
- url: exports.site + "/work/" + novel.id,
- }));
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- var _a;
- return __awaiter(this, void 0, void 0, function* () {
- const workID = novelUrl.split("/")[4];
- let result = yield (0, fetch_1.fetchApi)(`${apiUrl}v1/work/${workID}/details`, {
- headers: {
- Authorization: token,
- },
- });
- let json = (yield result.json());
- let novel = {
- url: novelUrl,
- name: json.title,
- cover: (json === null || json === void 0 ? void 0 : json.coverUrl) ? json.coverUrl.split("?")[0] : defaultCover_1.defaultCover,
- author: (json === null || json === void 0 ? void 0 : json.originalAuthor) ||
- (json === null || json === void 0 ? void 0 : json.authorFIO) ||
- (json === null || json === void 0 ? void 0 : json.coAuthorFIO) ||
- (json === null || json === void 0 ? void 0 : json.secondCoAuthorFIO) ||
- (json === null || json === void 0 ? void 0 : json.translator) ||
- "",
- genres: (_a = json === null || json === void 0 ? void 0 : json.tags) === null || _a === void 0 ? void 0 : _a.join(", "),
- status: (json === null || json === void 0 ? void 0 : json.isFinished) ? novelStatus_1.NovelStatus.Completed : novelStatus_1.NovelStatus.Ongoing,
- };
- novel.summary = "";
- novel.summary += (json === null || json === void 0 ? void 0 : json.annotation) ? json.annotation + "\n" : "";
- novel.summary += (json === null || json === void 0 ? void 0 : json.authorNotes)
- ? "Примечания автора:\n" + json.authorNotes
- : "";
- // all chapters
- let chaptersRaw = yield (0, fetch_1.fetchApi)(`${apiUrl}v1/work/${workID}/content`, {
- headers: {
- Authorization: token,
- },
- });
- let chaptersJSON = (yield chaptersRaw.json());
- let chapters = [];
- chaptersJSON === null || chaptersJSON === void 0 ? void 0 : chaptersJSON.forEach((chapter, index) => {
- if ((chapter === null || chapter === void 0 ? void 0 : chapter.isAvailable) && !(chapter === null || chapter === void 0 ? void 0 : chapter.isDraft)) {
- chapters.push({
- name: (chapter === null || chapter === void 0 ? void 0 : chapter.title) || `Глава ${index + 1}`,
- releaseTime: (0, dayjs_1.default)((chapter === null || chapter === void 0 ? void 0 : chapter.publishTime) || chapter.lastModificationTime).format("LLL"),
- url: `${apiUrl}v1/work/${workID}/chapter/${chapter.id}/text`,
- });
- }
- });
- novel.chapters = chapters;
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const result = yield (0, fetch_1.fetchApi)(chapterUrl, {
- headers: {
- Authorization: token,
- },
- });
- const json = (yield result.json());
- if (json === null || json === void 0 ? void 0 : json.code) {
- return json.code + "\n" + (json === null || json === void 0 ? void 0 : json.message);
- }
- let key = json.key.split("").reverse().join("") + "@_@";
- let text = "";
- for (let i = 0; i < json.text.length; i++) {
- text += String.fromCharCode(json.text.charCodeAt(i) ^ key.charCodeAt(Math.floor(i % key.length)));
- }
- const loadedCheerio = (0, cheerio_1.load)(text);
- loadedCheerio("img").each(function () {
- var _a;
- if (!((_a = loadedCheerio(this).attr("src")) === null || _a === void 0 ? void 0 : _a.startsWith("http"))) {
- const src = loadedCheerio(this).attr("src");
- loadedCheerio(this).attr("src", exports.site + src);
- }
- });
- const chapterText = loadedCheerio.html();
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = `${exports.site}/search?category=works&q=${searchTerm}`;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio("div.book-row").each(function () {
- var _a;
- const name = loadedCheerio(this)
- .find('div[class="book-title"] a')
- .text()
- .trim();
- let cover = loadedCheerio(this).find("img").attr("src");
- const url = exports.site +
- "/work/" +
- ((_a = loadedCheerio(this)
- .find('div[class="book-title"] a')
- .attr("href")) === null || _a === void 0 ? void 0 : _a.split("/")[2]);
- if (cover) {
- cover = cover.split("?")[0];
- }
- else {
- cover = defaultCover_1.defaultCover;
- }
- novels.push({ name, cover, url });
- });
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-exports.fetchImage = fetch_1.fetchFile;
-exports.filters = [
- {
- key: "sort",
- label: "Сортировка",
- values: [
- { label: "По популярности", value: "popular" },
- { label: "По количеству лайков", value: "likes" },
- { label: "По комментариям", value: "comments" },
- { label: "По новизне", value: "recent" },
- { label: "По просмотрам", value: "views" },
- { label: "Набирающие популярность", value: "trending" },
- ],
- inputType: filterInputs_1.FilterInputs.Picker,
- },
- {
- key: "genre",
- label: "Жанры",
- values: [
- { label: "Альтернативная история", value: "sf-history" },
- { label: "Антиутопия", value: "dystopia" },
- { label: "Бизнес-литература", value: "biznes-literatura" },
- { label: "Боевая фантастика", value: "sf-action" },
- { label: "Боевик", value: "action" },
- { label: "Боевое фэнтези", value: "fantasy-action" },
- { label: "Бояръ-Аниме", value: "boyar-anime" },
- { label: "Героическая фантастика", value: "sf-heroic" },
- { label: "Героическое фэнтези", value: "heroic-fantasy" },
- { label: "Городское фэнтези", value: "urban-fantasy" },
- { label: "Детектив", value: "detective" },
- { label: "Детская литература", value: "detskaya-literatura" },
- { label: "Документальная проза", value: "non-fiction" },
- { label: "Историческая проза", value: "historical-fiction" },
- {
- label: "Исторические приключения",
- value: "historical-adventure",
- },
- { label: "Исторический детектив", value: "historical-mystery" },
- {
- label: "Исторический любовный роман",
- value: "historical-romance",
- },
- { label: "Историческое фэнтези", value: "historical-fantasy" },
- { label: "Киберпанк", value: "cyberpunk" },
- { label: "Короткий любовный роман", value: "short-romance" },
- { label: "Космическая фантастика", value: "sf-space" },
- { label: "ЛитРПГ", value: "litrpg" },
- { label: "Любовное фэнтези", value: "love-fantasy" },
- { label: "Любовные романы", value: "romance" },
- { label: "Мистика", value: "paranormal" },
- { label: "Назад в СССР", value: "back-to-ussr" },
- { label: "Научная фантастика", value: "science-fiction" },
- { label: "Подростковая проза", value: "teen-prose" },
- { label: "Политический роман", value: "political-fiction" },
- { label: "Попаданцы", value: "popadantsy" },
- { label: "Попаданцы в космос", value: "popadantsy-v-kosmos" },
- {
- label: "Попаданцы в магические миры",
- value: "popadantsy-v-magicheskie-miry",
- },
- { label: "Попаданцы во времени", value: "popadantsy-vo-vremeni" },
- { label: "Постапокалипсис", value: "postapocalyptic" },
- { label: "Поэзия", value: "poetry" },
- { label: "Приключения", value: "adventure" },
- { label: "Публицистика", value: "publicism" },
- { label: "Развитие личности", value: "razvitie-lichnosti" },
- { label: "Разное", value: "other" },
- { label: "РеалРПГ", value: "realrpg" },
- { label: "Романтическая эротика", value: "romantic-erotika" },
- { label: "Сказка", value: "fairy-tale" },
- { label: "Современная проза", value: "modern-prose" },
- {
- label: "Современный любовный роман",
- value: "contemporary-romance",
- },
- { label: "Социальная фантастика", value: "sf-social" },
- { label: "Стимпанк", value: "steampunk" },
- { label: "Темное фэнтези", value: "dark-fantasy" },
- { label: "Триллер", value: "thriller" },
- { label: "Ужасы", value: "horror" },
- { label: "Фантастика", value: "sci-fi" },
- {
- label: "Фантастический детектив",
- value: "detective-science-fiction",
- },
- { label: "Фанфик", value: "fanfiction" },
- { label: "Фэнтези", value: "fantasy" },
- { label: "Шпионский детектив", value: "spy-mystery" },
- { label: "Эпическое фэнтези", value: "epic-fantasy" },
- { label: "Эротика", value: "erotica" },
- { label: "Эротическая фантастика", value: "sf-erotika" },
- { label: "Эротический фанфик", value: "fanfiction-erotika" },
- { label: "Эротическое фэнтези", value: "fantasy-erotika" },
- { label: "Юмор", value: "humor" },
- { label: "Юмористическая фантастика", value: "sf-humor" },
- { label: "Юмористическое фэнтези", value: "ironical-fantasy" },
- ],
- inputType: filterInputs_1.FilterInputs.Picker,
- },
- {
- key: "form",
- label: "Форма произведения",
- values: [
- { label: "Любой", value: "any" },
- { label: "Перевод", value: "translation" },
- { label: "Повесть", value: "tale" },
- { label: "Рассказ", value: "story" },
- { label: "Роман", value: "novel" },
- { label: "Сборник поэзии", value: "poetry" },
- { label: "Сборник рассказов", value: "story-book" },
- ],
- inputType: filterInputs_1.FilterInputs.Picker,
- },
- {
- key: "state",
- label: "Статус произведения",
- values: [
- { label: "Любой статус", value: "any" },
- { label: "В процессе", value: "in-progress" },
- { label: "Завершено", value: "finished" },
- ],
- inputType: filterInputs_1.FilterInputs.Picker,
- },
- {
- key: "series",
- label: "Статус цикла",
- values: [
- { label: "Не важно", value: "any" },
- { label: "Вне цикла", value: "out" },
- { label: "Цикл завершен", value: "finished" },
- { label: "Цикл не завершен", value: "unfinished" },
- ],
- inputType: filterInputs_1.FilterInputs.Picker,
- },
- {
- key: "access",
- label: "Тип доступа",
- values: [
- { label: "Любой", value: "any" },
- { label: "Платный", value: "paid" },
- { label: "Бесплатный", value: "free" },
- ],
- inputType: filterInputs_1.FilterInputs.Picker,
- },
- {
- key: "promo",
- label: "Промо-фрагмент",
- values: [
- { label: "Скрывать", value: "hide" },
- { label: "Показывать", value: "show" },
- ],
- inputType: filterInputs_1.FilterInputs.Picker,
- },
-];
diff --git a/js/plugins/russian/bookriver.js b/js/plugins/russian/bookriver.js
deleted file mode 100644
index 1d15591..0000000
--- a/js/plugins/russian/bookriver.js
+++ /dev/null
@@ -1,222 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.icon = exports.version = exports.site = exports.name = exports.id = void 0;
-const filterInputs_1 = require("@libs/filterInputs");
-const fetch_1 = require("@libs/fetch");
-const novelStatus_1 = require("@libs/novelStatus");
-const cheerio_1 = require("cheerio");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "bookriver";
-exports.name = "Bookriver";
-exports.site = "https://bookriver.ru";
-exports.version = "1.0.0";
-exports.icon = "src/ru/bookriver/icon.png";
-const popularNovels = function (page, { showLatestNovels, filters }) {
- var _a, _b, _c;
- return __awaiter(this, void 0, void 0, function* () {
- let url = exports.site + `/genre?page=${page}&perPage=24&sortingType=`;
- url += showLatestNovels ? "last-update" : (filters === null || filters === void 0 ? void 0 : filters.sort) || "bestseller";
- if (filters) {
- if (Array.isArray(filters.genres) && filters.genres.length) {
- url += "&g=" + filters.genres.join(",");
- }
- }
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- const jsonRaw = loadedCheerio("#__NEXT_DATA__").html();
- if (jsonRaw) {
- let json = JSON.parse(jsonRaw);
- (_c = (_b = (_a = json.props.pageProps.state.pagesFilter) === null || _a === void 0 ? void 0 : _a.genre) === null || _b === void 0 ? void 0 : _b.books) === null || _c === void 0 ? void 0 : _c.forEach((novel) => novels.push({
- name: novel.name,
- cover: novel.coverImages[0].url,
- url: exports.site + "/book/" + novel.slug,
- }));
- }
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- var _a, _b, _c, _d, _e;
- return __awaiter(this, void 0, void 0, function* () {
- const result = yield (0, fetch_1.fetchApi)(novelUrl);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- const jsonRaw = loadedCheerio("#__NEXT_DATA__").html();
- const json = JSON.parse(jsonRaw || '{}');
- let book = (_a = json.props.pageProps.state.book) === null || _a === void 0 ? void 0 : _a.bookPage;
- let novel = {
- url: novelUrl,
- name: book === null || book === void 0 ? void 0 : book.name,
- cover: book === null || book === void 0 ? void 0 : book.coverImages[0].url,
- summary: book === null || book === void 0 ? void 0 : book.annotation,
- author: (_b = book === null || book === void 0 ? void 0 : book.author) === null || _b === void 0 ? void 0 : _b.name,
- genres: (_c = book === null || book === void 0 ? void 0 : book.tags) === null || _c === void 0 ? void 0 : _c.map((item) => item.name).join(", "),
- status: (book === null || book === void 0 ? void 0 : book.statusComplete) === "writing"
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed,
- };
- let chapters = [];
- (_e = (_d = book === null || book === void 0 ? void 0 : book.ebook) === null || _d === void 0 ? void 0 : _d.chapters) === null || _e === void 0 ? void 0 : _e.forEach((chapter) => {
- if (chapter.available) {
- chapters.push({
- name: chapter.name,
- releaseTime: (0, dayjs_1.default)((chapter === null || chapter === void 0 ? void 0 : chapter.firstPublishedAt) || chapter.createdAt).format("LLL"),
- url: exports.site + "/reader/" + (book === null || book === void 0 ? void 0 : book.slug) + "/" + chapter.chapterId,
- });
- }
- });
- novel.chapters = chapters;
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- var _a, _b;
- return __awaiter(this, void 0, void 0, function* () {
- const url = "https://api.bookriver.ru/api/v1/books/chapter/text/";
- const result = yield (0, fetch_1.fetchApi)(url + chapterUrl.split("/").pop());
- const json = (yield result.json());
- let chapterText = json.data.content || "Конец произведения";
- if ((_b = (_a = json.data) === null || _a === void 0 ? void 0 : _a.audio) === null || _b === void 0 ? void 0 : _b.available) {
- chapterText += "\n" + json.data.audio.url;
- }
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- var _a, _b;
- return __awaiter(this, void 0, void 0, function* () {
- const url = `https://api.bookriver.ru/api/v1/search/autocomplete?keyword=${searchTerm}&page=1&perPage=10`;
- const result = yield (0, fetch_1.fetchApi)(url);
- const json = (yield result.json());
- let novels = [];
- (_b = (_a = json === null || json === void 0 ? void 0 : json.data) === null || _a === void 0 ? void 0 : _a.books) === null || _b === void 0 ? void 0 : _b.forEach((novel) => novels.push({
- name: novel.name,
- cover: novel.coverImages[0].url,
- url: exports.site + "/book/" + novel.slug,
- }));
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-exports.fetchImage = fetch_1.fetchFile;
-exports.filters = [
- {
- key: "sort",
- label: "Сортировка",
- values: [
- { label: "Бестселлеры", value: "bestseller" },
- { label: "Дате добавления", value: "newest" },
- { label: "Дате обновления", value: "last-update" },
- ],
- inputType: filterInputs_1.FilterInputs.Picker,
- },
- {
- key: "genres",
- label: "жанры",
- values: [
- {
- label: "Альтернативная история",
- value: "alternativnaya-istoriya",
- },
- { label: "Боевая фантастика", value: "boevaya-fantastika" },
- { label: "Боевое фэнтези", value: "boevoe-fentezi" },
- { label: "Бытовое фэнтези", value: "bytovoe-fentezi" },
- {
- label: "Героическая фантастика",
- value: "geroicheskaya-fantastika",
- },
- { label: "Героическое фэнтези", value: "geroicheskoe-fentezi" },
- { label: "Городское фэнтези", value: "gorodskoe-fentezi" },
- { label: "Детектив", value: "detektiv" },
- {
- label: "Детективная фантастика",
- value: "detektivnaya-fantastika",
- },
- { label: "Жёсткая эротика", value: "zhyostkaya-erotika" },
- { label: "Исторический детектив", value: "istoricheskii-detektiv" },
- {
- label: "Исторический любовный роман",
- value: "istoricheskii-lyubovnyi-roman",
- },
- { label: "Историческое фэнтези", value: "istoricheskoe-fentezi" },
- { label: "Киберпанк", value: "kiberpank" },
- { label: "Классический детектив", value: "klassicheskii-detektiv" },
- {
- label: "Короткий любовный роман",
- value: "korotkii-lyubovnyi-roman",
- },
- {
- label: "Космическая фантастика",
- value: "kosmicheskaya-fantastika",
- },
- { label: "Криминальный детектив", value: "kriminalnyi-detektiv" },
- { label: "ЛитРПГ", value: "litrpg" },
- { label: "Любовная фантастика", value: "lyubovnaya-fantastika" },
- { label: "Любовное фэнтези", value: "lyubovnoe-fentezi" },
- { label: "Любовный роман", value: "lyubovnyi-roman" },
- { label: "Мистика", value: "mistika" },
- { label: "Молодежная проза", value: "molodezhnaya-proza" },
- { label: "Научная фантастика", value: "nauchnaya-fantastika" },
- {
- label: "Остросюжетный любовный роман",
- value: "ostrosyuzhetnyi-lyubovnyi-roman",
- },
- { label: "Политический детектив", value: "politicheskii-detektiv" },
- { label: "Попаданцы", value: "popadantsy" },
- { label: "Постапокалипсис", value: "postapokalipsis" },
- {
- label: "Приключенческое фэнтези",
- value: "priklyuchencheskoe-fentezi",
- },
- {
- label: "Романтическая эротика",
- value: "romanticheskaya-erotika",
- },
- { label: "С элементами эротики", value: "s-elementami-erotiki" },
- { label: "Славянское фэнтези", value: "slavyanskoe-fentezi" },
- {
- label: "Современный любовный роман",
- value: "sovremennyi-lyubovnyi-roman",
- },
- { label: "Социальная фантастика", value: "sotsialnaya-fantastika" },
- { label: "Тёмное фэнтези", value: "temnoe-fentezi" },
- { label: "Фантастика", value: "fantastika" },
- { label: "Фэнтези", value: "fentezi" },
- { label: "Шпионский детектив", value: "shpionskii-detektiv" },
- { label: "Эпическое фэнтези", value: "epicheskoe-fentezi" },
- { label: "Эротика", value: "erotika" },
- {
- label: "Эротическая фантастика",
- value: "eroticheskaya-fantastika",
- },
- { label: "Эротический фанфик", value: "eroticheskii-fanfik" },
- { label: "Эротическое фэнтези", value: "eroticheskoe-fentezi" },
- {
- label: "Юмористический детектив",
- value: "yumoristicheskii-detektiv",
- },
- {
- label: "Юмористическое фэнтези",
- value: "yumoristicheskoe-fentezi",
- },
- ],
- inputType: filterInputs_1.FilterInputs.Checkbox,
- },
-];
diff --git a/js/plugins/russian/ficbook.js b/js/plugins/russian/ficbook.js
deleted file mode 100644
index 4ebdaba..0000000
--- a/js/plugins/russian/ficbook.js
+++ /dev/null
@@ -1,2596 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.fetchImage = exports.filters = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.icon = exports.version = exports.site = exports.name = exports.id = void 0;
-const filterInputs_1 = require("@libs/filterInputs");
-const fetch_1 = require("@libs/fetch");
-const novelStatus_1 = require("@libs/novelStatus");
-const cheerio_1 = require("cheerio");
-const defaultCover_1 = require("@libs/defaultCover");
-exports.id = "ficbook";
-exports.name = "ficbook";
-exports.site = "https://ficbook.net";
-exports.version = "1.0.0";
-exports.icon = "src/ru/ficbook/icon.png";
-const popularNovels = function (page, { filters }) {
- return __awaiter(this, void 0, void 0, function* () {
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.directions) {
- url += "/popular-fanfics/" + filters.directions;
- }
- else if (filters === null || filters === void 0 ? void 0 : filters.tags) {
- url += "/tags/" + filters.tags + "?p=" + page;
- }
- else {
- url += "/" + ((filters === null || filters === void 0 ? void 0 : filters.sort) || "fanfiction") + "?p=" + page;
- }
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- const novels = [];
- loadedCheerio("article.fanfic-inline").each(function () {
- const name = loadedCheerio(this).find("h3 > a").text().trim();
- let cover = loadedCheerio(this).find("picture > img").attr("src");
- const url = loadedCheerio(this).find("h3 > a").attr("href");
- cover = cover
- ? cover.replace(/covers\/m_|covers\/d_/g, "covers/")
- : defaultCover_1.defaultCover;
- if (!name || !url)
- return;
- novels.push({ name, cover, url: exports.site + url.replace(/\?.*/g, "") });
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- var _a;
- return __awaiter(this, void 0, void 0, function* () {
- const result = yield (0, fetch_1.fetchApi)(novelUrl);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- const novel = {
- url: novelUrl,
- };
- novel.name = (loadedCheerio('h1[itemprop="headline"]').text() ||
- loadedCheerio('h1[itemprop="name"]').text()).trim();
- novel.cover = loadedCheerio('meta[property="og:image"]').attr("content");
- novel.summary = loadedCheerio('div[itemprop="description"]').text().trim();
- novel.author = loadedCheerio('a[itemprop="author"]').text();
- novel.status =
- loadedCheerio("div.fanfic-main-info > section:nth-child(3) > div:nth-child(3) > span:nth-child(2)").text() === "В процессе"
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- const tags = loadedCheerio('div[class="tags"] > a')
- .map((index, element) => loadedCheerio(element).text())
- .get();
- if (tags) {
- novel.genres = tags.join(",");
- }
- if (!novel.cover || ((_a = novel.cover) === null || _a === void 0 ? void 0 : _a.includes("/design/"))) {
- novel.cover = defaultCover_1.defaultCover;
- }
- else {
- novel.cover = novel.cover.replace(/covers\/m_|covers\/d_/g, "covers/");
- }
- const chapters = [];
- if (loadedCheerio("#content").length == 1) {
- const name = loadedCheerio(".title-area > h2").text();
- const releaseTime = loadedCheerio(".part-date > span").attr("title");
- if (name)
- chapters.push({ name, releaseTime, url: novelUrl });
- }
- else {
- loadedCheerio("li.part").each(function () {
- const name = loadedCheerio(this).find("h3").text();
- const releaseTime = loadedCheerio(this)
- .find("div > span")
- .attr("title");
- const url = loadedCheerio(this).find("a:nth-child(1)").attr("href");
- if (!name || !url)
- return;
- chapters.push({ name, releaseTime, url: exports.site + url });
- });
- }
- novel.chapters = chapters;
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- var _a, _b;
- return __awaiter(this, void 0, void 0, function* () {
- const result = yield (0, fetch_1.fetchApi)(chapterUrl);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- let chapterText = "";
- (_b = (_a = loadedCheerio("#content").text()) === null || _a === void 0 ? void 0 : _a.split("\n")) === null || _b === void 0 ? void 0 : _b.forEach((line) => {
- if (line.trim()) {
- chapterText += "" + line + "
";
- }
- else {
- chapterText += "
";
- }
- });
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- var _a, _b;
- return __awaiter(this, void 0, void 0, function* () {
- const formData = new FormData();
- formData.append("term", searchTerm);
- formData.append("page", "1");
- const result = yield (0, fetch_1.fetchApi)(exports.site + "/search/fanfic", {
- method: "POST",
- body: formData,
- });
- const json = (yield result.json());
- const novels = [];
- (_b = (_a = json.data) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.forEach((novel) => {
- const name = novel.title.trim();
- const url = exports.site + "/readfic/" + novel.slug;
- const cover = novel.cover
- ? "https://images.ficbook.net/fanfic-covers/" + novel.cover
- : defaultCover_1.defaultCover;
- novels.push({ name, cover, url });
- });
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-exports.filters = [
- {
- key: "sort",
- label: "Сортировка:",
- values: [
- { label: "Горячие работы", value: "fanfiction" },
- { label: "Популярные ", value: "popular-fanfics" },
- ],
- inputType: filterInputs_1.FilterInputs.Picker,
- },
- {
- key: "directions",
- label: "Направление:",
- values: [
- { label: "Джен", value: "gen" },
- { label: "Гет", value: "het" },
- { label: "Слэш", value: "slash-fics-3712917" },
- { label: "Фемслэш", value: "femslash-fanfics-9374932" },
- { label: "Статьи", value: "article" },
- { label: "Смешанный", value: "mixed" },
- { label: "Другой", value: "other" },
- ],
- inputType: filterInputs_1.FilterInputs.Picker,
- },
- {
- key: "tags",
- label: "Тэги:",
- values: [
- { label: "#1fic1week", value: "884" },
- { label: "#7daystowrite", value: "2961" },
- { label: "#Бинго_ТФ", value: "1458" },
- { label: "#миниатюры3days", value: "2118" },
- { label: "#Не_Тайный_Санта", value: "2760" },
- { label: "#Писательские фанты-блиц", value: "2613" },
- { label: "#cosmowrite", value: "2284" },
- { label: "#femKHRweek", value: "2658" },
- { label: "#FourShips", value: "2588" },
- { label: "#Goretober", value: "1861" },
- { label: "#InternationalVampireDay / #WorldDraculaDay", value: "2048" },
- { label: "#KattWeek", value: "2717" },
- { label: "#Kinktober", value: "1867" },
- { label: "#LotorWeek", value: "2657" },
- { label: "#MerMay", value: "1122" },
- { label: "#NaNoWriMo", value: "1852" },
- { label: "#nsfweruriweek", value: "2944" },
- { label: "#RCMiaChallenge", value: "2700" },
- { label: "#SheithMonth", value: "2432" },
- { label: "#SixDrabbles", value: "2293" },
- { label: "#Writober", value: "1831" },
- { label: "1900-е годы", value: "369" },
- { label: "1910-е годы", value: "213" },
- { label: "1920-е годы", value: "81" },
- { label: "1930-е годы", value: "82" },
- { label: "1940-е годы", value: "83" },
- { label: "1950-е годы", value: "84" },
- { label: "1960-е годы", value: "85" },
- { label: "1970-е годы", value: "86" },
- { label: "1980-е годы", value: "87" },
- { label: "1990-е годы", value: "88" },
- { label: "2000-е годы", value: "590" },
- { label: "2010-е годы", value: "2562" },
- { label: "2014 год", value: "2977" },
- { label: "2P", value: "1910" },
- { label: "9 мая", value: "1019" },
- { label: "Аборт / Выкидыш", value: "306" },
- { label: "Аватары", value: "2401" },
- { label: "Авиатранспорт", value: "962" },
- { label: "Авиация", value: "455" },
- { label: "Аврорат", value: "1906" },
- { label: "Австралия", value: "767" },
- { label: "Австрия", value: "1024" },
- { label: "Автомастерские", value: "788" },
- { label: "Авторская пунктуация", value: "2886" },
- { label: "Авторские неологизмы", value: "1123" },
- { label: "Автоспорт", value: "856" },
- { label: "Автостоп", value: "1429" },
- { label: "Аддикции", value: "1230" },
- { label: "Адреналиновая зависимость", value: "1480" },
- { label: "Азартные игры", value: "1009" },
- { label: "Азкабан", value: "1922" },
- { label: "Аквакинез", value: "1380" },
- { label: "Аквапарки", value: "789" },
- { label: "Акростих", value: "911" },
- { label: "Актеры", value: "408" },
- { label: "Акустикофилия", value: "903" },
- { label: "Алекситимия", value: "2020" },
- { label: "Алкоголь", value: "201" },
- { label: "Алкогольные игры", value: "1534" },
- { label: "Аллергии", value: "746" },
- { label: "Алхимия", value: "1174" },
- { label: "Альбинизм", value: "1213" },
- { label: "Альпинизм", value: "1448" },
- { label: "Альтернативная мировая история", value: "442" },
- { label: "Альтернативное размножение", value: "2751" },
- { label: "Альтернативные судьбы", value: "2839" },
- { label: "Амазонки", value: "1424" },
- { label: "Амегакуре", value: "2571" },
- { label: "Американский футбол", value: "808" },
- { label: "Ампутация", value: "704" },
- { label: "Амфибии", value: "2792" },
- { label: "Анальгезия", value: "1254" },
- { label: "Анальный оргазм", value: "999" },
- { label: "Анальный секс", value: "215" },
- { label: "Анархия", value: "1175" },
- { label: "Анахронизмы", value: "780" },
- { label: "Ангелы", value: "91" },
- { label: "Ангелы-хранители", value: "1044" },
- { label: "Ангст", value: "1665" },
- { label: "Андрогинная внешность", value: "2602" },
- { label: "Андроиды", value: "155" },
- { label: "Анимагия", value: "2519" },
- { label: "Анимализм", value: "1443" },
- { label: "Аномальные зоны", value: "822" },
- { label: "Анонимный секс", value: "112" },
- { label: "Анрождение", value: "1246" },
- { label: "Антарктида", value: "2205" },
- { label: "Анти-Сью (Анти-Стью)", value: "1150" },
- { label: "Антигерои", value: "418" },
- { label: "Антизлодеи", value: "1833" },
- { label: "Антикварные магазины", value: "1496" },
- { label: "Антисоциальное расстройство личности", value: "734" },
- { label: "Антиутопия", value: "1700" },
- { label: "Античность", value: "237" },
- { label: "Апатия", value: "1850" },
- { label: "Аптеки", value: "1240" },
- { label: "Аргентина", value: "1146" },
- { label: "Арены", value: "940" },
- { label: "Аристократия", value: "16" },
- { label: "Арктика", value: "2426" },
- { label: "Армия", value: "22" },
- { label: "Аромантичные персонажи", value: "339" },
- { label: "Артефакты", value: "924" },
- { label: "Археологи", value: "405" },
- { label: "Архивы", value: "2594" },
- { label: "Архитекторы", value: "1011" },
- { label: "Асексофобия", value: "1120" },
- { label: "Асексуальные персонажи", value: "168" },
- { label: "Аскетизм", value: "606" },
- { label: "Асоциальность", value: "2019" },
- { label: "Ассистенты", value: "2641" },
- { label: "Астма", value: "1121" },
- { label: "Астральное проецирование", value: "2530" },
- { label: "Астральные миры", value: "1379" },
- { label: "Астрология", value: "476" },
- { label: "Астронавты", value: "2220" },
- { label: "Астрономия", value: "1372" },
- { label: "Асфиксия", value: "104" },
- { label: "Атеисты", value: "669" },
- { label: "Атлантида", value: "1144" },
- { label: "Атмокинез", value: "1964" },
- { label: "Атмосферная зарисовка", value: "2802" },
- { label: "Атомные электростанции", value: "2192" },
- { label: "Аудиокинез", value: "2849" },
- { label: "Аукционы", value: "607" },
- { label: "Аутоассасинофилия", value: "2025" },
- { label: "Аутоканнибализм", value: "2593" },
- { label: "Аутофелляция / Аутокуннилингус", value: "610" },
- { label: "Африка", value: "791" },
- { label: "Афродизиаки", value: "103" },
- { label: "Аффект", value: "938" },
- { label: "Аэрокинез", value: "2850" },
- { label: "Байкеры", value: "522" },
- { label: "Байронические герои", value: "2900" },
- { label: "Балет", value: "404" },
- { label: "Баллада", value: "2318" },
- { label: "Банки / Биржи", value: "937" },
- { label: "Банши", value: "250" },
- { label: "Барти Крауч-младший — не Пожиратель Смерти", value: "2795" },
- { label: "Бары", value: "142" },
- { label: "Баскетбол", value: "829" },
- { label: "Баски", value: "1763" },
- { label: "Бастарды", value: "603" },
- { label: "Батохаки", value: "2830" },
- { label: "Бедность", value: "979" },
- { label: "Без Волдеморта", value: "2160" },
- { label: "Без диалогов (стилизация)", value: "2885" },
- { label: "Без золотого трио", value: "2648" },
- { label: "Без Избранного (Гарри Поттер)", value: "2762" },
- { label: "Без канонических персонажей", value: "2694" },
- { label: "Без Таноса", value: "2381" },
- { label: "БезГражданки", value: "2418" },
- { label: "Бездомные", value: "916" },
- { label: "Безответственность", value: "2152" },
- { label: "Безумные ученые", value: "2559" },
- { label: "Безэмоциональность", value: "1488" },
- { label: "Бейсбол", value: "1489" },
- { label: "Беларусь", value: "1030" },
- { label: "Белый день", value: "683" },
- { label: "Белый стих", value: "1998" },
- { label: "Бельгия", value: "1039" },
- { label: "Беременность", value: "1712" },
- { label: "Бермудский треугольник", value: "1158" },
- { label: "Берсерки", value: "566" },
- { label: "Бесконтактный секс", value: "2214" },
- { label: "Бесплодие", value: "719" },
- { label: "Беспокойство", value: "2888" },
- { label: "Беспризорники", value: "604" },
- { label: "Беспричудный Изуку", value: "2422" },
- { label: "Бессмертие", value: "219" },
- { label: "Бессмертный конкурс 2023", value: "3016" },
- { label: "Бестелесность", value: "2607" },
- { label: "Би-персонажи", value: "300" },
- { label: "Библейские темы и мотивы", value: "1468" },
- { label: "Библиотекари", value: "2631" },
- { label: "Библиотеки", value: "310" },
- { label: "Бизнесмены / Бизнесвумен", value: "573" },
- { label: "Биологическое оружие", value: "1188" },
- { label: "Биопанк", value: "281" },
- { label: "Биороботы", value: "2256" },
- { label: "Биполярное расстройство", value: "690" },
- { label: "Битва за Хогвартс", value: "2774" },
- { label: "Битва Историй", value: "2960" },
- { label: "Благородные разбойники", value: "952" },
- { label: "Благотворительность", value: "613" },
- { label: "Бладплей", value: "109" },
- { label: "Ближний Восток", value: "1041" },
- { label: "Близкие враги", value: "721" },
- { label: "Близнецы", value: "295" },
- { label: "Блиц-свидания", value: "2511" },
- { label: "Блогеры", value: "1471" },
- { label: "Блокадный Ленинград", value: "1111" },
- { label: "Блэкигуд", value: "2905" },
- { label: "Богачи", value: "1549" },
- { label: "Боги / Божественные сущности", value: "149" },
- { label: "Боди-арт", value: "2260" },
- { label: "Бодипозитив", value: "1153" },
- { label: "Боевая пара", value: "1919" },
- { label: "Боевые искусства", value: "918" },
- { label: "Бои без правил", value: "1390" },
- { label: "Бокс", value: "765" },
- { label: "Болгария", value: "1786" },
- { label: "Болезнь Альцгеймера", value: "2533" },
- { label: "Боль", value: "1803" },
- { label: "Больницы", value: "20" },
- { label: "Большая Игра профессора Дамблдора", value: "2890" },
- { label: "Бордели", value: "120" },
- { label: "Борьба за власть", value: "2300" },
- { label: "Борьба за отношения", value: "1251" },
- { label: "Борьба за справедливость", value: "2335" },
- { label: "Боязнь боли", value: "2441" },
- { label: "Боязнь воды", value: "1084" },
- { label: "Боязнь врачей", value: "2063" },
- { label: "Боязнь высоты", value: "1085" },
- { label: "Боязнь грозы", value: "1124" },
- { label: "Боязнь громких звуков", value: "1090" },
- { label: "Боязнь грязи", value: "1277" },
- { label: "Боязнь замкнутых пространств", value: "821" },
- { label: "Боязнь зеркал", value: "2739" },
- { label: "Боязнь клоунов", value: "2970" },
- { label: "Боязнь крови", value: "1312" },
- { label: "Боязнь людей", value: "1082" },
- { label: "Боязнь мужчин", value: "1264" },
- { label: "Боязнь насекомых / Боязнь пауков", value: "1119" },
- { label: "Боязнь неудачи", value: "2713" },
- { label: "Боязнь огня", value: "1258" },
- { label: "Боязнь одиночества", value: "1491" },
- { label: "Боязнь открытых пространств", value: "965" },
- { label: "Боязнь привязанности", value: "1343" },
- { label: "Боязнь призраков", value: "2770" },
- { label: "Боязнь прикосновений", value: "823" },
- { label: "Боязнь сексуальных домогательств", value: "2319" },
- { label: "Боязнь смерти", value: "1515" },
- { label: "Боязнь сна", value: "2262" },
- { label: "Боязнь темноты", value: "1494" },
- { label: "Боязнь тишины", value: "2233" },
- { label: "Бразилия", value: "833" },
- { label: "Брак по договоренности", value: "35" },
- { label: "Брак по расчету", value: "303" },
- { label: "БРД", value: "2907" },
- { label: "Бродячие артисты", value: "2661" },
- { label: "Бродячие певцы", value: "1497" },
- { label: "Броманс", value: "171" },
- { label: "Будущее", value: "227" },
- { label: "Буллёзный эпидермолиз", value: "2725" },
- { label: "Буллинг", value: "436" },
- { label: "Бухгалтеры", value: "2509" },
- { label: "Буч и фэм", value: "486" },
- { label: "Бывшие", value: "311" },
- { label: "Бывшие враги", value: "2812" },
- { label: "Бывшие серийные убийцы", value: "2498" },
- { label: "Бытовое фэнтези", value: "2702" },
- { label: "В одном теле", value: "1425" },
- { label: "В поисках отношений", value: "1576" },
- { label: "В. А. О. Н.", value: "2377" },
- { label: "Вагинальный секс", value: "395" },
- { label: "Ваканда", value: "2668" },
- { label: "Валькирии", value: "557" },
- { label: "Вампиры", value: "27" },
- { label: "Василиски", value: "863" },
- { label: "Вдовство", value: "2030" },
- { label: "Вебкам-модели", value: "2299" },
- { label: "Вегетарианцы / Веганы", value: "577" },
- { label: "Ведьмы / Колдуны", value: "33" },
- { label: "Великая депрессия", value: "2224" },
- { label: "Великая французская революция", value: "2000" },
- { label: "Великобритания", value: "673" },
- { label: "Великое Княжество Литовское", value: "2587" },
- { label: "Великолепный мерзавец", value: "1244" },
- { label: "Велоспорт", value: "2978" },
- { label: "Венгрия", value: "1432" },
- { label: "Вендиго", value: "251" },
- { label: "Верность", value: "459" },
- { label: "Вертикальный инцест", value: "337" },
- { label: "Вестерн", value: "2329" },
- { label: "Ветераны", value: "555" },
- { label: "Ветеринары", value: "629" },
- { label: "Вечеринки", value: "854" },
- { label: "Вечная молодость", value: "2405" },
- { label: "Вещие сны", value: "1993" },
- { label: "Взаимопонимание", value: "2887" },
- { label: "Взросление", value: "909" },
- { label: "Вигиланты", value: "1514" },
- { label: "Видеоигры", value: "2508" },
- { label: "Визажисты / Гримеры", value: "1801" },
- { label: "Викинги", value: "676" },
- { label: "Виктимблейминг", value: "331" },
- { label: "Викторианская эпоха", value: "469" },
- { label: "Виртуальная реальность", value: "803" },
- { label: "Виртуальный секс", value: "268" },
- { label: "Витилиго", value: "1167" },
- { label: "Вице-королевство Новая Испания", value: "2603" },
- { label: "ВИЧ / СПИД", value: "542" },
- { label: "Влюбленность", value: "1303" },
- { label: "Вне закона", value: "1089" },
- { label: "Внутренний сексизм", value: "2155" },
- { label: "Внутренняя гомофобия", value: "2154" },
- { label: "Внутренняя трансфобия", value: "2716" },
- { label: "Водители / Шоферы", value: "879" },
- { label: "Военные", value: "313" },
- { label: "Военные городки", value: "2095" },
- { label: "Военные преступления", value: "2356" },
- { label: "Возвращение", value: "1522" },
- { label: "Возвращение Артура", value: "2570" },
- { label: "Воздержание", value: "921" },
- { label: "Воздушная атлетика", value: "2811" },
- { label: "Война", value: "232" },
- { label: "Война в Афганистане", value: "1050" },
- { label: "Война во Вьетнаме", value: "1332" },
- { label: "Война за независимость США", value: "2065" },
- { label: "Война миров", value: "1222" },
- { label: "Волдигуд", value: "1874" },
- { label: "Волейбол", value: "1095" },
- { label: "Волк в овечьей шкуре", value: "2228" },
- { label: "Волонтеры", value: "900" },
- { label: "Волшебники / Волшебницы", value: "93" },
- { label: "Воображаемые друзья", value: "738" },
- { label: "Ворарефилия", value: "157" },
- { label: "Воры", value: "320" },
- { label: "Воскрешение", value: "256" },
- { label: "Воспоминания", value: "1118" },
- { label: "Воссоединение", value: "498" },
- { label: "Восстание машин", value: "817" },
- { label: "Восточное побережье", value: "770" },
- { label: "Восьмое марта", value: "493" },
- { label: "Вражда", value: "681" },
- { label: "Вражда семей", value: "2867" },
- { label: "Врачи", value: "374" },
- { label: "Времена Мародеров", value: "1872" },
- { label: "Времена Основателей", value: "1891" },
- { label: "Временная смерть персонажа", value: "439" },
- { label: "Временное бессмертие", value: "2755" },
- { label: "Временное воскрешение персонажей", value: "2649" },
- { label: "Временные петли", value: "147" },
- { label: "Временные превращения", value: "927" },
- { label: "Врожденные заболевания", value: "1781" },
- { label: "Всадники Апокалипсиса", value: "1326" },
- { label: "Все живы / Никто не умер", value: "535" },
- { label: "Все за Одного — отец Изуку", value: "2421" },
- { label: "Всезнающий рассказчик", value: "1368" },
- { label: "Вселение в тело", value: "1181" },
- { label: "Вторая мировая", value: "488" },
- { label: "Вторжение пришельцев", value: "755" },
- { label: "Вторичный стыд", value: "1393" },
- { label: "Второй шанс", value: "1799" },
- { label: "Второстепенные оригинальные персонажи", value: "1536" },
- { label: "Вуайеризм", value: "174" },
- { label: "Вуду", value: "678" },
- { label: "Выбор", value: "2808" },
- { label: "Выгорание", value: "2914" },
- { label: "Выживание", value: "216" },
- { label: "Вымирающий вид", value: "2373" },
- { label: "Вымышленная анатомия", value: "1317" },
- { label: "Вымышленная география", value: "1294" },
- { label: "Вымышленная религия", value: "2062" },
- { label: "Вымышленная физика", value: "2132" },
- { label: "Вымышленные виды спорта", value: "1777" },
- { label: "Вымышленные заболевания", value: "1295" },
- { label: "Вымышленные науки", value: "1333" },
- { label: "Вымышленные праздники", value: "1769" },
- { label: "Вымышленные профессии", value: "1391" },
- { label: "Вымышленные существа", value: "1685" },
- { label: "Вымышленные языки", value: "536" },
- { label: "Выпускные", value: "717" },
- { label: "Высшее общество", value: "1093" },
- { label: "Высшие учебные заведения", value: "97" },
- { label: "Выученная беспомощность", value: "2772" },
- { label: "Выхаживание", value: "511" },
- { label: "Выход из нездоровых отношений", value: "2891" },
- { label: "Гадалки / Ясновидящие", value: "2662" },
- { label: "Гадкий утенок", value: "1225" },
- { label: "Газлайтинг", value: "1418" },
- { label: "Галлюцинации / Иллюзии", value: "365" },
- { label: "Гаремник", value: "50" },
- { label: "Гаремы", value: "115" },
- { label: "Гарпии", value: "1482" },
- { label: "Гарри Поттер и Драко Малфой — друзья", value: "1923" },
- { label: "Гастроли", value: "2487" },
- { label: "Гедонизм", value: "736" },
- { label: "Гей-клубы", value: "2482" },
- { label: "Геймеры", value: "356" },
- { label: "Геймлит", value: "23" },
- { label: "Гейши / Кисэн", value: "332" },
- { label: "Гемофилия", value: "1341" },
- { label: "Гендерная дисфория", value: "431" },
- { label: "Гендерная интрига", value: "55" },
- { label: "Гендерное неравенство", value: "2568" },
- { label: "Гендерный нонконформизм", value: "1417" },
- { label: "Гендерсвап", value: "1691" },
- { label: "Генетика / Эволюция", value: "2131" },
- { label: "Гении", value: "445" },
- { label: "Генитальные пытки", value: "2104" },
- { label: "Геноцид", value: "720" },
- { label: "Геокинез", value: "2889" },
- { label: "Геологи / Географы", value: "934" },
- { label: "Германия", value: "688" },
- { label: "Германия — не Священная Римская Империя", value: "2470" },
- { label: "Герой поневоле", value: "2145" },
- { label: "Геронтофилия", value: "162" },
- { label: "Гетерохромия", value: "1210" },
- { label: "Гетто", value: "1783" },
- { label: "Гибристофилия", value: "1843" },
- { label: "Гиганты", value: "735" },
- { label: "Гидра трэш-пати", value: "2804" },
- { label: "Гики", value: "482" },
- { label: "Гильдии", value: "957" },
- { label: "Гимнастика", value: "1974" },
- { label: "Гиперакузия", value: "2866" },
- { label: "Гиперсексуальность", value: "945" },
- { label: "Гипноз", value: "700" },
- { label: "Гладиаторы", value: "677" },
- { label: "Глобальные катастрофы", value: "525" },
- { label: "Глухота", value: "595" },
- { label: "Гнев", value: "2806" },
- { label: "Гнездование", value: "1452" },
- { label: "Гномы", value: "138" },
- { label: "Гоблины", value: "188" },
- { label: "Големы", value: "1208" },
- { label: "Голод", value: "868" },
- { label: "Голодные Фэндомные Игры", value: "2895" },
- { label: "Гомофобия", value: "428" },
- { label: "Гомункулы", value: "1366" },
- { label: "Горе / Утрата", value: "1113" },
- { label: "Горизонтальный инцест", value: "338" },
- { label: "Городские легенды", value: "1832" },
- { label: "Горы", value: "702" },
- { label: "Горячие источники", value: "2813" },
- { label: "Гостевой брак", value: "1354" },
- { label: "Гостиницы", value: "384" },
- { label: "Готический роман", value: "963" },
- { label: "Готы", value: "575" },
- { label: "Гравиокинез", value: "1985" },
- { label: "Гражданская война", value: "370" },
- { label: "Гражданская война в России", value: "1282" },
- { label: "Гражданская война в США", value: "1018" },
- { label: "Графичные описания", value: "2854" },
- { label: "Грейнджергад", value: "1892" },
- { label: "Грейромантичные персонажи", value: "707" },
- { label: "Гремлины", value: "189" },
- { label: "Греция", value: "1040" },
- { label: "Грифоны", value: "335" },
- { label: "Громкий секс", value: "1184" },
- { label: "Грубый секс", value: "121" },
- { label: "Грудное кормление", value: "296" },
- { label: "Групи", value: "2925" },
- { label: "Групповое изнасилование", value: "2203" },
- { label: "Групповой секс", value: "1654" },
- { label: "Грязный реализм", value: "634" },
- { label: "Гувернантки", value: "1179" },
- { label: "Гули", value: "367" },
- { label: "Гэвин Рид — андроид", value: "2692" },
- { label: "Даб-кон", value: "57" },
- { label: "Даби — не Тойя Тодороки", value: "2821" },
- { label: "Даби — Тойя Тодороки", value: "2423" },
- { label: "Дадзава", value: "2915" },
- { label: "Дадмайт", value: "2917" },
- { label: "Дайверы", value: "939" },
- { label: "Дайвинг", value: "2823" },
- { label: "Дама в беде", value: "1259" },
- { label: "Дамбигад", value: "1863" },
- { label: "Дамбигуд", value: "1873" },
- { label: "Дампиры", value: "2860" },
- { label: "Дандэрэ", value: "1364" },
- { label: "Дарк", value: "1678" },
- { label: "Даркнет", value: "1287" },
- { label: "Дачи", value: "930" },
- { label: "Двойники", value: "305" },
- { label: "Двойное проникновение", value: "107" },
- { label: "Двойной кноттинг", value: "2619" },
- { label: "Двойные агенты", value: "441" },
- { label: "Дворцовые интриги", value: "2075" },
- { label: "Девиантное поведение", value: "1814" },
- { label: "Девичники / Мальчишники", value: "1191" },
- { label: "Девочки из Эквестрии", value: "2912" },
- { label: "Дежавю", value: "2049" },
- { label: "Декаданс", value: "2353" },
- { label: "Деконструкция", value: "1322" },
- { label: "Деми-персонажи", value: "723" },
- { label: "Демиурги", value: "819" },
- { label: "Демонология", value: "2485" },
- { label: "Демоны", value: "73" },
- { label: "Демоны-хранители", value: "2045" },
- { label: "Дендрофилия", value: "491" },
- { label: "День благодарения", value: "754" },
- { label: "День знаний", value: "1075" },
- { label: "День матери", value: "2979" },
- { label: "День мертвых", value: "1074" },
- { label: "День независимости США", value: "1008" },
- { label: "День рождения", value: "298" },
- { label: "День святого Валентина", value: "204" },
- { label: "День святого Патрика", value: "1129" },
- { label: "День смерти", value: "2251" },
- { label: "День учителя", value: "1076" },
- { label: "Деперсонализация", value: "1197" },
- { label: "Депрессия", value: "354" },
- { label: "Депривация сна", value: "551" },
- { label: "Дереализация", value: "1198" },
- { label: "Деревни", value: "364" },
- { label: "Дерматозойный бред", value: "2779" },
- { label: "Деспоты / Тираны", value: "1345" },
- { label: "Детектив", value: "1672" },
- { label: "Дети", value: "217" },
- { label: "Детоненавистничество", value: "1836" },
- { label: "Детская влюбленность", value: "186" },
- { label: "Детские дома", value: "355" },
- { label: "Детские лагеря", value: "222" },
- { label: "Детские сады", value: "567" },
- { label: "Дефекты зрения", value: "2639" },
- { label: "Дефекты речи", value: "737" },
- { label: "Джинны / Пери", value: "456" },
- { label: "Джон Ватсон — преступник", value: "1932" },
- { label: "Джуманджи — не игровой мир", value: "2799" },
- { label: "Диабет", value: "820" },
- { label: "Диалоги (стилизация)", value: "1139" },
- { label: "Дизайнеры", value: "1875" },
- { label: "Дизельпанк", value: "294" },
- { label: "Дикие животные", value: "622" },
- { label: "Дикий Запад", value: "293" },
- { label: "Дилетанты", value: "2443" },
- { label: "Динозавры", value: "670" },
- { label: "Дипломатия", value: "1790" },
- { label: "Дисбаланс власти", value: "732" },
- { label: "Дискриминация", value: "2230" },
- { label: "Дискриминация по внешности", value: "1414" },
- { label: "Дискриминация по возрасту", value: "2843" },
- { label: "Дислексия", value: "860" },
- { label: "Дисморфофобия", value: "1108" },
- { label: "Диссоциативное расстройство идентичности", value: "2127" },
- { label: "Дистанционное обучение", value: "2592" },
- { label: "Дисфункциональные семьи", value: "602" },
- { label: "Дневники (стилизация)", value: "214" },
- { label: "Добрый Сальери", value: "2522" },
- { label: "Доверие", value: "1117" },
- { label: "Договоры / Сделки", value: "2137" },
- { label: "Документы / Отчеты (стилизация)", value: "752" },
- { label: "Долголетие", value: "2130" },
- { label: "Домашнее насилие", value: "42" },
- { label: "Домашние животные", value: "517" },
- { label: "Домашний арест", value: "2526" },
- { label: "Домашний ремонт", value: "867" },
- { label: "Домовые", value: "1423" },
- { label: "Допросы", value: "2654" },
- { label: "Дорожное приключение", value: "47" },
- { label: "Драббл", value: "2935" },
- { label: "Драки", value: "1367" },
- { label: "Драконы", value: "43" },
- { label: "Драма", value: "1668" },
- { label: "Драуги", value: "2264" },
- { label: "Древний Восток", value: "1940" },
- { label: "Древний Египет", value: "474" },
- { label: "Древний Китай", value: "1438" },
- { label: "Древняя Русь", value: "466" },
- { label: "Дремлющее зло", value: "2719" },
- { label: "Дремлющие способности", value: "2084" },
- { label: "Другая магическая школа", value: "1864" },
- { label: "Другие планеты", value: "1415" },
- { label: "Другой избранный", value: "2054" },
- { label: "Другой факультет", value: "1866" },
- { label: "Дружба", value: "1701" },
- { label: "Дружба втайне", value: "2303" },
- { label: "Дружба по расчету", value: "2331" },
- { label: "Друзья детства", value: "343" },
- { label: "Друзья по переписке", value: "1466" },
- { label: "Друзья поневоле", value: "627" },
- { label: "Друзья с привилегиями", value: "113" },
- { label: "Друиды", value: "1199" },
- { label: "Дрэг (субкультура)", value: "1248" },
- { label: "Дурмстранг", value: "2389" },
- { label: "Дурслигуд", value: "2058" },
- { label: "Духи природы", value: "503" },
- { label: "Духовенство", value: "478" },
- { label: "Духовная связь", value: "2090" },
- { label: "Духокинез", value: "2500" },
- { label: "Дуэли", value: "446" },
- { label: "Дьяволы", value: "2369" },
- { label: "Дэдди-кинк", value: "165" },
- { label: "Еда / Кулинария", value: "1195" },
- { label: "Единороги", value: "373" },
- { label: "Ёкаи", value: "416" },
- { label: "Естественные враги", value: "728" },
- { label: "Жамевю", value: "2050" },
- { label: "Жаргон", value: "1016" },
- { label: "Ждун Фест", value: "2936" },
- { label: "Железнодорожники", value: "2680" },
- { label: "Железные дороги", value: "811" },
- { label: "Женская дружба", value: "2156" },
- { label: "Жертвы обстоятельств", value: "1475" },
- { label: "Жестокое обращение с животными", value: "722" },
- { label: "Жестокость", value: "1710" },
- { label: "Живой сосуд", value: "2072" },
- { label: "Животные-компаньоны", value: "2371" },
- { label: "Живые машины", value: "961" },
- { label: "ЖиП", value: "143" },
- { label: "Журналисты", value: "438" },
- { label: "Заболевания", value: "1268" },
- { label: "Заболевания крови", value: "2254" },
- { label: "Заболевания сердца", value: "1767" },
- { label: "Забота / Поддержка", value: "1302" },
- { label: "Заброшенные города", value: "1276" },
- { label: "Заброшенные здания", value: "1483" },
- { label: "Забытый герой", value: "2337" },
- { label: "Завещание", value: "1262" },
- { label: "Зависимое расстройство личности", value: "2349" },
- { label: "Зависть", value: "990" },
- { label: "Завоевание", value: "978" },
- { label: "Загробный мир", value: "275" },
- { label: "Закавказье", value: "2819" },
- { label: "Заклятые друзья", value: "1316" },
- { label: "Закрытые города", value: "1481" },
- { label: "Закрытые учебные заведения", value: "98" },
- { label: "Закрытый детектив", value: "2616" },
- { label: "Заложники", value: "845" },
- { label: "Замки", value: "654" },
- { label: "Замкнутое пространство", value: "2306" },
- { label: "Замкнутый мир", value: "874" },
- { label: "Занавесочная история", value: "1688" },
- { label: "Запахи", value: "1385" },
- { label: "Заповедники", value: "618" },
- { label: "Запредельно одаренный персонаж", value: "1241" },
- { label: "Запрет на магию", value: "2663" },
- { label: "Запретные отношения", value: "362" },
- { label: "Засосы / Укусы", value: "913" },
- { label: "Застенчивость", value: "2807" },
- { label: "Затворники", value: "1059" },
- { label: "Затерянные миры", value: "2448" },
- { label: "Защита любимого", value: "2492" },
- { label: "Защитники природы", value: "628" },
- { label: "Защищенный секс", value: "636" },
- { label: "Звездные слезы", value: "2971" },
- { label: "Здоровые механизмы преодоления", value: "2147" },
- { label: "Здоровые отношения", value: "1853" },
- { label: "Зеркала", value: "724" },
- { label: "Зимняя Фандомная Битва", value: "254" },
- { label: "Злобные бывшие", value: "518" },
- { label: "Зловещая находка", value: "2275" },
- { label: "Знаки зодиака", value: "643" },
- { label: "Знаменитости", value: "1360" },
- { label: "Золотая клетка", value: "480" },
- { label: "Золотая молодежь", value: "796" },
- { label: "Золотая Орда", value: "1143" },
- { label: "Золушка", value: "1226" },
- { label: "Зомби", value: "31" },
- { label: "Зоопарки", value: "792" },
- { label: "Зоофилия", value: "1662" },
- { label: "Зоофобии", value: "2715" },
- { label: "ЗППП", value: "630" },
- { label: "ЗПР", value: "2259" },
- { label: "Зрелые персонажи", value: "851" },
- { label: "Иван Купала", value: "1068" },
- { label: "Игровое расстройство", value: "949" },
- { label: "Игрушки", value: "1346" },
- { label: "Игры на выживание", value: "554" },
- { label: "Игры на раздевание", value: "1535" },
- { label: "Игры с сосками", value: "423" },
- { label: "Игры с температурой", value: "230" },
- { label: "Идеализация", value: "1540" },
- { label: "Иерархический строй", value: "652" },
- { label: "Избранные", value: "847" },
- { label: "Избыточный физиологизм", value: "2334" },
- { label: "Изгнанники", value: "871" },
- { label: "Измена", value: "62" },
- { label: "Измененное состояние сознания", value: "2242" },
- { label: "Изменились за лето", value: "1908" },
- { label: "Изнасилование", value: "1650" },
- { label: "Изоляция", value: "1296" },
- { label: "Израиль", value: "1094" },
- { label: "Изуку Мидория — злодей", value: "2472" },
- { label: "Иллюзионисты", value: "532" },
- { label: "Имейджин", value: "838" },
- { label: "Импотенция", value: "632" },
- { label: "Импринтинг", value: "635" },
- { label: "Импрореал", value: "2955" },
- { label: "Импрофест", value: "2947" },
- { label: "Имя вместо цвета", value: "2919" },
- { label: "Инвалидность", value: "197" },
- { label: "Индия", value: "1002" },
- { label: "Инквизиция", value: "1130" },
- { label: "Инопланетяне", value: "58" },
- { label: "Инсектоиды / Арахноиды", value: "953" },
- { label: "Инсектофилия / Арахнофилия", value: "664" },
- { label: "Инсценированная смерть персонажа", value: "440" },
- { label: "Интерактивная работа", value: "419" },
- { label: "Интервью (стилизация)", value: "2446" },
- { label: "Интернет", value: "1286" },
- { label: "Интерсекс-персонажи", value: "299" },
- { label: "Интрамаммарный секс", value: "840" },
- { label: "Инфантильность", value: "1300" },
- { label: "Инцест", value: "1651" },
- { label: "Ипохондрия", value: "2178" },
- { label: "Ирландия", value: "1035" },
- { label: "Иронический детектив", value: "2638" },
- { label: "Искра Стайлз Стилински", value: "1975" },
- { label: "Искупление", value: "877" },
- { label: "Искусственно вызванные чувства", value: "626" },
- { label: "Искусственные интеллекты", value: "150" },
- { label: "Искусственные существа", value: "2277" },
- { label: "Искусство", value: "2257" },
- { label: "Искусствоведы", value: "2873" },
- { label: "Искушение", value: "776" },
- { label: "Испания", value: "1020" },
- { label: "Исповеди", value: "1342" },
- { label: "Исправительные лагеря", value: "2439" },
- { label: "Истинные", value: "1855" },
- { label: "Историческая Хеталия", value: "1865" },
- { label: "Исторические эпохи", value: "1698" },
- { label: "Исторический Кантриболс", value: "2913" },
- { label: "Историческое допущение", value: "2681" },
- { label: "Исцеление", value: "802" },
- { label: "Италия", value: "1003" },
- { label: "Ихтиоморфы", value: "972" },
- { label: "Йога", value: "483" },
- { label: "Йоль", value: "2143" },
- { label: "Кабаре", value: "457" },
- { label: "Кабэ-дон", value: "2626" },
- { label: "Казахстан", value: "1260" },
- { label: "Казино", value: "620" },
- { label: "Казнь", value: "548" },
- { label: "Как ориджинал", value: "1032" },
- { label: "Каламбуры", value: "881" },
- { label: "Каминг-аут", value: "559" },
- { label: "Канада", value: "695" },
- { label: "Каникулы", value: "805" },
- { label: "Каннибализм", value: "1706" },
- { label: "Канонная смерть персонажа", value: "564" },
- { label: "Капитан Гидра", value: "1928" },
- { label: "Карантинные зоны", value: "1290" },
- { label: "Карантины", value: "2734" },
- { label: "Караоке", value: "886" },
- { label: "Карательная психиатрия", value: "730" },
- { label: "Карибский бассейн", value: "1172" },
- { label: "Карма", value: "647" },
- { label: "Карьеризм", value: "956" },
- { label: "Каскадеры", value: "2267" },
- { label: "Катарсис", value: "824" },
- { label: "Кафе / Кофейни / Чайные", value: "13" },
- { label: "Квай-Гад", value: "2894" },
- { label: "Квантовая физика", value: "2744" },
- { label: "Квисины", value: "2722" },
- { label: "Кемономими", value: "997" },
- { label: "Кемпинг", value: "182" },
- { label: "Кентавры", value: "64" },
- { label: "Кибербуллинг", value: "1858" },
- { label: "Киберпанк", value: "24" },
- { label: "Киберспорт", value: "745" },
- { label: "Кибертрон", value: "2775" },
- { label: "Киборги", value: "154" },
- { label: "Киевская Русь", value: "515" },
- { label: "Кинк на беременность", value: "2281" },
- { label: "Кинк на волосы", value: "2089" },
- { label: "Кинк на волосы на теле", value: "1337" },
- { label: "Кинк на девственность", value: "2282" },
- { label: "Кинк на инвалидность", value: "633" },
- { label: "Кинк на интеллект", value: "2798" },
- { label: "Кинк на клыки", value: "2325" },
- { label: "Кинк на колготки", value: "2644" },
- { label: "Кинк на крылья", value: "2035" },
- { label: "Кинк на латекс", value: "134" },
- { label: "Кинк на мольбы", value: "1543" },
- { label: "Кинк на наручники", value: "1065" },
- { label: "Кинк на нижнее белье", value: "145" },
- { label: "Кинк на очки", value: "1723" },
- { label: "Кинк на ошейники", value: "388" },
- { label: "Кинк на полноту", value: "552" },
- { label: "Кинк на похвалу", value: "1042" },
- { label: "Кинк на протезы", value: "2682" },
- { label: "Кинк на рога", value: "2320" },
- { label: "Кинк на руки", value: "915" },
- { label: "Кинк на сердцебиение", value: "941" },
- { label: "Кинк на силу", value: "1476" },
- { label: "Кинк на слезы", value: "1373" },
- { label: "Кинк на служение", value: "2980" },
- { label: "Кинк на страх", value: "2246" },
- { label: "Кинк на стыд", value: "747" },
- { label: "Кинк на унижение", value: "2291" },
- { label: "Кинк на униформу", value: "1350" },
- { label: "Кинк на уши", value: "2370" },
- { label: "Кинк на формальную одежду", value: "1064" },
- { label: "Кинк на чужую одежду", value: "2920" },
- { label: "Кинк на чулки", value: "810" },
- { label: "Кинк на шрамы", value: "2831" },
- { label: "Кинк на щекотку", value: "2396" },
- { label: "Кинк-бинго", value: "2290" },
- { label: "Кинки / Фетиши", value: "1659" },
- { label: "Кинотеатры", value: "981" },
- { label: "Киригакуре", value: "2475" },
- { label: "Китай", value: "757" },
- { label: "Кладбища", value: "501" },
- { label: "Кланы", value: "2879" },
- { label: "Классизм", value: "1927" },
- { label: "Клейма", value: "1548" },
- { label: "Клептомания", value: "1160" },
- { label: "Клетка Люцифера", value: "1884" },
- { label: "Клетки", value: "1069" },
- { label: "Клиническая смерть", value: "2068" },
- { label: "Клокпанк / Ветропанк", value: "1812" },
- { label: "Клоны", value: "358" },
- { label: "Клоуны", value: "1520" },
- { label: "Клубы по интересам", value: "1369" },
- { label: "Клюква", value: "1001" },
- { label: "Кляпы / Затыкание рта", value: "379" },
- { label: "Книги", value: "2746" },
- { label: "Книжные магазины", value: "444" },
- { label: "Кноттинг", value: "99" },
- { label: "Ковбои", value: "330" },
- { label: "Кода", value: "1943" },
- { label: "Кожаная одежда", value: "1517" },
- { label: "Колдовстворец", value: "2600" },
- { label: "Кома", value: "516" },
- { label: "Командная работа", value: "708" },
- { label: "Комики", value: "1315" },
- { label: "Комиксисты / Мангаки", value: "576" },
- { label: "Коммунальные квартиры", value: "1437" },
- { label: "Коммуны", value: "797" },
- { label: "Комнатные растения", value: "1792" },
- { label: "Комплекс Бога", value: "2087" },
- { label: "Комплекс превосходства", value: "2191" },
- { label: "Комплексы", value: "2529" },
- { label: "Конкурс от BUBBLE", value: "2937" },
- { label: "Конный спорт", value: "1378" },
- { label: "Конохагакуре", value: "2477" },
- { label: "Конспирология", value: "1911" },
- { label: "Контрабандисты", value: "2363" },
- { label: "Контроль / Подчинение", value: "932" },
- { label: "Контроль памяти", value: "2540" },
- { label: "Контроль сознания", value: "257" },
- { label: "Конфликт мировоззрений", value: "2678" },
- { label: "Концентрационные лагеря", value: "547" },
- { label: "Концерты / Выступления", value: "1236" },
- { label: "Конюшни", value: "514" },
- { label: "Копирование сознания", value: "1231" },
- { label: "Копирование способностей", value: "1825" },
- { label: "Копро-кинк", value: "763" },
- { label: "Корё", value: "1142" },
- { label: "Корейская война", value: "2187" },
- { label: "Коренные народы", value: "1505" },
- { label: "Королевства", value: "2794" },
- { label: "Корпорация BOBSOC", value: "2940" },
- { label: "Корректирующее изнасилование", value: "2856" },
- { label: "Коррупция", value: "2150" },
- { label: "Косвенные убийства", value: "2846" },
- { label: "Космоопера", value: "48" },
- { label: "Космос", value: "236" },
- { label: "Косплееры", value: "944" },
- { label: "Кочевники", value: "1793" },
- { label: "Кошмары", value: "1228" },
- { label: "Красная нить судьбы", value: "608" },
- { label: "Крепости / Башни", value: "2321" },
- { label: "Крестовые походы", value: "2070" },
- { label: "Крестражи", value: "2238" },
- { label: "Кризис гендера", value: "1406" },
- { label: "Кризис ориентации", value: "1405" },
- { label: "Криминалистическая экспертиза", value: "2361" },
- { label: "Криминальная пара", value: "1920" },
- { label: "Криокинез", value: "1804" },
- { label: "Криптиды", value: "60" },
- { label: "Криптоистория", value: "179" },
- { label: "Кровь / Травмы", value: "800" },
- { label: "Кроссдрессинг", value: "65" },
- { label: "Кроссовер", value: "10" },
- { label: "Кроули — Архангел Рафаэль", value: "2471" },
- { label: "Круизы", value: "2488" },
- { label: "Крушение «Титаника»", value: "2200" },
- { label: "Крылатые", value: "92" },
- { label: "Крэк", value: "1408" },
- { label: "Ксенофилия", value: "1711" },
- { label: "Ксенофобия", value: "589" },
- { label: "Куба", value: "773" },
- { label: "Кудэрэ", value: "1216" },
- { label: "Куклы", value: "1221" },
- { label: "Куколдинг", value: "524" },
- { label: "Культ Дракона", value: "2244" },
- { label: "Кумогакуре", value: "2474" },
- { label: "Куннилингус", value: "172" },
- { label: "Купальни", value: "964" },
- { label: "Курение", value: "202" },
- { label: "Курортный роман", value: "181" },
- { label: "Курьеры", value: "2735" },
- { label: "Лабиринты", value: "1981" },
- { label: "Лаборатории", value: "1115" },
- { label: "Лабораторные опыты", value: "146" },
- { label: "Лав-отели", value: "801" },
- { label: "Лавандовый брак", value: "1357" },
- { label: "Лакросс", value: "830" },
- { label: "Лапслок", value: "267" },
- { label: "Латентная гомосексуальность", value: "2339" },
- { label: "ЛГБТ-родители", value: "2723" },
- { label: "Лебединая верность", value: "537" },
- { label: "Левитация", value: "1281" },
- { label: "Легкая атлетика", value: "1797" },
- { label: "Лекарственная зависимость", value: "2632" },
- { label: "Леса", value: "703" },
- { label: "Летние ОтМетки", value: "2956" },
- { label: "Летние школы", value: "2803" },
- { label: "Лето девяносто девятого", value: "1990" },
- { label: "Лжебоги", value: "2869" },
- { label: "Лингвистический кинк", value: "2042" },
- { label: "Лирика", value: "2005" },
- { label: "Лихтенштейн", value: "1023" },
- { label: "Личность против системы", value: "1912" },
- { label: "Ложная беременность", value: "1428" },
- { label: "Ложные воспоминания", value: "376" },
- { label: "Ложные обвинения", value: "1204" },
- { label: "Локальный постапокалипсис", value: "2455" },
- { label: "Лолита (субкультура)", value: "1207" },
- { label: "Ломка", value: "1846" },
- { label: "Лошади", value: "1083" },
- { label: "Лугнасад", value: "2621" },
- { label: "Лудомания", value: "947" },
- { label: "Лучники", value: "1521" },
- { label: "Любить луну", value: "2901" },
- { label: "Любовная магия", value: "2317" },
- { label: "Любовный магнит", value: "1407" },
- { label: "Любовный многоугольник", value: "63" },
- { label: "Любовь с первого взгляда", value: "813" },
- { label: "Любовь/Ненависть", value: "1703" },
- { label: "Люди", value: "1538" },
- { label: "Людоеды", value: "1288" },
- { label: "Магазины", value: "1063" },
- { label: "Магическая связь", value: "2720" },
- { label: "Магические клятвы", value: "2245" },
- { label: "Магические лавки", value: "2629" },
- { label: "Магические учебные заведения", value: "1338" },
- { label: "Магический реализм", value: "9" },
- { label: "Магия", value: "1419" },
- { label: "Магия крови", value: "2857" },
- { label: "Маленькие города", value: "221" },
- { label: "Малфоигуд", value: "1890" },
- { label: "Мамми-кинк", value: "273" },
- { label: "Мандалорцы", value: "2870" },
- { label: "Манекены", value: "1509" },
- { label: "Манипуляции", value: "992" },
- { label: "Марафонный секс", value: "316" },
- { label: "Маргиналы", value: "394" },
- { label: "Марди Гра", value: "2407" },
- { label: "Маскарады / Балы", value: "443" },
- { label: "Массаж", value: "2218" },
- { label: "Мастурбация", value: "226" },
- { label: "Матриархат", value: "706" },
- { label: "Матчасть", value: "2328" },
- { label: "Махотокоро", value: "2943" },
- { label: "Маяки", value: "1356" },
- { label: "Мегаломания", value: "985" },
- { label: "Мегаполисы", value: "451" },
- { label: "Медицинский кинк", value: "748" },
- { label: "Медицинское использование наркотиков", value: "925" },
- { label: "Медовый месяц", value: "2235" },
- { label: "Медсестры / Медбратья", value: "2236" },
- { label: "Межбедренный секс", value: "931" },
- { label: "Междумирье", value: "2280" },
- { label: "Межэтнические отношения", value: "2121" },
- { label: "Мейлдом", value: "59" },
- { label: "Мексика", value: "768" },
- { label: "Меланхолия", value: "2108" },
- { label: "Мелодрама", value: "2881" },
- { label: "Менструация", value: "1570" },
- { label: "Ментальная тюрьма", value: "2294" },
- { label: "Месть", value: "907" },
- { label: "Металлисты", value: "1206" },
- { label: "Металлокинез", value: "1532" },
- { label: "Метафизические существа", value: "2097" },
- { label: "Метки", value: "1398" },
- { label: "Метросексуалы", value: "558" },
- { label: "Механофилия / Технофилия", value: "587" },
- { label: "Мечники", value: "2783" },
- { label: "Мечты", value: "993" },
- { label: "Миддлпанк", value: "2076" },
- { label: "Мизофилия", value: "1970" },
- { label: "Микро / Макро", value: "407" },
- { label: "Микрофикшен", value: "417" },
- { label: "Мимикрия", value: "2083" },
- { label: "Минет", value: "231" },
- { label: "Министерство Магии", value: "1917" },
- { label: "Минотавры", value: "2820" },
- { label: "Мир без гомофобии", value: "2660" },
- { label: "Мир Желаний (Однажды в сказке)", value: "2923" },
- { label: "Мир Института Войны", value: "2379" },
- { label: "Мироустройство", value: "989" },
- { label: "Мистерия", value: "2012" },
- { label: "Мистика", value: "1671" },
- { label: "Мистическая беременность", value: "1784" },
- { label: "Мистические защитники", value: "2162" },
- { label: "Мифы и мифология", value: "18" },
- { label: "Мнимая беременность", value: "1096" },
- { label: "Мнимая проза", value: "1098" },
- { label: "Мнимая свобода", value: "2708" },
- { label: "Многодетные семьи", value: "2785" },
- { label: "Множественное проникновение", value: "2059" },
- { label: "Множественные оргазмы", value: "317" },
- { label: "Множественные финалы", value: "312" },
- { label: "Могучие Рейнджеры: Дино Заряд", value: "2931" },
- { label: "Могучие Рейнджеры: Мегафорс", value: "2930" },
- { label: "Могучие Рейнджеры: Мистическая Сила", value: "2933" },
- { label: "Могучие Рейнджеры: Самураи", value: "2929" },
- { label: "Могучие Рейнджеры: Успеть на помощь", value: "2934" },
- { label: "Могучие Рейнджеры: Ярость Джунглей", value: "2932" },
- { label: "Модели", value: "399" },
- { label: "Модельеры", value: "598" },
- { label: "Модельный бизнес", value: "435" },
- { label: "Модификации тела", value: "890" },
- { label: "Молдова", value: "2967" },
- { label: "Молчание", value: "2465" },
- { label: "Монастыри", value: "352" },
- { label: "Монахи", value: "353" },
- { label: "Монолог", value: "2333" },
- { label: "Монстрофилия", value: "94" },
- { label: "Монстры", value: "529" },
- { label: "Моральные дилеммы", value: "959" },
- { label: "Морлед", value: "2255" },
- { label: "Моря / Океаны", value: "955" },
- { label: "Моряки", value: "406" },
- { label: "Мотоспорт", value: "1461" },
- { label: "Мужская беременность", value: "1660" },
- { label: "Мужская дружба", value: "2157" },
- { label: "Мужское грудное кормление", value: "297" },
- { label: "Музеи / Галереи", value: "795" },
- { label: "Музы", value: "2001" },
- { label: "Музыканты", value: "141" },
- { label: "Муковисцидоз", value: "2764" },
- { label: "Мультикроссовер", value: "2247" },
- { label: "Мумии", value: "579" },
- { label: "Мутанты", value: "740" },
- { label: "Мэри Сью (Марти Стью)", value: "1655" },
- { label: "Мятежи / Восстания", value: "584" },
- { label: "На грани жизни и смерти", value: "2545" },
- { label: "Наблюдатели", value: "1816" },
- { label: "Навязчивая опека", value: "954" },
- { label: "Навязчивые мысли", value: "2851" },
- { label: "Наги", value: "90" },
- { label: "Надежда", value: "2627" },
- { label: "Наемники", value: "512" },
- { label: "Наемные убийцы", value: "192" },
- { label: "Названные сиблинги", value: "2927" },
- { label: "Намеки на отношения", value: "1387" },
- { label: "Намеки на секс", value: "1382" },
- { label: "Напарники", value: "1291" },
- { label: "Наперегонки со временем", value: "2240" },
- { label: "НапиСанта", value: "2946" },
- { label: "Наполеоновские войны", value: "470" },
- { label: "Нарколепсия", value: "586" },
- { label: "Наркоторговля", value: "1116" },
- { label: "Нарушение этических норм", value: "968" },
- { label: "Нарциссизм", value: "546" },
- { label: "Насекомые", value: "2358" },
- { label: "Насилие", value: "1649" },
- { label: "Насилие над детьми", value: "726" },
- { label: "Наследие (Гарри Поттер)", value: "1935" },
- { label: "Наследство", value: "2172" },
- { label: "Наставничество", value: "935" },
- { label: "Настольные игры", value: "1513" },
- { label: "Настольные ролевые игры", value: "644" },
- { label: "Натуризм / Нудизм", value: "1810" },
- { label: "Наука", value: "2624" },
- { label: "Научная фантастика", value: "596" },
- { label: "Научно-исследовательские организации", value: "1503" },
- { label: "Научное фэнтези", value: "180" },
- { label: "Начало отношений", value: "1328" },
- { label: "Небинарные персонажи", value: "314" },
- { label: "Невезение", value: "2689" },
- { label: "Невзаимные предначертанные", value: "1484" },
- { label: "Невзаимные чувства", value: "105" },
- { label: "Невидимость", value: "359" },
- { label: "Невидимый мир", value: "2286" },
- { label: "Неграфичные описания", value: "2855" },
- { label: "Недоверие", value: "1842" },
- { label: "Недопонимания", value: "614" },
- { label: "Недостатки внешности", value: "923" },
- { label: "Нежелательная беременность", value: "715" },
- { label: "Нежелательные сверхспособности", value: "1335" },
- { label: "Нежелательные чувства", value: "2078" },
- { label: "Нежный секс", value: "280" },
- { label: "Незащищенный секс", value: "497" },
- { label: "Нездоровые механизмы преодоления", value: "1528" },
- { label: "Нездоровые отношения", value: "71" },
- { label: "Нездоровый образ жизни", value: "2148" },
- { label: "Нездоровый BDSM", value: "1062" },
- { label: "Неидеальный омегаверс", value: "2712" },
- { label: "Неизвестность", value: "2826" },
- { label: "Неизвестные родственники", value: "2752" },
- { label: "Неизлечимые заболевания", value: "1269" },
- { label: "Нейтрализация сверхспособностей", value: "2343" },
- { label: "Некромаги", value: "679" },
- { label: "Некрофилия", value: "1663" },
- { label: "Нелинейное повествование", value: "1699" },
- { label: "Неловкий секс", value: "2883" },
- { label: "Неловкость", value: "2459" },
- { label: "Нелюбящие родители", value: "2817" },
- { label: "Немертвые", value: "495" },
- { label: "Немота", value: "414" },
- { label: "Ненависть", value: "685" },
- { label: "Ненависть к себе", value: "1441" },
- { label: "Ненависть с первого взгляда", value: "814" },
- { label: "Ненадежный рассказчик", value: "322" },
- { label: "Ненасильственная смерть", value: "2531" },
- { label: "Необитаемые острова", value: "1196" },
- { label: "Необратимые превращения", value: "926" },
- { label: "Неозвученные чувства", value: "258" },
- { label: "Неприятие отношений", value: "2056" },
- { label: "Неравные отношения", value: "545" },
- { label: "Неравный брак", value: "409" },
- { label: "Неразрывная связь", value: "2569" },
- { label: "Нервный срыв", value: "1190" },
- { label: "Нерды", value: "481" },
- { label: "Нереалистичность", value: "2350" },
- { label: "Несексуальная близость", value: "2874" },
- { label: "Нестандартная поэзия", value: "1704" },
- { label: "Несчастливые отношения", value: "2080" },
- { label: "Несчастливый финал", value: "61" },
- { label: "Несчастные случаи", value: "499" },
- { label: "Нетаймори", value: "2323" },
- { label: "Неторопливое повествование", value: "1815" },
- { label: "Нетрадиционное использование Силы", value: "2520" },
- {
- label: "Неумышленное употребление наркотических веществ",
- value: "1192",
- },
- { label: "Неуставные отношения", value: "1396" },
- { label: "Нефилимы", value: "1086" },
- { label: "Неформальный брак", value: "1355" },
- { label: "Нецензурная лексика", value: "1653" },
- { label: "Нечеловеческая мораль", value: "2551" },
- { label: "Нечеловеческие виды", value: "995" },
- { label: "Нечистая сила", value: "1464" },
- { label: "Нидерланды", value: "1141" },
- { label: "Низкая самооценка", value: "2014" },
- { label: "Низкое фэнтези", value: "2007" },
- { label: "Нимфы", value: "1477" },
- { label: "Ниндзя", value: "471" },
- { label: "Новая жизнь", value: "2018" },
- { label: "Новая Зеландия", value: "1789" },
- { label: "Новеллизация", value: "262" },
- { label: "Новые отношения", value: "1827" },
- { label: "Новый год", value: "206" },
- { label: "Новый канон ЗВ", value: "1948" },
- { label: "Норны", value: "2206" },
- { label: "Ностальгия", value: "878" },
- { label: "Ночное видение", value: "2006" },
- { label: "Ночные клубы", value: "531" },
- { label: "Нуар", value: "137" },
- { label: "Няни", value: "570" },
- { label: "Обездвиживание", value: "116" },
- { label: "Обещания / Клятвы", value: "1823" },
- { label: "Обиды", value: "905" },
- { label: "Обман / Заблуждение", value: "650" },
- { label: "Обмен квами", value: "2572" },
- { label: "Обмен ролями", value: "1055" },
- { label: "Обмен телами", value: "49" },
- { label: "Обмороки", value: "2484" },
- { label: "Обнажение", value: "970" },
- { label: "Оборотни", value: "28" },
- { label: "Обоснованный ООС", value: "2549" },
- { label: "Образ тела", value: "2289" },
- { label: "Обратный омегаверс", value: "2435" },
- { label: "Обретенные семьи", value: "601" },
- { label: "Обреченные отношения", value: "653" },
- { label: "Обскуры", value: "2237" },
- { label: "Обсуждение кинков", value: "1072" },
- { label: "Обусловленная контекстом гомофобия", value: "2685" },
- { label: "Обусловленный контекстом расизм", value: "2686" },
- { label: "Обусловленный контекстом сексизм", value: "2687" },
- { label: "Общежития", value: "534" },
- { label: "Общественный транспорт", value: "615" },
- { label: "Объективация", value: "1837" },
- { label: "Объектофилия", value: "366" },
- { label: "Овипозиция", value: "269" },
- { label: "Огнестрельное оружие", value: "1189" },
- { label: "Ограбления", value: "2269" },
- { label: "Одержимость", value: "2248" },
- { label: "Одержимые", value: "496" },
- { label: "Один день", value: "2647" },
- { label: "Одиночество", value: "1015" },
- { label: "Одичавшие дети", value: "835" },
- { label: "Однолюбы", value: "2146" },
- { label: "Одноминутный канонический персонаж", value: "2184" },
- { label: "Однополый мир", value: "1462" },
- { label: "Ожидание", value: "2909" },
- { label: "ОЖП", value: "1657" },
- { label: "Окаменение", value: "2052" },
- { label: "Океания", value: "1058" },
- { label: "Оккультизм", value: "2374" },
- { label: "ОКР", value: "594" },
- { label: "Окулолинктус", value: "1470" },
- { label: "Олимпийские игры", value: "1127" },
- { label: "Олфактофилия", value: "1945" },
- { label: "Омегаверс", value: "1693" },
- { label: "Омегаверс: Альфа/Альфа", value: "2437" },
- { label: "Омегаверс: Альфа/Бета", value: "2741" },
- { label: "Омегаверс: Альфа/Бета/Омега", value: "2898" },
- { label: "Омегаверс: Альфа/Омега/Альфа", value: "2436" },
- { label: "Омегаверс: Бета/Бета", value: "2966" },
- { label: "Омегаверс: Больше трех полов", value: "2782" },
- { label: "Омегаверс: Омега/Альфа/Омега", value: "2544" },
- { label: "Омегаверс: Омега/Бета", value: "2965" },
- { label: "Омегаверс: Омега/Омега", value: "2564" },
- { label: "Омегаверс: Смена второго пола", value: "2776" },
- { label: "Омегаверс: f!Альфа/m!Омега", value: "2777" },
- { label: "ОМП", value: "1656" },
- { label: "Онейрокинез", value: "2067" },
- { label: "Онкологические заболевания", value: "540" },
- { label: "ООС", value: "1648" },
- { label: "Опасность", value: "2847" },
- { label: "Опера", value: "549" },
- { label: "Опричнина", value: "2252" },
- { label: "Оптимизм", value: "2420" },
- { label: "Оракулы / Провидцы", value: "2221" },
- { label: "Оральная фиксация", value: "2523" },
- { label: "Оргазм без стимуляции", value: "1000" },
- { label: "Организаторы свадеб", value: "858" },
- { label: "Орден Феникса", value: "1907" },
- { label: "Орки", value: "187" },
- { label: "Оружие массового поражения", value: "1193" },
- { label: "Освоение земель", value: "1824" },
- { label: "Оседлание", value: "1223" },
- { label: "Османская империя", value: "527" },
- { label: "Особняки / Резиденции", value: "500" },
- { label: "Осознанные сновидения", value: "530" },
- { label: "Остеокинез", value: "2845" },
- { label: "Острова", value: "799" },
- { label: "От антигероя к герою", value: "2173" },
- { label: "От антигероя к злодею", value: "2213" },
- { label: "От божественного существа к смертному", value: "2664" },
- { label: "От возлюбленных к врагам", value: "783" },
- { label: "От возлюбленных к друзьям", value: "782" },
- { label: "От врагов к возлюбленным", value: "346" },
- { label: "От врагов к друзьям", value: "347" },
- { label: "От врагов к друзьям к возлюбленным", value: "345" },
- { label: "От героя к антигерою", value: "2546" },
- { label: "От героя к злодею", value: "1027" },
- { label: "От героя к монстру", value: "2659" },
- { label: "От героя к обычному персонажу", value: "2584" },
- { label: "От друзей к возлюбленным", value: "344" },
- { label: "От друзей к врагам", value: "463" },
- { label: "От друзей к незнакомцам", value: "1870" },
- { label: "От злодея к антигерою", value: "2640" },
- { label: "От злодея к герою", value: "1026" },
- { label: "От напарников к друзьям к возлюбленным", value: "2460" },
- { label: "От нездоровых отношений к здоровым", value: "2301" },
- { label: "От незнакомцев к возлюбленным", value: "372" },
- { label: "От простонародья к аристократу", value: "2816" },
- { label: "От сексуальных партнеров к возлюбленным", value: "2069" },
- { label: "От смертного к божественному существу", value: "2665" },
- { label: "От супругов к возлюбленным", value: "2359" },
- { label: "Ответвление от канона", value: "2336" },
- { label: "Ответственность", value: "2468" },
- { label: "Отдаю на вдохновение", value: "2288" },
- { label: "Отечественная война 1812 года", value: "1162" },
- { label: "Отказ от чувств", value: "2227" },
- { label: "Отклонения от канона", value: "5" },
- { label: "Открытый финал", value: "185" },
- { label: "ОтМетки", value: "2945" },
- { label: "Отношения втайне", value: "285" },
- { label: "Отношения на расстоянии", value: "37" },
- { label: "Отношения на спор", value: "383" },
- { label: "Отношения наполовину", value: "1573" },
- { label: "Отпуск", value: "1828" },
- { label: "Отрицание", value: "1868" },
- { label: "Отрицание чувств", value: "648" },
- { label: "Отрицательный протагонист", value: "1442" },
- { label: "Отсутствие души", value: "1897" },
- { label: "Отшельники", value: "543" },
- { label: "Офисы", value: "74" },
- { label: "Официанты / Официантки", value: "2560" },
- { label: "Охота", value: "825" },
- { label: "Охота на разумных существ", value: "2784" },
- { label: "Охотники", value: "2036" },
- { label: "Охотники за головами", value: "2103" },
- { label: "Охотники на нечисть", value: "46" },
- { label: "Охранники", value: "1173" },
- { label: "Ошибки", value: "2554" },
- { label: "Ошибочная идентификация", value: "2490" },
- { label: "Паладины", value: "1194" },
- { label: "Пан-персонажи", value: "302" },
- { label: "Пандемия COVID-19", value: "2724" },
- { label: "Панические атаки", value: "751" },
- { label: "Паническое расстройство", value: "733" },
- { label: "Панки", value: "625" },
- { label: "Паразиты", value: "1877" },
- { label: "Паралич", value: "1941" },
- { label: "Параллельные миры", value: "378" },
- { label: "Паранойя", value: "1253" },
- { label: "Пари", value: "778" },
- { label: "Парки / Зоны отдыха", value: "1005" },
- { label: "Парки аттракционов / Ярмарки", value: "793" },
- { label: "Паркур", value: "553" },
- { label: "Пародия", value: "1676" },
- { label: "Партизаны", value: "850" },
- { label: "Парфюмеры", value: "1384" },
- { label: "Пасха", value: "562" },
- { label: "Патологическое бесстрашие", value: "1498" },
- { label: "Патологическое накопительство", value: "2691" },
- { label: "Патологоанатомы", value: "502" },
- { label: "Патриархат", value: "705" },
- { label: "Патриотические темы и мотивы", value: "2231" },
- { label: "Патронусы", value: "2390" },
- { label: "Патрули", value: "1819" },
- { label: "Пафос", value: "2589" },
- { label: "Пацифисты", value: "1939" },
- { label: "Пегасы", value: "1047" },
- { label: "Пеггинг", value: "159" },
- { label: "Пейзажная лирика", value: "2330" },
- { label: "Пекарни", value: "78" },
- { label: "Первая мировая", value: "487" },
- { label: "Первая чеченская война", value: "2428" },
- { label: "Первобытные времена", value: "465" },
- { label: "Первое апреля", value: "2315" },
- { label: "Первопроходцы", value: "351" },
- { label: "Первый контакт", value: "2093" },
- { label: "Первый поцелуй", value: "2790" },
- { label: "Первый раз", value: "1292" },
- { label: "Передача магических способностей", value: "2497" },
- { label: "Переезд", value: "658" },
- { label: "Перезапуск мира", value: "2710" },
- { label: "Перемирие", value: "1331" },
- { label: "Переписки и чаты (стилизация)", value: "38" },
- { label: "Перерыв в отношениях", value: "519" },
- { label: "Переселение душ", value: "1237" },
- { label: "Перестрелки", value: "2268" },
- { label: "Переходный возраст", value: "1297" },
- { label: "Период Эдо", value: "1140" },
- { label: "Персекуторный бред", value: "2136" },
- { label: "Персонажи-геи", value: "2141" },
- { label: "Персонажи-лесбиянки", value: "2142" },
- { label: "Персонификация", value: "994" },
- { label: "Персонификация смерти", value: "1046" },
- { label: "Перу", value: "2017" },
- { label: "Перфекционизм", value: "2730" },
- { label: "Пессимизм", value: "2709" },
- { label: "Пет-плей", value: "391" },
- { label: "Петербург: бикейм #Чимин Сергеевич", value: "1859" },
- { label: "Петтинг", value: "301" },
- { label: "Пещеры", value: "655" },
- { label: "Пижамные вечеринки", value: "1340" },
- { label: "Пикацизм", value: "1227" },
- { label: "Пикники", value: "1165" },
- { label: "Пионеры", value: "668" },
- { label: "Пираты", value: "72" },
- { label: "Пирокинез", value: "1180" },
- { label: "Пиромания", value: "899" },
- { label: "Пирсинг", value: "507" },
- { label: "Писатели", value: "196" },
- { label: "Письма", value: "2298" },
- { label: "Письма (стилизация)", value: "266" },
- { label: "Пиццерии / Дайнеры", value: "593" },
- { label: "Плавание", value: "1135" },
- { label: "Плантокинез", value: "2029" },
- { label: "Пластические операции", value: "1847" },
- { label: "Платонические отношения", value: "385" },
- { label: "Племена", value: "1336" },
- { label: "Плен", value: "290" },
- { label: "Плененные путешествием", value: "2615" },
- { label: "Плохая компания", value: "1502" },
- { label: "Плохие друзья", value: "2445" },
- { label: "Плохой хороший финал", value: "1265" },
- { label: "Плюшефилия", value: "520" },
- { label: "Пляжи", value: "766" },
- { label: "По разные стороны", value: "897" },
- { label: "Побег", value: "661" },
- { label: "Побег из дома", value: "2309" },
- { label: "Победа Волдеморта", value: "1887" },
- { label: "Победа Гриндевальда", value: "2398" },
- { label: "Повара", value: "2853" },
- { label: "Повелитель смерти", value: "1909" },
- { label: "Повествование в будущем времени", value: "2633" },
- { label: "Повествование в настоящем времени", value: "1826" },
- { label: "Повествование во втором лице", value: "166" },
- { label: "Повествование от нескольких лиц", value: "1157" },
- { label: "Повествование от первого лица", value: "1681" },
- { label: "Повседневность", value: "1677" },
- { label: "Повстанцы", value: "659" },
- { label: "Повторение судьбы", value: "1997" },
- { label: "Поглощение способностей", value: "2605" },
- { label: "Погони / Преследования", value: "1996" },
- { label: "Пограничный синдром", value: "710" },
- { label: "Погребение заживо", value: "1279" },
- { label: "Под одной крышей", value: "462" },
- { label: "Под старину (стилизация)", value: "2486" },
- { label: "Подарки", value: "1109" },
- { label: "Подвешивание", value: "914" },
- { label: "Подводный мир", value: "901" },
- { label: "Подземелья", value: "2314" },
- { label: "Подземный мир", value: "1453" },
- { label: "Подлость", value: "2625" },
- { label: "Подменыши", value: "2250" },
- { label: "Подпольные бои", value: "1389" },
- { label: "Подразумеваемая смерть персонажа", value: "2204" },
- { label: "Подростки", value: "218" },
- { label: "Подростковая беременность", value: "986" },
- { label: "Подростковая влюбленность", value: "581" },
- { label: "Подсознание", value: "2273" },
- { label: "Поедание разумных существ", value: "1795" },
- { label: "Пожарные", value: "2557" },
- { label: "Пожилые персонажи", value: "852" },
- { label: "Поза 69", value: "699" },
- { label: "Поиск работы", value: "2646" },
- { label: "Поиск родителей", value: "2033" },
- { label: "Поклонение телу", value: "712" },
- { label: "Покровительство", value: "2223" },
- { label: "Покушение на жизнь", value: "1057" },
- { label: "Покушение на свободу", value: "2655" },
- { label: "Полиамория", value: "1705" },
- { label: "Полиандрия", value: "761" },
- { label: "Полигиния", value: "760" },
- { label: "Политика", value: "1835" },
- { label: "Политики", value: "711" },
- { label: "Политические интриги", value: "183" },
- { label: "Полицейские", value: "14" },
- { label: "Половой диморфизм", value: "1780" },
- { label: "Полубоги", value: "437" },
- { label: "Полудемоны", value: "2872" },
- { label: "Полудраконы", value: "2859" },
- { label: "Полукровки", value: "368" },
- { label: "Польша", value: "777" },
- { label: "Полярные станции", value: "1493" },
- { label: "Помощь врагу", value: "1325" },
- { label: "Попаданцы: В реальный мир", value: "1499" },
- { label: "Попаданцы: В своем теле", value: "1412" },
- { label: "Попаданцы: В чужом теле", value: "1413" },
- { label: "Попаданцы: Из одного фандома в другой", value: "2699" },
- { label: "Попаданцы: Из фандома в ориджинал", value: "2193" },
- { label: "Попаданцы: По обмену", value: "2196" },
- { label: "Попаданчество", value: "1695" },
- { label: "Популярность", value: "2581" },
- { label: "Попытка изнасилования", value: "1440" },
- { label: "Порноактеры", value: "289" },
- { label: "Португалия", value: "1749" },
- { label: "Порты", value: "1028" },
- { label: "Поселки", value: "1298" },
- { label: "После таймскипа (Haikyuu!!)", value: "2906" },
- { label: "После таймскипа (Shingeki no Kyojin)", value: "2903" },
- { label: "Послевоенное время", value: "1080" },
- { label: "Последний раз", value: "2645" },
- { label: "Последний рубеж", value: "1178" },
- { label: "Последний шанс", value: "1209" },
- { label: "Последствия", value: "2491" },
- { label: "Последствия болезни", value: "2612" },
- { label: "Послеродовая депрессия", value: "988" },
- { label: "Посмертная любовь", value: "2670" },
- { label: "Посмертный персонаж", value: "2653" },
- { label: "Пост-Пацифист", value: "2408" },
- { label: "Пост-Рейхенбах", value: "1903" },
- { label: "Пост-третий сезон (Шерлок)", value: "1977" },
- { label: "Постапокалиптика", value: "1697" },
- { label: "ПостВБ", value: "2386" },
- { label: "Постканон", value: "6" },
- { label: "ПостРагнарек", value: "2537" },
- { label: "ПостХог", value: "1883" },
- { label: "ПостЭндгейм", value: "2179" },
- { label: "Потеря девственности", value: "1234" },
- { label: "Потеря конечностей", value: "1289" },
- { label: "Потеря магических способностей", value: "1430" },
- { label: "Потеря памяти", value: "36" },
- { label: "Потеря сверхспособностей", value: "1051" },
- { label: "Поттергад", value: "2417" },
- { label: "Похищение", value: "224" },
- { label: "Похороны", value: "786" },
- { label: "Почтовые работники", value: "1821" },
- { label: "Пошлый юмор", value: "1362" },
- { label: "Поэма", value: "1938" },
- { label: "Поэты", value: "357" },
- { label: "Пояс верности", value: "1779" },
- { label: "Правда или действие", value: "1982" },
- { label: "Практопия", value: "2249" },
- { label: "Пре-гет", value: "209" },
- { label: "Пре-Рош", value: "2047" },
- { label: "Пре-слэш", value: "207" },
- { label: "Пре-фемслэш", value: "208" },
- { label: "Предательство", value: "361" },
- { label: "Предвидение", value: "1876" },
- { label: "Предложение руки и сердца", value: "1081" },
- { label: "Предопределенность", value: "411" },
- { label: "Предрассудки", value: "2046" },
- { label: "Предсмертные сообщения", value: "2174" },
- { label: "Преканон", value: "7" },
- { label: "ПреКербер", value: "2726" },
- { label: "Прекрасная эпоха", value: "1809" },
- { label: "Прелюдия", value: "2395" },
- { label: "Пренебрежение гигиеной", value: "2921" },
- { label: "Пренебрежение жизнью", value: "2216" },
- { label: "Преодоление комплексов", value: "588" },
- { label: "Преподаватели", value: "403" },
- { label: "Преподаватель/Обучающийся", value: "2507" },
- { label: "Преступники", value: "1446" },
- { label: "Преступный мир", value: "12" },
- { label: "Прибрежные города", value: "984" },
- { label: "Приватный танец", value: "2786" },
- { label: "Привязанность", value: "2372" },
- { label: "Пригород", value: "452" },
- { label: "Приемные семьи", value: "844" },
- { label: "Признания в любви", value: "1049" },
- { label: "Призраки", value: "26" },
- { label: "Приключения", value: "21" },
- { label: "Приметы / Суеверия", value: "612" },
- { label: "Примирение", value: "660" },
- { label: "Принудительная феминизация", value: "656" },
- { label: "Принудительное лечение", value: "971" },
- { label: "Принудительные отношения", value: "2302" },
- { label: "Принудительный брак", value: "307" },
- { label: "Принудительный инцест", value: "2942" },
- { label: "Принуждение", value: "1323" },
- { label: "Принятие себя", value: "2754" },
- { label: "Прислуга", value: "804" },
- { label: "Прист-кинк", value: "342" },
- { label: "Приступы агрессии", value: "2788" },
- { label: "Притча", value: "1088" },
- { label: "Приюты для животных", value: "2345" },
- { label: "ПРЛ", value: "1092" },
- { label: "Проблемы доверия", value: "2208" },
- { label: "Проблемы с законом", value: "1007" },
- { label: "Проводники душ", value: "2348" },
- { label: "Программисты", value: "574" },
- { label: "Прогрессорство", value: "449" },
- { label: "Прогулки", value: "2462" },
- { label: "Продажа души", value: "887" },
- { label: "Прозопагнозия", value: "2013" },
- { label: "Производственный роман", value: "2119" },
- { label: "Проклятия", value: "875" },
- { label: "Пролапс", value: "2926" },
- { label: "Промискуитет", value: "1817" },
- { label: "Промышленные предприятия", value: "1456" },
- { label: "Пропавшие без вести", value: "2073" },
- { label: "Пропущенная сцена", value: "1702" },
- { label: "Пророчества", value: "834" },
- { label: "Просмотр порно", value: "2341" },
- { label: "Проституция", value: "178" },
- { label: "Протезы", value: "1581" },
- { label: "Противоположности", value: "948" },
- { label: "Противоречивые чувства", value: "2528" },
- { label: "Прошлое", value: "983" },
- { label: "Прощение", value: "1545" },
- { label: "Псевдо-инцест", value: "336" },
- { label: "Псевдо-мистика", value: "2159" },
- { label: "Псевдоисторический сеттинг", value: "1479" },
- { label: "Псионика", value: "2023" },
- { label: "Психиатрические больницы", value: "135" },
- { label: "Психические расстройства", value: "69" },
- { label: "Психоз", value: "1339" },
- { label: "Психологи / Психоаналитики", value: "611" },
- { label: "Психологическая война", value: "2595" },
- { label: "Психологические пытки", value: "2825" },
- { label: "Психологические травмы", value: "40" },
- { label: "Психологический мазохизм", value: "2212" },
- { label: "Психологический ужас", value: "1261" },
- { label: "Психологическое насилие", value: "836" },
- { label: "Психология", value: "1674" },
- { label: "Психопатия", value: "869" },
- { label: "Психосоматические расстройства", value: "1834" },
- { label: "Психотерапия", value: "958" },
- { label: "ПТСР", value: "425" },
- { label: "Публичное обнажение", value: "319" },
- { label: "Пурпурная проза", value: "599" },
- { label: "Пустоши", value: "1114" },
- { label: "Пустыни", value: "692" },
- { label: "Путешественники-исследователи", value: "888" },
- { label: "Путешествия", value: "894" },
- { label: "Пытки", value: "210" },
- { label: "Пьеса", value: "434" },
- { label: "Рабочие", value: "1771" },
- { label: "Рабство", value: "51" },
- { label: "Равнодушие", value: "2516" },
- { label: "Равные отношения", value: "2728" },
- { label: "Радикальная медицина", value: "731" },
- { label: "Радио", value: "974" },
- { label: "Разбойники", value: "473" },
- { label: "Развитие отношений", value: "1404" },
- { label: "Развод", value: "200" },
- { label: "Разговоры", value: "1401" },
- { label: "Раздвоение личности", value: "287" },
- { label: "Раздельное обучение", value: "1959" },
- { label: "Разлука / Прощания", value: "1104" },
- { label: "Разница в возрасте", value: "2" },
- { label: "Разница культур", value: "1079" },
- { label: "Разновозрастная дружба", value: "2402" },
- { label: "Разнополая дружба", value: "806" },
- { label: "Разоблачения", value: "2684" },
- { label: "Разочарования", value: "646" },
- { label: "Разрушение стереотипов", value: "2805" },
- { label: "Разрушение четвертой стены", value: "381" },
- { label: "Разрыв связи", value: "2582" },
- { label: "Разум роя", value: "1459" },
- { label: "Разумное оружие", value: "2675" },
- { label: "Разумные животные", value: "895" },
- { label: "Разумные растения", value: "1037" },
- { label: "Раптофилия", value: "729" },
- { label: "Расизм", value: "433" },
- { label: "Раскрытие личностей", value: "2120" },
- { label: "Раскрытие магии", value: "1878" },
- { label: "Расплата", value: "2464" },
- { label: "Рассказ в рассказе", value: "2077" },
- { label: "Расставание", value: "506" },
- { label: "Расстройства аутистического спектра", value: "541" },
- { label: "Расстройства цветового восприятия", value: "1330" },
- { label: "Расстройства шизофренического спектра", value: "912" },
- { label: "Растаманы", value: "857" },
- { label: "Расширенная Вселенная ЗВ", value: "1950" },
- { label: "Реабилитационные центры", value: "1467" },
- { label: "Реактивное расстройство привязанности", value: "2576" },
- { label: "Реакции (стилизация)", value: "1283" },
- { label: "Реализм", value: "1201" },
- { label: "Реалити-шоу", value: "2312" },
- { label: "Ревность", value: "544" },
- { label: "Революции", value: "585" },
- { label: "Регенерация", value: "1530" },
- { label: "Регресс", value: "450" },
- { label: "Регрессия возраста", value: "102" },
- { label: "Редкие заболевания", value: "1856" },
- { label: "Реинкарнация", value: "101" },
- { label: "Рейтинг за лексику", value: "276" },
- { label: "Рейтинг за насилие и/или жестокость", value: "277" },
- { label: "Рейтинг за секс", value: "278" },
- { label: "Религиозная нетерпимость", value: "2451" },
- { label: "Религиозные войны", value: "2911" },
- { label: "Религиозные темы и мотивы", value: "198" },
- { label: "Религиозный фанатизм", value: "2548" },
- { label: "Ренессанс", value: "239" },
- { label: "Репетиторы", value: "2413" },
- { label: "Репетиции", value: "2241" },
- { label: "Репродуктивное насилие", value: "2310" },
- { label: "Реставраторы", value: "2239" },
- { label: "Рестораны", value: "412" },
- { label: "Ретеллинг", value: "52" },
- { label: "Ретрофутуризм", value: "727" },
- { label: "Реформация", value: "2199" },
- { label: "Речь Посполитая", value: "1529" },
- { label: "Риветхеды", value: "2904" },
- { label: "Римминг", value: "170" },
- { label: "Риск", value: "2467" },
- { label: "Рискованная беременность", value: "998" },
- { label: "Ритуалы", value: "749" },
- { label: "Ритуальные услуги", value: "2362" },
- { label: "Роботы", value: "513" },
- { label: "Родео", value: "1314" },
- { label: "Родители-одиночки", value: "325" },
- { label: "Родительские чувства", value: "2308" },
- { label: "Родомагия", value: "1899" },
- { label: "Роды", value: "991" },
- { label: "Рождество", value: "211" },
- { label: "Розыгрыши", value: "1807" },
- { label: "Рокеры", value: "861" },
- { label: "Роковая женщина / Роковой мужчина", value: "982" },
- { label: "Роковое усилие", value: "2604" },
- { label: "Роллер-дерби", value: "1014" },
- { label: "Романтизация", value: "1898" },
- { label: "Романтика", value: "1664" },
- { label: "Романтическая дружба", value: "2307" },
- { label: "Ромком", value: "2768" },
- { label: "Российская империя", value: "475" },
- { label: "Россия", value: "701" },
- { label: "РПП", value: "286" },
- { label: "Румыния", value: "862" },
- { label: "Русалки", value: "32" },
- { label: "Русальная неделя", value: "1067" },
- { label: "Русреал", value: "53" },
- { label: "Руферы", value: "578" },
- { label: "Рыбалка", value: "855" },
- { label: "Рыцари", value: "426" },
- { label: "Рыцарские турниры", value: "2759" },
- { label: "С чистого листа", value: "987" },
- { label: "Савойя", value: "1036" },
- { label: "Садизм / Мазохизм", value: "461" },
- { label: "Садовники", value: "1348" },
- { label: "Сайз-кинк", value: "100" },
- { label: "Самобытные культуры", value: "663" },
- { label: "Самовнушение", value: "2169" },
- { label: "Самовставка", value: "1689" },
- { label: "Самозванцы", value: "1811" },
- { label: "Самоистязание", value: "1386" },
- { label: "Самоопределение / Самопознание", value: "1278" },
- { label: "Самопожертвование", value: "750" },
- { label: "Самосуд", value: "1402" },
- { label: "Самоуничижение", value: "2667" },
- { label: "Самураи", value: "472" },
- { label: "Санатории", value: "223" },
- { label: "Сандалпанк", value: "1986" },
- { label: "Сарказм", value: "2225" },
- { label: "Сатира", value: "1944" },
- { label: "Сатиры", value: "264" },
- { label: "Сахарный диабет", value: "2609" },
- { label: "Сборник драбблов", value: "39" },
- { label: "Сборник лимериков", value: "1989" },
- { label: "Сборник пирожков", value: "743" },
- { label: "Сборник стихотворений", value: "600" },
- { label: "Сборник японской поэзии", value: "1351" },
- { label: "Свадьба", value: "184" },
- { label: "Сверхразумы", value: "966" },
- { label: "Сверхскорость", value: "1902" },
- { label: "Сверхспособности", value: "597" },
- { label: "Светлые властелины", value: "2596" },
- { label: "Светские мероприятия", value: "973" },
- { label: "Свидание вслепую", value: "741" },
- { label: "Свидания", value: "1235" },
- { label: "Свидетели", value: "1242" },
- { label: "Свингерство", value: "203" },
- { label: "Свобода", value: "2166" },
- { label: "Свободные отношения", value: "255" },
- { label: "Сводничество", value: "568" },
- { label: "Сводные родственники", value: "1445" },
- { label: "Святые", value: "393" },
- { label: "Сгенерировано ИИ", value: "3014" },
- { label: "СДВГ", value: "539" },
- { label: "Севвитус", value: "1871" },
- { label: "Северная Корея", value: "2767" },
- { label: "Северус Снейп жив", value: "2406" },
- { label: "Сегрегация", value: "2158" },
- { label: "Секретари", value: "1170" },
- { label: "Секретные миссии", value: "1829" },
- { label: "Секс без обязательств", value: "387" },
- { label: "Секс в воде", value: "718" },
- { label: "Секс в нетрезвом виде", value: "1110" },
- { label: "Секс в одежде", value: "1013" },
- { label: "Секс в публичных местах", value: "123" },
- { label: "Секс в транспорте", value: "124" },
- { label: "Секс в церкви", value: "2968" },
- { label: "Секс во время беременности", value: "279" },
- { label: "Секс во время болезни", value: "1365" },
- { label: "Секс во время менструации", value: "153" },
- { label: "Секс на камеру", value: "1101" },
- { label: "Секс на природе", value: "1256" },
- { label: "Секс перед зеркалом", value: "1255" },
- { label: "Секс по расчету", value: "1212" },
- { label: "Секс по телефону", value: "133" },
- { label: "Секс при посторонних", value: "2514" },
- { label: "Секс с воображаемыми партнерами", value: "2276" },
- { label: "Секс с использованием магии", value: "1563" },
- { label: "Секс с использованием одурманивающих веществ", value: "2635" },
- { label: "Секс с использованием посторонних предметов", value: "1661" },
- { label: "Секс с использованием сверхспособностей", value: "2610" },
- { label: "Секс со смертельным исходом", value: "1171" },
- { label: "Секс-игрушки", value: "176" },
- { label: "Секс-индустрия", value: "447" },
- { label: "Секс-клубы / Секс-вечеринки", value: "936" },
- { label: "Секс-куклы", value: "1202" },
- { label: "Секс-магия", value: "1131" },
- { label: "Секс-машины", value: "1112" },
- { label: "Секс-шопы", value: "739" },
- { label: "Сексизм", value: "464" },
- { label: "Сексомния", value: "2024" },
- { label: "Секстинг", value: "2215" },
- { label: "Сексуальная неопытность", value: "1717" },
- { label: "Сексуальное насилие", value: "2495" },
- { label: "Сексуальное обучение", value: "967" },
- { label: "Сексуальное рабство", value: "1353" },
- { label: "Сексуальные фобии", value: "1537" },
- { label: "Селфхарм", value: "76" },
- { label: "Селфцест", value: "1708" },
- { label: "Семейная сага", value: "920" },
- { label: "Семейные тайны", value: "779" },
- { label: "Семейный бизнес", value: "2338" },
- { label: "Семьи", value: "220" },
- { label: "Сенсорная депривация", value: "282" },
- { label: "Сенсорная перегрузка", value: "2351" },
- { label: "Сентиментальность", value: "2567" },
- { label: "Серая мораль", value: "839" },
- { label: "Серая мышь", value: "1250" },
- { label: "Серая реальность", value: "2278" },
- { label: "Серийные насильники", value: "1942" },
- { label: "Серийные убийцы", value: "193" },
- { label: "Серфинг", value: "764" },
- { label: "Сиамские близнецы", value: "1252" },
- { label: "Сибари", value: "131" },
- { label: "Сиблинги", value: "617" },
- { label: "Сидение на лице", value: "713" },
- { label: "Силкпанк", value: "1813" },
- { label: "Симбиоз", value: "849" },
- { label: "Символизм", value: "538" },
- { label: "Симфорофилия", value: "492" },
- { label: "Синдром восьмиклассника", value: "2032" },
- { label: "Синдром выжившего", value: "1100" },
- { label: "Синдром Дауна", value: "2106" },
- { label: "Синдром Котара", value: "2765" },
- { label: "Синдром Питера Пэна", value: "687" },
- { label: "Синдром Туретта", value: "946" },
- { label: "Синестезия", value: "960" },
- { label: "Сирены", value: "1830" },
- { label: "Сириус Блэк жив", value: "2617" },
- { label: "Сироты", value: "689" },
- { label: "Ситком", value: "2553" },
- { label: "Сказка", value: "288" },
- { label: "Скайпанк", value: "976" },
- { label: "Скандинавия", value: "781" },
- { label: "Скандинавская мифология", value: "2304" },
- { label: "Сквиртинг", value: "950" },
- { label: "Сквозное видение", value: "1280" },
- { label: "Скейтбординг", value: "1395" },
- { label: "Скелеты", value: "1766" },
- { label: "Скинхэды", value: "1757" },
- { label: "Скрытая беременность", value: "2580" },
- { label: "Скрытность", value: "2577" },
- { label: "Скрытые способности", value: "2579" },
- { label: "Скрытый Этаж", value: "2763" },
- { label: "Скульпторы", value: "2976" },
- { label: "Слатшейминг", value: "2910" },
- { label: "Следующее поколение", value: "698" },
- { label: "Слежка", value: "2102" },
- { label: "Слепота", value: "413" },
- { label: "Слияние", value: "2324" },
- { label: "Словакия", value: "2938" },
- { label: "Словения", value: "1788" },
- { label: "Сложные отношения", value: "326" },
- { label: "Слом личности", value: "623" },
- { label: "Слоуберн", value: "19" },
- { label: "Служебные животные", value: "1506" },
- { label: "Служебные отношения", value: "1347" },
- { label: "Служебный роман", value: "75" },
- { label: "Слухи / Сплетни", value: "2809" },
- { label: "Случайные убийства", value: "2673" },
- { label: "Случайный брак", value: "304" },
- { label: "Случайный поцелуй", value: "2852" },
- { label: "Случайный секс", value: "1275" },
- { label: "Смена имени", value: "2094" },
- { label: "Смена мировоззрения", value: "2865" },
- { label: "Смена сущности", value: "1707" },
- { label: "Смертельные заболевания", value: "1132" },
- { label: "Смерть антагониста", value: "2650" },
- { label: "Смерть всех персонажей", value: "2611" },
- { label: "Смерть второстепенных персонажей", value: "1713" },
- { label: "Смерть животных", value: "2210" },
- { label: "Смерть основных персонажей", value: "1647" },
- { label: "СМИ", value: "2656" },
- { label: "Смирение", value: "2272" },
- { label: "Смотрины", value: "1495" },
- { label: "Смутное время", value: "2002" },
- { label: "Снайперы", value: "1762" },
- { label: "Сновидения", value: "490" },
- { label: "Сноубординг", value: "2180" },
- { label: "Соблазнение / Ухаживания", value: "616" },
- { label: "Собственничество", value: "908" },
- { label: "Советпанк", value: "397" },
- { label: "Советский Союз", value: "468" },
- { label: "Совместная кровать", value: "1229" },
- { label: "Совместное купание", value: "1301" },
- { label: "Современное искусство", value: "1087" },
- { label: "Современность", value: "80" },
- { label: "Согласование с каноном", value: "1388" },
- { label: "Сожаления", value: "550" },
- { label: "Создание общества", value: "2643" },
- { label: "Созидание", value: "2590" },
- { label: "Сокровища", value: "893" },
- { label: "Сокрытие убийства", value: "2311" },
- { label: "Солянка из Сансов", value: "2515" },
- { label: "Сомелье / Бармены", value: "865" },
- { label: "Сомнамбулизм", value: "1394" },
- { label: "Сомнения", value: "1544" },
- { label: "Сомнофилия", value: "95" },
- { label: "Сонный паралич", value: "1203" },
- { label: "Соперничество", value: "671" },
- { label: "Сорванная свадьба", value: "2044" },
- { label: "Сострадание", value: "885" },
- { label: "Состязания", value: "910" },
- { label: "Состязания с участием животных", value: "1154" },
- { label: "Сотриголова — отец Хитоши Шинсо", value: "2877" },
- { label: "Соулмейты", value: "1696" },
- { label: "Соулмейты: Действия", value: "2575" },
- { label: "Соулмейты: Изменение восприятия", value: "1400" },
- { label: "Соулмейты: Контакт через кожу", value: "2608" },
- { label: "Соулмейты: Ментальная связь", value: "2841" },
- { label: "Соулмейты: Общая боль", value: "2583" },
- { label: "Соулмейты: Общие эмоции", value: "2637" },
- { label: "Соулмейты: Опознавательные фразы", value: "1399" },
- { label: "Соулмейты: Предметы", value: "2563" },
- { label: "Соулмейты: Предпочтения", value: "2521" },
- { label: "Соулмейты: Разноцветные глаза", value: "2461" },
- { label: "Соулмейты: Ранения", value: "2134" },
- { label: "Соулмейты: Сны", value: "2414" },
- { label: "Соулмейты: Тактильный контакт", value: "2190" },
- { label: "Соулмейты: Татуировки", value: "2711" },
- { label: "Соулмейты: Физические проявления", value: "2864" },
- { label: "Социальная фантастика", value: "591" },
- { label: "Социальные темы и мотивы", value: "1017" },
- { label: "Социальные эксперименты", value: "2756" },
- { label: "Социальный паразитизм", value: "2444" },
- { label: "Социофобия", value: "826" },
- { label: "Спарринги", value: "1575" },
- { label: "Спасатели", value: "392" },
- { label: "Спасение жизни", value: "1299" },
- { label: "Спасение мира", value: "812" },
- { label: "Спектрофилия", value: "2634" },
- { label: "Спецагенты", value: "401" },
- { label: "Спиритизм", value: "1478" },
- { label: "Сплошинг", value: "424" },
- { label: "Спонтанный секс", value: "2918" },
- { label: "Спорт", value: "15" },
- { label: "Спортзалы", value: "1359" },
- { label: "Сражения", value: "2868" },
- { label: "Средневековье", value: "238" },
- { label: "Ссоры / Конфликты", value: "645" },
- { label: "Стаи", value: "2884" },
- { label: "Сталкеры / Диггеры (субкультура)", value: "1029" },
- { label: "Сталкинг", value: "605" },
- { label: "Становление героя", value: "680" },
- { label: "Стёб", value: "1690" },
- { label: "Стереотипы", value: "809" },
- { label: "Стимпанк", value: "25" },
- { label: "Стимуляция руками", value: "225" },
- { label: "Стихи", value: "1692" },
- { label: "Стихийные бедствия", value: "1352" },
- { label: "Стихотворные вставки", value: "2404" },
- { label: "СтихоТворцы", value: "3015" },
- { label: "Стокгольмский синдром / Лимский синдром", value: "1217" },
- { label: "Столетняя война", value: "2243" },
- { label: "Сторонний рассказчик", value: "1383" },
- { label: "Стоунпанк", value: "1987" },
- { label: "Страдания", value: "2009" },
- { label: "Странногеддон", value: "1882" },
- { label: "Страны Балтии", value: "1031" },
- { label: "Страпоны", value: "380" },
- { label: "Страсть", value: "1955" },
- { label: "Страх перед родителями", value: "2332" },
- { label: "Стрельба из лука", value: "1791" },
- { label: "Стримеры / Ютуберы", value: "1473" },
- { label: "Стрип-клубы", value: "79" },
- { label: "Стрит-арт", value: "1012" },
- { label: "Строители", value: "1774" },
- { label: "Студенты", value: "274" },
- { label: "Студенты по обмену", value: "859" },
- { label: "Студенческие городки", value: "753" },
- { label: "Субкультуры", value: "1061" },
- { label: "Субординация", value: "1099" },
- { label: "Суд", value: "827" },
- { label: "Суккубы / Инкубы", value: "334" },
- { label: "Сумасшествие", value: "1239" },
- { label: "Сунагакуре", value: "2476" },
- { label: "Супергерои", value: "67" },
- { label: "Суперзлодеи", value: "1205" },
- { label: "Супермаркеты", value: "843" },
- { label: "Суррогатная беременность", value: "1427" },
- { label: "Сухой закон", value: "2100" },
- { label: "Сухой оргазм", value: "2818" },
- { label: "Сфера ИТ", value: "2534" },
- { label: "Сфинксы", value: "1349" },
- { label: "Сценарий (стилизация)", value: "323" },
- { label: "Счастливый финал", value: "3" },
- { label: "США", value: "640" },
- { label: "Съемочная площадка", value: "410" },
- { label: "Сын Тьмы", value: "2175" },
- { label: "Сэнгоку Джидай", value: "2380" },
- { label: "Сэнгоку Дзидай", value: "2834" },
- { label: "Сэцубун", value: "2969" },
- { label: "Сюрреализм / Фантасмагория", value: "872" },
- { label: "Т/И / Л/И", value: "167" },
- { label: "Таджикистан", value: "2974" },
- { label: "Таиланд", value: "1034" },
- { label: "Тайна происхождения", value: "662" },
- { label: "Тайная личность", value: "194" },
- { label: "Тайная сущность", value: "1512" },
- { label: "Тайны / Секреты", value: "906" },
- { label: "Тайные друзья (игра)", value: "2908" },
- { label: "Тайные организации", value: "572" },
- { label: "Тайные поклонники", value: "1374" },
- { label: "Тайный НапиСанта", value: "2972" },
- { label: "Таксисты", value: "2679" },
- { label: "Тактильный голод", value: "2197" },
- { label: "Тактильный контакт", value: "2875" },
- { label: "Танабата", value: "2340" },
- { label: "Танцы", value: "108" },
- { label: "Танцы на пилоне", value: "1370" },
- { label: "Таро", value: "642" },
- { label: "Тату-салоны", value: "324" },
- { label: "Татуировки", value: "327" },
- { label: "Твинцест", value: "1652" },
- { label: "Творческий кризис", value: "2107" },
- { label: "Театры", value: "195" },
- { label: "Телекинез", value: "951" },
- { label: "Телепатия", value: "127" },
- { label: "Телепортация", value: "1794" },
- { label: "Телесные жидкости", value: "1220" },
- { label: "Телесные наказания", value: "132" },
- { label: "Телесный хоррор", value: "212" },
- { label: "Телохранители", value: "400" },
- { label: "Темная сторона (Гарри Поттер)", value: "1937" },
- { label: "Темная сторона Силы", value: "1946" },
- { label: "Темная Эра (Bungou Stray Dogs)", value: "2494" },
- { label: "Темное прошлое", value: "2229" },
- { label: "Темное фэнтези", value: "1963" },
- { label: "Темные властелины", value: "1224" },
- { label: "Темные эльфы", value: "2597" },
- { label: "Темный романтизм", value: "2128" },
- { label: "Темы ментального здоровья", value: "2344" },
- { label: "Темы этики и морали", value: "1106" },
- { label: "Теннис", value: "1066" },
- { label: "Тентакли", value: "129" },
- { label: "Теория инверсии", value: "1980" },
- { label: "Теория Одурманивания", value: "2493" },
- { label: "Термокинез", value: "2793" },
- { label: "Террористы", value: "556" },
- { label: "Теслапанк", value: "1988" },
- { label: "Техники", value: "1272" },
- { label: "Техногенные катастрофы", value: "526" },
- { label: "Технокинез", value: "1271" },
- { label: "Технологии", value: "1232" },
- { label: "Технотриллер", value: "649" },
- { label: "Течка / Гон", value: "283" },
- { label: "Тим Дрейк — Джокер-младший", value: "2454" },
- { label: "Тим Дрейк — Кэтлэд", value: "2453" },
- { label: "Тихий секс", value: "1185" },
- { label: "Товарищи по несчастью", value: "2666" },
- { label: "Токсичные родственники", value: "2008" },
- { label: "Том Реддл — не Темный Лорд", value: "2394" },
- { label: "Томбои", value: "565" },
- { label: "Томгерлз", value: "848" },
- { label: "Торговля органами", value: "1358" },
- { label: "Торговцы", value: "2098" },
- { label: "Торговые центры", value: "1416" },
- { label: "Тоталитаризм", value: "1169" },
- { label: "Травники / Травницы", value: "1211" },
- { label: "Трагедия", value: "919" },
- { label: "Трагикомедия", value: "1454" },
- { label: "Традиции", value: "1463" },
- { label: "Трансгендерные персонажи", value: "175" },
- { label: "Трансплантация", value: "2364" },
- { label: "Трансфобия", value: "420" },
- { label: "Тревожное расстройство личности", value: "1914" },
- { label: "Тревожность", value: "1318" },
- { label: "Трейлеры", value: "785" },
- { label: "Тренировки / Обучение", value: "876" },
- { label: "Третий лишний", value: "1176" },
- { label: "Третья мировая", value: "624" },
- { label: "Три корейских государства", value: "2322" },
- { label: "Трикстеры", value: "1507" },
- { label: "Триллер", value: "169" },
- { label: "Трилогия Юникрона", value: "2378" },
- { label: "Трипофобия", value: "2342" },
- { label: "Трисам", value: "758" },
- { label: "Трихотилломания", value: "2185" },
- { label: "Тролли", value: "190" },
- { label: "Трудные отношения с родителями", value: "1490" },
- { label: "Трудный характер", value: "2123" },
- { label: "Трудоголизм", value: "1848" },
- { label: "Трущобы", value: "2822" },
- { label: "Туалетный юмор", value: "1247" },
- { label: "Туберкулез", value: "2163" },
- { label: "Турция", value: "794" },
- { label: "Тщеславие", value: "2578" },
- { label: "Тюрьмы / Темницы", value: "117" },
- { label: "Тяжелое детство", value: "2614" },
- { label: "Убийства", value: "621" },
- { label: "Убийственная пара", value: "1918" },
- { label: "Убийца поневоле", value: "2671" },
- { label: "Уважение", value: "2688" },
- { label: "Ужасы", value: "1679" },
- { label: "Узбекистан", value: "1293" },
- { label: "Уизлигады", value: "1862" },
- { label: "Украина", value: "716" },
- { label: "Укрытия", value: "199" },
- { label: "Уличные артисты", value: "2550" },
- { label: "Уличные гонки", value: "880" },
- { label: "Умбракинез", value: "2355" },
- { label: "Универсалы", value: "657" },
- { label: "Унижения", value: "1319" },
- { label: "Упоминания аддикций", value: "2848" },
- { label: "Упоминания алкоголя", value: "2415" },
- { label: "Упоминания беременности", value: "2057" },
- { label: "Упоминания войны", value: "2707" },
- { label: "Упоминания жестокости", value: "2447" },
- { label: "Упоминания зоофилии", value: "2620" },
- { label: "Упоминания измены", value: "2876" },
- { label: "Упоминания изнасилования", value: "521" },
- { label: "Упоминания инвалидности", value: "2705" },
- { label: "Упоминания инцеста", value: "2285" },
- { label: "Упоминания каннибализма", value: "2427" },
- { label: "Упоминания курения", value: "2450" },
- { label: "Упоминания мужской беременности", value: "2226" },
- { label: "Упоминания наркотиков", value: "144" },
- { label: "Упоминания насилия", value: "2207" },
- { label: "Упоминания нездоровых отношений", value: "2892" },
- { label: "Упоминания проституции", value: "2618" },
- { label: "Упоминания пыток", value: "2410" },
- { label: "Упоминания расизма", value: "2737" },
- { label: "Упоминания религии", value: "1048" },
- { label: "Упоминания самоубийства", value: "77" },
- { label: "Упоминания секса", value: "2747" },
- { label: "Упоминания селфхарма", value: "2105" },
- { label: "Упоминания смертей", value: "2081" },
- { label: "Упоминания смертей животных", value: "2211" },
- { label: "Упоминания телесного хоррора", value: "2466" },
- { label: "Упоминания терроризма", value: "774" },
- { label: "Упоминания убийств", value: "1501" },
- { label: "Управление оргазмом", value: "118" },
- { label: "Управление стихиями", value: "2091" },
- { label: "Уретральное проникновение", value: "1469" },
- { label: "Уро-кинк", value: "762" },
- { label: "Условное бессмертие", value: "2117" },
- { label: "Уся / Сянься", value: "2714" },
- { label: "Утопия", value: "350" },
- { label: "Утраченная тройка", value: "2535" },
- { label: "Утренний секс", value: "2882" },
- { label: "Уход за персонажами с инвалидностью", value: "2133" },
- { label: "Ухудшение отношений", value: "1219" },
- { label: "Учебные заведения", value: "1694" },
- { label: "Ученые", value: "402" },
- { label: "Уют", value: "2738" },
- { label: "Фавориты", value: "2135" },
- { label: "Фамильяры", value: "1045" },
- { label: "Фан-Бинго", value: "2957" },
- { label: "Фан-Фанты", value: "2953" },
- { label: "Фандомная аналитика", value: "742" },
- { label: "Фандомная Битва", value: "253" },
- { label: "Фансервис", value: "2483" },
- { label: "Фантастика", value: "1670" },
- { label: "Фастберн", value: "2016" },
- { label: "Фастфуд / Закусочные", value: "1025" },
- { label: "Феи", value: "191" },
- { label: "Фельчинг", value: "2368" },
- { label: "Фемдом", value: "54" },
- { label: "Феминистские темы и мотивы", value: "523" },
- { label: "Феминитивы", value: "390" },
- { label: "Фениксы", value: "1215" },
- { label: "Феодализм", value: "1504" },
- { label: "Фермы / Ранчо", value: "329" },
- { label: "Фестивали", value: "1006" },
- { label: "Фехтование", value: "1775" },
- { label: "Фиггинг", value: "1439" },
- { label: "Фигурное катание", value: "460" },
- { label: "Физиотерапия", value: "2222" },
- { label: "Физическая сверхсила", value: "2880" },
- { label: "Фикрайтеры / Фикридеры", value: "1284" },
- { label: "Фиксированная раскладка", value: "1344" },
- { label: "Фиктивные отношения", value: "308" },
- { label: "Фиктивный брак", value: "34" },
- { label: "Философия", value: "1675" },
- { label: "Финляндия", value: "1133" },
- { label: "Фистинг", value: "151" },
- { label: "Флафф", value: "1667" },
- { label: "Флирт", value: "349" },
- { label: "Флот", value: "846" },
- { label: "Фобии", value: "977" },
- { label: "Фольклор и предания", value: "1273" },
- { label: "Форнифилия", value: "580" },
- { label: "Фотографы", value: "348" },
- { label: "Фотокинез", value: "1805" },
- { label: "Франция", value: "691" },
- { label: "Фред Уизли жив", value: "2941" },
- { label: "Фроттаж", value: "96" },
- { label: "Фуд-плей", value: "509" },
- { label: "Фуд-фетиш", value: "2168" },
- { label: "Фурри", value: "996" },
- { label: "Фут-фетиш", value: "432" },
- { label: "Футбол", value: "458" },
- { label: "Фэйри", value: "2028" },
- { label: "Фэнтези", value: "1669" },
- { label: "Хакеры", value: "340" },
- { label: "Ханами", value: "1155" },
- { label: "Ханахаки", value: "45" },
- { label: "Ханжество", value: "882" },
- { label: "Характерная для канона жестокость", value: "896" },
- { label: "Харассмент", value: "477" },
- { label: "Хиерофилия", value: "2366" },
- { label: "Химеры", value: "816" },
- { label: "Химическое оружие", value: "1186" },
- { label: "Химэдэрэ / Оджидэрэ", value: "1363" },
- { label: "Хип-хоп (субкультура)", value: "1822" },
- { label: "Хиппи", value: "784" },
- { label: "Хиромантия", value: "2749" },
- { label: "Хирургическая коррекция пола", value: "1249" },
- { label: "Хирургические операции", value: "1845" },
- { label: "Хобби", value: "1161" },
- { label: "Хогсмид", value: "2388" },
- { label: "Хоккей", value: "828" },
- { label: "Холодная война", value: "2140" },
- { label: "Холодное оружие", value: "1187" },
- { label: "Хорватия", value: "1433" },
- { label: "Хороший плохой финал", value: "1266" },
- { label: "Хронические заболевания", value: "1267" },
- { label: "Хронокинез", value: "1447" },
- { label: "Хронофантастика", value: "56" },
- { label: "Хтонические существа", value: "504" },
- { label: "Художники", value: "140" },
- { label: "Хуманизация", value: "177" },
- { label: "Хэллоуин", value: "205" },
- { label: "Хюльдры", value: "1397" },
- { label: "Цветочные магазины", value: "164" },
- { label: "Целители", value: "1107" },
- { label: "Церкви", value: "533" },
- { label: "Цикличность", value: "1979" },
- { label: "Цирки", value: "259" },
- { label: "Цукими", value: "1798" },
- { label: "Цундэрэ", value: "1137" },
- { label: "Цыгане", value: "1091" },
- { label: "Чайлдфри", value: "592" },
- { label: "Чайные церемонии", value: "2416" },
- { label: "Частичный ООС", value: "1409" },
- { label: "Частные детективы", value: "427" },
- { label: "Черная археология", value: "2503" },
- { label: "Черная мораль", value: "2438" },
- { label: "Чернобыльская катастрофа", value: "775" },
- { label: "Черный юмор", value: "66" },
- { label: "Чехия", value: "1021" },
- { label: "Чиновники", value: "1991" },
- { label: "Чирлидинг", value: "1431" },
- { label: "Чистокровные AU (Гарри Поттер)", value: "1905" },
- { label: "Чосон", value: "571" },
- { label: "Чувство вины", value: "902" },
- { label: "Чумные доктора", value: "1125" },
- { label: "Чхусок", value: "2973" },
- { label: "Шаманы", value: "484" },
- { label: "Шантаж", value: "569" },
- { label: "Шармбатон", value: "2733" },
- { label: "Швейцария", value: "1022" },
- { label: "Шейпшифтеры", value: "29" },
- { label: "Шелки", value: "2431" },
- { label: "Шифры", value: "2232" },
- { label: "Школьная иерархия", value: "2787" },
- { label: "Школьники", value: "2566" },
- { label: "Школьные годы Тома Реддла", value: "1913" },
- { label: "Школьные ОтМетки", value: "3017" },
- { label: "Школьные поездки", value: "2481" },
- { label: "Школьный роман", value: "2440" },
- { label: "Шопинг", value: "864" },
- { label: "Шоу-бизнес", value: "17" },
- { label: "Шпионы", value: "148" },
- { label: "Шрамирование", value: "891" },
- { label: "Шрамы", value: "328" },
- { label: "Эвтаназия", value: "1102" },
- { label: "Эгоизм", value: "2071" },
- { label: "Эдвардианская эпоха", value: "2975" },
- { label: "Эзотерические темы и мотивы", value: "2801" },
- { label: "Эйблизм", value: "453" },
- { label: "Эйдетическая память", value: "975" },
- { label: "Эйфория", value: "2458" },
- { label: "Экзамены", value: "2591" },
- { label: "Экзистенциальный кризис", value: "1200" },
- { label: "Экзорцизм", value: "494" },
- { label: "Экологи / Биологи", value: "631" },
- { label: "Экологический кризис", value: "485" },
- { label: "Экономический кризис", value: "1547" },
- { label: "Эксаудиризм", value: "2151" },
- { label: "Эксгибиционизм", value: "489" },
- { label: "Эксперимент", value: "1686" },
- { label: "Экстрасенсы", value: "371" },
- { label: "Экшн", value: "1673" },
- { label: "Электрокинез", value: "1857" },
- { label: "Электростимуляция", value: "807" },
- { label: "Элементы ангста", value: "2696" },
- { label: "Элементы гета", value: "1714" },
- { label: "Элементы дарка", value: "2703" },
- { label: "Элементы детектива", value: "2698" },
- { label: "Элементы драмы", value: "2697" },
- { label: "Элементы других видов отношений", value: "454" },
- { label: "Элементы мистики", value: "1324" },
- { label: "Элементы психологии", value: "2824" },
- { label: "Элементы романтики", value: "2742" },
- { label: "Элементы слэша", value: "1715" },
- { label: "Элементы ужасов", value: "2721" },
- { label: "Элементы фемслэша", value: "1716" },
- { label: "Элементы флаффа", value: "2731" },
- { label: "Элементы юмора / Элементы стёба", value: "2011" },
- { label: "Эльфы", value: "44" },
- { label: "Эметофилия", value: "1434" },
- { label: "Эмо", value: "641" },
- { label: "Эмоциональная одержимость", value: "1270" },
- { label: "Эмпатия", value: "1177" },
- { label: "Энергетический вампиризм", value: "818" },
- { label: "Эпидемии", value: "619" },
- { label: "Эпизод 23.5", value: "2469" },
- { label: "Эпилепсия", value: "1511" },
- { label: "Эпилог? Какой эпилог?", value: "2651" },
- { label: "Эпоха Бакумацу", value: "1472" },
- { label: "Эпоха Мэйдзи", value: "1435" },
- { label: "Эпоха Тайсё", value: "2015" },
- { label: "Эрик Киллмонгер жив", value: "2897" },
- { label: "Эрогуро", value: "1731" },
- { label: "Эротическая дрессировка", value: "2026" },
- { label: "Эротическая лактация", value: "284" },
- { label: "Эротическая мумификация", value: "415" },
- { label: "Эротическая сверхстимуляция", value: "1245" },
- { label: "Эротические наказания", value: "125" },
- { label: "Эротические ролевые игры", value: "111" },
- { label: "Эротические сны", value: "128" },
- { label: "Эротические фантазии", value: "561" },
- { label: "Эротический массаж", value: "1518" },
- { label: "Эротический перенос", value: "744" },
- { label: "Эротомания", value: "2922" },
- { label: "Эскапизм", value: "1552" },
- { label: "Эскорты", value: "922" },
- { label: "Эстетика", value: "2021" },
- { label: "ЭТЕРНА", value: "2948" },
- { label: "Этнические анклавы", value: "2732" },
- { label: "Этническое фэнтези", value: "667" },
- { label: "Эффект бабочки", value: "1572" },
- { label: "Ювелиры", value: "2964" },
- { label: "Южная Америка", value: "832" },
- { label: "Южная готика", value: "1077" },
- { label: "Южная Корея", value: "674" },
- { label: "Юмор", value: "1666" },
- { label: "Юристы", value: "333" },
- { label: "Я никогда не... (игра)", value: "1436" },
- { label: "Явное согласие", value: "1569" },
- { label: "Ядерная война", value: "889" },
- { label: "Язык жестов", value: "2962" },
- { label: "Язык животных", value: "1327" },
- { label: "Язык растений", value: "2622" },
- { label: "Язык цветов", value: "272" },
- { label: "Ямадад", value: "2916" },
- { label: "Янгирэ", value: "1257" },
- { label: "Яндэрэ", value: "1136" },
- { label: "Яогуаи", value: "2347" },
- { label: "Япония", value: "665" },
- { label: "Японские фестивали", value: "2555" },
- { label: "Ящеролюди", value: "682" },
- { label: "Abuse/Comfort", value: "2599" },
- { label: "Aged down", value: "229" },
- { label: "Aged up", value: "4" },
- { label: "Artfic", value: "68" },
- { label: "AU", value: "1683" },
- { label: "AU: Альтернативные способности", value: "2086" },
- { label: "AU: Без апокалипсиса", value: "2051" },
- { label: "AU: Без войны", value: "2305" },
- { label: "AU: Без магии", value: "1052" },
- { label: "AU: Без мистики", value: "2489" },
- { label: "AU: Без сверхспособностей", value: "1053" },
- { label: "AU: Без супергероев", value: "1152" },
- { label: "AU: Все гражданские", value: "2797" },
- { label: "AU: Все друзья", value: "2552" },
- { label: "AU: Все люди", value: "1151" },
- { label: "AU: Все хорошо", value: "2124" },
- { label: "AU: Другая страна", value: "2165" },
- { label: "AU: Другая эпоха", value: "2452" },
- { label: "AU: Другое детство", value: "2360" },
- { label: "AU: Другое знакомство", value: "2217" },
- { label: "AU: Другое семейное положение", value: "2902" },
- { label: "AU: Не родственники", value: "2167" },
- { label: "AU: Профессиональные герои (BNHA)", value: "2924" },
- { label: "AU: Родственники", value: "2164" },
- { label: "AU: Школа", value: "2532" },
- { label: "AU: Age swap", value: "917" },
- { label: "AU: Kitty Gang", value: "2928" },
- { label: "AU: Race swap", value: "933" },
- { label: "AU: Reverse", value: "1156" },
- { label: "AU: Role swap", value: "1054" },
- { label: "Authors Time", value: "2959" },
- { label: "BDSM", value: "1646" },
- { label: "BDSM-вселенная", value: "1078" },
- { label: "BDSM: Домспейс", value: "1444" },
- { label: "BDSM: Дроп", value: "1411" },
- { label: "BDSM: Сабспейс", value: "1410" },
- { label: "BDSM: Aftercare", value: "1523" },
- { label: "BEAST (Bungou Stray Dogs)", value: "2457" },
- { label: "Blackwatch", value: "2116" },
- { label: "Body inflation", value: "389" },
- { label: "Character study", value: "363" },
- { label: "Cockwarming", value: "318" },
- { label: "Dark academia", value: "2430" },
- { label: "DDLG / DDLB / MDLG / MDLB", value: "1033" },
- { label: "Dirty talk", value: "139" },
- { label: "Doggy style", value: "1361" },
- { label: "Dollification", value: "2780" },
- { label: "Dramione Authors Tournament", value: "2950" },
- { label: "EIQ", value: "271" },
- { label: "ER", value: "1687" },
- { label: "Final Haikyuu Quest", value: "2652" },
- { label: "Fix-it", value: "1" },
- { label: "Frenemies", value: "666" },
- { label: "Gangbang", value: "315" },
- { label: "Glory hole", value: "2188" },
- { label: "Golden Age Overwatch", value: "2112" },
- { label: "GOLockdown", value: "2391" },
- { label: "Gun play", value: "252" },
- { label: "Hurt/Comfort", value: "1682" },
- { label: "Hydra!AU", value: "1931" },
- { label: "Ironqrow week", value: "2209" },
- { label: "Kimetsu Gakuen", value: "2574" },
- { label: "Knife play", value: "152" },
- { label: "KPOP-AUFEST", value: "1851" },
- { label: "LARP", value: "1510" },
- { label: "LOVE ОтМетки", value: "2981" },
- { label: "Maleval week", value: "2382" },
- { label: "Marvel ГФИ", value: "2896" },
- { label: "Mate or die", value: "375" },
- { label: "Mirror!verse (Звездный путь)", value: "2899" },
- { label: "Moresome", value: "759" },
- { label: "N раз", value: "263" },
- { label: "Omnic Crisis Era", value: "2111" },
- { label: "ORIGINAL'S 2021", value: "2939" },
- { label: "Parentlock", value: "2053" },
- { label: "Patronus of Dramione", value: "2958" },
- { label: "Post-Fall of Overwatch", value: "2114" },
- { label: "Post-Recall", value: "2115" },
- { label: "PWP", value: "1680" },
- { label: "Rape/Revenge", value: "2195" },
- { label: "Reverse Falls", value: "1879" },
- { label: "RofR ДраМиВояж", value: "2954" },
- { label: "RST", value: "815" },
- { label: "RTFM", value: "2327" },
- { label: "Service top / Power bottom", value: "563" },
- { label: "Shingeki no Kyojin High School AU", value: "2037" },
- { label: "Shingeki! Kyojin Chuugakkou", value: "2038" },
- { label: "Sickfic", value: "422" },
- { label: "Songfic", value: "1684" },
- { label: "Spider-son & Iron-dad", value: "1885" },
- { label: "Sugar daddy", value: "106" },
- { label: "Sugar mommy", value: "160" },
- { label: "Superfamily (Мстители)", value: "2623" },
- { label: "Superior Iron Man", value: "2676" },
- { label: "Talon (Overwatch)", value: "2110" },
- { label: "The Big Four / The Super Six", value: "1954" },
- { label: "Trench AU", value: "2387" },
- { label: "TYL", value: "1933" },
- { label: "Underage", value: "1658" },
- { label: "URT", value: "2761" },
- { label: "UST", value: "1709" },
- { label: "Versefic", value: "2729" },
- { label: "Videofic", value: "2480" },
- { label: "Womance", value: "265" },
- { label: "X век", value: "240" },
- { label: "XI век", value: "241" },
- { label: "XII век", value: "242" },
- { label: "XIII век", value: "243" },
- { label: "XIV век", value: "244" },
- { label: "XIX век", value: "249" },
- { label: "XV век", value: "245" },
- { label: "XVI век", value: "246" },
- { label: "XVII век", value: "247" },
- { label: "XVIII век", value: "248" },
- { label: "XX век", value: "1004" },
- ],
- inputType: filterInputs_1.FilterInputs.Picker,
- },
-];
-exports.fetchImage = fetch_1.fetchFile;
diff --git a/js/plugins/russian/jaomix.js b/js/plugins/russian/jaomix.js
deleted file mode 100644
index dcb05fc..0000000
--- a/js/plugins/russian/jaomix.js
+++ /dev/null
@@ -1,299 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.fetchImage = exports.filters = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.icon = exports.version = exports.site = exports.name = exports.id = void 0;
-const filterInputs_1 = require("@libs/filterInputs");
-const fetch_1 = require("@libs/fetch");
-const novelStatus_1 = require("@libs/novelStatus");
-const cheerio_1 = require("cheerio");
-exports.id = "jaomix.ru";
-exports.name = "Jaomix";
-exports.site = "https://jaomix.ru";
-exports.version = "1.0.0";
-exports.icon = "src/ru/jaomix/icon.png";
-const popularNovels = function (page, { showLatestNovels, filters }) {
- return __awaiter(this, void 0, void 0, function* () {
- let url = exports.site + "/?searchrn";
- if ((filters === null || filters === void 0 ? void 0 : filters.lang) instanceof Array) {
- url += filters.lang.map((lang, idx) => `&lang[${idx}]=${lang}`).join("");
- }
- if ((filters === null || filters === void 0 ? void 0 : filters.genre) instanceof Array) {
- url += filters.genre.map((genre, idx) => `&genre[${idx}]=${genre}`).join("");
- }
- if ((filters === null || filters === void 0 ? void 0 : filters.delgenre) instanceof Array) {
- url += filters.delgenre.map((genre, idx) => `&delgenre[${idx}]=del ${genre}`).join("");
- }
- url += "&sortcountchapt=" + ((filters === null || filters === void 0 ? void 0 : filters.sortcountchapt) || "1");
- url += "&sortdaycreate=" + ((filters === null || filters === void 0 ? void 0 : filters.sortdaycreate) || "1");
- url += "&sortby=" + (showLatestNovels ? "upd" : (filters === null || filters === void 0 ? void 0 : filters.sortby) || "topweek");
- url += "&gpage=" + page;
- const result = yield (0, fetch_1.fetchApi)(url);
- let body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio('div[class="block-home"] > div[class="one"]').each(function () {
- var _a;
- const name = loadedCheerio(this)
- .find('div[class="img-home"] > a')
- .attr("title");
- const cover = (_a = loadedCheerio(this)
- .find('div[class="img-home"] > a > img')
- .attr("src")) === null || _a === void 0 ? void 0 : _a.replace("-150x150", "");
- const url = loadedCheerio(this)
- .find('div[class="img-home"] > a')
- .attr("href");
- if (!name || !url)
- return;
- novels.push({ name, cover, url });
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const result = yield (0, fetch_1.fetchApi)(novelUrl);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- let novel = {
- url: novelUrl,
- };
- novel.name = loadedCheerio('div[class="desc-book"] > h1').text().trim();
- novel.cover = loadedCheerio('div[class="img-book"] > img').attr("src");
- novel.summary = loadedCheerio('div[id="desc-tab"]').text().trim();
- loadedCheerio("#info-book > p").each(function () {
- let text = loadedCheerio(this).text().replace(/,/g, "").split(" ");
- if (text[0] === "Автор:") {
- novel.author = text.splice(1).join(" ");
- }
- else if (text[0] === "Жанры:") {
- novel.genres = text.splice(1).join(",");
- }
- else if (text[0] === "Статус:") {
- novel.status = text.includes("продолжается")
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- }
- });
- const chapters = [];
- loadedCheerio(".download-chapter div.title").each(function () {
- const name = loadedCheerio(this).find("a").attr("title");
- const releaseTime = loadedCheerio(this).find("time").text();
- const url = loadedCheerio(this).find("a").attr("href");
- if (!name || !url)
- return;
- chapters.push({ name, releaseTime, url });
- });
- novel.chapters = chapters.reverse();
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const result = yield (0, fetch_1.fetchApi)(chapterUrl);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('div[class="adblock-service"]').remove();
- const chapterText = loadedCheerio('div[class="entry-content"]').html();
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = `${exports.site}/?searchrn=${searchTerm}&but=Поиск по названию&sortby=upd`;
- const result = yield (0, fetch_1.fetchApi)(url);
- let body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio('div[class="block-home"] > div[class="one"]').each(function () {
- var _a;
- const name = loadedCheerio(this)
- .find('div[class="img-home"] > a')
- .attr("title");
- const cover = (_a = loadedCheerio(this)
- .find('div[class="img-home"] > a > img')
- .attr("src")) === null || _a === void 0 ? void 0 : _a.replace("-150x150", "");
- const url = loadedCheerio(this)
- .find('div[class="img-home"] > a')
- .attr("href");
- if (!name || !url)
- return;
- novels.push({ name, cover, url });
- });
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-exports.filters = [
- {
- key: "sortby",
- label: "Сортировка:",
- values: [
- { label: "Топ недели", value: "topweek" },
- { label: "По алфавиту", value: "alphabet" },
- { label: "По дате обновления", value: "upd" },
- { label: "По дате создания", value: "new" },
- { label: "По просмотрам", value: "count" },
- { label: "Топ года", value: "topyear" },
- { label: "Топ дня", value: "topday" },
- { label: "Топ за все время", value: "alltime" },
- { label: "Топ месяца", value: "topmonth" },
- ],
- inputType: filterInputs_1.FilterInputs.Picker,
- },
- {
- key: "sortdaycreate",
- label: "Дата добавления:",
- values: [
- { label: "Любое", value: "1" },
- { label: "От 120 до 180 дней", value: "1218" },
- { label: "От 180 до 365 дней", value: "1836" },
- { label: "От 30 до 60 дней", value: "3060" },
- { label: "От 365 дней", value: "365" },
- { label: "От 60 до 90 дней", value: "6090" },
- { label: "От 90 до 120 дней", value: "9012" },
- { label: "Послед. 30 дней", value: "30" },
- ],
- inputType: filterInputs_1.FilterInputs.Picker,
- },
- {
- key: "sortcountchapt",
- label: "Количество глав:",
- values: [
- { label: "Любое кол-во глав", value: "1" },
- { label: "До 500", value: "500" },
- { label: "От 1000 до 2000", value: "1020" },
- { label: "От 2000 до 3000", value: "2030" },
- { label: "От 3000 до 4000", value: "3040" },
- { label: "От 4000", value: "400" },
- { label: "От 500 до 1000", value: "510" },
- ],
- inputType: filterInputs_1.FilterInputs.Picker,
- },
- {
- key: "genre",
- label: "Жанры:",
- values: [
- { label: "Боевые Искусства", value: "Боевые Искусства" },
- { label: "Виртуальный Мир", value: "Виртуальный Мир" },
- { label: "Гарем", value: "Гарем" },
- { label: "Детектив", value: "Детектив" },
- { label: "Драма", value: "Драма" },
- { label: "Игра", value: "Игра" },
- { label: "Истории из жизни", value: "Истории из жизни" },
- { label: "Исторический", value: "Исторический" },
- { label: "История", value: "История" },
- { label: "Исэкай", value: "Исэкай" },
- { label: "Комедия", value: "Комедия" },
- { label: "Меха", value: "Меха" },
- { label: "Мистика", value: "Мистика" },
- { label: "Научная Фантастика", value: "Научная Фантастика" },
- { label: "Повседневность", value: "Повседневность" },
- { label: "Постапокалипсис", value: "Постапокалипсис" },
- { label: "Приключения", value: "Приключения" },
- { label: "Психология", value: "Психология" },
- { label: "Романтика", value: "Романтика" },
- { label: "Сверхъестественное", value: "Сверхъестественное" },
- { label: "Сёнэн", value: "Сёнэн" },
- { label: "Сёнэн-ай", value: "Сёнэн-ай" },
- { label: "Спорт", value: "Спорт" },
- { label: "Сэйнэн", value: "Сэйнэн" },
- { label: "Сюаньхуа", value: "Сюаньхуа" },
- { label: "Трагедия", value: "Трагедия" },
- { label: "Триллер", value: "Триллер" },
- { label: "Фантастика", value: "Фантастика" },
- { label: "Фэнтези", value: "Фэнтези" },
- { label: "Хоррор", value: "Хоррор" },
- { label: "Школьная жизнь", value: "Школьная жизнь" },
- { label: "Шоунен", value: "Шоунен" },
- { label: "Экшн", value: "Экшн" },
- { label: "Этти", value: "Этти" },
- { label: "Юри", value: "Юри" },
- { label: "Adult", value: "Adult" },
- { label: "Ecchi", value: "Ecchi" },
- { label: "Josei", value: "Josei" },
- { label: "Lolicon", value: "Lolicon" },
- { label: "Mature", value: "Mature" },
- { label: "Shoujo", value: "Shoujo" },
- { label: "Wuxia", value: "Wuxia" },
- { label: "Xianxia", value: "Xianxia" },
- { label: "Xuanhuan", value: "Xuanhuan" },
- { label: "Yaoi", value: "Yaoi" },
- ],
- inputType: filterInputs_1.FilterInputs.Checkbox,
- },
- {
- key: "delgenre",
- label: "Исключить жанры:",
- values: [
- { label: "Боевые Искусства", value: "Боевые Искусства" },
- { label: "Виртуальный Мир", value: "Виртуальный Мир" },
- { label: "Гарем", value: "Гарем" },
- { label: "Детектив", value: "Детектив" },
- { label: "Драма", value: "Драма" },
- { label: "Игра", value: "Игра" },
- { label: "Истории из жизни", value: "Истории из жизни" },
- { label: "Исторический", value: "Исторический" },
- { label: "История", value: "История" },
- { label: "Исэкай", value: "Исэкай" },
- { label: "Комедия", value: "Комедия" },
- { label: "Меха", value: "Меха" },
- { label: "Мистика", value: "Мистика" },
- { label: "Научная Фантастика", value: "Научная Фантастика" },
- { label: "Повседневность", value: "Повседневность" },
- { label: "Постапокалипсис", value: "Постапокалипсис" },
- { label: "Приключения", value: "Приключения" },
- { label: "Психология", value: "Психология" },
- { label: "Романтика", value: "Романтика" },
- { label: "Сверхъестественное", value: "Сверхъестественное" },
- { label: "Сёнэн", value: "Сёнэн" },
- { label: "Сёнэн-ай", value: "Сёнэн-ай" },
- { label: "Спорт", value: "Спорт" },
- { label: "Сэйнэн", value: "Сэйнэн" },
- { label: "Сюаньхуа", value: "Сюаньхуа" },
- { label: "Трагедия", value: "Трагедия" },
- { label: "Триллер", value: "Триллер" },
- { label: "Фантастика", value: "Фантастика" },
- { label: "Фэнтези", value: "Фэнтези" },
- { label: "Хоррор", value: "Хоррор" },
- { label: "Школьная жизнь", value: "Школьная жизнь" },
- { label: "Шоунен", value: "Шоунен" },
- { label: "Экшн", value: "Экшн" },
- { label: "Этти", value: "Этти" },
- { label: "Юри", value: "Юри" },
- { label: "Adult", value: "Adult" },
- { label: "Ecchi", value: "Ecchi" },
- { label: "Josei", value: "Josei" },
- { label: "Lolicon", value: "Lolicon" },
- { label: "Mature", value: "Mature" },
- { label: "Shoujo", value: "Shoujo" },
- { label: "Wuxia", value: "Wuxia" },
- { label: "Xianxia", value: "Xianxia" },
- { label: "Xuanhuan", value: "Xuanhuan" },
- { label: "Yaoi", value: "Yaoi" },
- ],
- inputType: filterInputs_1.FilterInputs.Checkbox,
- },
- {
- key: "lang",
- label: "Выбрать языки:",
- values: [
- { label: "Английский", value: "Английский" },
- { label: "Китайский", value: "Китайский" },
- { label: "Корейский", value: "Корейский" },
- { label: "Японский", value: "Японский" },
- ],
- inputType: filterInputs_1.FilterInputs.Checkbox,
- },
-];
-exports.fetchImage = fetch_1.fetchFile;
diff --git a/js/plugins/russian/novelTL.js b/js/plugins/russian/novelTL.js
deleted file mode 100644
index 86e4d28..0000000
--- a/js/plugins/russian/novelTL.js
+++ /dev/null
@@ -1,855 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.icon = exports.version = exports.site = exports.name = exports.id = void 0;
-const filterInputs_1 = require("@libs/filterInputs");
-const defaultCover_1 = require("@libs/defaultCover");
-const fetch_1 = require("@libs/fetch");
-const novelStatus_1 = require("@libs/novelStatus");
-const cheerio_1 = require("cheerio");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "TL";
-exports.name = "NovelTL";
-exports.site = "https://novel.tl";
-exports.version = "1.0.0";
-exports.icon = "src/ru/noveltl/icon.png";
-const popularNovels = (page, { filters }) => __awaiter(void 0, void 0, void 0, function* () {
- var _a, _b, _c;
- const result = yield (0, fetch_1.fetchApi)(exports.site + "/api/site/v2/graphql", {
- method: "post",
- headers: {
- Accept: "application/json, text/plain, */*",
- "Accept-Language": "ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3",
- "Content-Type": "application/json",
- },
- referrer: exports.site,
- body: JSON.stringify({
- operationName: "Projects",
- query: "query Projects($hostname:String! $filter:SearchFilter $page:Int $limit:Int){projects(section:{fullUrl:$hostname}filter:$filter page:{pageSize:$limit,pageNumber:$page}){content{title fullUrl covers{url}}}}",
- variables: {
- filter: {
- tags: (filters === null || filters === void 0 ? void 0 : filters.tags) || [],
- genres: (filters === null || filters === void 0 ? void 0 : filters.genres) || [],
- },
- hostname: "novel.tl",
- limit: 40,
- page,
- },
- }),
- });
- const json = (yield result.json());
- let novels = [];
- (_c = (_b = (_a = json.data) === null || _a === void 0 ? void 0 : _a.projects) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.forEach((novel) => {
- var _a, _b;
- return novels.push({
- name: novel.title,
- url: "https://" + novel.fullUrl,
- cover: ((_b = (_a = novel === null || novel === void 0 ? void 0 : novel.covers) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.url)
- ? exports.site + novel.covers[0].url
- : defaultCover_1.defaultCover,
- });
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- var _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
- const result = yield (0, fetch_1.fetchApi)(exports.site + "/api/site/v2/graphql", {
- method: "post",
- headers: {
- Accept: "application/json, text/plain, */*",
- "Accept-Language": "ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3",
- "Content-Type": "application/json",
- },
- referrer: exports.site,
- body: JSON.stringify({
- operationName: "Book",
- query: 'query Book($url:String){project(project:{fullUrl:$url}){title translationStatus fullUrl covers{url}persons(langs:["ru","en","*"],roles:["author","illustrator"]){role name{firstName lastName}}genres{nameRu nameEng}tags{nameRu nameEng}annotation{text}subprojects{content{title volumes{content{shortName chapters{title publishDate fullUrl published}}}}}}}',
- variables: {
- url: novelUrl,
- },
- }),
- });
- const json = (yield result.json());
- let novel = {
- url: novelUrl,
- name: (_d = json.data.project) === null || _d === void 0 ? void 0 : _d.title,
- cover: ((_g = (_f = (_e = json.data.project) === null || _e === void 0 ? void 0 : _e.covers) === null || _f === void 0 ? void 0 : _f[0]) === null || _g === void 0 ? void 0 : _g.url)
- ? exports.site + json.data.project.covers[0].url
- : defaultCover_1.defaultCover,
- summary: (_j = (_h = json.data.project) === null || _h === void 0 ? void 0 : _h.annotation) === null || _j === void 0 ? void 0 : _j.text,
- status: ((_k = json.data.project) === null || _k === void 0 ? void 0 : _k.translationStatus) === "active"
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed,
- };
- let genres = [(_l = json.data.project) === null || _l === void 0 ? void 0 : _l.tags, (_m = json.data.project) === null || _m === void 0 ? void 0 : _m.genres]
- .flat()
- .map((item) => (item === null || item === void 0 ? void 0 : item.nameRu) || (item === null || item === void 0 ? void 0 : item.nameEng))
- .filter((item) => item);
- if (genres === null || genres === void 0 ? void 0 : genres.length) {
- novel.genres = genres.join(", ");
- }
- (_p = (_o = json.data.project) === null || _o === void 0 ? void 0 : _o.persons) === null || _p === void 0 ? void 0 : _p.forEach((person) => {
- var _a;
- if (person.role == "author" && person.name.firstName) {
- novel.author =
- person.name.firstName + " " + (((_a = person.name) === null || _a === void 0 ? void 0 : _a.lastName) || "");
- }
- });
- let novelChapters = [];
- (_s = (_r = (_q = json.data.project) === null || _q === void 0 ? void 0 : _q.subprojects) === null || _r === void 0 ? void 0 : _r.content) === null || _s === void 0 ? void 0 : _s.forEach((work) => work.volumes.content.forEach((volume) => volume.chapters.forEach((chapter) => (chapter === null || chapter === void 0 ? void 0 : chapter.published) &&
- novelChapters.push({
- name: volume.shortName + " " + chapter.title,
- url: "https://" + chapter.fullUrl,
- releaseTime: (0, dayjs_1.default)(chapter.publishDate).format("LLL"),
- }))));
- novel.chapters = novelChapters;
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- var _t, _u;
- const result = yield (0, fetch_1.fetchApi)(exports.site + "/api/site/v2/graphql", {
- method: "post",
- headers: {
- Accept: "application/json, text/plain, */*",
- "Accept-Language": "ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3",
- "Content-Type": "application/json",
- },
- referrer: exports.site,
- body: JSON.stringify({
- query: "query($url:String){chapter(chapter:{fullUrl:$url}){text{text}}}",
- variables: {
- url: chapterUrl,
- },
- }),
- });
- const json = (yield result.json());
- const loadedCheerio = (0, cheerio_1.load)(((_u = (_t = json.data.chapter) === null || _t === void 0 ? void 0 : _t.text) === null || _u === void 0 ? void 0 : _u.text) || "");
- loadedCheerio("p > a[href]").each(function () {
- let url = exports.site + loadedCheerio(this).attr("href");
- if (!url.startsWith("http")) {
- url = exports.site + url;
- }
- loadedCheerio(this).find("picture").remove();
- loadedCheerio(this).removeAttr("href");
- loadedCheerio(`
`).appendTo(this);
- });
- const chapterText = loadedCheerio.html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- var _v, _w, _x;
- const result = yield (0, fetch_1.fetchApi)(exports.site + "/api/site/v2/graphql", {
- method: "post",
- headers: {
- Accept: "application/json, text/plain, */*",
- "Accept-Language": "ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3",
- "Content-Type": "application/json",
- },
- referrer: exports.site,
- body: JSON.stringify({
- operationName: "Projects",
- query: "query Projects($hostname:String! $filter:SearchFilter $page:Int $limit:Int){projects(section:{fullUrl:$hostname}filter:$filter page:{pageSize:$limit,pageNumber:$page}){content{title fullUrl covers{url}}}}",
- variables: {
- filter: {
- query: searchTerm,
- },
- hostname: "novel.tl",
- limit: 40,
- page: 1,
- },
- }),
- });
- const json = (yield result.json());
- let novels = [];
- (_x = (_w = (_v = json === null || json === void 0 ? void 0 : json.data) === null || _v === void 0 ? void 0 : _v.projects) === null || _w === void 0 ? void 0 : _w.content) === null || _x === void 0 ? void 0 : _x.forEach((novel) => {
- var _a, _b;
- return novels.push({
- name: novel.title,
- url: "https://" + novel.fullUrl,
- cover: ((_b = (_a = novel === null || novel === void 0 ? void 0 : novel.covers) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.url)
- ? exports.site + novel.covers[0].url
- : defaultCover_1.defaultCover,
- });
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-exports.fetchImage = fetch_1.fetchFile;
-exports.filters = [
- {
- key: "tags",
- label: "Тэги",
- values: [
- { label: "Автоматы", value: 64 },
- { label: "Агрессивные персонажи", value: 26 },
- { label: "Ад", value: 338 },
- { label: "Адаптация манги", value: 8 },
- { label: "Академия", value: 5 },
- { label: "Актёрское искусство", value: 7 },
- { label: "Актеры озвучки", value: 746 },
- { label: "Алхимия", value: 27 },
- { label: "Альтернативная реальность", value: 30 },
- { label: "Амнезия", value: 31 },
- { label: "Анабиоз", value: 170 },
- { label: "Анал", value: 33 },
- { label: "Ангелы", value: 38 },
- { label: "Андроиды", value: 37 },
- { label: "Анти-рост персонажа", value: 25 },
- { label: "Антигерой", value: 43 },
- { label: "Антикварный магазин", value: 44 },
- { label: "Антимагия", value: 41 },
- { label: "Антиутопия", value: 225 },
- { label: "Апатичный главный герой", value: 46 },
- { label: "Апокалипсис", value: 47 },
- { label: "Аристократия", value: 51 },
- { label: "Армия", value: 53 },
- { label: "Артефакты", value: 58 },
- { label: "Асоциальный главный герой", value: 42 },
- { label: "Ассасины", value: 61 },
- { label: "Атмосфера Европы", value: 245 },
- { label: "Банды", value: 302 },
- { label: "БДСМ", value: 77 },
- { label: "Бедный главный герой", value: 541 },
- { label: "Бездушный главный герой", value: 143 },
- { label: "Беззаботный герой", value: 115 },
- { label: "Безответная любовь", value: 213 },
- { label: "Безответная любовь", value: 740 },
- { label: "Безработные", value: 377 },
- { label: "Беременность", value: 551 },
- { label: "Бескорыстная любовь", value: 733 },
- { label: "Бессмертные", value: 359 },
- { label: "Бесстрашный главный герой", value: 274 },
- { label: "Библиотека", value: 393 },
- { label: "Биография", value: 86 },
- { label: "Близнецы", value: 729 },
- { label: "Богачи", value: 753 },
- { label: "Боги", value: 318 },
- { label: "Богини", value: 316 },
- { label: "Богоподобный протагонист", value: 314 },
- { label: "Боевая академия", value: 75 },
- { label: "Боевая парочка", value: 547 },
- { label: "Божественная защита", value: 208 },
- { label: "Божественная сила", value: 317 },
- { label: "Болеющие персонажи", value: 648 },
- { label: "Борьба за власть", value: 548 },
- { label: "Брак по расчету", value: 55 },
- { label: "Братство", value: 106 },
- { label: "Братья или сёстры", value: 646 },
- { label: "Брошенные дети", value: 1 },
- { label: "Бывший герой", value: 290 },
- { label: "Вампиры", value: 742 },
- { label: "Ваншот", value: 496 },
- { label: "Вдали от родителей", value: 3 },
- { label: "Ведьмы", value: 756 },
- { label: "Везучий главный герой", value: 411 },
- { label: "Верные подданные", value: 410 },
- { label: "Вероломные герои/плетение интриг", value: 424 },
- { label: "Взросление персонажа", value: 24 },
- { label: "Видит то, чего остальной люд не в силах", value: 617 },
- { label: "Виртуальная реальность", value: 744 },
- { label: "Владелец магазина", value: 677 },
- { label: "Владелец уникального оружия", value: 736 },
- { label: "Властные персонажи", value: 545 },
- { label: "Влияние прошлого", value: 517 },
- { label: "Внезапное обогащение", value: 691 },
- { label: "Внезапное обретение силы", value: 690 },
- { label: "Военные хроники", value: 749 },
- { label: "Возвращение в родной мир", value: 587 },
- { label: "Война", value: 750 },
- { label: "Вокалоид", value: 745 },
- { label: "Волшебные твари", value: 413 },
- { label: "Воскрешение", value: 586 },
- { label: "Воспитанный главный герой", value: 537 },
- { label: "Воспоминания прошлого", value: 283 },
- { label: "Враги становятся союзниками", value: 238 },
- { label: "Врата в иной мир", value: 303 },
- { label: "Временной парадокс", value: 711 },
- { label: "Вторжение на Землю", value: 228 },
- { label: "Второй шанс", value: 608 },
- { label: "Выживание", value: 695 },
- { label: "Вынужденные условия проживания", value: 287 },
- { label: "Высокомерный герой", value: 56 },
- { label: "Гадание", value: 207 },
- { label: "Галлюцинации", value: 189 },
- { label: "Гарем рабов", value: 656 },
- { label: "Геймеры", value: 301 },
- { label: "Генетические модификации", value: 306 },
- { label: "Герои", value: 341 },
- { label: "Герои непонятного пола", value: 36 },
- { label: "Героиня девушка-сорванец", value: 715 },
- { label: "Героиня красавица", value: 81 },
- { label: "Герой влюбляется первым", value: 561 },
- { label: "Герой использует щит", value: 636 },
- { label: "Герой красавец", value: 329 },
- { label: "Герой со множеством тел", value: 564 },
- { label: "Герой-бесстыдник", value: 632 },
- { label: "Герой-извращенец", value: 521 },
- { label: "Герой-трудяга", value: 330 },
- { label: "Герой-яндере", value: 421 },
- { label: "Гетерохромия", value: 342 },
- { label: "Гильдии", value: 324 },
- { label: "Гиперопека", value: 509 },
- { label: "Главная героиня — женщина", value: 277 },
- { label: "Главный герой - гений", value: 308 },
- { label: "Главный герой - Моб", value: 446 },
- { label: "Главный герой — знаменитость", value: 263 },
- { label: "Главный герой — мужчина", value: 419 },
- { label: "Главный герой в поисках гарема", value: 331 },
- { label: "Главный герой заранее готовится", value: 557 },
- { label: "Главный герой не человек", value: 488 },
- { label: "Главный герой приёмный", value: 20 },
- { label: "Главный герой сразу силён", value: 563 },
- { label: "Гладиаторы", value: 310 },
- { label: "Глухой к любви герой", value: 194 },
- { label: "Гоблины", value: 313 },
- { label: "Големы", value: 319 },
- { label: "Гомункул", value: 347 },
- { label: "Горничные", value: 418 },
- { label: "Государственные интриги", value: 212 },
- { label: "Гринд", value: 322 },
- { label: "Давняя травма", value: 518 },
- { label: "Двойник", value: 97 },
- { label: "Дворецкие", value: 111 },
- { label: "Дворфы", value: 224 },
- { label: "Дворяне", value: 487 },
- { label: "Двоюродные братья или сёстры", value: 162 },
- { label: "Девочки-волшебницы", value: 415 },
- { label: "Демоны", value: 193 },
- { label: "Депрессия", value: 196 },
- { label: "Детектив", value: 198 },
- { label: "Детективное расследование", value: 473 },
- { label: "Детское насилие", value: 125 },
- { label: "Детское обещание", value: 130 },
- { label: "Дискриминация", value: 203 },
- { label: "Длительный разрыв отношений", value: 400 },
- { label: "Домашняя жизнь", value: 45 },
- { label: "Драконы", value: 218 },
- { label: "Древний Китай", value: 34 },
- { label: "Дружба", value: 293 },
- { label: "Друзья детства", value: 128 },
- { label: "Друзья становятся врагами", value: 292 },
- { label: "Духи", value: 673 },
- { label: "Духовная сила", value: 665 },
- { label: "Духовный наставник", value: 671 },
- { label: "Душещипательная история", value: 335 },
- { label: "Души", value: 666 },
- { label: "Дьявольский путь культивации", value: 192 },
- { label: "Ёкай", value: 763 },
- { label: "Есть аниме-адаптация", value: 10 },
- { label: "Есть видеоигра", value: 13 },
- { label: "Есть дорама-адаптация", value: 11 },
- { label: "Есть манга-адаптация", value: 14 },
- { label: "Есть манхва-адаптация", value: 16 },
- { label: "Есть маньхуа-адаптация", value: 15 },
- { label: "Есть фильм", value: 17 },
- { label: "Есть CD дорама-адаптация", value: 12 },
- { label: "Жёсткий главный герой", value: 597 },
- { label: "Жестокие персонажи", value: 4 },
- { label: "Жёстокие персонажи", value: 169 },
- { label: "Животное-спутник", value: 78 },
- { label: "Жизнь в одиночку", value: 396 },
- { label: "Жрецы", value: 555 },
- { label: "Жрицы", value: 554 },
- { label: "Забота о детях", value: 127 },
- { label: "Заботливый главный герой", value: 116 },
- { label: "Загадочное заболевание", value: 471 },
- { label: "Загадочное прошлое родителей", value: 470 },
- { label: "Заговоры", value: 154 },
- { label: "Закалка тела", value: 96 },
- { label: "Закон джунглей", value: 682 },
- { label: "Закулисная борба", value: 603 },
- { label: "Замкнутый главный герой", value: 371 },
- { label: "Запечатанная сила", value: 607 },
- { label: "Затворник", value: 346 },
- { label: "Звери", value: 80 },
- { label: "Зверолюди", value: 39 },
- { label: "Звероподобные", value: 79 },
- { label: "Земледелие", value: 268 },
- { label: "Злобные благородные девы", value: 743 },
- { label: "Зловещие организации", value: 247 },
- { label: "Злой главный герой", value: 248 },
- { label: "Злые боги", value: 246 },
- { label: "Злые религии", value: 249 },
- { label: "Знаменитости", value: 118 },
- { label: "Знания из прошлой жизни", value: 553 },
- { label: "Зомби", value: 767 },
- { label: "Игра на выживание", value: 696 },
- { label: "Игровая рейтинговая система", value: 300 },
- { label: "Из грязи в князи", value: 542 },
- { label: "Известные родители", value: 262 },
- { label: "Изменение внешнего вида", value: 48 },
- { label: "Изнасилование", value: 574 },
- { label: "Инвалидность", value: 202 },
- { label: "Индустриализация", value: 364 },
- { label: "Инженер", value: 241 },
- { label: "Инцест", value: 361 },
- { label: "Искажённая личность", value: 730 },
- { label: "Искусственный интеллект", value: 59 },
- { label: "Исполнение желаний", value: 755 },
- { label: "Каннибализм", value: 113 },
- { label: "Карточные игры", value: 114 },
- { label: "Кладбищенский смотритель", value: 321 },
- { label: "Классика", value: 134 },
- { label: "Книги", value: 99 },
- { label: "Книги навыков", value: 654 },
- { label: "Книжный червь", value: 100 },
- { label: "Коллеги", value: 140 },
- { label: "Колледж/Университет", value: 145 },
- { label: "Командная работа", value: 701 },
- { label: "Комедийный подтекст", value: 147 },
- { label: "Комплекс брата", value: 105 },
- { label: "Комплекс неполноценности", value: 365 },
- { label: "Контракты", value: 155 },
- { label: "Контроль разума", value: 441 },
- { label: "Конфликт в семье", value: 261 },
- { label: "Конфликт верности", value: 153 },
- { label: "Копейщик", value: 668 },
- { label: "Королевская особа", value: 596 },
- { label: "Королевства", value: 382 },
- { label: "Короткий рассказ", value: 638 },
- { label: "Коррупция", value: 157 },
- { label: "Космические Войны", value: 158 },
- { label: "Космос", value: 507 },
- { label: "Косплей", value: 159 },
- { label: "Кража способностей", value: 2 },
- { label: "Крафтинг", value: 164 },
- { label: "Кризис личности", value: 357 },
- { label: "Кровь", value: 320 },
- { label: "Кружки, клубы", value: 138 },
- { label: "Кудэрэ", value: 384 },
- { label: "Кузнец", value: 90 },
- { label: "Кукловоды", value: 567 },
- { label: "Куклы/Марионетки", value: 211 },
- { label: "Кулинария", value: 156 },
- { label: "Культивация", value: 171 },
- { label: "Куннилингус", value: 172 },
- { label: "Легенды", value: 391 },
- { label: "Легкая жизнь", value: 229 },
- { label: "Лекари", value: 334 },
- { label: "Ленивый главный герой", value: 389 },
- { label: "Лидерство", value: 390 },
- { label: "Любит персонажа младше себя", value: 765 },
- { label: "Любит персонажа старше себя", value: 494 },
- { label: "Любовное соперничество", value: 406 },
- { label: "Любовные треугольники", value: 407 },
- { label: "Любовь детства", value: 129 },
- { label: "Любовь с первого взгляда", value: 404 },
- { label: "Любящие родители", value: 215 },
- { label: "Маги", value: 757 },
- { label: "Магические технологии", value: 417 },
- { label: "Магия", value: 412 },
- { label: "Магия призыва", value: 694 },
- { label: "Маленькие девочки", value: 397 },
- { label: "Мангака", value: 423 },
- { label: "Маниакальная любовь", value: 492 },
- { label: "Марти Сью", value: 508 },
- { label: "Мастер подземелий", value: 222 },
- { label: "Мастурбация", value: 432 },
- { label: "Матриархат", value: 433 },
- { label: "Межпространственные путешествия", value: 370 },
- { label: "Менеджмент", value: 422 },
- { label: "Месть", value: 588 },
- { label: "Мечи и магия", value: 697 },
- { label: "Мечники", value: 698 },
- { label: "Миленькие дети", value: 176 },
- { label: "Милитаризм", value: 439 },
- { label: "Миловидная история", value: 178 },
- { label: "Милый главный герой", value: 177 },
- { label: "Минет", value: 275 },
- { label: "Мировое древо", value: 760 },
- { label: "Миролюбивый главный герой", value: 510 },
- { label: "Мифология", value: 475 },
- { label: "Младшие сёстры", value: 766 },
- { label: "ММОРПГ", value: 445 },
- { label: "Множество временных линий", value: 463 },
- { label: "Модели", value: 447 },
- { label: "Молод не по годам", value: 49 },
- { label: "Монстры", value: 454 },
- { label: "Мрачность", value: 183 },
- { label: "Музыка", value: 466 },
- { label: "Музыкальные группы", value: 68 },
- { label: "Мутации", value: 468 },
- { label: "На волосок от смерти", value: 479 },
- { label: "На все руки мастер", value: 374 },
- { label: "Навыки имеют стоимость", value: 150 },
- { label: "Нагота", value: 490 },
- { label: "Наездники на драконах", value: 216 },
- { label: "Наёмники", value: 437 },
- { label: "Наивный главный герой", value: 476 },
- { label: "Наследие", value: 366 },
- { label: "Настоящая любовь", value: 200 },
- { label: "Настоящий гарем", value: 540 },
- { label: "Небесное испытание", value: 337 },
- { label: "Невезучий главный герой", value: 738 },
- { label: "Недоверчивый протагонист", value: 206 },
- { label: "Недооцененный главный герой", value: 734 },
- { label: "Недопонимание", value: 444 },
- { label: "Некромант", value: 480 },
- { label: "Нелинейное повествование", value: 489 },
- { label: "Неловкий главный герой", value: 67 },
- { label: "Нелюбимый протагонист", value: 333 },
- { label: "Немой персонаж", value: 469 },
- { label: "Ненадежный рассказчик", value: 739 },
- { label: "Непримечательный герой", value: 65 },
- { label: "Нерешительный протагонист", value: 363 },
- { label: "Несгибаемый главный герой", value: 676 },
- { label: "Несколько главных героев", value: 460 },
- { label: "Несколько миров", value: 461 },
- { label: "Несколько перерожденцев", value: 462 },
- { label: "Несколько попаданцев", value: 464 },
- { label: "Несравненная скорость культивации", value: 269 },
- { label: "Нехватка/отсутствие здравого смысла", value: 385 },
- { label: "Нечестный протагонист", value: 205 },
- { label: "НИИТ", value: 481 },
- { label: "Ниндзя", value: 486 },
- { label: "Обмен телами", value: 95 },
- { label: "Оборотни", value: 754 },
- { label: "Объект любви влюбился первым", value: 405 },
- { label: "Объект любви популярен", value: 543 },
- { label: "Огнестрельное оружие", value: 280 },
- { label: "Ограничение на время жизни", value: 394 },
- { label: "Одержимость", value: 544 },
- { label: "Один родитель", value: 651 },
- { label: "Одинокий главный герой", value: 399 },
- { label: "Одиночество", value: 398 },
- { label: "Одно тело на двоих", value: 634 },
- { label: "Око силы", value: 253 },
- { label: "Оммёдзи", value: 498 },
- { label: "Организованная преступность", value: 500 },
- { label: "Оргия", value: 501 },
- { label: "Орки", value: 499 },
- { label: "Основано на аниме", value: 74 },
- { label: "Основано на видеоигре", value: 72 },
- { label: "Основано на визуальной новелле", value: 73 },
- { label: "Основано на песне", value: 70 },
- { label: "Основано на фильме", value: 69 },
- { label: "Осторожный главный герой", value: 117 },
- { label: "От ненависти до любви один шаг", value: 239 },
- { label: "От сильного с сильнейшему", value: 684 },
- { label: "От слабого к сильному", value: 752 },
- { label: "Отаку", value: 503 },
- { label: "Отзывчивая любовь", value: 380 },
- { label: "Отзывчивый главный герой", value: 339 },
- { label: "Отношение учитель-ученик", value: 430 },
- { label: "Отношения бог-человек", value: 315 },
- { label: "Отношения между учителем и учеником", value: 687 },
- { label: "Отношения начальник-подчинённый", value: 101 },
- { label: "Отношения против воли", value: 286 },
- { label: "Отношения с нечеловеком", value: 353 },
- { label: "Отношения сэмпай-кохай", value: 621 },
- { label: "Отношения хозяин-слуга", value: 431 },
- { label: "Отомэ-игры", value: 504 },
- { label: "ОТП", value: 562 },
- { label: "Отшельники", value: 505 },
- { label: "Офисный работник", value: 600 },
- { label: "Официанты", value: 748 },
- { label: "Охотники", value: 355 },
- { label: "Падшие ангелы", value: 255 },
- { label: "Падшие дворяне", value: 256 },
- { label: "Пайзури", value: 511 },
- { label: "Паразиты", value: 513 },
- { label: "Параллельные миры", value: 512 },
- { label: "Парк развлечений", value: 32 },
- { label: "Пародия", value: 515 },
- { label: "Перемещение между мирами", value: 758 },
- { label: "Переодевание", value: 167 },
- { label: "Переплавка пилюль", value: 529 },
- { label: "Перерождение в девушку", value: 420 },
- { label: "Перерождение в другом мире", value: 580 },
- { label: "Перерождение в другом мире", value: 720 },
- { label: "Перерождение в игровом мире", value: 579 },
- { label: "Перерождение в монстра", value: 577 },
- { label: "Персонажи с мазохистскими наклонностями", value: 429 },
- { label: "Персонажи с садистскими наклонностями", value: 598 },
- { label: "Петля времени", value: 709 },
- { label: "Петтинг", value: 328 },
- { label: "Писатели", value: 761 },
- { label: "Питомцы", value: 522 },
- { label: "Племенное общество", value: 726 },
- { label: "Повелитель демонов", value: 191 },
- { label: "Повествование от нескольких лиц", value: 459 },
- { label: "Поглощение навыков", value: 653 },
- { label: "Подземелья", value: 223 },
- { label: "Поздно начинающаяся романтическая линия", value: 387 },
- { label: "Политика", value: 538 },
- { label: "Полулюди", value: 190 },
- { label: "Помолвка", value: 240 },
- { label: "Попаданец в другой мир", value: 723 },
- { label: "Попаданец в игровой мир", value: 722 },
- { label: "Постапокалипсис", value: 546 },
- { label: "Постижение Дао", value: 181 },
- { label: "Потеря девственности", value: 282 },
- { label: "Потустороннее пространство", value: 416 },
- { label: "Похищения", value: 379 },
- { label: "Прагматичный главный герой", value: 549 },
- { label: "Предательство", value: 83 },
- { label: "Предвидение", value: 550 },
- { label: "Преследователи", value: 674 },
- { label: "Преступление", value: 165 },
- { label: "Преступность", value: 166 },
- { label: "Приёмные дети", value: 19 },
- { label: "Призванный герой", value: 693 },
- { label: "Призраки", value: 309 },
- { label: "Приключения", value: 22 },
- { label: "Принуждение", value: 108 },
- { label: "Приручатель", value: 453 },
- { label: "Прислуга", value: 625 },
- { label: "Приставучий любовник", value: 136 },
- { label: "Притворная любовь", value: 552 },
- { label: "Пришельцы", value: 28 },
- { label: "Программист", value: 558 },
- { label: "Произведение - обладатель наград", value: 66 },
- { label: "Проклятия", value: 175 },
- { label: "Промывка мозгов", value: 102 },
- { label: "Пропуск времени", value: 712 },
- { label: "Пророчества", value: 559 },
- { label: "Протагонист в очках", value: 312 },
- { label: "Протагонист раб", value: 657 },
- { label: "Психокинез", value: 565 },
- { label: "Психопаты", value: 566 },
- { label: "Путешествия", value: 759 },
- { label: "Путешествия во времени", value: 713 },
- { label: "Пытки", value: 716 },
- { label: "Рабы", value: 658 },
- { label: "Развитие отношений", value: 160 },
- { label: "Развитие персонажа", value: 119 },
- { label: "Раздвоение личности", value: 458 },
- { label: "Размеренная романтика", value: 661 },
- { label: "Разница в статусе", value: 201 },
- { label: "Разорванная помолвка", value: 104 },
- { label: "Разумные предметы", value: 622 },
- { label: "Рай", value: 336 },
- { label: "Раняя романтика", value: 227 },
- { label: "Расизм", value: 573 },
- { label: "Расследования", value: 372 },
- { label: "Ребенок — главный герой", value: 126 },
- { label: "Реверс-гарем", value: 589 },
- { label: "Реверс-изнасилование", value: 590 },
- { label: "Резкая смена характера", value: 520 },
- { label: "Реинкарнация", value: 581 },
- { label: "Религии", value: 582 },
- { label: "Ресторан", value: 585 },
- { label: "Решительный главный герой", value: 199 },
- { label: "Робкий протагонист", value: 714 },
- { label: "Родительсткий комплекс", value: 514 },
- { label: "Родные не связанные кровью", value: 647 },
- { label: "Родословные", value: 94 },
- { label: "РПГ-система", value: 392 },
- { label: "Рыцари", value: 383 },
- { label: "Самовлюбленный главный герой", value: 477 },
- { label: "Самоубийства", value: 692 },
- { label: "Самураи", value: 601 },
- { label: "Сборник коротких историй", value: 144 },
- { label: "Свадьба", value: 426 },
- { label: "Связанные сюжетные линии", value: 369 },
- { label: "Святые", value: 599 },
- { label: "Секреты", value: 614 },
- { label: "Секс втроём", value: 707 },
- { label: "Секс-рабыня", value: 629 },
- { label: "Семейная любовь", value: 257 },
- { label: "Семь добродетелей", value: 627 },
- { label: "Семь смертных грехов", value: 626 },
- { label: "Серийные убийцы", value: 624 },
- { label: "Сикигами", value: 637 },
- { label: "Сильная любовь от старших", value: 214 },
- { label: "Синдром восьмиклассника", value: 132 },
- { label: "Синдром сестры", value: 652 },
- { label: "Сироты", value: 502 },
- { label: "Системный администратор", value: 699 },
- { label: "Скромный главный герой", value: 409 },
- { label: "Скрытые романтические отношения", value: 23 },
- { label: "Скрытые способности", value: 343 },
- { label: "Скряга", value: 450 },
- { label: "Скульпторы", value: 606 },
- { label: "Слабая романтика", value: 688 },
- { label: "Слабый главный герой", value: 751 },
- { label: "Сложные семейные отношения", value: 149 },
- { label: "Смена расы", value: 572 },
- { label: "Смертельное заболевание", value: 704 },
- { label: "Смерть", value: 185 },
- { label: "Смерть любимых", value: 186 },
- { label: "Современность", value: 448 },
- { label: "Современные знания в слаборазвитых мирах", value: 449 },
- { label: "Сожительство", value: 141 },
- { label: "Создание артефактов", value: 57 },
- { label: "Создание клана", value: 133 },
- { label: "Создание королевства", value: 381 },
- { label: "Создание навыков", value: 655 },
- { label: "Сокрытие истинных способностей", value: 344 },
- { label: "Сокрытие личности", value: 345 },
- { label: "Солдаты", value: 664 },
- { label: "Сон", value: 659 },
- { label: "Соседи по комнате", value: 595 },
- { label: "Социальные изгои", value: 663 },
- { label: "Спасение мира", value: 602 },
- { label: "Спорящая пара", value: 84 },
- { label: "Способность перевоплощения", value: 719 },
- { label: "Средневековье", value: 436 },
- { label: "Стеснительные персонажи", value: 643 },
- { label: "Стокгольмский синдром", value: 575 },
- { label: "Стокгольмский синдром", value: 675 },
- { label: "Стратег", value: 681 },
- { label: "Стратегические битвы", value: 680 },
- { label: "Стрелки", value: 325 },
- { label: "Стрельба из лука", value: 50 },
- { label: "Студенческий совет", value: 686 },
- { label: "Судьба", value: 197 },
- { label: "Суккубы", value: 689 },
- { label: "Суперспособности", value: 669 },
- { label: "Суровая тренировка", value: 332 },
- { label: "Сцены насилия", value: 195 },
- { label: "Таинственное прошлое", value: 472 },
- { label: "Тайная личность", value: 610 },
- { label: "Тайные организации", value: 611 },
- { label: "Телохранители", value: 98 },
- { label: "Тентакли", value: 703 },
- { label: "Террористы", value: 705 },
- { label: "Технологический разрыв", value: 702 },
- { label: "Тихие герои", value: 568 },
- { label: "Толстый протагонист", value: 271 },
- { label: "Торговцы", value: 438 },
- { label: "Травник", value: 340 },
- { label: "Трагичное прошлое", value: 718 },
- { label: "Трап", value: 725 },
- { label: "Триллер", value: 708 },
- { label: "Турнир", value: 76 },
- { label: "Тюрьма", value: 556 },
- { label: "Убийства", value: 465 },
- { label: "Уверенный в себе главный герой", value: 151 },
- { label: "Умная пара", value: 662 },
- { label: "Умный главный герой", value: 135 },
- { label: "Уникальная техника культивации", value: 735 },
- { label: "Уникальные оружия", value: 737 },
- { label: "Управление бизнесом", value: 109 },
- { label: "Управление временем", value: 710 },
- { label: "Управление пространством", value: 667 },
- { label: "Ускоренный рост", value: 6 },
- { label: "Учёные", value: 605 },
- { label: "Учителя", value: 700 },
- { label: "Фамильяры", value: 258 },
- { label: "Фанатизм", value: 264 },
- { label: "Фармацевт", value: 523 },
- { label: "Феи", value: 254 },
- { label: "Фениксы", value: 526 },
- { label: "Фетиш на грудь", value: 103 },
- { label: "Фетиш на очки", value: 311 },
- { label: "Философия", value: 524 },
- { label: "Фобии/Страхи", value: 525 },
- { label: "Фольклор", value: 285 },
- { label: "Формирование армии", value: 54 },
- { label: "Футанари", value: 295 },
- { label: "Футуристический мир", value: 296 },
- { label: "Фэнтези", value: 267 },
- { label: "Фэнтезийные существа", value: 266 },
- { label: "Хакеры", value: 326 },
- { label: "Харизматичный протагонист", value: 120 },
- { label: "Хитрый главный герой", value: 173 },
- { label: "Хладнокровный главный герой", value: 112 },
- { label: "Художники", value: 60 },
- { label: "Хулиганы", value: 188 },
- { label: "Цундере", value: 728 },
- { label: "Чат", value: 122 },
- { label: "Человек-оружие", value: 352 },
- { label: "Человекоподобный главный герой", value: 354 },
- { label: "Честный главный герой", value: 348 },
- { label: "Четкие любовные убеждения", value: 683 },
- { label: "Читы", value: 123 },
- { label: "Чудаковатые герои", value: 569 },
- { label: "Чужие воспоминания", value: 721 },
- { label: "Шантаж", value: 89 },
- { label: "Шеф-повар", value: 124 },
- { label: "Школа для девочек", value: 29 },
- { label: "Шоу-бизнес", value: 642 },
- { label: "Шпионы", value: 670 },
- { label: "Эволюция", value: 250 },
- { label: "Эгоистичный главный герой", value: 618 },
- { label: "Экзорцизм", value: 252 },
- { label: "Экономика", value: 230 },
- { label: "Эксгибиционизм", value: 251 },
- { label: "Эксперименты на людях", value: 351 },
- { label: "Элементальная магия", value: 234 },
- { label: "Элементы игрового мира", value: 299 },
- { label: "Элементы романтики", value: 594 },
- { label: "Элементы юри", value: 640 },
- { label: "Элементы яоя", value: 641 },
- { label: "Эльфы", value: 235 },
- { label: "Эпизодичность", value: 243 },
- { label: "Язвительные персонажи", value: 635 },
- { label: "Языковой барьер", value: 386 },
- { label: "Яндере", value: 762 },
- { label: "Яойщица", value: 294 },
- { label: "Японские силы самообороны", value: 378 },
- { label: "R-15", value: 570 },
- { label: "R-18", value: 571 },
- ],
- inputType: filterInputs_1.FilterInputs.Checkbox,
- },
- {
- key: "genres",
- label: "Жанры",
- values: [
- { label: "16+", value: 1 },
- { label: "18+", value: 2 },
- { label: "Боевик", value: 3 },
- { label: "Боевые искусства", value: 4 },
- { label: "Вампиры", value: 47 },
- { label: "Военное", value: 44 },
- { label: "Гарем", value: 5 },
- { label: "Демоны", value: 48 },
- { label: "Детектив", value: 6 },
- { label: "Дзёсей", value: 50 },
- { label: "Драма", value: 7 },
- { label: "Игры", value: 45 },
- { label: "Историческое", value: 8 },
- { label: "Киберпанк", value: 9 },
- { label: "Комедия", value: 10 },
- { label: "Космос", value: 46 },
- { label: "Магия", value: 42 },
- { label: "Махо-сёдзё", value: 12 },
- { label: "Меха", value: 13 },
- { label: "Мистика", value: 14 },
- { label: "Музыка", value: 49 },
- { label: "Научная фантастика", value: 15 },
- { label: "Пародия", value: 16 },
- { label: "Повседневность", value: 17 },
- { label: "Приключения", value: 18 },
- { label: "Психологическое", value: 19 },
- { label: "Романтика", value: 20 },
- { label: "Сверхъестественное", value: 21 },
- { label: "Сёдзё", value: 22 },
- { label: "Сёдзё-ай", value: 23 },
- { label: "Сёнэн", value: 24 },
- { label: "Сёнэн-ай", value: 25 },
- { label: "Смена пола", value: 26 },
- { label: "Современность", value: 27 },
- { label: "Спорт", value: 28 },
- { label: "Супер сила", value: 43 },
- { label: "Сэйнэн", value: 29 },
- { label: "Трагедия", value: 32 },
- { label: "Триллер", value: 33 },
- { label: "Ужасы", value: 34 },
- { label: "Уся", value: 35 },
- { label: "Фэнтези", value: 36 },
- { label: "Школьная жизнь", value: 37 },
- { label: "Этти", value: 38 },
- { label: "Юри", value: 39 },
- { label: "Яой", value: 40 },
- { label: "LitRPG", value: 41 },
- ],
- inputType: filterInputs_1.FilterInputs.Checkbox,
- },
-];
diff --git a/js/plugins/russian/ranobehub.js b/js/plugins/russian/ranobehub.js
deleted file mode 100644
index 1443676..0000000
--- a/js/plugins/russian/ranobehub.js
+++ /dev/null
@@ -1,1126 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.icon = exports.site = exports.version = exports.name = exports.id = void 0;
-const filterInputs_1 = require("@libs/filterInputs");
-const fetch_1 = require("@libs/fetch");
-const novelStatus_1 = require("@libs/novelStatus");
-const cheerio_1 = require("cheerio");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "RNBH.org";
-exports.name = "RanobeHub";
-exports.version = "1.0.0";
-exports.site = "https://ranobehub.org/";
-exports.icon = "src/ru/ranobehub/icon.png";
-const popularNovels = function (page, { showLatestNovels, filters }) {
- return __awaiter(this, void 0, void 0, function* () {
- let url = exports.site + `api/search?page=${page}&sort=`;
- url += showLatestNovels
- ? "last_chapter_at"
- : (filters === null || filters === void 0 ? void 0 : filters.sort) || "computed_rating";
- url += "&status=" + ((filters === null || filters === void 0 ? void 0 : filters.status) ? filters === null || filters === void 0 ? void 0 : filters.status : "0");
- if (filters) {
- if (Array.isArray(filters.country) && filters.country.length) {
- url += "&country=" + filters.country.join(",");
- }
- let tags = [filters === null || filters === void 0 ? void 0 : filters.tags, filters === null || filters === void 0 ? void 0 : filters.events].flat().filter((t) => t);
- if (tags.length) {
- url += "&tags:positive=" + tags.join(",");
- }
- }
- url += "&take=40";
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = (yield result.json());
- let novels = [];
- body.resource.forEach((novel) => {
- var _a;
- return novels.push({
- name: ((_a = novel.names) === null || _a === void 0 ? void 0 : _a.rus) || novel.names.eng,
- cover: novel.poster.medium,
- url: novel.url,
- });
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- var _a, _b, _c, _d;
- return __awaiter(this, void 0, void 0, function* () {
- const novelId = novelUrl
- .substring("https://ranobehub.org/ranobe/".length)
- .split("-")[0];
- const result = yield (0, fetch_1.fetchApi)(`${exports.site}api/ranobe/${novelId}`);
- const json = (yield result.json());
- let novel = {
- url: json.data.url,
- name: ((_a = json.data.names) === null || _a === void 0 ? void 0 : _a.rus) || json.data.names.eng,
- cover: json.data.posters.medium,
- summary: json.data.description,
- author: ((_d = (_c = (_b = json.data) === null || _b === void 0 ? void 0 : _b.authors) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.name_eng) || "",
- status: json.data.status.title.includes("процессе")
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed,
- };
- let tags = [json.data.tags.events, json.data.tags.genres]
- .flat()
- .map((tags) => { var _a, _b; return ((_a = tags === null || tags === void 0 ? void 0 : tags.names) === null || _a === void 0 ? void 0 : _a.rus) || ((_b = tags === null || tags === void 0 ? void 0 : tags.names) === null || _b === void 0 ? void 0 : _b.eng) || (tags === null || tags === void 0 ? void 0 : tags.title); })
- .filter((tags) => tags);
- if (tags.length > 0) {
- novel.genres = tags.join(", ");
- }
- let novelChapters = [];
- const fetchChaptersUrl = `${exports.site}api/ranobe/${novelId}/contents`;
- const chaptersRaw = yield (0, fetch_1.fetchApi)(fetchChaptersUrl);
- const chaptersJSON = (yield chaptersRaw.json());
- chaptersJSON.volumes.forEach((volume) => {
- var _a;
- return (_a = volume.chapters) === null || _a === void 0 ? void 0 : _a.forEach((chapter) => novelChapters.push({
- name: chapter.name,
- url: chapter.url,
- releaseTime: (0, dayjs_1.default)(parseInt(chapter.changed_at, 10) * 1000).format("LLL"),
- }));
- });
- novel.chapters = novelChapters;
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const result = yield (0, fetch_1.fetchApi)(chapterUrl);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio(".chapter-hoticons").remove();
- loadedCheerio("div.text:nth-child(1) img").each(function () {
- var _a;
- if (!((_a = loadedCheerio(this).attr("src")) === null || _a === void 0 ? void 0 : _a.startsWith("http"))) {
- const dataMediaId = loadedCheerio(this).attr("data-media-id");
- loadedCheerio(this).attr("src", exports.site + "api/media/" + dataMediaId);
- }
- });
- let chapterText = loadedCheerio("div.text:nth-child(1)").html() || "";
- // Remove script tags
- chapterText = chapterText === null || chapterText === void 0 ? void 0 : chapterText.replace(/<\s*script[^>]*>[\s\S]*?<\/script>/gim, "");
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- var _a, _b;
- return __awaiter(this, void 0, void 0, function* () {
- const url = `${exports.site}api/fulltext/global?query=${searchTerm}&take=10`;
- const result = yield (0, fetch_1.fetchApi)(url);
- const data = (yield result.json());
- let novels = [];
- (_b = (_a = data === null || data === void 0 ? void 0 : data.find((item) => { var _a; return ((_a = item === null || item === void 0 ? void 0 : item.meta) === null || _a === void 0 ? void 0 : _a.key) === "ranobe"; })) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.forEach((novel) => {
- var _a, _b, _c, _d, _e;
- return novels.push({
- name: ((_a = novel === null || novel === void 0 ? void 0 : novel.names) === null || _a === void 0 ? void 0 : _a.rus) || ((_b = novel === null || novel === void 0 ? void 0 : novel.names) === null || _b === void 0 ? void 0 : _b.eng) || (novel === null || novel === void 0 ? void 0 : novel.name) || "",
- url: "https://ranobehub.org/ranobe/" +
- ((_d = (_c = novel === null || novel === void 0 ? void 0 : novel.url) === null || _c === void 0 ? void 0 : _c.match(/https:\/\/ranobehub\.org\/ranobe\/(.*?)\?utm_source=search_name&utm_medium=search&utm_campaign=search_using/)) === null || _d === void 0 ? void 0 : _d[1]),
- cover: (_e = novel === null || novel === void 0 ? void 0 : novel.image) === null || _e === void 0 ? void 0 : _e.replace("/small", "/medium"),
- });
- });
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-exports.fetchImage = fetch_1.fetchFile;
-exports.filters = [
- {
- key: "sort",
- label: "Сортировка",
- values: [
- { label: "по рейтингу", value: "computed_rating" },
- { label: "по дате обновления", value: "last_chapter_at" },
- { label: "по дате добавления", value: "created_at" },
- { label: "по названию", value: "name_rus" },
- { label: "по просмотрам", value: "views" },
- { label: "по количеству глав", value: "count_chapters" },
- { label: "по объему перевода", value: "count_of_symbols" },
- ],
- inputType: filterInputs_1.FilterInputs.Picker,
- },
- {
- key: "status",
- label: "Статус перевода",
- values: [
- { label: "Любой", value: "" },
- { label: "В процессе", value: "1" },
- { label: "Завершено", value: "2" },
- { label: "Заморожено", value: "3" },
- { label: "Неизвестно", value: "4" },
- ],
- inputType: filterInputs_1.FilterInputs.Picker,
- },
- {
- key: "country",
- label: "Тип",
- values: [
- { label: "Китай", value: "2" },
- { label: "Корея", value: "3" },
- { label: "США", value: "4" },
- { label: "Япония", value: "1" },
- ],
- inputType: filterInputs_1.FilterInputs.Checkbox,
- },
- {
- key: "events",
- label: "События",
- values: [
- { label: "[Награжденная работа]", value: "611" },
- { label: "18+", value: "338" },
- { label: "Авантюристы", value: "353" },
- { label: "Автоматоны", value: "538" },
- { label: "Агрессивные персонажи", value: "434" },
- { label: "Ад", value: "509" },
- { label: "Адаптация в радиопостановку", value: "522" },
- { label: "Академия", value: "25" },
- { label: "Актеры озвучки", value: "578" },
- { label: "Активный главный герой", value: "132" },
- { label: "Алхимия", value: "116" },
- { label: "Альтернативный мир", value: "28" },
- { label: "Амнезия/Потеря памяти", value: "247" },
- { label: "Анабиоз", value: "657" },
- { label: "Ангелы", value: "218" },
- { label: "Андрогинные персонажи", value: "217" },
- { label: "Андроиды", value: "82" },
- { label: "Анти-магия", value: "471" },
- { label: "Антигерой", value: "346" },
- { label: "Антикварный магазин", value: "572" },
- { label: "Антисоциальный главный герой", value: "562" },
- { label: "Антиутопия", value: "663" },
- { label: "Апатичный протагонист", value: "29" },
- { label: "Апокалипсис", value: "314" },
- { label: "Аранжированный брак", value: "285" },
- { label: "Армия", value: "598" },
- { label: "Артефакты", value: "117" },
- { label: "Артисты", value: "460" },
- { label: "Банды", value: "581" },
- { label: "БДСМ", value: "676" },
- { label: "Бедный главный герой", value: "309" },
- { label: "Безжалостный главный герой", value: "144" },
- { label: "Беззаботный главный герой", value: "355" },
- { label: "Безусловная любовь", value: "650" },
- { label: "Беременность", value: "131" },
- { label: "Бесполый главный герой", value: "222" },
- { label: "Бессмертные", value: "275" },
- { label: "Бесстрашный протагонист", value: "619" },
- { label: "Бесстыдный главный герой", value: "256" },
- { label: "Бесчестный главный герой", value: "699" },
- { label: "Библиотека", value: "342" },
- { label: "Бизнесмен ", value: "813" },
- { label: "Биочип", value: "120" },
- { label: "Бисексуальный главный герой", value: "822" },
- { label: "Близнецы", value: "148" },
- { label: "Боги", value: "211" },
- { label: "Богини", value: "356" },
- { label: "Боевая академия", value: "369" },
- { label: "Боевые духи", value: "347" },
- { label: "Боевые соревнования", value: "422" },
- { label: "Божественная защита", value: "336" },
- { label: "Божественные силы", value: "224" },
- {
- label: "Большая разница в возрасте между героем и его любовным интересом",
- value: "348",
- },
- { label: "Борьба за власть", value: "544" },
- { label: "Брак", value: "363" },
- { label: "Брак по расчету", value: "65" },
- { label: "Братский комплекс", value: "31" },
- { label: "Братство", value: "413" },
- { label: "Братья и сестры", value: "518" },
- { label: "Буддизм", value: "742" },
- { label: "Быстрая культивация", value: "273" },
- { label: "Быстрообучаемый", value: "221" },
- { label: "Валькирии", value: "667" },
- { label: "Вампиры", value: "266" },
- { label: "Ваншот", value: "679" },
- { label: "Ведьмы", value: "169" },
- { label: "Вежливый главный герой", value: "289" },
- { label: "Верные подчиненные", value: "225" },
- { label: "Взрослый главный герой", value: "183" },
- { label: "Видит то, чего не видят другие", value: "636" },
- { label: "Виртуальная реальность", value: "313" },
- { label: "Владелец магазина", value: "653" },
- { label: "Внезапная сила", value: "376" },
- { label: "Внезапное богатство", value: "802" },
- {
- label: "Внешний вид отличается от фактического возраста",
- value: "334",
- },
- { label: "Военные Летописи", value: "740" },
- { label: "Возвращение из другого мира", value: "673" },
- { label: "Войны", value: "58" },
- { label: "Вокалоид", value: "678" },
- { label: "Волшебники/Волшебницы", value: "477" },
- { label: "Волшебные звери", value: "201" },
- { label: "Воображаемый друг", value: "614" },
- { label: "Воры", value: "326" },
- { label: "Воскрешение", value: "78" },
- { label: "Враги становятся возлюбленными", value: "428" },
- { label: "Враги становятся союзниками", value: "502" },
- { label: "Врата в другой мир", value: "558" },
- { label: "Врачи", value: "286" },
- { label: "Временной парадокс", value: "163" },
- { label: "Всемогущий главный герой", value: "42" },
- { label: "Вторжение на землю", value: "77" },
- { label: "Второй шанс", value: "112" },
- { label: "Вуайеризм", value: "851" },
- { label: "Выживание", value: "290" },
- { label: "Высокомерные персонажи", value: "268" },
- { label: "Гадание", value: "540" },
- { label: "Гарем рабов", value: "828" },
- { label: "Геймеры", value: "302" },
- { label: "Генералы", value: "223" },
- { label: "Генетические модификации", value: "620" },
- { label: "Гениальный главный герой", value: "566" },
- { label: "Герои", value: "173" },
- { label: "Героиня — сорванец", value: "525" },
- { label: "Герой влюбляется первым", value: "64" },
- { label: "Гетерохромия", value: "510" },
- { label: "Гильдии", value: "323" },
- { label: "Гипнотизм", value: "768" },
- { label: "Главный герой — бог", value: "486" },
- { label: "Главный герой — гуманоид", value: "595" },
- { label: "Главный герой — женщина", value: "63" },
- { label: "Главный герой — мужчина", value: "39" },
- { label: "Главный герой — наполовину человек", value: "362" },
- { label: "Главный герой — отец", value: "859" },
- { label: "Главный герой — раб", value: "832" },
- { label: "Главный герой — ребенок", value: "415" },
- { label: "Главный герой — рубака", value: "400" },
- { label: "Главный герой — собиратель гарема", value: "439" },
- { label: "Главный герой влюбляется первым", value: "655" },
- { label: "Главный герой играет роль", value: "396" },
- { label: "Главный герой носит очки", value: "637" },
- { label: "Главный герой пацифист", value: "675" },
- { label: "Главный герой с несколькими телами", value: "628" },
- { label: "Главный герой силен с самого начала", value: "45" },
- { label: "Гладиаторы", value: "549" },
- { label: "Глуповатый главный герой", value: "295" },
- { label: "Гоблины", value: "529" },
- { label: "Големы", value: "569" },
- { label: "Гомункул", value: "850" },
- { label: "Горничные", value: "380" },
- { label: "Госпиталь", value: "1043" },
- { label: "Готовка", value: "193" },
- { label: "Гриндинг", value: "303" },
- { label: "Дао Компаньон", value: "384" },
- { label: "Даосизм", value: "792" },
- { label: "Дарк", value: "151" },
- { label: "Дварфы", value: "220" },
- { label: "Двойная личность", value: "601" },
- { label: "Двойник", value: "547" },
- { label: "Дворецкий", value: "623" },
- { label: "Дворяне", value: "41" },
- { label: "Дворянство/Аристократия", value: "354" },
- { label: "Девушки-монстры", value: "634" },
- { label: "Демоническая техника культивации", value: "706" },
- { label: "Демоны", value: "6" },
- { label: "Денежный долг", value: "841" },
- { label: "Депрессия", value: "494" },
- { label: "Детективы", value: "561" },
- { label: "Дискриминация", value: "34" },
- {
- label: "Добыча денег одно из основных стремлений главного героя",
- value: "307",
- },
- { label: "Долгая разлука", value: "200" },
- { label: "Домашние дела", value: "178" },
- { label: "Домогательство", value: "394" },
- { label: "Драконы", value: "195" },
- { label: "Драконьи всадники", value: "555" },
- { label: "Древние времена", value: "102" },
- { label: "Древний Китай", value: "284" },
- { label: "Дружба", value: "97" },
- { label: "Друзья детства", value: "170" },
- { label: "Друзья становятся врагами", value: "507" },
- { label: "Друиды", value: "427" },
- { label: "Дух лисы", value: "842" },
- { label: "Духи/Призраки", value: "46" },
- { label: "Духовный советник", value: "351" },
- { label: "Душевность", value: "587" },
- { label: "Души", value: "136" },
- { label: "Европейская атмосфера", value: "457" },
- { label: "Ёкаи", value: "516" },
- { label: "Есть аниме-адаптация", value: "26" },
- { label: "Есть видеоигра по мотивам", value: "491" },
- { label: "Есть манга-адаптация", value: "27" },
- { label: "Есть манхва-адаптация", value: "453" },
- { label: "Есть маньхуа-адаптация", value: "298" },
- { label: "Есть сериал-адаптация", value: "421" },
- { label: "Есть фильм по мотивам", value: "47" },
- { label: "Женища-наставник", value: "438" },
- {
- label: "Жертва изнасилования влюбляется в насильника",
- value: "414",
- },
- { label: "Жесткая, двуличная личность", value: "249" },
- { label: "Жестокие персонажи", value: "436" },
- { label: "Жестокое обращение с ребенком", value: "617" },
- { label: "Жестокость", value: "127" },
- { label: "Животноводство", value: "765" },
- { label: "Животные черты", value: "466" },
- { label: "Жизнь в квартире", value: "554" },
- { label: "Жрицы", value: "564" },
- { label: "Заботливый главный герой", value: "176" },
- { label: "Забывчивый главный герой", value: "579" },
- { label: "Заговоры", value: "177" },
- { label: "Закалка тела", value: "269" },
- { label: "Законники", value: "769" },
- { label: "Замкнутый главный герой", value: "533" },
- { label: "Запечатанная сила", value: "344" },
- { label: "Застенчивые персонажи", value: "443" },
- { label: "Звери", value: "119" },
- { label: "Звери-компаньоны", value: "192" },
- { label: "Злой протагонист", value: "125" },
- { label: "Злые боги", value: "437" },
- { label: "Злые организации", value: "503" },
- { label: "Злые религии", value: "725" },
- { label: "Знаменитости", value: "397" },
- { label: "Знаменитый главный герой", value: "469" },
- { label: "Знания современного мира", value: "185" },
- { label: "Зомби", value: "321" },
- { label: "Игра на выживание", value: "162" },
- { label: "Игривый протагонист", value: "700" },
- { label: "Игровая система рейтинга", value: "301" },
- { label: "Игровые элементы", value: "152" },
- { label: "Игрушки (18+)", value: "644" },
- { label: "Из грязи в князи", value: "330" },
- { label: "Из женщины в мужчину ", value: "688" },
- { label: "Из мужчины в женщину", value: "698" },
- { label: "Из полного в худого", value: "809" },
- { label: "Из слабого в сильного", value: "81" },
- { label: "Из страшно(го/й) в красиво(го/ю)", value: "810" },
- { label: "Извращенный главный герой", value: "349" },
- { label: "Изгои", value: "472" },
- { label: "Изменение расы", value: "627" },
- { label: "Изменения внешнего вида", value: "191" },
- { label: "Изменения личности", value: "99" },
- { label: "Изнасилование", value: "110" },
- { label: "Изображения жестокости", value: "260" },
- { label: "Империи", value: "749" },
- { label: "Инвалидность", value: "656" },
- { label: "Индустриализация", value: "180" },
- { label: "Инженер", value: "35" },
- { label: "Инцест", value: "463" },
- { label: "Искусственный интеллект", value: "118" },
- { label: "Исследования", value: "635" },
- { label: "Каннибализм", value: "377" },
- { label: "Карточные игры", value: "654" },
- { label: "Киберспорт", value: "658" },
- { label: "Кланы", value: "950" },
- {
- label: "Класс безработного [Игровой класс в игре]",
- value: "727",
- },
- { label: "Клоны", value: "365" },
- { label: "Клубы", value: "96" },
- { label: "Книги", value: "341" },
- { label: "Книги навыков", value: "312" },
- { label: "Книжный червь", value: "455" },
- { label: "Коварство", value: "111" },
- { label: "Коллеги", value: "683" },
- { label: "Колледж/Университет", value: "712" },
- { label: "Кома", value: "826" },
- { label: "Командная работа", value: "426" },
- { label: "Комедийный оттенок", value: "523" },
- { label: "Комплекс неполноценности", value: "489" },
- { label: "Комплекс семейных отношений", value: "104" },
- { label: "Конкуренция", value: "746" },
- { label: "Контракты", value: "483" },
- { label: "Контроль разума/сознания", value: "262" },
- { label: "Копейщик", value: "339" },
- { label: "Королевская битва", value: "1025" },
- { label: "Королевская власть", value: "53" },
- { label: "Королевства", value: "141" },
- { label: "Коррупция", value: "378" },
- { label: "Космические войны", value: "674" },
- { label: "Красивый герой", value: "107" },
- { label: "Крафт", value: "287" },
- { label: "Кризис личности", value: "599" },
- { label: "Кругосветное путешествие", value: "257" },
- { label: "Кудере", value: "440" },
- { label: "Кузены", value: "701" },
- { label: "Кузнец", value: "454" },
- { label: "Кукловоды", value: "431" },
- { label: "Куклы/марионетки", value: "573" },
- { label: "Культивация", value: "123" },
- { label: "Куннилингус", value: "632" },
- { label: "Легенды", value: "430" },
- { label: "Легкая жизнь", value: "604" },
- { label: "Ленивый главный герой", value: "570" },
- { label: "Лидерство", value: "424" },
- { label: "Лоли", value: "92" },
- { label: "Лотерея", value: "401" },
- { label: "Любовный интерес влюбляется первым", value: "647" },
- {
- label: "Любовный интерес главного героя носит очки",
- value: "576",
- },
- { label: "Любовный треугольник", value: "98" },
- { label: "Любовь детства", value: "500" },
- { label: "Любовь с первого взгляда", value: "730" },
- { label: "Магические надписи", value: "373" },
- { label: "Магические печати", value: "277" },
- { label: "Магические технологии", value: "357" },
- {
- label: "Магическое пространство/измерение, доступное не всем персонажам",
- value: "244",
- },
- { label: "Магия", value: "38" },
- { label: "Магия призыва", value: "333" },
- { label: "Мазохистские персонажи", value: "660" },
- { label: "Манипулятивные персонажи", value: "130" },
- { label: "Мания", value: "91" },
- { label: "Мастер на все руки", value: "390" },
- { label: "Мастурбация", value: "846" },
- { label: "Махо-сёдзё", value: "496" },
- { label: "Медицинские знания", value: "441" },
- { label: "Медленная романтическая линия", value: "113" },
- { label: "Медленное развитие на старте ", value: "670" },
- { label: "Межпространственные путешествия", value: "316" },
- { label: "Менеджмент", value: "182" },
- { label: "Мертвый главный герой", value: "794" },
- { label: "Месть", value: "88" },
- { label: "Метаморфы", value: "234" },
- { label: "Меч и магия", value: "55" },
- { label: "Мечник", value: "607" },
- { label: "Мечты", value: "733" },
- { label: "Милая история", value: "709" },
- { label: "Милое дитя", value: "596" },
- { label: "Милый главный герой", value: "697" },
- { label: "Мировое дерево", value: "385" },
- { label: "Мистический ореол вокруг семьи", value: "409" },
- { label: "Мифические звери", value: "418" },
- { label: "Мифология", value: "468" },
- { label: "Младшие братья", value: "843" },
- { label: "Младшие сестры", value: "465" },
- { label: "ММОРПГ (ЛитРПГ)", value: "306" },
- { label: "Множество перемещенных людей", value: "488" },
- { label: "Множество реальностей", value: "278" },
- { label: "Множество реинкарнированных людей", value: "227" },
- { label: "Модели", value: "649" },
- { label: "Молчаливый персонаж", value: "705" },
- { label: "Монстры", value: "69" },
- { label: "Мужская гей-пара", value: "685" },
- { label: "Мужчина-яндере", value: "155" },
- { label: "Музыка", value: "589" },
- { label: "Музыкальные группы", value: "588" },
- { label: "Мутации", value: "668" },
- { label: "Мутированные существа", value: "317" },
- { label: "Навык кражи", value: "626" },
- { label: "Навязчивая любовь", value: "85" },
- { label: "Наемники", value: "324" },
- { label: "Назойливый возлюбленный", value: "501" },
- { label: "Наивный главный герой", value: "66" },
- { label: "Наркотики", value: "661" },
- { label: "Нарциссический главный герой", value: "470" },
- { label: "Насилие сексуального характера", value: "824" },
- { label: "Наследование", value: "372" },
- { label: "Национализм", value: "318" },
- { label: "Не блещущий внешне главный герой", value: "328" },
- { label: "Не родные братья и сестры", value: "464" },
- { label: "Небеса", value: "508" },
- { label: "Небесное испытание", value: "274" },
- { label: "Негуманоидный главный герой", value: "622" },
- { label: "Недоверчивый главный герой", value: "485" },
- { label: "Недооцененный главный герой", value: "140" },
- { label: "Недоразумения", value: "202" },
- { label: "Неизлечимая болезнь", value: "75" },
- { label: "Некромант", value: "308" },
- { label: "Нелинейная история", value: "157" },
- { label: "Ненавистный главный герой", value: "487" },
- { label: "Ненадежный рассказчик", value: "165" },
- { label: "Нерезиденты", value: "821" },
- { label: "Нерешительный главный герой", value: "741" },
- { label: "Несерьезный главный герой", value: "294" },
- { label: "Несколько временных линий", value: "517" },
- { label: "Несколько главных героев", value: "475" },
- { label: "Несколько идентичностей", value: "615" },
- { label: "Несколько личностей", value: "474" },
- { label: "Нетораре", value: "721" },
- { label: "Нетори", value: "450" },
- { label: "Неудачливый главный герой", value: "567" },
- { label: "Ниндзя", value: "358" },
- { label: "Обещание из детства", value: "738" },
- { label: "Обманщик", value: "411" },
- { label: "Обмен телами", value: "94" },
- { label: "Обнаженка", value: "417" },
- { label: "Обольщение", value: "718" },
- { label: "Оборотни", value: "624" },
- { label: "Обратный гарем", value: "255" },
- { label: "Общество монстров", value: "226" },
- { label: "Обязательство", value: "548" },
- { label: "Огнестрельное оружие", value: "179" },
- { label: "Ограниченная продолжительность жизни", value: "73" },
- { label: "Одержимость", value: "447" },
- { label: "Одинокий главный герой", value: "304" },
- { label: "Одиночество", value: "199" },
- { label: "Одиночное проживание", value: "207" },
- { label: "Околосмертные переживания", value: "773" },
- { label: "Оммёдзи", value: "542" },
- { label: "Омоложение", value: "237" },
- { label: "Организованная преступность", value: "478" },
- { label: "Оргия", value: "825" },
- { label: "Орки", value: "228" },
- { label: "Освоение навыков", value: "235" },
- { label: "Основано на аниме", value: "553" },
- { label: "Основано на видео игре", value: "704" },
- { label: "Основано на визуальной новелле ", value: "861" },
- { label: "Основано на песне", value: "677" },
- { label: "Основано на фильме", value: "552" },
- { label: "Осторожный главный герой", value: "122" },
- { label: "Отаку", value: "512" },
- { label: "Открытый космос", value: "150" },
- { label: "Отношения в сети", value: "713" },
- { label: "Отношения между богом и человеком", value: "603" },
- { label: "Отношения между людьми и нелюдьми", value: "205" },
- { label: "Отношения на расстоянии", value: "852" },
- { label: "Отношения начальник-подчиненный", value: "590" },
- { label: "Отношения Сенпай-Коухай", value: "513" },
- { label: "Отношения ученика и учителя", value: "451" },
- { label: "Отношения учитель-ученик", value: "343" },
- { label: "Отношения хозяин-слуга", value: "206" },
- { label: "Отомэ игра", value: "723" },
- { label: "Отсутствие здравого смысла", value: "605" },
- { label: "Отсутствие родителей", value: "575" },
- { label: "Офисный роман", value: "686" },
- { label: "Официанты", value: "681" },
- { label: "Охотники", value: "288" },
- { label: "Очаровательный главный герой", value: "659" },
- { label: "Падшее дворянство", value: "618" },
- { label: "Падшие ангелы", value: "505" },
- { label: "Пайзури", value: "630" },
- { label: "Паразиты", value: "535" },
- { label: "Параллельные миры", value: "86" },
- { label: "Парк развлечений", value: "586" },
- { label: "Пародия", value: "319" },
- { label: "Певцы/Певицы", value: "734" },
- { label: "Первая любовь", value: "716" },
- { label: "Первоисточник новеллы — манга", value: "560" },
- { label: "Первый раз", value: "845" },
- {
- label: "Перемещение в другой мир, имея при себе современные достижения",
- value: "732",
- },
- { label: "Перемещение в игровой мир", value: "532" },
- { label: "Перемещение в иной мир", value: "754" },
- { label: "Перерождение в ином мире", value: "755" },
- { label: "Переселение души/Трансмиграция", value: "139" },
- { label: "Персонаж использует щит", value: "631" },
- { label: "Петля времени", value: "79" },
- { label: "Пираты", value: "817" },
- { label: "Писатели", value: "408" },
- { label: "Питомцы", value: "253" },
- { label: "Племенное общество", value: "291" },
- { label: "Повелитель демонов", value: "171" },
- {
- label: "Повествование от нескольких лиц/Несколько точек зрения",
- value: "156",
- },
- { label: "Подземелья", value: "219" },
- { label: "Пожелания", value: "166" },
- { label: "Познание Дао", value: "360" },
- { label: "Покинутое дитя", value: "534" },
- { label: "Полигамия", value: "296" },
- { label: "Политика", value: "43" },
- { label: "Полиция", value: "801" },
- { label: "Полулюди", value: "335" },
- { label: "Пользователь уникального оружия", value: "432" },
- { label: "Популярный любовный интерес", value: "241" },
- { label: "Постапокалиптика", value: "60" },
- { label: "Потерянные цивилизации", value: "751" },
- { label: "Похищения людей", value: "707" },
- { label: "Поэзия", value: "404" },
- { label: "Правонарушители", value: "694" },
- { label: "Прагматичный главный герой", value: "536" },
- { label: "Преданный любовный интерес", value: "106" },
- { label: "Предательство", value: "103" },
- { label: "Предвидение", value: "52" },
- { label: "Прекрасная героиня", value: "30" },
- { label: "Преступники", value: "728" },
- { label: "Преступность", value: "83" },
- { label: "Призванный герой", value: "147" },
- { label: "Призраки", value: "51" },
- { label: "Принуждение к отношениям", value: "602" },
- { label: "Принцессы", value: "933" },
- { label: "Притворная пара", value: "600" },
- { label: "Причудливые персонажи", value: "297" },
- { label: "Пришельцы/Инопланетяне", value: "76" },
- { label: "Программист", value: "666" },
- { label: "Проклятия", value: "48" },
- { label: "Промывание мозгов", value: "519" },
- { label: "Пропуск времени", value: "138" },
- { label: "Пророчества", value: "429" },
- { label: "Проститутки", value: "844" },
- { label: "Пространственное манипулирование", value: "375" },
- { label: "Прошлое играет большую роль", value: "215" },
- { label: "Прыжки между мирами", value: "737" },
- { label: "Психические силы", value: "265" },
- { label: "Психопаты", value: "158" },
- { label: "Путешествие во времени", value: "80" },
- { label: "Пытка", value: "168" },
- { label: "Рабы", value: "829" },
- { label: "Развод", value: "771" },
- { label: "Разумные предметы", value: "174" },
- { label: "Расизм", value: "320" },
- { label: "Рассказ", value: "61" },
- { label: "Расторжения помолвки", value: "243" },
- { label: "Расы зооморфов", value: "209" },
- { label: "Ревность", value: "717" },
- { label: "Редакторы", value: "684" },
- { label: "Реинкарнация", value: "281" },
- { label: "Реинкарнация в монстра", value: "204" },
- { label: "Реинкарнация в объект", value: "692" },
- { label: "Религии", value: "565" },
- { label: "Репортеры", value: "837" },
- { label: "Ресторан", value: "652" },
- { label: "Решительный главный герой", value: "124" },
- { label: "Робкий главный герой", value: "800" },
- { label: "Родитель одиночка", value: "687" },
- { label: "Родительский комплекс", value: "531" },
- { label: "Родословная", value: "121" },
- { label: "Романтический подсюжет ", value: "159" },
- { label: "Рост персонажа", value: "95" },
- { label: "Рыцари", value: "142" },
- { label: "Садистские персонажи", value: "642" },
- { label: "Самоотверженный главный герой", value: "748" },
- { label: "Самоубийства", value: "616" },
- { label: "Самурай", value: "646" },
- { label: "Сборник коротких историй", value: "456" },
- { label: "Связанные сюжетные линии", value: "473" },
- { label: "Святые", value: "761" },
- { label: "Священники", value: "325" },
- { label: "Сдержанный главный герой", value: "799" },
- { label: "Секретные организации", value: "331" },
- { label: "Секреты", value: "577" },
- { label: "Секс рабы", value: "830" },
- { label: "Семейный конфликт", value: "770" },
- { label: "Семь добродетелей", value: "233" },
- { label: "Семь смертных грехов", value: "134" },
- { label: "Семья", value: "251" },
- { label: "Сёнэн-ай подсюжет ", value: "664" },
- { label: "Серийные убийцы", value: "497" },
- { label: "Сестринский комплекс", value: "498" },
- { label: "Сила духа", value: "282" },
- { label: "Сила, требующая платы за пользование", value: "520" },
- { label: "Сильная пара", value: "109" },
- { label: "Сильный в сильнейшего", value: "359" },
- { label: "Сильный любовный интерес", value: "161" },
- { label: "Синдром восьмиклассника", value: "90" },
- { label: "Сироты", value: "214" },
- { label: "Система уровней", value: "198" },
- { label: "Системный администратор", value: "476" },
- { label: "Скрытие истинной личности", value: "371" },
- { label: "Скрытие истинных способностей", value: "252" },
- { label: "Скрытный главный герой", value: "133" },
- { label: "Скрытые способности", value: "128" },
- { label: "Скульпторы", value: "366" },
- { label: "Слабо выраженная романтическая линия", value: "213" },
- { label: "Слабый главный герой", value: "188" },
- { label: "Слепой главный герой", value: "864" },
- { label: "Слуги", value: "232" },
- { label: "Смерть", value: "49" },
- { label: "Смерть близких", value: "361" },
- { label: "Собственнические персонажи", value: "108" },
- { label: "Современность", value: "40" },
- { label: "Сожительство", value: "482" },
- { label: "Создание армии", value: "175" },
- { label: "Создание артефактов", value: "292" },
- { label: "Создание клана", value: "448" },
- { label: "Создание королевства", value: "181" },
- { label: "Создание навыков", value: "236" },
- { label: "Создание секты", value: "393" },
- { label: "Солдаты/Военные", value: "71" },
- { label: "Сон", value: "571" },
- { label: "Состоятельные персонажи", value: "67" },
- { label: "Социальная иерархия на основе силы", value: "137" },
- { label: "Социальные изгои", value: "480" },
- { label: "Спасение мира", value: "597" },
- { label: "Специальные способности", value: "54" },
- { label: "Спокойный главный герой", value: "32" },
- { label: "Справедливый главный герой", value: "702" },
- { label: "Средневековье", value: "184" },
- { label: "Ссорящаяся пара", value: "293" },
- { label: "Сталкеры", value: "689" },
- { label: "Старение", value: "190" },
- { label: "Стоические персонажи", value: "444" },
- { label: "Стокгольмский синдром", value: "643" },
- { label: "Стратег", value: "425" },
- { label: "Стратегические битвы", value: "160" },
- { label: "Стратегия", value: "1038" },
- { label: "Стрелки", value: "458" },
- { label: "Стрельба из лука", value: "383" },
- { label: "Студенческий совет", value: "490" },
- { label: "Судьба", value: "271" },
- { label: "Суккубы", value: "484" },
- { label: "Супер герои", value: "1039" },
- { label: "Суровая подготовка", value: "261" },
- { label: "Таинственная болезнь", value: "74" },
- { label: "Таинственное прошлое", value: "263" },
- { label: "Тайная личность", value: "310" },
- { label: "Тайные отношения", value: "812" },
- { label: "Танцоры", value: "840" },
- { label: "Телохранители", value: "452" },
- { label: "Тентакли", value: "693" },
- { label: "Террористы", value: "515" },
- { label: "Технологический разрыв", value: "621" },
- { label: "Тихие персонажи", value: "546" },
- { label: "Толстый главный герой", value: "299" },
- { label: "Торговцы", value: "416" },
- { label: "Травля/Буллинг", value: "89" },
- { label: "Травник", value: "708" },
- { label: "Трагическое прошлое", value: "164" },
- { label: "Трансплантация воспоминаний", value: "367" },
- { label: "Трап (Путаница с гендером персонажа)", value: "582" },
- { label: "Трудолюбивый главный герой", value: "37" },
- { label: "Тюрьма", value: "479" },
- { label: "Убийства", value: "84" },
- { label: "Убийцы", value: "248" },
- { label: "Убийцы драконов", value: "606" },
- { label: "Уверенный главный герой", value: "270" },
- { label: "Удачливый главный герой", value: "402" },
- { label: "Укротитель монстров", value: "337" },
- { label: "Умения из прошлой жизни", value: "280" },
- { label: "Умная пара", value: "493" },
- { label: "Умный главный герой", value: "33" },
- { label: "Уникальная техника Культивации", value: "254" },
- { label: "Уникальное оружие", value: "340" },
- { label: "Управление бизнесом", value: "315" },
- { label: "Управление временем", value: "167" },
- { label: "Управление кровью", value: "764" },
- { label: "Упрямый главный герой", value: "672" },
- { label: "Уродливый главный герой", value: "803" },
- { label: "Ускоренный рост", value: "300" },
- { label: "Усыновленные дети", value: "481" },
- { label: "Усыновленный главный герой", value: "412" },
- { label: "Уход за детьми", value: "398" },
- { label: "Учителя", value: "345" },
- { label: "Фамильяры", value: "541" },
- { label: "Фанатизм", value: "613" },
- { label: "Фантастические существа", value: "322" },
- { label: "Фанфикшн", value: "388" },
- { label: "Фармацевт", value: "715" },
- { label: "Фарминг", value: "379" },
- { label: "Феи", value: "210" },
- { label: "Фелляция", value: "584" },
- { label: "Фениксы", value: "374" },
- { label: "Фетиш груди", value: "499" },
- { label: "Философия", value: "87" },
- { label: "Фильмы", value: "403" },
- { label: "Флэшбэки", value: "528" },
- { label: "Фобии", value: "100" },
- { label: "Фольклор", value: "467" },
- { label: "Футанари", value: "568" },
- { label: "Футуристический сеттинг", value: "382" },
- { label: "Фэнтези мир", value: "126" },
- { label: "Хакеры", value: "399" },
- { label: "Харизматический герой", value: "391" },
- { label: "Хикикомори/Затворники", value: "462" },
- { label: "Хитроумный главный герой", value: "105" },
- { label: "Хозяин подземелий", value: "557" },
- { label: "Холодный главный герой", value: "259" },
- { label: "Хорошие отношения с семьей", value: "506" },
- { label: "Хранители могил", value: "68" },
- { label: "Целители", value: "389" },
- { label: "Цзянши", value: "735" },
- { label: "Цундэрэ", value: "445" },
- { label: "Чаты", value: "580" },
- { label: "Человеческое оружие", value: "521" },
- { label: "Честный главный герой", value: "240" },
- { label: "Читы", value: "238" },
- { label: "Шантаж", value: "526" },
- { label: "Шеф-повар", value: "239" },
- { label: "Шикигами", value: "543" },
- { label: "Школа только для девочек", value: "633" },
- { label: "Шота", value: "514" },
- { label: "Шоу-бизнес", value: "407" },
- { label: "Шпионы", value: "563" },
- { label: "Эволюция", value: "196" },
- { label: "Эгоистичный главный герой", value: "539" },
- { label: "Эйдетическая память", value: "392" },
- { label: "Экзорсизм", value: "504" },
- { label: "Экономика", value: "492" },
- { label: "Эксгибиционизм", value: "639" },
- { label: "Эксперименты с людьми", value: "129" },
- { label: "Элементальная магия", value: "395" },
- { label: "Эльфы", value: "172" },
- { label: "Эмоционально слабый главный герой", value: "816" },
- { label: "Эпизодический", value: "612" },
- { label: "Юный любовный интерес", value: "446" },
- { label: "Яды", value: "410" },
- { label: "Языкастые персонажи", value: "406" },
- { label: "Языковой барьер", value: "59" },
- { label: "Яндере", value: "208" },
- { label: "Японские силы самообороны", value: "559" },
- { label: "Ярко выраженная романтическая линия", value: "272" },
- { label: "Abusive Characters", value: "625" },
- { label: "Adapted to Visual Novel", value: "1046" },
- { label: "Adopted-lead", value: "886" },
- { label: "Adultery", value: "866" },
- { label: "Affair", value: "645" },
- { label: "Age-gap", value: "923" },
- { label: "Almost-human-lead", value: "975" },
- { label: "An*l", value: "780" },
- { label: "Androgynous-male-lead", value: "1002" },
- { label: "Anti-hero-lead", value: "976" },
- { label: "Apathetic-lead", value: "967" },
- { label: "Arms Dealers", value: "839" },
- { label: "Army-commander", value: "1003" },
- { label: "Artifact-refining", value: "924" },
- { label: "Autism", value: "855" },
- { label: "Awkward Protagonist", value: "669" },
- { label: "Awkward-lead", value: "892" },
- { label: "Bestiality", value: "796" },
- { label: "Big-breasts", value: "908" },
- { label: "Birth-of-a-nation", value: "1004" },
- { label: "Bisexual-lead", value: "1027" },
- { label: "Body-refining", value: "947" },
- { label: "Body-swap/s", value: "1036" },
- { label: "Boss-subordinate-relationship", value: "876" },
- { label: "Bride-kidnapping", value: "948" },
- { label: "Caring-lead", value: "879" },
- { label: "Cautious-lead", value: "1032" },
- { label: "Changed-man", value: "925" },
- { label: "Charismatic-lead", value: "1005" },
- { label: "Child-lead", value: "936" },
- { label: "Clever-lead", value: "880" },
- { label: "Clumsy Love Interests", value: "815" },
- { label: "Cold Love Interests", value: "651" },
- { label: "Coming of Age", value: "860" },
- { label: "Confident-lead", value: "894" },
- { label: "Confident-male-lead", value: "951" },
- { label: "Confinement", value: "767" },
- { label: "Conflicting Loyalties", value: "793" },
- { label: "Couple Growth", value: "690" },
- { label: "Court Official", value: "863" },
- { label: "Cowardly Protagonist", value: "703" },
- { label: "Cowardly-lead", value: "1000" },
- { label: "Cross-dressing", value: "250" },
- { label: "Cunnilingus", value: "867" },
- { label: "Cunning-lead", value: "952" },
- { label: "Cunning-male-lead", value: "953" },
- { label: "Curious Protagonist", value: "849" },
- { label: "Cute-lead", value: "887" },
- { label: "Dense-lead", value: "868" },
- { label: "Determined-lead", value: "972" },
- { label: "Developing-technology", value: "1006" },
- { label: "Devil/s", value: "1007" },
- { label: "Different Social Status", value: "758" },
- { label: "Disfigurement", value: "838" },
- { label: "Doting Love Interests", value: "665" },
- { label: "Doting Older Siblings", value: "609" },
- { label: "Doting Parents", value: "530" },
- { label: "Dungeon/s-exploring", value: "990" },
- { label: "Elderly Protagonist", value: "774" },
- { label: "Enlightenment", value: "729" },
- { label: "Eunuch", value: "1047" },
- { label: "Eye Powers", value: "386" },
- { label: "Family Business", value: "785" },
- { label: "Famous Parents", value: "790" },
- { label: "Famous-lead", value: "897" },
- { label: "Fanfic", value: "942" },
- { label: "Fated Lovers", value: "797" },
- { label: "Fellatio", value: "870" },
- { label: "Female-lead", value: "888" },
- { label: "First-time-intercourse", value: "871" },
- { label: "Fleet Battles", value: "836" },
- { label: "Forced Living Arrangements", value: "808" },
- { label: "Forced Marriage", value: "835" },
- { label: "Former Hero", value: "752" },
- { label: "Fujoshi", value: "1045" },
- { label: "Galge", value: "848" },
- { label: "Gambling", value: "1031" },
- { label: "Gamelit", value: "994" },
- { label: "Genderless-lead", value: "1008" },
- { label: "Glasses-wearing-lead", value: "995" },
- { label: "Guardian Relationship", value: "197" },
- { label: "H*ndjob", value: "629" },
- { label: "Half-human-lead", value: "956" },
- { label: "Hard-working-lead", value: "957" },
- { label: "Hard-working-male-lead", value: "958" },
- { label: "Hard-working-protagonist/s", value: "1030" },
- { label: "Harem-seeking-lead", value: "929" },
- { label: "Harem-subtext", value: "909" },
- { label: "Helpful Protagonist", value: "760" },
- { label: "Helpful-lead", value: "882" },
- { label: "Hidden-gem", value: "998" },
- { label: "High-fantasy", value: "991" },
- { label: "Human-becomes-demon/monster", value: "1009" },
- { label: "Human-nonhuman-relationship", value: "914" },
- { label: "Humanoid-lead", value: "915" },
- { label: "Imperial Harem", value: "805" },
- { label: "Incubus", value: "1049" },
- { label: "Insects", value: "831" },
- { label: "Interspatial-storage", value: "959" },
- { label: "Kind Love Interests", value: "757" },
- { label: "Large-number-of-skills", value: "1010" },
- { label: "Legendary-hero", value: "1011" },
- { label: "Litrpg", value: "977" },
- { label: "Love Rivals", value: "788" },
- { label: "Lovers Reunited", value: "853" },
- { label: "Low-fantasy", value: "1037" },
- { label: "Master-disciple-relationship", value: "899" },
- { label: "Matriarchy", value: "807" },
- { label: "Mature-lead", value: "900" },
- { label: "Mind Break", value: "862" },
- { label: "Mismatched Couple", value: "695" },
- { label: "Mob Protagonist", value: "648" },
- { label: "Mob-lead", value: "902" },
- { label: "Modern", value: "988" },
- { label: "Monster-pov", value: "1012" },
- { label: "Mpreg", value: "856" },
- { label: "Multiple-povs", value: "1013" },
- { label: "Mystery Solving", value: "710" },
- { label: "Naive-lead", value: "1014" },
- { label: "Near-death-experience", value: "996" },
- { label: "Neet", value: "495" },
- { label: "Nightmares", value: "833" },
- { label: "Nobility", value: "1015" },
- { label: "Non-human-lead", value: "978" },
- { label: "Non-humanoid-lead", value: "1016" },
- { label: "Not-so-secret-identity", value: "979" },
- { label: "Omegaverse", value: "857" },
- { label: "Online-game", value: "910" },
- { label: "Online-gaming", value: "911" },
- { label: "Outdoor Interc**rse", value: "847" },
- { label: "Outdoor-intercourse", value: "903" },
- { label: "Overprotective Siblings", value: "610" },
- { label: "Part-Time Job", value: "865" },
- { label: "Past Trauma", value: "726" },
- { label: "Past-memories", value: "1017" },
- { label: "Persistent Love Interests", value: "714" },
- { label: "Perverted-lead", value: "932" },
- { label: "Photography", value: "798" },
- { label: "Pill Based Cultivation", value: "279" },
- { label: "Pill Concocting", value: "245" },
- { label: "Pilots", value: "820" },
- { label: "Playboys", value: "795" },
- { label: "Playful-lead", value: "989" },
- { label: "Polyandry", value: "811" },
- { label: "Portal-fantasy-/-isekai", value: "992" },
- { label: "Pragmatic-lead", value: "884" },
- { label: "Profanity", value: "980" },
- { label: "Protagonist-loyal-to-love-interest", value: "905" },
- { label: "R-15 (Японское возрастное ограничение)", value: "230" },
- { label: "Rebellion", value: "834" },
- { label: "Reincarnated in a Game World", value: "804" },
- { label: "Reluctant Protagonist", value: "696" },
- { label: "Reverse R*pe", value: "776" },
- { label: "Reversible Couple", value: "854" },
- { label: "Ruling-class", value: "943" },
- { label: "S*x Friends", value: "750" },
- { label: "S*xual Cultivation Technique", value: "823" },
- { label: "Salaryman", value: "1035" },
- { label: "Satire", value: "981" },
- { label: "Schemes And Conspiracies", value: "745" },
- { label: "Scientist/s", value: "997" },
- { label: "Scientists", value: "1029" },
- { label: "Secret Crush", value: "827" },
- { label: "Seme Protagonist", value: "1034" },
- { label: "Seme-lead", value: "1028" },
- { label: "Sentimental Protagonist", value: "1048" },
- { label: "Seven-heavenly-virtues", value: "1018" },
- { label: "Sexual Cultivation Technique", value: "350" },
- { label: "Sexual-content", value: "982" },
- { label: "Sexuality", value: "983" },
- { label: "Sharing A Body", value: "814" },
- { label: "Shotacon", value: "858" },
- { label: "Shoujo-Ai Subplot", value: "777" },
- { label: "Sibling Rivalry", value: "766" },
- { label: "Sibling's Care", value: "1042" },
- { label: "Sickly Characters", value: "787" },
- { label: "Skills", value: "1019" },
- { label: "Slave-harem", value: "1001" },
- { label: "Slime", value: "1020" },
- { label: "Smart-male-lead", value: "963" },
- { label: "Spirit Users", value: "739" },
- { label: "Straight Seme", value: "819" },
- { label: "Straight Uke", value: "818" },
- { label: "Strength-based-social-hierarchy", value: "974" },
- { label: "Strong-lead", value: "944" },
- { label: "Strong-male-lead", value: "964" },
- { label: "Student-teacher-relationship", value: "1026" },
- { label: "Suspense", value: "987" },
- { label: "Sword-and-sorcery", value: "875" },
- { label: "Threesome", value: "574" },
- { label: "Transformation Ability", value: "736" },
- { label: "Traumatising-content", value: "1040" },
- { label: "Underestimated-lead", value: "919" },
- { label: "Underestimated-male-lead", value: "966" },
- { label: "Unique-abilities", value: "1021" },
- { label: "Unique-skill", value: "1022" },
- { label: "Unique-skills", value: "1023" },
- { label: "Unlimited Flow", value: "1044" },
- { label: "Unrequited Love", value: "806" },
- { label: "Urban-fantasy", value: "1041" },
- { label: "Villainess Noble Girls", value: "719" },
- { label: "Weak-lead", value: "885" },
- { label: "Web-novel", value: "1024" },
- ],
- inputType: filterInputs_1.FilterInputs.Checkbox,
- },
- {
- key: "tags",
- label: "Жанры",
- values: [
- { label: "Боевые искусства", value: "22" },
- { label: "Гарем", value: "114" },
- { label: "Гендер бендер", value: "246" },
- { label: "Дзёсэй", value: "216" },
- { label: "Для взрослых", value: "115" },
- { label: "Для взрослых", value: "258" },
- { label: "Драма", value: "7" },
- { label: "Исторический", value: "101" },
- { label: "Комедия", value: "17" },
- { label: "Лоликон", value: "638" },
- { label: "Магический реализм", value: "922" },
- { label: "Меха", value: "24" },
- { label: "Милитари", value: "12" },
- { label: "Мистика", value: "2" },
- { label: "Научная фантастика", value: "13" },
- { label: "Непристойность", value: "747" },
- { label: "Повседневность", value: "93" },
- { label: "Приключение", value: "11" },
- { label: "Психология", value: "18" },
- { label: "Романтика", value: "9" },
- { label: "Сверхъестественное", value: "20" },
- { label: "Сёдзё", value: "15" },
- { label: "Сёдзё-ай", value: "23" },
- { label: "Сёнэн", value: "189" },
- { label: "Сёнэн-ай", value: "680" },
- { label: "Спорт", value: "420" },
- { label: "Сэйнэн", value: "5" },
- { label: "Сюаньхуа", value: "242" },
- { label: "Сянься", value: "364" },
- { label: "Трагедия", value: "19" },
- { label: "Триллер", value: "3" },
- { label: "Ужасы", value: "1" },
- { label: "Уся", value: "720" },
- { label: "Фэнтези", value: "8" },
- { label: "Школьная жизнь", value: "21" },
- { label: "Экшн", value: "14" },
- { label: "Эччи", value: "327" },
- { label: "Юри", value: "691" },
- { label: "Яой", value: "682" },
- { label: "Eastern fantasy", value: "907" },
- { label: "Isekai", value: "999" },
- { label: "Video games", value: "993" },
- ],
- inputType: filterInputs_1.FilterInputs.Checkbox,
- },
-];
diff --git a/js/plugins/russian/ranobelib.js b/js/plugins/russian/ranobelib.js
deleted file mode 100644
index 805aead..0000000
--- a/js/plugins/russian/ranobelib.js
+++ /dev/null
@@ -1,374 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.icon = exports.version = exports.site = exports.name = exports.id = void 0;
-const filterInputs_1 = require("@libs/filterInputs");
-const fetch_1 = require("@libs/fetch");
-const novelStatus_1 = require("@libs/novelStatus");
-const cheerio_1 = require("cheerio");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "RLIB";
-exports.name = "RanobeLib";
-exports.site = "https://ranobelib.me";
-exports.version = "1.0.0";
-exports.icon = "src/ru/ranobelib/icon.png";
-var ui;
-const popularNovels = function (page, { showLatestNovels, filters }) {
- var _a, _b, _c;
- return __awaiter(this, void 0, void 0, function* () {
- let url = `${exports.site}/manga-list?sort=`;
- url += showLatestNovels ? "last_chapter_at" : (filters === null || filters === void 0 ? void 0 : filters.sort) || "rate";
- url += "&dir=" + ((filters === null || filters === void 0 ? void 0 : filters.order) || "desc");
- if (filters) {
- if (Array.isArray(filters.type) && filters.type.length) {
- url += filters.type.map((i) => `&types[]=${i}`).join("");
- }
- if (Array.isArray(filters.format) && ((_a = filters.format) === null || _a === void 0 ? void 0 : _a.length)) {
- url += filters.format.map((i) => `&format[include][]=${i}`).join("");
- }
- if (Array.isArray(filters.status) && filters.status.length) {
- url += filters.status.map((i) => `&status[]=${i}`).join("");
- }
- if (Array.isArray(filters.statuss) && filters.statuss.length) {
- url += filters.statuss.map((i) => `&manga_status[]=${i}`).join("");
- }
- if (Array.isArray(filters.genres) && filters.genres.length) {
- url += filters.genres.map((i) => `&genres[include][]=${i}`).join("");
- }
- if (Array.isArray(filters.tags) && filters.tags.length) {
- url += filters.tags.map((i) => `&tags[include][]=${i}`).join("");
- }
- }
- url += "&page=" + page;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- ui = (_c = (_b = loadedCheerio("a.header-right-menu__item")
- .attr("href")) === null || _b === void 0 ? void 0 : _b.replace) === null || _c === void 0 ? void 0 : _c.call(_b, /[^0-9]/g, "");
- let novels = [];
- loadedCheerio(".media-card-wrap").each(function () {
- const name = loadedCheerio(this).find(".media-card__title").text();
- const cover = loadedCheerio(this).find("a.media-card").attr("data-src");
- const url = loadedCheerio(this).find("a.media-card").attr("href");
- if (!url)
- return;
- novels.push({ name, cover, url });
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- var _a, _b, _c, _d, _e, _f, _g;
- return __awaiter(this, void 0, void 0, function* () {
- const result = yield (0, fetch_1.fetchApi)(novelUrl);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- let novel = {
- url: novelUrl,
- };
- novel.name = loadedCheerio(".media-name__main").text().trim();
- novel.cover = loadedCheerio(".media-sidebar__cover img").attr("src");
- novel.summary = loadedCheerio(".media-description__text").text().trim();
- novel.genres = loadedCheerio('div[class="media-tags"]')
- .text()
- .trim()
- .replace(/[\n\r]+/g, ", ")
- .replace(/ /g, "");
- loadedCheerio('div[class="media-info-list paper"] > [class="media-info-list__item"]').each(function () {
- let name = loadedCheerio(this)
- .find('div[class="media-info-list__title"]')
- .text();
- if (name === "Статус перевода") {
- novel.status =
- loadedCheerio(this).find("div:nth-child(2)").text().trim() ===
- "Продолжается"
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- }
- else if (name === "Автор") {
- novel.author = loadedCheerio(this)
- .find("div:nth-child(2)")
- .text()
- .trim();
- }
- });
- let chapters = [];
- let chaptersRaw = body.match(/window.__DATA__ = [\s\S]*?window._SITE_COLOR_/gm);
- chaptersRaw = (_d = (_c = (_b = (_a = chaptersRaw === null || chaptersRaw === void 0 ? void 0 : chaptersRaw[0]) === null || _a === void 0 ? void 0 : _a.replace("window.__DATA__ = ", "")) === null || _b === void 0 ? void 0 : _b.replace("window._SITE_COLOR_", "")) === null || _c === void 0 ? void 0 : _c.trim()) === null || _d === void 0 ? void 0 : _d.slice(0, -1);
- let chaptersJson = JSON.parse(chaptersRaw);
- ui = (_e = chaptersJson === null || chaptersJson === void 0 ? void 0 : chaptersJson.user) === null || _e === void 0 ? void 0 : _e.id;
- (_g = (_f = chaptersJson.chapters) === null || _f === void 0 ? void 0 : _f.list) === null || _g === void 0 ? void 0 : _g.forEach((chapter) => {
- var _a;
- return chapters.push({
- name: (_a = `Том ${chapter.chapter_volume} Глава ${chapter.chapter_number} ${chapter.chapter_name}`) === null || _a === void 0 ? void 0 : _a.trim(),
- releaseTime: (0, dayjs_1.default)(chapter.chapter_created_at).format("LLL"),
- url: `${exports.site}/${chaptersJson.manga.slug}/v${chapter.chapter_volume}/c${chapter.chapter_number}?bid=` +
- ((chapter === null || chapter === void 0 ? void 0 : chapter.branch_id) || ""),
- });
- });
- novel.chapters = chapters.reverse();
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const result = yield (0, fetch_1.fetchApi)(chapterUrl + (ui ? `&ui=${ui}` : ""));
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio(".reader-container img").each(function () {
- const url = loadedCheerio(this).attr("data-src") || loadedCheerio(this).attr("src");
- if (!(url === null || url === void 0 ? void 0 : url.startsWith("http"))) {
- loadedCheerio(this).attr("src", exports.site + url);
- }
- else {
- loadedCheerio(this).attr("src", url);
- }
- loadedCheerio(this).removeAttr("data-src");
- });
- const chapterText = loadedCheerio(".reader-container").html();
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- return __awaiter(this, void 0, void 0, function* () {
- const result = yield (0, fetch_1.fetchApi)(`${exports.site}/search?q=${searchTerm}&type=manga`);
- const body = (yield result.json());
- let novels = [];
- body.forEach((novel) => novels.push({
- name: (novel === null || novel === void 0 ? void 0 : novel.rus_name) || novel.name,
- cover: novel === null || novel === void 0 ? void 0 : novel.coverImage,
- url: (novel === null || novel === void 0 ? void 0 : novel.href) || exports.site + "/" + novel.slug,
- }));
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-exports.fetchImage = fetch_1.fetchFile;
-exports.filters = [
- {
- key: "sort",
- label: "Сортировка",
- values: [
- { label: "Рейтинг", value: "rate" },
- { label: "Имя", value: "name" },
- { label: "Просмотры", value: "views" },
- { label: "Дате добавления", value: "created_at" },
- { label: "Дате обновления", value: "last_chapter_at" },
- { label: "Количество глав", value: "chap_count" },
- ],
- inputType: filterInputs_1.FilterInputs.Picker,
- },
- {
- key: "order",
- label: "Порядок",
- values: [
- { label: "По убыванию", value: "desc" },
- { label: "По возрастанию", value: "asc" },
- ],
- inputType: filterInputs_1.FilterInputs.Picker,
- },
- {
- key: "type",
- label: "Тип",
- values: [
- { label: "Авторский", value: "14" },
- { label: "Английский", value: "13" },
- { label: "Китай", value: "12" },
- { label: "Корея", value: "11" },
- { label: "Фанфик", value: "15" },
- { label: "Япония", value: "10" },
- ],
- inputType: filterInputs_1.FilterInputs.Checkbox,
- },
- {
- key: "format",
- label: "Формат выпуска",
- values: [
- { label: "4-кома (Ёнкома)", value: "1" },
- { label: "В цвете", value: "4" },
- { label: "Веб", value: "6" },
- { label: "Вебтун", value: "7" },
- { label: "Додзинси", value: "3" },
- { label: "Сборник", value: "2" },
- { label: "Сингл", value: "5" },
- ],
- inputType: filterInputs_1.FilterInputs.Checkbox,
- },
- {
- key: "status",
- label: "Статус перевода",
- values: [
- { label: "Продолжается", value: "1" },
- { label: "Завершен", value: "2" },
- { label: "Заморожен", value: "3" },
- { label: "Заброшен", value: "4" },
- ],
- inputType: filterInputs_1.FilterInputs.Checkbox,
- },
- {
- key: "statuss",
- label: "Статус тайтла",
- values: [
- { label: "Онгоинг", value: "1" },
- { label: "Завершён", value: "2" },
- { label: "Анонс", value: "3" },
- { label: "Приостановлен", value: "4" },
- { label: "Выпуск прекращён", value: "5" },
- ],
- inputType: filterInputs_1.FilterInputs.Checkbox,
- },
- {
- key: "genres",
- label: "Жанры",
- values: [
- { label: "Арт", value: "32" },
- { label: "Безумие", value: "91" },
- { label: "Боевик", value: "34" },
- { label: "Боевые искусства", value: "35" },
- { label: "Вампиры", value: "36" },
- { label: "Военное", value: "89" },
- { label: "Гарем", value: "37" },
- { label: "Гендерная интрига", value: "38" },
- { label: "Героическое фэнтези", value: "39" },
- { label: "Демоны", value: "81" },
- { label: "Детектив", value: "40" },
- { label: "Детское", value: "88" },
- { label: "Дзёсэй", value: "41" },
- { label: "Драма", value: "43" },
- { label: "Игра", value: "44" },
- { label: "Исекай", value: "79" },
- { label: "История", value: "45" },
- { label: "Киберпанк", value: "46" },
- { label: "Кодомо", value: "76" },
- { label: "Комедия", value: "47" },
- { label: "Космос", value: "83" },
- { label: "Магия", value: "85" },
- { label: "Махо-сёдзё", value: "48" },
- { label: "Машины", value: "90" },
- { label: "Меха", value: "49" },
- { label: "Мистика", value: "50" },
- { label: "Музыка", value: "80" },
- { label: "Научная фантастика", value: "51" },
- { label: "Омегаверс", value: "77" },
- { label: "Пародия", value: "86" },
- { label: "Повседневность", value: "52" },
- { label: "Полиция", value: "82" },
- { label: "Постапокалиптика", value: "53" },
- { label: "Приключения", value: "54" },
- { label: "Психология", value: "55" },
- { label: "Романтика", value: "56" },
- { label: "Самурайский боевик", value: "57" },
- { label: "Сверхъестественное", value: "58" },
- { label: "Сёдзё", value: "59" },
- { label: "Сёдзё-ай", value: "60" },
- { label: "Сёнэн", value: "61" },
- { label: "Сёнэн-ай", value: "62" },
- { label: "Спорт", value: "63" },
- { label: "Супер сила", value: "87" },
- { label: "Сэйнэн", value: "64" },
- { label: "Трагедия", value: "65" },
- { label: "Триллер", value: "66" },
- { label: "Ужасы", value: "67" },
- { label: "Фантастика", value: "68" },
- { label: "Фэнтези", value: "69" },
- { label: "Школа", value: "70" },
- { label: "Эротика", value: "71" },
- { label: "Этти", value: "72" },
- { label: "Юри", value: "73" },
- { label: "Яой", value: "74" },
- ],
- inputType: filterInputs_1.FilterInputs.Checkbox,
- },
- {
- key: "tags",
- label: "Теги",
- values: [
- { label: "Авантюристы", value: "328" },
- { label: "Антигерой", value: "176" },
- { label: "Бессмертные", value: "333" },
- { label: "Боги", value: "218" },
- { label: "Борьба за власть", value: "309" },
- { label: "Брат и сестра", value: "360" },
- { label: "Ведьма", value: "339" },
- { label: "Видеоигры", value: "204" },
- { label: "Виртуальная реальность", value: "214" },
- { label: "Владыка демонов", value: "349" },
- { label: "Военные", value: "198" },
- { label: "Воспоминания из другого мира", value: "310" },
- { label: "Выживание", value: "212" },
- { label: "ГГ женщина", value: "294" },
- { label: "ГГ имба", value: "292" },
- { label: "ГГ мужчина", value: "295" },
- { label: "ГГ не ояш", value: "325" },
- { label: "ГГ не человек", value: "331" },
- { label: "ГГ ояш", value: "326" },
- { label: "Главный герой бог", value: "324" },
- { label: "Глупый ГГ", value: "298" },
- { label: "Горничные", value: "171" },
- { label: "Гуро", value: "306" },
- { label: "Гяру", value: "197" },
- { label: "Демоны", value: "157" },
- { label: "Драконы", value: "313" },
- { label: "Древний мир", value: "317" },
- { label: "Зверолюди", value: "163" },
- { label: "Зомби", value: "155" },
- { label: "Исторические фигуры", value: "323" },
- { label: "Кулинария", value: "158" },
- { label: "Культивация", value: "161" },
- { label: "ЛГБТ", value: "344" },
- { label: "ЛитРПГ", value: "319" },
- { label: "Лоли", value: "206" },
- { label: "Магия", value: "170" },
- { label: "Машинный перевод", value: "345" },
- { label: "Медицина", value: "159" },
- { label: "Межгалактическая война", value: "330" },
- { label: "Монстр Девушки", value: "207" },
- { label: "Монстры", value: "208" },
- { label: "Мрачный мир", value: "316" },
- { label: "Музыка", value: "358" },
- { label: "Музыка", value: "209" },
- { label: "Ниндзя", value: "199" },
- { label: "Обратный Гарем", value: "210" },
- { label: "Офисные Работники", value: "200" },
- { label: "Пираты", value: "341" },
- { label: "Подземелья", value: "314" },
- { label: "Политика", value: "311" },
- { label: "Полиция", value: "201" },
- { label: "Преступники / Криминал", value: "205" },
- { label: "Призраки / Духи", value: "196" },
- { label: "Призыватели", value: "329" },
- { label: "Прыжки между мирами", value: "321" },
- { label: "Путешествие в другой мир", value: "318" },
- { label: "Путешествие во времени", value: "213" },
- { label: "Рабы", value: "355" },
- { label: "Ранги силы", value: "312" },
- { label: "Реинкарнация", value: "154" },
- { label: "Самураи", value: "202" },
- { label: "Скрытие личности", value: "315" },
- { label: "Средневековье", value: "174" },
- { label: "Традиционные игры", value: "203" },
- { label: "Умный ГГ", value: "303" },
- { label: "Характерный рост", value: "332" },
- { label: "Хикикомори", value: "167" },
- { label: "Эволюция", value: "322" },
- { label: "Элементы РПГ", value: "327" },
- { label: "Эльфы", value: "217" },
- { label: "Якудза", value: "165" },
- ],
- inputType: filterInputs_1.FilterInputs.Checkbox,
- },
-];
diff --git a/js/plugins/russian/ranoberf.js b/js/plugins/russian/ranoberf.js
deleted file mode 100644
index 1a0fc6a..0000000
--- a/js/plugins/russian/ranoberf.js
+++ /dev/null
@@ -1,143 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.icon = exports.version = exports.site = exports.name = exports.id = void 0;
-const filterInputs_1 = require("@libs/filterInputs");
-const defaultCover_1 = require("@libs/defaultCover");
-const fetch_1 = require("@libs/fetch");
-const novelStatus_1 = require("@libs/novelStatus");
-const cheerio_1 = require("cheerio");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "RNRF";
-exports.name = "РанобэРФ";
-exports.site = "https://ранобэ.рф";
-exports.version = "1.0.0";
-exports.icon = "src/ru/ranoberf/icon.png";
-const popularNovels = function (page, { showLatestNovels, filters }) {
- var _a, _b, _c;
- return __awaiter(this, void 0, void 0, function* () {
- let url = exports.site + "/books?order=";
- url += showLatestNovels ? "lastPublishedChapter" : (filters === null || filters === void 0 ? void 0 : filters.sort) || "popular";
- url += "&page=" + page;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- const jsonRaw = loadedCheerio("#__NEXT_DATA__").html();
- let json = JSON.parse(jsonRaw || '{}');
- let novels = [];
- (_c = (_b = (_a = json.props.pageProps) === null || _a === void 0 ? void 0 : _a.totalData) === null || _b === void 0 ? void 0 : _b.items) === null || _c === void 0 ? void 0 : _c.forEach((novel) => {
- var _a;
- return novels.push({
- name: novel.title,
- cover: ((_a = novel === null || novel === void 0 ? void 0 : novel.verticalImage) === null || _a === void 0 ? void 0 : _a.url)
- ? exports.site + novel.verticalImage.url
- : defaultCover_1.defaultCover,
- url: exports.site + "/" + novel.slug,
- });
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- var _a, _b;
- return __awaiter(this, void 0, void 0, function* () {
- const result = yield (0, fetch_1.fetchApi)(novelUrl);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- const jsonRaw = loadedCheerio("#__NEXT_DATA__").html();
- const book = JSON.parse(jsonRaw || '{}').props.pageProps.book;
- let novel = {
- url: novelUrl,
- name: book === null || book === void 0 ? void 0 : book.title,
- cover: ((_a = book === null || book === void 0 ? void 0 : book.verticalImage) === null || _a === void 0 ? void 0 : _a.url)
- ? exports.site + book.verticalImage.url
- : defaultCover_1.defaultCover,
- summary: book === null || book === void 0 ? void 0 : book.description,
- author: (book === null || book === void 0 ? void 0 : book.author) || "",
- genres: book === null || book === void 0 ? void 0 : book.genres.map((item) => item.title).join(", "),
- status: (book === null || book === void 0 ? void 0 : book.additionalInfo.includes("Активен"))
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed,
- };
- let chapters = [];
- (_b = book === null || book === void 0 ? void 0 : book.chapters) === null || _b === void 0 ? void 0 : _b.forEach((chapter) => {
- if (!(chapter === null || chapter === void 0 ? void 0 : chapter.isDonate) || (chapter === null || chapter === void 0 ? void 0 : chapter.isUserPaid)) {
- chapters.push({
- name: chapter.title,
- releaseTime: (0, dayjs_1.default)(chapter.publishedAt).format("LLL"),
- url: exports.site + chapter.url,
- });
- }
- });
- novel.chapters = chapters.reverse();
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- var _a, _b, _c;
- return __awaiter(this, void 0, void 0, function* () {
- const result = yield (0, fetch_1.fetchApi)(chapterUrl);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- let jsonRaw = loadedCheerio("#__NEXT_DATA__").html();
- let json = JSON.parse(jsonRaw || '{}');
- loadedCheerio = (0, cheerio_1.load)(((_c = (_b = (_a = json.props.pageProps) === null || _a === void 0 ? void 0 : _a.chapter) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.text) || "");
- loadedCheerio("img").each(function () {
- var _a;
- if (!((_a = loadedCheerio(this).attr("src")) === null || _a === void 0 ? void 0 : _a.startsWith("http"))) {
- const src = loadedCheerio(this).attr("src");
- loadedCheerio(this).attr("src", exports.site + src);
- }
- });
- const chapterText = loadedCheerio.html();
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = `${exports.site}/v3/books?filter[or][0][title][like]=${searchTerm}&filter[or][1][titleEn][like]=${searchTerm}&filter[or][2][fullTitle][like]=${searchTerm}&filter[status][]=active&filter[status][]=abandoned&filter[status][]=completed&expand=verticalImage`;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = (yield result.json());
- let novels = [];
- body.items.forEach((novel) => {
- var _a;
- return novels.push({
- name: novel.title,
- cover: ((_a = novel === null || novel === void 0 ? void 0 : novel.verticalImage) === null || _a === void 0 ? void 0 : _a.url)
- ? exports.site + novel.verticalImage.url
- : defaultCover_1.defaultCover,
- url: exports.site + "/" + novel.slug,
- });
- });
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-exports.fetchImage = fetch_1.fetchFile;
-exports.filters = [
- {
- key: "sort",
- label: "Сортировка",
- values: [
- { label: "Рейтинг", value: "popular" },
- { label: "Дате добавления", value: "new" },
- { label: "Дате обновления", value: "lastPublishedChapter" },
- { label: "Законченные", value: "completed" },
- ],
- inputType: filterInputs_1.FilterInputs.Picker,
- },
-];
diff --git a/js/plugins/russian/renovels.js b/js/plugins/russian/renovels.js
deleted file mode 100644
index 792d4f4..0000000
--- a/js/plugins/russian/renovels.js
+++ /dev/null
@@ -1,941 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.icon = exports.version = exports.site = exports.name = exports.id = void 0;
-const filterInputs_1 = require("@libs/filterInputs");
-const fetch_1 = require("@libs/fetch");
-const novelStatus_1 = require("@libs/novelStatus");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "ReN";
-exports.name = "Renovels";
-exports.site = "https://renovels.org";
-exports.version = "1.0.0";
-exports.icon = "src/ru/renovels/icon.png";
-const popularNovels = function (page, { showLatestNovels, filters }) {
- return __awaiter(this, void 0, void 0, function* () {
- let url = exports.site + "/api/search/catalog/?count=30&ordering=";
- url += (filters === null || filters === void 0 ? void 0 : filters.order) ? filters.order.replace("+", "") : "-";
- url += showLatestNovels ? "chapter_date" : (filters === null || filters === void 0 ? void 0 : filters.sort) || "rating";
- if ((filters === null || filters === void 0 ? void 0 : filters.genres) instanceof Array) {
- url += filters.genres.map((i) => `&genres=${i}`).join("");
- }
- if ((filters === null || filters === void 0 ? void 0 : filters.status) instanceof Array) {
- url += filters === null || filters === void 0 ? void 0 : filters.status.map((i) => `&status=${i}`).join("");
- }
- if ((filters === null || filters === void 0 ? void 0 : filters.types) instanceof Array) {
- url += filters.types.map((i) => `&types=${i}`).join("");
- }
- if ((filters === null || filters === void 0 ? void 0 : filters.categories) instanceof Array) {
- url += filters.categories.map((i) => `&categories=${i}`).join("");
- }
- if ((filters === null || filters === void 0 ? void 0 : filters.age_limit) instanceof Array) {
- url += filters.age_limit.map((i) => `&age_limit=${i}`).join("");
- }
- url += "&page=" + page;
- const result = yield (0, fetch_1.fetchApi)(url);
- let body = (yield result.json());
- let novels = [];
- body.content.forEach((novel) => {
- var _a, _b;
- return novels.push({
- name: novel.main_name || novel.secondary_name,
- cover: exports.site + (((_a = novel.img) === null || _a === void 0 ? void 0 : _a.high) || ((_b = novel.img) === null || _b === void 0 ? void 0 : _b.mid) || novel.img.low),
- url: exports.site + "/novel/" + novel.dir,
- });
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- var _a, _b, _c, _d, _e, _f;
- return __awaiter(this, void 0, void 0, function* () {
- let novelID = novelUrl.split("/")[4];
- const result = yield (0, fetch_1.fetchApi)(exports.site + "/api/titles/" + novelID);
- let body = (yield result.json());
- let novel = {
- url: novelUrl,
- name: body.content.main_name || body.content.secondary_name,
- summary: body.content.description,
- cover: exports.site +
- (((_a = body.content.img) === null || _a === void 0 ? void 0 : _a.high) ||
- ((_b = body.content.img) === null || _b === void 0 ? void 0 : _b.mid) ||
- body.content.img.low),
- status: body.content.status.name === "Продолжается"
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed,
- };
- let tags = [(_c = body.content) === null || _c === void 0 ? void 0 : _c.genres, (_d = body.content) === null || _d === void 0 ? void 0 : _d.categories]
- .flat()
- .map((tags) => tags === null || tags === void 0 ? void 0 : tags.name)
- .filter((tags) => tags);
- if (tags.length > 0) {
- novel.genres = tags.join(",");
- }
- let all = Math.floor(body.content.count_chapters / 100 + 1);
- let branch_id = ((_f = (_e = body.content.branches) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.id) || body.content.id;
- let chapters = [];
- for (let i = 0; i < all; i++) {
- let chapterResult = yield (0, fetch_1.fetchApi)(exports.site +
- "/api/titles/chapters/?branch_id=" +
- branch_id +
- "&count=100&page=" +
- (i + 1));
- let volumes = (yield chapterResult.json());
- volumes.content.forEach((chapter) => {
- var _a;
- if (!chapter.is_paid || chapter.is_bought) {
- chapters.push({
- name: (_a = `Том ${chapter.tome} Глава ${chapter.chapter} ${chapter.name}`) === null || _a === void 0 ? void 0 : _a.trim(),
- releaseTime: (0, dayjs_1.default)(chapter.upload_date).format("LLL"),
- url: `${exports.site}/novel/${novelID}/${chapter.id}/`,
- });
- }
- });
- }
- novel.chapters = chapters.reverse();
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- let url = exports.site + "/api/titles/chapters/" + chapterUrl.split("/")[5];
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = (yield result.json());
- return body.content.content;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = `${exports.site}/api/search/?query=${searchTerm}&count=100&field=titles`;
- const result = yield (0, fetch_1.fetchApi)(url);
- let body = (yield result.json());
- let novels = [];
- body.content.forEach((novel) => {
- var _a, _b;
- return novels.push({
- name: novel.main_name || novel.secondary_name,
- cover: exports.site + (((_a = novel.img) === null || _a === void 0 ? void 0 : _a.high) || ((_b = novel.img) === null || _b === void 0 ? void 0 : _b.mid) || novel.img.low),
- url: exports.site + "/novel/" + novel.dir,
- });
- });
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-exports.fetchImage = fetch_1.fetchFile;
-exports.filters = [
- {
- key: "sort",
- label: "Сортировка",
- values: [
- { label: "Рейтинг", value: "rating" },
- { label: "Просмотры", value: "views" },
- { label: "Лайкам", value: "votes" },
- { label: "Дате добавления", value: "id" },
- { label: "Дате обновления", value: "chapter_date" },
- { label: "Количество глав", value: "count_chapters" },
- ],
- inputType: filterInputs_1.FilterInputs.Picker,
- },
- {
- key: "order",
- label: "Порядок",
- values: [
- { label: "По убыванию", value: "-" },
- { label: "По возрастанию", value: "+" },
- ],
- inputType: filterInputs_1.FilterInputs.Picker,
- },
- {
- key: "genres",
- label: "Жанры:",
- values: [
- { label: "Боевик", value: "112" },
- { label: "Война", value: "123" },
- { label: "Детектив", value: "114" },
- { label: "Драма", value: "125" },
- { label: "Историческая проза", value: "115" },
- { label: "ЛитРПГ", value: "109" },
- { label: "Любовные романы", value: "116" },
- { label: "Мистика", value: "103" },
- { label: "Научная фантастика", value: "121" },
- { label: "Повседневность", value: "128" },
- { label: "Подростковая проза", value: "113" },
- { label: "Политический роман", value: "119" },
- { label: "Попаданцы", value: "108" },
- { label: "Поэзия", value: "105" },
- { label: "Разное", value: "111" },
- { label: "РеалРПГ", value: "117" },
- { label: "Романтика", value: "126" },
- { label: "Современная проза", value: "102" },
- { label: "Современная фантастика", value: "127" },
- { label: "Спорт", value: "122" },
- { label: "Трагедия", value: "129" },
- { label: "Триллер", value: "110" },
- { label: "Триллер и саспенс", value: "124" },
- { label: "Ужасы", value: "106" },
- { label: "Фантастика", value: "101" },
- { label: "Фанфик", value: "107" },
- { label: "Фьюжн роман", value: "120" },
- { label: "Фэнтези", value: "100" },
- { label: "Эротика", value: "118" },
- { label: "Юмор", value: "104" },
- ],
- inputType: filterInputs_1.FilterInputs.Checkbox,
- },
- {
- key: "categories",
- label: "Тэги:",
- values: [
- { label: "[Награжденная работа]", value: "648" },
- { label: "18+", value: "423" },
- { label: "Абьюзеры", value: "663" },
- { label: "Авантюристы", value: "436" },
- { label: "Автоматоны", value: "593" },
- { label: "Агрессивные персонажи", value: "502" },
- { label: "Ад", value: "569" },
- { label: "Адаптация в радиопостановку", value: "581" },
- { label: "Академия", value: "153" },
- { label: "Актеры озвучки", value: "627" },
- { label: "Активный главный герой", value: "251" },
- { label: "Алхимия", value: "233" },
- { label: "Альтернативная история", value: "147" },
- { label: "Альтернативный мир", value: "156" },
- { label: "Амнезия/Потеря памяти", value: "344" },
- { label: "Анабиоз", value: "685" },
- { label: "Ангелы", value: "183" },
- { label: "Андрогинные персонажи", value: "321" },
- { label: "Андроиды", value: "203" },
- { label: "Анти-магия", value: "533" },
- { label: "Антигерой", value: "432" },
- { label: "Антикварный магазин", value: "623" },
- { label: "Антисоциальный главный герой", value: "613" },
- { label: "Антиутопия", value: "142" },
- { label: "Апатичный протагонист", value: "157" },
- { label: "Апокалипсис", value: "402" },
- { label: "Аранжированный брак", value: "375" },
- { label: "Армия", value: "639" },
- { label: "Артефакты", value: "234" },
- { label: "Артисты", value: "523" },
- { label: "Банды", value: "630" },
- { label: "БДСМ", value: "699" },
- { label: "Бедный главный герой", value: "398" },
- { label: "Безжалостный главный герой", value: "261" },
- { label: "Беззаботный главный герой", value: "438" },
- { label: "Безусловная любовь", value: "679" },
- { label: "Беременность", value: "250" },
- { label: "Бесполый главный герой", value: "325" },
- { label: "Бессмертные", value: "368" },
- { label: "Бесстрашный протагонист", value: "656" },
- { label: "Бесстыдный главный герой", value: "352" },
- { label: "Бесчестный главный герой", value: "716" },
- { label: "Библиотека", value: "428" },
- { label: "Бизнес-литература", value: "121" },
- { label: "Бизнесмен", value: "769" },
- { label: "Биочип", value: "238" },
- { label: "Бисексуальный главный герой", value: "773" },
- { label: "Близнецы", value: "263" },
- { label: "Боги", value: "317" },
- { label: "Богини", value: "439" },
- { label: "Боевая академия", value: "450" },
- { label: "Боевая фантастика", value: "149" },
- { label: "Боевое фэнтези", value: "104" },
- { label: "Боевые духи", value: "433" },
- { label: "Боевые соревнования", value: "493" },
- { label: "Божественная защита", value: "421" },
- { label: "Божественные силы", value: "327" },
- { label: "Борьба за власть", value: "599" },
- { label: "Брак", value: "446" },
- { label: "Брак по расчету", value: "188" },
- { label: "Братский комплекс", value: "159" },
- { label: "Братство", value: "487" },
- { label: "Братья и сестры", value: "577" },
- { label: "Буддизм", value: "745" },
- { label: "Быстрая культивация", value: "366" },
- { label: "Быстрообучаемый", value: "324" },
- { label: "Валькирии", value: "692" },
- { label: "Вампиры", value: "360" },
- { label: "Ваншот", value: "702" },
- { label: "Ведьмы", value: "281" },
- { label: "Вежливый главный герой", value: "379" },
- { label: "Верные подчиненные", value: "328" },
- { label: "Взрослый главный герой", value: "295" },
- { label: "Видит то, чего не видят другие", value: "671" },
- { label: "Виртуальная реальность", value: "401" },
- { label: "Владелец магазина", value: "681" },
- { label: "Внезапная сила", value: "455" },
- { label: "Внезапное богатство", value: "765" },
- { label: "Внешний вид отличается от факт", value: "419" },
- { label: "Военные Летописи", value: "743" },
- { label: "Возвращение из другого мира", value: "696" },
- { label: "Войны", value: "181" },
- { label: "Вокалоид", value: "701" },
- { label: "Волшебники/Волшебницы", value: "539" },
- { label: "Волшебные звери", value: "308" },
- { label: "Воображаемый друг", value: "651" },
- { label: "Воры", value: "414" },
- { label: "Воскрешение", value: "199" },
- { label: "Враги становятся возлюбленными", value: "498" },
- { label: "Враги становятся союзниками", value: "562" },
- { label: "Врата в другой мир", value: "609" },
- { label: "Врачи", value: "376" },
- { label: "Временной парадокс", value: "275" },
- { label: "Всемогущий главный герой", value: "169" },
- { label: "Вторжение на землю", value: "198" },
- { label: "Второй шанс", value: "231" },
- { label: "Вуайеризм", value: "790" },
- { label: "Выживание", value: "380" },
- { label: "Высокомерные персонажи", value: "361" },
- { label: "Гадание", value: "595" },
- { label: "Гарем рабов", value: "777" },
- { label: "Гг - женщина", value: "186" },
- { label: "Гг - мужчина", value: "166" },
- { label: "Гг силен с самого начала", value: "171" },
- { label: "Геймеры", value: "392" },
- { label: "Генералы", value: "326" },
- { label: "Генетические модификации", value: "657" },
- { label: "Гениальный главный герой", value: "617" },
- { label: "Герои", value: "285" },
- { label: "Героиня — сорванец", value: "583" },
- { label: "Героическая фантастика", value: "140" },
- { label: "Героическое фэнтези", value: "107" },
- { label: "Герой влюбляется первым", value: "187" },
- { label: "Гетерохромия", value: "570" },
- { label: "Гильдии", value: "411" },
- { label: "Гипнотизм", value: "755" },
- { label: "Главный герой — бог", value: "547" },
- { label: "Главный герой — гуманоид", value: "636" },
- { label: "Главный герой — наполовину чел", value: "445" },
- { label: "Главный герой — отец", value: "792" },
- { label: "Главный герой — раб", value: "780" },
- { label: "Главный герой — ребенок", value: "488" },
- { label: "Главный герой — рубака", value: "476" },
- { label: "Главный герой влюбляется первы", value: "683" },
- { label: "Главный герой играет роль", value: "472" },
- { label: "Главный герой носит очки", value: "672" },
- { label: "Главный герой пацифист", value: "698" },
- { label: "Гладиаторы", value: "603" },
- { label: "Глуповатый главный герой", value: "385" },
- { label: "Гоблины", value: "586" },
- { label: "Големы", value: "620" },
- { label: "Гомункул", value: "789" },
- { label: "Горничные", value: "459" },
- { label: "Городское фэнтези", value: "105" },
- { label: "Госпиталь", value: "800" },
- { label: "Готовка", value: "302" },
- { label: "Гриндинг", value: "393" },
- { label: "Дао Компаньон", value: "462" },
- { label: "Даосизм", value: "760" },
- { label: "Дварфы", value: "323" },
- { label: "Двойная личность", value: "642" },
- { label: "Двойник", value: "601" },
- { label: "Дворецкий", value: "660" },
- { label: "Дворяне", value: "168" },
- { label: "Дворянство/Аристократия", value: "437" },
- { label: "Девушки-монстры", value: "669" },
- { label: "Демоническая техника культивац", value: "722" },
- { label: "Демоны", value: "152" },
- { label: "Денежный долг", value: "783" },
- { label: "Депрессия", value: "555" },
- { label: "Детектив", value: "116" },
- { label: "Детективы", value: "612" },
- { label: "Детская литература", value: "123" },
- { label: "Дискриминация", value: "162" },
- { label: "Добыча денег в приоритете", value: "396" },
- { label: "Документальная проза", value: "122" },
- { label: "Долгая разлука", value: "307" },
- { label: "Домашние дела", value: "290" },
- { label: "Домогательство", value: "470" },
- { label: "Драконы", value: "303" },
- { label: "Драконьи всадники", value: "607" },
- { label: "Древние времена", value: "221" },
- { label: "Древний Китай", value: "374" },
- { label: "Дружба", value: "217" },
- { label: "Друзья детства", value: "282" },
- { label: "Друзья становятся врагами", value: "567" },
- { label: "Друиды", value: "497" },
- { label: "Дух лисы", value: "784" },
- { label: "Духи/призраки", value: "172" },
- { label: "Духовный советник", value: "435" },
- { label: "Душевность", value: "633" },
- { label: "Души", value: "254" },
- { label: "Европейская атмосфера", value: "521" },
- { label: "Ёкаи", value: "575" },
- { label: "Есть аниме-адаптация", value: "154" },
- { label: "Есть видеоигра по мотивам", value: "552" },
- { label: "Есть манга", value: "155" },
- { label: "Есть манхва-адаптация", value: "517" },
- { label: "Есть маньхуа-адаптация", value: "388" },
- { label: "Есть сериал-адаптация", value: "492" },
- { label: "Есть фильм", value: "173" },
- { label: "Женища-наставник", value: "505" },
- { label: "Жесткая, двуличная личность", value: "346" },
- { label: "Жестокие персонажи", value: "503" },
- { label: "Жестокое обращение с ребенком", value: "654" },
- { label: "Жестокость", value: "245" },
- { label: "Животноводство", value: "754" },
- { label: "Животные черты", value: "528" },
- { label: "Жизнь в квартире", value: "606" },
- { label: "Жрицы", value: "615" },
- { label: "Заботливый главный герой", value: "288" },
- { label: "Забывчивый главный герой", value: "628" },
- { label: "Заговоры", value: "289" },
- { label: "Закалка тела", value: "362" },
- { label: "Законники", value: "756" },
- { label: "Замкнутый главный герой", value: "589" },
- { label: "Запечатанная сила", value: "430" },
- { label: "Застенчивые персонажи", value: "508" },
- { label: "Звери", value: "237" },
- { label: "Звери-компаньоны", value: "301" },
- { label: "Злой протагонист", value: "243" },
- { label: "Злые боги", value: "504" },
- { label: "Злые организации", value: "563" },
- { label: "Злые религии", value: "734" },
- { label: "Знаменитости", value: "473" },
- { label: "Знаменитый главный герой", value: "531" },
- { label: "Знания современного мира", value: "297" },
- { label: "Зомби", value: "409" },
- { label: "Игра на выживание", value: "274" },
- { label: "Игривый протагонист", value: "717" },
- { label: "Игровая система рейтинга", value: "391" },
- { label: "Игровые элементы", value: "266" },
- { label: "Игрушки (18+)", value: "676" },
- { label: "Из грязи в князи", value: "416" },
- { label: "Из женщины в мужчину", value: "709" },
- { label: "Из мужчины в женщину", value: "715" },
- { label: "Из полного в худого", value: "767" },
- { label: "Из слабого в сильного", value: "202" },
- { label: "Извращенный главный герой", value: "434" },
- { label: "Изгои", value: "534" },
- { label: "Изменение расы", value: "664" },
- { label: "Изменения внешнего вида", value: "300" },
- { label: "Изменения личности", value: "219" },
- { label: "Изнасилование", value: "229" },
- { label: "Изображения жестокости", value: "355" },
- { label: "ИИ", value: "235" },
- { label: "Империи", value: "748" },
- { label: "Инвалидность", value: "684" },
- { label: "Индустриализация", value: "292" },
- { label: "Инженер", value: "163" },
- { label: "Инцест", value: "525" },
- { label: "Искусственный интеллект", value: "236" },
- { label: "Исследования", value: "670" },
- { label: "Историческая проза", value: "119" },
- { label: "Исторические приключения", value: "120" },
- { label: "Исторический детектив", value: "117" },
- { label: "Исторический любовный роман", value: "138" },
- { label: "Историческое фэнтези", value: "110" },
- { label: "Каннибализм", value: "456" },
- { label: "Карточные игры", value: "682" },
- { label: "Киберпанк", value: "141" },
- { label: "Киберспорт", value: "686" },
- { label: "Кланы", value: "796" },
- { label: "Класс безработного", value: "735" },
- { label: "Клоны", value: "447" },
- { label: "Клубы", value: "216" },
- { label: "Книги", value: "427" },
- { label: "Книги навыков", value: "400" },
- { label: "Книжный червь", value: "519" },
- { label: "Коварство", value: "230" },
- { label: "Коллеги", value: "704" },
- { label: "Колледж/Университет", value: "726" },
- { label: "Кома", value: "776" },
- { label: "Командная работа", value: "496" },
- { label: "Комедийный оттенок", value: "582" },
- { label: "Комплекс неполноценности", value: "550" },
- { label: "Комплекс семейных отношений", value: "223" },
- { label: "Конкуренция", value: "746" },
- { label: "Контроль разума/сознания", value: "357" },
- { label: "Копейщик", value: "425" },
- { label: "Королевская битва", value: "797" },
- { label: "Королевская власть", value: "178" },
- { label: "Королевства", value: "259" },
- { label: "Короткий любовный роман", value: "136" },
- { label: "Коррупция", value: "457" },
- { label: "Космическая фантастика", value: "146" },
- { label: "Космические войны", value: "697" },
- { label: "Красивый герой", value: "226" },
- { label: "Крафт", value: "377" },
- { label: "Кризис личности", value: "640" },
- { label: "Кругосветное путешествие", value: "353" },
- { label: "Кудере", value: "506" },
- { label: "Кузены", value: "718" },
- { label: "Кузнец", value: "518" },
- { label: "Кукловоды", value: "501" },
- { label: "Куклы/марионетки", value: "624" },
- { label: "Культивация", value: "241" },
- { label: "Куннилингус", value: "667" },
- { label: "Легенды", value: "500" },
- { label: "Легкая жизнь", value: "644" },
- { label: "Ленивый главный герой", value: "621" },
- { label: "Лидерство", value: "494" },
- { label: "Лоли", value: "213" },
- { label: "Лотерея", value: "477" },
- { label: "Любовное фэнтези", value: "135" },
- { label: "Любовный треугольник", value: "218" },
- { label: "Любовь детства", value: "560" },
- { label: "Любовь с первого взгляда", value: "737" },
- { label: "Магические надписи", value: "453" },
- { label: "Магические печати", value: "369" },
- { label: "Магические технологии", value: "440" },
- { label: "Магия", value: "165" },
- { label: "Магия призыва", value: "418" },
- { label: "Мазохистские персонажи", value: "688" },
- { label: "Манипулятивные персонажи", value: "249" },
- { label: "Мания", value: "212" },
- { label: "Мастер на все руки", value: "466" },
- { label: "Мастурбация", value: "788" },
- { label: "Махо-сёдзё", value: "556" },
- { label: "Медицинские знания", value: "507" },
- { label: "Медленная романтическая линия", value: "232" },
- { label: "Медленное развитие на старте", value: "694" },
- { label: "Межпространственные путешестви", value: "404" },
- { label: "Менеджмент", value: "294" },
- { label: "Мертвый главный герой", value: "761" },
- { label: "Месть", value: "209" },
- { label: "Метаморфы", value: "335" },
- { label: "Меч и магия", value: "180" },
- { label: "Мечник", value: "647" },
- { label: "Мечты", value: "738" },
- { label: "Милая история", value: "725" },
- { label: "Милое дитя", value: "637" },
- { label: "Милый главный герой", value: "714" },
- { label: "Мировое дерево", value: "463" },
- { label: "Мистика", value: "151" },
- { label: "Мистический ореол вокруг семьи", value: "483" },
- { label: "Мифические звери", value: "491" },
- { label: "Мифология", value: "530" },
- { label: "Младшие братья", value: "785" },
- { label: "Младшие сестры", value: "527" },
- { label: "ММОРПГ (ЛитРПГ)", value: "395" },
- { label: "Множество перемещенных людей", value: "549" },
- { label: "Множество реальностей", value: "370" },
- { label: "Множество реинкарнированных лю", value: "330" },
- { label: "Модели", value: "678" },
- { label: "Молчаливый персонаж", value: "721" },
- { label: "Монстры", value: "192" },
- { label: "Мужская гей-пара", value: "706" },
- { label: "Мужчина-яндере", value: "267" },
- { label: "Музыка", value: "635" },
- { label: "Музыкальные группы", value: "634" },
- { label: "Мутации", value: "693" },
- { label: "Мутированные существа", value: "405" },
- { label: "Навык кражи", value: "662" },
- { label: "Навязчивая любовь", value: "206" },
- { label: "Наемники", value: "412" },
- { label: "Назойливый возлюбленный", value: "561" },
- { label: "Наивный главный герой", value: "189" },
- { label: "Наркотики", value: "689" },
- { label: "Нарциссический главный герой", value: "532" },
- { label: "Насилие сексуального характера", value: "774" },
- { label: "Наследование", value: "452" },
- { label: "Научная фантастика", value: "144" },
- { label: "Национализм", value: "406" },
- { label: "Не блещущий внешне главный гер", value: "415" },
- { label: "Не родные братья и сестры", value: "526" },
- { label: "Небеса", value: "568" },
- { label: "Небесное испытание", value: "367" },
- { label: "Негуманоидный главный герой", value: "659" },
- { label: "Недоверчивый главный герой", value: "546" },
- { label: "Недооцененный главный герой", value: "258" },
- { label: "Недоразумения", value: "309" },
- { label: "Неизлечимая болезнь", value: "196" },
- { label: "Некромант", value: "397" },
- { label: "Нелинейная история", value: "269" },
- { label: "Ненавистный главный герой", value: "548" },
- { label: "Ненадежный рассказчик", value: "277" },
- { label: "Нерезиденты", value: "772" },
- { label: "Нерешительный главный герой", value: "744" },
- { label: "Несерьезный главный герой", value: "384" },
- { label: "Несколько временных линий", value: "576" },
- { label: "Несколько гг", value: "268" },
- { label: "Несколько главных героев", value: "537" },
- { label: "Несколько идентичностей", value: "652" },
- { label: "Несколько личностей", value: "536" },
- { label: "Нетораре", value: "732" },
- { label: "Нетори", value: "514" },
- { label: "Неудачливый главный герой", value: "618" },
- { label: "Ниндзя", value: "441" },
- { label: "Новелла", value: "103" },
- { label: "Обещание из детства", value: "742" },
- { label: "Обманщик", value: "485" },
- { label: "Обмен телами", value: "214" },
- { label: "Обнаженка", value: "490" },
- { label: "Обольщение", value: "731" },
- { label: "Оборотни", value: "661" },
- { label: "Обратный гарем", value: "351" },
- { label: "Общество монстров", value: "329" },
- { label: "Обязательство", value: "602" },
- { label: "Огнестрельное оружие", value: "291" },
- { label: "Ограниченное время жизни", value: "194" },
- { label: "Одержимость", value: "512" },
- { label: "Одинокий главный герой", value: "394" },
- { label: "Одиночество", value: "306" },
- { label: "Одиночное проживание", value: "313" },
- { label: "Околосмертные переживания", value: "759" },
- { label: "Оммёдзи", value: "597" },
- { label: "Омоложение", value: "338" },
- { label: "Организованная преступность", value: "540" },
- { label: "Оргия", value: "775" },
- { label: "Орки", value: "331" },
- { label: "Освоение навыков", value: "336" },
- { label: "Основано на аниме", value: "605" },
- { label: "Основано на видео игре", value: "720" },
- { label: "Основано на визуальной новелле", value: "793" },
- { label: "Основано на песне", value: "700" },
- { label: "Основано на фильме", value: "604" },
- { label: "Осторожный главный герой", value: "240" },
- { label: "Отаку", value: "571" },
- { label: "Открытый космос", value: "264" },
- { label: "Отношения в сети", value: "727" },
- { label: "Отношения между людьми и нелюд", value: "311" },
- { label: "Отношения на расстоянии", value: "791" },
- { label: "Отношения Сенпай-Коухай", value: "572" },
- { label: "Отношения ученика и учителя", value: "515" },
- { label: "Отношения учитель-ученик", value: "429" },
- { label: "Отношения хозяин-слуга", value: "312" },
- { label: "Отомэ игра", value: "733" },
- { label: "Отсутствие здравого смысла", value: "645" },
- { label: "Отсутствие родителей", value: "625" },
- { label: "Офисный роман", value: "707" },
- { label: "Официанты", value: "703" },
- { label: "Охотники", value: "378" },
- { label: "Очаровательный главный герой", value: "687" },
- { label: "Падшее дворянство", value: "655" },
- { label: "Падшие ангелы", value: "565" },
- { label: "Пайзури", value: "665" },
- { label: "Паразиты", value: "591" },
- { label: "Параллельные миры", value: "207" },
- { label: "Парк", value: "265" },
- { label: "Парк развлечений", value: "632" },
- { label: "Пародия", value: "407" },
- { label: "Певцы/Певицы", value: "739" },
- { label: "Первая любовь", value: "729" },
- { label: "Первоисточник новеллы — манга", value: "611" },
- { label: "Первый раз", value: "787" },
- { label: "Перемещение в игровой мир", value: "588" },
- { label: "Перемещение в иной мир", value: "750" },
- { label: "Перерождение в ином мире", value: "751" },
- { label: "Переселение души/трансмиграция", value: "257" },
- { label: "Персонаж использует щит", value: "666" },
- { label: "Петля времени", value: "200" },
- { label: "Пираты", value: "771" },
- { label: "Писатели", value: "482" },
- { label: "Питомцы", value: "349" },
- { label: "Племенное общество", value: "381" },
- { label: "Повелитель демонов", value: "283" },
- { label: "Подземелья", value: "322" },
- { label: "Подростковая проза", value: "114" },
- { label: "Пожелания", value: "278" },
- { label: "Познание Дао", value: "443" },
- { label: "Покинутое дитя", value: "590" },
- { label: "Полигамия", value: "386" },
- { label: "Политика", value: "170" },
- { label: "Политический роман", value: "133" },
- { label: "Полиция", value: "764" },
- { label: "Полулюди", value: "420" },
- { label: "Популярный любовный интерес", value: "342" },
- { label: "Постапокалипсис", value: "145" },
- { label: "Постапокалиптика", value: "184" },
- { label: "Потерянные цивилизации", value: "749" },
- { label: "Похищения людей", value: "723" },
- { label: "Поэзия", value: "111" },
- { label: "Правонарушители", value: "713" },
- { label: "Прагматичный главный герой", value: "592" },
- { label: "Преданный любовный интерес", value: "225" },
- { label: "Предательство", value: "222" },
- { label: "Предвидение", value: "177" },
- { label: "Прекрасная героиня", value: "158" },
- { label: "Преступники", value: "736" },
- { label: "Преступность", value: "204" },
- { label: "Призванный герой", value: "262" },
- { label: "Призраки", value: "176" },
- { label: "Принуждение к отношениям", value: "643" },
- { label: "Принцессы", value: "795" },
- { label: "Притворная пара", value: "641" },
- { label: "Причудливые персонажи", value: "387" },
- { label: "Пришельцы/инопланетяне", value: "197" },
- { label: "Программист", value: "691" },
- { label: "Проклятия", value: "174" },
- { label: "Промывание мозгов", value: "578" },
- { label: "Пропуск времени", value: "256" },
- { label: "Пророчества", value: "499" },
- { label: "Проститутки", value: "786" },
- { label: "Прошлое играет большую роль", value: "320" },
- { label: "Прыжки между мирами", value: "741" },
- { label: "Психические силы", value: "359" },
- { label: "Психопаты", value: "270" },
- { label: "Публицистика", value: "124" },
- { label: "Путешествие во времени", value: "201" },
- { label: "Пытка", value: "280" },
- { label: "Рабы", value: "778" },
- { label: "Развитие личности", value: "125" },
- { label: "Развод", value: "758" },
- { label: "Разумные предметы", value: "286" },
- { label: "Расизм", value: "408" },
- { label: "Рассказ", value: "185" },
- { label: "Расторжения помолвки", value: "343" },
- { label: "Расы зооморфов", value: "315" },
- { label: "Реализм", value: "246" },
- { label: "Ревность", value: "730" },
- { label: "Редакторы", value: "705" },
- { label: "Реинкарнация", value: "372" },
- { label: "Реинкарнация в монстра", value: "310" },
- { label: "Реинкарнация в объект", value: "711" },
- { label: "Религии", value: "616" },
- { label: "Репортеры", value: "781" },
- { label: "Ресторан", value: "680" },
- { label: "Решительный главный герой", value: "242" },
- { label: "Робкий главный герой", value: "763" },
- { label: "Родитель одиночка", value: "708" },
- { label: "Родительский комплекс", value: "587" },
- { label: "Родословная", value: "239" },
- { label: "Романтическая эротика", value: "132" },
- { label: "Романтический подсюжет", value: "271" },
- { label: "Рост персонажа", value: "215" },
- { label: "Рыцари", value: "260" },
- { label: "Садистские персонажи", value: "674" },
- { label: "Самоотверженный главный герой", value: "747" },
- { label: "Самурай", value: "677" },
- { label: "Сборник коротких историй", value: "520" },
- { label: "Связанные сюжетные линии", value: "535" },
- { label: "Святые", value: "752" },
- { label: "Священники", value: "413" },
- { label: "Сдержанный главный герой", value: "762" },
- { label: "Секретные организации", value: "417" },
- { label: "Секреты", value: "626" },
- { label: "Секс рабы", value: "779" },
- { label: "Семейный конфликт", value: "757" },
- { label: "Семь добродетелей", value: "334" },
- { label: "Семь смертных грехов", value: "253" },
- { label: "Семья", value: "347" },
- { label: "Сёнэн-ай подсюжет", value: "690" },
- { label: "Серийные убийцы", value: "557" },
- { label: "Сестринский комплекс", value: "558" },
- { label: "Сила духа", value: "373" },
- { label: "Сила, требующая платы за польз", value: "579" },
- { label: "Сильная пара", value: "228" },
- { label: "Сильный в сильнейшего", value: "442" },
- { label: "Сильный любовный интерес", value: "273" },
- { label: "Синдром восьмиклассника", value: "211" },
- { label: "Сироты", value: "319" },
- { label: "Система уровней", value: "305" },
- { label: "Системный администратор", value: "538" },
- { label: "Сказка", value: "126" },
- { label: "Скрытие истинной личности", value: "451" },
- { label: "Скрытие истинных способностей", value: "348" },
- { label: "Скрытный главный герой", value: "252" },
- { label: "Скрытые способности", value: "247" },
- { label: "Скульпторы", value: "448" },
- { label: "Слабо выраженная романтическая", value: "318" },
- { label: "Слабый главный герой", value: "298" },
- { label: "Слепой главный герой", value: "794" },
- { label: "Слуги", value: "333" },
- { label: "Слэш", value: "131" },
- { label: "Смерть", value: "175" },
- { label: "Смерть близких", value: "444" },
- { label: "Собственнические персонажи", value: "227" },
- { label: "Современная проза", value: "150" },
- { label: "Современность", value: "167" },
- { label: "Современный любовный роман", value: "137" },
- { label: "Сожительство", value: "544" },
- { label: "Создание армии", value: "287" },
- { label: "Создание артефактов", value: "382" },
- { label: "Создание клана", value: "513" },
- { label: "Создание королевства", value: "293" },
- { label: "Создание навыков", value: "337" },
- { label: "Создание секты", value: "469" },
- { label: "Солдаты/военные", value: "193" },
- { label: "Сон", value: "622" },
- { label: "Состоятельные персонажи", value: "190" },
- { label: "Социальная иерархия по силе", value: "255" },
- { label: "Социальная фантастика", value: "148" },
- { label: "Социальные изгои", value: "542" },
- { label: "Спасение мира", value: "638" },
- { label: "Специальные способности", value: "179" },
- { label: "Спокойный главный герой", value: "160" },
- { label: "Справедливый главный герой", value: "719" },
- { label: "Средневековье", value: "296" },
- { label: "Ссорящаяся пара", value: "383" },
- { label: "Сталкеры", value: "710" },
- { label: "Старение", value: "299" },
- { label: "Стимпанк", value: "139" },
- { label: "Стоические персонажи", value: "509" },
- { label: "Стокгольмский синдром", value: "675" },
- { label: "Стратег", value: "495" },
- { label: "Стратегические битвы", value: "272" },
- { label: "Стратегия", value: "798" },
- { label: "Стрелки", value: "522" },
- { label: "Стрельба из лука", value: "461" },
- { label: "Студенческий совет", value: "551" },
- { label: "Судьба", value: "364" },
- { label: "Суккубы", value: "545" },
- { label: "Супер герои", value: "799" },
- { label: "Суровая подготовка", value: "356" },
- { label: "Таинственная болезнь", value: "195" },
- { label: "Таинственное прошлое", value: "358" },
- { label: "Тайная личность", value: "399" },
- { label: "Тайные отношения", value: "768" },
- { label: "Танцоры", value: "782" },
- { label: "Телохранители", value: "516" },
- { label: "Темное фэнтези", value: "106" },
- { label: "Тентакли", value: "712" },
- { label: "Террористы", value: "574" },
- { label: "Технологический разрыв", value: "658" },
- { label: "Тихие персонажи", value: "600" },
- { label: "Толстый главный герой", value: "389" },
- { label: "Торговцы", value: "489" },
- { label: "Травля/буллинг", value: "210" },
- { label: "Травник", value: "724" },
- { label: "Трагическое прошлое", value: "276" },
- { label: "Трансплантация воспоминаний", value: "449" },
- { label: "Триллер", value: "134" },
- { label: "Трудолюбивый главный герой", value: "164" },
- { label: "Тюрьма", value: "541" },
- { label: "Убийства", value: "205" },
- { label: "Убийцы", value: "345" },
- { label: "Убийцы драконов", value: "646" },
- { label: "Уверенный главный герой", value: "363" },
- { label: "Удачливый главный герой", value: "478" },
- { label: "Ужасы", value: "112" },
- { label: "Укротитель монстров", value: "422" },
- { label: "Умения из прошлой жизни", value: "371" },
- { label: "Умная пара", value: "554" },
- { label: "Умный главный герой", value: "161" },
- { label: "Уникальная техника Культивации", value: "350" },
- { label: "Уникальное оружие", value: "426" },
- { label: "Управление бизнесом", value: "403" },
- { label: "Управление временем", value: "279" },
- { label: "Управление кровью", value: "753" },
- { label: "Упрямый главный герой", value: "695" },
- { label: "Уродливый главный герой", value: "766" },
- { label: "Ускоренный рост", value: "390" },
- { label: "Усыновленные дети", value: "543" },
- { label: "Усыновленный главный герой", value: "486" },
- { label: "Уход за детьми", value: "474" },
- { label: "Учителя", value: "431" },
- { label: "Фамильяры", value: "596" },
- { label: "Фанатизм", value: "650" },
- { label: "Фантастические существа", value: "410" },
- { label: "Фантастический детектив", value: "115" },
- { label: "Фанфик", value: "113" },
- { label: "Фанфикшн", value: "464" },
- { label: "Фармацевт", value: "728" },
- { label: "Фарминг", value: "458" },
- { label: "Феи", value: "316" },
- { label: "Фелляция", value: "631" },
- { label: "Фемслэш", value: "127" },
- { label: "Фениксы", value: "454" },
- { label: "Фетиш груди", value: "559" },
- { label: "Философия", value: "208" },
- { label: "Фильмы", value: "479" },
- { label: "Флэшбэки", value: "585" },
- { label: "Фобии", value: "220" },
- { label: "Фольклор", value: "529" },
- { label: "Футанари", value: "619" },
- { label: "Футуристический сеттинг", value: "460" },
- { label: "Фэнтези мир", value: "244" },
- { label: "Хакеры", value: "475" },
- { label: "Харизматический герой", value: "467" },
- { label: "Хикикомори/Затворники", value: "524" },
- { label: "Хитроумный главный герой", value: "224" },
- { label: "Хозяин подземелий", value: "608" },
- { label: "Холодный главный герой", value: "354" },
- { label: "Хорошие отношения с семьей", value: "566" },
- { label: "Хранители могил", value: "191" },
- { label: "Целители", value: "465" },
- { label: "Цзянши", value: "740" },
- { label: "Цундэрэ", value: "510" },
- { label: "Чаты", value: "629" },
- { label: "Человеческое оружие", value: "580" },
- { label: "Честный главный герой", value: "341" },
- { label: "Читы", value: "339" },
- { label: "Шантаж", value: "584" },
- { label: "Шеф-повар", value: "340" },
- { label: "Шикигами", value: "598" },
- { label: "Школа только для девочек", value: "668" },
- { label: "Шота", value: "573" },
- { label: "Шоу-бизнес", value: "481" },
- { label: "Шпионский детектив", value: "118" },
- { label: "Шпионы", value: "614" },
- { label: "Эволюция", value: "304" },
- { label: "Эгоистичный главный герой", value: "594" },
- { label: "Эйдетическая память", value: "468" },
- { label: "Экзорсизм", value: "564" },
- { label: "Экономика", value: "553" },
- { label: "Эксгибиционизм", value: "673" },
- { label: "Эксперименты с людьми", value: "248" },
- { label: "Элементальная магия", value: "471" },
- { label: "Эльфы", value: "284" },
- { label: "Эмоционально слабый гг", value: "770" },
- { label: "Эпизодический", value: "649" },
- { label: "Эпическое фэнтези", value: "109" },
- { label: "Эротическая фантастика", value: "129" },
- { label: "Эротический фанфик", value: "128" },
- { label: "Эротическое фэнтези", value: "130" },
- { label: "Юмористическая фантастика", value: "143" },
- { label: "Юмористическое фэнтези", value: "108" },
- { label: "Юный любовный интерес", value: "511" },
- { label: "Яды", value: "484" },
- { label: "Языкастые персонажи", value: "480" },
- { label: "Языковой барьер", value: "182" },
- { label: "Яндере", value: "314" },
- { label: "Японские силы самообороны", value: "610" },
- { label: "Ярко выраженная романтика", value: "365" },
- { label: "R-15 Японское возрастное огр.", value: "332" },
- { label: "R-18", value: "424" },
- ],
- inputType: filterInputs_1.FilterInputs.Checkbox,
- },
- {
- key: "types",
- label: "Типы:",
- values: [
- { label: "Авторское", value: "1" },
- { label: "Другое", value: "7" },
- { label: "Запад", value: "5" },
- { label: "Китай", value: "4" },
- { label: "Корея", value: "3" },
- { label: "Фанфики", value: "6" },
- { label: "Япония", value: "2" },
- ],
- inputType: filterInputs_1.FilterInputs.Checkbox,
- },
- {
- key: "status",
- label: "Статус проекта:",
- values: [
- { label: "Анонс", value: "4" },
- { label: "Закончен", value: "0" },
- { label: "Заморожен", value: "2" },
- { label: "Лицензировано", value: "5" },
- { label: "Нет переводчика", value: "3" },
- { label: "Продолжается", value: "1" },
- ],
- inputType: filterInputs_1.FilterInputs.Checkbox,
- },
- {
- key: "age_limit",
- label: "Возрастной рейтинг:",
- values: [
- { label: "16+", value: "1" },
- { label: "18+", value: "2" },
- { label: "Для всех", value: "0" },
- ],
- inputType: filterInputs_1.FilterInputs.Checkbox,
- },
-];
diff --git a/js/plugins/spanish/hasutl.js b/js/plugins/spanish/hasutl.js
deleted file mode 100644
index 8a31f92..0000000
--- a/js/plugins/spanish/hasutl.js
+++ /dev/null
@@ -1,121 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.icon = exports.version = exports.site = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-exports.id = "HasuTL";
-exports.name = "Hasu Translations";
-exports.site = "https://hasutl.wordpress.com/";
-exports.version = "1.0.0";
-exports.icon = "src/es/hasutl/icon.png";
-const baseUrl = exports.site;
-const popularNovels = function (page) {
- return __awaiter(this, void 0, void 0, function* () {
- let url = baseUrl + "light-novels-activas/";
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio("div.wp-block-columns").each(function () {
- const novelName = loadedCheerio(this).find(".wp-block-button").text();
- const novelCover = loadedCheerio(this).find("img").attr("src");
- let novelUrl = loadedCheerio(this)
- .find(".wp-block-button > a")
- .attr("href");
- if (!novelUrl)
- return;
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = novelUrl;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- let novel = {
- url,
- };
- novel.url = novelUrl;
- novel.name = loadedCheerio(".post-header").text();
- novel.cover = loadedCheerio(".featured-media > img").attr("src");
- let novelSummary = loadedCheerio(".post-content").find("p").html();
- novel.summary = novelSummary;
- let novelChapters = [];
- loadedCheerio(".wp-block-media-text__content")
- .find("a")
- .each(function () {
- const chapterName = loadedCheerio(this).text().trim();
- const releaseDate = null;
- let chapterUrl = loadedCheerio(this).attr("href");
- if (!chapterUrl)
- return;
- const chapter = {
- name: chapterName,
- releaseTime: releaseDate,
- url: chapterUrl,
- };
- novelChapters.push(chapter);
- });
- novel.chapters = novelChapters;
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = chapterUrl;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- let chapterText = loadedCheerio(".post-content").html();
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = `${baseUrl}?s=${searchTerm}&post_type=wp-manga`;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio(".post-container ").each(function () {
- const novelName = loadedCheerio(this).find(".post-header").text();
- if (!novelName.includes("Cap") &&
- !novelName.includes("Vol") &&
- !novelName.includes("Light Novels")) {
- const novelCover = loadedCheerio(this).find("img").attr("src");
- let novelUrl = loadedCheerio(this).find("a").attr("href");
- if (!novelUrl)
- return;
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- }
- });
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-exports.fetchImage = fetch_1.fetchFile;
diff --git a/js/plugins/spanish/novelasligera.js b/js/plugins/spanish/novelasligera.js
deleted file mode 100644
index 40ab405..0000000
--- a/js/plugins/spanish/novelasligera.js
+++ /dev/null
@@ -1,157 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.icon = exports.version = exports.site = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-exports.id = "ligera.com";
-exports.name = "Novelas Ligera";
-exports.site = "https://novelasligera.com/";
-exports.version = "1.0.0";
-exports.icon = "src/es/novelasligera/icon.png";
-const baseUrl = exports.site;
-const popularNovels = function (page) {
- return __awaiter(this, void 0, void 0, function* () {
- let url = baseUrl;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio(".elementor-column").each(function () {
- const novelName = loadedCheerio(this)
- .find(".widget-image-caption.wp-caption-text")
- .text();
- if (novelName) {
- const novelCover = loadedCheerio(this)
- .find("a > img")
- .attr("data-lazy-src");
- let novelUrl = loadedCheerio(this).find("a").attr("href");
- if (!novelUrl)
- return;
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- }
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = baseUrl + "novela/" + novelUrl;
- // console.log(url);
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- let novel = { url };
- novel.name = loadedCheerio("h1").text();
- novel.cover = loadedCheerio(".elementor-widget-container")
- .find("img")
- .attr("src");
- loadedCheerio(".elementor-row")
- .find("p")
- .each(function () {
- if (loadedCheerio(this).text().includes("Autor:")) {
- novel.author = loadedCheerio(this)
- .text()
- .replace("Autor:", "")
- .trim();
- }
- if (loadedCheerio(this).text().includes("Estado:")) {
- novel.status = loadedCheerio(this)
- .text()
- .replace("Estado: ", "")
- .trim();
- }
- if (loadedCheerio(this).text().includes("Género:")) {
- loadedCheerio(this).find("span").remove();
- novel.genres = loadedCheerio(this)
- .text()
- .replace(/,\s/g, ",");
- }
- });
- novel.summary = loadedCheerio(".elementor-text-editor.elementor-clearfix").text();
- let novelChapters = [];
- loadedCheerio(".elementor-accordion-item").remove();
- loadedCheerio(".elementor-tab-content")
- .find("li")
- .each(function () {
- const chapterName = loadedCheerio(this).text();
- const releaseDate = null;
- const chapterUrl = loadedCheerio(this).find("a").attr("href");
- if (!chapterUrl)
- return;
- const chapter = {
- name: chapterName,
- releaseTime: releaseDate,
- url: chapterUrl,
- };
- novelChapters.push(chapter);
- });
- novel.chapters = novelChapters;
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = chapterUrl;
- // console.log(url);
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio(".osny-nightmode.osny-nightmode--left").remove();
- loadedCheerio(".code-block.code-block-1").remove();
- loadedCheerio(".adsb30").remove();
- loadedCheerio(".saboxplugin-wrap").remove();
- loadedCheerio(".wp-post-navigation").remove();
- let chapterText = loadedCheerio(".entry-content").html();
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- // console.log(url);
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio(".inside-article").each(function () {
- const novelCover = loadedCheerio(this).find("img").attr("src");
- let novelUrl = loadedCheerio(this).find("a").attr("href");
- let novelName;
- if (novelUrl) {
- novelName = novelUrl.replace(/-/g, " ").replace(/^./, function (x) {
- return x.toUpperCase();
- });
- }
- novelUrl += "/";
- if (!novelName || !novelUrl)
- return;
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- novels = [Object.assign({}, novels[1])];
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-exports.fetchImage = fetch_1.fetchFile;
diff --git a/js/plugins/spanish/skynovels.js b/js/plugins/spanish/skynovels.js
deleted file mode 100644
index e486dbf..0000000
--- a/js/plugins/spanish/skynovels.js
+++ /dev/null
@@ -1,116 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.icon = exports.version = exports.site = exports.name = exports.id = void 0;
-const fetch_1 = require("@libs/fetch");
-exports.id = "skynovels.net";
-exports.name = "SkyNovels";
-exports.site = "https://www.skynovels.net/";
-exports.version = "1.0.0";
-exports.icon = "src/es/skynovels/icon.png";
-const baseUrl = exports.site;
-const popularNovels = function (page) {
- var _a;
- return __awaiter(this, void 0, void 0, function* () {
- const url = "https://api.skynovels.net/api/novels?&q";
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.json();
- const novels = [];
- (_a = body.novels) === null || _a === void 0 ? void 0 : _a.forEach((res) => {
- const novelName = res.nvl_title;
- const novelCover = "https://api.skynovels.net/api/get-image/" +
- res.image +
- "/novels/false";
- const novelUrl = baseUrl + "novelas/" + res.id + "/" + res.nvl_name + "/";
- const novel = { name: novelName, url: novelUrl, cover: novelCover };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novUrl) {
- var _a, _b, _c;
- return __awaiter(this, void 0, void 0, function* () {
- const novelId = novUrl.split("/")[4];
- const url = "https://api.skynovels.net/api/novel/" + novelId + "/reading?&q";
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.json();
- const item = (_a = body === null || body === void 0 ? void 0 : body.novel) === null || _a === void 0 ? void 0 : _a[0];
- let novel = { url: novUrl };
- novel.name = item === null || item === void 0 ? void 0 : item.nvl_title;
- novel.cover =
- "https://api.skynovels.net/api/get-image/" +
- (item === null || item === void 0 ? void 0 : item.image) +
- "/novels/false";
- let genres = [];
- (_b = item === null || item === void 0 ? void 0 : item.genres) === null || _b === void 0 ? void 0 : _b.forEach((genre) => genres.push(genre.genre_name));
- novel.genres = genres.join(",");
- novel.author = item === null || item === void 0 ? void 0 : item.nvl_writer;
- novel.summary = item === null || item === void 0 ? void 0 : item.nvl_content;
- novel.status = item === null || item === void 0 ? void 0 : item.nvl_status;
- let novelChapters = [];
- (_c = item === null || item === void 0 ? void 0 : item.volumes) === null || _c === void 0 ? void 0 : _c.forEach((volume) => {
- var _a;
- (_a = volume === null || volume === void 0 ? void 0 : volume.chapters) === null || _a === void 0 ? void 0 : _a.forEach((chapter) => {
- const chapterName = chapter.chp_index_title;
- const releaseDate = new Date(chapter.createdAt).toDateString();
- const chapterUrl = novUrl + chapter.id + "/" + chapter.chp_name;
- const chap = {
- name: chapterName,
- releaseTime: releaseDate,
- url: chapterUrl,
- };
- novelChapters.push(chap);
- });
- });
- novel.chapters = novelChapters;
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapUrl) {
- var _a;
- return __awaiter(this, void 0, void 0, function* () {
- let chapterId = chapUrl.split("/")[6];
- const url = `https://api.skynovels.net/api/novel-chapter/${chapterId}`;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.json();
- const item = (_a = body === null || body === void 0 ? void 0 : body.chapter) === null || _a === void 0 ? void 0 : _a[0];
- let chapterText = (item === null || item === void 0 ? void 0 : item.chp_content) || '404';
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- var _a;
- return __awaiter(this, void 0, void 0, function* () {
- searchTerm = searchTerm.toLowerCase();
- const url = "https://api.skynovels.net/api/novels?&q";
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.json();
- ;
- let results = (_a = body === null || body === void 0 ? void 0 : body.novels) === null || _a === void 0 ? void 0 : _a.filter((novel) => novel.nvl_title.toLowerCase().includes(searchTerm));
- const novels = [];
- results === null || results === void 0 ? void 0 : results.forEach((res) => {
- const novelName = res.nvl_title;
- const novelCover = "https://api.skynovels.net/api/get-image/" +
- res.image +
- "/novels/false";
- const novelUrl = baseUrl + "novelas/" + res.id + "/" + res.nvl_name + "/";
- const novel = { name: novelName, url: novelUrl, cover: novelCover };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-exports.fetchImage = fetch_1.fetchFile;
diff --git a/js/plugins/spanish/tunovelaligera.js b/js/plugins/spanish/tunovelaligera.js
deleted file mode 100644
index d279fe8..0000000
--- a/js/plugins/spanish/tunovelaligera.js
+++ /dev/null
@@ -1,146 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.icon = exports.version = exports.site = exports.name = exports.id = void 0;
-const fetch_1 = require("@libs/fetch");
-const cheerio_1 = require("cheerio");
-const novelStatus_1 = require("@libs/novelStatus");
-const defaultCover_1 = require("@libs/defaultCover");
-exports.id = "TNL.com";
-exports.name = "TuNovelaLigera";
-exports.site = "https://tunovelaligera.com/";
-exports.version = "1.0.0";
-exports.icon = "src/es/tunovelaligera/icon.png";
-const baseUrl = exports.site;
-const popularNovels = function (page) {
- return __awaiter(this, void 0, void 0, function* () {
- let url = baseUrl + "novelas/page/" + page + "/?m_orderby=rating";
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio(".page-item-detail").each(function () {
- const novelName = loadedCheerio(this).find(".h5 > a").text();
- const novelCover = loadedCheerio(this).find("img").attr("src");
- let novelUrl = loadedCheerio(this).find(".h5 > a").attr("href");
- if (!novelUrl)
- return;
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = novelUrl;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- let novel = {
- url,
- };
- loadedCheerio(".manga-title-badges").remove();
- novel.name = loadedCheerio(".post-title > h1").text().trim();
- let novelCover = loadedCheerio(".summary_image > a > img");
- novel.cover =
- novelCover.attr("data-src") ||
- novelCover.attr("src") ||
- defaultCover_1.defaultCover;
- loadedCheerio(".post-content_item").each(function () {
- const detailName = loadedCheerio(this)
- .find(".summary-heading > h5")
- .text()
- .trim();
- const detail = loadedCheerio(this)
- .find(".summary-content")
- .text()
- .trim();
- switch (detailName) {
- case "Generos":
- novel.genres = detail.replace(/, /g, ",");
- break;
- case "Autores":
- novel.author = detail;
- break;
- case "Estado":
- novel.status =
- detail.includes("OnGoing") ||
- detail.includes("Updating")
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- novel.summary = loadedCheerio("div.summary__content > p").text().trim();
- let novelChapters = [];
- loadedCheerio(".lcp_catlist li").each(function () {
- const chapterName = loadedCheerio(this)
- .find("a")
- .text()
- .replace(/[\t\n]/g, "")
- .trim();
- const releaseDate = loadedCheerio(this).find("span").text().trim();
- let chapterUrl = loadedCheerio(this).find("a").attr("href");
- if (!chapterUrl)
- return;
- novelChapters.push({
- name: chapterName,
- releaseTime: releaseDate,
- url: chapterUrl,
- });
- });
- novel.chapters = novelChapters.reverse();
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = chapterUrl;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- let chapterText = loadedCheerio("#hola_siguiente").next().text();
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = `${baseUrl}?s=${searchTerm}&post_type=wp-manga`;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio(".c-tabs-item__content").each(function () {
- const novelName = loadedCheerio(this).find(".h4 > a").text();
- const novelCover = loadedCheerio(this).find("img").attr("src");
- let novelUrl = loadedCheerio(this).find(".h4 > a").attr("href");
- if (!novelUrl)
- return;
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-exports.fetchImage = fetch_1.fetchFile;
diff --git a/js/plugins/spanish/yukitls.js b/js/plugins/spanish/yukitls.js
deleted file mode 100644
index 6b7547e..0000000
--- a/js/plugins/spanish/yukitls.js
+++ /dev/null
@@ -1,160 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.icon = exports.version = exports.site = exports.name = exports.id = void 0;
-const fetch_1 = require("@libs/fetch");
-const cheerio_1 = require("cheerio");
-exports.id = "yuukitls.com";
-exports.name = "Yuuki Tls";
-exports.site = "https://yuukitls.com/";
-exports.version = "1.0.0";
-exports.icon = "src/es/yuukitls/icon.png";
-const baseUrl = exports.site;
-const popularNovels = function (page) {
- return __awaiter(this, void 0, void 0, function* () {
- let url = baseUrl;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio(".quadmenu-navbar-collapse ul li:nth-child(2)")
- .find("li")
- .each(function () {
- const novelName = loadedCheerio(this)
- .text()
- .replace(/[\s\n]+/g, " ");
- const novelCover = loadedCheerio(this).find("img").attr("src");
- let novelUrl = loadedCheerio(this).find("a").attr("href");
- if (!novelUrl)
- return;
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = novelUrl;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- let novel = {
- url,
- };
- novel.name = loadedCheerio("h1.entry-title")
- .text()
- .replace(/[\t\n]/g, "")
- .trim();
- novel.cover = loadedCheerio('img[loading="lazy"]').attr("src");
- loadedCheerio(".entry-content")
- .find("div")
- .each(function () {
- if (loadedCheerio(this).text().includes("Escritor:")) {
- novel.author = loadedCheerio(this)
- .text()
- .replace("Escritor: ", "")
- .trim();
- }
- if (loadedCheerio(this).text().includes("Género:")) {
- novel.genres = loadedCheerio(this)
- .text()
- .replace(/Género: |\s/g, "");
- }
- if (loadedCheerio(this).text().includes("Sinopsis:")) {
- novel.summary = loadedCheerio(this).next().text();
- }
- });
- let novelChapters = [];
- if (loadedCheerio(".entry-content").find("li").length) {
- loadedCheerio(".entry-content")
- .find("li")
- .each(function () {
- let chapterUrl = loadedCheerio(this).find("a").attr("href");
- if (chapterUrl && chapterUrl.includes(baseUrl)) {
- const chapterName = loadedCheerio(this).text();
- const releaseDate = null;
- const chapter = {
- name: chapterName,
- releaseTime: releaseDate,
- url: chapterUrl,
- };
- novelChapters.push(chapter);
- }
- });
- }
- else {
- loadedCheerio(".entry-content")
- .find("p")
- .each(function () {
- let chapterUrl = loadedCheerio(this).find("a").attr("href");
- if (chapterUrl && chapterUrl.includes(baseUrl)) {
- const chapterName = loadedCheerio(this).text();
- const releaseDate = null;
- const chapter = {
- name: chapterName,
- releaseTime: releaseDate,
- url: chapterUrl,
- };
- novelChapters.push(chapter);
- }
- });
- }
- novel.chapters = novelChapters;
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = chapterUrl;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- let chapterText = loadedCheerio(".entry-content").html();
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- return __awaiter(this, void 0, void 0, function* () {
- searchTerm = searchTerm.toLowerCase();
- let url = baseUrl;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio(".menu-item-2869")
- .find(".menu-item.menu-item-type-post_type.menu-item-object-post")
- .each(function () {
- const novelName = loadedCheerio(this).text();
- const novelCover = loadedCheerio(this).find("img").attr("src");
- let novelUrl = loadedCheerio(this).find("a").attr("href");
- if (!novelUrl)
- return;
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- novels = novels.filter((novel) => novel.name.toLowerCase().includes(searchTerm));
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-exports.fetchImage = fetch_1.fetchFile;
diff --git a/js/plugins/turkish/TurkceLightNovels[madara].js b/js/plugins/turkish/TurkceLightNovels[madara].js
deleted file mode 100644
index 2438a6b..0000000
--- a/js/plugins/turkish/TurkceLightNovels[madara].js
+++ /dev/null
@@ -1,179 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const filterInputs_1 = require("@libs/filterInputs");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "turkcelightnovels";
-exports.name = "TurkceLightNovels [madara]";
-exports.icon = "multisrc/madara/icons/turkcelightnovels.png";
-exports.version = "1.0.0";
-exports.site = "https://turkcelightnovels.com/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "novel-genre/" + filters.genres + '/';
- }
- else {
- url += "light-novel/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (false) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "light-novel" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [{ "key": "sort", "label": "Order by", "values": [{ "label": "Rating", "value": "rating" }, { "label": "A-Z", "value": "alphabet" }, { "label": "Latest", "value": "latest" }, { "label": "Most Views", "value": "views" }, { "label": "New", "value": "new-manga" }, { "label": "Trending", "value": "trending" }], "inputType": filterInputs_1.FilterInputs.Picker }];
diff --git a/js/plugins/turkish/WebNovelOku[madara].js b/js/plugins/turkish/WebNovelOku[madara].js
deleted file mode 100644
index b9d173d..0000000
--- a/js/plugins/turkish/WebNovelOku[madara].js
+++ /dev/null
@@ -1,179 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const filterInputs_1 = require("@libs/filterInputs");
-const defaultCover_1 = require("@libs/defaultCover");
-const novelStatus_1 = require("@libs/novelStatus");
-const parseMadaraDate_1 = require("@libs/parseMadaraDate");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "webnoveloku";
-exports.name = "WebNovelOku [madara]";
-exports.icon = "multisrc/madara/icons/webnoveloku.png";
-exports.version = "1.0.0";
-exports.site = "https://www.webnoveloku.com/";
-const baseUrl = exports.site;
-const popularNovels = (pageNo, { filters, showLatestNovels }) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- let url = exports.site;
- if (filters === null || filters === void 0 ? void 0 : filters.genres) {
- url += "novel-genre/" + filters.genres + '/';
- }
- else {
- url += "novel/";
- }
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : ((filters === null || filters === void 0 ? void 0 : filters.sort) || 'rating'));
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const body = yield (0, fetch_1.fetchApi)(novelUrl).then(res => res.text());
- let loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.manga-title-badges').remove();
- novel.name = loadedCheerio('.post-title h1').text().trim();
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover_1.defaultCover;
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed;
- break;
- }
- });
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
- let html;
- if (false) {
- const novelId = loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- };
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'wp-admin/admin-ajax.php', {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- }
- else {
- html = yield (0, fetch_1.fetchApi)(baseUrl + 'ajax/chapters/', { method: 'POST' })
- .then(res => res.text());
- }
- if (html !== '0') {
- loadedCheerio = (0, cheerio_1.load)(html);
- }
- const chapters = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
- if (releaseDate) {
- releaseDate = (0, parseMadaraDate_1.parseMadaraDate)(releaseDate);
- }
- else {
- /**
- * Insert current date
- */
- releaseDate = (0, dayjs_1.default)().format('LL');
- }
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
- novel.chapters = chapters.reverse();
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
- const body = yield (0, fetch_1.fetchApi)(chapterUrl).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
- const body = yield (0, fetch_1.fetchApi)(url).then(res => res.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- return yield (0, fetch_1.fetchFile)(url);
-});
-exports.fetchImage = fetchImage;
-exports.filters = [{ "key": "sort", "label": "Sırala", "values": [{ "label": "A-Z", "value": "alphabet" }, { "label": "En Son", "value": "latest" }, { "label": "Görüntülenme", "value": "views" }, { "label": "Popülarite", "value": "trending" }, { "label": "Reyting", "value": "rating" }, { "label": "Yeni", "value": "new-manga" }], "inputType": filterInputs_1.FilterInputs.Picker }];
diff --git a/js/plugins/turkish/epiknovel.js b/js/plugins/turkish/epiknovel.js
deleted file mode 100644
index a80159c..0000000
--- a/js/plugins/turkish/epiknovel.js
+++ /dev/null
@@ -1,142 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.icon = exports.version = exports.site = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-exports.id = "epiknovel.com";
-exports.name = "EpikNovel";
-exports.site = "https://www.epiknovel.com/";
-exports.version = "1.0.0";
-exports.icon = "src/tr/epiknovel/icon.png";
-const baseUrl = exports.site;
-const popularNovels = function (page) {
- return __awaiter(this, void 0, void 0, function* () {
- let url = baseUrl + "seri-listesi?Sayfa=" + page;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio("div.col-lg-12.col-md-12").each(function () {
- const novelName = loadedCheerio(this).find("h3").text();
- const novelCover = loadedCheerio(this).find("img").attr("data-src");
- const novelUrl = loadedCheerio(this).find("h3 > a").attr("href");
- if (!novelUrl)
- return;
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- // console.log(novels);
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = novelUrl;
- // console.log(url);
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- let novel = { url };
- novel.name = loadedCheerio("h1#tables").text().trim();
- novel.cover = loadedCheerio("img.manga-cover").attr("src");
- novel.summary = loadedCheerio("#wrapper > div.row > div.col-md-9 > div:nth-child(6) > p:nth-child(3)")
- .text()
- .trim();
- novel.status = loadedCheerio("#wrapper > div.row > div.col-md-9 > div.row > div.col-md-9 > h4:nth-child(3) > a")
- .text()
- .trim();
- novel.author = loadedCheerio("#NovelInfo > p:nth-child(4)")
- .text()
- .replace(/Publisher:|\s/g, "")
- .trim();
- let novelChapters = [];
- loadedCheerio("table").find("tr").first().remove();
- loadedCheerio("table")
- .find("tr")
- .each(function () {
- const releaseDate = loadedCheerio(this)
- .find("td:nth-child(3)")
- .text();
- let chapterName = loadedCheerio(this)
- .find("td:nth-child(1) > a")
- .text();
- if (loadedCheerio(this).find("td:nth-child(1) > span").length >
- 0) {
- chapterName = "🔒 " + chapterName;
- }
- const chapterUrl = loadedCheerio(this)
- .find(" td:nth-child(1) > a")
- .attr("href");
- if (!chapterUrl)
- return;
- novelChapters.push({
- name: chapterName,
- url: chapterUrl,
- releaseTime: releaseDate,
- });
- });
- novel.chapters = novelChapters;
- // console.log(novel);
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = chapterUrl;
- // console.log(url);
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- let chapterName, chapterText;
- if (result.url === "https://www.epiknovel.com/login") {
- chapterName = "";
- chapterText = "Premium Chapter";
- }
- else {
- chapterName = loadedCheerio("#icerik > center > h4 > b").text();
- chapterText = loadedCheerio("div#icerik").html();
- }
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = baseUrl + "seri-listesi?q=" + searchTerm;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- let novels = [];
- loadedCheerio("div.col-lg-12.col-md-12").each(function () {
- const novelName = loadedCheerio(this).find("h3").text();
- const novelCover = loadedCheerio(this).find("img").attr("data-src");
- const novelUrl = loadedCheerio(this).find("h3 > a").attr("href");
- if (!novelUrl)
- return;
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-exports.fetchImage = fetch_1.fetchFile;
diff --git a/js/plugins/turkish/lshnovel.js b/js/plugins/turkish/lshnovel.js
deleted file mode 100644
index 4e3eeec..0000000
--- a/js/plugins/turkish/lshnovel.js
+++ /dev/null
@@ -1,247 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.filters = exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.icon = exports.version = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-const filterInputs_1 = require("@libs/filterInputs");
-exports.id = "lshnovel";
-exports.name = "Liebe Schnee Hiver Novel";
-exports.version = "1.0.0";
-exports.icon = "multisrc/wpmangastream/icons/lshnovel.png";
-exports.site = "https://lshnovel.com/";
-const pluginId = exports.id;
-const baseUrl = exports.site;
-const popularNovels = function (page, { filters }) {
- return __awaiter(this, void 0, void 0, function* () {
- let link = `${baseUrl}series/?page=${page}`;
- if (filters) {
- if (Array.isArray(filters.genres) && filters.genres.length) {
- link += filters.genres.map((i) => `&genre[]=${i}`).join("");
- }
- if (Array.isArray(filters.type) && filters.type.length) {
- link += filters.type.map((i) => `&lang[]=${i}`).join("");
- }
- }
- link += "&status=" + ((filters === null || filters === void 0 ? void 0 : filters.status) ? filters === null || filters === void 0 ? void 0 : filters.status : "");
- link += "&order=" + ((filters === null || filters === void 0 ? void 0 : filters.order) ? filters === null || filters === void 0 ? void 0 : filters.order : "popular");
- const body = yield (0, fetch_1.fetchApi)(link, {}, pluginId).then((result) => result.text());
- const loadedCheerio = (0, cheerio_1.load)(body);
- const novels = [];
- loadedCheerio("article.bs").each(function () {
- const novelName = loadedCheerio(this).find(".ntitle").text().trim();
- let image = loadedCheerio(this).find("img");
- const novelCover = image.attr("data-src") || image.attr("src");
- const novelUrl = loadedCheerio(this).find("a").attr("href");
- if (!novelUrl)
- return;
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
- novels.push(novel);
- });
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = novelUrl;
- const result = yield (0, fetch_1.fetchApi)(url, {}, pluginId);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- const novel = {
- url,
- chapters: [],
- };
- novel.name = loadedCheerio(".entry-title").text();
- novel.cover =
- loadedCheerio("img.wp-post-image").attr("data-src") ||
- loadedCheerio("img.wp-post-image").attr("src");
- loadedCheerio("div.spe > span").each(function () {
- const detailName = loadedCheerio(this).find("b").text().trim();
- const detail = loadedCheerio(this)
- .find("b")
- .remove()
- .end()
- .text()
- .trim();
- switch (detailName) {
- case "المؤلف:":
- case "Yazar:":
- case "Autor:":
- case "Author:":
- novel.author = detail;
- break;
- case "Status:":
- case "Seviye:":
- novel.status = detail;
- break;
- }
- });
- novel.genres = loadedCheerio(".genxed")
- .text()
- .trim()
- .replace(/\s/g, ",");
- loadedCheerio('div[itemprop="description"] h3,p.a,strong').remove();
- novel.summary = loadedCheerio('div[itemprop="description"]')
- .find("br")
- .replaceWith("\n")
- .end()
- .text();
- let chapter = [];
- loadedCheerio(".eplister")
- .find("li")
- .each(function () {
- const chapterName = loadedCheerio(this).find(".epl-num").text() +
- " - " +
- loadedCheerio(this).find(".epl-title").text();
- const releaseDate = loadedCheerio(this)
- .find(".epl-date")
- .text()
- .trim();
- const chapterUrl = loadedCheerio(this).find("a").attr("href");
- if (!chapterUrl)
- return;
- chapter.push({
- name: chapterName,
- releaseTime: releaseDate,
- url: chapterUrl,
- });
- });
- novel.chapters = chapter.reverse();
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- return __awaiter(this, void 0, void 0, function* () {
- const result = yield (0, fetch_1.fetchApi)(chapterUrl, {}, pluginId);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- let chapterText = loadedCheerio("div.epcontent").html();
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- return __awaiter(this, void 0, void 0, function* () {
- const url = `${baseUrl}?s=${searchTerm}`;
- const result = yield (0, fetch_1.fetchApi)(url, {}, pluginId);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- const novels = [];
- loadedCheerio("article.bs").each(function () {
- const novelName = loadedCheerio(this).find(".ntitle").text().trim();
- const novelCover = loadedCheerio(this).find("img").attr("src");
- const novelUrl = loadedCheerio(this).find("a").attr("href");
- if (!novelUrl)
- return;
- novels.push({
- name: novelName,
- url: novelUrl,
- cover: novelCover,
- });
- });
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-const fetchImage = function (url) {
- return __awaiter(this, void 0, void 0, function* () {
- const headers = {
- Referer: baseUrl,
- };
- return yield (0, fetch_1.fetchFile)(url, { headers: headers });
- });
-};
-exports.fetchImage = fetchImage;
-exports.filters = [
- {
- key: "order",
- label: "Önerilen",
- values: [
- { label: "Varsayılan", value: "" },
- { label: "A-Z", value: "title" },
- { label: "Z-A", value: "titlereverse" },
- { label: "Son Yüklemeler", value: "update" },
- { label: "Son Eklenenler", value: "latest" },
- { label: "Bestimiz", value: "popular" },
- ],
- inputType: filterInputs_1.FilterInputs.Picker,
- },
- {
- key: "status",
- label: "Statü",
- values: [
- { label: "Tümü", value: "" },
- { label: "Ongoing", value: "ongoing" },
- { label: "Hiatus", value: "hiatus" },
- { label: "Completed", value: "completed" },
- ],
- inputType: filterInputs_1.FilterInputs.Picker,
- },
- {
- key: "type",
- label: "Tür",
- values: [
- { label: "Çeviri Novel", value: "ceviri-novel" },
- { label: "Liz-Chan", value: "liz-chan" },
- { label: "Manhwa", value: "manhwa" },
- { label: "Orijinal Novel", value: "orijinal-novel" },
- { label: "Web Novel", value: "web-novel" },
- ],
- inputType: filterInputs_1.FilterInputs.Checkbox,
- },
- {
- key: "genres",
- label: "Kategori",
- values: [
- { label: "+18", value: "18" },
- { label: "Action", value: "action" },
- { label: "Adult", value: "adult" },
- { label: "Aksiyon", value: "aksiyon" },
- { label: "BL", value: "bl" },
- { label: "Comedy", value: "comedy" },
- { label: "Doğaüstü", value: "dogaustu" },
- { label: "Dram", value: "dram" },
- { label: "Drama", value: "drama" },
- { label: "Ecchi", value: "ecchi" },
- { label: "Fantastik", value: "fantastik" },
- { label: "Fantasy", value: "fantasy" },
- { label: "Gizem", value: "gizem" },
- { label: "Harem", value: "harem" },
- { label: "Historical", value: "historical" },
- { label: "Josei", value: "josei" },
- { label: "Macera", value: "macera" },
- { label: "Manhwa", value: "manhwa" },
- { label: "Martial Arts", value: "martial-arts" },
- { label: "Mature", value: "mature" },
- { label: "Novel", value: "novel" },
- { label: "Okul", value: "okul" },
- { label: "Psikolojik", value: "psikolojik" },
- { label: "Psychological", value: "psychological" },
- { label: "Reverse Harem", value: "reverse-harem" },
- { label: "Romance", value: "romance" },
- { label: "Romantik", value: "romantik" },
- { label: "Shoujo", value: "shoujo" },
- { label: "Slice Of Life", value: "slice-of-life" },
- { label: "Smut", value: "smut" },
- { label: "Supernatural", value: "supernatural" },
- { label: "Tarihi", value: "tarihi" },
- { label: "Tragedy", value: "tragedy" },
- { label: "Yaoi", value: "yaoi" },
- ],
- inputType: filterInputs_1.FilterInputs.Checkbox,
- },
-];
diff --git a/js/plugins/ukraine/smakolykytl.js b/js/plugins/ukraine/smakolykytl.js
deleted file mode 100644
index fc95ecf..0000000
--- a/js/plugins/ukraine/smakolykytl.js
+++ /dev/null
@@ -1,139 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.icon = exports.version = exports.site = exports.name = exports.id = void 0;
-const fetch_1 = require("@libs/fetch");
-const novelStatus_1 = require("@libs/novelStatus");
-const dayjs_1 = __importDefault(require("dayjs"));
-exports.id = "smakolykytl";
-exports.name = "Смаколики";
-exports.site = "https://smakolykytl.site/";
-exports.version = "1.0.0";
-exports.icon = "src/ua/smakolykytl/icon.png";
-const popularNovels = function (page, { showLatestNovels }) {
- var _a;
- return __awaiter(this, void 0, void 0, function* () {
- const url = showLatestNovels
- ? "https://api.smakolykytl.site/api/user/updates"
- : "https://api.smakolykytl.site/api/user/projects";
- const result = yield (0, fetch_1.fetchApi)(url);
- const json = (yield result.json());
- let novels = [];
- (_a = ((json === null || json === void 0 ? void 0 : json.projects) || (json === null || json === void 0 ? void 0 : json.updates))) === null || _a === void 0 ? void 0 : _a.forEach((novel) => novels.push({
- name: novel.title,
- cover: novel.image.url,
- url: exports.site + "titles/" + novel.id,
- }));
- return novels;
- });
-};
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = function (novelUrl) {
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
- return __awaiter(this, void 0, void 0, function* () {
- const id = novelUrl.split("/").pop();
- const result = yield (0, fetch_1.fetchApi)("https://api.smakolykytl.site/api/user/projects/" + id);
- const book = (yield result.json());
- let novel = {
- url: novelUrl,
- name: (_a = book === null || book === void 0 ? void 0 : book.project) === null || _a === void 0 ? void 0 : _a.title,
- cover: (_c = (_b = book === null || book === void 0 ? void 0 : book.project) === null || _b === void 0 ? void 0 : _b.image) === null || _c === void 0 ? void 0 : _c.url,
- summary: (_d = book === null || book === void 0 ? void 0 : book.project) === null || _d === void 0 ? void 0 : _d.description,
- author: (_e = book === null || book === void 0 ? void 0 : book.project) === null || _e === void 0 ? void 0 : _e.author,
- status: ((_f = book === null || book === void 0 ? void 0 : book.project) === null || _f === void 0 ? void 0 : _f.status_translate.includes("Триває"))
- ? novelStatus_1.NovelStatus.Ongoing
- : novelStatus_1.NovelStatus.Completed,
- };
- let tags = [(_g = book === null || book === void 0 ? void 0 : book.project) === null || _g === void 0 ? void 0 : _g.genres, (_h = book === null || book === void 0 ? void 0 : book.project) === null || _h === void 0 ? void 0 : _h.tags]
- .flat()
- .map((tags) => tags === null || tags === void 0 ? void 0 : tags.title)
- .filter((tags) => tags);
- if (tags.length > 0) {
- novel.genres = tags.join(", ");
- }
- let chapters = [];
- const res = yield (0, fetch_1.fetchApi)("https://api.smakolykytl.site/api/user/projects/" + id + "/books");
- const data = (yield res.json());
- (_j = data === null || data === void 0 ? void 0 : data.books) === null || _j === void 0 ? void 0 : _j.forEach((volume) => {
- var _a;
- return (_a = volume === null || volume === void 0 ? void 0 : volume.chapters) === null || _a === void 0 ? void 0 : _a.map((chapter) => chapters.push({
- name: volume.title + " " + chapter.title,
- releaseTime: (0, dayjs_1.default)(chapter.modifiedAt).format("LLL"),
- url: exports.site + "read/" + chapter.id,
- }));
- });
- novel.chapters = chapters;
- return novel;
- });
-};
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = function (chapterUrl) {
- var _a;
- return __awaiter(this, void 0, void 0, function* () {
- const id = chapterUrl.split("/").pop();
- const result = yield (0, fetch_1.fetchApi)("https://api.smakolykytl.site/api/user/chapters/" + id);
- const json = (yield result.json());
- const chapterRaw = JSON.parse(((_a = json === null || json === void 0 ? void 0 : json.chapter) === null || _a === void 0 ? void 0 : _a.content) || "{}");
- const chapterText = jsonToHtml(chapterRaw);
- return chapterText;
- });
-};
-exports.parseChapter = parseChapter;
-const searchNovels = function (searchTerm) {
- var _a, _b;
- return __awaiter(this, void 0, void 0, function* () {
- const result = yield (0, fetch_1.fetchApi)("https://api.smakolykytl.site/api/user/projects");
- const json = (yield result.json());
- let novels = [];
- (_b = (_a = json === null || json === void 0 ? void 0 : json.projects) === null || _a === void 0 ? void 0 : _a.filter((novel) => novel.title.includes(searchTerm) || String(novel.id) === searchTerm)) === null || _b === void 0 ? void 0 : _b.forEach((novel) => novels.push({
- name: novel.title,
- cover: novel.image.url,
- url: exports.site + "titles/" + novel.id,
- }));
- return novels;
- });
-};
-exports.searchNovels = searchNovels;
-exports.fetchImage = fetch_1.fetchFile;
-function jsonToHtml(json, html = "") {
- json.forEach((element) => {
- switch (element.type) {
- case "hardBreak":
- html += "
";
- break;
- case "horizontalRule":
- html += "
";
- break;
- case "image":
- if (element.attrs) {
- const attrs = Object.entries(element.attrs)
- .filter((attr) => attr === null || attr === void 0 ? void 0 : attr[1])
- .map((attr) => `${attr[0]}="${attr[1]}"`);
- html += "
";
- }
- break;
- case "paragraph":
- html +=
- "" + (element.content ? jsonToHtml(element.content) : "
") + "
";
- break;
- case "text":
- html += element.text;
- break;
- default:
- html += JSON.stringify(element, null, "\t"); //maybe I missed something.
- break;
- }
- });
- return html;
-}
diff --git a/js/plugins/vietnamese/LNHako.js b/js/plugins/vietnamese/LNHako.js
deleted file mode 100644
index 668d1e7..0000000
--- a/js/plugins/vietnamese/LNHako.js
+++ /dev/null
@@ -1,162 +0,0 @@
-"use strict";
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-};
-Object.defineProperty(exports, "__esModule", { value: true });
-exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
-const cheerio_1 = require("cheerio");
-const fetch_1 = require("@libs/fetch");
-// import dayjs from "dayjs";
-// import { FilterInputs } from "@libs/filterInputs";
-// import { NovelStatus } from "@libs/novelStatus";
-const isAbsoluteUrl_1 = require("@libs/isAbsoluteUrl");
-// import { parseMadaraDate } from "@libs/parseMadaraDate";
-const pluginId = "ln.hako";
-const baseUrl = "https://ln.hako.vn";
-exports.id = pluginId; // string and must be unique
-exports.name = "Hako";
-exports.icon = "src/vi/hakolightnovel/icon.png"; // The relative path to the icon without @icons . For example: 'src/vi/hakolightnovel/icon.png'
-exports.version = "1.0.0"; // xx.xx.xx
-exports.site = baseUrl; // the link to the site
-const popularNovels = (pageNo) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const link = baseUrl + "/danh-sach?truyendich=1&sapxep=topthang&page=" + pageNo;
- const result = yield (0, fetch_1.fetchApi)(link);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio("main.row > .thumb-item-flow").each(function () {
- let url = loadedCheerio(this)
- .find("div.thumb_attr.series-title > a")
- .attr("href");
- if (url && !(0, isAbsoluteUrl_1.isUrlAbsolute)(url)) {
- url = baseUrl + url;
- }
- if (url) {
- const name = loadedCheerio(this)
- .find(".series-title")
- .text()
- .trim();
- let cover = loadedCheerio(this)
- .find(".img-in-ratio")
- .attr("data-bg");
- if (cover && !(0, isAbsoluteUrl_1.isUrlAbsolute)(cover)) {
- cover = baseUrl + cover;
- }
- const novel = {
- name,
- url,
- cover,
- };
- novels.push(novel);
- }
- });
- return novels;
-});
-exports.popularNovels = popularNovels;
-const parseNovelAndChapters = (novelUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const novel = {
- url: novelUrl,
- };
- const result = yield (0, fetch_1.fetchApi)(novelUrl);
- const body = yield result.text();
- let loadedCheerio = (0, cheerio_1.load)(body);
- novel.name = loadedCheerio(".series-name").text();
- const background = loadedCheerio(".series-cover > .a6-ratio > div").attr("style") || "";
- const novelCover = background.substring(background.indexOf("http"), background.length - 2);
- novel.cover = novelCover
- ? (0, isAbsoluteUrl_1.isUrlAbsolute)(novelCover)
- ? novelCover
- : baseUrl + novelCover
- : "";
- novel.summary = loadedCheerio(".summary-content").text().trim();
- novel.author = loadedCheerio("#mainpart > div:nth-child(2) > div > div:nth-child(1) > section > main > div.top-part > div > div.col-12.col-md-9 > div.series-information > div:nth-child(2) > span.info-value > a")
- .text()
- .trim();
- novel.genres = loadedCheerio(".series-gernes")
- .text()
- .trim()
- .replace(/ +/g, " ")
- .split("\n")
- .filter((e) => e.trim())
- .join(", ");
- novel.status = loadedCheerio("#mainpart > div:nth-child(2) > div > div:nth-child(1) > section > main > div.top-part > div > div.col-12.col-md-9 > div.series-information > div:nth-child(4) > span.info-value > a")
- .text()
- .trim();
- const chapters = [];
- loadedCheerio(".list-chapters li").each(function () {
- let chapterUrl = loadedCheerio(this).find("a").attr("href");
- if (chapterUrl && !(0, isAbsoluteUrl_1.isUrlAbsolute)(chapterUrl)) {
- chapterUrl = baseUrl + chapterUrl;
- }
- if (chapterUrl) {
- const chapterName = loadedCheerio(this)
- .find(".chapter-name")
- .text()
- .trim();
- const releaseTime = loadedCheerio(this)
- .find(".chapter-time")
- .text();
- const chapter = {
- name: chapterName,
- releaseTime: releaseTime,
- url: chapterUrl,
- };
- chapters.push(chapter);
- }
- });
- novel.chapters = chapters;
- return novel;
-});
-exports.parseNovelAndChapters = parseNovelAndChapters;
-const parseChapter = (chapterUrl) => __awaiter(void 0, void 0, void 0, function* () {
- const result = yield (0, fetch_1.fetchApi)(chapterUrl);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- const chapterText = loadedCheerio("#chapter-content").html() || "";
- return chapterText;
-});
-exports.parseChapter = parseChapter;
-const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
- const novels = [];
- const url = baseUrl + "/tim-kiem?keywords=" + searchTerm;
- const result = yield (0, fetch_1.fetchApi)(url);
- const body = yield result.text();
- const loadedCheerio = (0, cheerio_1.load)(body);
- loadedCheerio("div.row > .thumb-item-flow").each(function () {
- let novelUrl = loadedCheerio(this)
- .find("div.thumb_attr.series-title > a")
- .attr("href");
- if (novelUrl && !(0, isAbsoluteUrl_1.isUrlAbsolute)(novelUrl)) {
- novelUrl = baseUrl + novelUrl;
- }
- if (novelUrl) {
- const novelName = loadedCheerio(this).find(".series-title").text();
- let novelCover = loadedCheerio(this)
- .find(".img-in-ratio")
- .attr("data-bg");
- if (novelCover && !(0, isAbsoluteUrl_1.isUrlAbsolute)(novelCover)) {
- novelCover = baseUrl + novelCover;
- }
- novels.push({
- name: novelName,
- url: novelUrl,
- cover: novelCover,
- });
- }
- });
- return novels;
-});
-exports.searchNovels = searchNovels;
-const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
- const headers = {
- Referer: "https://ln.hako.vn",
- };
- return yield (0, fetch_1.fetchFile)(url, { headers: headers });
-});
-exports.fetchImage = fetchImage;
diff --git a/libs/fetch.ts b/libs/fetch.ts
index 39282ce..b740b0b 100644
--- a/libs/fetch.ts
+++ b/libs/fetch.ts
@@ -1,26 +1,18 @@
-import { Plugin } from "@typings/plugin";
-import { NodeFetchParams, getNodeFetch } from "./nodeFetch";
-
-const fetch = async (...args: NodeFetchParams) =>
- (await getNodeFetch())(...args);
-
const defaultUserAgentString =
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36";
export async function fetchApi(
url: string,
- init?: NodeFetchParams[1],
- pluginId?: string
+ init?: RequestInit,
) {
const headers = {
"User-Agent": defaultUserAgentString,
...init?.headers,
};
- if (pluginId) console.log("Enable CloudFlare cookie for", pluginId);
return await fetch(url, { ...init, headers });
}
-export const fetchFile: Plugin.fetchImage = async function (url, init) {
+export const fetchFile = async function (url: string, init?: RequestInit) {
if (!init) init = {};
try {
const res = await fetch(url, init);
diff --git a/libs/filterInputs.ts b/libs/filterInputs.ts
index 2327a77..7077d5f 100644
--- a/libs/filterInputs.ts
+++ b/libs/filterInputs.ts
@@ -2,6 +2,7 @@ export interface FilterValue {
label: string;
value: string | number;
}
+
export enum FilterInputs {
TextInput,
Picker,
@@ -11,5 +12,5 @@ export interface Filter {
key: string;
label: string;
values: FilterValue[];
- inputType: FilterInputs;
+ inputType: FilterInputs | string;
}
diff --git a/libs/nodeFetch.ts b/libs/nodeFetch.ts
deleted file mode 100644
index d815177..0000000
--- a/libs/nodeFetch.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-const nodeFetch = import("node-fetch");
-
-export type NodeFetchFunction = Awaited["default"];
-
-export type NodeFetchParams = Parameters;
-
-export const getNodeFetch = async (): Promise => {
- return (await nodeFetch).default;
-};
diff --git a/nodemon.json b/nodemon.json
index 879d47a..533f64e 100644
--- a/nodemon.json
+++ b/nodemon.json
@@ -1,5 +1,5 @@
{
"ext": "js,mjs,json,ts",
- "ignore": ["js/**"],
- "exec": "tsc && node ./js/index.js"
+ "ignore": [".js/**", "test_web/**"],
+ "exec": "tsc && node ./.js/index.js"
}
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 3343b8f..27abe72 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -15,7 +15,6 @@
"dayjs": "^1.11.4",
"express": "^4.18.2",
"module-alias": "^2.2.2",
- "node-fetch": "^3",
"ts-node": "^10.9.1",
"tsc-alias": "^1.8.6",
"typescript": "^5.1.3"
@@ -562,14 +561,6 @@
"type": "^1.0.1"
}
},
- "node_modules/data-uri-to-buffer": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
- "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
- "engines": {
- "node": ">= 12"
- }
- },
"node_modules/dayjs": {
"version": "1.11.4",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.4.tgz",
@@ -888,28 +879,6 @@
"reusify": "^1.0.4"
}
},
- "node_modules/fetch-blob": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
- "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/jimmywarting"
- },
- {
- "type": "paypal",
- "url": "https://paypal.me/jimmywarting"
- }
- ],
- "dependencies": {
- "node-domexception": "^1.0.0",
- "web-streams-polyfill": "^3.0.3"
- },
- "engines": {
- "node": "^12.20 || >= 14.13"
- }
- },
"node_modules/fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
@@ -951,17 +920,6 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
},
- "node_modules/formdata-polyfill": {
- "version": "4.0.10",
- "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
- "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
- "dependencies": {
- "fetch-blob": "^3.1.2"
- },
- "engines": {
- "node": ">=12.20.0"
- }
- },
"node_modules/forwarded": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
@@ -1352,41 +1310,6 @@
"resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz",
"integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ=="
},
- "node_modules/node-domexception": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
- "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/jimmywarting"
- },
- {
- "type": "github",
- "url": "https://paypal.me/jimmywarting"
- }
- ],
- "engines": {
- "node": ">=10.5.0"
- }
- },
- "node_modules/node-fetch": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.1.tgz",
- "integrity": "sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==",
- "dependencies": {
- "data-uri-to-buffer": "^4.0.0",
- "fetch-blob": "^3.1.4",
- "formdata-polyfill": "^4.0.10"
- },
- "engines": {
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/node-fetch"
- }
- },
"node_modules/nodemon": {
"version": "2.0.22",
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.22.tgz",
@@ -2076,14 +1999,6 @@
"node": ">= 0.8"
}
},
- "node_modules/web-streams-polyfill": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz",
- "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==",
- "engines": {
- "node": ">= 8"
- }
- },
"node_modules/which": {
"version": "1.2.14",
"resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz",
@@ -2553,11 +2468,6 @@
"type": "^1.0.1"
}
},
- "data-uri-to-buffer": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
- "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A=="
- },
"dayjs": {
"version": "1.11.4",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.4.tgz",
@@ -2820,15 +2730,6 @@
"reusify": "^1.0.4"
}
},
- "fetch-blob": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
- "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
- "requires": {
- "node-domexception": "^1.0.0",
- "web-streams-polyfill": "^3.0.3"
- }
- },
"fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
@@ -2866,14 +2767,6 @@
}
}
},
- "formdata-polyfill": {
- "version": "4.0.10",
- "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
- "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
- "requires": {
- "fetch-blob": "^3.1.2"
- }
- },
"forwarded": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
@@ -3159,21 +3052,6 @@
"resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz",
"integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ=="
},
- "node-domexception": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
- "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="
- },
- "node-fetch": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.1.tgz",
- "integrity": "sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==",
- "requires": {
- "data-uri-to-buffer": "^4.0.0",
- "fetch-blob": "^3.1.4",
- "formdata-polyfill": "^4.0.10"
- }
- },
"nodemon": {
"version": "2.0.22",
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.22.tgz",
@@ -3672,11 +3550,6 @@
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
"integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="
},
- "web-streams-polyfill": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz",
- "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q=="
- },
"which": {
"version": "1.2.14",
"resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz",
diff --git a/package.json b/package.json
index 50110ef..1b200fb 100644
--- a/package.json
+++ b/package.json
@@ -6,8 +6,9 @@
"scripts": {
"start": "nodemon",
"test": "exit 0",
- "json": "tsc && node ./js/scripts/json_plugins.js && git add plugins && git add dist && git add js/plugins",
- "generate": "ts-node ./scripts/multisrc/generate.ts"
+ "json": "tsc && node ./.js/scripts/json_plugins.js && git add plugins && git add .dist && git add .js/plugins",
+ "generate": "ts-node ./scripts/multisrc/generate.ts",
+ "clearMulti": "ts-node ./scripts/clearMultisrc.ts"
},
"author": "",
"license": "MIT",
@@ -18,17 +19,16 @@
"dayjs": "^1.11.4",
"express": "^4.18.2",
"module-alias": "^2.2.2",
- "node-fetch": "^3",
"ts-node": "^10.9.1",
"tsc-alias": "^1.8.6",
"typescript": "^5.1.3"
},
"_moduleAliases": {
- "@libs": "./js/libs",
- "@icons": "./js/icons",
- "@plugins": "./js/plugins",
- "@scripts": "./js/scripts",
- "@typings": "./js/types"
+ "@libs": "./.js/libs",
+ "@icons": "./.js/icons",
+ "@plugins": "./.js/plugins",
+ "@scripts": "./.js/scripts",
+ "@typings": "./.js/types"
},
"devDependencies": {
"@types/express": "^4.17.17",
diff --git a/plugins/arabic/ArMTL[madara].ts b/plugins/arabic/ArMTL[madara].ts
index 6d2ed5e..10066af 100644
--- a/plugins/arabic/ArMTL[madara].ts
+++ b/plugins/arabic/ArMTL[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "ar-mtl";
-export const name = "ArMTL [madara]";
-export const icon = "multisrc/madara/icons/armtl.png";
-export const version = "1.0.0";
-export const site = "https://ar-mtl.club/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "novel-genre/" + filters.genres + '/';
- } else {
- url += "novel/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (true) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"ar-mtl","sourceSite":"https://ar-mtl.club/","sourceName":"ArMTL","filters":[],"options":{"useNewChapterEndpoint":true,"lang":"Arabic"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/arabic/ArNovel[madara].ts b/plugins/arabic/ArNovel[madara].ts
index 224837d..544282d 100644
--- a/plugins/arabic/ArNovel[madara].ts
+++ b/plugins/arabic/ArNovel[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "arnovel";
-export const name = "ArNovel [madara]";
-export const icon = "multisrc/madara/icons/arnovel.png";
-export const version = "1.0.0";
-export const site = "https://arnovel.me/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "home/novel-genre/" + filters.genres + '/';
- } else {
- url += "novel/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (true) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [{"key":"sort","label":"الترتيب حسب","values":[{"label":"A-Z","value":"alphabet"},{"label":"الآخير","value":"latest"},{"label":"الأكثر مشاهدة","value":"views"},{"label":"التقييم","value":"rating"},{"label":"جديد","value":"new-manga"},{"label":"شائع","value":"trending"}],"inputType":FilterInputs.Picker},{"key":"genres","label":"التصنيفات","values":[{"label":"أكشن","value":"%d8%a3%d9%83%d8%b4%d9%86"},{"label":"إتشي","value":"%d8%a5%d8%aa%d8%b4%d9%80%d9%8a"},{"label":"بالغ","value":"%d8%a8%d8%a7%d9%84%d8%ba"},{"label":"تاريخي","value":"%d8%aa%d8%a7%d8%b1%d9%8a%d8%ae%d9%8a"},{"label":"تراجدي","value":"%d8%aa%d8%b1%d8%a7%d8%ac%d8%af%d9%8a"},{"label":"جوسي","value":"%d8%ac%d9%88%d8%b3%d9%8a"},{"label":"حريم","value":"%d8%ad%d8%b1%d9%8a%d9%85"},{"label":"حياة مدرسية","value":"%d8%ad%d9%8a%d8%a7%d8%a9-%d9%85%d8%af%d8%b1%d8%b3%d9%8a%d8%a9"},{"label":"خارق لطبيعية","value":"%d8%ae%d8%a7%d8%b1%d9%82-%d9%84%d8%b7%d8%a8%d9%8a%d8%b9%d9%8a%d8%a9"},{"label":"خيال","value":"%d8%ae%d9%8a%d8%a7%d9%84"},{"label":"خيال علمي","value":"%d8%ae%d9%8a%d8%a7%d9%84-%d8%b9%d9%84%d9%85%d9%8a"},{"label":"دراما","value":"%d8%af%d8%b1%d8%a7%d9%85%d8%a7"},{"label":"راشد","value":"%d8%b1%d8%a7%d8%b4%d8%af"},{"label":"رعب","value":"%d8%b1%d8%b9%d8%a8"},{"label":"رومنسي","value":"%d8%b1%d9%88%d9%85%d9%86%d8%b3%d9%8a"},{"label":"رياضي","value":"%d8%b1%d9%8a%d8%a7%d8%b6%d9%8a"},{"label":"سينين","value":"%d8%b3%d9%8a%d9%86%d9%8a%d9%86"},{"label":"شريحة من الحياة","value":"%d8%b4%d8%b1%d9%8a%d8%ad%d8%a9-%d9%85%d9%86-%d8%a7%d9%84%d8%ad%d9%8a%d8%a7%d8%a9"},{"label":"شوجو","value":"%d8%b4%d9%88%d8%ac%d9%88"},{"label":"شونين","value":"%d8%b4%d9%88%d9%86%d9%8a%d9%86"},{"label":"غموض","value":"%d8%ba%d9%85%d9%88%d8%b6"},{"label":"فنون قتال","value":"%d9%81%d9%86%d9%88%d9%86-%d9%82%d8%aa%d8%a7%d9%84"},{"label":"كوميديا","value":"%d9%83%d9%88%d9%85%d9%8a%d8%af%d9%8a%d8%a7"},{"label":"مغامرات","value":"%d9%85%d8%ba%d8%a7%d9%85%d8%b1%d8%a7%d8%aa"},{"label":"منتهية","value":"%d9%85%d9%86%d8%aa%d9%87%d9%8a%d8%a9"},{"label":"ميكا","value":"%d9%85%d9%8a%d9%83%d8%a7"},{"label":"نفسي","value":"%d9%86%d9%81%d8%b3%d9%8a"}],"inputType":FilterInputs.Picker}];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"arnovel","sourceSite":"https://arnovel.me/","sourceName":"ArNovel","filters":[{"key":"sort","label":"الترتيب حسب","values":[{"label":"A-Z","value":"alphabet"},{"label":"الآخير","value":"latest"},{"label":"الأكثر مشاهدة","value":"views"},{"label":"التقييم","value":"rating"},{"label":"جديد","value":"new-manga"},{"label":"شائع","value":"trending"}],"inputType":"Picker"},{"key":"genres","label":"التصنيفات","values":[{"label":"أكشن","value":"%d8%a3%d9%83%d8%b4%d9%86"},{"label":"إتشي","value":"%d8%a5%d8%aa%d8%b4%d9%80%d9%8a"},{"label":"بالغ","value":"%d8%a8%d8%a7%d9%84%d8%ba"},{"label":"تاريخي","value":"%d8%aa%d8%a7%d8%b1%d9%8a%d8%ae%d9%8a"},{"label":"تراجدي","value":"%d8%aa%d8%b1%d8%a7%d8%ac%d8%af%d9%8a"},{"label":"جوسي","value":"%d8%ac%d9%88%d8%b3%d9%8a"},{"label":"حريم","value":"%d8%ad%d8%b1%d9%8a%d9%85"},{"label":"حياة مدرسية","value":"%d8%ad%d9%8a%d8%a7%d8%a9-%d9%85%d8%af%d8%b1%d8%b3%d9%8a%d8%a9"},{"label":"خارق لطبيعية","value":"%d8%ae%d8%a7%d8%b1%d9%82-%d9%84%d8%b7%d8%a8%d9%8a%d8%b9%d9%8a%d8%a9"},{"label":"خيال","value":"%d8%ae%d9%8a%d8%a7%d9%84"},{"label":"خيال علمي","value":"%d8%ae%d9%8a%d8%a7%d9%84-%d8%b9%d9%84%d9%85%d9%8a"},{"label":"دراما","value":"%d8%af%d8%b1%d8%a7%d9%85%d8%a7"},{"label":"راشد","value":"%d8%b1%d8%a7%d8%b4%d8%af"},{"label":"رعب","value":"%d8%b1%d8%b9%d8%a8"},{"label":"رومنسي","value":"%d8%b1%d9%88%d9%85%d9%86%d8%b3%d9%8a"},{"label":"رياضي","value":"%d8%b1%d9%8a%d8%a7%d8%b6%d9%8a"},{"label":"سينين","value":"%d8%b3%d9%8a%d9%86%d9%8a%d9%86"},{"label":"شريحة من الحياة","value":"%d8%b4%d8%b1%d9%8a%d8%ad%d8%a9-%d9%85%d9%86-%d8%a7%d9%84%d8%ad%d9%8a%d8%a7%d8%a9"},{"label":"شوجو","value":"%d8%b4%d9%88%d8%ac%d9%88"},{"label":"شونين","value":"%d8%b4%d9%88%d9%86%d9%8a%d9%86"},{"label":"غموض","value":"%d8%ba%d9%85%d9%88%d8%b6"},{"label":"فنون قتال","value":"%d9%81%d9%86%d9%88%d9%86-%d9%82%d8%aa%d8%a7%d9%84"},{"label":"كوميديا","value":"%d9%83%d9%88%d9%85%d9%8a%d8%af%d9%8a%d8%a7"},{"label":"مغامرات","value":"%d9%85%d8%ba%d8%a7%d9%85%d8%b1%d8%a7%d8%aa"},{"label":"منتهية","value":"%d9%85%d9%86%d8%aa%d9%87%d9%8a%d8%a9"},{"label":"ميكا","value":"%d9%85%d9%8a%d9%83%d8%a7"},{"label":"نفسي","value":"%d9%86%d9%81%d8%b3%d9%8a"}],"inputType":"Picker"}],"options":{"path":{"genres":"home/novel-genre"},"useNewChapterEndpoint":true,"lang":"Arabic"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/arabic/HizoManga[madara].ts b/plugins/arabic/HizoManga[madara].ts
index 053bb67..b4dbf6e 100644
--- a/plugins/arabic/HizoManga[madara].ts
+++ b/plugins/arabic/HizoManga[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "hizomanga";
-export const name = "HizoManga [madara]";
-export const icon = "multisrc/madara/icons/hizomanga.png";
-export const version = "1.0.0";
-export const site = "https://hizomanga.com/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "manga-genre/" + filters.genres + '/';
- } else {
- url += "serie/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (true) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "serie" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [{"key":"sort","label":"ترتيب حسب","values":[{"label":"A-Z","value":"alphabet"},{"label":"New","value":"new-manga"},{"label":"الأحدث","value":"latest"},{"label":"الأكثر مشاهدة","value":"views"},{"label":"التقييم","value":"rating"},{"label":"الرائج","value":"trending"}],"inputType":FilterInputs.Picker},{"key":"genres","label":"التصنيفات","values":[{"label":"آلات","value":"mechanisms"},{"label":"أكشن","value":"action"},{"label":"إثارة","value":"excitement"},{"label":"إيسكاي","value":"%d8%a5%d9%8a%d8%b3%d9%83%d8%a7%d9%8a"},{"label":"الحياة اليومية","value":"slice-of-life"},{"label":"الحياة مدرسية","value":"school-life"},{"label":"تاريخي","value":"historical"},{"label":"تراجيدي","value":"tragic"},{"label":"جريمة","value":"%d8%ac%d8%b1%d9%8a%d9%85%d8%a9"},{"label":"جندر بندر","value":"%d8%ac%d9%86%d8%af%d8%b1-%d8%a8%d9%86%d8%af%d8%b1"},{"label":"جوسي","value":"josei"},{"label":"حريم","value":"harem"},{"label":"خارق للطبيعة","value":"supernatural"},{"label":"خيال","value":"fantasy"},{"label":"خيال علمي","value":"sci-fi"},{"label":"دراما","value":"drama"},{"label":"دموي","value":"%d8%af%d9%85%d9%88%d9%8a"},{"label":"راشد","value":"mature"},{"label":"رعب","value":"horror"},{"label":"رومانسي","value":"romance"},{"label":"رياضة","value":"sports"},{"label":"زمنكاني","value":"my-time"},{"label":"زومبي","value":"%d8%b2%d9%88%d9%85%d8%a8%d9%8a"},{"label":"سينين","value":"seinen"},{"label":"شريحة من الحياة","value":"%d8%b4%d8%b1%d9%8a%d8%ad%d8%a9-%d9%85%d9%86-%d8%a7%d9%84%d8%ad%d9%8a%d8%a7%d8%a9"},{"label":"شوجو","value":"shoujo"},{"label":"شونين","value":"shounen"},{"label":"طبي","value":"%d8%b7%d8%a8%d9%8a"},{"label":"غموض","value":"ambiguity"},{"label":"فنون قتالية","value":"martial-arts"},{"label":"قوة خارقة","value":"superpower"},{"label":"كوميدي","value":"comedy"},{"label":"مغامرات","value":"adventure"},{"label":"نفسي","value":"psychological"}],"inputType":FilterInputs.Picker}];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"hizomanga","sourceSite":"https://hizomanga.com/","sourceName":"HizoManga","filters":[{"key":"sort","label":"ترتيب حسب","values":[{"label":"A-Z","value":"alphabet"},{"label":"New","value":"new-manga"},{"label":"الأحدث","value":"latest"},{"label":"الأكثر مشاهدة","value":"views"},{"label":"التقييم","value":"rating"},{"label":"الرائج","value":"trending"}],"inputType":"Picker"},{"key":"genres","label":"التصنيفات","values":[{"label":"آلات","value":"mechanisms"},{"label":"أكشن","value":"action"},{"label":"إثارة","value":"excitement"},{"label":"إيسكاي","value":"%d8%a5%d9%8a%d8%b3%d9%83%d8%a7%d9%8a"},{"label":"الحياة اليومية","value":"slice-of-life"},{"label":"الحياة مدرسية","value":"school-life"},{"label":"تاريخي","value":"historical"},{"label":"تراجيدي","value":"tragic"},{"label":"جريمة","value":"%d8%ac%d8%b1%d9%8a%d9%85%d8%a9"},{"label":"جندر بندر","value":"%d8%ac%d9%86%d8%af%d8%b1-%d8%a8%d9%86%d8%af%d8%b1"},{"label":"جوسي","value":"josei"},{"label":"حريم","value":"harem"},{"label":"خارق للطبيعة","value":"supernatural"},{"label":"خيال","value":"fantasy"},{"label":"خيال علمي","value":"sci-fi"},{"label":"دراما","value":"drama"},{"label":"دموي","value":"%d8%af%d9%85%d9%88%d9%8a"},{"label":"راشد","value":"mature"},{"label":"رعب","value":"horror"},{"label":"رومانسي","value":"romance"},{"label":"رياضة","value":"sports"},{"label":"زمنكاني","value":"my-time"},{"label":"زومبي","value":"%d8%b2%d9%88%d9%85%d8%a8%d9%8a"},{"label":"سينين","value":"seinen"},{"label":"شريحة من الحياة","value":"%d8%b4%d8%b1%d9%8a%d8%ad%d8%a9-%d9%85%d9%86-%d8%a7%d9%84%d8%ad%d9%8a%d8%a7%d8%a9"},{"label":"شوجو","value":"shoujo"},{"label":"شونين","value":"shounen"},{"label":"طبي","value":"%d8%b7%d8%a8%d9%8a"},{"label":"غموض","value":"ambiguity"},{"label":"فنون قتالية","value":"martial-arts"},{"label":"قوة خارقة","value":"superpower"},{"label":"كوميدي","value":"comedy"},{"label":"مغامرات","value":"adventure"},{"label":"نفسي","value":"psychological"}],"inputType":"Picker"}],"options":{"path":{"novels":"serie","novel":"serie","chapter":"serie","genres":"manga-genre"},"useNewChapterEndpoint":true,"lang":"Arabic"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/arabic/Novel4Up[madara].ts b/plugins/arabic/Novel4Up[madara].ts
index 0b3788c..04ddfb1 100644
--- a/plugins/arabic/Novel4Up[madara].ts
+++ b/plugins/arabic/Novel4Up[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "novel4up";
-export const name = "Novel4Up [madara]";
-export const icon = "multisrc/madara/icons/novel4up.png";
-export const version = "1.0.0";
-export const site = "https://novel4up.com/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "novel-genre/" + filters.genres + '/';
- } else {
- url += "novel/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (false) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [{"key":"sort","label":"ترتيب حسب:","values":[{"label":"أ-ي","value":"alphabet"},{"label":"الأحدث","value":"latest"},{"label":"الأكثر مشاهدة","value":"views"},{"label":"التقييم","value":"rating"},{"label":"الجديد","value":"new-manga"},{"label":"الشائع","value":"trending"}],"inputType":FilterInputs.Picker},{"key":"genres","label":"التصنيفات","values":[{"label":"أكشن","value":"action"},{"label":"الخارق للطبيعة","value":"supernatural"},{"label":"تاريخي","value":"historical"},{"label":"تحقيق","value":"detective"},{"label":"تراجيديا","value":"tragedy"},{"label":"حريم","value":"harem"},{"label":"حياة مدرسية","value":"school-life"},{"label":"خيال علمي","value":"sci-fi"},{"label":"دراما","value":"drama"},{"label":"رعب","value":"horror"},{"label":"رومانسي","value":"romance"},{"label":"رياضة","value":"sports"},{"label":"سحر","value":"magic"},{"label":"شريحة من الحياة","value":"slice-of-life"},{"label":"شوانهوا","value":"xuanhuan"},{"label":"شوجو","value":"shoujo"},{"label":"شونين","value":"shounen"},{"label":"غموض","value":"mystery"},{"label":"فانتازيا","value":"fantasy"},{"label":"فنون قتال","value":"martial-arts"},{"label":"كوميديا","value":"comedy"},{"label":"مغامرة","value":"adventure"},{"label":"ميكا","value":"mecha"},{"label":"نفسي","value":"psychological"},{"label":"ون شوت","value":"one-shot"},{"label":"ووشيا","value":"wuxia"}],"inputType":FilterInputs.Picker}];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"novel4up","sourceSite":"https://novel4up.com/","sourceName":"Novel4Up","filters":[{"key":"sort","label":"ترتيب حسب:","values":[{"label":"أ-ي","value":"alphabet"},{"label":"الأحدث","value":"latest"},{"label":"الأكثر مشاهدة","value":"views"},{"label":"التقييم","value":"rating"},{"label":"الجديد","value":"new-manga"},{"label":"الشائع","value":"trending"}],"inputType":"Picker"},{"key":"genres","label":"التصنيفات","values":[{"label":"أكشن","value":"action"},{"label":"الخارق للطبيعة","value":"supernatural"},{"label":"تاريخي","value":"historical"},{"label":"تحقيق","value":"detective"},{"label":"تراجيديا","value":"tragedy"},{"label":"حريم","value":"harem"},{"label":"حياة مدرسية","value":"school-life"},{"label":"خيال علمي","value":"sci-fi"},{"label":"دراما","value":"drama"},{"label":"رعب","value":"horror"},{"label":"رومانسي","value":"romance"},{"label":"رياضة","value":"sports"},{"label":"سحر","value":"magic"},{"label":"شريحة من الحياة","value":"slice-of-life"},{"label":"شوانهوا","value":"xuanhuan"},{"label":"شوجو","value":"shoujo"},{"label":"شونين","value":"shounen"},{"label":"غموض","value":"mystery"},{"label":"فانتازيا","value":"fantasy"},{"label":"فنون قتال","value":"martial-arts"},{"label":"كوميديا","value":"comedy"},{"label":"مغامرة","value":"adventure"},{"label":"ميكا","value":"mecha"},{"label":"نفسي","value":"psychological"},{"label":"ون شوت","value":"one-shot"},{"label":"ووشيا","value":"wuxia"}],"inputType":"Picker"}],"options":{"lang":"Arabic"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/arabic/Riwyat[madara].ts b/plugins/arabic/Riwyat[madara].ts
index 9f3f0ae..e2064ce 100644
--- a/plugins/arabic/Riwyat[madara].ts
+++ b/plugins/arabic/Riwyat[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "riwyat";
-export const name = "Riwyat [madara]";
-export const icon = "multisrc/madara/icons/riwyat.png";
-export const version = "1.0.0";
-export const site = "https://riwyat.com/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "novel-genre/" + filters.genres + '/';
- } else {
- url += "novel/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (true) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":FilterInputs.Picker},{"key":"genres","label":"GENRES","values":[{"label":"أكشن","value":"%d8%a3%d9%83%d8%b4%d9%86"},{"label":"أيتشي","value":"%d8%a3%d9%8a%d8%aa%d8%b4%d9%8a"},{"label":"استراتجي","value":"%d8%a7%d8%b3%d8%aa%d8%b1%d8%a7%d8%aa%d8%ac%d9%8a"},{"label":"العصر الحديث","value":"%d8%a7%d9%84%d8%b9%d8%b5%d8%b1-%d8%a7%d9%84%d8%ad%d8%af%d9%8a%d8%ab"},{"label":"انتقام","value":"%d8%a7%d9%86%d8%aa%d9%82%d8%a7%d9%85"},{"label":"بالغ","value":"%d8%a8%d8%a7%d9%84%d8%ba"},{"label":"بناء مملكة","value":"%d8%a8%d9%86%d8%a7%d8%a1-%d9%85%d9%85%d9%84%d9%83%d8%a9"},{"label":"بوليسي","value":"%d8%a8%d9%88%d9%84%d9%8a%d8%b3%d9%8a"},{"label":"تاريخي","value":"%d8%aa%d8%a7%d8%b1%d9%8a%d8%ae%d9%8a"},{"label":"جوسي","value":"%d8%ac%d9%88%d8%b3%d9%8a"},{"label":"حريم","value":"%d8%ad%d8%b1%d9%8a%d9%85"},{"label":"حياة يومية","value":"%d8%ad%d9%8a%d8%a7%d8%a9-%d9%8a%d9%88%d9%85%d9%8a%d8%a9"},{"label":"خيال","value":"%d8%ae%d9%8a%d8%a7%d9%84"},{"label":"خيال علمي","value":"%d8%ae%d9%8a%d8%a7%d9%84-%d8%b9%d9%84%d9%85%d9%8a"},{"label":"دراما","value":"%d8%af%d8%b1%d8%a7%d9%85%d8%a7"},{"label":"رعب","value":"%d8%b1%d8%b9%d8%a8"},{"label":"رومانسية","value":"%d8%b1%d9%88%d9%85%d8%a7%d9%86%d8%b3%d9%8a%d8%a9"},{"label":"رياضي","value":"%d8%b1%d9%8a%d8%a7%d8%b6%d9%8a"},{"label":"زيانشيا","value":"xianxia"},{"label":"سنين","value":"%d8%b3%d9%86%d9%8a%d9%86"},{"label":"شريحة حياة","value":"%d8%b4%d8%b1%d9%8a%d8%ad%d8%a9-%d8%ad%d9%8a%d8%a7%d8%a9"},{"label":"شوانهوان","value":"xuanhuan"},{"label":"شوجو","value":"%d8%b4%d9%88%d8%ac%d9%88"},{"label":"شونين","value":"%d8%b4%d9%88%d9%86%d9%8a%d9%86"},{"label":"شيانشيا","value":"%d8%b4%d9%8a%d8%a7%d9%86%d8%b4%d9%8a%d8%a7"},{"label":"عسكري","value":"%d8%b9%d8%b3%d9%83%d8%b1%d9%8a"},{"label":"غموض","value":"%d8%ba%d9%85%d9%88%d8%b6"},{"label":"فانتازيا","value":"%d9%81%d8%a7%d9%86%d8%aa%d8%a7%d8%b2%d9%8a%d8%a7"},{"label":"فنون قتالية","value":"%d9%81%d9%86%d9%88%d9%86-%d9%82%d8%aa%d8%a7%d9%84%d9%8a%d8%a9"},{"label":"قوى خارقة","value":"%d9%82%d9%88%d9%89-%d8%ae%d8%a7%d8%b1%d9%82%d8%a9"},{"label":"كوميديا","value":"%d9%83%d9%88%d9%85%d9%8a%d8%af%d9%8a%d8%a7"},{"label":"كوميك","value":"%d9%83%d9%88%d9%85%d9%8a%d9%83"},{"label":"للكبار","value":"%d9%84%d9%84%d9%83%d8%a8%d8%a7%d8%b1"},{"label":"مأساة","value":"%d9%85%d8%a3%d8%b3%d8%a7%d8%a9"},{"label":"مانجا","value":"%d9%85%d8%a7%d9%86%d8%ac%d8%a7"},{"label":"مانها","value":"%d9%85%d8%a7%d9%86%d9%87%d8%a7"},{"label":"مانهوا","value":"%d9%85%d8%a7%d9%86%d9%87%d9%88%d8%a7"},{"label":"مدرسي","value":"%d9%85%d8%af%d8%b1%d8%b3%d9%8a"},{"label":"مصاصي دماء","value":"%d9%85%d8%b5%d8%a7%d8%b5%d9%8a-%d8%af%d9%85%d8%a7%d8%a1"},{"label":"مغامرة","value":"%d9%85%d8%ba%d8%a7%d9%85%d8%b1%d8%a9"},{"label":"مكتملة","value":"%d9%85%d9%83%d8%aa%d9%85%d9%84%d8%a9"},{"label":"نفسي","value":"%d9%86%d9%81%d8%b3%d9%8a"},{"label":"نهاية العالم","value":"%d9%86%d9%87%d8%a7%d9%8a%d8%a9-%d8%a7%d9%84%d8%b9%d8%a7%d9%84%d9%85"},{"label":"واب تون","value":"%d9%88%d8%a7%d8%a8-%d8%aa%d9%88%d9%86"},{"label":"وان شوت","value":"%d9%88%d8%a7%d9%86-%d8%b4%d9%88%d8%aa"}],"inputType":FilterInputs.Picker}];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"riwyat","sourceSite":"https://riwyat.com/","sourceName":"Riwyat","filters":[{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":"Picker"},{"key":"genres","label":"GENRES","values":[{"label":"أكشن","value":"%d8%a3%d9%83%d8%b4%d9%86"},{"label":"أيتشي","value":"%d8%a3%d9%8a%d8%aa%d8%b4%d9%8a"},{"label":"استراتجي","value":"%d8%a7%d8%b3%d8%aa%d8%b1%d8%a7%d8%aa%d8%ac%d9%8a"},{"label":"العصر الحديث","value":"%d8%a7%d9%84%d8%b9%d8%b5%d8%b1-%d8%a7%d9%84%d8%ad%d8%af%d9%8a%d8%ab"},{"label":"انتقام","value":"%d8%a7%d9%86%d8%aa%d9%82%d8%a7%d9%85"},{"label":"بالغ","value":"%d8%a8%d8%a7%d9%84%d8%ba"},{"label":"بناء مملكة","value":"%d8%a8%d9%86%d8%a7%d8%a1-%d9%85%d9%85%d9%84%d9%83%d8%a9"},{"label":"بوليسي","value":"%d8%a8%d9%88%d9%84%d9%8a%d8%b3%d9%8a"},{"label":"تاريخي","value":"%d8%aa%d8%a7%d8%b1%d9%8a%d8%ae%d9%8a"},{"label":"جوسي","value":"%d8%ac%d9%88%d8%b3%d9%8a"},{"label":"حريم","value":"%d8%ad%d8%b1%d9%8a%d9%85"},{"label":"حياة يومية","value":"%d8%ad%d9%8a%d8%a7%d8%a9-%d9%8a%d9%88%d9%85%d9%8a%d8%a9"},{"label":"خيال","value":"%d8%ae%d9%8a%d8%a7%d9%84"},{"label":"خيال علمي","value":"%d8%ae%d9%8a%d8%a7%d9%84-%d8%b9%d9%84%d9%85%d9%8a"},{"label":"دراما","value":"%d8%af%d8%b1%d8%a7%d9%85%d8%a7"},{"label":"رعب","value":"%d8%b1%d8%b9%d8%a8"},{"label":"رومانسية","value":"%d8%b1%d9%88%d9%85%d8%a7%d9%86%d8%b3%d9%8a%d8%a9"},{"label":"رياضي","value":"%d8%b1%d9%8a%d8%a7%d8%b6%d9%8a"},{"label":"زيانشيا","value":"xianxia"},{"label":"سنين","value":"%d8%b3%d9%86%d9%8a%d9%86"},{"label":"شريحة حياة","value":"%d8%b4%d8%b1%d9%8a%d8%ad%d8%a9-%d8%ad%d9%8a%d8%a7%d8%a9"},{"label":"شوانهوان","value":"xuanhuan"},{"label":"شوجو","value":"%d8%b4%d9%88%d8%ac%d9%88"},{"label":"شونين","value":"%d8%b4%d9%88%d9%86%d9%8a%d9%86"},{"label":"شيانشيا","value":"%d8%b4%d9%8a%d8%a7%d9%86%d8%b4%d9%8a%d8%a7"},{"label":"عسكري","value":"%d8%b9%d8%b3%d9%83%d8%b1%d9%8a"},{"label":"غموض","value":"%d8%ba%d9%85%d9%88%d8%b6"},{"label":"فانتازيا","value":"%d9%81%d8%a7%d9%86%d8%aa%d8%a7%d8%b2%d9%8a%d8%a7"},{"label":"فنون قتالية","value":"%d9%81%d9%86%d9%88%d9%86-%d9%82%d8%aa%d8%a7%d9%84%d9%8a%d8%a9"},{"label":"قوى خارقة","value":"%d9%82%d9%88%d9%89-%d8%ae%d8%a7%d8%b1%d9%82%d8%a9"},{"label":"كوميديا","value":"%d9%83%d9%88%d9%85%d9%8a%d8%af%d9%8a%d8%a7"},{"label":"كوميك","value":"%d9%83%d9%88%d9%85%d9%8a%d9%83"},{"label":"للكبار","value":"%d9%84%d9%84%d9%83%d8%a8%d8%a7%d8%b1"},{"label":"مأساة","value":"%d9%85%d8%a3%d8%b3%d8%a7%d8%a9"},{"label":"مانجا","value":"%d9%85%d8%a7%d9%86%d8%ac%d8%a7"},{"label":"مانها","value":"%d9%85%d8%a7%d9%86%d9%87%d8%a7"},{"label":"مانهوا","value":"%d9%85%d8%a7%d9%86%d9%87%d9%88%d8%a7"},{"label":"مدرسي","value":"%d9%85%d8%af%d8%b1%d8%b3%d9%8a"},{"label":"مصاصي دماء","value":"%d9%85%d8%b5%d8%a7%d8%b5%d9%8a-%d8%af%d9%85%d8%a7%d8%a1"},{"label":"مغامرة","value":"%d9%85%d8%ba%d8%a7%d9%85%d8%b1%d8%a9"},{"label":"مكتملة","value":"%d9%85%d9%83%d8%aa%d9%85%d9%84%d8%a9"},{"label":"نفسي","value":"%d9%86%d9%81%d8%b3%d9%8a"},{"label":"نهاية العالم","value":"%d9%86%d9%87%d8%a7%d9%8a%d8%a9-%d8%a7%d9%84%d8%b9%d8%a7%d9%84%d9%85"},{"label":"واب تون","value":"%d9%88%d8%a7%d8%a8-%d8%aa%d9%88%d9%86"},{"label":"وان شوت","value":"%d9%88%d8%a7%d9%86-%d8%b4%d9%88%d8%aa"}],"inputType":"Picker"}],"options":{"useNewChapterEndpoint":true,"lang":"Arabic"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/arabic/TeamXNovel[madara].ts b/plugins/arabic/TeamXNovel[madara].ts
index cad5251..060d16d 100644
--- a/plugins/arabic/TeamXNovel[madara].ts
+++ b/plugins/arabic/TeamXNovel[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "teamxnovel";
-export const name = "TeamXNovel [madara]";
-export const icon = "multisrc/madara/icons/teamxnovel.png";
-export const version = "1.0.0";
-export const site = "https://teamxnovel.com/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "novel-genre/" + filters.genres + '/';
- } else {
- url += "novel/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (true) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"teamxnovel","sourceSite":"https://teamxnovel.com/","sourceName":"TeamXNovel","filters":[],"options":{"useNewChapterEndpoint":true,"lang":"Arabic"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/arabic/kolnovel.ts b/plugins/arabic/kolnovel.ts
index f9e786e..5d0d62f 100644
--- a/plugins/arabic/kolnovel.ts
+++ b/plugins/arabic/kolnovel.ts
@@ -1,74 +1,73 @@
import { load as parseHTML } from "cheerio";
import { fetchApi, fetchFile } from "@libs/fetch";
-import { FilterInputs } from "@libs/filterInputs";
-import { Chapter, Novel, Plugin } from "@typings/plugin";
+import { Filter, FilterInputs } from "@libs/filterInputs";
+import { Plugin } from "@typings/plugin";
-export const id = "kolnovel";
-export const name = "KolNovel";
-export const version = "1.0.0";
-export const icon = "multisrc/wpmangastream/icons/kolnovel.png";
-export const site = "https://kolnovel.com/";
+class KolNovel implements Plugin.PluginBase {
+ id = "kolnovel";
+ name = "KolNovel";
+ icon = "multisrc/wpmangastream/icons/kolnovel.png"
+ site = "https://kolnovel.lol/";
+ version = "1.0.0";
+ userAgent = "";
+ cookieString = "";
+ async popularNovels(pageNo: number, {filters}: Plugin.PopularNovelsOptions): Promise {
+ let link = `${this.site}series/?page=${pageNo}`;
+ if (filters) {
+ if (Array.isArray(filters.genres) && filters.genres.length) {
+ link += filters.genres.map((i) => `&genre[]=${i}`).join("");
+ }
-const pluginId = id;
-const baseUrl = site;
-
-export const popularNovels: Plugin.popularNovels = async function (
- page,
- { filters }
-) {
- let link = `${baseUrl}series/?page=${page}`;
-
- if (filters) {
- if (Array.isArray(filters.genres) && filters.genres.length) {
- link += filters.genres.map((i) => `&genre[]=${i}`).join("");
+ if (Array.isArray(filters.type) && filters.type.length)
+ link += filters.type.map((i) => `&lang[]=${i}`).join("");
}
+ link += "&status=" + (filters?.status ? filters.status : "");
- if (Array.isArray(filters.type) && filters.type.length)
- link += filters.type.map((i) => `&lang[]=${i}`).join("");
+ link += "&order=" + (filters?.order ? filters.order : "popular");
+ const headers = new Headers();
+ if(this.cookieString){
+ headers.append("cookie", this.cookieString);
+ }
+ const body = await fetchApi(link, {headers}).then((result) =>
+ result.text()
+ );
+
+ const loadedCheerio = parseHTML(body);
+
+ const novels: Plugin.NovelItem[] = [];
+
+ loadedCheerio("article.maindet").each(function () {
+ const novelName = loadedCheerio(this).find("h2").text();
+ let image = loadedCheerio(this).find("img");
+ const novelCover = image.attr("data-src") || image.attr("src");
+ const novelUrl = loadedCheerio(this).find("h2 a").attr("href");
+
+ if (!novelUrl) return;
+
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
}
- link += "&status=" + (filters?.status ? filters.status : "");
-
- link += "&order=" + (filters?.order ? filters.order : "popular");
-
- const body = await fetchApi(link, {}, pluginId).then((result) =>
- result.text()
- );
-
- const loadedCheerio = parseHTML(body);
-
- const novels: Novel.Item[] = [];
-
- loadedCheerio("article.maindet").each(function () {
- const novelName = loadedCheerio(this).find("h2").text();
- let image = loadedCheerio(this).find("img");
- const novelCover = image.attr("data-src") || image.attr("src");
- const novelUrl = loadedCheerio(this).find("h2 a").attr("href");
-
- if (!novelUrl) return;
-
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters =
- async function parseNovelAndChapters(novelUrl) {
+ async parseNovelAndChapters(novelUrl: string): Promise {
const url = novelUrl;
-
- const result = await fetchApi(url, {}, pluginId);
+ const headers = new Headers();
+ if(this.cookieString){
+ headers.append("cookie", this.cookieString);
+ }
+ const result = await fetch(url, {headers});
const body = await result.text();
let loadedCheerio = parseHTML(body);
- const novel: Novel.instance = {
+ const novel: Plugin.SourceNovel = {
url,
chapters: [],
};
@@ -105,7 +104,7 @@ export const parseNovelAndChapters: Plugin.parseNovelAndChapters =
.end()
.text();
- let chapter: Chapter.Item[] = [];
+ let chapter: Plugin.ChapterItem[] = [];
loadedCheerio(".eplister")
.find("li")
@@ -134,190 +133,193 @@ export const parseNovelAndChapters: Plugin.parseNovelAndChapters =
novel.chapters = chapter.reverse();
return novel;
- };
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const headers = new Headers();
+ if(this.cookieString){
+ headers.append("cookie", this.cookieString);
+ }
+ const result = await fetch(chapterUrl, {headers});
+ const body = await result.text();
+
+ const loadedCheerio = parseHTML(body);
-export const parseChapter: Plugin.parseChapter = async function parseChapter(
- chapterUrl
-) {
- const result = await fetchApi(chapterUrl, {}, pluginId);
- const body = await result.text();
+ loadedCheerio('.epcontent > div, i').remove();
+ let ignore = loadedCheerio('article > style').text().trim().split(',');
+ ignore.push(...(ignore.pop()?.match(/^\.\w+/) || []));
+ ignore.map(tag => loadedCheerio(`p${tag}`).remove());
- const loadedCheerio = parseHTML(body);
+ let chapterText = loadedCheerio('.epcontent').html() || "";
+
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const url = `${this.site}?s=${searchTerm}`;
+ const headers = new Headers();
+ if(this.cookieString){
+ headers.append("cookie", this.cookieString);
+ }
+ const result = await fetchApi(url, {headers});
+ const body = await result.text();
- let ignore = loadedCheerio(".epcontent > p").next().attr("class");
- loadedCheerio(`p.${ignore}`).remove();
- let chapterText = loadedCheerio(".epcontent").html();
+ const loadedCheerio = parseHTML(body);
- return chapterText;
-};
-export const searchNovels: Plugin.searchNovels = async function searchNovels(
- searchTerm
-) {
- const url = `${baseUrl}?s=${searchTerm}`;
+ const novels: Plugin.NovelItem[] = [];
- const result = await fetchApi(url, {}, pluginId);
- const body = await result.text();
+ loadedCheerio("article.maindet").each(function () {
+ const novelName = loadedCheerio(this).find("h2").text();
+ let image = loadedCheerio(this).find("img");
+ const novelCover = image.attr("data-src") || image.attr("src");
+ const novelUrl = loadedCheerio(this).find("h2 a").attr("href");
- const loadedCheerio = parseHTML(body);
+ if (!novelUrl) return;
- const novels: Novel.Item[] = [];
-
- loadedCheerio("article.maindet").each(function () {
- const novelName = loadedCheerio(this).find("h2").text();
- let image = loadedCheerio(this).find("img");
- const novelCover = image.attr("data-src") || image.attr("src");
- const novelUrl = loadedCheerio(this).find("h2 a").attr("href");
-
- if (!novelUrl) return;
-
- novels.push({
- name: novelName,
- url: novelUrl,
- cover: novelCover,
+ novels.push({
+ name: novelName,
+ url: novelUrl,
+ cover: novelCover,
+ });
});
- });
- return novels;
-};
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url);
+ }
+ filters = [
+ {
+ key: "order",
+ label: "ترتيب حسب",
+ values: [
+ { label: "الإعداد الأولي", value: "" },
+
+ { label: "A-Z", value: "title" },
+
+ { label: "Z-A", value: "titlereverse" },
+
+ { label: "أخر التحديثات", value: "update" },
+
+ { label: "أخر ما تم إضافته", value: "latest" },
+
+ { label: "الرائجة", value: "popular" },
+ ],
+ inputType: FilterInputs.Picker,
+ },
+ {
+ key: "status",
+ label: "الحالة",
+ values: [
+ { label: "All", value: "" },
+
+ { label: "Ongoing", value: "ongoing" },
+
+ { label: "Hiatus", value: "hiatus" },
+
+ { label: "Completed", value: "completed" },
+ ],
+ inputType: FilterInputs.Picker,
+ },
+ {
+ key: "type",
+ label: "النوع",
+ values: [
+ { label: "إنجليزية", value: "english" },
+
+ { label: "روايةلايت", value: "light-novel" },
+
+ { label: "روايةويب", value: "web-novel" },
+
+ { label: "صينية", value: "chinese" },
+
+ { label: "عربية", value: "arabic" },
+
+ { label: "كورية", value: "korean" },
+
+ { label: "يابانية", value: "japanese" },
+ ],
+ inputType: FilterInputs.Checkbox,
+ },
+ {
+ key: "genres",
+ label: "تصنيف",
+ values: [
+ { label: "Wuxia", value: "wuxia" },
+
+ { label: "Xianxia", value: "xianxia" },
+
+ { label: "XUANHUAN", value: "xuanhuan" },
+
+ { label: "أكشن", value: "action" },
+
+ { label: "إثارة", value: "excitement" },
+
+ { label: "إنتقالالىعالمأخر", value: "isekai" },
+
+ { label: "إيتشي", value: "etchi" },
+
+ { label: "الخيالالعلمي", value: "sci-fi" },
+
+ { label: "بوليسي", value: "policy" },
+
+ { label: "تاريخي", value: "historical" },
+
+ { label: "تحقيقات", value: "%d8%aa%d8%ad%d9%82%d9%8a%d9%82" },
+
+ { label: "تقمصشخصيات", value: "rpg" },
+
+ { label: "جريمة", value: "crime" },
+
+ { label: "جوسى", value: "josei" },
+
+ { label: "حريم", value: "harem" },
+
+ { label: "حياةمدرسية", value: "school-life" },
+
+ { label: "خيالي(فانتازيا)", value: "fantasy" },
+
+ { label: "دراما", value: "drama" },
+
+ { label: "رعب", value: "horror" },
+
+ { label: "رومانسي", value: "romantic" },
+
+ { label: "سحر", value: "magic" },
+
+ { label: "سينن", value: "senen" },
+
+ { label: "شريحةمنالحياة", value: "slice-of-life" },
+
+ { label: "شوجو", value: "shojo" },
+
+ { label: "شونين", value: "shonen" },
+
+ { label: "طبي", value: "medical" },
+
+ { label: "ظواهرخارقةللطبيعة", value: "supernatural" },
+
+ { label: "غموض", value: "mysteries" },
+
+ { label: "فنونالقتال", value: "martial-arts" },
+
+ { label: "قوىخارقة", value: "superpower" },
+
+ { label: "كوميدي", value: "comedy" },
+
+ { label: "مأساوي", value: "tragedy" },
+
+ { label: "مابعدالكارثة", value: "after-the-disaster" },
+
+ { label: "مغامرة", value: "adventure" },
+
+ { label: "ميكا", value: "mechanical" },
+
+ { label: "ناضج", value: "mature" },
+
+ { label: "نفسي", value: "psychological" },
+ ],
+ inputType: FilterInputs.Checkbox,
+ },
+ ];
+}
-export const fetchImage: Plugin.fetchImage = async function fetchImage(url) {
- const headers = {
- Referer: baseUrl,
- };
- return await fetchFile(url, { headers: headers });
-};
-
-export const filters = [
- {
- key: "order",
- label: "ترتيب حسب",
- values: [
- { label: "الإعداد الأولي", value: "" },
-
- { label: "A-Z", value: "title" },
-
- { label: "Z-A", value: "titlereverse" },
-
- { label: "أخر التحديثات", value: "update" },
-
- { label: "أخر ما تم إضافته", value: "latest" },
-
- { label: "الرائجة", value: "popular" },
- ],
- inputType: FilterInputs.Picker,
- },
- {
- key: "status",
- label: "الحالة",
- values: [
- { label: "All", value: "" },
-
- { label: "Ongoing", value: "ongoing" },
-
- { label: "Hiatus", value: "hiatus" },
-
- { label: "Completed", value: "completed" },
- ],
- inputType: FilterInputs.Picker,
- },
- {
- key: "type",
- label: "النوع",
- values: [
- { label: "إنجليزية", value: "english" },
-
- { label: "روايةلايت", value: "light-novel" },
-
- { label: "روايةويب", value: "web-novel" },
-
- { label: "صينية", value: "chinese" },
-
- { label: "عربية", value: "arabic" },
-
- { label: "كورية", value: "korean" },
-
- { label: "يابانية", value: "japanese" },
- ],
- inputType: FilterInputs.Checkbox,
- },
- {
- key: "genres",
- label: "تصنيف",
- values: [
- { label: "Wuxia", value: "wuxia" },
-
- { label: "Xianxia", value: "xianxia" },
-
- { label: "XUANHUAN", value: "xuanhuan" },
-
- { label: "أكشن", value: "action" },
-
- { label: "إثارة", value: "excitement" },
-
- { label: "إنتقالالىعالمأخر", value: "isekai" },
-
- { label: "إيتشي", value: "etchi" },
-
- { label: "الخيالالعلمي", value: "sci-fi" },
-
- { label: "بوليسي", value: "policy" },
-
- { label: "تاريخي", value: "historical" },
-
- { label: "تحقيقات", value: "%d8%aa%d8%ad%d9%82%d9%8a%d9%82" },
-
- { label: "تقمصشخصيات", value: "rpg" },
-
- { label: "جريمة", value: "crime" },
-
- { label: "جوسى", value: "josei" },
-
- { label: "حريم", value: "harem" },
-
- { label: "حياةمدرسية", value: "school-life" },
-
- { label: "خيالي(فانتازيا)", value: "fantasy" },
-
- { label: "دراما", value: "drama" },
-
- { label: "رعب", value: "horror" },
-
- { label: "رومانسي", value: "romantic" },
-
- { label: "سحر", value: "magic" },
-
- { label: "سينن", value: "senen" },
-
- { label: "شريحةمنالحياة", value: "slice-of-life" },
-
- { label: "شوجو", value: "shojo" },
-
- { label: "شونين", value: "shonen" },
-
- { label: "طبي", value: "medical" },
-
- { label: "ظواهرخارقةللطبيعة", value: "supernatural" },
-
- { label: "غموض", value: "mysteries" },
-
- { label: "فنونالقتال", value: "martial-arts" },
-
- { label: "قوىخارقة", value: "superpower" },
-
- { label: "كوميدي", value: "comedy" },
-
- { label: "مأساوي", value: "tragedy" },
-
- { label: "مابعدالكارثة", value: "after-the-disaster" },
-
- { label: "مغامرة", value: "adventure" },
-
- { label: "ميكا", value: "mechanical" },
-
- { label: "ناضج", value: "mature" },
-
- { label: "نفسي", value: "psychological" },
- ],
- inputType: FilterInputs.Checkbox,
- },
-];
+export default new KolNovel();
\ No newline at end of file
diff --git a/plugins/chinese/.chinese b/plugins/chinese/.gitkeep
similarity index 100%
rename from plugins/chinese/.chinese
rename to plugins/chinese/.gitkeep
diff --git a/plugins/chinese/linovelib.ts b/plugins/chinese/linovelib.ts
new file mode 100644
index 0000000..b73ad0d
--- /dev/null
+++ b/plugins/chinese/linovelib.ts
@@ -0,0 +1,559 @@
+import { CheerioAPI, load as parseHTML } from "cheerio";
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter, FilterInputs } from "@libs/filterInputs";
+import { Plugin } from "@typings/plugin";
+import { showToast } from "@libs/showToast";
+
+class Linovelib implements Plugin.PluginBase {
+ id = "linovelib";
+ name = "Linovelib";
+ icon = "src/cn/linovelib/icon.png";
+ site = "https://w.linovelib.com";
+ version = "1.0.0";
+ userAgent = "";
+ cookieString = "";
+ async popularNovels(pageNo: number, {filters}: Plugin.PopularNovelsOptions): Promise {
+ let link = `${this.site}/top/`;
+
+ link += (filters?.sort ? filters.sort : "monthvisit");
+
+ link += `/${pageNo}.html`;
+
+ const headers = new Headers();
+ if(this.cookieString){
+ headers.append("cookie", this.cookieString);
+ }
+ const body = await fetchApi(link, {headers}).then((result) =>
+ result.text()
+ );
+
+ const loadedCheerio = parseHTML(body);
+
+ const novels: Plugin.NovelItem[] = [];
+
+ loadedCheerio(".module-rank-booklist .book-layout").each((i, el) => {
+ let url = loadedCheerio(el).attr('href');
+
+ const novelName = loadedCheerio(el).find('.book-title').text();
+ const novelCover = loadedCheerio(el)
+ .find('img.book-cover')
+ .attr('data-src');
+ const novelUrl = this.site + url;
+
+ if (!url) return;
+
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ };
+
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const url = novelUrl;
+ const headers = new Headers();
+ if(this.cookieString){
+ headers.append("cookie", this.cookieString);
+ }
+ const result = await fetchApi(url, {headers});
+ const body = await result.text();
+
+ let loadedCheerio = parseHTML(body);
+
+ const novel: Plugin.SourceNovel = {
+ url,
+ chapters: [],
+ };
+
+ novel.name = loadedCheerio('#bookDetailWrapper .book-title').text();
+
+ novel.cover = loadedCheerio('#bookDetailWrapper img.book-cover').attr(
+ 'src',
+ );
+
+ novel.summary = loadedCheerio('#bookSummary content').text();
+
+ novel.author = loadedCheerio('#bookDetailWrapper .book-rand-a a').text();
+
+ // TODO: Need some regex and dirty selector to get it
+ // Need to look into how to translate that message
+ novel.status = undefined;
+
+ novel.genres = loadedCheerio('.tag-small.red')
+ .children("a")
+ .map((i, el) => loadedCheerio(el).text())
+ .toArray()
+ .join(",");
+
+ // Table of Content is on a different page than the summary page
+ let chapter: Plugin.ChapterItem[] = [];
+
+ const idPattern = /\/(\d+)\.html/;
+ const novelId = url.match(idPattern)?.[1];
+
+ const chaptersUrl = this.site + loadedCheerio('#btnReadBook').attr('href');
+ const chaptersResult = await fetchApi(chaptersUrl, {headers});
+ const chaptersBody = await chaptersResult.text();
+
+ const chaptersLoadedCheerio = parseHTML(chaptersBody);
+
+ let volumeName:string, chapterId:number;
+
+ chaptersLoadedCheerio('#volumes .chapter-li').each((i, el) => {
+ if (chaptersLoadedCheerio(el).hasClass('chapter-bar')) {
+ volumeName = chaptersLoadedCheerio(el).text();
+ } else {
+ const urlPart = chaptersLoadedCheerio(el)
+ .find('.chapter-li-a')
+ .attr('href');
+ const chapterIdMatch = urlPart?.match(idPattern);
+
+ // Sometimes the href attribute does not contain the url, but javascript:cid(0).
+ // Increment the previous chapter ID should result in the right URL
+ if (chapterIdMatch) {
+ chapterId = +chapterIdMatch[1];
+ } else {
+ chapterId++;
+ }}
+
+
+ const chapterUrl = `${this.site}/novel/${novelId}/${chapterId}.html`;
+ const chapterName =
+ volumeName +
+ ' — ' +
+ chaptersLoadedCheerio(el).find('.chapter-index').text().trim();
+ const releaseDate = null;
+
+ if (!chapterId) return;
+
+ chapter.push({
+ name: chapterName,
+ releaseTime: releaseDate,
+ url: chapterUrl,
+ });
+ });
+
+ novel.chapters = chapter;
+
+ return novel;
+ }
+
+ async parseChapter(chapterUrl: string): Promise {
+ const headers = new Headers();
+ if(this.cookieString){
+ headers.append("cookie", this.cookieString);
+ }
+ let chapterName, chapterText = "", hasNextPage, pageHasNextPage, pageText = "";
+ let pageNumber = 1;
+
+ /*
+ * TODO: Maybe there are other ways to get the translation table
+ * It is embed and encrypted inside readtool.js
+ * UPDATE: Decrypted, see skillgg
+ */
+ // const mapping_dict = {
+ // '“': '「',
+ // '’': '』',
+ // '': '是',
+ // '': '不',
+ // '': '好',
+ // '': '个',
+ // '': '开',
+ // '': '样',
+ // '': '想',
+ // '': '说',
+ // '': '年',
+ // '': '那',
+ // '': '她',
+ // '': '美',
+ // '': '自',
+ // '': '家',
+ // '': '而',
+ // '': '去',
+ // '': '都',
+ // '': '于',
+ // '': '舔',
+ // '': '他',
+ // '': '只',
+ // '': '看',
+ // '': '来',
+ // '': '用',
+ // '': '道',
+ // '': '得',
+ // '': '乳',
+ // '': '茎',
+ // '': '肉',
+ // '': '胸',
+ // '': '淫',
+ // '': '性',
+ // '': '骚',
+ // '”': '」',
+ // '': '的',
+ // '': '当',
+ // '': '人',
+ // '': '有',
+ // '': '上',
+ // '': '到',
+ // '': '地',
+ // '': '中',
+ // '': '生',
+ // '': '着',
+ // '': '和',
+ // '': '起',
+ // '': '交',
+ // '': '以',
+ // '': '可',
+ // '': '过',
+ // '': '能',
+ // '': '多',
+ // '': '心',
+ // '': '小',
+ // '': '成',
+ // '': '了',
+ // '': '把',
+ // '': '发',
+ // '': '第',
+ // '': '子',
+ // '': '事',
+ // '': '阴',
+ // '': '欲',
+ // '': '里',
+ // '': '私',
+ // '': '臀',
+ // '': '脱',
+ // '': '唇',
+ // '‘': '『',
+ // '': '一',
+ // '': '我',
+ // '': '在',
+ // '': '这',
+ // '': '们',
+ // '': '时',
+ // '': '为',
+ // '': '你',
+ // '': '国',
+ // '': '就',
+ // '': '要',
+ // '': '也',
+ // '': '后',
+ // '': '没',
+ // '': '下',
+ // '': '天',
+ // '': '对',
+ // '': '然',
+ // '': '学',
+ // '': '之',
+ // '': '出',
+ // '': '没',
+ // '': '如',
+ // '': '还',
+ // '': '大',
+ // '': '作',
+ // '': '种',
+ // '': '液',
+ // '': '呻',
+ // '': '射',
+ // '': '穴',
+ // '': '么',
+ // '': '裸',
+ // };
+ const skillgg: Record = {
+ '\u201c': '\u300c',
+ '\u201d': '\u300d',
+ '\u2018': '\u300e',
+ '\u2019': '\u300f',
+ '\ue82c': '\u7684',
+ '\ue852': '\u4e00',
+ '\ue82d': '\u662f',
+ '\ue819': '\u4e86',
+ '\ue856': '\u6211',
+ '\ue857': '\u4e0d',
+ '\ue816': '\u4eba',
+ '\ue83c': '\u5728',
+ '\ue830': '\u4ed6',
+ '\ue82e': '\u6709',
+ '\ue836': '\u8fd9',
+ '\ue859': '\u4e2a',
+ '\ue80a': '\u4e0a',
+ '\ue855': '\u4eec',
+ '\ue842': '\u6765',
+ '\ue858': '\u5230',
+ '\ue80b': '\u65f6',
+ '\ue81f': '\u5927',
+ '\ue84a': '\u5730',
+ '\ue853': '\u4e3a',
+ '\ue81e': '\u5b50',
+ '\ue822': '\u4e2d',
+ '\ue813': '\u4f60',
+ '\ue85b': '\u8bf4',
+ '\ue807': '\u751f',
+ '\ue818': '\u56fd',
+ '\ue810': '\u5e74',
+ '\ue812': '\u7740',
+ '\ue851': '\u5c31',
+ '\ue801': '\u90a3',
+ '\ue80c': '\u548c',
+ '\ue815': '\u8981',
+ '\ue84c': '\u5979',
+ '\ue840': '\u51fa',
+ '\ue848': '\u4e5f',
+ '\ue835': '\u5f97',
+ '\ue800': '\u91cc',
+ '\ue826': '\u540e',
+ '\ue863': '\u81ea',
+ '\ue861': '\u4ee5',
+ '\ue854': '\u4f1a',
+ '\ue827': '\u5bb6',
+ '\ue83b': '\u53ef',
+ '\ue85d': '\u4e0b',
+ '\ue84d': '\u800c',
+ '\ue862': '\u8fc7',
+ '\ue81c': '\u5929',
+ '\ue81d': '\u53bb',
+ '\ue860': '\u80fd',
+ '\ue843': '\u5bf9',
+ '\ue82f': '\u5c0f',
+ '\ue802': '\u591a',
+ '\ue831': '\u7136',
+ '\ue84b': '\u4e8e',
+ '\ue837': '\u5fc3',
+ '\ue829': '\u5b66',
+ '\ue85e': '\u4e48',
+ '\ue83a': '\u4e4b',
+ '\ue832': '\u90fd',
+ '\ue808': '\u597d',
+ '\ue841': '\u770b',
+ '\ue821': '\u8d77',
+ '\ue845': '\u53d1',
+ '\ue803': '\u5f53',
+ '\ue828': '\u6ca1',
+ '\ue81b': '\u6210',
+ '\ue83e': '\u53ea',
+ '\ue820': '\u5982',
+ '\ue84e': '\u4e8b',
+ '\ue85a': '\u628a',
+ '\ue806': '\u8fd8',
+ '\ue83f': '\u7528',
+ '\ue833': '\u7b2c',
+ '\ue811': '\u6837',
+ '\ue804': '\u9053',
+ '\ue814': '\u60f3',
+ '\ue80f': '\u4f5c',
+ '\ue84f': '\u79cd',
+ '\ue80e': '\u5f00',
+ '\ue823': '\u7f8e',
+ '\ue849': '\u4e73',
+ '\ue805': '\u9634',
+ '\ue809': '\u6db2',
+ '\ue81a': '\u830e',
+ '\ue844': '\u6b32',
+ '\ue847': '\u547b',
+ '\ue850': '\u8089',
+ '\ue824': '\u4ea4',
+ '\ue85f': '\u6027',
+ '\ue817': '\u80f8',
+ '\ue85c': '\u79c1',
+ '\ue838': '\u7a74',
+ '\ue82a': '\u6deb',
+ '\ue83d': '\u81c0',
+ '\ue82b': '\u8214',
+ '\ue80d': '\u5c04',
+ '\ue839': '\u8131',
+ '\ue834': '\u88f8',
+ '\ue846': '\u9a9a',
+ '\ue825': '\u5507',
+ };
+ const addPage = async (pageCheerio: CheerioAPI) => {
+ const formatPage = async () => {
+ // Remove JS
+ pageCheerio('#ccacontent .cgo').remove();
+
+ // Load lazyloaded images
+ pageCheerio('#ccacontent img.imagecontent').each((i, el) => {
+ // Sometimes images are either in data-src or src
+ const imgSrc =
+ pageCheerio(el).attr('data-src') || pageCheerio(el).attr('src');
+ if (imgSrc) {
+ // The original CDN URL is locked behind a CF-like challenge, switch the URL to bypass that
+ // There are no react-native-url-polyfill lib, can't use URL API
+ const regex = /\/\/.+\.com\//;
+ const imgUrl = imgSrc.replace(regex, '//img.linovelib.com/');
+ // Clean up img element
+ pageCheerio(el)
+ .attr('src', imgUrl)
+ .removeAttr('data-src')
+ .removeClass('lazyload');
+ }
+ });
+
+ // Recover the original character
+ pageText = pageCheerio('#ccacontent').html() || "";
+ pageText = pageText.replace(/./g, char => skillgg[char] || char);
+
+ return Promise.resolve();
+ };
+
+ await formatPage();
+ chapterName =
+ pageCheerio('#atitle + h3').text() +
+ ' — ' +
+ pageCheerio('#atitle').text();
+ if (chapterText === "") {
+ chapterText = '' + chapterName + '
';
+ }
+ chapterText += pageText;
+ };
+
+ const loadPage = async (url:string) => {
+ const result = await fetchApi(url, {headers});
+ const body = await result.text();
+ const pageCheerio = parseHTML(body);
+ await addPage(pageCheerio);
+ pageHasNextPage =
+ pageCheerio('#footlink a:last').text() === '下一页' ? true : false;
+ return { pageCheerio, pageHasNextPage };
+ };
+
+ let url = chapterUrl;
+ do {
+ const page = await loadPage(url);
+ hasNextPage = page.pageHasNextPage;
+ if (hasNextPage === true) {
+ pageNumber++;
+ url = chapterUrl.replace(/\.html/gi, `_${pageNumber}` + '.html');
+ }
+ } while (hasNextPage === true);
+
+ return chapterText;
+ }
+
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const searchUrl = `${this.site}/search/`;
+ const Term = encodeURI(searchTerm);
+ const headers = new Headers();
+ if(this.cookieString){
+ headers.append("cookie", this.cookieString);
+ }
+ let NextPage, NoNextPage:boolean, DeadEnd;
+ pageNo = 1;
+ const novels: Plugin.NovelItem[] = [];
+
+ const addPage = async (pageCheerio: CheerioAPI, redirect: string) => {
+ const loadSearchResults = () => {
+ pageCheerio('.book-ol .book-layout').each((i, el) => {
+ let nUrl = pageCheerio(el).attr('href');
+
+ const novelName = pageCheerio(el).find('.book-title').text();
+ const novelCover = pageCheerio(el)
+ .find('img.book-cover')
+ .attr('data-src');
+ const novelUrl = this.site + nUrl;
+
+ if (!nUrl) return;
+
+ novels.push({
+ name: novelName,
+ url: novelUrl,
+ cover: novelCover,
+ });
+ }
+ );
+ };
+
+ const novelResults = pageCheerio('.book-ol a.book-layout');
+ if (novelResults.length === 0) {
+ showToast('Bypass check by searching in Webview');
+ } else {
+ loadSearchResults();
+ }
+
+ if (redirect.length) {
+ novels.length = 0;
+ const novelName = pageCheerio('#bookDetailWrapper .book-title').text();
+
+ const novelCover = pageCheerio('#bookDetailWrapper img.book-cover').attr(
+ 'src',
+ );
+ const novelUrl =
+ this.site +
+ pageCheerio('#btnReadBook').attr('href')?.slice(0, -8) +
+ '.html';
+ novels.push({
+ name: novelName,
+ url: novelUrl,
+ cover: novelCover,
+ });
+ }
+ };
+
+ const loadPage = async (url:string) => {
+ const result = await fetchApi(url, {headers});
+ const body = await result.text();
+ const pageCheerio = parseHTML(body);
+ const redirect = pageCheerio('div.book-layout').text();
+ await addPage(pageCheerio, redirect);
+ NextPage = pageCheerio('.next').attr('href');
+ if (!NextPage) {
+ NoNextPage === true;
+ } else {
+ NoNextPage = NextPage === '#' ? true : false;
+ }
+ return { pageCheerio, NoNextPage };
+ };
+
+ let url = `${searchUrl}${Term}_${pageNo}.html`;
+ do {
+ const page = await loadPage(url);
+ DeadEnd = page.NoNextPage;
+ if (DeadEnd === false) {
+ pageNo++;
+ url = `${searchUrl}${Term}_${pageNo}.html`;
+ }
+ } while (DeadEnd === false);
+
+ return novels;
+ };
+
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url);
+ }
+ filters = [
+ {
+ key: "sort",
+ label: "Sort By",
+ values: [
+ { label: "月点击榜", value: "monthvisit" },
+
+ { label: "周点击榜", value: "weekvisit" },
+
+ { label: "月推荐榜", value: "monthvote" },
+
+ { label: "周推荐榜", value: "weekvote" },
+
+ { label: "月鲜花榜", value: "monthflower" },
+
+ { label: "周鲜花榜", value: "weekflower" },
+
+ { label: "月鸡蛋榜", value: "monthegg" },
+
+ { label: "周鸡蛋榜", value: "weekegg" },
+
+ { label: "最近更新", value: "lastupdate" },
+
+ { label: "最新入库", value: "postdate" },
+
+ { label: "收藏榜", value: "goodnum" },
+
+ { label: "新书榜", value: "newhot" },
+ ],
+ inputType: FilterInputs.Picker,
+ },
+ ];
+}
+
+export default new Linovelib();
diff --git a/plugins/english/.english b/plugins/english/.english
deleted file mode 100644
index e69de29..0000000
diff --git a/plugins/english/BoxNovel[madara].ts b/plugins/english/BoxNovel[madara].ts
index a472494..a82bf1a 100644
--- a/plugins/english/BoxNovel[madara].ts
+++ b/plugins/english/BoxNovel[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "boxnovel";
-export const name = "BoxNovel [madara]";
-export const icon = "multisrc/madara/icons/boxnovel.png";
-export const version = "1.0.0";
-export const site = "https://boxnovel.com/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "manga-genre/" + filters.genres + '/';
- } else {
- url += "novel/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (true) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":FilterInputs.Picker},{"key":"genres","label":"GENRES","values":[{"label":"Action","value":"action"},{"label":"Adventure","value":"adventure"},{"label":"Comedy","value":"comedy"},{"label":"Drama","value":"drama"},{"label":"Ecchi","value":"ecchi"},{"label":"Fantasy","value":"fantasy"},{"label":"Gender Bender","value":"gender-bender"},{"label":"Harem","value":"harem"},{"label":"Historical","value":"historical"},{"label":"Horror","value":"horror"},{"label":"Josei","value":"josei"},{"label":"Martial Arts","value":"martial-arts"},{"label":"Mature","value":"mature"},{"label":"Mecha","value":"mecha"},{"label":"Mystery","value":"mystery"},{"label":"Psychological","value":"psychological"},{"label":"Romance","value":"romance"},{"label":"School Life","value":"school-life"},{"label":"Sci-fi","value":"sci-fi"},{"label":"Seinen","value":"seinen"},{"label":"Shoujo","value":"shoujo"},{"label":"Shounen","value":"shounen"},{"label":"Slice of Life","value":"slice-of-life"},{"label":"Smut","value":"smut"},{"label":"Sports","value":"sports"},{"label":"Supernatural","value":"supernatural"},{"label":"Tragedy","value":"tragedy"},{"label":"Wuxia","value":"wuxia"},{"label":"Xianxia","value":"xianxia"},{"label":"Xuanhuan","value":"xuanhuan"},{"label":"Yaoi","value":"yaoi"}],"inputType":FilterInputs.Picker}];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"boxnovel","sourceSite":"https://boxnovel.com/","sourceName":"BoxNovel","filters":[{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":"Picker"},{"key":"genres","label":"GENRES","values":[{"label":"Action","value":"action"},{"label":"Adventure","value":"adventure"},{"label":"Comedy","value":"comedy"},{"label":"Drama","value":"drama"},{"label":"Ecchi","value":"ecchi"},{"label":"Fantasy","value":"fantasy"},{"label":"Gender Bender","value":"gender-bender"},{"label":"Harem","value":"harem"},{"label":"Historical","value":"historical"},{"label":"Horror","value":"horror"},{"label":"Josei","value":"josei"},{"label":"Martial Arts","value":"martial-arts"},{"label":"Mature","value":"mature"},{"label":"Mecha","value":"mecha"},{"label":"Mystery","value":"mystery"},{"label":"Psychological","value":"psychological"},{"label":"Romance","value":"romance"},{"label":"School Life","value":"school-life"},{"label":"Sci-fi","value":"sci-fi"},{"label":"Seinen","value":"seinen"},{"label":"Shoujo","value":"shoujo"},{"label":"Shounen","value":"shounen"},{"label":"Slice of Life","value":"slice-of-life"},{"label":"Smut","value":"smut"},{"label":"Sports","value":"sports"},{"label":"Supernatural","value":"supernatural"},{"label":"Tragedy","value":"tragedy"},{"label":"Wuxia","value":"wuxia"},{"label":"Xianxia","value":"xianxia"},{"label":"Xuanhuan","value":"xuanhuan"},{"label":"Yaoi","value":"yaoi"}],"inputType":"Picker"}],"options":{"path":{"genres":"manga-genre"},"useNewChapterEndpoint":true,"lang":"English"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/english/ClickNovel[madara].ts b/plugins/english/ClickNovel[madara].ts
index 50b0040..dcb66fb 100644
--- a/plugins/english/ClickNovel[madara].ts
+++ b/plugins/english/ClickNovel[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "clicknovel";
-export const name = "ClickNovel [madara]";
-export const icon = "multisrc/madara/icons/clicknovel.png";
-export const version = "1.0.0";
-export const site = "https://clicknovel.net/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "novel-genre/" + filters.genres + '/';
- } else {
- url += "novel/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (false) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"clicknovel","sourceSite":"https://clicknovel.net/","sourceName":"ClickNovel","filters":[],"options":{"lang":"English"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/english/CrateNovel[madara].ts b/plugins/english/CrateNovel[madara].ts
index 33239e6..dd0fa3e 100644
--- a/plugins/english/CrateNovel[madara].ts
+++ b/plugins/english/CrateNovel[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "cratenovel";
-export const name = "CrateNovel [madara]";
-export const icon = "multisrc/madara/icons/cratenovel.png";
-export const version = "1.0.0";
-export const site = "https://cratenovel.com/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "novel-genre/" + filters.genres + '/';
- } else {
- url += "novel/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (true) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"cratenovel","sourceSite":"https://cratenovel.com/","sourceName":"CrateNovel","filters":[],"options":{"useNewChapterEndpoint":true,"lang":"English"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/english/DaoNovel[madara].ts b/plugins/english/DaoNovel[madara].ts
index ec316a7..ae84271 100644
--- a/plugins/english/DaoNovel[madara].ts
+++ b/plugins/english/DaoNovel[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "daonovel";
-export const name = "DaoNovel [madara]";
-export const icon = "multisrc/madara/icons/daonovel.png";
-export const version = "1.0.0";
-export const site = "https://daonovel.com/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "novel-genre/" + filters.genres + '/';
- } else {
- url += "novels-list/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (true) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "novels" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":FilterInputs.Picker}];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"daonovel","sourceSite":"https://daonovel.com/","sourceName":"DaoNovel","filters":[{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":"Picker"}],"options":{"path":{"novels":"novels-list","novel":"novels","chapter":"novels"},"useNewChapterEndpoint":true,"lang":"English"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/english/FansTranslations[madara].ts b/plugins/english/FansTranslations[madara].ts
index 347e7d9..4e1666e 100644
--- a/plugins/english/FansTranslations[madara].ts
+++ b/plugins/english/FansTranslations[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "fanTLS";
-export const name = "Fans Translations [madara]";
-export const icon = "multisrc/madara/icons/fanstranslations.png";
-export const version = "1.0.0";
-export const site = "https://fanstranslations.com/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "novel-genre/" + filters.genres + '/';
- } else {
- url += "novel/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (true) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":FilterInputs.Picker}];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"fanTLS","sourceSite":"https://fanstranslations.com/","sourceName":"Fans Translations","filters":[{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":"Picker"}],"options":{"useNewChapterEndpoint":true,"lang":"English"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/english/FirstKissNovel[madara].ts b/plugins/english/FirstKissNovel[madara].ts
index f763f88..86086c6 100644
--- a/plugins/english/FirstKissNovel[madara].ts
+++ b/plugins/english/FirstKissNovel[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "1stkissnovel";
-export const name = "FirstKissNovel [madara]";
-export const icon = "multisrc/madara/icons/firstkissnovel.png";
-export const version = "1.0.0";
-export const site = "https://1stkissnovel.org/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "novel-genre/" + filters.genres + '/';
- } else {
- url += "novel/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (true) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":FilterInputs.Picker},{"key":"genres","label":"GENRES","values":[{"label":"Action","value":"action"},{"label":"Adult","value":"adult"},{"label":"Adventure","value":"adventure"},{"label":"Anime","value":"anime"},{"label":"Apocalypse","value":"apocalypse"},{"label":"Boy's Love","value":"boys-love"},{"label":"Comedy","value":"comedy"},{"label":"Completed","value":"completed"},{"label":"Cooking","value":"cooking"},{"label":"Demons","value":"demons"},{"label":"Detective","value":"detective"},{"label":"Drama","value":"drama"},{"label":"Ecchi","value":"ecchi"},{"label":"Fan-Fiction","value":"fan-fiction"},{"label":"Fantasy","value":"fantasy"},{"label":"Food","value":"food"},{"label":"Game","value":"game"},{"label":"Gender Bender","value":"gender-bender"},{"label":"Girls Love","value":"girls-love"},{"label":"Harem","value":"harem"},{"label":"Historical","value":"historical"},{"label":"Horror","value":"horror"},{"label":"Humor","value":"humor"},{"label":"Isekai","value":"isekai"},{"label":"Josei","value":"josei"},{"label":"Magic","value":"magic"},{"label":"Magical","value":"magical"},{"label":"Manhua","value":"manhua"},{"label":"Manhwa","value":"manhwa"},{"label":"Martial Arts","value":"martial-arts"},{"label":"Mature","value":"mature"},{"label":"Mecha","value":"mecha"},{"label":"Medical","value":"medical"},{"label":"Military","value":"military"},{"label":"Moder","value":"moder"},{"label":"Modern","value":"modern"},{"label":"Murim","value":"murim"},{"label":"Music","value":"music"},{"label":"Mystery","value":"mystery"},{"label":"Psychological","value":"psychological"},{"label":"Reverse","value":"reverse"},{"label":"Reverse harem","value":"reverse-harem"},{"label":"Romance","value":"romance"},{"label":"School Life","value":"school-life"},{"label":"Sci-fi","value":"sci-fi"},{"label":"Seinen","value":"seinen"},{"label":"Shoujo","value":"shoujo"},{"label":"Shoujo Ai","value":"shoujo-ai"},{"label":"Shounen","value":"shounen"},{"label":"Shounen Ai","value":"shounen-ai"},{"label":"Slice of Life","value":"slice-of-life"},{"label":"Smut","value":"smut"},{"label":"Sports","value":"sports"},{"label":"Super power","value":"super-power"},{"label":"Superhero","value":"superhero"},{"label":"Supernatural","value":"supernatural"},{"label":"Thriller","value":"thriller"},{"label":"Tragedy","value":"tragedy"},{"label":"Urban Life","value":"urban-life"},{"label":"Vampire","value":"vampire"},{"label":"Webtoons","value":"webtoons"},{"label":"Wuxia","value":"wuxia"},{"label":"Xianxia","value":"xianxia"},{"label":"Xuanhuan","value":"xuanhuan"},{"label":"Yaoi","value":"yaoi"},{"label":"Yuri","value":"yuri"}],"inputType":FilterInputs.Picker}];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"1stkissnovel","sourceSite":"https://1stkissnovel.org/","sourceName":"FirstKissNovel","filters":[{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":"Picker"},{"key":"genres","label":"GENRES","values":[{"label":"Action","value":"action"},{"label":"Adult","value":"adult"},{"label":"Adventure","value":"adventure"},{"label":"Anime","value":"anime"},{"label":"Apocalypse","value":"apocalypse"},{"label":"Boy's Love","value":"boys-love"},{"label":"Comedy","value":"comedy"},{"label":"Completed","value":"completed"},{"label":"Cooking","value":"cooking"},{"label":"Demons","value":"demons"},{"label":"Detective","value":"detective"},{"label":"Drama","value":"drama"},{"label":"Ecchi","value":"ecchi"},{"label":"Fan-Fiction","value":"fan-fiction"},{"label":"Fantasy","value":"fantasy"},{"label":"Food","value":"food"},{"label":"Game","value":"game"},{"label":"Gender Bender","value":"gender-bender"},{"label":"Girls Love","value":"girls-love"},{"label":"Harem","value":"harem"},{"label":"Historical","value":"historical"},{"label":"Horror","value":"horror"},{"label":"Humor","value":"humor"},{"label":"Isekai","value":"isekai"},{"label":"Josei","value":"josei"},{"label":"Magic","value":"magic"},{"label":"Magical","value":"magical"},{"label":"Manhua","value":"manhua"},{"label":"Manhwa","value":"manhwa"},{"label":"Martial Arts","value":"martial-arts"},{"label":"Mature","value":"mature"},{"label":"Mecha","value":"mecha"},{"label":"Medical","value":"medical"},{"label":"Military","value":"military"},{"label":"Moder","value":"moder"},{"label":"Modern","value":"modern"},{"label":"Murim","value":"murim"},{"label":"Music","value":"music"},{"label":"Mystery","value":"mystery"},{"label":"Psychological","value":"psychological"},{"label":"Reverse","value":"reverse"},{"label":"Reverse harem","value":"reverse-harem"},{"label":"Romance","value":"romance"},{"label":"School Life","value":"school-life"},{"label":"Sci-fi","value":"sci-fi"},{"label":"Seinen","value":"seinen"},{"label":"Shoujo","value":"shoujo"},{"label":"Shoujo Ai","value":"shoujo-ai"},{"label":"Shounen","value":"shounen"},{"label":"Shounen Ai","value":"shounen-ai"},{"label":"Slice of Life","value":"slice-of-life"},{"label":"Smut","value":"smut"},{"label":"Sports","value":"sports"},{"label":"Super power","value":"super-power"},{"label":"Superhero","value":"superhero"},{"label":"Supernatural","value":"supernatural"},{"label":"Thriller","value":"thriller"},{"label":"Tragedy","value":"tragedy"},{"label":"Urban Life","value":"urban-life"},{"label":"Vampire","value":"vampire"},{"label":"Webtoons","value":"webtoons"},{"label":"Wuxia","value":"wuxia"},{"label":"Xianxia","value":"xianxia"},{"label":"Xuanhuan","value":"xuanhuan"},{"label":"Yaoi","value":"yaoi"},{"label":"Yuri","value":"yuri"}],"inputType":"Picker"}],"options":{"useNewChapterEndpoint":true,"lang":"English"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/english/FreeNovelMe[madara].ts b/plugins/english/FreeNovelMe[madara].ts
index 62a0cc5..c3197ff 100644
--- a/plugins/english/FreeNovelMe[madara].ts
+++ b/plugins/english/FreeNovelMe[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "freenovel.me";
-export const name = "FreeNovelMe [madara]";
-export const icon = "multisrc/madara/icons/freenovelme.png";
-export const version = "1.0.0";
-export const site = "https://freenovel.me/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "novel-genre/" + filters.genres + '/';
- } else {
- url += "novel/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (false) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":FilterInputs.Picker},{"key":"genres","label":"GENRES","values":[{"label":"Action","value":"action"},{"label":"Adult","value":"adult"},{"label":"Adventure","value":"adventure"},{"label":"Cartoon","value":"cartoon"},{"label":"Comedy","value":"comedy"},{"label":"Cooking","value":"cooking"},{"label":"Detective","value":"detective"},{"label":"Drama","value":"drama"},{"label":"Fantasy","value":"fantasy"},{"label":"Game","value":"game"},{"label":"Gender Bender","value":"gender-bender"},{"label":"Historical","value":"historical"},{"label":"History","value":"history"},{"label":"Horror","value":"horror"},{"label":"Josei","value":"josei"},{"label":"Live action","value":"live-action"},{"label":"Martial","value":"martial"},{"label":"Martial Arts","value":"martial-arts"},{"label":"Mature","value":"mature"},{"label":"Mecha","value":"mecha"},{"label":"Mystery","value":"mystery"},{"label":"One shot","value":"one-shot"},{"label":"Premium","value":"premium"},{"label":"Psychological","value":"psychological"},{"label":"Reincarnation","value":"reincarnation"},{"label":"Romance","value":"romance"},{"label":"School Life","value":"school-life"},{"label":"Sci-fi","value":"sci-fi"},{"label":"Slice of Life","value":"slice-of-life"},{"label":"Smut","value":"smut"},{"label":"Sports","value":"sports"},{"label":"Supernatural","value":"supernatural"},{"label":"Tragedy","value":"tragedy"},{"label":"Wuxia","value":"wuxia"},{"label":"Xianxia","value":"xianxia"},{"label":"Xuanhuan","value":"xuanhuan"}],"inputType":FilterInputs.Picker}];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"freenovel.me","sourceSite":"https://freenovel.me/","sourceName":"FreeNovelMe","filters":[{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":"Picker"},{"key":"genres","label":"GENRES","values":[{"label":"Action","value":"action"},{"label":"Adult","value":"adult"},{"label":"Adventure","value":"adventure"},{"label":"Cartoon","value":"cartoon"},{"label":"Comedy","value":"comedy"},{"label":"Cooking","value":"cooking"},{"label":"Detective","value":"detective"},{"label":"Drama","value":"drama"},{"label":"Fantasy","value":"fantasy"},{"label":"Game","value":"game"},{"label":"Gender Bender","value":"gender-bender"},{"label":"Historical","value":"historical"},{"label":"History","value":"history"},{"label":"Horror","value":"horror"},{"label":"Josei","value":"josei"},{"label":"Live action","value":"live-action"},{"label":"Martial","value":"martial"},{"label":"Martial Arts","value":"martial-arts"},{"label":"Mature","value":"mature"},{"label":"Mecha","value":"mecha"},{"label":"Mystery","value":"mystery"},{"label":"One shot","value":"one-shot"},{"label":"Premium","value":"premium"},{"label":"Psychological","value":"psychological"},{"label":"Reincarnation","value":"reincarnation"},{"label":"Romance","value":"romance"},{"label":"School Life","value":"school-life"},{"label":"Sci-fi","value":"sci-fi"},{"label":"Slice of Life","value":"slice-of-life"},{"label":"Smut","value":"smut"},{"label":"Sports","value":"sports"},{"label":"Supernatural","value":"supernatural"},{"label":"Tragedy","value":"tragedy"},{"label":"Wuxia","value":"wuxia"},{"label":"Xianxia","value":"xianxia"},{"label":"Xuanhuan","value":"xuanhuan"}],"inputType":"Picker"}],"options":{"lang":"English"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/english/Guavaread[madara].ts b/plugins/english/Guavaread[madara].ts
index 9dcafcc..e54ca29 100644
--- a/plugins/english/Guavaread[madara].ts
+++ b/plugins/english/Guavaread[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "guavaread";
-export const name = "Guavaread [madara]";
-export const icon = "multisrc/madara/icons/guavaread.png";
-export const version = "1.0.0";
-export const site = "https://guavaread.com/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "novel-genre/" + filters.genres + '/';
- } else {
- url += "novel/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (true) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":FilterInputs.Picker},{"key":"genres","label":"GENRES","values":[{"label":"Action","value":"action"},{"label":"Adult","value":"adult"},{"label":"Adventure","value":"adventure"},{"label":"Comedy","value":"comedy"},{"label":"Complete","value":"complete"},{"label":"Cooking","value":"cooking"},{"label":"Detective","value":"detective"},{"label":"Drama","value":"drama"},{"label":"Dropped","value":"dropped"},{"label":"Ecchi","value":"ecchi"},{"label":"Fantasy","value":"fantasy"},{"label":"Gender Bender","value":"gender-bender"},{"label":"Historical","value":"historical"},{"label":"Horror","value":"horror"},{"label":"Josei","value":"josei"},{"label":"Mature","value":"mature"},{"label":"Mystery","value":"mystery"},{"label":"Original Story","value":"original-story"},{"label":"Pilot","value":"pilot"},{"label":"Psychological","value":"psychological"},{"label":"R-15","value":"r-15"},{"label":"R-19","value":"r-19"},{"label":"Reverse Harem","value":"reverse-harem"},{"label":"Romance","value":"romance"},{"label":"School Life","value":"school-life"},{"label":"Sci-fi","value":"sci-fi"},{"label":"Shoujo","value":"shoujo"},{"label":"Slice of Life","value":"slice-of-life"},{"label":"Smut","value":"smut"},{"label":"Supernatural","value":"supernatural"},{"label":"Tragedy","value":"tragedy"}],"inputType":FilterInputs.Picker}];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"guavaread","sourceSite":"https://guavaread.com/","sourceName":"Guavaread","filters":[{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":"Picker"},{"key":"genres","label":"GENRES","values":[{"label":"Action","value":"action"},{"label":"Adult","value":"adult"},{"label":"Adventure","value":"adventure"},{"label":"Comedy","value":"comedy"},{"label":"Complete","value":"complete"},{"label":"Cooking","value":"cooking"},{"label":"Detective","value":"detective"},{"label":"Drama","value":"drama"},{"label":"Dropped","value":"dropped"},{"label":"Ecchi","value":"ecchi"},{"label":"Fantasy","value":"fantasy"},{"label":"Gender Bender","value":"gender-bender"},{"label":"Historical","value":"historical"},{"label":"Horror","value":"horror"},{"label":"Josei","value":"josei"},{"label":"Mature","value":"mature"},{"label":"Mystery","value":"mystery"},{"label":"Original Story","value":"original-story"},{"label":"Pilot","value":"pilot"},{"label":"Psychological","value":"psychological"},{"label":"R-15","value":"r-15"},{"label":"R-19","value":"r-19"},{"label":"Reverse Harem","value":"reverse-harem"},{"label":"Romance","value":"romance"},{"label":"School Life","value":"school-life"},{"label":"Sci-fi","value":"sci-fi"},{"label":"Shoujo","value":"shoujo"},{"label":"Slice of Life","value":"slice-of-life"},{"label":"Smut","value":"smut"},{"label":"Supernatural","value":"supernatural"},{"label":"Tragedy","value":"tragedy"}],"inputType":"Picker"}],"options":{"useNewChapterEndpoint":true,"lang":"English"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/english/LightNovelHeaven[madara].ts b/plugins/english/LightNovelHeaven[madara].ts
index fb44646..eeaa04d 100644
--- a/plugins/english/LightNovelHeaven[madara].ts
+++ b/plugins/english/LightNovelHeaven[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "lnheaven";
-export const name = "LightNovelHeaven [madara]";
-export const icon = "multisrc/madara/icons/lightnovelheaven.png";
-export const version = "1.0.0";
-export const site = "https://lightnovelheaven.com/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "novel-genre/" + filters.genres + '/';
- } else {
- url += "series/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (true) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "series" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":FilterInputs.Picker}];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"lnheaven","sourceSite":"https://lightnovelheaven.com/","sourceName":"LightNovelHeaven","filters":[{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":"Picker"}],"options":{"path":{"novels":"series","novel":"series","chapter":"series"},"useNewChapterEndpoint":true,"lang":"English"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/english/LightNovelReader.ts b/plugins/english/LightNovelReader.broken.ts
similarity index 100%
rename from plugins/english/LightNovelReader.ts
rename to plugins/english/LightNovelReader.broken.ts
diff --git a/plugins/english/Ltnovelcom[readwn].ts b/plugins/english/Ltnovelcom[readwn].ts
deleted file mode 100644
index dcc57e1..0000000
--- a/plugins/english/Ltnovelcom[readwn].ts
+++ /dev/null
@@ -1,195 +0,0 @@
-
-import { load as parseHTML } from "cheerio";
-// import dayjs from 'dayjs';
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { parseMadaraDate } from "@libs/parseMadaraDate";
-// import { isUrlAbsolute } from '@libs/isAbsoluteUrl';
-// import { showToast } from "@libs/showToast";
-import { FilterInputs } from "@libs/filterInputs";
-// import { NovelStatus } from '@libs/novelStatus';
-// import { defaultCover } from "@libs/defaultCover";
-
-export const id = "Ltnovel.com";
-export const name = "Ltnovel.com";
-export const icon = "multisrc/readwn/icons/ltnovel.png";
-export const version = "1.0.0";
-export const site = "https://www.ltnovel.com/";
-
-export const popularNovels: Plugin.popularNovels = async function (
- page,
- { filters, showLatestNovels }
-) {
- const novels: Novel.Item[] = [];
- const pageNo = page - 1;
-
- let url = site + 'list/';
- url += (filters?.genres || 'all') + '/';
- url += (filters?.status || 'all') + '-';
- url += (showLatestNovels ? 'lastdotime' : filters?.sort || 'newstime') + '-';
- url += pageNo + '.html';
-
- const result = await fetchApi(url);
- const body = await result.text();
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('li.novel-item').each(function () {
- const novelName = loadedCheerio(this).find('h4').text();
- const novelUrl = site + loadedCheerio(this).find('a').attr('href');
-
- const coverUri = loadedCheerio(this)
- .find('.novel-cover > img')
- .attr('data-src');
-
- const novelCover = site + coverUri;
-
- const novel = { name: novelName, cover: novelCover, url: novelUrl };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters =
- async function (novelUrl) {
- const result = await fetchApi(novelUrl);
- const body = await result.text();
-
- let loadedCheerio = parseHTML(body);
-
- const novel: Novel.instance = {
- url: novelUrl,
- chapters: [],
- };
-
- novel.name = loadedCheerio('h1.novel-title').text();
-
- const coverUri = loadedCheerio('figure.cover > img').attr('data-src');
- novel.cover = site + coverUri;
-
- novel.summary = loadedCheerio('.summary')
- .text()
- .replace('Summary', '')
- .trim();
-
- novel.genres = '';
-
- loadedCheerio('div.categories > ul > li').each(function () {
- novel.genres += loadedCheerio(this).text().trim() + ',';
- });
-
- loadedCheerio('div.header-stats > span').each(function () {
- if (loadedCheerio(this).find('small').text() === 'Status') {
- novel.status = loadedCheerio(this).find('strong').text();
- }
- });
-
- novel.genres = novel.genres.slice(0, -1);
-
- novel.author = loadedCheerio('span[itemprop=author]').text();
-
- let novelChapters: Chapter.Item[] = [];
-
- const novelId = novelUrl.replace('.html', '').replace(site, '');
-
- const latestChapterNo = parseInt(loadedCheerio('.header-stats')
- .find('span > strong')
- .first()
- .text()
- .trim());
-
- let lastChapterNo = 1;
- loadedCheerio('.chapter-list li').each(function () {
- const chapterName = loadedCheerio(this)
- .find('a .chapter-title')
- .text()
- .trim();
-
- const chapterUrl = site + loadedCheerio(this).find('a').attr('href')?.trim();
-
- const releaseDate = loadedCheerio(this)
- .find('a .chapter-update')
- .text()
- .trim();
-
- lastChapterNo = parseInt(loadedCheerio(this).find('a .chapter-no').text().trim());
-
- const chapter = { name: chapterName, releaseTime: parseMadaraDate(releaseDate), url: chapterUrl };
-
- novelChapters.push(chapter);
- });
-
- // Itterate once more before loop to finish off
- lastChapterNo++;
- for (let i = lastChapterNo; i <= latestChapterNo; i++) {
- const chapterName = 'Chapter ' + i;
- const chapterUrl = site + novelId+'_'+ i +'.html';
- const releaseDate = null;
-
- const chapter = { name: chapterName, releaseTime: releaseDate,url: chapterUrl };
-
- novelChapters.push(chapter);
- }
-
- novel.chapters = novelChapters;
- return novel;
- };
-
-export const parseChapter: Plugin.parseChapter = async function (chapterUrl) {
- const result = await fetchApi(chapterUrl);
- const body = await result.text();
-
- const loadedCheerio = parseHTML(body);
-
- const chapterText = loadedCheerio('.chapter-content').html();
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const searchUrl = site + 'e/search/index.php';
-
- const result = await fetchApi(searchUrl, {
- headers: {
- 'Content-Type': 'application/x-www-form-urlencoded',
- Referer: site + 'search.html',
- Origin: site,
- 'user-agent':
- 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36',
- },
- method: 'POST',
- body: JSON.stringify({
- show: 'title',
- tempid: 1,
- tbname: 'news',
- keyboard: searchTerm,
- }),
- });
- const body = await result.text();
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('li.novel-item').each(function () {
- const novelName = loadedCheerio(this).find('h4').text();
- const novelUrl = site + loadedCheerio(this).find('a').attr('href');
-
- const coverUri = site + loadedCheerio(this).find('img').attr('data-src');
- const novelCover = site + coverUri;
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = fetchFile;
-
-export const filters = [{"key":"sort","label":"Sort By","values":[{"label":"New","value":"newstime"},{"label":"Popular","value":"onclick"},{"label":"Updates","value":"lastdotime"}], "inputType":FilterInputs.Picker},{"key":"status","label":"Status","values":[{"label":"All","value":"all"},{"label":"Completed","value":"Completed"},{"label":"Ongoing","value":"Ongoing"}], "inputType":FilterInputs.Picker},{"key":"genres","label":"Genre / Category","values":[{"label":"All","value":"all"},{"label":"Action","value":"action"},{"label":"Adult","value":"adult"},{"label":"Adventure","value":"adventure"},{"label":"Comedy","value":"comedy"},{"label":"Contemporary Romance","value":"contemporary-romance"},{"label":"Drama","value":"drama"},{"label":"Eastern Fantasy","value":"eastern-fantasy"},{"label":"Ecchi","value":"ecchi"},{"label":"Fantasy","value":"fantasy"},{"label":"Fantasy Romance","value":"fantasy-romance"},{"label":"Game","value":"game"},{"label":"Gender Bender","value":"gender-bender"},{"label":"Harem","value":"harem"},{"label":"Historical","value":"historical"},{"label":"Horror","value":"horror"},{"label":"Josei","value":"josei"},{"label":"Lolicon","value":"lolicon"},{"label":"Magical Realism","value":"magical-realism"},{"label":"Martial Arts","value":"martial-arts"},{"label":"Mature","value":"mature"},{"label":"Mecha","value":"mecha"},{"label":"Mystery","value":"mystery"},{"label":"Psychological","value":"psychological"},{"label":"Romance","value":"romance"},{"label":"School Life","value":"school-life"},{"label":"Sci-fi","value":"sci-fi"},{"label":"Seinen","value":"seinen"},{"label":"Shoujo","value":"shoujo"},{"label":"Shounen","value":"shounen"},{"label":"Shounen Ai","value":"shounen-ai"},{"label":"Slice of Life","value":"slice-of-life"},{"label":"Smut","value":"smut"},{"label":"Sports","value":"sports"},{"label":"Supernatural","value":"supernatural"},{"label":"Tragedy","value":"tragedy"},{"label":"Video Games","value":"video-games"},{"label":"Wuxia","value":"wuxia"},{"label":"Xianxia","value":"xianxia"},{"label":"Xuanhuan","value":"xuanhuan"},{"label":"Yaoi","value":"yaoi"}], "inputType":FilterInputs.Picker}];
\ No newline at end of file
diff --git a/plugins/english/LunarLetters[madara].ts b/plugins/english/LunarLetters[madara].ts
index cb6ba59..c259387 100644
--- a/plugins/english/LunarLetters[madara].ts
+++ b/plugins/english/LunarLetters[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "lunarletters";
-export const name = "LunarLetters [madara]";
-export const icon = "multisrc/madara/icons/lunarletters.png";
-export const version = "1.0.0";
-export const site = "https://www.lunarletters.com/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "novel-genre/" + filters.genres + '/';
- } else {
- url += "series/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (true) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "series" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":FilterInputs.Picker}];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"lunarletters","sourceSite":"https://www.lunarletters.com/","sourceName":"LunarLetters","filters":[{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":"Picker"}],"options":{"path":{"novels":"series","novel":"series","chapter":"series"},"useNewChapterEndpoint":true,"lang":"English"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/english/MTLNovelClub[madara].ts b/plugins/english/MTLNovelClub[madara].ts
index d9baa1e..e09cada 100644
--- a/plugins/english/MTLNovelClub[madara].ts
+++ b/plugins/english/MTLNovelClub[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "mtlnovel.club";
-export const name = "MTLNovel.Club [madara]";
-export const icon = "multisrc/madara/icons/mtlnovel.club.png";
-export const version = "1.0.0";
-export const site = "https://mtlnovel.club/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "novel-genre/" + filters.genres + '/';
- } else {
- url += "novel/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (true) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"mtlnovel.club","sourceSite":"https://mtlnovel.club/","sourceName":"MTLNovel.Club","filters":[],"options":{"useNewChapterEndpoint":true,"lang":"English"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/english/MTLNovel[madara].ts b/plugins/english/MTLNovel[madara].ts
index ca80952..a914264 100644
--- a/plugins/english/MTLNovel[madara].ts
+++ b/plugins/english/MTLNovel[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "mtl-novel";
-export const name = "MTL-Novel [madara]";
-export const icon = "multisrc/madara/icons/mtl-novel.png";
-export const version = "1.0.0";
-export const site = "https://mtl-novel.com/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "manga-genre/" + filters.genres + '/';
- } else {
- url += "novel/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (true) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":FilterInputs.Picker},{"key":"genres","label":"GENRES","values":[{"label":"Action","value":"action"},{"label":"Adult","value":"adult"},{"label":"Adventure","value":"adventure"},{"label":"Chinese","value":"chinese"},{"label":"Comedy","value":"comedy"},{"label":"Conan","value":"conan"},{"label":"Drama","value":"drama"},{"label":"Erciyuan","value":"erciyuan"},{"label":"Fairy Tail","value":"fairy-tail"},{"label":"Faloo","value":"faloo"},{"label":"Fan-Fiction","value":"fan-fiction"},{"label":"Fantasy","value":"fantasy"},{"label":"FoodWars!","value":"foodwars"},{"label":"Game","value":"game"},{"label":"Gender Bender","value":"gender-bender"},{"label":"Harem","value":"harem"},{"label":"Historical","value":"historical"},{"label":"Horror","value":"horror"},{"label":"Hunter x Hunter","value":"hunter-x-hunter"},{"label":"Japanese","value":"japanese"},{"label":"Jojo","value":"jojo"},{"label":"Josei","value":"josei"},{"label":"Korean","value":"korean"},{"label":"Martial Arts","value":"martial-arts"},{"label":"Marvel","value":"marvel"},{"label":"Mature","value":"mature"},{"label":"Mecha","value":"mecha"},{"label":"Military","value":"military"},{"label":"Mystery","value":"mystery"},{"label":"Naruto","value":"naruto"},{"label":"One piece","value":"one-piece"},{"label":"Pokemon","value":"pokemon"},{"label":"Psychological","value":"psychological"},{"label":"Romance","value":"romance"},{"label":"School Life","value":"school-life"},{"label":"Sci-fi","value":"sci-fi"},{"label":"Seinen","value":"seinen"},{"label":"Shoujo","value":"shoujo"},{"label":"Shoujo Ai","value":"shoujo-ai"},{"label":"Shounen Ai","value":"shounen-ai"},{"label":"Slice of Life","value":"slice-of-life"},{"label":"Smut","value":"smut"},{"label":"Sport","value":"sport"},{"label":"Sports","value":"sports"},{"label":"Supernatural","value":"supernatural"},{"label":"System","value":"system"},{"label":"Tragedy","value":"tragedy"},{"label":"Urban","value":"urban"},{"label":"Urban Life","value":"urban-life"},{"label":"Wuxia","value":"wuxia"},{"label":"Xianxia","value":"xianxia"},{"label":"Xuanhuan","value":"xuanhuan"},{"label":"Yaoi","value":"yaoi"},{"label":"Yuri","value":"yuri"}],"inputType":FilterInputs.Picker}];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"mtl-novel","sourceSite":"https://mtl-novel.com/","sourceName":"MTL-Novel","filters":[{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":"Picker"},{"key":"genres","label":"GENRES","values":[{"label":"Action","value":"action"},{"label":"Adult","value":"adult"},{"label":"Adventure","value":"adventure"},{"label":"Chinese","value":"chinese"},{"label":"Comedy","value":"comedy"},{"label":"Conan","value":"conan"},{"label":"Drama","value":"drama"},{"label":"Erciyuan","value":"erciyuan"},{"label":"Fairy Tail","value":"fairy-tail"},{"label":"Faloo","value":"faloo"},{"label":"Fan-Fiction","value":"fan-fiction"},{"label":"Fantasy","value":"fantasy"},{"label":"FoodWars!","value":"foodwars"},{"label":"Game","value":"game"},{"label":"Gender Bender","value":"gender-bender"},{"label":"Harem","value":"harem"},{"label":"Historical","value":"historical"},{"label":"Horror","value":"horror"},{"label":"Hunter x Hunter","value":"hunter-x-hunter"},{"label":"Japanese","value":"japanese"},{"label":"Jojo","value":"jojo"},{"label":"Josei","value":"josei"},{"label":"Korean","value":"korean"},{"label":"Martial Arts","value":"martial-arts"},{"label":"Marvel","value":"marvel"},{"label":"Mature","value":"mature"},{"label":"Mecha","value":"mecha"},{"label":"Military","value":"military"},{"label":"Mystery","value":"mystery"},{"label":"Naruto","value":"naruto"},{"label":"One piece","value":"one-piece"},{"label":"Pokemon","value":"pokemon"},{"label":"Psychological","value":"psychological"},{"label":"Romance","value":"romance"},{"label":"School Life","value":"school-life"},{"label":"Sci-fi","value":"sci-fi"},{"label":"Seinen","value":"seinen"},{"label":"Shoujo","value":"shoujo"},{"label":"Shoujo Ai","value":"shoujo-ai"},{"label":"Shounen Ai","value":"shounen-ai"},{"label":"Slice of Life","value":"slice-of-life"},{"label":"Smut","value":"smut"},{"label":"Sport","value":"sport"},{"label":"Sports","value":"sports"},{"label":"Supernatural","value":"supernatural"},{"label":"System","value":"system"},{"label":"Tragedy","value":"tragedy"},{"label":"Urban","value":"urban"},{"label":"Urban Life","value":"urban-life"},{"label":"Wuxia","value":"wuxia"},{"label":"Xianxia","value":"xianxia"},{"label":"Xuanhuan","value":"xuanhuan"},{"label":"Yaoi","value":"yaoi"},{"label":"Yuri","value":"yuri"}],"inputType":"Picker"}],"options":{"path":{"genres":"manga-genre"},"useNewChapterEndpoint":true,"lang":"English"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/english/MostNovel[madara].ts b/plugins/english/MostNovel[madara].ts
index e556082..7e2559d 100644
--- a/plugins/english/MostNovel[madara].ts
+++ b/plugins/english/MostNovel[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "mostnovel";
-export const name = "MostNovel [madara]";
-export const icon = "multisrc/madara/icons/mostnovel.png";
-export const version = "1.0.0";
-export const site = "https://mostnovel.com/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "manga-genre/" + filters.genres + '/';
- } else {
- url += "manga/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (false) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "manga" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":FilterInputs.Picker},{"key":"genres","label":"GENRES","values":[{"label":"ACG","value":"acg"},{"label":"Action","value":"action"},{"label":"Adult","value":"adult"},{"label":"Adventure","value":"adventure"},{"label":"AGA","value":"aga"},{"label":"Anime","value":"anime"},{"label":"Anime & Comics","value":"anime-comics"},{"label":"Bender","value":"bender"},{"label":"BL","value":"bl"},{"label":"Cartoon","value":"cartoon"},{"label":"Comedy","value":"comedy"},{"label":"Comic","value":"comic"},{"label":"Contemporary Romance","value":"contemporary-romance"},{"label":"Cooking","value":"cooking"},{"label":"Cultivation","value":"cultivation"},{"label":"Detective","value":"detective"},{"label":"Doujinshi","value":"doujinshi"},{"label":"Drama","value":"drama"},{"label":"Eastern Fantasy","value":"eastern-fantasy"},{"label":"Ecchi","value":"ecchi"},{"label":"Fantasy","value":"fantasy"},{"label":"Gender Bender","value":"gender-bender"},{"label":"Harem","value":"harem"},{"label":"Historical","value":"historical"},{"label":"Horror","value":"horror"},{"label":"Horror&Thriller","value":"horrorthriller"},{"label":"Josei","value":"josei"},{"label":"Live action","value":"live-action"},{"label":"Magical Realism","value":"magical-realism"},{"label":"Manga","value":"manga"},{"label":"Manhua","value":"manhua"},{"label":"Manhwa","value":"manhwa"},{"label":"Martial Arts","value":"martial-arts"},{"label":"Mature","value":"mature"},{"label":"Mecha","value":"mecha"},{"label":"Modern","value":"modern"},{"label":"Movies","value":"movies"},{"label":"Mystery","value":"mystery"},{"label":"One shot","value":"one-shot"},{"label":"Psychological","value":"psychological"},{"label":"Romance","value":"romance"},{"label":"School Life","value":"school-life"},{"label":"Sci-fi","value":"sci-fi"},{"label":"Seinen","value":"seinen"},{"label":"Shoujo","value":"shoujo"},{"label":"Shoujo Ai","value":"shoujo-ai"},{"label":"Shounen","value":"shounen"},{"label":"Shounen Ai","value":"shounen-ai"},{"label":"Slice of Life","value":"slice-of-life"},{"label":"Smart MC","value":"smart-mc"},{"label":"Smut","value":"smut"},{"label":"Soft Yaoi","value":"soft-yaoi"},{"label":"Soft Yuri","value":"soft-yuri"},{"label":"Sports","value":"sports"},{"label":"Supernatural","value":"supernatural"},{"label":"Tragedy","value":"tragedy"},{"label":"Urban Life","value":"urban-life"},{"label":"Video Games","value":"video-games"},{"label":"Webtoon","value":"webtoon"},{"label":"Wuxia","value":"wuxia"},{"label":"Xianxia","value":"xianxia"},{"label":"Xuanhuan","value":"xuanhuan"},{"label":"Yaoi","value":"yaoi"},{"label":"Yuri","value":"yuri"}],"inputType":FilterInputs.Picker}];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"mostnovel","sourceSite":"https://mostnovel.com/","sourceName":"MostNovel","filters":[{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":"Picker"},{"key":"genres","label":"GENRES","values":[{"label":"ACG","value":"acg"},{"label":"Action","value":"action"},{"label":"Adult","value":"adult"},{"label":"Adventure","value":"adventure"},{"label":"AGA","value":"aga"},{"label":"Anime","value":"anime"},{"label":"Anime & Comics","value":"anime-comics"},{"label":"Bender","value":"bender"},{"label":"BL","value":"bl"},{"label":"Cartoon","value":"cartoon"},{"label":"Comedy","value":"comedy"},{"label":"Comic","value":"comic"},{"label":"Contemporary Romance","value":"contemporary-romance"},{"label":"Cooking","value":"cooking"},{"label":"Cultivation","value":"cultivation"},{"label":"Detective","value":"detective"},{"label":"Doujinshi","value":"doujinshi"},{"label":"Drama","value":"drama"},{"label":"Eastern Fantasy","value":"eastern-fantasy"},{"label":"Ecchi","value":"ecchi"},{"label":"Fantasy","value":"fantasy"},{"label":"Gender Bender","value":"gender-bender"},{"label":"Harem","value":"harem"},{"label":"Historical","value":"historical"},{"label":"Horror","value":"horror"},{"label":"Horror&Thriller","value":"horrorthriller"},{"label":"Josei","value":"josei"},{"label":"Live action","value":"live-action"},{"label":"Magical Realism","value":"magical-realism"},{"label":"Manga","value":"manga"},{"label":"Manhua","value":"manhua"},{"label":"Manhwa","value":"manhwa"},{"label":"Martial Arts","value":"martial-arts"},{"label":"Mature","value":"mature"},{"label":"Mecha","value":"mecha"},{"label":"Modern","value":"modern"},{"label":"Movies","value":"movies"},{"label":"Mystery","value":"mystery"},{"label":"One shot","value":"one-shot"},{"label":"Psychological","value":"psychological"},{"label":"Romance","value":"romance"},{"label":"School Life","value":"school-life"},{"label":"Sci-fi","value":"sci-fi"},{"label":"Seinen","value":"seinen"},{"label":"Shoujo","value":"shoujo"},{"label":"Shoujo Ai","value":"shoujo-ai"},{"label":"Shounen","value":"shounen"},{"label":"Shounen Ai","value":"shounen-ai"},{"label":"Slice of Life","value":"slice-of-life"},{"label":"Smart MC","value":"smart-mc"},{"label":"Smut","value":"smut"},{"label":"Soft Yaoi","value":"soft-yaoi"},{"label":"Soft Yuri","value":"soft-yuri"},{"label":"Sports","value":"sports"},{"label":"Supernatural","value":"supernatural"},{"label":"Tragedy","value":"tragedy"},{"label":"Urban Life","value":"urban-life"},{"label":"Video Games","value":"video-games"},{"label":"Webtoon","value":"webtoon"},{"label":"Wuxia","value":"wuxia"},{"label":"Xianxia","value":"xianxia"},{"label":"Xuanhuan","value":"xuanhuan"},{"label":"Yaoi","value":"yaoi"},{"label":"Yuri","value":"yuri"}],"inputType":"Picker"}],"options":{"path":{"novels":"manga","novel":"manga","chapter":"manga","genres":"manga-genre"},"lang":"English"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/english/MysticalSeries[madara].ts b/plugins/english/MysticalSeries[madara].ts
index 2f25d22..0cda7aa 100644
--- a/plugins/english/MysticalSeries[madara].ts
+++ b/plugins/english/MysticalSeries[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "mysticalmerries";
-export const name = "MysticalSeries [madara]";
-export const icon = "multisrc/madara/icons/mysticalseries.png";
-export const version = "1.0.0";
-export const site = "https://mysticalmerries.com/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "genre/" + filters.genres + '/';
- } else {
- url += "series/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (true) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "series" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":FilterInputs.Picker},{"key":"genres","label":"GENRES","values":[{"label":"Action","value":"action"},{"label":"Adaptation","value":"adaptation"},{"label":"Adventure","value":"adventure"},{"label":"bilibili","value":"bilibili"},{"label":"Chinese Novel","value":"chinese-novel"},{"label":"Comedy","value":"comedy"},{"label":"Crossdressing","value":"crossdressing"},{"label":"Drama","value":"drama"},{"label":"Dropped","value":"dropped"},{"label":"Family","value":"family"},{"label":"Fantasy","value":"fantasy"},{"label":"Gender Bender","value":"gender-bender"},{"label":"Historical","value":"historical"},{"label":"Horror","value":"horror"},{"label":"Isekai","value":"isekai"},{"label":"Korean Novel","value":"korean-novell"},{"label":"Manga","value":"manga"},{"label":"Manhua","value":"manhua"},{"label":"Manhwa","value":"manhwa"},{"label":"Modern Romance","value":"modern-romance"},{"label":"Mystery","value":"mystery"},{"label":"Office Workers","value":"office-workers"},{"label":"One shot","value":"one-shot"},{"label":"Pilot Novel","value":"pilot-novel"},{"label":"R15","value":"r15"},{"label":"R19","value":"r19"},{"label":"Regression","value":"regression"},{"label":"Reincarnation","value":"reincarnation"},{"label":"Reverse Harem","value":"reverse-harem"},{"label":"Romance Fantasy","value":"romance-fantasy"},{"label":"School Life","value":"school-life"},{"label":"Sci-fi","value":"sci-fi"},{"label":"Slice of Life","value":"slice-of-life"},{"label":"Smut","value":"smut"},{"label":"Supernatural","value":"supernatural"},{"label":"Violence","value":"violence"}],"inputType":FilterInputs.Picker}];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"mysticalmerries","sourceSite":"https://mysticalmerries.com/","sourceName":"MysticalSeries","filters":[{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":"Picker"},{"key":"genres","label":"GENRES","values":[{"label":"Action","value":"action"},{"label":"Adaptation","value":"adaptation"},{"label":"Adventure","value":"adventure"},{"label":"bilibili","value":"bilibili"},{"label":"Chinese Novel","value":"chinese-novel"},{"label":"Comedy","value":"comedy"},{"label":"Crossdressing","value":"crossdressing"},{"label":"Drama","value":"drama"},{"label":"Dropped","value":"dropped"},{"label":"Family","value":"family"},{"label":"Fantasy","value":"fantasy"},{"label":"Gender Bender","value":"gender-bender"},{"label":"Historical","value":"historical"},{"label":"Horror","value":"horror"},{"label":"Isekai","value":"isekai"},{"label":"Korean Novel","value":"korean-novell"},{"label":"Manga","value":"manga"},{"label":"Manhua","value":"manhua"},{"label":"Manhwa","value":"manhwa"},{"label":"Modern Romance","value":"modern-romance"},{"label":"Mystery","value":"mystery"},{"label":"Office Workers","value":"office-workers"},{"label":"One shot","value":"one-shot"},{"label":"Pilot Novel","value":"pilot-novel"},{"label":"R15","value":"r15"},{"label":"R19","value":"r19"},{"label":"Regression","value":"regression"},{"label":"Reincarnation","value":"reincarnation"},{"label":"Reverse Harem","value":"reverse-harem"},{"label":"Romance Fantasy","value":"romance-fantasy"},{"label":"School Life","value":"school-life"},{"label":"Sci-fi","value":"sci-fi"},{"label":"Slice of Life","value":"slice-of-life"},{"label":"Smut","value":"smut"},{"label":"Supernatural","value":"supernatural"},{"label":"Violence","value":"violence"}],"inputType":"Picker"}],"options":{"path":{"novels":"series","novel":"series","chapter":"series","genres":"genre"},"useNewChapterEndpoint":true,"lang":"English"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/english/NeoSekaiTranslations[madara].ts b/plugins/english/NeoSekaiTranslations[madara].ts
index ddbc72e..647bfd0 100644
--- a/plugins/english/NeoSekaiTranslations[madara].ts
+++ b/plugins/english/NeoSekaiTranslations[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "neosekaiTLS";
-export const name = "NeoSekai Translations [madara]";
-export const icon = "multisrc/madara/icons/neosekaitranslations.png";
-export const version = "1.0.0";
-export const site = "https://www.neosekaitranslations.com/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "novel-genre/" + filters.genres + '/';
- } else {
- url += "novel/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (false) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":FilterInputs.Picker},{"key":"genres","label":"GENRES","values":[{"label":"Action","value":"action"},{"label":"Adventure","value":"adventure"},{"label":"Comedy","value":"comedy"},{"label":"Drama","value":"drama"},{"label":"Fantasy","value":"fantasy"},{"label":"Harem","value":"harem"},{"label":"Horror","value":"horror"},{"label":"Mature","value":"mature"},{"label":"Mecha","value":"mecha"},{"label":"Mystery","value":"mystery"},{"label":"Psychological","value":"psychological"},{"label":"Romance","value":"romance"},{"label":"School Life","value":"school-life"},{"label":"Sci-Fi","value":"sci-fi"},{"label":"Slice of Life","value":"slice-of-life"}],"inputType":FilterInputs.Picker}];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"neosekaiTLS","sourceSite":"https://www.neosekaitranslations.com/","sourceName":"NeoSekai Translations","filters":[{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":"Picker"},{"key":"genres","label":"GENRES","values":[{"label":"Action","value":"action"},{"label":"Adventure","value":"adventure"},{"label":"Comedy","value":"comedy"},{"label":"Drama","value":"drama"},{"label":"Fantasy","value":"fantasy"},{"label":"Harem","value":"harem"},{"label":"Horror","value":"horror"},{"label":"Mature","value":"mature"},{"label":"Mecha","value":"mecha"},{"label":"Mystery","value":"mystery"},{"label":"Psychological","value":"psychological"},{"label":"Romance","value":"romance"},{"label":"School Life","value":"school-life"},{"label":"Sci-Fi","value":"sci-fi"},{"label":"Slice of Life","value":"slice-of-life"}],"inputType":"Picker"}],"options":{"lang":"English"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/english/NocturneTranslations[madara].ts b/plugins/english/NocturneTranslations[madara].ts
index 8adf67b..f3b2b46 100644
--- a/plugins/english/NocturneTranslations[madara].ts
+++ b/plugins/english/NocturneTranslations[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "nocturneTLS";
-export const name = "Nocturne Translations [madara]";
-export const icon = "multisrc/madara/icons/nocturnetranslations.png";
-export const version = "1.0.0";
-export const site = "https://nocturnetls.net/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "manga-genre/" + filters.genres + '/';
- } else {
- url += "novels/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (false) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "novels" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":FilterInputs.Picker},{"key":"genres","label":"GENRES","values":[{"label":"Action","value":"action"},{"label":"Adult","value":"adult"},{"label":"Adventure","value":"adventure"},{"label":"Anime","value":"anime"},{"label":"Cartoon","value":"cartoon"},{"label":"Comedy","value":"comedy"},{"label":"Comic","value":"comic"},{"label":"Cooking","value":"cooking"},{"label":"Detective","value":"detective"},{"label":"Doujinshi","value":"doujinshi"},{"label":"Drama","value":"drama"},{"label":"Ecchi","value":"ecchi"},{"label":"Fantasy","value":"fantasy"},{"label":"Gender Bender","value":"gender-bender"},{"label":"Harem","value":"harem"},{"label":"Historical","value":"historical"},{"label":"Horror","value":"horror"},{"label":"Josei","value":"josei"},{"label":"Live action","value":"live-action"},{"label":"Manga","value":"manga"},{"label":"Manhua","value":"manhua"},{"label":"Manhwa","value":"manhwa"},{"label":"Martial Arts","value":"martial-arts"},{"label":"Mature","value":"mature"},{"label":"Mecha","value":"mecha"},{"label":"Mystery","value":"mystery"},{"label":"One shot","value":"one-shot"},{"label":"Psychological","value":"psychological"},{"label":"Romance","value":"romance"},{"label":"School Life","value":"school-life"},{"label":"Sci-fi","value":"sci-fi"},{"label":"Seinen","value":"seinen"},{"label":"Shoujo","value":"shoujo"},{"label":"Shoujo Ai","value":"shoujo-ai"},{"label":"Shounen","value":"shounen"},{"label":"Shounen Ai","value":"shounen-ai"},{"label":"Slice of Life","value":"slice-of-life"},{"label":"Smut","value":"smut"},{"label":"Soft Yaoi","value":"soft-yaoi"},{"label":"Soft Yuri","value":"soft-yuri"},{"label":"Sports","value":"sports"},{"label":"Supernatural","value":"supernatural"},{"label":"Tragedy","value":"tragedy"},{"label":"Webtoon","value":"webtoon"},{"label":"Yaoi","value":"yaoi"},{"label":"Yuri","value":"yuri"}],"inputType":FilterInputs.Picker}];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"nocturneTLS","sourceSite":"https://nocturnetls.net/","sourceName":"Nocturne Translations","filters":[{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":"Picker"},{"key":"genres","label":"GENRES","values":[{"label":"Action","value":"action"},{"label":"Adult","value":"adult"},{"label":"Adventure","value":"adventure"},{"label":"Anime","value":"anime"},{"label":"Cartoon","value":"cartoon"},{"label":"Comedy","value":"comedy"},{"label":"Comic","value":"comic"},{"label":"Cooking","value":"cooking"},{"label":"Detective","value":"detective"},{"label":"Doujinshi","value":"doujinshi"},{"label":"Drama","value":"drama"},{"label":"Ecchi","value":"ecchi"},{"label":"Fantasy","value":"fantasy"},{"label":"Gender Bender","value":"gender-bender"},{"label":"Harem","value":"harem"},{"label":"Historical","value":"historical"},{"label":"Horror","value":"horror"},{"label":"Josei","value":"josei"},{"label":"Live action","value":"live-action"},{"label":"Manga","value":"manga"},{"label":"Manhua","value":"manhua"},{"label":"Manhwa","value":"manhwa"},{"label":"Martial Arts","value":"martial-arts"},{"label":"Mature","value":"mature"},{"label":"Mecha","value":"mecha"},{"label":"Mystery","value":"mystery"},{"label":"One shot","value":"one-shot"},{"label":"Psychological","value":"psychological"},{"label":"Romance","value":"romance"},{"label":"School Life","value":"school-life"},{"label":"Sci-fi","value":"sci-fi"},{"label":"Seinen","value":"seinen"},{"label":"Shoujo","value":"shoujo"},{"label":"Shoujo Ai","value":"shoujo-ai"},{"label":"Shounen","value":"shounen"},{"label":"Shounen Ai","value":"shounen-ai"},{"label":"Slice of Life","value":"slice-of-life"},{"label":"Smut","value":"smut"},{"label":"Soft Yaoi","value":"soft-yaoi"},{"label":"Soft Yuri","value":"soft-yuri"},{"label":"Sports","value":"sports"},{"label":"Supernatural","value":"supernatural"},{"label":"Tragedy","value":"tragedy"},{"label":"Webtoon","value":"webtoon"},{"label":"Yaoi","value":"yaoi"},{"label":"Yuri","value":"yuri"}],"inputType":"Picker"}],"options":{"path":{"novels":"novels","novel":"novels","chapter":"novels","genres":"manga-genre"},"lang":"English"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/english/NoobchanTranslation[madara].ts b/plugins/english/NoobchanTranslation[madara].ts
index 0bb737e..710c49c 100644
--- a/plugins/english/NoobchanTranslation[madara].ts
+++ b/plugins/english/NoobchanTranslation[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "noobchanTL";
-export const name = "Noobchan Translation [madara]";
-export const icon = "multisrc/madara/icons/noobchantranslation.png";
-export const version = "1.0.0";
-export const site = "https://noobchan.xyz/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "novel-genre/" + filters.genres + '/';
- } else {
- url += "novel/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (true) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"noobchanTL","sourceSite":"https://noobchan.xyz/","sourceName":"Noobchan Translation","filters":[],"options":{"useNewChapterEndpoint":true,"lang":"English"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/english/NovelFullMe.ts b/plugins/english/NovelFullMe.broken.ts
similarity index 100%
rename from plugins/english/NovelFullMe.ts
rename to plugins/english/NovelFullMe.broken.ts
diff --git a/plugins/english/NovelMultiverse[madara].ts b/plugins/english/NovelMultiverse[madara].ts
index e073558..566a6f5 100644
--- a/plugins/english/NovelMultiverse[madara].ts
+++ b/plugins/english/NovelMultiverse[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "novelmultiverse";
-export const name = "NovelMultiverse [madara]";
-export const icon = "multisrc/madara/icons/novelmultiverse.png";
-export const version = "1.0.0";
-export const site = "https://www.novelmultiverse.com/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "novel-genre/" + filters.genres + '/';
- } else {
- url += "novel/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (false) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":FilterInputs.Picker},{"key":"genres","label":"GENRES","values":[{"label":"Action","value":"action"},{"label":"Adult","value":"adult"},{"label":"Adventure","value":"adventure"},{"label":"Anime","value":"anime"},{"label":"Cartoon","value":"cartoon"},{"label":"Comedy","value":"comedy"},{"label":"Comic","value":"comic"},{"label":"Cooking","value":"cooking"},{"label":"Detective","value":"detective"},{"label":"Doujinshi","value":"doujinshi"},{"label":"Drama","value":"drama"},{"label":"Ecchi","value":"ecchi"},{"label":"Fantasy","value":"fantasy"},{"label":"Gender Bender","value":"gender-bender"},{"label":"Harem","value":"harem"},{"label":"Historical","value":"historical"},{"label":"Horror","value":"horror"},{"label":"Josei","value":"josei"},{"label":"Live action","value":"live-action"},{"label":"Manga","value":"manga"},{"label":"Manhua","value":"manhua"},{"label":"Manhwa","value":"manhwa"},{"label":"Martial Arts","value":"martial-arts"},{"label":"Mature","value":"mature"},{"label":"Mecha","value":"mecha"},{"label":"Mystery","value":"mystery"},{"label":"One shot","value":"one-shot"},{"label":"Original","value":"original"},{"label":"Psychological","value":"psychological"},{"label":"Romance","value":"romance"},{"label":"School Life","value":"school-life"},{"label":"Sci-fi","value":"sci-fi"},{"label":"Seinen","value":"seinen"},{"label":"Shoujo","value":"shoujo"},{"label":"Shoujo Ai","value":"shoujo-ai"},{"label":"Shounen","value":"shounen"},{"label":"Shounen Ai","value":"shounen-ai"},{"label":"Slice of Life","value":"slice-of-life"},{"label":"Smut","value":"smut"},{"label":"Soft Yaoi","value":"soft-yaoi"},{"label":"Soft Yuri","value":"soft-yuri"},{"label":"Sports","value":"sports"},{"label":"Supernatural","value":"supernatural"},{"label":"Tragedy","value":"tragedy"},{"label":"Translation","value":"translation"},{"label":"Webtoon","value":"webtoon"},{"label":"Wuxia","value":"wuxia"},{"label":"Xianxia","value":"xianxia"},{"label":"Xuanhuan","value":"xuanhuan"},{"label":"Yaoi","value":"yaoi"},{"label":"Yuri","value":"yuri"}],"inputType":FilterInputs.Picker}];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"novelmultiverse","sourceSite":"https://www.novelmultiverse.com/","sourceName":"NovelMultiverse","filters":[{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":"Picker"},{"key":"genres","label":"GENRES","values":[{"label":"Action","value":"action"},{"label":"Adult","value":"adult"},{"label":"Adventure","value":"adventure"},{"label":"Anime","value":"anime"},{"label":"Cartoon","value":"cartoon"},{"label":"Comedy","value":"comedy"},{"label":"Comic","value":"comic"},{"label":"Cooking","value":"cooking"},{"label":"Detective","value":"detective"},{"label":"Doujinshi","value":"doujinshi"},{"label":"Drama","value":"drama"},{"label":"Ecchi","value":"ecchi"},{"label":"Fantasy","value":"fantasy"},{"label":"Gender Bender","value":"gender-bender"},{"label":"Harem","value":"harem"},{"label":"Historical","value":"historical"},{"label":"Horror","value":"horror"},{"label":"Josei","value":"josei"},{"label":"Live action","value":"live-action"},{"label":"Manga","value":"manga"},{"label":"Manhua","value":"manhua"},{"label":"Manhwa","value":"manhwa"},{"label":"Martial Arts","value":"martial-arts"},{"label":"Mature","value":"mature"},{"label":"Mecha","value":"mecha"},{"label":"Mystery","value":"mystery"},{"label":"One shot","value":"one-shot"},{"label":"Original","value":"original"},{"label":"Psychological","value":"psychological"},{"label":"Romance","value":"romance"},{"label":"School Life","value":"school-life"},{"label":"Sci-fi","value":"sci-fi"},{"label":"Seinen","value":"seinen"},{"label":"Shoujo","value":"shoujo"},{"label":"Shoujo Ai","value":"shoujo-ai"},{"label":"Shounen","value":"shounen"},{"label":"Shounen Ai","value":"shounen-ai"},{"label":"Slice of Life","value":"slice-of-life"},{"label":"Smut","value":"smut"},{"label":"Soft Yaoi","value":"soft-yaoi"},{"label":"Soft Yuri","value":"soft-yuri"},{"label":"Sports","value":"sports"},{"label":"Supernatural","value":"supernatural"},{"label":"Tragedy","value":"tragedy"},{"label":"Translation","value":"translation"},{"label":"Webtoon","value":"webtoon"},{"label":"Wuxia","value":"wuxia"},{"label":"Xianxia","value":"xianxia"},{"label":"Xuanhuan","value":"xuanhuan"},{"label":"Yaoi","value":"yaoi"},{"label":"Yuri","value":"yuri"}],"inputType":"Picker"}],"options":{"lang":"English"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/english/NovelOnline.ts b/plugins/english/NovelOnline.broken.ts
similarity index 100%
rename from plugins/english/NovelOnline.ts
rename to plugins/english/NovelOnline.broken.ts
diff --git a/plugins/english/NovelR18[madara].ts b/plugins/english/NovelR18[madara].ts
index 14937f5..f7e0db5 100644
--- a/plugins/english/NovelR18[madara].ts
+++ b/plugins/english/NovelR18[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "novelr18";
-export const name = "NovelR18 [madara]";
-export const icon = "multisrc/madara/icons/novelr18.png";
-export const version = "1.0.0";
-export const site = "https://novelr18.com/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "novel-genre/" + filters.genres + '/';
- } else {
- url += "novel/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (true) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "manga" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [{"key":"sort","label":"Sort by :","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest Update","value":"latest"},{"label":"Most Views","value":"views"},{"label":"Newly Added Novels","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":FilterInputs.Picker}];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"novelr18","sourceSite":"https://novelr18.com/","sourceName":"NovelR18","filters":[{"key":"sort","label":"Sort by :","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest Update","value":"latest"},{"label":"Most Views","value":"views"},{"label":"Newly Added Novels","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":"Picker"}],"options":{"path":{"novels":"novel","novel":"manga","chapter":"manga"},"useNewChapterEndpoint":true,"lang":"English"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/english/NovelTranslate[madara].ts b/plugins/english/NovelTranslate[madara].ts
index 0fb49f9..efa9572 100644
--- a/plugins/english/NovelTranslate[madara].ts
+++ b/plugins/english/NovelTranslate[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "novelTL";
-export const name = "NovelTranslate [madara]";
-export const icon = "multisrc/madara/icons/noveltranslate.png";
-export const version = "1.0.0";
-export const site = "https://noveltranslate.com/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "manga-genre/" + filters.genres + '/';
- } else {
- url += "all-novels/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (false) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "manga" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":FilterInputs.Picker},{"key":"genres","label":"GENRES","values":[{"label":"Action","value":"action"},{"label":"Adult","value":"adult"},{"label":"Adventure","value":"adventure"},{"label":"Bleach","value":"bleach"},{"label":"Chinese","value":"chinese"},{"label":"Comedy","value":"comedy"},{"label":"Conan","value":"conan"},{"label":"cooking","value":"cooking"},{"label":"Dragon Ball","value":"dragon-ball"},{"label":"Drama","value":"drama"},{"label":"Ecchi","value":"ecchi"},{"label":"Erciyuan","value":"erciyuan"},{"label":"Fairy Tail","value":"fairy-tail"},{"label":"Faloo","value":"faloo"},{"label":"Fan-Fiction","value":"fan-fiction"},{"label":"Fantasy","value":"fantasy"},{"label":"FoodWars!","value":"foodwars"},{"label":"Game","value":"game"},{"label":"Gender Bender","value":"gender-bender"},{"label":"Harem","value":"harem"},{"label":"Historical","value":"historical"},{"label":"Horror","value":"horror"},{"label":"Hunter x Hunter","value":"hunter-x-hunter"},{"label":"Isekai","value":"isekai"},{"label":"Japanese","value":"japanese"},{"label":"Jojo","value":"jojo"},{"label":"Josei","value":"josei"},{"label":"Korean","value":"korean"},{"label":"Martial Arts","value":"martial-arts"},{"label":"Marvel","value":"marvel"},{"label":"Mature","value":"mature"},{"label":"Mecha","value":"mecha"},{"label":"Military","value":"military"},{"label":"Mystery","value":"mystery"},{"label":"Naruto","value":"naruto"},{"label":"One piece","value":"one-piece"},{"label":"Pokemon","value":"pokemon"},{"label":"Political","value":"political"},{"label":"Psychological","value":"psychological"},{"label":"Romance","value":"romance"},{"label":"School Life","value":"school-life"},{"label":"Sci-fi","value":"sci-fi"},{"label":"Seinen","value":"seinen"},{"label":"Shoujo","value":"shoujo"},{"label":"Shoujo Ai","value":"shoujo-ai"},{"label":"Shounen","value":"shounen"},{"label":"Shounen Ai","value":"shounen-ai"},{"label":"Slice of Life","value":"slice-of-life"},{"label":"Smut","value":"smut"},{"label":"Sport","value":"sport"},{"label":"Sports","value":"sports"},{"label":"Supernatural","value":"supernatural"},{"label":"System","value":"system"},{"label":"Toriko","value":"toriko"},{"label":"Tragedy","value":"tragedy"},{"label":"Urban","value":"urban"},{"label":"Urban Life","value":"urban-life"},{"label":"Wuxia","value":"wuxia"},{"label":"Xianxia","value":"xianxia"},{"label":"Xuanhuan","value":"xuanhuan"},{"label":"Yaoi","value":"yaoi"},{"label":"Yuri","value":"yuri"}],"inputType":FilterInputs.Picker}];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"novelTL","sourceSite":"https://noveltranslate.com/","sourceName":"NovelTranslate","filters":[{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":"Picker"},{"key":"genres","label":"GENRES","values":[{"label":"Action","value":"action"},{"label":"Adult","value":"adult"},{"label":"Adventure","value":"adventure"},{"label":"Bleach","value":"bleach"},{"label":"Chinese","value":"chinese"},{"label":"Comedy","value":"comedy"},{"label":"Conan","value":"conan"},{"label":"cooking","value":"cooking"},{"label":"Dragon Ball","value":"dragon-ball"},{"label":"Drama","value":"drama"},{"label":"Ecchi","value":"ecchi"},{"label":"Erciyuan","value":"erciyuan"},{"label":"Fairy Tail","value":"fairy-tail"},{"label":"Faloo","value":"faloo"},{"label":"Fan-Fiction","value":"fan-fiction"},{"label":"Fantasy","value":"fantasy"},{"label":"FoodWars!","value":"foodwars"},{"label":"Game","value":"game"},{"label":"Gender Bender","value":"gender-bender"},{"label":"Harem","value":"harem"},{"label":"Historical","value":"historical"},{"label":"Horror","value":"horror"},{"label":"Hunter x Hunter","value":"hunter-x-hunter"},{"label":"Isekai","value":"isekai"},{"label":"Japanese","value":"japanese"},{"label":"Jojo","value":"jojo"},{"label":"Josei","value":"josei"},{"label":"Korean","value":"korean"},{"label":"Martial Arts","value":"martial-arts"},{"label":"Marvel","value":"marvel"},{"label":"Mature","value":"mature"},{"label":"Mecha","value":"mecha"},{"label":"Military","value":"military"},{"label":"Mystery","value":"mystery"},{"label":"Naruto","value":"naruto"},{"label":"One piece","value":"one-piece"},{"label":"Pokemon","value":"pokemon"},{"label":"Political","value":"political"},{"label":"Psychological","value":"psychological"},{"label":"Romance","value":"romance"},{"label":"School Life","value":"school-life"},{"label":"Sci-fi","value":"sci-fi"},{"label":"Seinen","value":"seinen"},{"label":"Shoujo","value":"shoujo"},{"label":"Shoujo Ai","value":"shoujo-ai"},{"label":"Shounen","value":"shounen"},{"label":"Shounen Ai","value":"shounen-ai"},{"label":"Slice of Life","value":"slice-of-life"},{"label":"Smut","value":"smut"},{"label":"Sport","value":"sport"},{"label":"Sports","value":"sports"},{"label":"Supernatural","value":"supernatural"},{"label":"System","value":"system"},{"label":"Toriko","value":"toriko"},{"label":"Tragedy","value":"tragedy"},{"label":"Urban","value":"urban"},{"label":"Urban Life","value":"urban-life"},{"label":"Wuxia","value":"wuxia"},{"label":"Xianxia","value":"xianxia"},{"label":"Xuanhuan","value":"xuanhuan"},{"label":"Yaoi","value":"yaoi"},{"label":"Yuri","value":"yuri"}],"inputType":"Picker"}],"options":{"path":{"novels":"all-novels","novel":"manga","chapter":"manga","genres":"manga-genre"},"lang":"English"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/english/Novelmtcom[readwn].ts b/plugins/english/Novelmtcom[readwn].ts
deleted file mode 100644
index 9cdce91..0000000
--- a/plugins/english/Novelmtcom[readwn].ts
+++ /dev/null
@@ -1,195 +0,0 @@
-
-import { load as parseHTML } from "cheerio";
-// import dayjs from 'dayjs';
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { parseMadaraDate } from "@libs/parseMadaraDate";
-// import { isUrlAbsolute } from '@libs/isAbsoluteUrl';
-// import { showToast } from "@libs/showToast";
-import { FilterInputs } from "@libs/filterInputs";
-// import { NovelStatus } from '@libs/novelStatus';
-// import { defaultCover } from "@libs/defaultCover";
-
-export const id = "Novelmt.com";
-export const name = "Novelmt.com";
-export const icon = "multisrc/readwn/icons/novelmt.png";
-export const version = "1.0.0";
-export const site = "https://www.novelmt.com/";
-
-export const popularNovels: Plugin.popularNovels = async function (
- page,
- { filters, showLatestNovels }
-) {
- const novels: Novel.Item[] = [];
- const pageNo = page - 1;
-
- let url = site + 'list/';
- url += (filters?.genres || 'all') + '/';
- url += (filters?.status || 'all') + '-';
- url += (showLatestNovels ? 'lastdotime' : filters?.sort || 'newstime') + '-';
- url += pageNo + '.html';
-
- const result = await fetchApi(url);
- const body = await result.text();
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('li.novel-item').each(function () {
- const novelName = loadedCheerio(this).find('h4').text();
- const novelUrl = site + loadedCheerio(this).find('a').attr('href');
-
- const coverUri = loadedCheerio(this)
- .find('.novel-cover > img')
- .attr('data-src');
-
- const novelCover = site + coverUri;
-
- const novel = { name: novelName, cover: novelCover, url: novelUrl };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters =
- async function (novelUrl) {
- const result = await fetchApi(novelUrl);
- const body = await result.text();
-
- let loadedCheerio = parseHTML(body);
-
- const novel: Novel.instance = {
- url: novelUrl,
- chapters: [],
- };
-
- novel.name = loadedCheerio('h1.novel-title').text();
-
- const coverUri = loadedCheerio('figure.cover > img').attr('data-src');
- novel.cover = site + coverUri;
-
- novel.summary = loadedCheerio('.summary')
- .text()
- .replace('Summary', '')
- .trim();
-
- novel.genres = '';
-
- loadedCheerio('div.categories > ul > li').each(function () {
- novel.genres += loadedCheerio(this).text().trim() + ',';
- });
-
- loadedCheerio('div.header-stats > span').each(function () {
- if (loadedCheerio(this).find('small').text() === 'Status') {
- novel.status = loadedCheerio(this).find('strong').text();
- }
- });
-
- novel.genres = novel.genres.slice(0, -1);
-
- novel.author = loadedCheerio('span[itemprop=author]').text();
-
- let novelChapters: Chapter.Item[] = [];
-
- const novelId = novelUrl.replace('.html', '').replace(site, '');
-
- const latestChapterNo = parseInt(loadedCheerio('.header-stats')
- .find('span > strong')
- .first()
- .text()
- .trim());
-
- let lastChapterNo = 1;
- loadedCheerio('.chapter-list li').each(function () {
- const chapterName = loadedCheerio(this)
- .find('a .chapter-title')
- .text()
- .trim();
-
- const chapterUrl = site + loadedCheerio(this).find('a').attr('href')?.trim();
-
- const releaseDate = loadedCheerio(this)
- .find('a .chapter-update')
- .text()
- .trim();
-
- lastChapterNo = parseInt(loadedCheerio(this).find('a .chapter-no').text().trim());
-
- const chapter = { name: chapterName, releaseTime: parseMadaraDate(releaseDate), url: chapterUrl };
-
- novelChapters.push(chapter);
- });
-
- // Itterate once more before loop to finish off
- lastChapterNo++;
- for (let i = lastChapterNo; i <= latestChapterNo; i++) {
- const chapterName = 'Chapter ' + i;
- const chapterUrl = site + novelId+'_'+ i +'.html';
- const releaseDate = null;
-
- const chapter = { name: chapterName, releaseTime: releaseDate,url: chapterUrl };
-
- novelChapters.push(chapter);
- }
-
- novel.chapters = novelChapters;
- return novel;
- };
-
-export const parseChapter: Plugin.parseChapter = async function (chapterUrl) {
- const result = await fetchApi(chapterUrl);
- const body = await result.text();
-
- const loadedCheerio = parseHTML(body);
-
- const chapterText = loadedCheerio('.chapter-content').html();
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const searchUrl = site + 'e/search/index.php';
-
- const result = await fetchApi(searchUrl, {
- headers: {
- 'Content-Type': 'application/x-www-form-urlencoded',
- Referer: site + 'search.html',
- Origin: site,
- 'user-agent':
- 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36',
- },
- method: 'POST',
- body: JSON.stringify({
- show: 'title',
- tempid: 1,
- tbname: 'news',
- keyboard: searchTerm,
- }),
- });
- const body = await result.text();
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('li.novel-item').each(function () {
- const novelName = loadedCheerio(this).find('h4').text();
- const novelUrl = site + loadedCheerio(this).find('a').attr('href');
-
- const coverUri = site + loadedCheerio(this).find('img').attr('data-src');
- const novelCover = site + coverUri;
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = fetchFile;
-
-export const filters = [{"key":"sort","label":"Sort By","values":[{"label":"New","value":"newstime"},{"label":"Popular","value":"onclick"},{"label":"Updates","value":"lastdotime"}], "inputType":FilterInputs.Picker},{"key":"status","label":"Status","values":[{"label":"All","value":"all"},{"label":"Completed","value":"Completed"},{"label":"Ongoing","value":"Ongoing"}], "inputType":FilterInputs.Picker},{"key":"genres","label":"Genre / Category","values":[{"label":"All","value":"all"},{"label":"Action","value":"action"},{"label":"Adult","value":"adult"},{"label":"Adventure","value":"adventure"},{"label":"Billionaire","value":"billionaire"},{"label":"CEO","value":"ceo"},{"label":"Chinese","value":"chinese"},{"label":"Comedy","value":"comedy"},{"label":"Contemporary Romance","value":"contemporary-romance"},{"label":"Drama","value":"drama"},{"label":"Eastern Fantasy","value":"eastern-fantasy"},{"label":"Ecchi","value":"ecchi"},{"label":"Erciyuan","value":"erciyuan"},{"label":"Faloo","value":"faloo"},{"label":"Fan-Fiction","value":"fan-fiction"},{"label":"Fantasy","value":"fantasy"},{"label":"Fantasy Romance","value":"fantasy-romance"},{"label":"Farming","value":"farming"},{"label":"Game","value":"game"},{"label":"Games","value":"games"},{"label":"Gay Romance","value":"gay-romance"},{"label":"Gender Bender","value":"gender-bender"},{"label":"Harem","value":"harem"},{"label":"Historical","value":"historical"},{"label":"Historical Romance","value":"historical-romance"},{"label":"Horror","value":"horror"},{"label":"Isekai","value":"isekai"},{"label":"Japanese","value":"japanese"},{"label":"Josei","value":"josei"},{"label":"Korean","value":"korean"},{"label":"Lolicon","value":"lolicon"},{"label":"Magic","value":"magic"},{"label":"Magical Realism","value":"magical-realism"},{"label":"Martial Arts","value":"martial-arts"},{"label":"Mature","value":"mature"},{"label":"Mecha","value":"mecha"},{"label":"Military","value":"military"},{"label":"Modern Life","value":"modern-life"},{"label":"Modern Romance","value":"modern-romance"},{"label":"Mystery","value":"mystery"},{"label":"Psychological","value":"psychological"},{"label":"Romance","value":"romance"},{"label":"Romantic","value":"romantic"},{"label":"School Life","value":"school-life"},{"label":"Sci-fi","value":"sci-fi"},{"label":"Seinen","value":"seinen"},{"label":"Shoujo","value":"shoujo"},{"label":"Shoujo Ai","value":"shoujo-ai"},{"label":"Shounen","value":"shounen"},{"label":"Shounen Ai","value":"shounen-ai"},{"label":"Slice of Life","value":"slice-of-life"},{"label":"Smut","value":"smut"},{"label":"Sports","value":"sports"},{"label":"Supernatural","value":"supernatural"},{"label":"Tragedy","value":"tragedy"},{"label":"Two-dimensional","value":"two-dimensional"},{"label":"Urban","value":"urban"},{"label":"Urban Life","value":"urban-life"},{"label":"Video Games","value":"video-games"},{"label":"Virtual Reality","value":"virtual-reality"},{"label":"Wuxia","value":"wuxia"},{"label":"Xianxia","value":"xianxia"},{"label":"Xuanhuan","value":"xuanhuan"},{"label":"Yaoi","value":"yaoi"},{"label":"Yuri","value":"yuri"}], "inputType":FilterInputs.Picker}];
\ No newline at end of file
diff --git a/plugins/english/Novelroomnet[madara].ts b/plugins/english/Novelroomnet[madara].ts
index 6bae24b..d074355 100644
--- a/plugins/english/Novelroomnet[madara].ts
+++ b/plugins/english/Novelroomnet[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "novelroom";
-export const name = "Novelroom.net [madara]";
-export const icon = "multisrc/madara/icons/novelroom.net.png";
-export const version = "1.0.0";
-export const site = "https://novelroom.net/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "novel-genre/" + filters.genres + '/';
- } else {
- url += "manga/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (false) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "manga" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"novelroom","sourceSite":"https://novelroom.net/","sourceName":"Novelroom.net","filters":[],"options":{"path":{"novels":"manga","novel":"manga","chapter":"manga"},"lang":"English"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/english/Novelstic[madara].ts b/plugins/english/Novelstic[madara].ts
index 05ac934..c9d81ed 100644
--- a/plugins/english/Novelstic[madara].ts
+++ b/plugins/english/Novelstic[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "novelstic";
-export const name = "Novelstic [madara]";
-export const icon = "multisrc/madara/icons/novelstic.png";
-export const version = "1.0.0";
-export const site = "https://novelstic.com/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "novel-genre/" + filters.genres + '/';
- } else {
- url += "novel/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (true) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":FilterInputs.Picker}];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"novelstic","sourceSite":"https://novelstic.com/","sourceName":"Novelstic","filters":[{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":"Picker"}],"options":{"useNewChapterEndpoint":true,"lang":"English"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/english/OnlyMTL[madara].ts b/plugins/english/OnlyMTL[madara].ts
index b427b3a..e8aa732 100644
--- a/plugins/english/OnlyMTL[madara].ts
+++ b/plugins/english/OnlyMTL[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "onlymtl";
-export const name = "OnlyMTL [madara]";
-export const icon = "multisrc/madara/icons/onlymtl.png";
-export const version = "1.0.0";
-export const site = "https://www.onlymtl.com/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "novel-genre/" + filters.genres + '/';
- } else {
- url += "novel/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (true) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"onlymtl","sourceSite":"https://www.onlymtl.com/","sourceName":"OnlyMTL","filters":[],"options":{"useNewChapterEndpoint":true,"lang":"English"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/english/ReadWebNovels[madara].ts b/plugins/english/ReadWebNovels[madara].ts
index e1bb54b..39af4b1 100644
--- a/plugins/english/ReadWebNovels[madara].ts
+++ b/plugins/english/ReadWebNovels[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "readwebnovels";
-export const name = "ReadWebNovels [madara]";
-export const icon = "multisrc/madara/icons/readwebnovels.png";
-export const version = "1.0.0";
-export const site = "https://readwebnovels.net/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "novel-genre/" + filters.genres + '/';
- } else {
- url += "novel/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (false) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":FilterInputs.Picker}];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"readwebnovels","sourceSite":"https://readwebnovels.net/","sourceName":"ReadWebNovels","filters":[{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":"Picker"}],"options":{"lang":"English"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/english/Readwncom[readwn].ts b/plugins/english/Readwncom[readwn].ts
deleted file mode 100644
index 415dd65..0000000
--- a/plugins/english/Readwncom[readwn].ts
+++ /dev/null
@@ -1,195 +0,0 @@
-
-import { load as parseHTML } from "cheerio";
-// import dayjs from 'dayjs';
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { parseMadaraDate } from "@libs/parseMadaraDate";
-// import { isUrlAbsolute } from '@libs/isAbsoluteUrl';
-// import { showToast } from "@libs/showToast";
-import { FilterInputs } from "@libs/filterInputs";
-// import { NovelStatus } from '@libs/novelStatus';
-// import { defaultCover } from "@libs/defaultCover";
-
-export const id = "Readwn.com";
-export const name = "Readwn.com";
-export const icon = "multisrc/readwn/icons/readwn.png";
-export const version = "1.0.0";
-export const site = "https://www.readwn.com/";
-
-export const popularNovels: Plugin.popularNovels = async function (
- page,
- { filters, showLatestNovels }
-) {
- const novels: Novel.Item[] = [];
- const pageNo = page - 1;
-
- let url = site + 'list/';
- url += (filters?.genres || 'all') + '/';
- url += (filters?.status || 'all') + '-';
- url += (showLatestNovels ? 'lastdotime' : filters?.sort || 'newstime') + '-';
- url += pageNo + '.html';
-
- const result = await fetchApi(url);
- const body = await result.text();
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('li.novel-item').each(function () {
- const novelName = loadedCheerio(this).find('h4').text();
- const novelUrl = site + loadedCheerio(this).find('a').attr('href');
-
- const coverUri = loadedCheerio(this)
- .find('.novel-cover > img')
- .attr('data-src');
-
- const novelCover = site + coverUri;
-
- const novel = { name: novelName, cover: novelCover, url: novelUrl };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters =
- async function (novelUrl) {
- const result = await fetchApi(novelUrl);
- const body = await result.text();
-
- let loadedCheerio = parseHTML(body);
-
- const novel: Novel.instance = {
- url: novelUrl,
- chapters: [],
- };
-
- novel.name = loadedCheerio('h1.novel-title').text();
-
- const coverUri = loadedCheerio('figure.cover > img').attr('data-src');
- novel.cover = site + coverUri;
-
- novel.summary = loadedCheerio('.summary')
- .text()
- .replace('Summary', '')
- .trim();
-
- novel.genres = '';
-
- loadedCheerio('div.categories > ul > li').each(function () {
- novel.genres += loadedCheerio(this).text().trim() + ',';
- });
-
- loadedCheerio('div.header-stats > span').each(function () {
- if (loadedCheerio(this).find('small').text() === 'Status') {
- novel.status = loadedCheerio(this).find('strong').text();
- }
- });
-
- novel.genres = novel.genres.slice(0, -1);
-
- novel.author = loadedCheerio('span[itemprop=author]').text();
-
- let novelChapters: Chapter.Item[] = [];
-
- const novelId = novelUrl.replace('.html', '').replace(site, '');
-
- const latestChapterNo = parseInt(loadedCheerio('.header-stats')
- .find('span > strong')
- .first()
- .text()
- .trim());
-
- let lastChapterNo = 1;
- loadedCheerio('.chapter-list li').each(function () {
- const chapterName = loadedCheerio(this)
- .find('a .chapter-title')
- .text()
- .trim();
-
- const chapterUrl = site + loadedCheerio(this).find('a').attr('href')?.trim();
-
- const releaseDate = loadedCheerio(this)
- .find('a .chapter-update')
- .text()
- .trim();
-
- lastChapterNo = parseInt(loadedCheerio(this).find('a .chapter-no').text().trim());
-
- const chapter = { name: chapterName, releaseTime: parseMadaraDate(releaseDate), url: chapterUrl };
-
- novelChapters.push(chapter);
- });
-
- // Itterate once more before loop to finish off
- lastChapterNo++;
- for (let i = lastChapterNo; i <= latestChapterNo; i++) {
- const chapterName = 'Chapter ' + i;
- const chapterUrl = site + novelId+'_'+ i +'.html';
- const releaseDate = null;
-
- const chapter = { name: chapterName, releaseTime: releaseDate,url: chapterUrl };
-
- novelChapters.push(chapter);
- }
-
- novel.chapters = novelChapters;
- return novel;
- };
-
-export const parseChapter: Plugin.parseChapter = async function (chapterUrl) {
- const result = await fetchApi(chapterUrl);
- const body = await result.text();
-
- const loadedCheerio = parseHTML(body);
-
- const chapterText = loadedCheerio('.chapter-content').html();
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const searchUrl = site + 'e/search/index.php';
-
- const result = await fetchApi(searchUrl, {
- headers: {
- 'Content-Type': 'application/x-www-form-urlencoded',
- Referer: site + 'search.html',
- Origin: site,
- 'user-agent':
- 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36',
- },
- method: 'POST',
- body: JSON.stringify({
- show: 'title',
- tempid: 1,
- tbname: 'news',
- keyboard: searchTerm,
- }),
- });
- const body = await result.text();
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('li.novel-item').each(function () {
- const novelName = loadedCheerio(this).find('h4').text();
- const novelUrl = site + loadedCheerio(this).find('a').attr('href');
-
- const coverUri = site + loadedCheerio(this).find('img').attr('data-src');
- const novelCover = site + coverUri;
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = fetchFile;
-
-export const filters = [{"key":"sort","label":"Sort By","values":[{"label":"New","value":"newstime"},{"label":"Popular","value":"onclick"},{"label":"Updates","value":"lastdotime"}], "inputType":FilterInputs.Picker},{"key":"status","label":"Status","values":[{"label":"All","value":"all"},{"label":"Completed","value":"Completed"},{"label":"Ongoing","value":"Ongoing"}], "inputType":FilterInputs.Picker},{"key":"genres","label":"Genre / Category","values":[{"label":"All","value":"all"},{"label":"Action","value":"action"},{"label":"Adventure","value":"adventure"},{"label":"Chinese","value":"chinese"},{"label":"Comedy","value":"comedy"},{"label":"Contemporary Romance","value":"contemporary-romance"},{"label":"Drama","value":"drama"},{"label":"Eastern Fantasy","value":"eastern-fantasy"},{"label":"Ecchi","value":"ecchi"},{"label":"Erciyuan","value":"erciyuan"},{"label":"Faloo","value":"faloo"},{"label":"Fan-Fiction","value":"fan-fiction"},{"label":"Fantasy","value":"fantasy"},{"label":"Fantasy Romance","value":"fantasy-romance"},{"label":"Game","value":"game"},{"label":"Gender Bender","value":"gender-bender"},{"label":"Harem","value":"harem"},{"label":"Hentai","value":"hentai"},{"label":"Historical","value":"historical"},{"label":"Horror","value":"horror"},{"label":"Isekai","value":"isekai"},{"label":"Japanese","value":"japanese"},{"label":"Josei","value":"josei"},{"label":"Korean","value":"korean"},{"label":"Lolicon","value":"lolicon"},{"label":"Magic","value":"magic"},{"label":"Magical Realism","value":"magical-realism"},{"label":"Martial Arts","value":"martial-arts"},{"label":"Mecha","value":"mecha"},{"label":"Military","value":"military"},{"label":"Mystery","value":"mystery"},{"label":"Official Circles","value":"official_circles"},{"label":"Psychological","value":"psychological"},{"label":"Romance","value":"romance"},{"label":"School Life","value":"school-life"},{"label":"Sci-fi","value":"sci-fi"},{"label":"Science Fiction","value":"science_fiction"},{"label":"Seinen","value":"seinen"},{"label":"Shoujo","value":"shoujo"},{"label":"Shoujo Ai","value":"shoujo-ai"},{"label":"Shounen","value":"shounen"},{"label":"Shounen Ai","value":"shounen-ai"},{"label":"Slice of Life","value":"slice-of-life"},{"label":"Sports","value":"sports"},{"label":"Supernatural","value":"supernatural"},{"label":"Suspense Thriller","value":"suspense_thriller"},{"label":"Tragedy","value":"tragedy"},{"label":"Travel Through Time","value":"travel_through_time"},{"label":"Two-dimensional","value":"two-dimensional"},{"label":"Urban","value":"urban"},{"label":"Urban Life","value":"urban-life"},{"label":"Video Games","value":"video-games"},{"label":"Virtual Reality","value":"virtual-reality"},{"label":"Wuxia","value":"wuxia"},{"label":"Wuxia Xianxia","value":"wuxia_xianxia"},{"label":"Xianxia","value":"xianxia"},{"label":"Xuanhuan","value":"xuanhuan"},{"label":"Yaoi","value":"yaoi"},{"label":"Yuri","value":"yuri"}], "inputType":FilterInputs.Picker}];
\ No newline at end of file
diff --git a/plugins/english/SleepyTranslations[madara].ts b/plugins/english/SleepyTranslations[madara].ts
index 69f5623..4591520 100644
--- a/plugins/english/SleepyTranslations[madara].ts
+++ b/plugins/english/SleepyTranslations[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "sleeptTLS";
-export const name = "SleepyTranslations [madara]";
-export const icon = "multisrc/madara/icons/sleepytranslations.png";
-export const version = "1.0.0";
-export const site = "https://sleepytranslations.com/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "novel-genre/" + filters.genres + '/';
- } else {
- url += "series/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (true) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "series" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":FilterInputs.Picker}];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"sleeptTLS","sourceSite":"https://sleepytranslations.com/","sourceName":"SleepyTranslations","filters":[{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":"Picker"}],"options":{"path":{"novels":"series","novel":"series","chapter":"series"},"useNewChapterEndpoint":true,"lang":"English"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/english/SonicMTL[madara].ts b/plugins/english/SonicMTL[madara].ts
index 6d21056..71a73e1 100644
--- a/plugins/english/SonicMTL[madara].ts
+++ b/plugins/english/SonicMTL[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "sonicmtl";
-export const name = "SonicMTL [madara]";
-export const icon = "multisrc/madara/icons/sonicmtl.png";
-export const version = "1.0.0";
-export const site = "https://www.sonicmtl.com/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "novel-genre/" + filters.genres + '/';
- } else {
- url += "novel/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (true) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":FilterInputs.Picker},{"key":"genres","label":"GENRES","values":[{"label":"Action","value":"action"},{"label":"Adult","value":"adult"},{"label":"Adventure","value":"adventure"},{"label":"Comedy","value":"comedy"},{"label":"Cooking","value":"cooking"},{"label":"Detective","value":"detective"},{"label":"Doujinshi","value":"doujinshi"},{"label":"Drama","value":"drama"},{"label":"Ecchi","value":"ecchi"},{"label":"Fan-Fiction","value":"fan-fiction"},{"label":"Fantasy","value":"fantasy"},{"label":"Gender Bender","value":"gender-bender"},{"label":"Harem","value":"harem"},{"label":"Historical","value":"historical"},{"label":"Horror","value":"horror"},{"label":"Josei","value":"josei"},{"label":"Live action","value":"live-action"},{"label":"Manga","value":"manga"},{"label":"Manhua","value":"manhua"},{"label":"Manhwa","value":"manhwa"},{"label":"Martial Arts","value":"martial-arts"},{"label":"Mature","value":"mature"},{"label":"Mecha","value":"mecha"},{"label":"Mystery","value":"mystery"},{"label":"One shot","value":"one-shot"},{"label":"Psychological","value":"psychological"},{"label":"Romance","value":"romance"},{"label":"School Life","value":"school-life"},{"label":"Sci-fi","value":"sci-fi"},{"label":"Seinen","value":"seinen"},{"label":"Shoujo","value":"shoujo"},{"label":"Shoujo Ai","value":"shoujo-ai"},{"label":"Shounen","value":"shounen"},{"label":"Shounen Ai","value":"shounen-ai"},{"label":"Slice of Life","value":"slice-of-life"},{"label":"Smut","value":"smut"},{"label":"Soft Yaoi","value":"soft-yaoi"},{"label":"Soft Yuri","value":"soft-yuri"},{"label":"Sports","value":"sports"},{"label":"Supernatural","value":"supernatural"},{"label":"Tragedy","value":"tragedy"},{"label":"Urban Life","value":"urban-life"},{"label":"Wuxia","value":"wuxia"},{"label":"Xianxia","value":"xianxia"},{"label":"Xuanhuan","value":"xuanhuan"},{"label":"Yaoi","value":"yaoi"},{"label":"Yuri","value":"yuri"}],"inputType":FilterInputs.Picker}];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"sonicmtl","sourceSite":"https://www.sonicmtl.com/","sourceName":"SonicMTL","filters":[{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":"Picker"},{"key":"genres","label":"GENRES","values":[{"label":"Action","value":"action"},{"label":"Adult","value":"adult"},{"label":"Adventure","value":"adventure"},{"label":"Comedy","value":"comedy"},{"label":"Cooking","value":"cooking"},{"label":"Detective","value":"detective"},{"label":"Doujinshi","value":"doujinshi"},{"label":"Drama","value":"drama"},{"label":"Ecchi","value":"ecchi"},{"label":"Fan-Fiction","value":"fan-fiction"},{"label":"Fantasy","value":"fantasy"},{"label":"Gender Bender","value":"gender-bender"},{"label":"Harem","value":"harem"},{"label":"Historical","value":"historical"},{"label":"Horror","value":"horror"},{"label":"Josei","value":"josei"},{"label":"Live action","value":"live-action"},{"label":"Manga","value":"manga"},{"label":"Manhua","value":"manhua"},{"label":"Manhwa","value":"manhwa"},{"label":"Martial Arts","value":"martial-arts"},{"label":"Mature","value":"mature"},{"label":"Mecha","value":"mecha"},{"label":"Mystery","value":"mystery"},{"label":"One shot","value":"one-shot"},{"label":"Psychological","value":"psychological"},{"label":"Romance","value":"romance"},{"label":"School Life","value":"school-life"},{"label":"Sci-fi","value":"sci-fi"},{"label":"Seinen","value":"seinen"},{"label":"Shoujo","value":"shoujo"},{"label":"Shoujo Ai","value":"shoujo-ai"},{"label":"Shounen","value":"shounen"},{"label":"Shounen Ai","value":"shounen-ai"},{"label":"Slice of Life","value":"slice-of-life"},{"label":"Smut","value":"smut"},{"label":"Soft Yaoi","value":"soft-yaoi"},{"label":"Soft Yuri","value":"soft-yuri"},{"label":"Sports","value":"sports"},{"label":"Supernatural","value":"supernatural"},{"label":"Tragedy","value":"tragedy"},{"label":"Urban Life","value":"urban-life"},{"label":"Wuxia","value":"wuxia"},{"label":"Xianxia","value":"xianxia"},{"label":"Xuanhuan","value":"xuanhuan"},{"label":"Yaoi","value":"yaoi"},{"label":"Yuri","value":"yuri"}],"inputType":"Picker"}],"options":{"useNewChapterEndpoint":true,"lang":"English"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/english/SugarBabies[madara].ts b/plugins/english/SugarBabies[madara].ts
index 4b13e63..9db8cc7 100644
--- a/plugins/english/SugarBabies[madara].ts
+++ b/plugins/english/SugarBabies[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "sugarbbscan";
-export const name = "Sugar Babies [madara]";
-export const icon = "multisrc/madara/icons/sugarbabies.png";
-export const version = "1.0.0";
-export const site = "https://sugarbbscan.com/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "novel-genre/" + filters.genres + '/';
- } else {
- url += "series/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (false) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "series" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"sugarbbscan","sourceSite":"https://sugarbbscan.com/","sourceName":"Sugar Babies","filters":[],"options":{"path":{"novels":"series","novel":"series","chapter":"series"},"lang":"English"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/english/SweetEscapeTranslations[madara].ts b/plugins/english/SweetEscapeTranslations[madara].ts
index d6b8a0b..fc1922f 100644
--- a/plugins/english/SweetEscapeTranslations[madara].ts
+++ b/plugins/english/SweetEscapeTranslations[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "sweetEscapeTL";
-export const name = "Sweet Escape Translations [madara]";
-export const icon = "multisrc/madara/icons/sweetescapetranslations.png";
-export const version = "1.0.0";
-export const site = "https://sweetescapetranslations.com/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "manga-genre/" + filters.genres + '/';
- } else {
- url += "manga/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (false) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "manga" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":FilterInputs.Picker},{"key":"genres","label":"GENRES","values":[{"label":"Action","value":"action"},{"label":"Adult","value":"adult"},{"label":"Comedy","value":"comedy"},{"label":"Drama","value":"drama"},{"label":"Fantasy","value":"fantasy"},{"label":"Gender Bender","value":"gender-bender"},{"label":"Mature","value":"mature"},{"label":"Modern","value":"modern"},{"label":"Mystery","value":"mystery"},{"label":"R-15","value":"r-15"},{"label":"Romance","value":"romance"},{"label":"Slice of Life","value":"slice-of-life"}],"inputType":FilterInputs.Picker}];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"sweetEscapeTL","sourceSite":"https://sweetescapetranslations.com/","sourceName":"Sweet Escape Translations","filters":[{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":"Picker"},{"key":"genres","label":"GENRES","values":[{"label":"Action","value":"action"},{"label":"Adult","value":"adult"},{"label":"Comedy","value":"comedy"},{"label":"Drama","value":"drama"},{"label":"Fantasy","value":"fantasy"},{"label":"Gender Bender","value":"gender-bender"},{"label":"Mature","value":"mature"},{"label":"Modern","value":"modern"},{"label":"Mystery","value":"mystery"},{"label":"R-15","value":"r-15"},{"label":"Romance","value":"romance"},{"label":"Slice of Life","value":"slice-of-life"}],"inputType":"Picker"}],"options":{"path":{"novels":"manga","novel":"manga","chapter":"manga","genres":"manga-genre"},"useNewChapterEndpoint":false,"lang":"English"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/english/WebNovelLover[madara].ts b/plugins/english/WebNovelLover[madara].ts
index 12e87c2..91209e1 100644
--- a/plugins/english/WebNovelLover[madara].ts
+++ b/plugins/english/WebNovelLover[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "webnovelover";
-export const name = "WebNovelLover [madara]";
-export const icon = "multisrc/madara/icons/webnovellover.png";
-export const version = "1.0.0";
-export const site = "https://www.webnovelover.com/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "novel-genre/" + filters.genres + '/';
- } else {
- url += "novel/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (false) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":FilterInputs.Picker},{"key":"genres","label":"GENRES","values":[{"label":"Action","value":"action"},{"label":"Adapted into drama","value":"adapted-into-drama"},{"label":"Adventure","value":"adventure"},{"label":"Comedy","value":"comedy"},{"label":"Completed","value":"completed"},{"label":"Drama","value":"drama"},{"label":"English Novel","value":"english-novel"},{"label":"Fantasy","value":"fantasy"},{"label":"Gender Bender","value":"gender-bender"},{"label":"Harem","value":"harem"},{"label":"Historical","value":"historical"},{"label":"Horror","value":"horror"},{"label":"Indo Novel","value":"indo-novel"},{"label":"Josei","value":"josei"},{"label":"Martial Arts","value":"martial-arts"},{"label":"Mature","value":"mature"},{"label":"Mystery","value":"mystery"},{"label":"Rebirth","value":"rebirth"},{"label":"Reincarnation","value":"reincarnation"},{"label":"Romance","value":"romance"},{"label":"Sci-fi","value":"sci-fi"},{"label":"Shoujo","value":"shoujo"},{"label":"Shounen","value":"shounen"},{"label":"Slice of Life","value":"slice-of-life"},{"label":"Spiritual","value":"spiritual"},{"label":"Supernatural","value":"supernatural"},{"label":"Tragedy","value":"tragedy"},{"label":"Transmigration","value":"transmigration"},{"label":"University","value":"university"},{"label":"Wuxia","value":"wuxia"},{"label":"Xianxia","value":"xianxia"},{"label":"Xuanhuan","value":"xuanhuan"},{"label":"Youth","value":"youth"}],"inputType":FilterInputs.Picker}];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"webnovelover","sourceSite":"https://www.webnovelover.com/","sourceName":"WebNovelLover","filters":[{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":"Picker"},{"key":"genres","label":"GENRES","values":[{"label":"Action","value":"action"},{"label":"Adapted into drama","value":"adapted-into-drama"},{"label":"Adventure","value":"adventure"},{"label":"Comedy","value":"comedy"},{"label":"Completed","value":"completed"},{"label":"Drama","value":"drama"},{"label":"English Novel","value":"english-novel"},{"label":"Fantasy","value":"fantasy"},{"label":"Gender Bender","value":"gender-bender"},{"label":"Harem","value":"harem"},{"label":"Historical","value":"historical"},{"label":"Horror","value":"horror"},{"label":"Indo Novel","value":"indo-novel"},{"label":"Josei","value":"josei"},{"label":"Martial Arts","value":"martial-arts"},{"label":"Mature","value":"mature"},{"label":"Mystery","value":"mystery"},{"label":"Rebirth","value":"rebirth"},{"label":"Reincarnation","value":"reincarnation"},{"label":"Romance","value":"romance"},{"label":"Sci-fi","value":"sci-fi"},{"label":"Shoujo","value":"shoujo"},{"label":"Shounen","value":"shounen"},{"label":"Slice of Life","value":"slice-of-life"},{"label":"Spiritual","value":"spiritual"},{"label":"Supernatural","value":"supernatural"},{"label":"Tragedy","value":"tragedy"},{"label":"Transmigration","value":"transmigration"},{"label":"University","value":"university"},{"label":"Wuxia","value":"wuxia"},{"label":"Xianxia","value":"xianxia"},{"label":"Xuanhuan","value":"xuanhuan"},{"label":"Youth","value":"youth"}],"inputType":"Picker"}],"options":{"lang":"English"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/english/WuxiaWorldSite[madara].ts b/plugins/english/WuxiaWorldSite[madara].ts
index 2e2e9f0..9b800c3 100644
--- a/plugins/english/WuxiaWorldSite[madara].ts
+++ b/plugins/english/WuxiaWorldSite[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "wuxiaworld.site";
-export const name = "WuxiaWorld.Site [madara]";
-export const icon = "multisrc/madara/icons/wuxiaworld.site.png";
-export const version = "1.0.0";
-export const site = "https://wuxiaworld.site/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "novel-genre/" + filters.genres + '/';
- } else {
- url += "novel/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (true) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":FilterInputs.Picker}];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"wuxiaworld.site","sourceSite":"https://wuxiaworld.site/","sourceName":"WuxiaWorld.Site","filters":[{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":"Picker"}],"options":{"useNewChapterEndpoint":true,"lang":"English"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/english/ZetroTranslation[madara].ts b/plugins/english/ZetroTranslation[madara].ts
index cf159bf..a22e6b9 100644
--- a/plugins/english/ZetroTranslation[madara].ts
+++ b/plugins/english/ZetroTranslation[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "zetroTL";
-export const name = "Zetro Translation [madara]";
-export const icon = "multisrc/madara/icons/zetrotranslation.png";
-export const version = "1.0.0";
-export const site = "https://zetrotranslation.com/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "genre/" + filters.genres + '/';
- } else {
- url += "novel/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (false) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":FilterInputs.Picker},{"key":"genres","label":"GENRES","values":[{"label":"Action","value":"action"},{"label":"Adventure","value":"adventure"},{"label":"Comedy","value":"comedy"},{"label":"Dark Elf","value":"dark-elf"},{"label":"Drama","value":"drama"},{"label":"Ecchi","value":"ecchi"},{"label":"Fantasy","value":"fantasy"},{"label":"Harem","value":"harem"},{"label":"Horror","value":"horror"},{"label":"Isekai","value":"isekai"},{"label":"Mecha","value":"mecha"},{"label":"Mystery","value":"mystery"},{"label":"NTR","value":"ntr"},{"label":"Original Works","value":"original-works"},{"label":"Rom-Com","value":"rom-com"},{"label":"Romance","value":"romance"},{"label":"School","value":"school"},{"label":"Shoujo","value":"shoujo"},{"label":"Slice of Life","value":"slice-of-life"},{"label":"Villain","value":"villain"},{"label":"Yuri","value":"yuri"}],"inputType":FilterInputs.Picker}];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"zetroTL","sourceSite":"https://zetrotranslation.com/","sourceName":"Zetro Translation","filters":[{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":"Picker"},{"key":"genres","label":"GENRES","values":[{"label":"Action","value":"action"},{"label":"Adventure","value":"adventure"},{"label":"Comedy","value":"comedy"},{"label":"Dark Elf","value":"dark-elf"},{"label":"Drama","value":"drama"},{"label":"Ecchi","value":"ecchi"},{"label":"Fantasy","value":"fantasy"},{"label":"Harem","value":"harem"},{"label":"Horror","value":"horror"},{"label":"Isekai","value":"isekai"},{"label":"Mecha","value":"mecha"},{"label":"Mystery","value":"mystery"},{"label":"NTR","value":"ntr"},{"label":"Original Works","value":"original-works"},{"label":"Rom-Com","value":"rom-com"},{"label":"Romance","value":"romance"},{"label":"School","value":"school"},{"label":"Shoujo","value":"shoujo"},{"label":"Slice of Life","value":"slice-of-life"},{"label":"Villain","value":"villain"},{"label":"Yuri","value":"yuri"}],"inputType":"Picker"}],"options":{"path":{"genres":"genre"},"lang":"English"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/english/ZinnNovel[madara].ts b/plugins/english/ZinnNovel[madara].ts
index 5d7b94c..d83f336 100644
--- a/plugins/english/ZinnNovel[madara].ts
+++ b/plugins/english/ZinnNovel[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "zinnovel";
-export const name = "ZinnNovel [madara]";
-export const icon = "multisrc/madara/icons/zinnnovel.png";
-export const version = "1.0.0";
-export const site = "https://zinnovel.com/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "manga-genre/" + filters.genres + '/';
- } else {
- url += "manga/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (false) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "manga" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":FilterInputs.Picker},{"key":"genres","label":"GENRES","values":[{"label":"Action","value":"action"},{"label":"Adult","value":"adult"},{"label":"Adventure","value":"adventure"},{"label":"Anime","value":"anime"},{"label":"Cartoon","value":"cartoon"},{"label":"Comedy","value":"comedy"},{"label":"Comic","value":"comic"},{"label":"Cooking","value":"cooking"},{"label":"Detective","value":"detective"},{"label":"Doujinshi","value":"doujinshi"},{"label":"Drama","value":"drama"},{"label":"Ecchi","value":"ecchi"},{"label":"Fantasy","value":"fantasy"},{"label":"Game","value":"game"},{"label":"Gender Bender","value":"gender-bender"},{"label":"Harem","value":"harem"},{"label":"Historical","value":"historical"},{"label":"Horror","value":"horror"},{"label":"Isekai","value":"isekai"},{"label":"Josei","value":"josei"},{"label":"Live action","value":"live-action"},{"label":"Lolicon","value":"lolicon"},{"label":"Magical Realism","value":"magical-realism"},{"label":"Manga","value":"manga"},{"label":"Manhua","value":"manhua"},{"label":"Manhwa","value":"manhwa"},{"label":"Martial Arts","value":"martial-arts"},{"label":"Mature","value":"mature"},{"label":"Mecha","value":"mecha"},{"label":"Mystery","value":"mystery"},{"label":"One shot","value":"one-shot"},{"label":"Psychological","value":"psychological"},{"label":"Reincarnation","value":"reincarnation"},{"label":"Romance","value":"romance"},{"label":"School Life","value":"school-life"},{"label":"Sci-fi","value":"sci-fi"},{"label":"Seinen","value":"seinen"},{"label":"Shoujo","value":"shoujo"},{"label":"Shoujo Ai","value":"shoujo-ai"},{"label":"Shounen","value":"shounen"},{"label":"Shounen Ai","value":"shounen-ai"},{"label":"Slice of Life","value":"slice-of-life"},{"label":"Smut","value":"smut"},{"label":"Soft Yaoi","value":"soft-yaoi"},{"label":"Soft Yuri","value":"soft-yuri"},{"label":"Sports","value":"sports"},{"label":"Supernatural","value":"supernatural"},{"label":"Tragedy","value":"tragedy"},{"label":"Video Games","value":"video-games"},{"label":"Webtoon","value":"webtoon"},{"label":"Wuxia","value":"wuxia"},{"label":"Xianxia","value":"xianxia"},{"label":"Xuanhuan","value":"xuanhuan"},{"label":"Yaoi","value":"yaoi"},{"label":"Yuri","value":"yuri"}],"inputType":FilterInputs.Picker}];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"zinnovel","sourceSite":"https://zinnovel.com/","sourceName":"ZinnNovel","filters":[{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":"Picker"},{"key":"genres","label":"GENRES","values":[{"label":"Action","value":"action"},{"label":"Adult","value":"adult"},{"label":"Adventure","value":"adventure"},{"label":"Anime","value":"anime"},{"label":"Cartoon","value":"cartoon"},{"label":"Comedy","value":"comedy"},{"label":"Comic","value":"comic"},{"label":"Cooking","value":"cooking"},{"label":"Detective","value":"detective"},{"label":"Doujinshi","value":"doujinshi"},{"label":"Drama","value":"drama"},{"label":"Ecchi","value":"ecchi"},{"label":"Fantasy","value":"fantasy"},{"label":"Game","value":"game"},{"label":"Gender Bender","value":"gender-bender"},{"label":"Harem","value":"harem"},{"label":"Historical","value":"historical"},{"label":"Horror","value":"horror"},{"label":"Isekai","value":"isekai"},{"label":"Josei","value":"josei"},{"label":"Live action","value":"live-action"},{"label":"Lolicon","value":"lolicon"},{"label":"Magical Realism","value":"magical-realism"},{"label":"Manga","value":"manga"},{"label":"Manhua","value":"manhua"},{"label":"Manhwa","value":"manhwa"},{"label":"Martial Arts","value":"martial-arts"},{"label":"Mature","value":"mature"},{"label":"Mecha","value":"mecha"},{"label":"Mystery","value":"mystery"},{"label":"One shot","value":"one-shot"},{"label":"Psychological","value":"psychological"},{"label":"Reincarnation","value":"reincarnation"},{"label":"Romance","value":"romance"},{"label":"School Life","value":"school-life"},{"label":"Sci-fi","value":"sci-fi"},{"label":"Seinen","value":"seinen"},{"label":"Shoujo","value":"shoujo"},{"label":"Shoujo Ai","value":"shoujo-ai"},{"label":"Shounen","value":"shounen"},{"label":"Shounen Ai","value":"shounen-ai"},{"label":"Slice of Life","value":"slice-of-life"},{"label":"Smut","value":"smut"},{"label":"Soft Yaoi","value":"soft-yaoi"},{"label":"Soft Yuri","value":"soft-yuri"},{"label":"Sports","value":"sports"},{"label":"Supernatural","value":"supernatural"},{"label":"Tragedy","value":"tragedy"},{"label":"Video Games","value":"video-games"},{"label":"Webtoon","value":"webtoon"},{"label":"Wuxia","value":"wuxia"},{"label":"Xianxia","value":"xianxia"},{"label":"Xuanhuan","value":"xuanhuan"},{"label":"Yaoi","value":"yaoi"},{"label":"Yuri","value":"yuri"}],"inputType":"Picker"}],"options":{"path":{"novels":"manga","novel":"manga","chapter":"manga","genres":"manga-genre"},"lang":"English"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/english/allnovelfull.ts b/plugins/english/allnovelfull.broken.ts
similarity index 100%
rename from plugins/english/allnovelfull.ts
rename to plugins/english/allnovelfull.broken.ts
diff --git a/plugins/english/bestlightnovel.ts b/plugins/english/bestlightnovel.ts
index ae3aa29..ec41219 100644
--- a/plugins/english/bestlightnovel.ts
+++ b/plugins/english/bestlightnovel.ts
@@ -1,59 +1,60 @@
import { load as cheerioload } from "cheerio";
-import { Chapter, Novel, Plugin } from "@typings/plugin";
+import { Plugin } from "@typings/plugin";
import { defaultCover } from "@libs/defaultCover";
-import { fetchApi, fetchFile } from "@libs/fetch";
+import { fetchFile } from "@libs/fetch";
import { NovelStatus } from "@libs/novelStatus";
+import { Filter } from "@libs/filterInputs";
-export const id = "BLN.com";
-export const name = "BestLightNovel";
-export const site = "https://bestlightnovel.com/";
-export const version = "1.0.0";
-export const icon = "src/en/bestlightnovel/icon.png";
+class BLN implements Plugin.PluginBase {
+ id = "BLN.com";
+ name = "BestLightNovel";
+ icon = "src/en/bestlightnovel/icon.png";
+ site = "https://bestlightnovel.com/";
+ filter?: Filter[] | undefined;
+ version = "1.0.0";
+ userAgent = "";
+ cookieString = "";
+ async popularNovels(pageNo: number, options: Plugin.PopularNovelsOptions): Promise {
+ const url = this.site + "novel_list?type=topview&category=all&state=all&page=1" + pageNo;
-export const popularNovels: Plugin.popularNovels = async function (page) {
- const url =
- site + "novel_list?type=topview&category=all&state=all&page=1" + page;
-
- const result = await fetchApi(url);
- if (!result.ok) {
- console.error(await result.text());
- // TODO: Cloudflare protection or other error
- return [];
- }
- const body = await result.text();
-
- const loadedCheerio = cheerioload(body);
-
- let novels: Novel.Item[] = [];
-
- loadedCheerio(".update_item.list_category").each(function () {
- const novelName = loadedCheerio(this).find("h3 > a").text();
- const novelCover = loadedCheerio(this).find("img").attr("src");
- const novelUrl = loadedCheerio(this).find("h3 > a").attr("href");
-
- if (!novelUrl) {
- // TODO: Handle error
- console.error("No novel url!");
- return;
+ const result = await fetch(url);
+ if (!result.ok) {
+ console.error(await result.text());
+ // TODO: Cloudflare protection or other error
+ return [];
}
+ const body = await result.text();
- const novel = {
- name: novelName,
- url: novelUrl,
- cover: novelCover,
- };
+ const loadedCheerio = cheerioload(body);
- novels.push(novel);
- });
+ let novels: Plugin.NovelItem[] = [];
- return novels;
-};
+ loadedCheerio(".update_item.list_category").each(function () {
+ const novelName = loadedCheerio(this).find("h3 > a").text();
+ const novelCover = loadedCheerio(this).find("img").attr("src");
+ const novelUrl = loadedCheerio(this).find("h3 > a").attr("href");
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters =
- async function (novelUrl) {
+ if (!novelUrl) {
+ // TODO: Handle error
+ console.error("No novel url!");
+ return;
+ }
+
+ const novel = {
+ name: novelName,
+ url: novelUrl,
+ cover: novelCover,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
const url = novelUrl;
- const result = await fetchApi(url);
+ const result = await fetch(url);
if (!result.ok) {
console.error(await result.text());
// TODO: Cloudflare protection
@@ -63,7 +64,7 @@ export const parseNovelAndChapters: Plugin.parseNovelAndChapters =
let loadedCheerio = cheerioload(body);
- let novel: Novel.instance = {
+ let novel: Plugin.SourceNovel = {
url,
name: "",
cover: "",
@@ -97,7 +98,7 @@ export const parseNovelAndChapters: Plugin.parseNovelAndChapters =
? NovelStatus.Completed
: NovelStatus.Unknown;
- let novelChapters: Chapter.Item[] = [];
+ let novelChapters: Plugin.ChapterItem[] = [];
loadedCheerio(".chapter-list div.row").each(function () {
const chapterName = loadedCheerio(this).find("a").text().trim();
@@ -123,50 +124,51 @@ export const parseNovelAndChapters: Plugin.parseNovelAndChapters =
novel.chapters = novelChapters.reverse();
return novel;
- };
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const url = chapterUrl;
-export const parseChapter: Plugin.parseChapter = async function (chapterUrl) {
- const url = chapterUrl;
+ const result = await fetch(url);
+ const body = await result.text();
- const result = await fetchApi(url);
- const body = await result.text();
+ let loadedCheerio = cheerioload(body);
- let loadedCheerio = cheerioload(body);
+ const chapterText = loadedCheerio("#vung_doc").html() || "";
- const chapterText = loadedCheerio("#vung_doc").html();
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const url = `${this.site}search_novels/${searchTerm}`;
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async function (searchTerm) {
- const url = `${site}search_novels/${searchTerm}`;
-
- const result = await fetchApi(url);
- const body = await result.text();
-
- let loadedCheerio = cheerioload(body);
-
- let novels: Novel.Item[] = [];
-
- loadedCheerio(".update_item.list_category").each(function () {
- const novelName = loadedCheerio(this).find("h3 > a").text();
- const novelCover = loadedCheerio(this).find("img").attr("src");
- const novelUrl = loadedCheerio(this).find("h3 > a").attr("href");
-
- if (!novelUrl) {
- // TODO: Handle error
- console.error("No novel url!");
- return;
- }
-
- const novel = { name: novelName, cover: novelCover, url: novelUrl };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = (...args) => fetchFile(...args);
+ const result = await fetch(url);
+ const body = await result.text();
+
+ let loadedCheerio = cheerioload(body);
+
+ let novels: Plugin.NovelItem[] = [];
+
+ loadedCheerio(".update_item.list_category").each(function () {
+ const novelName = loadedCheerio(this).find("h3 > a").text();
+ const novelCover = loadedCheerio(this).find("img").attr("src");
+ const novelUrl = loadedCheerio(this).find("h3 > a").attr("href");
+
+ if (!novelUrl) {
+ // TODO: Handle error
+ console.error("No novel url!");
+ return;
+ }
+
+ const novel = { name: novelName, cover: novelCover, url: novelUrl };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url);
+ }
+}
+export default new BLN();
diff --git a/plugins/english/comrademao.ts b/plugins/english/comrademao.broken.ts
similarity index 100%
rename from plugins/english/comrademao.ts
rename to plugins/english/comrademao.broken.ts
diff --git a/plugins/english/divinedaolibrary.ts b/plugins/english/divinedaolibrary.broken.ts
similarity index 100%
rename from plugins/english/divinedaolibrary.ts
rename to plugins/english/divinedaolibrary.broken.ts
diff --git a/plugins/english/earlynovel.ts b/plugins/english/earlynovel.broken.ts
similarity index 100%
rename from plugins/english/earlynovel.ts
rename to plugins/english/earlynovel.broken.ts
diff --git a/plugins/english/fastnovel.ts b/plugins/english/fastnovel.broken.ts
similarity index 100%
rename from plugins/english/fastnovel.ts
rename to plugins/english/fastnovel.broken.ts
diff --git a/plugins/english/foxaholic.ts b/plugins/english/foxaholic.broken.ts
similarity index 100%
rename from plugins/english/foxaholic.ts
rename to plugins/english/foxaholic.broken.ts
diff --git a/plugins/english/freenovelupdates.ts b/plugins/english/freenovelupdates.broken.ts
similarity index 100%
rename from plugins/english/freenovelupdates.ts
rename to plugins/english/freenovelupdates.broken.ts
diff --git a/plugins/english/freewebnovel.ts b/plugins/english/freewebnovel.broken.ts
similarity index 100%
rename from plugins/english/freewebnovel.ts
rename to plugins/english/freewebnovel.broken.ts
diff --git a/plugins/english/lightnovelpub.ts b/plugins/english/lightnovelpub.broken.ts
similarity index 100%
rename from plugins/english/lightnovelpub.ts
rename to plugins/english/lightnovelpub.broken.ts
diff --git a/plugins/english/mtlreader.ts b/plugins/english/mtlreader.broken.ts
similarity index 100%
rename from plugins/english/mtlreader.ts
rename to plugins/english/mtlreader.broken.ts
diff --git a/plugins/english/nitroscans.ts b/plugins/english/nitroscans.broken.ts
similarity index 100%
rename from plugins/english/nitroscans.ts
rename to plugins/english/nitroscans.broken.ts
diff --git a/plugins/english/nobleMTL.ts b/plugins/english/nobleMTL.ts
index a370f79..b2eac9f 100644
--- a/plugins/english/nobleMTL.ts
+++ b/plugins/english/nobleMTL.ts
@@ -1,72 +1,76 @@
-import { load as cheerioload } from "cheerio";
+import { load as parseHTML } from "cheerio";
import { fetchApi, fetchFile } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
import { Filter, FilterInputs } from "@libs/filterInputs";
+import { Plugin } from "@typings/plugin";
-export const id = "NobleMTL";
-export const name = "NobleMTL";
-export const version = "1.0.0";
-export const icon = "src/en/noblemtl/icon.png";
-export const site = "https://www.noblemtl.com/";
+class NobleMTL implements Plugin.PluginBase {
+ id = "noblemtl";
+ name = "NobleMTL";
+ icon = "src/en/noblemtl/icon.png";
+ site = "https://noblemtl.com/";
+ version = "1.0.0";
+ userAgent = "";
+ cookieString = "";
+ async popularNovels(pageNo: number, {filters}: Plugin.PopularNovelsOptions): Promise {
+ let link = `${this.site}series/?page=${pageNo}`;
+ if (filters) {
+ if (Array.isArray(filters.genres) && filters.genres.length) {
+ link += filters.genres.map((i) => `&genre[]=${i}`).join("");
+ }
-export const popularNovels: Plugin.popularNovels = async function (
- page,
- { filters }
-) {
- let link = `${site}series/?page=${page}`;
+ if (Array.isArray(filters.type) && filters.type.length)
+ link += filters.type.map((i) => `&lang[]=${i}`).join("");
+ }
+ link += "&status=" + (filters?.status ? filters.status : "");
- if (filters?.genres?.length) {
- if (Array.isArray(filters.genres))
- link += filters.genres.map((i) => `&genre[]=${i}`).join("");
- }
+ link += "&order=" + (filters?.order ? filters.order : "popular");
- if (filters?.type?.length) {
- if (Array.isArray(filters.type))
- link += filters.type.map((i) => `&lang[]=${i}`).join("");
- }
+ const headers = new Headers();
+ if(this.cookieString){
+ headers.append("cookie", this.cookieString);
+ }
+ const body = await fetchApi(link, {headers}).then((result) =>
+ result.text()
+ );
- link += "&status=" + (filters?.status ? filters?.status : "");
+ const loadedCheerio = parseHTML(body);
- link += "&order=" + (filters?.order ? filters?.order : "popular");
+ const novels: Plugin.NovelItem[] = [];
- const body = await fetchApi(link).then((result) => result.text());
+ loadedCheerio("article.bs").each(function () {
+ const novelName = loadedCheerio(this).find(".ntitle").text().trim();
+ let image = loadedCheerio(this).find("img");
+ const novelCover = image.attr("data-src") || image.attr("src");
- const loadedCheerio = cheerioload(body);
+ const novelUrl = loadedCheerio(this).find("a").attr("href");
- const novels: Novel.Item[] = [];
+ if (!novelUrl) return;
- loadedCheerio("article.bs").each(function () {
- const novelName = loadedCheerio(this).find(".ntitle").text().trim();
- let image = loadedCheerio(this).find("img");
- const novelCover = image.attr("data-src") || image.attr("src");
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
- const novelUrl = loadedCheerio(this).find("a").attr("href");
+ novels.push(novel);
+ });
- if (!novelUrl) return;
+ return novels;
+ };
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters =
- async function parseNovelAndChapters(novelUrl) {
+ async parseNovelAndChapters(novelUrl: string): Promise {
const url = novelUrl;
-
- const result = await fetchApi(url);
+ const headers = new Headers();
+ if(this.cookieString){
+ headers.append("cookie", this.cookieString);
+ }
+ const result = await fetchApi(url, {headers});
const body = await result.text();
- let loadedCheerio = cheerioload(body);
+ let loadedCheerio = parseHTML(body);
- const novel: Novel.instance = {
+ const novel: Plugin.SourceNovel = {
url,
chapters: [],
};
@@ -79,22 +83,13 @@ export const parseNovelAndChapters: Plugin.parseNovelAndChapters =
loadedCheerio("div.spe > span").each(function () {
const detailName = loadedCheerio(this).find("b").text().trim();
- const detail = loadedCheerio(this)
- .find("b")
- .remove()
- .end()
- .text()
- .trim();
+ const detail = loadedCheerio(this).find('b').remove().end().text().trim();
switch (detailName) {
- case "المؤلف:":
- case "Yazar:":
- case "Autor:":
case "Author:":
novel.author = detail;
break;
case "Status:":
- case "Seviye:":
novel.status = detail;
break;
}
@@ -112,7 +107,7 @@ export const parseNovelAndChapters: Plugin.parseNovelAndChapters =
.end()
.text();
- let chapter: Chapter.Item[] = [];
+ let chapter: Plugin.ChapterItem[] = [];
loadedCheerio(".eplister")
.find("li")
@@ -141,276 +136,282 @@ export const parseNovelAndChapters: Plugin.parseNovelAndChapters =
novel.chapters = chapter.reverse();
return novel;
- };
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const headers = new Headers();
+ if(this.cookieString){
+ headers.append("cookie", this.cookieString);
+ }
+ const result = await fetchApi(chapterUrl, {headers});
+ const body = await result.text();
-export const parseChapter: Plugin.parseChapter = async function (chapterUrl) {
- const result = await fetchApi(chapterUrl);
- const body = await result.text();
+ const loadedCheerio = parseHTML(body);
- const loadedCheerio = cheerioload(body);
+ let chapterText = loadedCheerio(".epcontent").html() || "";
- let chapterText = loadedCheerio("div.epcontent").html();
+ return chapterText;
+ }
- return chapterText;
-};
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const url = `${this.site}?s=${searchTerm}`;
+ const headers = new Headers();
+ if(this.cookieString){
+ headers.append("cookie", this.cookieString);
+ }
+ const result = await fetchApi(url, {headers});
+ const body = await result.text();
-export const searchNovels: Plugin.searchNovels = async function (searchTerm) {
- const url = `${site}?s=${searchTerm}`;
+ const loadedCheerio = parseHTML(body);
- const result = await fetchApi(url);
- const body = await result.text();
+ const novels: Plugin.NovelItem[] = [];
- const loadedCheerio = cheerioload(body);
+ loadedCheerio("article.bs").each(function () {
+ const novelName = loadedCheerio(this).find(".ntitle").text().trim();
+ const novelCover = loadedCheerio(this).find("img").attr("src");
+ const novelUrl = loadedCheerio(this).find("a").attr("href");
+ if (!novelUrl) return;
- const novels: Novel.Item[] = [];
-
- loadedCheerio("article.bs").each(function () {
- const novelName = loadedCheerio(this).find(".ntitle").text().trim();
- const novelCover = loadedCheerio(this).find("img").attr("src");
- const novelUrl = loadedCheerio(this).find("a").attr("href");
- if (!novelUrl) return;
-
- novels.push({
- name: novelName,
- url: novelUrl,
- cover: novelCover,
+ novels.push({
+ name: novelName,
+ url: novelUrl,
+ cover: novelCover,
+ });
});
- });
- return novels;
-};
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url);
+ }
-export const fetchImage: Plugin.fetchImage = async function (url) {
- const headers = {
- Referer: site,
- };
- return await fetchFile(url, { headers: headers });
-};
-export const filters: Filter[] = [
- {
- key: "order",
- label: "Sort By",
- values: [
- { label: "Default", value: "" },
+ filters = [
+ {
+ key: "order",
+ label: "Sort By",
+ values: [
+ { label: "Default", value: "" },
- { label: "A-Z", value: "title" },
+ { label: "A-Z", value: "title" },
- { label: "Z-A", value: "titlereverse" },
+ { label: "Z-A", value: "titlereverse" },
- { label: "Latest Update", value: "update" },
+ { label: "Latest Update", value: "update" },
- { label: "Latest Added", value: "latest" },
+ { label: "Latest Added", value: "latest" },
- { label: "Popular", value: "popular" },
- ],
- inputType: FilterInputs.Picker,
- },
- {
- key: "status",
- label: "Status",
- values: [
- { label: "All", value: "" },
+ { label: "Popular", value: "popular" },
+ ],
+ inputType: FilterInputs.Picker,
+ },
+ {
+ key: "status",
+ label: "Status",
+ values: [
+ { label: "All", value: "" },
- { label: "Ongoing", value: "ongoing" },
+ { label: "Ongoing", value: "ongoing" },
- { label: "Hiatus", value: "hiatus" },
+ { label: "Hiatus", value: "hiatus" },
- { label: "Completed", value: "completed" },
- ],
- inputType: FilterInputs.Picker,
- },
- {
- key: "type",
- label: "Type",
- values: [
- { label: "Chinese novel", value: "chinese-novel" },
+ { label: "Completed", value: "completed" },
+ ],
+ inputType: FilterInputs.Picker,
+ },
+ {
+ key: "type",
+ label: "Type",
+ values: [
+ { label: "Chinese novel", value: "chinese-novel" },
- { label: "habyeol", value: "habyeol" },
+ { label: "habyeol", value: "habyeol" },
- { label: "korean novel", value: "korean-novel" },
+ { label: "korean novel", value: "korean-novel" },
- { label: "Web Novel", value: "web-novel" },
+ { label: "Web Novel", value: "web-novel" },
- { label: "삼심", value: "%ec%82%bc%ec%8b%ac" },
+ { label: "삼심", value: "%ec%82%bc%ec%8b%ac" },
- { label: "호곡", value: "%ed%98%b8%ea%b3%a1" },
- ],
- inputType: FilterInputs.Checkbox,
- },
- {
- key: "genres",
- label: "Genres",
- values: [
- { label: "A.I", value: "a.i" },
+ { label: "호곡", value: "%ed%98%b8%ea%b3%a1" },
+ ],
+ inputType: FilterInputs.Checkbox,
+ },
+ {
+ key: "genres",
+ label: "Genres",
+ values: [
+ { label: "A.I", value: "a.i" },
- { label: "Academy", value: "academy" },
+ { label: "Academy", value: "academy" },
- { label: "Action", value: "action" },
+ { label: "Action", value: "action" },
- { label: "Adult", value: "adult" },
+ { label: "Adult", value: "adult" },
- { label: "Adventure", value: "adventure" },
+ { label: "Adventure", value: "adventure" },
- { label: "Alternative History", value: "alternative-history" },
+ { label: "Alternative History", value: "alternative-history" },
- { label: "Another World", value: "another-world" },
+ { label: "Another World", value: "another-world" },
- { label: "Apocalypse", value: "apocalypse" },
+ { label: "Apocalypse", value: "apocalypse" },
- { label: "Bromance", value: "bromance" },
+ { label: "Bromance", value: "bromance" },
- { label: "Comedy", value: "comedy" },
+ { label: "Comedy", value: "comedy" },
- { label: "Dark fantasy", value: "dark-fantasy" },
+ { label: "Dark fantasy", value: "dark-fantasy" },
- { label: "Demons", value: "demons" },
+ { label: "Demons", value: "demons" },
- { label: "Drama", value: "drama" },
+ { label: "Drama", value: "drama" },
- { label: "Dystopia", value: "dystopia" },
+ { label: "Dystopia", value: "dystopia" },
- { label: "Ecchi", value: "ecchi" },
+ { label: "Ecchi", value: "ecchi" },
- { label: "Entertainment", value: "entertainment" },
+ { label: "Entertainment", value: "entertainment" },
- { label: "Exhaustion", value: "exhaustion" },
+ { label: "Exhaustion", value: "exhaustion" },
- { label: "Fanfiction", value: "fanfiction" },
+ { label: "Fanfiction", value: "fanfiction" },
- { label: "fantasy", value: "fantasy" },
+ { label: "fantasy", value: "fantasy" },
- { label: "finance", value: "finance" },
+ { label: "finance", value: "finance" },
- { label: "Full color", value: "full-color" },
+ { label: "Full color", value: "full-color" },
- { label: "Game", value: "game" },
+ { label: "Game", value: "game" },
- { label: "Gender Bender", value: "gender-bender" },
+ { label: "Gender Bender", value: "gender-bender" },
- { label: "Genius", value: "genius" },
+ { label: "Genius", value: "genius" },
- { label: "Harem", value: "harem" },
+ { label: "Harem", value: "harem" },
- { label: "Hero", value: "hero" },
+ { label: "Hero", value: "hero" },
- { label: "Historical", value: "historical" },
+ { label: "Historical", value: "historical" },
- { label: "Hunter", value: "hunter" },
+ { label: "Hunter", value: "hunter" },
- { label: "korean novel", value: "korean-novel" },
+ { label: "korean novel", value: "korean-novel" },
- { label: "Light Novel", value: "light-novel" },
+ { label: "Light Novel", value: "light-novel" },
- {
- label: "List Adventure Manga Genres",
- value: "list-adventure-manga-genres",
- },
+ {
+ label: "List Adventure Manga Genres",
+ value: "list-adventure-manga-genres",
+ },
- { label: "Long Strip", value: "long-strip" },
+ { label: "Long Strip", value: "long-strip" },
- { label: "Love comedy", value: "love-comedy" },
+ { label: "Love comedy", value: "love-comedy" },
- { label: "magic", value: "magic" },
+ { label: "magic", value: "magic" },
- { label: "Manhua", value: "manhua" },
+ { label: "Manhua", value: "manhua" },
- { label: "Martial Arts", value: "martial-arts" },
+ { label: "Martial Arts", value: "martial-arts" },
- { label: "Mature", value: "mature" },
+ { label: "Mature", value: "mature" },
- { label: "Medieval", value: "medieval" },
+ { label: "Medieval", value: "medieval" },
- { label: "Misunderstanding", value: "misunderstanding" },
+ { label: "Misunderstanding", value: "misunderstanding" },
- { label: "Modern", value: "modern" },
+ { label: "Modern", value: "modern" },
- { label: "modern fantasy", value: "modern-fantasy" },
+ { label: "modern fantasy", value: "modern-fantasy" },
- { label: "music", value: "music" },
+ { label: "music", value: "music" },
- { label: "Mystery", value: "mystery" },
+ { label: "Mystery", value: "mystery" },
- { label: "Necromancy", value: "necromancy" },
+ { label: "Necromancy", value: "necromancy" },
- { label: "No Romance", value: "no-romance" },
+ { label: "No Romance", value: "no-romance" },
- { label: "NTL", value: "ntl" },
+ { label: "NTL", value: "ntl" },
- { label: "o", value: "o" },
+ { label: "o", value: "o" },
- { label: "Obsession", value: "obsession" },
+ { label: "Obsession", value: "obsession" },
- { label: "Politics", value: "politics" },
+ { label: "Politics", value: "politics" },
- { label: "Possession", value: "possession" },
+ { label: "Possession", value: "possession" },
- { label: "Programming", value: "programming" },
+ { label: "Programming", value: "programming" },
- { label: "Psychological", value: "psychological" },
+ { label: "Psychological", value: "psychological" },
- { label: "Pure Love", value: "pure-love" },
+ { label: "Pure Love", value: "pure-love" },
- { label: "Redemption", value: "redemption" },
+ { label: "Redemption", value: "redemption" },
- { label: "Regression", value: "regression" },
+ { label: "Regression", value: "regression" },
- { label: "Regret", value: "regret" },
+ { label: "Regret", value: "regret" },
- { label: "Reincarnation", value: "reincarnation" },
+ { label: "Reincarnation", value: "reincarnation" },
- { label: "Revenge", value: "revenge" },
+ { label: "Revenge", value: "revenge" },
- { label: "Romance", value: "romance" },
+ { label: "Romance", value: "romance" },
- { label: "Romance Fanrasy", value: "romance-fanrasy" },
+ { label: "Romance Fanrasy", value: "romance-fanrasy" },
- { label: "Salvation", value: "salvation" },
+ { label: "Salvation", value: "salvation" },
- { label: "School Life", value: "school-life" },
+ { label: "School Life", value: "school-life" },
- { label: "Sci-fi", value: "sci-fi" },
+ { label: "Sci-fi", value: "sci-fi" },
- { label: "Science fiction", value: "science-fiction" },
+ { label: "Science fiction", value: "science-fiction" },
- { label: "Seinen", value: "seinen" },
+ { label: "Seinen", value: "seinen" },
- { label: "Shounen", value: "shounen" },
+ { label: "Shounen", value: "shounen" },
- { label: "Slice of Life", value: "slice-of-life" },
+ { label: "Slice of Life", value: "slice-of-life" },
- { label: "Soft yandere", value: "soft-yandere" },
+ { label: "Soft yandere", value: "soft-yandere" },
- { label: "Sports", value: "sports" },
+ { label: "Sports", value: "sports" },
- { label: "Supernatural", value: "supernatural" },
+ { label: "Supernatural", value: "supernatural" },
- { label: "Survival", value: "survival" },
+ { label: "Survival", value: "survival" },
- { label: "system", value: "system" },
+ { label: "system", value: "system" },
- { label: "Time limit", value: "time-limit" },
+ { label: "Time limit", value: "time-limit" },
- { label: "Tragedy", value: "tragedy" },
+ { label: "Tragedy", value: "tragedy" },
- { label: "Transmigration", value: "transmigration" },
+ { label: "Transmigration", value: "transmigration" },
- { label: "TS", value: "ts" },
+ { label: "TS", value: "ts" },
- { label: "Tsundere", value: "tsundere" },
+ { label: "Tsundere", value: "tsundere" },
- { label: "Unique", value: "unique" },
+ { label: "Unique", value: "unique" },
- { label: "Wholesome", value: "wholesome" },
+ { label: "Wholesome", value: "wholesome" },
- { label: "Wuxia", value: "wuxia" },
+ { label: "Wuxia", value: "wuxia" },
- { label: "Xuanhuan", value: "xuanhuan" },
+ { label: "Xuanhuan", value: "xuanhuan" },
- { label: "Yandere", value: "yandere" },
+ { label: "Yandere", value: "yandere" },
- { label: "Yuri", value: "yuri" },
- ],
- inputType: FilterInputs.Checkbox,
- },
-];
+ { label: "Yuri", value: "yuri" },
+ ],
+ inputType: FilterInputs.Checkbox,
+ },
+ ];
+}
+
+export default new NobleMTL();
\ No newline at end of file
diff --git a/plugins/english/novelforest.ts b/plugins/english/novelforest.broken.ts
similarity index 100%
rename from plugins/english/novelforest.ts
rename to plugins/english/novelforest.broken.ts
diff --git a/plugins/english/novelfull.ts b/plugins/english/novelfull.broken.ts
similarity index 100%
rename from plugins/english/novelfull.ts
rename to plugins/english/novelfull.broken.ts
diff --git a/plugins/english/novelhold.ts b/plugins/english/novelhold.broken.ts
similarity index 100%
rename from plugins/english/novelhold.ts
rename to plugins/english/novelhold.broken.ts
diff --git a/plugins/english/novelpub.ts b/plugins/english/novelpub.broken.ts
similarity index 100%
rename from plugins/english/novelpub.ts
rename to plugins/english/novelpub.broken.ts
diff --git a/plugins/english/pandaMTL.ts b/plugins/english/pandaMTL.ts
index 4057bfc..06f8282 100644
--- a/plugins/english/pandaMTL.ts
+++ b/plugins/english/pandaMTL.ts
@@ -1,76 +1,74 @@
import { load as parseHTML } from "cheerio";
import { fetchApi, fetchFile } from "@libs/fetch";
-import { FilterInputs } from "@libs/filterInputs";
-import { Chapter, Novel, Plugin } from "@typings/plugin";
+import { Filter, FilterInputs } from "@libs/filterInputs";
+import { Plugin } from "@typings/plugin";
-export const id = "PandaMTL";
-export const name = "PandaMTL";
-export const version = "1.0.0";
-export const icon = "src/en/wordpress/icon.png";
-export const site = "https://www.pandamtl.com/";
+class PandaMTL implements Plugin.PluginBase {
+ id = "pandamtl";
+ name = "PandaMTL";
+ icon = "src/en/wordpress/icon.png";
+ site = "https://pandamtl.com/";
+ version = "1.0.0";
+ userAgent = "";
+ cookieString = "";
+ async popularNovels(pageNo: number, {filters}: Plugin.PopularNovelsOptions): Promise {
+ let link = `${this.site}series/?page=${pageNo}`;
+ if (filters) {
+ if (Array.isArray(filters.genres) && filters.genres.length) {
+ link += filters.genres.map((i) => `&genre[]=${i}`).join("");
+ }
-const pluginId = id;
-const baseUrl = site;
-
-export const popularNovels: Plugin.popularNovels = async function (
- page,
- { filters }
-) {
- let link = `${baseUrl}series/?page=${page}`;
-
- if (filters) {
- if (Array.isArray(filters.genres) && filters.genres.length) {
- link += filters.genres.map((i) => `&genre[]=${i}`).join("");
+ if (Array.isArray(filters.type) && filters.type.length)
+ link += filters.type.map((i) => `&lang[]=${i}`).join("");
}
+ link += "&status=" + (filters?.status ? filters.status : "");
- if (Array.isArray(filters.type) && filters.type.length) {
- link += filters.type.map((i) => `&lang[]=${i}`).join("");
+ link += "&order=" + (filters?.order ? filters.order : "popular");
+
+ const headers = new Headers();
+ if(this.cookieString){
+ headers.append("cookie", this.cookieString);
}
+ const body = await fetchApi(link, {headers}).then((result) =>
+ result.text()
+ );
+
+ const loadedCheerio = parseHTML(body);
+
+ const novels: Plugin.NovelItem[] = [];
+
+ loadedCheerio("article.maindet").each(function () {
+ const novelName = loadedCheerio(this).find("h2").text();
+ let image = loadedCheerio(this).find("img");
+ const novelCover = image.attr("data-src") || image.attr("src");
+ const novelUrl = loadedCheerio(this).find("h2 a").attr("href");
+
+ if (!novelUrl) return;
+
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
}
-
- link += "&status=" + (filters?.status ? filters?.status : "");
-
- link += "&order=" + (filters?.order ? filters?.order : "popular");
-
- const body = await fetchApi(link, {}, pluginId).then((result) =>
- result.text()
- );
-
- const loadedCheerio = parseHTML(body);
-
- const novels: Novel.Item[] = [];
-
- loadedCheerio("article.maindet").each(function () {
- const novelName = loadedCheerio(this).find("h2").text();
- let image = loadedCheerio(this).find("img");
- const novelCover = image.attr("data-src") || image.attr("src");
- const novelUrl = loadedCheerio(this).find("h2 a").attr("href");
-
- if (!novelUrl) return;
-
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters =
- async function (novelUrl) {
+ async parseNovelAndChapters(novelUrl: string): Promise {
const url = novelUrl;
-
- const result = await fetchApi(url, {}, pluginId);
+ const headers = new Headers();
+ if(this.cookieString){
+ headers.append("cookie", this.cookieString);
+ }
+ const result = await fetchApi(url, {headers});
const body = await result.text();
let loadedCheerio = parseHTML(body);
- const novel: Novel.instance = {
+ const novel: Plugin.SourceNovel = {
url,
chapters: [],
};
@@ -81,19 +79,18 @@ export const parseNovelAndChapters: Plugin.parseNovelAndChapters =
loadedCheerio("img.wp-post-image").attr("data-src") ||
loadedCheerio("img.wp-post-image").attr("src");
- loadedCheerio("div.serl:nth-child(3) > span").each(function () {
+ loadedCheerio(".serl:nth-child(3) > span").each(function () {
const detailName = loadedCheerio(this).text().trim();
const detail = loadedCheerio(this).next().text().trim();
switch (detailName) {
- case "الكاتب":
case "Author":
novel.author = detail;
break;
}
});
- novel.status = loadedCheerio("div.sertostat > span").attr("class");
+ novel.status = loadedCheerio(".sertostat > span").attr("class");
novel.genres = loadedCheerio(".sertogenre")
.children("a")
@@ -107,7 +104,7 @@ export const parseNovelAndChapters: Plugin.parseNovelAndChapters =
.end()
.text();
- let chapter: Chapter.Item[] = [];
+ let chapter: Plugin.ChapterItem[] = [];
loadedCheerio(".eplister")
.find("li")
@@ -136,139 +133,144 @@ export const parseNovelAndChapters: Plugin.parseNovelAndChapters =
novel.chapters = chapter.reverse();
return novel;
- };
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const headers = new Headers();
+ if(this.cookieString){
+ headers.append("cookie", this.cookieString);
+ }
+ const result = await fetchApi(chapterUrl, {headers});
+ const body = await result.text();
-export const parseChapter: Plugin.parseChapter = async function (chapterUrl) {
- const result = await fetchApi(chapterUrl, {}, pluginId);
- const body = await result.text();
+ const loadedCheerio = parseHTML(body);
- const loadedCheerio = parseHTML(body);
+ let chapterText = loadedCheerio(".epcontent").html() || "";
- let chapterText = loadedCheerio(".epcontent").html();
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const url = `${this.site}?s=${searchTerm}`;
+ const headers = new Headers();
+ if(this.cookieString){
+ headers.append("cookie", this.cookieString);
+ }
+ const result = await fetchApi(url, {headers});
+ const body = await result.text();
- return chapterText;
-};
+ const loadedCheerio = parseHTML(body);
-export const searchNovels: Plugin.searchNovels = async function (searchTerm) {
- const url = `${baseUrl}?s=${searchTerm}`;
+ const novels: Plugin.NovelItem[] = [];
- const result = await fetchApi(url, {}, pluginId);
- const body = await result.text();
+ loadedCheerio("article.maindet").each(function () {
+ const novelName = loadedCheerio(this).find("h2").text();
+ let image = loadedCheerio(this).find("img");
+ const novelCover = image.attr("data-src") || image.attr("src");
+ const novelUrl = loadedCheerio(this).find("h2 a").attr("href");
- const loadedCheerio = parseHTML(body);
+ if (!novelUrl) return;
- const novels: Novel.Item[] = [];
-
- loadedCheerio("article.maindet").each(function () {
- const novelName = loadedCheerio(this).find("h2").text();
- let image = loadedCheerio(this).find("img");
- const novelCover = image.attr("data-src") || image.attr("src");
- const novelUrl = loadedCheerio(this).find("h2 a").attr("href");
-
- if (!novelUrl) return;
-
- novels.push({
- name: novelName,
- url: novelUrl,
- cover: novelCover,
+ novels.push({
+ name: novelName,
+ url: novelUrl,
+ cover: novelCover,
+ });
});
- });
- return novels;
-};
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url);
+ }
-export const fetchImage: Plugin.fetchImage = async function (url) {
- const headers = {
- Referer: baseUrl,
- };
- return await fetchFile(url, { headers: headers });
-};
-export const filters = [
- {
- key: "order",
- label: "Sort By",
- values: [
- { label: "Default", value: "" },
+ filters = [
+ {
+ key: "order",
+ label: "Sort By",
+ values: [
+ { label: "Default", value: "" },
- { label: "A-Z", value: "title" },
+ { label: "A-Z", value: "title" },
- { label: "Z-A", value: "titlereverse" },
+ { label: "Z-A", value: "titlereverse" },
- { label: "Latest Update", value: "update" },
+ { label: "Latest Update", value: "update" },
- { label: "Latest Added", value: "latest" },
+ { label: "Latest Added", value: "latest" },
- { label: "Popular", value: "popular" },
- ],
- inputType: FilterInputs.Picker,
- },
- {
- key: "status",
- label: "Status",
- values: [
- { label: "All", value: "" },
+ { label: "Popular", value: "popular" },
+ ],
+ inputType: FilterInputs.Picker,
+ },
+ {
+ key: "status",
+ label: "Status",
+ values: [
+ { label: "All", value: "" },
- { label: "Ongoing", value: "ongoing" },
+ { label: "Ongoing", value: "ongoing" },
- { label: "Hiatus", value: "hiatus" },
+ { label: "Hiatus", value: "hiatus" },
- { label: "Completed", value: "completed" },
- ],
- inputType: FilterInputs.Picker,
- },
- {
- key: "type",
- label: "Type",
- values: [
- { label: "Light Novel (KR)", value: "light-novel-kr" },
+ { label: "Completed", value: "completed" },
+ ],
+ inputType: FilterInputs.Picker,
+ },
+ {
+ key: "type",
+ label: "Type",
+ values: [
+ { label: "Light Novel (KR)", value: "light-novel-kr" },
- { label: "Web Novel", value: "web-novel" },
- ],
- inputType: FilterInputs.Checkbox,
- },
- {
- key: "genres",
- label: "Genres",
- values: [
- { label: "Action", value: "action" },
+ { label: "Web Novel", value: "web-novel" },
+ ],
+ inputType: FilterInputs.Checkbox,
+ },
+ {
+ key: "genres",
+ label: "Genres",
+ values: [
+ { label: "Action", value: "action" },
- { label: "Adult", value: "adult" },
+ { label: "Adult", value: "adult" },
- { label: "Adventure", value: "adventure" },
+ { label: "Adventure", value: "adventure" },
- { label: "Comedy", value: "comedy" },
+ { label: "Comedy", value: "comedy" },
- { label: "Ecchi", value: "ecchi" },
+ { label: "Ecchi", value: "ecchi" },
- { label: "Fantasy", value: "fantasy" },
+ { label: "Fantasy", value: "fantasy" },
- { label: "Harem", value: "harem" },
+ { label: "Harem", value: "harem" },
- { label: "Josei", value: "josei" },
+ { label: "Josei", value: "josei" },
- { label: "Martial Arts", value: "martial-arts" },
+ { label: "Martial Arts", value: "martial-arts" },
- { label: "Mature", value: "mature" },
+ { label: "Mature", value: "mature" },
- { label: "Romance", value: "romance" },
+ { label: "Romance", value: "romance" },
- { label: "School Life", value: "school-life" },
+ { label: "School Life", value: "school-life" },
- { label: "Sci-fi", value: "sci-fi" },
+ { label: "Sci-fi", value: "sci-fi" },
- { label: "Seinen", value: "seinen" },
+ { label: "Seinen", value: "seinen" },
- { label: "Slice of Life", value: "slice-of-life" },
+ { label: "Slice of Life", value: "slice-of-life" },
- { label: "Smut", value: "smut" },
+ { label: "Smut", value: "smut" },
- { label: "Sports", value: "sports" },
+ { label: "Sports", value: "sports" },
- { label: "Supernatural", value: "supernatural" },
+ { label: "Supernatural", value: "supernatural" },
- { label: "Tragedy", value: "tragedy" },
- ],
- inputType: FilterInputs.Checkbox,
- },
-];
+ { label: "Tragedy", value: "tragedy" },
+ ],
+ inputType: FilterInputs.Checkbox,
+ },
+ ];
+}
+
+export default new PandaMTL();
\ No newline at end of file
diff --git a/plugins/french/.french b/plugins/french/.french
deleted file mode 100644
index e69de29..0000000
diff --git a/plugins/french/chireads.ts b/plugins/french/chireads.broken.ts
similarity index 100%
rename from plugins/french/chireads.ts
rename to plugins/french/chireads.broken.ts
diff --git a/plugins/indonesian/.indonesian b/plugins/indonesian/.indonesian
deleted file mode 100644
index e69de29..0000000
diff --git a/plugins/indonesian/MeioNovel[madara].ts b/plugins/indonesian/MeioNovel[madara].ts
index 8811f0d..6c3eb8c 100644
--- a/plugins/indonesian/MeioNovel[madara].ts
+++ b/plugins/indonesian/MeioNovel[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "meionovel";
-export const name = "MeioNovel [madara]";
-export const icon = "multisrc/madara/icons/meionovel.png";
-export const version = "1.0.0";
-export const site = "https://meionovel.id/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "novel-genre/" + filters.genres + '/';
- } else {
- url += "novel/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (true) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":FilterInputs.Picker},{"key":"genres","label":"GENRES","values":[{"label":"Action","value":"action"},{"label":"Adventure","value":"adventure"},{"label":"Comedy","value":"comedy"},{"label":"Cooking","value":"cooking"},{"label":"Drama","value":"drama"},{"label":"Ecchi","value":"ecchi"},{"label":"Fanfiction","value":"fanfiction"},{"label":"Fantasy","value":"fantasy"},{"label":"Gender Bender","value":"gender-bender"},{"label":"Harem","value":"harem"},{"label":"Historical","value":"historical"},{"label":"Horror","value":"horror"},{"label":"Isekai","value":"isekai"},{"label":"Josei","value":"josei"},{"label":"Magic","value":"magic"},{"label":"Martial Arts","value":"martial-arts"},{"label":"Mature","value":"mature"},{"label":"Mecha","value":"mecha"},{"label":"Mystery","value":"mystery"},{"label":"One shot","value":"one-shot"},{"label":"Psychological","value":"psychological"},{"label":"Reverse Harem","value":"reverse-harem"},{"label":"Romance","value":"romance"},{"label":"School Life","value":"school-life"},{"label":"Sci-fi","value":"sci-fi"},{"label":"Seinen","value":"seinen"},{"label":"Shoujo","value":"shoujo"},{"label":"Shoujo Ai","value":"shoujo-ai"},{"label":"Shounen","value":"shounen"},{"label":"Shounen Ai","value":"shounen-ai"},{"label":"Slice of Life","value":"slice-of-life"},{"label":"Smut","value":"smut"},{"label":"Sports","value":"sports"},{"label":"Supernatural","value":"supernatural"},{"label":"Tragedy","value":"tragedy"},{"label":"Virtual Reality","value":"virtual-reality"},{"label":"Wuxia","value":"wuxia"},{"label":"Xianxia","value":"xianxia"},{"label":"Xuanhuan","value":"xuanhuan"},{"label":"Yuri","value":"yuri"}],"inputType":FilterInputs.Picker}];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"meionovel","sourceSite":"https://meionovel.id/","sourceName":"MeioNovel","filters":[{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":"Picker"},{"key":"genres","label":"GENRES","values":[{"label":"Action","value":"action"},{"label":"Adventure","value":"adventure"},{"label":"Comedy","value":"comedy"},{"label":"Cooking","value":"cooking"},{"label":"Drama","value":"drama"},{"label":"Ecchi","value":"ecchi"},{"label":"Fanfiction","value":"fanfiction"},{"label":"Fantasy","value":"fantasy"},{"label":"Gender Bender","value":"gender-bender"},{"label":"Harem","value":"harem"},{"label":"Historical","value":"historical"},{"label":"Horror","value":"horror"},{"label":"Isekai","value":"isekai"},{"label":"Josei","value":"josei"},{"label":"Magic","value":"magic"},{"label":"Martial Arts","value":"martial-arts"},{"label":"Mature","value":"mature"},{"label":"Mecha","value":"mecha"},{"label":"Mystery","value":"mystery"},{"label":"One shot","value":"one-shot"},{"label":"Psychological","value":"psychological"},{"label":"Reverse Harem","value":"reverse-harem"},{"label":"Romance","value":"romance"},{"label":"School Life","value":"school-life"},{"label":"Sci-fi","value":"sci-fi"},{"label":"Seinen","value":"seinen"},{"label":"Shoujo","value":"shoujo"},{"label":"Shoujo Ai","value":"shoujo-ai"},{"label":"Shounen","value":"shounen"},{"label":"Shounen Ai","value":"shounen-ai"},{"label":"Slice of Life","value":"slice-of-life"},{"label":"Smut","value":"smut"},{"label":"Sports","value":"sports"},{"label":"Supernatural","value":"supernatural"},{"label":"Tragedy","value":"tragedy"},{"label":"Virtual Reality","value":"virtual-reality"},{"label":"Wuxia","value":"wuxia"},{"label":"Xianxia","value":"xianxia"},{"label":"Xuanhuan","value":"xuanhuan"},{"label":"Yuri","value":"yuri"}],"inputType":"Picker"}],"options":{"useNewChapterEndpoint":true,"lang":"Indonesian"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/indonesian/MoreNovel[madara].ts b/plugins/indonesian/MoreNovel[madara].ts
index 87d0394..924c6c1 100644
--- a/plugins/indonesian/MoreNovel[madara].ts
+++ b/plugins/indonesian/MoreNovel[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "morenovel";
-export const name = "MoreNovel [madara]";
-export const icon = "multisrc/madara/icons/morenovel.png";
-export const version = "1.0.0";
-export const site = "https://morenovel.net/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "novel-genre/" + filters.genres + '/';
- } else {
- url += "novel/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (true) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":FilterInputs.Picker},{"key":"genres","label":"GENRES","values":[{"label":"Action","value":"action"},{"label":"Adventure","value":"adventure"},{"label":"Comedy","value":"comedy"},{"label":"Drama","value":"drama"},{"label":"Ecchi","value":"ecchi"},{"label":"Fantasy","value":"fantasy"},{"label":"Gender Bender","value":"gender-bender"},{"label":"Harem","value":"harem"},{"label":"Historical","value":"historical"},{"label":"Horror","value":"horror"},{"label":"Josei","value":"josei"},{"label":"Martial Arts","value":"martial-arts"},{"label":"Mature","value":"mature"},{"label":"Mecha","value":"mecha"},{"label":"Mystery","value":"mystery"},{"label":"Psychological","value":"psychological"},{"label":"Romance","value":"romance"},{"label":"School Life","value":"school-life"},{"label":"Sci-fi","value":"sci-fi"},{"label":"Seinen","value":"seinen"},{"label":"Shoujo","value":"shoujo"},{"label":"Shoujo Ai","value":"shoujo-ai"},{"label":"Shounen","value":"shounen"},{"label":"Shounen Ai","value":"shounen-ai"},{"label":"Slice of Life","value":"slice-of-life"},{"label":"Sports","value":"sports"},{"label":"Supernatural","value":"supernatural"},{"label":"Tragedy","value":"tragedy"},{"label":"Wuxia","value":"wuxia"},{"label":"Xianxia","value":"xianxia"},{"label":"Xuanhuan","value":"xuanhuan"},{"label":"Yaoi","value":"yaoi"},{"label":"Yuri","value":"yuri"}],"inputType":FilterInputs.Picker}];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"morenovel","sourceSite":"https://morenovel.net/","sourceName":"MoreNovel","filters":[{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":"Picker"},{"key":"genres","label":"GENRES","values":[{"label":"Action","value":"action"},{"label":"Adventure","value":"adventure"},{"label":"Comedy","value":"comedy"},{"label":"Drama","value":"drama"},{"label":"Ecchi","value":"ecchi"},{"label":"Fantasy","value":"fantasy"},{"label":"Gender Bender","value":"gender-bender"},{"label":"Harem","value":"harem"},{"label":"Historical","value":"historical"},{"label":"Horror","value":"horror"},{"label":"Josei","value":"josei"},{"label":"Martial Arts","value":"martial-arts"},{"label":"Mature","value":"mature"},{"label":"Mecha","value":"mecha"},{"label":"Mystery","value":"mystery"},{"label":"Psychological","value":"psychological"},{"label":"Romance","value":"romance"},{"label":"School Life","value":"school-life"},{"label":"Sci-fi","value":"sci-fi"},{"label":"Seinen","value":"seinen"},{"label":"Shoujo","value":"shoujo"},{"label":"Shoujo Ai","value":"shoujo-ai"},{"label":"Shounen","value":"shounen"},{"label":"Shounen Ai","value":"shounen-ai"},{"label":"Slice of Life","value":"slice-of-life"},{"label":"Sports","value":"sports"},{"label":"Supernatural","value":"supernatural"},{"label":"Tragedy","value":"tragedy"},{"label":"Wuxia","value":"wuxia"},{"label":"Xianxia","value":"xianxia"},{"label":"Xuanhuan","value":"xuanhuan"},{"label":"Yaoi","value":"yaoi"},{"label":"Yuri","value":"yuri"}],"inputType":"Picker"}],"options":{"useNewChapterEndpoint":true,"lang":"Indonesian"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/indonesian/WBNovel[madara].ts b/plugins/indonesian/WBNovel[madara].ts
index 6151eb0..f7493fb 100644
--- a/plugins/indonesian/WBNovel[madara].ts
+++ b/plugins/indonesian/WBNovel[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "wbnovel";
-export const name = "WBNovel [madara]";
-export const icon = "multisrc/madara/icons/wbnovel.png";
-export const version = "1.0.0";
-export const site = "https://wbnovel.com/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "novel-genre/" + filters.genres + '/';
- } else {
- url += "novel/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (false) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":FilterInputs.Picker},{"key":"genres","label":"GENRES","values":[{"label":"Action","value":"action"},{"label":"Adventure","value":"adventure"},{"label":"Alchemy","value":"alchemy"},{"label":"Comedy","value":"comedy"},{"label":"Crafting","value":"crafting"},{"label":"Cultivation","value":"cultivation"},{"label":"Drama","value":"drama"},{"label":"Dungeon Crawling","value":"dungeon-crawling"},{"label":"Eci","value":"eci"},{"label":"Fantasy","value":"fantasy"},{"label":"Game","value":"game"},{"label":"Harem","value":"harem"},{"label":"Horror","value":"horror"},{"label":"Josei","value":"josei"},{"label":"Kingdom Building","value":"kingdom-building"},{"label":"Martial Arts","value":"martial-arts"},{"label":"Mature","value":"mature"},{"label":"Mecha","value":"mecha"},{"label":"Modern Setting","value":"modern-setting"},{"label":"Mystery","value":"mystery"},{"label":"Pets","value":"pets"},{"label":"Psychological","value":"psychological"},{"label":"Reincarnator","value":"reincarnator"},{"label":"Romance","value":"romance"},{"label":"School Life","value":"school-life"},{"label":"Sci-fi","value":"sci-fi"},{"label":"Seinen","value":"seinen"},{"label":"Shounen","value":"shounen"},{"label":"Slice of Life","value":"slice-of-life"},{"label":"Sports","value":"sports"},{"label":"Supernatural","value":"supernatural"},{"label":"Tragedy","value":"tragedy"},{"label":"Transmigration","value":"transmigration"},{"label":"Virtual Reality","value":"virtual-reality"},{"label":"Wuxia","value":"wuxia"},{"label":"Xianxia","value":"xianxia"},{"label":"Xuanhuan","value":"xuanhuan"}],"inputType":FilterInputs.Picker}];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"wbnovel","sourceSite":"https://wbnovel.com/","sourceName":"WBNovel","filters":[{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":"Picker"},{"key":"genres","label":"GENRES","values":[{"label":"Action","value":"action"},{"label":"Adventure","value":"adventure"},{"label":"Alchemy","value":"alchemy"},{"label":"Comedy","value":"comedy"},{"label":"Crafting","value":"crafting"},{"label":"Cultivation","value":"cultivation"},{"label":"Drama","value":"drama"},{"label":"Dungeon Crawling","value":"dungeon-crawling"},{"label":"Eci","value":"eci"},{"label":"Fantasy","value":"fantasy"},{"label":"Game","value":"game"},{"label":"Harem","value":"harem"},{"label":"Horror","value":"horror"},{"label":"Josei","value":"josei"},{"label":"Kingdom Building","value":"kingdom-building"},{"label":"Martial Arts","value":"martial-arts"},{"label":"Mature","value":"mature"},{"label":"Mecha","value":"mecha"},{"label":"Modern Setting","value":"modern-setting"},{"label":"Mystery","value":"mystery"},{"label":"Pets","value":"pets"},{"label":"Psychological","value":"psychological"},{"label":"Reincarnator","value":"reincarnator"},{"label":"Romance","value":"romance"},{"label":"School Life","value":"school-life"},{"label":"Sci-fi","value":"sci-fi"},{"label":"Seinen","value":"seinen"},{"label":"Shounen","value":"shounen"},{"label":"Slice of Life","value":"slice-of-life"},{"label":"Sports","value":"sports"},{"label":"Supernatural","value":"supernatural"},{"label":"Tragedy","value":"tragedy"},{"label":"Transmigration","value":"transmigration"},{"label":"Virtual Reality","value":"virtual-reality"},{"label":"Wuxia","value":"wuxia"},{"label":"Xianxia","value":"xianxia"},{"label":"Xuanhuan","value":"xuanhuan"}],"inputType":"Picker"}],"options":{"lang":"Indonesian"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/indonesian/indowebnovel.ts b/plugins/indonesian/indowebnovel.broken.ts
similarity index 100%
rename from plugins/indonesian/indowebnovel.ts
rename to plugins/indonesian/indowebnovel.broken.ts
diff --git a/plugins/indonesian/novelringan.ts b/plugins/indonesian/novelringan.broken.ts
similarity index 100%
rename from plugins/indonesian/novelringan.ts
rename to plugins/indonesian/novelringan.broken.ts
diff --git a/plugins/indonesian/sakuranovel.ts b/plugins/indonesian/sakuranovel.broken.ts
similarity index 100%
rename from plugins/indonesian/sakuranovel.ts
rename to plugins/indonesian/sakuranovel.broken.ts
diff --git a/plugins/japanese/.japanese b/plugins/japanese/.japanese
deleted file mode 100644
index e69de29..0000000
diff --git a/plugins/japanese/Syosetu.ts b/plugins/japanese/Syosetu.broken.ts
similarity index 100%
rename from plugins/japanese/Syosetu.ts
rename to plugins/japanese/Syosetu.broken.ts
diff --git a/plugins/korean/Agitoon.ts b/plugins/korean/Agitoon.broken.ts
similarity index 100%
rename from plugins/korean/Agitoon.ts
rename to plugins/korean/Agitoon.broken.ts
diff --git a/plugins/portuguese/.portuguese b/plugins/portuguese/.portuguese
deleted file mode 100644
index e69de29..0000000
diff --git a/plugins/portuguese/lightnovelbrasil.ts b/plugins/portuguese/lightnovelbrasil.ts
index e978bc9..1c675a0 100644
--- a/plugins/portuguese/lightnovelbrasil.ts
+++ b/plugins/portuguese/lightnovelbrasil.ts
@@ -1,77 +1,76 @@
import { load as parseHTML } from "cheerio";
import { fetchApi, fetchFile } from "@libs/fetch";
-import { FilterInputs } from "@libs/filterInputs";
-import { Chapter, Novel, Plugin } from "@typings/plugin";
+import { Filter, FilterInputs } from "@libs/filterInputs";
+import { Plugin } from "@typings/plugin";
-export const id = "lightnovelbrasil";
-export const name = "Light Novel Brasil";
-export const version = "1.0.0";
-export const icon = "multisrc/wpmangastream/icons/lightnovelbrasil.png";
-export const site = "https://lightnovelbrasil.com/";
+class LightNovelBrasil implements Plugin.PluginBase {
+ id = "lightnovelbrasil";
+ name = "Light Novel Brasil";
+ icon = "multisrc/wpmangastream/icons/lightnovelbrasil.png";
+ site = "https://lightnovelbrasil.com/";
+ version = "1.0.0";
+ userAgent = "";
+ cookieString = "";
+ async popularNovels(pageNo: number, {filters}: Plugin.PopularNovelsOptions): Promise {
+ let link = `${this.site}series/?page=${pageNo}`;
+ if (filters) {
+ if (Array.isArray(filters.genres) && filters.genres.length) {
+ link += filters.genres.map((i) => `&genre[]=${i}`).join("");
+ }
-const pluginId = id;
-const baseUrl = site;
-
-export const popularNovels: Plugin.popularNovels = async function (
- page,
- { filters }
-) {
- let link = `${baseUrl}series/?page=${page}`;
-
- if (filters) {
- if (Array.isArray(filters.genres) && filters.genres.length) {
- link += filters.genres.map((i) => `&genre[]=${i}`).join("");
+ if (Array.isArray(filters.type) && filters.type.length)
+ link += filters.type.map((i) => `&lang[]=${i}`).join("");
}
+ link += "&status=" + (filters?.status ? filters.status : "");
- if (Array.isArray(filters.type) && filters.type.length) {
- link += filters.type.map((i) => `&lang[]=${i}`).join("");
+ link += "&order=" + (filters?.order ? filters.order : "popular");
+
+ const headers = new Headers();
+ if(this.cookieString){
+ headers.append("cookie", this.cookieString);
}
- }
+ const body = await fetchApi(link, {headers}).then((result) =>
+ result.text()
+ );
- link += "&status=" + (filters?.status ? filters?.status : "");
+ const loadedCheerio = parseHTML(body);
- link += "&order=" + (filters?.order ? filters?.order : "popular");
+ const novels: Plugin.NovelItem[] = [];
- const body = await fetchApi(link, {}, pluginId).then((result) =>
- result.text()
- );
+ loadedCheerio("article.bs").each(function () {
+ const novelName = loadedCheerio(this).find(".ntitle").text().trim();
+ let image = loadedCheerio(this).find("img");
+ const novelCover = image.attr("data-src") || image.attr("src");
- const loadedCheerio = parseHTML(body);
+ const novelUrl = loadedCheerio(this).find("a").attr("href");
- const novels: Novel.Item[] = [];
+ if (!novelUrl) return;
- loadedCheerio("article.bs").each(function () {
- const novelName = loadedCheerio(this).find(".ntitle").text().trim();
- let image = loadedCheerio(this).find("img");
- const novelCover = image.attr("data-src") || image.attr("src");
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
- const novelUrl = loadedCheerio(this).find("a").attr("href");
+ novels.push(novel);
+ });
- if (!novelUrl) return;
+ return novels;
+ };
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters =
- async function (novelUrl) {
+ async parseNovelAndChapters(novelUrl: string): Promise {
const url = novelUrl;
-
- const result = await fetchApi(url, {}, pluginId);
+ const headers = new Headers();
+ if(this.cookieString){
+ headers.append("cookie", this.cookieString);
+ }
+ const result = await fetchApi(url, {headers});
const body = await result.text();
let loadedCheerio = parseHTML(body);
- const novel: Novel.instance = {
+ const novel: Plugin.SourceNovel = {
url,
chapters: [],
};
@@ -84,22 +83,14 @@ export const parseNovelAndChapters: Plugin.parseNovelAndChapters =
loadedCheerio("div.spe > span").each(function () {
const detailName = loadedCheerio(this).find("b").text().trim();
- const detail = loadedCheerio(this)
- .find("b")
- .remove()
- .end()
- .text()
- .trim();
+ const detail = loadedCheerio(this).find('b').remove().end().text().trim();
switch (detailName) {
- case "المؤلف:":
- case "Yazar:":
case "Autor:":
case "Author:":
novel.author = detail;
break;
case "Status:":
- case "Seviye:":
novel.status = detail;
break;
}
@@ -117,7 +108,7 @@ export const parseNovelAndChapters: Plugin.parseNovelAndChapters =
.end()
.text();
- let chapter: Chapter.Item[] = [];
+ let chapter: Plugin.ChapterItem[] = [];
loadedCheerio(".eplister")
.find("li")
@@ -146,276 +137,282 @@ export const parseNovelAndChapters: Plugin.parseNovelAndChapters =
novel.chapters = chapter.reverse();
return novel;
- };
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const headers = new Headers();
+ if(this.cookieString){
+ headers.append("cookie", this.cookieString);
+ }
+ const result = await fetchApi(chapterUrl, {headers});
+ const body = await result.text();
-export const parseChapter: Plugin.parseChapter = async function (chapterUrl) {
- const result = await fetchApi(chapterUrl, {}, pluginId);
- const body = await result.text();
+ const loadedCheerio = parseHTML(body);
- const loadedCheerio = parseHTML(body);
+ let chapterText = loadedCheerio(".epcontent").html() || "";
- let chapterText = loadedCheerio("div.epcontent").html();
+ return chapterText;
+ }
- return chapterText;
-};
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const url = `${this.site}?s=${searchTerm}`;
+ const headers = new Headers();
+ if(this.cookieString){
+ headers.append("cookie", this.cookieString);
+ }
+ const result = await fetchApi(url, {headers});
+ const body = await result.text();
-export const searchNovels: Plugin.searchNovels = async function (searchTerm) {
- const url = `${baseUrl}?s=${searchTerm}`;
+ const loadedCheerio = parseHTML(body);
- const result = await fetchApi(url, {}, pluginId);
- const body = await result.text();
+ const novels: Plugin.NovelItem[] = [];
- const loadedCheerio = parseHTML(body);
+ loadedCheerio("article.bs").each(function () {
+ const novelName = loadedCheerio(this).find(".ntitle").text().trim();
+ const novelCover = loadedCheerio(this).find("img").attr("src");
+ const novelUrl = loadedCheerio(this).find("a").attr("href");
+ if (!novelUrl) return;
- const novels: Novel.Item[] = [];
-
- loadedCheerio("article.bs").each(function () {
- const novelName = loadedCheerio(this).find(".ntitle").text().trim();
- const novelCover = loadedCheerio(this).find("img").attr("src");
- const novelUrl = loadedCheerio(this).find("a").attr("href");
-
- if (!novelUrl) return;
- novels.push({
- name: novelName,
- url: novelUrl,
- cover: novelCover,
+ novels.push({
+ name: novelName,
+ url: novelUrl,
+ cover: novelCover,
+ });
});
- });
- return novels;
-};
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url);
+ }
-export const fetchImage: Plugin.fetchImage = async function (url) {
- const headers = {
- Referer: baseUrl,
- };
- return await fetchFile(url, { headers: headers });
-};
-export const filters = [
- {
- key: "order",
- label: "Sort By",
- values: [
- { label: "Default", value: "" },
+ filters = [
+ {
+ key: "order",
+ label: "Sort By",
+ values: [
+ { label: "Default", value: "" },
- { label: "A-Z", value: "title" },
+ { label: "A-Z", value: "title" },
- { label: "Z-A", value: "titlereverse" },
+ { label: "Z-A", value: "titlereverse" },
- { label: "Latest Update", value: "update" },
+ { label: "Latest Update", value: "update" },
- { label: "Latest Added", value: "latest" },
+ { label: "Latest Added", value: "latest" },
- { label: "Popular", value: "popular" },
- ],
- inputType: FilterInputs.Picker,
- },
- {
- key: "status",
- label: "Status",
- values: [
- { label: "All", value: "" },
+ { label: "Popular", value: "popular" },
+ ],
+ inputType: FilterInputs.Picker,
+ },
+ {
+ key: "status",
+ label: "Status",
+ values: [
+ { label: "All", value: "" },
- { label: "Ongoing", value: "ongoing" },
+ { label: "Ongoing", value: "ongoing" },
- { label: "Hiatus", value: "hiatus" },
+ { label: "Hiatus", value: "hiatus" },
- { label: "Completed", value: "completed" },
- ],
- inputType: FilterInputs.Picker,
- },
- {
- key: "type",
- label: "Type",
- values: [
- { label: "Chinese novel", value: "chinese-novel" },
+ { label: "Completed", value: "completed" },
+ ],
+ inputType: FilterInputs.Picker,
+ },
+ {
+ key: "type",
+ label: "Type",
+ values: [
+ { label: "Chinese novel", value: "chinese-novel" },
- { label: "habyeol", value: "habyeol" },
+ { label: "habyeol", value: "habyeol" },
- { label: "korean novel", value: "korean-novel" },
+ { label: "korean novel", value: "korean-novel" },
- { label: "Web Novel", value: "web-novel" },
+ { label: "Web Novel", value: "web-novel" },
- { label: "삼심", value: "%ec%82%bc%ec%8b%ac" },
+ { label: "삼심", value: "%ec%82%bc%ec%8b%ac" },
- { label: "호곡", value: "%ed%98%b8%ea%b3%a1" },
- ],
- inputType: FilterInputs.Checkbox,
- },
- {
- key: "genres",
- label: "Genres",
- values: [
- { label: "A.I", value: "a.i" },
+ { label: "호곡", value: "%ed%98%b8%ea%b3%a1" },
+ ],
+ inputType: FilterInputs.Checkbox,
+ },
+ {
+ key: "genres",
+ label: "Genres",
+ values: [
+ { label: "A.I", value: "a.i" },
- { label: "Academy", value: "academy" },
+ { label: "Academy", value: "academy" },
- { label: "Action", value: "action" },
+ { label: "Action", value: "action" },
- { label: "Adult", value: "adult" },
+ { label: "Adult", value: "adult" },
- { label: "Adventure", value: "adventure" },
+ { label: "Adventure", value: "adventure" },
- { label: "Alternative History", value: "alternative-history" },
+ { label: "Alternative History", value: "alternative-history" },
- { label: "Another World", value: "another-world" },
+ { label: "Another World", value: "another-world" },
- { label: "Apocalypse", value: "apocalypse" },
+ { label: "Apocalypse", value: "apocalypse" },
- { label: "Bromance", value: "bromance" },
+ { label: "Bromance", value: "bromance" },
- { label: "Comedy", value: "comedy" },
+ { label: "Comedy", value: "comedy" },
- { label: "Dark fantasy", value: "dark-fantasy" },
+ { label: "Dark fantasy", value: "dark-fantasy" },
- { label: "Demons", value: "demons" },
+ { label: "Demons", value: "demons" },
- { label: "Drama", value: "drama" },
+ { label: "Drama", value: "drama" },
- { label: "Dystopia", value: "dystopia" },
+ { label: "Dystopia", value: "dystopia" },
- { label: "Ecchi", value: "ecchi" },
+ { label: "Ecchi", value: "ecchi" },
- { label: "Entertainment", value: "entertainment" },
+ { label: "Entertainment", value: "entertainment" },
- { label: "Exhaustion", value: "exhaustion" },
+ { label: "Exhaustion", value: "exhaustion" },
- { label: "Fanfiction", value: "fanfiction" },
+ { label: "Fanfiction", value: "fanfiction" },
- { label: "fantasy", value: "fantasy" },
+ { label: "fantasy", value: "fantasy" },
- { label: "finance", value: "finance" },
+ { label: "finance", value: "finance" },
- { label: "Full color", value: "full-color" },
+ { label: "Full color", value: "full-color" },
- { label: "Game", value: "game" },
+ { label: "Game", value: "game" },
- { label: "Gender Bender", value: "gender-bender" },
+ { label: "Gender Bender", value: "gender-bender" },
- { label: "Genius", value: "genius" },
+ { label: "Genius", value: "genius" },
- { label: "Harem", value: "harem" },
+ { label: "Harem", value: "harem" },
- { label: "Hero", value: "hero" },
+ { label: "Hero", value: "hero" },
- { label: "Historical", value: "historical" },
+ { label: "Historical", value: "historical" },
- { label: "Hunter", value: "hunter" },
+ { label: "Hunter", value: "hunter" },
- { label: "korean novel", value: "korean-novel" },
+ { label: "korean novel", value: "korean-novel" },
- { label: "Light Novel", value: "light-novel" },
+ { label: "Light Novel", value: "light-novel" },
- {
- label: "List Adventure Manga Genres",
- value: "list-adventure-manga-genres",
- },
+ {
+ label: "List Adventure Manga Genres",
+ value: "list-adventure-manga-genres",
+ },
- { label: "Long Strip", value: "long-strip" },
+ { label: "Long Strip", value: "long-strip" },
- { label: "Love comedy", value: "love-comedy" },
+ { label: "Love comedy", value: "love-comedy" },
- { label: "magic", value: "magic" },
+ { label: "magic", value: "magic" },
- { label: "Manhua", value: "manhua" },
+ { label: "Manhua", value: "manhua" },
- { label: "Martial Arts", value: "martial-arts" },
+ { label: "Martial Arts", value: "martial-arts" },
- { label: "Mature", value: "mature" },
+ { label: "Mature", value: "mature" },
- { label: "Medieval", value: "medieval" },
+ { label: "Medieval", value: "medieval" },
- { label: "Misunderstanding", value: "misunderstanding" },
+ { label: "Misunderstanding", value: "misunderstanding" },
- { label: "Modern", value: "modern" },
+ { label: "Modern", value: "modern" },
- { label: "modern fantasy", value: "modern-fantasy" },
+ { label: "modern fantasy", value: "modern-fantasy" },
- { label: "music", value: "music" },
+ { label: "music", value: "music" },
- { label: "Mystery", value: "mystery" },
+ { label: "Mystery", value: "mystery" },
- { label: "Necromancy", value: "necromancy" },
+ { label: "Necromancy", value: "necromancy" },
- { label: "No Romance", value: "no-romance" },
+ { label: "No Romance", value: "no-romance" },
- { label: "NTL", value: "ntl" },
+ { label: "NTL", value: "ntl" },
- { label: "o", value: "o" },
+ { label: "o", value: "o" },
- { label: "Obsession", value: "obsession" },
+ { label: "Obsession", value: "obsession" },
- { label: "Politics", value: "politics" },
+ { label: "Politics", value: "politics" },
- { label: "Possession", value: "possession" },
+ { label: "Possession", value: "possession" },
- { label: "Programming", value: "programming" },
+ { label: "Programming", value: "programming" },
- { label: "Psychological", value: "psychological" },
+ { label: "Psychological", value: "psychological" },
- { label: "Pure Love", value: "pure-love" },
+ { label: "Pure Love", value: "pure-love" },
- { label: "Redemption", value: "redemption" },
+ { label: "Redemption", value: "redemption" },
- { label: "Regression", value: "regression" },
+ { label: "Regression", value: "regression" },
- { label: "Regret", value: "regret" },
+ { label: "Regret", value: "regret" },
- { label: "Reincarnation", value: "reincarnation" },
+ { label: "Reincarnation", value: "reincarnation" },
- { label: "Revenge", value: "revenge" },
+ { label: "Revenge", value: "revenge" },
- { label: "Romance", value: "romance" },
+ { label: "Romance", value: "romance" },
- { label: "Romance Fanrasy", value: "romance-fanrasy" },
+ { label: "Romance Fanrasy", value: "romance-fanrasy" },
- { label: "Salvation", value: "salvation" },
+ { label: "Salvation", value: "salvation" },
- { label: "School Life", value: "school-life" },
+ { label: "School Life", value: "school-life" },
- { label: "Sci-fi", value: "sci-fi" },
+ { label: "Sci-fi", value: "sci-fi" },
- { label: "Science fiction", value: "science-fiction" },
+ { label: "Science fiction", value: "science-fiction" },
- { label: "Seinen", value: "seinen" },
+ { label: "Seinen", value: "seinen" },
- { label: "Shounen", value: "shounen" },
+ { label: "Shounen", value: "shounen" },
- { label: "Slice of Life", value: "slice-of-life" },
+ { label: "Slice of Life", value: "slice-of-life" },
- { label: "Soft yandere", value: "soft-yandere" },
+ { label: "Soft yandere", value: "soft-yandere" },
- { label: "Sports", value: "sports" },
+ { label: "Sports", value: "sports" },
- { label: "Supernatural", value: "supernatural" },
+ { label: "Supernatural", value: "supernatural" },
- { label: "Survival", value: "survival" },
+ { label: "Survival", value: "survival" },
- { label: "system", value: "system" },
+ { label: "system", value: "system" },
- { label: "Time limit", value: "time-limit" },
+ { label: "Time limit", value: "time-limit" },
- { label: "Tragedy", value: "tragedy" },
+ { label: "Tragedy", value: "tragedy" },
- { label: "Transmigration", value: "transmigration" },
+ { label: "Transmigration", value: "transmigration" },
- { label: "TS", value: "ts" },
+ { label: "TS", value: "ts" },
- { label: "Tsundere", value: "tsundere" },
+ { label: "Tsundere", value: "tsundere" },
- { label: "Unique", value: "unique" },
+ { label: "Unique", value: "unique" },
- { label: "Wholesome", value: "wholesome" },
+ { label: "Wholesome", value: "wholesome" },
- { label: "Wuxia", value: "wuxia" },
+ { label: "Wuxia", value: "wuxia" },
- { label: "Xuanhuan", value: "xuanhuan" },
+ { label: "Xuanhuan", value: "xuanhuan" },
- { label: "Yandere", value: "yandere" },
+ { label: "Yandere", value: "yandere" },
- { label: "Yuri", value: "yuri" },
- ],
- inputType: FilterInputs.Checkbox,
- },
-];
+ { label: "Yuri", value: "yuri" },
+ ],
+ inputType: FilterInputs.Checkbox,
+ },
+ ];
+}
+
+export default new LightNovelBrasil();
\ No newline at end of file
diff --git a/plugins/russian/.russian b/plugins/russian/.russian
deleted file mode 100644
index e69de29..0000000
diff --git a/plugins/russian/Erolate[rulate].ts b/plugins/russian/Erolate[rulate].ts
deleted file mode 100644
index 623633f..0000000
--- a/plugins/russian/Erolate[rulate].ts
+++ /dev/null
@@ -1,226 +0,0 @@
-
-import { load as parseHTML } from "cheerio";
-// import dayjs from 'dayjs';
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-// import { parseMadaraDate } from "@libs/parseMadaraDate";
-// import { isUrlAbsolute } from '@libs/isAbsoluteUrl';
-// import { showToast } from "@libs/showToast";
-import { FilterInputs } from "@libs/filterInputs";
-import { NovelStatus } from '@libs/novelStatus';
-// import { defaultCover } from "@libs/defaultCover";
-
-export const id = "erolate";
-export const name = "Erolate";
-export const icon = "multisrc/rulate/icons/erolate.png";
-export const version = "1.0.0";
-export const site = "https://erolate.com";
-
-export const popularNovels: Plugin.popularNovels = async function (
- page,
- { filters, showLatestNovels }
-) {
- let url = site + '/search?t=';
- url += '&cat=' + (filters?.cat || '0');
- url += '&s_lang=' + (filters?.s_lang || '0');
- url += '&t_lang=' + (filters?.t_lang || '0');
- url += '&type=' + (filters?.type || '0');
- url += '&sort=' + (showLatestNovels ? '4' : (filters?.sort || '6'));
- url += '&atmosphere=' + (filters?.atmosphere || '0');
- url += '&adult=' + (filters?.adult || '0');
-
- if (filters?.genres instanceof Array) {
- url += filters.genres.map(i => '&genres[]=' + i).join('');
- }
-
- if (filters?.genres_ex instanceof Array) {
- url += filters.genres_ex.map(i => '&genres_ex[]=' + i).join('');
- }
-
- if (filters?.tags instanceof Array) {
- url += filters.tags.map(i => '&tags[]=' + i).join('');
- }
-
- if (filters?.tags_ex instanceof Array) {
- url += filters.tags_ex.map(i => '&tags_ex[]=' + i).join('');
- }
-
- if (filters?.fandoms instanceof Array) {
- url += filters.fandoms.map(i => '&fandoms[]=' + i).join('');
- }
-
- if (filters?.fandoms_ex instanceof Array) {
- url += filters.fandoms_ex.map(i => '&fandoms_ex[]=' + i).join('');
- }
-
- if (filters?.trash instanceof Array) {
- url += filters.trash.map(i => '&' + i + '=1').join('');
- }
-
- url += '&Book_page=' + page;
-
- const result = await fetchApi(url);
- const body = await result.text();
- const loadedCheerio = parseHTML(body);
-
- const novels: Novel.Item[] = [];
-
- loadedCheerio(
- 'ul[class="search-results"] > li:not([class="ad_type_catalog"])',
- ).each(function () {
- novels.push({
- name: loadedCheerio(this).find('p > a').text(),
- cover: site + loadedCheerio(this).find('img').attr('src'),
- url: site + loadedCheerio(this).find('p > a').attr('href') || '',
- });
- });
-
- return novels;
-};
-
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters =
- async function (novelUrl) {
- const novel: Novel.instance = {
- url: novelUrl,
- chapters: [],
- };
- let result = await fetchApi(novelUrl);
- if (result.url.includes('mature?path=')) {
- const formData = new FormData();
- formData.append('path', novelUrl);
- formData.append('ok', 'Да');
-
- await fetchApi(result.url, {
- method: 'POST',
- body: formData,
- });
-
- result = await fetchApi(novelUrl);
- }
- const body = await result.text();
- const loadedCheerio = parseHTML(body);
-
- novel.name = loadedCheerio('div[class="container"] > div > div > h1, div.span8:nth-child(1) > h1:nth-child(2)')
- .text()
- .trim();
- novel.cover =
- site + loadedCheerio('div[class="images"] > div img').attr('src');
- novel.summary = loadedCheerio('#Info > div:nth-child(3), .book-description').text();
- novel.author = loadedCheerio('.book-stats-icons_author > span:nth-child(2) > a:nth-child(1)').text()
- let genres: string[] = [];
-
- loadedCheerio('div.span5 > p, .span5 > div:nth-child(2) > p').each(function () {
- switch (loadedCheerio(this).find('strong').text()) {
- case 'Автор:':
- novel.author = loadedCheerio(this).find('em > a').text().trim();
- break;
- case 'Выпуск:':
- novel.status =
- loadedCheerio(this).find('em').text().trim() === 'продолжается'
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- case 'Тэги:':
- loadedCheerio(this)
- .find('em > a')
- .each(function () {
- genres.push(loadedCheerio(this).text());
- });
- break;
- case 'Жанры:':
- loadedCheerio(this)
- .find('em > a')
- .each(function () {
- genres.push(loadedCheerio(this).text());
- });
- break;
- }
- });
-
- if (genres.length > 0) {
- novel.genres = genres.reverse().join(',');
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('table > tbody > tr.chapter_row').each(function () {
- const chapterName = loadedCheerio(this)
- .find('td[class="t"] > a')
- .text()
- .trim();
- const releaseDate = loadedCheerio(this)
- .find('td > span')
- .attr('title')
- ?.trim();
- const chapterUrl = site + loadedCheerio(this)
- .find('td[class="t"] > a')
- .attr('href');
-
- if (
- loadedCheerio(this).find('td > span[class="disabled"]').length < 1 &&
- releaseDate
- ) {
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- }
- });
-
- novel.chapters = chapters;
- return novel;
- };
-
-export const parseChapter: Plugin.parseChapter = async function (chapterUrl) {
- let result = await fetchApi(chapterUrl);
- if (result.url.includes('mature?path=')) {
- const formData = new FormData();
- formData.append('ok', 'Да');
-
- await fetchApi(result.url, {
- method: 'POST',
- body: formData,
- });
-
- result = await fetchApi(chapterUrl);
- }
- const body = await result.text();
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.content-text img').each(function () {
- if (!loadedCheerio(this).attr('src')?.startsWith('http')) {
- const src = loadedCheerio(this).attr('src');
- loadedCheerio(this).attr('src', site + src);
- }
- });
-
- const chapterText = loadedCheerio('.content-text').html();
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const result = await fetchApi(
- site + '/search/autocomplete?query=' + searchTerm,
- );
- let json = await result.json() as response[];
-
- json.forEach((item) => {
- const novelName = item.title_one + ' / ' + item.title_two;
- const novelCover = site + item.img;
- const novelUrl = site + item.url;
-
- novels.push({ name: novelName, cover: novelCover, url: novelUrl });
- });
-
- return novels;
-};
-
-interface response {
- id: number;
- title_one: string;
- title_two: string;
- url: string;
- img: string;
-};
-
-export const fetchImage: Plugin.fetchImage = fetchFile;
-
-export const filters = [{"key":"cat","label":"Из раздела каталога:","values":[{"label":"Неважно","value":"0"},{"label":"Авторские","value":"12"},{"label":"Авторские","value":"35"},{"label":"Английские","value":"34"},{"label":"Игры 18+","value":"3"},{"label":"Китайские","value":"31"},{"label":"Комиксы","value":"29"},{"label":"Корейские","value":"33"},{"label":"Манга для взрослых","value":"30"},{"label":"Машинный перевод","value":"38"},{"label":"Переводы","value":"15"},{"label":"Фанфики","value":"16"},{"label":"Эротические рассказы","value":"2"}],"inputType":FilterInputs.Picker},{"key":"s_lang","label":"Язык оригинала:","values":[{"label":"Неважно","value":"0"},{"label":"Абхазский","value":"20"},{"label":"Аварский","value":"21"},{"label":"Азербайджанский","value":"22"},{"label":"Аймара","value":"23"},{"label":"Акан","value":"24"},{"label":"Албанский","value":"25"},{"label":"Амхарский","value":"26"},{"label":"Английский","value":"2"},{"label":"Арабский","value":"27"},{"label":"Арагонский","value":"28"},{"label":"Арберешский","value":"29"},{"label":"Армянский","value":"30"},{"label":"Ассамский","value":"31"},{"label":"Астурийский","value":"32"},{"label":"Афарский","value":"33"},{"label":"Африкаанс","value":"34"},{"label":"Ацтекский","value":"35"},{"label":"Баварский","value":"36"},{"label":"Бамбарийский","value":"37"},{"label":"Баскский","value":"39"},{"label":"Башкирский","value":"40"},{"label":"Белорусский","value":"10"},{"label":"Бенгальский","value":"41"},{"label":"Бирманский","value":"42"},{"label":"Бислама","value":"43"},{"label":"Бихари","value":"44"},{"label":"Болгарский","value":"45"},{"label":"Боснийский","value":"234"},{"label":"Бретонский","value":"47"},{"label":"Валенсийский","value":"48"},{"label":"Валлийский","value":"49"},{"label":"Валлонский","value":"50"},{"label":"Венгерский","value":"51"},{"label":"Венда","value":"52"},{"label":"Венетский","value":"53"},{"label":"Верхнелужицкий","value":"54"},{"label":"Волоф","value":"55"},{"label":"Вьетнамский","value":"57"},{"label":"Гавайский","value":"58"},{"label":"Гаитянский","value":"59"},{"label":"Галисийский","value":"60"},{"label":"Гереро","value":"61"},{"label":"Голландский","value":"62"},{"label":"Греческий","value":"63"},{"label":"Грузинский","value":"64"},{"label":"Гуарани","value":"65"},{"label":"Гуджарати","value":"66"},{"label":"Датский","value":"19"},{"label":"Дзонг-кэ","value":"68"},{"label":"Древнегреческий","value":"69"},{"label":"Западно-фламандский","value":"70"},{"label":"Зулу","value":"71"},{"label":"Иврит","value":"15"},{"label":"Игбо","value":"72"},{"label":"Идиш","value":"73"},{"label":"Илоко","value":"74"},{"label":"Индонезийский","value":"75"},{"label":"Интерлингва","value":"76"},{"label":"Инуктитут","value":"77"},{"label":"Инупиак","value":"78"},{"label":"Ирландский","value":"79"},{"label":"Исландский","value":"80"},{"label":"Испанский","value":"6"},{"label":"Итальянский","value":"5"},{"label":"Йоруба","value":"81"},{"label":"Кабильский","value":"82"},{"label":"Казахский","value":"83"},{"label":"Калмыцкий","value":"235"},{"label":"Каннада","value":"84"},{"label":"Кантонский юэ","value":"85"},{"label":"Канури","value":"86"},{"label":"Каталанский","value":"87"},{"label":"Кашмири","value":"88"},{"label":"Кечуа","value":"90"},{"label":"Кикуйю","value":"91"},{"label":"Киньяруанда","value":"92"},{"label":"Киргизский","value":"93"},{"label":"Китайский","value":"7"},{"label":"Клингонский","value":"94"},{"label":"Коми","value":"95"},{"label":"Конго","value":"96"},{"label":"Конкани","value":"97"},{"label":"Корейский","value":"98"},{"label":"Корсиканский","value":"100"},{"label":"Котава","value":"101"},{"label":"Кри","value":"102"},{"label":"Курдский","value":"105"},{"label":"Кхмерский","value":"107"},{"label":"Лакский","value":"233"},{"label":"Лаосский","value":"109"},{"label":"Латынь","value":"110"},{"label":"Латышский","value":"111"},{"label":"Лезгинский","value":"112"},{"label":"Лимбургский","value":"113"},{"label":"Лингала","value":"114"},{"label":"Литовский","value":"115"},{"label":"Луба","value":"118"},{"label":"Луганда","value":"119"},{"label":"Люксембургский","value":"120"},{"label":"Македонский","value":"121"},{"label":"Малагасийский","value":"122"},{"label":"Малайский","value":"123"},{"label":"Мальдивский","value":"125"},{"label":"Мальтийский","value":"126"},{"label":"Маори","value":"127"},{"label":"Марийский","value":"232"},{"label":"Маршалльский","value":"130"},{"label":"Молдавский","value":"11"},{"label":"Монгольский","value":"133"},{"label":"Мяо (хмонг)","value":"209"},{"label":"Навахо","value":"135"},{"label":"Неаполитанский","value":"139"},{"label":"Немецкий","value":"3"},{"label":"Непальский","value":"140"},{"label":"Норвежский","value":"18"},{"label":"Осетинский","value":"147"},{"label":"Пакистанский","value":"230"},{"label":"Пенджабский","value":"149"},{"label":"Персидский","value":"151"},{"label":"Польский","value":"152"},{"label":"Португальский","value":"153"},{"label":"Румынский","value":"158"},{"label":"Русский","value":"1"},{"label":"Санскрит","value":"163"},{"label":"Сардинский","value":"164"},{"label":"Сербохорватский","value":"166"},{"label":"Словацкий","value":"170"},{"label":"Словенский","value":"171"},{"label":"Сомали","value":"172"},{"label":"Старотурецкий","value":"174"},{"label":"Суахили","value":"175"},{"label":"Сунданский","value":"176"},{"label":"Тагальский","value":"177"},{"label":"Таджикский","value":"178"},{"label":"Таитянский","value":"179"},{"label":"Тайваньский","value":"180"},{"label":"Тайский","value":"181"},{"label":"Тамильский","value":"182"},{"label":"Татарский","value":"12"},{"label":"Телугу","value":"184"},{"label":"Тибетский","value":"185"},{"label":"Тигринья","value":"186"},{"label":"Ток-писин","value":"187"},{"label":"Токи пона","value":"188"},{"label":"Тонганский","value":"189"},{"label":"Тсвана","value":"191"},{"label":"Тсонга","value":"192"},{"label":"Турецкий","value":"193"},{"label":"Туркменский","value":"194"},{"label":"Удмуртский","value":"196"},{"label":"Узбекский","value":"197"},{"label":"Уйгурский","value":"198"},{"label":"Украинский","value":"9"},{"label":"Фиджийский","value":"201"},{"label":"Филиппинский","value":"229"},{"label":"Финский","value":"17"},{"label":"Французский","value":"4"},{"label":"Фризский","value":"203"},{"label":"Фулах","value":"204"},{"label":"Хауса","value":"206"},{"label":"Хинди","value":"207"},{"label":"Хири-моту","value":"208"},{"label":"Чеченский","value":"213"},{"label":"Чешский","value":"13"},{"label":"Чувашский","value":"217"},{"label":"Шведский","value":"16"},{"label":"Швейцарский немецкий","value":"218"},{"label":"Шона","value":"219"},{"label":"Шотландский","value":"67"},{"label":"Эве","value":"221"},{"label":"Эскимосский","value":"223"},{"label":"Эсперанто","value":"14"},{"label":"Эстонский","value":"224"},{"label":"Южно-корейский","value":"231"},{"label":"Юкатекский","value":"225"},{"label":"Яванский","value":"227"},{"label":"Японский","value":"8"}],"inputType":FilterInputs.Picker},{"key":"t_lang","label":"Язык перевода:","values":[{"label":"Неважно","value":"0"},{"label":"Абхазский","value":"20"},{"label":"Аварский","value":"21"},{"label":"Азербайджанский","value":"22"},{"label":"Аймара","value":"23"},{"label":"Акан","value":"24"},{"label":"Албанский","value":"25"},{"label":"Амхарский","value":"26"},{"label":"Английский","value":"2"},{"label":"Арабский","value":"27"},{"label":"Арагонский","value":"28"},{"label":"Арберешский","value":"29"},{"label":"Армянский","value":"30"},{"label":"Ассамский","value":"31"},{"label":"Астурийский","value":"32"},{"label":"Афарский","value":"33"},{"label":"Африкаанс","value":"34"},{"label":"Ацтекский","value":"35"},{"label":"Баварский","value":"36"},{"label":"Бамбарийский","value":"37"},{"label":"Баскский","value":"39"},{"label":"Башкирский","value":"40"},{"label":"Белорусский","value":"10"},{"label":"Бенгальский","value":"41"},{"label":"Бирманский","value":"42"},{"label":"Бислама","value":"43"},{"label":"Бихари","value":"44"},{"label":"Болгарский","value":"45"},{"label":"Боснийский","value":"234"},{"label":"Бретонский","value":"47"},{"label":"Валенсийский","value":"48"},{"label":"Валлийский","value":"49"},{"label":"Валлонский","value":"50"},{"label":"Венгерский","value":"51"},{"label":"Венда","value":"52"},{"label":"Венетский","value":"53"},{"label":"Верхнелужицкий","value":"54"},{"label":"Волоф","value":"55"},{"label":"Вьетнамский","value":"57"},{"label":"Гавайский","value":"58"},{"label":"Гаитянский","value":"59"},{"label":"Галисийский","value":"60"},{"label":"Гереро","value":"61"},{"label":"Голландский","value":"62"},{"label":"Греческий","value":"63"},{"label":"Грузинский","value":"64"},{"label":"Гуарани","value":"65"},{"label":"Гуджарати","value":"66"},{"label":"Датский","value":"19"},{"label":"Дзонг-кэ","value":"68"},{"label":"Древнегреческий","value":"69"},{"label":"Западно-фламандский","value":"70"},{"label":"Зулу","value":"71"},{"label":"Иврит","value":"15"},{"label":"Игбо","value":"72"},{"label":"Идиш","value":"73"},{"label":"Илоко","value":"74"},{"label":"Индонезийский","value":"75"},{"label":"Интерлингва","value":"76"},{"label":"Инуктитут","value":"77"},{"label":"Инупиак","value":"78"},{"label":"Ирландский","value":"79"},{"label":"Исландский","value":"80"},{"label":"Испанский","value":"6"},{"label":"Итальянский","value":"5"},{"label":"Йоруба","value":"81"},{"label":"Кабильский","value":"82"},{"label":"Казахский","value":"83"},{"label":"Калмыцкий","value":"235"},{"label":"Каннада","value":"84"},{"label":"Кантонский юэ","value":"85"},{"label":"Канури","value":"86"},{"label":"Каталанский","value":"87"},{"label":"Кашмири","value":"88"},{"label":"Кечуа","value":"90"},{"label":"Кикуйю","value":"91"},{"label":"Киньяруанда","value":"92"},{"label":"Киргизский","value":"93"},{"label":"Китайский","value":"7"},{"label":"Клингонский","value":"94"},{"label":"Коми","value":"95"},{"label":"Конго","value":"96"},{"label":"Конкани","value":"97"},{"label":"Корейский","value":"98"},{"label":"Корсиканский","value":"100"},{"label":"Котава","value":"101"},{"label":"Кри","value":"102"},{"label":"Курдский","value":"105"},{"label":"Кхмерский","value":"107"},{"label":"Лакский","value":"233"},{"label":"Лаосский","value":"109"},{"label":"Латынь","value":"110"},{"label":"Латышский","value":"111"},{"label":"Лезгинский","value":"112"},{"label":"Лимбургский","value":"113"},{"label":"Лингала","value":"114"},{"label":"Литовский","value":"115"},{"label":"Луба","value":"118"},{"label":"Луганда","value":"119"},{"label":"Люксембургский","value":"120"},{"label":"Македонский","value":"121"},{"label":"Малагасийский","value":"122"},{"label":"Малайский","value":"123"},{"label":"Мальдивский","value":"125"},{"label":"Мальтийский","value":"126"},{"label":"Маори","value":"127"},{"label":"Марийский","value":"232"},{"label":"Маршалльский","value":"130"},{"label":"Молдавский","value":"11"},{"label":"Монгольский","value":"133"},{"label":"Мяо (хмонг)","value":"209"},{"label":"Навахо","value":"135"},{"label":"Неаполитанский","value":"139"},{"label":"Немецкий","value":"3"},{"label":"Непальский","value":"140"},{"label":"Норвежский","value":"18"},{"label":"Осетинский","value":"147"},{"label":"Пакистанский","value":"230"},{"label":"Пенджабский","value":"149"},{"label":"Персидский","value":"151"},{"label":"Польский","value":"152"},{"label":"Португальский","value":"153"},{"label":"Румынский","value":"158"},{"label":"Русский","value":"1"},{"label":"Санскрит","value":"163"},{"label":"Сардинский","value":"164"},{"label":"Сербохорватский","value":"166"},{"label":"Словацкий","value":"170"},{"label":"Словенский","value":"171"},{"label":"Сомали","value":"172"},{"label":"Старотурецкий","value":"174"},{"label":"Суахили","value":"175"},{"label":"Сунданский","value":"176"},{"label":"Тагальский","value":"177"},{"label":"Таджикский","value":"178"},{"label":"Таитянский","value":"179"},{"label":"Тайваньский","value":"180"},{"label":"Тайский","value":"181"},{"label":"Тамильский","value":"182"},{"label":"Татарский","value":"12"},{"label":"Телугу","value":"184"},{"label":"Тибетский","value":"185"},{"label":"Тигринья","value":"186"},{"label":"Ток-писин","value":"187"},{"label":"Токи пона","value":"188"},{"label":"Тонганский","value":"189"},{"label":"Тсвана","value":"191"},{"label":"Тсонга","value":"192"},{"label":"Турецкий","value":"193"},{"label":"Туркменский","value":"194"},{"label":"Удмуртский","value":"196"},{"label":"Узбекский","value":"197"},{"label":"Уйгурский","value":"198"},{"label":"Украинский","value":"9"},{"label":"Фиджийский","value":"201"},{"label":"Филиппинский","value":"229"},{"label":"Финский","value":"17"},{"label":"Французский","value":"4"},{"label":"Фризский","value":"203"},{"label":"Фулах","value":"204"},{"label":"Хауса","value":"206"},{"label":"Хинди","value":"207"},{"label":"Хири-моту","value":"208"},{"label":"Чеченский","value":"213"},{"label":"Чешский","value":"13"},{"label":"Чувашский","value":"217"},{"label":"Шведский","value":"16"},{"label":"Швейцарский немецкий","value":"218"},{"label":"Шона","value":"219"},{"label":"Шотландский","value":"67"},{"label":"Эве","value":"221"},{"label":"Эскимосский","value":"223"},{"label":"Эсперанто","value":"14"},{"label":"Эстонский","value":"224"},{"label":"Южно-корейский","value":"231"},{"label":"Юкатекский","value":"225"},{"label":"Яванский","value":"227"},{"label":"Японский","value":"8"}],"inputType":FilterInputs.Picker},{"key":"type","label":"Тип:","values":[{"label":"Неважно","value":"0"},{"label":"Только авторские","value":"2"},{"label":"Только переводы","value":"1"}],"inputType":FilterInputs.Picker},{"key":"trash","label":"Другое:","values":[{"label":"Без фэндомов","value":"fandoms_ex_all"},{"label":"Готовые на 100%","value":"ready"},{"label":"Доступные для перевода","value":"tr"},{"label":"Доступные для скачивания","value":"gen"},{"label":"Завершённые проекты","value":"wealth"},{"label":"Распродажа","value":"discount"},{"label":"Только онгоинги","value":"ongoings"},{"label":"Убрать машинный","value":"remove_machinelate"}],"inputType":FilterInputs.Checkbox},{"key":"sort","label":"Сортировка:","values":[{"label":"По рейтингу","value":"6"},{"label":"По дате последней активности","value":"4"},{"label":"По дате создания","value":"3"},{"label":"По кол-ву бесплатных глав","value":"11"},{"label":"По кол-ву в закладках","value":"13"},{"label":"По кол-ву в избранном","value":"14"},{"label":"По кол-ву лайков","value":"8"},{"label":"По кол-ву переведённых глав","value":"7"},{"label":"По кол-ву рецензий","value":"12"},{"label":"По кол-ву страниц","value":"10"},{"label":"По названию на языке оригинала","value":"1"},{"label":"По названию на языке перевода","value":"2"},{"label":"По просмотрам","value":"5"},{"label":"По степени готовности","value":"0"},{"label":"Случайно","value":"9"}],"inputType":FilterInputs.Picker},{"key":"genres","label":"Жанры:","values":[{"label":"Анал","value":"2"},{"label":"Бдсм","value":"3"},{"label":"Большая грудь","value":"5"},{"label":"Большая попка","value":"6"},{"label":"Большой член","value":"7"},{"label":"Бондаж","value":"8"},{"label":"В первый раз","value":"9"},{"label":"В цвете","value":"10"},{"label":"Гарем","value":"11"},{"label":"Гендарная интрига","value":"12"},{"label":"Групповой секс","value":"13"},{"label":"Детектив","value":"39"},{"label":"Драма","value":"14"},{"label":"Зрелые женщины (milf)","value":"15"},{"label":"Измена","value":"16"},{"label":"Изнасилование","value":"17"},{"label":"Инцест","value":"18"},{"label":"Исторический","value":"19"},{"label":"Комедия","value":"20"},{"label":"Контроль над разумом","value":"35"},{"label":"Маленькая грудь","value":"21"},{"label":"Мистика","value":"40"},{"label":"Научная фантастика","value":"22"},{"label":"Нетораре","value":"23"},{"label":"Оральный секс","value":"24"},{"label":"Повседневность","value":"41"},{"label":"Приключения","value":"38"},{"label":"Публичный секс","value":"33"},{"label":"Романтика","value":"25"},{"label":"С изображениями","value":"36"},{"label":"Сверхъестественное","value":"34"},{"label":"Смат","value":"37"},{"label":"Тентакли","value":"26"},{"label":"Трагедия","value":"27"},{"label":"Ужасы","value":"28"},{"label":"Фантастика","value":"32"},{"label":"Фэнтези","value":"29"},{"label":"Чикан","value":"30"},{"label":"Этти","value":"31"},{"label":"Ahegao","value":"1"}],"inputType":FilterInputs.Checkbox},{"key":"tags","label":"Тэги:","values":[{"label":"+18","value":"141"},{"label":"18+","value":"200"},{"label":"21+","value":"334"},{"label":"Адекватные главные герои","value":"253"},{"label":"Азартные игры","value":"210"},{"label":"Айдолы","value":"364"},{"label":"Акула","value":"53"},{"label":"Альтернативное развитие событий","value":"338"},{"label":"Аморальный главный герой","value":"219"},{"label":"Анал","value":"7"},{"label":"Анальный секс","value":"67"},{"label":"Ангелы","value":"114"},{"label":"Антигерой","value":"226"},{"label":"Аристократия","value":"260"},{"label":"Артефакт","value":"379"},{"label":"Афродизиак","value":"276"},{"label":"Ахегао","value":"240"},{"label":"Бабушка беременна от внука","value":"393"},{"label":"Бабушка и внук","value":"380"},{"label":"Бдсм","value":"131"},{"label":"Беременность","value":"148"},{"label":"Бесплатно","value":"79"},{"label":"Бесстрашные персонажи","value":"339"},{"label":"Библиотека","value":"265"},{"label":"Бистиалити","value":"391"},{"label":"Битва за трон","value":"404"},{"label":"Близнецы","value":"198"},{"label":"Блондинка","value":"91"},{"label":"Богатые персонажи","value":"248"},{"label":"Боги","value":"115"},{"label":"Боевик","value":"252"},{"label":"Большая грудь","value":"33"},{"label":"Большая попка","value":"328"},{"label":"Большой член","value":"76"},{"label":"Большой член сына","value":"396"},{"label":"Босс и подчиненный","value":"330"},{"label":"Брак","value":"182"},{"label":"Брак по расчёту","value":"346"},{"label":"Брат","value":"29"},{"label":"Брат и сестра","value":"30"},{"label":"Брюнетка","value":"28"},{"label":"Бэтмен","value":"369"},{"label":"Бэтмен","value":"170"},{"label":"В первый раз","value":"179"},{"label":"Вагинальный секс","value":"57"},{"label":"Вагинальный секс","value":"171"},{"label":"Вайурист","value":"9"},{"label":"Вампиры","value":"133"},{"label":"Ван-пис","value":"335"},{"label":"Веб камера","value":"289"},{"label":"Ведьмы","value":"232"},{"label":"Викинги","value":"307"},{"label":"Виртуальная реальность","value":"382"},{"label":"Вирус","value":"203"},{"label":"Внучка","value":"189"},{"label":"Война","value":"387"},{"label":"Воспоминания из прошлого","value":"405"},{"label":"Враги становятся любовниками","value":"410"},{"label":"Время","value":"81"},{"label":"Второй шанс","value":"244"},{"label":"Вуайеризм","value":"62"},{"label":"Выживание","value":"135"},{"label":"Гарем","value":"107"},{"label":"Гарри поттер","value":"97"},{"label":"Гвен","value":"402"},{"label":"Гг имба","value":"87"},{"label":"Генетические модификации","value":"314"},{"label":"Гипноз","value":"143"},{"label":"Главная героиня девушка","value":"147"},{"label":"Главный герой женщина","value":"213"},{"label":"Главный герой извращенец","value":"116"},{"label":"Главный герой мужчина","value":"117"},{"label":"Глубокое горло","value":"94"},{"label":"Гоблины","value":"230"},{"label":"Город","value":"139"},{"label":"Городское фэнтези","value":"297"},{"label":"Грудное молоко","value":"225"},{"label":"Групповой секс","value":"72"},{"label":"Гэнг-бэнг","value":"235"},{"label":"Гяру","value":"222"},{"label":"Двойное проникновение","value":"42"},{"label":"Двойной анал","value":"47"},{"label":"Дворяне","value":"246"},{"label":"Деамоны старший школы","value":"291"},{"label":"Девственница","value":"119"},{"label":"Девушки-монстры","value":"223"},{"label":"Демоны","value":"98"},{"label":"Детектив","value":"249"},{"label":"Дзёсэй","value":"259"},{"label":"Доктор","value":"326"},{"label":"Дом","value":"138"},{"label":"Доминирование","value":"18"},{"label":"Дочь","value":"153"},{"label":"Дочь беременна от отца","value":"348"},{"label":"Древние времена","value":"383"},{"label":"Древний китай","value":"261"},{"label":"Другой мир","value":"365"},{"label":"Дружба","value":"325"},{"label":"Друзья детства","value":"183"},{"label":"Дядя","value":"160"},{"label":"Жена","value":"70"},{"label":"Жена и муж","value":"99"},{"label":"Жена шлюха","value":"236"},{"label":"Женское доминирование","value":"100"},{"label":"Жесткий секс","value":"283"},{"label":"Жёсткий секс","value":"101"},{"label":"Жестокие персонажи","value":"254"},{"label":"Жестокий мир","value":"336"},{"label":"Жестокость","value":"123"},{"label":"Заботливый главный герой","value":"340"},{"label":"Зависимость","value":"370"},{"label":"Заключение","value":"196"},{"label":"Заключённые","value":"384"},{"label":"Замок","value":"140"},{"label":"Запретная любовь","value":"273"},{"label":"Заражение","value":"206"},{"label":"Звёздные войны","value":"120"},{"label":"Зверодевочки","value":"158"},{"label":"Зло","value":"343"},{"label":"Золовка","value":"77"},{"label":"Золотой дождь","value":"146"},{"label":"Зомби апокалипсис","value":"241"},{"label":"Зоофилия","value":"144"},{"label":"Зрелые женщины","value":"398"},{"label":"Игровые элементы","value":"385"},{"label":"Извращения","value":"192"},{"label":"Измена","value":"71"},{"label":"Изменения внешности","value":"315"},{"label":"Изменения личности","value":"316"},{"label":"Изнасилование","value":"275"},{"label":"Изуку мидория","value":"337"},{"label":"Ино","value":"127"},{"label":"Инопланетяне","value":"304"},{"label":"Интересный сюжет","value":"349"},{"label":"Интимные сцены","value":"322"},{"label":"Интриги и заговоры","value":"262"},{"label":"Интроверт","value":"38"},{"label":"Инфекция","value":"207"},{"label":"Инцест","value":"35"},{"label":"Исторический роман","value":"406"},{"label":"Камера","value":"92"},{"label":"Колледж","value":"82"},{"label":"Комикс","value":"286"},{"label":"Контроль","value":"19"},{"label":"Контроль над разумом","value":"181"},{"label":"Контроль разума","value":"65"},{"label":"Кончил внутрь","value":"221"},{"label":"Королевская семья","value":"358"},{"label":"Коррупция","value":"49"},{"label":"Космос","value":"204"},{"label":"Красивая главная героиня","value":"255"},{"label":"Красивые женщины","value":"321"},{"label":"Красивый главный герой","value":"266"},{"label":"Ксенофилия","value":"386"},{"label":"Кулинария","value":"362"},{"label":"Культвация","value":"86"},{"label":"Кунилингус","value":"152"},{"label":"Кушина","value":"399"},{"label":"Лактация","value":"11"},{"label":"Лесби","value":"408"},{"label":"Лишение девственности","value":"212"},{"label":"Лоли","value":"218"},{"label":"Лунатизм","value":"279"},{"label":"Любовь","value":"89"},{"label":"Магический мир","value":"357"},{"label":"Магия","value":"80"},{"label":"Мама","value":"3"},{"label":"Мама беременна от сына","value":"274"},{"label":"Мама и дочь","value":"163"},{"label":"Мама и сын","value":"1"},{"label":"Мама супермена","value":"39"},{"label":"Манипуляция временем","value":"292"},{"label":"Марвел","value":"290"},{"label":"Марвел","value":"173"},{"label":"Марти стью","value":"102"},{"label":"Массаж","value":"224"},{"label":"Мастурбация","value":"63"},{"label":"Мать","value":"239"},{"label":"Мать и дочь","value":"381"},{"label":"Мать и сын","value":"237"},{"label":"Мафия","value":"256"},{"label":"Мачеха","value":"197"},{"label":"Мачеха беременна от сына","value":"395"},{"label":"Мачеха и сын","value":"394"},{"label":"Медсестра","value":"341"},{"label":"Межрассовый","value":"54"},{"label":"Месть","value":"306"},{"label":"Меха","value":"268"},{"label":"Ми","value":"243"},{"label":"Милф","value":"34"},{"label":"Милф","value":"180"},{"label":"Минет","value":"52"},{"label":"Мистика","value":"250"},{"label":"Младшая сестра","value":"154"},{"label":"Много спермы","value":"409"},{"label":"Модель","value":"324"},{"label":"Монстры","value":"333"},{"label":"Мошеничество","value":"44"},{"label":"Мужская беременность","value":"363"},{"label":"Мужчина протагонист","value":"108"},{"label":"Музыка","value":"331"},{"label":"Мэри съюха","value":"309"},{"label":"Наруко","value":"400"},{"label":"Наруто","value":"46"},{"label":"Насилие","value":"128"},{"label":"Насилие и жестокость","value":"193"},{"label":"Научный эксперимент","value":"313"},{"label":"Нежить","value":"373"},{"label":"Некромантия","value":"298"},{"label":"Ненормативная лексика","value":"124"},{"label":"Нетораре","value":"69"},{"label":"Нетори","value":"284"},{"label":"Нижнее бельё","value":"392"},{"label":"Ниндзя","value":"296"},{"label":"Ношеные трусики","value":"166"},{"label":"Нудизм","value":"156"},{"label":"Няня","value":"88"},{"label":"Обмен женами","value":"78"},{"label":"Оборотни","value":"136"},{"label":"Обратный гарем","value":"214"},{"label":"Одержимость","value":"345"},{"label":"Омегаверс","value":"368"},{"label":"Оплодотворение","value":"157"},{"label":"Оральный секс","value":"10"},{"label":"Оргия","value":"356"},{"label":"Орки","value":"388"},{"label":"От слабого к сильному","value":"351"},{"label":"Отец","value":"2"},{"label":"Отец делится с сыном","value":"6"},{"label":"Отец и дочь","value":"205"},{"label":"Отец куколд","value":"272"},{"label":"Офис","value":"234"},{"label":"Падчерица","value":"271"},{"label":"Пайзури","value":"195"},{"label":"Папа и дочь","value":"360"},{"label":"Паразиты","value":"208"},{"label":"Параллельный мир","value":"320"},{"label":"Пародия","value":"371"},{"label":"Первый раз","value":"159"},{"label":"Перемещение в другой мир","value":"347"},{"label":"Перемещение во времени","value":"245"},{"label":"Перерождение","value":"109"},{"label":"Перерождение в злодея","value":"202"},{"label":"Пирсинг","value":"145"},{"label":"Писатель","value":"267"},{"label":"Планомерное развитие событий","value":"350"},{"label":"Повседневность","value":"247"},{"label":"Подглядывание","value":"280"},{"label":"Подчинение","value":"106"},{"label":"Подчинение и унижение","value":"211"},{"label":"Поедание киски","value":"26"},{"label":"Покемоны","value":"132"},{"label":"Покорная","value":"8"},{"label":"Полигамия","value":"352"},{"label":"Половое воспитание","value":"37"},{"label":"Полулюди","value":"231"},{"label":"Попаданец","value":"103"},{"label":"Попадание в книгу","value":"361"},{"label":"Порка","value":"20"},{"label":"Порно","value":"278"},{"label":"Постапокалипсис","value":"332"},{"label":"Потеря девственности","value":"142"},{"label":"Похищение","value":"161"},{"label":"Преданные любовный интерес","value":"407"},{"label":"Призраки","value":"412"},{"label":"Приключения","value":"134"},{"label":"Принуждение","value":"66"},{"label":"Психология","value":"238"},{"label":"Публично","value":"85"},{"label":"Публичный секс","value":"233"},{"label":"Раб","value":"353"},{"label":"Рабы","value":"308"},{"label":"Разват","value":"58"},{"label":"Разврат","value":"64"},{"label":"Райзен","value":"95"},{"label":"Раса инопланетных космических лесбиянок","value":"294"},{"label":"Религия","value":"403"},{"label":"Рестленг","value":"84"},{"label":"Риас гремори","value":"389"},{"label":"Романтика","value":"178"},{"label":"Рыжий","value":"90"},{"label":"С","value":"413"},{"label":"Сакура","value":"126"},{"label":"Самолет","value":"93"},{"label":"Санса старк","value":"277"},{"label":"Санта","value":"372"},{"label":"Свадьба","value":"73"},{"label":"Сверхсила","value":"228"},{"label":"Сверхъестественное","value":"319"},{"label":"Свингеры","value":"201"},{"label":"Свободные отношения","value":"186"},{"label":"Связывание","value":"137"},{"label":"Сёдзе","value":"264"},{"label":"Секс","value":"21"},{"label":"Секс без проникновения","value":"68"},{"label":"Секс втроем","value":"43"},{"label":"Секс игрушки","value":"59"},{"label":"Секс рабыня","value":"55"},{"label":"Секс с монстрами","value":"56"},{"label":"Секс с учителем","value":"184"},{"label":"Секса будет много","value":"151"},{"label":"Сексуальное желание","value":"209"},{"label":"Селфцест","value":"397"},{"label":"Семья","value":"5"},{"label":"Сестра","value":"31"},{"label":"Сестра беременна от брата","value":"355"},{"label":"Сильный с самого начала","value":"112"},{"label":"Симбиоз","value":"50"},{"label":"Сирена","value":"51"},{"label":"Система","value":"104"},{"label":"Сиськи","value":"285"},{"label":"Сквирт","value":"164"},{"label":"Скрытый секс","value":"287"},{"label":"Служанка","value":"215"},{"label":"Соб","value":"281"},{"label":"Соблазнение","value":"162"},{"label":"Современность","value":"217"},{"label":"Соколиный Глаз","value":"176"},{"label":"Соперничество","value":"216"},{"label":"Соседи","value":"61"},{"label":"Соседка","value":"312"},{"label":"Сперма","value":"229"},{"label":"Сперма на лицо","value":"199"},{"label":"Спящие","value":"187"},{"label":"Старшая сестра","value":"311"},{"label":"Стеб","value":"111"},{"label":"Студенты","value":"177"},{"label":"Суккуб","value":"390"},{"label":"Супергерои","value":"305"},{"label":"Суперспособности","value":"300"},{"label":"Сын","value":"4"},{"label":"Твинцест","value":"188"},{"label":"Темное фэнтези","value":"293"},{"label":"Тентакли","value":"303"},{"label":"Тетя","value":"113"},{"label":"Тетя беременна от племянника","value":"376"},{"label":"Тетя и племянник","value":"377"},{"label":"Техника","value":"302"},{"label":"Технологии","value":"301"},{"label":"Тёща","value":"270"},{"label":"Тиран","value":"310"},{"label":"Трагическое прошлое","value":"251"},{"label":"Трансмиграция","value":"269"},{"label":"Трансформация","value":"317"},{"label":"Триллер","value":"344"},{"label":"Трусики","value":"165"},{"label":"Убийства","value":"258"},{"label":"Удача","value":"299"},{"label":"Ужасы","value":"375"},{"label":"Улучшение тела","value":"288"},{"label":"Умная главная героиня","value":"242"},{"label":"Умные персонажи","value":"257"},{"label":"Умный главный герой","value":"354"},{"label":"Университет","value":"323"},{"label":"Ученик","value":"83"},{"label":"Ф","value":"149"},{"label":"Фанатичная любовь","value":"366"},{"label":"Фанаты","value":"367"},{"label":"Фантастика","value":"295"},{"label":"Фанфик","value":"40"},{"label":"Фелляция","value":"22"},{"label":"Ферма","value":"191"},{"label":"Фетиш","value":"60"},{"label":"Флэш","value":"121"},{"label":"Футанария","value":"150"},{"label":"Фэнтези","value":"359"},{"label":"Хентай","value":"75"},{"label":"Хината","value":"110"},{"label":"Холодная главная героиня","value":"263"},{"label":"Черная вдова","value":"220"},{"label":"Черная Вдова","value":"175"},{"label":"Черный юмор","value":"374"},{"label":"Читерство","value":"45"},{"label":"Чтение мыслей","value":"227"},{"label":"Чудовища","value":"378"},{"label":"Шантаж","value":"129"},{"label":"Школа","value":"118"},{"label":"Школьная жизнь","value":"318"},{"label":"Шлюха","value":"32"},{"label":"Шоу-бизнес","value":"329"},{"label":"Шоу-бизнес","value":"172"},{"label":"Эксгибиционизм","value":"74"},{"label":"Элементы бдсм","value":"185"},{"label":"Эмма уотсон","value":"342"},{"label":"Эмма Уотсон","value":"169"},{"label":"Эротика","value":"36"},{"label":"Этти","value":"327"},{"label":"Юмор","value":"105"},{"label":"Яндере","value":"155"},{"label":"Bl","value":"125"},{"label":"Dc","value":"411"},{"label":"Gl","value":"96"},{"label":"Harry potter","value":"190"},{"label":"Harry potter","value":"168"},{"label":"Hentai","value":"282"},{"label":"Marvel","value":"194"},{"label":"Marvel","value":"174"},{"label":"Milf","value":"167"},{"label":"Mj","value":"401"}],"inputType":FilterInputs.Checkbox},{"key":"fandoms","label":"Фэндом:","values":[{"label":"Аватар: Легенда о Корре / Avatar legend of Korra","value":"46"},{"label":"Аватар: Легенда об Аанге / Avatar: The Legend of Aang / Avatar: The Last Airbender","value":"45"},{"label":"Аладдин / Aladdin","value":"86"},{"label":"Алиса в Стране чудес / Alice in Wonderland","value":"90"},{"label":"Американский папаша / American Dad","value":"85"},{"label":"Атака титанов / Атака на титанов / Attack on Titan","value":"41"},{"label":"Блич / Bleach","value":"58"},{"label":"Боевой континент","value":"101"},{"label":"Большой куш / One Piece","value":"18"},{"label":"Боруто: Новое поколение Наруто / Boruto: Naruto Next Generations","value":"9"},{"label":"Бэтмен / The Batman","value":"36"},{"label":"Ведьмак / The Witcher","value":"53"},{"label":"Военная хроника маленькой девочки","value":"100"},{"label":"Волейбол / Haikyu!!","value":"37"},{"label":"Вселенная Марвел / Marvel Universe","value":"7"},{"label":"Вселенная Марвел / Marvel Universe / Marvel Comics","value":"52"},{"label":"Вселенная Стивена","value":"61"},{"label":"Вселенная DC / DC Universe / DC Comics","value":"48"},{"label":"Гарри Поттер / Harry Potter","value":"4"},{"label":"Гоэтия / Гоетия / Yοητεία / Ars Goetia","value":"77"},{"label":"Демоны старшей школы / High School DxD","value":"10"},{"label":"День сурка / Groundhog Day","value":"3"},{"label":"Джессика Джонс / Marvel's Jessica Jones","value":"42"},{"label":"Дисней / The Walt Disney Company","value":"74"},{"label":"Древние свитки: Скайрим / TES: Skyrim","value":"15"},{"label":"Дэдпул / Deadpool","value":"22"},{"label":"Дэнни-призрак / Danny Phantom","value":"51"},{"label":"Железный человек / Iron Man","value":"19"},{"label":"Звёздная принцесса и силы зла / Стар против сил зла / Star vs. The Forces of Evil","value":"50"},{"label":"Звездные Войны / Star Wars","value":"43"},{"label":"Звёздные Войны / Star Wars","value":"16"},{"label":"Игра престолов","value":"78"},{"label":"Касльвания / Castlevania","value":"29"},{"label":"Киберпанк 2077 / Cyberpunk 2077","value":"6"},{"label":"Код Гиас / Code Geass","value":"84"},{"label":"Кольцо Элдена","value":"60"},{"label":"Королевства Сердец / Kingdom Hearts","value":"93"},{"label":"Красавица и чудовище / Beauty and the Beast","value":"91"},{"label":"Красный, Белый, Черный, Желтый / RWBY","value":"32"},{"label":"Кунг фу панда","value":"81"},{"label":"Лига Легенд / League of Legends","value":"5"},{"label":"Люди Икс / X-Men","value":"25"},{"label":"Маг на полную ставку / Quanzhi Fashi","value":"30"},{"label":"Мастера меча онлайн / Sword Art Online / SAO","value":"47"},{"label":"Мир Тьмы / World of Darkness","value":"28"},{"label":"Мой маленький пони / My Little Pony","value":"72"},{"label":"Мой маленький пони: Дружба — это чудо / My Little Pony: Friendship is Magic","value":"71"},{"label":"Моя геройская академия / Boku no Hero Academia","value":"8"},{"label":"Мстители / The Avengers","value":"20"},{"label":"Мстители. Эра Альтрона / The Avengers. Age of Ultron","value":"24"},{"label":"Мулан / Mulan","value":"94"},{"label":"Наруто / Naruto","value":"2"},{"label":"Овервотч","value":"79"},{"label":"Поднятие уровня в одиночку","value":"87"},{"label":"Порновселенная / Porn Universe","value":"31"},{"label":"Прототип / Prototype","value":"44"},{"label":"Рапунцель: Запутанная история / Tangled","value":"96"},{"label":"Розовая пора моей школьной жизни сплошной обман / Yahari Ore no Seishun Love Come wa Machigatteiru","value":"14"},{"label":"Русалочка / The Little Mermaid","value":"97"},{"label":"Сага о Винланде","value":"66"},{"label":"Светлячок / Firefly","value":"76"},{"label":"Сильнейший в истории ученик Кэнити / Shijou Saikyou no Deshi Kenichi","value":"13"},{"label":"Симпсоны / The Simpsons","value":"73"},{"label":"Судьба: Великий Приказ / Fate: Grand Order","value":"54"},{"label":"Супергёрл(телесериал, 2015) / Supergirl","value":"95"},{"label":"Супермен / Superman","value":"1"},{"label":"Теория большого взрыва / The Big Bang Theory","value":"75"},{"label":"Тор / Thor","value":"27"},{"label":"У Коми-сан проблемы с общением / 古見さんは、コミュ症です / Komi Can't Communicate","value":"11"},{"label":"Убийца Акаме / Akame ga Kill","value":"40"},{"label":"Уэнздей / Wednesday","value":"26"},{"label":"Фантастическая четвёрка / Fantastic Four","value":"21"},{"label":"Флэш / The Flash","value":"17"},{"label":"Хвост Феи / Fairy Tail","value":"59"},{"label":"Холодное сердце / Frozen","value":"92"},{"label":"Человек одного удара / Ванпанчмен / One Punch-Man","value":"39"},{"label":"Человек-паук / Spider-Man","value":"23"},{"label":"Чёрный зверь / Чёрный Пёс / Kuroinu","value":"35"},{"label":"Чёрный зверь: Развращение Благородных Воительниц / Black Beast: Corruption of the Noble Warriors","value":"34"},{"label":"Школа мертвецов","value":"67"},{"label":"Школа строгого режима / Prison School","value":"12"},{"label":"Эффект Массы / Mass Effect","value":"57"},{"label":"Юные Титаны / Teen Titans","value":"49"},{"label":"Ars Goetia | Gods and Demons","value":"69"},{"label":"Biohazard","value":"99"},{"label":"CL","value":"70"},{"label":"Daraku Reijou Hakoiri Ojou-sama Netorare Choukyou Kiroku","value":"55"},{"label":"Doom","value":"64"},{"label":"Granblue fantasy","value":"88"},{"label":"Halo","value":"80"},{"label":"Highschool of the Dead/Школа мертвецов","value":"68"},{"label":"JK Bitch ni Shiboraretai","value":"56"},{"label":"Monogatari Series","value":"65"},{"label":"Monster girl quest","value":"62"},{"label":"Over","value":"102"},{"label":"Rapunzel/Рапунцель","value":"83"},{"label":"Resident Evil","value":"98"},{"label":"Solo leveling","value":"63"},{"label":"Tentacle Locker","value":"89"},{"label":"X-COM","value":"82"}],"inputType":FilterInputs.Checkbox},{"key":"genres_ex","label":"Исключить жанры:","values":[{"label":"Анал","value":"2"},{"label":"Бдсм","value":"3"},{"label":"Большая грудь","value":"5"},{"label":"Большая попка","value":"6"},{"label":"Большой член","value":"7"},{"label":"Бондаж","value":"8"},{"label":"В первый раз","value":"9"},{"label":"В цвете","value":"10"},{"label":"Гарем","value":"11"},{"label":"Гендарная интрига","value":"12"},{"label":"Групповой секс","value":"13"},{"label":"Детектив","value":"39"},{"label":"Драма","value":"14"},{"label":"Зрелые женщины (milf)","value":"15"},{"label":"Измена","value":"16"},{"label":"Изнасилование","value":"17"},{"label":"Инцест","value":"18"},{"label":"Исторический","value":"19"},{"label":"Комедия","value":"20"},{"label":"Контроль над разумом","value":"35"},{"label":"Маленькая грудь","value":"21"},{"label":"Мистика","value":"40"},{"label":"Научная фантастика","value":"22"},{"label":"Нетораре","value":"23"},{"label":"Оральный секс","value":"24"},{"label":"Повседневность","value":"41"},{"label":"Приключения","value":"38"},{"label":"Публичный секс","value":"33"},{"label":"Романтика","value":"25"},{"label":"С изображениями","value":"36"},{"label":"Сверхъестественное","value":"34"},{"label":"Смат","value":"37"},{"label":"Тентакли","value":"26"},{"label":"Трагедия","value":"27"},{"label":"Ужасы","value":"28"},{"label":"Фантастика","value":"32"},{"label":"Фэнтези","value":"29"},{"label":"Чикан","value":"30"},{"label":"Этти","value":"31"},{"label":"Ahegao","value":"1"}],"inputType":FilterInputs.Checkbox},{"key":"tags_ex","label":"Исключить тэги:","values":[{"label":"+18","value":"141"},{"label":"18+","value":"200"},{"label":"21+","value":"334"},{"label":"Адекватные главные герои","value":"253"},{"label":"Азартные игры","value":"210"},{"label":"Айдолы","value":"364"},{"label":"Акула","value":"53"},{"label":"Альтернативное развитие событий","value":"338"},{"label":"Аморальный главный герой","value":"219"},{"label":"Анал","value":"7"},{"label":"Анальный секс","value":"67"},{"label":"Ангелы","value":"114"},{"label":"Антигерой","value":"226"},{"label":"Аристократия","value":"260"},{"label":"Артефакт","value":"379"},{"label":"Афродизиак","value":"276"},{"label":"Ахегао","value":"240"},{"label":"Бабушка беременна от внука","value":"393"},{"label":"Бабушка и внук","value":"380"},{"label":"Бдсм","value":"131"},{"label":"Беременность","value":"148"},{"label":"Бесплатно","value":"79"},{"label":"Бесстрашные персонажи","value":"339"},{"label":"Библиотека","value":"265"},{"label":"Бистиалити","value":"391"},{"label":"Битва за трон","value":"404"},{"label":"Близнецы","value":"198"},{"label":"Блондинка","value":"91"},{"label":"Богатые персонажи","value":"248"},{"label":"Боги","value":"115"},{"label":"Боевик","value":"252"},{"label":"Большая грудь","value":"33"},{"label":"Большая попка","value":"328"},{"label":"Большой член","value":"76"},{"label":"Большой член сына","value":"396"},{"label":"Босс и подчиненный","value":"330"},{"label":"Брак","value":"182"},{"label":"Брак по расчёту","value":"346"},{"label":"Брат","value":"29"},{"label":"Брат и сестра","value":"30"},{"label":"Брюнетка","value":"28"},{"label":"Бэтмен","value":"369"},{"label":"Бэтмен","value":"170"},{"label":"В первый раз","value":"179"},{"label":"Вагинальный секс","value":"57"},{"label":"Вагинальный секс","value":"171"},{"label":"Вайурист","value":"9"},{"label":"Вампиры","value":"133"},{"label":"Ван-пис","value":"335"},{"label":"Веб камера","value":"289"},{"label":"Ведьмы","value":"232"},{"label":"Викинги","value":"307"},{"label":"Виртуальная реальность","value":"382"},{"label":"Вирус","value":"203"},{"label":"Внучка","value":"189"},{"label":"Война","value":"387"},{"label":"Воспоминания из прошлого","value":"405"},{"label":"Враги становятся любовниками","value":"410"},{"label":"Время","value":"81"},{"label":"Второй шанс","value":"244"},{"label":"Вуайеризм","value":"62"},{"label":"Выживание","value":"135"},{"label":"Гарем","value":"107"},{"label":"Гарри поттер","value":"97"},{"label":"Гвен","value":"402"},{"label":"Гг имба","value":"87"},{"label":"Генетические модификации","value":"314"},{"label":"Гипноз","value":"143"},{"label":"Главная героиня девушка","value":"147"},{"label":"Главный герой женщина","value":"213"},{"label":"Главный герой извращенец","value":"116"},{"label":"Главный герой мужчина","value":"117"},{"label":"Глубокое горло","value":"94"},{"label":"Гоблины","value":"230"},{"label":"Город","value":"139"},{"label":"Городское фэнтези","value":"297"},{"label":"Грудное молоко","value":"225"},{"label":"Групповой секс","value":"72"},{"label":"Гэнг-бэнг","value":"235"},{"label":"Гяру","value":"222"},{"label":"Двойное проникновение","value":"42"},{"label":"Двойной анал","value":"47"},{"label":"Дворяне","value":"246"},{"label":"Деамоны старший школы","value":"291"},{"label":"Девственница","value":"119"},{"label":"Девушки-монстры","value":"223"},{"label":"Демоны","value":"98"},{"label":"Детектив","value":"249"},{"label":"Дзёсэй","value":"259"},{"label":"Доктор","value":"326"},{"label":"Дом","value":"138"},{"label":"Доминирование","value":"18"},{"label":"Дочь","value":"153"},{"label":"Дочь беременна от отца","value":"348"},{"label":"Древние времена","value":"383"},{"label":"Древний китай","value":"261"},{"label":"Другой мир","value":"365"},{"label":"Дружба","value":"325"},{"label":"Друзья детства","value":"183"},{"label":"Дядя","value":"160"},{"label":"Жена","value":"70"},{"label":"Жена и муж","value":"99"},{"label":"Жена шлюха","value":"236"},{"label":"Женское доминирование","value":"100"},{"label":"Жесткий секс","value":"283"},{"label":"Жёсткий секс","value":"101"},{"label":"Жестокие персонажи","value":"254"},{"label":"Жестокий мир","value":"336"},{"label":"Жестокость","value":"123"},{"label":"Заботливый главный герой","value":"340"},{"label":"Зависимость","value":"370"},{"label":"Заключение","value":"196"},{"label":"Заключённые","value":"384"},{"label":"Замок","value":"140"},{"label":"Запретная любовь","value":"273"},{"label":"Заражение","value":"206"},{"label":"Звёздные войны","value":"120"},{"label":"Зверодевочки","value":"158"},{"label":"Зло","value":"343"},{"label":"Золовка","value":"77"},{"label":"Золотой дождь","value":"146"},{"label":"Зомби апокалипсис","value":"241"},{"label":"Зоофилия","value":"144"},{"label":"Зрелые женщины","value":"398"},{"label":"Игровые элементы","value":"385"},{"label":"Извращения","value":"192"},{"label":"Измена","value":"71"},{"label":"Изменения внешности","value":"315"},{"label":"Изменения личности","value":"316"},{"label":"Изнасилование","value":"275"},{"label":"Изуку мидория","value":"337"},{"label":"Ино","value":"127"},{"label":"Инопланетяне","value":"304"},{"label":"Интересный сюжет","value":"349"},{"label":"Интимные сцены","value":"322"},{"label":"Интриги и заговоры","value":"262"},{"label":"Интроверт","value":"38"},{"label":"Инфекция","value":"207"},{"label":"Инцест","value":"35"},{"label":"Исторический роман","value":"406"},{"label":"Камера","value":"92"},{"label":"Колледж","value":"82"},{"label":"Комикс","value":"286"},{"label":"Контроль","value":"19"},{"label":"Контроль над разумом","value":"181"},{"label":"Контроль разума","value":"65"},{"label":"Кончил внутрь","value":"221"},{"label":"Королевская семья","value":"358"},{"label":"Коррупция","value":"49"},{"label":"Космос","value":"204"},{"label":"Красивая главная героиня","value":"255"},{"label":"Красивые женщины","value":"321"},{"label":"Красивый главный герой","value":"266"},{"label":"Ксенофилия","value":"386"},{"label":"Кулинария","value":"362"},{"label":"Культвация","value":"86"},{"label":"Кунилингус","value":"152"},{"label":"Кушина","value":"399"},{"label":"Лактация","value":"11"},{"label":"Лесби","value":"408"},{"label":"Лишение девственности","value":"212"},{"label":"Лоли","value":"218"},{"label":"Лунатизм","value":"279"},{"label":"Любовь","value":"89"},{"label":"Магический мир","value":"357"},{"label":"Магия","value":"80"},{"label":"Мама","value":"3"},{"label":"Мама беременна от сына","value":"274"},{"label":"Мама и дочь","value":"163"},{"label":"Мама и сын","value":"1"},{"label":"Мама супермена","value":"39"},{"label":"Манипуляция временем","value":"292"},{"label":"Марвел","value":"290"},{"label":"Марвел","value":"173"},{"label":"Марти стью","value":"102"},{"label":"Массаж","value":"224"},{"label":"Мастурбация","value":"63"},{"label":"Мать","value":"239"},{"label":"Мать и дочь","value":"381"},{"label":"Мать и сын","value":"237"},{"label":"Мафия","value":"256"},{"label":"Мачеха","value":"197"},{"label":"Мачеха беременна от сына","value":"395"},{"label":"Мачеха и сын","value":"394"},{"label":"Медсестра","value":"341"},{"label":"Межрассовый","value":"54"},{"label":"Месть","value":"306"},{"label":"Меха","value":"268"},{"label":"Ми","value":"243"},{"label":"Милф","value":"34"},{"label":"Милф","value":"180"},{"label":"Минет","value":"52"},{"label":"Мистика","value":"250"},{"label":"Младшая сестра","value":"154"},{"label":"Много спермы","value":"409"},{"label":"Модель","value":"324"},{"label":"Монстры","value":"333"},{"label":"Мошеничество","value":"44"},{"label":"Мужская беременность","value":"363"},{"label":"Мужчина протагонист","value":"108"},{"label":"Музыка","value":"331"},{"label":"Мэри съюха","value":"309"},{"label":"Наруко","value":"400"},{"label":"Наруто","value":"46"},{"label":"Насилие","value":"128"},{"label":"Насилие и жестокость","value":"193"},{"label":"Научный эксперимент","value":"313"},{"label":"Нежить","value":"373"},{"label":"Некромантия","value":"298"},{"label":"Ненормативная лексика","value":"124"},{"label":"Нетораре","value":"69"},{"label":"Нетори","value":"284"},{"label":"Нижнее бельё","value":"392"},{"label":"Ниндзя","value":"296"},{"label":"Ношеные трусики","value":"166"},{"label":"Нудизм","value":"156"},{"label":"Няня","value":"88"},{"label":"Обмен женами","value":"78"},{"label":"Оборотни","value":"136"},{"label":"Обратный гарем","value":"214"},{"label":"Одержимость","value":"345"},{"label":"Омегаверс","value":"368"},{"label":"Оплодотворение","value":"157"},{"label":"Оральный секс","value":"10"},{"label":"Оргия","value":"356"},{"label":"Орки","value":"388"},{"label":"От слабого к сильному","value":"351"},{"label":"Отец","value":"2"},{"label":"Отец делится с сыном","value":"6"},{"label":"Отец и дочь","value":"205"},{"label":"Отец куколд","value":"272"},{"label":"Офис","value":"234"},{"label":"Падчерица","value":"271"},{"label":"Пайзури","value":"195"},{"label":"Папа и дочь","value":"360"},{"label":"Паразиты","value":"208"},{"label":"Параллельный мир","value":"320"},{"label":"Пародия","value":"371"},{"label":"Первый раз","value":"159"},{"label":"Перемещение в другой мир","value":"347"},{"label":"Перемещение во времени","value":"245"},{"label":"Перерождение","value":"109"},{"label":"Перерождение в злодея","value":"202"},{"label":"Пирсинг","value":"145"},{"label":"Писатель","value":"267"},{"label":"Планомерное развитие событий","value":"350"},{"label":"Повседневность","value":"247"},{"label":"Подглядывание","value":"280"},{"label":"Подчинение","value":"106"},{"label":"Подчинение и унижение","value":"211"},{"label":"Поедание киски","value":"26"},{"label":"Покемоны","value":"132"},{"label":"Покорная","value":"8"},{"label":"Полигамия","value":"352"},{"label":"Половое воспитание","value":"37"},{"label":"Полулюди","value":"231"},{"label":"Попаданец","value":"103"},{"label":"Попадание в книгу","value":"361"},{"label":"Порка","value":"20"},{"label":"Порно","value":"278"},{"label":"Постапокалипсис","value":"332"},{"label":"Потеря девственности","value":"142"},{"label":"Похищение","value":"161"},{"label":"Преданные любовный интерес","value":"407"},{"label":"Призраки","value":"412"},{"label":"Приключения","value":"134"},{"label":"Принуждение","value":"66"},{"label":"Психология","value":"238"},{"label":"Публично","value":"85"},{"label":"Публичный секс","value":"233"},{"label":"Раб","value":"353"},{"label":"Рабы","value":"308"},{"label":"Разват","value":"58"},{"label":"Разврат","value":"64"},{"label":"Райзен","value":"95"},{"label":"Раса инопланетных космических лесбиянок","value":"294"},{"label":"Религия","value":"403"},{"label":"Рестленг","value":"84"},{"label":"Риас гремори","value":"389"},{"label":"Романтика","value":"178"},{"label":"Рыжий","value":"90"},{"label":"С","value":"413"},{"label":"Сакура","value":"126"},{"label":"Самолет","value":"93"},{"label":"Санса старк","value":"277"},{"label":"Санта","value":"372"},{"label":"Свадьба","value":"73"},{"label":"Сверхсила","value":"228"},{"label":"Сверхъестественное","value":"319"},{"label":"Свингеры","value":"201"},{"label":"Свободные отношения","value":"186"},{"label":"Связывание","value":"137"},{"label":"Сёдзе","value":"264"},{"label":"Секс","value":"21"},{"label":"Секс без проникновения","value":"68"},{"label":"Секс втроем","value":"43"},{"label":"Секс игрушки","value":"59"},{"label":"Секс рабыня","value":"55"},{"label":"Секс с монстрами","value":"56"},{"label":"Секс с учителем","value":"184"},{"label":"Секса будет много","value":"151"},{"label":"Сексуальное желание","value":"209"},{"label":"Селфцест","value":"397"},{"label":"Семья","value":"5"},{"label":"Сестра","value":"31"},{"label":"Сестра беременна от брата","value":"355"},{"label":"Сильный с самого начала","value":"112"},{"label":"Симбиоз","value":"50"},{"label":"Сирена","value":"51"},{"label":"Система","value":"104"},{"label":"Сиськи","value":"285"},{"label":"Сквирт","value":"164"},{"label":"Скрытый секс","value":"287"},{"label":"Служанка","value":"215"},{"label":"Соб","value":"281"},{"label":"Соблазнение","value":"162"},{"label":"Современность","value":"217"},{"label":"Соколиный Глаз","value":"176"},{"label":"Соперничество","value":"216"},{"label":"Соседи","value":"61"},{"label":"Соседка","value":"312"},{"label":"Сперма","value":"229"},{"label":"Сперма на лицо","value":"199"},{"label":"Спящие","value":"187"},{"label":"Старшая сестра","value":"311"},{"label":"Стеб","value":"111"},{"label":"Студенты","value":"177"},{"label":"Суккуб","value":"390"},{"label":"Супергерои","value":"305"},{"label":"Суперспособности","value":"300"},{"label":"Сын","value":"4"},{"label":"Твинцест","value":"188"},{"label":"Темное фэнтези","value":"293"},{"label":"Тентакли","value":"303"},{"label":"Тетя","value":"113"},{"label":"Тетя беременна от племянника","value":"376"},{"label":"Тетя и племянник","value":"377"},{"label":"Техника","value":"302"},{"label":"Технологии","value":"301"},{"label":"Тёща","value":"270"},{"label":"Тиран","value":"310"},{"label":"Трагическое прошлое","value":"251"},{"label":"Трансмиграция","value":"269"},{"label":"Трансформация","value":"317"},{"label":"Триллер","value":"344"},{"label":"Трусики","value":"165"},{"label":"Убийства","value":"258"},{"label":"Удача","value":"299"},{"label":"Ужасы","value":"375"},{"label":"Улучшение тела","value":"288"},{"label":"Умная главная героиня","value":"242"},{"label":"Умные персонажи","value":"257"},{"label":"Умный главный герой","value":"354"},{"label":"Университет","value":"323"},{"label":"Ученик","value":"83"},{"label":"Ф","value":"149"},{"label":"Фанатичная любовь","value":"366"},{"label":"Фанаты","value":"367"},{"label":"Фантастика","value":"295"},{"label":"Фанфик","value":"40"},{"label":"Фелляция","value":"22"},{"label":"Ферма","value":"191"},{"label":"Фетиш","value":"60"},{"label":"Флэш","value":"121"},{"label":"Футанария","value":"150"},{"label":"Фэнтези","value":"359"},{"label":"Хентай","value":"75"},{"label":"Хината","value":"110"},{"label":"Холодная главная героиня","value":"263"},{"label":"Черная вдова","value":"220"},{"label":"Черная Вдова","value":"175"},{"label":"Черный юмор","value":"374"},{"label":"Читерство","value":"45"},{"label":"Чтение мыслей","value":"227"},{"label":"Чудовища","value":"378"},{"label":"Шантаж","value":"129"},{"label":"Школа","value":"118"},{"label":"Школьная жизнь","value":"318"},{"label":"Шлюха","value":"32"},{"label":"Шоу-бизнес","value":"329"},{"label":"Шоу-бизнес","value":"172"},{"label":"Эксгибиционизм","value":"74"},{"label":"Элементы бдсм","value":"185"},{"label":"Эмма уотсон","value":"342"},{"label":"Эмма Уотсон","value":"169"},{"label":"Эротика","value":"36"},{"label":"Этти","value":"327"},{"label":"Юмор","value":"105"},{"label":"Яндере","value":"155"},{"label":"Bl","value":"125"},{"label":"Dc","value":"411"},{"label":"Gl","value":"96"},{"label":"Harry potter","value":"190"},{"label":"Harry potter","value":"168"},{"label":"Hentai","value":"282"},{"label":"Marvel","value":"194"},{"label":"Marvel","value":"174"},{"label":"Milf","value":"167"},{"label":"Mj","value":"401"}],"inputType":FilterInputs.Checkbox},{"key":"fandoms_ex","label":"Исключить фэндомы:","values":[{"label":"Аватар: Легенда о Корре / Avatar legend of Korra","value":"46"},{"label":"Аватар: Легенда об Аанге / Avatar: The Legend of Aang / Avatar: The Last Airbender","value":"45"},{"label":"Аладдин / Aladdin","value":"86"},{"label":"Алиса в Стране чудес / Alice in Wonderland","value":"90"},{"label":"Американский папаша / American Dad","value":"85"},{"label":"Атака титанов / Атака на титанов / Attack on Titan","value":"41"},{"label":"Блич / Bleach","value":"58"},{"label":"Боевой континент","value":"101"},{"label":"Большой куш / One Piece","value":"18"},{"label":"Боруто: Новое поколение Наруто / Boruto: Naruto Next Generations","value":"9"},{"label":"Бэтмен / The Batman","value":"36"},{"label":"Ведьмак / The Witcher","value":"53"},{"label":"Военная хроника маленькой девочки","value":"100"},{"label":"Волейбол / Haikyu!!","value":"37"},{"label":"Вселенная Марвел / Marvel Universe","value":"7"},{"label":"Вселенная Марвел / Marvel Universe / Marvel Comics","value":"52"},{"label":"Вселенная Стивена","value":"61"},{"label":"Вселенная DC / DC Universe / DC Comics","value":"48"},{"label":"Гарри Поттер / Harry Potter","value":"4"},{"label":"Гоэтия / Гоетия / Yοητεία / Ars Goetia","value":"77"},{"label":"Демоны старшей школы / High School DxD","value":"10"},{"label":"День сурка / Groundhog Day","value":"3"},{"label":"Джессика Джонс / Marvel's Jessica Jones","value":"42"},{"label":"Дисней / The Walt Disney Company","value":"74"},{"label":"Древние свитки: Скайрим / TES: Skyrim","value":"15"},{"label":"Дэдпул / Deadpool","value":"22"},{"label":"Дэнни-призрак / Danny Phantom","value":"51"},{"label":"Железный человек / Iron Man","value":"19"},{"label":"Звёздная принцесса и силы зла / Стар против сил зла / Star vs. The Forces of Evil","value":"50"},{"label":"Звездные Войны / Star Wars","value":"43"},{"label":"Звёздные Войны / Star Wars","value":"16"},{"label":"Игра престолов","value":"78"},{"label":"Касльвания / Castlevania","value":"29"},{"label":"Киберпанк 2077 / Cyberpunk 2077","value":"6"},{"label":"Код Гиас / Code Geass","value":"84"},{"label":"Кольцо Элдена","value":"60"},{"label":"Королевства Сердец / Kingdom Hearts","value":"93"},{"label":"Красавица и чудовище / Beauty and the Beast","value":"91"},{"label":"Красный, Белый, Черный, Желтый / RWBY","value":"32"},{"label":"Кунг фу панда","value":"81"},{"label":"Лига Легенд / League of Legends","value":"5"},{"label":"Люди Икс / X-Men","value":"25"},{"label":"Маг на полную ставку / Quanzhi Fashi","value":"30"},{"label":"Мастера меча онлайн / Sword Art Online / SAO","value":"47"},{"label":"Мир Тьмы / World of Darkness","value":"28"},{"label":"Мой маленький пони / My Little Pony","value":"72"},{"label":"Мой маленький пони: Дружба — это чудо / My Little Pony: Friendship is Magic","value":"71"},{"label":"Моя геройская академия / Boku no Hero Academia","value":"8"},{"label":"Мстители / The Avengers","value":"20"},{"label":"Мстители. Эра Альтрона / The Avengers. Age of Ultron","value":"24"},{"label":"Мулан / Mulan","value":"94"},{"label":"Наруто / Naruto","value":"2"},{"label":"Овервотч","value":"79"},{"label":"Поднятие уровня в одиночку","value":"87"},{"label":"Порновселенная / Porn Universe","value":"31"},{"label":"Прототип / Prototype","value":"44"},{"label":"Рапунцель: Запутанная история / Tangled","value":"96"},{"label":"Розовая пора моей школьной жизни сплошной обман / Yahari Ore no Seishun Love Come wa Machigatteiru","value":"14"},{"label":"Русалочка / The Little Mermaid","value":"97"},{"label":"Сага о Винланде","value":"66"},{"label":"Светлячок / Firefly","value":"76"},{"label":"Сильнейший в истории ученик Кэнити / Shijou Saikyou no Deshi Kenichi","value":"13"},{"label":"Симпсоны / The Simpsons","value":"73"},{"label":"Судьба: Великий Приказ / Fate: Grand Order","value":"54"},{"label":"Супергёрл(телесериал, 2015) / Supergirl","value":"95"},{"label":"Супермен / Superman","value":"1"},{"label":"Теория большого взрыва / The Big Bang Theory","value":"75"},{"label":"Тор / Thor","value":"27"},{"label":"У Коми-сан проблемы с общением / 古見さんは、コミュ症です / Komi Can't Communicate","value":"11"},{"label":"Убийца Акаме / Akame ga Kill","value":"40"},{"label":"Уэнздей / Wednesday","value":"26"},{"label":"Фантастическая четвёрка / Fantastic Four","value":"21"},{"label":"Флэш / The Flash","value":"17"},{"label":"Хвост Феи / Fairy Tail","value":"59"},{"label":"Холодное сердце / Frozen","value":"92"},{"label":"Человек одного удара / Ванпанчмен / One Punch-Man","value":"39"},{"label":"Человек-паук / Spider-Man","value":"23"},{"label":"Чёрный зверь / Чёрный Пёс / Kuroinu","value":"35"},{"label":"Чёрный зверь: Развращение Благородных Воительниц / Black Beast: Corruption of the Noble Warriors","value":"34"},{"label":"Школа мертвецов","value":"67"},{"label":"Школа строгого режима / Prison School","value":"12"},{"label":"Эффект Массы / Mass Effect","value":"57"},{"label":"Юные Титаны / Teen Titans","value":"49"},{"label":"Ars Goetia | Gods and Demons","value":"69"},{"label":"Biohazard","value":"99"},{"label":"CL","value":"70"},{"label":"Daraku Reijou Hakoiri Ojou-sama Netorare Choukyou Kiroku","value":"55"},{"label":"Doom","value":"64"},{"label":"Granblue fantasy","value":"88"},{"label":"Halo","value":"80"},{"label":"Highschool of the Dead/Школа мертвецов","value":"68"},{"label":"JK Bitch ni Shiboraretai","value":"56"},{"label":"Monogatari Series","value":"65"},{"label":"Monster girl quest","value":"62"},{"label":"Over","value":"102"},{"label":"Rapunzel/Рапунцель","value":"83"},{"label":"Resident Evil","value":"98"},{"label":"Solo leveling","value":"63"},{"label":"Tentacle Locker","value":"89"},{"label":"X-COM","value":"82"}],"inputType":FilterInputs.Checkbox},{"key":"atmosphere","label":"Атмосфера:","values":[{"label":"Неважно","value":"0"},{"label":"Позитивная","value":"1"},{"label":"Dark","value":"2"}],"inputType":FilterInputs.Picker},{"key":"adult","label":"Возрастные ограничения:","values":[{"label":"Все","value":"0"},{"label":"Только 18+","value":"2"},{"label":"Убрать 18+","value":"1"}],"inputType":FilterInputs.Picker}];
\ No newline at end of file
diff --git a/plugins/russian/LitSpace.ts b/plugins/russian/LitSpace.broken.ts
similarity index 100%
rename from plugins/russian/LitSpace.ts
rename to plugins/russian/LitSpace.broken.ts
diff --git a/plugins/russian/Rulate[rulate].ts b/plugins/russian/Rulate[rulate].ts
deleted file mode 100644
index 8e88c19..0000000
--- a/plugins/russian/Rulate[rulate].ts
+++ /dev/null
@@ -1,226 +0,0 @@
-
-import { load as parseHTML } from "cheerio";
-// import dayjs from 'dayjs';
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-// import { parseMadaraDate } from "@libs/parseMadaraDate";
-// import { isUrlAbsolute } from '@libs/isAbsoluteUrl';
-// import { showToast } from "@libs/showToast";
-import { FilterInputs } from "@libs/filterInputs";
-import { NovelStatus } from '@libs/novelStatus';
-// import { defaultCover } from "@libs/defaultCover";
-
-export const id = "tl.rulate";
-export const name = "Rulate";
-export const icon = "multisrc/rulate/icons/rulate.png";
-export const version = "1.0.0";
-export const site = "https://tl.rulate.ru";
-
-export const popularNovels: Plugin.popularNovels = async function (
- page,
- { filters, showLatestNovels }
-) {
- let url = site + '/search?t=';
- url += '&cat=' + (filters?.cat || '0');
- url += '&s_lang=' + (filters?.s_lang || '0');
- url += '&t_lang=' + (filters?.t_lang || '0');
- url += '&type=' + (filters?.type || '0');
- url += '&sort=' + (showLatestNovels ? '4' : (filters?.sort || '6'));
- url += '&atmosphere=' + (filters?.atmosphere || '0');
- url += '&adult=' + (filters?.adult || '0');
-
- if (filters?.genres instanceof Array) {
- url += filters.genres.map(i => '&genres[]=' + i).join('');
- }
-
- if (filters?.genres_ex instanceof Array) {
- url += filters.genres_ex.map(i => '&genres_ex[]=' + i).join('');
- }
-
- if (filters?.tags instanceof Array) {
- url += filters.tags.map(i => '&tags[]=' + i).join('');
- }
-
- if (filters?.tags_ex instanceof Array) {
- url += filters.tags_ex.map(i => '&tags_ex[]=' + i).join('');
- }
-
- if (filters?.fandoms instanceof Array) {
- url += filters.fandoms.map(i => '&fandoms[]=' + i).join('');
- }
-
- if (filters?.fandoms_ex instanceof Array) {
- url += filters.fandoms_ex.map(i => '&fandoms_ex[]=' + i).join('');
- }
-
- if (filters?.trash instanceof Array) {
- url += filters.trash.map(i => '&' + i + '=1').join('');
- }
-
- url += '&Book_page=' + page;
-
- const result = await fetchApi(url);
- const body = await result.text();
- const loadedCheerio = parseHTML(body);
-
- const novels: Novel.Item[] = [];
-
- loadedCheerio(
- 'ul[class="search-results"] > li:not([class="ad_type_catalog"])',
- ).each(function () {
- novels.push({
- name: loadedCheerio(this).find('p > a').text(),
- cover: site + loadedCheerio(this).find('img').attr('src'),
- url: site + loadedCheerio(this).find('p > a').attr('href') || '',
- });
- });
-
- return novels;
-};
-
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters =
- async function (novelUrl) {
- const novel: Novel.instance = {
- url: novelUrl,
- chapters: [],
- };
- let result = await fetchApi(novelUrl);
- if (result.url.includes('mature?path=')) {
- const formData = new FormData();
- formData.append('path', novelUrl);
- formData.append('ok', 'Да');
-
- await fetchApi(result.url, {
- method: 'POST',
- body: formData,
- });
-
- result = await fetchApi(novelUrl);
- }
- const body = await result.text();
- const loadedCheerio = parseHTML(body);
-
- novel.name = loadedCheerio('div[class="container"] > div > div > h1, div.span8:nth-child(1) > h1:nth-child(2)')
- .text()
- .trim();
- novel.cover =
- site + loadedCheerio('div[class="images"] > div img').attr('src');
- novel.summary = loadedCheerio('#Info > div:nth-child(3), .book-description').text();
- novel.author = loadedCheerio('.book-stats-icons_author > span:nth-child(2) > a:nth-child(1)').text()
- let genres: string[] = [];
-
- loadedCheerio('div.span5 > p, .span5 > div:nth-child(2) > p').each(function () {
- switch (loadedCheerio(this).find('strong').text()) {
- case 'Автор:':
- novel.author = loadedCheerio(this).find('em > a').text().trim();
- break;
- case 'Выпуск:':
- novel.status =
- loadedCheerio(this).find('em').text().trim() === 'продолжается'
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- case 'Тэги:':
- loadedCheerio(this)
- .find('em > a')
- .each(function () {
- genres.push(loadedCheerio(this).text());
- });
- break;
- case 'Жанры:':
- loadedCheerio(this)
- .find('em > a')
- .each(function () {
- genres.push(loadedCheerio(this).text());
- });
- break;
- }
- });
-
- if (genres.length > 0) {
- novel.genres = genres.reverse().join(',');
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('table > tbody > tr.chapter_row').each(function () {
- const chapterName = loadedCheerio(this)
- .find('td[class="t"] > a')
- .text()
- .trim();
- const releaseDate = loadedCheerio(this)
- .find('td > span')
- .attr('title')
- ?.trim();
- const chapterUrl = site + loadedCheerio(this)
- .find('td[class="t"] > a')
- .attr('href');
-
- if (
- loadedCheerio(this).find('td > span[class="disabled"]').length < 1 &&
- releaseDate
- ) {
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- }
- });
-
- novel.chapters = chapters;
- return novel;
- };
-
-export const parseChapter: Plugin.parseChapter = async function (chapterUrl) {
- let result = await fetchApi(chapterUrl);
- if (result.url.includes('mature?path=')) {
- const formData = new FormData();
- formData.append('ok', 'Да');
-
- await fetchApi(result.url, {
- method: 'POST',
- body: formData,
- });
-
- result = await fetchApi(chapterUrl);
- }
- const body = await result.text();
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.content-text img').each(function () {
- if (!loadedCheerio(this).attr('src')?.startsWith('http')) {
- const src = loadedCheerio(this).attr('src');
- loadedCheerio(this).attr('src', site + src);
- }
- });
-
- const chapterText = loadedCheerio('.content-text').html();
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const result = await fetchApi(
- site + '/search/autocomplete?query=' + searchTerm,
- );
- let json = await result.json() as response[];
-
- json.forEach((item) => {
- const novelName = item.title_one + ' / ' + item.title_two;
- const novelCover = site + item.img;
- const novelUrl = site + item.url;
-
- novels.push({ name: novelName, cover: novelCover, url: novelUrl });
- });
-
- return novels;
-};
-
-interface response {
- id: number;
- title_one: string;
- title_two: string;
- url: string;
- img: string;
-};
-
-export const fetchImage: Plugin.fetchImage = fetchFile;
-
-export const filters = [{"key":"cat","label":"Из раздела каталога:","values":[{"label":"Неважно","value":"0"},{"label":"Авторские","value":"18"},{"label":"Авторские","value":"35"},{"label":"Авторские фанфики","value":"51"},{"label":"Английские","value":"28"},{"label":"Английские","value":"34"},{"label":"Английские","value":"48"},{"label":"Аниме","value":"20"},{"label":"Аудиокниги","value":"25"},{"label":"Блич","value":"42"},{"label":"Большие игры","value":"22"},{"label":"Ван-Пис","value":"41"},{"label":"Визуальные новеллы","value":"8"},{"label":"Вьетнамские","value":"39"},{"label":"Вьетнамские","value":"49"},{"label":"Игры","value":"3"},{"label":"Китайские","value":"5"},{"label":"Китайские","value":"31"},{"label":"Китайские","value":"45"},{"label":"Книги","value":"2"},{"label":"Книги","value":"14"},{"label":"Комиксы","value":"29"},{"label":"Корейские","value":"7"},{"label":"Корейские","value":"33"},{"label":"Корейские","value":"47"},{"label":"Маленькие игры","value":"23"},{"label":"Манга","value":"16"},{"label":"Манга","value":"30"},{"label":"Марвел","value":"43"},{"label":"Машинный перевод","value":"44"},{"label":"Наруто","value":"40"},{"label":"Новеллы и ранобэ","value":"12"},{"label":"Переводы фанфиков","value":"19"},{"label":"Психология","value":"37"},{"label":"Путешествия","value":"36"},{"label":"Статьи","value":"13"},{"label":"Субтитры","value":"15"},{"label":"Фильмы","value":"21"},{"label":"Японские","value":"6"},{"label":"Японские","value":"32"},{"label":"Японские","value":"46"}],"inputType":FilterInputs.Picker},{"key":"s_lang","label":"Язык оригинала:","values":[{"label":"Неважно","value":"0"},{"label":"Абхазский","value":"20"},{"label":"Аварский","value":"21"},{"label":"Азербайджанский","value":"22"},{"label":"Аймара","value":"23"},{"label":"Акан","value":"24"},{"label":"Албанский","value":"25"},{"label":"Амхарский","value":"26"},{"label":"Английский","value":"2"},{"label":"Арабский","value":"27"},{"label":"Арагонский","value":"28"},{"label":"Арберешский","value":"29"},{"label":"Армянский","value":"30"},{"label":"Ассамский","value":"31"},{"label":"Астурийский","value":"32"},{"label":"Афарский","value":"33"},{"label":"Африкаанс","value":"34"},{"label":"Ацтекский","value":"35"},{"label":"Баварский","value":"36"},{"label":"Бамбарийский","value":"37"},{"label":"Баскский","value":"39"},{"label":"Башкирский","value":"40"},{"label":"Белорусский","value":"10"},{"label":"Бенгальский","value":"41"},{"label":"Бирманский","value":"42"},{"label":"Бислама","value":"43"},{"label":"Бихари","value":"44"},{"label":"Болгарский","value":"45"},{"label":"Боснийский","value":"234"},{"label":"Бретонский","value":"47"},{"label":"Валенсийский","value":"48"},{"label":"Валлийский","value":"49"},{"label":"Валлонский","value":"50"},{"label":"Венгерский","value":"51"},{"label":"Венда","value":"52"},{"label":"Венетский","value":"53"},{"label":"Верхнелужицкий","value":"54"},{"label":"Волоф","value":"55"},{"label":"Вьетнамский","value":"57"},{"label":"Гавайский","value":"58"},{"label":"Гаитянский","value":"59"},{"label":"Галисийский","value":"60"},{"label":"Гереро","value":"61"},{"label":"Голландский","value":"62"},{"label":"Греческий","value":"63"},{"label":"Грузинский","value":"64"},{"label":"Гуарани","value":"65"},{"label":"Гуджарати","value":"66"},{"label":"Датский","value":"19"},{"label":"Дзонг-кэ","value":"68"},{"label":"Древнегреческий","value":"69"},{"label":"Западно-фламандский","value":"70"},{"label":"Зулу","value":"71"},{"label":"Иврит","value":"15"},{"label":"Игбо","value":"72"},{"label":"Идиш","value":"73"},{"label":"Илоко","value":"74"},{"label":"Индонезийский","value":"75"},{"label":"Интерлингва","value":"76"},{"label":"Инуктитут","value":"77"},{"label":"Инупиак","value":"78"},{"label":"Ирландский","value":"79"},{"label":"Исландский","value":"80"},{"label":"Испанский","value":"6"},{"label":"Итальянский","value":"5"},{"label":"Йоруба","value":"81"},{"label":"Кабильский","value":"82"},{"label":"Казахский","value":"83"},{"label":"Калмыцкий","value":"235"},{"label":"Каннада","value":"84"},{"label":"Кантонский юэ","value":"85"},{"label":"Канури","value":"86"},{"label":"Каталанский","value":"87"},{"label":"Кашмири","value":"88"},{"label":"Кечуа","value":"90"},{"label":"Кикуйю","value":"91"},{"label":"Киньяруанда","value":"92"},{"label":"Киргизский","value":"93"},{"label":"Китайский","value":"7"},{"label":"Клингонский","value":"94"},{"label":"Коми","value":"95"},{"label":"Конго","value":"96"},{"label":"Конкани","value":"97"},{"label":"Корейский","value":"98"},{"label":"Корсиканский","value":"100"},{"label":"Котава","value":"101"},{"label":"Кри","value":"102"},{"label":"Курдский","value":"105"},{"label":"Кхмерский","value":"107"},{"label":"Лакский","value":"233"},{"label":"Лаосский","value":"109"},{"label":"Латынь","value":"110"},{"label":"Латышский","value":"111"},{"label":"Лезгинский","value":"112"},{"label":"Лимбургский","value":"113"},{"label":"Лингала","value":"114"},{"label":"Литовский","value":"115"},{"label":"Луба","value":"118"},{"label":"Луганда","value":"119"},{"label":"Люксембургский","value":"120"},{"label":"Македонский","value":"121"},{"label":"Малагасийский","value":"122"},{"label":"Малайский","value":"123"},{"label":"Мальдивский","value":"125"},{"label":"Мальтийский","value":"126"},{"label":"Маори","value":"127"},{"label":"Марийский","value":"232"},{"label":"Маршалльский","value":"130"},{"label":"Молдавский","value":"11"},{"label":"Монгольский","value":"133"},{"label":"Мяо (хмонг)","value":"209"},{"label":"Навахо","value":"135"},{"label":"Неаполитанский","value":"139"},{"label":"Немецкий","value":"3"},{"label":"Непальский","value":"140"},{"label":"Норвежский","value":"18"},{"label":"Осетинский","value":"147"},{"label":"Пакистанский","value":"230"},{"label":"Пенджабский","value":"149"},{"label":"Персидский","value":"151"},{"label":"Польский","value":"152"},{"label":"Португальский","value":"153"},{"label":"Румынский","value":"158"},{"label":"Русский","value":"1"},{"label":"Санскрит","value":"163"},{"label":"Сардинский","value":"164"},{"label":"Сербохорватский","value":"166"},{"label":"Словацкий","value":"170"},{"label":"Словенский","value":"171"},{"label":"Сомали","value":"172"},{"label":"Старотурецкий","value":"174"},{"label":"Суахили","value":"175"},{"label":"Сунданский","value":"176"},{"label":"Тагальский","value":"177"},{"label":"Таджикский","value":"178"},{"label":"Таитянский","value":"179"},{"label":"Тайваньский","value":"180"},{"label":"Тайский","value":"181"},{"label":"Тамильский","value":"182"},{"label":"Татарский","value":"12"},{"label":"Телугу","value":"184"},{"label":"Тибетский","value":"185"},{"label":"Тигринья","value":"186"},{"label":"Ток-писин","value":"187"},{"label":"Токи пона","value":"188"},{"label":"Тонганский","value":"189"},{"label":"Тсвана","value":"191"},{"label":"Тсонга","value":"192"},{"label":"Турецкий","value":"193"},{"label":"Туркменский","value":"194"},{"label":"Удмуртский","value":"196"},{"label":"Узбекский","value":"197"},{"label":"Уйгурский","value":"198"},{"label":"Украинский","value":"9"},{"label":"Фиджийский","value":"201"},{"label":"Филиппинский","value":"229"},{"label":"Финский","value":"17"},{"label":"Французский","value":"4"},{"label":"Фризский","value":"203"},{"label":"Фулах","value":"204"},{"label":"Хауса","value":"206"},{"label":"Хинди","value":"207"},{"label":"Хири-моту","value":"208"},{"label":"Чеченский","value":"213"},{"label":"Чешский","value":"13"},{"label":"Чувашский","value":"217"},{"label":"Шведский","value":"16"},{"label":"Швейцарский немецкий","value":"218"},{"label":"Шона","value":"219"},{"label":"Шотландский","value":"67"},{"label":"Эве","value":"221"},{"label":"Эскимосский","value":"223"},{"label":"Эсперанто","value":"14"},{"label":"Эстонский","value":"224"},{"label":"Южно-корейский","value":"231"},{"label":"Юкатекский","value":"225"},{"label":"Яванский","value":"227"},{"label":"Японский","value":"8"}],"inputType":FilterInputs.Picker},{"key":"t_lang","label":"Язык перевода:","values":[{"label":"Неважно","value":"0"},{"label":"Абхазский","value":"20"},{"label":"Аварский","value":"21"},{"label":"Азербайджанский","value":"22"},{"label":"Аймара","value":"23"},{"label":"Акан","value":"24"},{"label":"Албанский","value":"25"},{"label":"Амхарский","value":"26"},{"label":"Английский","value":"2"},{"label":"Арабский","value":"27"},{"label":"Арагонский","value":"28"},{"label":"Арберешский","value":"29"},{"label":"Армянский","value":"30"},{"label":"Ассамский","value":"31"},{"label":"Астурийский","value":"32"},{"label":"Афарский","value":"33"},{"label":"Африкаанс","value":"34"},{"label":"Ацтекский","value":"35"},{"label":"Баварский","value":"36"},{"label":"Бамбарийский","value":"37"},{"label":"Баскский","value":"39"},{"label":"Башкирский","value":"40"},{"label":"Белорусский","value":"10"},{"label":"Бенгальский","value":"41"},{"label":"Бирманский","value":"42"},{"label":"Бислама","value":"43"},{"label":"Бихари","value":"44"},{"label":"Болгарский","value":"45"},{"label":"Боснийский","value":"234"},{"label":"Бретонский","value":"47"},{"label":"Валенсийский","value":"48"},{"label":"Валлийский","value":"49"},{"label":"Валлонский","value":"50"},{"label":"Венгерский","value":"51"},{"label":"Венда","value":"52"},{"label":"Венетский","value":"53"},{"label":"Верхнелужицкий","value":"54"},{"label":"Волоф","value":"55"},{"label":"Вьетнамский","value":"57"},{"label":"Гавайский","value":"58"},{"label":"Гаитянский","value":"59"},{"label":"Галисийский","value":"60"},{"label":"Гереро","value":"61"},{"label":"Голландский","value":"62"},{"label":"Греческий","value":"63"},{"label":"Грузинский","value":"64"},{"label":"Гуарани","value":"65"},{"label":"Гуджарати","value":"66"},{"label":"Датский","value":"19"},{"label":"Дзонг-кэ","value":"68"},{"label":"Древнегреческий","value":"69"},{"label":"Западно-фламандский","value":"70"},{"label":"Зулу","value":"71"},{"label":"Иврит","value":"15"},{"label":"Игбо","value":"72"},{"label":"Идиш","value":"73"},{"label":"Илоко","value":"74"},{"label":"Индонезийский","value":"75"},{"label":"Интерлингва","value":"76"},{"label":"Инуктитут","value":"77"},{"label":"Инупиак","value":"78"},{"label":"Ирландский","value":"79"},{"label":"Исландский","value":"80"},{"label":"Испанский","value":"6"},{"label":"Итальянский","value":"5"},{"label":"Йоруба","value":"81"},{"label":"Кабильский","value":"82"},{"label":"Казахский","value":"83"},{"label":"Калмыцкий","value":"235"},{"label":"Каннада","value":"84"},{"label":"Кантонский юэ","value":"85"},{"label":"Канури","value":"86"},{"label":"Каталанский","value":"87"},{"label":"Кашмири","value":"88"},{"label":"Кечуа","value":"90"},{"label":"Кикуйю","value":"91"},{"label":"Киньяруанда","value":"92"},{"label":"Киргизский","value":"93"},{"label":"Китайский","value":"7"},{"label":"Клингонский","value":"94"},{"label":"Коми","value":"95"},{"label":"Конго","value":"96"},{"label":"Конкани","value":"97"},{"label":"Корейский","value":"98"},{"label":"Корсиканский","value":"100"},{"label":"Котава","value":"101"},{"label":"Кри","value":"102"},{"label":"Курдский","value":"105"},{"label":"Кхмерский","value":"107"},{"label":"Лакский","value":"233"},{"label":"Лаосский","value":"109"},{"label":"Латынь","value":"110"},{"label":"Латышский","value":"111"},{"label":"Лезгинский","value":"112"},{"label":"Лимбургский","value":"113"},{"label":"Лингала","value":"114"},{"label":"Литовский","value":"115"},{"label":"Луба","value":"118"},{"label":"Луганда","value":"119"},{"label":"Люксембургский","value":"120"},{"label":"Македонский","value":"121"},{"label":"Малагасийский","value":"122"},{"label":"Малайский","value":"123"},{"label":"Мальдивский","value":"125"},{"label":"Мальтийский","value":"126"},{"label":"Маори","value":"127"},{"label":"Марийский","value":"232"},{"label":"Маршалльский","value":"130"},{"label":"Молдавский","value":"11"},{"label":"Монгольский","value":"133"},{"label":"Мяо (хмонг)","value":"209"},{"label":"Навахо","value":"135"},{"label":"Неаполитанский","value":"139"},{"label":"Немецкий","value":"3"},{"label":"Непальский","value":"140"},{"label":"Норвежский","value":"18"},{"label":"Осетинский","value":"147"},{"label":"Пакистанский","value":"230"},{"label":"Пенджабский","value":"149"},{"label":"Персидский","value":"151"},{"label":"Польский","value":"152"},{"label":"Португальский","value":"153"},{"label":"Румынский","value":"158"},{"label":"Русский","value":"1"},{"label":"Санскрит","value":"163"},{"label":"Сардинский","value":"164"},{"label":"Сербохорватский","value":"166"},{"label":"Словацкий","value":"170"},{"label":"Словенский","value":"171"},{"label":"Сомали","value":"172"},{"label":"Старотурецкий","value":"174"},{"label":"Суахили","value":"175"},{"label":"Сунданский","value":"176"},{"label":"Тагальский","value":"177"},{"label":"Таджикский","value":"178"},{"label":"Таитянский","value":"179"},{"label":"Тайваньский","value":"180"},{"label":"Тайский","value":"181"},{"label":"Тамильский","value":"182"},{"label":"Татарский","value":"12"},{"label":"Телугу","value":"184"},{"label":"Тибетский","value":"185"},{"label":"Тигринья","value":"186"},{"label":"Ток-писин","value":"187"},{"label":"Токи пона","value":"188"},{"label":"Тонганский","value":"189"},{"label":"Тсвана","value":"191"},{"label":"Тсонга","value":"192"},{"label":"Турецкий","value":"193"},{"label":"Туркменский","value":"194"},{"label":"Удмуртский","value":"196"},{"label":"Узбекский","value":"197"},{"label":"Уйгурский","value":"198"},{"label":"Украинский","value":"9"},{"label":"Фиджийский","value":"201"},{"label":"Филиппинский","value":"229"},{"label":"Финский","value":"17"},{"label":"Французский","value":"4"},{"label":"Фризский","value":"203"},{"label":"Фулах","value":"204"},{"label":"Хауса","value":"206"},{"label":"Хинди","value":"207"},{"label":"Хири-моту","value":"208"},{"label":"Чеченский","value":"213"},{"label":"Чешский","value":"13"},{"label":"Чувашский","value":"217"},{"label":"Шведский","value":"16"},{"label":"Швейцарский немецкий","value":"218"},{"label":"Шона","value":"219"},{"label":"Шотландский","value":"67"},{"label":"Эве","value":"221"},{"label":"Эскимосский","value":"223"},{"label":"Эсперанто","value":"14"},{"label":"Эстонский","value":"224"},{"label":"Южно-корейский","value":"231"},{"label":"Юкатекский","value":"225"},{"label":"Яванский","value":"227"},{"label":"Японский","value":"8"}],"inputType":FilterInputs.Picker},{"key":"type","label":"Тип:","values":[{"label":"Неважно","value":"0"},{"label":"Только авторские","value":"2"},{"label":"Только переводы","value":"1"}],"inputType":FilterInputs.Picker},{"key":"trash","label":"Другое:","values":[{"label":"Без фэндомов","value":"fandoms_ex_all"},{"label":"Готовые на 100%","value":"ready"},{"label":"Доступные для перевода","value":"tr"},{"label":"Доступные для скачивания","value":"gen"},{"label":"Завершённые проекты","value":"wealth"},{"label":"Распродажа","value":"discount"},{"label":"Только онгоинги","value":"ongoings"},{"label":"Убрать машинный","value":"remove_machinelate"}],"inputType":FilterInputs.Checkbox},{"key":"sort","label":"Сортировка:","values":[{"label":"По рейтингу","value":"6"},{"label":"По дате последней активности","value":"4"},{"label":"По дате создания","value":"3"},{"label":"По кол-ву бесплатных глав","value":"11"},{"label":"По кол-ву в закладках","value":"13"},{"label":"По кол-ву в избранном","value":"14"},{"label":"По кол-ву лайков","value":"8"},{"label":"По кол-ву переведённых глав","value":"7"},{"label":"По кол-ву рецензий","value":"12"},{"label":"По кол-ву страниц","value":"10"},{"label":"По названию на языке оригинала","value":"1"},{"label":"По названию на языке перевода","value":"2"},{"label":"По просмотрам","value":"5"},{"label":"По степени готовности","value":"0"},{"label":"Случайно","value":"9"}],"inputType":FilterInputs.Picker},{"key":"genres","label":"Жанры:","values":[{"label":"18+","value":"52"},{"label":"Арт","value":"1"},{"label":"Боевик","value":"2"},{"label":"Боевые искусства","value":"3"},{"label":"Гаремник","value":"5"},{"label":"Героическое фэнтези","value":"7"},{"label":"Детектив","value":"8"},{"label":"Дзёсэй","value":"9"},{"label":"Додзинси","value":"10"},{"label":"Драма","value":"11"},{"label":"История","value":"13"},{"label":"Киберпанк","value":"46"},{"label":"Кодомо","value":"14"},{"label":"Комедия","value":"15"},{"label":"Литрпг","value":"48"},{"label":"Махо-сёдзё","value":"16"},{"label":"Мелодрама","value":"49"},{"label":"Меха","value":"17"},{"label":"Мистика","value":"18"},{"label":"Научная фантастика","value":"19"},{"label":"Повседневность","value":"20"},{"label":"Постапокалиптика","value":"21"},{"label":"Приключения","value":"22"},{"label":"Психология","value":"23"},{"label":"Романтика","value":"24"},{"label":"Самурайский боевик","value":"25"},{"label":"Сверхъестественное","value":"26"},{"label":"Сёдзё","value":"27"},{"label":"Сёнэн","value":"29"},{"label":"Смат","value":"45"},{"label":"Спорт","value":"31"},{"label":"Сэйнэн","value":"32"},{"label":"Сюаньхуа","value":"44"},{"label":"Сюаньхуань","value":"47"},{"label":"Сянься (XianXia)","value":"42"},{"label":"Трагедия","value":"33"},{"label":"Триллер","value":"34"},{"label":"Ужасы","value":"35"},{"label":"Уся (wuxia)","value":"41"},{"label":"Фантастика","value":"36"},{"label":"Фанфик","value":"50"},{"label":"Фэнтези","value":"37"},{"label":"Школа","value":"38"},{"label":"Этти","value":"39"},{"label":"Bl","value":"43"},{"label":"Gl","value":"40"}],"inputType":FilterInputs.Checkbox},{"key":"tags","label":"Тэги:","values":[{"label":"12+","value":"3316"},{"label":"16+","value":"83"},{"label":"Абсурд","value":"7973"},{"label":"Авантюристы","value":"222"},{"label":"Автомат","value":"5272"},{"label":"Авторский мир","value":"1062"},{"label":"Агрессивные персонажи","value":"3249"},{"label":"Ад","value":"2623"},{"label":"Ад и рай","value":"817"},{"label":"Адам дженсен","value":"1649"},{"label":"Адаптация произведения","value":"192"},{"label":"Адвокат","value":"6340"},{"label":"Адекватные главные герои","value":"1953"},{"label":"Азартные игры","value":"5301"},{"label":"Азгард","value":"3494"},{"label":"Азула","value":"5550"},{"label":"Аид","value":"7641"},{"label":"Айдолы","value":"4081"},{"label":"Академия","value":"316"},{"label":"Акамэ","value":"5059"},{"label":"Аквакинез","value":"5952"},{"label":"Акира","value":"2639"},{"label":"Акнология","value":"4634"},{"label":"Актерское мастерство","value":"4798"},{"label":"Актёры","value":"7506"},{"label":"Активные герои","value":"6376"},{"label":"Акутагава рюноске","value":"4113"},{"label":"Аладдин","value":"6489"},{"label":"Алая ведьма","value":"4767"},{"label":"Алиса","value":"4761"},{"label":"Алкоголь","value":"5508"},{"label":"Аллегория","value":"271"},{"label":"Алукард","value":"4914"},{"label":"Алхимики","value":"1164"},{"label":"Алхимия","value":"1473"},{"label":"Алчность","value":"6897"},{"label":"Альбус дамблдор","value":"5784"},{"label":"Альтернативное развитие событий","value":"5330"},{"label":"Альянсы","value":"328"},{"label":"Амбициозный главный герой","value":"3751"},{"label":"Америка","value":"4082"},{"label":"Амнезия","value":"2207"},{"label":"Аморальный герой","value":"18"},{"label":"Анбу","value":"8129"},{"label":"Ангелы","value":"857"},{"label":"Ангелы и демоны","value":"1327"},{"label":"Ангст","value":"4638"},{"label":"Андроиды","value":"1993"},{"label":"Анимализм","value":"5249"},{"label":"Аниме","value":"1294"},{"label":"Анко митараши","value":"5768"},{"label":"Антагонист","value":"2144"},{"label":"Антигерой","value":"7725"},{"label":"Антиквариат","value":"3552"},{"label":"Антимаг","value":"1348"},{"label":"Антиутопия","value":"662"},{"label":"Апокалипсис","value":"1498"},{"label":"Аристократия","value":"371"},{"label":"Аристократы","value":"7338"},{"label":"Армия","value":"1723"},{"label":"Артас","value":"6700"},{"label":"Артефакты","value":"2296"},{"label":"Археология","value":"6523"},{"label":"Асгард","value":"3635"},{"label":"Ассасин","value":"1415"},{"label":"Асуна","value":"5044"},{"label":"Аугментации","value":"7751"},{"label":"Ацуши накаджима","value":"4109"},{"label":"Аянокоджи киетака","value":"6862"},{"label":"Бандиты","value":"2188"},{"label":"Басейн","value":"6847"},{"label":"Баскетбол","value":"7933"},{"label":"Бастарды","value":"76"},{"label":"Бедность","value":"1207"},{"label":"Без культивации","value":"668"},{"label":"Без любовной линий","value":"2225"},{"label":"Без перерождений","value":"262"},{"label":"Без попаданца","value":"8065"},{"label":"Без системы","value":"747"},{"label":"Без юмора","value":"763"},{"label":"Бездна","value":"1026"},{"label":"Безжалостное домашнее животное","value":"1245"},{"label":"Безжалостные персонажи","value":"2986"},{"label":"Беззаботные персонажи","value":"3123"},{"label":"Безответная любовь","value":"7815"},{"label":"Безработный","value":"2202"},{"label":"Безумие","value":"37"},{"label":"Безумные персонажи","value":"2049"},{"label":"Бейсбол","value":"7623"},{"label":"Беременность","value":"2122"},{"label":"Бесконечный поток","value":"7556"},{"label":"Беспечные персонажи","value":"742"},{"label":"Бесплатно","value":"8403"},{"label":"Бессмертные персонажи","value":"566"},{"label":"Бесстрашные персонажи","value":"6921"},{"label":"Бесстыдные персонажи","value":"1257"},{"label":"Бесстыдный главный герой","value":"8190"},{"label":"Библиотека","value":"4210"},{"label":"Библия","value":"488"},{"label":"Бизнес","value":"704"},{"label":"Биология","value":"2220"},{"label":"Биомехи","value":"1968"},{"label":"Биседзе","value":"777"},{"label":"Битва за веру","value":"721"},{"label":"Битва за трон","value":"7211"},{"label":"Битва королевств","value":"1151"},{"label":"Битва рас","value":"6989"},{"label":"Битвы","value":"1740"},{"label":"Благородные персонажи","value":"2201"},{"label":"Близнецы","value":"2931"},{"label":"Богатство","value":"6522"},{"label":"Богатые персонажи","value":"520"},{"label":"Боги","value":"173"},{"label":"Богини","value":"30"},{"label":"Богиня","value":"8324"},{"label":"Богоубийца","value":"1253"},{"label":"Богохульство","value":"95"},{"label":"Боевая академия","value":"2108"},{"label":"Большая грудь","value":"4717"},{"label":"Борос","value":"6533"},{"label":"Борьба","value":"1925"},{"label":"Борьба за власть","value":"8072"},{"label":"Босс и подчиненный","value":"7157"},{"label":"Бояръ","value":"2307"},{"label":"Брак","value":"1558"},{"label":"Брак по расчету","value":"1389"},{"label":"Брат и сестра","value":"615"},{"label":"Братский комплекс","value":"2321"},{"label":"Броманс","value":"1103"},{"label":"Брошенные дети","value":"2846"},{"label":"Буддизм","value":"1871"},{"label":"Будущее","value":"1820"},{"label":"Бывший муж","value":"8080"},{"label":"Быстрое развитие","value":"1443"},{"label":"Бэтгерл","value":"2584"},{"label":"Бэтмен","value":"4668"},{"label":"В первый раз","value":"6212"},{"label":"В этот же мир","value":"49"},{"label":"Ваканда","value":"8331"},{"label":"Валькирии","value":"4047"},{"label":"Вампиры","value":"2206"},{"label":"Веб камера","value":"5664"},{"label":"Веб новелла","value":"2349"},{"label":"Ведьмак","value":"843"},{"label":"Ведьмы","value":"643"},{"label":"Везучие персонажи","value":"1879"},{"label":"Веном","value":"3994"},{"label":"Вестерн","value":"2131"},{"label":"Вестерос","value":"8171"},{"label":"Взросление","value":"624"},{"label":"Взрослый главный герой","value":"2416"},{"label":"Видео игры","value":"2630"},{"label":"Викинги","value":"267"},{"label":"Вино","value":"6972"},{"label":"Вирт","value":"6213"},{"label":"Виртуальная реальность","value":"325"},{"label":"Вирусы","value":"3327"},{"label":"Владыка демонов","value":"555"},{"label":"Власть","value":"756"},{"label":"Влюбленность","value":"6132"},{"label":"Внешний вид отличается от личности","value":"1938"},{"label":"Внучка","value":"8399"},{"label":"Военные","value":"1096"},{"label":"Возрождение","value":"1160"},{"label":"Воины","value":"287"},{"label":"Война","value":"443"},{"label":"Войны","value":"2431"},{"label":"Воландеморт","value":"4278"},{"label":"Волейбол","value":"6415"},{"label":"Волки","value":"1166"},{"label":"Волшебники","value":"122"},{"label":"Волшебные существа","value":"1689"},{"label":"Волшебство","value":"719"},{"label":"Вор","value":"1399"},{"label":"Воровка","value":"6948"},{"label":"Ворон","value":"848"},{"label":"Воскрешение","value":"6915"},{"label":"Воспоминания из другого мира","value":"1366"},{"label":"Воспоминания из прошлого","value":"1372"},{"label":"Воссоединие семьи","value":"8130"},{"label":"Восхождение","value":"380"},{"label":"Враги становятся любовниками","value":"978"},{"label":"Врата","value":"40"},{"label":"Врата в другой мир","value":"1957"},{"label":"Врач","value":"1243"},{"label":"Временная петля","value":"2852"},{"label":"Врмморпг","value":"2043"},{"label":"Все дозволено","value":"96"},{"label":"Всемогущий главный герой","value":"1414"},{"label":"Второй шанс","value":"2372"},{"label":"Вуайеризм","value":"2498"},{"label":"Выживание","value":"501"},{"label":"Вымышленные существа","value":"3466"},{"label":"Вынужденный брак","value":"7705"},{"label":"Высокие технологии","value":"653"},{"label":"Высокомерные персонажи","value":"3250"},{"label":"Галустян","value":"5199"},{"label":"Гангстеры","value":"7704"},{"label":"Гарем","value":"440"},{"label":"Гарри поттер","value":"226"},{"label":"Геймеры","value":"2130"},{"label":"Генетические модификации","value":"1750"},{"label":"Гениальный главный герой","value":"1500"},{"label":"Гений","value":"1650"},{"label":"Гермиона грейнджер","value":"4280"},{"label":"Герои","value":"185"},{"label":"Гигаполис","value":"8393"},{"label":"Гильгамеш","value":"6031"},{"label":"Гильдии","value":"900"},{"label":"Гильдия авантюристов","value":"1858"},{"label":"Гинтама","value":"4544"},{"label":"Гипноз","value":"358"},{"label":"Главная героиня влюбляется первой","value":"973"},{"label":"Главный герой бог","value":"164"},{"label":"Главный герой влюбляется первым","value":"3629"},{"label":"Главный герой выживальщик","value":"120"},{"label":"Главный герой гонг","value":"7877"},{"label":"Главный герой девушка","value":"257"},{"label":"Главный герой демон","value":"136"},{"label":"Главный герой женщина","value":"7329"},{"label":"Главный герой жестокий","value":"1553"},{"label":"Главный герой извращенец","value":"94"},{"label":"Главный герой имба","value":"2421"},{"label":"Главный герой киборг","value":"7780"},{"label":"Главный герой монстр","value":"869"},{"label":"Главный герой мужчина","value":"1997"},{"label":"Главный герой на стороне сил зла","value":"1514"},{"label":"Главный герой не адекватный","value":"5"},{"label":"Главный герой не психопат","value":"7804"},{"label":"Главный герой не человек","value":"2172"},{"label":"Главный герой не эмоционален","value":"1150"},{"label":"Главный герой подросток","value":"2215"},{"label":"Главный герой позитивный","value":"7787"},{"label":"Главный герой психопат","value":"7803"},{"label":"Главный герой ребенок","value":"2347"},{"label":"Главный герой русский","value":"2417"},{"label":"Главный герой сильный с самого начала","value":"88"},{"label":"Главный герой скрывает свою силу","value":"1059"},{"label":"Главный герой эгоист","value":"8326"},{"label":"Гномы","value":"1870"},{"label":"Гоблины","value":"2029"},{"label":"Годзилла","value":"6990"},{"label":"Големы","value":"1690"},{"label":"Голливуд","value":"7754"},{"label":"Головоломка","value":"1697"},{"label":"Горничные","value":"8091"},{"label":"Гробница","value":"388"},{"label":"Дазай осаму","value":"4112"},{"label":"Даньмэй","value":"3411"},{"label":"Даосизм","value":"258"},{"label":"Дарк соулс","value":"6057"},{"label":"Дарт вейдер","value":"6826"},{"label":"Дафна гринграсс","value":"5192"},{"label":"Дворяне","value":"7204"},{"label":"Девушки","value":"7668"},{"label":"Девушки монстры","value":"2231"},{"label":"Дедушка и внучка","value":"8400"},{"label":"Дейви джонс","value":"8061"},{"label":"Действие","value":"1425"},{"label":"Демон лорд","value":"153"},{"label":"Демонология","value":"2024"},{"label":"Демоны","value":"1406"},{"label":"Дети","value":"580"},{"label":"Джарвис","value":"933"},{"label":"Джедай","value":"4442"},{"label":"Джин","value":"4024"},{"label":"Джокер","value":"3351"},{"label":"Джон сноу","value":"7412"},{"label":"Джоффри баратеон","value":"3936"},{"label":"Дзесэй","value":"678"},{"label":"Дин винчестер","value":"6953"},{"label":"Династии","value":"2982"},{"label":"Динозавры","value":"3666"},{"label":"Директор","value":"1417"},{"label":"Для девушек","value":"1441"},{"label":"Дневник","value":"298"},{"label":"Добби","value":"6762"},{"label":"Добрый мир","value":"1685"},{"label":"Договоры с богами","value":"2152"},{"label":"Договоры с демонами","value":"1922"},{"label":"Доктор","value":"1991"},{"label":"Доктор стрэндж","value":"7634"},{"label":"Доминирование","value":"2054"},{"label":"Дота","value":"6965"},{"label":"Доудзюцу","value":"7133"},{"label":"Дочь","value":"3291"},{"label":"Драко малфой","value":"46"},{"label":"Драконы","value":"282"},{"label":"Драконы оборотни","value":"8082"},{"label":"Древние времена","value":"7781"},{"label":"Древний египет","value":"7614"},{"label":"Древний китай","value":"473"},{"label":"Древний мир","value":"4"},{"label":"Другая вселенная","value":"39"},{"label":"Другие планеты","value":"2371"},{"label":"Другой мир","value":"2248"},{"label":"Дружба","value":"1903"},{"label":"Друзья детства","value":"1153"},{"label":"Духи","value":"114"},{"label":"Духовные силы","value":"1955"},{"label":"Души","value":"1212"},{"label":"Дьявол","value":"1094"},{"label":"Дьявольские фрукты","value":"1564"},{"label":"Дэдпул","value":"4399"},{"label":"Евнух","value":"6293"},{"label":"Европейская атмосфера","value":"5837"},{"label":"Египет","value":"528"},{"label":"Еда","value":"2056"},{"label":"Единороги","value":"437"},{"label":"Екаи","value":"655"},{"label":"Жалкий главный герой","value":"97"},{"label":"Жена","value":"5729"},{"label":"Женское доминирование","value":"4622"},{"label":"Женщина в теле мужчины","value":"2748"},{"label":"Женщина кошка","value":"7513"},{"label":"Жестокие персонажи","value":"3153"},{"label":"Жестокий мир","value":"1532"},{"label":"Жестокость","value":"7880"},{"label":"Животные","value":"7488"},{"label":"Животные компаньоны","value":"2061"},{"label":"Жизнь и смерть","value":"2014"},{"label":"Жнец","value":"6288"},{"label":"Жойен рид","value":"3926"},{"label":"Заботливый главный герой","value":"338"},{"label":"Закалка тела","value":"148"},{"label":"Заклинания","value":"558"},{"label":"Заключенные","value":"3052"},{"label":"Занпакто","value":"1102"},{"label":"Запретная любовь","value":"8033"},{"label":"Запутанный сюжет","value":"1041"},{"label":"Захват мира","value":"315"},{"label":"Зачарованные","value":"4169"},{"label":"Звери","value":"1638"},{"label":"Зверодевочки","value":"2006"},{"label":"Зверолюди","value":"1018"},{"label":"Земля","value":"82"},{"label":"Злая организация","value":"7768"},{"label":"Зло","value":"1512"},{"label":"Злодей","value":"1060"},{"label":"Злодейка","value":"2376"},{"label":"Злой главный герой","value":"616"},{"label":"Злые боги","value":"7109"},{"label":"Злые персонажи","value":"3243"},{"label":"Змей","value":"5721"},{"label":"Знаменитости","value":"1341"},{"label":"Знание медицины","value":"1411"},{"label":"Золушка","value":"2980"},{"label":"Зомби","value":"1743"},{"label":"Зомби апокалипсис","value":"912"},{"label":"Зона 51","value":"3051"},{"label":"Зооморфы","value":"375"},{"label":"Зорро","value":"6736"},{"label":"Зрелые женщины","value":"1458"},{"label":"Игра","value":"663"},{"label":"Игра на выживание","value":"2182"},{"label":"Игровая система","value":"384"},{"label":"Игровые элементы","value":"720"},{"label":"Извращения","value":"651"},{"label":"Измена","value":"1874"},{"label":"Изменение характера","value":"1113"},{"label":"Изменения внешности","value":"259"},{"label":"Изменения личности","value":"1080"},{"label":"Изобретения","value":"126"},{"label":"Изуку мидория","value":"6967"},{"label":"Император","value":"867"},{"label":"Империи","value":"712"},{"label":"Империя","value":"1716"},{"label":"Инвалидность","value":"2073"},{"label":"Инквизитор","value":"143"},{"label":"Инкуб","value":"3264"},{"label":"Инопланетное вторжение","value":"209"},{"label":"Инопланетяне","value":"866"},{"label":"Интерактив с читателями","value":"472"},{"label":"Интересный сюжет","value":"7374"},{"label":"Интернет","value":"739"},{"label":"Интимные сцены","value":"3450"},{"label":"Интрига","value":"317"},{"label":"Интриги и заговоры","value":"1009"},{"label":"Иные миры","value":"35"},{"label":"Исекай","value":"2979"},{"label":"Искусственный интеллект","value":"1900"},{"label":"Исследование","value":"1626"},{"label":"Исторический роман","value":"573"},{"label":"Итачи учиха","value":"4556"},{"label":"Ичиго","value":"7254"},{"label":"Йода","value":"6829"},{"label":"Йоруичи","value":"6755"},{"label":"Калипсо","value":"8062"},{"label":"Каннибализм","value":"2249"},{"label":"Капитан америка","value":"6301"},{"label":"Каракура","value":"7473"},{"label":"Карточная игра","value":"1557"},{"label":"Кастиэль","value":"6954"},{"label":"Кафе","value":"3934"},{"label":"Кацуки бакуго","value":"7696"},{"label":"Квесты","value":"1707"},{"label":"Киберспорт","value":"1984"},{"label":"Кино","value":"7126"},{"label":"Китай","value":"3762"},{"label":"Кицунэ","value":"241"},{"label":"Кланы","value":"834"},{"label":"Клоны","value":"1624"},{"label":"Книги","value":"1068"},{"label":"Книжный червь","value":"521"},{"label":"Колдовство","value":"2681"},{"label":"колледж","value":"5058"},{"label":"Коллекционер","value":"2588"},{"label":"Кольцо","value":"1628"},{"label":"Коммунисты","value":"1042"},{"label":"Коноха","value":"2827"},{"label":"Контракт","value":"4304"},{"label":"Контроль разума","value":"485"},{"label":"Конфеты","value":"341"},{"label":"Корейцы","value":"6535"},{"label":"Корея","value":"2443"},{"label":"Королевская власть","value":"55"},{"label":"Королевская семья","value":"276"},{"label":"Королевство","value":"1695"},{"label":"Короткий рассказ","value":"239"},{"label":"Коррупция","value":"831"},{"label":"Космическая опера","value":"2245"},{"label":"Космические рейнджеры","value":"5860"},{"label":"Космос","value":"329"},{"label":"Кот","value":"5171"},{"label":"Кража навыков","value":"1159"},{"label":"Красивая главная героиня","value":"186"},{"label":"Красивые женщины","value":"66"},{"label":"Красивые персонажи","value":"5787"},{"label":"Красивый главный герой","value":"895"},{"label":"Крафт","value":"1599"},{"label":"Кроссовер","value":"75"},{"label":"Ктулху","value":"920"},{"label":"Кузнец","value":"853"},{"label":"Кукла","value":"3085"},{"label":"Кулинария","value":"2230"},{"label":"Культивация","value":"1901"},{"label":"Культивирование","value":"1860"},{"label":"Курама","value":"5709"},{"label":"Курилин","value":"6134"},{"label":"Кушина узумаки","value":"5222"},{"label":"Лавкрафт","value":"6063"},{"label":"Лара крофт","value":"6435"},{"label":"Легенда о зельде","value":"5707"},{"label":"Ленивый главный герой","value":"1516"},{"label":"Леон золдик","value":"7469"},{"label":"Лес","value":"6645"},{"label":"Лечебная магия","value":"562"},{"label":"Локи","value":"1725"},{"label":"Лоли","value":"1576"},{"label":"Лопата","value":"4989"},{"label":"Лорд","value":"8404"},{"label":"Лориен","value":"7397"},{"label":"Лошади","value":"6110"},{"label":"Лунатизм","value":"3520"},{"label":"Луффи","value":"274"},{"label":"Лучник","value":"1038"},{"label":"Любовный интерес влюбляется первым","value":"7753"},{"label":"Любовный треугольник","value":"2109"},{"label":"Любовь","value":"2297"},{"label":"Любовь с первого взгляда","value":"7748"},{"label":"Любящие родители","value":"2699"},{"label":"Люди","value":"3572"},{"label":"Люцифер","value":"5883"},{"label":"Маг","value":"780"},{"label":"Магазин","value":"4762"},{"label":"Маги","value":"58"},{"label":"Магическая академия","value":"6788"},{"label":"Магические звери","value":"684"},{"label":"Магические предметы","value":"1648"},{"label":"Магический мир","value":"578"},{"label":"Магия","value":"150"},{"label":"Магия воды","value":"6450"},{"label":"Магия воздуха","value":"7627"},{"label":"Магия земли","value":"7626"},{"label":"Магия и технология","value":"107"},{"label":"Магия крови","value":"7976"},{"label":"Магия льда","value":"1379"},{"label":"Магия огня","value":"7625"},{"label":"Магия призыва","value":"885"},{"label":"Магия природы","value":"6226"},{"label":"Магия стихий","value":"7673"},{"label":"Магия тьмы","value":"3596"},{"label":"Мадара","value":"2929"},{"label":"Мазохизм","value":"1961"},{"label":"Мама","value":"12"},{"label":"Мама и дочь","value":"7894"},{"label":"Мама и сын","value":"7895"},{"label":"Манга","value":"2464"},{"label":"Манипуляция временем","value":"932"},{"label":"Маньяк","value":"2026"},{"label":"Маргери тирелл","value":"3935"},{"label":"Марионетки","value":"3175"},{"label":"Марс","value":"4013"},{"label":"Марти стью","value":"594"},{"label":"Мастер на все руки","value":"3189"},{"label":"Матриархат","value":"7197"},{"label":"Мать и сестры","value":"7946"},{"label":"Мафия","value":"353"},{"label":"Мачеха","value":"4664"},{"label":"Мегаполис","value":"3322"},{"label":"Медицина","value":"441"},{"label":"Медленная романтика","value":"8383"},{"label":"Медленное развитие истории","value":"7462"},{"label":"Мелиодас","value":"7224"},{"label":"Мелодрама","value":"1507"},{"label":"Менеджмент","value":"368"},{"label":"Мерлин","value":"3977"},{"label":"Месть","value":"1218"},{"label":"Меч","value":"48"},{"label":"Мечники","value":"969"},{"label":"Мечта","value":"527"},{"label":"Мизуки","value":"4269"},{"label":"Микото","value":"3862"},{"label":"Милая главная героиня","value":"134"},{"label":"Милф","value":"1987"},{"label":"Милый главный герой","value":"2678"},{"label":"Мимик","value":"5706"},{"label":"Мина ашидо","value":"7695"},{"label":"Минато намикадзе","value":"5223"},{"label":"Мир будущего","value":"1770"},{"label":"Мир земли","value":"8394"},{"label":"Мир меча и магии","value":"1271"},{"label":"Мистер пропер","value":"565"},{"label":"Мифические существа","value":"1878"},{"label":"Мифы и легенды","value":"4463"},{"label":"Младшая сестра","value":"1523"},{"label":"Мморпг","value":"620"},{"label":"Много главных героев","value":"1191"},{"label":"Много крови","value":"5318"},{"label":"Много персонажей","value":"1539"},{"label":"Множество королевств","value":"32"},{"label":"Модерн","value":"5457"},{"label":"Мокутон","value":"4438"},{"label":"Молоко","value":"5469"},{"label":"Монархия","value":"3590"},{"label":"Монстры","value":"307"},{"label":"Море","value":"922"},{"label":"Моритика ринносукэ","value":"1142"},{"label":"Мортал комбат","value":"5861"},{"label":"Мошенник","value":"959"},{"label":"Мрачный мир","value":"1"},{"label":"Мужчина в женском теле","value":"8405"},{"label":"Музыка","value":"1183"},{"label":"Мультивселенная","value":"7410"},{"label":"Мурим","value":"7342"},{"label":"Мутанты","value":"2392"},{"label":"Мутация","value":"29"},{"label":"Мясо","value":"1503"},{"label":"На реальных событиях","value":"26"},{"label":"Навыки","value":"415"},{"label":"Нагато узумаки","value":"5221"},{"label":"Наемники","value":"1668"},{"label":"Назарик","value":"5369"},{"label":"Наивный главный герой","value":"159"},{"label":"Наложница","value":"4867"},{"label":"Наноботы","value":"2332"},{"label":"Наруто","value":"7177"},{"label":"Наруто и хината","value":"5766"},{"label":"Насилие и жестокость","value":"1440"},{"label":"Наука","value":"2150"},{"label":"Национализм","value":"5556"},{"label":"Нацу","value":"5826"},{"label":"Нацуки субару","value":"6656"},{"label":"Начальная школа","value":"3920"},{"label":"Наши дни","value":"1814"},{"label":"Не всесильный главный герой","value":"42"},{"label":"Не по канону","value":"1611"},{"label":"Неверность","value":"5735"},{"label":"Невеста","value":"6011"},{"label":"Неджи хьюга","value":"3099"},{"label":"Недооценённый главный герой","value":"43"},{"label":"Нежить","value":"1949"},{"label":"Некромаг","value":"7441"},{"label":"Некромант","value":"1914"},{"label":"Некромантия","value":"754"},{"label":"Ненормативная лексика","value":"160"},{"label":"Необычные герои","value":"67"},{"label":"Нет людей","value":"7486"},{"label":"Нетораре","value":"403"},{"label":"Нетори","value":"5393"},{"label":"Нефилимы","value":"7764"},{"label":"Нецензурная лексика","value":"4912"},{"label":"Нечисть","value":"4559"},{"label":"Ник фьюри","value":"6304"},{"label":"Ниндзюцу","value":"2354"},{"label":"Ниндзя","value":"1330"},{"label":"Новелла","value":"2105"},{"label":"Нэко","value":"147"},{"label":"Оби ван кеноби","value":"6830"},{"label":"Обито учиха","value":"2814"},{"label":"Оборотни","value":"53"},{"label":"Обратный гарем","value":"3303"},{"label":"Овощ","value":"6098"},{"label":"Огнестрельное оружие","value":"3155"},{"label":"Одержимость","value":"708"},{"label":"Один в поле воин","value":"6498"},{"label":"Онлайн игра","value":"1565"},{"label":"Ооками теппей","value":"849"},{"label":"Оригинальные персонажи","value":"7741"},{"label":"Орки","value":"1597"},{"label":"Оружие","value":"125"},{"label":"Основано на видео игре","value":"602"},{"label":"Особые способности","value":"2904"},{"label":"От бедности к богатству","value":"901"},{"label":"От слабого до сильного","value":"118"},{"label":"Отель","value":"2879"},{"label":"Отец","value":"3290"},{"label":"Отношения","value":"398"},{"label":"Отношения человек/нечеловек","value":"7406"},{"label":"Офис","value":"3460"},{"label":"Охотники","value":"2263"},{"label":"Оцуцуки","value":"5101"},{"label":"Ошейник","value":"2362"},{"label":"Ояш","value":"8048"},{"label":"Падчерица","value":"7023"},{"label":"Падший ангел","value":"184"},{"label":"Палач","value":"852"},{"label":"Палочка","value":"2682"},{"label":"Пандорум","value":"4360"},{"label":"Папа и дочь","value":"7647"},{"label":"Паразит","value":"1213"},{"label":"Параллельный мир","value":"2092"},{"label":"Парень","value":"619"},{"label":"Паркур","value":"3391"},{"label":"Пародия","value":"898"},{"label":"Пасхалки","value":"455"},{"label":"Паук","value":"2209"},{"label":"Пекарь","value":"5073"},{"label":"Первая книга","value":"269"},{"label":"Первая любовь","value":"640"},{"label":"Первый раз","value":"1465"},{"label":"Переводы","value":"24"},{"label":"Перевоплощение","value":"1596"},{"label":"Перевоплощение в игровом мире","value":"92"},{"label":"Перемещение в другой мир","value":"1288"},{"label":"Перемещение во времени","value":"146"},{"label":"Перерождение","value":"894"},{"label":"Перерождение в демона","value":"1111"},{"label":"Перерождение в дракона","value":"6867"},{"label":"Перерождение в злодейку","value":"5619"},{"label":"Перерождение в злодея","value":"749"},{"label":"Перерождение в ином мире","value":"109"},{"label":"Перерождение в монстра","value":"917"},{"label":"Перерождений","value":"335"},{"label":"Переселение","value":"813"},{"label":"Переселение души","value":"1864"},{"label":"Перси джексон","value":"6329"},{"label":"Пилот","value":"5521"},{"label":"Пилюли","value":"1531"},{"label":"Пират","value":"1579"},{"label":"Пирог","value":"80"},{"label":"Писатель","value":"734"},{"label":"Пистолеты","value":"4916"},{"label":"Письмо","value":"840"},{"label":"Питомцы","value":"3122"},{"label":"Планомерное развитие событий","value":"62"},{"label":"Племянник","value":"8303"},{"label":"Пленница","value":"4897"},{"label":"Плети","value":"4839"},{"label":"Пляж","value":"4243"},{"label":"Повар","value":"658"},{"label":"Повествование от первого лица","value":"1054"},{"label":"Повествование от разных лиц","value":"600"},{"label":"Повествование от третьего лица","value":"2116"},{"label":"Подавитель","value":"497"},{"label":"Подземелье","value":"798"},{"label":"Подростки","value":"636"},{"label":"Подруга","value":"5804"},{"label":"Подчинение","value":"8343"},{"label":"Подчинение и унижение","value":"4500"},{"label":"Покемоны","value":"2840"},{"label":"Полиамория","value":"1300"},{"label":"Полигамия","value":"1336"},{"label":"Политика","value":"1313"},{"label":"Полицейский","value":"1907"},{"label":"Полубог","value":"7170"},{"label":"Полукровка","value":"999"},{"label":"Полулюди","value":"2273"},{"label":"Поношенные трусики","value":"1204"},{"label":"Попаданец","value":"2396"},{"label":"Попаданец в другой мир","value":"685"},{"label":"Попаданец в игру","value":"6466"},{"label":"Попадание в книгу","value":"6957"},{"label":"Постапокалипсис","value":"1079"},{"label":"Похищение","value":"7452"},{"label":"Поэзия","value":"1120"},{"label":"Правитель","value":"2261"},{"label":"Превращения в животных","value":"3410"},{"label":"Преданный любовный интерес","value":"2055"},{"label":"Предательство","value":"70"},{"label":"Президент","value":"4334"},{"label":"Преступник","value":"4049"},{"label":"Преступный мир","value":"965"},{"label":"Призрак","value":"511"},{"label":"Призыв","value":"332"},{"label":"Призыв в другой мир","value":"781"},{"label":"Призыв существ","value":"412"},{"label":"Приложение на телефоне","value":"5345"},{"label":"Принудительный брак","value":"2954"},{"label":"Принуждение","value":"1442"},{"label":"Принц","value":"362"},{"label":"Принцесса","value":"2403"},{"label":"Приручение мостров","value":"2338"},{"label":"Прислуга","value":"5185"},{"label":"Пришельцы","value":"273"},{"label":"Проза","value":"2012"},{"label":"Прокачка","value":"1070"},{"label":"Проклятия","value":"1347"},{"label":"Проработанный мир","value":"1711"},{"label":"Пророчество","value":"7762"},{"label":"Против наркотиков","value":"8406"},{"label":"Псайкеры","value":"3659"},{"label":"Псионика","value":"5216"},{"label":"Психбольница","value":"6969"},{"label":"Психические расстройства","value":"2445"},{"label":"Психологические травмы","value":"3418"},{"label":"Публичный дом","value":"7860"},{"label":"Путешествие в другой мир","value":"10"},{"label":"Пух","value":"4286"},{"label":"Пушечное мясо","value":"7234"},{"label":"Пытки","value":"1756"},{"label":"Пьяный мастер","value":"1655"},{"label":"Пэнси паркинсон","value":"7411"},{"label":"Раб","value":"977"},{"label":"Рабы","value":"1240"},{"label":"Разведение животных","value":"3990"},{"label":"Развитие","value":"208"},{"label":"Развитие персонажа","value":"1780"},{"label":"Развитие поселения","value":"7203"},{"label":"Развитие технологий","value":"1875"},{"label":"Раздвоение личности","value":"2062"},{"label":"Разные расы","value":"1188"},{"label":"Разорванная помолвка","value":"2057"},{"label":"Разработчик","value":"2333"},{"label":"Ранги","value":"1568"},{"label":"Ранобэ","value":"1764"},{"label":"Расизм","value":"3554"},{"label":"Растение","value":"407"},{"label":"Реализм","value":"1180"},{"label":"Ребенок","value":"2881"},{"label":"Ревность","value":"293"},{"label":"Революция","value":"3996"},{"label":"Реинкарнация","value":"1302"},{"label":"Реинкарнация в другом мире","value":"2180"},{"label":"Реинкарнация в игровой мир","value":"304"},{"label":"Рейджер","value":"5147"},{"label":"Религия","value":"2184"},{"label":"Рем","value":"6655"},{"label":"Ремесленник","value":"1483"},{"label":"Ремонт","value":"5703"},{"label":"Репликаторы","value":"3495"},{"label":"Ресторан","value":"7519"},{"label":"Риас гремори","value":"6950"},{"label":"Рим","value":"612"},{"label":"Риннеган","value":"4230"},{"label":"Ритуал","value":"1233"},{"label":"Робот","value":"4011"},{"label":"Роботы","value":"467"},{"label":"Рок ли","value":"7002"},{"label":"Рокси","value":"7380"},{"label":"Рон уизли","value":"4279"},{"label":"Ророноа зоро","value":"1590"},{"label":"Росомаха","value":"1035"},{"label":"Российская империя","value":"2146"},{"label":"Россия","value":"4246"},{"label":"Рудеус","value":"7379"},{"label":"Руны","value":"2393"},{"label":"Русалки","value":"3127"},{"label":"Русь","value":"2016"},{"label":"Рыцари","value":"1902"},{"label":"Рэо хатаке","value":"2823"},{"label":"Сабли","value":"6136"},{"label":"Сайян","value":"6802"},{"label":"Сакура","value":"2515"},{"label":"Самец","value":"1592"},{"label":"Самураи","value":"576"},{"label":"Санса старк","value":"3925"},{"label":"Сарказм","value":"4658"},{"label":"Саске","value":"7237"},{"label":"Сатира","value":"215"},{"label":"Сборник","value":"7367"},{"label":"Свадьба","value":"1524"},{"label":"Сверхсила","value":"1055"},{"label":"Свинцовые книги","value":"5322"},{"label":"Связывание","value":"4506"},{"label":"Священик","value":"61"},{"label":"Северус снейп","value":"5783"},{"label":"Сёдзе","value":"2219"},{"label":"Секты","value":"1234"},{"label":"Сельское хозяйство","value":"787"},{"label":"Семейный конфликт","value":"935"},{"label":"Семья","value":"728"},{"label":"Сенджу","value":"6069"},{"label":"Серийный убийца","value":"261"},{"label":"Сестра","value":"2342"},{"label":"Сила глаза","value":"1019"},{"label":"Сильная героиня","value":"7292"},{"label":"Сильная главная героиня","value":"1994"},{"label":"Сильный главный герой","value":"570"},{"label":"Сильфиетта","value":"7381"},{"label":"Симбиот","value":"2648"},{"label":"Сириус блэк","value":"7655"},{"label":"Сирота","value":"297"},{"label":"Система","value":"251"},{"label":"Система уровней","value":"2174"},{"label":"Ситх","value":"1618"},{"label":"Сказка","value":"3570"},{"label":"Скайрим","value":"4032"},{"label":"Скайуокер","value":"6828"},{"label":"Сквиб","value":"4101"},{"label":"Скелет","value":"1315"},{"label":"Скрытые способности","value":"3417"},{"label":"Скульптор","value":"1178"},{"label":"Слабая главная героиня","value":"5805"},{"label":"Слабый главный герой","value":"731"},{"label":"Славяне","value":"2168"},{"label":"Слизерин","value":"6979"},{"label":"Слизь","value":"1095"},{"label":"Сломанная игрушка","value":"8396"},{"label":"Служанка","value":"3486"},{"label":"Смартфон","value":"457"},{"label":"Смена сущности","value":"8391"},{"label":"Смерть","value":"1779"},{"label":"Смерть основного персонажа","value":"1530"},{"label":"Собаки","value":"6109"},{"label":"Соблазн","value":"7994"},{"label":"Соблазнение","value":"2290"},{"label":"Современность","value":"568"},{"label":"Современные знания","value":"988"},{"label":"Сожительство","value":"3026"},{"label":"Создание армии","value":"1992"},{"label":"Создание королевства","value":"1497"},{"label":"Создание пилюль","value":"816"},{"label":"Создатель","value":"1045"},{"label":"Сокровища","value":"6521"},{"label":"Сокрытие истинной личности","value":"2894"},{"label":"Сома и эрина","value":"5737"},{"label":"Соперничество","value":"7699"},{"label":"Соседи","value":"4075"},{"label":"Сотрудник","value":"6339"},{"label":"Социология","value":"7618"},{"label":"Спокойная главная героиня","value":"236"},{"label":"Спокойный главный герой","value":"1656"},{"label":"Спор","value":"3484"},{"label":"Спортивное тело","value":"8317"},{"label":"Способность кражи","value":"7784"},{"label":"Сражения","value":"23"},{"label":"Средневековье","value":"1022"},{"label":"Сталкер","value":"1932"},{"label":"Становление государства","value":"111"},{"label":"Старшая школа","value":"1658"},{"label":"Стёб","value":"454"},{"label":"Стекло","value":"7453"},{"label":"Стеснительный персонаж","value":"152"},{"label":"Стимпанк","value":"1894"},{"label":"Стихи","value":"1309"},{"label":"Стратегия","value":"569"},{"label":"Строительство","value":"921"},{"label":"Студент","value":"1464"},{"label":"Студентка","value":"7518"},{"label":"Суккубы","value":"2662"},{"label":"Супер зрение","value":"6574"},{"label":"Супер удача","value":"489"},{"label":"Супергерои","value":"1481"},{"label":"Суперзлодеи","value":"2125"},{"label":"Супермен","value":"6997"},{"label":"Суперсилы","value":"2276"},{"label":"Существа","value":"6033"},{"label":"Сферы","value":"1077"},{"label":"Схемы и заговоры","value":"7116"},{"label":"Сценарий","value":"7489"},{"label":"Счастливый конец","value":"3293"},{"label":"Сын","value":"3297"},{"label":"Сэм винчестер","value":"7461"},{"label":"Сюаньхуа","value":"2560"},{"label":"Сюжетные повороты","value":"7202"},{"label":"Таблетки для развития","value":"589"},{"label":"Таинственное прошлое","value":"769"},{"label":"Тайная личность","value":"8096"},{"label":"Тайная любовь","value":"113"},{"label":"Тайны","value":"7481"},{"label":"Тайные отношения","value":"7450"},{"label":"Тайцы","value":"6413"},{"label":"Танки","value":"1787"},{"label":"Творчество","value":"20"},{"label":"Тейлор эберт","value":"3526"},{"label":"Телекинез","value":"2203"},{"label":"Телепортация","value":"914"},{"label":"Телохранитель","value":"723"},{"label":"Темари","value":"4810"},{"label":"Темная магия","value":"4788"},{"label":"Темное фэнтези","value":"1675"},{"label":"Темные эльфы","value":"7198"},{"label":"Тенсейган","value":"4367"},{"label":"Тетя","value":"4194"},{"label":"Техномагия","value":"508"},{"label":"Тиран","value":"1174"},{"label":"Титаны","value":"3308"},{"label":"Тодороки шото","value":"5105"},{"label":"Токио","value":"5791"},{"label":"Том реддл","value":"6652"},{"label":"Тони старк","value":"1338"},{"label":"Тор","value":"1800"},{"label":"Тор и локи","value":"2645"},{"label":"Торговля","value":"1637"},{"label":"Травничество","value":"221"},{"label":"Трагическое прошлое","value":"644"},{"label":"Трактир","value":"1918"},{"label":"Трансмиграция","value":"1071"},{"label":"Трансформация","value":"156"},{"label":"Трансформеры","value":"4616"},{"label":"Тревор филипс","value":"5427"},{"label":"Тройняшки","value":"7169"},{"label":"Троли","value":"4250"},{"label":"Трудолюбивый главный герой","value":"248"},{"label":"Тупой главный герой","value":"3710"},{"label":"Тьма","value":"1919"},{"label":"Тюрьма","value":"5597"},{"label":"Тяжёлое детство","value":"2253"},{"label":"Убийства","value":"378"},{"label":"Убийцы","value":"1766"},{"label":"Убийцы драконов","value":"1484"},{"label":"Увечья","value":"3266"},{"label":"Удача","value":"6575"},{"label":"Узумаки","value":"7579"},{"label":"Укротитель","value":"367"},{"label":"Умения","value":"531"},{"label":"Умная главная героиня","value":"1381"},{"label":"Умные персонажи","value":"2756"},{"label":"Умный главный герой","value":"2093"},{"label":"Университет","value":"2102"},{"label":"Унижение","value":"8342"},{"label":"Уничтожение мира","value":"81"},{"label":"Управление временем","value":"5648"},{"label":"Уровни","value":"8"},{"label":"Усиление","value":"3549"},{"label":"Усопп","value":"6737"},{"label":"Устроенный брак","value":"2223"},{"label":"Усыновление","value":"395"},{"label":"Утопия","value":"4677"},{"label":"Уход за детьми","value":"7609"},{"label":"Учеба в университете","value":"2797"},{"label":"Учебное заведение","value":"1817"},{"label":"Ученые","value":"1843"},{"label":"Учитель","value":"845"},{"label":"Учиха","value":"5348"},{"label":"Фамильяры","value":"1471"},{"label":"Фанатичная любовь","value":"6721"},{"label":"Фанаты","value":"7739"},{"label":"Фантастический мир","value":"2414"},{"label":"Фармацевт","value":"1706"},{"label":"Фашисты","value":"3118"},{"label":"Феи","value":"7185"},{"label":"Фелляция","value":"5880"},{"label":"Феминизм","value":"6527"},{"label":"Феникс","value":"2413"},{"label":"Фенрир","value":"2740"},{"label":"Феодализм","value":"280"},{"label":"Ферма","value":"285"},{"label":"Фехтовальщик","value":"4685"},{"label":"Филиппины","value":"128"},{"label":"Философия","value":"1859"},{"label":"Флафф","value":"5048"},{"label":"Флер делакур","value":"5191"},{"label":"Флэш","value":"4667"},{"label":"Фокусник","value":"7602"},{"label":"Фольклор","value":"4086"},{"label":"Фугаку","value":"6161"},{"label":"Фурри","value":"6631"},{"label":"Футбол","value":"1121"},{"label":"Фэнтезийный мир","value":"1556"},{"label":"Хакер","value":"475"},{"label":"Халк","value":"1196"},{"label":"Хан нуньен синг","value":"4817"},{"label":"Ханма юджиро","value":"4369"},{"label":"Хаос","value":"3117"},{"label":"Харизматичный главный герой","value":"2350"},{"label":"Хатаке какаши","value":"2820"},{"label":"Хиддлстон","value":"5903"},{"label":"Химавари","value":"2583"},{"label":"Хината","value":"2513"},{"label":"Хитрый главный герой","value":"2036"},{"label":"Хоббит","value":"6698"},{"label":"Хогвартс","value":"5954"},{"label":"Холодная главная героиня","value":"6507"},{"label":"Холодное оружие","value":"4889"},{"label":"Холодный главный герой","value":"2686"},{"label":"Храм","value":"2135"},{"label":"Христианство","value":"877"},{"label":"Художественная литература","value":"2380"},{"label":"Художница","value":"518"},{"label":"Хулиганы","value":"854"},{"label":"Цветок","value":"902"},{"label":"Цезарь","value":"1705"},{"label":"Целители","value":"4523"},{"label":"Церковь","value":"1980"},{"label":"Цундере","value":"1078"},{"label":"Чакра","value":"1393"},{"label":"Чат-система","value":"8407"},{"label":"Черный юмор","value":"2868"},{"label":"Честная главная героиня","value":"5855"},{"label":"Честный главный герой","value":"129"},{"label":"Читы","value":"451"},{"label":"Шантаж","value":"7175"},{"label":"Шаринган","value":"5165"},{"label":"Шинигами","value":"4661"},{"label":"Шиноби","value":"1227"},{"label":"Школьная жизнь","value":"284"},{"label":"Школьники","value":"218"},{"label":"Школьницы","value":"5946"},{"label":"Шлюха","value":"5822"},{"label":"Шоу-бизнес","value":"7119"},{"label":"Шпионы","value":"4262"},{"label":"Эволюция","value":"2040"},{"label":"Экзорцизм","value":"676"},{"label":"Экономика","value":"121"},{"label":"Экспансия","value":"110"},{"label":"Эксперименты над людьми","value":"7408"},{"label":"Элементальная магия","value":"1264"},{"label":"Эльфы","value":"1362"},{"label":"Эротика","value":"2053"},{"label":"Юмор","value":"7360"},{"label":"Яды","value":"201"},{"label":"Якудза","value":"4599"},{"label":"Яндере","value":"7111"},{"label":"Rpg","value":"90"},{"label":"Star wars","value":"1985"},{"label":"Time skip","value":"824"},{"label":"Warrior of light","value":"5289"}],"inputType":FilterInputs.Checkbox},{"key":"fandoms","label":"Фэндом:","values":[{"label":"19 Дней - Один день / 19 Days - One Day","value":"838"},{"label":"47-й / Хитмэн: Агент 47 / Наёмный убийца / Hitman","value":"589"},{"label":"Абсолютный дуэт / Absolute Duo","value":"1029"},{"label":"Аватар (Короля; об Аанге; об Корре) / Avatar","value":"1889"},{"label":"Аватар: Легенда о Корре / Avatar legend of Korra","value":"351"},{"label":"Аватар: Легенда об Аанге / Avatar: The Legend of Aang / Avatar: The Last Airbender","value":"303"},{"label":"Аватар(Фильм, 2009) / Avatar","value":"19"},{"label":"Ад Данте(Данте Алигьери) / Dante's Inferno(Dante Alighieri)","value":"1502"},{"label":"Азур Лейн / Azur Lane","value":"1009"},{"label":"Айон / Aion","value":"1005"},{"label":"Аладдин / Aladdin","value":"502"},{"label":"Алиса в Стране чудес / Alice in Wonderland","value":"616"},{"label":"Альдноа.Зеро / Aldnoah.Zero","value":"1799"},{"label":"Амагами СС / Amagami SS","value":"900"},{"label":"Амано Мегуми полна любви! / Amano Megumi wa Sukidarake!","value":"991"},{"label":"Американские боги / American Gods","value":"1843"},{"label":"Американский папаша! / American Dad","value":"348"},{"label":"Ангельские ритмы! / Angel Beats!","value":"880"},{"label":"Анлимитед: Хёбу Кёске / Zettai Karen Children: The Unlimited - Hyoubu Kyousuke","value":"74"},{"label":"Апостол карточек / The Apostle of Cards","value":"1504"},{"label":"Арифурэта: сильнейший ремесленник в мире / Arifureta: From Commonplace to World's Strongest","value":"62"},{"label":"Аркан: О Паровых Заводах и Магии Обскуры / Arcanum: Of Steamworks and Magick Obscura","value":"1495"},{"label":"Аркейн / Arcane: League of Legends","value":"1154"},{"label":"Аркнайтс(Games) / Arknights","value":"1210"},{"label":"Армелло(Games) / Armello","value":"1846"},{"label":"Астра, затерянная в космосе / Kanata no Astra","value":"1851"},{"label":"Атака титанов / Атака на титанов / Attack on Titan","value":"106"},{"label":"Атлантида: Затерянный мир / Atlantis: The Lost Empire","value":"985"},{"label":"Бакуган Отчаянные бойцы / Bakugan Battle Brawlers","value":"1069"},{"label":"Банановая рыба / Banana Fish","value":"1685"},{"label":"Баскетбол Куроко / Kuroko no basuke","value":"582"},{"label":"Баффи - Истребительница вампиров / Buffy the Vampire Slayer","value":"115"},{"label":"Башня Бога / Tower of God","value":"58"},{"label":"Бездарная Нана / Munou na Nana","value":"954"},{"label":"Бездомный бог / Норагами / Noragami","value":"1014"},{"label":"Безумные Мотивы / Looney Tunes","value":"1140"},{"label":"Безумный азарт / Kakegurui","value":"334"},{"label":"Бейблэйд / Beyblade","value":"921"},{"label":"Бен - 10 / Ben 10","value":"475"},{"label":"Берсерк / Berserk","value":"479"},{"label":"Бесконечное лето / Everlasting Summer","value":"966"},{"label":"Бесконечный ужас / Terror Infinity","value":"381"},{"label":"Бесподобный Воинственный Бог / Peerless Martial God","value":"419"},{"label":"Бессмертный Деревенщина(Games) / Immortal Redneck","value":"1524"},{"label":"Бесстыжие / Shameless","value":"1759"},{"label":"Био шок(Games) / BioShock","value":"1095"},{"label":"Блейд / Blade","value":"1479"},{"label":"Блич / Bleach","value":"7"},{"label":"Бог войны / God Of War","value":"352"},{"label":"Бог из машины / Deus Ex","value":"612"},{"label":"Боги поступают плохо / Игры богов / Gods Behaving Badly","value":"301"},{"label":"Боевая академия города Астериск / Gakusen Toshi Asterisk","value":"884"},{"label":"Боевой континент / Combat Continent / Douluo Dalu","value":"739"},{"label":"Боевой молот 40-го тысячелетия / WH40K / Warhammer 40,000","value":"341"},{"label":"Боевой молот Фэнтезийная битва / Warhammer Fantasy Battles","value":"1742"},{"label":"Боевые машины(Games) / BattleTech","value":"1667"},{"label":"Боец Баки / Baki the Grappler","value":"821"},{"label":"Божественность II: Эго Дракона(Games) / Divinity II: Ego Draconis","value":"1538"},{"label":"Божественные Врата / Divine Gate","value":"1490"},{"label":"Большая автомобильная кража 5 / GTA V / Grand Theft Auto V","value":"1139"},{"label":"Большая автомобильная кража: Сан-Андреас / GTA: SA / Grand Theft Auto: San Andreas","value":"820"},{"label":"Большая разница / Far Cry","value":"939"},{"label":"Большой куш / Ван Пис / One Piece","value":"25"},{"label":"Боруто: Следующие поколения Наруто / Boruto: Naruto Next Generations","value":"602"},{"label":"Брак по договоренности с принцессой красных скорпионов / Arranged marriage to the princess of the Red Scorpions","value":"1386"},{"label":"Бэтмен за гранью: Наследие / Batman Beyond: Legacy","value":"1380"},{"label":"В другом мире со смартфоном / Isekai wa Smartphone to Tomo ni","value":"947"},{"label":"В объятиях шлюхи / JK Bitch ni Shiboraretai","value":"1283"},{"label":"В ожидании бедности, я собираюсь стать кузнецом / Expecting to Fall into Ruin, I Aim to Become a Blacksmith","value":"1475"},{"label":"В Повелителе как Довакин / In Overlord as a Dovahkiin","value":"1816"},{"label":"Вакфу / Wakfu","value":"814"},{"label":"ВАЛЛ-И / Wally","value":"801"},{"label":"Вампир: Маскарад - Родословные / Vampire: The Masquerade Bloodline","value":"1212"},{"label":"Вампирелла / Vampirella","value":"1214"},{"label":"Варфрейм / Warframe","value":"967"},{"label":"Ведьмак / The Witcher","value":"278"},{"label":"Великий из бродячих псов / Bungou Stray Dogs","value":"75"},{"label":"Великолепный парк Амаги / Amagi Brilliant Park","value":"813"},{"label":"Вельзепуз / Вельзевул / Beelzebub","value":"765"},{"label":"Веном / Venom","value":"978"},{"label":"Веселая ферма / Fun Farm","value":"1124"},{"label":"Вечная история / The Neverending Story","value":"547"},{"label":"Вечные(Фильм, 2021) / Eternal","value":"1234"},{"label":"Виви: Песнь флюоритового глаза / Vivy: Fluorite Eye's Song","value":"1819"},{"label":"Викинги / Vikings","value":"369"},{"label":"Владелец ранчо со слизью(Games) / Ранчо слизи / Slime Rancher","value":"1529"},{"label":"Властелин колец / Lord of the Ring","value":"254"},{"label":"Власть книжного червя / Honzuki no Gekokujou","value":"1399"},{"label":"Внук Мудрец / Kenjo no Mago","value":"1260"},{"label":"Внук Нурарихёна / Nurarihyon no Mago","value":"66"},{"label":"Во всеоружии / Overgeared","value":"1021"},{"label":"Во тьме(Games) / The Darkness","value":"938"},{"label":"Военная хроника маленькой девочки / Сага о злой Тане / The Saga of Tanya the Evil / \tGekijouban Youjo Senki","value":"1726"},{"label":"Возвращение в детские годы / Gaki ni Modotte Yarinaoshi!!!","value":"1031"},{"label":"Возрождение Серийного Убийцы / Rebirth Of A Serial Killer","value":"1358"},{"label":"Воинственный Бог Асура / Martial God Asura","value":"771"},{"label":"Война будущего / The Tomorrow War","value":"1174"},{"label":"Война Любовь Снег / War Love Snow","value":"1417"},{"label":"Волейбол! / Haikyuu!!","value":"697"},{"label":"Волчонок / Teen Wolf","value":"795"},{"label":"Волшебная Девушка Спецоперация Аска / Magical Girl Spec-Ops Asuka","value":"1470"},{"label":"Волшебник-воин Орфен / Majutsushi Orphen Hagure Tabi: Kimluck-hen","value":"1128"},{"label":"Волшебники / The Magicians","value":"1314"},{"label":"Волшебный учитель Нэгима! / Negima!: Magister Negi Mag","value":"1777"},{"label":"Воля второго цикла мироздания. / Will of the second cycle of the Worldifice.","value":"1036"},{"label":"Воспитание хозяина / Yours to Claim","value":"839"},{"label":"Восставший против неба / Against the Gods","value":"957"},{"label":"Восстание стражей / Хранители снов / Rise of the Guardians","value":"1488"},{"label":"Восхождение в Голливуде / I'm in Hollywood","value":"1237"},{"label":"Восхождение героя щита / The Rising of the Shield Hero","value":"103"},{"label":"Врата Штейна / Steins: Gate","value":"1044"},{"label":"Врата: там бьются наши воины / Gate: Jieitai Kanochi nite, Kaku Tatakaeri","value":"727"},{"label":"Время / In Time","value":"542"},{"label":"Всегда вялый Танака-кун / Tanaka-kun wa Itsumo Kedaruge","value":"1082"},{"label":"Всего лишь восьмой сын? Я с этим не смирюсь! / Hachinan tte, Sore wa Nai Deshou! / Eighth son, I don’t think so!","value":"1473"},{"label":"Вселенная Марвел / Marvel Universe / Marvel Comics","value":"6"},{"label":"Вселенная монстров / Monsterverse / Monster Verse","value":"905"},{"label":"Вселенная Стивена / Steven universe","value":"573"},{"label":"Вселенная Стрелы / Arrowverse","value":"488"},{"label":"Вселенная Тип Луны(Игровая компания) / Universe Type Moon","value":"1221"},{"label":"Вселенная DC / DC Universe / DC Comics","value":"36"},{"label":"Выпадение радиоактивных осадков / Fallout","value":"55"},{"label":"Выращивание онлайн / Cultivation Online","value":"1252"},{"label":"Галактическая секс-звезда / Galaxy Sex Star","value":"1539"},{"label":"Гало(Games) / Halo","value":"1338"},{"label":"Ганц / Gantz","value":"256"},{"label":"Гарем рабов в лабиринте другого мира / Slave Harem in the Labyrinth of the Other World","value":"1853"},{"label":"Гарри Поттер / Harry Potter","value":"1"},{"label":"Гвен-паук / Spider-Gwen","value":"920"},{"label":"Генерал маньяк с его сумасшедшей системой / The Maniacal General with his Crazy System","value":"1356"},{"label":"Генерал, вы вправе уйти. / General, You May Leave Now","value":"1385"},{"label":"Геншин Импакт / Genshin Impact","value":"689"},{"label":"Геркулес / Hercules","value":"721"},{"label":"Герои и замки / Heroes & Castles","value":"940"},{"label":"Герои меча и магии / Heroes of Might and Magic","value":"1002"},{"label":"Герои(телесериал) / Heroes","value":"864"},{"label":"Гильгамеш / Gilgamesh","value":"1143"},{"label":"Гинтама / Gintama","value":"129"},{"label":"Глубина(Фильм, 2002) / Below","value":"1186"},{"label":"Гнев Асуры / Asura's wrath","value":"100"},{"label":"Годзилла / Godzilla","value":"922"},{"label":"Голодные игры / The Hunger Games","value":"859"},{"label":"Горец / Highlander","value":"1761"},{"label":"Горожане(Games) / Townsmen","value":"1599"},{"label":"Госпожа Кагуя: в любви как на войне / Kaguya sama: Love is war","value":"533"},{"label":"Готика / Gothic","value":"418"},{"label":"Готов ли ты влюбиться в извращенку до тех пор, пока она милая? / Hentai demo Suki ni Natte Kuremasu ka","value":"1383"},{"label":"Гоэтия / Гоетия / Yοητεία / Ars Goetia","value":"772"},{"label":"Гравити Фолз / Gravity Falls","value":"491"},{"label":"Граница пустоты / Kara no Kyoukai","value":"1101"},{"label":"Гриффины / Family Guy","value":"349"},{"label":"Гром над небом / Thunder over the sky","value":"793"},{"label":"Гуррен-Лаганн / Tengen Toppa Gurren Lagann","value":"719"},{"label":"Да будет благословенен этот прекрасный мир! / Konosuba / Kono Subarashii Sekai ni Shukufuku wo!","value":"82"},{"label":"Да Здравствует Призыв! / Long Live Summons!","value":"948"},{"label":"Да, я паук, и что с того? / So I'm a Spider, So What? / Kumo Desu ga, Nani ka?","value":"910"},{"label":"Данганронпа / Danganronpa","value":"972"},{"label":"Две звезды Онмёджи / Sousei no Onmyouji","value":"1108"},{"label":"Дворянство / Благородство / Noblesse","value":"636"},{"label":"Девочка-волшебница Мадока Магика / Mahou Shoujo Madoka Magica","value":"1412"},{"label":"Девочка, которая видит это / Mieruko-chan","value":"1645"},{"label":"Декстер(телесериал) / Dexter","value":"1543"},{"label":"Демон Бездны всех царств / Abyss Demon of All Realms","value":"1419"},{"label":"Демоны старшей школы / High School DxD","value":"8"},{"label":"День независимости(Фильм, 1996) / Independence Day","value":"850"},{"label":"Детектив Конан / Detective Conan","value":"1554"},{"label":"Дети индиго из другого мира / Mondaiji-tachi ga isekai kara kuru sô desu yo","value":"1484"},{"label":"Джаггед Альянс 2: Агония Власти(Games) / Jagged Alliance 2","value":"1668"},{"label":"Джессика Джонс / Marvel's Jessica Jones","value":"1817"},{"label":"Джон Уик / John Wick","value":"388"},{"label":"Дисней / The Walt Disney Company","value":"503"},{"label":"Для тебя, Бессмертный / Fumetsu no Anata e / To Your Eternity","value":"1802"},{"label":"Дневник Будущего / Mirai Nikki","value":"368"},{"label":"Дневники вампира / The Vampire Diaries","value":"160"},{"label":"Доблесть рыцаря-неудачника / Chivalry of a Failed Knight","value":"1462"},{"label":"Добро пожаловать в ад, Ирума / Welcome to Demon School! Iruma-kun","value":"261"},{"label":"Добро пожаловать в класс превосходства / Classroom of the Elite","value":"122"},{"label":"Добро пожаловать! В лес похотливых эльфов! / Youkoso! Sukebe Elf no Mori e","value":"1034"},{"label":"Добывать ремесло / Майнкрафт / Minecraft","value":"102"},{"label":"Доктор Кто / Doctor Who","value":"277"},{"label":"Доктор Стоун / Dr. Stone","value":"720"},{"label":"Доля секунды: скорость / Split - second: velocity","value":"890"},{"label":"Дом кролика / Кофейня "Кроличий домик" / Gochuumon wa Usagi Desu ka?","value":"642"},{"label":"Домашний очаг / Hearthstone: Heroes of Warcraft / Hearthstone","value":"934"},{"label":"Домекано / Domestic Na Kanojo","value":"632"},{"label":"Дорогой звёзд / Звёздное преобразование / Stellar Transformation / Xing Chen Bian","value":"1155"},{"label":"Доспехи Бога 2: Операция Кондор / Armour of God II: Operation Condor","value":"1829"},{"label":"Дота 2 / Dota 2","value":"1105"},{"label":"Дофус / Dofus","value":"817"},{"label":"Дракенгард / Drakengard / Drag-On Dragoon","value":"919"},{"label":"Дракон-горничная госпожи Кобаяси / Kobayashi-san Chi no Maid Dragon","value":"673"},{"label":"Дракон-сама из семьи Касумигаока / Dragon-sama of the Kasumigaoka Family","value":"1458"},{"label":"Драконий жемчуг Зет / Dragon Ball Z","value":"307"},{"label":"Дракониум Онлайн / Draconic Online","value":"1360"},{"label":"Дракула / Dracula","value":"709"},{"label":"Древнегреческая мифология / Ancient Greek mythology","value":"1159"},{"label":"Дре́вние / Первородные / The Originals","value":"863"},{"label":"Древние свитки / The Elder Scrolls","value":"428"},{"label":"Древние свитки: Скайрим / TES: Skyrim","value":"337"},{"label":"Другой мир / Underworld","value":"480"},{"label":"Друид с Сеульской станции / Seoul Station Druid","value":"1178"},{"label":"Дьявол / Диабло / Diablo","value":"1787"},{"label":"Дьявол может плакать / Devil May Cry / DMC","value":"339"},{"label":"Дьявол Юраги-су / The Devil of Yuragi-sou","value":"431"},{"label":"Дьявол II(Games) / Диабло II / Diablo II","value":"1055"},{"label":"Дэдпул / Deadpool","value":"810"},{"label":"Дэнни-призрак / Danny Phantom","value":"109"},{"label":"Евангелион / Neon Genesis Evangelion","value":"583"},{"label":"Единство семи магов / Тринити: Семь Магов / Trinity Seven","value":"442"},{"label":"Еженедельный прыжок сёнэн / Weekly Shōnen Jump","value":"1629"},{"label":"Ёрмунганд / Jormungand","value":"77"},{"label":"Жажда скорости / Need For Speed","value":"1493"},{"label":"Железный человек / Iron Man","value":"710"},{"label":"Жемчуг дракона / Dragon Ball","value":"309"},{"label":"Женщина-Халк(телесериал) / She-Hulk: Attorney at Law","value":"1593"},{"label":"Жизнь девушки в игровом мире / A Girl’s Life In A Gaming World","value":"1406"},{"label":"Жизнь после / Days Gone","value":"1279"},{"label":"За гранью / Beyond the Boundary","value":"357"},{"label":"Загипнотизировать Семью / Kyonyuu Kazoku Saimin","value":"1032"},{"label":"Закон Уэки / The Law of Ueki","value":"790"},{"label":"Закулисье / Backrooms","value":"1827"},{"label":"Зачарованные / Charmed","value":"113"},{"label":"Защитники / Defenders","value":"1832"},{"label":"Защитница Химари / Omamori Himari","value":"279"},{"label":"Звёздная принцесса и силы зла\t / Стар против сил зла / Star vs. The Forces of Evil","value":"782"},{"label":"Звёздное дитя / Oshi no Ko","value":"1903"},{"label":"Звёздное ремесло / StarCraft","value":"386"},{"label":"Звездные Войны / Star Wars","value":"40"},{"label":"Звёздные войны: Войны клонов - Все типы носителей(мультсериал, 2008) / Star Wars: The Clone Wars","value":"1182"},{"label":"Звёздные врата / Stargate","value":"770"},{"label":"Звёздные врата: Атлантида / Stargate: Atlantis","value":"1097"},{"label":"Звездный путь / Стартрек / Star Trek","value":"849"},{"label":"Зверополис / Zootopia","value":"1449"},{"label":"Зеленая Жизнь / Green Life","value":"1196"},{"label":"Зеленый фонарь / The Green Lantern","value":"1222"},{"label":"Зетмен / Zetman","value":"1191"},{"label":"Игра в кальмара(телесериал) / Squid game","value":"1065"},{"label":"Игра престолов / Game of Thrones","value":"22"},{"label":"Игрок / The Gamer","value":"126"},{"label":"Идеальная судьба / The Perfect Destiny","value":"781"},{"label":"Идолмастер / The Idolmaster","value":"807"},{"label":"Иерихон Клайва Баркера / Иерихон / Clive Barker’s Jericho /Jericho","value":"320"},{"label":"Извивающийся дракон / Coiling Dragon","value":"692"},{"label":"Изгнаные королевства РПГ / Exiled Kingdoms RPG","value":"1375"},{"label":"Импульс Валькирии: Сирена / Варукири Дораиву: Сирена / Valkyrie Drive: Mermaid","value":"1736"},{"label":"Индекс волшебства / A Certain Magical Index","value":"68"},{"label":"Инуяша - Пес-демон / InuYasha","value":"481"},{"label":"Искусственный отбор / Triage X","value":"1037"},{"label":"Истинный мир боевых искусств / Zhenwu Shijie / True Martial World","value":"867"},{"label":"История монстров / Monogatari","value":"911"},{"label":"История о второстепенном персонаже который стал игроком в другой игре. / The story is about a minor character who became a player in another game.","value":"868"},{"label":"Кабанери железной крепости / Koutetsujou no Kabaneri","value":"1494"},{"label":"Каждый раз, когда я сплю, моя душа покидает мое тело / Every Day I Sleep, My Soul Goes Out of My Body","value":"1048"},{"label":"Как воспитать героиню из обычной девушки / Saenai Heroine no Sodatekata","value":"1637"},{"label":"Как игрок глупой FPS попал в иной мир / Как дурачок из стрелялки в другой мир попал / Manuke na FPS Player ga Isekai e Ochita Baai","value":"746"},{"label":"Как приручить дракона / How to Train Your Dragon","value":"687"},{"label":"Капитан Америка / Captain America","value":"1425"},{"label":"Капитан Марвел(Фильм, 2019) / Captain Marvel","value":"1594"},{"label":"Каратель / The Punisher","value":"387"},{"label":"Касл / Castle","value":"389"},{"label":"Касльвания / Castlevania","value":"1215"},{"label":"Катаклизм: Тёмные дни впереди / DDA / Cataclysm: Dark Days Ahead","value":"680"},{"label":"Квайзер со Стигматом / Адепт Святого Знака / The Qwaser of Stigmata","value":"72"},{"label":"Квартет из альтернативного мира / Isekai Quartet","value":"1801"},{"label":"Квест Девушки-монстра / Monster Girl Questt","value":"928"},{"label":"Квест титана(Games) / Титанический квест / Titan Quest","value":"1483"},{"label":"Кенши(Games) / Kenshi","value":"1230"},{"label":"Киберпанк 2077 / Cyberpunk 2077","value":"416"},{"label":"Ким Пять-с-плюсом / Kim Possible","value":"436"},{"label":"Киру ра Киру / Круши Кромсай / Убей или умри / Kill la Kill","value":"763"},{"label":"Класс убийц / Assassination classroom","value":"610"},{"label":"Клеймор / Claymore","value":"110"},{"label":"Клинок зла / Evil Blade / Übel Blatt","value":"722"},{"label":"Клинок королевы / Queen’s Blade","value":"757"},{"label":"Клинок Маню: Тайна сисечного свитка / Manyuu Hiken-chou","value":"501"},{"label":"Клинок рассекающий демонов / Demon Slayer: Kimetsu no Yaiba","value":"21"},{"label":"Клуб Винкс / Winx Club","value":"397"},{"label":"Книга джунглей / The Jungle Book","value":"1688"},{"label":"Князь тьмы с задней парты / Demon King Daimao / Ichiban Ushiro no Daimaou","value":"1207"},{"label":"Код Гиас / Code Geass","value":"340"},{"label":"Код Квалидеи / Qualidea Code","value":"76"},{"label":"Кольцо Элдена / Elden Ring","value":"1408"},{"label":"Комната / The Room","value":"889"},{"label":"Конь и клинок: Боевой отряд(Games) / Mount and Blade:Warband","value":"1477"},{"label":"Королевства Сердец / Kingdom Hearts","value":"407"},{"label":"Короли крестоносцев / Crusader kings","value":"572"},{"label":"Король бойцов / The King of Fighters","value":"1378"},{"label":"Король лев / The Lion king","value":"1705"},{"label":"Король Шаманов / Shaman King","value":"744"},{"label":"Корона греха / Guilty Crown","value":"1007"},{"label":"Корпорация лоботомии / Lobotomy corporation","value":"852"},{"label":"Космические рейнджеры(Games) / Space Rangers","value":"1508"},{"label":"Кошечка из Сакурасо / Sakurasou no Pet na Kanojo","value":"605"},{"label":"Красавица и чудовище / Beauty and the Beast","value":"1765"},{"label":"Красная угроза 3 / Command & Conquer: Red Alert 3","value":"742"},{"label":"Красный, Белый, Черный, Желтый / RWBY","value":"131"},{"label":"Кредо убийцы / Assassin's Creed","value":"690"},{"label":"Кризис / Crysis","value":"1734"},{"label":"Крушитель / The Breaker","value":"1080"},{"label":"Кунг-фу панда / Kung Fu Panda","value":"831"},{"label":"Кэйон! / K-On!","value":"1785"},{"label":"Кэнган Асура / Kengan Asura","value":"726"},{"label":"Лаборатория Декстера / Dexter Lab","value":"639"},{"label":"Лавкрафт / Говард Филлипс Лавкрафт / Howard Phillips Lovecraft","value":"1259"},{"label":"Легенда о восьми псах востока / Hakkenden: Touhou Hakken Ibun","value":"1699"},{"label":"Легенда о Зельде / The Legend of Zelda","value":"870"},{"label":"Легенда о Короле Драконов / Legend of the Dragon King","value":"623"},{"label":"Легенда о Легендарных Героях / Densetsu no Yuusha no Densetsu","value":"193"},{"label":"Легион Супергероев / The Legion of Super-Heroes","value":"450"},{"label":"Леди Баг и Супер-Кот / Miraculous Ladybug","value":"327"},{"label":"Летняя сага / Summertime Saga","value":"1441"},{"label":"Лига Легенд / League of Legends","value":"65"},{"label":"Линия фронта для девочек / Girls' Frontline","value":"1686"},{"label":"Литературный клуб Доки Доки / Литературный клуб / Doki Doki literature club!","value":"819"},{"label":"Лорд героев(Games) / Lord of Heroes","value":"1771"},{"label":"Лорд человечества / Lord of the People","value":"1896"},{"label":"Лориенская Сага / Lorien Legacies","value":"521"},{"label":"Любимая жена господина генерального директора / Mr.CEO's Beloved Wife","value":"1389"},{"label":"Любовные неприятности / To love ru","value":"353"},{"label":"Любовь, Деньги, Рок-н-Ролл / Love, Money, Rock'n'Roll","value":"1890"},{"label":"Люди в чёрном(Фильм) / Men in Black","value":"1193"},{"label":"Люди Икс / X-Men","value":"371"},{"label":"Лютер Строуд Сага / The Luther Strode Saga","value":"1700"},{"label":"Люцифер(телесериал) / Lucifer","value":"681"},{"label":"Маг на полную ставку / Quanzhi Fashi","value":"291"},{"label":"Маг смерти не желающий четвертой реинкарнации / The Death Mage Who Doesn’t Want a Fourth Time","value":"1775"},{"label":"Маг-целитель: Новый старт / Kaifuku Jutsushi no Yarinaoshi","value":"1311"},{"label":"Маги: Волшебный лабиринт / Magi: The Labyrinth of Magic","value":"1581"},{"label":"Магистр дьявольского культа / The Grandmaster of Demonic Cultivation","value":"608"},{"label":"Магическая академия Атараксия: Гибрид х Сердце / Hybrid x Heart Magias Academy Ataraxia","value":"1898"},{"label":"Магическая битва / Magic Battle / Jujutsu Kaisen","value":"671"},{"label":"Маленькие кошмары 2 / Little Nightmares 2","value":"601"},{"label":"Малефисента / Maleficent","value":"775"},{"label":"Мальчик с оленьими рогами / Сладкоежка / Sweet tooth","value":"1772"},{"label":"Маска / The mask","value":"847"},{"label":"Мастер Урадана / The Master of Uradan","value":"1395"},{"label":"Мастера меча онлайн / Sword Art Online / SAO","value":"324"},{"label":"Межвидовые Рецензенты / Interspecies Reviewers","value":"1555"},{"label":"Менеджер среднего звена Тонэгава / Chuukan Kanriroku Tonegawa","value":"1084"},{"label":"Мерлин / Merlin","value":"486"},{"label":"Мертвы к Рассвету / Dead by Daylight","value":"899"},{"label":"Мертвый или живой / Dead or Alive","value":"1563"},{"label":"Мертвый остров / Dead Island","value":"124"},{"label":"Месть Масамуне-куна! / Masamune-kun no Revenge","value":"571"},{"label":"Метавселенная Рудазова / Rudazov's Metauniverse","value":"1211"},{"label":"Метро 2033(Games) / Metro 2033","value":"1584"},{"label":"Милый во Франксе / Любимый во Франксе / Darling in the Franxx","value":"942"},{"label":"Мир боевых искусств / 武极天下 / Wuji Tianxia / Martial World","value":"620"},{"label":"Мир зомби / Zombie World","value":"1880"},{"label":"Мир Льда и Пламени / The World of Ice & Fire","value":"415"},{"label":"Мир приключений Джеки Чана(мультсериал, 2000) / ackie Chan Adventures","value":"1544"},{"label":"Мир танков / WoT Blitz / World of Tanks Blitz","value":"525"},{"label":"Мир Тьмы / World of Darkness","value":"145"},{"label":"Мир Эрастай / The World of Erasthay","value":"1836"},{"label":"Мир Warcraft / World of Warcraft","value":"89"},{"label":"Мировая война Z / Война миров Z / World War Z","value":"1217"},{"label":"Моана / Moana","value":"686"},{"label":"Моб психо 100 / Mob Psycho 100","value":"866"},{"label":"Мобильные легенды: Бах-Бах(Games) / Mobile Legends: Bang Bang","value":"1497"},{"label":"Могучие рейнджеры / Power Rangers","value":"1486"},{"label":"Может, я встречу тебя в подземелье? / DanMachi","value":"9"},{"label":"Мой жених сбежал / My Groom Ran Away","value":"1047"},{"label":"Мой маленький пони / My Little Pony","value":"655"},{"label":"Мой маленький пони: Дружба — это чудо / My Little Pony: Friendship is Magic","value":"658"},{"label":"Мой шумный дом(мультсериал, 2016) / The Loud House","value":"1467"},{"label":"Монстер Хай / Monster High","value":"1012"},{"label":"Моя возлюбленная чпокается со всеми / Kanojo wa Dare to demo Sex Sur","value":"1274"},{"label":"Моя геройская академия / Boku no Hero Academia","value":"69"},{"label":"Моя девушка - зомби / My Girlfriend is a Zombie","value":"754"},{"label":"Моя жена - красивый генеральный директор / My Wife is a Beautiful CEO","value":"1025"},{"label":"Моя жена — президент студенческого совета! / My Wife is the Student Council President / Okusama ga Seitokaichou","value":"241"},{"label":"Моя Марвел Академия / My marvel academia","value":"696"},{"label":"Моя первая модница / Hajimete no Gal","value":"1835"},{"label":"Моя Супер-Бывшая / My Super Ex-Girlfriend","value":"1828"},{"label":"Мрачный рассвет / Grim Dawn","value":"1113"},{"label":"Мстители / The Avengers","value":"1747"},{"label":"Мстители. Эра Альтрона / The Avengers. Age of Ultron","value":"784"},{"label":"Мулан / Mulan","value":"706"},{"label":"Мы не можем учится / Bokutachi wa Benkyou ga Dekinai","value":"912"},{"label":"Мэй Гунцин / Mei Gongqing","value":"753"},{"label":"Наблюдать / Overwatch","value":"607"},{"label":"Надпись / Inscription","value":"1718"},{"label":"Нам Ён / Nam Yeon","value":"1188"},{"label":"Наруто / Naruto","value":"3"},{"label":"Начало после конца / The Beginning After The End","value":"888"},{"label":"Не голодай / Don't Starve","value":"274"},{"label":"Не издевайся надо мной, Нагаторо / Ijiranaide / Nagatoro-san Don't Toy with Me, Miss Nagatoro","value":"1041"},{"label":"Не люблю боль, так что вкачаю все в защиту / Itai no wa Iya nano de Bougyoryoku ni Kyokufuri Shitai to Omoimasu","value":"517"},{"label":"Не моя вина, что я непопулярна! / Watashi ga Motenai no wa Dou Kangaetemo Omaera ga Warui","value":"1381"},{"label":"Небесный замок Лапута / Tenkuu no Shiro Laputa","value":"1109"},{"label":"Невероятные приключения ДжоДжо / JoJo's Bizarre Adventure","value":"20"},{"label":"Негодник, которому не снилась девочка-зайка / Rascal Does Not Dream of Bunny Girl Senpai","value":"1897"},{"label":"Негодяй спасает мужскую роль / The Villain Saves the Male Lead","value":"1224"},{"label":"Неизвестен / Persona","value":"205"},{"label":"Некий магический индекс / To Aru Majutsu no Index","value":"562"},{"label":"Некий научный акселератор / Toaru Kagaku no Accelerator","value":"1487"},{"label":"Ненасытный Берсерк / Boushoku no Berserk: Ore dake Level to Iu Gainen wo Toppa suru the Comic","value":"1195"},{"label":"Необъятные небеса / Infinite Stratos / IS","value":"280"},{"label":"Необъятный океан / Grand Blue","value":"531"},{"label":"Непревзойденная / Master Piece The Animation","value":"712"},{"label":"Непризнанный школой владыка демонов / Maou Gakuin no Futekigousha","value":"1476"},{"label":"Непутевый ученик в школе магии / Mahouka Koukou No Rettousei","value":"982"},{"label":"Непутевый ученик в школе магии / The Irregular at Magic High School","value":"630"},{"label":"Несокрушимая механическая кукла / Machine-Doll wa Kizutsukanai","value":"1030"},{"label":"Несправедливость / Injustice","value":"1026"},{"label":"Нет игры - нет жизни / Без игры жизни нет / No Game No Life","value":"718"},{"label":"Неуязвимый / Invincible","value":"702"},{"label":"НиоХ(Games) / NioH","value":"1465"},{"label":"Новый завет Владыки тьмы / Shinmai Maou no Testament","value":"1432"},{"label":"Ну и ну! Земляничные яйца / I My Me! Strawberry Eggs","value":"1485"},{"label":"Нулевой Уровень Целомудрия / Teisou Kannen Zero","value":"1209"},{"label":"О моём перерождении в меч / Tensei Shitara Ken deshita","value":"53"},{"label":"О моём перерождении в слизь / Tensei shitara Slime Datta Ken","value":"64"},{"label":"О моя Богиня / Aa! Megami-sama! / Ah! My Goddess","value":"915"},{"label":"Обесчещенный(Games) / Dishonored","value":"1073"},{"label":"Обитель зла / Resident Evil","value":"86"},{"label":"Огненная эмблема / Fire Emblem","value":"1615"},{"label":"Огненная эмблема: Пробуждение / Fire Emblem: Awakening","value":"1616"},{"label":"Огненная эмблема: Три Дома / Fire Emblem:Three Houses","value":"1716"},{"label":"Одинокий рокер! / Bocchi the Rock!","value":"1904"},{"label":"Одному лишь Богу ведомый мир / World God Only Knows","value":"1248"},{"label":"Она становится гламурной после расторжения помолвки / She gets glamorous after the engagement is annulled","value":"1404"},{"label":"Орк-рубака / Orc Grunt","value":"779"},{"label":"Освободите эту ведьму / Release that witch","value":"994"},{"label":"Острые козырьки(телесериал) / Peaky Blinders","value":"1177"},{"label":"От заката до рассвета! / From Dusk till Dawn!","value":"1416"},{"label":"Отброс из семьи графа / Trash of counts family","value":"853"},{"label":"Отряд самоубийц / The Suicide Squad","value":"1844"},{"label":"Отчаянные домохозяйки / Desperate Housewives","value":"1011"},{"label":"Отчет о буйстве духов / YuYu Hakusho","value":"1008"},{"label":"Охота демонического короля на свою жену / Xie Wang Zhui Qi","value":"1737"},{"label":"Охотник х Охотник / Hunter x Hunter","value":"101"},{"label":"Охотницы на демонов / Taimanin Asagi","value":"1463"},{"label":"Очень приятно Бог! / Kamisama Hajimemashita","value":"1585"},{"label":"Очень Странные Дела(телесериал) / Stranger Things","value":"1834"},{"label":"ПАЗЛ / PUZZLE","value":"1762"},{"label":"Палач Рока / DOOM","value":"132"},{"label":"Параграф 78(Фильм) / Paragraph 78","value":"923"},{"label":"Паразит: Учение о жизни / Parasyte: The Maxim","value":"1176"},{"label":"Пастырь(Фильм, 2011) / Priest","value":"1173"},{"label":"Пацаны / The Boys","value":"133"},{"label":"Первый детский сад во вселенной / The First Kindergarten in the Universe","value":"1049"},{"label":"Перевозчик / Le Transporteur","value":"365"},{"label":"Передающийся через кровь / Bloodborne","value":"229"},{"label":"Пережить / Outlast","value":"645"},{"label":"Перерождение / Rebirth","value":"550"},{"label":"Перерождение бессмертного горожанина-культиватора / Rebirth – City Cultivation / Rebirth of the Urban Immortal Cultivator","value":"843"},{"label":"Перерождение в монстра / Re:Monster","value":"85"},{"label":"Перестрой мир / Sekai O Sai Kochiku / Rebuild World","value":"961"},{"label":"Период полураспада(Valve) / Half-Life","value":"895"},{"label":"Перси Джексон / Percy Jackson","value":"308"},{"label":"Персона 5 / Persona 5","value":"1614"},{"label":"Печать ветра / Kaze no Stigma","value":"845"},{"label":"Пик боевых искусств / Martial Peak","value":"414"},{"label":"Пираты Карибского моря / Pirates of the Caribbean","value":"932"},{"label":"Пираты черной лагуны / Black Lagoon","value":"621"},{"label":"Пламенная бригада пожарных / Fire Force / Enen no Shouboutai","value":"841"},{"label":"Пламя бесчисленых невзгод / I' m really not demon god's lackey","value":"1452"},{"label":"Планетарная аннигиляция / Planetary Annihilation","value":"487"},{"label":"Плоскостной пейзаж: Мучение / Planescape: Torment","value":"1768"},{"label":"По велению адской сестры / The Testament of Sister New Devil","value":"18"},{"label":"Поборники тьмы / Darksiders","value":"1028"},{"label":"Повар небесной гостиницы / Чем кормят в ином мире / Kakuriyo no Yadomeshi","value":"998"},{"label":"Повар-боец Сома / В поисках божественного рецепта / Shokugeki no Souma","value":"191"},{"label":"Повелитель тьмы на подработке! / Hataraku Maou-sama!","value":"674"},{"label":"Повелитель тьмы: Другая история мира / How Not to Summon a Demon Lord / Isekai Maou to Shoukan Shoujo no Dorei Majutsu","value":"699"},{"label":"Повелитель(Куганэ Маруяма) / Overlord","value":"27"},{"label":"Повелитель(Games) / Overlord","value":"1623"},{"label":"Повесть о Конце Света / Record of Ragnarok","value":"332"},{"label":"Повесть о лунной принцессе / Tsukihime: Lunar Legend","value":"750"},{"label":"Повесть о Небесных островах / Фэнтези Гранблю / Granblue Fantasy","value":"808"},{"label":"Повседневная жизнь бессмертного короля / The Daily Life of the Immortal King / Xian Wang de Richang Shenghuo","value":"1466"},{"label":"Повседневная жизнь с девушкой-монстром / Monster Musume","value":"760"},{"label":"Пограничье(Games) / Borderlands","value":"992"},{"label":"Под лунами Драконьих глаз / Beneath the Dragoneye Moons","value":"1735"},{"label":"Подземелья и драконы / Dungeons & Dragons","value":"81"},{"label":"Подземная история / Андертейл / Undertale","value":"390"},{"label":"Поднявшийся(Games) / Risen","value":"1273"},{"label":"Поднятие уровня в одиночку / Solo Leveling","value":"127"},{"label":"Подручный Луизы-Нулизы / Zero no Tsukaima","value":"580"},{"label":"Пожиратель богов / God Eater","value":"1321"},{"label":"Поймай себя ! Моя дорогая жена / Catch You ! My Dear Wife","value":"1317"},{"label":"Покемон / Pokemon","value":"43"},{"label":"Политическая Хроника Молодой Девушки / A Young Woman's Political Record","value":"1306"},{"label":"Полностью пленённые / Totally Captivated","value":"1086"},{"label":"Полый Рыцарь(Games) / Hollow Knight","value":"1198"},{"label":"Пользователи Силы / Forceusers","value":"1162"},{"label":"Поля битвы Неизвестного игрока / ПАБГ / Player Unknown's Battlegrounds / PUBG","value":"622"},{"label":"Попытка приручить злого повелителя / Trying to Tame an Evil Overlord","value":"983"},{"label":"Поработитель Ада / Helltaker","value":"776"},{"label":"Порновселенная / Porn Universe","value":"1776"},{"label":"Портал(Valve) / Portal","value":"800"},{"label":"Последние из нас / Last Of Us","value":"1717"},{"label":"Последний Серафим / Owari no Seraph","value":"551"},{"label":"Последняя из рода Блау(Тайга Ри) / The last of the Blau family","value":"1507"},{"label":"Последняя фантазия / ファイナルファンタジ / Final Fantasy","value":"769"},{"label":"Преподобное безумие / Reverend Insanity","value":"1280"},{"label":"Преподобный Гу / Gu Zhen Ren / Daoist Gu","value":"1464"},{"label":"Призрачный бегун / Ghostrunner","value":"613"},{"label":"Призрачный гонщик / Ghost Rider","value":"823"},{"label":"Принц Драконов Хаоса / The Chaos Dragon Prince","value":"1397"},{"label":"Принц Персии / Prince of Persia","value":"1535"},{"label":"Принцесса монстров / Princess Resurrection","value":"1304"},{"label":"Принцесса Цу / Не проиграю! / Maken Ki","value":"675"},{"label":"Проект „Восток“ / Touhou Project","value":"809"},{"label":"Проект Кей / K Project","value":"73"},{"label":"Проклятие: Автоматизация / NieR:Automata","value":"1496"},{"label":"Противостояние святого / Renegade Immortal","value":"926"},{"label":"Прототип / Prototype","value":"54"},{"label":"Пуленепробиваемый / Bang-Tan / BTS","value":"520"},{"label":"Путешествие на Запад / Journey to the West","value":"1833"},{"label":"Пять невест / Go-Toubun no Hanayome","value":"713"},{"label":"Пять ночей у Фредди / Five nights at freddy's","value":"930"},{"label":"Рагнарёк Онлайн / Ragnarok Online","value":"953"},{"label":"Радуга 6: Осада / Rainbow Six: Siege","value":"421"},{"label":"Развращение Дочери / Daraku Reijou Hakoiri Ojou-sama Netorare Choukyou Kiroku","value":"1284"},{"label":"Рай Грисайи / Эдем в серых тонах / Grisaia no Rakuen","value":"584"},{"label":"Рандеву с жизнью / Date A live","value":"851"},{"label":"Ранма ½ / Ranma ½","value":"1192"},{"label":"Рапунцель: Запутанная история / Tangled","value":"773"},{"label":"Расколотая битвой синева небес / Battle Through the Heavens","value":"927"},{"label":"Рассказ служанки / The Handmaid's Tale","value":"1135"},{"label":"Расхитительница гробниц / Tomb Raider","value":"988"},{"label":"Резатель / Лангриссер / Langrisser","value":"792"},{"label":"Реинкарнация безработного / Mushoku Tensei","value":"569"},{"label":"Реинкарнация Богини / Megami Tensei","value":"1161"},{"label":"Репликант НиеР / NieR Replicant / NieR Gestalt","value":"1299"},{"label":"Рецеттия: Повесть о магазине предметов / Recettear: An Item Shop's Tale","value":"858"},{"label":"Ривердэйл / Riverdale","value":"637"},{"label":"Рик и Морти / Rick and Morty","value":"315"},{"label":"Розарий и Вампир / Rosario+Vampire","value":"83"},{"label":"Розовая пора моей школьной жизни сплошной обман / Yahari Ore no Seishun Love Come wa Machigatteiru","value":"856"},{"label":"Рок шоу! / Show By Rock!!","value":"344"},{"label":"Русалочка / The Little Mermaid","value":"892"},{"label":"Рыцарь и маг / Knight's & Magic","value":"1491"},{"label":"Сага о Винланде / Vinland Saga","value":"1200"},{"label":"Садистская смесь / Blend S","value":"1120"},{"label":"Сайт волшебниц / Mahou Shoujo Site","value":"909"},{"label":"Сверхъестественное(телесериал) / Supernatural","value":"916"},{"label":"Связь принцесс: повторное погружение / Princess Connect! Re:Dive","value":"1481"},{"label":"Святые / Saints Row","value":"1390"},{"label":"Сейлор Мун / Sailor Moon","value":"114"},{"label":"Секире: Тени Умирают Дважды / Sekiro: Shadows Die Twice","value":"1076"},{"label":"Семь смертных грехов / Nanatsu no Taizai","value":"61"},{"label":"Семья шпиона / Spy x Family","value":"1646"},{"label":"Сердца Пандоры / Pandora Hearts","value":"497"},{"label":"Серия Метроидов / Metroid Series","value":"1612"},{"label":"Серый человек / Ди: Гурэйман / D.Gray-man","value":"367"},{"label":"Си Тянь Гуань / Si Tian Guan","value":"1189"},{"label":"Сильнейший в истории ученик Кэнити / Shijou Saikyou no Deshi Kenichi","value":"242"},{"label":"Сильнейший в истории ученик Кэнъити / KenIchi: The Mightiest Disciple","value":"745"},{"label":"Сильнейший магнат / The Strongest Tycoon","value":"1340"},{"label":"Сильнейший мудрец низшей эмблемы / Shikkakumon no Saikyou Kenja","value":"1472"},{"label":"Симпсоны / The Simpsons","value":"1461"},{"label":"Симс / The Sims","value":"654"},{"label":"Симфония морской стали / Aoki Hagane no Arpeggio","value":"958"},{"label":"Сингулярность(Games) / Singularity","value":"1793"},{"label":"Синий Архив / Blue Archive","value":"1411"},{"label":"Синий экзорцист / Blue Exorcist","value":"312"},{"label":"Синяя Тюрьма: Блю Лок / Blue Lock","value":"1792"},{"label":"Система Богов и Демонов / God and Devil World","value":"1648"},{"label":"Система Спаси-Себя-Сам / The Scum Villain's Self-Saving System: Ren Zha Fanpai Zijiu Xitong","value":"1505"},{"label":"Система: Восьмой уровень(Д. Серебряков) / System: Eighth level","value":"1175"},{"label":"Сисястая Принцесса под гипнозом / Kyonyuu Princess Saimin","value":"1618"},{"label":"Сказание о Демонах и Богах / Tales of Demons and Gods","value":"59"},{"label":"Сказание о Тёмном Рыцаре ~ Призван, чтобы одолеть Героя ~ / Tale of Dark Knight~Summoned to Defeat The Hero~","value":"1647"},{"label":"Сказки хранителей(Games) / Guardian tales","value":"1068"},{"label":"Скрытая Похотливая Натура Моих Русских Сестренок и Мачехи / Muttsuri do Sukebe ro Gibo Shimai","value":"1282"},{"label":"Скуби-Ду / Scooby-Doo","value":"638"},{"label":"Скучный мир, где не существует самой идеи похабных шуток / Shimoneta to Iu Gainen ga Sonzai Shinai Taikutsu na Sekai","value":"830"},{"label":"Сладкая жизнь / Happy Sugar Life","value":"1099"},{"label":"Сладкий флирт / Amour Sucré / Sweet Crush","value":"495"},{"label":"Сладости и Сигареты / Candy & Cigarettes","value":"778"},{"label":"Следопыт Гнев Праведников / Pathfinder Wrath Of The Righteous","value":"1077"},{"label":"Следопыт: Творец королей / Pathfinder: Kingmaker","value":"1770"},{"label":"Смертельная битва / Мортал Комбат / Mortal Kombat","value":"806"},{"label":"Смертельный укус","value":"1902"},{"label":"Созданный в бездне / Made in Abyss","value":"952"},{"label":"Сок джунглей","value":"1901"},{"label":"Сокрушитель: Новые волны / The Breaker: New Waves","value":"1500"},{"label":"Соник еж / Sonic the hedgehog","value":"1052"},{"label":"Сорвиголова / Daredevil","value":"1690"},{"label":"Сотня / Hundred","value":"885"},{"label":"Спаун / Spawn","value":"1254"},{"label":"Спецагент Арчер / Archer","value":"624"},{"label":"Специалист по апгрейду из другого мира / Endless Sea of Clouds ESC","value":"1499"},{"label":"Спираль / Удзумаки / Uzumaki","value":"1164"},{"label":"СТАЛКЕР / STALKER / S.T.A.L.K.E.R","value":"677"},{"label":"Стальная тревога / Full Metal Panic! The Second Raid","value":"1489"},{"label":"Стальной алхимик / Fullmetal Alchemist","value":"1123"},{"label":"Стальной Гигант / The Iron Giant","value":"1241"},{"label":"Становление богом / Bai Lian Cheng Shen","value":"1315"},{"label":"Старгерл / Stargirl","value":"1137"},{"label":"Стелларис / Stellaris","value":"1098"},{"label":"Сторожевые Псы / Watch Dogs","value":"1886"},{"label":"Стражи Галактики / Guardians of the Galaxy","value":"1426"},{"label":"Страна Самоцветов / Houseki no Kuni","value":"1305"},{"label":"Страна чудес смертников / Зона-парк смертников / Deadman Wonderland","value":"857"},{"label":"Страношары / Кантриболз / Countryballs","value":"1895"},{"label":"Студии 20-й век / 20th Century Studios","value":"1715"},{"label":"Судьба / Fate","value":"1740"},{"label":"Судьба: Апокриф / Fate: Apocrypha","value":"231"},{"label":"Судьба: Великий Орден / Fate: Grand Order","value":"60"},{"label":"Судьба: Девочка волшебница Илия / Fate: Kaleid Liner Prisma","value":"789"},{"label":"Судьба: Истоки / Fate: Zero","value":"230"},{"label":"Судьба: Ночь схватки / Fate: Stay Night","value":"536"},{"label":"Сумерки / Twilight","value":"471"},{"label":"Супер ген бога / Super God Gene","value":"316"},{"label":"Супер Марио / Super Mario","value":"1661"},{"label":"Супергёрл(телесериал, 2015) / Supergirl","value":"1088"},{"label":"Супермедицинский ниндзя / Super medical ninja","value":"1391"},{"label":"Суперсемейка / The Incredibles","value":"306"},{"label":"Сэкирэй / Sekirei","value":"111"},{"label":"Тада не может влюбиться! / Tada-kun wa koi wo shinai!","value":"1905"},{"label":"Тайны Смолвиля / Smallville","value":"449"},{"label":"Танец клинка Элементалиста / Seireitsukai no Blade Dance","value":"1498"},{"label":"Твоя апрельская ложь / Your lie in april","value":"532"},{"label":"Те, кто охотятся на эльфов / エルフを狩るモノたち / Those Who Hunt Elves","value":"1168"},{"label":"Темнейшее подземелье / Darkest dungeon","value":"1405"},{"label":"Темные Души / Dark Souls","value":"200"},{"label":"Темный Ангел / Dark Angel","value":"1010"},{"label":"Тёмный Дворецкий / Kuroshitsuj / Dark Butler","value":"411"},{"label":"Темный дворецкий / Kuroshitsuji","value":"1043"},{"label":"Темный призыватель Апокалипсиса / The Dark Summoner of the Apocalypse","value":"1407"},{"label":"Тень ежа / Ёж Шэдоу / Shadow the hedgehog","value":"796"},{"label":"Терминатор / The Terminator","value":"759"},{"label":"Террарий / Terraria","value":"805"},{"label":"Тетрадь смерти / Death Note","value":"78"},{"label":"Тибериумные войны / Tiberium Wars","value":"1893"},{"label":"Титаник / Titanic","value":"1842"},{"label":"Тихий Холм / Сайлент Хилл / Silent Hill","value":"848"},{"label":"Тихоокеанский рубеж / Pacific Rim","value":"832"},{"label":"Тогайну но Чи ~Потерял кровь~(Games) / Togainu no Chi ~Lost Blood~","value":"1540"},{"label":"Токийские вороны / Tokyo Ravens","value":"836"},{"label":"Токийские мстители / Tokyo Revengers","value":"1064"},{"label":"Токийский Гуль / Tokyo Ghoul","value":"271"},{"label":"Тор / Thor","value":"764"},{"label":"Торико / Toriko","value":"342"},{"label":"Точка зрения Всеведущего читателя / Omniscient Reader’s Viewpoint","value":"1872"},{"label":"Трансформеры / Transformers","value":"117"},{"label":"Трес Наварра / Tres Navarre","value":"1197"},{"label":"Три Икса / xXx","value":"364"},{"label":"Трон: Восстание / Tron: Uprising","value":"1887"},{"label":"Тропико / Tropico","value":"694"},{"label":"Ты единственная, кто любит Великого Меня / Ore wo Suki nano wa Omae dake ka yo","value":"1818"},{"label":"Ты же любишь мамочку, удары которой бьют по площади двойным уроном? / Tsuujou Kougeki ga Zentai Kougeki de Ni-kai Kougeki no Okaasan wa Suki Desu ka?","value":"333"},{"label":"Тэнти - лишний! / Tenchi Muyo","value":"1316"},{"label":"У Коми-сан проблемы с общением / 古見さんは、コミュ症です / Komi Can't Communicate","value":"591"},{"label":"У меня мало друзей / Boku wa Tomodachi ga Sukunai","value":"1506"},{"label":"Убийца Акаме / Akame ga Kill","value":"30"},{"label":"Убийца Брайан / Carl Robert Brown","value":"1092"},{"label":"Убийца гоблинов / Goblin slayer","value":"803"},{"label":"Удар крови / Very AU strike the blood","value":"1255"},{"label":"Уж не зомби ли это? / Kore wa Zombie Desu ka?","value":"725"},{"label":"Уличный боец(Games) / Суторито Фаита / Street Fighter","value":"1203"},{"label":"Ультрафиолет / Ultraviolet","value":"1831"},{"label":"Усио и Тора / Ushio and Tora","value":"1501"},{"label":"Утраченное небесами / Sora no Otoshimoto / Lost Property of the Sky","value":"627"},{"label":"Ученик Мудреца / Kenja no Deshi wo Nanoru Kenja","value":"1474"},{"label":"Ученик чародея / The Sorcerer's Apprentice","value":"862"},{"label":"Ученики(Games) / Disciples","value":"1478"},{"label":"Учитель Хокаге / Hokage Master","value":"1319"},{"label":"Учитель-мафиози Реборн! / Katekyo Hitman Reborn!","value":"134"},{"label":"Ушастые Друзья / Kemono Friends","value":"578"},{"label":"Фальшивая любовь / Nisekoi","value":"1103"},{"label":"Фантастическая четвёрка / Fantastic Four","value":"625"},{"label":"Фантастические твари и где они обитают / Fantastic Beasts and Where to Find Them","value":"246"},{"label":"Финес и Ферб / Phineas and Ferb","value":"898"},{"label":"Флотская коллекция / Kantai Collection","value":"1194"},{"label":"Флэш / The Flash","value":"1136"},{"label":"Фонд SCP / SCP / SCP Foundation","value":"822"},{"label":"Форма голоса / A Silent Voice","value":"1100"},{"label":"Форсаж / The Fast and the Furious","value":"363"},{"label":"Фронт кровавой блокады / Кровавый круг - линия фронта / Kekkai Sensen / Blood Blockade Battlefront","value":"794"},{"label":"Футадом мир / Futadom world","value":"984"},{"label":"Халк / Hulk","value":"973"},{"label":"Хвост Феи / Fairy Tail","value":"13"},{"label":"Хеллбой / Hellboy","value":"1171"},{"label":"Хеллсинг: Война с нечистью / Hellsing","value":"116"},{"label":"Хикару и го / Hikaru no Go","value":"1121"},{"label":"Хищник / Predator","value":"747"},{"label":"Хоббит(Дж. Р. Р. Толкина) / The Hobbit(John R.R. Tolkien)","value":"1127"},{"label":"Ходячие мертвецы / The Walking Dead","value":"704"},{"label":"Холодное сердце / Frozen","value":"633"},{"label":"Хонкай удар / Honkai impact","value":"1332"},{"label":"Хранители Пандоры / The guardians of Pandora","value":"1187"},{"label":"Хранитель вечности / UQ Holder","value":"1469"},{"label":"Хроники Акаши / Rokudenashi Majutsu Koushi to Akashic Records","value":"1166"},{"label":"Хроники Ксенобладания / Дзэнобурэйдо / Xenoblade Chronicles","value":"1110"},{"label":"Хроники Миров(Е. Лукин) / Chronicles of the Worlds(E. Lukin)","value":"346"},{"label":"Хроники расхитителей гробниц / Даому Биджи / Grave Robbery Note / Dao Mu Bi Ji / Daomu Biji","value":"724"},{"label":"Хроники Ренегата / The Renegade Chronicles","value":"1225"},{"label":"Царь Горы / The Gog of the Highschool","value":"1285"},{"label":"Чародейки / W.I.T.C.H.","value":"118"},{"label":"Человек — бензопила / Chainsaw Man","value":"797"},{"label":"Человек — летучая мышь / Бэтмен / Bat-man / Batman","value":"440"},{"label":"Человек одного удара / Ванпанчмен / One Punch-Man","value":"70"},{"label":"Человек-паук / Spider-Man","value":"326"},{"label":"Чемпион! / Campione!","value":"534"},{"label":"Червь(Джон Маккрей) / Worm(John C. McCrae(Wildbow))","value":"700"},{"label":"Черная Пантера(Фильм, 2018) / Black Panther","value":"1605"},{"label":"Черновик(С.Лукьяненко) / Draft","value":"1023"},{"label":"Чернокнижник в Мире Магов / Варлок / Warlock","value":"635"},{"label":"Чёрные души / Black Souls","value":"1439"},{"label":"Чёрный зверь / Чёрный Пёс / Kuroinu","value":"755"},{"label":"Чёрный зверь: Развращение Благородных Воительниц / Black Beast: Corruption of the Noble Warriors","value":"1733"},{"label":"Чёрный клевер / Black Clover","value":"11"},{"label":"Что такое настоящий мир? / What is real peace?","value":"1336"},{"label":"Чудачества любви не помеха! / Chuunibyou Demo Koi ga Shitai!","value":"1719"},{"label":"Чужой / Чужие / Aliens","value":"1791"},{"label":"Чужой / Alien","value":"748"},{"label":"Чума инкорпорейтед / Plague Inc","value":"125"},{"label":"Шазам! / Shazam!","value":"1560"},{"label":"Шальной последний босс появился! / A Wild Last Boss Appeared!","value":"968"},{"label":"Шальные девчонки / Girl the Wild's","value":"965"},{"label":"Шан Чи и легенда десяти колец / Shang-Chi and the Legend of the Ten Rings","value":"1424"},{"label":"Шарлотта / Charlotte","value":"71"},{"label":"Шерлок (ВВС) / Sherlock","value":"492"},{"label":"Шестерни войны / Gears of War","value":"1346"},{"label":"Школа мертвецов / Highschool of the Dead","value":"98"},{"label":"Школа строгого режима / Prison School","value":"676"},{"label":"Школьные воины / Сила тысячи / Ikki Tosen","value":"818"},{"label":"Шрек(мультфильм) / Шрэк / Shrek","value":"1586"},{"label":"Шухер, у нас новый студент / Transfer Student The Storm Bringer","value":"628"},{"label":"Эволюционировать(Games) / Evolve","value":"1789"},{"label":"Эволюция. Естественный Отбор / Game Evolution","value":"287"},{"label":"Эльсворд: Эль-ий Йоин / Elsword","value":"199"},{"label":"Эльфийская песнь / Elfen Lied","value":"1899"},{"label":"Эпоха Драконов / Dragon Age","value":"253"},{"label":"Эр Ген Я запечатаю небеса / ISSTH / Er Gen I shall seal the heavens","value":"1170"},{"label":"Эрагон(Кристофер Паолини) / Eragon","value":"417"},{"label":"Эроманга-сэнсэй / Ero-manga Sensei","value":"1094"},{"label":"Эстетика заблудшего героя / Hagure Yuusha no Aesthetica","value":"1310"},{"label":"Эта гяру будет встречаться с отаку через 100 дней. / 100-nichigo ni Otaku-kun to Tsukiau Gal","value":"1246"},{"label":"Эта фарфоровая кукла влюбилась / Sono Bisque Doll wa Koi wo Suru My Dress-Up Darling","value":"1335"},{"label":"Это не Гарри Поттер / This is not Harry Potter","value":"1219"},{"label":"Этот герой неуязвим, но очень осторожен / This Hero Is Invincible but Too Cautious","value":"1276"},{"label":"Эффект массы / Mass Effect","value":"213"},{"label":"Эхо пули / Bullet Echo","value":"1523"},{"label":"Югио: Дуэльные монстры / Yu-Gi-Oh","value":"1814"},{"label":"Югио! Вреинс / Yu-Gi-Oh! VRAINS","value":"1888"},{"label":"Юна из гостиницы Юраги / Yuuna of Yuragi Manor","value":"493"},{"label":"Юная Лига Справедливости / Young Justice","value":"1020"},{"label":"Юные Титаны / Teen Titans","value":"420"},{"label":"Я - Четвертый / I Am Number Four","value":"590"},{"label":"Я Король-Волшебник / I Am The Sorcerer King","value":"1292"},{"label":"Я мачеха, но моя дочь слишком милая / I'm stepmother but daughter is too cute","value":"777"},{"label":"Я не родился счастливчиком / I Wasn’t Born Lucky","value":"996"},{"label":"Я получил читерские способности в другом мире и стал экстраординарным в реальном мире / I Got a Cheat Skill in Another World and Became Unrivaled in The Real World, Too","value":"1900"},{"label":"Я стала потерянной дочерью злодея / I Became the Villain’s Lost Daughter","value":"1387"},{"label":"Ядерный трон / Nuclear Throne","value":"1456"},{"label":"Ярость [Пересмотрено] / Rage [Revised]","value":"1337"},{"label":"Ящик предложений Мэдаки / Medaka box","value":"874"},{"label":"Cказка для Дьявола / Tale For Satan","value":"1271"},{"label":"D&D стиль / D&D style","value":"1289"},{"label":"Dying Light 2: Stay Human","value":"1906"},{"label":"Fallout: Нью-Вегас / Fallout: New Vegas","value":"1249"},{"label":"Re: Жизнь в альтернативном мире с нуля / Re: Zero, Starting Life in Another World","value":"57"},{"label":"Re:Zero Начало жизни в другом мире / Re:Zero Starting Life in Another World","value":"1531"},{"label":"Rimworld","value":"1894"},{"label":"The Second Coming of Gluttony / The Second Coming of Avarice","value":"1236"},{"label":"Vfhdbk","value":"1884"},{"label":"XCOM: Враг внутри / XCOM: Enemy Unknown","value":"476"},{"label":"Xenus: Точка кипения / Boiling point: Road To Hell / Xenus: Boiling Point","value":"695"}],"inputType":FilterInputs.Checkbox},{"key":"genres_ex","label":"Исключить жанры:","values":[{"label":"18+","value":"52"},{"label":"Арт","value":"1"},{"label":"Боевик","value":"2"},{"label":"Боевые искусства","value":"3"},{"label":"Гаремник","value":"5"},{"label":"Героическое фэнтези","value":"7"},{"label":"Детектив","value":"8"},{"label":"Дзёсэй","value":"9"},{"label":"Додзинси","value":"10"},{"label":"Драма","value":"11"},{"label":"История","value":"13"},{"label":"Киберпанк","value":"46"},{"label":"Кодомо","value":"14"},{"label":"Комедия","value":"15"},{"label":"Литрпг","value":"48"},{"label":"Махо-сёдзё","value":"16"},{"label":"Мелодрама","value":"49"},{"label":"Меха","value":"17"},{"label":"Мистика","value":"18"},{"label":"Научная фантастика","value":"19"},{"label":"Повседневность","value":"20"},{"label":"Постапокалиптика","value":"21"},{"label":"Приключения","value":"22"},{"label":"Психология","value":"23"},{"label":"Романтика","value":"24"},{"label":"Самурайский боевик","value":"25"},{"label":"Сверхъестественное","value":"26"},{"label":"Сёдзё","value":"27"},{"label":"Сёнэн","value":"29"},{"label":"Смат","value":"45"},{"label":"Спорт","value":"31"},{"label":"Сэйнэн","value":"32"},{"label":"Сюаньхуа","value":"44"},{"label":"Сюаньхуань","value":"47"},{"label":"Сянься (XianXia)","value":"42"},{"label":"Трагедия","value":"33"},{"label":"Триллер","value":"34"},{"label":"Ужасы","value":"35"},{"label":"Уся (wuxia)","value":"41"},{"label":"Фантастика","value":"36"},{"label":"Фанфик","value":"50"},{"label":"Фэнтези","value":"37"},{"label":"Школа","value":"38"},{"label":"Этти","value":"39"},{"label":"Bl","value":"43"},{"label":"Gl","value":"40"}],"inputType":FilterInputs.Checkbox},{"key":"tags_ex","label":"Исключить тэги:","values":[{"label":"12+","value":"3316"},{"label":"16+","value":"83"},{"label":"Абсурд","value":"7973"},{"label":"Авантюристы","value":"222"},{"label":"Автомат","value":"5272"},{"label":"Авторский мир","value":"1062"},{"label":"Агрессивные персонажи","value":"3249"},{"label":"Ад","value":"2623"},{"label":"Ад и рай","value":"817"},{"label":"Адам дженсен","value":"1649"},{"label":"Адаптация произведения","value":"192"},{"label":"Адвокат","value":"6340"},{"label":"Адекватные главные герои","value":"1953"},{"label":"Азартные игры","value":"5301"},{"label":"Азгард","value":"3494"},{"label":"Азула","value":"5550"},{"label":"Аид","value":"7641"},{"label":"Айдолы","value":"4081"},{"label":"Академия","value":"316"},{"label":"Акамэ","value":"5059"},{"label":"Аквакинез","value":"5952"},{"label":"Акира","value":"2639"},{"label":"Акнология","value":"4634"},{"label":"Актерское мастерство","value":"4798"},{"label":"Актёры","value":"7506"},{"label":"Активные герои","value":"6376"},{"label":"Акутагава рюноске","value":"4113"},{"label":"Аладдин","value":"6489"},{"label":"Алая ведьма","value":"4767"},{"label":"Алиса","value":"4761"},{"label":"Алкоголь","value":"5508"},{"label":"Аллегория","value":"271"},{"label":"Алукард","value":"4914"},{"label":"Алхимики","value":"1164"},{"label":"Алхимия","value":"1473"},{"label":"Алчность","value":"6897"},{"label":"Альбус дамблдор","value":"5784"},{"label":"Альтернативное развитие событий","value":"5330"},{"label":"Альянсы","value":"328"},{"label":"Амбициозный главный герой","value":"3751"},{"label":"Америка","value":"4082"},{"label":"Амнезия","value":"2207"},{"label":"Аморальный герой","value":"18"},{"label":"Анбу","value":"8129"},{"label":"Ангелы","value":"857"},{"label":"Ангелы и демоны","value":"1327"},{"label":"Ангст","value":"4638"},{"label":"Андроиды","value":"1993"},{"label":"Анимализм","value":"5249"},{"label":"Аниме","value":"1294"},{"label":"Анко митараши","value":"5768"},{"label":"Антагонист","value":"2144"},{"label":"Антигерой","value":"7725"},{"label":"Антиквариат","value":"3552"},{"label":"Антимаг","value":"1348"},{"label":"Антиутопия","value":"662"},{"label":"Апокалипсис","value":"1498"},{"label":"Аристократия","value":"371"},{"label":"Аристократы","value":"7338"},{"label":"Армия","value":"1723"},{"label":"Артас","value":"6700"},{"label":"Артефакты","value":"2296"},{"label":"Археология","value":"6523"},{"label":"Асгард","value":"3635"},{"label":"Ассасин","value":"1415"},{"label":"Асуна","value":"5044"},{"label":"Аугментации","value":"7751"},{"label":"Ацуши накаджима","value":"4109"},{"label":"Аянокоджи киетака","value":"6862"},{"label":"Бандиты","value":"2188"},{"label":"Басейн","value":"6847"},{"label":"Баскетбол","value":"7933"},{"label":"Бастарды","value":"76"},{"label":"Бедность","value":"1207"},{"label":"Без культивации","value":"668"},{"label":"Без любовной линий","value":"2225"},{"label":"Без перерождений","value":"262"},{"label":"Без попаданца","value":"8065"},{"label":"Без системы","value":"747"},{"label":"Без юмора","value":"763"},{"label":"Бездна","value":"1026"},{"label":"Безжалостное домашнее животное","value":"1245"},{"label":"Безжалостные персонажи","value":"2986"},{"label":"Беззаботные персонажи","value":"3123"},{"label":"Безответная любовь","value":"7815"},{"label":"Безработный","value":"2202"},{"label":"Безумие","value":"37"},{"label":"Безумные персонажи","value":"2049"},{"label":"Бейсбол","value":"7623"},{"label":"Беременность","value":"2122"},{"label":"Бесконечный поток","value":"7556"},{"label":"Беспечные персонажи","value":"742"},{"label":"Бесплатно","value":"8403"},{"label":"Бессмертные персонажи","value":"566"},{"label":"Бесстрашные персонажи","value":"6921"},{"label":"Бесстыдные персонажи","value":"1257"},{"label":"Бесстыдный главный герой","value":"8190"},{"label":"Библиотека","value":"4210"},{"label":"Библия","value":"488"},{"label":"Бизнес","value":"704"},{"label":"Биология","value":"2220"},{"label":"Биомехи","value":"1968"},{"label":"Биседзе","value":"777"},{"label":"Битва за веру","value":"721"},{"label":"Битва за трон","value":"7211"},{"label":"Битва королевств","value":"1151"},{"label":"Битва рас","value":"6989"},{"label":"Битвы","value":"1740"},{"label":"Благородные персонажи","value":"2201"},{"label":"Близнецы","value":"2931"},{"label":"Богатство","value":"6522"},{"label":"Богатые персонажи","value":"520"},{"label":"Боги","value":"173"},{"label":"Богини","value":"30"},{"label":"Богиня","value":"8324"},{"label":"Богоубийца","value":"1253"},{"label":"Богохульство","value":"95"},{"label":"Боевая академия","value":"2108"},{"label":"Большая грудь","value":"4717"},{"label":"Борос","value":"6533"},{"label":"Борьба","value":"1925"},{"label":"Борьба за власть","value":"8072"},{"label":"Босс и подчиненный","value":"7157"},{"label":"Бояръ","value":"2307"},{"label":"Брак","value":"1558"},{"label":"Брак по расчету","value":"1389"},{"label":"Брат и сестра","value":"615"},{"label":"Братский комплекс","value":"2321"},{"label":"Броманс","value":"1103"},{"label":"Брошенные дети","value":"2846"},{"label":"Буддизм","value":"1871"},{"label":"Будущее","value":"1820"},{"label":"Бывший муж","value":"8080"},{"label":"Быстрое развитие","value":"1443"},{"label":"Бэтгерл","value":"2584"},{"label":"Бэтмен","value":"4668"},{"label":"В первый раз","value":"6212"},{"label":"В этот же мир","value":"49"},{"label":"Ваканда","value":"8331"},{"label":"Валькирии","value":"4047"},{"label":"Вампиры","value":"2206"},{"label":"Веб камера","value":"5664"},{"label":"Веб новелла","value":"2349"},{"label":"Ведьмак","value":"843"},{"label":"Ведьмы","value":"643"},{"label":"Везучие персонажи","value":"1879"},{"label":"Веном","value":"3994"},{"label":"Вестерн","value":"2131"},{"label":"Вестерос","value":"8171"},{"label":"Взросление","value":"624"},{"label":"Взрослый главный герой","value":"2416"},{"label":"Видео игры","value":"2630"},{"label":"Викинги","value":"267"},{"label":"Вино","value":"6972"},{"label":"Вирт","value":"6213"},{"label":"Виртуальная реальность","value":"325"},{"label":"Вирусы","value":"3327"},{"label":"Владыка демонов","value":"555"},{"label":"Власть","value":"756"},{"label":"Влюбленность","value":"6132"},{"label":"Внешний вид отличается от личности","value":"1938"},{"label":"Внучка","value":"8399"},{"label":"Военные","value":"1096"},{"label":"Возрождение","value":"1160"},{"label":"Воины","value":"287"},{"label":"Война","value":"443"},{"label":"Войны","value":"2431"},{"label":"Воландеморт","value":"4278"},{"label":"Волейбол","value":"6415"},{"label":"Волки","value":"1166"},{"label":"Волшебники","value":"122"},{"label":"Волшебные существа","value":"1689"},{"label":"Волшебство","value":"719"},{"label":"Вор","value":"1399"},{"label":"Воровка","value":"6948"},{"label":"Ворон","value":"848"},{"label":"Воскрешение","value":"6915"},{"label":"Воспоминания из другого мира","value":"1366"},{"label":"Воспоминания из прошлого","value":"1372"},{"label":"Воссоединие семьи","value":"8130"},{"label":"Восхождение","value":"380"},{"label":"Враги становятся любовниками","value":"978"},{"label":"Врата","value":"40"},{"label":"Врата в другой мир","value":"1957"},{"label":"Врач","value":"1243"},{"label":"Временная петля","value":"2852"},{"label":"Врмморпг","value":"2043"},{"label":"Все дозволено","value":"96"},{"label":"Всемогущий главный герой","value":"1414"},{"label":"Второй шанс","value":"2372"},{"label":"Вуайеризм","value":"2498"},{"label":"Выживание","value":"501"},{"label":"Вымышленные существа","value":"3466"},{"label":"Вынужденный брак","value":"7705"},{"label":"Высокие технологии","value":"653"},{"label":"Высокомерные персонажи","value":"3250"},{"label":"Галустян","value":"5199"},{"label":"Гангстеры","value":"7704"},{"label":"Гарем","value":"440"},{"label":"Гарри поттер","value":"226"},{"label":"Геймеры","value":"2130"},{"label":"Генетические модификации","value":"1750"},{"label":"Гениальный главный герой","value":"1500"},{"label":"Гений","value":"1650"},{"label":"Гермиона грейнджер","value":"4280"},{"label":"Герои","value":"185"},{"label":"Гигаполис","value":"8393"},{"label":"Гильгамеш","value":"6031"},{"label":"Гильдии","value":"900"},{"label":"Гильдия авантюристов","value":"1858"},{"label":"Гинтама","value":"4544"},{"label":"Гипноз","value":"358"},{"label":"Главная героиня влюбляется первой","value":"973"},{"label":"Главный герой бог","value":"164"},{"label":"Главный герой влюбляется первым","value":"3629"},{"label":"Главный герой выживальщик","value":"120"},{"label":"Главный герой гонг","value":"7877"},{"label":"Главный герой девушка","value":"257"},{"label":"Главный герой демон","value":"136"},{"label":"Главный герой женщина","value":"7329"},{"label":"Главный герой жестокий","value":"1553"},{"label":"Главный герой извращенец","value":"94"},{"label":"Главный герой имба","value":"2421"},{"label":"Главный герой киборг","value":"7780"},{"label":"Главный герой монстр","value":"869"},{"label":"Главный герой мужчина","value":"1997"},{"label":"Главный герой на стороне сил зла","value":"1514"},{"label":"Главный герой не адекватный","value":"5"},{"label":"Главный герой не психопат","value":"7804"},{"label":"Главный герой не человек","value":"2172"},{"label":"Главный герой не эмоционален","value":"1150"},{"label":"Главный герой подросток","value":"2215"},{"label":"Главный герой позитивный","value":"7787"},{"label":"Главный герой психопат","value":"7803"},{"label":"Главный герой ребенок","value":"2347"},{"label":"Главный герой русский","value":"2417"},{"label":"Главный герой сильный с самого начала","value":"88"},{"label":"Главный герой скрывает свою силу","value":"1059"},{"label":"Главный герой эгоист","value":"8326"},{"label":"Гномы","value":"1870"},{"label":"Гоблины","value":"2029"},{"label":"Годзилла","value":"6990"},{"label":"Големы","value":"1690"},{"label":"Голливуд","value":"7754"},{"label":"Головоломка","value":"1697"},{"label":"Горничные","value":"8091"},{"label":"Гробница","value":"388"},{"label":"Дазай осаму","value":"4112"},{"label":"Даньмэй","value":"3411"},{"label":"Даосизм","value":"258"},{"label":"Дарк соулс","value":"6057"},{"label":"Дарт вейдер","value":"6826"},{"label":"Дафна гринграсс","value":"5192"},{"label":"Дворяне","value":"7204"},{"label":"Девушки","value":"7668"},{"label":"Девушки монстры","value":"2231"},{"label":"Дедушка и внучка","value":"8400"},{"label":"Дейви джонс","value":"8061"},{"label":"Действие","value":"1425"},{"label":"Демон лорд","value":"153"},{"label":"Демонология","value":"2024"},{"label":"Демоны","value":"1406"},{"label":"Дети","value":"580"},{"label":"Джарвис","value":"933"},{"label":"Джедай","value":"4442"},{"label":"Джин","value":"4024"},{"label":"Джокер","value":"3351"},{"label":"Джон сноу","value":"7412"},{"label":"Джоффри баратеон","value":"3936"},{"label":"Дзесэй","value":"678"},{"label":"Дин винчестер","value":"6953"},{"label":"Династии","value":"2982"},{"label":"Динозавры","value":"3666"},{"label":"Директор","value":"1417"},{"label":"Для девушек","value":"1441"},{"label":"Дневник","value":"298"},{"label":"Добби","value":"6762"},{"label":"Добрый мир","value":"1685"},{"label":"Договоры с богами","value":"2152"},{"label":"Договоры с демонами","value":"1922"},{"label":"Доктор","value":"1991"},{"label":"Доктор стрэндж","value":"7634"},{"label":"Доминирование","value":"2054"},{"label":"Дота","value":"6965"},{"label":"Доудзюцу","value":"7133"},{"label":"Дочь","value":"3291"},{"label":"Драко малфой","value":"46"},{"label":"Драконы","value":"282"},{"label":"Драконы оборотни","value":"8082"},{"label":"Древние времена","value":"7781"},{"label":"Древний египет","value":"7614"},{"label":"Древний китай","value":"473"},{"label":"Древний мир","value":"4"},{"label":"Другая вселенная","value":"39"},{"label":"Другие планеты","value":"2371"},{"label":"Другой мир","value":"2248"},{"label":"Дружба","value":"1903"},{"label":"Друзья детства","value":"1153"},{"label":"Духи","value":"114"},{"label":"Духовные силы","value":"1955"},{"label":"Души","value":"1212"},{"label":"Дьявол","value":"1094"},{"label":"Дьявольские фрукты","value":"1564"},{"label":"Дэдпул","value":"4399"},{"label":"Евнух","value":"6293"},{"label":"Европейская атмосфера","value":"5837"},{"label":"Египет","value":"528"},{"label":"Еда","value":"2056"},{"label":"Единороги","value":"437"},{"label":"Екаи","value":"655"},{"label":"Жалкий главный герой","value":"97"},{"label":"Жена","value":"5729"},{"label":"Женское доминирование","value":"4622"},{"label":"Женщина в теле мужчины","value":"2748"},{"label":"Женщина кошка","value":"7513"},{"label":"Жестокие персонажи","value":"3153"},{"label":"Жестокий мир","value":"1532"},{"label":"Жестокость","value":"7880"},{"label":"Животные","value":"7488"},{"label":"Животные компаньоны","value":"2061"},{"label":"Жизнь и смерть","value":"2014"},{"label":"Жнец","value":"6288"},{"label":"Жойен рид","value":"3926"},{"label":"Заботливый главный герой","value":"338"},{"label":"Закалка тела","value":"148"},{"label":"Заклинания","value":"558"},{"label":"Заключенные","value":"3052"},{"label":"Занпакто","value":"1102"},{"label":"Запретная любовь","value":"8033"},{"label":"Запутанный сюжет","value":"1041"},{"label":"Захват мира","value":"315"},{"label":"Зачарованные","value":"4169"},{"label":"Звери","value":"1638"},{"label":"Зверодевочки","value":"2006"},{"label":"Зверолюди","value":"1018"},{"label":"Земля","value":"82"},{"label":"Злая организация","value":"7768"},{"label":"Зло","value":"1512"},{"label":"Злодей","value":"1060"},{"label":"Злодейка","value":"2376"},{"label":"Злой главный герой","value":"616"},{"label":"Злые боги","value":"7109"},{"label":"Злые персонажи","value":"3243"},{"label":"Змей","value":"5721"},{"label":"Знаменитости","value":"1341"},{"label":"Знание медицины","value":"1411"},{"label":"Золушка","value":"2980"},{"label":"Зомби","value":"1743"},{"label":"Зомби апокалипсис","value":"912"},{"label":"Зона 51","value":"3051"},{"label":"Зооморфы","value":"375"},{"label":"Зорро","value":"6736"},{"label":"Зрелые женщины","value":"1458"},{"label":"Игра","value":"663"},{"label":"Игра на выживание","value":"2182"},{"label":"Игровая система","value":"384"},{"label":"Игровые элементы","value":"720"},{"label":"Извращения","value":"651"},{"label":"Измена","value":"1874"},{"label":"Изменение характера","value":"1113"},{"label":"Изменения внешности","value":"259"},{"label":"Изменения личности","value":"1080"},{"label":"Изобретения","value":"126"},{"label":"Изуку мидория","value":"6967"},{"label":"Император","value":"867"},{"label":"Империи","value":"712"},{"label":"Империя","value":"1716"},{"label":"Инвалидность","value":"2073"},{"label":"Инквизитор","value":"143"},{"label":"Инкуб","value":"3264"},{"label":"Инопланетное вторжение","value":"209"},{"label":"Инопланетяне","value":"866"},{"label":"Интерактив с читателями","value":"472"},{"label":"Интересный сюжет","value":"7374"},{"label":"Интернет","value":"739"},{"label":"Интимные сцены","value":"3450"},{"label":"Интрига","value":"317"},{"label":"Интриги и заговоры","value":"1009"},{"label":"Иные миры","value":"35"},{"label":"Исекай","value":"2979"},{"label":"Искусственный интеллект","value":"1900"},{"label":"Исследование","value":"1626"},{"label":"Исторический роман","value":"573"},{"label":"Итачи учиха","value":"4556"},{"label":"Ичиго","value":"7254"},{"label":"Йода","value":"6829"},{"label":"Йоруичи","value":"6755"},{"label":"Калипсо","value":"8062"},{"label":"Каннибализм","value":"2249"},{"label":"Капитан америка","value":"6301"},{"label":"Каракура","value":"7473"},{"label":"Карточная игра","value":"1557"},{"label":"Кастиэль","value":"6954"},{"label":"Кафе","value":"3934"},{"label":"Кацуки бакуго","value":"7696"},{"label":"Квесты","value":"1707"},{"label":"Киберспорт","value":"1984"},{"label":"Кино","value":"7126"},{"label":"Китай","value":"3762"},{"label":"Кицунэ","value":"241"},{"label":"Кланы","value":"834"},{"label":"Клоны","value":"1624"},{"label":"Книги","value":"1068"},{"label":"Книжный червь","value":"521"},{"label":"Колдовство","value":"2681"},{"label":"колледж","value":"5058"},{"label":"Коллекционер","value":"2588"},{"label":"Кольцо","value":"1628"},{"label":"Коммунисты","value":"1042"},{"label":"Коноха","value":"2827"},{"label":"Контракт","value":"4304"},{"label":"Контроль разума","value":"485"},{"label":"Конфеты","value":"341"},{"label":"Корейцы","value":"6535"},{"label":"Корея","value":"2443"},{"label":"Королевская власть","value":"55"},{"label":"Королевская семья","value":"276"},{"label":"Королевство","value":"1695"},{"label":"Короткий рассказ","value":"239"},{"label":"Коррупция","value":"831"},{"label":"Космическая опера","value":"2245"},{"label":"Космические рейнджеры","value":"5860"},{"label":"Космос","value":"329"},{"label":"Кот","value":"5171"},{"label":"Кража навыков","value":"1159"},{"label":"Красивая главная героиня","value":"186"},{"label":"Красивые женщины","value":"66"},{"label":"Красивые персонажи","value":"5787"},{"label":"Красивый главный герой","value":"895"},{"label":"Крафт","value":"1599"},{"label":"Кроссовер","value":"75"},{"label":"Ктулху","value":"920"},{"label":"Кузнец","value":"853"},{"label":"Кукла","value":"3085"},{"label":"Кулинария","value":"2230"},{"label":"Культивация","value":"1901"},{"label":"Культивирование","value":"1860"},{"label":"Курама","value":"5709"},{"label":"Курилин","value":"6134"},{"label":"Кушина узумаки","value":"5222"},{"label":"Лавкрафт","value":"6063"},{"label":"Лара крофт","value":"6435"},{"label":"Легенда о зельде","value":"5707"},{"label":"Ленивый главный герой","value":"1516"},{"label":"Леон золдик","value":"7469"},{"label":"Лес","value":"6645"},{"label":"Лечебная магия","value":"562"},{"label":"Локи","value":"1725"},{"label":"Лоли","value":"1576"},{"label":"Лопата","value":"4989"},{"label":"Лорд","value":"8404"},{"label":"Лориен","value":"7397"},{"label":"Лошади","value":"6110"},{"label":"Лунатизм","value":"3520"},{"label":"Луффи","value":"274"},{"label":"Лучник","value":"1038"},{"label":"Любовный интерес влюбляется первым","value":"7753"},{"label":"Любовный треугольник","value":"2109"},{"label":"Любовь","value":"2297"},{"label":"Любовь с первого взгляда","value":"7748"},{"label":"Любящие родители","value":"2699"},{"label":"Люди","value":"3572"},{"label":"Люцифер","value":"5883"},{"label":"Маг","value":"780"},{"label":"Магазин","value":"4762"},{"label":"Маги","value":"58"},{"label":"Магическая академия","value":"6788"},{"label":"Магические звери","value":"684"},{"label":"Магические предметы","value":"1648"},{"label":"Магический мир","value":"578"},{"label":"Магия","value":"150"},{"label":"Магия воды","value":"6450"},{"label":"Магия воздуха","value":"7627"},{"label":"Магия земли","value":"7626"},{"label":"Магия и технология","value":"107"},{"label":"Магия крови","value":"7976"},{"label":"Магия льда","value":"1379"},{"label":"Магия огня","value":"7625"},{"label":"Магия призыва","value":"885"},{"label":"Магия природы","value":"6226"},{"label":"Магия стихий","value":"7673"},{"label":"Магия тьмы","value":"3596"},{"label":"Мадара","value":"2929"},{"label":"Мазохизм","value":"1961"},{"label":"Мама","value":"12"},{"label":"Мама и дочь","value":"7894"},{"label":"Мама и сын","value":"7895"},{"label":"Манга","value":"2464"},{"label":"Манипуляция временем","value":"932"},{"label":"Маньяк","value":"2026"},{"label":"Маргери тирелл","value":"3935"},{"label":"Марионетки","value":"3175"},{"label":"Марс","value":"4013"},{"label":"Марти стью","value":"594"},{"label":"Мастер на все руки","value":"3189"},{"label":"Матриархат","value":"7197"},{"label":"Мать и сестры","value":"7946"},{"label":"Мафия","value":"353"},{"label":"Мачеха","value":"4664"},{"label":"Мегаполис","value":"3322"},{"label":"Медицина","value":"441"},{"label":"Медленная романтика","value":"8383"},{"label":"Медленное развитие истории","value":"7462"},{"label":"Мелиодас","value":"7224"},{"label":"Мелодрама","value":"1507"},{"label":"Менеджмент","value":"368"},{"label":"Мерлин","value":"3977"},{"label":"Месть","value":"1218"},{"label":"Меч","value":"48"},{"label":"Мечники","value":"969"},{"label":"Мечта","value":"527"},{"label":"Мизуки","value":"4269"},{"label":"Микото","value":"3862"},{"label":"Милая главная героиня","value":"134"},{"label":"Милф","value":"1987"},{"label":"Милый главный герой","value":"2678"},{"label":"Мимик","value":"5706"},{"label":"Мина ашидо","value":"7695"},{"label":"Минато намикадзе","value":"5223"},{"label":"Мир будущего","value":"1770"},{"label":"Мир земли","value":"8394"},{"label":"Мир меча и магии","value":"1271"},{"label":"Мистер пропер","value":"565"},{"label":"Мифические существа","value":"1878"},{"label":"Мифы и легенды","value":"4463"},{"label":"Младшая сестра","value":"1523"},{"label":"Мморпг","value":"620"},{"label":"Много главных героев","value":"1191"},{"label":"Много крови","value":"5318"},{"label":"Много персонажей","value":"1539"},{"label":"Множество королевств","value":"32"},{"label":"Модерн","value":"5457"},{"label":"Мокутон","value":"4438"},{"label":"Молоко","value":"5469"},{"label":"Монархия","value":"3590"},{"label":"Монстры","value":"307"},{"label":"Море","value":"922"},{"label":"Моритика ринносукэ","value":"1142"},{"label":"Мортал комбат","value":"5861"},{"label":"Мошенник","value":"959"},{"label":"Мрачный мир","value":"1"},{"label":"Мужчина в женском теле","value":"8405"},{"label":"Музыка","value":"1183"},{"label":"Мультивселенная","value":"7410"},{"label":"Мурим","value":"7342"},{"label":"Мутанты","value":"2392"},{"label":"Мутация","value":"29"},{"label":"Мясо","value":"1503"},{"label":"На реальных событиях","value":"26"},{"label":"Навыки","value":"415"},{"label":"Нагато узумаки","value":"5221"},{"label":"Наемники","value":"1668"},{"label":"Назарик","value":"5369"},{"label":"Наивный главный герой","value":"159"},{"label":"Наложница","value":"4867"},{"label":"Наноботы","value":"2332"},{"label":"Наруто","value":"7177"},{"label":"Наруто и хината","value":"5766"},{"label":"Насилие и жестокость","value":"1440"},{"label":"Наука","value":"2150"},{"label":"Национализм","value":"5556"},{"label":"Нацу","value":"5826"},{"label":"Нацуки субару","value":"6656"},{"label":"Начальная школа","value":"3920"},{"label":"Наши дни","value":"1814"},{"label":"Не всесильный главный герой","value":"42"},{"label":"Не по канону","value":"1611"},{"label":"Неверность","value":"5735"},{"label":"Невеста","value":"6011"},{"label":"Неджи хьюга","value":"3099"},{"label":"Недооценённый главный герой","value":"43"},{"label":"Нежить","value":"1949"},{"label":"Некромаг","value":"7441"},{"label":"Некромант","value":"1914"},{"label":"Некромантия","value":"754"},{"label":"Ненормативная лексика","value":"160"},{"label":"Необычные герои","value":"67"},{"label":"Нет людей","value":"7486"},{"label":"Нетораре","value":"403"},{"label":"Нетори","value":"5393"},{"label":"Нефилимы","value":"7764"},{"label":"Нецензурная лексика","value":"4912"},{"label":"Нечисть","value":"4559"},{"label":"Ник фьюри","value":"6304"},{"label":"Ниндзюцу","value":"2354"},{"label":"Ниндзя","value":"1330"},{"label":"Новелла","value":"2105"},{"label":"Нэко","value":"147"},{"label":"Оби ван кеноби","value":"6830"},{"label":"Обито учиха","value":"2814"},{"label":"Оборотни","value":"53"},{"label":"Обратный гарем","value":"3303"},{"label":"Овощ","value":"6098"},{"label":"Огнестрельное оружие","value":"3155"},{"label":"Одержимость","value":"708"},{"label":"Один в поле воин","value":"6498"},{"label":"Онлайн игра","value":"1565"},{"label":"Ооками теппей","value":"849"},{"label":"Оригинальные персонажи","value":"7741"},{"label":"Орки","value":"1597"},{"label":"Оружие","value":"125"},{"label":"Основано на видео игре","value":"602"},{"label":"Особые способности","value":"2904"},{"label":"От бедности к богатству","value":"901"},{"label":"От слабого до сильного","value":"118"},{"label":"Отель","value":"2879"},{"label":"Отец","value":"3290"},{"label":"Отношения","value":"398"},{"label":"Отношения человек/нечеловек","value":"7406"},{"label":"Офис","value":"3460"},{"label":"Охотники","value":"2263"},{"label":"Оцуцуки","value":"5101"},{"label":"Ошейник","value":"2362"},{"label":"Ояш","value":"8048"},{"label":"Падчерица","value":"7023"},{"label":"Падший ангел","value":"184"},{"label":"Палач","value":"852"},{"label":"Палочка","value":"2682"},{"label":"Пандорум","value":"4360"},{"label":"Папа и дочь","value":"7647"},{"label":"Паразит","value":"1213"},{"label":"Параллельный мир","value":"2092"},{"label":"Парень","value":"619"},{"label":"Паркур","value":"3391"},{"label":"Пародия","value":"898"},{"label":"Пасхалки","value":"455"},{"label":"Паук","value":"2209"},{"label":"Пекарь","value":"5073"},{"label":"Первая книга","value":"269"},{"label":"Первая любовь","value":"640"},{"label":"Первый раз","value":"1465"},{"label":"Переводы","value":"24"},{"label":"Перевоплощение","value":"1596"},{"label":"Перевоплощение в игровом мире","value":"92"},{"label":"Перемещение в другой мир","value":"1288"},{"label":"Перемещение во времени","value":"146"},{"label":"Перерождение","value":"894"},{"label":"Перерождение в демона","value":"1111"},{"label":"Перерождение в дракона","value":"6867"},{"label":"Перерождение в злодейку","value":"5619"},{"label":"Перерождение в злодея","value":"749"},{"label":"Перерождение в ином мире","value":"109"},{"label":"Перерождение в монстра","value":"917"},{"label":"Перерождений","value":"335"},{"label":"Переселение","value":"813"},{"label":"Переселение души","value":"1864"},{"label":"Перси джексон","value":"6329"},{"label":"Пилот","value":"5521"},{"label":"Пилюли","value":"1531"},{"label":"Пират","value":"1579"},{"label":"Пирог","value":"80"},{"label":"Писатель","value":"734"},{"label":"Пистолеты","value":"4916"},{"label":"Письмо","value":"840"},{"label":"Питомцы","value":"3122"},{"label":"Планомерное развитие событий","value":"62"},{"label":"Племянник","value":"8303"},{"label":"Пленница","value":"4897"},{"label":"Плети","value":"4839"},{"label":"Пляж","value":"4243"},{"label":"Повар","value":"658"},{"label":"Повествование от первого лица","value":"1054"},{"label":"Повествование от разных лиц","value":"600"},{"label":"Повествование от третьего лица","value":"2116"},{"label":"Подавитель","value":"497"},{"label":"Подземелье","value":"798"},{"label":"Подростки","value":"636"},{"label":"Подруга","value":"5804"},{"label":"Подчинение","value":"8343"},{"label":"Подчинение и унижение","value":"4500"},{"label":"Покемоны","value":"2840"},{"label":"Полиамория","value":"1300"},{"label":"Полигамия","value":"1336"},{"label":"Политика","value":"1313"},{"label":"Полицейский","value":"1907"},{"label":"Полубог","value":"7170"},{"label":"Полукровка","value":"999"},{"label":"Полулюди","value":"2273"},{"label":"Поношенные трусики","value":"1204"},{"label":"Попаданец","value":"2396"},{"label":"Попаданец в другой мир","value":"685"},{"label":"Попаданец в игру","value":"6466"},{"label":"Попадание в книгу","value":"6957"},{"label":"Постапокалипсис","value":"1079"},{"label":"Похищение","value":"7452"},{"label":"Поэзия","value":"1120"},{"label":"Правитель","value":"2261"},{"label":"Превращения в животных","value":"3410"},{"label":"Преданный любовный интерес","value":"2055"},{"label":"Предательство","value":"70"},{"label":"Президент","value":"4334"},{"label":"Преступник","value":"4049"},{"label":"Преступный мир","value":"965"},{"label":"Призрак","value":"511"},{"label":"Призыв","value":"332"},{"label":"Призыв в другой мир","value":"781"},{"label":"Призыв существ","value":"412"},{"label":"Приложение на телефоне","value":"5345"},{"label":"Принудительный брак","value":"2954"},{"label":"Принуждение","value":"1442"},{"label":"Принц","value":"362"},{"label":"Принцесса","value":"2403"},{"label":"Приручение мостров","value":"2338"},{"label":"Прислуга","value":"5185"},{"label":"Пришельцы","value":"273"},{"label":"Проза","value":"2012"},{"label":"Прокачка","value":"1070"},{"label":"Проклятия","value":"1347"},{"label":"Проработанный мир","value":"1711"},{"label":"Пророчество","value":"7762"},{"label":"Против наркотиков","value":"8406"},{"label":"Псайкеры","value":"3659"},{"label":"Псионика","value":"5216"},{"label":"Психбольница","value":"6969"},{"label":"Психические расстройства","value":"2445"},{"label":"Психологические травмы","value":"3418"},{"label":"Публичный дом","value":"7860"},{"label":"Путешествие в другой мир","value":"10"},{"label":"Пух","value":"4286"},{"label":"Пушечное мясо","value":"7234"},{"label":"Пытки","value":"1756"},{"label":"Пьяный мастер","value":"1655"},{"label":"Пэнси паркинсон","value":"7411"},{"label":"Раб","value":"977"},{"label":"Рабы","value":"1240"},{"label":"Разведение животных","value":"3990"},{"label":"Развитие","value":"208"},{"label":"Развитие персонажа","value":"1780"},{"label":"Развитие поселения","value":"7203"},{"label":"Развитие технологий","value":"1875"},{"label":"Раздвоение личности","value":"2062"},{"label":"Разные расы","value":"1188"},{"label":"Разорванная помолвка","value":"2057"},{"label":"Разработчик","value":"2333"},{"label":"Ранги","value":"1568"},{"label":"Ранобэ","value":"1764"},{"label":"Расизм","value":"3554"},{"label":"Растение","value":"407"},{"label":"Реализм","value":"1180"},{"label":"Ребенок","value":"2881"},{"label":"Ревность","value":"293"},{"label":"Революция","value":"3996"},{"label":"Реинкарнация","value":"1302"},{"label":"Реинкарнация в другом мире","value":"2180"},{"label":"Реинкарнация в игровой мир","value":"304"},{"label":"Рейджер","value":"5147"},{"label":"Религия","value":"2184"},{"label":"Рем","value":"6655"},{"label":"Ремесленник","value":"1483"},{"label":"Ремонт","value":"5703"},{"label":"Репликаторы","value":"3495"},{"label":"Ресторан","value":"7519"},{"label":"Риас гремори","value":"6950"},{"label":"Рим","value":"612"},{"label":"Риннеган","value":"4230"},{"label":"Ритуал","value":"1233"},{"label":"Робот","value":"4011"},{"label":"Роботы","value":"467"},{"label":"Рок ли","value":"7002"},{"label":"Рокси","value":"7380"},{"label":"Рон уизли","value":"4279"},{"label":"Ророноа зоро","value":"1590"},{"label":"Росомаха","value":"1035"},{"label":"Российская империя","value":"2146"},{"label":"Россия","value":"4246"},{"label":"Рудеус","value":"7379"},{"label":"Руны","value":"2393"},{"label":"Русалки","value":"3127"},{"label":"Русь","value":"2016"},{"label":"Рыцари","value":"1902"},{"label":"Рэо хатаке","value":"2823"},{"label":"Сабли","value":"6136"},{"label":"Сайян","value":"6802"},{"label":"Сакура","value":"2515"},{"label":"Самец","value":"1592"},{"label":"Самураи","value":"576"},{"label":"Санса старк","value":"3925"},{"label":"Сарказм","value":"4658"},{"label":"Саске","value":"7237"},{"label":"Сатира","value":"215"},{"label":"Сборник","value":"7367"},{"label":"Свадьба","value":"1524"},{"label":"Сверхсила","value":"1055"},{"label":"Свинцовые книги","value":"5322"},{"label":"Связывание","value":"4506"},{"label":"Священик","value":"61"},{"label":"Северус снейп","value":"5783"},{"label":"Сёдзе","value":"2219"},{"label":"Секты","value":"1234"},{"label":"Сельское хозяйство","value":"787"},{"label":"Семейный конфликт","value":"935"},{"label":"Семья","value":"728"},{"label":"Сенджу","value":"6069"},{"label":"Серийный убийца","value":"261"},{"label":"Сестра","value":"2342"},{"label":"Сила глаза","value":"1019"},{"label":"Сильная героиня","value":"7292"},{"label":"Сильная главная героиня","value":"1994"},{"label":"Сильный главный герой","value":"570"},{"label":"Сильфиетта","value":"7381"},{"label":"Симбиот","value":"2648"},{"label":"Сириус блэк","value":"7655"},{"label":"Сирота","value":"297"},{"label":"Система","value":"251"},{"label":"Система уровней","value":"2174"},{"label":"Ситх","value":"1618"},{"label":"Сказка","value":"3570"},{"label":"Скайрим","value":"4032"},{"label":"Скайуокер","value":"6828"},{"label":"Сквиб","value":"4101"},{"label":"Скелет","value":"1315"},{"label":"Скрытые способности","value":"3417"},{"label":"Скульптор","value":"1178"},{"label":"Слабая главная героиня","value":"5805"},{"label":"Слабый главный герой","value":"731"},{"label":"Славяне","value":"2168"},{"label":"Слизерин","value":"6979"},{"label":"Слизь","value":"1095"},{"label":"Сломанная игрушка","value":"8396"},{"label":"Служанка","value":"3486"},{"label":"Смартфон","value":"457"},{"label":"Смена сущности","value":"8391"},{"label":"Смерть","value":"1779"},{"label":"Смерть основного персонажа","value":"1530"},{"label":"Собаки","value":"6109"},{"label":"Соблазн","value":"7994"},{"label":"Соблазнение","value":"2290"},{"label":"Современность","value":"568"},{"label":"Современные знания","value":"988"},{"label":"Сожительство","value":"3026"},{"label":"Создание армии","value":"1992"},{"label":"Создание королевства","value":"1497"},{"label":"Создание пилюль","value":"816"},{"label":"Создатель","value":"1045"},{"label":"Сокровища","value":"6521"},{"label":"Сокрытие истинной личности","value":"2894"},{"label":"Сома и эрина","value":"5737"},{"label":"Соперничество","value":"7699"},{"label":"Соседи","value":"4075"},{"label":"Сотрудник","value":"6339"},{"label":"Социология","value":"7618"},{"label":"Спокойная главная героиня","value":"236"},{"label":"Спокойный главный герой","value":"1656"},{"label":"Спор","value":"3484"},{"label":"Спортивное тело","value":"8317"},{"label":"Способность кражи","value":"7784"},{"label":"Сражения","value":"23"},{"label":"Средневековье","value":"1022"},{"label":"Сталкер","value":"1932"},{"label":"Становление государства","value":"111"},{"label":"Старшая школа","value":"1658"},{"label":"Стёб","value":"454"},{"label":"Стекло","value":"7453"},{"label":"Стеснительный персонаж","value":"152"},{"label":"Стимпанк","value":"1894"},{"label":"Стихи","value":"1309"},{"label":"Стратегия","value":"569"},{"label":"Строительство","value":"921"},{"label":"Студент","value":"1464"},{"label":"Студентка","value":"7518"},{"label":"Суккубы","value":"2662"},{"label":"Супер зрение","value":"6574"},{"label":"Супер удача","value":"489"},{"label":"Супергерои","value":"1481"},{"label":"Суперзлодеи","value":"2125"},{"label":"Супермен","value":"6997"},{"label":"Суперсилы","value":"2276"},{"label":"Существа","value":"6033"},{"label":"Сферы","value":"1077"},{"label":"Схемы и заговоры","value":"7116"},{"label":"Сценарий","value":"7489"},{"label":"Счастливый конец","value":"3293"},{"label":"Сын","value":"3297"},{"label":"Сэм винчестер","value":"7461"},{"label":"Сюаньхуа","value":"2560"},{"label":"Сюжетные повороты","value":"7202"},{"label":"Таблетки для развития","value":"589"},{"label":"Таинственное прошлое","value":"769"},{"label":"Тайная личность","value":"8096"},{"label":"Тайная любовь","value":"113"},{"label":"Тайны","value":"7481"},{"label":"Тайные отношения","value":"7450"},{"label":"Тайцы","value":"6413"},{"label":"Танки","value":"1787"},{"label":"Творчество","value":"20"},{"label":"Тейлор эберт","value":"3526"},{"label":"Телекинез","value":"2203"},{"label":"Телепортация","value":"914"},{"label":"Телохранитель","value":"723"},{"label":"Темари","value":"4810"},{"label":"Темная магия","value":"4788"},{"label":"Темное фэнтези","value":"1675"},{"label":"Темные эльфы","value":"7198"},{"label":"Тенсейган","value":"4367"},{"label":"Тетя","value":"4194"},{"label":"Техномагия","value":"508"},{"label":"Тиран","value":"1174"},{"label":"Титаны","value":"3308"},{"label":"Тодороки шото","value":"5105"},{"label":"Токио","value":"5791"},{"label":"Том реддл","value":"6652"},{"label":"Тони старк","value":"1338"},{"label":"Тор","value":"1800"},{"label":"Тор и локи","value":"2645"},{"label":"Торговля","value":"1637"},{"label":"Травничество","value":"221"},{"label":"Трагическое прошлое","value":"644"},{"label":"Трактир","value":"1918"},{"label":"Трансмиграция","value":"1071"},{"label":"Трансформация","value":"156"},{"label":"Трансформеры","value":"4616"},{"label":"Тревор филипс","value":"5427"},{"label":"Тройняшки","value":"7169"},{"label":"Троли","value":"4250"},{"label":"Трудолюбивый главный герой","value":"248"},{"label":"Тупой главный герой","value":"3710"},{"label":"Тьма","value":"1919"},{"label":"Тюрьма","value":"5597"},{"label":"Тяжёлое детство","value":"2253"},{"label":"Убийства","value":"378"},{"label":"Убийцы","value":"1766"},{"label":"Убийцы драконов","value":"1484"},{"label":"Увечья","value":"3266"},{"label":"Удача","value":"6575"},{"label":"Узумаки","value":"7579"},{"label":"Укротитель","value":"367"},{"label":"Умения","value":"531"},{"label":"Умная главная героиня","value":"1381"},{"label":"Умные персонажи","value":"2756"},{"label":"Умный главный герой","value":"2093"},{"label":"Университет","value":"2102"},{"label":"Унижение","value":"8342"},{"label":"Уничтожение мира","value":"81"},{"label":"Управление временем","value":"5648"},{"label":"Уровни","value":"8"},{"label":"Усиление","value":"3549"},{"label":"Усопп","value":"6737"},{"label":"Устроенный брак","value":"2223"},{"label":"Усыновление","value":"395"},{"label":"Утопия","value":"4677"},{"label":"Уход за детьми","value":"7609"},{"label":"Учеба в университете","value":"2797"},{"label":"Учебное заведение","value":"1817"},{"label":"Ученые","value":"1843"},{"label":"Учитель","value":"845"},{"label":"Учиха","value":"5348"},{"label":"Фамильяры","value":"1471"},{"label":"Фанатичная любовь","value":"6721"},{"label":"Фанаты","value":"7739"},{"label":"Фантастический мир","value":"2414"},{"label":"Фармацевт","value":"1706"},{"label":"Фашисты","value":"3118"},{"label":"Феи","value":"7185"},{"label":"Фелляция","value":"5880"},{"label":"Феминизм","value":"6527"},{"label":"Феникс","value":"2413"},{"label":"Фенрир","value":"2740"},{"label":"Феодализм","value":"280"},{"label":"Ферма","value":"285"},{"label":"Фехтовальщик","value":"4685"},{"label":"Филиппины","value":"128"},{"label":"Философия","value":"1859"},{"label":"Флафф","value":"5048"},{"label":"Флер делакур","value":"5191"},{"label":"Флэш","value":"4667"},{"label":"Фокусник","value":"7602"},{"label":"Фольклор","value":"4086"},{"label":"Фугаку","value":"6161"},{"label":"Фурри","value":"6631"},{"label":"Футбол","value":"1121"},{"label":"Фэнтезийный мир","value":"1556"},{"label":"Хакер","value":"475"},{"label":"Халк","value":"1196"},{"label":"Хан нуньен синг","value":"4817"},{"label":"Ханма юджиро","value":"4369"},{"label":"Хаос","value":"3117"},{"label":"Харизматичный главный герой","value":"2350"},{"label":"Хатаке какаши","value":"2820"},{"label":"Хиддлстон","value":"5903"},{"label":"Химавари","value":"2583"},{"label":"Хината","value":"2513"},{"label":"Хитрый главный герой","value":"2036"},{"label":"Хоббит","value":"6698"},{"label":"Хогвартс","value":"5954"},{"label":"Холодная главная героиня","value":"6507"},{"label":"Холодное оружие","value":"4889"},{"label":"Холодный главный герой","value":"2686"},{"label":"Храм","value":"2135"},{"label":"Христианство","value":"877"},{"label":"Художественная литература","value":"2380"},{"label":"Художница","value":"518"},{"label":"Хулиганы","value":"854"},{"label":"Цветок","value":"902"},{"label":"Цезарь","value":"1705"},{"label":"Целители","value":"4523"},{"label":"Церковь","value":"1980"},{"label":"Цундере","value":"1078"},{"label":"Чакра","value":"1393"},{"label":"Чат-система","value":"8407"},{"label":"Черный юмор","value":"2868"},{"label":"Честная главная героиня","value":"5855"},{"label":"Честный главный герой","value":"129"},{"label":"Читы","value":"451"},{"label":"Шантаж","value":"7175"},{"label":"Шаринган","value":"5165"},{"label":"Шинигами","value":"4661"},{"label":"Шиноби","value":"1227"},{"label":"Школьная жизнь","value":"284"},{"label":"Школьники","value":"218"},{"label":"Школьницы","value":"5946"},{"label":"Шлюха","value":"5822"},{"label":"Шоу-бизнес","value":"7119"},{"label":"Шпионы","value":"4262"},{"label":"Эволюция","value":"2040"},{"label":"Экзорцизм","value":"676"},{"label":"Экономика","value":"121"},{"label":"Экспансия","value":"110"},{"label":"Эксперименты над людьми","value":"7408"},{"label":"Элементальная магия","value":"1264"},{"label":"Эльфы","value":"1362"},{"label":"Эротика","value":"2053"},{"label":"Юмор","value":"7360"},{"label":"Яды","value":"201"},{"label":"Якудза","value":"4599"},{"label":"Яндере","value":"7111"},{"label":"Rpg","value":"90"},{"label":"Star wars","value":"1985"},{"label":"Time skip","value":"824"},{"label":"Warrior of light","value":"5289"}],"inputType":FilterInputs.Checkbox},{"key":"fandoms_ex","label":"Исключить фэндомы:","values":[{"label":"19 Дней - Один день / 19 Days - One Day","value":"838"},{"label":"47-й / Хитмэн: Агент 47 / Наёмный убийца / Hitman","value":"589"},{"label":"Абсолютный дуэт / Absolute Duo","value":"1029"},{"label":"Аватар (Короля; об Аанге; об Корре) / Avatar","value":"1889"},{"label":"Аватар: Легенда о Корре / Avatar legend of Korra","value":"351"},{"label":"Аватар: Легенда об Аанге / Avatar: The Legend of Aang / Avatar: The Last Airbender","value":"303"},{"label":"Аватар(Фильм, 2009) / Avatar","value":"19"},{"label":"Ад Данте(Данте Алигьери) / Dante's Inferno(Dante Alighieri)","value":"1502"},{"label":"Азур Лейн / Azur Lane","value":"1009"},{"label":"Айон / Aion","value":"1005"},{"label":"Аладдин / Aladdin","value":"502"},{"label":"Алиса в Стране чудес / Alice in Wonderland","value":"616"},{"label":"Альдноа.Зеро / Aldnoah.Zero","value":"1799"},{"label":"Амагами СС / Amagami SS","value":"900"},{"label":"Амано Мегуми полна любви! / Amano Megumi wa Sukidarake!","value":"991"},{"label":"Американские боги / American Gods","value":"1843"},{"label":"Американский папаша! / American Dad","value":"348"},{"label":"Ангельские ритмы! / Angel Beats!","value":"880"},{"label":"Анлимитед: Хёбу Кёске / Zettai Karen Children: The Unlimited - Hyoubu Kyousuke","value":"74"},{"label":"Апостол карточек / The Apostle of Cards","value":"1504"},{"label":"Арифурэта: сильнейший ремесленник в мире / Arifureta: From Commonplace to World's Strongest","value":"62"},{"label":"Аркан: О Паровых Заводах и Магии Обскуры / Arcanum: Of Steamworks and Magick Obscura","value":"1495"},{"label":"Аркейн / Arcane: League of Legends","value":"1154"},{"label":"Аркнайтс(Games) / Arknights","value":"1210"},{"label":"Армелло(Games) / Armello","value":"1846"},{"label":"Астра, затерянная в космосе / Kanata no Astra","value":"1851"},{"label":"Атака титанов / Атака на титанов / Attack on Titan","value":"106"},{"label":"Атлантида: Затерянный мир / Atlantis: The Lost Empire","value":"985"},{"label":"Бакуган Отчаянные бойцы / Bakugan Battle Brawlers","value":"1069"},{"label":"Банановая рыба / Banana Fish","value":"1685"},{"label":"Баскетбол Куроко / Kuroko no basuke","value":"582"},{"label":"Баффи - Истребительница вампиров / Buffy the Vampire Slayer","value":"115"},{"label":"Башня Бога / Tower of God","value":"58"},{"label":"Бездарная Нана / Munou na Nana","value":"954"},{"label":"Бездомный бог / Норагами / Noragami","value":"1014"},{"label":"Безумные Мотивы / Looney Tunes","value":"1140"},{"label":"Безумный азарт / Kakegurui","value":"334"},{"label":"Бейблэйд / Beyblade","value":"921"},{"label":"Бен - 10 / Ben 10","value":"475"},{"label":"Берсерк / Berserk","value":"479"},{"label":"Бесконечное лето / Everlasting Summer","value":"966"},{"label":"Бесконечный ужас / Terror Infinity","value":"381"},{"label":"Бесподобный Воинственный Бог / Peerless Martial God","value":"419"},{"label":"Бессмертный Деревенщина(Games) / Immortal Redneck","value":"1524"},{"label":"Бесстыжие / Shameless","value":"1759"},{"label":"Био шок(Games) / BioShock","value":"1095"},{"label":"Блейд / Blade","value":"1479"},{"label":"Блич / Bleach","value":"7"},{"label":"Бог войны / God Of War","value":"352"},{"label":"Бог из машины / Deus Ex","value":"612"},{"label":"Боги поступают плохо / Игры богов / Gods Behaving Badly","value":"301"},{"label":"Боевая академия города Астериск / Gakusen Toshi Asterisk","value":"884"},{"label":"Боевой континент / Combat Continent / Douluo Dalu","value":"739"},{"label":"Боевой молот 40-го тысячелетия / WH40K / Warhammer 40,000","value":"341"},{"label":"Боевой молот Фэнтезийная битва / Warhammer Fantasy Battles","value":"1742"},{"label":"Боевые машины(Games) / BattleTech","value":"1667"},{"label":"Боец Баки / Baki the Grappler","value":"821"},{"label":"Божественность II: Эго Дракона(Games) / Divinity II: Ego Draconis","value":"1538"},{"label":"Божественные Врата / Divine Gate","value":"1490"},{"label":"Большая автомобильная кража 5 / GTA V / Grand Theft Auto V","value":"1139"},{"label":"Большая автомобильная кража: Сан-Андреас / GTA: SA / Grand Theft Auto: San Andreas","value":"820"},{"label":"Большая разница / Far Cry","value":"939"},{"label":"Большой куш / Ван Пис / One Piece","value":"25"},{"label":"Боруто: Следующие поколения Наруто / Boruto: Naruto Next Generations","value":"602"},{"label":"Брак по договоренности с принцессой красных скорпионов / Arranged marriage to the princess of the Red Scorpions","value":"1386"},{"label":"Бэтмен за гранью: Наследие / Batman Beyond: Legacy","value":"1380"},{"label":"В другом мире со смартфоном / Isekai wa Smartphone to Tomo ni","value":"947"},{"label":"В объятиях шлюхи / JK Bitch ni Shiboraretai","value":"1283"},{"label":"В ожидании бедности, я собираюсь стать кузнецом / Expecting to Fall into Ruin, I Aim to Become a Blacksmith","value":"1475"},{"label":"В Повелителе как Довакин / In Overlord as a Dovahkiin","value":"1816"},{"label":"Вакфу / Wakfu","value":"814"},{"label":"ВАЛЛ-И / Wally","value":"801"},{"label":"Вампир: Маскарад - Родословные / Vampire: The Masquerade Bloodline","value":"1212"},{"label":"Вампирелла / Vampirella","value":"1214"},{"label":"Варфрейм / Warframe","value":"967"},{"label":"Ведьмак / The Witcher","value":"278"},{"label":"Великий из бродячих псов / Bungou Stray Dogs","value":"75"},{"label":"Великолепный парк Амаги / Amagi Brilliant Park","value":"813"},{"label":"Вельзепуз / Вельзевул / Beelzebub","value":"765"},{"label":"Веном / Venom","value":"978"},{"label":"Веселая ферма / Fun Farm","value":"1124"},{"label":"Вечная история / The Neverending Story","value":"547"},{"label":"Вечные(Фильм, 2021) / Eternal","value":"1234"},{"label":"Виви: Песнь флюоритового глаза / Vivy: Fluorite Eye's Song","value":"1819"},{"label":"Викинги / Vikings","value":"369"},{"label":"Владелец ранчо со слизью(Games) / Ранчо слизи / Slime Rancher","value":"1529"},{"label":"Властелин колец / Lord of the Ring","value":"254"},{"label":"Власть книжного червя / Honzuki no Gekokujou","value":"1399"},{"label":"Внук Мудрец / Kenjo no Mago","value":"1260"},{"label":"Внук Нурарихёна / Nurarihyon no Mago","value":"66"},{"label":"Во всеоружии / Overgeared","value":"1021"},{"label":"Во тьме(Games) / The Darkness","value":"938"},{"label":"Военная хроника маленькой девочки / Сага о злой Тане / The Saga of Tanya the Evil / \tGekijouban Youjo Senki","value":"1726"},{"label":"Возвращение в детские годы / Gaki ni Modotte Yarinaoshi!!!","value":"1031"},{"label":"Возрождение Серийного Убийцы / Rebirth Of A Serial Killer","value":"1358"},{"label":"Воинственный Бог Асура / Martial God Asura","value":"771"},{"label":"Война будущего / The Tomorrow War","value":"1174"},{"label":"Война Любовь Снег / War Love Snow","value":"1417"},{"label":"Волейбол! / Haikyuu!!","value":"697"},{"label":"Волчонок / Teen Wolf","value":"795"},{"label":"Волшебная Девушка Спецоперация Аска / Magical Girl Spec-Ops Asuka","value":"1470"},{"label":"Волшебник-воин Орфен / Majutsushi Orphen Hagure Tabi: Kimluck-hen","value":"1128"},{"label":"Волшебники / The Magicians","value":"1314"},{"label":"Волшебный учитель Нэгима! / Negima!: Magister Negi Mag","value":"1777"},{"label":"Воля второго цикла мироздания. / Will of the second cycle of the Worldifice.","value":"1036"},{"label":"Воспитание хозяина / Yours to Claim","value":"839"},{"label":"Восставший против неба / Against the Gods","value":"957"},{"label":"Восстание стражей / Хранители снов / Rise of the Guardians","value":"1488"},{"label":"Восхождение в Голливуде / I'm in Hollywood","value":"1237"},{"label":"Восхождение героя щита / The Rising of the Shield Hero","value":"103"},{"label":"Врата Штейна / Steins: Gate","value":"1044"},{"label":"Врата: там бьются наши воины / Gate: Jieitai Kanochi nite, Kaku Tatakaeri","value":"727"},{"label":"Время / In Time","value":"542"},{"label":"Всегда вялый Танака-кун / Tanaka-kun wa Itsumo Kedaruge","value":"1082"},{"label":"Всего лишь восьмой сын? Я с этим не смирюсь! / Hachinan tte, Sore wa Nai Deshou! / Eighth son, I don’t think so!","value":"1473"},{"label":"Вселенная Марвел / Marvel Universe / Marvel Comics","value":"6"},{"label":"Вселенная монстров / Monsterverse / Monster Verse","value":"905"},{"label":"Вселенная Стивена / Steven universe","value":"573"},{"label":"Вселенная Стрелы / Arrowverse","value":"488"},{"label":"Вселенная Тип Луны(Игровая компания) / Universe Type Moon","value":"1221"},{"label":"Вселенная DC / DC Universe / DC Comics","value":"36"},{"label":"Выпадение радиоактивных осадков / Fallout","value":"55"},{"label":"Выращивание онлайн / Cultivation Online","value":"1252"},{"label":"Галактическая секс-звезда / Galaxy Sex Star","value":"1539"},{"label":"Гало(Games) / Halo","value":"1338"},{"label":"Ганц / Gantz","value":"256"},{"label":"Гарем рабов в лабиринте другого мира / Slave Harem in the Labyrinth of the Other World","value":"1853"},{"label":"Гарри Поттер / Harry Potter","value":"1"},{"label":"Гвен-паук / Spider-Gwen","value":"920"},{"label":"Генерал маньяк с его сумасшедшей системой / The Maniacal General with his Crazy System","value":"1356"},{"label":"Генерал, вы вправе уйти. / General, You May Leave Now","value":"1385"},{"label":"Геншин Импакт / Genshin Impact","value":"689"},{"label":"Геркулес / Hercules","value":"721"},{"label":"Герои и замки / Heroes & Castles","value":"940"},{"label":"Герои меча и магии / Heroes of Might and Magic","value":"1002"},{"label":"Герои(телесериал) / Heroes","value":"864"},{"label":"Гильгамеш / Gilgamesh","value":"1143"},{"label":"Гинтама / Gintama","value":"129"},{"label":"Глубина(Фильм, 2002) / Below","value":"1186"},{"label":"Гнев Асуры / Asura's wrath","value":"100"},{"label":"Годзилла / Godzilla","value":"922"},{"label":"Голодные игры / The Hunger Games","value":"859"},{"label":"Горец / Highlander","value":"1761"},{"label":"Горожане(Games) / Townsmen","value":"1599"},{"label":"Госпожа Кагуя: в любви как на войне / Kaguya sama: Love is war","value":"533"},{"label":"Готика / Gothic","value":"418"},{"label":"Готов ли ты влюбиться в извращенку до тех пор, пока она милая? / Hentai demo Suki ni Natte Kuremasu ka","value":"1383"},{"label":"Гоэтия / Гоетия / Yοητεία / Ars Goetia","value":"772"},{"label":"Гравити Фолз / Gravity Falls","value":"491"},{"label":"Граница пустоты / Kara no Kyoukai","value":"1101"},{"label":"Гриффины / Family Guy","value":"349"},{"label":"Гром над небом / Thunder over the sky","value":"793"},{"label":"Гуррен-Лаганн / Tengen Toppa Gurren Lagann","value":"719"},{"label":"Да будет благословенен этот прекрасный мир! / Konosuba / Kono Subarashii Sekai ni Shukufuku wo!","value":"82"},{"label":"Да Здравствует Призыв! / Long Live Summons!","value":"948"},{"label":"Да, я паук, и что с того? / So I'm a Spider, So What? / Kumo Desu ga, Nani ka?","value":"910"},{"label":"Данганронпа / Danganronpa","value":"972"},{"label":"Две звезды Онмёджи / Sousei no Onmyouji","value":"1108"},{"label":"Дворянство / Благородство / Noblesse","value":"636"},{"label":"Девочка-волшебница Мадока Магика / Mahou Shoujo Madoka Magica","value":"1412"},{"label":"Девочка, которая видит это / Mieruko-chan","value":"1645"},{"label":"Декстер(телесериал) / Dexter","value":"1543"},{"label":"Демон Бездны всех царств / Abyss Demon of All Realms","value":"1419"},{"label":"Демоны старшей школы / High School DxD","value":"8"},{"label":"День независимости(Фильм, 1996) / Independence Day","value":"850"},{"label":"Детектив Конан / Detective Conan","value":"1554"},{"label":"Дети индиго из другого мира / Mondaiji-tachi ga isekai kara kuru sô desu yo","value":"1484"},{"label":"Джаггед Альянс 2: Агония Власти(Games) / Jagged Alliance 2","value":"1668"},{"label":"Джессика Джонс / Marvel's Jessica Jones","value":"1817"},{"label":"Джон Уик / John Wick","value":"388"},{"label":"Дисней / The Walt Disney Company","value":"503"},{"label":"Для тебя, Бессмертный / Fumetsu no Anata e / To Your Eternity","value":"1802"},{"label":"Дневник Будущего / Mirai Nikki","value":"368"},{"label":"Дневники вампира / The Vampire Diaries","value":"160"},{"label":"Доблесть рыцаря-неудачника / Chivalry of a Failed Knight","value":"1462"},{"label":"Добро пожаловать в ад, Ирума / Welcome to Demon School! Iruma-kun","value":"261"},{"label":"Добро пожаловать в класс превосходства / Classroom of the Elite","value":"122"},{"label":"Добро пожаловать! В лес похотливых эльфов! / Youkoso! Sukebe Elf no Mori e","value":"1034"},{"label":"Добывать ремесло / Майнкрафт / Minecraft","value":"102"},{"label":"Доктор Кто / Doctor Who","value":"277"},{"label":"Доктор Стоун / Dr. Stone","value":"720"},{"label":"Доля секунды: скорость / Split - second: velocity","value":"890"},{"label":"Дом кролика / Кофейня "Кроличий домик" / Gochuumon wa Usagi Desu ka?","value":"642"},{"label":"Домашний очаг / Hearthstone: Heroes of Warcraft / Hearthstone","value":"934"},{"label":"Домекано / Domestic Na Kanojo","value":"632"},{"label":"Дорогой звёзд / Звёздное преобразование / Stellar Transformation / Xing Chen Bian","value":"1155"},{"label":"Доспехи Бога 2: Операция Кондор / Armour of God II: Operation Condor","value":"1829"},{"label":"Дота 2 / Dota 2","value":"1105"},{"label":"Дофус / Dofus","value":"817"},{"label":"Дракенгард / Drakengard / Drag-On Dragoon","value":"919"},{"label":"Дракон-горничная госпожи Кобаяси / Kobayashi-san Chi no Maid Dragon","value":"673"},{"label":"Дракон-сама из семьи Касумигаока / Dragon-sama of the Kasumigaoka Family","value":"1458"},{"label":"Драконий жемчуг Зет / Dragon Ball Z","value":"307"},{"label":"Дракониум Онлайн / Draconic Online","value":"1360"},{"label":"Дракула / Dracula","value":"709"},{"label":"Древнегреческая мифология / Ancient Greek mythology","value":"1159"},{"label":"Дре́вние / Первородные / The Originals","value":"863"},{"label":"Древние свитки / The Elder Scrolls","value":"428"},{"label":"Древние свитки: Скайрим / TES: Skyrim","value":"337"},{"label":"Другой мир / Underworld","value":"480"},{"label":"Друид с Сеульской станции / Seoul Station Druid","value":"1178"},{"label":"Дьявол / Диабло / Diablo","value":"1787"},{"label":"Дьявол может плакать / Devil May Cry / DMC","value":"339"},{"label":"Дьявол Юраги-су / The Devil of Yuragi-sou","value":"431"},{"label":"Дьявол II(Games) / Диабло II / Diablo II","value":"1055"},{"label":"Дэдпул / Deadpool","value":"810"},{"label":"Дэнни-призрак / Danny Phantom","value":"109"},{"label":"Евангелион / Neon Genesis Evangelion","value":"583"},{"label":"Единство семи магов / Тринити: Семь Магов / Trinity Seven","value":"442"},{"label":"Еженедельный прыжок сёнэн / Weekly Shōnen Jump","value":"1629"},{"label":"Ёрмунганд / Jormungand","value":"77"},{"label":"Жажда скорости / Need For Speed","value":"1493"},{"label":"Железный человек / Iron Man","value":"710"},{"label":"Жемчуг дракона / Dragon Ball","value":"309"},{"label":"Женщина-Халк(телесериал) / She-Hulk: Attorney at Law","value":"1593"},{"label":"Жизнь девушки в игровом мире / A Girl’s Life In A Gaming World","value":"1406"},{"label":"Жизнь после / Days Gone","value":"1279"},{"label":"За гранью / Beyond the Boundary","value":"357"},{"label":"Загипнотизировать Семью / Kyonyuu Kazoku Saimin","value":"1032"},{"label":"Закон Уэки / The Law of Ueki","value":"790"},{"label":"Закулисье / Backrooms","value":"1827"},{"label":"Зачарованные / Charmed","value":"113"},{"label":"Защитники / Defenders","value":"1832"},{"label":"Защитница Химари / Omamori Himari","value":"279"},{"label":"Звёздная принцесса и силы зла\t / Стар против сил зла / Star vs. The Forces of Evil","value":"782"},{"label":"Звёздное дитя / Oshi no Ko","value":"1903"},{"label":"Звёздное ремесло / StarCraft","value":"386"},{"label":"Звездные Войны / Star Wars","value":"40"},{"label":"Звёздные войны: Войны клонов - Все типы носителей(мультсериал, 2008) / Star Wars: The Clone Wars","value":"1182"},{"label":"Звёздные врата / Stargate","value":"770"},{"label":"Звёздные врата: Атлантида / Stargate: Atlantis","value":"1097"},{"label":"Звездный путь / Стартрек / Star Trek","value":"849"},{"label":"Зверополис / Zootopia","value":"1449"},{"label":"Зеленая Жизнь / Green Life","value":"1196"},{"label":"Зеленый фонарь / The Green Lantern","value":"1222"},{"label":"Зетмен / Zetman","value":"1191"},{"label":"Игра в кальмара(телесериал) / Squid game","value":"1065"},{"label":"Игра престолов / Game of Thrones","value":"22"},{"label":"Игрок / The Gamer","value":"126"},{"label":"Идеальная судьба / The Perfect Destiny","value":"781"},{"label":"Идолмастер / The Idolmaster","value":"807"},{"label":"Иерихон Клайва Баркера / Иерихон / Clive Barker’s Jericho /Jericho","value":"320"},{"label":"Извивающийся дракон / Coiling Dragon","value":"692"},{"label":"Изгнаные королевства РПГ / Exiled Kingdoms RPG","value":"1375"},{"label":"Импульс Валькирии: Сирена / Варукири Дораиву: Сирена / Valkyrie Drive: Mermaid","value":"1736"},{"label":"Индекс волшебства / A Certain Magical Index","value":"68"},{"label":"Инуяша - Пес-демон / InuYasha","value":"481"},{"label":"Искусственный отбор / Triage X","value":"1037"},{"label":"Истинный мир боевых искусств / Zhenwu Shijie / True Martial World","value":"867"},{"label":"История монстров / Monogatari","value":"911"},{"label":"История о второстепенном персонаже который стал игроком в другой игре. / The story is about a minor character who became a player in another game.","value":"868"},{"label":"Кабанери железной крепости / Koutetsujou no Kabaneri","value":"1494"},{"label":"Каждый раз, когда я сплю, моя душа покидает мое тело / Every Day I Sleep, My Soul Goes Out of My Body","value":"1048"},{"label":"Как воспитать героиню из обычной девушки / Saenai Heroine no Sodatekata","value":"1637"},{"label":"Как игрок глупой FPS попал в иной мир / Как дурачок из стрелялки в другой мир попал / Manuke na FPS Player ga Isekai e Ochita Baai","value":"746"},{"label":"Как приручить дракона / How to Train Your Dragon","value":"687"},{"label":"Капитан Америка / Captain America","value":"1425"},{"label":"Капитан Марвел(Фильм, 2019) / Captain Marvel","value":"1594"},{"label":"Каратель / The Punisher","value":"387"},{"label":"Касл / Castle","value":"389"},{"label":"Касльвания / Castlevania","value":"1215"},{"label":"Катаклизм: Тёмные дни впереди / DDA / Cataclysm: Dark Days Ahead","value":"680"},{"label":"Квайзер со Стигматом / Адепт Святого Знака / The Qwaser of Stigmata","value":"72"},{"label":"Квартет из альтернативного мира / Isekai Quartet","value":"1801"},{"label":"Квест Девушки-монстра / Monster Girl Questt","value":"928"},{"label":"Квест титана(Games) / Титанический квест / Titan Quest","value":"1483"},{"label":"Кенши(Games) / Kenshi","value":"1230"},{"label":"Киберпанк 2077 / Cyberpunk 2077","value":"416"},{"label":"Ким Пять-с-плюсом / Kim Possible","value":"436"},{"label":"Киру ра Киру / Круши Кромсай / Убей или умри / Kill la Kill","value":"763"},{"label":"Класс убийц / Assassination classroom","value":"610"},{"label":"Клеймор / Claymore","value":"110"},{"label":"Клинок зла / Evil Blade / Übel Blatt","value":"722"},{"label":"Клинок королевы / Queen’s Blade","value":"757"},{"label":"Клинок Маню: Тайна сисечного свитка / Manyuu Hiken-chou","value":"501"},{"label":"Клинок рассекающий демонов / Demon Slayer: Kimetsu no Yaiba","value":"21"},{"label":"Клуб Винкс / Winx Club","value":"397"},{"label":"Книга джунглей / The Jungle Book","value":"1688"},{"label":"Князь тьмы с задней парты / Demon King Daimao / Ichiban Ushiro no Daimaou","value":"1207"},{"label":"Код Гиас / Code Geass","value":"340"},{"label":"Код Квалидеи / Qualidea Code","value":"76"},{"label":"Кольцо Элдена / Elden Ring","value":"1408"},{"label":"Комната / The Room","value":"889"},{"label":"Конь и клинок: Боевой отряд(Games) / Mount and Blade:Warband","value":"1477"},{"label":"Королевства Сердец / Kingdom Hearts","value":"407"},{"label":"Короли крестоносцев / Crusader kings","value":"572"},{"label":"Король бойцов / The King of Fighters","value":"1378"},{"label":"Король лев / The Lion king","value":"1705"},{"label":"Король Шаманов / Shaman King","value":"744"},{"label":"Корона греха / Guilty Crown","value":"1007"},{"label":"Корпорация лоботомии / Lobotomy corporation","value":"852"},{"label":"Космические рейнджеры(Games) / Space Rangers","value":"1508"},{"label":"Кошечка из Сакурасо / Sakurasou no Pet na Kanojo","value":"605"},{"label":"Красавица и чудовище / Beauty and the Beast","value":"1765"},{"label":"Красная угроза 3 / Command & Conquer: Red Alert 3","value":"742"},{"label":"Красный, Белый, Черный, Желтый / RWBY","value":"131"},{"label":"Кредо убийцы / Assassin's Creed","value":"690"},{"label":"Кризис / Crysis","value":"1734"},{"label":"Крушитель / The Breaker","value":"1080"},{"label":"Кунг-фу панда / Kung Fu Panda","value":"831"},{"label":"Кэйон! / K-On!","value":"1785"},{"label":"Кэнган Асура / Kengan Asura","value":"726"},{"label":"Лаборатория Декстера / Dexter Lab","value":"639"},{"label":"Лавкрафт / Говард Филлипс Лавкрафт / Howard Phillips Lovecraft","value":"1259"},{"label":"Легенда о восьми псах востока / Hakkenden: Touhou Hakken Ibun","value":"1699"},{"label":"Легенда о Зельде / The Legend of Zelda","value":"870"},{"label":"Легенда о Короле Драконов / Legend of the Dragon King","value":"623"},{"label":"Легенда о Легендарных Героях / Densetsu no Yuusha no Densetsu","value":"193"},{"label":"Легион Супергероев / The Legion of Super-Heroes","value":"450"},{"label":"Леди Баг и Супер-Кот / Miraculous Ladybug","value":"327"},{"label":"Летняя сага / Summertime Saga","value":"1441"},{"label":"Лига Легенд / League of Legends","value":"65"},{"label":"Линия фронта для девочек / Girls' Frontline","value":"1686"},{"label":"Литературный клуб Доки Доки / Литературный клуб / Doki Doki literature club!","value":"819"},{"label":"Лорд героев(Games) / Lord of Heroes","value":"1771"},{"label":"Лорд человечества / Lord of the People","value":"1896"},{"label":"Лориенская Сага / Lorien Legacies","value":"521"},{"label":"Любимая жена господина генерального директора / Mr.CEO's Beloved Wife","value":"1389"},{"label":"Любовные неприятности / To love ru","value":"353"},{"label":"Любовь, Деньги, Рок-н-Ролл / Love, Money, Rock'n'Roll","value":"1890"},{"label":"Люди в чёрном(Фильм) / Men in Black","value":"1193"},{"label":"Люди Икс / X-Men","value":"371"},{"label":"Лютер Строуд Сага / The Luther Strode Saga","value":"1700"},{"label":"Люцифер(телесериал) / Lucifer","value":"681"},{"label":"Маг на полную ставку / Quanzhi Fashi","value":"291"},{"label":"Маг смерти не желающий четвертой реинкарнации / The Death Mage Who Doesn’t Want a Fourth Time","value":"1775"},{"label":"Маг-целитель: Новый старт / Kaifuku Jutsushi no Yarinaoshi","value":"1311"},{"label":"Маги: Волшебный лабиринт / Magi: The Labyrinth of Magic","value":"1581"},{"label":"Магистр дьявольского культа / The Grandmaster of Demonic Cultivation","value":"608"},{"label":"Магическая академия Атараксия: Гибрид х Сердце / Hybrid x Heart Magias Academy Ataraxia","value":"1898"},{"label":"Магическая битва / Magic Battle / Jujutsu Kaisen","value":"671"},{"label":"Маленькие кошмары 2 / Little Nightmares 2","value":"601"},{"label":"Малефисента / Maleficent","value":"775"},{"label":"Мальчик с оленьими рогами / Сладкоежка / Sweet tooth","value":"1772"},{"label":"Маска / The mask","value":"847"},{"label":"Мастер Урадана / The Master of Uradan","value":"1395"},{"label":"Мастера меча онлайн / Sword Art Online / SAO","value":"324"},{"label":"Межвидовые Рецензенты / Interspecies Reviewers","value":"1555"},{"label":"Менеджер среднего звена Тонэгава / Chuukan Kanriroku Tonegawa","value":"1084"},{"label":"Мерлин / Merlin","value":"486"},{"label":"Мертвы к Рассвету / Dead by Daylight","value":"899"},{"label":"Мертвый или живой / Dead or Alive","value":"1563"},{"label":"Мертвый остров / Dead Island","value":"124"},{"label":"Месть Масамуне-куна! / Masamune-kun no Revenge","value":"571"},{"label":"Метавселенная Рудазова / Rudazov's Metauniverse","value":"1211"},{"label":"Метро 2033(Games) / Metro 2033","value":"1584"},{"label":"Милый во Франксе / Любимый во Франксе / Darling in the Franxx","value":"942"},{"label":"Мир боевых искусств / 武极天下 / Wuji Tianxia / Martial World","value":"620"},{"label":"Мир зомби / Zombie World","value":"1880"},{"label":"Мир Льда и Пламени / The World of Ice & Fire","value":"415"},{"label":"Мир приключений Джеки Чана(мультсериал, 2000) / ackie Chan Adventures","value":"1544"},{"label":"Мир танков / WoT Blitz / World of Tanks Blitz","value":"525"},{"label":"Мир Тьмы / World of Darkness","value":"145"},{"label":"Мир Эрастай / The World of Erasthay","value":"1836"},{"label":"Мир Warcraft / World of Warcraft","value":"89"},{"label":"Мировая война Z / Война миров Z / World War Z","value":"1217"},{"label":"Моана / Moana","value":"686"},{"label":"Моб психо 100 / Mob Psycho 100","value":"866"},{"label":"Мобильные легенды: Бах-Бах(Games) / Mobile Legends: Bang Bang","value":"1497"},{"label":"Могучие рейнджеры / Power Rangers","value":"1486"},{"label":"Может, я встречу тебя в подземелье? / DanMachi","value":"9"},{"label":"Мой жених сбежал / My Groom Ran Away","value":"1047"},{"label":"Мой маленький пони / My Little Pony","value":"655"},{"label":"Мой маленький пони: Дружба — это чудо / My Little Pony: Friendship is Magic","value":"658"},{"label":"Мой шумный дом(мультсериал, 2016) / The Loud House","value":"1467"},{"label":"Монстер Хай / Monster High","value":"1012"},{"label":"Моя возлюбленная чпокается со всеми / Kanojo wa Dare to demo Sex Sur","value":"1274"},{"label":"Моя геройская академия / Boku no Hero Academia","value":"69"},{"label":"Моя девушка - зомби / My Girlfriend is a Zombie","value":"754"},{"label":"Моя жена - красивый генеральный директор / My Wife is a Beautiful CEO","value":"1025"},{"label":"Моя жена — президент студенческого совета! / My Wife is the Student Council President / Okusama ga Seitokaichou","value":"241"},{"label":"Моя Марвел Академия / My marvel academia","value":"696"},{"label":"Моя первая модница / Hajimete no Gal","value":"1835"},{"label":"Моя Супер-Бывшая / My Super Ex-Girlfriend","value":"1828"},{"label":"Мрачный рассвет / Grim Dawn","value":"1113"},{"label":"Мстители / The Avengers","value":"1747"},{"label":"Мстители. Эра Альтрона / The Avengers. Age of Ultron","value":"784"},{"label":"Мулан / Mulan","value":"706"},{"label":"Мы не можем учится / Bokutachi wa Benkyou ga Dekinai","value":"912"},{"label":"Мэй Гунцин / Mei Gongqing","value":"753"},{"label":"Наблюдать / Overwatch","value":"607"},{"label":"Надпись / Inscription","value":"1718"},{"label":"Нам Ён / Nam Yeon","value":"1188"},{"label":"Наруто / Naruto","value":"3"},{"label":"Начало после конца / The Beginning After The End","value":"888"},{"label":"Не голодай / Don't Starve","value":"274"},{"label":"Не издевайся надо мной, Нагаторо / Ijiranaide / Nagatoro-san Don't Toy with Me, Miss Nagatoro","value":"1041"},{"label":"Не люблю боль, так что вкачаю все в защиту / Itai no wa Iya nano de Bougyoryoku ni Kyokufuri Shitai to Omoimasu","value":"517"},{"label":"Не моя вина, что я непопулярна! / Watashi ga Motenai no wa Dou Kangaetemo Omaera ga Warui","value":"1381"},{"label":"Небесный замок Лапута / Tenkuu no Shiro Laputa","value":"1109"},{"label":"Невероятные приключения ДжоДжо / JoJo's Bizarre Adventure","value":"20"},{"label":"Негодник, которому не снилась девочка-зайка / Rascal Does Not Dream of Bunny Girl Senpai","value":"1897"},{"label":"Негодяй спасает мужскую роль / The Villain Saves the Male Lead","value":"1224"},{"label":"Неизвестен / Persona","value":"205"},{"label":"Некий магический индекс / To Aru Majutsu no Index","value":"562"},{"label":"Некий научный акселератор / Toaru Kagaku no Accelerator","value":"1487"},{"label":"Ненасытный Берсерк / Boushoku no Berserk: Ore dake Level to Iu Gainen wo Toppa suru the Comic","value":"1195"},{"label":"Необъятные небеса / Infinite Stratos / IS","value":"280"},{"label":"Необъятный океан / Grand Blue","value":"531"},{"label":"Непревзойденная / Master Piece The Animation","value":"712"},{"label":"Непризнанный школой владыка демонов / Maou Gakuin no Futekigousha","value":"1476"},{"label":"Непутевый ученик в школе магии / Mahouka Koukou No Rettousei","value":"982"},{"label":"Непутевый ученик в школе магии / The Irregular at Magic High School","value":"630"},{"label":"Несокрушимая механическая кукла / Machine-Doll wa Kizutsukanai","value":"1030"},{"label":"Несправедливость / Injustice","value":"1026"},{"label":"Нет игры - нет жизни / Без игры жизни нет / No Game No Life","value":"718"},{"label":"Неуязвимый / Invincible","value":"702"},{"label":"НиоХ(Games) / NioH","value":"1465"},{"label":"Новый завет Владыки тьмы / Shinmai Maou no Testament","value":"1432"},{"label":"Ну и ну! Земляничные яйца / I My Me! Strawberry Eggs","value":"1485"},{"label":"Нулевой Уровень Целомудрия / Teisou Kannen Zero","value":"1209"},{"label":"О моём перерождении в меч / Tensei Shitara Ken deshita","value":"53"},{"label":"О моём перерождении в слизь / Tensei shitara Slime Datta Ken","value":"64"},{"label":"О моя Богиня / Aa! Megami-sama! / Ah! My Goddess","value":"915"},{"label":"Обесчещенный(Games) / Dishonored","value":"1073"},{"label":"Обитель зла / Resident Evil","value":"86"},{"label":"Огненная эмблема / Fire Emblem","value":"1615"},{"label":"Огненная эмблема: Пробуждение / Fire Emblem: Awakening","value":"1616"},{"label":"Огненная эмблема: Три Дома / Fire Emblem:Three Houses","value":"1716"},{"label":"Одинокий рокер! / Bocchi the Rock!","value":"1904"},{"label":"Одному лишь Богу ведомый мир / World God Only Knows","value":"1248"},{"label":"Она становится гламурной после расторжения помолвки / She gets glamorous after the engagement is annulled","value":"1404"},{"label":"Орк-рубака / Orc Grunt","value":"779"},{"label":"Освободите эту ведьму / Release that witch","value":"994"},{"label":"Острые козырьки(телесериал) / Peaky Blinders","value":"1177"},{"label":"От заката до рассвета! / From Dusk till Dawn!","value":"1416"},{"label":"Отброс из семьи графа / Trash of counts family","value":"853"},{"label":"Отряд самоубийц / The Suicide Squad","value":"1844"},{"label":"Отчаянные домохозяйки / Desperate Housewives","value":"1011"},{"label":"Отчет о буйстве духов / YuYu Hakusho","value":"1008"},{"label":"Охота демонического короля на свою жену / Xie Wang Zhui Qi","value":"1737"},{"label":"Охотник х Охотник / Hunter x Hunter","value":"101"},{"label":"Охотницы на демонов / Taimanin Asagi","value":"1463"},{"label":"Очень приятно Бог! / Kamisama Hajimemashita","value":"1585"},{"label":"Очень Странные Дела(телесериал) / Stranger Things","value":"1834"},{"label":"ПАЗЛ / PUZZLE","value":"1762"},{"label":"Палач Рока / DOOM","value":"132"},{"label":"Параграф 78(Фильм) / Paragraph 78","value":"923"},{"label":"Паразит: Учение о жизни / Parasyte: The Maxim","value":"1176"},{"label":"Пастырь(Фильм, 2011) / Priest","value":"1173"},{"label":"Пацаны / The Boys","value":"133"},{"label":"Первый детский сад во вселенной / The First Kindergarten in the Universe","value":"1049"},{"label":"Перевозчик / Le Transporteur","value":"365"},{"label":"Передающийся через кровь / Bloodborne","value":"229"},{"label":"Пережить / Outlast","value":"645"},{"label":"Перерождение / Rebirth","value":"550"},{"label":"Перерождение бессмертного горожанина-культиватора / Rebirth – City Cultivation / Rebirth of the Urban Immortal Cultivator","value":"843"},{"label":"Перерождение в монстра / Re:Monster","value":"85"},{"label":"Перестрой мир / Sekai O Sai Kochiku / Rebuild World","value":"961"},{"label":"Период полураспада(Valve) / Half-Life","value":"895"},{"label":"Перси Джексон / Percy Jackson","value":"308"},{"label":"Персона 5 / Persona 5","value":"1614"},{"label":"Печать ветра / Kaze no Stigma","value":"845"},{"label":"Пик боевых искусств / Martial Peak","value":"414"},{"label":"Пираты Карибского моря / Pirates of the Caribbean","value":"932"},{"label":"Пираты черной лагуны / Black Lagoon","value":"621"},{"label":"Пламенная бригада пожарных / Fire Force / Enen no Shouboutai","value":"841"},{"label":"Пламя бесчисленых невзгод / I' m really not demon god's lackey","value":"1452"},{"label":"Планетарная аннигиляция / Planetary Annihilation","value":"487"},{"label":"Плоскостной пейзаж: Мучение / Planescape: Torment","value":"1768"},{"label":"По велению адской сестры / The Testament of Sister New Devil","value":"18"},{"label":"Поборники тьмы / Darksiders","value":"1028"},{"label":"Повар небесной гостиницы / Чем кормят в ином мире / Kakuriyo no Yadomeshi","value":"998"},{"label":"Повар-боец Сома / В поисках божественного рецепта / Shokugeki no Souma","value":"191"},{"label":"Повелитель тьмы на подработке! / Hataraku Maou-sama!","value":"674"},{"label":"Повелитель тьмы: Другая история мира / How Not to Summon a Demon Lord / Isekai Maou to Shoukan Shoujo no Dorei Majutsu","value":"699"},{"label":"Повелитель(Куганэ Маруяма) / Overlord","value":"27"},{"label":"Повелитель(Games) / Overlord","value":"1623"},{"label":"Повесть о Конце Света / Record of Ragnarok","value":"332"},{"label":"Повесть о лунной принцессе / Tsukihime: Lunar Legend","value":"750"},{"label":"Повесть о Небесных островах / Фэнтези Гранблю / Granblue Fantasy","value":"808"},{"label":"Повседневная жизнь бессмертного короля / The Daily Life of the Immortal King / Xian Wang de Richang Shenghuo","value":"1466"},{"label":"Повседневная жизнь с девушкой-монстром / Monster Musume","value":"760"},{"label":"Пограничье(Games) / Borderlands","value":"992"},{"label":"Под лунами Драконьих глаз / Beneath the Dragoneye Moons","value":"1735"},{"label":"Подземелья и драконы / Dungeons & Dragons","value":"81"},{"label":"Подземная история / Андертейл / Undertale","value":"390"},{"label":"Поднявшийся(Games) / Risen","value":"1273"},{"label":"Поднятие уровня в одиночку / Solo Leveling","value":"127"},{"label":"Подручный Луизы-Нулизы / Zero no Tsukaima","value":"580"},{"label":"Пожиратель богов / God Eater","value":"1321"},{"label":"Поймай себя ! Моя дорогая жена / Catch You ! My Dear Wife","value":"1317"},{"label":"Покемон / Pokemon","value":"43"},{"label":"Политическая Хроника Молодой Девушки / A Young Woman's Political Record","value":"1306"},{"label":"Полностью пленённые / Totally Captivated","value":"1086"},{"label":"Полый Рыцарь(Games) / Hollow Knight","value":"1198"},{"label":"Пользователи Силы / Forceusers","value":"1162"},{"label":"Поля битвы Неизвестного игрока / ПАБГ / Player Unknown's Battlegrounds / PUBG","value":"622"},{"label":"Попытка приручить злого повелителя / Trying to Tame an Evil Overlord","value":"983"},{"label":"Поработитель Ада / Helltaker","value":"776"},{"label":"Порновселенная / Porn Universe","value":"1776"},{"label":"Портал(Valve) / Portal","value":"800"},{"label":"Последние из нас / Last Of Us","value":"1717"},{"label":"Последний Серафим / Owari no Seraph","value":"551"},{"label":"Последняя из рода Блау(Тайга Ри) / The last of the Blau family","value":"1507"},{"label":"Последняя фантазия / ファイナルファンタジ / Final Fantasy","value":"769"},{"label":"Преподобное безумие / Reverend Insanity","value":"1280"},{"label":"Преподобный Гу / Gu Zhen Ren / Daoist Gu","value":"1464"},{"label":"Призрачный бегун / Ghostrunner","value":"613"},{"label":"Призрачный гонщик / Ghost Rider","value":"823"},{"label":"Принц Драконов Хаоса / The Chaos Dragon Prince","value":"1397"},{"label":"Принц Персии / Prince of Persia","value":"1535"},{"label":"Принцесса монстров / Princess Resurrection","value":"1304"},{"label":"Принцесса Цу / Не проиграю! / Maken Ki","value":"675"},{"label":"Проект „Восток“ / Touhou Project","value":"809"},{"label":"Проект Кей / K Project","value":"73"},{"label":"Проклятие: Автоматизация / NieR:Automata","value":"1496"},{"label":"Противостояние святого / Renegade Immortal","value":"926"},{"label":"Прототип / Prototype","value":"54"},{"label":"Пуленепробиваемый / Bang-Tan / BTS","value":"520"},{"label":"Путешествие на Запад / Journey to the West","value":"1833"},{"label":"Пять невест / Go-Toubun no Hanayome","value":"713"},{"label":"Пять ночей у Фредди / Five nights at freddy's","value":"930"},{"label":"Рагнарёк Онлайн / Ragnarok Online","value":"953"},{"label":"Радуга 6: Осада / Rainbow Six: Siege","value":"421"},{"label":"Развращение Дочери / Daraku Reijou Hakoiri Ojou-sama Netorare Choukyou Kiroku","value":"1284"},{"label":"Рай Грисайи / Эдем в серых тонах / Grisaia no Rakuen","value":"584"},{"label":"Рандеву с жизнью / Date A live","value":"851"},{"label":"Ранма ½ / Ranma ½","value":"1192"},{"label":"Рапунцель: Запутанная история / Tangled","value":"773"},{"label":"Расколотая битвой синева небес / Battle Through the Heavens","value":"927"},{"label":"Рассказ служанки / The Handmaid's Tale","value":"1135"},{"label":"Расхитительница гробниц / Tomb Raider","value":"988"},{"label":"Резатель / Лангриссер / Langrisser","value":"792"},{"label":"Реинкарнация безработного / Mushoku Tensei","value":"569"},{"label":"Реинкарнация Богини / Megami Tensei","value":"1161"},{"label":"Репликант НиеР / NieR Replicant / NieR Gestalt","value":"1299"},{"label":"Рецеттия: Повесть о магазине предметов / Recettear: An Item Shop's Tale","value":"858"},{"label":"Ривердэйл / Riverdale","value":"637"},{"label":"Рик и Морти / Rick and Morty","value":"315"},{"label":"Розарий и Вампир / Rosario+Vampire","value":"83"},{"label":"Розовая пора моей школьной жизни сплошной обман / Yahari Ore no Seishun Love Come wa Machigatteiru","value":"856"},{"label":"Рок шоу! / Show By Rock!!","value":"344"},{"label":"Русалочка / The Little Mermaid","value":"892"},{"label":"Рыцарь и маг / Knight's & Magic","value":"1491"},{"label":"Сага о Винланде / Vinland Saga","value":"1200"},{"label":"Садистская смесь / Blend S","value":"1120"},{"label":"Сайт волшебниц / Mahou Shoujo Site","value":"909"},{"label":"Сверхъестественное(телесериал) / Supernatural","value":"916"},{"label":"Связь принцесс: повторное погружение / Princess Connect! Re:Dive","value":"1481"},{"label":"Святые / Saints Row","value":"1390"},{"label":"Сейлор Мун / Sailor Moon","value":"114"},{"label":"Секире: Тени Умирают Дважды / Sekiro: Shadows Die Twice","value":"1076"},{"label":"Семь смертных грехов / Nanatsu no Taizai","value":"61"},{"label":"Семья шпиона / Spy x Family","value":"1646"},{"label":"Сердца Пандоры / Pandora Hearts","value":"497"},{"label":"Серия Метроидов / Metroid Series","value":"1612"},{"label":"Серый человек / Ди: Гурэйман / D.Gray-man","value":"367"},{"label":"Си Тянь Гуань / Si Tian Guan","value":"1189"},{"label":"Сильнейший в истории ученик Кэнити / Shijou Saikyou no Deshi Kenichi","value":"242"},{"label":"Сильнейший в истории ученик Кэнъити / KenIchi: The Mightiest Disciple","value":"745"},{"label":"Сильнейший магнат / The Strongest Tycoon","value":"1340"},{"label":"Сильнейший мудрец низшей эмблемы / Shikkakumon no Saikyou Kenja","value":"1472"},{"label":"Симпсоны / The Simpsons","value":"1461"},{"label":"Симс / The Sims","value":"654"},{"label":"Симфония морской стали / Aoki Hagane no Arpeggio","value":"958"},{"label":"Сингулярность(Games) / Singularity","value":"1793"},{"label":"Синий Архив / Blue Archive","value":"1411"},{"label":"Синий экзорцист / Blue Exorcist","value":"312"},{"label":"Синяя Тюрьма: Блю Лок / Blue Lock","value":"1792"},{"label":"Система Богов и Демонов / God and Devil World","value":"1648"},{"label":"Система Спаси-Себя-Сам / The Scum Villain's Self-Saving System: Ren Zha Fanpai Zijiu Xitong","value":"1505"},{"label":"Система: Восьмой уровень(Д. Серебряков) / System: Eighth level","value":"1175"},{"label":"Сисястая Принцесса под гипнозом / Kyonyuu Princess Saimin","value":"1618"},{"label":"Сказание о Демонах и Богах / Tales of Demons and Gods","value":"59"},{"label":"Сказание о Тёмном Рыцаре ~ Призван, чтобы одолеть Героя ~ / Tale of Dark Knight~Summoned to Defeat The Hero~","value":"1647"},{"label":"Сказки хранителей(Games) / Guardian tales","value":"1068"},{"label":"Скрытая Похотливая Натура Моих Русских Сестренок и Мачехи / Muttsuri do Sukebe ro Gibo Shimai","value":"1282"},{"label":"Скуби-Ду / Scooby-Doo","value":"638"},{"label":"Скучный мир, где не существует самой идеи похабных шуток / Shimoneta to Iu Gainen ga Sonzai Shinai Taikutsu na Sekai","value":"830"},{"label":"Сладкая жизнь / Happy Sugar Life","value":"1099"},{"label":"Сладкий флирт / Amour Sucré / Sweet Crush","value":"495"},{"label":"Сладости и Сигареты / Candy & Cigarettes","value":"778"},{"label":"Следопыт Гнев Праведников / Pathfinder Wrath Of The Righteous","value":"1077"},{"label":"Следопыт: Творец королей / Pathfinder: Kingmaker","value":"1770"},{"label":"Смертельная битва / Мортал Комбат / Mortal Kombat","value":"806"},{"label":"Смертельный укус","value":"1902"},{"label":"Созданный в бездне / Made in Abyss","value":"952"},{"label":"Сок джунглей","value":"1901"},{"label":"Сокрушитель: Новые волны / The Breaker: New Waves","value":"1500"},{"label":"Соник еж / Sonic the hedgehog","value":"1052"},{"label":"Сорвиголова / Daredevil","value":"1690"},{"label":"Сотня / Hundred","value":"885"},{"label":"Спаун / Spawn","value":"1254"},{"label":"Спецагент Арчер / Archer","value":"624"},{"label":"Специалист по апгрейду из другого мира / Endless Sea of Clouds ESC","value":"1499"},{"label":"Спираль / Удзумаки / Uzumaki","value":"1164"},{"label":"СТАЛКЕР / STALKER / S.T.A.L.K.E.R","value":"677"},{"label":"Стальная тревога / Full Metal Panic! The Second Raid","value":"1489"},{"label":"Стальной алхимик / Fullmetal Alchemist","value":"1123"},{"label":"Стальной Гигант / The Iron Giant","value":"1241"},{"label":"Становление богом / Bai Lian Cheng Shen","value":"1315"},{"label":"Старгерл / Stargirl","value":"1137"},{"label":"Стелларис / Stellaris","value":"1098"},{"label":"Сторожевые Псы / Watch Dogs","value":"1886"},{"label":"Стражи Галактики / Guardians of the Galaxy","value":"1426"},{"label":"Страна Самоцветов / Houseki no Kuni","value":"1305"},{"label":"Страна чудес смертников / Зона-парк смертников / Deadman Wonderland","value":"857"},{"label":"Страношары / Кантриболз / Countryballs","value":"1895"},{"label":"Студии 20-й век / 20th Century Studios","value":"1715"},{"label":"Судьба / Fate","value":"1740"},{"label":"Судьба: Апокриф / Fate: Apocrypha","value":"231"},{"label":"Судьба: Великий Орден / Fate: Grand Order","value":"60"},{"label":"Судьба: Девочка волшебница Илия / Fate: Kaleid Liner Prisma","value":"789"},{"label":"Судьба: Истоки / Fate: Zero","value":"230"},{"label":"Судьба: Ночь схватки / Fate: Stay Night","value":"536"},{"label":"Сумерки / Twilight","value":"471"},{"label":"Супер ген бога / Super God Gene","value":"316"},{"label":"Супер Марио / Super Mario","value":"1661"},{"label":"Супергёрл(телесериал, 2015) / Supergirl","value":"1088"},{"label":"Супермедицинский ниндзя / Super medical ninja","value":"1391"},{"label":"Суперсемейка / The Incredibles","value":"306"},{"label":"Сэкирэй / Sekirei","value":"111"},{"label":"Тада не может влюбиться! / Tada-kun wa koi wo shinai!","value":"1905"},{"label":"Тайны Смолвиля / Smallville","value":"449"},{"label":"Танец клинка Элементалиста / Seireitsukai no Blade Dance","value":"1498"},{"label":"Твоя апрельская ложь / Your lie in april","value":"532"},{"label":"Те, кто охотятся на эльфов / エルフを狩るモノたち / Those Who Hunt Elves","value":"1168"},{"label":"Темнейшее подземелье / Darkest dungeon","value":"1405"},{"label":"Темные Души / Dark Souls","value":"200"},{"label":"Темный Ангел / Dark Angel","value":"1010"},{"label":"Тёмный Дворецкий / Kuroshitsuj / Dark Butler","value":"411"},{"label":"Темный дворецкий / Kuroshitsuji","value":"1043"},{"label":"Темный призыватель Апокалипсиса / The Dark Summoner of the Apocalypse","value":"1407"},{"label":"Тень ежа / Ёж Шэдоу / Shadow the hedgehog","value":"796"},{"label":"Терминатор / The Terminator","value":"759"},{"label":"Террарий / Terraria","value":"805"},{"label":"Тетрадь смерти / Death Note","value":"78"},{"label":"Тибериумные войны / Tiberium Wars","value":"1893"},{"label":"Титаник / Titanic","value":"1842"},{"label":"Тихий Холм / Сайлент Хилл / Silent Hill","value":"848"},{"label":"Тихоокеанский рубеж / Pacific Rim","value":"832"},{"label":"Тогайну но Чи ~Потерял кровь~(Games) / Togainu no Chi ~Lost Blood~","value":"1540"},{"label":"Токийские вороны / Tokyo Ravens","value":"836"},{"label":"Токийские мстители / Tokyo Revengers","value":"1064"},{"label":"Токийский Гуль / Tokyo Ghoul","value":"271"},{"label":"Тор / Thor","value":"764"},{"label":"Торико / Toriko","value":"342"},{"label":"Точка зрения Всеведущего читателя / Omniscient Reader’s Viewpoint","value":"1872"},{"label":"Трансформеры / Transformers","value":"117"},{"label":"Трес Наварра / Tres Navarre","value":"1197"},{"label":"Три Икса / xXx","value":"364"},{"label":"Трон: Восстание / Tron: Uprising","value":"1887"},{"label":"Тропико / Tropico","value":"694"},{"label":"Ты единственная, кто любит Великого Меня / Ore wo Suki nano wa Omae dake ka yo","value":"1818"},{"label":"Ты же любишь мамочку, удары которой бьют по площади двойным уроном? / Tsuujou Kougeki ga Zentai Kougeki de Ni-kai Kougeki no Okaasan wa Suki Desu ka?","value":"333"},{"label":"Тэнти - лишний! / Tenchi Muyo","value":"1316"},{"label":"У Коми-сан проблемы с общением / 古見さんは、コミュ症です / Komi Can't Communicate","value":"591"},{"label":"У меня мало друзей / Boku wa Tomodachi ga Sukunai","value":"1506"},{"label":"Убийца Акаме / Akame ga Kill","value":"30"},{"label":"Убийца Брайан / Carl Robert Brown","value":"1092"},{"label":"Убийца гоблинов / Goblin slayer","value":"803"},{"label":"Удар крови / Very AU strike the blood","value":"1255"},{"label":"Уж не зомби ли это? / Kore wa Zombie Desu ka?","value":"725"},{"label":"Уличный боец(Games) / Суторито Фаита / Street Fighter","value":"1203"},{"label":"Ультрафиолет / Ultraviolet","value":"1831"},{"label":"Усио и Тора / Ushio and Tora","value":"1501"},{"label":"Утраченное небесами / Sora no Otoshimoto / Lost Property of the Sky","value":"627"},{"label":"Ученик Мудреца / Kenja no Deshi wo Nanoru Kenja","value":"1474"},{"label":"Ученик чародея / The Sorcerer's Apprentice","value":"862"},{"label":"Ученики(Games) / Disciples","value":"1478"},{"label":"Учитель Хокаге / Hokage Master","value":"1319"},{"label":"Учитель-мафиози Реборн! / Katekyo Hitman Reborn!","value":"134"},{"label":"Ушастые Друзья / Kemono Friends","value":"578"},{"label":"Фальшивая любовь / Nisekoi","value":"1103"},{"label":"Фантастическая четвёрка / Fantastic Four","value":"625"},{"label":"Фантастические твари и где они обитают / Fantastic Beasts and Where to Find Them","value":"246"},{"label":"Финес и Ферб / Phineas and Ferb","value":"898"},{"label":"Флотская коллекция / Kantai Collection","value":"1194"},{"label":"Флэш / The Flash","value":"1136"},{"label":"Фонд SCP / SCP / SCP Foundation","value":"822"},{"label":"Форма голоса / A Silent Voice","value":"1100"},{"label":"Форсаж / The Fast and the Furious","value":"363"},{"label":"Фронт кровавой блокады / Кровавый круг - линия фронта / Kekkai Sensen / Blood Blockade Battlefront","value":"794"},{"label":"Футадом мир / Futadom world","value":"984"},{"label":"Халк / Hulk","value":"973"},{"label":"Хвост Феи / Fairy Tail","value":"13"},{"label":"Хеллбой / Hellboy","value":"1171"},{"label":"Хеллсинг: Война с нечистью / Hellsing","value":"116"},{"label":"Хикару и го / Hikaru no Go","value":"1121"},{"label":"Хищник / Predator","value":"747"},{"label":"Хоббит(Дж. Р. Р. Толкина) / The Hobbit(John R.R. Tolkien)","value":"1127"},{"label":"Ходячие мертвецы / The Walking Dead","value":"704"},{"label":"Холодное сердце / Frozen","value":"633"},{"label":"Хонкай удар / Honkai impact","value":"1332"},{"label":"Хранители Пандоры / The guardians of Pandora","value":"1187"},{"label":"Хранитель вечности / UQ Holder","value":"1469"},{"label":"Хроники Акаши / Rokudenashi Majutsu Koushi to Akashic Records","value":"1166"},{"label":"Хроники Ксенобладания / Дзэнобурэйдо / Xenoblade Chronicles","value":"1110"},{"label":"Хроники Миров(Е. Лукин) / Chronicles of the Worlds(E. Lukin)","value":"346"},{"label":"Хроники расхитителей гробниц / Даому Биджи / Grave Robbery Note / Dao Mu Bi Ji / Daomu Biji","value":"724"},{"label":"Хроники Ренегата / The Renegade Chronicles","value":"1225"},{"label":"Царь Горы / The Gog of the Highschool","value":"1285"},{"label":"Чародейки / W.I.T.C.H.","value":"118"},{"label":"Человек — бензопила / Chainsaw Man","value":"797"},{"label":"Человек — летучая мышь / Бэтмен / Bat-man / Batman","value":"440"},{"label":"Человек одного удара / Ванпанчмен / One Punch-Man","value":"70"},{"label":"Человек-паук / Spider-Man","value":"326"},{"label":"Чемпион! / Campione!","value":"534"},{"label":"Червь(Джон Маккрей) / Worm(John C. McCrae(Wildbow))","value":"700"},{"label":"Черная Пантера(Фильм, 2018) / Black Panther","value":"1605"},{"label":"Черновик(С.Лукьяненко) / Draft","value":"1023"},{"label":"Чернокнижник в Мире Магов / Варлок / Warlock","value":"635"},{"label":"Чёрные души / Black Souls","value":"1439"},{"label":"Чёрный зверь / Чёрный Пёс / Kuroinu","value":"755"},{"label":"Чёрный зверь: Развращение Благородных Воительниц / Black Beast: Corruption of the Noble Warriors","value":"1733"},{"label":"Чёрный клевер / Black Clover","value":"11"},{"label":"Что такое настоящий мир? / What is real peace?","value":"1336"},{"label":"Чудачества любви не помеха! / Chuunibyou Demo Koi ga Shitai!","value":"1719"},{"label":"Чужой / Чужие / Aliens","value":"1791"},{"label":"Чужой / Alien","value":"748"},{"label":"Чума инкорпорейтед / Plague Inc","value":"125"},{"label":"Шазам! / Shazam!","value":"1560"},{"label":"Шальной последний босс появился! / A Wild Last Boss Appeared!","value":"968"},{"label":"Шальные девчонки / Girl the Wild's","value":"965"},{"label":"Шан Чи и легенда десяти колец / Shang-Chi and the Legend of the Ten Rings","value":"1424"},{"label":"Шарлотта / Charlotte","value":"71"},{"label":"Шерлок (ВВС) / Sherlock","value":"492"},{"label":"Шестерни войны / Gears of War","value":"1346"},{"label":"Школа мертвецов / Highschool of the Dead","value":"98"},{"label":"Школа строгого режима / Prison School","value":"676"},{"label":"Школьные воины / Сила тысячи / Ikki Tosen","value":"818"},{"label":"Шрек(мультфильм) / Шрэк / Shrek","value":"1586"},{"label":"Шухер, у нас новый студент / Transfer Student The Storm Bringer","value":"628"},{"label":"Эволюционировать(Games) / Evolve","value":"1789"},{"label":"Эволюция. Естественный Отбор / Game Evolution","value":"287"},{"label":"Эльсворд: Эль-ий Йоин / Elsword","value":"199"},{"label":"Эльфийская песнь / Elfen Lied","value":"1899"},{"label":"Эпоха Драконов / Dragon Age","value":"253"},{"label":"Эр Ген Я запечатаю небеса / ISSTH / Er Gen I shall seal the heavens","value":"1170"},{"label":"Эрагон(Кристофер Паолини) / Eragon","value":"417"},{"label":"Эроманга-сэнсэй / Ero-manga Sensei","value":"1094"},{"label":"Эстетика заблудшего героя / Hagure Yuusha no Aesthetica","value":"1310"},{"label":"Эта гяру будет встречаться с отаку через 100 дней. / 100-nichigo ni Otaku-kun to Tsukiau Gal","value":"1246"},{"label":"Эта фарфоровая кукла влюбилась / Sono Bisque Doll wa Koi wo Suru My Dress-Up Darling","value":"1335"},{"label":"Это не Гарри Поттер / This is not Harry Potter","value":"1219"},{"label":"Этот герой неуязвим, но очень осторожен / This Hero Is Invincible but Too Cautious","value":"1276"},{"label":"Эффект массы / Mass Effect","value":"213"},{"label":"Эхо пули / Bullet Echo","value":"1523"},{"label":"Югио: Дуэльные монстры / Yu-Gi-Oh","value":"1814"},{"label":"Югио! Вреинс / Yu-Gi-Oh! VRAINS","value":"1888"},{"label":"Юна из гостиницы Юраги / Yuuna of Yuragi Manor","value":"493"},{"label":"Юная Лига Справедливости / Young Justice","value":"1020"},{"label":"Юные Титаны / Teen Titans","value":"420"},{"label":"Я - Четвертый / I Am Number Four","value":"590"},{"label":"Я Король-Волшебник / I Am The Sorcerer King","value":"1292"},{"label":"Я мачеха, но моя дочь слишком милая / I'm stepmother but daughter is too cute","value":"777"},{"label":"Я не родился счастливчиком / I Wasn’t Born Lucky","value":"996"},{"label":"Я получил читерские способности в другом мире и стал экстраординарным в реальном мире / I Got a Cheat Skill in Another World and Became Unrivaled in The Real World, Too","value":"1900"},{"label":"Я стала потерянной дочерью злодея / I Became the Villain’s Lost Daughter","value":"1387"},{"label":"Ядерный трон / Nuclear Throne","value":"1456"},{"label":"Ярость [Пересмотрено] / Rage [Revised]","value":"1337"},{"label":"Ящик предложений Мэдаки / Medaka box","value":"874"},{"label":"Cказка для Дьявола / Tale For Satan","value":"1271"},{"label":"D&D стиль / D&D style","value":"1289"},{"label":"Dying Light 2: Stay Human","value":"1906"},{"label":"Fallout: Нью-Вегас / Fallout: New Vegas","value":"1249"},{"label":"Re: Жизнь в альтернативном мире с нуля / Re: Zero, Starting Life in Another World","value":"57"},{"label":"Re:Zero Начало жизни в другом мире / Re:Zero Starting Life in Another World","value":"1531"},{"label":"Rimworld","value":"1894"},{"label":"The Second Coming of Gluttony / The Second Coming of Avarice","value":"1236"},{"label":"Vfhdbk","value":"1884"},{"label":"XCOM: Враг внутри / XCOM: Enemy Unknown","value":"476"},{"label":"Xenus: Точка кипения / Boiling point: Road To Hell / Xenus: Boiling Point","value":"695"}],"inputType":FilterInputs.Checkbox},{"key":"atmosphere","label":"Атмосфера:","values":[{"label":"Неважно","value":"0"},{"label":"Позитивная","value":"1"},{"label":"Dark","value":"2"}],"inputType":FilterInputs.Picker},{"key":"adult","label":"Возрастные ограничения:","values":[{"label":"Все","value":"0"},{"label":"Только 18+","value":"2"},{"label":"Убрать 18+","value":"1"}],"inputType":FilterInputs.Picker}];
\ No newline at end of file
diff --git a/plugins/russian/authortoday.ts b/plugins/russian/authortoday.broken.ts
similarity index 100%
rename from plugins/russian/authortoday.ts
rename to plugins/russian/authortoday.broken.ts
diff --git a/plugins/russian/bookriver.ts b/plugins/russian/bookriver.broken.ts
similarity index 100%
rename from plugins/russian/bookriver.ts
rename to plugins/russian/bookriver.broken.ts
diff --git a/plugins/russian/ficbook.ts b/plugins/russian/ficbook.broken.ts
similarity index 100%
rename from plugins/russian/ficbook.ts
rename to plugins/russian/ficbook.broken.ts
diff --git a/plugins/russian/jaomix.ts b/plugins/russian/jaomix.broken.ts
similarity index 100%
rename from plugins/russian/jaomix.ts
rename to plugins/russian/jaomix.broken.ts
diff --git a/plugins/russian/novelTL.ts b/plugins/russian/novelTL.broken.ts
similarity index 100%
rename from plugins/russian/novelTL.ts
rename to plugins/russian/novelTL.broken.ts
diff --git a/plugins/russian/ranobehub.ts b/plugins/russian/ranobehub.broken.ts
similarity index 100%
rename from plugins/russian/ranobehub.ts
rename to plugins/russian/ranobehub.broken.ts
diff --git a/plugins/russian/ranobelib.ts b/plugins/russian/ranobelib.broken.ts
similarity index 100%
rename from plugins/russian/ranobelib.ts
rename to plugins/russian/ranobelib.broken.ts
diff --git a/plugins/russian/ranoberf.ts b/plugins/russian/ranoberf.broken.ts
similarity index 100%
rename from plugins/russian/ranoberf.ts
rename to plugins/russian/ranoberf.broken.ts
diff --git a/plugins/russian/renovels.ts b/plugins/russian/renovels.broken.ts
similarity index 100%
rename from plugins/russian/renovels.ts
rename to plugins/russian/renovels.broken.ts
diff --git a/plugins/spanish/.spanish b/plugins/spanish/.spanish
deleted file mode 100644
index e69de29..0000000
diff --git a/plugins/spanish/hasutl.ts b/plugins/spanish/hasutl.broken.ts
similarity index 100%
rename from plugins/spanish/hasutl.ts
rename to plugins/spanish/hasutl.broken.ts
diff --git a/plugins/spanish/novelasligera.ts b/plugins/spanish/novelasligera.broken.ts
similarity index 100%
rename from plugins/spanish/novelasligera.ts
rename to plugins/spanish/novelasligera.broken.ts
diff --git a/plugins/spanish/skynovels.ts b/plugins/spanish/skynovels.broken.ts
similarity index 100%
rename from plugins/spanish/skynovels.ts
rename to plugins/spanish/skynovels.broken.ts
diff --git a/plugins/spanish/tunovelaligera.ts b/plugins/spanish/tunovelaligera.ts
index 6134a7e..4b80f3a 100644
--- a/plugins/spanish/tunovelaligera.ts
+++ b/plugins/spanish/tunovelaligera.ts
@@ -1,56 +1,72 @@
+import { CheerioAPI, load as parseHTML } from "cheerio";
import { fetchApi, fetchFile } from "@libs/fetch";
-import { load as parseHTML } from "cheerio";
-import { NovelStatus } from "@libs/novelStatus";
+import { Filter, FilterInputs } from "@libs/filterInputs";
+import { Plugin } from "@typings/plugin";
+import { showToast } from "@libs/showToast";
import { defaultCover } from "@libs/defaultCover";
-import { Chapter, Novel, Plugin } from "@typings/plugin";
+import { NovelStatus } from "@libs/novelStatus";
-export const id = "TNL.com";
-export const name = "TuNovelaLigera";
-export const site = "https://tunovelaligera.com/";
-export const version = "1.0.0";
-export const icon = "src/es/tunovelaligera/icon.png";
+class TuNovelaLigera implements Plugin.PluginBase {
+ id = "tunovelaligera";
+ name = "TuNovelaLigera";
+ icon = "src/es/tunovelaligera/icon.png";
+ site = "https://tunovelaligera.com/";
+ version = "1.0.0";
+ userAgent = "";
+ cookieString = "";
-const baseUrl = site;
+ async popularNovels(pageNo: number, {filters}: Plugin.PopularNovelsOptions): Promise {
+ let link = `${this.site}`;
-export const popularNovels: Plugin.popularNovels = async function (page) {
- let url = baseUrl + "novelas/page/" + page + "/?m_orderby=rating";
+ link += (filters?.genres ? `genero/` + filters.genres : "novelas");
- const result = await fetchApi(url);
- const body = await result.text();
+ link += `/page/${pageNo}`;
- let loadedCheerio = parseHTML(body);
+ link += (filters?.order ? filters.order : "?m_orderby=rating")
- let novels: Novel.Item[] = [];
+ const headers = new Headers();
+ if(this.cookieString){
+ headers.append("cookie", this.cookieString);
+ }
+ const result = await fetchApi(link, {headers})
+ const body = await result.text();
- loadedCheerio(".page-item-detail").each(function () {
- const novelName = loadedCheerio(this).find(".h5 > a").text();
- const novelCover = loadedCheerio(this).find("img").attr("src");
+ const loadedCheerio = parseHTML(body);
- let novelUrl = loadedCheerio(this).find(".h5 > a").attr("href");
- if (!novelUrl) return;
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
+ const novels: Plugin.NovelItem[] = [];
- novels.push(novel);
- });
+ loadedCheerio(".page-item-detail").each((i,el) => {
+ const novelName = loadedCheerio(el).find(".h5 > a").text();
+ const novelCover = loadedCheerio(el).find("img").attr("src");
+ const novelUrl = loadedCheerio(el).find(".h5 > a").attr("href");
- return novels;
-};
+ if (!novelUrl) return;
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters =
- async function (novelUrl) {
+ novels.push(novel);
+ });
+
+ return novels;
+ };
+
+ async parseNovelAndChapters(novelUrl: string): Promise {
const url = novelUrl;
-
- const result = await fetchApi(url);
+ const headers = new Headers();
+ if(this.cookieString){
+ headers.append("cookie", this.cookieString);
+ }
+ const result = await fetchApi(url, {headers});
const body = await result.text();
let loadedCheerio = parseHTML(body);
- let novel: Novel.instance = {
+ const novel: Plugin.SourceNovel = {
url,
+ chapters: [],
};
loadedCheerio(".manga-title-badges").remove();
@@ -62,6 +78,7 @@ export const parseNovelAndChapters: Plugin.parseNovelAndChapters =
novel.cover =
novelCover.attr("data-src") ||
novelCover.attr("src") ||
+ novelCover.attr('data-cfsrc') ||
defaultCover;
loadedCheerio(".post-content_item").each(function () {
@@ -93,69 +110,264 @@ export const parseNovelAndChapters: Plugin.parseNovelAndChapters =
novel.summary = loadedCheerio("div.summary__content > p").text().trim();
- let novelChapters: Chapter.Item[] = [];
+ let chapter: Plugin.ChapterItem[] = [];
- loadedCheerio(".lcp_catlist li").each(function () {
- const chapterName = loadedCheerio(this)
- .find("a")
- .text()
- .replace(/[\t\n]/g, "")
- .trim();
+ const delay = (ms: number) => new Promise((res) => setTimeout(res, ms));
+ let lastPage = 1;
+ lastPage = +loadedCheerio('.lcp_paginator li:last').prev().text();
- const releaseDate = loadedCheerio(this).find("span").text().trim();
+ const getChapters = async () => {
+ const n = url.split('/');
+ const novelName = n[4];
+ showToast('Cargando desde Archivo...');
- let chapterUrl = loadedCheerio(this).find("a").attr("href");
- if (!chapterUrl) return;
- novelChapters.push({
- name: chapterName,
- releaseTime: releaseDate,
- url: chapterUrl,
+ const formData = new FormData()
+ formData.append("action", "madara_load_more");
+ formData.append("page", "0");
+ formData.append("template", "html/loop/content");
+ formData.append("vars[category_name]", novelName);
+ formData.append("vars[posts_per_page]", "10000");
+
+ const result = await fetchApi(
+ `${this.site}wp-admin/admin-ajax.php`,
+ {
+ method: "POST",
+ body: formData,
+ headers
+ },
+ );
+ const text = await result.text();
+
+ loadedCheerio = parseHTML(text);
+
+ loadedCheerio('.heading').each((i, el) => {
+ const chapterName = loadedCheerio(el)
+ .text()
+ .replace(/[\t\n]/g, '')
+ .trim();
+ const releaseDate = null;
+ const chapterUrl = loadedCheerio(el).find('a').attr('href') || "";
+
+ chapter.push({
+ name: chapterName,
+ url: chapterUrl,
+ releaseTime: releaseDate,
+ });
});
- });
+ return chapter.reverse();
+ };
+
+ const getPageChapters = async () => {
+ for (let i = 1; i <= lastPage; i++) {
+ const chaptersUrl = `${novelUrl}?lcp_page0=${i}`;
+ showToast(`Cargando desde la página ${i}/${lastPage}...`);
+ const result = await fetchApi(chaptersUrl, {headers});
+ const chaptersHTML = await result.text();
- novel.chapters = novelChapters.reverse();
+ let chapterCheerio = parseHTML(chaptersHTML);
+ chapterCheerio('.lcp_catlist li').each((i, el) => {
+ const chapterName = chapterCheerio(el)
+ .find('a')
+ .text()
+ .replace(/[\t\n]/g, '')
+ .trim();
+
+ const releaseDate = chapterCheerio(el)
+ .find('span')
+ .text()
+ .trim();
+
+ const chapterUrl =
+ chapterCheerio(el).find('a').attr('href') || "";
+
+ chapter.push({
+ name: chapterName,
+ releaseTime: releaseDate,
+ url: chapterUrl,
+ });
+ });
+ await delay(1000);
+ }
+ return chapter.reverse();
+ }
+
+ novel.chapters = await getChapters();
+
+ if (!novel.chapters.length) {
+ showToast('¡Archivo no encontrado!');
+ await delay(1000);
+ novel.chapters = await getPageChapters();
+ }
+
return novel;
+ }
+
+ async parseChapter(chapterUrl: string): Promise {
+ const headers = new Headers();
+ if(this.cookieString){
+ headers.append("cookie", this.cookieString);
+ }
+ const result = await fetchApi(chapterUrl);
+ const body = await result.text();
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio("#hola_siguiente").next().find('div').remove();
+ const chapterText = loadedCheerio("#hola_siguiente").next().html() || "";
+
+ return chapterText;
};
-export const parseChapter: Plugin.parseChapter = async function (chapterUrl) {
- const url = chapterUrl;
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const url = `${this.site}?s=${searchTerm}&post_type=wp-manga`;
- const result = await fetchApi(url);
- const body = await result.text();
+ const result = await fetchApi(url);
+ const body = await result.text();
- let loadedCheerio = parseHTML(body);
+ const loadedCheerio = parseHTML(body);
- let chapterText = loadedCheerio("#hola_siguiente").next().text();
+ const novels: Plugin.NovelItem[] = [];
- return chapterText;
-};
+ loadedCheerio(".c-tabs-item__content").each((i, el) => {
+ const novelName = loadedCheerio(el).find(".h4 > a").text();
+ const novelCover = loadedCheerio(el).find("img").attr("src");
+ const novelUrl = loadedCheerio(el).find(".h4 > a").attr("href");
+ if (!novelUrl) return;
+ novels.push({
+ name: novelName,
+ url: novelUrl,
+ cover: novelCover,
+ });
+ });
-export const searchNovels: Plugin.searchNovels = async function (searchTerm) {
- const url = `${baseUrl}?s=${searchTerm}&post_type=wp-manga`;
+ return novels;
+ };
- const result = await fetchApi(url);
- const body = await result.text();
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url);
+ }
- let loadedCheerio = parseHTML(body);
+ filters = [
+ {
+ key: "order",
+ label: "Ordenado por",
+ values: [
+ { label: "Lo mas reciente", value: "?m_orderby=latest" },
- let novels: Novel.Item[] = [];
+ { label: "A-Z", value: "?m_orderby=alphabet" },
+
+ { label: "Clasificación", value: "?m_orderby=rating" },
+
+ { label: "Trending", value: "?m_orderby=trending" },
+
+ { label: "Mas visto", value: "?m_orderby=views" },
+
+ { label: "Nuevo", value: "?m_orderby=new-manga" },
+ ],
+ inputType: FilterInputs.Picker,
+ },
+ {
+ key: "genres",
+ label: "Generos",
+ values: [
+ { label: "Acción", value: "accion" },
- loadedCheerio(".c-tabs-item__content").each(function () {
- const novelName = loadedCheerio(this).find(".h4 > a").text();
- const novelCover = loadedCheerio(this).find("img").attr("src");
+ { label: "Adulto", value: "adulto" },
+
+ { label: "Artes Marciales", value: "artes-marciales" },
+
+ { label: "Aventura", value: "aventura" },
+
+ { label: "Ciencia Ficción", value: "ciencia-ficcion" },
+
+ { label: "Comedia", value: "comedia" },
+
+ { label: "Deportes", value: "deportes" },
+
+ { label: "Drama", value: "drama" },
+
+ { label: "Eastern Fantasy", value: "eastern-fantasy" },
+
+ { label: "Ecchi", value: "ecchi" },
+
+ { label: "FanFiction", value: "fan-fiction" },
+
+ { label: "Fantasía", value: "fantasia" },
+
+ { label: "Fantasía oriental", value: "fantasia-oriental" },
+
+ { label: "Ficción Romántica", value: "ficcion-romantica" },
+
+ { label: "Gender Bender", value: "gender-bender" },
+
+ { label: "Harem", value: "harem" },
+
+ { label: "Histórico", value: "historico" },
+
+ { label: "Horror", value: "horror" },
+
+ { label: "Josei", value: "josei" },
+
+ { label: "Maduro", value: "maduro" },
+
+ { label: "Mecha", value: "mecha" },
+
+ { label: "Misterio", value: "misterio" },
+
+ { label: "Novela China", value: "novela-china" },
+
+ { label: "Novela FanFiction", value: "novela-fanfiction" },
+
+ { label: "Novela Japonesa", value: "novela-japonesa" },
+
+ { label: "Novela Koreana", value: "novela-koreana" },
+
+ { label: "Novela ligera", value: "novela-ligera" },
+
+ { label: "Novela original", value: "novela-original" },
+
+ { label: "Novela Web", value: "web-novel" },
+
+ { label: "Psicológico", value: "psicologico" },
+
+ { label: "Realismo Mágico", value: "realismo-magico" },
+
+ { label: "Recuento de vida", value: "recuento-de-vida" },
+
+ { label: "Romance", value: "romance" },
+
+ { label: "Romance contemporáneo", value: "romance-contemporaneo" },
+
+ { label: "Romance Moderno", value: "romance-moderno" },
+
+ { label: "Seinen", value: "seinen" },
+
+ { label: "Shoujo", value: "shoujo" },
+
+ { label: "Shounen", value: "shounen" },
+
+ { label: "Sobrenatural", value: "sobrenatural" },
+
+ { label: "Tragedia", value: "tragedia" },
+
+ { label: "Vampiros", value: "vampiros" },
+
+ { label: "Vida Escolar", value: "vida-escolar" },
+
+ { label: "Western Fantasy", value: "western-fantasy" },
+
+ { label: "Wuxia", value: "wuxia" },
+
+ { label: "Xianxia", value: "xianxia" },
+
+ { label: "Xuanhuan", value: "xuanhuan" },
+
+ { label: "Yaoi", value: "yaoi" },
+ ],
+ inputType: FilterInputs.Picker,
+ },
+ ];
+}
- let novelUrl = loadedCheerio(this).find(".h4 > a").attr("href");
- if (!novelUrl) return;
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-export const fetchImage: Plugin.fetchImage = fetchFile;
+export default new TuNovelaLigera();
diff --git a/plugins/spanish/yukitls.ts b/plugins/spanish/yukitls.broken.ts
similarity index 100%
rename from plugins/spanish/yukitls.ts
rename to plugins/spanish/yukitls.broken.ts
diff --git a/plugins/turkish/.turkish b/plugins/turkish/.turkish
deleted file mode 100644
index e69de29..0000000
diff --git a/plugins/turkish/TurkceLightNovels[madara].ts b/plugins/turkish/TurkceLightNovels[madara].ts
index 6fea7a9..dd0b746 100644
--- a/plugins/turkish/TurkceLightNovels[madara].ts
+++ b/plugins/turkish/TurkceLightNovels[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "turkcelightnovels";
-export const name = "TurkceLightNovels [madara]";
-export const icon = "multisrc/madara/icons/turkcelightnovels.png";
-export const version = "1.0.0";
-export const site = "https://turkcelightnovels.com/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "novel-genre/" + filters.genres + '/';
- } else {
- url += "light-novel/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (false) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "light-novel" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":FilterInputs.Picker}];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise {
+ return await fetchFile(url, {});
+ }
+}
+const plugin = new MadaraPlugin({"id":"turkcelightnovels","sourceSite":"https://turkcelightnovels.com/","sourceName":"TurkceLightNovels","filters":[{"key":"sort","label":"Order by","values":[{"label":"Rating","value":"rating"},{"label":"A-Z","value":"alphabet"},{"label":"Latest","value":"latest"},{"label":"Most Views","value":"views"},{"label":"New","value":"new-manga"},{"label":"Trending","value":"trending"}],"inputType":"Picker"}],"options":{"path":{"novels":"light-novel","novel":"light-novel","chapter":"light-novel"},"lang":"Turkish"}});
+export default plugin;
+
\ No newline at end of file
diff --git a/plugins/turkish/WebNovelOku[madara].ts b/plugins/turkish/WebNovelOku[madara].ts
index 3a0557d..9587bdc 100644
--- a/plugins/turkish/WebNovelOku[madara].ts
+++ b/plugins/turkish/WebNovelOku[madara].ts
@@ -1,213 +1,252 @@
+import { fetchApi, fetchFile } from "@libs/fetch";
+import { Filter } from "@libs/filterInputs";
+import { Plugin } from '@typings/plugin'
import { load as parseHTML } from "cheerio";
-import { fetchFile, fetchApi } from "@libs/fetch";
-import { Novel, Plugin, Chapter } from "@typings/plugin";
-import { FilterInputs } from "@libs/filterInputs";
import { defaultCover } from "@libs/defaultCover";
-import { NovelStatus } from "@libs/novelStatus"
+import { NovelStatus } from "@libs/novelStatus";
import { parseMadaraDate } from "@libs/parseMadaraDate";
import dayjs from "dayjs";
-export const id = "webnoveloku";
-export const name = "WebNovelOku [madara]";
-export const icon = "multisrc/madara/icons/webnoveloku.png";
-export const version = "1.0.0";
-export const site = "https://www.webnoveloku.com/";
-const baseUrl = site;
+interface MadaraOptionPath{
+ genres?: string,
+ novels?: string,
+ novel?: string,
+ chapter?: string,
+}
-export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => {
- const novels: Novel.Item[] = [];
+const MadaraDefaultPath: MadaraOptionPath = {
+ novels: 'novel',
+ novel: 'novel',
+ chapter: 'novel'
+}
- let url = site;
+interface MadaraOptions {
+ useNewChapterEndpoint?: boolean,
+ path?: MadaraOptionPath,
+ lang?: string,
+ orderBy?: string
+}
- if (filters?.genres) {
- url += "novel-genre/" + filters.genres + '/';
- } else {
- url += "novel/";
+export interface MadaraMetadata {
+ id: string,
+ sourceSite: string,
+ sourceName: string,
+ options?: MadaraOptions,
+ filters?: Filter[],
+}
+class MadaraPlugin implements Plugin.PluginBase {
+ id: string;
+ name: string;
+ icon: string;
+ site: string;
+ version: string;
+ userAgent: string;
+ cookieString: string;
+ options?: MadaraOptions;
+ filter?: Filter[] | undefined;
+
+ constructor(metadata: MadaraMetadata){
+ this.id = metadata.id;
+ this.name = metadata.sourceName + "[madara]";
+ const iconFileName = metadata.sourceName.replace(/\s+/g, "").toLowerCase();
+ this.icon = `multisrc/madara/icons/${iconFileName}.png`;
+ this.site = metadata.sourceSite;
+ this.version = "1.0.0";
+ this.userAgent = "";
+ this.cookieString = "";
+ this.options = metadata.options;
+ this.filter = metadata.filters;
}
+ async popularNovels(pageNo: number, {filters, showLatestNovels}: Plugin.PopularNovelsOptions): Promise {
+ const novels: Plugin.NovelItem[] = [];
- url += '/page/' + pageNo + '/' +
- '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- loadedCheerio('.page-item-detail').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this).find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel: Novel.Item = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
-
- return novels;
-};
-
-export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async (
- novelUrl
-) => {
- const novel: Novel.instance = {
- url: novelUrl,
- };
-
- const body = await fetchApi(novelUrl).then(res => res.text());
-
- let loadedCheerio = parseHTML(body);
-
- loadedCheerio('.manga-title-badges').remove();
-
- novel.name = loadedCheerio('.post-title h1').text().trim();
-
- novel.cover =
- loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
- loadedCheerio('.summary_image > a > img').attr('data-src') ||
- loadedCheerio('.summary_image > a > img').attr('src') ||
- defaultCover;
-
- loadedCheerio('.post-content_item, .post-content').each(function () {
- const detailName = loadedCheerio(this).find('h5').text().trim();
- const detail = loadedCheerio(this).find('.summary-content').text().trim();
-
- switch (detailName) {
- case 'Genre(s)':
- case 'التصنيفات':
- novel.genres = detail.replace(/[\t\n]/g, ',');
- break;
- case 'Author(s)':
- case 'المؤلف':
- case 'المؤلف (ين)':
- novel.author = detail;
- break;
- case 'Status':
- case 'الحالة':
- novel.status =
- detail.includes('OnGoing') || detail.includes('مستمرة')
- ? NovelStatus.Ongoing
- : NovelStatus.Completed;
- break;
- }
- });
-
- loadedCheerio('div.summary__content .code-block,script').remove();
- novel.summary = loadedCheerio('div.summary__content').text().trim();
-
-
- let html;
-
- if (false) {
- const novelId =
- loadedCheerio('.rating-post-id').attr('value') ||
- loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
-
- const body = {
- action: "manga_get_chapters",
- manga: novelId,
- }
- html = await fetchApi(
- baseUrl + 'wp-admin/admin-ajax.php',
- {
- method: 'POST',
- body: JSON.stringify(body),
- })
- .then(res => res.text());
- } else {
- html = await fetchApi(
- baseUrl + 'ajax/chapters/',
- { method: 'POST' })
- .then(res => res.text());
- }
-
- if (html !== '0') {
- loadedCheerio = parseHTML(html);
- }
-
- const chapters: Chapter.Item[] = [];
- loadedCheerio('.wp-manga-chapter').each(function () {
- const chapterName = loadedCheerio(this).find('a').text().trim();
-
- let releaseDate = null;
- releaseDate = loadedCheerio(this)
- .find('span.chapter-release-date')
- .text()
- .trim();
-
- if (releaseDate) {
- releaseDate = parseMadaraDate(releaseDate);
+ let url = this.site;
+ if (filters?.genres && this.options?.path?.genres) {
+ url += this.options?.path?.genres + filters.genres + '/';
} else {
- /**
- * Insert current date
- */
-
- releaseDate = dayjs().format('LL');
+ url += this.options?.path?.novels ? this.options.path.novels : MadaraDefaultPath.novels;
}
+
+ url += '/page/' + pageNo + '/' +
+ '?m_orderby=' + (showLatestNovels ? 'latest' : (filters?.sort || 'rating'));
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges').remove();
+
+ loadedCheerio('.page-item-detail').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this).find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel: Plugin.NovelItem = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+
+ return novels;
+ }
+ async parseNovelAndChapters(novelUrl: string): Promise {
+ const novel: Plugin.SourceNovel = {
+ url: novelUrl,
+ };
+
+ const body = await fetchApi(novelUrl).then(res => res.text());
+
+ let loadedCheerio = parseHTML(body);
+
+ loadedCheerio('.manga-title-badges, #manga-title span').remove();
+ novel.name =
+ loadedCheerio('.post-title h1').text().trim() ||
+ loadedCheerio('#manga-title h1').text();
+
+ novel.cover =
+ loadedCheerio('.summary_image > a > img').attr('data-lazy-src') ||
+ loadedCheerio('.summary_image > a > img').attr('data-src') ||
+ loadedCheerio('.summary_image > a > img').attr('src') ||
+ defaultCover;
+
+ loadedCheerio('.post-content_item, .post-content').each(function () {
+ const detailName = loadedCheerio(this).find('h5').text().trim();
+ const detail = loadedCheerio(this).find('.summary-content').text().trim();
+
+ switch (detailName) {
+ case 'Genre(s)':
+ case 'التصنيفات':
+ novel.genres = detail.replace(/[\\t\\n]/g, ',');
+ break;
+ case 'Author(s)':
+ case 'المؤلف':
+ case 'المؤلف (ين)':
+ novel.author = detail;
+ break;
+ case 'Status':
+ case 'الحالة':
+ novel.status =
+ detail.includes('OnGoing') || detail.includes('مستمرة')
+ ? NovelStatus.Ongoing
+ : NovelStatus.Completed;
+ break;
+ }
+ });
+
+ loadedCheerio('div.summary__content .code-block,script').remove();
+ novel.summary =
+ loadedCheerio('div.summary__content').text().trim() ||
+ loadedCheerio('#tab-manga-about').text().trim() ||
+ loadedCheerio('.post-content_item h5:contains("Summary")').next().text().trim();
+
+ let html;
+
+ if (this.options?.useNewChapterEndpoint !== true) {
+ const novelId =
+ loadedCheerio('.rating-post-id').attr('value') ||
+ loadedCheerio('#manga-chapters-holder').attr('data-id') || '';
+
+ const formData = new FormData()
+ formData.append("action", "manga_get_chapters");
+ formData.append("manga", novelId);
- let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+ html = await fetchApi(
+ this.site + 'wp-admin/admin-ajax.php',
+ {
+ method: 'POST',
+ body: formData,
+ })
+ .then(res => res.text());
+ } else {
+ html = await fetchApi(
+ novelUrl + 'ajax/chapters/',
+ { method: 'POST' })
+ .then(res => res.text());
+ }
+
+ if (html !== '0') {
+ loadedCheerio = parseHTML(html);
+ }
+
+ const chapters: Plugin.ChapterItem[] = [];
+ loadedCheerio('.wp-manga-chapter').each(function () {
+ const chapterName = loadedCheerio(this).find('a').text().trim();
+
+ let releaseDate = null;
+ releaseDate = loadedCheerio(this)
+ .find('span.chapter-release-date')
+ .text()
+ .trim();
+
+ if (releaseDate) {
+ releaseDate = parseMadaraDate(releaseDate);
+ } else {
+ /**
+ * Insert current date
+ */
+
+ releaseDate = dayjs().format('LL');
+ }
+
+ let chapterUrl = loadedCheerio(this).find('a').attr('href') || '';
+
+ chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
+ });
+
+ novel.chapters = chapters.reverse();
+ return novel;
+ }
+ async parseChapter(chapterUrl: string): Promise {
+ const body = await fetchApi(chapterUrl).then(res => res.text());
- chapters.push({ name: chapterName, releaseTime: releaseDate, url: chapterUrl });
- });
+ const loadedCheerio = parseHTML(body);
+ const chapterText =
+ loadedCheerio('.text-left').html() ||
+ loadedCheerio('.text-right').html() ||
+ loadedCheerio('.entry-content').html() || "";
- novel.chapters = chapters.reverse();
- return novel;
-};
-
-export const parseChapter: Plugin.parseChapter = async (chapterUrl) => {
- const url = baseUrl + "/" + "novel" + "/" + chapterUrl;
-
- const body = await fetchApi(chapterUrl).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
- const chapterText =
- loadedCheerio('.text-left').html() ||
- loadedCheerio('.text-right').html() ||
- loadedCheerio('.entry-content').html();
-
- return chapterText;
-};
-
-export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
- const novels: Novel.Item[] = [];
- const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
-
- const body = await fetchApi(url).then(res => res.text());
-
- const loadedCheerio = parseHTML(body);
-
-
- loadedCheerio('.c-tabs-item__content').each(function () {
- const novelName = loadedCheerio(this).find('.post-title').text().trim();
-
- let image = loadedCheerio(this).find('img');
- const novelCover = image.attr('data-src') || image.attr('src');
-
- let novelUrl = loadedCheerio(this)
- .find('.post-title')
- .find('a')
- .attr('href') || '';
- const novel = {
- name: novelName,
- cover: novelCover,
- url: novelUrl,
- };
-
- novels.push(novel);
- });
- return novels;
-};
-
-export const fetchImage: Plugin.fetchImage = async (url) => {
- return await fetchFile(url);
-};
-
-export const filters = [{"key":"sort","label":"Sırala","values":[{"label":"A-Z","value":"alphabet"},{"label":"En Son","value":"latest"},{"label":"Görüntülenme","value":"views"},{"label":"Popülarite","value":"trending"},{"label":"Reyting","value":"rating"},{"label":"Yeni","value":"new-manga"}],"inputType":FilterInputs.Picker}];
\ No newline at end of file
+ return chapterText;
+ }
+ async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise {
+ const novels: Plugin.NovelItem[] = [];
+ const url = this.site + "?s=" + searchTerm + "&post_type=wp-manga";
+
+ const body = await fetchApi(url).then(res => res.text());
+
+ const loadedCheerio = parseHTML(body);
+
+
+ loadedCheerio('.c-tabs-item__content').each(function () {
+ const novelName = loadedCheerio(this).find('.post-title').text().trim();
+
+ let image = loadedCheerio(this).find('img');
+ const novelCover = image.attr('data-src') || image.attr('src');
+
+ let novelUrl = loadedCheerio(this)
+ .find('.post-title')
+ .find('a')
+ .attr('href') || '';
+ const novel = {
+ name: novelName,
+ cover: novelCover,
+ url: novelUrl,
+ };
+
+ novels.push(novel);
+ });
+ return novels;
+ }
+ async fetchImage(url: string): Promise