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 { + return await fetchFile(url, {}); + } +} +const 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"}}); +export default plugin; + \ No newline at end of file diff --git a/plugins/turkish/epiknovel.ts b/plugins/turkish/epiknovel.broken.ts similarity index 100% rename from plugins/turkish/epiknovel.ts rename to plugins/turkish/epiknovel.broken.ts diff --git a/plugins/turkish/lshnovel.ts b/plugins/turkish/lshnovel.ts index 473a98a..6ccd147 100644 --- a/plugins/turkish/lshnovel.ts +++ b/plugins/turkish/lshnovel.ts @@ -1,75 +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 = "lshnovel"; -export const name = "Liebe Schnee Hiver Novel"; -export const version = "1.0.0"; -export const icon = "multisrc/wpmangastream/icons/lshnovel.png"; -export const site = "https://lshnovel.com/"; +class LSHNovel implements Plugin.PluginBase { + id = "lshnovel"; + name = "Liebe Schnee Hiver Novel"; + icon = "multisrc/wpmangastream/icons/lshnovel.png"; + site = "https://lshnovel.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"); - if (!novelUrl) return; - const novel = { - name: novelName, - cover: novelCover, - url: novelUrl, - }; + novels.push(novel); + }); - novels.push(novel); - }); + return novels; + }; - 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: [], }; @@ -82,21 +83,12 @@ 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; @@ -115,7 +107,7 @@ export const parseNovelAndChapters: Plugin.parseNovelAndChapters = .end() .text(); - let chapter: Chapter.Item[] = []; + let chapter: Plugin.ChapterItem[] = []; loadedCheerio(".eplister") .find("li") @@ -131,7 +123,9 @@ export const parseNovelAndChapters: Plugin.parseNovelAndChapters = .trim(); const chapterUrl = loadedCheerio(this).find("a").attr("href"); + if (!chapterUrl) return; + chapter.push({ name: chapterName, releaseTime: releaseDate, @@ -142,172 +136,179 @@ 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: "Önerilen", - values: [ - { label: "Varsayılan", value: "" }, + filters = [ + { + key: "order", + label: "Önerilen", + values: [ + { label: "Varsayılan", value: "" }, - { label: "A-Z", value: "title" }, + { label: "A-Z", value: "title" }, - { label: "Z-A", value: "titlereverse" }, + { label: "Z-A", value: "titlereverse" }, - { label: "Son Yüklemeler", value: "update" }, + { label: "Son Yüklemeler", value: "update" }, - { label: "Son Eklenenler", value: "latest" }, + { label: "Son Eklenenler", value: "latest" }, - { label: "Bestimiz", value: "popular" }, - ], - inputType: FilterInputs.Picker, - }, - { - key: "status", - label: "Statü", - values: [ - { label: "Tümü", value: "" }, + { label: "Bestimiz", value: "popular" }, + ], + inputType: FilterInputs.Picker, + }, + { + key: "status", + label: "Statü", + values: [ + { label: "Tümü", 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: "Tür", - values: [ - { label: "Çeviri Novel", value: "ceviri-novel" }, + { label: "Completed", value: "completed" }, + ], + inputType: FilterInputs.Picker, + }, + { + key: "type", + label: "Tür", + values: [ + { label: "Çeviri Novel", value: "ceviri-novel" }, - { label: "Liz-Chan", value: "liz-chan" }, + { label: "Liz-Chan", value: "liz-chan" }, - { label: "Manhwa", value: "manhwa" }, + { label: "Manhwa", value: "manhwa" }, - { label: "Orijinal Novel", value: "orijinal-novel" }, + { label: "Orijinal Novel", value: "orijinal-novel" }, - { label: "Web Novel", value: "web-novel" }, - ], - inputType: FilterInputs.Checkbox, - }, - { - key: "genres", - label: "Kategori", - values: [ - { label: "+18", value: "18" }, + { label: "Web Novel", value: "web-novel" }, + ], + inputType: FilterInputs.Checkbox, + }, + { + key: "genres", + label: "Kategori", + values: [ + { label: "+18", value: "18" }, - { label: "Action", value: "action" }, + { label: "Action", value: "action" }, - { label: "Adult", value: "adult" }, + { label: "Adult", value: "adult" }, - { label: "Aksiyon", value: "aksiyon" }, + { label: "Aksiyon", value: "aksiyon" }, - { label: "BL", value: "bl" }, + { label: "BL", value: "bl" }, - { label: "Comedy", value: "comedy" }, + { label: "Comedy", value: "comedy" }, - { label: "Doğaüstü", value: "dogaustu" }, + { label: "Doğaüstü", value: "dogaustu" }, - { label: "Dram", value: "dram" }, + { label: "Dram", value: "dram" }, - { label: "Drama", value: "drama" }, + { label: "Drama", value: "drama" }, - { label: "Ecchi", value: "ecchi" }, + { label: "Ecchi", value: "ecchi" }, - { label: "Fantastik", value: "fantastik" }, + { label: "Fantastik", value: "fantastik" }, - { label: "Fantasy", value: "fantasy" }, + { label: "Fantasy", value: "fantasy" }, - { label: "Gizem", value: "gizem" }, + { label: "Gizem", value: "gizem" }, - { label: "Harem", value: "harem" }, + { label: "Harem", value: "harem" }, - { label: "Historical", value: "historical" }, + { label: "Historical", value: "historical" }, - { label: "Josei", value: "josei" }, + { label: "Josei", value: "josei" }, - { label: "Macera", value: "macera" }, + { label: "Macera", value: "macera" }, - { label: "Manhwa", value: "manhwa" }, + { label: "Manhwa", value: "manhwa" }, - { label: "Martial Arts", value: "martial-arts" }, + { label: "Martial Arts", value: "martial-arts" }, - { label: "Mature", value: "mature" }, + { label: "Mature", value: "mature" }, - { label: "Novel", value: "novel" }, + { label: "Novel", value: "novel" }, - { label: "Okul", value: "okul" }, + { label: "Okul", value: "okul" }, - { label: "Psikolojik", value: "psikolojik" }, + { label: "Psikolojik", value: "psikolojik" }, - { label: "Psychological", value: "psychological" }, + { label: "Psychological", value: "psychological" }, - { label: "Reverse Harem", value: "reverse-harem" }, + { label: "Reverse Harem", value: "reverse-harem" }, - { label: "Romance", value: "romance" }, + { label: "Romance", value: "romance" }, - { label: "Romantik", value: "romantik" }, + { label: "Romantik", value: "romantik" }, - { label: "Shoujo", value: "shoujo" }, + { label: "Shoujo", value: "shoujo" }, - { 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: "Supernatural", value: "supernatural" }, + { label: "Supernatural", value: "supernatural" }, - { label: "Tarihi", value: "tarihi" }, + { label: "Tarihi", value: "tarihi" }, - { label: "Tragedy", value: "tragedy" }, + { label: "Tragedy", value: "tragedy" }, - { label: "Yaoi", value: "yaoi" }, - ], - inputType: FilterInputs.Checkbox, - }, -]; + { label: "Yaoi", value: "yaoi" }, + ], + inputType: FilterInputs.Checkbox, + }, + ]; +} + +export default new LSHNovel(); \ No newline at end of file diff --git a/plugins/ukraine/smakolykytl.ts b/plugins/ukraine/smakolykytl.broken.ts similarity index 100% rename from plugins/ukraine/smakolykytl.ts rename to plugins/ukraine/smakolykytl.broken.ts diff --git a/plugins/vietnamese/.vietnamese b/plugins/vietnamese/.vietnamese deleted file mode 100644 index e69de29..0000000 diff --git a/plugins/vietnamese/LNHako.ts b/plugins/vietnamese/LNHako.ts index a9ca1c7..43c22c1 100644 --- a/plugins/vietnamese/LNHako.ts +++ b/plugins/vietnamese/LNHako.ts @@ -1,197 +1,161 @@ -import { load as parseHTML } from "cheerio"; +import { CheerioAPI, load as parseHTML } from "cheerio"; import { fetchApi, fetchFile } from "@libs/fetch"; -import { Chapter, Novel, Plugin } from "@typings/plugin"; -// import dayjs from "dayjs"; -// import { FilterInputs } from "@libs/filterInputs"; -// import { NovelStatus } from "@libs/novelStatus"; +import { Plugin } from "@typings/plugin"; import { isUrlAbsolute } from "@libs/isAbsoluteUrl"; -// import { parseMadaraDate } from "@libs/parseMadaraDate"; +import { Filter } from "@libs/filterInputs"; +class HakoPlugin implements Plugin.PluginBase { + id: string; + name: string; + icon: string; + site: string; + version: string; + userAgent: string; + cookieString: string; + constructor(){ + 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 = ""; + } + parseNovels(loadedCheerio: CheerioAPI){ + const novels: Plugin.NovelItem[] = []; + loadedCheerio(".row > .thumb-item-flow").each((index, ele) => { + let url = loadedCheerio(ele) + .find("div.thumb_attr.series-title > a") + .attr("href"); -const pluginId = "ln.hako"; -const baseUrl = "https://ln.hako.vn"; - -export const id = pluginId; // string and must be unique -export const name = "Hako"; -export const icon = "src/vi/hakolightnovel/icon.png"; // The relative path to the icon without @icons . For example: 'src/vi/hakolightnovel/icon.png' -export const version = "1.0.0"; // xx.xx.xx -export const site = baseUrl; // the link to the site - - -export const popularNovels: Plugin.popularNovels = async (pageNo) => { - const novels: Novel.Item[] = []; - const link = - baseUrl + "/danh-sach?truyendich=1&sapxep=topthang&page=" + pageNo; - const result = await fetchApi(link); - const body = await result.text(); - - const loadedCheerio = parseHTML(body); - - loadedCheerio("main.row > .thumb-item-flow").each(function () { - let url = loadedCheerio(this) - .find("div.thumb_attr.series-title > a") - .attr("href"); - - if (url && !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 && !isUrlAbsolute(cover)) { - cover = baseUrl + cover; + if (url && !isUrlAbsolute(url)) { + url = this.site + url; } - const novel = { - name, - url, - cover, - }; + if (url) { + const name = loadedCheerio(ele) + .find(".series-title") + .text() + .trim(); + let cover = loadedCheerio(ele) + .find(".img-in-ratio") + .attr("data-bg"); - novels.push(novel); - } - }); + if (cover && !isUrlAbsolute(cover)) { + cover = this.site + cover; + } - return novels; -}; + const novel = {name, url, cover}; -export const parseNovelAndChapters: Plugin.parseNovelAndChapters = async ( - novelUrl -) => { - const novel: Novel.instance = { - url: novelUrl, - }; - const result = await fetchApi(novelUrl); - const body = await result.text(); - - let loadedCheerio = parseHTML(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 - ? 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: Chapter.Item[] = []; - loadedCheerio(".list-chapters li").each(function () { - let chapterUrl = loadedCheerio(this).find("a").attr("href"); - - if (chapterUrl && !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; -}; - -export const parseChapter: Plugin.parseChapter = async (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 url = baseUrl + "/tim-kiem?keywords=" + searchTerm; - const result = await fetchApi(url); - const body = await result.text(); - - const loadedCheerio = parseHTML(body); - - loadedCheerio("div.row > .thumb-item-flow").each(function () { - let novelUrl = loadedCheerio(this) - .find("div.thumb_attr.series-title > a") - .attr("href"); - - if (novelUrl && !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 && !isUrlAbsolute(novelCover)) { - novelCover = baseUrl + novelCover; + novels.push(novel); } + }); + return novels; + } + async popularNovels(pageNo: number, options: Plugin.PopularNovelsOptions): Promise { + const link = this.site + "/danh-sach?truyendich=1&sapxep=topthang&page=" + pageNo; + const result = await fetch(link); + const body = await result.text(); + const loadedCheerio = parseHTML(body); + return this.parseNovels(loadedCheerio); + } + async parseNovelAndChapters(novelUrl: string): Promise { + const novel: Plugin.SourceNovel = { + url: novelUrl, + }; + const result = await fetch(novelUrl); + const body = await result.text(); + + let loadedCheerio = parseHTML(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 + ? 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((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: Plugin.ChapterItem[] = []; + loadedCheerio(".list-chapters li").each((index, ele) => { + let chapterUrl = loadedCheerio(ele).find("a").attr("href"); + + if (chapterUrl && !isUrlAbsolute(chapterUrl)) { + chapterUrl = this.site + chapterUrl; + } + + if (chapterUrl) { + const chapterName = loadedCheerio(ele) + .find(".chapter-name") + .text() + .trim(); + const releaseTime = loadedCheerio(ele) + .find(".chapter-time") + .text(); + + const chapter = { + name: chapterName, + releaseTime: releaseTime, + url: chapterUrl, + }; + + chapters.push(chapter); + } + }); + novel.chapters = chapters; + return novel; + } + async parseChapter(chapterUrl: string): Promise { + const result = await fetch(chapterUrl); + const body = await result.text(); - novels.push({ - name: novelName, - url: novelUrl, - cover: novelCover, - }); - } - }); + const loadedCheerio = parseHTML(body); - return novels; -}; + const chapterText = loadedCheerio("#chapter-content").html() || ""; -export const fetchImage: Plugin.fetchImage = async (url) => { - const headers = { - Referer: "https://ln.hako.vn", - }; - return await fetchFile(url, { headers: headers }); -}; + return chapterText; + } + async searchNovels(searchTerm: string, pageNo?: number | undefined): Promise { + const url = this.site + "/tim-kiem?keywords=" + searchTerm; + const result = await fetch(url); + const body = await result.text(); + const loadedCheerio = parseHTML(body); + return this.parseNovels(loadedCheerio); + } + async fetchImage(url: string): Promise { + const headers = { + Referer: "https://ln.hako.vn", + }; + return await fetchFile(url, { headers: headers }); + } +} + +export default new HakoPlugin(); diff --git a/scripts/clearMultisrc.ts b/scripts/clearMultisrc.ts new file mode 100644 index 0000000..da3fcfa --- /dev/null +++ b/scripts/clearMultisrc.ts @@ -0,0 +1,12 @@ +import * as path from 'path' +import * as fs from 'fs' + +const pluginDir = 'plugins' +fs.readdirSync(pluginDir).forEach(lang => { + const langDir = path.join(pluginDir, lang); + fs.readdirSync(langDir).forEach(plugin => { + if(plugin.endsWith('.ts') && plugin.includes("[")){ + fs.unlinkSync(path.join(langDir, plugin)); + } + }) +}) \ No newline at end of file diff --git a/scripts/json_plugins.ts b/scripts/json_plugins.ts index dd8ebda..a7542b7 100644 --- a/scripts/json_plugins.ts +++ b/scripts/json_plugins.ts @@ -16,11 +16,11 @@ if (!username || !repo || !branch) { console.error("config.json not provided!"); process.exit(1); } -if (!fs.existsSync(path.join(outRoot, "dist", username))) { - fs.mkdirSync(path.join(outRoot, "dist", username)); +if (!fs.existsSync(path.join(outRoot, ".dist", username))) { + fs.mkdirSync(path.join(outRoot, ".dist", username)); } const githubIconsLink = `https://raw.githubusercontent.com/${username}/${repo}/${branch}/icons`; -const githubPluginsLink = `https://raw.githubusercontent.com/${username}/${repo}/${branch}/js/plugins`; +const githubPluginsLink = `https://raw.githubusercontent.com/${username}/${repo}/${branch}/.js/plugins`; const json: { [key: string]: { @@ -33,8 +33,8 @@ const json: { iconUrl: string; }[]; } = {}; -const jsonPath = path.join(outRoot, "dist", username, "plugins.json"); -const jsonMinPath = path.join(outRoot, "dist", username, "plugins.min.json"); +const jsonPath = path.join(outRoot, ".dist", username, "plugins.json"); +const jsonMinPath = path.join(outRoot, ".dist", username, "plugins.min.json"); const pluginSet = new Set(); for (let language in languages) { @@ -47,10 +47,10 @@ for (let language in languages) { plugins.forEach((plugin) => { if (plugin.startsWith(".")) return; const instance: - | Plugin.instance + | Plugin.PluginBase | unknown = require(`../plugins/${language.toLowerCase()}/${ plugin.split(".")[0] - }`); + }`).default; if (!isPlugin(instance)) { console.log(plugin); diff --git a/scripts/multisrc/generate.ts b/scripts/multisrc/generate.ts index b0c6f5c..a065a29 100644 --- a/scripts/multisrc/generate.ts +++ b/scripts/multisrc/generate.ts @@ -19,7 +19,6 @@ const generate = async (name: string): Promise => { if (!isScriptGenerator(generateAll)) return false; const sources = generateAll(); - for (let source of sources) { const { lang, filename, pluginScript } = source; if(!lang || !filename || !pluginScript){ diff --git a/scripts/multisrc/madara/generator.ts b/scripts/multisrc/madara/generator.ts index 360303f..b800651 100644 --- a/scripts/multisrc/madara/generator.ts +++ b/scripts/multisrc/madara/generator.ts @@ -1,244 +1,28 @@ import { ScrpitGeneratorFunction } from "../generate"; import list from "./sources.json"; +import { MadaraMetadata } from "./template"; +import { readFileSync } from 'fs'; +import path from "path"; -type sourceData = (typeof list)[number]; export const generateAll: ScrpitGeneratorFunction = function () { - return list.map((source) => { - return generator(source); + return list.map((metadata: MadaraMetadata) => { + return generator(metadata); }); }; -const generator = function generator(sourceJson: sourceData) { - const { id, sourceSite, sourceName, options } = sourceJson; - const lang = options?.lang || "English"; - const path = { - genres: options?.path?.genres || "novel-genre", - novels: options?.path?.novels || "novel", - novel: options?.path?.novel || "novel", - chapter: options?.path?.chapter || "novel", - }; - const useNewChapterEndpoint = options?.useNewChapterEndpoint || false; - const iconFileName = sourceName.replace(/\s+/g, "").toLowerCase(); - const filters = sourceJson.filters; - const filetersString = JSON.stringify(filters).replace(/(\"inputType\":)\s*\"([^\"]+)\"/g, "$1FilterInputs.$2"); +const generator = function generator(metadata: MadaraMetadata) { + const lang = metadata.options?.lang || "English"; + + const madaraTemplate = readFileSync(path.join(__dirname, 'template.ts'), {encoding: 'utf-8'}); const pluginScript = ` -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 { parseMadaraDate } from "@libs/parseMadaraDate"; -import dayjs from "dayjs"; - -export const id = "${id}"; -export const name = "${sourceName} [madara]"; -export const icon = "multisrc/madara/icons/${iconFileName}.png"; -export const version = "1.0.0"; -export const site = "${sourceSite}"; -const baseUrl = site; - -export const popularNovels: Plugin.popularNovels = async (pageNo, {filters, showLatestNovels}) => { - const novels: Novel.Item[] = []; - - let url = site; - - if (filters?.genres) { - url += "${path.genres}/" + filters.genres + '/'; - } else { - url += "${path.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: 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 (${useNewChapterEndpoint}) { - 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); - } 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; -}; - -export const parseChapter: Plugin.parseChapter = async (chapterUrl) => { - const url = baseUrl + "/" + "${path.chapter}" + "/" + 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 = ${filetersString};`; - +${madaraTemplate} +const plugin = new MadaraPlugin(${JSON.stringify(metadata)}); +export default plugin; + ` return { lang, - filename: sourceName, + filename: metadata.sourceName, pluginScript, }; }; diff --git a/scripts/multisrc/madara/sources.json b/scripts/multisrc/madara/sources.json index 1e1cda6..0eac867 100644 --- a/scripts/multisrc/madara/sources.json +++ b/scripts/multisrc/madara/sources.json @@ -5363,4 +5363,4 @@ "lang": "Turkish" } } -] \ No newline at end of file +] diff --git a/scripts/multisrc/madara/template.ts b/scripts/multisrc/madara/template.ts new file mode 100644 index 0000000..9a8a530 --- /dev/null +++ b/scripts/multisrc/madara/template.ts @@ -0,0 +1,248 @@ +import { fetchApi, fetchFile } from "@libs/fetch"; +import { Filter } from "@libs/filterInputs"; +import { Plugin } from '@typings/plugin' +import { load as parseHTML } from "cheerio"; +import { defaultCover } from "@libs/defaultCover"; +import { NovelStatus } from "@libs/novelStatus"; +import { parseMadaraDate } from "@libs/parseMadaraDate"; +import dayjs from "dayjs"; + +interface MadaraOptionPath{ + genres?: string, + novels?: string, + novel?: string, + chapter?: string, +} + +const MadaraDefaultPath: MadaraOptionPath = { + novels: 'novel', + novel: 'novel', + chapter: 'novel' +} + +interface MadaraOptions { + useNewChapterEndpoint?: boolean, + path?: MadaraOptionPath, + lang?: string, + orderBy?: string +} + +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[] = []; + + let url = this.site; + if (filters?.genres && this.options?.path?.genres) { + url += this.options?.path?.genres + filters.genres + '/'; + } else { + 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); + + 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()); + + const loadedCheerio = parseHTML(body); + const chapterText = + loadedCheerio('.text-left').html() || + loadedCheerio('.text-right').html() || + loadedCheerio('.entry-content').html() || ""; + + 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, {}); + } +} \ No newline at end of file diff --git a/scripts/multisrc/readwn/generator.ts b/scripts/multisrc/readwn/generator.ts deleted file mode 100644 index 19be43b..0000000 --- a/scripts/multisrc/readwn/generator.ts +++ /dev/null @@ -1,221 +0,0 @@ -import { ScrpitGeneratorFunction } from "../generate"; -import list from "./sources.json"; - -type sourceData = (typeof list)[number]; - -export const generateAll: ScrpitGeneratorFunction = function () { - return list.map((source) => { - return generator(source); - }); -}; - -const generator = function generator(sourceJson: sourceData) { - const pluginId = sourceJson.id; - const sourceName = sourceJson.sourceName; - const site = sourceJson.sourceSite; - const iconFileName = sourceName.split('.')[0].toLowerCase() + '.png'; - const filters = sourceJson.filters; - const filetersString = JSON.stringify(filters) - .replace(/(\"inputType\":)\s*\"([^\"]+)\"/g, " $1FilterInputs.$2"); - - const pluginScript = ` -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 = "${pluginId}"; -export const name = "${sourceName}"; -export const icon = "multisrc/readwn/icons/${iconFileName}"; -export const version = "1.0.0"; -export const site = "${site}"; - -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 = ${filetersString};` - return { - lang: "English", - filename: sourceName, - pluginScript, - }; -}; diff --git a/scripts/multisrc/readwn/sources.json b/scripts/multisrc/readwn/sources.json deleted file mode 100644 index 9a7d358..0000000 --- a/scripts/multisrc/readwn/sources.json +++ /dev/null @@ -1,818 +0,0 @@ -[ - { - "id": "Readwn.com", - "sourceSite": "https://www.readwn.com/", - "sourceName": "Readwn.com", - "filters": [ - { - "key": "sort", - "label": "Sort By", - "values": [ - { - "label": "New", - "value": "newstime" - }, - { - "label": "Popular", - "value": "onclick" - }, - { - "label": "Updates", - "value": "lastdotime" - } - ], - "inputType": "Picker" - }, - { - "key": "status", - "label": "Status", - "values": [ - { - "label": "All", - "value": "all" - }, - { - "label": "Completed", - "value": "Completed" - }, - { - "label": "Ongoing", - "value": "Ongoing" - } - ], - "inputType": "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": "Picker" - } - ] - }, - { - "id": "Novelmt.com", - "sourceSite": "https://www.novelmt.com/", - "sourceName": "Novelmt.com", - "filters": [ - { - "key": "sort", - "label": "Sort By", - "values": [ - { - "label": "New", - "value": "newstime" - }, - { - "label": "Popular", - "value": "onclick" - }, - { - "label": "Updates", - "value": "lastdotime" - } - ], - "inputType": "Picker" - }, - { - "key": "status", - "label": "Status", - "values": [ - { - "label": "All", - "value": "all" - }, - { - "label": "Completed", - "value": "Completed" - }, - { - "label": "Ongoing", - "value": "Ongoing" - } - ], - "inputType": "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": "Picker" - } - ] - }, - { - "id": "Ltnovel.com", - "sourceSite": "https://www.ltnovel.com/", - "sourceName": "Ltnovel.com", - "filters": [ - { - "key": "sort", - "label": "Sort By", - "values": [ - { - "label": "New", - "value": "newstime" - }, - { - "label": "Popular", - "value": "onclick" - }, - { - "label": "Updates", - "value": "lastdotime" - } - ], - "inputType": "Picker" - }, - { - "key": "status", - "label": "Status", - "values": [ - { - "label": "All", - "value": "all" - }, - { - "label": "Completed", - "value": "Completed" - }, - { - "label": "Ongoing", - "value": "Ongoing" - } - ], - "inputType": "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": "Picker" - } - ] - } -] \ No newline at end of file diff --git a/scripts/multisrc/rulate/generator.ts b/scripts/multisrc/rulate/generator.ts deleted file mode 100644 index 7dd3098..0000000 --- a/scripts/multisrc/rulate/generator.ts +++ /dev/null @@ -1,251 +0,0 @@ -import { ScrpitGeneratorFunction } from "../generate"; -import list from "./sources.json"; - -type sourceData = (typeof list)[number]; - -export const generateAll: ScrpitGeneratorFunction = function () { - return list.map((source) => { - return generator(source); - }); -}; - -const generator = function generator(sourceJson: sourceData) { - const pluginId = sourceJson.id; - const sourceName = sourceJson.sourceName; - const iconFileName = sourceName.split('.')[0].toLowerCase() + '.png'; - const site = sourceJson.sourceSite; - const filters = sourceJson.filters; - const filetersString = JSON.stringify(filters).replace(/(\"inputType\":)\s*\"([^\"]+)\"/g, "$1FilterInputs.$2"); - const pluginScript = ` -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 = "${pluginId}"; -export const name = "${sourceName}"; -export const icon = "multisrc/rulate/icons/${iconFileName}"; -export const version = "1.0.0"; -export const site = "${site}"; - -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 = ${filetersString};` - - return { - lang: "Russian", - filename: sourceName, - pluginScript, - }; -}; diff --git a/scripts/multisrc/rulate/sources.json b/scripts/multisrc/rulate/sources.json deleted file mode 100644 index 15642d5..0000000 --- a/scripts/multisrc/rulate/sources.json +++ /dev/null @@ -1,22556 +0,0 @@ -[ - { - "id": "tl.rulate", - "sourceSite": "https://tl.rulate.ru", - "sourceName": "Rulate", - "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": "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": "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": "Picker" - }, - { - "key": "type", - "label": "Тип:", - "values": [ - { - "label": "Неважно", - "value": "0" - }, - { - "label": "Только авторские", - "value": "2" - }, - { - "label": "Только переводы", - "value": "1" - } - ], - "inputType": "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": "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": "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": "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": "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": "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": "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": "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": "Checkbox" - }, - { - "key": "atmosphere", - "label": "Атмосфера:", - "values": [ - { - "label": "Неважно", - "value": "0" - }, - { - "label": "Позитивная", - "value": "1" - }, - { - "label": "Dark", - "value": "2" - } - ], - "inputType": "Picker" - }, - { - "key": "adult", - "label": "Возрастные ограничения:", - "values": [ - { - "label": "Все", - "value": "0" - }, - { - "label": "Только 18+", - "value": "2" - }, - { - "label": "Убрать 18+", - "value": "1" - } - ], - "inputType": "Picker" - } - ] - }, - { - "id": "erolate", - "sourceSite": "https://erolate.com", - "sourceName": "Erolate", - "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": "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": "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": "Picker" - }, - { - "key": "type", - "label": "Тип:", - "values": [ - { - "label": "Неважно", - "value": "0" - }, - { - "label": "Только авторские", - "value": "2" - }, - { - "label": "Только переводы", - "value": "1" - } - ], - "inputType": "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": "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": "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": "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": "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": "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": "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": "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": "Checkbox" - }, - { - "key": "atmosphere", - "label": "Атмосфера:", - "values": [ - { - "label": "Неважно", - "value": "0" - }, - { - "label": "Позитивная", - "value": "1" - }, - { - "label": "Dark", - "value": "2" - } - ], - "inputType": "Picker" - }, - { - "key": "adult", - "label": "Возрастные ограничения:", - "values": [ - { - "label": "Все", - "value": "0" - }, - { - "label": "Только 18+", - "value": "2" - }, - { - "label": "Убрать 18+", - "value": "1" - } - ], - "inputType": "Picker" - } - ] - } -] \ No newline at end of file diff --git a/template.min.ts b/template.min.ts deleted file mode 100644 index 9800bf3..0000000 --- a/template.min.ts +++ /dev/null @@ -1,54 +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 { Filter, FilterInputs } from "@libs/filterInputs"; -// import { NovelStatus } from '@libs/novelStatus'; -// import { defaultCover } from "@libs/defaultCover"; - - -export const id = ""; -export const name = "Source name"; -export const icon = ""; -export const version = "0.0.0"; -export const site = ""; -// export const filters: Filter[] = []; - -export const popularNovels: Plugin.popularNovels = async function ( - page, - { filters, showLatestNovels } -) { - const novels: Novel.Item[] = []; - - return novels; -}; - - -export const parseNovelAndChapters: Plugin.parseNovelAndChapters = - async function (novelUrl) { - const novel: Novel.instance = { - url: novelUrl, - chapters: [], - }; - - return novel; - }; - -export const parseChapter: Plugin.parseChapter = async function (chapterUrl) { - const chapterText = ""; - - return chapterText; -}; - -export const searchNovels: Plugin.searchNovels = async (searchTerm) => { - const novels: Novel.Item[] = []; - - return novels; -}; - -export const fetchImage: Plugin.fetchImage = async (url) => { - return await fetchFile(url, {}); -}; diff --git a/template.ts b/template.ts deleted file mode 100644 index 801eb25..0000000 --- a/template.ts +++ /dev/null @@ -1,90 +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 { Filter, FilterInputs } from "@libs/filterInputs"; -// import { NovelStatus } from '@libs/novelStatus'; -// import { defaultCover } from "@libs/defaultCover"; - -export const id = ""; // string and must be unique -export const name = "Source name"; -export const icon = ""; // The relative path to the icon without @icons . For example: 'src/vi/hakolightnovel/icon.png' -export const version = "0.0.0"; // xx.xx.xx -export const site = ""; // the link to the site -// export const filters: Filter[] = []; - -export const popularNovels: Plugin.popularNovels = async function ( - page, - { filters, showLatestNovels } -) { - const novels: Novel.Item[] = []; - /* - Do something.... - novel = { - name: '', - url: '', must be absolute - cover: '', - } - novels.push(novel); - */ - return novels; -}; - -export const parseNovelAndChapters: Plugin.parseNovelAndChapters = - async function (novelUrl) { - const novel: Novel.instance = { - url: novelUrl, - chapters: [], - }; - - /** - * novel.name = ''; - * novel.cover = ''; - * novel.summary = ''; - * novel.author = ''; - * novel.artist = ''; - * novel.status = ''; - * novel.genres = ''; join by commas. For example: 'romcom, action, school' - */ - - /* - Do something.... - chapter = { - name: '', chapter name should contain vol, chap num (eg: vol 1 chap 11.5: abcxyz) - it helps a alot in migation - url: '', must be absoulute - releaseTime: '', - } - novel.chapters.push(chapter); - */ - - return novel; - }; - -export const parseChapter: Plugin.parseChapter = async function (chapterUrl) { - // Do something... - const chapterText = ""; - return chapterText; -}; - -export const searchNovels: Plugin.searchNovels = async function (searchTerm) { - const novels: Novel.Item[] = []; - /* - Do something.... - const novel = { - name: '', - url: '', must be absolute - cover: '', - } - novels.push(novel); - */ - return novels; -}; - -export const fetchImage: Plugin.fetchImage = async function (url) { - // Some site cant fetch images normally (maybe need some headers) - // Must return base64 of image - return await fetchFile(url, {}); -}; diff --git a/test_web/api/plugins.ts b/test_web/api/plugins.ts index e0011ca..f43c0a0 100644 --- a/test_web/api/plugins.ts +++ b/test_web/api/plugins.ts @@ -24,9 +24,9 @@ export const all_plugins = (): PluginList => { const requirePath = `@plugins/${languageEnglish.toLowerCase()}/${ plugin.split(".")[0] }`; - const instance = require(requirePath); + const instance = require(requirePath).default; const { id, name, version, icon } = instance; - const info: Plugin.Info = { + const info: Plugin.PluginItem = { id, name, lang: languageNative, @@ -42,21 +42,20 @@ export const all_plugins = (): PluginList => { const getPlugin = async ( requirePath: string -): Promise => { - const plugin = await require(requirePath); +): Promise => { + const plugin = await require(requirePath).default; if (isPlugin(plugin)) return plugin; return null; }; +export const getFilter = async ( + pluginRequirePath: string +) => (await getPlugin(pluginRequirePath))?.filters; + export const popularNovels = async ( pluginRequirePath: string, - options: Plugin.Options -) => { - const plugin = await getPlugin(pluginRequirePath); - if (!plugin) return null; - const popularNovels = await plugin.popularNovels(1, options); - return popularNovels; -}; + options: Plugin.PopularNovelsOptions +) => (await getPlugin(pluginRequirePath))?.popularNovels(1, options); export const searchNovels = async ( pluginRequirePath: string, diff --git a/test_web/index.html b/test_web/index.html index 177f13a..a23278c 100644 --- a/test_web/index.html +++ b/test_web/index.html @@ -7,6 +7,7 @@ + Testing plugin @@ -30,9 +31,31 @@
+
popularNovels - +
Loading...
@@ -46,7 +69,7 @@
- +
@@ -62,7 +85,7 @@
- +
@@ -82,7 +105,7 @@
- +
@@ -100,7 +123,7 @@
- +
@@ -111,7 +134,9 @@
- + + + \ No newline at end of file diff --git a/test_web/static/css/index.css b/test_web/static/css/index.css index bc2b149..d2a612e 100644 --- a/test_web/static/css/index.css +++ b/test_web/static/css/index.css @@ -1,3 +1,8 @@ +*{ + margin: 0; + padding: 0; + box-sizing: border-box; +} .navbar{ width: 1080px; align-items: center; @@ -119,3 +124,7 @@ grid-template-columns: 15rem 15rem 15rem 15rem; grid-gap: 0, 0; } + +.select-option-text{ + padding-left: 1rem; +} \ No newline at end of file diff --git a/test_web/static/css/mdb5.css b/test_web/static/css/mdb5.css new file mode 100644 index 0000000..982382c --- /dev/null +++ b/test_web/static/css/mdb5.css @@ -0,0 +1,19301 @@ +/*! + * + * Version: MDB Pro 6.4.2 + * + * Copyright: Material Design for Bootstrap + * https://mdbootstrap.com/ + * + * If you don't have a PRO license, you can purchase one here: + * https://mdbootstrap.com/docs/standard/pro/ + * + * Enterprise quotations, standard license & license customization: + * https://mdbootstrap.com/general/license/ + * + * Documentation: + * https://mdbootstrap.com/docs/standard/ + * + * Support: + * https://mdbootstrap.com/support/ + * + * Contact: + * contact@mdbootstrap.com + * + */ + :root { + --mdb-red: #f44336; + --mdb-pink: #e91e63; + --mdb-purple: #9c27b0; + --mdb-indigo: #3f51b5; + --mdb-blue: #2196f3; + --mdb-cyan: #00bcd4; + --mdb-teal: #009688; + --mdb-green: #4caf50; + --mdb-yellow: #ffeb3b; + --mdb-orange: #ff9800; + --mdb-white: #fff; + --mdb-black: #000; + --mdb-gray: #757575; + --mdb-gray-dark: #4f4f4f; + --mdb-gray-50: #fbfbfb; + --mdb-gray-100: #f5f5f5; + --mdb-gray-200: #eee; + --mdb-gray-300: #e0e0e0; + --mdb-gray-400: #bdbdbd; + --mdb-gray-500: #9e9e9e; + --mdb-gray-600: #757575; + --mdb-gray-700: #616161; + --mdb-gray-800: #4f4f4f; + --mdb-gray-900: #262626; + --mdb-primary: #3b71ca; + --mdb-secondary: #9fa6b2; + --mdb-success: #14a44d; + --mdb-danger: #dc4c64; + --mdb-warning: #e4a11b; + --mdb-info: #54b4d3; + --mdb-light: #fbfbfb; + --mdb-dark: #332d2d; + --mdb-primary-rgb: 59,113,202; + --mdb-secondary-rgb: 159,166,178; + --mdb-success-rgb: 20,164,77; + --mdb-danger-rgb: 220,76,100; + --mdb-warning-rgb: 228,161,27; + --mdb-info-rgb: 84,180,211; + --mdb-light-rgb: 251,251,251; + --mdb-dark-rgb: 51,45,45; + --mdb-white-rgb: 255,255,255; + --mdb-black-rgb: 0,0,0; + --mdb-body-color-rgb: 79,79,79; + --mdb-body-bg-rgb: 255,255,255; + --mdb-font-sans-serif: system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue","Noto Sans","Liberation Sans",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"; + --mdb-font-monospace: SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace; + --mdb-gradient: linear-gradient(180deg,hsla(0,0%,100%,0.15),hsla(0,0%,100%,0)); + --mdb-body-font-family: var(--mdb-font-roboto); + --mdb-body-font-size: 1rem; + --mdb-body-font-weight: 400; + --mdb-body-line-height: 1.6; + --mdb-body-color: #4f4f4f; + --mdb-body-bg: #fff; + --mdb-border-width: 1px; + --mdb-border-style: solid; + --mdb-border-color: #e0e0e0; + --mdb-border-color-translucent: rgba(0,0,0,0.175); + --mdb-border-radius: 0.25rem; + --mdb-border-radius-sm: 0.25rem; + --mdb-border-radius-lg: 0.5rem; + --mdb-border-radius-xl: 1rem; + --mdb-border-radius-2xl: 2rem; + --mdb-border-radius-pill: 50rem; + --mdb-link-color: #3b71ca; + --mdb-link-hover-color: #386bc0; + --mdb-code-color: #e91e63; + --mdb-highlight-bg: #fff9c4 +} + +*,:after,:before { + box-sizing: border-box +} + +@media(prefers-reduced-motion:no-preference) { + :root { + scroll-behavior: smooth + } +} + +body { + margin: 0; + font-family: var(--mdb-body-font-family); + font-size: var(--mdb-body-font-size); + font-weight: var(--mdb-body-font-weight); + line-height: var(--mdb-body-line-height); + color: var(--mdb-body-color); + text-align: var(--mdb-body-text-align); + background-color: var(--mdb-body-bg); + -webkit-text-size-adjust: 100%; + -webkit-tap-highlight-color: rgba(0,0,0,0) +} + +hr { + margin: 1rem 0; + color: inherit; + border: 0; + border-top: 1px solid; + opacity: .25 +} + +.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6 { + margin-top: 0; + margin-bottom: .5rem; + font-weight: 500; + line-height: 1.2 +} + +.h1,h1 { + font-size: calc(1.375rem + 1.5vw) +} + +@media(min-width: 1200px) { + .h1,h1 { + font-size:2.5rem + } +} + +.h2,h2 { + font-size: calc(1.325rem + .9vw) +} + +@media(min-width: 1200px) { + .h2,h2 { + font-size:2rem + } +} + +.h3,h3 { + font-size: calc(1.3rem + .6vw) +} + +@media(min-width: 1200px) { + .h3,h3 { + font-size:1.75rem + } +} + +.h4,h4 { + font-size: calc(1.275rem + .3vw) +} + +@media(min-width: 1200px) { + .h4,h4 { + font-size:1.5rem + } +} + +.h5,h5 { + font-size: 1.25rem +} + +.h6,h6 { + font-size: 1rem +} + +p { + margin-top: 0; + margin-bottom: 1rem +} + +abbr[title] { + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; + cursor: help; + -webkit-text-decoration-skip-ink: none; + text-decoration-skip-ink: none +} + +address { + margin-bottom: 1rem; + font-style: normal; + line-height: inherit +} + +ol,ul { + padding-left: 2rem +} + +dl,ol,ul { + margin-top: 0; + margin-bottom: 1rem +} + +ol ol,ol ul,ul ol,ul ul { + margin-bottom: 0 +} + +dt { + font-weight: 700 +} + +dd { + margin-bottom: .5rem; + margin-left: 0 +} + +blockquote { + margin: 0 0 1rem +} + +b,strong { + font-weight: bolder +} + +.small,small { + font-size: .875em +} + +.mark,mark { + padding: .1875em; + background-color: var(--mdb-highlight-bg) +} + +sub,sup { + position: relative; + font-size: .75em; + line-height: 0; + vertical-align: baseline +} + +sub { + bottom: -.25em +} + +sup { + top: -.5em +} + +a { + color: var(--mdb-link-color) +} + +a,a:hover { + text-decoration: none +} + +a:hover { + color: var(--mdb-link-hover-color) +} + +a:not([href]):not([class]),a:not([href]):not([class]):hover { + color: inherit; + text-decoration: none +} + +code,kbd,pre,samp { + font-family: var(--mdb-font-monospace); + font-size: 1em +} + +pre { + display: block; + margin-top: 0; + margin-bottom: 1rem; + overflow: auto; + font-size: .875em +} + +pre code { + font-size: inherit; + color: inherit; + word-break: normal +} + +code { + font-size: .875em; + color: var(--mdb-code-color); + word-wrap: break-word +} + +a>code { + color: inherit +} + +kbd { + padding: .1875rem .375rem; + font-size: .875em; + color: var(--mdb-body-bg); + background-color: var(--mdb-body-color); + border-radius: .25rem +} + +kbd kbd { + padding: 0; + font-size: 1em +} + +figure { + margin: 0 0 1rem +} + +img,svg { + vertical-align: middle +} + +table { + caption-side: bottom; + border-collapse: collapse +} + +caption { + padding-top: 1rem; + padding-bottom: 1rem; + color: #757575; + text-align: left +} + +th { + text-align: inherit; + text-align: -webkit-match-parent +} + +tbody,td,tfoot,th,thead,tr { + border: 0 solid; + border-color: inherit +} + +label { + display: inline-block +} + +button { + border-radius: 0 +} + +button:focus:not(:focus-visible) { + outline: 0 +} + +button,input,optgroup,select,textarea { + margin: 0; + font-family: inherit; + font-size: inherit; + line-height: inherit +} + +button,select { + text-transform: none +} + +[role=button] { + cursor: pointer +} + +select { + word-wrap: normal +} + +select:disabled { + opacity: 1 +} + +[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator { + display: none!important +} + +[type=button],[type=reset],[type=submit],button { + -webkit-appearance: button +} + +[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled) { + cursor: pointer +} + +::-moz-focus-inner { + padding: 0; + border-style: none +} + +textarea { + resize: vertical +} + +fieldset { + min-width: 0; + padding: 0; + margin: 0; + border: 0 +} + +legend { + float: left; + width: 100%; + padding: 0; + margin-bottom: .5rem; + font-size: calc(1.275rem + .3vw); + line-height: inherit +} + +@media(min-width: 1200px) { + legend { + font-size:1.5rem + } +} + +legend+* { + clear: left +} + +::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field { + padding: 0 +} + +::-webkit-inner-spin-button { + height: auto +} + +[type=search] { + outline-offset: -2px; + -webkit-appearance: textfield +} + +/*!rtl:raw: +[type="tel"], +[type="url"], +[type="email"], +[type="number"] { + direction: ltr; +} +*/ +::-webkit-search-decoration { + -webkit-appearance: none +} + +::-webkit-color-swatch-wrapper { + padding: 0 +} + +::file-selector-button { + font: inherit; + -webkit-appearance: button +} + +output { + display: inline-block +} + +iframe { + border: 0 +} + +summary { + display: list-item; + cursor: pointer +} + +progress { + vertical-align: baseline +} + +[hidden] { + display: none!important +} + +.lead { + font-size: 1.25rem; + font-weight: 300 +} + +.display-1 { + font-size: calc(1.625rem + 4.5vw); + font-weight: 300; + line-height: 1.2 +} + +@media(min-width: 1200px) { + .display-1 { + font-size:5rem + } +} + +.display-2 { + font-size: calc(1.575rem + 3.9vw); + font-weight: 300; + line-height: 1.2 +} + +@media(min-width: 1200px) { + .display-2 { + font-size:4.5rem + } +} + +.display-3 { + font-size: calc(1.525rem + 3.3vw); + font-weight: 300; + line-height: 1.2 +} + +@media(min-width: 1200px) { + .display-3 { + font-size:4rem + } +} + +.display-4 { + font-size: calc(1.475rem + 2.7vw); + font-weight: 300; + line-height: 1.2 +} + +@media(min-width: 1200px) { + .display-4 { + font-size:3.5rem + } +} + +.display-5 { + font-size: calc(1.425rem + 2.1vw); + font-weight: 300; + line-height: 1.2 +} + +@media(min-width: 1200px) { + .display-5 { + font-size:3rem + } +} + +.display-6 { + font-size: calc(1.375rem + 1.5vw); + font-weight: 300; + line-height: 1.2 +} + +@media(min-width: 1200px) { + .display-6 { + font-size:2.5rem + } +} + +.list-inline,.list-unstyled { + padding-left: 0; + list-style: none +} + +.list-inline-item { + display: inline-block +} + +.list-inline-item:not(:last-child) { + margin-right: .5rem +} + +.initialism { + font-size: .875em; + text-transform: uppercase +} + +.blockquote { + margin-bottom: 1rem; + font-size: 1.25rem +} + +.blockquote>:last-child { + margin-bottom: 0 +} + +.blockquote-footer { + margin-top: -1rem; + margin-bottom: 1rem; + font-size: .875em; + color: #757575 +} + +.blockquote-footer:before { + content: "— " +} + +.img-fluid,.img-thumbnail { + max-width: 100%; + height: auto +} + +.img-thumbnail { + padding: .25rem; + background-color: #fff; + border: 1px solid var(--mdb-border-color); + border-radius: .25rem; + box-shadow: 0 .125rem .25rem rgba(0,0,0,.075) +} + +.figure { + display: inline-block +} + +.figure-img { + margin-bottom: .5rem; + line-height: 1 +} + +.figure-caption { + font-size: .875em; + color: #757575 +} + +.container,.container-fluid,.container-lg,.container-md,.container-sm,.container-xl,.container-xxl { + --mdb-gutter-x: 1.5rem; + --mdb-gutter-y: 0; + width: 100%; + padding-right: calc(var(--mdb-gutter-x)*0.5); + padding-left: calc(var(--mdb-gutter-x)*0.5); + margin-right: auto; + margin-left: auto +} + +@media(min-width: 576px) { + .container,.container-sm { + max-width:540px + } +} + +@media(min-width: 768px) { + .container,.container-md,.container-sm { + max-width:720px + } +} + +@media(min-width: 992px) { + .container,.container-lg,.container-md,.container-sm { + max-width:960px + } +} + +@media(min-width: 1200px) { + .container,.container-lg,.container-md,.container-sm,.container-xl { + max-width:1140px + } +} + +@media(min-width: 1400px) { + .container,.container-lg,.container-md,.container-sm,.container-xl,.container-xxl { + max-width:1320px + } +} + +.row { + --mdb-gutter-x: 1.5rem; + --mdb-gutter-y: 0; + display: flex; + flex-wrap: wrap; + margin-top: calc(var(--mdb-gutter-y)*-1); + margin-right: calc(var(--mdb-gutter-x)*-0.5); + margin-left: calc(var(--mdb-gutter-x)*-0.5) +} + +.row>* { + flex-shrink: 0; + width: 100%; + max-width: 100%; + padding-right: calc(var(--mdb-gutter-x)*0.5); + padding-left: calc(var(--mdb-gutter-x)*0.5); + margin-top: var(--mdb-gutter-y) +} + +.col { + flex: 1 0 0% +} + +.row-cols-auto>* { + flex: 0 0 auto; + width: auto +} + +.row-cols-1>* { + flex: 0 0 auto; + width: 100% +} + +.row-cols-2>* { + flex: 0 0 auto; + width: 50% +} + +.row-cols-3>* { + flex: 0 0 auto; + width: 33.3333333333% +} + +.row-cols-4>* { + flex: 0 0 auto; + width: 25% +} + +.row-cols-5>* { + flex: 0 0 auto; + width: 20% +} + +.row-cols-6>* { + flex: 0 0 auto; + width: 16.6666666667% +} + +.col-auto { + flex: 0 0 auto; + width: auto +} + +.col-1 { + flex: 0 0 auto; + width: 8.33333333% +} + +.col-2 { + flex: 0 0 auto; + width: 16.66666667% +} + +.col-3 { + flex: 0 0 auto; + width: 25% +} + +.col-4 { + flex: 0 0 auto; + width: 33.33333333% +} + +.col-5 { + flex: 0 0 auto; + width: 41.66666667% +} + +.col-6 { + flex: 0 0 auto; + width: 50% +} + +.col-7 { + flex: 0 0 auto; + width: 58.33333333% +} + +.col-8 { + flex: 0 0 auto; + width: 66.66666667% +} + +.col-9 { + flex: 0 0 auto; + width: 75% +} + +.col-10 { + flex: 0 0 auto; + width: 83.33333333% +} + +.col-11 { + flex: 0 0 auto; + width: 91.66666667% +} + +.col-12 { + flex: 0 0 auto; + width: 100% +} + +.offset-1 { + margin-left: 8.33333333% +} + +.offset-2 { + margin-left: 16.66666667% +} + +.offset-3 { + margin-left: 25% +} + +.offset-4 { + margin-left: 33.33333333% +} + +.offset-5 { + margin-left: 41.66666667% +} + +.offset-6 { + margin-left: 50% +} + +.offset-7 { + margin-left: 58.33333333% +} + +.offset-8 { + margin-left: 66.66666667% +} + +.offset-9 { + margin-left: 75% +} + +.offset-10 { + margin-left: 83.33333333% +} + +.offset-11 { + margin-left: 91.66666667% +} + +.g-0,.gx-0 { + --mdb-gutter-x: 0 +} + +.g-0,.gy-0 { + --mdb-gutter-y: 0 +} + +.g-1,.gx-1 { + --mdb-gutter-x: 0.25rem +} + +.g-1,.gy-1 { + --mdb-gutter-y: 0.25rem +} + +.g-2,.gx-2 { + --mdb-gutter-x: 0.5rem +} + +.g-2,.gy-2 { + --mdb-gutter-y: 0.5rem +} + +.g-3,.gx-3 { + --mdb-gutter-x: 1rem +} + +.g-3,.gy-3 { + --mdb-gutter-y: 1rem +} + +.g-4,.gx-4 { + --mdb-gutter-x: 1.5rem +} + +.g-4,.gy-4 { + --mdb-gutter-y: 1.5rem +} + +.g-5,.gx-5 { + --mdb-gutter-x: 3rem +} + +.g-5,.gy-5 { + --mdb-gutter-y: 3rem +} + +@media(min-width: 576px) { + .col-sm { + flex:1 0 0% + } + + .row-cols-sm-auto>* { + flex: 0 0 auto; + width: auto + } + + .row-cols-sm-1>* { + flex: 0 0 auto; + width: 100% + } + + .row-cols-sm-2>* { + flex: 0 0 auto; + width: 50% + } + + .row-cols-sm-3>* { + flex: 0 0 auto; + width: 33.3333333333% + } + + .row-cols-sm-4>* { + flex: 0 0 auto; + width: 25% + } + + .row-cols-sm-5>* { + flex: 0 0 auto; + width: 20% + } + + .row-cols-sm-6>* { + flex: 0 0 auto; + width: 16.6666666667% + } + + .col-sm-auto { + flex: 0 0 auto; + width: auto + } + + .col-sm-1 { + flex: 0 0 auto; + width: 8.33333333% + } + + .col-sm-2 { + flex: 0 0 auto; + width: 16.66666667% + } + + .col-sm-3 { + flex: 0 0 auto; + width: 25% + } + + .col-sm-4 { + flex: 0 0 auto; + width: 33.33333333% + } + + .col-sm-5 { + flex: 0 0 auto; + width: 41.66666667% + } + + .col-sm-6 { + flex: 0 0 auto; + width: 50% + } + + .col-sm-7 { + flex: 0 0 auto; + width: 58.33333333% + } + + .col-sm-8 { + flex: 0 0 auto; + width: 66.66666667% + } + + .col-sm-9 { + flex: 0 0 auto; + width: 75% + } + + .col-sm-10 { + flex: 0 0 auto; + width: 83.33333333% + } + + .col-sm-11 { + flex: 0 0 auto; + width: 91.66666667% + } + + .col-sm-12 { + flex: 0 0 auto; + width: 100% + } + + .offset-sm-0 { + margin-left: 0 + } + + .offset-sm-1 { + margin-left: 8.33333333% + } + + .offset-sm-2 { + margin-left: 16.66666667% + } + + .offset-sm-3 { + margin-left: 25% + } + + .offset-sm-4 { + margin-left: 33.33333333% + } + + .offset-sm-5 { + margin-left: 41.66666667% + } + + .offset-sm-6 { + margin-left: 50% + } + + .offset-sm-7 { + margin-left: 58.33333333% + } + + .offset-sm-8 { + margin-left: 66.66666667% + } + + .offset-sm-9 { + margin-left: 75% + } + + .offset-sm-10 { + margin-left: 83.33333333% + } + + .offset-sm-11 { + margin-left: 91.66666667% + } + + .g-sm-0,.gx-sm-0 { + --mdb-gutter-x: 0 + } + + .g-sm-0,.gy-sm-0 { + --mdb-gutter-y: 0 + } + + .g-sm-1,.gx-sm-1 { + --mdb-gutter-x: 0.25rem + } + + .g-sm-1,.gy-sm-1 { + --mdb-gutter-y: 0.25rem + } + + .g-sm-2,.gx-sm-2 { + --mdb-gutter-x: 0.5rem + } + + .g-sm-2,.gy-sm-2 { + --mdb-gutter-y: 0.5rem + } + + .g-sm-3,.gx-sm-3 { + --mdb-gutter-x: 1rem + } + + .g-sm-3,.gy-sm-3 { + --mdb-gutter-y: 1rem + } + + .g-sm-4,.gx-sm-4 { + --mdb-gutter-x: 1.5rem + } + + .g-sm-4,.gy-sm-4 { + --mdb-gutter-y: 1.5rem + } + + .g-sm-5,.gx-sm-5 { + --mdb-gutter-x: 3rem + } + + .g-sm-5,.gy-sm-5 { + --mdb-gutter-y: 3rem + } +} + +@media(min-width: 768px) { + .col-md { + flex:1 0 0% + } + + .row-cols-md-auto>* { + flex: 0 0 auto; + width: auto + } + + .row-cols-md-1>* { + flex: 0 0 auto; + width: 100% + } + + .row-cols-md-2>* { + flex: 0 0 auto; + width: 50% + } + + .row-cols-md-3>* { + flex: 0 0 auto; + width: 33.3333333333% + } + + .row-cols-md-4>* { + flex: 0 0 auto; + width: 25% + } + + .row-cols-md-5>* { + flex: 0 0 auto; + width: 20% + } + + .row-cols-md-6>* { + flex: 0 0 auto; + width: 16.6666666667% + } + + .col-md-auto { + flex: 0 0 auto; + width: auto + } + + .col-md-1 { + flex: 0 0 auto; + width: 8.33333333% + } + + .col-md-2 { + flex: 0 0 auto; + width: 16.66666667% + } + + .col-md-3 { + flex: 0 0 auto; + width: 25% + } + + .col-md-4 { + flex: 0 0 auto; + width: 33.33333333% + } + + .col-md-5 { + flex: 0 0 auto; + width: 41.66666667% + } + + .col-md-6 { + flex: 0 0 auto; + width: 50% + } + + .col-md-7 { + flex: 0 0 auto; + width: 58.33333333% + } + + .col-md-8 { + flex: 0 0 auto; + width: 66.66666667% + } + + .col-md-9 { + flex: 0 0 auto; + width: 75% + } + + .col-md-10 { + flex: 0 0 auto; + width: 83.33333333% + } + + .col-md-11 { + flex: 0 0 auto; + width: 91.66666667% + } + + .col-md-12 { + flex: 0 0 auto; + width: 100% + } + + .offset-md-0 { + margin-left: 0 + } + + .offset-md-1 { + margin-left: 8.33333333% + } + + .offset-md-2 { + margin-left: 16.66666667% + } + + .offset-md-3 { + margin-left: 25% + } + + .offset-md-4 { + margin-left: 33.33333333% + } + + .offset-md-5 { + margin-left: 41.66666667% + } + + .offset-md-6 { + margin-left: 50% + } + + .offset-md-7 { + margin-left: 58.33333333% + } + + .offset-md-8 { + margin-left: 66.66666667% + } + + .offset-md-9 { + margin-left: 75% + } + + .offset-md-10 { + margin-left: 83.33333333% + } + + .offset-md-11 { + margin-left: 91.66666667% + } + + .g-md-0,.gx-md-0 { + --mdb-gutter-x: 0 + } + + .g-md-0,.gy-md-0 { + --mdb-gutter-y: 0 + } + + .g-md-1,.gx-md-1 { + --mdb-gutter-x: 0.25rem + } + + .g-md-1,.gy-md-1 { + --mdb-gutter-y: 0.25rem + } + + .g-md-2,.gx-md-2 { + --mdb-gutter-x: 0.5rem + } + + .g-md-2,.gy-md-2 { + --mdb-gutter-y: 0.5rem + } + + .g-md-3,.gx-md-3 { + --mdb-gutter-x: 1rem + } + + .g-md-3,.gy-md-3 { + --mdb-gutter-y: 1rem + } + + .g-md-4,.gx-md-4 { + --mdb-gutter-x: 1.5rem + } + + .g-md-4,.gy-md-4 { + --mdb-gutter-y: 1.5rem + } + + .g-md-5,.gx-md-5 { + --mdb-gutter-x: 3rem + } + + .g-md-5,.gy-md-5 { + --mdb-gutter-y: 3rem + } +} + +@media(min-width: 992px) { + .col-lg { + flex:1 0 0% + } + + .row-cols-lg-auto>* { + flex: 0 0 auto; + width: auto + } + + .row-cols-lg-1>* { + flex: 0 0 auto; + width: 100% + } + + .row-cols-lg-2>* { + flex: 0 0 auto; + width: 50% + } + + .row-cols-lg-3>* { + flex: 0 0 auto; + width: 33.3333333333% + } + + .row-cols-lg-4>* { + flex: 0 0 auto; + width: 25% + } + + .row-cols-lg-5>* { + flex: 0 0 auto; + width: 20% + } + + .row-cols-lg-6>* { + flex: 0 0 auto; + width: 16.6666666667% + } + + .col-lg-auto { + flex: 0 0 auto; + width: auto + } + + .col-lg-1 { + flex: 0 0 auto; + width: 8.33333333% + } + + .col-lg-2 { + flex: 0 0 auto; + width: 16.66666667% + } + + .col-lg-3 { + flex: 0 0 auto; + width: 25% + } + + .col-lg-4 { + flex: 0 0 auto; + width: 33.33333333% + } + + .col-lg-5 { + flex: 0 0 auto; + width: 41.66666667% + } + + .col-lg-6 { + flex: 0 0 auto; + width: 50% + } + + .col-lg-7 { + flex: 0 0 auto; + width: 58.33333333% + } + + .col-lg-8 { + flex: 0 0 auto; + width: 66.66666667% + } + + .col-lg-9 { + flex: 0 0 auto; + width: 75% + } + + .col-lg-10 { + flex: 0 0 auto; + width: 83.33333333% + } + + .col-lg-11 { + flex: 0 0 auto; + width: 91.66666667% + } + + .col-lg-12 { + flex: 0 0 auto; + width: 100% + } + + .offset-lg-0 { + margin-left: 0 + } + + .offset-lg-1 { + margin-left: 8.33333333% + } + + .offset-lg-2 { + margin-left: 16.66666667% + } + + .offset-lg-3 { + margin-left: 25% + } + + .offset-lg-4 { + margin-left: 33.33333333% + } + + .offset-lg-5 { + margin-left: 41.66666667% + } + + .offset-lg-6 { + margin-left: 50% + } + + .offset-lg-7 { + margin-left: 58.33333333% + } + + .offset-lg-8 { + margin-left: 66.66666667% + } + + .offset-lg-9 { + margin-left: 75% + } + + .offset-lg-10 { + margin-left: 83.33333333% + } + + .offset-lg-11 { + margin-left: 91.66666667% + } + + .g-lg-0,.gx-lg-0 { + --mdb-gutter-x: 0 + } + + .g-lg-0,.gy-lg-0 { + --mdb-gutter-y: 0 + } + + .g-lg-1,.gx-lg-1 { + --mdb-gutter-x: 0.25rem + } + + .g-lg-1,.gy-lg-1 { + --mdb-gutter-y: 0.25rem + } + + .g-lg-2,.gx-lg-2 { + --mdb-gutter-x: 0.5rem + } + + .g-lg-2,.gy-lg-2 { + --mdb-gutter-y: 0.5rem + } + + .g-lg-3,.gx-lg-3 { + --mdb-gutter-x: 1rem + } + + .g-lg-3,.gy-lg-3 { + --mdb-gutter-y: 1rem + } + + .g-lg-4,.gx-lg-4 { + --mdb-gutter-x: 1.5rem + } + + .g-lg-4,.gy-lg-4 { + --mdb-gutter-y: 1.5rem + } + + .g-lg-5,.gx-lg-5 { + --mdb-gutter-x: 3rem + } + + .g-lg-5,.gy-lg-5 { + --mdb-gutter-y: 3rem + } +} + +@media(min-width: 1200px) { + .col-xl { + flex:1 0 0% + } + + .row-cols-xl-auto>* { + flex: 0 0 auto; + width: auto + } + + .row-cols-xl-1>* { + flex: 0 0 auto; + width: 100% + } + + .row-cols-xl-2>* { + flex: 0 0 auto; + width: 50% + } + + .row-cols-xl-3>* { + flex: 0 0 auto; + width: 33.3333333333% + } + + .row-cols-xl-4>* { + flex: 0 0 auto; + width: 25% + } + + .row-cols-xl-5>* { + flex: 0 0 auto; + width: 20% + } + + .row-cols-xl-6>* { + flex: 0 0 auto; + width: 16.6666666667% + } + + .col-xl-auto { + flex: 0 0 auto; + width: auto + } + + .col-xl-1 { + flex: 0 0 auto; + width: 8.33333333% + } + + .col-xl-2 { + flex: 0 0 auto; + width: 16.66666667% + } + + .col-xl-3 { + flex: 0 0 auto; + width: 25% + } + + .col-xl-4 { + flex: 0 0 auto; + width: 33.33333333% + } + + .col-xl-5 { + flex: 0 0 auto; + width: 41.66666667% + } + + .col-xl-6 { + flex: 0 0 auto; + width: 50% + } + + .col-xl-7 { + flex: 0 0 auto; + width: 58.33333333% + } + + .col-xl-8 { + flex: 0 0 auto; + width: 66.66666667% + } + + .col-xl-9 { + flex: 0 0 auto; + width: 75% + } + + .col-xl-10 { + flex: 0 0 auto; + width: 83.33333333% + } + + .col-xl-11 { + flex: 0 0 auto; + width: 91.66666667% + } + + .col-xl-12 { + flex: 0 0 auto; + width: 100% + } + + .offset-xl-0 { + margin-left: 0 + } + + .offset-xl-1 { + margin-left: 8.33333333% + } + + .offset-xl-2 { + margin-left: 16.66666667% + } + + .offset-xl-3 { + margin-left: 25% + } + + .offset-xl-4 { + margin-left: 33.33333333% + } + + .offset-xl-5 { + margin-left: 41.66666667% + } + + .offset-xl-6 { + margin-left: 50% + } + + .offset-xl-7 { + margin-left: 58.33333333% + } + + .offset-xl-8 { + margin-left: 66.66666667% + } + + .offset-xl-9 { + margin-left: 75% + } + + .offset-xl-10 { + margin-left: 83.33333333% + } + + .offset-xl-11 { + margin-left: 91.66666667% + } + + .g-xl-0,.gx-xl-0 { + --mdb-gutter-x: 0 + } + + .g-xl-0,.gy-xl-0 { + --mdb-gutter-y: 0 + } + + .g-xl-1,.gx-xl-1 { + --mdb-gutter-x: 0.25rem + } + + .g-xl-1,.gy-xl-1 { + --mdb-gutter-y: 0.25rem + } + + .g-xl-2,.gx-xl-2 { + --mdb-gutter-x: 0.5rem + } + + .g-xl-2,.gy-xl-2 { + --mdb-gutter-y: 0.5rem + } + + .g-xl-3,.gx-xl-3 { + --mdb-gutter-x: 1rem + } + + .g-xl-3,.gy-xl-3 { + --mdb-gutter-y: 1rem + } + + .g-xl-4,.gx-xl-4 { + --mdb-gutter-x: 1.5rem + } + + .g-xl-4,.gy-xl-4 { + --mdb-gutter-y: 1.5rem + } + + .g-xl-5,.gx-xl-5 { + --mdb-gutter-x: 3rem + } + + .g-xl-5,.gy-xl-5 { + --mdb-gutter-y: 3rem + } +} + +@media(min-width: 1400px) { + .col-xxl { + flex:1 0 0% + } + + .row-cols-xxl-auto>* { + flex: 0 0 auto; + width: auto + } + + .row-cols-xxl-1>* { + flex: 0 0 auto; + width: 100% + } + + .row-cols-xxl-2>* { + flex: 0 0 auto; + width: 50% + } + + .row-cols-xxl-3>* { + flex: 0 0 auto; + width: 33.3333333333% + } + + .row-cols-xxl-4>* { + flex: 0 0 auto; + width: 25% + } + + .row-cols-xxl-5>* { + flex: 0 0 auto; + width: 20% + } + + .row-cols-xxl-6>* { + flex: 0 0 auto; + width: 16.6666666667% + } + + .col-xxl-auto { + flex: 0 0 auto; + width: auto + } + + .col-xxl-1 { + flex: 0 0 auto; + width: 8.33333333% + } + + .col-xxl-2 { + flex: 0 0 auto; + width: 16.66666667% + } + + .col-xxl-3 { + flex: 0 0 auto; + width: 25% + } + + .col-xxl-4 { + flex: 0 0 auto; + width: 33.33333333% + } + + .col-xxl-5 { + flex: 0 0 auto; + width: 41.66666667% + } + + .col-xxl-6 { + flex: 0 0 auto; + width: 50% + } + + .col-xxl-7 { + flex: 0 0 auto; + width: 58.33333333% + } + + .col-xxl-8 { + flex: 0 0 auto; + width: 66.66666667% + } + + .col-xxl-9 { + flex: 0 0 auto; + width: 75% + } + + .col-xxl-10 { + flex: 0 0 auto; + width: 83.33333333% + } + + .col-xxl-11 { + flex: 0 0 auto; + width: 91.66666667% + } + + .col-xxl-12 { + flex: 0 0 auto; + width: 100% + } + + .offset-xxl-0 { + margin-left: 0 + } + + .offset-xxl-1 { + margin-left: 8.33333333% + } + + .offset-xxl-2 { + margin-left: 16.66666667% + } + + .offset-xxl-3 { + margin-left: 25% + } + + .offset-xxl-4 { + margin-left: 33.33333333% + } + + .offset-xxl-5 { + margin-left: 41.66666667% + } + + .offset-xxl-6 { + margin-left: 50% + } + + .offset-xxl-7 { + margin-left: 58.33333333% + } + + .offset-xxl-8 { + margin-left: 66.66666667% + } + + .offset-xxl-9 { + margin-left: 75% + } + + .offset-xxl-10 { + margin-left: 83.33333333% + } + + .offset-xxl-11 { + margin-left: 91.66666667% + } + + .g-xxl-0,.gx-xxl-0 { + --mdb-gutter-x: 0 + } + + .g-xxl-0,.gy-xxl-0 { + --mdb-gutter-y: 0 + } + + .g-xxl-1,.gx-xxl-1 { + --mdb-gutter-x: 0.25rem + } + + .g-xxl-1,.gy-xxl-1 { + --mdb-gutter-y: 0.25rem + } + + .g-xxl-2,.gx-xxl-2 { + --mdb-gutter-x: 0.5rem + } + + .g-xxl-2,.gy-xxl-2 { + --mdb-gutter-y: 0.5rem + } + + .g-xxl-3,.gx-xxl-3 { + --mdb-gutter-x: 1rem + } + + .g-xxl-3,.gy-xxl-3 { + --mdb-gutter-y: 1rem + } + + .g-xxl-4,.gx-xxl-4 { + --mdb-gutter-x: 1.5rem + } + + .g-xxl-4,.gy-xxl-4 { + --mdb-gutter-y: 1.5rem + } + + .g-xxl-5,.gx-xxl-5 { + --mdb-gutter-x: 3rem + } + + .g-xxl-5,.gy-xxl-5 { + --mdb-gutter-y: 3rem + } +} + +.table { + --mdb-table-color: var(--mdb-body-color); + --mdb-table-bg: transparent; + --mdb-table-border-color: var(--mdb-border-color); + --mdb-table-accent-bg: transparent; + --mdb-table-striped-color: var(--mdb-body-color); + --mdb-table-striped-bg: rgba(0,0,0,0.02); + --mdb-table-active-color: var(--mdb-body-color); + --mdb-table-active-bg: rgba(0,0,0,0.1); + --mdb-table-hover-color: var(--mdb-body-color); + --mdb-table-hover-bg: rgba(0,0,0,0.025); + width: 100%; + margin-bottom: 1rem; + color: var(--mdb-table-color); + vertical-align: top; + border-color: var(--mdb-table-border-color) +} + +.table>:not(caption)>*>* { + padding: 1rem 1.4rem; + background-color: var(--mdb-table-bg); + border-bottom-width: 1px; + box-shadow: inset 0 0 0 9999px var(--mdb-table-accent-bg) +} + +.table>tbody { + vertical-align: inherit +} + +.table>thead { + vertical-align: bottom +} + +.table-group-divider { + border-top: 2px solid inherit +} + +.caption-top { + caption-side: top +} + +.table-sm>:not(caption)>*>* { + padding: .5rem +} + +.table-bordered>:not(caption)>* { + border-width: 1px 0 +} + +.table-bordered>:not(caption)>*>* { + border-width: 0 1px +} + +.table-borderless>:not(caption)>*>* { + border-bottom-width: 0 +} + +.table-borderless>:not(:first-child) { + border-top-width: 0 +} + +.table-striped-columns>:not(caption)>tr>:nth-child(2n),.table-striped>tbody>tr:nth-of-type(odd)>* { + --mdb-table-accent-bg: var(--mdb-table-striped-bg); + color: var(--mdb-table-striped-color) +} + +.table-active { + --mdb-table-accent-bg: var(--mdb-table-active-bg); + color: var(--mdb-table-active-color) +} + +.table-hover>tbody>tr:hover>* { + --mdb-table-accent-bg: var(--mdb-table-hover-bg); + color: var(--mdb-table-hover-color) +} + +.table-responsive { + overflow-x: auto; + -webkit-overflow-scrolling: touch +} + +@media(max-width: 575.98px) { + .table-responsive-sm { + overflow-x:auto; + -webkit-overflow-scrolling: touch + } +} + +@media(max-width: 767.98px) { + .table-responsive-md { + overflow-x:auto; + -webkit-overflow-scrolling: touch + } +} + +@media(max-width: 991.98px) { + .table-responsive-lg { + overflow-x:auto; + -webkit-overflow-scrolling: touch + } +} + +@media(max-width: 1199.98px) { + .table-responsive-xl { + overflow-x:auto; + -webkit-overflow-scrolling: touch + } +} + +@media(max-width: 1399.98px) { + .table-responsive-xxl { + overflow-x:auto; + -webkit-overflow-scrolling: touch + } +} + +.form-label { + margin-bottom: .5rem; + color: rgba(0,0,0,.6) +} + +.col-form-label { + padding-top: calc(.375rem + 1px); + padding-bottom: calc(.375rem + 1px); + margin-bottom: 0; + font-size: inherit; + line-height: 1.6; + color: rgba(0,0,0,.6) +} + +.col-form-label-lg { + padding-top: calc(.5rem + 1px); + padding-bottom: calc(.5rem + 1px); + font-size: 1rem +} + +.col-form-label-sm { + padding-top: calc(.25rem + 1px); + padding-bottom: calc(.25rem + 1px); + font-size: .775rem +} + +.form-text { + margin-top: .25rem; + font-size: .875em; + color: #757575 +} + +.form-control { + display: block; + width: 100%; + padding: .375rem .75rem; + font-size: 1rem; + font-weight: 400; + line-height: 1.6; + color: #4f4f4f; + background-color: #fff; + background-clip: padding-box; + border: 1px solid #bdbdbd; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + border-radius: .25rem; + box-shadow: inset 0 1px 2px rgba(0,0,0,.075); + transition: all .2s linear +} + +@media(prefers-reduced-motion:reduce) { + .form-control { + transition: none + } +} + +.form-control[type=file] { + overflow: hidden +} + +.form-control[type=file]:not(:disabled):not([readonly]) { + cursor: pointer +} + +.form-control:focus { + color: #4f4f4f; + background-color: #fff; + outline: 0; + box-shadow: inset 0 1px 2px rgba(0,0,0,.075),0 0 0 .25rem rgba(59,113,202,.25) +} + +.form-control::-webkit-date-and-time-value { + height: 1.6em +} + +.form-control::-moz-placeholder { + color: #757575; + opacity: 1 +} + +.form-control::placeholder { + color: #757575; + opacity: 1 +} + +.form-control:disabled { + background-color: #eee; + opacity: 1 +} + +.form-control::file-selector-button { + padding: .375rem .75rem; + margin: -.375rem -.75rem; + -webkit-margin-end: .75rem; + margin-inline-end:.75rem;color: #4f4f4f; + background-color: #eee; + pointer-events: none; + border: 0 solid; + border-color: inherit; + border-inline-end-width:1px;border-radius: 0; + transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out +} + +@media(prefers-reduced-motion:reduce) { + .form-control::file-selector-button { + transition: none + } +} + +.form-control:hover:not(:disabled):not([readonly])::file-selector-button { + background-color: #e2e2e2 +} + +.form-control-plaintext { + display: block; + width: 100%; + padding: .375rem 0; + margin-bottom: 0; + line-height: 1.6; + color: #4f4f4f; + background-color: transparent; + border: solid transparent; + border-width: 1px 0 +} + +.form-control-plaintext:focus { + outline: 0 +} + +.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm { + padding-right: 0; + padding-left: 0 +} + +.form-control-sm { + min-height: calc(1.6em + .5rem + 2px); + padding: .25rem .5rem; + font-size: .775rem; + border-radius: .25rem +} + +.form-control-sm::file-selector-button { + padding: .25rem .5rem; + margin: -.25rem -.5rem; + -webkit-margin-end: .5rem; + margin-inline-end:.5rem} + +.form-control-lg { + min-height: calc(1.6em + 1rem + 2px); + padding: .5rem 1rem; + font-size: 1rem; + border-radius: .5rem +} + +.form-control-lg::file-selector-button { + padding: .5rem 1rem; + margin: -.5rem -1rem; + -webkit-margin-end: 1rem; + margin-inline-end:1rem} + +textarea.form-control { + min-height: calc(1.6em + .75rem + 2px) +} + +textarea.form-control-sm { + min-height: calc(1.6em + .5rem + 2px) +} + +textarea.form-control-lg { + min-height: calc(1.6em + 1rem + 2px) +} + +.form-control-color { + width: 3rem; + height: calc(1.6em + .75rem + 2px); + padding: .375rem +} + +.form-control-color:not(:disabled):not([readonly]) { + cursor: pointer +} + +.form-control-color::-moz-color-swatch { + border: 0!important; + border-radius: .25rem +} + +.form-control-color::-webkit-color-swatch { + border-radius: .25rem +} + +.form-control-color.form-control-sm { + height: calc(1.6em + .5rem + 2px) +} + +.form-control-color.form-control-lg { + height: calc(1.6em + 1rem + 2px) +} + +.form-select { + display: block; + width: 100%; + padding: .375rem 2.25rem .375rem .75rem; + -moz-padding-start: calc(.75rem - 3px); + font-size: 1rem; + font-weight: 400; + line-height: 1.6; + color: #4f4f4f; + background-color: #fff; + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%234f4f4f' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3E%3C/svg%3E"); + background-repeat: no-repeat; + background-position: right .75rem center; + background-size: 16px 12px; + border: 1px solid #bdbdbd; + border-radius: .25rem; + box-shadow: inset 0 1px 2px rgba(0,0,0,.075); + -webkit-appearance: none; + -moz-appearance: none; + appearance: none +} + +@media(prefers-reduced-motion:reduce) { + .form-select { + transition: none + } +} + +.form-select:focus { + box-shadow: inset 0 1px 2px rgba(0,0,0,.075),0 0 0 .25rem rgba(59,113,202,.25) +} + +.form-select[multiple],.form-select[size]:not([size="1"]) { + padding-right: .75rem; + background-image: none +} + +.form-select:disabled { + background-color: #eee +} + +.form-select:-moz-focusring { + color: transparent; + text-shadow: 0 0 0 #4f4f4f +} + +.form-select-sm { + padding-top: .25rem; + padding-bottom: .25rem; + padding-left: .5rem; + font-size: .775rem; + border-radius: .25rem +} + +.form-select-lg { + padding-top: .5rem; + padding-bottom: .5rem; + padding-left: 1rem; + font-size: 1rem; + border-radius: .5rem +} + +.form-check { + display: block; + min-height: 1.6rem; + padding-left: 1.5em; + margin-bottom: .125rem +} + +.form-check .form-check-input { + float: left; + margin-left: -1.5em +} + +.form-check-reverse { + padding-right: 1.5em; + padding-left: 0; + text-align: right +} + +.form-check-reverse .form-check-input { + float: right; + margin-right: -1.5em; + margin-left: 0 +} + +.form-check-input { + width: 1em; + height: 1em; + margin-top: .3em; + vertical-align: top; + background-repeat: no-repeat; + background-position: 50%; + background-size: contain; + border: 1px solid rgba(0,0,0,.25); + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + print-color-adjust: exact +} + +.form-check-input[type=checkbox] { + border-radius: .25em +} + +.form-check-input:active { + filter: brightness(90%) +} + +.form-check-input:focus { + border-color: #3b71ca; + outline: 0; + box-shadow: 0 0 0 .25rem rgba(59,113,202,.25) +} + +.form-check-input:checked { + background-color: #3b71ca +} + +.form-check-input:checked[type=checkbox] { + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10l3 3 6-6'/%3E%3C/svg%3E") +} + +.form-check-input:checked[type=radio] { + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='2' fill='%23fff'/%3E%3C/svg%3E") +} + +.form-check-input[type=checkbox]:indeterminate { + background-color: #3b71ca; + border-color: #757575; + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3E%3C/svg%3E") +} + +.form-check-input:disabled { + pointer-events: none; + filter: none; + opacity: .5 +} + +.form-check-input:disabled~.form-check-label,.form-check-input[disabled]~.form-check-label { + cursor: default; + opacity: .5 +} + +.form-switch { + padding-left: 2.5em +} + +.form-switch .form-check-input { + width: 2em; + margin-left: -2.5em; + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='rgba(0, 0, 0, 0.25)'/%3E%3C/svg%3E"); + background-position: 0; + border-radius: 2em; + transition: background-position .15s ease-in-out +} + +@media(prefers-reduced-motion:reduce) { + .form-switch .form-check-input { + transition: none + } +} + +.form-switch .form-check-input:focus { + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%233b71ca'/%3E%3C/svg%3E") +} + +.form-switch .form-check-input:checked { + background-position: 100%; + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E") +} + +.form-switch.form-check-reverse { + padding-right: 2.5em; + padding-left: 0 +} + +.form-switch.form-check-reverse .form-check-input { + margin-right: -2.5em; + margin-left: 0 +} + +.form-check-inline { + display: inline-block; + margin-right: 1rem +} + +.btn-check { + position: absolute; + clip: rect(0,0,0,0); + pointer-events: none +} + +.btn-check:disabled+.btn,.btn-check[disabled]+.btn { + pointer-events: none; + filter: none; + opacity: .65 +} + +.form-range { + width: 100%; + height: 1.5rem; + padding: 0; + background-color: transparent; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none +} + +.form-range:focus { + outline: 0 +} + +.form-range:focus::-webkit-slider-thumb { + box-shadow: 0 0 0 1px #fff,0 0 0 .25rem rgba(59,113,202,.25) +} + +.form-range:focus::-moz-range-thumb { + box-shadow: 0 0 0 1px #fff,0 0 0 .25rem rgba(59,113,202,.25) +} + +.form-range::-webkit-slider-thumb { + width: 1rem; + height: 1rem; + margin-top: -.25rem; + background-color: #3b71ca; + border: 0; + border-radius: 1rem; + box-shadow: 0 .1rem .25rem rgba(0,0,0,.1); + -webkit-transition: background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out; + transition: background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out +} + +@media(prefers-reduced-motion:reduce) { + .form-range::-webkit-slider-thumb { + -webkit-transition: none; + transition: none + } +} + +.form-range::-webkit-slider-thumb:active { + background-color: #c4d4ef +} + +.form-range::-webkit-slider-runnable-track { + width: 100%; + height: .5rem; + color: transparent; + cursor: pointer; + background-color: #e0e0e0; + border-color: transparent; + border-radius: 1rem; + box-shadow: inset 0 1px 2px rgba(0,0,0,.075) +} + +.form-range::-moz-range-thumb { + width: 1rem; + height: 1rem; + background-color: #3b71ca; + border: 0; + border-radius: 1rem; + box-shadow: 0 .1rem .25rem rgba(0,0,0,.1); + -moz-transition: background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out; + transition: background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out +} + +@media(prefers-reduced-motion:reduce) { + .form-range::-moz-range-thumb { + -moz-transition: none; + transition: none + } +} + +.form-range::-moz-range-thumb:active { + background-color: #c4d4ef +} + +.form-range::-moz-range-track { + width: 100%; + height: .5rem; + color: transparent; + cursor: pointer; + background-color: #e0e0e0; + border-color: transparent; + border-radius: 1rem; + box-shadow: inset 0 1px 2px rgba(0,0,0,.075) +} + +.form-range:disabled { + pointer-events: none +} + +.form-range:disabled::-webkit-slider-thumb { + background-color: #9e9e9e +} + +.form-range:disabled::-moz-range-thumb { + background-color: #9e9e9e +} + +.form-floating { + position: relative +} + +.form-floating>.form-control,.form-floating>.form-control-plaintext,.form-floating>.form-select { + height: calc(3.5rem + 2px); + line-height: 1.25 +} + +.form-floating>label { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + padding: 1rem .75rem; + overflow: hidden; + text-align: start; + text-overflow: ellipsis; + white-space: nowrap; + pointer-events: none; + border: 1px solid transparent; + transform-origin: 0 0; + transition: opacity .1s ease-in-out,transform .1s ease-in-out +} + +@media(prefers-reduced-motion:reduce) { + .form-floating>label { + transition: none + } +} + +.form-floating>.form-control,.form-floating>.form-control-plaintext { + padding: 1rem .75rem +} + +.form-floating>.form-control-plaintext::-moz-placeholder,.form-floating>.form-control::-moz-placeholder { + color: transparent +} + +.form-floating>.form-control-plaintext::placeholder,.form-floating>.form-control::placeholder { + color: transparent +} + +.form-floating>.form-control-plaintext:not(:-moz-placeholder-shown),.form-floating>.form-control:not(:-moz-placeholder-shown) { + padding-top: 1.625rem; + padding-bottom: .625rem +} + +.form-floating>.form-control-plaintext:focus,.form-floating>.form-control-plaintext:not(:placeholder-shown),.form-floating>.form-control:focus,.form-floating>.form-control:not(:placeholder-shown) { + padding-top: 1.625rem; + padding-bottom: .625rem +} + +.form-floating>.form-control-plaintext:-webkit-autofill,.form-floating>.form-control:-webkit-autofill { + padding-top: 1.625rem; + padding-bottom: .625rem +} + +.form-floating>.form-select { + padding-top: 1.625rem; + padding-bottom: .625rem +} + +.form-floating>.form-control:not(:-moz-placeholder-shown)~label { + opacity: .65; + transform: scale(.85) translateY(-.5rem) translateX(.15rem) +} + +.form-floating>.form-control-plaintext~label,.form-floating>.form-control:focus~label,.form-floating>.form-control:not(:placeholder-shown)~label,.form-floating>.form-select~label { + opacity: .65; + transform: scale(.85) translateY(-.5rem) translateX(.15rem) +} + +.form-floating>.form-control:-webkit-autofill~label { + opacity: .65; + transform: scale(.85) translateY(-.5rem) translateX(.15rem) +} + +.form-floating>.form-control-plaintext~label { + border-width: 1px 0 +} + +.input-group { + position: relative; + display: flex; + flex-wrap: wrap; + align-items: stretch; + width: 100% +} + +.input-group>.form-control,.input-group>.form-floating,.input-group>.form-select { + position: relative; + flex: 1 1 auto; + width: 1%; + min-width: 0 +} + +.input-group>.form-control:focus,.input-group>.form-floating:focus-within,.input-group>.form-select:focus { + z-index: 5 +} + +.input-group .btn { + position: relative; + z-index: 2 +} + +.input-group .btn:focus { + z-index: 5 +} + +.input-group-text { + display: flex; + align-items: center; + padding: .375rem .75rem; + font-size: 1rem; + font-weight: 400; + line-height: 1.6; + color: #4f4f4f; + text-align: center; + white-space: nowrap; + background-color: #eee; + border: 1px solid #bdbdbd; + border-radius: .25rem +} + +.input-group-lg>.btn,.input-group-lg>.form-control,.input-group-lg>.form-select,.input-group-lg>.input-group-text { + padding: .5rem 1rem; + font-size: 1rem; + border-radius: .5rem +} + +.input-group-sm>.btn,.input-group-sm>.form-control,.input-group-sm>.form-select,.input-group-sm>.input-group-text { + padding: .25rem .5rem; + font-size: .775rem; + border-radius: .25rem +} + +.input-group-lg>.form-select,.input-group-sm>.form-select { + padding-right: 3rem +} + +.input-group.has-validation>.dropdown-toggle:nth-last-child(n+4),.input-group.has-validation>.form-floating:nth-last-child(n+3)>.form-control,.input-group.has-validation>.form-floating:nth-last-child(n+3)>.form-select,.input-group.has-validation>:nth-last-child(n+3):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating),.input-group:not(.has-validation)>.dropdown-toggle:nth-last-child(n+3),.input-group:not(.has-validation)>.form-floating:not(:last-child)>.form-control,.input-group:not(.has-validation)>.form-floating:not(:last-child)>.form-select,.input-group:not(.has-validation)>:not(:last-child):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating) { + border-top-right-radius: 0; + border-bottom-right-radius: 0 +} + +.input-group>:not(:first-child):not(.dropdown-menu):not(.valid-tooltip):not(.valid-feedback):not(.invalid-tooltip):not(.invalid-feedback) { + margin-left: -1px; + border-top-left-radius: 0; + border-bottom-left-radius: 0 +} + +.input-group>.form-floating:not(:first-child)>.form-control,.input-group>.form-floating:not(:first-child)>.form-select { + border-top-left-radius: 0; + border-bottom-left-radius: 0 +} + +.valid-feedback { + width: 100%; + margin-top: .25rem; + font-size: .875em +} + +.valid-tooltip { + color: #000; + border-radius: .25rem +} + +.form-control.is-valid,.was-validated .form-control:valid { + padding-right: calc(1.6em + .75rem); + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%2314a44d' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3E%3C/svg%3E"); + background-repeat: no-repeat; + background-position: right calc(.4em + .1875rem) center; + background-size: calc(.8em + .375rem) calc(.8em + .375rem) +} + +.was-validated textarea.form-control:valid,textarea.form-control.is-valid { + padding-right: calc(1.6em + .75rem); + background-position: top calc(.4em + .1875rem) right calc(.4em + .1875rem) +} + +.form-select.is-valid:not([multiple]):not([size]),.form-select.is-valid:not([multiple])[size="1"],.was-validated .form-select:valid:not([multiple]):not([size]),.was-validated .form-select:valid:not([multiple])[size="1"] { + padding-right: 4.125rem; + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%234f4f4f' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3E%3C/svg%3E"),url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%2314a44d' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3E%3C/svg%3E"); + background-position: right .75rem center,center right 2.25rem; + background-size: 16px 12px,calc(.8em + .375rem) calc(.8em + .375rem) +} + +.form-control-color.is-valid,.was-validated .form-control-color:valid { + width: calc(3.75rem + 1.6em) +} + +.form-check-input.is-valid:focus,.was-validated .form-check-input:valid:focus { + box-shadow: 0 0 0 .25rem rgba(20,164,77,.25) +} + +.input-group>.form-control:not(:focus).is-valid,.input-group>.form-floating:not(:focus-within).is-valid,.input-group>.form-select:not(:focus).is-valid,.was-validated .input-group>.form-control:not(:focus):valid,.was-validated .input-group>.form-floating:not(:focus-within):valid,.was-validated .input-group>.form-select:not(:focus):valid { + z-index: 3 +} + +.invalid-feedback { + width: 100%; + margin-top: .25rem; + font-size: .875em +} + +.invalid-tooltip { + color: #000; + border-radius: .25rem +} + +.form-control.is-invalid,.was-validated .form-control:invalid { + padding-right: calc(1.6em + .75rem); + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc4c64'%3E%3Ccircle cx='6' cy='6' r='4.5'/%3E%3Cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3E%3Ccircle cx='6' cy='8.2' r='.6' fill='%23dc4c64' stroke='none'/%3E%3C/svg%3E"); + background-repeat: no-repeat; + background-position: right calc(.4em + .1875rem) center; + background-size: calc(.8em + .375rem) calc(.8em + .375rem) +} + +.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid { + padding-right: calc(1.6em + .75rem); + background-position: top calc(.4em + .1875rem) right calc(.4em + .1875rem) +} + +.form-select.is-invalid:not([multiple]):not([size]),.form-select.is-invalid:not([multiple])[size="1"],.was-validated .form-select:invalid:not([multiple]):not([size]),.was-validated .form-select:invalid:not([multiple])[size="1"] { + padding-right: 4.125rem; + background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%234f4f4f' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3E%3C/svg%3E"),url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc4c64'%3E%3Ccircle cx='6' cy='6' r='4.5'/%3E%3Cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3E%3Ccircle cx='6' cy='8.2' r='.6' fill='%23dc4c64' stroke='none'/%3E%3C/svg%3E"); + background-position: right .75rem center,center right 2.25rem; + background-size: 16px 12px,calc(.8em + .375rem) calc(.8em + .375rem) +} + +.form-control-color.is-invalid,.was-validated .form-control-color:invalid { + width: calc(3.75rem + 1.6em) +} + +.form-check-input.is-invalid:focus,.was-validated .form-check-input:invalid:focus { + box-shadow: 0 0 0 .25rem rgba(220,76,100,.25) +} + +.input-group>.form-control:not(:focus).is-invalid,.input-group>.form-floating:not(:focus-within).is-invalid,.input-group>.form-select:not(:focus).is-invalid,.was-validated .input-group>.form-control:not(:focus):invalid,.was-validated .input-group>.form-floating:not(:focus-within):invalid,.was-validated .input-group>.form-select:not(:focus):invalid { + z-index: 4 +} + +.btn { + --mdb-btn-padding-x: 1.5rem; + --mdb-btn-padding-y: 0.375rem; + --mdb-btn-font-size: 0.75rem; + --mdb-btn-font-weight: 500; + --mdb-btn-line-height: 1.5; + --mdb-btn-color: #4f4f4f; + --mdb-btn-bg: transparent; + --mdb-btn-border-width: 2px; + --mdb-btn-border-color: transparent; + --mdb-btn-hover-border-color: transparent; + --mdb-btn-disabled-opacity: 0.65; + --mdb-btn-focus-box-shadow: 0 0 0 0.25rem rgba(var(--mdb-btn-focus-shadow-rgb),0.5); + display: inline-block; + padding: var(--mdb-btn-padding-y) var(--mdb-btn-padding-x); + font-family: var(--mdb-btn-font-family); + font-size: var(--mdb-btn-font-size); + font-weight: var(--mdb-btn-font-weight); + line-height: var(--mdb-btn-line-height); + color: var(--mdb-btn-color); + text-align: center; + vertical-align: middle; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + border: var(--mdb-btn-border-width) solid var(--mdb-btn-border-color); + background-color: var(--mdb-btn-bg); + transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out +} + +@media(prefers-reduced-motion:reduce) { + .btn { + transition: none + } +} + +.btn:hover { + color: var(--mdb-btn-hover-color); + background-color: var(--mdb-btn-hover-bg); + border-color: var(--mdb-btn-hover-border-color) +} + +.btn-check+.btn:hover { + color: var(--mdb-btn-color); + background-color: var(--mdb-btn-bg); + border-color: var(--mdb-btn-border-color) +} + +.btn:focus-visible { + color: var(--mdb-btn-hover-color); + background-color: var(--mdb-btn-hover-bg) +} + +.btn-check:focus-visible+.btn,.btn:focus-visible { + border-color: var(--mdb-btn-hover-border-color); + outline: 0; + box-shadow: var(--mdb-btn-box-shadow),var(--mdb-btn-focus-box-shadow) +} + +.btn-check:checked+.btn,.btn.active,.btn.show,.btn:first-child:active,:not(.btn-check)+.btn:active { + color: var(--mdb-btn-active-color); + background-color: var(--mdb-btn-active-bg); + border-color: var(--mdb-btn-active-border-color); + box-shadow: var(--mdb-btn-active-shadow) +} + +.btn-check:checked+.btn:focus-visible,.btn.active:focus-visible,.btn.show:focus-visible,.btn:first-child:active:focus-visible,:not(.btn-check)+.btn:active:focus-visible { + box-shadow: var(--mdb-btn-active-shadow),var(--mdb-btn-focus-box-shadow) +} + +.btn.disabled,.btn:disabled,fieldset:disabled .btn { + color: var(--mdb-btn-disabled-color); + pointer-events: none; + background-color: var(--mdb-btn-disabled-bg); + border-color: var(--mdb-btn-disabled-border-color); + opacity: var(--mdb-btn-disabled-opacity); + box-shadow: none +} + +.btn-primary { + --mdb-btn-border-color: #3b71ca; + --mdb-btn-hover-border-color: #2f5aa2; + --mdb-btn-focus-shadow-rgb: 88,134,210; + --mdb-btn-active-border-color: #2c5598; + --mdb-btn-active-shadow: 0 8px 9px -4px rgba(0,0,0,0.15),0 4px 18px 0 rgba(0,0,0,0.1); + --mdb-btn-disabled-color: #fff; + --mdb-btn-disabled-bg: #3b71ca; + --mdb-btn-disabled-border-color: #3b71ca +} + +.btn-secondary { + --mdb-btn-color: #000; + --mdb-btn-bg: #9fa6b2; + --mdb-btn-border-color: #9fa6b2; + --mdb-btn-hover-color: #000; + --mdb-btn-hover-bg: #adb3be; + --mdb-btn-hover-border-color: #a9afba; + --mdb-btn-focus-shadow-rgb: 135,141,151; + --mdb-btn-active-color: #000; + --mdb-btn-active-bg: #b2b8c1; + --mdb-btn-active-border-color: #a9afba; + --mdb-btn-active-shadow: 0 8px 9px -4px rgba(0,0,0,0.15),0 4px 18px 0 rgba(0,0,0,0.1); + --mdb-btn-disabled-color: #000; + --mdb-btn-disabled-bg: #9fa6b2; + --mdb-btn-disabled-border-color: #9fa6b2 +} + +.btn-success { + --mdb-btn-color: #000; + --mdb-btn-border-color: #14a44d; + --mdb-btn-hover-color: #000; + --mdb-btn-hover-bg: #37b268; + --mdb-btn-hover-border-color: #2cad5f; + --mdb-btn-focus-shadow-rgb: 17,139,65; + --mdb-btn-active-color: #000; + --mdb-btn-active-bg: #43b671; + --mdb-btn-active-border-color: #2cad5f; + --mdb-btn-active-shadow: 0 8px 9px -4px rgba(0,0,0,0.15),0 4px 18px 0 rgba(0,0,0,0.1); + --mdb-btn-disabled-color: #000; + --mdb-btn-disabled-bg: #14a44d; + --mdb-btn-disabled-border-color: #14a44d +} + +.btn-danger { + --mdb-btn-color: #000; + --mdb-btn-border-color: #dc4c64; + --mdb-btn-hover-color: #000; + --mdb-btn-hover-bg: #e1677b; + --mdb-btn-hover-border-color: #e05e74; + --mdb-btn-focus-shadow-rgb: 187,65,85; + --mdb-btn-active-color: #000; + --mdb-btn-active-bg: #e37083; + --mdb-btn-active-border-color: #e05e74; + --mdb-btn-active-shadow: 0 8px 9px -4px rgba(0,0,0,0.15),0 4px 18px 0 rgba(0,0,0,0.1); + --mdb-btn-disabled-color: #000; + --mdb-btn-disabled-bg: #dc4c64; + --mdb-btn-disabled-border-color: #dc4c64 +} + +.btn-warning { + --mdb-btn-color: #000; + --mdb-btn-border-color: #e4a11b; + --mdb-btn-hover-color: #000; + --mdb-btn-hover-bg: #e8af3d; + --mdb-btn-hover-border-color: #e7aa32; + --mdb-btn-focus-shadow-rgb: 194,137,23; + --mdb-btn-active-color: #000; + --mdb-btn-active-bg: #e9b449; + --mdb-btn-active-border-color: #e7aa32; + --mdb-btn-active-shadow: 0 8px 9px -4px rgba(0,0,0,0.15),0 4px 18px 0 rgba(0,0,0,0.1); + --mdb-btn-disabled-color: #000; + --mdb-btn-disabled-bg: #e4a11b; + --mdb-btn-disabled-border-color: #e4a11b +} + +.btn-info { + --mdb-btn-color: #000; + --mdb-btn-border-color: #54b4d3; + --mdb-btn-hover-color: #000; + --mdb-btn-hover-bg: #6ebfda; + --mdb-btn-hover-border-color: #65bcd7; + --mdb-btn-focus-shadow-rgb: 71,153,179; + --mdb-btn-active-color: #000; + --mdb-btn-active-bg: #76c3dc; + --mdb-btn-active-border-color: #65bcd7; + --mdb-btn-active-shadow: 0 8px 9px -4px rgba(0,0,0,0.15),0 4px 18px 0 rgba(0,0,0,0.1); + --mdb-btn-disabled-color: #000; + --mdb-btn-disabled-bg: #54b4d3; + --mdb-btn-disabled-border-color: #54b4d3 +} + +.btn-light { + --mdb-btn-color: #000; + --mdb-btn-border-color: #fbfbfb; + --mdb-btn-hover-color: #000; + --mdb-btn-hover-border-color: #c9c9c9; + --mdb-btn-focus-shadow-rgb: 213,213,213; + --mdb-btn-active-color: #000; + --mdb-btn-active-border-color: #bcbcbc; + --mdb-btn-active-shadow: 0 8px 9px -4px rgba(0,0,0,0.15),0 4px 18px 0 rgba(0,0,0,0.1); + --mdb-btn-disabled-color: #000; + --mdb-btn-disabled-bg: #fbfbfb; + --mdb-btn-disabled-border-color: #fbfbfb +} + +.btn-dark { + --mdb-btn-border-color: #332d2d; + --mdb-btn-hover-bg: #524d4d; + --mdb-btn-hover-border-color: #474242; + --mdb-btn-focus-shadow-rgb: 82,77,77; + --mdb-btn-active-bg: #5c5757; + --mdb-btn-active-border-color: #474242; + --mdb-btn-active-shadow: 0 8px 9px -4px rgba(0,0,0,0.15),0 4px 18px 0 rgba(0,0,0,0.1); + --mdb-btn-disabled-color: #fff; + --mdb-btn-disabled-bg: #332d2d; + --mdb-btn-disabled-border-color: #332d2d +} + +.btn-outline-primary { + --mdb-btn-hover-color: #fff; + --mdb-btn-hover-bg: #3b71ca; + --mdb-btn-hover-border-color: #3b71ca; + --mdb-btn-focus-shadow-rgb: 59,113,202; + --mdb-btn-active-color: #fff; + --mdb-btn-active-bg: #3b71ca; + --mdb-btn-active-border-color: #3b71ca; + --mdb-btn-active-shadow: 0 8px 9px -4px rgba(0,0,0,0.15),0 4px 18px 0 rgba(0,0,0,0.1); + --mdb-btn-disabled-color: #3b71ca; + --mdb-btn-disabled-bg: transparent; + --mdb-btn-disabled-border-color: #3b71ca; + --mdb-gradient: none +} + +.btn-outline-secondary { + --mdb-btn-color: #9fa6b2; + --mdb-btn-border-color: #9fa6b2; + --mdb-btn-hover-color: #000; + --mdb-btn-hover-bg: #9fa6b2; + --mdb-btn-hover-border-color: #9fa6b2; + --mdb-btn-focus-shadow-rgb: 159,166,178; + --mdb-btn-active-color: #000; + --mdb-btn-active-bg: #9fa6b2; + --mdb-btn-active-border-color: #9fa6b2; + --mdb-btn-active-shadow: 0 8px 9px -4px rgba(0,0,0,0.15),0 4px 18px 0 rgba(0,0,0,0.1); + --mdb-btn-disabled-color: #9fa6b2; + --mdb-btn-disabled-bg: transparent; + --mdb-btn-disabled-border-color: #9fa6b2; + --mdb-gradient: none +} + +.btn-outline-success { + --mdb-btn-hover-color: #000; + --mdb-btn-hover-bg: #14a44d; + --mdb-btn-hover-border-color: #14a44d; + --mdb-btn-focus-shadow-rgb: 20,164,77; + --mdb-btn-active-color: #000; + --mdb-btn-active-bg: #14a44d; + --mdb-btn-active-border-color: #14a44d; + --mdb-btn-active-shadow: 0 8px 9px -4px rgba(0,0,0,0.15),0 4px 18px 0 rgba(0,0,0,0.1); + --mdb-btn-disabled-color: #14a44d; + --mdb-btn-disabled-bg: transparent; + --mdb-btn-disabled-border-color: #14a44d; + --mdb-gradient: none +} + +.btn-outline-danger { + --mdb-btn-hover-color: #000; + --mdb-btn-hover-bg: #dc4c64; + --mdb-btn-hover-border-color: #dc4c64; + --mdb-btn-focus-shadow-rgb: 220,76,100; + --mdb-btn-active-color: #000; + --mdb-btn-active-bg: #dc4c64; + --mdb-btn-active-border-color: #dc4c64; + --mdb-btn-active-shadow: 0 8px 9px -4px rgba(0,0,0,0.15),0 4px 18px 0 rgba(0,0,0,0.1); + --mdb-btn-disabled-color: #dc4c64; + --mdb-btn-disabled-bg: transparent; + --mdb-btn-disabled-border-color: #dc4c64; + --mdb-gradient: none +} + +.btn-outline-warning { + --mdb-btn-hover-color: #000; + --mdb-btn-hover-bg: #e4a11b; + --mdb-btn-hover-border-color: #e4a11b; + --mdb-btn-focus-shadow-rgb: 228,161,27; + --mdb-btn-active-color: #000; + --mdb-btn-active-bg: #e4a11b; + --mdb-btn-active-border-color: #e4a11b; + --mdb-btn-active-shadow: 0 8px 9px -4px rgba(0,0,0,0.15),0 4px 18px 0 rgba(0,0,0,0.1); + --mdb-btn-disabled-color: #e4a11b; + --mdb-btn-disabled-bg: transparent; + --mdb-btn-disabled-border-color: #e4a11b; + --mdb-gradient: none +} + +.btn-outline-info { + --mdb-btn-hover-color: #000; + --mdb-btn-hover-bg: #54b4d3; + --mdb-btn-hover-border-color: #54b4d3; + --mdb-btn-focus-shadow-rgb: 84,180,211; + --mdb-btn-active-color: #000; + --mdb-btn-active-bg: #54b4d3; + --mdb-btn-active-border-color: #54b4d3; + --mdb-btn-active-shadow: 0 8px 9px -4px rgba(0,0,0,0.15),0 4px 18px 0 rgba(0,0,0,0.1); + --mdb-btn-disabled-color: #54b4d3; + --mdb-btn-disabled-bg: transparent; + --mdb-btn-disabled-border-color: #54b4d3; + --mdb-gradient: none +} + +.btn-outline-light { + --mdb-btn-hover-color: #000; + --mdb-btn-hover-bg: #fbfbfb; + --mdb-btn-hover-border-color: #fbfbfb; + --mdb-btn-focus-shadow-rgb: 251,251,251; + --mdb-btn-active-color: #000; + --mdb-btn-active-bg: #fbfbfb; + --mdb-btn-active-border-color: #fbfbfb; + --mdb-btn-active-shadow: 0 8px 9px -4px rgba(0,0,0,0.15),0 4px 18px 0 rgba(0,0,0,0.1); + --mdb-btn-disabled-color: #fbfbfb; + --mdb-btn-disabled-bg: transparent; + --mdb-btn-disabled-border-color: #fbfbfb; + --mdb-gradient: none +} + +.btn-outline-dark { + --mdb-btn-hover-color: #fff; + --mdb-btn-hover-bg: #332d2d; + --mdb-btn-hover-border-color: #332d2d; + --mdb-btn-focus-shadow-rgb: 51,45,45; + --mdb-btn-active-color: #fff; + --mdb-btn-active-bg: #332d2d; + --mdb-btn-active-border-color: #332d2d; + --mdb-btn-active-shadow: 0 8px 9px -4px rgba(0,0,0,0.15),0 4px 18px 0 rgba(0,0,0,0.1); + --mdb-btn-disabled-color: #332d2d; + --mdb-btn-disabled-bg: transparent; + --mdb-btn-disabled-border-color: #332d2d; + --mdb-gradient: none +} + +.btn-link { + --mdb-btn-font-weight: 400; + --mdb-btn-bg: transparent; + --mdb-btn-border-color: transparent; + --mdb-btn-hover-border-color: transparent; + --mdb-btn-active-color: #386bc0; + --mdb-btn-active-border-color: transparent; + --mdb-btn-disabled-border-color: transparent; + --mdb-btn-focus-shadow-rgb: 88,134,210 +} + +.btn-link:focus-visible,.btn-link:hover { + text-decoration: none +} + +.btn-link:focus-visible { + color: var(--mdb-btn-color) +} + +.btn-link:hover { + color: var(--mdb-btn-hover-color) +} + +.btn-group-lg>.btn,.btn-lg { + --mdb-btn-padding-y: 0.5rem; + --mdb-btn-border-radius: 0.5rem +} + +.btn-group-sm>.btn,.btn-sm { + --mdb-btn-padding-y: 0.25rem; + --mdb-btn-border-radius: 0.25rem +} + +.fade { + transition: opacity .15s linear +} + +@media(prefers-reduced-motion:reduce) { + .fade { + transition: none + } +} + +.fade:not(.show) { + opacity: 0 +} + +.collapse:not(.show) { + display: none +} + +.collapsing { + height: 0; + overflow: hidden; + transition: height .35s ease +} + +@media(prefers-reduced-motion:reduce) { + .collapsing { + transition: none + } +} + +.collapsing.collapse-horizontal { + width: 0; + height: auto; + transition: width .35s ease +} + +@media(prefers-reduced-motion:reduce) { + .collapsing.collapse-horizontal { + transition: none + } +} + +.dropdown,.dropdown-center,.dropend,.dropstart,.dropup,.dropup-center { + position: relative +} + +.dropdown-toggle { + white-space: nowrap +} + +.dropdown-toggle:after { + display: inline-block; + margin-left: .255em; + vertical-align: .255em; + content: ""; + border-top: .3em solid; + border-right: .3em solid transparent; + border-bottom: 0; + border-left: .3em solid transparent +} + +.dropdown-toggle:empty:after { + margin-left: 0 +} + +.dropdown-menu { + --mdb-dropdown-zindex: 1000; + --mdb-dropdown-min-width: 10rem; + --mdb-dropdown-padding-x: 0; + --mdb-dropdown-padding-y: 0.5rem; + --mdb-dropdown-spacer: 0.125rem; + --mdb-dropdown-font-size: 0.875rem; + --mdb-dropdown-color: #4f4f4f; + --mdb-dropdown-bg: #fff; + --mdb-dropdown-border-color: var(--mdb-border-color-translucent); + --mdb-dropdown-border-radius: 0.5rem; + --mdb-dropdown-border-width: 1px; + --mdb-dropdown-inner-border-radius: calc(0.5rem - 1px); + --mdb-dropdown-divider-bg: #f5f5f5; + --mdb-dropdown-divider-margin-y: 0.5rem; + --mdb-dropdown-box-shadow: 0 2px 15px -3px rgba(0,0,0,0.07),0 10px 20px -2px rgba(0,0,0,0.04); + --mdb-dropdown-link-color: #262626; + --mdb-dropdown-link-hover-color: #222; + --mdb-dropdown-link-hover-bg: #eee; + --mdb-dropdown-link-active-color: #fff; + --mdb-dropdown-link-active-bg: #3b71ca; + --mdb-dropdown-link-disabled-color: #9e9e9e; + --mdb-dropdown-item-padding-x: 1rem; + --mdb-dropdown-item-padding-y: 0.5rem; + --mdb-dropdown-header-color: #757575; + --mdb-dropdown-header-padding-x: 1rem; + --mdb-dropdown-header-padding-y: 0.5rem; + position: absolute; + z-index: var(--mdb-dropdown-zindex); + display: none; + min-width: var(--mdb-dropdown-min-width); + padding: var(--mdb-dropdown-padding-y) var(--mdb-dropdown-padding-x); + text-align: left; + list-style: none; + background-color: var(--mdb-dropdown-bg); + background-clip: padding-box; + border: var(--mdb-dropdown-border-width) solid var(--mdb-dropdown-border-color); + border-radius: var(--mdb-dropdown-border-radius) +} + +.dropdown-menu[data-mdb-popper] { + top: 100%; + left: 0; + margin-top: var(--mdb-dropdown-spacer) +} + +.dropdown-menu-start { + --mdb-position: start +} + +.dropdown-menu-start[data-mdb-popper] { + right: auto; + left: 0 +} + +.dropdown-menu-end { + --mdb-position: end +} + +.dropdown-menu-end[data-mdb-popper] { + right: 0; + left: auto +} + +@media(min-width: 576px) { + .dropdown-menu-sm-start { + --mdb-position:start + } + + .dropdown-menu-sm-start[data-mdb-popper] { + right: auto; + left: 0 + } + + .dropdown-menu-sm-end { + --mdb-position: end + } + + .dropdown-menu-sm-end[data-mdb-popper] { + right: 0; + left: auto + } +} + +@media(min-width: 768px) { + .dropdown-menu-md-start { + --mdb-position:start + } + + .dropdown-menu-md-start[data-mdb-popper] { + right: auto; + left: 0 + } + + .dropdown-menu-md-end { + --mdb-position: end + } + + .dropdown-menu-md-end[data-mdb-popper] { + right: 0; + left: auto + } +} + +@media(min-width: 992px) { + .dropdown-menu-lg-start { + --mdb-position:start + } + + .dropdown-menu-lg-start[data-mdb-popper] { + right: auto; + left: 0 + } + + .dropdown-menu-lg-end { + --mdb-position: end + } + + .dropdown-menu-lg-end[data-mdb-popper] { + right: 0; + left: auto + } +} + +@media(min-width: 1200px) { + .dropdown-menu-xl-start { + --mdb-position:start + } + + .dropdown-menu-xl-start[data-mdb-popper] { + right: auto; + left: 0 + } + + .dropdown-menu-xl-end { + --mdb-position: end + } + + .dropdown-menu-xl-end[data-mdb-popper] { + right: 0; + left: auto + } +} + +@media(min-width: 1400px) { + .dropdown-menu-xxl-start { + --mdb-position:start + } + + .dropdown-menu-xxl-start[data-mdb-popper] { + right: auto; + left: 0 + } + + .dropdown-menu-xxl-end { + --mdb-position: end + } + + .dropdown-menu-xxl-end[data-mdb-popper] { + right: 0; + left: auto + } +} + +.dropup .dropdown-menu[data-mdb-popper] { + top: auto; + bottom: 100%; + margin-top: 0; + margin-bottom: var(--mdb-dropdown-spacer) +} + +.dropup .dropdown-toggle:after { + display: inline-block; + margin-left: .255em; + vertical-align: .255em; + content: ""; + border-top: 0; + border-right: .3em solid transparent; + border-bottom: .3em solid; + border-left: .3em solid transparent +} + +.dropup .dropdown-toggle:empty:after { + margin-left: 0 +} + +.dropend .dropdown-menu[data-mdb-popper] { + top: 0; + right: auto; + left: 100%; + margin-top: 0; + margin-left: var(--mdb-dropdown-spacer) +} + +.dropend .dropdown-toggle:after { + display: inline-block; + margin-left: .255em; + vertical-align: .255em; + content: ""; + border-top: .3em solid transparent; + border-right: 0; + border-bottom: .3em solid transparent; + border-left: .3em solid +} + +.dropend .dropdown-toggle:empty:after { + margin-left: 0 +} + +.dropend .dropdown-toggle:after { + vertical-align: 0 +} + +.dropstart .dropdown-menu[data-mdb-popper] { + top: 0; + right: 100%; + left: auto; + margin-top: 0; + margin-right: var(--mdb-dropdown-spacer) +} + +.dropstart .dropdown-toggle:after { + display: inline-block; + margin-left: .255em; + vertical-align: .255em; + content: ""; + display: none +} + +.dropstart .dropdown-toggle:before { + display: inline-block; + margin-right: .255em; + vertical-align: .255em; + content: ""; + border-top: .3em solid transparent; + border-right: .3em solid; + border-bottom: .3em solid transparent +} + +.dropstart .dropdown-toggle:empty:after { + margin-left: 0 +} + +.dropstart .dropdown-toggle:before { + vertical-align: 0 +} + +.dropdown-divider { + height: 0; + margin: var(--mdb-dropdown-divider-margin-y) 0; + overflow: hidden; + border-top: 1px solid var(--mdb-dropdown-divider-bg) +} + +.dropdown-item { + display: block; + width: 100%; + clear: both; + font-weight: 400; + color: var(--mdb-dropdown-link-color); + text-align: inherit; + white-space: nowrap; + background-color: transparent; + border: 0 +} + +.dropdown-item:focus,.dropdown-item:hover { + color: var(--mdb-dropdown-link-hover-color); + background-color: var(--mdb-dropdown-link-hover-bg) +} + +.dropdown-item.active,.dropdown-item:active { + color: var(--mdb-dropdown-link-active-color); + text-decoration: none; + background-color: var(--mdb-dropdown-link-active-bg) +} + +.dropdown-item.disabled,.dropdown-item:disabled { + color: var(--mdb-dropdown-link-disabled-color); + pointer-events: none; + background-color: transparent +} + +.dropdown-menu.show { + display: block +} + +.dropdown-header { + display: block; + padding: var(--mdb-dropdown-header-padding-y) var(--mdb-dropdown-header-padding-x); + margin-bottom: 0; + font-size: .875rem; + color: var(--mdb-dropdown-header-color); + white-space: nowrap +} + +.dropdown-item-text { + display: block; + padding: var(--mdb-dropdown-item-padding-y) var(--mdb-dropdown-item-padding-x); + color: var(--mdb-dropdown-link-color) +} + +.dropdown-menu-dark { + --mdb-dropdown-color: #e0e0e0; + --mdb-dropdown-bg: #4f4f4f; + --mdb-dropdown-border-color: var(--mdb-border-color-translucent); + --mdb-dropdown-link-color: #e0e0e0; + --mdb-dropdown-link-hover-color: #fff; + --mdb-dropdown-divider-bg: #f5f5f5; + --mdb-dropdown-link-hover-bg: hsla(0,0%,100%,0.15); + --mdb-dropdown-link-active-color: #fff; + --mdb-dropdown-link-active-bg: #3b71ca; + --mdb-dropdown-link-disabled-color: #9e9e9e; + --mdb-dropdown-header-color: #9e9e9e +} + +.btn-group,.btn-group-vertical { + position: relative; + display: inline-flex; + vertical-align: middle +} + +.btn-group-vertical>.btn,.btn-group>.btn { + position: relative; + flex: 1 1 auto +} + +.btn-group-vertical>.btn-check:checked+.btn,.btn-group-vertical>.btn-check:focus+.btn,.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn-check:checked+.btn,.btn-group>.btn-check:focus+.btn,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover { + z-index: 1 +} + +.btn-toolbar { + display: flex; + flex-wrap: wrap; + justify-content: flex-start +} + +.btn-toolbar .input-group { + width: auto +} + +.btn-group { + border-radius: .25rem +} + +.btn-group>.btn-group:not(:first-child),.btn-group>:not(.btn-check:first-child)+.btn { + margin-left: -2px +} + +.btn-group>.btn-group:not(:last-child)>.btn,.btn-group>.btn.dropdown-toggle-split:first-child,.btn-group>.btn:not(:last-child):not(.dropdown-toggle) { + border-top-right-radius: 0; + border-bottom-right-radius: 0 +} + +.btn-group>.btn-group:not(:first-child)>.btn,.btn-group>.btn:nth-child(n+3),.btn-group>:not(.btn-check)+.btn { + border-top-left-radius: 0; + border-bottom-left-radius: 0 +} + +.dropdown-toggle-split { + padding-right: 1.125rem; + padding-left: 1.125rem +} + +.dropdown-toggle-split:after,.dropend .dropdown-toggle-split:after,.dropup .dropdown-toggle-split:after { + margin-left: 0 +} + +.dropstart .dropdown-toggle-split:before { + margin-right: 0 +} + +.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split { + padding-right: .75rem; + padding-left: .75rem +} + +.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split { + padding-right: 1.265625rem; + padding-left: 1.265625rem +} + +.btn-group.show .dropdown-toggle { + box-shadow: 0 8px 9px -4px rgba(0,0,0,.15),0 4px 18px 0 rgba(0,0,0,.1) +} + +.btn-group.show .dropdown-toggle.btn-link { + box-shadow: none +} + +.btn-group-vertical { + flex-direction: column; + align-items: flex-start; + justify-content: center +} + +.btn-group-vertical>.btn,.btn-group-vertical>.btn-group { + width: 100% +} + +.btn-group-vertical>.btn-group:not(:first-child),.btn-group-vertical>.btn:not(:first-child) { + margin-top: -2px +} + +.btn-group-vertical>.btn-group:not(:last-child)>.btn,.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle) { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0 +} + +.btn-group-vertical>.btn-group:not(:first-child)>.btn,.btn-group-vertical>.btn~.btn { + border-top-left-radius: 0; + border-top-right-radius: 0 +} + +.nav { + --mdb-nav-link-padding-x: 1rem; + --mdb-nav-link-padding-y: 0.5rem; + --mdb-nav-link-color: var(--mdb-link-color); + --mdb-nav-link-hover-color: var(--mdb-link-hover-color); + --mdb-nav-link-disabled-color: #757575; + display: flex; + flex-wrap: wrap; + padding-left: 0; + margin-bottom: 0; + list-style: none +} + +.nav-link { + display: block; + padding: var(--mdb-nav-link-padding-y) var(--mdb-nav-link-padding-x); + font-size: var(--mdb-nav-link-font-size); + font-weight: var(--mdb-nav-link-font-weight); + color: var(--mdb-nav-link-color); + transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out +} + +@media(prefers-reduced-motion:reduce) { + .nav-link { + transition: none + } +} + +.nav-link:focus,.nav-link:hover { + color: var(--mdb-nav-link-hover-color) +} + +.nav-link.disabled { + color: var(--mdb-nav-link-disabled-color); + pointer-events: none; + cursor: default +} + +.nav-tabs { + --mdb-nav-tabs-border-width: 1px; + --mdb-nav-tabs-border-color: #e0e0e0; + --mdb-nav-tabs-border-radius: 0.25rem; + --mdb-nav-tabs-link-hover-border-color: #eee #eee #e0e0e0; + --mdb-nav-tabs-link-active-color: #3b71ca; + --mdb-nav-tabs-link-active-bg: #fff; + --mdb-nav-tabs-link-active-border-color: #3b71ca; + border-bottom: var(--mdb-nav-tabs-border-width) solid var(--mdb-nav-tabs-border-color) +} + +.nav-tabs .nav-link { + margin-bottom: calc(var(--mdb-nav-tabs-border-width)*-1); + background: none; + border: var(--mdb-nav-tabs-border-width) solid transparent; + border-top-left-radius: var(--mdb-nav-tabs-border-radius); + border-top-right-radius: var(--mdb-nav-tabs-border-radius) +} + +.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover { + isolation: isolate; + border-color: var(--mdb-nav-tabs-link-hover-border-color) +} + +.nav-tabs .nav-link.disabled,.nav-tabs .nav-link:disabled { + color: var(--mdb-nav-link-disabled-color); + background-color: transparent; + border-color: transparent +} + +.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active { + background-color: var(--mdb-nav-tabs-link-active-bg) +} + +.nav-tabs .dropdown-menu { + margin-top: calc(var(--mdb-nav-tabs-border-width)*-1); + border-top-left-radius: 0; + border-top-right-radius: 0 +} + +.nav-pills { + --mdb-nav-pills-border-radius: 0.25rem; + --mdb-nav-pills-link-active-color: #285192; + --mdb-nav-pills-link-active-bg: #e3ebf7 +} + +.nav-pills .nav-link { + background: none; + border: 0; + border-radius: var(--mdb-nav-pills-border-radius) +} + +.nav-pills .nav-link:disabled { + color: var(--mdb-nav-link-disabled-color); + background-color: transparent; + border-color: transparent +} + +.nav-fill .nav-item,.nav-fill>.nav-link { + flex: 1 1 auto; + text-align: center +} + +.nav-justified .nav-item,.nav-justified>.nav-link { + flex-basis: 0; + flex-grow: 1; + text-align: center +} + +.nav-fill .nav-item .nav-link,.nav-justified .nav-item .nav-link { + width: 100% +} + +.tab-content>.tab-pane { + display: none +} + +.tab-content>.active { + display: block +} + +.navbar { + --mdb-navbar-padding-x: 0; + --mdb-navbar-padding-y: 0.5rem; + --mdb-navbar-color: rgba(0,0,0,0.55); + --mdb-navbar-hover-color: rgba(0,0,0,0.7); + --mdb-navbar-disabled-color: rgba(0,0,0,0.3); + --mdb-navbar-active-color: rgba(0,0,0,0.9); + --mdb-navbar-brand-padding-y: 0.3rem; + --mdb-navbar-brand-margin-end: 1rem; + --mdb-navbar-brand-font-size: 1.25rem; + --mdb-navbar-brand-color: rgba(0,0,0,0.9); + --mdb-navbar-brand-hover-color: rgba(0,0,0,0.9); + --mdb-navbar-nav-link-padding-x: 0.5rem; + --mdb-navbar-toggler-padding-y: 0.25rem; + --mdb-navbar-toggler-padding-x: 0.75rem; + --mdb-navbar-toggler-font-size: 1.25rem; + --mdb-navbar-toggler-icon-bg: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3E%3Cpath stroke='rgba(0, 0, 0, 0.55)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E"); + --mdb-navbar-toggler-border-color: rgba(0,0,0,0.1); + --mdb-navbar-toggler-border-radius: 0.25rem; + --mdb-navbar-toggler-focus-width: 0.25rem; + --mdb-navbar-toggler-transition: box-shadow 0.15s ease-in-out; + position: relative; + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: space-between; + padding: var(--mdb-navbar-padding-y) var(--mdb-navbar-padding-x) +} + +.navbar>.container,.navbar>.container-fluid,.navbar>.container-lg,.navbar>.container-md,.navbar>.container-sm,.navbar>.container-xl,.navbar>.container-xxl { + display: flex; + flex-wrap: inherit; + align-items: center; + justify-content: space-between +} + +.navbar-brand { + padding-top: var(--mdb-navbar-brand-padding-y); + padding-bottom: var(--mdb-navbar-brand-padding-y); + margin-right: var(--mdb-navbar-brand-margin-end); + font-size: var(--mdb-navbar-brand-font-size); + color: var(--mdb-navbar-brand-color); + white-space: nowrap +} + +.navbar-brand:focus,.navbar-brand:hover { + color: var(--mdb-navbar-brand-hover-color) +} + +.navbar-nav { + --mdb-nav-link-padding-x: 0; + --mdb-nav-link-padding-y: 0.5rem; + --mdb-nav-link-color: var(--mdb-navbar-color); + --mdb-nav-link-hover-color: var(--mdb-navbar-hover-color); + --mdb-nav-link-disabled-color: var(--mdb-navbar-disabled-color); + display: flex; + flex-direction: column; + padding-left: 0; + margin-bottom: 0; + list-style: none +} + +.navbar-nav .nav-link.active,.navbar-nav .show>.nav-link { + color: var(--mdb-navbar-active-color) +} + +.navbar-nav .dropdown-menu { + position: static +} + +.navbar-text { + padding-top: .5rem; + padding-bottom: .5rem; + color: var(--mdb-navbar-color) +} + +.navbar-text a,.navbar-text a:focus,.navbar-text a:hover { + color: var(--mdb-navbar-active-color) +} + +.navbar-collapse { + flex-basis: 100%; + flex-grow: 1; + align-items: center +} + +.navbar-toggler { + padding: var(--mdb-navbar-toggler-padding-y) var(--mdb-navbar-toggler-padding-x); + font-size: var(--mdb-navbar-toggler-font-size); + line-height: 1; + color: var(--mdb-navbar-color); + background-color: transparent; + border: var(--mdb-border-width) solid var(--mdb-navbar-toggler-border-color); + border-radius: var(--mdb-navbar-toggler-border-radius); + transition: var(--mdb-navbar-toggler-transition) +} + +@media(prefers-reduced-motion:reduce) { + .navbar-toggler { + transition: none + } +} + +.navbar-toggler:hover { + text-decoration: none +} + +.navbar-toggler:focus { + text-decoration: none; + outline: 0; + box-shadow: 0 0 0 var(--mdb-navbar-toggler-focus-width) +} + +.navbar-toggler-icon { + display: inline-block; + width: 1.5em; + height: 1.5em; + vertical-align: middle; + background-image: var(--mdb-navbar-toggler-icon-bg); + background-repeat: no-repeat; + background-position: 50%; + background-size: 100% +} + +.navbar-nav-scroll { + max-height: var(--mdb-scroll-height,75vh); + overflow-y: auto +} + +@media(min-width: 576px) { + .navbar-expand-sm { + flex-wrap:nowrap; + justify-content: flex-start + } + + .navbar-expand-sm .navbar-nav { + flex-direction: row + } + + .navbar-expand-sm .navbar-nav .dropdown-menu { + position: absolute + } + + .navbar-expand-sm .navbar-nav .nav-link { + padding-right: var(--mdb-navbar-nav-link-padding-x); + padding-left: var(--mdb-navbar-nav-link-padding-x) + } + + .navbar-expand-sm .navbar-nav-scroll { + overflow: visible + } + + .navbar-expand-sm .navbar-collapse { + display: flex!important; + flex-basis: auto + } + + .navbar-expand-sm .navbar-toggler { + display: none + } + + .navbar-expand-sm .offcanvas { + position: static; + z-index: auto; + flex-grow: 1; + width: auto!important; + height: auto!important; + visibility: visible!important; + background-color: transparent!important; + border: 0!important; + transform: none!important; + box-shadow: none; + transition: none + } + + .navbar-expand-sm .offcanvas .offcanvas-header { + display: none + } + + .navbar-expand-sm .offcanvas .offcanvas-body { + display: flex; + flex-grow: 0; + padding: 0; + overflow-y: visible + } +} + +@media(min-width: 768px) { + .navbar-expand-md { + flex-wrap:nowrap; + justify-content: flex-start + } + + .navbar-expand-md .navbar-nav { + flex-direction: row + } + + .navbar-expand-md .navbar-nav .dropdown-menu { + position: absolute + } + + .navbar-expand-md .navbar-nav .nav-link { + padding-right: var(--mdb-navbar-nav-link-padding-x); + padding-left: var(--mdb-navbar-nav-link-padding-x) + } + + .navbar-expand-md .navbar-nav-scroll { + overflow: visible + } + + .navbar-expand-md .navbar-collapse { + display: flex!important; + flex-basis: auto + } + + .navbar-expand-md .navbar-toggler { + display: none + } + + .navbar-expand-md .offcanvas { + position: static; + z-index: auto; + flex-grow: 1; + width: auto!important; + height: auto!important; + visibility: visible!important; + background-color: transparent!important; + border: 0!important; + transform: none!important; + box-shadow: none; + transition: none + } + + .navbar-expand-md .offcanvas .offcanvas-header { + display: none + } + + .navbar-expand-md .offcanvas .offcanvas-body { + display: flex; + flex-grow: 0; + padding: 0; + overflow-y: visible + } +} + +@media(min-width: 992px) { + .navbar-expand-lg { + flex-wrap:nowrap; + justify-content: flex-start + } + + .navbar-expand-lg .navbar-nav { + flex-direction: row + } + + .navbar-expand-lg .navbar-nav .dropdown-menu { + position: absolute + } + + .navbar-expand-lg .navbar-nav .nav-link { + padding-right: var(--mdb-navbar-nav-link-padding-x); + padding-left: var(--mdb-navbar-nav-link-padding-x) + } + + .navbar-expand-lg .navbar-nav-scroll { + overflow: visible + } + + .navbar-expand-lg .navbar-collapse { + display: flex!important; + flex-basis: auto + } + + .navbar-expand-lg .navbar-toggler { + display: none + } + + .navbar-expand-lg .offcanvas { + position: static; + z-index: auto; + flex-grow: 1; + width: auto!important; + height: auto!important; + visibility: visible!important; + background-color: transparent!important; + border: 0!important; + transform: none!important; + box-shadow: none; + transition: none + } + + .navbar-expand-lg .offcanvas .offcanvas-header { + display: none + } + + .navbar-expand-lg .offcanvas .offcanvas-body { + display: flex; + flex-grow: 0; + padding: 0; + overflow-y: visible + } +} + +@media(min-width: 1200px) { + .navbar-expand-xl { + flex-wrap:nowrap; + justify-content: flex-start + } + + .navbar-expand-xl .navbar-nav { + flex-direction: row + } + + .navbar-expand-xl .navbar-nav .dropdown-menu { + position: absolute + } + + .navbar-expand-xl .navbar-nav .nav-link { + padding-right: var(--mdb-navbar-nav-link-padding-x); + padding-left: var(--mdb-navbar-nav-link-padding-x) + } + + .navbar-expand-xl .navbar-nav-scroll { + overflow: visible + } + + .navbar-expand-xl .navbar-collapse { + display: flex!important; + flex-basis: auto + } + + .navbar-expand-xl .navbar-toggler { + display: none + } + + .navbar-expand-xl .offcanvas { + position: static; + z-index: auto; + flex-grow: 1; + width: auto!important; + height: auto!important; + visibility: visible!important; + background-color: transparent!important; + border: 0!important; + transform: none!important; + box-shadow: none; + transition: none + } + + .navbar-expand-xl .offcanvas .offcanvas-header { + display: none + } + + .navbar-expand-xl .offcanvas .offcanvas-body { + display: flex; + flex-grow: 0; + padding: 0; + overflow-y: visible + } +} + +@media(min-width: 1400px) { + .navbar-expand-xxl { + flex-wrap:nowrap; + justify-content: flex-start + } + + .navbar-expand-xxl .navbar-nav { + flex-direction: row + } + + .navbar-expand-xxl .navbar-nav .dropdown-menu { + position: absolute + } + + .navbar-expand-xxl .navbar-nav .nav-link { + padding-right: var(--mdb-navbar-nav-link-padding-x); + padding-left: var(--mdb-navbar-nav-link-padding-x) + } + + .navbar-expand-xxl .navbar-nav-scroll { + overflow: visible + } + + .navbar-expand-xxl .navbar-collapse { + display: flex!important; + flex-basis: auto + } + + .navbar-expand-xxl .navbar-toggler { + display: none + } + + .navbar-expand-xxl .offcanvas { + position: static; + z-index: auto; + flex-grow: 1; + width: auto!important; + height: auto!important; + visibility: visible!important; + background-color: transparent!important; + border: 0!important; + transform: none!important; + box-shadow: none; + transition: none + } + + .navbar-expand-xxl .offcanvas .offcanvas-header { + display: none + } + + .navbar-expand-xxl .offcanvas .offcanvas-body { + display: flex; + flex-grow: 0; + padding: 0; + overflow-y: visible + } +} + +.navbar-expand { + flex-wrap: nowrap; + justify-content: flex-start +} + +.navbar-expand .navbar-nav { + flex-direction: row +} + +.navbar-expand .navbar-nav .dropdown-menu { + position: absolute +} + +.navbar-expand .navbar-nav .nav-link { + padding-right: var(--mdb-navbar-nav-link-padding-x); + padding-left: var(--mdb-navbar-nav-link-padding-x) +} + +.navbar-expand .navbar-nav-scroll { + overflow: visible +} + +.navbar-expand .navbar-collapse { + display: flex!important; + flex-basis: auto +} + +.navbar-expand .navbar-toggler { + display: none +} + +.navbar-expand .offcanvas { + position: static; + z-index: auto; + flex-grow: 1; + width: auto!important; + height: auto!important; + visibility: visible!important; + background-color: transparent!important; + border: 0!important; + transform: none!important; + box-shadow: none; + transition: none +} + +.navbar-expand .offcanvas .offcanvas-header { + display: none +} + +.navbar-expand .offcanvas .offcanvas-body { + display: flex; + flex-grow: 0; + padding: 0; + overflow-y: visible +} + +.navbar-dark { + --mdb-navbar-color: hsla(0,0%,100%,0.55); + --mdb-navbar-hover-color: hsla(0,0%,100%,0.75); + --mdb-navbar-disabled-color: hsla(0,0%,100%,0.25); + --mdb-navbar-active-color: #fff; + --mdb-navbar-brand-color: #fff; + --mdb-navbar-brand-hover-color: #fff; + --mdb-navbar-toggler-border-color: hsla(0,0%,100%,0.1); + --mdb-navbar-toggler-icon-bg: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3E%3Cpath stroke='rgba(255, 255, 255, 0.55)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E") +} + +.card { + --mdb-card-spacer-y: 1.5rem; + --mdb-card-spacer-x: 1.5rem; + --mdb-card-title-spacer-y: 0.5rem; + --mdb-card-border-width: 1px; + --mdb-card-border-color: var(--mdb-border-color-translucent); + --mdb-card-border-radius: 0.5rem; + --mdb-card-box-shadow: 0 2px 15px -3px rgba(0,0,0,0.07),0 10px 20px -2px rgba(0,0,0,0.04); + --mdb-card-inner-border-radius: calc(0.5rem - 1px); + --mdb-card-cap-padding-y: 0.75rem; + --mdb-card-cap-padding-x: 1.5rem; + --mdb-card-cap-bg: hsla(0,0%,100%,0); + --mdb-card-bg: #fff; + --mdb-card-img-overlay-padding: 1.5rem; + --mdb-card-group-margin: 0.75rem; + position: relative; + display: flex; + flex-direction: column; + min-width: 0; + height: var(--mdb-card-height); + word-wrap: break-word; + background-color: var(--mdb-card-bg); + background-clip: border-box; + border: var(--mdb-card-border-width) solid var(--mdb-card-border-color); + border-radius: var(--mdb-card-border-radius); + box-shadow: var(--mdb-card-box-shadow) +} + +.card>hr { + margin-right: 0; + margin-left: 0 +} + +.card>.list-group { + border-top: inherit; + border-bottom: inherit +} + +.card>.list-group:first-child { + border-top-width: 0; + border-top-left-radius: var(--mdb-card-inner-border-radius); + border-top-right-radius: var(--mdb-card-inner-border-radius) +} + +.card>.list-group:last-child { + border-bottom-width: 0; + border-bottom-right-radius: var(--mdb-card-inner-border-radius); + border-bottom-left-radius: var(--mdb-card-inner-border-radius) +} + +.card>.card-header+.list-group,.card>.list-group+.card-footer { + border-top: 0 +} + +.card-body { + flex: 1 1 auto; + padding: var(--mdb-card-spacer-y) var(--mdb-card-spacer-x); + color: var(--mdb-card-color) +} + +.card-title { + margin-bottom: var(--mdb-card-title-spacer-y) +} + +.card-subtitle { + margin-top: calc(var(--mdb-card-title-spacer-y)*-0.5) +} + +.card-subtitle,.card-text:last-child { + margin-bottom: 0 +} + +.card-link+.card-link { + margin-left: var(--mdb-card-spacer-x) +} + +.card-header { + padding: var(--mdb-card-cap-padding-y) var(--mdb-card-cap-padding-x); + margin-bottom: 0; + color: var(--mdb-card-cap-color); + background-color: var(--mdb-card-cap-bg); + border-bottom: var(--mdb-card-border-width) solid var(--mdb-card-border-color) +} + +.card-header:first-child { + border-radius: var(--mdb-card-inner-border-radius) var(--mdb-card-inner-border-radius) 0 0 +} + +.card-footer { + padding: var(--mdb-card-cap-padding-y) var(--mdb-card-cap-padding-x); + color: var(--mdb-card-cap-color); + background-color: var(--mdb-card-cap-bg); + border-top: var(--mdb-card-border-width) solid var(--mdb-card-border-color) +} + +.card-footer:last-child { + border-radius: 0 0 var(--mdb-card-inner-border-radius) var(--mdb-card-inner-border-radius) +} + +.card-header-tabs { + margin-right: calc(var(--mdb-card-cap-padding-x)*-0.5); + margin-bottom: calc(var(--mdb-card-cap-padding-y)*-1); + margin-left: calc(var(--mdb-card-cap-padding-x)*-0.5); + border-bottom: 0 +} + +.card-header-tabs .nav-link.active { + background-color: var(--mdb-card-bg); + border-bottom-color: var(--mdb-card-bg) +} + +.card-header-pills { + margin-right: calc(var(--mdb-card-cap-padding-x)*-0.5); + margin-left: calc(var(--mdb-card-cap-padding-x)*-0.5) +} + +.card-img-overlay { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + padding: var(--mdb-card-img-overlay-padding); + border-radius: var(--mdb-card-inner-border-radius) +} + +.card-img,.card-img-bottom,.card-img-top { + width: 100% +} + +.card-img,.card-img-top { + border-top-left-radius: var(--mdb-card-inner-border-radius); + border-top-right-radius: var(--mdb-card-inner-border-radius) +} + +.card-img,.card-img-bottom { + border-bottom-right-radius: var(--mdb-card-inner-border-radius); + border-bottom-left-radius: var(--mdb-card-inner-border-radius) +} + +.card-group>.card { + margin-bottom: var(--mdb-card-group-margin) +} + +@media(min-width: 576px) { + .card-group { + display:flex; + flex-flow: row wrap + } + + .card-group>.card { + flex: 1 0 0%; + margin-bottom: 0 + } + + .card-group>.card+.card { + margin-left: 0; + border-left: 0 + } + + .card-group>.card:not(:last-child) { + border-top-right-radius: 0; + border-bottom-right-radius: 0 + } + + .card-group>.card:not(:last-child) .card-header,.card-group>.card:not(:last-child) .card-img-top { + border-top-right-radius: 0 + } + + .card-group>.card:not(:last-child) .card-footer,.card-group>.card:not(:last-child) .card-img-bottom { + border-bottom-right-radius: 0 + } + + .card-group>.card:not(:first-child) { + border-top-left-radius: 0; + border-bottom-left-radius: 0 + } + + .card-group>.card:not(:first-child) .card-header,.card-group>.card:not(:first-child) .card-img-top { + border-top-left-radius: 0 + } + + .card-group>.card:not(:first-child) .card-footer,.card-group>.card:not(:first-child) .card-img-bottom { + border-bottom-left-radius: 0 + } +} + +.breadcrumb { + --mdb-breadcrumb-padding-x: 0; + --mdb-breadcrumb-padding-y: 0; + --mdb-breadcrumb-margin-bottom: 1rem; + --mdb-breadcrumb-divider-color: #757575; + --mdb-breadcrumb-item-padding-x: 0.5rem; + --mdb-breadcrumb-item-active-color: #757575; + display: flex; + flex-wrap: wrap; + padding: var(--mdb-breadcrumb-padding-y) var(--mdb-breadcrumb-padding-x); + margin-bottom: var(--mdb-breadcrumb-margin-bottom); + font-size: var(--mdb-breadcrumb-font-size); + list-style: none; + background-color: var(--mdb-breadcrumb-bg); + border-radius: var(--mdb-breadcrumb-border-radius) +} + +.breadcrumb-item+.breadcrumb-item { + padding-left: var(--mdb-breadcrumb-item-padding-x) +} + +.breadcrumb-item+.breadcrumb-item:before { + float: left; + padding-right: var(--mdb-breadcrumb-item-padding-x); + color: var(--mdb-breadcrumb-divider-color); + content: var(--mdb-breadcrumb-divider,"/") +} + +.breadcrumb-item.active { + color: var(--mdb-breadcrumb-item-active-color) +} + +.pagination { + --mdb-pagination-padding-x: 0.75rem; + --mdb-pagination-padding-y: 0.375rem; + --mdb-pagination-font-size: 0.9rem; + --mdb-pagination-color: #4f4f4f; + --mdb-pagination-bg: #fff; + --mdb-pagination-border-width: 1px; + --mdb-pagination-border-color: #e0e0e0; + --mdb-pagination-hover-color: #4f4f4f; + --mdb-pagination-hover-bg: #eee; + --mdb-pagination-hover-border-color: #e0e0e0; + --mdb-pagination-focus-color: var(--mdb-link-hover-color); + --mdb-pagination-focus-bg: #eee; + --mdb-pagination-focus-box-shadow: 0 0 0 0.25rem rgba(59,113,202,0.25); + --mdb-pagination-active-color: #285192; + --mdb-pagination-active-bg: #e3ebf7; + --mdb-pagination-active-border-color: #e3ebf7; + --mdb-pagination-disabled-color: #757575; + --mdb-pagination-disabled-bg: #fff; + --mdb-pagination-disabled-border-color: #e0e0e0; + display: flex; + padding-left: 0; + list-style: none +} + +.page-link { + position: relative; + display: block; + padding: var(--mdb-pagination-padding-y) var(--mdb-pagination-padding-x); + font-size: var(--mdb-pagination-font-size); + color: var(--mdb-pagination-color); + background-color: var(--mdb-pagination-bg); + border: var(--mdb-pagination-border-width) solid var(--mdb-pagination-border-color); + transition: all .3s linear +} + +@media(prefers-reduced-motion:reduce) { + .page-link { + transition: none + } +} + +.page-link:hover { + z-index: 2; + color: var(--mdb-pagination-hover-color); + background-color: var(--mdb-pagination-hover-bg); + border-color: var(--mdb-pagination-hover-border-color) +} + +.page-link:focus { + z-index: 3; + color: var(--mdb-pagination-focus-color); + background-color: var(--mdb-pagination-focus-bg); + outline: 0; + box-shadow: var(--mdb-pagination-focus-box-shadow) +} + +.active>.page-link,.page-link.active { + z-index: 3; + color: var(--mdb-pagination-active-color); + background-color: var(--mdb-pagination-active-bg); + border-color: var(--mdb-pagination-active-border-color) +} + +.disabled>.page-link,.page-link.disabled { + color: var(--mdb-pagination-disabled-color); + pointer-events: none; + background-color: var(--mdb-pagination-disabled-bg); + border-color: var(--mdb-pagination-disabled-border-color) +} + +.page-item:not(:first-child) .page-link { + margin-left: -1px +} + +.pagination-lg { + --mdb-pagination-padding-x: 1.5rem; + --mdb-pagination-padding-y: 0.75rem; + --mdb-pagination-font-size: 1.25rem; + --mdb-pagination-border-radius: 0.5rem +} + +.pagination-sm { + --mdb-pagination-padding-x: 0.5rem; + --mdb-pagination-padding-y: 0.25rem; + --mdb-pagination-font-size: 0.875rem; + --mdb-pagination-border-radius: 0.25rem +} + +.badge { + --mdb-badge-padding-x: 0.65em; + --mdb-badge-padding-y: 0.35em; + --mdb-badge-font-size: 0.75em; + --mdb-badge-font-weight: 700; + --mdb-badge-color: #fff; + --mdb-badge-border-radius: 0.27rem; + display: inline-block; + padding: var(--mdb-badge-padding-y) var(--mdb-badge-padding-x); + font-size: var(--mdb-badge-font-size); + font-weight: var(--mdb-badge-font-weight); + line-height: 1; + color: var(--mdb-badge-color); + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: var(--mdb-badge-border-radius) +} + +.badge:empty { + display: none +} + +.btn .badge { + position: relative; + top: -1px +} + +.alert { + --mdb-alert-bg: transparent; + --mdb-alert-padding-x: 1.5rem; + --mdb-alert-padding-y: 1.25rem; + --mdb-alert-margin-bottom: 1rem; + --mdb-alert-color: inherit; + --mdb-alert-border-color: transparent; + --mdb-alert-border: 1px solid var(--mdb-alert-border-color); + --mdb-alert-border-radius: 0.5rem; + position: relative; + padding: var(--mdb-alert-padding-y) var(--mdb-alert-padding-x); + margin-bottom: var(--mdb-alert-margin-bottom); + color: var(--mdb-alert-color); + background-color: var(--mdb-alert-bg); + border: var(--mdb-alert-border); + border-radius: var(--mdb-alert-border-radius) +} + +.alert-heading { + color: inherit +} + +.alert-link { + font-weight: 700 +} + +.alert-dismissible { + padding-right: 4.5rem +} + +.alert-dismissible .btn-close { + position: absolute; + top: 0; + right: 0; + z-index: 2; + padding: 1.5625rem 1.5rem +} + +.alert-primary { + --mdb-alert-color: #234479; + --mdb-alert-bg: #d8e3f4; + --mdb-alert-border-color: #c4d4ef +} + +.alert-primary .alert-link { + color: #1c3661 +} + +.alert-secondary { + --mdb-alert-color: #5f646b; + --mdb-alert-bg: #ecedf0; + --mdb-alert-border-color: #e2e4e8 +} + +.alert-secondary .alert-link { + color: #4c5056 +} + +.alert-success { + --mdb-alert-color: #0c622e; + --mdb-alert-bg: #d0eddb; + --mdb-alert-border-color: #b9e4ca +} + +.alert-success .alert-link { + color: #0a4e25 +} + +.alert-danger { + --mdb-alert-color: #842e3c; + --mdb-alert-bg: #f8dbe0; + --mdb-alert-border-color: #f5c9d1 +} + +.alert-danger .alert-link { + color: #6a2530 +} + +.alert-warning { + --mdb-alert-color: #896110; + --mdb-alert-bg: #faecd1; + --mdb-alert-border-color: #f7e3bb +} + +.alert-warning .alert-link { + color: #6e4e0d +} + +.alert-info { + --mdb-alert-color: #326c7f; + --mdb-alert-bg: #ddf0f6; + --mdb-alert-border-color: #cce9f2 +} + +.alert-info .alert-link { + color: #285666 +} + +.alert-light { + --mdb-alert-color: #646464; + --mdb-alert-bg: #fefefe; + --mdb-alert-border-color: #fefefe +} + +.alert-light .alert-link { + color: #505050 +} + +.alert-dark { + --mdb-alert-color: #1f1b1b; + --mdb-alert-bg: #d6d5d5; + --mdb-alert-border-color: #c2c0c0 +} + +.alert-dark .alert-link { + color: #191616 +} + +.accordion { + --mdb-accordion-color: #4f4f4f; + --mdb-accordion-bg: #fff; + --mdb-accordion-transition: color 0.15s ease-in-out,background-color 0.15s ease-in-out,border-color 0.15s ease-in-out,box-shadow 0.15s ease-in-out,border-radius 0.15s ease; + --mdb-accordion-border-color: var(--mdb-border-color); + --mdb-accordion-border-width: 1px; + --mdb-accordion-border-radius: 0.5rem; + --mdb-accordion-inner-border-radius: calc(0.5rem - 1px); + --mdb-accordion-btn-padding-x: 1.5rem; + --mdb-accordion-btn-padding-y: 1.15rem; + --mdb-accordion-btn-color: #4f4f4f; + --mdb-accordion-btn-bg: var(--mdb-accordion-bg); + --mdb-accordion-btn-icon: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%234f4f4f'%3E%3Cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 01.708 0L8 10.293l5.646-5.647a.5.5 0 01.708.708l-6 6a.5.5 0 01-.708 0l-6-6a.5.5 0 010-.708z'/%3E%3C/svg%3E"); + --mdb-accordion-btn-icon-width: 1.25rem; + --mdb-accordion-btn-icon-transform: rotate(-180deg); + --mdb-accordion-btn-icon-transition: transform 0.2s ease-in-out; + --mdb-accordion-btn-active-icon: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%233b71ca'%3E%3Cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 01.708 0L8 10.293l5.646-5.647a.5.5 0 01.708.708l-6 6a.5.5 0 01-.708 0l-6-6a.5.5 0 010-.708z'/%3E%3C/svg%3E"); + --mdb-accordion-btn-focus-border-color: #3b71ca; + --mdb-accordion-btn-focus-box-shadow: inset 0 -1px 0 rgba(0,0,0,0.125); + --mdb-accordion-body-padding-x: 1.5rem; + --mdb-accordion-body-padding-y: 1.15rem; + --mdb-accordion-active-color: #3b71ca; + --mdb-accordion-active-bg: #fff +} + +.accordion-button { + position: relative; + display: flex; + align-items: center; + width: 100%; + padding: var(--mdb-accordion-btn-padding-y) var(--mdb-accordion-btn-padding-x); + font-size: 1rem; + color: var(--mdb-accordion-btn-color); + text-align: left; + background-color: var(--mdb-accordion-btn-bg); + border: 0; + border-radius: 0; + overflow-anchor: none; + transition: var(--mdb-accordion-transition) +} + +@media(prefers-reduced-motion:reduce) { + .accordion-button { + transition: none + } +} + +.accordion-button:not(.collapsed) { + color: var(--mdb-accordion-active-color); + background-color: var(--mdb-accordion-active-bg); + box-shadow: inset 0 calc(var(--mdb-accordion-border-width)*-1) 0 var(--mdb-accordion-border-color) +} + +.accordion-button:not(.collapsed):after { + background-image: var(--mdb-accordion-btn-active-icon); + transform: var(--mdb-accordion-btn-icon-transform) +} + +.accordion-button:after { + flex-shrink: 0; + width: var(--mdb-accordion-btn-icon-width); + height: var(--mdb-accordion-btn-icon-width); + margin-left: auto; + content: ""; + background-image: var(--mdb-accordion-btn-icon); + background-repeat: no-repeat; + background-size: var(--mdb-accordion-btn-icon-width); + transition: var(--mdb-accordion-btn-icon-transition) +} + +@media(prefers-reduced-motion:reduce) { + .accordion-button:after { + transition: none + } +} + +.accordion-button:hover { + z-index: 2 +} + +.accordion-button:focus { + z-index: 3; + box-shadow: var(--mdb-accordion-btn-focus-box-shadow) +} + +.accordion-header { + margin-bottom: 0 +} + +.accordion-item { + color: var(--mdb-accordion-color); + background-color: var(--mdb-accordion-bg); + border: var(--mdb-accordion-border-width) solid var(--mdb-accordion-border-color) +} + +.accordion-item:first-of-type { + border-top-left-radius: var(--mdb-accordion-border-radius); + border-top-right-radius: var(--mdb-accordion-border-radius) +} + +.accordion-item:first-of-type .accordion-button { + border-top-left-radius: var(--mdb-accordion-inner-border-radius); + border-top-right-radius: var(--mdb-accordion-inner-border-radius) +} + +.accordion-item:not(:first-of-type) { + border-top: 0 +} + +.accordion-item:last-of-type { + border-bottom-right-radius: var(--mdb-accordion-border-radius); + border-bottom-left-radius: var(--mdb-accordion-border-radius) +} + +.accordion-item:last-of-type .accordion-button.collapsed { + border-bottom-right-radius: var(--mdb-accordion-inner-border-radius); + border-bottom-left-radius: var(--mdb-accordion-inner-border-radius) +} + +.accordion-item:last-of-type .accordion-collapse { + border-bottom-right-radius: var(--mdb-accordion-border-radius); + border-bottom-left-radius: var(--mdb-accordion-border-radius) +} + +.accordion-body { + padding: var(--mdb-accordion-body-padding-y) var(--mdb-accordion-body-padding-x) +} + +.accordion-flush .accordion-collapse { + border-width: 0 +} + +.accordion-flush .accordion-item { + border-right: 0; + border-left: 0; + border-radius: 0 +} + +.accordion-flush .accordion-item:first-child { + border-top: 0 +} + +.accordion-flush .accordion-item:last-child { + border-bottom: 0 +} + +.accordion-flush .accordion-item .accordion-button,.accordion-flush .accordion-item .accordion-button.collapsed { + border-radius: 0 +} + +@keyframes progress-bar-stripes { + 0% { + background-position-x: 4px + } +} + +.progress { + --mdb-progress-height: 4px; + --mdb-progress-font-size: 0.75rem; + --mdb-progress-bg: #eee; + --mdb-progress-border-radius: 0.25rem; + --mdb-progress-box-shadow: inset 0 1px 2px rgba(0,0,0,0.075); + --mdb-progress-bar-color: #fff; + --mdb-progress-bar-bg: #3b71ca; + --mdb-progress-bar-transition: width 0.6s ease; + height: var(--mdb-progress-height); + font-size: var(--mdb-progress-font-size); + background-color: var(--mdb-progress-bg); + border-radius: var(--mdb-progress-border-radius); + box-shadow: var(--mdb-progress-box-shadow) +} + +.progress,.progress-bar { + display: flex; + overflow: hidden +} + +.progress-bar { + flex-direction: column; + justify-content: center; + color: var(--mdb-progress-bar-color); + text-align: center; + white-space: nowrap; + background-color: var(--mdb-progress-bar-bg); + transition: var(--mdb-progress-bar-transition) +} + +@media(prefers-reduced-motion:reduce) { + .progress-bar { + transition: none + } +} + +.progress-bar-striped { + background-image: linear-gradient(45deg,hsla(0,0%,100%,.15) 25%,transparent 0,transparent 50%,hsla(0,0%,100%,.15) 0,hsla(0,0%,100%,.15) 75%,transparent 0,transparent); + background-size: var(--mdb-progress-height) var(--mdb-progress-height) +} + +.progress-bar-animated { + animation: progress-bar-stripes 1s linear infinite +} + +@media(prefers-reduced-motion:reduce) { + .progress-bar-animated { + animation: none + } +} + +.placeholder { + display: inline-block; + min-height: 1em; + vertical-align: middle; + cursor: wait; + background-color: currentcolor; + opacity: .5 +} + +.placeholder.btn:before { + display: inline-block; + content: "" +} + +.placeholder-xs { + min-height: .6em +} + +.placeholder-sm { + min-height: .8em +} + +.placeholder-lg { + min-height: 1.2em +} + +.placeholder-glow .placeholder { + animation: placeholder-glow 2s ease-in-out infinite +} + +@keyframes placeholder-glow { + 50% { + opacity: .2 + } +} + +.placeholder-wave { + -webkit-mask-image: linear-gradient(130deg,#000 55%,rgba(0,0,0,.8) 75%,#000 95%); + mask-image: linear-gradient(130deg,#000 55%,rgba(0,0,0,.8) 75%,#000 95%); + -webkit-mask-size: 200% 100%; + mask-size: 200% 100%; + animation: placeholder-wave 2s linear infinite +} + +@keyframes placeholder-wave { + to { + -webkit-mask-position: -200% 0; + mask-position: -200% 0 + } +} + +.list-group { + --mdb-list-group-color: #4f4f4f; + --mdb-list-group-bg: #fff; + --mdb-list-group-border-color: rgba(0,0,0,0.125); + --mdb-list-group-border-width: 1px; + --mdb-list-group-border-radius: 0.5rem; + --mdb-list-group-item-padding-x: 1.5rem; + --mdb-list-group-item-padding-y: 0.5rem; + --mdb-list-group-action-color: #616161; + --mdb-list-group-action-hover-color: #616161; + --mdb-list-group-action-hover-bg: #f5f5f5; + --mdb-list-group-action-active-color: #4f4f4f; + --mdb-list-group-action-active-bg: #eee; + --mdb-list-group-disabled-color: #757575; + --mdb-list-group-disabled-bg: #fff; + --mdb-list-group-active-color: #2c58a0; + --mdb-list-group-active-bg: #dfe7f6; + --mdb-list-group-active-border-color: #dfe7f6; + display: flex; + flex-direction: column; + padding-left: 0; + margin-bottom: 0; + border-radius: var(--mdb-list-group-border-radius) +} + +.list-group-numbered { + list-style-type: none; + counter-reset: section +} + +.list-group-numbered>.list-group-item:before { + content: counters(section,".") ". "; + counter-increment: section +} + +.list-group-item-action { + width: 100%; + color: var(--mdb-list-group-action-color); + text-align: inherit +} + +.list-group-item-action:focus,.list-group-item-action:hover { + z-index: 1; + color: var(--mdb-list-group-action-hover-color); + text-decoration: none; + background-color: var(--mdb-list-group-action-hover-bg) +} + +.list-group-item-action:active { + color: var(--mdb-list-group-action-active-color); + background-color: var(--mdb-list-group-action-active-bg) +} + +.list-group-item { + position: relative; + display: block; + padding: var(--mdb-list-group-item-padding-y) var(--mdb-list-group-item-padding-x); + color: var(--mdb-list-group-color); + background-color: var(--mdb-list-group-bg); + border: var(--mdb-list-group-border-width) solid var(--mdb-list-group-border-color) +} + +.list-group-item:first-child { + border-top-left-radius: inherit; + border-top-right-radius: inherit +} + +.list-group-item:last-child { + border-bottom-right-radius: inherit; + border-bottom-left-radius: inherit +} + +.list-group-item.disabled,.list-group-item:disabled { + color: var(--mdb-list-group-disabled-color); + pointer-events: none; + background-color: var(--mdb-list-group-disabled-bg) +} + +.list-group-item.active { + z-index: 2; + color: var(--mdb-list-group-active-color); + background-color: var(--mdb-list-group-active-bg); + border-color: var(--mdb-list-group-active-border-color) +} + +.list-group-item+.list-group-item { + border-top-width: 0 +} + +.list-group-item+.list-group-item.active { + margin-top: calc(var(--mdb-list-group-border-width)*-1); + border-top-width: var(--mdb-list-group-border-width) +} + +.list-group-horizontal { + flex-direction: row +} + +.list-group-horizontal>.list-group-item:first-child:not(:last-child) { + border-bottom-left-radius: var(--mdb-list-group-border-radius); + border-top-right-radius: 0 +} + +.list-group-horizontal>.list-group-item:last-child:not(:first-child) { + border-top-right-radius: var(--mdb-list-group-border-radius); + border-bottom-left-radius: 0 +} + +.list-group-horizontal>.list-group-item.active { + margin-top: 0 +} + +.list-group-horizontal>.list-group-item+.list-group-item { + border-top-width: var(--mdb-list-group-border-width); + border-left-width: 0 +} + +.list-group-horizontal>.list-group-item+.list-group-item.active { + margin-left: calc(var(--mdb-list-group-border-width)*-1); + border-left-width: var(--mdb-list-group-border-width) +} + +@media(min-width: 576px) { + .list-group-horizontal-sm { + flex-direction:row + } + + .list-group-horizontal-sm>.list-group-item:first-child:not(:last-child) { + border-bottom-left-radius: var(--mdb-list-group-border-radius); + border-top-right-radius: 0 + } + + .list-group-horizontal-sm>.list-group-item:last-child:not(:first-child) { + border-top-right-radius: var(--mdb-list-group-border-radius); + border-bottom-left-radius: 0 + } + + .list-group-horizontal-sm>.list-group-item.active { + margin-top: 0 + } + + .list-group-horizontal-sm>.list-group-item+.list-group-item { + border-top-width: var(--mdb-list-group-border-width); + border-left-width: 0 + } + + .list-group-horizontal-sm>.list-group-item+.list-group-item.active { + margin-left: calc(var(--mdb-list-group-border-width)*-1); + border-left-width: var(--mdb-list-group-border-width) + } +} + +@media(min-width: 768px) { + .list-group-horizontal-md { + flex-direction:row + } + + .list-group-horizontal-md>.list-group-item:first-child:not(:last-child) { + border-bottom-left-radius: var(--mdb-list-group-border-radius); + border-top-right-radius: 0 + } + + .list-group-horizontal-md>.list-group-item:last-child:not(:first-child) { + border-top-right-radius: var(--mdb-list-group-border-radius); + border-bottom-left-radius: 0 + } + + .list-group-horizontal-md>.list-group-item.active { + margin-top: 0 + } + + .list-group-horizontal-md>.list-group-item+.list-group-item { + border-top-width: var(--mdb-list-group-border-width); + border-left-width: 0 + } + + .list-group-horizontal-md>.list-group-item+.list-group-item.active { + margin-left: calc(var(--mdb-list-group-border-width)*-1); + border-left-width: var(--mdb-list-group-border-width) + } +} + +@media(min-width: 992px) { + .list-group-horizontal-lg { + flex-direction:row + } + + .list-group-horizontal-lg>.list-group-item:first-child:not(:last-child) { + border-bottom-left-radius: var(--mdb-list-group-border-radius); + border-top-right-radius: 0 + } + + .list-group-horizontal-lg>.list-group-item:last-child:not(:first-child) { + border-top-right-radius: var(--mdb-list-group-border-radius); + border-bottom-left-radius: 0 + } + + .list-group-horizontal-lg>.list-group-item.active { + margin-top: 0 + } + + .list-group-horizontal-lg>.list-group-item+.list-group-item { + border-top-width: var(--mdb-list-group-border-width); + border-left-width: 0 + } + + .list-group-horizontal-lg>.list-group-item+.list-group-item.active { + margin-left: calc(var(--mdb-list-group-border-width)*-1); + border-left-width: var(--mdb-list-group-border-width) + } +} + +@media(min-width: 1200px) { + .list-group-horizontal-xl { + flex-direction:row + } + + .list-group-horizontal-xl>.list-group-item:first-child:not(:last-child) { + border-bottom-left-radius: var(--mdb-list-group-border-radius); + border-top-right-radius: 0 + } + + .list-group-horizontal-xl>.list-group-item:last-child:not(:first-child) { + border-top-right-radius: var(--mdb-list-group-border-radius); + border-bottom-left-radius: 0 + } + + .list-group-horizontal-xl>.list-group-item.active { + margin-top: 0 + } + + .list-group-horizontal-xl>.list-group-item+.list-group-item { + border-top-width: var(--mdb-list-group-border-width); + border-left-width: 0 + } + + .list-group-horizontal-xl>.list-group-item+.list-group-item.active { + margin-left: calc(var(--mdb-list-group-border-width)*-1); + border-left-width: var(--mdb-list-group-border-width) + } +} + +@media(min-width: 1400px) { + .list-group-horizontal-xxl { + flex-direction:row + } + + .list-group-horizontal-xxl>.list-group-item:first-child:not(:last-child) { + border-bottom-left-radius: var(--mdb-list-group-border-radius); + border-top-right-radius: 0 + } + + .list-group-horizontal-xxl>.list-group-item:last-child:not(:first-child) { + border-top-right-radius: var(--mdb-list-group-border-radius); + border-bottom-left-radius: 0 + } + + .list-group-horizontal-xxl>.list-group-item.active { + margin-top: 0 + } + + .list-group-horizontal-xxl>.list-group-item+.list-group-item { + border-top-width: var(--mdb-list-group-border-width); + border-left-width: 0 + } + + .list-group-horizontal-xxl>.list-group-item+.list-group-item.active { + margin-left: calc(var(--mdb-list-group-border-width)*-1); + border-left-width: var(--mdb-list-group-border-width) + } +} + +.list-group-flush { + border-radius: 0 +} + +.list-group-flush>.list-group-item { + border-left-width: 0; + border-bottom-width: var(--mdb-list-group-border-width); + border-right-width: 0; + border-top-width: 0 +} + +.list-group-flush>.list-group-item:last-child { + border-bottom-width: 0 +} + +.list-group-item-primary { + color: #234479; + background-color: #d8e3f4 +} + +.list-group-item-primary.list-group-item-action:focus,.list-group-item-primary.list-group-item-action:hover { + color: #234479; + background-color: #c2ccdc +} + +.list-group-item-primary.list-group-item-action.active { + color: #fff; + background-color: #234479; + border-color: #234479 +} + +.list-group-item-secondary { + color: #5f646b; + background-color: #ecedf0 +} + +.list-group-item-secondary.list-group-item-action:focus,.list-group-item-secondary.list-group-item-action:hover { + color: #5f646b; + background-color: #d4d5d8 +} + +.list-group-item-secondary.list-group-item-action.active { + color: #fff; + background-color: #5f646b; + border-color: #5f646b +} + +.list-group-item-success { + color: #0c622e; + background-color: #d0eddb +} + +.list-group-item-success.list-group-item-action:focus,.list-group-item-success.list-group-item-action:hover { + color: #0c622e; + background-color: #bbd5c5 +} + +.list-group-item-success.list-group-item-action.active { + color: #fff; + background-color: #0c622e; + border-color: #0c622e +} + +.list-group-item-danger { + color: #842e3c; + background-color: #f8dbe0 +} + +.list-group-item-danger.list-group-item-action:focus,.list-group-item-danger.list-group-item-action:hover { + color: #842e3c; + background-color: #dfc5ca +} + +.list-group-item-danger.list-group-item-action.active { + color: #fff; + background-color: #842e3c; + border-color: #842e3c +} + +.list-group-item-warning { + color: #896110; + background-color: #faecd1 +} + +.list-group-item-warning.list-group-item-action:focus,.list-group-item-warning.list-group-item-action:hover { + color: #896110; + background-color: #e1d4bc +} + +.list-group-item-warning.list-group-item-action.active { + color: #fff; + background-color: #896110; + border-color: #896110 +} + +.list-group-item-info { + color: #326c7f; + background-color: #ddf0f6 +} + +.list-group-item-info.list-group-item-action:focus,.list-group-item-info.list-group-item-action:hover { + color: #326c7f; + background-color: #c7d8dd +} + +.list-group-item-info.list-group-item-action.active { + color: #fff; + background-color: #326c7f; + border-color: #326c7f +} + +.list-group-item-light { + color: #646464; + background-color: #fefefe +} + +.list-group-item-light.list-group-item-action:focus,.list-group-item-light.list-group-item-action:hover { + color: #646464; + background-color: #e5e5e5 +} + +.list-group-item-light.list-group-item-action.active { + color: #fff; + background-color: #646464; + border-color: #646464 +} + +.list-group-item-dark { + color: #1f1b1b; + background-color: #d6d5d5 +} + +.list-group-item-dark.list-group-item-action:focus,.list-group-item-dark.list-group-item-action:hover { + color: #1f1b1b; + background-color: #c1c0c0 +} + +.list-group-item-dark.list-group-item-action.active { + color: #fff; + background-color: #1f1b1b; + border-color: #1f1b1b +} + +.btn-close { + box-sizing: content-box; + width: 1em; + height: 1em; + padding: .25em; + color: #000; + background: transparent url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M.293.293a1 1 0 011.414 0L8 6.586 14.293.293a1 1 0 111.414 1.414L9.414 8l6.293 6.293a1 1 0 01-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 01-1.414-1.414L6.586 8 .293 1.707a1 1 0 010-1.414z'/%3E%3C/svg%3E") 50%/1em auto no-repeat; + border: 0; + border-radius: .25rem; + opacity: .5 +} + +.btn-close:hover { + color: #000; + text-decoration: none; + opacity: .75 +} + +.btn-close:focus { + outline: 0; + box-shadow: 0 0 0 .25rem rgba(59,113,202,.25); + opacity: 1 +} + +.btn-close.disabled,.btn-close:disabled { + pointer-events: none; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + opacity: .25 +} + +.btn-close-white { + filter: invert(1) grayscale(100%) brightness(200%) +} + +.toast { + --mdb-toast-zindex: 1060; + --mdb-toast-padding-x: 1rem; + --mdb-toast-padding-y: 0.65rem; + --mdb-toast-spacing: 1.5rem; + --mdb-toast-max-width: 350px; + --mdb-toast-font-size: 0.875rem; + --mdb-toast-bg: #fff; + --mdb-toast-border-width: 1px; + --mdb-toast-border-color: var(--mdb-border-color-translucent); + --mdb-toast-border-radius: 0.5rem; + --mdb-toast-box-shadow: 0 2px 15px -3px rgba(0,0,0,0.07),0 10px 20px -2px rgba(0,0,0,0.04); + --mdb-toast-header-color: #757575; + --mdb-toast-header-bg: #fff; + --mdb-toast-header-border-color: rgba(0,0,0,0.05); + width: var(--mdb-toast-max-width); + max-width: 100%; + font-size: var(--mdb-toast-font-size); + color: var(--mdb-toast-color); + pointer-events: auto; + background-color: var(--mdb-toast-bg); + background-clip: padding-box; + border: var(--mdb-toast-border-width) solid var(--mdb-toast-border-color); + box-shadow: var(--mdb-toast-box-shadow); + border-radius: var(--mdb-toast-border-radius) +} + +.toast.showing { + opacity: 0 +} + +.toast:not(.show) { + display: none +} + +.toast-container { + --mdb-toast-zindex: 1060; + position: absolute; + z-index: var(--mdb-toast-zindex); + width: -webkit-max-content; + width: -moz-max-content; + width: max-content; + max-width: 100%; + pointer-events: none +} + +.toast-container>:not(:last-child) { + margin-bottom: var(--mdb-toast-spacing) +} + +.toast-header { + display: flex; + align-items: center; + padding: var(--mdb-toast-padding-y) var(--mdb-toast-padding-x); + color: var(--mdb-toast-header-color); + background-color: var(--mdb-toast-header-bg); + background-clip: padding-box; + border-bottom: var(--mdb-toast-border-width) solid var(--mdb-toast-header-border-color); + border-top-left-radius: calc(var(--mdb-toast-border-radius) - var(--mdb-toast-border-width)); + border-top-right-radius: calc(var(--mdb-toast-border-radius) - var(--mdb-toast-border-width)) +} + +.toast-header .btn-close { + margin-right: calc(var(--mdb-toast-padding-x)*-0.5); + margin-left: var(--mdb-toast-padding-x) +} + +.toast-body { + padding: var(--mdb-toast-padding-x); + word-wrap: break-word +} + +.modal { + --mdb-modal-zindex: 1055; + --mdb-modal-width: 500px; + --mdb-modal-padding: 1rem; + --mdb-modal-margin: 0.5rem; + --mdb-modal-bg: #fff; + --mdb-modal-border-color: var(--mdb-border-color-translucent); + --mdb-modal-border-width: 1px; + --mdb-modal-border-radius: 0.5rem; + --mdb-modal-box-shadow: 0 0.125rem 0.25rem rgba(0,0,0,0.075); + --mdb-modal-inner-border-radius: calc(0.5rem - 1px); + --mdb-modal-header-padding-x: 1rem; + --mdb-modal-header-padding-y: 1rem; + --mdb-modal-header-padding: 1rem 1rem; + --mdb-modal-header-border-color: #f5f5f5; + --mdb-modal-header-border-width: 2px; + --mdb-modal-title-line-height: 1.6; + --mdb-modal-footer-gap: 0.5rem; + --mdb-modal-footer-border-color: #f5f5f5; + --mdb-modal-footer-border-width: 2px; + position: fixed; + top: 0; + left: 0; + z-index: var(--mdb-modal-zindex); + display: none; + width: 100%; + height: 100%; + overflow-x: hidden; + overflow-y: auto; + outline: 0 +} + +.modal-dialog { + position: relative; + width: auto; + margin: var(--mdb-modal-margin); + pointer-events: none +} + +.modal.fade .modal-dialog { + transition: transform .3s ease-out; + transform: translateY(-50px) +} + +@media(prefers-reduced-motion:reduce) { + .modal.fade .modal-dialog { + transition: none + } +} + +.modal.show .modal-dialog { + transform: none +} + +.modal.modal-static .modal-dialog { + transform: scale(1.02) +} + +.modal-dialog-scrollable { + height: calc(100% - var(--mdb-modal-margin)*2) +} + +.modal-dialog-scrollable .modal-content { + max-height: 100%; + overflow: hidden +} + +.modal-dialog-scrollable .modal-body { + overflow-y: auto +} + +.modal-dialog-centered { + display: flex; + align-items: center; + min-height: calc(100% - var(--mdb-modal-margin)*2) +} + +.modal-content { + position: relative; + display: flex; + flex-direction: column; + width: 100%; + color: var(--mdb-modal-color); + pointer-events: auto; + background-color: var(--mdb-modal-bg); + background-clip: padding-box; + border: var(--mdb-modal-border-width) solid var(--mdb-modal-border-color); + border-radius: var(--mdb-modal-border-radius); + outline: 0 +} + +.modal-backdrop { + --mdb-backdrop-zindex: 1050; + --mdb-backdrop-bg: #000; + --mdb-backdrop-opacity: 0.5; + position: fixed; + top: 0; + left: 0; + z-index: var(--mdb-backdrop-zindex); + width: 100vw; + height: 100vh; + background-color: var(--mdb-backdrop-bg) +} + +.modal-backdrop.fade { + opacity: 0 +} + +.modal-backdrop.show { + opacity: var(--mdb-backdrop-opacity) +} + +.modal-header { + display: flex; + flex-shrink: 0; + align-items: center; + justify-content: space-between; + padding: var(--mdb-modal-header-padding); + border-bottom: var(--mdb-modal-header-border-width) solid var(--mdb-modal-header-border-color); + border-top-left-radius: var(--mdb-modal-inner-border-radius); + border-top-right-radius: var(--mdb-modal-inner-border-radius) +} + +.modal-header .btn-close { + padding: calc(var(--mdb-modal-header-padding-y)*0.5) calc(var(--mdb-modal-header-padding-x)*0.5); + margin: calc(var(--mdb-modal-header-padding-y)*-0.5) calc(var(--mdb-modal-header-padding-x)*-0.5) calc(var(--mdb-modal-header-padding-y)*-0.5) auto +} + +.modal-title { + margin-bottom: 0; + line-height: var(--mdb-modal-title-line-height) +} + +.modal-body { + position: relative; + flex: 1 1 auto; + padding: var(--mdb-modal-padding) +} + +.modal-footer { + display: flex; + flex-shrink: 0; + flex-wrap: wrap; + align-items: center; + justify-content: flex-end; + padding: calc(var(--mdb-modal-padding) - var(--mdb-modal-footer-gap)*0.5); + background-color: var(--mdb-modal-footer-bg); + border-top: var(--mdb-modal-footer-border-width) solid var(--mdb-modal-footer-border-color); + border-bottom-right-radius: var(--mdb-modal-inner-border-radius); + border-bottom-left-radius: var(--mdb-modal-inner-border-radius) +} + +.modal-footer>* { + margin: calc(var(--mdb-modal-footer-gap)*0.5) +} + +@media(min-width: 576px) { + .modal { + --mdb-modal-margin:1.75rem; + --mdb-modal-box-shadow: 0 0.5rem 1rem rgba(0,0,0,0.15) + } + + .modal-dialog { + max-width: var(--mdb-modal-width); + margin-right: auto; + margin-left: auto + } + + .modal-sm { + --mdb-modal-width: 300px + } +} + +@media(min-width: 992px) { + .modal-lg,.modal-xl { + --mdb-modal-width:800px + } +} + +@media(min-width: 1200px) { + .modal-xl { + --mdb-modal-width:1140px + } +} + +.modal-fullscreen { + width: 100vw; + max-width: none; + height: 100%; + margin: 0 +} + +.modal-fullscreen .modal-content { + height: 100%; + border: 0; + border-radius: 0 +} + +.modal-fullscreen .modal-footer,.modal-fullscreen .modal-header { + border-radius: 0 +} + +.modal-fullscreen .modal-body { + overflow-y: auto +} + +@media(max-width: 575.98px) { + .modal-fullscreen-sm-down { + width:100vw; + max-width: none; + height: 100%; + margin: 0 + } + + .modal-fullscreen-sm-down .modal-content { + height: 100%; + border: 0; + border-radius: 0 + } + + .modal-fullscreen-sm-down .modal-footer,.modal-fullscreen-sm-down .modal-header { + border-radius: 0 + } + + .modal-fullscreen-sm-down .modal-body { + overflow-y: auto + } +} + +@media(max-width: 767.98px) { + .modal-fullscreen-md-down { + width:100vw; + max-width: none; + height: 100%; + margin: 0 + } + + .modal-fullscreen-md-down .modal-content { + height: 100%; + border: 0; + border-radius: 0 + } + + .modal-fullscreen-md-down .modal-footer,.modal-fullscreen-md-down .modal-header { + border-radius: 0 + } + + .modal-fullscreen-md-down .modal-body { + overflow-y: auto + } +} + +@media(max-width: 991.98px) { + .modal-fullscreen-lg-down { + width:100vw; + max-width: none; + height: 100%; + margin: 0 + } + + .modal-fullscreen-lg-down .modal-content { + height: 100%; + border: 0; + border-radius: 0 + } + + .modal-fullscreen-lg-down .modal-footer,.modal-fullscreen-lg-down .modal-header { + border-radius: 0 + } + + .modal-fullscreen-lg-down .modal-body { + overflow-y: auto + } +} + +@media(max-width: 1199.98px) { + .modal-fullscreen-xl-down { + width:100vw; + max-width: none; + height: 100%; + margin: 0 + } + + .modal-fullscreen-xl-down .modal-content { + height: 100%; + border: 0; + border-radius: 0 + } + + .modal-fullscreen-xl-down .modal-footer,.modal-fullscreen-xl-down .modal-header { + border-radius: 0 + } + + .modal-fullscreen-xl-down .modal-body { + overflow-y: auto + } +} + +@media(max-width: 1399.98px) { + .modal-fullscreen-xxl-down { + width:100vw; + max-width: none; + height: 100%; + margin: 0 + } + + .modal-fullscreen-xxl-down .modal-content { + height: 100%; + border: 0; + border-radius: 0 + } + + .modal-fullscreen-xxl-down .modal-footer,.modal-fullscreen-xxl-down .modal-header { + border-radius: 0 + } + + .modal-fullscreen-xxl-down .modal-body { + overflow-y: auto + } +} + +.popover { + --mdb-popover-zindex: 1080; + --mdb-popover-max-width: 276px; + --mdb-popover-font-size: 0.875rem; + --mdb-popover-bg: #fff; + --mdb-popover-border-width: 1px; + --mdb-popover-border-color: #f5f5f5; + --mdb-popover-border-radius: 0.5rem; + --mdb-popover-inner-border-radius: calc(0.5rem - 1px); + --mdb-popover-box-shadow: 0 0px 3px 0 rgba(0,0,0,0.07),0 2px 2px 0 rgba(0,0,0,0.04); + --mdb-popover-header-padding-x: 1rem; + --mdb-popover-header-padding-y: 0.5rem; + --mdb-popover-header-font-size: 1rem; + --mdb-popover-header-bg: #fff; + --mdb-popover-body-padding-x: 1rem; + --mdb-popover-body-padding-y: 1rem; + --mdb-popover-body-color: #4f4f4f; + --mdb-popover-arrow-width: 1rem; + --mdb-popover-arrow-height: 0.5rem; + --mdb-popover-arrow-border: var(--mdb-popover-border-color); + z-index: var(--mdb-popover-zindex); + display: block; + max-width: var(--mdb-popover-max-width); + font-family: var(--mdb-font-roboto); + font-style: normal; + font-weight: 400; + line-height: 1.6; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + letter-spacing: normal; + word-break: normal; + white-space: normal; + word-spacing: normal; + line-break: auto; + font-size: var(--mdb-popover-font-size); + word-wrap: break-word; + background-color: var(--mdb-popover-bg); + background-clip: padding-box; + border: var(--mdb-popover-border-width) solid var(--mdb-popover-border-color); + border-radius: var(--mdb-popover-border-radius); + box-shadow: var(--mdb-popover-box-shadow) +} + +.popover .popover-arrow { + display: block; + width: var(--mdb-popover-arrow-width); + height: var(--mdb-popover-arrow-height) +} + +.popover .popover-arrow:after,.popover .popover-arrow:before { + position: absolute; + display: block; + content: ""; + border: 0 solid transparent +} + +.bs-popover-auto[data-popper-placement^=top]>.popover-arrow,.bs-popover-top>.popover-arrow { + bottom: calc(var(--mdb-popover-arrow-height)*-1 - var(--mdb-popover-border-width)) +} + +.bs-popover-auto[data-popper-placement^=top]>.popover-arrow:after,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow:before,.bs-popover-top>.popover-arrow:after,.bs-popover-top>.popover-arrow:before { + border-left-width: calc(var(--mdb-popover-arrow-width)*0.5); + border-bottom-width: 0; + border-right-width: calc(var(--mdb-popover-arrow-width)*0.5); + border-top-width: var(--mdb-popover-arrow-height) +} + +.bs-popover-auto[data-popper-placement^=top]>.popover-arrow:before,.bs-popover-top>.popover-arrow:before { + bottom: 0; + border-top-color: var(--mdb-popover-arrow-border) +} + +.bs-popover-auto[data-popper-placement^=top]>.popover-arrow:after,.bs-popover-top>.popover-arrow:after { + bottom: var(--mdb-popover-border-width); + border-top-color: var(--mdb-popover-bg) +} + +/*!rtl:begin:ignore*/ +.bs-popover-auto[data-popper-placement^=right]>.popover-arrow,.bs-popover-end>.popover-arrow { + left: calc(var(--mdb-popover-arrow-height)*-1 - var(--mdb-popover-border-width)); + width: var(--mdb-popover-arrow-height); + height: var(--mdb-popover-arrow-width) +} + +.bs-popover-auto[data-popper-placement^=right]>.popover-arrow:after,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow:before,.bs-popover-end>.popover-arrow:after,.bs-popover-end>.popover-arrow:before { + border-left-width: 0; + border-bottom-width: calc(var(--mdb-popover-arrow-width)*0.5); + border-right-width: var(--mdb-popover-arrow-height); + border-top-width: calc(var(--mdb-popover-arrow-width)*0.5) +} + +.bs-popover-auto[data-popper-placement^=right]>.popover-arrow:before,.bs-popover-end>.popover-arrow:before { + left: 0; + border-right-color: var(--mdb-popover-arrow-border) +} + +.bs-popover-auto[data-popper-placement^=right]>.popover-arrow:after,.bs-popover-end>.popover-arrow:after { + left: var(--mdb-popover-border-width); + border-right-color: var(--mdb-popover-bg) +} + +/*!rtl:end:ignore*/ +.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow,.bs-popover-bottom>.popover-arrow { + top: calc(var(--mdb-popover-arrow-height)*-1 - var(--mdb-popover-border-width)) +} + +.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow:after,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow:before,.bs-popover-bottom>.popover-arrow:after,.bs-popover-bottom>.popover-arrow:before { + border-left-width: calc(var(--mdb-popover-arrow-width)*0.5); + border-bottom-width: var(--mdb-popover-arrow-height); + border-right-width: calc(var(--mdb-popover-arrow-width)*0.5); + border-top-width: 0 +} + +.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow:before,.bs-popover-bottom>.popover-arrow:before { + top: 0; + border-bottom-color: var(--mdb-popover-arrow-border) +} + +.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow:after,.bs-popover-bottom>.popover-arrow:after { + top: var(--mdb-popover-border-width); + border-bottom-color: var(--mdb-popover-bg) +} + +.bs-popover-auto[data-popper-placement^=bottom] .popover-header:before,.bs-popover-bottom .popover-header:before { + position: absolute; + top: 0; + left: 50%; + display: block; + width: var(--mdb-popover-arrow-width); + margin-left: calc(var(--mdb-popover-arrow-width)*-0.5); + content: ""; + border-bottom: var(--mdb-popover-border-width) solid var(--mdb-popover-header-bg) +} + +/*!rtl:begin:ignore*/ +.bs-popover-auto[data-popper-placement^=left]>.popover-arrow,.bs-popover-start>.popover-arrow { + right: calc(var(--mdb-popover-arrow-height)*-1 - var(--mdb-popover-border-width)); + width: var(--mdb-popover-arrow-height); + height: var(--mdb-popover-arrow-width) +} + +.bs-popover-auto[data-popper-placement^=left]>.popover-arrow:after,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow:before,.bs-popover-start>.popover-arrow:after,.bs-popover-start>.popover-arrow:before { + border-left-width: var(--mdb-popover-arrow-height); + border-bottom-width: calc(var(--mdb-popover-arrow-width)*0.5); + border-right-width: 0; + border-top-width: calc(var(--mdb-popover-arrow-width)*0.5) +} + +.bs-popover-auto[data-popper-placement^=left]>.popover-arrow:before,.bs-popover-start>.popover-arrow:before { + right: 0; + border-left-color: var(--mdb-popover-arrow-border) +} + +.bs-popover-auto[data-popper-placement^=left]>.popover-arrow:after,.bs-popover-start>.popover-arrow:after { + right: var(--mdb-popover-border-width); + border-left-color: var(--mdb-popover-bg) +} + +/*!rtl:end:ignore*/ +.popover-header { + padding: var(--mdb-popover-header-padding-y) var(--mdb-popover-header-padding-x); + margin-bottom: 0; + font-size: var(--mdb-popover-header-font-size); + color: var(--mdb-popover-header-color); + background-color: var(--mdb-popover-header-bg); + border-bottom: var(--mdb-popover-border-width) solid var(--mdb-popover-border-color); + border-top-left-radius: var(--mdb-popover-inner-border-radius); + border-top-right-radius: var(--mdb-popover-inner-border-radius) +} + +.popover-header:empty { + display: none +} + +.popover-body { + padding: var(--mdb-popover-body-padding-y) var(--mdb-popover-body-padding-x); + color: var(--mdb-popover-body-color) +} + +.spinner-border,.spinner-grow { + display: inline-block; + width: var(--mdb-spinner-width); + height: var(--mdb-spinner-height); + vertical-align: var(--mdb-spinner-vertical-align); + border-radius: 50%; + animation: var(--mdb-spinner-animation-speed) linear infinite var(--mdb-spinner-animation-name) +} + +@keyframes spinner-border { + to { + transform: rotate(1turn) + } +} + +.spinner-border { + --mdb-spinner-width: 2rem; + --mdb-spinner-height: 2rem; + --mdb-spinner-vertical-align: -0.125em; + --mdb-spinner-border-width: 0.25em; + --mdb-spinner-animation-speed: 0.75s; + --mdb-spinner-animation-name: spinner-border; + border: var(--mdb-spinner-border-width) solid; + border-right-color: transparent +} + +.spinner-border-sm { + --mdb-spinner-width: 1rem; + --mdb-spinner-height: 1rem; + --mdb-spinner-border-width: 0.2em +} + +@keyframes spinner-grow { + 0% { + transform: scale(0) + } + + 50% { + opacity: 1; + transform: none + } +} + +.spinner-grow { + --mdb-spinner-width: 2rem; + --mdb-spinner-height: 2rem; + --mdb-spinner-vertical-align: -0.125em; + --mdb-spinner-animation-speed: 0.75s; + --mdb-spinner-animation-name: spinner-grow; + background-color: currentcolor; + opacity: 0 +} + +.spinner-grow-sm { + --mdb-spinner-width: 1rem; + --mdb-spinner-height: 1rem +} + +@media(prefers-reduced-motion:reduce) { + .spinner-border,.spinner-grow { + --mdb-spinner-animation-speed: 1.5s + } +} + +.tooltip { + --mdb-tooltip-zindex: 1090; + --mdb-tooltip-max-width: 200px; + --mdb-tooltip-padding-x: 16px; + --mdb-tooltip-padding-y: 6px; + --mdb-tooltip-font-size: 0.875rem; + --mdb-tooltip-color: #fff; + --mdb-tooltip-bg: #6d6d6d; + --mdb-tooltip-border-radius: 0.25rem; + --mdb-tooltip-opacity: 0.9; + --mdb-tooltip-arrow-width: 0.8rem; + --mdb-tooltip-arrow-height: 0.4rem; + z-index: var(--mdb-tooltip-zindex); + display: block; + padding: var(--mdb-tooltip-arrow-height); + margin: var(--mdb-tooltip-margin); + font-family: var(--mdb-font-roboto); + font-style: normal; + font-weight: 400; + line-height: 1.6; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + letter-spacing: normal; + word-break: normal; + white-space: normal; + word-spacing: normal; + line-break: auto; + font-size: var(--mdb-tooltip-font-size); + word-wrap: break-word; + opacity: 0 +} + +.tooltip.show { + opacity: var(--mdb-tooltip-opacity) +} + +.tooltip .tooltip-arrow { + display: block; + width: var(--mdb-tooltip-arrow-width); + height: var(--mdb-tooltip-arrow-height) +} + +.tooltip .tooltip-arrow:before { + position: absolute; + content: ""; + border-color: transparent; + border-style: solid +} + +.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow,.bs-tooltip-top .tooltip-arrow { + bottom: 0 +} + +.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow:before,.bs-tooltip-top .tooltip-arrow:before { + top: -1px; + border-left-width: calc(var(--mdb-tooltip-arrow-width)*0.5); + border-bottom-width: 0; + border-right-width: calc(var(--mdb-tooltip-arrow-width)*0.5); + border-top-width: var(--mdb-tooltip-arrow-height); + border-top-color: var(--mdb-tooltip-bg) +} + +/*!rtl:begin:ignore*/ +.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow,.bs-tooltip-end .tooltip-arrow { + left: 0; + width: var(--mdb-tooltip-arrow-height); + height: var(--mdb-tooltip-arrow-width) +} + +.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow:before,.bs-tooltip-end .tooltip-arrow:before { + right: -1px; + border-left-width: 0; + border-bottom-width: calc(var(--mdb-tooltip-arrow-width)*0.5); + border-right-width: var(--mdb-tooltip-arrow-height); + border-top-width: calc(var(--mdb-tooltip-arrow-width)*0.5); + border-right-color: var(--mdb-tooltip-bg) +} + +/*!rtl:end:ignore*/ +.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow,.bs-tooltip-bottom .tooltip-arrow { + top: 0 +} + +.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow:before,.bs-tooltip-bottom .tooltip-arrow:before { + bottom: -1px; + border-left-width: calc(var(--mdb-tooltip-arrow-width)*0.5); + border-bottom-width: var(--mdb-tooltip-arrow-height); + border-right-width: calc(var(--mdb-tooltip-arrow-width)*0.5); + border-top-width: 0; + border-bottom-color: var(--mdb-tooltip-bg) +} + +/*!rtl:begin:ignore*/ +.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow,.bs-tooltip-start .tooltip-arrow { + right: 0; + width: var(--mdb-tooltip-arrow-height); + height: var(--mdb-tooltip-arrow-width) +} + +.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow:before,.bs-tooltip-start .tooltip-arrow:before { + left: -1px; + border-left-width: var(--mdb-tooltip-arrow-height); + border-bottom-width: calc(var(--mdb-tooltip-arrow-width)*0.5); + border-right-width: 0; + border-top-width: calc(var(--mdb-tooltip-arrow-width)*0.5); + border-left-color: var(--mdb-tooltip-bg) +} + +/*!rtl:end:ignore*/ +.tooltip-inner { + max-width: var(--mdb-tooltip-max-width); + padding: var(--mdb-tooltip-padding-y) var(--mdb-tooltip-padding-x); + color: var(--mdb-tooltip-color); + text-align: center; + background-color: var(--mdb-tooltip-bg); + border-radius: var(--mdb-tooltip-border-radius) +} + +.clearfix:after { + display: block; + clear: both; + content: "" +} + +.text-bg-primary { + color: #fff!important; + background-color: RGBA(59,113,202,var(--mdb-bg-opacity,1))!important +} + +.text-bg-secondary { + color: #000!important; + background-color: RGBA(159,166,178,var(--mdb-bg-opacity,1))!important +} + +.text-bg-success { + color: #000!important; + background-color: RGBA(20,164,77,var(--mdb-bg-opacity,1))!important +} + +.text-bg-danger { + color: #000!important; + background-color: RGBA(220,76,100,var(--mdb-bg-opacity,1))!important +} + +.text-bg-warning { + color: #000!important; + background-color: RGBA(228,161,27,var(--mdb-bg-opacity,1))!important +} + +.text-bg-info { + color: #000!important; + background-color: RGBA(84,180,211,var(--mdb-bg-opacity,1))!important +} + +.text-bg-light { + color: #000!important; + background-color: RGBA(251,251,251,var(--mdb-bg-opacity,1))!important +} + +.text-bg-dark { + color: #fff!important; + background-color: RGBA(51,45,45,var(--mdb-bg-opacity,1))!important +} + +.link-primary { + color: #3b71ca!important +} + +.link-primary:focus,.link-primary:hover { + color: #386bc0!important +} + +.link-secondary { + color: #9fa6b2!important +} + +.link-secondary:focus,.link-secondary:hover { + color: #a4aab6!important +} + +.link-success { + color: #14a44d!important +} + +.link-success:focus,.link-success:hover { + color: #20a956!important +} + +.link-danger { + color: #dc4c64!important +} + +.link-danger:focus,.link-danger:hover { + color: #de556c!important +} + +.link-warning { + color: #e4a11b!important +} + +.link-warning:focus,.link-warning:hover { + color: #e5a626!important +} + +.link-info { + color: #54b4d3!important +} + +.link-info:focus,.link-info:hover { + color: #5db8d5!important +} + +.link-light,.link-light:focus,.link-light:hover { + color: #fbfbfb!important +} + +.link-dark { + color: #332d2d!important +} + +.link-dark:focus,.link-dark:hover { + color: #302b2b!important +} + +.ratio { + position: relative; + width: 100% +} + +.ratio:before { + display: block; + padding-top: var(--mdb-aspect-ratio); + content: "" +} + +.ratio>* { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100% +} + +.ratio-1x1 { + --mdb-aspect-ratio: 100% +} + +.ratio-4x3 { + --mdb-aspect-ratio: 75% +} + +.ratio-16x9 { + --mdb-aspect-ratio: 56.25% +} + +.ratio-21x9 { + --mdb-aspect-ratio: 42.8571428571% +} + +.fixed-top { + top: 0 +} + +.fixed-bottom,.fixed-top { + position: fixed; + right: 0; + left: 0; + z-index: 1030 +} + +.fixed-bottom { + bottom: 0 +} + +.sticky-top { + top: 0 +} + +.sticky-bottom,.sticky-top { + position: -webkit-sticky; + position: sticky; + z-index: 1020 +} + +.sticky-bottom { + bottom: 0 +} + +@media(min-width: 576px) { + .sticky-sm-top { + top:0 + } + + .sticky-sm-bottom,.sticky-sm-top { + position: -webkit-sticky; + position: sticky; + z-index: 1020 + } + + .sticky-sm-bottom { + bottom: 0 + } +} + +@media(min-width: 768px) { + .sticky-md-top { + top:0 + } + + .sticky-md-bottom,.sticky-md-top { + position: -webkit-sticky; + position: sticky; + z-index: 1020 + } + + .sticky-md-bottom { + bottom: 0 + } +} + +@media(min-width: 992px) { + .sticky-lg-top { + top:0 + } + + .sticky-lg-bottom,.sticky-lg-top { + position: -webkit-sticky; + position: sticky; + z-index: 1020 + } + + .sticky-lg-bottom { + bottom: 0 + } +} + +@media(min-width: 1200px) { + .sticky-xl-top { + top:0 + } + + .sticky-xl-bottom,.sticky-xl-top { + position: -webkit-sticky; + position: sticky; + z-index: 1020 + } + + .sticky-xl-bottom { + bottom: 0 + } +} + +@media(min-width: 1400px) { + .sticky-xxl-top { + top:0 + } + + .sticky-xxl-bottom,.sticky-xxl-top { + position: -webkit-sticky; + position: sticky; + z-index: 1020 + } + + .sticky-xxl-bottom { + bottom: 0 + } +} + +.hstack { + flex-direction: row; + align-items: center +} + +.hstack,.vstack { + display: flex; + align-self: stretch +} + +.vstack { + flex: 1 1 auto; + flex-direction: column +} + +.visually-hidden,.visually-hidden-focusable:not(:focus):not(:focus-within) { + position: absolute!important; + width: 1px!important; + height: 1px!important; + padding: 0!important; + margin: -1px!important; + overflow: hidden!important; + clip: rect(0,0,0,0)!important; + white-space: nowrap!important; + border: 0!important +} + +.stretched-link:after { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1; + content: "" +} + +.text-truncate { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap +} + +.vr { + display: inline-block; + align-self: stretch; + width: 1px; + min-height: 1em; + background-color: currentcolor; + opacity: .25 +} + +.align-baseline { + vertical-align: baseline!important +} + +.align-top { + vertical-align: top!important +} + +.align-middle { + vertical-align: middle!important +} + +.align-bottom { + vertical-align: bottom!important +} + +.align-text-bottom { + vertical-align: text-bottom!important +} + +.align-text-top { + vertical-align: text-top!important +} + +.float-start { + float: left!important +} + +.float-end { + float: right!important +} + +.float-none { + float: none!important +} + +.opacity-0 { + opacity: 0!important +} + +.opacity-5 { + opacity: .05!important +} + +.opacity-10 { + opacity: .1!important +} + +.opacity-15 { + opacity: .15!important +} + +.opacity-20 { + opacity: .2!important +} + +.opacity-25 { + opacity: .25!important +} + +.opacity-30 { + opacity: .3!important +} + +.opacity-35 { + opacity: .35!important +} + +.opacity-40 { + opacity: .4!important +} + +.opacity-45 { + opacity: .45!important +} + +.opacity-50 { + opacity: .5!important +} + +.opacity-55 { + opacity: .55!important +} + +.opacity-60 { + opacity: .6!important +} + +.opacity-65 { + opacity: .65!important +} + +.opacity-70 { + opacity: .7!important +} + +.opacity-75 { + opacity: .75!important +} + +.opacity-80 { + opacity: .8!important +} + +.opacity-85 { + opacity: .85!important +} + +.opacity-90 { + opacity: .9!important +} + +.opacity-95 { + opacity: .95!important +} + +.opacity-100 { + opacity: 1!important +} + +.overflow-auto { + overflow: auto!important +} + +.overflow-hidden { + overflow: hidden!important +} + +.overflow-visible { + overflow: visible!important +} + +.overflow-scroll { + overflow: scroll!important +} + +.d-inline { + display: inline!important +} + +.d-inline-block { + display: inline-block!important +} + +.d-block { + display: block!important +} + +.d-grid { + display: grid!important +} + +.d-table { + display: table!important +} + +.d-table-row { + display: table-row!important +} + +.d-table-cell { + display: table-cell!important +} + +.d-flex { + display: flex!important +} + +.d-inline-flex { + display: inline-flex!important +} + +.d-none { + display: none!important +} + +.shadow { + box-shadow: 0 .5rem 1rem rgba(0,0,0,.15)!important +} + +.shadow-sm { + box-shadow: 0 .125rem .25rem rgba(0,0,0,.075)!important +} + +.shadow-lg { + box-shadow: 0 1rem 3rem rgba(0,0,0,.175)!important +} + +.shadow-0,.shadow-none { + box-shadow: none!important +} + +.shadow-1 { + box-shadow: 0 0 2px 0 rgba(0,0,0,.07),0 1px 1px 0 rgba(0,0,0,.04)!important +} + +.shadow-2 { + box-shadow: 0 0 3px 0 rgba(0,0,0,.07),0 2px 2px 0 rgba(0,0,0,.04)!important +} + +.shadow-3 { + box-shadow: 0 2px 6px -1px rgba(0,0,0,.07),0 6px 18px -1px rgba(0,0,0,.04)!important +} + +.shadow-4 { + box-shadow: 0 2px 15px -3px rgba(0,0,0,.07),0 10px 20px -2px rgba(0,0,0,.04)!important +} + +.shadow-5 { + box-shadow: 0 2px 25px -5px rgba(0,0,0,.07),0 25px 21px -5px rgba(0,0,0,.04)!important +} + +.shadow-6 { + box-shadow: 0 2px 35px -12px rgba(0,0,0,.21),0 50px 40px -5px rgba(0,0,0,.04)!important +} + +.shadow-1-soft { + box-shadow: 0 1px 5px 0 rgba(0,0,0,.05)!important +} + +.shadow-2-soft { + box-shadow: 0 2px 10px 0 rgba(0,0,0,.05)!important +} + +.shadow-3-soft { + box-shadow: 0 5px 15px 0 rgba(0,0,0,.05)!important +} + +.shadow-4-soft { + box-shadow: 0 10px 20px 0 rgba(0,0,0,.05)!important +} + +.shadow-5-soft { + box-shadow: 0 15px 30px 0 rgba(0,0,0,.05)!important +} + +.shadow-6-soft { + box-shadow: 0 20px 40px 0 rgba(0,0,0,.05)!important +} + +.shadow-1-strong { + box-shadow: 0 0 2px 0 rgba(0,0,0,.16),0 1px 1px 0 rgba(0,0,0,.1)!important +} + +.shadow-2-strong { + box-shadow: 0 0 3px 0 rgba(0,0,0,.16),0 2px 2px 0 rgba(0,0,0,.1)!important +} + +.shadow-3-strong { + box-shadow: 0 2px 6px -1px rgba(0,0,0,.16),0 6px 18px -1px rgba(0,0,0,.1)!important +} + +.shadow-4-strong { + box-shadow: 0 2px 15px -3px rgba(0,0,0,.16),0 10px 20px -2px rgba(0,0,0,.1)!important +} + +.shadow-5-strong { + box-shadow: 0 2px 25px -5px rgba(0,0,0,.16),0 25px 21px -5px rgba(0,0,0,.1)!important +} + +.shadow-6-strong { + box-shadow: 0 2px 35px -12px rgba(0,0,0,.26),0 50px 40px -5px rgba(0,0,0,.1)!important +} + +.shadow-inner { + box-shadow: inset 0 2px 4px 0 rgba(0,0,0,.06)!important +} + +.position-static { + position: static!important +} + +.position-relative { + position: relative!important +} + +.position-absolute { + position: absolute!important +} + +.position-fixed { + position: fixed!important +} + +.position-sticky { + position: -webkit-sticky!important; + position: sticky!important +} + +.top-0 { + top: 0!important +} + +.top-50 { + top: 50%!important +} + +.top-100 { + top: 100%!important +} + +.bottom-0 { + bottom: 0!important +} + +.bottom-50 { + bottom: 50%!important +} + +.bottom-100 { + bottom: 100%!important +} + +.start-0 { + left: 0!important +} + +.start-50 { + left: 50%!important +} + +.start-100 { + left: 100%!important +} + +.end-0 { + right: 0!important +} + +.end-50 { + right: 50%!important +} + +.end-100 { + right: 100%!important +} + +.translate-middle { + transform: translate(-50%,-50%)!important +} + +.translate-middle-x { + transform: translateX(-50%)!important +} + +.translate-middle-y { + transform: translateY(-50%)!important +} + +.border { + border: var(--mdb-border-width) var(--mdb-border-style) var(--mdb-border-color)!important +} + +.border-0 { + border: 0!important +} + +.border-top { + border-top: var(--mdb-border-width) var(--mdb-border-style) var(--mdb-border-color)!important +} + +.border-top-0 { + border-top: 0!important +} + +.border-end { + border-right: var(--mdb-border-width) var(--mdb-border-style) var(--mdb-border-color)!important +} + +.border-end-0 { + border-right: 0!important +} + +.border-bottom { + border-bottom: var(--mdb-border-width) var(--mdb-border-style) var(--mdb-border-color)!important +} + +.border-bottom-0 { + border-bottom: 0!important +} + +.border-start { + border-left: var(--mdb-border-width) var(--mdb-border-style) var(--mdb-border-color)!important +} + +.border-start-0 { + border-left: 0!important +} + +.border-primary { + --mdb-border-opacity: 1; + border-color: rgba(var(--mdb-primary-rgb),var(--mdb-border-opacity))!important +} + +.border-secondary { + --mdb-border-opacity: 1; + border-color: rgba(var(--mdb-secondary-rgb),var(--mdb-border-opacity))!important +} + +.border-success { + --mdb-border-opacity: 1; + border-color: rgba(var(--mdb-success-rgb),var(--mdb-border-opacity))!important +} + +.border-danger { + --mdb-border-opacity: 1; + border-color: rgba(var(--mdb-danger-rgb),var(--mdb-border-opacity))!important +} + +.border-warning { + --mdb-border-opacity: 1; + border-color: rgba(var(--mdb-warning-rgb),var(--mdb-border-opacity))!important +} + +.border-info { + --mdb-border-opacity: 1; + border-color: rgba(var(--mdb-info-rgb),var(--mdb-border-opacity))!important +} + +.border-light { + --mdb-border-opacity: 1; + border-color: rgba(var(--mdb-light-rgb),var(--mdb-border-opacity))!important +} + +.border-dark { + --mdb-border-opacity: 1; + border-color: rgba(var(--mdb-dark-rgb),var(--mdb-border-opacity))!important +} + +.border-white { + --mdb-border-opacity: 1; + border-color: rgba(var(--mdb-white-rgb),var(--mdb-border-opacity))!important +} + +.border-1 { + --mdb-border-width: 1px +} + +.border-2 { + --mdb-border-width: 2px +} + +.border-3 { + --mdb-border-width: 3px +} + +.border-4 { + --mdb-border-width: 4px +} + +.border-5 { + --mdb-border-width: 5px +} + +.border-opacity-10 { + --mdb-border-opacity: 0.1 +} + +.border-opacity-25 { + --mdb-border-opacity: 0.25 +} + +.border-opacity-50 { + --mdb-border-opacity: 0.5 +} + +.border-opacity-75 { + --mdb-border-opacity: 0.75 +} + +.border-opacity-100 { + --mdb-border-opacity: 1 +} + +.w-25 { + width: 25%!important +} + +.w-50 { + width: 50%!important +} + +.w-75 { + width: 75%!important +} + +.w-100 { + width: 100%!important +} + +.w-auto { + width: auto!important +} + +.mw-100 { + max-width: 100%!important +} + +.vw-100 { + width: 100vw!important +} + +.min-vw-100 { + min-width: 100vw!important +} + +.h-25 { + height: 25%!important +} + +.h-50 { + height: 50%!important +} + +.h-75 { + height: 75%!important +} + +.h-100 { + height: 100%!important +} + +.h-auto { + height: auto!important +} + +.mh-100 { + max-height: 100%!important +} + +.vh-100 { + height: 100vh!important +} + +.min-vh-100 { + min-height: 100vh!important +} + +.flex-fill { + flex: 1 1 auto!important +} + +.flex-row { + flex-direction: row!important +} + +.flex-column { + flex-direction: column!important +} + +.flex-row-reverse { + flex-direction: row-reverse!important +} + +.flex-column-reverse { + flex-direction: column-reverse!important +} + +.flex-grow-0 { + flex-grow: 0!important +} + +.flex-grow-1 { + flex-grow: 1!important +} + +.flex-shrink-0 { + flex-shrink: 0!important +} + +.flex-shrink-1 { + flex-shrink: 1!important +} + +.flex-wrap { + flex-wrap: wrap!important +} + +.flex-nowrap { + flex-wrap: nowrap!important +} + +.flex-wrap-reverse { + flex-wrap: wrap-reverse!important +} + +.justify-content-start { + justify-content: flex-start!important +} + +.justify-content-end { + justify-content: flex-end!important +} + +.justify-content-center { + justify-content: center!important +} + +.justify-content-between { + justify-content: space-between!important +} + +.justify-content-around { + justify-content: space-around!important +} + +.justify-content-evenly { + justify-content: space-evenly!important +} + +.align-items-start { + align-items: flex-start!important +} + +.align-items-end { + align-items: flex-end!important +} + +.align-items-center { + align-items: center!important +} + +.align-items-baseline { + align-items: baseline!important +} + +.align-items-stretch { + align-items: stretch!important +} + +.align-content-start { + align-content: flex-start!important +} + +.align-content-end { + align-content: flex-end!important +} + +.align-content-center { + align-content: center!important +} + +.align-content-between { + align-content: space-between!important +} + +.align-content-around { + align-content: space-around!important +} + +.align-content-stretch { + align-content: stretch!important +} + +.align-self-auto { + align-self: auto!important +} + +.align-self-start { + align-self: flex-start!important +} + +.align-self-end { + align-self: flex-end!important +} + +.align-self-center { + align-self: center!important +} + +.align-self-baseline { + align-self: baseline!important +} + +.align-self-stretch { + align-self: stretch!important +} + +.order-first { + order: -1!important +} + +.order-0 { + order: 0!important +} + +.order-1 { + order: 1!important +} + +.order-2 { + order: 2!important +} + +.order-3 { + order: 3!important +} + +.order-4 { + order: 4!important +} + +.order-5 { + order: 5!important +} + +.order-last { + order: 6!important +} + +.m-0 { + margin: 0!important +} + +.m-1 { + margin: .25rem!important +} + +.m-2 { + margin: .5rem!important +} + +.m-3 { + margin: 1rem!important +} + +.m-4 { + margin: 1.5rem!important +} + +.m-5 { + margin: 3rem!important +} + +.m-auto { + margin: auto!important +} + +.mx-0 { + margin-right: 0!important; + margin-left: 0!important +} + +.mx-1 { + margin-right: .25rem!important; + margin-left: .25rem!important +} + +.mx-2 { + margin-right: .5rem!important; + margin-left: .5rem!important +} + +.mx-3 { + margin-right: 1rem!important; + margin-left: 1rem!important +} + +.mx-4 { + margin-right: 1.5rem!important; + margin-left: 1.5rem!important +} + +.mx-5 { + margin-right: 3rem!important; + margin-left: 3rem!important +} + +.mx-auto { + margin-right: auto!important; + margin-left: auto!important +} + +.my-0 { + margin-top: 0!important; + margin-bottom: 0!important +} + +.my-1 { + margin-top: .25rem!important; + margin-bottom: .25rem!important +} + +.my-2 { + margin-top: .5rem!important; + margin-bottom: .5rem!important +} + +.my-3 { + margin-top: 1rem!important; + margin-bottom: 1rem!important +} + +.my-4 { + margin-top: 1.5rem!important; + margin-bottom: 1.5rem!important +} + +.my-5 { + margin-top: 3rem!important; + margin-bottom: 3rem!important +} + +.my-auto { + margin-top: auto!important; + margin-bottom: auto!important +} + +.mt-0 { + margin-top: 0!important +} + +.mt-1 { + margin-top: .25rem!important +} + +.mt-2 { + margin-top: .5rem!important +} + +.mt-3 { + margin-top: 1rem!important +} + +.mt-4 { + margin-top: 1.5rem!important +} + +.mt-5 { + margin-top: 3rem!important +} + +.mt-auto { + margin-top: auto!important +} + +.me-0 { + margin-right: 0!important +} + +.me-1 { + margin-right: .25rem!important +} + +.me-2 { + margin-right: .5rem!important +} + +.me-3 { + margin-right: 1rem!important +} + +.me-4 { + margin-right: 1.5rem!important +} + +.me-5 { + margin-right: 3rem!important +} + +.me-auto { + margin-right: auto!important +} + +.mb-0 { + margin-bottom: 0!important +} + +.mb-1 { + margin-bottom: .25rem!important +} + +.mb-2 { + margin-bottom: .5rem!important +} + +.mb-3 { + margin-bottom: 1rem!important +} + +.mb-4 { + margin-bottom: 1.5rem!important +} + +.mb-5 { + margin-bottom: 3rem!important +} + +.mb-auto { + margin-bottom: auto!important +} + +.mb-6 { + margin-bottom: 3.5rem!important +} + +.mb-7 { + margin-bottom: 4rem!important +} + +.mb-8 { + margin-bottom: 5rem!important +} + +.mb-9 { + margin-bottom: 6rem!important +} + +.mb-10 { + margin-bottom: 8rem!important +} + +.mb-11 { + margin-bottom: 10rem!important +} + +.mb-12 { + margin-bottom: 12rem!important +} + +.mb-13 { + margin-bottom: 14rem!important +} + +.mb-14 { + margin-bottom: 16rem!important +} + +.ms-0 { + margin-left: 0!important +} + +.ms-1 { + margin-left: .25rem!important +} + +.ms-2 { + margin-left: .5rem!important +} + +.ms-3 { + margin-left: 1rem!important +} + +.ms-4 { + margin-left: 1.5rem!important +} + +.ms-5 { + margin-left: 3rem!important +} + +.ms-auto { + margin-left: auto!important +} + +.m-n1 { + margin: -.25rem!important +} + +.m-n2 { + margin: -.5rem!important +} + +.m-n3 { + margin: -1rem!important +} + +.m-n4 { + margin: -1.5rem!important +} + +.m-n5 { + margin: -3rem!important +} + +.mx-n1 { + margin-right: -.25rem!important; + margin-left: -.25rem!important +} + +.mx-n2 { + margin-right: -.5rem!important; + margin-left: -.5rem!important +} + +.mx-n3 { + margin-right: -1rem!important; + margin-left: -1rem!important +} + +.mx-n4 { + margin-right: -1.5rem!important; + margin-left: -1.5rem!important +} + +.mx-n5 { + margin-right: -3rem!important; + margin-left: -3rem!important +} + +.my-n1 { + margin-top: -.25rem!important; + margin-bottom: -.25rem!important +} + +.my-n2 { + margin-top: -.5rem!important; + margin-bottom: -.5rem!important +} + +.my-n3 { + margin-top: -1rem!important; + margin-bottom: -1rem!important +} + +.my-n4 { + margin-top: -1.5rem!important; + margin-bottom: -1.5rem!important +} + +.my-n5 { + margin-top: -3rem!important; + margin-bottom: -3rem!important +} + +.mt-n1 { + margin-top: -.25rem!important +} + +.mt-n2 { + margin-top: -.5rem!important +} + +.mt-n3 { + margin-top: -1rem!important +} + +.mt-n4 { + margin-top: -1.5rem!important +} + +.mt-n5 { + margin-top: -3rem!important +} + +.me-n1 { + margin-right: -.25rem!important +} + +.me-n2 { + margin-right: -.5rem!important +} + +.me-n3 { + margin-right: -1rem!important +} + +.me-n4 { + margin-right: -1.5rem!important +} + +.me-n5 { + margin-right: -3rem!important +} + +.mb-n1 { + margin-bottom: -.25rem!important +} + +.mb-n2 { + margin-bottom: -.5rem!important +} + +.mb-n3 { + margin-bottom: -1rem!important +} + +.mb-n4 { + margin-bottom: -1.5rem!important +} + +.mb-n5 { + margin-bottom: -3rem!important +} + +.ms-n1 { + margin-left: -.25rem!important +} + +.ms-n2 { + margin-left: -.5rem!important +} + +.ms-n3 { + margin-left: -1rem!important +} + +.ms-n4 { + margin-left: -1.5rem!important +} + +.ms-n5 { + margin-left: -3rem!important +} + +.p-0 { + padding: 0!important +} + +.p-1 { + padding: .25rem!important +} + +.p-2 { + padding: .5rem!important +} + +.p-3 { + padding: 1rem!important +} + +.p-4 { + padding: 1.5rem!important +} + +.p-5 { + padding: 3rem!important +} + +.px-0 { + padding-right: 0!important; + padding-left: 0!important +} + +.px-1 { + padding-right: .25rem!important; + padding-left: .25rem!important +} + +.px-2 { + padding-right: .5rem!important; + padding-left: .5rem!important +} + +.px-3 { + padding-right: 1rem!important; + padding-left: 1rem!important +} + +.px-4 { + padding-right: 1.5rem!important; + padding-left: 1.5rem!important +} + +.px-5 { + padding-right: 3rem!important; + padding-left: 3rem!important +} + +.py-0 { + padding-top: 0!important; + padding-bottom: 0!important +} + +.py-1 { + padding-top: .25rem!important; + padding-bottom: .25rem!important +} + +.py-2 { + padding-top: .5rem!important; + padding-bottom: .5rem!important +} + +.py-3 { + padding-top: 1rem!important; + padding-bottom: 1rem!important +} + +.py-4 { + padding-top: 1.5rem!important; + padding-bottom: 1.5rem!important +} + +.py-5 { + padding-top: 3rem!important; + padding-bottom: 3rem!important +} + +.pt-0 { + padding-top: 0!important +} + +.pt-1 { + padding-top: .25rem!important +} + +.pt-2 { + padding-top: .5rem!important +} + +.pt-3 { + padding-top: 1rem!important +} + +.pt-4 { + padding-top: 1.5rem!important +} + +.pt-5 { + padding-top: 3rem!important +} + +.pe-0 { + padding-right: 0!important +} + +.pe-1 { + padding-right: .25rem!important +} + +.pe-2 { + padding-right: .5rem!important +} + +.pe-3 { + padding-right: 1rem!important +} + +.pe-4 { + padding-right: 1.5rem!important +} + +.pe-5 { + padding-right: 3rem!important +} + +.pb-0 { + padding-bottom: 0!important +} + +.pb-1 { + padding-bottom: .25rem!important +} + +.pb-2 { + padding-bottom: .5rem!important +} + +.pb-3 { + padding-bottom: 1rem!important +} + +.pb-4 { + padding-bottom: 1.5rem!important +} + +.pb-5 { + padding-bottom: 3rem!important +} + +.ps-0 { + padding-left: 0!important +} + +.ps-1 { + padding-left: .25rem!important +} + +.ps-2 { + padding-left: .5rem!important +} + +.ps-3 { + padding-left: 1rem!important +} + +.ps-4 { + padding-left: 1.5rem!important +} + +.ps-5 { + padding-left: 3rem!important +} + +.gap-0 { + gap: 0!important +} + +.gap-1 { + gap: .25rem!important +} + +.gap-2 { + gap: .5rem!important +} + +.gap-3 { + gap: 1rem!important +} + +.gap-4 { + gap: 1.5rem!important +} + +.gap-5 { + gap: 3rem!important +} + +.font-monospace { + font-family: var(--mdb-font-monospace)!important +} + +.fs-1 { + font-size: calc(1.375rem + 1.5vw)!important +} + +.fs-2 { + font-size: calc(1.325rem + .9vw)!important +} + +.fs-3 { + font-size: calc(1.3rem + .6vw)!important +} + +.fs-4 { + font-size: calc(1.275rem + .3vw)!important +} + +.fs-5 { + font-size: 1.25rem!important +} + +.fs-6 { + font-size: 1rem!important +} + +.fst-italic { + font-style: italic!important +} + +.fst-normal { + font-style: normal!important +} + +.fw-light { + font-weight: 300!important +} + +.fw-lighter { + font-weight: lighter!important +} + +.fw-normal { + font-weight: 400!important +} + +.fw-bold { + font-weight: 700!important +} + +.fw-semibold { + font-weight: 600!important +} + +.fw-bolder { + font-weight: bolder!important +} + +.lh-1 { + line-height: 1!important +} + +.lh-sm { + line-height: 1.25!important +} + +.lh-base { + line-height: 1.6!important +} + +.lh-lg { + line-height: 2!important +} + +.text-start { + text-align: left!important +} + +.text-end { + text-align: right!important +} + +.text-center { + text-align: center!important +} + +.text-decoration-none { + text-decoration: none!important +} + +.text-decoration-underline { + text-decoration: underline!important +} + +.text-decoration-line-through { + text-decoration: line-through!important +} + +.text-lowercase { + text-transform: lowercase!important +} + +.text-uppercase { + text-transform: uppercase!important +} + +.text-capitalize { + text-transform: capitalize!important +} + +.text-wrap { + white-space: normal!important +} + +.text-nowrap { + white-space: nowrap!important +} + +/*!rtl:begin:remove*/ +.text-break { + word-wrap: break-word!important; + word-break: break-word!important +} + +/*!rtl:end:remove*/ +.text-primary { + --mdb-text-opacity: 1; + color: rgba(var(--mdb-primary-rgb),var(--mdb-text-opacity))!important +} + +.text-secondary { + --mdb-text-opacity: 1; + color: rgba(var(--mdb-secondary-rgb),var(--mdb-text-opacity))!important +} + +.text-success { + --mdb-text-opacity: 1; + color: rgba(var(--mdb-success-rgb),var(--mdb-text-opacity))!important +} + +.text-danger { + --mdb-text-opacity: 1; + color: rgba(var(--mdb-danger-rgb),var(--mdb-text-opacity))!important +} + +.text-warning { + --mdb-text-opacity: 1; + color: rgba(var(--mdb-warning-rgb),var(--mdb-text-opacity))!important +} + +.text-info { + --mdb-text-opacity: 1; + color: rgba(var(--mdb-info-rgb),var(--mdb-text-opacity))!important +} + +.text-light { + --mdb-text-opacity: 1; + color: rgba(var(--mdb-light-rgb),var(--mdb-text-opacity))!important +} + +.text-dark { + --mdb-text-opacity: 1; + color: rgba(var(--mdb-dark-rgb),var(--mdb-text-opacity))!important +} + +.text-black { + --mdb-text-opacity: 1; + color: rgba(var(--mdb-black-rgb),var(--mdb-text-opacity))!important +} + +.text-white { + --mdb-text-opacity: 1; + color: rgba(var(--mdb-white-rgb),var(--mdb-text-opacity))!important +} + +.text-body { + --mdb-text-opacity: 1; + color: rgba(var(--mdb-body-color-rgb),var(--mdb-text-opacity))!important +} + +.text-muted { + --mdb-text-opacity: 1; + color: #757575!important +} + +.text-black-50 { + --mdb-text-opacity: 1; + color: rgba(0,0,0,.5)!important +} + +.text-white-50 { + --mdb-text-opacity: 1; + color: hsla(0,0%,100%,.5)!important +} + +.text-reset { + --mdb-text-opacity: 1; + color: inherit!important +} + +.text-opacity-25 { + --mdb-text-opacity: 0.25 +} + +.text-opacity-50 { + --mdb-text-opacity: 0.5 +} + +.text-opacity-75 { + --mdb-text-opacity: 0.75 +} + +.text-opacity-100 { + --mdb-text-opacity: 1 +} + +.bg-primary { + --mdb-bg-opacity: 1; + background-color: rgba(var(--mdb-primary-rgb),var(--mdb-bg-opacity))!important +} + +.bg-secondary { + --mdb-bg-opacity: 1; + background-color: rgba(var(--mdb-secondary-rgb),var(--mdb-bg-opacity))!important +} + +.bg-success { + --mdb-bg-opacity: 1; + background-color: rgba(var(--mdb-success-rgb),var(--mdb-bg-opacity))!important +} + +.bg-danger { + --mdb-bg-opacity: 1; + background-color: rgba(var(--mdb-danger-rgb),var(--mdb-bg-opacity))!important +} + +.bg-warning { + --mdb-bg-opacity: 1; + background-color: rgba(var(--mdb-warning-rgb),var(--mdb-bg-opacity))!important +} + +.bg-info { + --mdb-bg-opacity: 1; + background-color: rgba(var(--mdb-info-rgb),var(--mdb-bg-opacity))!important +} + +.bg-light { + --mdb-bg-opacity: 1; + background-color: rgba(var(--mdb-light-rgb),var(--mdb-bg-opacity))!important +} + +.bg-dark { + --mdb-bg-opacity: 1; + background-color: rgba(var(--mdb-dark-rgb),var(--mdb-bg-opacity))!important +} + +.bg-black { + --mdb-bg-opacity: 1; + background-color: rgba(var(--mdb-black-rgb),var(--mdb-bg-opacity))!important +} + +.bg-white { + --mdb-bg-opacity: 1; + background-color: rgba(var(--mdb-white-rgb),var(--mdb-bg-opacity))!important +} + +.bg-body { + --mdb-bg-opacity: 1; + background-color: rgba(var(--mdb-body-bg-rgb),var(--mdb-bg-opacity))!important +} + +.bg-transparent { + --mdb-bg-opacity: 1; + background-color: transparent!important +} + +.bg-opacity-10 { + --mdb-bg-opacity: 0.1 +} + +.bg-opacity-25 { + --mdb-bg-opacity: 0.25 +} + +.bg-opacity-50 { + --mdb-bg-opacity: 0.5 +} + +.bg-opacity-75 { + --mdb-bg-opacity: 0.75 +} + +.bg-opacity-100 { + --mdb-bg-opacity: 1 +} + +.bg-gradient { + background-image: var(--mdb-gradient)!important +} + +.user-select-all { + -webkit-user-select: all!important; + -moz-user-select: all!important; + user-select: all!important +} + +.user-select-auto { + -webkit-user-select: auto!important; + -moz-user-select: auto!important; + user-select: auto!important +} + +.user-select-none { + -webkit-user-select: none!important; + -moz-user-select: none!important; + user-select: none!important +} + +.pe-none { + pointer-events: none!important +} + +.pe-auto { + pointer-events: auto!important +} + +.rounded { + border-radius: var(--mdb-border-radius)!important +} + +.rounded-0 { + border-radius: 0!important +} + +.rounded-1 { + border-radius: var(--mdb-border-radius-sm)!important +} + +.rounded-2 { + border-radius: var(--mdb-border-radius)!important +} + +.rounded-3 { + border-radius: var(--mdb-border-radius-lg)!important +} + +.rounded-4 { + border-radius: .375rem!important +} + +.rounded-5 { + border-radius: .5rem!important +} + +.rounded-circle { + border-radius: 50%!important +} + +.rounded-pill { + border-radius: var(--mdb-border-radius-pill)!important +} + +.rounded-6 { + border-radius: .75rem!important +} + +.rounded-7 { + border-radius: 1rem!important +} + +.rounded-8 { + border-radius: 1.25rem!important +} + +.rounded-9 { + border-radius: 1.5rem!important +} + +.rounded-top { + border-top-left-radius: var(--mdb-border-radius)!important +} + +.rounded-end,.rounded-top { + border-top-right-radius: var(--mdb-border-radius)!important +} + +.rounded-bottom,.rounded-end { + border-bottom-right-radius: var(--mdb-border-radius)!important +} + +.rounded-bottom,.rounded-start { + border-bottom-left-radius: var(--mdb-border-radius)!important +} + +.rounded-start { + border-top-left-radius: var(--mdb-border-radius)!important +} + +.visible { + visibility: visible!important +} + +.invisible { + visibility: hidden!important +} + +.ls-tighter { + letter-spacing: -.05em!important +} + +.ls-tight { + letter-spacing: -.025em!important +} + +.ls-normal { + letter-spacing: 0!important +} + +.ls-wide { + letter-spacing: .025em!important +} + +.ls-wider { + letter-spacing: .05em!important +} + +.ls-widest { + letter-spacing: .1em!important +} + +.object-cover { + -o-object-fit: cover!important; + object-fit: cover!important +} + +.object-top { + -o-object-position: top!important; + object-position: top!important +} + +.object-center { + -o-object-position: center!important; + object-position: center!important +} + +.object-bottom { + -o-object-position: bottom!important; + object-position: bottom!important +} + +@media(min-width: 576px) { + .float-sm-start { + float:left!important + } + + .float-sm-end { + float: right!important + } + + .float-sm-none { + float: none!important + } + + .d-sm-inline { + display: inline!important + } + + .d-sm-inline-block { + display: inline-block!important + } + + .d-sm-block { + display: block!important + } + + .d-sm-grid { + display: grid!important + } + + .d-sm-table { + display: table!important + } + + .d-sm-table-row { + display: table-row!important + } + + .d-sm-table-cell { + display: table-cell!important + } + + .d-sm-flex { + display: flex!important + } + + .d-sm-inline-flex { + display: inline-flex!important + } + + .d-sm-none { + display: none!important + } + + .flex-sm-fill { + flex: 1 1 auto!important + } + + .flex-sm-row { + flex-direction: row!important + } + + .flex-sm-column { + flex-direction: column!important + } + + .flex-sm-row-reverse { + flex-direction: row-reverse!important + } + + .flex-sm-column-reverse { + flex-direction: column-reverse!important + } + + .flex-sm-grow-0 { + flex-grow: 0!important + } + + .flex-sm-grow-1 { + flex-grow: 1!important + } + + .flex-sm-shrink-0 { + flex-shrink: 0!important + } + + .flex-sm-shrink-1 { + flex-shrink: 1!important + } + + .flex-sm-wrap { + flex-wrap: wrap!important + } + + .flex-sm-nowrap { + flex-wrap: nowrap!important + } + + .flex-sm-wrap-reverse { + flex-wrap: wrap-reverse!important + } + + .justify-content-sm-start { + justify-content: flex-start!important + } + + .justify-content-sm-end { + justify-content: flex-end!important + } + + .justify-content-sm-center { + justify-content: center!important + } + + .justify-content-sm-between { + justify-content: space-between!important + } + + .justify-content-sm-around { + justify-content: space-around!important + } + + .justify-content-sm-evenly { + justify-content: space-evenly!important + } + + .align-items-sm-start { + align-items: flex-start!important + } + + .align-items-sm-end { + align-items: flex-end!important + } + + .align-items-sm-center { + align-items: center!important + } + + .align-items-sm-baseline { + align-items: baseline!important + } + + .align-items-sm-stretch { + align-items: stretch!important + } + + .align-content-sm-start { + align-content: flex-start!important + } + + .align-content-sm-end { + align-content: flex-end!important + } + + .align-content-sm-center { + align-content: center!important + } + + .align-content-sm-between { + align-content: space-between!important + } + + .align-content-sm-around { + align-content: space-around!important + } + + .align-content-sm-stretch { + align-content: stretch!important + } + + .align-self-sm-auto { + align-self: auto!important + } + + .align-self-sm-start { + align-self: flex-start!important + } + + .align-self-sm-end { + align-self: flex-end!important + } + + .align-self-sm-center { + align-self: center!important + } + + .align-self-sm-baseline { + align-self: baseline!important + } + + .align-self-sm-stretch { + align-self: stretch!important + } + + .order-sm-first { + order: -1!important + } + + .order-sm-0 { + order: 0!important + } + + .order-sm-1 { + order: 1!important + } + + .order-sm-2 { + order: 2!important + } + + .order-sm-3 { + order: 3!important + } + + .order-sm-4 { + order: 4!important + } + + .order-sm-5 { + order: 5!important + } + + .order-sm-last { + order: 6!important + } + + .m-sm-0 { + margin: 0!important + } + + .m-sm-1 { + margin: .25rem!important + } + + .m-sm-2 { + margin: .5rem!important + } + + .m-sm-3 { + margin: 1rem!important + } + + .m-sm-4 { + margin: 1.5rem!important + } + + .m-sm-5 { + margin: 3rem!important + } + + .m-sm-auto { + margin: auto!important + } + + .mx-sm-0 { + margin-right: 0!important; + margin-left: 0!important + } + + .mx-sm-1 { + margin-right: .25rem!important; + margin-left: .25rem!important + } + + .mx-sm-2 { + margin-right: .5rem!important; + margin-left: .5rem!important + } + + .mx-sm-3 { + margin-right: 1rem!important; + margin-left: 1rem!important + } + + .mx-sm-4 { + margin-right: 1.5rem!important; + margin-left: 1.5rem!important + } + + .mx-sm-5 { + margin-right: 3rem!important; + margin-left: 3rem!important + } + + .mx-sm-auto { + margin-right: auto!important; + margin-left: auto!important + } + + .my-sm-0 { + margin-top: 0!important; + margin-bottom: 0!important + } + + .my-sm-1 { + margin-top: .25rem!important; + margin-bottom: .25rem!important + } + + .my-sm-2 { + margin-top: .5rem!important; + margin-bottom: .5rem!important + } + + .my-sm-3 { + margin-top: 1rem!important; + margin-bottom: 1rem!important + } + + .my-sm-4 { + margin-top: 1.5rem!important; + margin-bottom: 1.5rem!important + } + + .my-sm-5 { + margin-top: 3rem!important; + margin-bottom: 3rem!important + } + + .my-sm-auto { + margin-top: auto!important; + margin-bottom: auto!important + } + + .mt-sm-0 { + margin-top: 0!important + } + + .mt-sm-1 { + margin-top: .25rem!important + } + + .mt-sm-2 { + margin-top: .5rem!important + } + + .mt-sm-3 { + margin-top: 1rem!important + } + + .mt-sm-4 { + margin-top: 1.5rem!important + } + + .mt-sm-5 { + margin-top: 3rem!important + } + + .mt-sm-auto { + margin-top: auto!important + } + + .me-sm-0 { + margin-right: 0!important + } + + .me-sm-1 { + margin-right: .25rem!important + } + + .me-sm-2 { + margin-right: .5rem!important + } + + .me-sm-3 { + margin-right: 1rem!important + } + + .me-sm-4 { + margin-right: 1.5rem!important + } + + .me-sm-5 { + margin-right: 3rem!important + } + + .me-sm-auto { + margin-right: auto!important + } + + .mb-sm-0 { + margin-bottom: 0!important + } + + .mb-sm-1 { + margin-bottom: .25rem!important + } + + .mb-sm-2 { + margin-bottom: .5rem!important + } + + .mb-sm-3 { + margin-bottom: 1rem!important + } + + .mb-sm-4 { + margin-bottom: 1.5rem!important + } + + .mb-sm-5 { + margin-bottom: 3rem!important + } + + .mb-sm-auto { + margin-bottom: auto!important + } + + .mb-sm-6 { + margin-bottom: 3.5rem!important + } + + .mb-sm-7 { + margin-bottom: 4rem!important + } + + .mb-sm-8 { + margin-bottom: 5rem!important + } + + .mb-sm-9 { + margin-bottom: 6rem!important + } + + .mb-sm-10 { + margin-bottom: 8rem!important + } + + .mb-sm-11 { + margin-bottom: 10rem!important + } + + .mb-sm-12 { + margin-bottom: 12rem!important + } + + .mb-sm-13 { + margin-bottom: 14rem!important + } + + .mb-sm-14 { + margin-bottom: 16rem!important + } + + .ms-sm-0 { + margin-left: 0!important + } + + .ms-sm-1 { + margin-left: .25rem!important + } + + .ms-sm-2 { + margin-left: .5rem!important + } + + .ms-sm-3 { + margin-left: 1rem!important + } + + .ms-sm-4 { + margin-left: 1.5rem!important + } + + .ms-sm-5 { + margin-left: 3rem!important + } + + .ms-sm-auto { + margin-left: auto!important + } + + .m-sm-n1 { + margin: -.25rem!important + } + + .m-sm-n2 { + margin: -.5rem!important + } + + .m-sm-n3 { + margin: -1rem!important + } + + .m-sm-n4 { + margin: -1.5rem!important + } + + .m-sm-n5 { + margin: -3rem!important + } + + .mx-sm-n1 { + margin-right: -.25rem!important; + margin-left: -.25rem!important + } + + .mx-sm-n2 { + margin-right: -.5rem!important; + margin-left: -.5rem!important + } + + .mx-sm-n3 { + margin-right: -1rem!important; + margin-left: -1rem!important + } + + .mx-sm-n4 { + margin-right: -1.5rem!important; + margin-left: -1.5rem!important + } + + .mx-sm-n5 { + margin-right: -3rem!important; + margin-left: -3rem!important + } + + .my-sm-n1 { + margin-top: -.25rem!important; + margin-bottom: -.25rem!important + } + + .my-sm-n2 { + margin-top: -.5rem!important; + margin-bottom: -.5rem!important + } + + .my-sm-n3 { + margin-top: -1rem!important; + margin-bottom: -1rem!important + } + + .my-sm-n4 { + margin-top: -1.5rem!important; + margin-bottom: -1.5rem!important + } + + .my-sm-n5 { + margin-top: -3rem!important; + margin-bottom: -3rem!important + } + + .mt-sm-n1 { + margin-top: -.25rem!important + } + + .mt-sm-n2 { + margin-top: -.5rem!important + } + + .mt-sm-n3 { + margin-top: -1rem!important + } + + .mt-sm-n4 { + margin-top: -1.5rem!important + } + + .mt-sm-n5 { + margin-top: -3rem!important + } + + .me-sm-n1 { + margin-right: -.25rem!important + } + + .me-sm-n2 { + margin-right: -.5rem!important + } + + .me-sm-n3 { + margin-right: -1rem!important + } + + .me-sm-n4 { + margin-right: -1.5rem!important + } + + .me-sm-n5 { + margin-right: -3rem!important + } + + .mb-sm-n1 { + margin-bottom: -.25rem!important + } + + .mb-sm-n2 { + margin-bottom: -.5rem!important + } + + .mb-sm-n3 { + margin-bottom: -1rem!important + } + + .mb-sm-n4 { + margin-bottom: -1.5rem!important + } + + .mb-sm-n5 { + margin-bottom: -3rem!important + } + + .ms-sm-n1 { + margin-left: -.25rem!important + } + + .ms-sm-n2 { + margin-left: -.5rem!important + } + + .ms-sm-n3 { + margin-left: -1rem!important + } + + .ms-sm-n4 { + margin-left: -1.5rem!important + } + + .ms-sm-n5 { + margin-left: -3rem!important + } + + .p-sm-0 { + padding: 0!important + } + + .p-sm-1 { + padding: .25rem!important + } + + .p-sm-2 { + padding: .5rem!important + } + + .p-sm-3 { + padding: 1rem!important + } + + .p-sm-4 { + padding: 1.5rem!important + } + + .p-sm-5 { + padding: 3rem!important + } + + .px-sm-0 { + padding-right: 0!important; + padding-left: 0!important + } + + .px-sm-1 { + padding-right: .25rem!important; + padding-left: .25rem!important + } + + .px-sm-2 { + padding-right: .5rem!important; + padding-left: .5rem!important + } + + .px-sm-3 { + padding-right: 1rem!important; + padding-left: 1rem!important + } + + .px-sm-4 { + padding-right: 1.5rem!important; + padding-left: 1.5rem!important + } + + .px-sm-5 { + padding-right: 3rem!important; + padding-left: 3rem!important + } + + .py-sm-0 { + padding-top: 0!important; + padding-bottom: 0!important + } + + .py-sm-1 { + padding-top: .25rem!important; + padding-bottom: .25rem!important + } + + .py-sm-2 { + padding-top: .5rem!important; + padding-bottom: .5rem!important + } + + .py-sm-3 { + padding-top: 1rem!important; + padding-bottom: 1rem!important + } + + .py-sm-4 { + padding-top: 1.5rem!important; + padding-bottom: 1.5rem!important + } + + .py-sm-5 { + padding-top: 3rem!important; + padding-bottom: 3rem!important + } + + .pt-sm-0 { + padding-top: 0!important + } + + .pt-sm-1 { + padding-top: .25rem!important + } + + .pt-sm-2 { + padding-top: .5rem!important + } + + .pt-sm-3 { + padding-top: 1rem!important + } + + .pt-sm-4 { + padding-top: 1.5rem!important + } + + .pt-sm-5 { + padding-top: 3rem!important + } + + .pe-sm-0 { + padding-right: 0!important + } + + .pe-sm-1 { + padding-right: .25rem!important + } + + .pe-sm-2 { + padding-right: .5rem!important + } + + .pe-sm-3 { + padding-right: 1rem!important + } + + .pe-sm-4 { + padding-right: 1.5rem!important + } + + .pe-sm-5 { + padding-right: 3rem!important + } + + .pb-sm-0 { + padding-bottom: 0!important + } + + .pb-sm-1 { + padding-bottom: .25rem!important + } + + .pb-sm-2 { + padding-bottom: .5rem!important + } + + .pb-sm-3 { + padding-bottom: 1rem!important + } + + .pb-sm-4 { + padding-bottom: 1.5rem!important + } + + .pb-sm-5 { + padding-bottom: 3rem!important + } + + .ps-sm-0 { + padding-left: 0!important + } + + .ps-sm-1 { + padding-left: .25rem!important + } + + .ps-sm-2 { + padding-left: .5rem!important + } + + .ps-sm-3 { + padding-left: 1rem!important + } + + .ps-sm-4 { + padding-left: 1.5rem!important + } + + .ps-sm-5 { + padding-left: 3rem!important + } + + .gap-sm-0 { + gap: 0!important + } + + .gap-sm-1 { + gap: .25rem!important + } + + .gap-sm-2 { + gap: .5rem!important + } + + .gap-sm-3 { + gap: 1rem!important + } + + .gap-sm-4 { + gap: 1.5rem!important + } + + .gap-sm-5 { + gap: 3rem!important + } + + .text-sm-start { + text-align: left!important + } + + .text-sm-end { + text-align: right!important + } + + .text-sm-center { + text-align: center!important + } +} + +@media(min-width: 768px) { + .float-md-start { + float:left!important + } + + .float-md-end { + float: right!important + } + + .float-md-none { + float: none!important + } + + .d-md-inline { + display: inline!important + } + + .d-md-inline-block { + display: inline-block!important + } + + .d-md-block { + display: block!important + } + + .d-md-grid { + display: grid!important + } + + .d-md-table { + display: table!important + } + + .d-md-table-row { + display: table-row!important + } + + .d-md-table-cell { + display: table-cell!important + } + + .d-md-flex { + display: flex!important + } + + .d-md-inline-flex { + display: inline-flex!important + } + + .d-md-none { + display: none!important + } + + .flex-md-fill { + flex: 1 1 auto!important + } + + .flex-md-row { + flex-direction: row!important + } + + .flex-md-column { + flex-direction: column!important + } + + .flex-md-row-reverse { + flex-direction: row-reverse!important + } + + .flex-md-column-reverse { + flex-direction: column-reverse!important + } + + .flex-md-grow-0 { + flex-grow: 0!important + } + + .flex-md-grow-1 { + flex-grow: 1!important + } + + .flex-md-shrink-0 { + flex-shrink: 0!important + } + + .flex-md-shrink-1 { + flex-shrink: 1!important + } + + .flex-md-wrap { + flex-wrap: wrap!important + } + + .flex-md-nowrap { + flex-wrap: nowrap!important + } + + .flex-md-wrap-reverse { + flex-wrap: wrap-reverse!important + } + + .justify-content-md-start { + justify-content: flex-start!important + } + + .justify-content-md-end { + justify-content: flex-end!important + } + + .justify-content-md-center { + justify-content: center!important + } + + .justify-content-md-between { + justify-content: space-between!important + } + + .justify-content-md-around { + justify-content: space-around!important + } + + .justify-content-md-evenly { + justify-content: space-evenly!important + } + + .align-items-md-start { + align-items: flex-start!important + } + + .align-items-md-end { + align-items: flex-end!important + } + + .align-items-md-center { + align-items: center!important + } + + .align-items-md-baseline { + align-items: baseline!important + } + + .align-items-md-stretch { + align-items: stretch!important + } + + .align-content-md-start { + align-content: flex-start!important + } + + .align-content-md-end { + align-content: flex-end!important + } + + .align-content-md-center { + align-content: center!important + } + + .align-content-md-between { + align-content: space-between!important + } + + .align-content-md-around { + align-content: space-around!important + } + + .align-content-md-stretch { + align-content: stretch!important + } + + .align-self-md-auto { + align-self: auto!important + } + + .align-self-md-start { + align-self: flex-start!important + } + + .align-self-md-end { + align-self: flex-end!important + } + + .align-self-md-center { + align-self: center!important + } + + .align-self-md-baseline { + align-self: baseline!important + } + + .align-self-md-stretch { + align-self: stretch!important + } + + .order-md-first { + order: -1!important + } + + .order-md-0 { + order: 0!important + } + + .order-md-1 { + order: 1!important + } + + .order-md-2 { + order: 2!important + } + + .order-md-3 { + order: 3!important + } + + .order-md-4 { + order: 4!important + } + + .order-md-5 { + order: 5!important + } + + .order-md-last { + order: 6!important + } + + .m-md-0 { + margin: 0!important + } + + .m-md-1 { + margin: .25rem!important + } + + .m-md-2 { + margin: .5rem!important + } + + .m-md-3 { + margin: 1rem!important + } + + .m-md-4 { + margin: 1.5rem!important + } + + .m-md-5 { + margin: 3rem!important + } + + .m-md-auto { + margin: auto!important + } + + .mx-md-0 { + margin-right: 0!important; + margin-left: 0!important + } + + .mx-md-1 { + margin-right: .25rem!important; + margin-left: .25rem!important + } + + .mx-md-2 { + margin-right: .5rem!important; + margin-left: .5rem!important + } + + .mx-md-3 { + margin-right: 1rem!important; + margin-left: 1rem!important + } + + .mx-md-4 { + margin-right: 1.5rem!important; + margin-left: 1.5rem!important + } + + .mx-md-5 { + margin-right: 3rem!important; + margin-left: 3rem!important + } + + .mx-md-auto { + margin-right: auto!important; + margin-left: auto!important + } + + .my-md-0 { + margin-top: 0!important; + margin-bottom: 0!important + } + + .my-md-1 { + margin-top: .25rem!important; + margin-bottom: .25rem!important + } + + .my-md-2 { + margin-top: .5rem!important; + margin-bottom: .5rem!important + } + + .my-md-3 { + margin-top: 1rem!important; + margin-bottom: 1rem!important + } + + .my-md-4 { + margin-top: 1.5rem!important; + margin-bottom: 1.5rem!important + } + + .my-md-5 { + margin-top: 3rem!important; + margin-bottom: 3rem!important + } + + .my-md-auto { + margin-top: auto!important; + margin-bottom: auto!important + } + + .mt-md-0 { + margin-top: 0!important + } + + .mt-md-1 { + margin-top: .25rem!important + } + + .mt-md-2 { + margin-top: .5rem!important + } + + .mt-md-3 { + margin-top: 1rem!important + } + + .mt-md-4 { + margin-top: 1.5rem!important + } + + .mt-md-5 { + margin-top: 3rem!important + } + + .mt-md-auto { + margin-top: auto!important + } + + .me-md-0 { + margin-right: 0!important + } + + .me-md-1 { + margin-right: .25rem!important + } + + .me-md-2 { + margin-right: .5rem!important + } + + .me-md-3 { + margin-right: 1rem!important + } + + .me-md-4 { + margin-right: 1.5rem!important + } + + .me-md-5 { + margin-right: 3rem!important + } + + .me-md-auto { + margin-right: auto!important + } + + .mb-md-0 { + margin-bottom: 0!important + } + + .mb-md-1 { + margin-bottom: .25rem!important + } + + .mb-md-2 { + margin-bottom: .5rem!important + } + + .mb-md-3 { + margin-bottom: 1rem!important + } + + .mb-md-4 { + margin-bottom: 1.5rem!important + } + + .mb-md-5 { + margin-bottom: 3rem!important + } + + .mb-md-auto { + margin-bottom: auto!important + } + + .mb-md-6 { + margin-bottom: 3.5rem!important + } + + .mb-md-7 { + margin-bottom: 4rem!important + } + + .mb-md-8 { + margin-bottom: 5rem!important + } + + .mb-md-9 { + margin-bottom: 6rem!important + } + + .mb-md-10 { + margin-bottom: 8rem!important + } + + .mb-md-11 { + margin-bottom: 10rem!important + } + + .mb-md-12 { + margin-bottom: 12rem!important + } + + .mb-md-13 { + margin-bottom: 14rem!important + } + + .mb-md-14 { + margin-bottom: 16rem!important + } + + .ms-md-0 { + margin-left: 0!important + } + + .ms-md-1 { + margin-left: .25rem!important + } + + .ms-md-2 { + margin-left: .5rem!important + } + + .ms-md-3 { + margin-left: 1rem!important + } + + .ms-md-4 { + margin-left: 1.5rem!important + } + + .ms-md-5 { + margin-left: 3rem!important + } + + .ms-md-auto { + margin-left: auto!important + } + + .m-md-n1 { + margin: -.25rem!important + } + + .m-md-n2 { + margin: -.5rem!important + } + + .m-md-n3 { + margin: -1rem!important + } + + .m-md-n4 { + margin: -1.5rem!important + } + + .m-md-n5 { + margin: -3rem!important + } + + .mx-md-n1 { + margin-right: -.25rem!important; + margin-left: -.25rem!important + } + + .mx-md-n2 { + margin-right: -.5rem!important; + margin-left: -.5rem!important + } + + .mx-md-n3 { + margin-right: -1rem!important; + margin-left: -1rem!important + } + + .mx-md-n4 { + margin-right: -1.5rem!important; + margin-left: -1.5rem!important + } + + .mx-md-n5 { + margin-right: -3rem!important; + margin-left: -3rem!important + } + + .my-md-n1 { + margin-top: -.25rem!important; + margin-bottom: -.25rem!important + } + + .my-md-n2 { + margin-top: -.5rem!important; + margin-bottom: -.5rem!important + } + + .my-md-n3 { + margin-top: -1rem!important; + margin-bottom: -1rem!important + } + + .my-md-n4 { + margin-top: -1.5rem!important; + margin-bottom: -1.5rem!important + } + + .my-md-n5 { + margin-top: -3rem!important; + margin-bottom: -3rem!important + } + + .mt-md-n1 { + margin-top: -.25rem!important + } + + .mt-md-n2 { + margin-top: -.5rem!important + } + + .mt-md-n3 { + margin-top: -1rem!important + } + + .mt-md-n4 { + margin-top: -1.5rem!important + } + + .mt-md-n5 { + margin-top: -3rem!important + } + + .me-md-n1 { + margin-right: -.25rem!important + } + + .me-md-n2 { + margin-right: -.5rem!important + } + + .me-md-n3 { + margin-right: -1rem!important + } + + .me-md-n4 { + margin-right: -1.5rem!important + } + + .me-md-n5 { + margin-right: -3rem!important + } + + .mb-md-n1 { + margin-bottom: -.25rem!important + } + + .mb-md-n2 { + margin-bottom: -.5rem!important + } + + .mb-md-n3 { + margin-bottom: -1rem!important + } + + .mb-md-n4 { + margin-bottom: -1.5rem!important + } + + .mb-md-n5 { + margin-bottom: -3rem!important + } + + .ms-md-n1 { + margin-left: -.25rem!important + } + + .ms-md-n2 { + margin-left: -.5rem!important + } + + .ms-md-n3 { + margin-left: -1rem!important + } + + .ms-md-n4 { + margin-left: -1.5rem!important + } + + .ms-md-n5 { + margin-left: -3rem!important + } + + .p-md-0 { + padding: 0!important + } + + .p-md-1 { + padding: .25rem!important + } + + .p-md-2 { + padding: .5rem!important + } + + .p-md-3 { + padding: 1rem!important + } + + .p-md-4 { + padding: 1.5rem!important + } + + .p-md-5 { + padding: 3rem!important + } + + .px-md-0 { + padding-right: 0!important; + padding-left: 0!important + } + + .px-md-1 { + padding-right: .25rem!important; + padding-left: .25rem!important + } + + .px-md-2 { + padding-right: .5rem!important; + padding-left: .5rem!important + } + + .px-md-3 { + padding-right: 1rem!important; + padding-left: 1rem!important + } + + .px-md-4 { + padding-right: 1.5rem!important; + padding-left: 1.5rem!important + } + + .px-md-5 { + padding-right: 3rem!important; + padding-left: 3rem!important + } + + .py-md-0 { + padding-top: 0!important; + padding-bottom: 0!important + } + + .py-md-1 { + padding-top: .25rem!important; + padding-bottom: .25rem!important + } + + .py-md-2 { + padding-top: .5rem!important; + padding-bottom: .5rem!important + } + + .py-md-3 { + padding-top: 1rem!important; + padding-bottom: 1rem!important + } + + .py-md-4 { + padding-top: 1.5rem!important; + padding-bottom: 1.5rem!important + } + + .py-md-5 { + padding-top: 3rem!important; + padding-bottom: 3rem!important + } + + .pt-md-0 { + padding-top: 0!important + } + + .pt-md-1 { + padding-top: .25rem!important + } + + .pt-md-2 { + padding-top: .5rem!important + } + + .pt-md-3 { + padding-top: 1rem!important + } + + .pt-md-4 { + padding-top: 1.5rem!important + } + + .pt-md-5 { + padding-top: 3rem!important + } + + .pe-md-0 { + padding-right: 0!important + } + + .pe-md-1 { + padding-right: .25rem!important + } + + .pe-md-2 { + padding-right: .5rem!important + } + + .pe-md-3 { + padding-right: 1rem!important + } + + .pe-md-4 { + padding-right: 1.5rem!important + } + + .pe-md-5 { + padding-right: 3rem!important + } + + .pb-md-0 { + padding-bottom: 0!important + } + + .pb-md-1 { + padding-bottom: .25rem!important + } + + .pb-md-2 { + padding-bottom: .5rem!important + } + + .pb-md-3 { + padding-bottom: 1rem!important + } + + .pb-md-4 { + padding-bottom: 1.5rem!important + } + + .pb-md-5 { + padding-bottom: 3rem!important + } + + .ps-md-0 { + padding-left: 0!important + } + + .ps-md-1 { + padding-left: .25rem!important + } + + .ps-md-2 { + padding-left: .5rem!important + } + + .ps-md-3 { + padding-left: 1rem!important + } + + .ps-md-4 { + padding-left: 1.5rem!important + } + + .ps-md-5 { + padding-left: 3rem!important + } + + .gap-md-0 { + gap: 0!important + } + + .gap-md-1 { + gap: .25rem!important + } + + .gap-md-2 { + gap: .5rem!important + } + + .gap-md-3 { + gap: 1rem!important + } + + .gap-md-4 { + gap: 1.5rem!important + } + + .gap-md-5 { + gap: 3rem!important + } + + .text-md-start { + text-align: left!important + } + + .text-md-end { + text-align: right!important + } + + .text-md-center { + text-align: center!important + } +} + +@media(min-width: 992px) { + .float-lg-start { + float:left!important + } + + .float-lg-end { + float: right!important + } + + .float-lg-none { + float: none!important + } + + .d-lg-inline { + display: inline!important + } + + .d-lg-inline-block { + display: inline-block!important + } + + .d-lg-block { + display: block!important + } + + .d-lg-grid { + display: grid!important + } + + .d-lg-table { + display: table!important + } + + .d-lg-table-row { + display: table-row!important + } + + .d-lg-table-cell { + display: table-cell!important + } + + .d-lg-flex { + display: flex!important + } + + .d-lg-inline-flex { + display: inline-flex!important + } + + .d-lg-none { + display: none!important + } + + .flex-lg-fill { + flex: 1 1 auto!important + } + + .flex-lg-row { + flex-direction: row!important + } + + .flex-lg-column { + flex-direction: column!important + } + + .flex-lg-row-reverse { + flex-direction: row-reverse!important + } + + .flex-lg-column-reverse { + flex-direction: column-reverse!important + } + + .flex-lg-grow-0 { + flex-grow: 0!important + } + + .flex-lg-grow-1 { + flex-grow: 1!important + } + + .flex-lg-shrink-0 { + flex-shrink: 0!important + } + + .flex-lg-shrink-1 { + flex-shrink: 1!important + } + + .flex-lg-wrap { + flex-wrap: wrap!important + } + + .flex-lg-nowrap { + flex-wrap: nowrap!important + } + + .flex-lg-wrap-reverse { + flex-wrap: wrap-reverse!important + } + + .justify-content-lg-start { + justify-content: flex-start!important + } + + .justify-content-lg-end { + justify-content: flex-end!important + } + + .justify-content-lg-center { + justify-content: center!important + } + + .justify-content-lg-between { + justify-content: space-between!important + } + + .justify-content-lg-around { + justify-content: space-around!important + } + + .justify-content-lg-evenly { + justify-content: space-evenly!important + } + + .align-items-lg-start { + align-items: flex-start!important + } + + .align-items-lg-end { + align-items: flex-end!important + } + + .align-items-lg-center { + align-items: center!important + } + + .align-items-lg-baseline { + align-items: baseline!important + } + + .align-items-lg-stretch { + align-items: stretch!important + } + + .align-content-lg-start { + align-content: flex-start!important + } + + .align-content-lg-end { + align-content: flex-end!important + } + + .align-content-lg-center { + align-content: center!important + } + + .align-content-lg-between { + align-content: space-between!important + } + + .align-content-lg-around { + align-content: space-around!important + } + + .align-content-lg-stretch { + align-content: stretch!important + } + + .align-self-lg-auto { + align-self: auto!important + } + + .align-self-lg-start { + align-self: flex-start!important + } + + .align-self-lg-end { + align-self: flex-end!important + } + + .align-self-lg-center { + align-self: center!important + } + + .align-self-lg-baseline { + align-self: baseline!important + } + + .align-self-lg-stretch { + align-self: stretch!important + } + + .order-lg-first { + order: -1!important + } + + .order-lg-0 { + order: 0!important + } + + .order-lg-1 { + order: 1!important + } + + .order-lg-2 { + order: 2!important + } + + .order-lg-3 { + order: 3!important + } + + .order-lg-4 { + order: 4!important + } + + .order-lg-5 { + order: 5!important + } + + .order-lg-last { + order: 6!important + } + + .m-lg-0 { + margin: 0!important + } + + .m-lg-1 { + margin: .25rem!important + } + + .m-lg-2 { + margin: .5rem!important + } + + .m-lg-3 { + margin: 1rem!important + } + + .m-lg-4 { + margin: 1.5rem!important + } + + .m-lg-5 { + margin: 3rem!important + } + + .m-lg-auto { + margin: auto!important + } + + .mx-lg-0 { + margin-right: 0!important; + margin-left: 0!important + } + + .mx-lg-1 { + margin-right: .25rem!important; + margin-left: .25rem!important + } + + .mx-lg-2 { + margin-right: .5rem!important; + margin-left: .5rem!important + } + + .mx-lg-3 { + margin-right: 1rem!important; + margin-left: 1rem!important + } + + .mx-lg-4 { + margin-right: 1.5rem!important; + margin-left: 1.5rem!important + } + + .mx-lg-5 { + margin-right: 3rem!important; + margin-left: 3rem!important + } + + .mx-lg-auto { + margin-right: auto!important; + margin-left: auto!important + } + + .my-lg-0 { + margin-top: 0!important; + margin-bottom: 0!important + } + + .my-lg-1 { + margin-top: .25rem!important; + margin-bottom: .25rem!important + } + + .my-lg-2 { + margin-top: .5rem!important; + margin-bottom: .5rem!important + } + + .my-lg-3 { + margin-top: 1rem!important; + margin-bottom: 1rem!important + } + + .my-lg-4 { + margin-top: 1.5rem!important; + margin-bottom: 1.5rem!important + } + + .my-lg-5 { + margin-top: 3rem!important; + margin-bottom: 3rem!important + } + + .my-lg-auto { + margin-top: auto!important; + margin-bottom: auto!important + } + + .mt-lg-0 { + margin-top: 0!important + } + + .mt-lg-1 { + margin-top: .25rem!important + } + + .mt-lg-2 { + margin-top: .5rem!important + } + + .mt-lg-3 { + margin-top: 1rem!important + } + + .mt-lg-4 { + margin-top: 1.5rem!important + } + + .mt-lg-5 { + margin-top: 3rem!important + } + + .mt-lg-auto { + margin-top: auto!important + } + + .me-lg-0 { + margin-right: 0!important + } + + .me-lg-1 { + margin-right: .25rem!important + } + + .me-lg-2 { + margin-right: .5rem!important + } + + .me-lg-3 { + margin-right: 1rem!important + } + + .me-lg-4 { + margin-right: 1.5rem!important + } + + .me-lg-5 { + margin-right: 3rem!important + } + + .me-lg-auto { + margin-right: auto!important + } + + .mb-lg-0 { + margin-bottom: 0!important + } + + .mb-lg-1 { + margin-bottom: .25rem!important + } + + .mb-lg-2 { + margin-bottom: .5rem!important + } + + .mb-lg-3 { + margin-bottom: 1rem!important + } + + .mb-lg-4 { + margin-bottom: 1.5rem!important + } + + .mb-lg-5 { + margin-bottom: 3rem!important + } + + .mb-lg-auto { + margin-bottom: auto!important + } + + .mb-lg-6 { + margin-bottom: 3.5rem!important + } + + .mb-lg-7 { + margin-bottom: 4rem!important + } + + .mb-lg-8 { + margin-bottom: 5rem!important + } + + .mb-lg-9 { + margin-bottom: 6rem!important + } + + .mb-lg-10 { + margin-bottom: 8rem!important + } + + .mb-lg-11 { + margin-bottom: 10rem!important + } + + .mb-lg-12 { + margin-bottom: 12rem!important + } + + .mb-lg-13 { + margin-bottom: 14rem!important + } + + .mb-lg-14 { + margin-bottom: 16rem!important + } + + .ms-lg-0 { + margin-left: 0!important + } + + .ms-lg-1 { + margin-left: .25rem!important + } + + .ms-lg-2 { + margin-left: .5rem!important + } + + .ms-lg-3 { + margin-left: 1rem!important + } + + .ms-lg-4 { + margin-left: 1.5rem!important + } + + .ms-lg-5 { + margin-left: 3rem!important + } + + .ms-lg-auto { + margin-left: auto!important + } + + .m-lg-n1 { + margin: -.25rem!important + } + + .m-lg-n2 { + margin: -.5rem!important + } + + .m-lg-n3 { + margin: -1rem!important + } + + .m-lg-n4 { + margin: -1.5rem!important + } + + .m-lg-n5 { + margin: -3rem!important + } + + .mx-lg-n1 { + margin-right: -.25rem!important; + margin-left: -.25rem!important + } + + .mx-lg-n2 { + margin-right: -.5rem!important; + margin-left: -.5rem!important + } + + .mx-lg-n3 { + margin-right: -1rem!important; + margin-left: -1rem!important + } + + .mx-lg-n4 { + margin-right: -1.5rem!important; + margin-left: -1.5rem!important + } + + .mx-lg-n5 { + margin-right: -3rem!important; + margin-left: -3rem!important + } + + .my-lg-n1 { + margin-top: -.25rem!important; + margin-bottom: -.25rem!important + } + + .my-lg-n2 { + margin-top: -.5rem!important; + margin-bottom: -.5rem!important + } + + .my-lg-n3 { + margin-top: -1rem!important; + margin-bottom: -1rem!important + } + + .my-lg-n4 { + margin-top: -1.5rem!important; + margin-bottom: -1.5rem!important + } + + .my-lg-n5 { + margin-top: -3rem!important; + margin-bottom: -3rem!important + } + + .mt-lg-n1 { + margin-top: -.25rem!important + } + + .mt-lg-n2 { + margin-top: -.5rem!important + } + + .mt-lg-n3 { + margin-top: -1rem!important + } + + .mt-lg-n4 { + margin-top: -1.5rem!important + } + + .mt-lg-n5 { + margin-top: -3rem!important + } + + .me-lg-n1 { + margin-right: -.25rem!important + } + + .me-lg-n2 { + margin-right: -.5rem!important + } + + .me-lg-n3 { + margin-right: -1rem!important + } + + .me-lg-n4 { + margin-right: -1.5rem!important + } + + .me-lg-n5 { + margin-right: -3rem!important + } + + .mb-lg-n1 { + margin-bottom: -.25rem!important + } + + .mb-lg-n2 { + margin-bottom: -.5rem!important + } + + .mb-lg-n3 { + margin-bottom: -1rem!important + } + + .mb-lg-n4 { + margin-bottom: -1.5rem!important + } + + .mb-lg-n5 { + margin-bottom: -3rem!important + } + + .ms-lg-n1 { + margin-left: -.25rem!important + } + + .ms-lg-n2 { + margin-left: -.5rem!important + } + + .ms-lg-n3 { + margin-left: -1rem!important + } + + .ms-lg-n4 { + margin-left: -1.5rem!important + } + + .ms-lg-n5 { + margin-left: -3rem!important + } + + .p-lg-0 { + padding: 0!important + } + + .p-lg-1 { + padding: .25rem!important + } + + .p-lg-2 { + padding: .5rem!important + } + + .p-lg-3 { + padding: 1rem!important + } + + .p-lg-4 { + padding: 1.5rem!important + } + + .p-lg-5 { + padding: 3rem!important + } + + .px-lg-0 { + padding-right: 0!important; + padding-left: 0!important + } + + .px-lg-1 { + padding-right: .25rem!important; + padding-left: .25rem!important + } + + .px-lg-2 { + padding-right: .5rem!important; + padding-left: .5rem!important + } + + .px-lg-3 { + padding-right: 1rem!important; + padding-left: 1rem!important + } + + .px-lg-4 { + padding-right: 1.5rem!important; + padding-left: 1.5rem!important + } + + .px-lg-5 { + padding-right: 3rem!important; + padding-left: 3rem!important + } + + .py-lg-0 { + padding-top: 0!important; + padding-bottom: 0!important + } + + .py-lg-1 { + padding-top: .25rem!important; + padding-bottom: .25rem!important + } + + .py-lg-2 { + padding-top: .5rem!important; + padding-bottom: .5rem!important + } + + .py-lg-3 { + padding-top: 1rem!important; + padding-bottom: 1rem!important + } + + .py-lg-4 { + padding-top: 1.5rem!important; + padding-bottom: 1.5rem!important + } + + .py-lg-5 { + padding-top: 3rem!important; + padding-bottom: 3rem!important + } + + .pt-lg-0 { + padding-top: 0!important + } + + .pt-lg-1 { + padding-top: .25rem!important + } + + .pt-lg-2 { + padding-top: .5rem!important + } + + .pt-lg-3 { + padding-top: 1rem!important + } + + .pt-lg-4 { + padding-top: 1.5rem!important + } + + .pt-lg-5 { + padding-top: 3rem!important + } + + .pe-lg-0 { + padding-right: 0!important + } + + .pe-lg-1 { + padding-right: .25rem!important + } + + .pe-lg-2 { + padding-right: .5rem!important + } + + .pe-lg-3 { + padding-right: 1rem!important + } + + .pe-lg-4 { + padding-right: 1.5rem!important + } + + .pe-lg-5 { + padding-right: 3rem!important + } + + .pb-lg-0 { + padding-bottom: 0!important + } + + .pb-lg-1 { + padding-bottom: .25rem!important + } + + .pb-lg-2 { + padding-bottom: .5rem!important + } + + .pb-lg-3 { + padding-bottom: 1rem!important + } + + .pb-lg-4 { + padding-bottom: 1.5rem!important + } + + .pb-lg-5 { + padding-bottom: 3rem!important + } + + .ps-lg-0 { + padding-left: 0!important + } + + .ps-lg-1 { + padding-left: .25rem!important + } + + .ps-lg-2 { + padding-left: .5rem!important + } + + .ps-lg-3 { + padding-left: 1rem!important + } + + .ps-lg-4 { + padding-left: 1.5rem!important + } + + .ps-lg-5 { + padding-left: 3rem!important + } + + .gap-lg-0 { + gap: 0!important + } + + .gap-lg-1 { + gap: .25rem!important + } + + .gap-lg-2 { + gap: .5rem!important + } + + .gap-lg-3 { + gap: 1rem!important + } + + .gap-lg-4 { + gap: 1.5rem!important + } + + .gap-lg-5 { + gap: 3rem!important + } + + .text-lg-start { + text-align: left!important + } + + .text-lg-end { + text-align: right!important + } + + .text-lg-center { + text-align: center!important + } +} + +@media(min-width: 1200px) { + .float-xl-start { + float:left!important + } + + .float-xl-end { + float: right!important + } + + .float-xl-none { + float: none!important + } + + .d-xl-inline { + display: inline!important + } + + .d-xl-inline-block { + display: inline-block!important + } + + .d-xl-block { + display: block!important + } + + .d-xl-grid { + display: grid!important + } + + .d-xl-table { + display: table!important + } + + .d-xl-table-row { + display: table-row!important + } + + .d-xl-table-cell { + display: table-cell!important + } + + .d-xl-flex { + display: flex!important + } + + .d-xl-inline-flex { + display: inline-flex!important + } + + .d-xl-none { + display: none!important + } + + .flex-xl-fill { + flex: 1 1 auto!important + } + + .flex-xl-row { + flex-direction: row!important + } + + .flex-xl-column { + flex-direction: column!important + } + + .flex-xl-row-reverse { + flex-direction: row-reverse!important + } + + .flex-xl-column-reverse { + flex-direction: column-reverse!important + } + + .flex-xl-grow-0 { + flex-grow: 0!important + } + + .flex-xl-grow-1 { + flex-grow: 1!important + } + + .flex-xl-shrink-0 { + flex-shrink: 0!important + } + + .flex-xl-shrink-1 { + flex-shrink: 1!important + } + + .flex-xl-wrap { + flex-wrap: wrap!important + } + + .flex-xl-nowrap { + flex-wrap: nowrap!important + } + + .flex-xl-wrap-reverse { + flex-wrap: wrap-reverse!important + } + + .justify-content-xl-start { + justify-content: flex-start!important + } + + .justify-content-xl-end { + justify-content: flex-end!important + } + + .justify-content-xl-center { + justify-content: center!important + } + + .justify-content-xl-between { + justify-content: space-between!important + } + + .justify-content-xl-around { + justify-content: space-around!important + } + + .justify-content-xl-evenly { + justify-content: space-evenly!important + } + + .align-items-xl-start { + align-items: flex-start!important + } + + .align-items-xl-end { + align-items: flex-end!important + } + + .align-items-xl-center { + align-items: center!important + } + + .align-items-xl-baseline { + align-items: baseline!important + } + + .align-items-xl-stretch { + align-items: stretch!important + } + + .align-content-xl-start { + align-content: flex-start!important + } + + .align-content-xl-end { + align-content: flex-end!important + } + + .align-content-xl-center { + align-content: center!important + } + + .align-content-xl-between { + align-content: space-between!important + } + + .align-content-xl-around { + align-content: space-around!important + } + + .align-content-xl-stretch { + align-content: stretch!important + } + + .align-self-xl-auto { + align-self: auto!important + } + + .align-self-xl-start { + align-self: flex-start!important + } + + .align-self-xl-end { + align-self: flex-end!important + } + + .align-self-xl-center { + align-self: center!important + } + + .align-self-xl-baseline { + align-self: baseline!important + } + + .align-self-xl-stretch { + align-self: stretch!important + } + + .order-xl-first { + order: -1!important + } + + .order-xl-0 { + order: 0!important + } + + .order-xl-1 { + order: 1!important + } + + .order-xl-2 { + order: 2!important + } + + .order-xl-3 { + order: 3!important + } + + .order-xl-4 { + order: 4!important + } + + .order-xl-5 { + order: 5!important + } + + .order-xl-last { + order: 6!important + } + + .m-xl-0 { + margin: 0!important + } + + .m-xl-1 { + margin: .25rem!important + } + + .m-xl-2 { + margin: .5rem!important + } + + .m-xl-3 { + margin: 1rem!important + } + + .m-xl-4 { + margin: 1.5rem!important + } + + .m-xl-5 { + margin: 3rem!important + } + + .m-xl-auto { + margin: auto!important + } + + .mx-xl-0 { + margin-right: 0!important; + margin-left: 0!important + } + + .mx-xl-1 { + margin-right: .25rem!important; + margin-left: .25rem!important + } + + .mx-xl-2 { + margin-right: .5rem!important; + margin-left: .5rem!important + } + + .mx-xl-3 { + margin-right: 1rem!important; + margin-left: 1rem!important + } + + .mx-xl-4 { + margin-right: 1.5rem!important; + margin-left: 1.5rem!important + } + + .mx-xl-5 { + margin-right: 3rem!important; + margin-left: 3rem!important + } + + .mx-xl-auto { + margin-right: auto!important; + margin-left: auto!important + } + + .my-xl-0 { + margin-top: 0!important; + margin-bottom: 0!important + } + + .my-xl-1 { + margin-top: .25rem!important; + margin-bottom: .25rem!important + } + + .my-xl-2 { + margin-top: .5rem!important; + margin-bottom: .5rem!important + } + + .my-xl-3 { + margin-top: 1rem!important; + margin-bottom: 1rem!important + } + + .my-xl-4 { + margin-top: 1.5rem!important; + margin-bottom: 1.5rem!important + } + + .my-xl-5 { + margin-top: 3rem!important; + margin-bottom: 3rem!important + } + + .my-xl-auto { + margin-top: auto!important; + margin-bottom: auto!important + } + + .mt-xl-0 { + margin-top: 0!important + } + + .mt-xl-1 { + margin-top: .25rem!important + } + + .mt-xl-2 { + margin-top: .5rem!important + } + + .mt-xl-3 { + margin-top: 1rem!important + } + + .mt-xl-4 { + margin-top: 1.5rem!important + } + + .mt-xl-5 { + margin-top: 3rem!important + } + + .mt-xl-auto { + margin-top: auto!important + } + + .me-xl-0 { + margin-right: 0!important + } + + .me-xl-1 { + margin-right: .25rem!important + } + + .me-xl-2 { + margin-right: .5rem!important + } + + .me-xl-3 { + margin-right: 1rem!important + } + + .me-xl-4 { + margin-right: 1.5rem!important + } + + .me-xl-5 { + margin-right: 3rem!important + } + + .me-xl-auto { + margin-right: auto!important + } + + .mb-xl-0 { + margin-bottom: 0!important + } + + .mb-xl-1 { + margin-bottom: .25rem!important + } + + .mb-xl-2 { + margin-bottom: .5rem!important + } + + .mb-xl-3 { + margin-bottom: 1rem!important + } + + .mb-xl-4 { + margin-bottom: 1.5rem!important + } + + .mb-xl-5 { + margin-bottom: 3rem!important + } + + .mb-xl-auto { + margin-bottom: auto!important + } + + .mb-xl-6 { + margin-bottom: 3.5rem!important + } + + .mb-xl-7 { + margin-bottom: 4rem!important + } + + .mb-xl-8 { + margin-bottom: 5rem!important + } + + .mb-xl-9 { + margin-bottom: 6rem!important + } + + .mb-xl-10 { + margin-bottom: 8rem!important + } + + .mb-xl-11 { + margin-bottom: 10rem!important + } + + .mb-xl-12 { + margin-bottom: 12rem!important + } + + .mb-xl-13 { + margin-bottom: 14rem!important + } + + .mb-xl-14 { + margin-bottom: 16rem!important + } + + .ms-xl-0 { + margin-left: 0!important + } + + .ms-xl-1 { + margin-left: .25rem!important + } + + .ms-xl-2 { + margin-left: .5rem!important + } + + .ms-xl-3 { + margin-left: 1rem!important + } + + .ms-xl-4 { + margin-left: 1.5rem!important + } + + .ms-xl-5 { + margin-left: 3rem!important + } + + .ms-xl-auto { + margin-left: auto!important + } + + .m-xl-n1 { + margin: -.25rem!important + } + + .m-xl-n2 { + margin: -.5rem!important + } + + .m-xl-n3 { + margin: -1rem!important + } + + .m-xl-n4 { + margin: -1.5rem!important + } + + .m-xl-n5 { + margin: -3rem!important + } + + .mx-xl-n1 { + margin-right: -.25rem!important; + margin-left: -.25rem!important + } + + .mx-xl-n2 { + margin-right: -.5rem!important; + margin-left: -.5rem!important + } + + .mx-xl-n3 { + margin-right: -1rem!important; + margin-left: -1rem!important + } + + .mx-xl-n4 { + margin-right: -1.5rem!important; + margin-left: -1.5rem!important + } + + .mx-xl-n5 { + margin-right: -3rem!important; + margin-left: -3rem!important + } + + .my-xl-n1 { + margin-top: -.25rem!important; + margin-bottom: -.25rem!important + } + + .my-xl-n2 { + margin-top: -.5rem!important; + margin-bottom: -.5rem!important + } + + .my-xl-n3 { + margin-top: -1rem!important; + margin-bottom: -1rem!important + } + + .my-xl-n4 { + margin-top: -1.5rem!important; + margin-bottom: -1.5rem!important + } + + .my-xl-n5 { + margin-top: -3rem!important; + margin-bottom: -3rem!important + } + + .mt-xl-n1 { + margin-top: -.25rem!important + } + + .mt-xl-n2 { + margin-top: -.5rem!important + } + + .mt-xl-n3 { + margin-top: -1rem!important + } + + .mt-xl-n4 { + margin-top: -1.5rem!important + } + + .mt-xl-n5 { + margin-top: -3rem!important + } + + .me-xl-n1 { + margin-right: -.25rem!important + } + + .me-xl-n2 { + margin-right: -.5rem!important + } + + .me-xl-n3 { + margin-right: -1rem!important + } + + .me-xl-n4 { + margin-right: -1.5rem!important + } + + .me-xl-n5 { + margin-right: -3rem!important + } + + .mb-xl-n1 { + margin-bottom: -.25rem!important + } + + .mb-xl-n2 { + margin-bottom: -.5rem!important + } + + .mb-xl-n3 { + margin-bottom: -1rem!important + } + + .mb-xl-n4 { + margin-bottom: -1.5rem!important + } + + .mb-xl-n5 { + margin-bottom: -3rem!important + } + + .ms-xl-n1 { + margin-left: -.25rem!important + } + + .ms-xl-n2 { + margin-left: -.5rem!important + } + + .ms-xl-n3 { + margin-left: -1rem!important + } + + .ms-xl-n4 { + margin-left: -1.5rem!important + } + + .ms-xl-n5 { + margin-left: -3rem!important + } + + .p-xl-0 { + padding: 0!important + } + + .p-xl-1 { + padding: .25rem!important + } + + .p-xl-2 { + padding: .5rem!important + } + + .p-xl-3 { + padding: 1rem!important + } + + .p-xl-4 { + padding: 1.5rem!important + } + + .p-xl-5 { + padding: 3rem!important + } + + .px-xl-0 { + padding-right: 0!important; + padding-left: 0!important + } + + .px-xl-1 { + padding-right: .25rem!important; + padding-left: .25rem!important + } + + .px-xl-2 { + padding-right: .5rem!important; + padding-left: .5rem!important + } + + .px-xl-3 { + padding-right: 1rem!important; + padding-left: 1rem!important + } + + .px-xl-4 { + padding-right: 1.5rem!important; + padding-left: 1.5rem!important + } + + .px-xl-5 { + padding-right: 3rem!important; + padding-left: 3rem!important + } + + .py-xl-0 { + padding-top: 0!important; + padding-bottom: 0!important + } + + .py-xl-1 { + padding-top: .25rem!important; + padding-bottom: .25rem!important + } + + .py-xl-2 { + padding-top: .5rem!important; + padding-bottom: .5rem!important + } + + .py-xl-3 { + padding-top: 1rem!important; + padding-bottom: 1rem!important + } + + .py-xl-4 { + padding-top: 1.5rem!important; + padding-bottom: 1.5rem!important + } + + .py-xl-5 { + padding-top: 3rem!important; + padding-bottom: 3rem!important + } + + .pt-xl-0 { + padding-top: 0!important + } + + .pt-xl-1 { + padding-top: .25rem!important + } + + .pt-xl-2 { + padding-top: .5rem!important + } + + .pt-xl-3 { + padding-top: 1rem!important + } + + .pt-xl-4 { + padding-top: 1.5rem!important + } + + .pt-xl-5 { + padding-top: 3rem!important + } + + .pe-xl-0 { + padding-right: 0!important + } + + .pe-xl-1 { + padding-right: .25rem!important + } + + .pe-xl-2 { + padding-right: .5rem!important + } + + .pe-xl-3 { + padding-right: 1rem!important + } + + .pe-xl-4 { + padding-right: 1.5rem!important + } + + .pe-xl-5 { + padding-right: 3rem!important + } + + .pb-xl-0 { + padding-bottom: 0!important + } + + .pb-xl-1 { + padding-bottom: .25rem!important + } + + .pb-xl-2 { + padding-bottom: .5rem!important + } + + .pb-xl-3 { + padding-bottom: 1rem!important + } + + .pb-xl-4 { + padding-bottom: 1.5rem!important + } + + .pb-xl-5 { + padding-bottom: 3rem!important + } + + .ps-xl-0 { + padding-left: 0!important + } + + .ps-xl-1 { + padding-left: .25rem!important + } + + .ps-xl-2 { + padding-left: .5rem!important + } + + .ps-xl-3 { + padding-left: 1rem!important + } + + .ps-xl-4 { + padding-left: 1.5rem!important + } + + .ps-xl-5 { + padding-left: 3rem!important + } + + .gap-xl-0 { + gap: 0!important + } + + .gap-xl-1 { + gap: .25rem!important + } + + .gap-xl-2 { + gap: .5rem!important + } + + .gap-xl-3 { + gap: 1rem!important + } + + .gap-xl-4 { + gap: 1.5rem!important + } + + .gap-xl-5 { + gap: 3rem!important + } + + .text-xl-start { + text-align: left!important + } + + .text-xl-end { + text-align: right!important + } + + .text-xl-center { + text-align: center!important + } +} + +@media(min-width: 1400px) { + .float-xxl-start { + float:left!important + } + + .float-xxl-end { + float: right!important + } + + .float-xxl-none { + float: none!important + } + + .d-xxl-inline { + display: inline!important + } + + .d-xxl-inline-block { + display: inline-block!important + } + + .d-xxl-block { + display: block!important + } + + .d-xxl-grid { + display: grid!important + } + + .d-xxl-table { + display: table!important + } + + .d-xxl-table-row { + display: table-row!important + } + + .d-xxl-table-cell { + display: table-cell!important + } + + .d-xxl-flex { + display: flex!important + } + + .d-xxl-inline-flex { + display: inline-flex!important + } + + .d-xxl-none { + display: none!important + } + + .flex-xxl-fill { + flex: 1 1 auto!important + } + + .flex-xxl-row { + flex-direction: row!important + } + + .flex-xxl-column { + flex-direction: column!important + } + + .flex-xxl-row-reverse { + flex-direction: row-reverse!important + } + + .flex-xxl-column-reverse { + flex-direction: column-reverse!important + } + + .flex-xxl-grow-0 { + flex-grow: 0!important + } + + .flex-xxl-grow-1 { + flex-grow: 1!important + } + + .flex-xxl-shrink-0 { + flex-shrink: 0!important + } + + .flex-xxl-shrink-1 { + flex-shrink: 1!important + } + + .flex-xxl-wrap { + flex-wrap: wrap!important + } + + .flex-xxl-nowrap { + flex-wrap: nowrap!important + } + + .flex-xxl-wrap-reverse { + flex-wrap: wrap-reverse!important + } + + .justify-content-xxl-start { + justify-content: flex-start!important + } + + .justify-content-xxl-end { + justify-content: flex-end!important + } + + .justify-content-xxl-center { + justify-content: center!important + } + + .justify-content-xxl-between { + justify-content: space-between!important + } + + .justify-content-xxl-around { + justify-content: space-around!important + } + + .justify-content-xxl-evenly { + justify-content: space-evenly!important + } + + .align-items-xxl-start { + align-items: flex-start!important + } + + .align-items-xxl-end { + align-items: flex-end!important + } + + .align-items-xxl-center { + align-items: center!important + } + + .align-items-xxl-baseline { + align-items: baseline!important + } + + .align-items-xxl-stretch { + align-items: stretch!important + } + + .align-content-xxl-start { + align-content: flex-start!important + } + + .align-content-xxl-end { + align-content: flex-end!important + } + + .align-content-xxl-center { + align-content: center!important + } + + .align-content-xxl-between { + align-content: space-between!important + } + + .align-content-xxl-around { + align-content: space-around!important + } + + .align-content-xxl-stretch { + align-content: stretch!important + } + + .align-self-xxl-auto { + align-self: auto!important + } + + .align-self-xxl-start { + align-self: flex-start!important + } + + .align-self-xxl-end { + align-self: flex-end!important + } + + .align-self-xxl-center { + align-self: center!important + } + + .align-self-xxl-baseline { + align-self: baseline!important + } + + .align-self-xxl-stretch { + align-self: stretch!important + } + + .order-xxl-first { + order: -1!important + } + + .order-xxl-0 { + order: 0!important + } + + .order-xxl-1 { + order: 1!important + } + + .order-xxl-2 { + order: 2!important + } + + .order-xxl-3 { + order: 3!important + } + + .order-xxl-4 { + order: 4!important + } + + .order-xxl-5 { + order: 5!important + } + + .order-xxl-last { + order: 6!important + } + + .m-xxl-0 { + margin: 0!important + } + + .m-xxl-1 { + margin: .25rem!important + } + + .m-xxl-2 { + margin: .5rem!important + } + + .m-xxl-3 { + margin: 1rem!important + } + + .m-xxl-4 { + margin: 1.5rem!important + } + + .m-xxl-5 { + margin: 3rem!important + } + + .m-xxl-auto { + margin: auto!important + } + + .mx-xxl-0 { + margin-right: 0!important; + margin-left: 0!important + } + + .mx-xxl-1 { + margin-right: .25rem!important; + margin-left: .25rem!important + } + + .mx-xxl-2 { + margin-right: .5rem!important; + margin-left: .5rem!important + } + + .mx-xxl-3 { + margin-right: 1rem!important; + margin-left: 1rem!important + } + + .mx-xxl-4 { + margin-right: 1.5rem!important; + margin-left: 1.5rem!important + } + + .mx-xxl-5 { + margin-right: 3rem!important; + margin-left: 3rem!important + } + + .mx-xxl-auto { + margin-right: auto!important; + margin-left: auto!important + } + + .my-xxl-0 { + margin-top: 0!important; + margin-bottom: 0!important + } + + .my-xxl-1 { + margin-top: .25rem!important; + margin-bottom: .25rem!important + } + + .my-xxl-2 { + margin-top: .5rem!important; + margin-bottom: .5rem!important + } + + .my-xxl-3 { + margin-top: 1rem!important; + margin-bottom: 1rem!important + } + + .my-xxl-4 { + margin-top: 1.5rem!important; + margin-bottom: 1.5rem!important + } + + .my-xxl-5 { + margin-top: 3rem!important; + margin-bottom: 3rem!important + } + + .my-xxl-auto { + margin-top: auto!important; + margin-bottom: auto!important + } + + .mt-xxl-0 { + margin-top: 0!important + } + + .mt-xxl-1 { + margin-top: .25rem!important + } + + .mt-xxl-2 { + margin-top: .5rem!important + } + + .mt-xxl-3 { + margin-top: 1rem!important + } + + .mt-xxl-4 { + margin-top: 1.5rem!important + } + + .mt-xxl-5 { + margin-top: 3rem!important + } + + .mt-xxl-auto { + margin-top: auto!important + } + + .me-xxl-0 { + margin-right: 0!important + } + + .me-xxl-1 { + margin-right: .25rem!important + } + + .me-xxl-2 { + margin-right: .5rem!important + } + + .me-xxl-3 { + margin-right: 1rem!important + } + + .me-xxl-4 { + margin-right: 1.5rem!important + } + + .me-xxl-5 { + margin-right: 3rem!important + } + + .me-xxl-auto { + margin-right: auto!important + } + + .mb-xxl-0 { + margin-bottom: 0!important + } + + .mb-xxl-1 { + margin-bottom: .25rem!important + } + + .mb-xxl-2 { + margin-bottom: .5rem!important + } + + .mb-xxl-3 { + margin-bottom: 1rem!important + } + + .mb-xxl-4 { + margin-bottom: 1.5rem!important + } + + .mb-xxl-5 { + margin-bottom: 3rem!important + } + + .mb-xxl-auto { + margin-bottom: auto!important + } + + .mb-xxl-6 { + margin-bottom: 3.5rem!important + } + + .mb-xxl-7 { + margin-bottom: 4rem!important + } + + .mb-xxl-8 { + margin-bottom: 5rem!important + } + + .mb-xxl-9 { + margin-bottom: 6rem!important + } + + .mb-xxl-10 { + margin-bottom: 8rem!important + } + + .mb-xxl-11 { + margin-bottom: 10rem!important + } + + .mb-xxl-12 { + margin-bottom: 12rem!important + } + + .mb-xxl-13 { + margin-bottom: 14rem!important + } + + .mb-xxl-14 { + margin-bottom: 16rem!important + } + + .ms-xxl-0 { + margin-left: 0!important + } + + .ms-xxl-1 { + margin-left: .25rem!important + } + + .ms-xxl-2 { + margin-left: .5rem!important + } + + .ms-xxl-3 { + margin-left: 1rem!important + } + + .ms-xxl-4 { + margin-left: 1.5rem!important + } + + .ms-xxl-5 { + margin-left: 3rem!important + } + + .ms-xxl-auto { + margin-left: auto!important + } + + .m-xxl-n1 { + margin: -.25rem!important + } + + .m-xxl-n2 { + margin: -.5rem!important + } + + .m-xxl-n3 { + margin: -1rem!important + } + + .m-xxl-n4 { + margin: -1.5rem!important + } + + .m-xxl-n5 { + margin: -3rem!important + } + + .mx-xxl-n1 { + margin-right: -.25rem!important; + margin-left: -.25rem!important + } + + .mx-xxl-n2 { + margin-right: -.5rem!important; + margin-left: -.5rem!important + } + + .mx-xxl-n3 { + margin-right: -1rem!important; + margin-left: -1rem!important + } + + .mx-xxl-n4 { + margin-right: -1.5rem!important; + margin-left: -1.5rem!important + } + + .mx-xxl-n5 { + margin-right: -3rem!important; + margin-left: -3rem!important + } + + .my-xxl-n1 { + margin-top: -.25rem!important; + margin-bottom: -.25rem!important + } + + .my-xxl-n2 { + margin-top: -.5rem!important; + margin-bottom: -.5rem!important + } + + .my-xxl-n3 { + margin-top: -1rem!important; + margin-bottom: -1rem!important + } + + .my-xxl-n4 { + margin-top: -1.5rem!important; + margin-bottom: -1.5rem!important + } + + .my-xxl-n5 { + margin-top: -3rem!important; + margin-bottom: -3rem!important + } + + .mt-xxl-n1 { + margin-top: -.25rem!important + } + + .mt-xxl-n2 { + margin-top: -.5rem!important + } + + .mt-xxl-n3 { + margin-top: -1rem!important + } + + .mt-xxl-n4 { + margin-top: -1.5rem!important + } + + .mt-xxl-n5 { + margin-top: -3rem!important + } + + .me-xxl-n1 { + margin-right: -.25rem!important + } + + .me-xxl-n2 { + margin-right: -.5rem!important + } + + .me-xxl-n3 { + margin-right: -1rem!important + } + + .me-xxl-n4 { + margin-right: -1.5rem!important + } + + .me-xxl-n5 { + margin-right: -3rem!important + } + + .mb-xxl-n1 { + margin-bottom: -.25rem!important + } + + .mb-xxl-n2 { + margin-bottom: -.5rem!important + } + + .mb-xxl-n3 { + margin-bottom: -1rem!important + } + + .mb-xxl-n4 { + margin-bottom: -1.5rem!important + } + + .mb-xxl-n5 { + margin-bottom: -3rem!important + } + + .ms-xxl-n1 { + margin-left: -.25rem!important + } + + .ms-xxl-n2 { + margin-left: -.5rem!important + } + + .ms-xxl-n3 { + margin-left: -1rem!important + } + + .ms-xxl-n4 { + margin-left: -1.5rem!important + } + + .ms-xxl-n5 { + margin-left: -3rem!important + } + + .p-xxl-0 { + padding: 0!important + } + + .p-xxl-1 { + padding: .25rem!important + } + + .p-xxl-2 { + padding: .5rem!important + } + + .p-xxl-3 { + padding: 1rem!important + } + + .p-xxl-4 { + padding: 1.5rem!important + } + + .p-xxl-5 { + padding: 3rem!important + } + + .px-xxl-0 { + padding-right: 0!important; + padding-left: 0!important + } + + .px-xxl-1 { + padding-right: .25rem!important; + padding-left: .25rem!important + } + + .px-xxl-2 { + padding-right: .5rem!important; + padding-left: .5rem!important + } + + .px-xxl-3 { + padding-right: 1rem!important; + padding-left: 1rem!important + } + + .px-xxl-4 { + padding-right: 1.5rem!important; + padding-left: 1.5rem!important + } + + .px-xxl-5 { + padding-right: 3rem!important; + padding-left: 3rem!important + } + + .py-xxl-0 { + padding-top: 0!important; + padding-bottom: 0!important + } + + .py-xxl-1 { + padding-top: .25rem!important; + padding-bottom: .25rem!important + } + + .py-xxl-2 { + padding-top: .5rem!important; + padding-bottom: .5rem!important + } + + .py-xxl-3 { + padding-top: 1rem!important; + padding-bottom: 1rem!important + } + + .py-xxl-4 { + padding-top: 1.5rem!important; + padding-bottom: 1.5rem!important + } + + .py-xxl-5 { + padding-top: 3rem!important; + padding-bottom: 3rem!important + } + + .pt-xxl-0 { + padding-top: 0!important + } + + .pt-xxl-1 { + padding-top: .25rem!important + } + + .pt-xxl-2 { + padding-top: .5rem!important + } + + .pt-xxl-3 { + padding-top: 1rem!important + } + + .pt-xxl-4 { + padding-top: 1.5rem!important + } + + .pt-xxl-5 { + padding-top: 3rem!important + } + + .pe-xxl-0 { + padding-right: 0!important + } + + .pe-xxl-1 { + padding-right: .25rem!important + } + + .pe-xxl-2 { + padding-right: .5rem!important + } + + .pe-xxl-3 { + padding-right: 1rem!important + } + + .pe-xxl-4 { + padding-right: 1.5rem!important + } + + .pe-xxl-5 { + padding-right: 3rem!important + } + + .pb-xxl-0 { + padding-bottom: 0!important + } + + .pb-xxl-1 { + padding-bottom: .25rem!important + } + + .pb-xxl-2 { + padding-bottom: .5rem!important + } + + .pb-xxl-3 { + padding-bottom: 1rem!important + } + + .pb-xxl-4 { + padding-bottom: 1.5rem!important + } + + .pb-xxl-5 { + padding-bottom: 3rem!important + } + + .ps-xxl-0 { + padding-left: 0!important + } + + .ps-xxl-1 { + padding-left: .25rem!important + } + + .ps-xxl-2 { + padding-left: .5rem!important + } + + .ps-xxl-3 { + padding-left: 1rem!important + } + + .ps-xxl-4 { + padding-left: 1.5rem!important + } + + .ps-xxl-5 { + padding-left: 3rem!important + } + + .gap-xxl-0 { + gap: 0!important + } + + .gap-xxl-1 { + gap: .25rem!important + } + + .gap-xxl-2 { + gap: .5rem!important + } + + .gap-xxl-3 { + gap: 1rem!important + } + + .gap-xxl-4 { + gap: 1.5rem!important + } + + .gap-xxl-5 { + gap: 3rem!important + } + + .text-xxl-start { + text-align: left!important + } + + .text-xxl-end { + text-align: right!important + } + + .text-xxl-center { + text-align: center!important + } +} + +@media(min-width: 1200px) { + .fs-1 { + font-size:2.5rem!important + } + + .fs-2 { + font-size: 2rem!important + } + + .fs-3 { + font-size: 1.75rem!important + } + + .fs-4 { + font-size: 1.5rem!important + } +} + +@media print { + .d-print-inline { + display: inline!important + } + + .d-print-inline-block { + display: inline-block!important + } + + .d-print-block { + display: block!important + } + + .d-print-grid { + display: grid!important + } + + .d-print-table { + display: table!important + } + + .d-print-table-row { + display: table-row!important + } + + .d-print-table-cell { + display: table-cell!important + } + + .d-print-flex { + display: flex!important + } + + .d-print-inline-flex { + display: inline-flex!important + } + + .d-print-none { + display: none!important + } +} + +.diagonal-fractions { + font-variant-numeric: diagonal-fractions +} + +.bg-super-light { + --mdb-bg-super-light: #fbfbfb; + background-color: var(--mdb-bg-super-light) +} + +.bg-local { + background-attachment: local +} + +.bg-scroll { + background-attachment: scroll +} + +.overflow-y-scroll { + overflow-y: scroll +} + +.overflow-x-scroll { + overflow-x: scroll +} + +.table-fixed { + table-layout: fixed +} + +.table-auto { + table-layout: auto +} + +.link-danger,.link-dark,.link-info,.link-light,.link-primary,.link-secondary,.link-success,.link-warning { + transition: color .15s +} + +:root { + --mdb-font-roboto: "Roboto",sans-serif; + --mdb-bg-opacity: 1 +} + +hr:not([size]).hr { + --mdb-divider-height: 2px; + --mdb-divider-bg: #f5f5f5; + --mdb-divider-opacity: 1; + --mdb-divider-blurry-bg: transparent; + --mdb-divider-blurry-bg-image: linear-gradient(90deg,transparent,#666,transparent); + --mdb-divider-blurry-height: 1px; + --mdb-divider-blurry-opacity: 0.25; + height: var(--mdb-divider-height); + background-color: var(--mdb-divider-bg); + opacity: var(--mdb-divider-opacity) +} + +hr:not([size]).hr.hr-blurry { + background-color: var(--mdb-divider-blurry-bg); + background-image: var(--mdb-divider-blurry-bg-image); + height: var(--mdb-divider-blurry-height); + opacity: var(--mdb-divider-blurry-opacity) +} + +hr:not([size]).vr { + height: auto +} + +hr.hr,hr.vr { + border-top: none!important +} + +.vr { + --mdb-divider-width: 2px; + --mdb-divider-bg: #f5f5f5; + --mdb-divider-opacity: 1; + width: var(--mdb-divider-width); + background-color: var(--mdb-divider-bg); + opacity: var(--mdb-divider-opacity) +} + +.vr-blurry { + --mdb-divider-blurry-vr-bg-image: linear-gradient(180deg,transparent,#666,transparent); + --mdb-divider-blurry-vr-width: 1px; + --mdb-divider-blurry-opacity: 0.25; + background-image: var(--mdb-divider-blurry-vr-bg-image); + width: var(--mdb-divider-blurry-vr-width); + opacity: var(--mdb-divider-blurry-opacity) +} + +a { + --mdb-link-decoration: none; + -webkit-text-decoration: var(--mdb-link-decoration); + text-decoration: var(--mdb-link-decoration) +} + +.note { + --mdb-note-padding: 10px; + --mdb-note-border-width: 6px; + --mdb-note-border-radius: 5px; + --mdb-note-strong-font-weight: 600; + padding: var(--mdb-note-padding); + border-left: var(--mdb-note-border-width) solid; + border-radius: var(--mdb-note-border-radius) +} + +.note strong { + font-weight: var(--mdb-note-strong-font-weight) +} + +.note-primary { + background-color: #dfe7f6; + border-color: #376fc8 +} + +.note-secondary { + background-color: #ebedef; + border-color: #565e6c +} + +.note-success { + background-color: #d6f0e0; + border-color: #139647 +} + +.note-danger { + background-color: #f9e1e5; + border-color: #d62e4a +} + +.note-warning { + background-color: #fbf0da; + border-color: #a17112 +} + +.note-info { + background-color: #def1f7; + border-color: #2686a6 +} + +.note-light { + background-color: #f5f5f5; + border-color: #8c8c8c +} + +.note-dark { + background-color: #332e2e; + border-color: #e8e8e8 +} + +@media(min-width: 1199px) { + .w-responsive { + width:75% + } +} + +.bg-primary { + --mdb--bg-opacity: 1; + background-color: rgba(59,113,202,var(--mdb--bg-opacity)) +} + +.bg-secondary { + --mdb--bg-opacity: 1; + background-color: rgba(159,166,178,var(--mdb--bg-opacity)) +} + +.bg-success { + --mdb--bg-opacity: 1; + background-color: rgba(20,164,77,var(--mdb--bg-opacity)) +} + +.bg-danger { + --mdb--bg-opacity: 1; + background-color: rgba(220,76,100,var(--mdb--bg-opacity)) +} + +.bg-warning { + --mdb--bg-opacity: 1; + background-color: rgba(228,161,27,var(--mdb--bg-opacity)) +} + +.bg-info { + background-color: rgba(84,180,211,var(--mdb--bg-opacity)) +} + +.bg-info,.bg-light { + --mdb--bg-opacity: 1 +} + +.bg-light { + background-color: rgba(251,251,251,var(--mdb--bg-opacity)) +} + +.bg-dark { + --mdb--bg-opacity: 1; + background-color: rgba(51,45,45,var(--mdb--bg-opacity)) +} + +/*! + * # Semantic UI 2.4.2 - Flag + * http://github.com/semantic-org/semantic-ui/ + * + * + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ +#mdb-table-flag tr { + cursor: pointer +} + +.mdb-flag-selected { + border-top-left-radius: 5px; + border-top-right-radius: 5px; + text-align: center; + max-width: 150px; + margin: 10px auto 0 +} + +.mdb-selected-flag-text { + margin: 0 auto; + max-width: 150px +} + +i.flag:not(.icon) { + margin: 0 .5em 0 0; + line-height: 11px; + text-decoration: inherit; + vertical-align: baseline; + -webkit-backface-visibility: hidden; + backface-visibility: hidden +} + +i.flag:before,i.flag:not(.icon) { + display: inline-block; + width: 16px; + height: 11px +} + +i.flag:before { + content: ""; + background: url(https://mdbootstrap.com/img/svg/flags.png) no-repeat -108px -1976px +} + +i.flag-ad:before,i.flag-andorra:before { + background-position: 0 0!important +} + +i.flag-ae:before,i.flag-uae:before,i.flag-united-arab-emirates:before { + background-position: 0 -26px!important +} + +i.flag-af:before,i.flag-afghanistan:before { + background-position: 0 -52px!important +} + +i.flag-ag:before,i.flag-antigua:before { + background-position: 0 -78px!important +} + +i.flag-ai:before,i.flag-anguilla:before { + background-position: 0 -104px!important +} + +i.flag-al:before,i.flag-albania:before { + background-position: 0 -130px!important +} + +i.flag-am:before,i.flag-armenia:before { + background-position: 0 -156px!important +} + +i.flag-an:before,i.flag-netherlands-antilles:before { + background-position: 0 -182px!important +} + +i.flag-angola:before,i.flag-ao:before { + background-position: 0 -208px!important +} + +i.flag-ar:before,i.flag-argentina:before { + background-position: 0 -234px!important +} + +i.flag-american-samoa:before,i.flag-as:before { + background-position: 0 -260px!important +} + +i.flag-at:before,i.flag-austria:before { + background-position: 0 -286px!important +} + +i.flag-au:before,i.flag-australia:before { + background-position: 0 -312px!important +} + +i.flag-aruba:before,i.flag-aw:before { + background-position: 0 -338px!important +} + +i.flag-aland-islands:before,i.flag-ax:before { + background-position: 0 -364px!important +} + +i.flag-az:before,i.flag-azerbaijan:before { + background-position: 0 -390px!important +} + +i.flag-ba:before,i.flag-bosnia:before { + background-position: 0 -416px!important +} + +i.flag-barbados:before,i.flag-bb:before { + background-position: 0 -442px!important +} + +i.flag-bangladesh:before,i.flag-bd:before { + background-position: 0 -468px!important +} + +i.flag-be:before,i.flag-belgium:before { + background-position: 0 -494px!important +} + +i.flag-bf:before,i.flag-burkina-faso:before { + background-position: 0 -520px!important +} + +i.flag-bg:before,i.flag-bulgaria:before { + background-position: 0 -546px!important +} + +i.flag-bahrain:before,i.flag-bh:before { + background-position: 0 -572px!important +} + +i.flag-bi:before,i.flag-burundi:before { + background-position: 0 -598px!important +} + +i.flag-benin:before,i.flag-bj:before { + background-position: 0 -624px!important +} + +i.flag-bermuda:before,i.flag-bm:before { + background-position: 0 -650px!important +} + +i.flag-bn:before,i.flag-brunei:before { + background-position: 0 -676px!important +} + +i.flag-bo:before,i.flag-bolivia:before { + background-position: 0 -702px!important +} + +i.flag-br:before,i.flag-brazil:before { + background-position: 0 -728px!important +} + +i.flag-bahamas:before,i.flag-bs:before { + background-position: 0 -754px!important +} + +i.flag-bhutan:before,i.flag-bt:before { + background-position: 0 -780px!important +} + +i.flag-bouvet-island:before,i.flag-bv:before { + background-position: 0 -806px!important +} + +i.flag-botswana:before,i.flag-bw:before { + background-position: 0 -832px!important +} + +i.flag-belarus:before,i.flag-by:before { + background-position: 0 -858px!important +} + +i.flag-belize:before,i.flag-bz:before { + background-position: 0 -884px!important +} + +i.flag-ca:before,i.flag-canada:before { + background-position: 0 -910px!important +} + +i.flag-cc:before,i.flag-cocos-islands:before { + background-position: 0 -962px!important +} + +i.flag-cd:before,i.flag-congo:before { + background-position: 0 -988px!important +} + +i.flag-central-african-republic:before,i.flag-cf:before { + background-position: 0 -1014px!important +} + +i.flag-cg:before,i.flag-congo-brazzaville:before { + background-position: 0 -1040px!important +} + +i.flag-ch:before,i.flag-switzerland:before { + background-position: 0 -1066px!important +} + +i.flag-ci:before,i.flag-cote-divoire:before { + background-position: 0 -1092px!important +} + +i.flag-ck:before,i.flag-cook-islands:before { + background-position: 0 -1118px!important +} + +i.flag-chile:before,i.flag-cl:before { + background-position: 0 -1144px!important +} + +i.flag-cameroon:before,i.flag-cm:before { + background-position: 0 -1170px!important +} + +i.flag-china:before,i.flag-cn:before { + background-position: 0 -1196px!important +} + +i.flag-co:before,i.flag-colombia:before { + background-position: 0 -1222px!important +} + +i.flag-costa-rica:before,i.flag-cr:before { + background-position: 0 -1248px!important +} + +i.flag-cs:before,i.flag-serbia:before { + background-position: 0 -1274px!important +} + +i.flag-cu:before,i.flag-cuba:before { + background-position: 0 -1300px!important +} + +i.flag-cape-verde:before,i.flag-cv:before { + background-position: 0 -1326px!important +} + +i.flag-christmas-island:before,i.flag-cx:before { + background-position: 0 -1352px!important +} + +i.flag-cy:before,i.flag-cyprus:before { + background-position: 0 -1378px!important +} + +i.flag-cz:before,i.flag-czech-republic:before { + background-position: 0 -1404px!important +} + +i.flag-de:before,i.flag-germany:before { + background-position: 0 -1430px!important +} + +i.flag-dj:before,i.flag-djibouti:before { + background-position: 0 -1456px!important +} + +i.flag-denmark:before,i.flag-dk:before { + background-position: 0 -1482px!important +} + +i.flag-dm:before,i.flag-dominica:before { + background-position: 0 -1508px!important +} + +i.flag-do:before,i.flag-dominican-republic:before { + background-position: 0 -1534px!important +} + +i.flag-algeria:before,i.flag-dz:before { + background-position: 0 -1560px!important +} + +i.flag-ec:before,i.flag-ecuador:before { + background-position: 0 -1586px!important +} + +i.flag-ee:before,i.flag-estonia:before { + background-position: 0 -1612px!important +} + +i.flag-eg:before,i.flag-egypt:before { + background-position: 0 -1638px!important +} + +i.flag-eh:before,i.flag-western-sahara:before { + background-position: 0 -1664px!important +} + +i.flag-england:before,i.flag-gb-eng:before { + background-position: 0 -1690px!important +} + +i.flag-er:before,i.flag-eritrea:before { + background-position: 0 -1716px!important +} + +i.flag-es:before,i.flag-spain:before { + background-position: 0 -1742px!important +} + +i.flag-et:before,i.flag-ethiopia:before { + background-position: 0 -1768px!important +} + +i.flag-eu:before,i.flag-european-union:before { + background-position: 0 -1794px!important +} + +i.flag-fi:before,i.flag-finland:before { + background-position: 0 -1846px!important +} + +i.flag-fiji:before,i.flag-fj:before { + background-position: 0 -1872px!important +} + +i.flag-falkland-islands:before,i.flag-fk:before { + background-position: 0 -1898px!important +} + +i.flag-fm:before,i.flag-micronesia:before { + background-position: 0 -1924px!important +} + +i.flag-faroe-islands:before,i.flag-fo:before { + background-position: 0 -1950px!important +} + +i.flag-fr:before,i.flag-france:before { + background-position: 0 -1976px!important +} + +i.flag-ga:before,i.flag-gabon:before { + background-position: -36px 0!important +} + +i.flag-gb:before,i.flag-uk:before,i.flag-united-kingdom:before { + background-position: -36px -26px!important +} + +i.flag-gd:before,i.flag-grenada:before { + background-position: -36px -52px!important +} + +i.flag-ge:before,i.flag-georgia:before { + background-position: -36px -78px!important +} + +i.flag-french-guiana:before,i.flag-gf:before { + background-position: -36px -104px!important +} + +i.flag-gh:before,i.flag-ghana:before { + background-position: -36px -130px!important +} + +i.flag-gi:before,i.flag-gibraltar:before { + background-position: -36px -156px!important +} + +i.flag-gl:before,i.flag-greenland:before { + background-position: -36px -182px!important +} + +i.flag-gambia:before,i.flag-gm:before { + background-position: -36px -208px!important +} + +i.flag-gn:before,i.flag-guinea:before { + background-position: -36px -234px!important +} + +i.flag-gp:before,i.flag-guadeloupe:before { + background-position: -36px -260px!important +} + +i.flag-equatorial-guinea:before,i.flag-gq:before { + background-position: -36px -286px!important +} + +i.flag-gr:before,i.flag-greece:before { + background-position: -36px -312px!important +} + +i.flag-gs:before,i.flag-sandwich-islands:before { + background-position: -36px -338px!important +} + +i.flag-gt:before,i.flag-guatemala:before { + background-position: -36px -364px!important +} + +i.flag-gu:before,i.flag-guam:before { + background-position: -36px -390px!important +} + +i.flag-guinea-bissau:before,i.flag-gw:before { + background-position: -36px -416px!important +} + +i.flag-guyana:before,i.flag-gy:before { + background-position: -36px -442px!important +} + +i.flag-hk:before,i.flag-hong-kong:before { + background-position: -36px -468px!important +} + +i.flag-heard-island:before,i.flag-hm:before { + background-position: -36px -494px!important +} + +i.flag-hn:before,i.flag-honduras:before { + background-position: -36px -520px!important +} + +i.flag-croatia:before,i.flag-hr:before { + background-position: -36px -546px!important +} + +i.flag-haiti:before,i.flag-ht:before { + background-position: -36px -572px!important +} + +i.flag-hu:before,i.flag-hungary:before { + background-position: -36px -598px!important +} + +i.flag-id:before,i.flag-indonesia:before { + background-position: -36px -624px!important +} + +i.flag-ie:before,i.flag-ireland:before { + background-position: -36px -650px!important +} + +i.flag-il:before,i.flag-israel:before { + background-position: -36px -676px!important +} + +i.flag-in:before,i.flag-india:before { + background-position: -36px -702px!important +} + +i.flag-indian-ocean-territory:before,i.flag-io:before { + background-position: -36px -728px!important +} + +i.flag-iq:before,i.flag-iraq:before { + background-position: -36px -754px!important +} + +i.flag-ir:before,i.flag-iran:before { + background-position: -36px -780px!important +} + +i.flag-iceland:before,i.flag-is:before { + background-position: -36px -806px!important +} + +i.flag-it:before,i.flag-italy:before { + background-position: -36px -832px!important +} + +i.flag-jamaica:before,i.flag-jm:before { + background-position: -36px -858px!important +} + +i.flag-jo:before,i.flag-jordan:before { + background-position: -36px -884px!important +} + +i.flag-japan:before,i.flag-jp:before { + background-position: -36px -910px!important +} + +i.flag-ke:before,i.flag-kenya:before { + background-position: -36px -936px!important +} + +i.flag-kg:before,i.flag-kyrgyzstan:before { + background-position: -36px -962px!important +} + +i.flag-cambodia:before,i.flag-kh:before { + background-position: -36px -988px!important +} + +i.flag-ki:before,i.flag-kiribati:before { + background-position: -36px -1014px!important +} + +i.flag-comoros:before,i.flag-km:before { + background-position: -36px -1040px!important +} + +i.flag-kn:before,i.flag-saint-kitts-and-nevis:before { + background-position: -36px -1066px!important +} + +i.flag-kp:before,i.flag-north-korea:before { + background-position: -36px -1092px!important +} + +i.flag-kr:before,i.flag-south-korea:before { + background-position: -36px -1118px!important +} + +i.flag-kuwait:before,i.flag-kw:before { + background-position: -36px -1144px!important +} + +i.flag-cayman-islands:before,i.flag-ky:before { + background-position: -36px -1170px!important +} + +i.flag-kazakhstan:before,i.flag-kz:before { + background-position: -36px -1196px!important +} + +i.flag-la:before,i.flag-laos:before { + background-position: -36px -1222px!important +} + +i.flag-lb:before,i.flag-lebanon:before { + background-position: -36px -1248px!important +} + +i.flag-lc:before,i.flag-saint-lucia:before { + background-position: -36px -1274px!important +} + +i.flag-li:before,i.flag-liechtenstein:before { + background-position: -36px -1300px!important +} + +i.flag-lk:before,i.flag-sri-lanka:before { + background-position: -36px -1326px!important +} + +i.flag-liberia:before,i.flag-lr:before { + background-position: -36px -1352px!important +} + +i.flag-lesotho:before,i.flag-ls:before { + background-position: -36px -1378px!important +} + +i.flag-lithuania:before,i.flag-lt:before { + background-position: -36px -1404px!important +} + +i.flag-lu:before,i.flag-luxembourg:before { + background-position: -36px -1430px!important +} + +i.flag-latvia:before,i.flag-lv:before { + background-position: -36px -1456px!important +} + +i.flag-libya:before,i.flag-ly:before { + background-position: -36px -1482px!important +} + +i.flag-ma:before,i.flag-morocco:before { + background-position: -36px -1508px!important +} + +i.flag-mc:before,i.flag-monaco:before { + background-position: -36px -1534px!important +} + +i.flag-md:before,i.flag-moldova:before { + background-position: -36px -1560px!important +} + +i.flag-me:before,i.flag-montenegro:before { + background-position: -36px -1586px!important +} + +i.flag-madagascar:before,i.flag-mg:before { + background-position: -36px -1613px!important +} + +i.flag-marshall-islands:before,i.flag-mh:before { + background-position: -36px -1639px!important +} + +i.flag-macedonia:before,i.flag-mk:before { + background-position: -36px -1665px!important +} + +i.flag-mali:before,i.flag-ml:before { + background-position: -36px -1691px!important +} + +i.flag-burma:before,i.flag-mm:before,i.flag-myanmar:before { + background-position: -73px -1821px!important +} + +i.flag-mn:before,i.flag-mongolia:before { + background-position: -36px -1743px!important +} + +i.flag-macau:before,i.flag-mo:before { + background-position: -36px -1769px!important +} + +i.flag-mp:before,i.flag-northern-mariana-islands:before { + background-position: -36px -1795px!important +} + +i.flag-martinique:before,i.flag-mq:before { + background-position: -36px -1821px!important +} + +i.flag-mauritania:before,i.flag-mr:before { + background-position: -36px -1847px!important +} + +i.flag-montserrat:before,i.flag-ms:before { + background-position: -36px -1873px!important +} + +i.flag-malta:before,i.flag-mt:before { + background-position: -36px -1899px!important +} + +i.flag-mauritius:before,i.flag-mu:before { + background-position: -36px -1925px!important +} + +i.flag-maldives:before,i.flag-mv:before { + background-position: -36px -1951px!important +} + +i.flag-malawi:before,i.flag-mw:before { + background-position: -36px -1977px!important +} + +i.flag-mexico:before,i.flag-mx:before { + background-position: -72px 0!important +} + +i.flag-malaysia:before,i.flag-my:before { + background-position: -72px -26px!important +} + +i.flag-mozambique:before,i.flag-mz:before { + background-position: -72px -52px!important +} + +i.flag-na:before,i.flag-namibia:before { + background-position: -72px -78px!important +} + +i.flag-nc:before,i.flag-new-caledonia:before { + background-position: -72px -104px!important +} + +i.flag-ne:before,i.flag-niger:before { + background-position: -72px -130px!important +} + +i.flag-nf:before,i.flag-norfolk-island:before { + background-position: -72px -156px!important +} + +i.flag-ng:before,i.flag-nigeria:before { + background-position: -72px -182px!important +} + +i.flag-ni:before,i.flag-nicaragua:before { + background-position: -72px -208px!important +} + +i.flag-netherlands:before,i.flag-nl:before { + background-position: -72px -234px!important +} + +i.flag-no:before,i.flag-norway:before { + background-position: -72px -260px!important +} + +i.flag-nepal:before,i.flag-np:before { + background-position: -72px -286px!important +} + +i.flag-nauru:before,i.flag-nr:before { + background-position: -72px -312px!important +} + +i.flag-niue:before,i.flag-nu:before { + background-position: -72px -338px!important +} + +i.flag-new-zealand:before,i.flag-nz:before { + background-position: -72px -364px!important +} + +i.flag-om:before,i.flag-oman:before { + background-position: -72px -390px!important +} + +i.flag-pa:before,i.flag-panama:before { + background-position: -72px -416px!important +} + +i.flag-pe:before,i.flag-peru:before { + background-position: -72px -442px!important +} + +i.flag-french-polynesia:before,i.flag-pf:before { + background-position: -72px -468px!important +} + +i.flag-new-guinea:before,i.flag-pg:before { + background-position: -72px -494px!important +} + +i.flag-ph:before,i.flag-philippines:before { + background-position: -72px -520px!important +} + +i.flag-pakistan:before,i.flag-pk:before { + background-position: -72px -546px!important +} + +i.flag-pl:before,i.flag-poland:before { + background-position: -72px -572px!important +} + +i.flag-pm:before,i.flag-saint-pierre:before { + background-position: -72px -598px!important +} + +i.flag-pitcairn-islands:before,i.flag-pn:before { + background-position: -72px -624px!important +} + +i.flag-pr:before,i.flag-puerto-rico:before { + background-position: -72px -650px!important +} + +i.flag-palestine:before,i.flag-ps:before { + background-position: -72px -676px!important +} + +i.flag-portugal:before,i.flag-pt:before { + background-position: -72px -702px!important +} + +i.flag-palau:before,i.flag-pw:before { + background-position: -72px -728px!important +} + +i.flag-paraguay:before,i.flag-py:before { + background-position: -72px -754px!important +} + +i.flag-qa:before,i.flag-qatar:before { + background-position: -72px -780px!important +} + +i.flag-re:before,i.flag-reunion:before { + background-position: -72px -806px!important +} + +i.flag-ro:before,i.flag-romania:before { + background-position: -72px -832px!important +} + +i.flag-rs:before,i.flag-serbia:before { + background-position: -72px -858px!important +} + +i.flag-ru:before,i.flag-russia:before { + background-position: -72px -884px!important +} + +i.flag-rw:before,i.flag-rwanda:before { + background-position: -72px -910px!important +} + +i.flag-sa:before,i.flag-saudi-arabia:before { + background-position: -72px -936px!important +} + +i.flag-sb:before,i.flag-solomon-islands:before { + background-position: -72px -962px!important +} + +i.flag-sc:before,i.flag-seychelles:before { + background-position: -72px -988px!important +} + +i.flag-gb-sct:before,i.flag-scotland:before { + background-position: -72px -1014px!important +} + +i.flag-sd:before,i.flag-sudan:before { + background-position: -72px -1040px!important +} + +i.flag-se:before,i.flag-sweden:before { + background-position: -72px -1066px!important +} + +i.flag-sg:before,i.flag-singapore:before { + background-position: -72px -1092px!important +} + +i.flag-saint-helena:before,i.flag-sh:before { + background-position: -72px -1118px!important +} + +i.flag-si:before,i.flag-slovenia:before { + background-position: -72px -1144px!important +} + +i.flag-jan-mayen:before,i.flag-sj:before,i.flag-svalbard:before { + background-position: -72px -1170px!important +} + +i.flag-sk:before,i.flag-slovakia:before { + background-position: -72px -1196px!important +} + +i.flag-sierra-leone:before,i.flag-sl:before { + background-position: -72px -1222px!important +} + +i.flag-san-marino:before,i.flag-sm:before { + background-position: -72px -1248px!important +} + +i.flag-senegal:before,i.flag-sn:before { + background-position: -72px -1274px!important +} + +i.flag-so:before,i.flag-somalia:before { + background-position: -72px -1300px!important +} + +i.flag-sr:before,i.flag-suriname:before { + background-position: -72px -1326px!important +} + +i.flag-sao-tome:before,i.flag-st:before { + background-position: -72px -1352px!important +} + +i.flag-el-salvador:before,i.flag-sv:before { + background-position: -72px -1378px!important +} + +i.flag-sy:before,i.flag-syria:before { + background-position: -72px -1404px!important +} + +i.flag-swaziland:before,i.flag-sz:before { + background-position: -72px -1430px!important +} + +i.flag-caicos-islands:before,i.flag-tc:before { + background-position: -72px -1456px!important +} + +i.flag-chad:before,i.flag-td:before { + background-position: -72px -1482px!important +} + +i.flag-french-territories:before,i.flag-tf:before { + background-position: -72px -1508px!important +} + +i.flag-tg:before,i.flag-togo:before { + background-position: -72px -1534px!important +} + +i.flag-th:before,i.flag-thailand:before { + background-position: -72px -1560px!important +} + +i.flag-tajikistan:before,i.flag-tj:before { + background-position: -72px -1586px!important +} + +i.flag-tk:before,i.flag-tokelau:before { + background-position: -72px -1612px!important +} + +i.flag-timorleste:before,i.flag-tl:before { + background-position: -72px -1638px!important +} + +i.flag-tm:before,i.flag-turkmenistan:before { + background-position: -72px -1664px!important +} + +i.flag-tn:before,i.flag-tunisia:before { + background-position: -72px -1690px!important +} + +i.flag-to:before,i.flag-tonga:before { + background-position: -72px -1716px!important +} + +i.flag-tr:before,i.flag-turkey:before { + background-position: -72px -1742px!important +} + +i.flag-trinidad:before,i.flag-tt:before { + background-position: -72px -1768px!important +} + +i.flag-tuvalu:before,i.flag-tv:before { + background-position: -72px -1794px!important +} + +i.flag-taiwan:before,i.flag-tw:before { + background-position: -72px -1820px!important +} + +i.flag-tanzania:before,i.flag-tz:before { + background-position: -72px -1846px!important +} + +i.flag-ua:before,i.flag-ukraine:before { + background-position: -72px -1872px!important +} + +i.flag-ug:before,i.flag-uganda:before { + background-position: -72px -1898px!important +} + +i.flag-um:before,i.flag-us-minor-islands:before { + background-position: -72px -1924px!important +} + +i.flag-america:before,i.flag-united-states:before,i.flag-us:before { + background-position: -72px -1950px!important +} + +i.flag-uruguay:before,i.flag-uy:before { + background-position: -72px -1976px!important +} + +i.flag-uz:before,i.flag-uzbekistan:before { + background-position: -108px 0!important +} + +i.flag-va:before,i.flag-vatican-city:before { + background-position: -108px -26px!important +} + +i.flag-saint-vincent:before,i.flag-vc:before { + background-position: -108px -52px!important +} + +i.flag-ve:before,i.flag-venezuela:before { + background-position: -108px -78px!important +} + +i.flag-british-virgin-islands:before,i.flag-vg:before { + background-position: -108px -104px!important +} + +i.flag-us-virgin-islands:before,i.flag-vi:before { + background-position: -108px -130px!important +} + +i.flag-vietnam:before,i.flag-vn:before { + background-position: -108px -156px!important +} + +i.flag-vanuatu:before,i.flag-vu:before { + background-position: -108px -182px!important +} + +i.flag-gb-wls:before,i.flag-wales:before { + background-position: -108px -208px!important +} + +i.flag-wallis-and-futuna:before,i.flag-wf:before { + background-position: -108px -234px!important +} + +i.flag-samoa:before,i.flag-ws:before { + background-position: -108px -260px!important +} + +i.flag-ye:before,i.flag-yemen:before { + background-position: -108px -286px!important +} + +i.flag-mayotte:before,i.flag-yt:before { + background-position: -108px -312px!important +} + +i.flag-south-africa:before,i.flag-za:before { + background-position: -108px -338px!important +} + +i.flag-zambia:before,i.flag-zm:before { + background-position: -108px -364px!important +} + +i.flag-zimbabwe:before,i.flag-zw:before { + background-position: -108px -390px!important +} + +.bg-fixed { + background-attachment: fixed +} + +.bg-image { + position: relative; + overflow: hidden; + background-repeat: no-repeat; + background-size: cover; + background-position: 50% +} + +.mask { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + width: 100%; + height: 100%; + overflow: hidden; + background-attachment: fixed +} + +.hover-overlay .mask { + --mdb-image-hover-transition: all 0.3s ease-in-out; + opacity: 0; + transition: var(--mdb-image-hover-transition) +} + +.hover-overlay .mask:hover { + opacity: 1 +} + +.hover-zoom { + --mdb-image-hover-zoom-transition: all 0.3s linear; + --mdb-image-hover-zoom-transform: scale(1.1) +} + +.hover-zoom img,.hover-zoom video { + transition: var(--mdb-image-hover-zoom-transition) +} + +.hover-zoom:hover img,.hover-zoom:hover video { + transform: var(--mdb-image-hover-zoom-transform) +} + +.card.hover-shadow,.card.hover-shadow-soft,.hover-shadow,.hover-shadow-soft { + --mdb-image-hover-shadow-transition: all 0.3s ease-in-out; + transition: var(--mdb-image-hover-shadow-transition) +} + +.card.hover-shadow-soft:hover,.card.hover-shadow:hover,.hover-shadow-soft:hover,.hover-shadow:hover { + transition: var(--mdb-image-hover-shadow-transition) +} + +.card.hover-shadow,.hover-shadow { + --mdb-image-hover-shadow-box-shadow: 0 2px 15px -3px rgba(0,0,0,0.16),0 10px 20px -2px rgba(0,0,0,0.1); + box-shadow: none +} + +.card.hover-shadow:hover,.hover-shadow:hover { + box-shadow: var(--mdb-image-hover-shadow-box-shadow) +} + +.card.hover-shadow-soft,.hover-shadow-soft { + --mdb-image-hover-shadow-box-shadow-soft: 0 2px 25px -5px rgba(0,0,0,0.07),0 25px 21px -5px rgba(0,0,0,0.04); + box-shadow: none +} + +.card.hover-shadow-soft:hover,.hover-shadow-soft:hover { + box-shadow: var(--mdb-image-hover-shadow-box-shadow-soft) +} + +.form-control { + min-height: auto; + padding: 4.5px 12px 3.68px +} + +.form-control,.form-control:focus { + transition: all .1s linear; + box-shadow: none +} + +.form-control:focus { + border-color: #3b71ca; + box-shadow: inset 0 0 0 1px #3b71ca +} + +.form-control.form-control-sm { + font-size: .775rem; + line-height: 1.5 +} + +.form-control.form-control-lg { + line-height: 2.15; + border-radius: .25rem +} + +.form-outline { + position: relative; + width: 100% +} + +.form-outline .form-helper { + width: 100%; + position: absolute; + font-size: .875em; + color: #757575 +} + +.form-outline .form-helper .form-counter { + text-align: right +} + +.form-outline .trailing { + position: absolute; + right: 10px; + left: auto; + top: 50%; + transform: translateY(-50%); + pointer-events: none +} + +.form-outline .form-icon-trailing { + padding-right: 2rem!important +} + +.form-outline .form-control { + min-height: auto; + padding: .32rem .75rem; + border: 0; + background: transparent; + transition: all .2s linear +} + +.form-outline .form-control~.form-label { + position: absolute; + top: 0; + max-width: 90%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + left: .75rem; + padding-top: .37rem; + pointer-events: none; + transform-origin: 0 0; + transition: all .2s ease-out; + color: rgba(0,0,0,.6); + margin-bottom: 0 +} + +.form-outline .form-control~.form-notch { + display: flex; + position: absolute; + left: 0; + top: 0; + width: 100%; + max-width: 100%; + height: 100%; + text-align: left; + pointer-events: none +} + +.form-outline .form-control~.form-notch div { + pointer-events: none; + border: 1px solid #bdbdbd; + box-sizing: border-box; + background: transparent; + transition: all .2s linear +} + +.form-outline .form-control~.form-notch .form-notch-leading { + left: 0; + top: 0; + height: 100%; + width: .5rem; + border-right: none; + border-radius: .25rem 0 0 .25rem +} + +.form-outline .form-control~.form-notch .form-notch-middle { + flex: 0 0 auto; + width: auto; + max-width: calc(100% - 1rem); + height: 100%; + border-right: none; + border-left: none +} + +.form-outline .form-control~.form-notch .form-notch-trailing { + flex-grow: 1; + height: 100%; + border-left: none; + border-radius: 0 .25rem .25rem 0 +} + +.form-outline .form-control:not(.placeholder-active)::-moz-placeholder { + opacity: 0 +} + +.form-outline .form-control:not(.placeholder-active)::placeholder { + opacity: 0 +} + +.form-outline .form-control.active::-moz-placeholder,.form-outline .form-control:focus::-moz-placeholder { + opacity: 1 +} + +.form-outline .form-control.active::placeholder,.form-outline .form-control:focus::placeholder { + opacity: 1 +} + +.form-outline .form-control:focus { + box-shadow: none!important +} + +.form-outline .form-control.active~.form-label,.form-outline .form-control:focus~.form-label { + transform: translateY(-1rem) translateY(.1rem) scale(.8) +} + +.form-outline .form-control:focus~.form-label { + color: #3b71ca +} + +.form-outline .form-control.active~.form-notch .form-notch-middle,.form-outline .form-control:focus~.form-notch .form-notch-middle { + border-right: none; + border-left: none; + border-top: 1px solid transparent +} + +.form-outline .form-control:focus~.form-notch .form-notch-middle { + border-color: #3b71ca; + box-shadow: 0 1px 0 0 #3b71ca; + border-top: 1px solid transparent +} + +.form-outline .form-control.active~.form-notch .form-notch-leading,.form-outline .form-control:focus~.form-notch .form-notch-leading { + border-right: none +} + +.form-outline .form-control:focus~.form-notch .form-notch-leading { + border-color: #3b71ca; + box-shadow: -1px 0 0 0 #3b71ca,0 1px 0 0 #3b71ca,0 -1px 0 0 #3b71ca +} + +.form-outline .form-control.active~.form-notch .form-notch-trailing,.form-outline .form-control:focus~.form-notch .form-notch-trailing { + border-left: none +} + +.form-outline .form-control:focus~.form-notch .form-notch-trailing { + border-color: #3b71ca; + box-shadow: 1px 0 0 0 #3b71ca,0 -1px 0 0 #3b71ca,0 1px 0 0 #3b71ca +} + +.form-outline .form-control.disabled,.form-outline .form-control:disabled,.form-outline .form-control[readonly] { + background-color: #e9ecef +} + +.form-outline .form-control.form-control-lg { + font-size: 1rem; + line-height: 2.15 +} + +.form-outline .form-control.form-control-lg~.form-label { + padding-top: .7rem +} + +.form-outline .form-control.form-control-lg.active~.form-label,.form-outline .form-control.form-control-lg:focus~.form-label { + transform: translateY(-1.25rem) translateY(.1rem) scale(.8) +} + +.form-outline .form-control.form-control-sm { + padding-top: .32rem; + padding-bottom: .32rem; + font-size: .775rem; + line-height: 1.5 +} + +.form-outline .form-control.form-control-sm~.form-label { + padding-top: .33rem; + font-size: .775rem +} + +.form-outline .form-control.form-control-sm.active~.form-label,.form-outline .form-control.form-control-sm:focus~.form-label { + transform: translateY(-.85rem) translateY(.1rem) scale(.8) +} + +.form-outline.form-white .form-control { + color: #fff +} + +.form-outline.form-white .form-control~.form-label { + color: #fbfbfb +} + +.form-outline.form-white .form-control~.form-notch div { + border-color: #fbfbfb +} + +.form-outline.form-white .form-control:focus~.form-label { + color: #fff +} + +.form-outline.form-white .form-control:focus~.form-notch .form-notch-middle { + border-color: #fff; + box-shadow: 0 1px 0 0 #fff; + border-top: 1px solid transparent +} + +.form-outline.form-white .form-control:focus~.form-notch .form-notch-leading { + border-color: #fff; + box-shadow: -1px 0 0 0 #fff,0 1px 0 0 #fff,0 -1px 0 0 #fff +} + +.form-outline.form-white .form-control:focus~.form-notch .form-notch-trailing { + border-color: #fff; + box-shadow: 1px 0 0 0 #fff,0 -1px 0 0 #fff,0 1px 0 0 #fff +} + +.form-outline.form-white .form-control::-moz-placeholder { + color: hsla(0,0%,100%,.7) +} + +.form-outline.form-white .form-control::placeholder { + color: hsla(0,0%,100%,.7) +} + +.form-outline.form-white .form-control.disabled,.form-outline.form-white .form-control:disabled,.form-outline.form-white .form-control[readonly] { + background-color: hsla(0,0%,100%,.45) +} + +.select-input.form-control[readonly]:not([disabled]) { + background-color: transparent +} + +.form-select { + transition: all .2s linear +} + +.form-select:focus { + border-color: #3b71ca; + outline: 0; + box-shadow: inset 0 0 0 1px #3b71ca +} + +.form-check { + min-height: 1.5rem +} + +.form-check-input { + position: relative; + width: 1.125rem; + height: 1.125rem; + background-color: #fff; + border: .125rem solid rgba(0,0,0,.25) +} + +.form-check-input:before { + content: ""; + position: absolute; + box-shadow: 0 0 0 13px transparent; + border-radius: 50%; + width: .875rem; + height: .875rem; + background-color: transparent; + opacity: 0; + pointer-events: none; + transform: scale(0) +} + +.form-check-input:hover { + cursor: pointer +} + +.form-check-input:hover:before { + opacity: .04; + box-shadow: 0 0 0 13px rgba(0,0,0,.6) +} + +.form-check-input:focus { + box-shadow: none; + border-color: rgba(0,0,0,.25); + transition: border-color .2s +} + +.form-check-input:focus:before { + opacity: .12; + box-shadow: 0 0 0 13px rgba(0,0,0,.6); + transform: scale(1); + transition: box-shadow .2s,transform .2s +} + +.form-check-input:checked { + border-color: #3b71ca +} + +.form-check-input:checked:before { + opacity: .16 +} + +.form-check-input:checked:after { + content: ""; + position: absolute +} + +.form-check-input:checked:focus { + border-color: #3b71ca +} + +.form-check-input:checked:focus:before { + box-shadow: 0 0 0 13px #3b71ca; + transform: scale(1); + transition: box-shadow .2s,transform .2s +} + +.form-check-input:indeterminate:focus:before { + box-shadow: 0 0 0 13px #3b71ca +} + +.form-check-input[type=checkbox] { + border-radius: .25rem; + margin-top: .19em; + margin-right: 6px +} + +.form-check-input[type=checkbox]:focus:after { + content: ""; + position: absolute; + width: .875rem; + height: .875rem; + z-index: 1; + display: block; + border-radius: 0; + background-color: #fff +} + +.form-check-input[type=checkbox]:checked { + background-image: none; + background-color: #3b71ca +} + +.form-check-input[type=checkbox]:checked:after { + display: block; + transform: rotate(45deg) /*!rtl:ignore*/; + width: .375rem; + height: .8125rem; + border: .125rem solid #fff; + border-top: 0; + border-left: 0 /*!rtl:ignore*/; + margin-left: .25rem; + margin-top: -1px; + background-color: transparent +} + +.form-check-input[type=checkbox]:checked:focus { + background-color: #3b71ca +} + +.form-check-input[type=checkbox]:indeterminate { + border-color: #3b71ca +} + +.form-check-input[type=radio] { + border-radius: 50%; + width: 1.25rem; + height: 1.25rem; + margin-top: .125em; + margin-right: 4px +} + +.form-check-input[type=radio]:before { + width: 1rem; + height: 1rem +} + +.form-check-input[type=radio]:after { + content: ""; + position: absolute; + width: 1rem; + height: 1rem; + z-index: 1; + display: block; + border-radius: 50%; + background-color: #fff +} + +.form-check-input[type=radio]:checked { + background-image: none; + background-color: #fff +} + +.form-check-input[type=radio]:checked:after { + border-radius: 50%; + width: .625rem; + height: .625rem; + border-color: #3b71ca; + background-color: #3b71ca; + transition: border-color; + transform: translate(-50%,-50%); + position: absolute; + left: 50%; + top: 50% +} + +.form-check-input[type=radio]:checked:focus { + background-color: #fff +} + +.form-check-label { + padding-left: .15rem +} + +.form-check-label:hover { + cursor: pointer +} + +.form-switch .form-check-input { + background-image: none; + border-width: 0; + border-radius: .4375rem; + width: 2rem; + height: .875rem; + background-color: rgba(0,0,0,.25); + margin-top: .3em; + margin-right: 8px +} + +.form-switch .form-check-input:after { + content: ""; + position: absolute; + border: none; + z-index: 2; + border-radius: 50%; + width: 1.25rem; + height: 1.25rem; + background-color: #fff; + margin-top: -.1875rem; + box-shadow: 0 0 3px 0 rgba(0,0,0,.07),0 2px 2px 0 rgba(0,0,0,.04); + transition: background-color .2s,transform .2s +} + +.form-switch .form-check-input:focus { + background-image: none +} + +.form-switch .form-check-input:focus:before { + box-shadow: 3px -1px 0 13px rgba(0,0,0,.6); + transform: scale(1); + transition: box-shadow .2s,transform .2s +} + +.form-switch .form-check-input:focus:after { + border-radius: 50%; + width: 1.25rem; + height: 1.25rem +} + +.form-switch .form-check-input:checked,.form-switch .form-check-input:checked:focus { + background-image: none +} + +.form-switch .form-check-input:checked:focus:before { + margin-left: 1.0625rem; + box-shadow: 3px -1px 0 13px #3b71ca; + transform: scale(1); + transition: box-shadow .2s,transform .2s +} + +.form-switch .form-check-input:checked[type=checkbox] { + background-image: none +} + +.form-switch .form-check-input:checked[type=checkbox]:after { + content: ""; + position: absolute; + border: none; + z-index: 2; + border-radius: 50%; + width: 1.25rem; + height: 1.25rem; + background-color: #3b71ca; + margin-top: -3px; + margin-left: 1.0625rem; + box-shadow: 0 3px 1px -2px rgba(0,0,0,.2),0 2px 2px 0 rgba(0,0,0,.14),0 1px 5px 0 rgba(0,0,0,.12); + transition: background-color .2s,transform .2s +} + +.form-control:hover:not(:disabled):not([readonly])::-webkit-file-upload-button,.form-control[type=file]::-webkit-file-upload-button { + background-color: transparent +} + +.input-group { + flex-wrap: nowrap +} + +.input-group>.form-control { + min-height: calc(2.08rem + 2px); + height: calc(2.08rem + 2px); + padding-top: .27rem; + padding-bottom: .27rem; + transition: all .2s linear +} + +.input-group>.form-control:focus { + transition: all .2s linear; + border-color: #3b71ca; + outline: 0; + box-shadow: inset 0 0 0 1px #3b71ca +} + +.input-group-text { + background-color: transparent; + padding-top: .26rem; + padding-bottom: .26rem +} + +.input-group-text>.form-check-input[type=checkbox] { + margin-left: 1px; + margin-right: 1px +} + +.input-group-text>.form-check-input[type=radio] { + margin-right: 0 +} + +.input-group-lg>.form-control { + height: calc(2.645rem + 2px); + font-size: 1rem; + padding-top: .33rem; + padding-bottom: .33rem +} + +.input-group-lg .input-group-text { + font-size: 1rem +} + +.input-group-sm>.form-control { + min-height: calc(1.66rem + 2px); + height: calc(1.66rem + 2px); + font-size: .775rem; + padding-top: .33rem; + padding-bottom: .33rem +} + +.input-group-sm .input-group-text { + font-size: .775rem; + line-height: 1.5 +} + +.input-group.form-outline .input-group-text { + border-left: 0 +} + +.input-group.form-outline input+.input-group-text { + border: 0; + border-left: 1px solid #bdbdbd +} + +.input-group .form-outline:not(:first-child),.input-group .form-outline:not(:first-child) .form-notch-leading,.input-group .select-wrapper:not(:first-child),.input-group .select-wrapper:not(:first-child) .form-notch-leading { + border-top-left-radius: 0!important; + border-bottom-left-radius: 0!important +} + +.input-group .form-outline:not(:last-child),.input-group .form-outline:not(:last-child) .form-notch-trailing,.input-group .select-wrapper:not(:last-child),.input-group .select-wrapper:not(:last-child) .form-notch-trailing { + border-top-right-radius: 0!important; + border-bottom-right-radius: 0!important +} + +.input-group>[class*=btn-outline-]+[class*=btn-outline-] { + border-left: 0 +} + +.input-group>.btn[class*=btn-outline-] { + padding-top: .47rem +} + +.input-group>.btn { + padding-top: .59rem +} + +.input-group.input-group-lg .input-group-text { + height: calc(2.645rem + 2px) +} + +.input-group .input-group-text { + height: calc(2.08rem + 2px) +} + +.input-group .btn { + line-height: 1 +} + +.input-group.input-group-sm .input-group-text { + height: calc(1.66rem + 2px) +} + +.input-group .invalid-feedback,.input-group .valid-feedback,.was-validated .input-group .invalid-feedback,.was-validated .input-group .valid-feedback { + margin-top: 2.5rem +} + +.valid-feedback { + width: auto; + color: #14a44d; + margin-top: -.75rem +} + +.valid-feedback,.valid-tooltip { + position: absolute; + display: none; + font-size: .875rem +} + +.valid-tooltip { + top: 100%; + z-index: 5; + max-width: 100%; + padding: 6px 16px; + margin-top: .1rem; + background-color: rgba(20,164,77,.9); + border-radius: .25rem!important; + color: #fff +} + +.is-valid~.valid-feedback,.is-valid~.valid-tooltip,.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip { + display: block +} + +.form-control.is-valid,.was-validated .form-control:valid { + margin-bottom: 1rem; + background-image: none; + border-color: #14a44d +} + +.form-control.is-valid:focus,.was-validated .form-control:valid:focus { + border-color: #14a44d; + box-shadow: 0 0 0 .25rem rgba(20,164,77,.25) +} + +.form-outline .form-control.is-valid~.form-label,.was-validated .form-outline .form-control:valid~.form-label { + color: #14a44d +} + +.form-outline .form-control.is-valid~.form-notch .form-notch-leading,.form-outline .form-control.is-valid~.form-notch .form-notch-middle,.form-outline .form-control.is-valid~.form-notch .form-notch-trailing,.was-validated .form-outline .form-control:valid~.form-notch .form-notch-leading,.was-validated .form-outline .form-control:valid~.form-notch .form-notch-middle,.was-validated .form-outline .form-control:valid~.form-notch .form-notch-trailing { + border-color: #14a44d +} + +.form-outline .form-control.is-valid.active~.form-notch .form-notch-middle,.form-outline .form-control.is-valid:focus~.form-notch .form-notch-middle,.was-validated .form-outline .form-control:valid.active~.form-notch .form-notch-middle,.was-validated .form-outline .form-control:valid:focus~.form-notch .form-notch-middle { + border-top: 1px solid transparent +} + +.form-outline .form-control.is-valid:focus~.form-notch .form-notch-middle,.was-validated .form-outline .form-control:valid:focus~.form-notch .form-notch-middle { + box-shadow: 0 1px 0 0 #14a44d +} + +.form-outline .form-control.is-valid:focus~.form-notch .form-notch-leading,.was-validated .form-outline .form-control:valid:focus~.form-notch .form-notch-leading { + box-shadow: -1px 0 0 0 #14a44d,0 1px 0 0 #14a44d,0 -1px 0 0 #14a44d +} + +.form-outline .form-control.is-valid:focus~.form-notch .form-notch-trailing,.was-validated .form-outline .form-control:valid:focus~.form-notch .form-notch-trailing { + box-shadow: 1px 0 0 0 #14a44d,0 -1px 0 0 #14a44d,0 1px 0 0 #14a44d +} + +.form-outline .form-control.is-valid.select-input.focused~.form-notch .form-notch-leading,.was-validated .form-outline .form-control:valid.select-input.focused~.form-notch .form-notch-leading { + box-shadow: -1px 0 0 0 #14a44d,0 1px 0 0 #14a44d,0 -1px 0 0 #14a44d +} + +.form-outline .form-control.is-valid.select-input.focused~.form-notch .form-notch-middle,.was-validated .form-outline .form-control:valid.select-input.focused~.form-notch .form-notch-middle { + box-shadow: 0 1px 0 0 #14a44d; + border-top: 1px solid transparent +} + +.form-outline .form-control.is-valid.select-input.focused~.form-notch .form-notch-trailing,.was-validated .form-outline .form-control:valid.select-input.focused~.form-notch .form-notch-trailing { + box-shadow: 1px 0 0 0 #14a44d,0 -1px 0 0 #14a44d,0 1px 0 0 #14a44d +} + +.form-select.is-valid,.was-validated .form-select:valid { + border-color: #14a44d +} + +.form-select.is-valid:focus,.was-validated .form-select:valid:focus { + border-color: #14a44d; + box-shadow: 0 0 0 .25rem rgba(20,164,77,.25) +} + +.form-select.is-valid~.valid-feedback,.was-validated .form-select:valid~.valid-feedback { + margin-top: 0 +} + +.input-group .form-control.is-valid,.was-validated .input-group .form-control:valid { + margin-bottom: 0 +} + +.was-validated input[type=file].form-control:valid .valid-feedback,input[type=file].form-control.is-valid .valid-feedback { + margin-top: 0 +} + +.was-validated input[type=file].form-control:valid:focus,input[type=file].form-control.is-valid:focus { + box-shadow: inset 0 0 0 1px #14a44d; + border-color: #14a44d +} + +.was-validated input[type=file].form-control:valid:focus~.form-file-label,input[type=file].form-control.is-valid:focus~.form-file-label { + box-shadow: none +} + +.was-validated input[type=file].form-control:valid:focus-within~.form-file-label .form-file-button,.was-validated input[type=file].form-control:valid:focus-within~.form-file-label .form-file-text,input[type=file].form-control.is-valid:focus-within~.form-file-label .form-file-button,input[type=file].form-control.is-valid:focus-within~.form-file-label .form-file-text { + border-color: #14a44d +} + +.form-check-input.is-valid,.was-validated .form-check-input:valid { + border-color: #14a44d +} + +.form-check-input.is-valid:checked,.was-validated .form-check-input:valid:checked { + background-color: #14a44d +} + +.form-check-input.is-valid:checked:focus:before,.was-validated .form-check-input:valid:checked:focus:before { + box-shadow: 0 0 0 13px #14a44d +} + +.form-check-input.is-valid:focus,.was-validated .form-check-input:valid:focus { + box-shadow: none +} + +.form-check-input.is-valid:focus:before,.was-validated .form-check-input:valid:focus:before { + box-shadow: 0 0 0 13px #14a44d +} + +.form-check-input.is-valid~.form-check-label,.was-validated .form-check-input:valid~.form-check-label { + color: #14a44d; + margin-bottom: 1rem +} + +.form-check-input.is-valid[type=checkbox]:checked:focus,.was-validated .form-check-input:valid[type=checkbox]:checked:focus { + background-color: #14a44d; + border-color: #14a44d +} + +.form-check-input.is-valid[type=radio]:checked,.was-validated .form-check-input:valid[type=radio]:checked { + border-color: #14a44d; + background-color: #fff +} + +.form-check-input.is-valid[type=radio]:checked:focus:before,.was-validated .form-check-input:valid[type=radio]:checked:focus:before { + box-shadow: 0 0 0 13px #14a44d +} + +.form-check-input.is-valid[type=radio]:checked:after,.was-validated .form-check-input:valid[type=radio]:checked:after { + border-color: #14a44d; + background-color: #14a44d +} + +.form-check-inline .form-check-input~.valid-feedback { + margin-left: .5em +} + +.form-switch .form-check-input.is-valid:focus:before,.was-validated .form-switch .form-check-input:valid:focus:before { + box-shadow: 3px -1px 0 13px rgba(0,0,0,.6) +} + +.form-switch .form-check-input.is-valid:checked[type=checkbox]:after,.was-validated .form-switch .form-check-input:valid:checked[type=checkbox]:after { + background-color: #14a44d; + box-shadow: 0 3px 1px -2px rgba(0,0,0,.2),0 2px 2px 0 rgba(0,0,0,.14),0 1px 5px 0 rgba(0,0,0,.12) +} + +.form-switch .form-check-input.is-valid:checked:focus:before,.was-validated .form-switch .form-check-input:valid:checked:focus:before { + box-shadow: 3px -1px 0 13px #14a44d +} + +.invalid-feedback { + width: auto; + color: #dc4c64; + margin-top: -.75rem +} + +.invalid-feedback,.invalid-tooltip { + position: absolute; + display: none; + font-size: .875rem +} + +.invalid-tooltip { + top: 100%; + z-index: 5; + max-width: 100%; + padding: 6px 16px; + margin-top: .1rem; + background-color: rgba(220,76,100,.9); + border-radius: .25rem!important; + color: #fff +} + +.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip,.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip { + display: block +} + +.form-control.is-invalid,.was-validated .form-control:invalid { + margin-bottom: 1rem; + background-image: none; + border-color: #dc4c64 +} + +.form-control.is-invalid:focus,.was-validated .form-control:invalid:focus { + border-color: #dc4c64; + box-shadow: 0 0 0 .25rem rgba(220,76,100,.25) +} + +.form-outline .form-control.is-invalid~.form-label,.was-validated .form-outline .form-control:invalid~.form-label { + color: #dc4c64 +} + +.form-outline .form-control.is-invalid~.form-notch .form-notch-leading,.form-outline .form-control.is-invalid~.form-notch .form-notch-middle,.form-outline .form-control.is-invalid~.form-notch .form-notch-trailing,.was-validated .form-outline .form-control:invalid~.form-notch .form-notch-leading,.was-validated .form-outline .form-control:invalid~.form-notch .form-notch-middle,.was-validated .form-outline .form-control:invalid~.form-notch .form-notch-trailing { + border-color: #dc4c64 +} + +.form-outline .form-control.is-invalid.active~.form-notch .form-notch-middle,.form-outline .form-control.is-invalid:focus~.form-notch .form-notch-middle,.was-validated .form-outline .form-control:invalid.active~.form-notch .form-notch-middle,.was-validated .form-outline .form-control:invalid:focus~.form-notch .form-notch-middle { + border-top: 1px solid transparent +} + +.form-outline .form-control.is-invalid:focus~.form-notch .form-notch-middle,.was-validated .form-outline .form-control:invalid:focus~.form-notch .form-notch-middle { + box-shadow: 0 1px 0 0 #dc4c64 +} + +.form-outline .form-control.is-invalid:focus~.form-notch .form-notch-leading,.was-validated .form-outline .form-control:invalid:focus~.form-notch .form-notch-leading { + box-shadow: -1px 0 0 0 #dc4c64,0 1px 0 0 #dc4c64,0 -1px 0 0 #dc4c64 +} + +.form-outline .form-control.is-invalid:focus~.form-notch .form-notch-trailing,.was-validated .form-outline .form-control:invalid:focus~.form-notch .form-notch-trailing { + box-shadow: 1px 0 0 0 #dc4c64,0 -1px 0 0 #dc4c64,0 1px 0 0 #dc4c64 +} + +.form-outline .form-control.is-invalid.select-input.focused~.form-notch .form-notch-leading,.was-validated .form-outline .form-control:invalid.select-input.focused~.form-notch .form-notch-leading { + box-shadow: -1px 0 0 0 #dc4c64,0 1px 0 0 #dc4c64,0 -1px 0 0 #dc4c64 +} + +.form-outline .form-control.is-invalid.select-input.focused~.form-notch .form-notch-middle,.was-validated .form-outline .form-control:invalid.select-input.focused~.form-notch .form-notch-middle { + box-shadow: 0 1px 0 0 #dc4c64; + border-top: 1px solid transparent +} + +.form-outline .form-control.is-invalid.select-input.focused~.form-notch .form-notch-trailing,.was-validated .form-outline .form-control:invalid.select-input.focused~.form-notch .form-notch-trailing { + box-shadow: 1px 0 0 0 #dc4c64,0 -1px 0 0 #dc4c64,0 1px 0 0 #dc4c64 +} + +.form-select.is-invalid,.was-validated .form-select:invalid { + border-color: #dc4c64 +} + +.form-select.is-invalid:focus,.was-validated .form-select:invalid:focus { + border-color: #dc4c64; + box-shadow: 0 0 0 .25rem rgba(220,76,100,.25) +} + +.form-select.is-invalid~.invalid-feedback,.was-validated .form-select:invalid~.invalid-feedback { + margin-top: 0 +} + +.input-group .form-control.is-invalid,.was-validated .input-group .form-control:invalid { + margin-bottom: 0 +} + +.was-validated input[type=file].form-control:invalid .invalid-feedback,input[type=file].form-control.is-invalid .invalid-feedback { + margin-top: 0 +} + +.was-validated input[type=file].form-control:invalid:focus,input[type=file].form-control.is-invalid:focus { + box-shadow: inset 0 0 0 1px #dc4c64; + border-color: #dc4c64 +} + +.was-validated input[type=file].form-control:invalid:focus~.form-file-label,input[type=file].form-control.is-invalid:focus~.form-file-label { + box-shadow: none +} + +.was-validated input[type=file].form-control:invalid:focus-within~.form-file-label .form-file-button,.was-validated input[type=file].form-control:invalid:focus-within~.form-file-label .form-file-text,input[type=file].form-control.is-invalid:focus-within~.form-file-label .form-file-button,input[type=file].form-control.is-invalid:focus-within~.form-file-label .form-file-text { + border-color: #dc4c64 +} + +.form-check-input.is-invalid,.was-validated .form-check-input:invalid { + border-color: #dc4c64 +} + +.form-check-input.is-invalid:checked,.was-validated .form-check-input:invalid:checked { + background-color: #dc4c64 +} + +.form-check-input.is-invalid:checked:focus:before,.was-validated .form-check-input:invalid:checked:focus:before { + box-shadow: 0 0 0 13px #dc4c64 +} + +.form-check-input.is-invalid:focus,.was-validated .form-check-input:invalid:focus { + box-shadow: none +} + +.form-check-input.is-invalid:focus:before,.was-validated .form-check-input:invalid:focus:before { + box-shadow: 0 0 0 13px #dc4c64 +} + +.form-check-input.is-invalid~.form-check-label,.was-validated .form-check-input:invalid~.form-check-label { + color: #dc4c64; + margin-bottom: 1rem +} + +.form-check-input.is-invalid[type=checkbox]:checked:focus,.was-validated .form-check-input:invalid[type=checkbox]:checked:focus { + background-color: #dc4c64; + border-color: #dc4c64 +} + +.form-check-input.is-invalid[type=radio]:checked,.was-validated .form-check-input:invalid[type=radio]:checked { + border-color: #dc4c64; + background-color: #fff +} + +.form-check-input.is-invalid[type=radio]:checked:focus:before,.was-validated .form-check-input:invalid[type=radio]:checked:focus:before { + box-shadow: 0 0 0 13px #dc4c64 +} + +.form-check-input.is-invalid[type=radio]:checked:after,.was-validated .form-check-input:invalid[type=radio]:checked:after { + border-color: #dc4c64; + background-color: #dc4c64 +} + +.form-check-inline .form-check-input~.invalid-feedback { + margin-left: .5em +} + +.form-switch .form-check-input.is-invalid:focus:before,.was-validated .form-switch .form-check-input:invalid:focus:before { + box-shadow: 3px -1px 0 13px rgba(0,0,0,.6) +} + +.form-switch .form-check-input.is-invalid:checked[type=checkbox]:after,.was-validated .form-switch .form-check-input:invalid:checked[type=checkbox]:after { + background-color: #dc4c64; + box-shadow: 0 3px 1px -2px rgba(0,0,0,.2),0 2px 2px 0 rgba(0,0,0,.14),0 1px 5px 0 rgba(0,0,0,.12) +} + +.form-switch .form-check-input.is-invalid:checked:focus:before,.was-validated .form-switch .form-check-input:invalid:checked:focus:before { + box-shadow: 3px -1px 0 13px #dc4c64 +} + +.form-range:focus { + box-shadow: none +} + +.form-range:focus::-webkit-slider-thumb { + box-shadow: none +} + +.form-range:focus::-moz-range-thumb { + box-shadow: none +} + +.form-range:focus::-ms-thumb { + box-shadow: none +} + +.form-range::-moz-focus-outer { + border: 0 +} + +.form-range::-webkit-slider-thumb { + margin-top: -6px; + box-shadow: none; + -webkit-appearance: none; + appearance: none +} + +.form-range::-webkit-slider-runnable-track { + height: 4px; + border-radius: 0; + box-shadow: none +} + +.form-range::-moz-range-thumb { + box-shadow: none; + -moz-appearance: none; + appearance: none +} + +.form-range::-moz-range-track { + box-shadow: none +} + +.table { + --mdb-table-font-size: 0.9rem; + --mdb-table-divider-color: rgba(0,0,0,0.1); + font-size: var(--mdb-table-font-size) +} + +.table th { + font-weight: 500 +} + +.table tbody { + font-weight: 400 +} + +.table>:not(:last-child)>:last-child>* { + border-bottom-color: inherit +} + +.table-primary { + --mdb-table-color: #000; + --mdb-table-bg: #d8e3f4; + --mdb-table-border-color: #c2ccdc; + --mdb-table-striped-bg: #cdd8e8; + --mdb-table-striped-color: #000; + --mdb-table-active-bg: #c2ccdc; + --mdb-table-active-color: #000; + --mdb-table-hover-bg: #c8d2e2; + --mdb-table-hover-color: #000 +} + +.table-primary,.table-secondary { + color: var(--mdb-table-color); + border-color: var(--mdb-table-border-color) +} + +.table-secondary { + --mdb-table-color: #000; + --mdb-table-bg: #ecedf0; + --mdb-table-border-color: #d4d5d8; + --mdb-table-striped-bg: #e0e1e4; + --mdb-table-striped-color: #000; + --mdb-table-active-bg: #d4d5d8; + --mdb-table-active-color: #000; + --mdb-table-hover-bg: #dadbde; + --mdb-table-hover-color: #000 +} + +.table-success { + --mdb-table-color: #000; + --mdb-table-bg: #d0eddb; + --mdb-table-border-color: #bbd5c5; + --mdb-table-striped-bg: #c6e1d0; + --mdb-table-striped-color: #000; + --mdb-table-active-bg: #bbd5c5; + --mdb-table-active-color: #000; + --mdb-table-hover-bg: #c0dbcb; + --mdb-table-hover-color: #000 +} + +.table-info,.table-success { + color: var(--mdb-table-color); + border-color: var(--mdb-table-border-color) +} + +.table-info { + --mdb-table-color: #000; + --mdb-table-bg: #ddf0f6; + --mdb-table-border-color: #c7d8dd; + --mdb-table-striped-bg: #d2e4ea; + --mdb-table-striped-color: #000; + --mdb-table-active-bg: #c7d8dd; + --mdb-table-active-color: #000; + --mdb-table-hover-bg: #ccdee4; + --mdb-table-hover-color: #000 +} + +.table-warning { + --mdb-table-color: #000; + --mdb-table-bg: #faecd1; + --mdb-table-border-color: #e1d4bc; + --mdb-table-striped-bg: #eee0c7; + --mdb-table-striped-color: #000; + --mdb-table-active-bg: #e1d4bc; + --mdb-table-active-color: #000; + --mdb-table-hover-bg: #e7dac1; + --mdb-table-hover-color: #000 +} + +.table-danger,.table-warning { + color: var(--mdb-table-color); + border-color: var(--mdb-table-border-color) +} + +.table-danger { + --mdb-table-color: #000; + --mdb-table-bg: #f8dbe0; + --mdb-table-border-color: #dfc5ca; + --mdb-table-striped-bg: #ecd0d5; + --mdb-table-striped-color: #000; + --mdb-table-active-bg: #dfc5ca; + --mdb-table-active-color: #000; + --mdb-table-hover-bg: #e5cbcf; + --mdb-table-hover-color: #000 +} + +.table-light { + --mdb-table-color: #000; + --mdb-table-bg: #fbfbfb; + --mdb-table-border-color: #e2e2e2; + --mdb-table-striped-bg: #eee; + --mdb-table-striped-color: #000; + --mdb-table-active-bg: #e2e2e2; + --mdb-table-active-color: #000; + --mdb-table-hover-bg: #e8e8e8; + --mdb-table-hover-color: #000 +} + +.table-dark,.table-light { + color: var(--mdb-table-color); + border-color: var(--mdb-table-border-color) +} + +.table-dark { + --mdb-table-color: #fff; + --mdb-table-bg: #332d2d; + --mdb-table-border-color: #474242; + --mdb-table-striped-bg: #3d3838; + --mdb-table-striped-color: #fff; + --mdb-table-active-bg: #474242; + --mdb-table-active-color: #fff; + --mdb-table-hover-bg: #423d3d; + --mdb-table-hover-color: #fff +} + +.table-hover>tbody>tr { + transition: .5s +} + +.table-hover>tbody>tr:hover { + --mdb-table-accent-bg: transparent; + background-color: var(--mdb-table-hover-bg) +} + +.table-group-divider { + border-top: 2px solid; + border-top-color: inherit +} + +.table-divider-color { + border-top-color: var(--mdb-table-divider-color) +} + +.btn { + --mdb-btn-padding-top: 0.625rem; + --mdb-btn-padding-bottom: 0.5rem; + --mdb-btn-border-width: 0; + --mdb-btn-border-color: none; + --mdb-btn-border-radius: 0.25rem; + --mdb-btn-box-shadow: 0 4px 9px -4px rgba(0,0,0,0.35); + --mdb-btn-hover-box-shadow: 0 8px 9px -4px rgba(0,0,0,0.15),0 4px 18px 0 rgba(0,0,0,0.1); + --mdb-btn-focus-box-shadow: 0 8px 9px -4px rgba(0,0,0,0.15),0 4px 18px 0 rgba(0,0,0,0.1); + --mdb-btn-active-box-shadow: 0 8px 9px -4px rgba(0,0,0,0.15),0 4px 18px 0 rgba(0,0,0,0.1); + padding-top: var(--mdb-btn-padding-top); + padding-bottom: var(--mdb-btn-padding-bottom); + text-transform: uppercase; + vertical-align: bottom; + border: 0; + border-radius: var(--mdb-btn-border-radius); + box-shadow: var(--mdb-btn-box-shadow) +} + +.btn:first-child:hover,.btn:focus-visible,.btn:hover,:not(.btn-check)+.btn:hover { + box-shadow: var(--mdb-btn-hover-box-shadow) +} + +.btn-check:focus+.btn,.btn-check:focus-visible+.btn,.btn:focus { + box-shadow: var(--mdb-btn-focus-box-shadow) +} + +.btn-check:active+.btn,.btn-check:checked+.btn,.btn.active,.btn.show,.btn:active { + box-shadow: var(--mdb-btn-active-box-shadow) +} + +.btn-check:active+.btn:focus,.btn-check:checked+.btn:focus,.btn.active:focus,.btn.show:focus,.btn:active:focus { + box-shadow: var(--mdb-btn-focus-box-shadow) +} + +.btn.disabled,.btn:disabled,fieldset:disabled .btn { + box-shadow: var(--mdb-btn-box-shadow) +} + +[class*=btn-outline-] { + --mdb-btn-padding-top: 0.5rem; + --mdb-btn-padding-bottom: 0.375rem; + --mdb-btn-padding-x: 1.375rem; + --mdb-btn-border-width: 2px; + --mdb-btn-line-height: 1.5; + padding: var(--mdb-btn-padding-top) var(--mdb-btn-padding-x) var(--mdb-btn-padding-bottom); + border-width: var(--mdb-btn-border-width); + border-style: solid; + box-shadow: none +} + +.btn-check:active+[class*=btn-outline-],.btn-check:active+[class*=btn-outline-]:focus,.btn-check:checked+[class*=btn-outline-],.btn-check:checked+[class*=btn-outline-]:focus,.btn-check:focus+[class*=btn-outline-],.btn-check:focus-visible+[class*=btn-outline-],:not(.btn-check)+[class*=btn-outline-]:hover,[class*=btn-outline-].active,[class*=btn-outline-].active:focus,[class*=btn-outline-].disabled,[class*=btn-outline-].show,[class*=btn-outline-].show:focus,[class*=btn-outline-]:active,[class*=btn-outline-]:active:focus,[class*=btn-outline-]:disabled,[class*=btn-outline-]:first-child:hover,[class*=btn-outline-]:focus,[class*=btn-outline-]:focus-visible,[class*=btn-outline-]:hover,fieldset:disabled [class*=btn-outline-] { + box-shadow: none +} + +.btn-group-lg>[class*=btn-outline-].btn,[class*=btn-outline-].btn-lg { + --mdb-btn-padding-top: 0.625rem; + --mdb-btn-padding-bottom: 0.5625rem; + --mdb-btn-padding-x: 1.5625rem; + --mdb-btn-font-size: 0.875rem; + --mdb-btn-line-height: 1.6 +} + +.btn-group-sm>[class*=btn-outline-].btn,[class*=btn-outline-].btn-sm { + --mdb-btn-padding-top: 0.25rem; + --mdb-btn-padding-bottom: 0.1875rem; + --mdb-btn-padding-x: 0.875rem; + --mdb-btn-font-size: 0.75rem; + --mdb-btn-line-height: 1.5 +} + +.btn-secondary { + box-shadow: none +} + +.btn-secondary:first-child:hover,.btn-secondary:focus-visible,.btn-secondary:hover,:not(.btn-check)+.btn-secondary:hover { + box-shadow: none!important +} + +.btn-check:active+.btn-secondary,.btn-check:active+.btn-secondary:focus,.btn-check:checked+.btn-secondary,.btn-check:checked+.btn-secondary:focus,.btn-check:focus+.btn-secondary,.btn-check:focus-visible+.btn-secondary,.btn-secondary.active,.btn-secondary.active:focus,.btn-secondary.disabled,.btn-secondary.show,.btn-secondary.show:focus,.btn-secondary:active,.btn-secondary:active:focus,.btn-secondary:disabled,.btn-secondary:focus,fieldset:disabled .btn-secondary { + box-shadow: none +} + +.btn-primary { + --mdb-btn-bg: #3b71ca; + --mdb-btn-color: #fff; + --mdb-btn-box-shadow: 0 4px 9px -4px #3b71ca; + --mdb-btn-hover-bg: #386bc0; + --mdb-btn-hover-color: #fff; + --mdb-btn-focus-bg: #386bc0; + --mdb-btn-focus-color: #fff; + --mdb-btn-active-bg: #3566b6; + --mdb-btn-active-color: #fff; + --mdb-btn-box-shadow-state: 0 8px 9px -4px rgba(59,113,202,0.3),0 4px 18px 0 rgba(59,113,202,0.2) +} + +.btn-primary:first-child:hover,.btn-primary:focus-visible,.btn-primary:hover,:not(.btn-check)+.btn-primary:hover { + box-shadow: var(--mdb-btn-box-shadow-state) +} + +.btn-check:focus+.btn-primary,.btn-check:focus-visible+.btn-primary,.btn-primary:focus { + box-shadow: var(--mdb-btn-box-shadow-state); + background-color: var(--mdb-btn-focus-bg) +} + +.btn-check:active+.btn-primary,.btn-check:active+.btn-primary:focus,.btn-check:checked+.btn-primary,.btn-check:checked+.btn-primary:focus,.btn-primary.active,.btn-primary.active:focus,.btn-primary.show,.btn-primary.show:focus,.btn-primary:active,.btn-primary:active:focus { + box-shadow: var(--mdb-btn-box-shadow-state) +} + +.btn-check:active+.btn-primary:hover,.btn-check:checked+.btn-primary:hover,.btn-primary.active:hover,.btn-primary.show:hover,.btn-primary:active:hover { + background-color: var(--mdb-btn-active-bg) +} + +.btn-primary.disabled,.btn-primary:disabled,fieldset:disabled .btn-primary { + box-shadow: var(--mdb-btn-box-shadow) +} + +.btn-secondary { + --mdb-btn-bg: #e3ebf7; + --mdb-btn-color: #285192; + --mdb-btn-box-shadow: 0 4px 9px -4px #e3ebf7; + --mdb-btn-hover-bg: #d8dfeb; + --mdb-btn-hover-color: #285192; + --mdb-btn-focus-bg: #d8dfeb; + --mdb-btn-focus-color: #285192; + --mdb-btn-active-bg: #ccd4de; + --mdb-btn-active-color: #285192; + --mdb-btn-box-shadow-state: 0 8px 9px -4px rgba(227,235,247,0.3),0 4px 18px 0 rgba(227,235,247,0.2) +} + +.btn-secondary:first-child:hover,.btn-secondary:focus-visible,.btn-secondary:hover,:not(.btn-check)+.btn-secondary:hover { + box-shadow: var(--mdb-btn-box-shadow-state) +} + +.btn-check:focus+.btn-secondary,.btn-check:focus-visible+.btn-secondary,.btn-secondary:focus { + box-shadow: var(--mdb-btn-box-shadow-state); + background-color: var(--mdb-btn-focus-bg) +} + +.btn-check:active+.btn-secondary,.btn-check:active+.btn-secondary:focus,.btn-check:checked+.btn-secondary,.btn-check:checked+.btn-secondary:focus,.btn-secondary.active,.btn-secondary.active:focus,.btn-secondary.show,.btn-secondary.show:focus,.btn-secondary:active,.btn-secondary:active:focus { + box-shadow: var(--mdb-btn-box-shadow-state) +} + +.btn-check:active+.btn-secondary:hover,.btn-check:checked+.btn-secondary:hover,.btn-secondary.active:hover,.btn-secondary.show:hover,.btn-secondary:active:hover { + background-color: var(--mdb-btn-active-bg) +} + +.btn-secondary.disabled,.btn-secondary:disabled,fieldset:disabled .btn-secondary { + box-shadow: var(--mdb-btn-box-shadow) +} + +.btn-success { + --mdb-btn-bg: #14a44d; + --mdb-btn-color: #fff; + --mdb-btn-box-shadow: 0 4px 9px -4px #14a44d; + --mdb-btn-hover-bg: #139c49; + --mdb-btn-hover-color: #fff; + --mdb-btn-focus-bg: #139c49; + --mdb-btn-focus-color: #fff; + --mdb-btn-active-bg: #129445; + --mdb-btn-active-color: #fff; + --mdb-btn-box-shadow-state: 0 8px 9px -4px rgba(20,164,77,0.3),0 4px 18px 0 rgba(20,164,77,0.2) +} + +.btn-success:first-child:hover,.btn-success:focus-visible,.btn-success:hover,:not(.btn-check)+.btn-success:hover { + box-shadow: var(--mdb-btn-box-shadow-state) +} + +.btn-check:focus+.btn-success,.btn-check:focus-visible+.btn-success,.btn-success:focus { + box-shadow: var(--mdb-btn-box-shadow-state); + background-color: var(--mdb-btn-focus-bg) +} + +.btn-check:active+.btn-success,.btn-check:active+.btn-success:focus,.btn-check:checked+.btn-success,.btn-check:checked+.btn-success:focus,.btn-success.active,.btn-success.active:focus,.btn-success.show,.btn-success.show:focus,.btn-success:active,.btn-success:active:focus { + box-shadow: var(--mdb-btn-box-shadow-state) +} + +.btn-check:active+.btn-success:hover,.btn-check:checked+.btn-success:hover,.btn-success.active:hover,.btn-success.show:hover,.btn-success:active:hover { + background-color: var(--mdb-btn-active-bg) +} + +.btn-success.disabled,.btn-success:disabled,fieldset:disabled .btn-success { + box-shadow: var(--mdb-btn-box-shadow) +} + +.btn-danger { + --mdb-btn-bg: #dc4c64; + --mdb-btn-color: #fff; + --mdb-btn-box-shadow: 0 4px 9px -4px #dc4c64; + --mdb-btn-hover-bg: #d1485f; + --mdb-btn-hover-color: #fff; + --mdb-btn-focus-bg: #d1485f; + --mdb-btn-focus-color: #fff; + --mdb-btn-active-bg: #c6445a; + --mdb-btn-active-color: #fff; + --mdb-btn-box-shadow-state: 0 8px 9px -4px rgba(220,76,100,0.3),0 4px 18px 0 rgba(220,76,100,0.2) +} + +.btn-danger:first-child:hover,.btn-danger:focus-visible,.btn-danger:hover,:not(.btn-check)+.btn-danger:hover { + box-shadow: var(--mdb-btn-box-shadow-state) +} + +.btn-check:focus+.btn-danger,.btn-check:focus-visible+.btn-danger,.btn-danger:focus { + box-shadow: var(--mdb-btn-box-shadow-state); + background-color: var(--mdb-btn-focus-bg) +} + +.btn-check:active+.btn-danger,.btn-check:active+.btn-danger:focus,.btn-check:checked+.btn-danger,.btn-check:checked+.btn-danger:focus,.btn-danger.active,.btn-danger.active:focus,.btn-danger.show,.btn-danger.show:focus,.btn-danger:active,.btn-danger:active:focus { + box-shadow: var(--mdb-btn-box-shadow-state) +} + +.btn-check:active+.btn-danger:hover,.btn-check:checked+.btn-danger:hover,.btn-danger.active:hover,.btn-danger.show:hover,.btn-danger:active:hover { + background-color: var(--mdb-btn-active-bg) +} + +.btn-danger.disabled,.btn-danger:disabled,fieldset:disabled .btn-danger { + box-shadow: var(--mdb-btn-box-shadow) +} + +.btn-warning { + --mdb-btn-bg: #e4a11b; + --mdb-btn-color: #fff; + --mdb-btn-box-shadow: 0 4px 9px -4px #e4a11b; + --mdb-btn-hover-bg: #d9991a; + --mdb-btn-hover-color: #fff; + --mdb-btn-focus-bg: #d9991a; + --mdb-btn-focus-color: #fff; + --mdb-btn-active-bg: #cd9118; + --mdb-btn-active-color: #fff; + --mdb-btn-box-shadow-state: 0 8px 9px -4px rgba(228,161,27,0.3),0 4px 18px 0 rgba(228,161,27,0.2) +} + +.btn-warning:first-child:hover,.btn-warning:focus-visible,.btn-warning:hover,:not(.btn-check)+.btn-warning:hover { + box-shadow: var(--mdb-btn-box-shadow-state) +} + +.btn-check:focus+.btn-warning,.btn-check:focus-visible+.btn-warning,.btn-warning:focus { + box-shadow: var(--mdb-btn-box-shadow-state); + background-color: var(--mdb-btn-focus-bg) +} + +.btn-check:active+.btn-warning,.btn-check:active+.btn-warning:focus,.btn-check:checked+.btn-warning,.btn-check:checked+.btn-warning:focus,.btn-warning.active,.btn-warning.active:focus,.btn-warning.show,.btn-warning.show:focus,.btn-warning:active,.btn-warning:active:focus { + box-shadow: var(--mdb-btn-box-shadow-state) +} + +.btn-check:active+.btn-warning:hover,.btn-check:checked+.btn-warning:hover,.btn-warning.active:hover,.btn-warning.show:hover,.btn-warning:active:hover { + background-color: var(--mdb-btn-active-bg) +} + +.btn-warning.disabled,.btn-warning:disabled,fieldset:disabled .btn-warning { + box-shadow: var(--mdb-btn-box-shadow) +} + +.btn-info { + --mdb-btn-bg: #54b4d3; + --mdb-btn-color: #fff; + --mdb-btn-box-shadow: 0 4px 9px -4px #54b4d3; + --mdb-btn-hover-bg: #50abc8; + --mdb-btn-hover-color: #fff; + --mdb-btn-focus-bg: #50abc8; + --mdb-btn-focus-color: #fff; + --mdb-btn-active-bg: #4ca2be; + --mdb-btn-active-color: #fff; + --mdb-btn-box-shadow-state: 0 8px 9px -4px rgba(84,180,211,0.3),0 4px 18px 0 rgba(84,180,211,0.2) +} + +.btn-info:first-child:hover,.btn-info:focus-visible,.btn-info:hover,:not(.btn-check)+.btn-info:hover { + box-shadow: var(--mdb-btn-box-shadow-state) +} + +.btn-check:focus+.btn-info,.btn-check:focus-visible+.btn-info,.btn-info:focus { + box-shadow: var(--mdb-btn-box-shadow-state); + background-color: var(--mdb-btn-focus-bg) +} + +.btn-check:active+.btn-info,.btn-check:active+.btn-info:focus,.btn-check:checked+.btn-info,.btn-check:checked+.btn-info:focus,.btn-info.active,.btn-info.active:focus,.btn-info.show,.btn-info.show:focus,.btn-info:active,.btn-info:active:focus { + box-shadow: var(--mdb-btn-box-shadow-state) +} + +.btn-check:active+.btn-info:hover,.btn-check:checked+.btn-info:hover,.btn-info.active:hover,.btn-info.show:hover,.btn-info:active:hover { + background-color: var(--mdb-btn-active-bg) +} + +.btn-info.disabled,.btn-info:disabled,fieldset:disabled .btn-info { + box-shadow: var(--mdb-btn-box-shadow) +} + +.btn-light { + --mdb-btn-bg: #fbfbfb; + --mdb-btn-color: #4f4f4f; + --mdb-btn-box-shadow: 0 4px 9px -4px #fbfbfb; + --mdb-btn-hover-bg: #eee; + --mdb-btn-hover-color: #4f4f4f; + --mdb-btn-focus-bg: #eee; + --mdb-btn-focus-color: #4f4f4f; + --mdb-btn-active-bg: #e2e2e2; + --mdb-btn-active-color: #4f4f4f; + --mdb-btn-box-shadow-state: 0 8px 9px -4px hsla(0,0%,98.4%,0.3),0 4px 18px 0 hsla(0,0%,98.4%,0.2) +} + +.btn-light:first-child:hover,.btn-light:focus-visible,.btn-light:hover,:not(.btn-check)+.btn-light:hover { + box-shadow: var(--mdb-btn-box-shadow-state) +} + +.btn-check:focus+.btn-light,.btn-check:focus-visible+.btn-light,.btn-light:focus { + box-shadow: var(--mdb-btn-box-shadow-state); + background-color: var(--mdb-btn-focus-bg) +} + +.btn-check:active+.btn-light,.btn-check:active+.btn-light:focus,.btn-check:checked+.btn-light,.btn-check:checked+.btn-light:focus,.btn-light.active,.btn-light.active:focus,.btn-light.show,.btn-light.show:focus,.btn-light:active,.btn-light:active:focus { + box-shadow: var(--mdb-btn-box-shadow-state) +} + +.btn-check:active+.btn-light:hover,.btn-check:checked+.btn-light:hover,.btn-light.active:hover,.btn-light.show:hover,.btn-light:active:hover { + background-color: var(--mdb-btn-active-bg) +} + +.btn-light.disabled,.btn-light:disabled,fieldset:disabled .btn-light { + box-shadow: var(--mdb-btn-box-shadow) +} + +.btn-dark { + --mdb-btn-bg: #332d2d; + --mdb-btn-color: #fff; + --mdb-btn-box-shadow: 0 4px 9px -4px #332d2d; + --mdb-btn-hover-bg: #302b2b; + --mdb-btn-hover-color: #fff; + --mdb-btn-focus-bg: #302b2b; + --mdb-btn-focus-color: #fff; + --mdb-btn-active-bg: #2e2929; + --mdb-btn-active-color: #fff; + --mdb-btn-box-shadow-state: 0 8px 9px -4px rgba(51,45,45,0.3),0 4px 18px 0 rgba(51,45,45,0.2) +} + +.btn-dark:first-child:hover,.btn-dark:focus-visible,.btn-dark:hover,:not(.btn-check)+.btn-dark:hover { + box-shadow: var(--mdb-btn-box-shadow-state) +} + +.btn-check:focus+.btn-dark,.btn-check:focus-visible+.btn-dark,.btn-dark:focus { + box-shadow: var(--mdb-btn-box-shadow-state); + background-color: var(--mdb-btn-focus-bg) +} + +.btn-check:active+.btn-dark,.btn-check:active+.btn-dark:focus,.btn-check:checked+.btn-dark,.btn-check:checked+.btn-dark:focus,.btn-dark.active,.btn-dark.active:focus,.btn-dark.show,.btn-dark.show:focus,.btn-dark:active,.btn-dark:active:focus { + box-shadow: var(--mdb-btn-box-shadow-state) +} + +.btn-check:active+.btn-dark:hover,.btn-check:checked+.btn-dark:hover,.btn-dark.active:hover,.btn-dark.show:hover,.btn-dark:active:hover { + background-color: var(--mdb-btn-active-bg) +} + +.btn-dark.disabled,.btn-dark:disabled,fieldset:disabled .btn-dark { + box-shadow: var(--mdb-btn-box-shadow) +} + +.btn-white { + --mdb-btn-bg: #fff; + --mdb-btn-color: #000; + --mdb-btn-box-shadow: 0 4px 9px -4px #fff; + --mdb-btn-hover-bg: #f2f2f2; + --mdb-btn-hover-color: #000; + --mdb-btn-focus-bg: #f2f2f2; + --mdb-btn-focus-color: #000; + --mdb-btn-active-bg: #e6e6e6; + --mdb-btn-active-color: #000; + --mdb-btn-box-shadow-state: 0 8px 9px -4px hsla(0,0%,100%,0.3),0 4px 18px 0 hsla(0,0%,100%,0.2) +} + +.btn-white:first-child:hover,.btn-white:focus-visible,.btn-white:hover,:not(.btn-check)+.btn-white:hover { + box-shadow: var(--mdb-btn-box-shadow-state) +} + +.btn-check:focus+.btn-white,.btn-check:focus-visible+.btn-white,.btn-white:focus { + box-shadow: var(--mdb-btn-box-shadow-state); + background-color: var(--mdb-btn-focus-bg) +} + +.btn-check:active+.btn-white,.btn-check:active+.btn-white:focus,.btn-check:checked+.btn-white,.btn-check:checked+.btn-white:focus,.btn-white.active,.btn-white.active:focus,.btn-white.show,.btn-white.show:focus,.btn-white:active,.btn-white:active:focus { + box-shadow: var(--mdb-btn-box-shadow-state) +} + +.btn-check:active+.btn-white:hover,.btn-check:checked+.btn-white:hover,.btn-white.active:hover,.btn-white.show:hover,.btn-white:active:hover { + background-color: var(--mdb-btn-active-bg) +} + +.btn-white.disabled,.btn-white:disabled,fieldset:disabled .btn-white { + box-shadow: var(--mdb-btn-box-shadow) +} + +.btn-black { + --mdb-btn-bg: #000; + --mdb-btn-color: #fff; + --mdb-btn-box-shadow: 0 4px 9px -4px #000; + --mdb-btn-hover-bg: #000; + --mdb-btn-hover-color: #fff; + --mdb-btn-focus-bg: #000; + --mdb-btn-focus-color: #fff; + --mdb-btn-active-bg: #000; + --mdb-btn-active-color: #fff; + --mdb-btn-box-shadow-state: 0 8px 9px -4px rgba(0,0,0,0.3),0 4px 18px 0 rgba(0,0,0,0.2) +} + +.btn-black:first-child:hover,.btn-black:focus-visible,.btn-black:hover,:not(.btn-check)+.btn-black:hover { + box-shadow: var(--mdb-btn-box-shadow-state) +} + +.btn-black:focus,.btn-check:focus+.btn-black,.btn-check:focus-visible+.btn-black { + box-shadow: var(--mdb-btn-box-shadow-state); + background-color: var(--mdb-btn-focus-bg) +} + +.btn-black.active,.btn-black.active:focus,.btn-black.show,.btn-black.show:focus,.btn-black:active,.btn-black:active:focus,.btn-check:active+.btn-black,.btn-check:active+.btn-black:focus,.btn-check:checked+.btn-black,.btn-check:checked+.btn-black:focus { + box-shadow: var(--mdb-btn-box-shadow-state) +} + +.btn-black.active:hover,.btn-black.show:hover,.btn-black:active:hover,.btn-check:active+.btn-black:hover,.btn-check:checked+.btn-black:hover { + background-color: var(--mdb-btn-active-bg) +} + +.btn-black.disabled,.btn-black:disabled,fieldset:disabled .btn-black { + box-shadow: var(--mdb-btn-box-shadow) +} + +.btn-outline-primary { + --mdb-btn-bg: transparent; + --mdb-btn-color: #3b71ca; + --mdb-btn-hover-bg: transparent; + --mdb-btn-hover-color: #386bc0; + --mdb-btn-focus-bg: transparent; + --mdb-btn-focus-color: #386bc0; + --mdb-btn-active-bg: transparent; + --mdb-btn-active-color: #3566b6; + --mdb-btn-border-color: #3b71ca; + --mdb-btn-focus-border-color: #386bc0; + --mdb-btn-hover-border-color: #386bc0; + border-color: var(--mdb-btn-border-color) +} + +.btn-outline-primary:first-child:hover,.btn-outline-primary:focus-visible,.btn-outline-primary:hover,:not(.btn-check)+.btn-outline-primary:hover { + border-color: var(--mdb-btn-hover-border-color) +} + +.btn-check:focus+.btn-outline-primary,.btn-check:focus-visible+.btn-outline-primary,.btn-outline-primary:focus { + border-color: var(--mdb-btn-focus-border-color) +} + +.btn-check:active+.btn-outline-primary,.btn-check:checked+.btn-outline-primary,.btn-outline-primary.active,.btn-outline-primary.show,.btn-outline-primary:active { + border-color: var(--mdb-btn-active-border-color) +} + +.btn-check:active+.btn-outline-primary:focus,.btn-check:checked+.btn-outline-primary:focus,.btn-outline-primary.active:focus,.btn-outline-primary.show:focus,.btn-outline-primary:active:focus { + border-color: var(--mdb-btn-focus-border-color) +} + +.btn-outline-primary.disabled,.btn-outline-primary:disabled,.btn-outline-secondary,fieldset:disabled .btn-outline-primary { + border-color: var(--mdb-btn-border-color) +} + +.btn-outline-secondary { + --mdb-btn-bg: transparent; + --mdb-btn-color: #285192; + --mdb-btn-hover-bg: transparent; + --mdb-btn-hover-color: #264d8b; + --mdb-btn-focus-bg: transparent; + --mdb-btn-focus-color: #264d8b; + --mdb-btn-active-bg: transparent; + --mdb-btn-active-color: #244983; + --mdb-btn-border-color: #e3ebf7; + --mdb-btn-focus-border-color: #d8dfeb; + --mdb-btn-hover-border-color: #d8dfeb +} + +.btn-outline-secondary:first-child:hover,.btn-outline-secondary:focus-visible,.btn-outline-secondary:hover,:not(.btn-check)+.btn-outline-secondary:hover { + border-color: var(--mdb-btn-hover-border-color) +} + +.btn-check:focus+.btn-outline-secondary,.btn-check:focus-visible+.btn-outline-secondary,.btn-outline-secondary:focus { + border-color: var(--mdb-btn-focus-border-color) +} + +.btn-check:active+.btn-outline-secondary,.btn-check:checked+.btn-outline-secondary,.btn-outline-secondary.active,.btn-outline-secondary.show,.btn-outline-secondary:active { + border-color: var(--mdb-btn-active-border-color) +} + +.btn-check:active+.btn-outline-secondary:focus,.btn-check:checked+.btn-outline-secondary:focus,.btn-outline-secondary.active:focus,.btn-outline-secondary.show:focus,.btn-outline-secondary:active:focus { + border-color: var(--mdb-btn-focus-border-color) +} + +.btn-outline-secondary.disabled,.btn-outline-secondary:disabled,.btn-outline-success,fieldset:disabled .btn-outline-secondary { + border-color: var(--mdb-btn-border-color) +} + +.btn-outline-success { + --mdb-btn-bg: transparent; + --mdb-btn-color: #14a44d; + --mdb-btn-hover-bg: transparent; + --mdb-btn-hover-color: #139c49; + --mdb-btn-focus-bg: transparent; + --mdb-btn-focus-color: #139c49; + --mdb-btn-active-bg: transparent; + --mdb-btn-active-color: #129445; + --mdb-btn-border-color: #14a44d; + --mdb-btn-focus-border-color: #139c49; + --mdb-btn-hover-border-color: #139c49 +} + +.btn-outline-success:first-child:hover,.btn-outline-success:focus-visible,.btn-outline-success:hover,:not(.btn-check)+.btn-outline-success:hover { + border-color: var(--mdb-btn-hover-border-color) +} + +.btn-check:focus+.btn-outline-success,.btn-check:focus-visible+.btn-outline-success,.btn-outline-success:focus { + border-color: var(--mdb-btn-focus-border-color) +} + +.btn-check:active+.btn-outline-success,.btn-check:checked+.btn-outline-success,.btn-outline-success.active,.btn-outline-success.show,.btn-outline-success:active { + border-color: var(--mdb-btn-active-border-color) +} + +.btn-check:active+.btn-outline-success:focus,.btn-check:checked+.btn-outline-success:focus,.btn-outline-success.active:focus,.btn-outline-success.show:focus,.btn-outline-success:active:focus { + border-color: var(--mdb-btn-focus-border-color) +} + +.btn-outline-danger,.btn-outline-success.disabled,.btn-outline-success:disabled,fieldset:disabled .btn-outline-success { + border-color: var(--mdb-btn-border-color) +} + +.btn-outline-danger { + --mdb-btn-bg: transparent; + --mdb-btn-color: #dc4c64; + --mdb-btn-hover-bg: transparent; + --mdb-btn-hover-color: #d1485f; + --mdb-btn-focus-bg: transparent; + --mdb-btn-focus-color: #d1485f; + --mdb-btn-active-bg: transparent; + --mdb-btn-active-color: #c6445a; + --mdb-btn-border-color: #dc4c64; + --mdb-btn-focus-border-color: #d1485f; + --mdb-btn-hover-border-color: #d1485f +} + +.btn-outline-danger:first-child:hover,.btn-outline-danger:focus-visible,.btn-outline-danger:hover,:not(.btn-check)+.btn-outline-danger:hover { + border-color: var(--mdb-btn-hover-border-color) +} + +.btn-check:focus+.btn-outline-danger,.btn-check:focus-visible+.btn-outline-danger,.btn-outline-danger:focus { + border-color: var(--mdb-btn-focus-border-color) +} + +.btn-check:active+.btn-outline-danger,.btn-check:checked+.btn-outline-danger,.btn-outline-danger.active,.btn-outline-danger.show,.btn-outline-danger:active { + border-color: var(--mdb-btn-active-border-color) +} + +.btn-check:active+.btn-outline-danger:focus,.btn-check:checked+.btn-outline-danger:focus,.btn-outline-danger.active:focus,.btn-outline-danger.show:focus,.btn-outline-danger:active:focus { + border-color: var(--mdb-btn-focus-border-color) +} + +.btn-outline-danger.disabled,.btn-outline-danger:disabled,.btn-outline-warning,fieldset:disabled .btn-outline-danger { + border-color: var(--mdb-btn-border-color) +} + +.btn-outline-warning { + --mdb-btn-bg: transparent; + --mdb-btn-color: #e4a11b; + --mdb-btn-hover-bg: transparent; + --mdb-btn-hover-color: #d9991a; + --mdb-btn-focus-bg: transparent; + --mdb-btn-focus-color: #d9991a; + --mdb-btn-active-bg: transparent; + --mdb-btn-active-color: #cd9118; + --mdb-btn-border-color: #e4a11b; + --mdb-btn-focus-border-color: #d9991a; + --mdb-btn-hover-border-color: #d9991a +} + +.btn-outline-warning:first-child:hover,.btn-outline-warning:focus-visible,.btn-outline-warning:hover,:not(.btn-check)+.btn-outline-warning:hover { + border-color: var(--mdb-btn-hover-border-color) +} + +.btn-check:focus+.btn-outline-warning,.btn-check:focus-visible+.btn-outline-warning,.btn-outline-warning:focus { + border-color: var(--mdb-btn-focus-border-color) +} + +.btn-check:active+.btn-outline-warning,.btn-check:checked+.btn-outline-warning,.btn-outline-warning.active,.btn-outline-warning.show,.btn-outline-warning:active { + border-color: var(--mdb-btn-active-border-color) +} + +.btn-check:active+.btn-outline-warning:focus,.btn-check:checked+.btn-outline-warning:focus,.btn-outline-warning.active:focus,.btn-outline-warning.show:focus,.btn-outline-warning:active:focus { + border-color: var(--mdb-btn-focus-border-color) +} + +.btn-outline-info,.btn-outline-warning.disabled,.btn-outline-warning:disabled,fieldset:disabled .btn-outline-warning { + border-color: var(--mdb-btn-border-color) +} + +.btn-outline-info { + --mdb-btn-bg: transparent; + --mdb-btn-color: #54b4d3; + --mdb-btn-hover-bg: transparent; + --mdb-btn-hover-color: #50abc8; + --mdb-btn-focus-bg: transparent; + --mdb-btn-focus-color: #50abc8; + --mdb-btn-active-bg: transparent; + --mdb-btn-active-color: #4ca2be; + --mdb-btn-border-color: #54b4d3; + --mdb-btn-focus-border-color: #50abc8; + --mdb-btn-hover-border-color: #50abc8 +} + +.btn-outline-info:first-child:hover,.btn-outline-info:focus-visible,.btn-outline-info:hover,:not(.btn-check)+.btn-outline-info:hover { + border-color: var(--mdb-btn-hover-border-color) +} + +.btn-check:focus+.btn-outline-info,.btn-check:focus-visible+.btn-outline-info,.btn-outline-info:focus { + border-color: var(--mdb-btn-focus-border-color) +} + +.btn-check:active+.btn-outline-info,.btn-check:checked+.btn-outline-info,.btn-outline-info.active,.btn-outline-info.show,.btn-outline-info:active { + border-color: var(--mdb-btn-active-border-color) +} + +.btn-check:active+.btn-outline-info:focus,.btn-check:checked+.btn-outline-info:focus,.btn-outline-info.active:focus,.btn-outline-info.show:focus,.btn-outline-info:active:focus { + border-color: var(--mdb-btn-focus-border-color) +} + +.btn-outline-info.disabled,.btn-outline-info:disabled,.btn-outline-light,fieldset:disabled .btn-outline-info { + border-color: var(--mdb-btn-border-color) +} + +.btn-outline-light { + --mdb-btn-bg: transparent; + --mdb-btn-color: #fbfbfb; + --mdb-btn-hover-bg: transparent; + --mdb-btn-hover-color: #eee; + --mdb-btn-focus-bg: transparent; + --mdb-btn-focus-color: #eee; + --mdb-btn-active-bg: transparent; + --mdb-btn-active-color: #e2e2e2; + --mdb-btn-border-color: #fbfbfb; + --mdb-btn-focus-border-color: #eee; + --mdb-btn-hover-border-color: #eee +} + +.btn-outline-light:first-child:hover,.btn-outline-light:focus-visible,.btn-outline-light:hover,:not(.btn-check)+.btn-outline-light:hover { + border-color: var(--mdb-btn-hover-border-color) +} + +.btn-check:focus+.btn-outline-light,.btn-check:focus-visible+.btn-outline-light,.btn-outline-light:focus { + border-color: var(--mdb-btn-focus-border-color) +} + +.btn-check:active+.btn-outline-light,.btn-check:checked+.btn-outline-light,.btn-outline-light.active,.btn-outline-light.show,.btn-outline-light:active { + border-color: var(--mdb-btn-active-border-color) +} + +.btn-check:active+.btn-outline-light:focus,.btn-check:checked+.btn-outline-light:focus,.btn-outline-light.active:focus,.btn-outline-light.show:focus,.btn-outline-light:active:focus { + border-color: var(--mdb-btn-focus-border-color) +} + +.btn-outline-dark,.btn-outline-light.disabled,.btn-outline-light:disabled,fieldset:disabled .btn-outline-light { + border-color: var(--mdb-btn-border-color) +} + +.btn-outline-dark { + --mdb-btn-bg: transparent; + --mdb-btn-color: #332d2d; + --mdb-btn-hover-bg: transparent; + --mdb-btn-hover-color: #302b2b; + --mdb-btn-focus-bg: transparent; + --mdb-btn-focus-color: #302b2b; + --mdb-btn-active-bg: transparent; + --mdb-btn-active-color: #2e2929; + --mdb-btn-border-color: #332d2d; + --mdb-btn-focus-border-color: #302b2b; + --mdb-btn-hover-border-color: #302b2b +} + +.btn-outline-dark:first-child:hover,.btn-outline-dark:focus-visible,.btn-outline-dark:hover,:not(.btn-check)+.btn-outline-dark:hover { + border-color: var(--mdb-btn-hover-border-color) +} + +.btn-check:focus+.btn-outline-dark,.btn-check:focus-visible+.btn-outline-dark,.btn-outline-dark:focus { + border-color: var(--mdb-btn-focus-border-color) +} + +.btn-check:active+.btn-outline-dark,.btn-check:checked+.btn-outline-dark,.btn-outline-dark.active,.btn-outline-dark.show,.btn-outline-dark:active { + border-color: var(--mdb-btn-active-border-color) +} + +.btn-check:active+.btn-outline-dark:focus,.btn-check:checked+.btn-outline-dark:focus,.btn-outline-dark.active:focus,.btn-outline-dark.show:focus,.btn-outline-dark:active:focus { + border-color: var(--mdb-btn-focus-border-color) +} + +.btn-outline-dark.disabled,.btn-outline-dark:disabled,.btn-outline-white,fieldset:disabled .btn-outline-dark { + border-color: var(--mdb-btn-border-color) +} + +.btn-outline-white { + --mdb-btn-bg: transparent; + --mdb-btn-color: #fff; + --mdb-btn-hover-bg: transparent; + --mdb-btn-hover-color: #f2f2f2; + --mdb-btn-focus-bg: transparent; + --mdb-btn-focus-color: #f2f2f2; + --mdb-btn-active-bg: transparent; + --mdb-btn-active-color: #e6e6e6; + --mdb-btn-border-color: #fff; + --mdb-btn-focus-border-color: #f2f2f2; + --mdb-btn-hover-border-color: #f2f2f2 +} + +.btn-outline-white:first-child:hover,.btn-outline-white:focus-visible,.btn-outline-white:hover,:not(.btn-check)+.btn-outline-white:hover { + border-color: var(--mdb-btn-hover-border-color) +} + +.btn-check:focus+.btn-outline-white,.btn-check:focus-visible+.btn-outline-white,.btn-outline-white:focus { + border-color: var(--mdb-btn-focus-border-color) +} + +.btn-check:active+.btn-outline-white,.btn-check:checked+.btn-outline-white,.btn-outline-white.active,.btn-outline-white.show,.btn-outline-white:active { + border-color: var(--mdb-btn-active-border-color) +} + +.btn-check:active+.btn-outline-white:focus,.btn-check:checked+.btn-outline-white:focus,.btn-outline-white.active:focus,.btn-outline-white.show:focus,.btn-outline-white:active:focus { + border-color: var(--mdb-btn-focus-border-color) +} + +.btn-outline-black,.btn-outline-white.disabled,.btn-outline-white:disabled,fieldset:disabled .btn-outline-white { + border-color: var(--mdb-btn-border-color) +} + +.btn-outline-black { + --mdb-btn-bg: transparent; + --mdb-btn-color: #000; + --mdb-btn-hover-bg: transparent; + --mdb-btn-hover-color: #000; + --mdb-btn-focus-bg: transparent; + --mdb-btn-focus-color: #000; + --mdb-btn-active-bg: transparent; + --mdb-btn-active-color: #000; + --mdb-btn-border-color: #000; + --mdb-btn-focus-border-color: #000; + --mdb-btn-hover-border-color: #000 +} + +.btn-outline-black:first-child:hover,.btn-outline-black:focus-visible,.btn-outline-black:hover,:not(.btn-check)+.btn-outline-black:hover { + border-color: var(--mdb-btn-hover-border-color) +} + +.btn-check:focus+.btn-outline-black,.btn-check:focus-visible+.btn-outline-black,.btn-outline-black:focus { + border-color: var(--mdb-btn-focus-border-color) +} + +.btn-check:active+.btn-outline-black,.btn-check:checked+.btn-outline-black,.btn-outline-black.active,.btn-outline-black.show,.btn-outline-black:active { + border-color: var(--mdb-btn-active-border-color) +} + +.btn-check:active+.btn-outline-black:focus,.btn-check:checked+.btn-outline-black:focus,.btn-outline-black.active:focus,.btn-outline-black.show:focus,.btn-outline-black:active:focus { + border-color: var(--mdb-btn-focus-border-color) +} + +.btn-outline-black.disabled,.btn-outline-black:disabled,fieldset:disabled .btn-outline-black { + border-color: var(--mdb-btn-border-color) +} + +.btn-link { + --mdb-btn-font-weight: 500; + --mdb-btn-color: #3b71ca; + --mdb-btn-hover-color: #386bc0; + --mdb-btn-hover-bg: #f5f5f5; + --mdb-btn-focus-color: #3566b6; + --mdb-btn-active-color: #3260ac; + --mdb-btn-disabled-color: #9e9e9e; + --mdb-btn-box-shadow: none +} + +.btn-link,.btn-link:first-child:hover,.btn-link:focus-visible,.btn-link:hover,:not(.btn-check)+.btn-link:hover { + text-decoration: none; + box-shadow: var(--mdb-btn-box-shadow) +} + +.btn-check:focus+.btn-link,.btn-check:focus-visible+.btn-link,.btn-link:focus { + color: var(--mdb-btn-focus-color); + box-shadow: var(--mdb-btn-box-shadow) +} + +.btn-check:active+.btn-link,.btn-check:checked+.btn-link,.btn-link.active,.btn-link.show,.btn-link:active { + color: var(--mdb-btn-active-color); + box-shadow: var(--mdb-btn-box-shadow) +} + +.btn-check:active+.btn-link:focus,.btn-check:checked+.btn-link:focus,.btn-link.active:focus,.btn-link.show:focus,.btn-link:active:focus { + color: var(--mdb-btn-focus-color); + box-shadow: var(--mdb-btn-box-shadow) +} + +.btn-link.disabled,.btn-link:disabled,fieldset:disabled .btn-link { + box-shadow: var(--mdb-btn-box-shadow) +} + +.btn-tertiary { + --mdb-btn-font-weight: 500; + --mdb-btn-color: #3b71ca; + --mdb-btn-hover-color: #386bc0; + --mdb-btn-hover-bg: transparent; + --mdb-btn-focus-color: #3566b6; + --mdb-btn-active-color: #3260ac; + --mdb-btn-disabled-color: #9e9e9e; + --mdb-btn-box-shadow: none; + padding-left: 0; + padding-right: 0 +} + +.btn-tertiary,.btn-tertiary:first-child:hover,.btn-tertiary:focus-visible,.btn-tertiary:hover,:not(.btn-check)+.btn-tertiary:hover { + text-decoration: none; + box-shadow: var(--mdb-btn-box-shadow) +} + +.btn-check:focus+.btn-tertiary,.btn-check:focus-visible+.btn-tertiary,.btn-tertiary:focus { + color: var(--mdb-btn-focus-color); + box-shadow: var(--mdb-btn-box-shadow) +} + +.btn-check:active+.btn-tertiary,.btn-check:checked+.btn-tertiary,.btn-tertiary.active,.btn-tertiary.show,.btn-tertiary:active { + color: var(--mdb-btn-active-color); + box-shadow: var(--mdb-btn-box-shadow) +} + +.btn-check:active+.btn-tertiary:focus,.btn-check:checked+.btn-tertiary:focus,.btn-tertiary.active:focus,.btn-tertiary.show:focus,.btn-tertiary:active:focus { + color: var(--mdb-btn-focus-color); + box-shadow: var(--mdb-btn-box-shadow) +} + +.btn-tertiary.disabled,.btn-tertiary:disabled,fieldset:disabled .btn-tertiary { + box-shadow: var(--mdb-btn-box-shadow) +} + +.btn-group-lg>.btn,.btn-lg { + --mdb-btn-padding-top: 0.75rem; + --mdb-btn-padding-bottom: 0.6875rem; + --mdb-btn-padding-x: 1.6875rem; + --mdb-btn-font-size: 0.875rem; + --mdb-btn-line-height: 1.6 +} + +.btn-group-sm>.btn,.btn-sm { + --mdb-btn-padding-top: 0.375rem; + --mdb-btn-padding-bottom: 0.3125rem; + --mdb-btn-padding-x: 1rem; + --mdb-btn-font-size: 0.75rem; + --mdb-btn-line-height: 1.5 +} + +.btn-rounded { + --mdb-btn-border-radius: 10rem; + border-radius: var(--mdb-btn-border-radius) +} + +.btn-floating,[class*=btn-outline-].btn-floating { + --mdb-btn-border-radius: 50%; + border-radius: var(--mdb-btn-border-radius); + padding: 0; + position: relative; + display: inline-flex; + align-items: center; + justify-content: center +} + +.btn-floating { + --mdb-btn-width: 2.3125rem; + --mdb-btn-height: 2.3125rem; + --mdb-btn-icon-width: 2.3125rem; + --mdb-btn-icon-line-height: 2.3125rem; + --mdb-btn-width-lg: 2.8125rem; + --mdb-btn-height-lg: 2.8125rem; + --mdb-btn-icon-width-lg: 2.8125rem; + --mdb-btn-icon-line-height-lg: 2.8125rem; + --mdb-btn-width-sm: 1.8125rem; + --mdb-btn-height-sm: 1.8125rem; + --mdb-btn-icon-width-sm: 1.8125rem; + --mdb-btn-icon-line-height-sm: 1.8125rem; + width: var(--mdb-btn-width); + height: var(--mdb-btn-height) +} + +.btn-floating .fab,.btn-floating .far,.btn-floating .fas { + width: var(--mdb-btn-icon-width); + line-height: var(--mdb-btn-icon-line-height) +} + +.btn-floating.btn-lg,.btn-group-lg>.btn-floating.btn { + width: var(--mdb-btn-width-lg); + height: var(--mdb-btn-height-lg) +} + +.btn-floating.btn-lg .fab,.btn-floating.btn-lg .far,.btn-floating.btn-lg .fas,.btn-group-lg>.btn-floating.btn .fab,.btn-group-lg>.btn-floating.btn .far,.btn-group-lg>.btn-floating.btn .fas { + width: var(--mdb-btn-icon-width-lg); + line-height: var(--mdb-btn-icon-line-height-lg) +} + +.btn-floating.btn-sm,.btn-group-sm>.btn-floating.btn { + width: var(--mdb-btn-width-sm); + height: var(--mdb-btn-height-sm) +} + +.btn-floating.btn-sm .fab,.btn-floating.btn-sm .far,.btn-floating.btn-sm .fas,.btn-group-sm>.btn-floating.btn .fab,.btn-group-sm>.btn-floating.btn .far,.btn-group-sm>.btn-floating.btn .fas { + width: var(--mdb-btn-icon-width-sm); + line-height: var(--mdb-btn-icon-line-height-sm) +} + +[class*=btn-outline-].btn-floating { + --mdb-btn-icon-width: 2.0625rem; + --mdb-btn-icon-width-lg: 2.5625rem; + --mdb-btn-icon-width-sm: 1.5625rem; + --mdb-btn-icon-line-height: 2.0625rem; + --mdb-btn-icon-line-height-lg: 2.5625rem; + --mdb-btn-icon-line-height-sm: 1.5625rem +} + +[class*=btn-outline-].btn-floating .fab,[class*=btn-outline-].btn-floating .far,[class*=btn-outline-].btn-floating .fas { + width: var(--mdb-btn-icon-width); + line-height: var(--mdb-btn-icon-line-height) +} + +.btn-group-lg>[class*=btn-outline-].btn-floating.btn .fab,.btn-group-lg>[class*=btn-outline-].btn-floating.btn .far,.btn-group-lg>[class*=btn-outline-].btn-floating.btn .fas,[class*=btn-outline-].btn-floating.btn-lg .fab,[class*=btn-outline-].btn-floating.btn-lg .far,[class*=btn-outline-].btn-floating.btn-lg .fas { + width: var(--mdb-btn-icon-width-lg); + line-height: var(--mdb-btn-icon-line-height-lg) +} + +.btn-group-sm>[class*=btn-outline-].btn-floating.btn .fab,.btn-group-sm>[class*=btn-outline-].btn-floating.btn .far,.btn-group-sm>[class*=btn-outline-].btn-floating.btn .fas,[class*=btn-outline-].btn-floating.btn-sm .fab,[class*=btn-outline-].btn-floating.btn-sm .far,[class*=btn-outline-].btn-floating.btn-sm .fas { + width: var(--mdb-btn-icon-width-sm); + line-height: var(--mdb-btn-icon-line-height-sm) +} + +.fixed-action-btn { + --mdb-btn-right: 2.1875rem; + --mdb-btn-bottom: 2.1875rem; + --mdb-btn-zindex: 1030; + --mdb-btn-padding-top: 0.9375rem; + --mdb-btn-padding-bottom: 1.25rem; + --mdb-btn-padding-x: 1.25rem; + --mdb-btn-margin-bottom: 1.5rem; + position: fixed; + right: var(--mdb-btn-right); + bottom: var(--mdb-btn-bottom); + z-index: var(--mdb-btn-zindex); + display: flex; + flex-flow: column-reverse nowrap; + align-items: center; + padding: var(--mdb-btn-padding-top) var(--mdb-btn-padding-x) var(--mdb-btn-padding-bottom); + margin-bottom: 0; + height: auto; + overflow: hidden +} + +.fixed-action-btn>.btn-floating { + position: relative; + transform: scale(1.2); + z-index: 10 +} + +.fixed-action-btn ul { + position: absolute; + bottom: 0; + left: 0; + right: 0; + display: flex; + flex-direction: column; + padding: 0; + margin: 0; + text-align: center; + opacity: 0; + transition: transform .4s,opacity .4s; + z-index: -1 +} + +.fixed-action-btn ul li { + z-index: 0; + display: flex; + margin-right: auto; + margin-bottom: var(--mdb-btn-margin-bottom); + margin-left: auto +} + +.fixed-action-btn ul li:first-of-type { + margin-top: calc(var(--mdb-btn-margin-bottom)*0.5) +} + +.fixed-action-btn ul a.btn { + opacity: 0; + transition: opacity .4s ease-in +} + +.fixed-action-btn.active ul,.fixed-action-btn ul a.btn.shown { + opacity: 1 +} + +.btn-block { + --mdb-btn-margin-top: 0.5rem; + display: block; + width: 100% +} + +.btn-block+.btn-block { + margin-top: var(--mdb-btn-margin-top) +} + +hr.divider-horizontal:not([size]) { + height: 2px +} + +.divider-horizontal { + opacity: 1; + background-color: #f5f5f5; + height: 2px +} + +.divider-vertical { + opacity: 1; + background-color: #f5f5f5; + display: inline-block; + width: 2px; + margin: 0 1rem +} + +hr.divider-horizontal-blurry { + background-image: linear-gradient(90deg,transparent,#666,transparent); + background-color: transparent +} + +hr.divider-vertical-blurry { + background-image: linear-gradient(180deg,transparent,#666,transparent); + background-color: transparent; + width: 1px; + top: 0; + right: 0 +} + +.dropdown-menu { + --mdb-dropdown-item-border-radius: 0.5rem; + color: var(--mdb-dropdown-color); + margin: 0; + padding-top: 0; + padding-bottom: 0; + border: 0; + box-shadow: var(--mdb-dropdown-box-shadow); + font-size: var(--mdb-dropdown-font-size); + top: 100%; + left: 0; + margin-top: var(--mdb-dropdown-spacer) +} + +.dropdown-menu>li { + border-radius: 0 +} + +.dropdown-menu>li:first-child,.dropdown-menu>li:first-child .dropdown-item { + border-top-left-radius: var(--mdb-dropdown-item-border-radius); + border-top-right-radius: var(--mdb-dropdown-item-border-radius); + border-bottom-left-radius: 0; + border-bottom-right-radius: 0 +} + +.dropdown-menu>li:not(:first-child):not(:last-child) .dropdown-item { + border-radius: 0 +} + +.dropdown-menu>li:last-child,.dropdown-menu>li:last-child .dropdown-item { + border-top-left-radius: 0; + border-top-right-radius: 0; + border-bottom-left-radius: var(--mdb-dropdown-item-border-radius); + border-bottom-right-radius: var(--mdb-dropdown-item-border-radius) +} + +.dropdown-menu.animation { + --mdb-dropdown-menu-animated-animation-duration: 0.55s; + --mdb-dropdown-menu-animated-animation-timing-function: ease; + display: block; + animation-duration: var(--mdb-dropdown-menu-animated-animation-duration); + animation-timing-function: var(--mdb-dropdown-menu-animated-animation-timing-function) +} + +.dropdown-item { + --mdb-dropdown-state-color: #16181b; + --mdb-dropdown-state-background-color: #eee; + padding: var(--mdb-dropdown-item-padding-y) var(--mdb-dropdown-item-padding-x); + color: var(--mdb-dropdown-color); + border-radius: 0 +} + +.dropdown-item.active,.dropdown-item:active,.dropdown-item:focus,.dropdown-item:hover { + color: var(--mdb-dropdown-state-color); + background-color: var(--mdb-dropdown-state-background-color) +} + +.hidden-arrow.dropdown-toggle:after { + display: none +} + +.animation { + animation-duration: 1s; + animation-fill-mode: both; + padding: auto +} + +@media(prefers-reduced-motion) { + .animation { + transition: none!important; + animation: unset!important + } +} + +@keyframes fade-in { + 0% { + opacity: 0 + } + + to { + opacity: 1 + } +} + +.fade-in { + animation-name: fade-in +} + +@keyframes fade-out { + 0% { + opacity: 1 + } + + to { + opacity: 0 + } +} + +.fade-out { + animation-name: fade-out +} + +.dropdown-divider { + --mdb-dropdown-divider-border-top-width: 2px; + --mdb-dropdown-divider-border-top-bg: #f5f5f5; + border-top: var(--mdb-dropdown-divider-border-top-width) solid var(--mdb-dropdown-divider-border-top-bg); + opacity: 1 +} + +.dropdown-menu INPUT:not(:-webkit-autofill),.dropdown-menu SELECT:not(:-webkit-autofill),.dropdown-menu TEXTAREA:not(:-webkit-autofill) { + animation-name: none!important +} + +.btn-group,.btn-group-vertical { + --mdb-btn-box-shadow: 0 4px 9px -4px rgba(0,0,0,0.35); + --mdb-btn-hover-box-shadow: 0 8px 9px -4px rgba(0,0,0,0.15),0 4px 18px 0 rgba(0,0,0,0.1); + --mdb-btn-focus-box-shadow: 0 8px 9px -4px rgba(0,0,0,0.15),0 4px 18px 0 rgba(0,0,0,0.1); + --mdb-btn-active-box-shadow: 0 8px 9px -4px rgba(0,0,0,0.15),0 4px 18px 0 rgba(0,0,0,0.1); + --mdb-btn-group-transition: color 0.15s ease-in-out,background-color 0.15s ease-in-out,border-color 0.15s ease-in-out,box-shadow 0.15s ease-in-out; + box-shadow: var(--mdb-btn-box-shadow); + transition: var(--mdb-btn-group-transition) +} + +.btn-group-vertical:hover,.btn-group:hover { + box-shadow: var(--mdb-btn-hover-box-shadow) +} + +.btn-group-vertical.focus,.btn-group-vertical:focus,.btn-group.focus,.btn-group:focus { + box-shadow: var(--mdb-btn-focus-box-shadow) +} + +.btn-group-vertical.active,.btn-group-vertical:active,.btn-group.active,.btn-group:active { + box-shadow: var(--mdb-btn-active-box-shadow) +} + +.btn-group-vertical.active:focus,.btn-group-vertical:active:focus,.btn-group.active:focus,.btn-group:active:focus { + box-shadow: var(--mdb-btn-focus-box-shadow) +} + +.btn-group-vertical.disabled,.btn-group-vertical:disabled,.btn-group.disabled,.btn-group:disabled,fieldset:disabled .btn-group,fieldset:disabled .btn-group-vertical { + box-shadow: var(--mdb-btn-box-shadow); + border: 0 +} + +.btn-group-vertical>.btn,.btn-group>.btn { + box-shadow: none +} + +.btn-group-vertical>.btn:first-child:hover,.btn-group-vertical>.btn:focus-visible,.btn-group-vertical>.btn:hover,.btn-group>.btn:first-child:hover,.btn-group>.btn:focus-visible,.btn-group>.btn:hover,:not(.btn-check)+.btn-group-vertical>.btn:hover,:not(.btn-check)+.btn-group>.btn:hover { + box-shadow: none!important +} + +.btn-check:active+.btn-group-vertical>.btn,.btn-check:active+.btn-group-vertical>.btn:focus,.btn-check:active+.btn-group>.btn,.btn-check:active+.btn-group>.btn:focus,.btn-check:checked+.btn-group-vertical>.btn,.btn-check:checked+.btn-group-vertical>.btn:focus,.btn-check:checked+.btn-group>.btn,.btn-check:checked+.btn-group>.btn:focus,.btn-check:focus+.btn-group-vertical>.btn,.btn-check:focus+.btn-group>.btn,.btn-check:focus-visible+.btn-group-vertical>.btn,.btn-check:focus-visible+.btn-group>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn.active,.btn-group-vertical>.btn.active:focus,.btn-group-vertical>.btn.disabled,.btn-group-vertical>.btn.show,.btn-group-vertical>.btn.show:focus,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:active:focus,.btn-group-vertical>.btn:disabled,.btn-group-vertical>.btn:focus,.btn-group>.btn-group,.btn-group>.btn.active,.btn-group>.btn.active:focus,.btn-group>.btn.disabled,.btn-group>.btn.show,.btn-group>.btn.show:focus,.btn-group>.btn:active,.btn-group>.btn:active:focus,.btn-group>.btn:disabled,.btn-group>.btn:focus,fieldset:disabled .btn-group-vertical>.btn,fieldset:disabled .btn-group>.btn { + box-shadow: none +} + +.btn-group-vertical>.btn-link:first-child,.btn-group-vertical>.btn-tertiary:first-child,.btn-group>.btn-link:first-child,.btn-group>.btn-tertiary:first-child { + border-top-left-radius: 0; + border-bottom-left-radius: 0 +} + +.btn-group-vertical>.btn-link:last-child,.btn-group-vertical>.btn-tertiary:last-child,.btn-group>.btn-link:last-child,.btn-group>.btn-tertiary:last-child { + border-top-right-radius: 0; + border-bottom-right-radius: 0 +} + +.btn-group,.btn-group-lg>.btn,.btn-group-sm>.btn { + --mdb-btn-border-radius: 0.25rem; + border-radius: var(--mdb-btn-border-radius) +} + +.nav-tabs { + border-bottom: 0 +} + +.nav-tabs .nav-link { + --mdb-nav-tabs-link-font-weight: 500; + --mdb-nav-tabs-link-font-size: 12px; + --mdb-nav-tabs-link-color: rgba(0,0,0,0.55); + --mdb-nav-tabs-link-padding-top: 17px; + --mdb-nav-tabs-link-padding-bottom: 16px; + --mdb-nav-tabs-link-padding-x: 29px; + --mdb-nav-tabs-link-hover-bgc: #f7f7f7; + --mdb-nav-tabs-link-border-bottom-width: 2px; + --mdb-nav-tabs-link-active-color: #3b71ca; + --mdb-nav-tabs-link-active-border-color: #3b71ca; + border-width: 0; + border-bottom: var(--mdb-nav-tabs-link-border-bottom-width) solid transparent; + border-radius: 0; + text-transform: uppercase; + line-height: 1; + font-weight: var(--mdb-nav-tabs-link-font-weight); + font-size: var(--mdb-nav-tabs-link-font-size); + color: var(--mdb-nav-tabs-link-color); + padding: var(--mdb-nav-tabs-link-padding-top) var(--mdb-nav-tabs-link-padding-x) var(--mdb-nav-tabs-link-padding-bottom) var(--mdb-nav-tabs-link-padding-x) +} + +.nav-tabs .nav-link:hover { + background-color: var(--mdb-nav-tabs-link-hover-bgc); + border-color: transparent +} + +.nav-tabs .nav-link:focus { + border-color: transparent +} + +.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active { + color: var(--mdb-nav-tabs-link-active-color); + border-color: var(--mdb-nav-tabs-link-active-border-color) +} + +.nav-pills { + margin-left: -.5rem +} + +.nav-pills .nav-link { + --mdb-nav-pills-link-border-radius: 0.25rem; + --mdb-nav-pills-link-font-size: 12px; + --mdb-nav-pills-link-padding-top: 17px; + --mdb-nav-pills-link-padding-bottom: 16px; + --mdb-nav-pills-link-padding-x: 29px; + --mdb-nav-pills-link-line-height: 1; + --mdb-nav-pills-link-hover-bg: #f7f7f7; + --mdb-nav-pills-link-font-weight: 500; + --mdb-nav-pills-link-color: rgba(0,0,0,0.55); + --mdb-nav-pills-margin: 0.5rem; + border-radius: var(--mdb-nav-pills-link-border-radius); + font-size: var(--mdb-nav-pills-link-font-size); + text-transform: uppercase; + padding: var(--mdb-nav-pills-link-padding-top) var(--mdb-nav-pills-link-padding-x) var(--mdb-nav-pills-link-padding-bottom) var(--mdb-nav-pills-link-padding-x); + line-height: var(--mdb-nav-pills-link-line-height); + background-color: var(--mdb-nav-pills-link-hover-bg); + font-weight: var(--mdb-nav-pills-link-font-weight); + color: var(--mdb-nav-pills-link-color); + margin: var(--mdb-nav-pills-margin) +} + +.nav-pills .nav-link.active,.nav-pills .show>.nav-link { + --mdb-nav-pills-link-active-bg: #e3ebf7; + --mdb-nav-pills-link-active-color: #285192; + background-color: var(--mdb-nav-pills-link-active-bg); + color: var(--mdb-nav-pills-link-active-color) +} + +.nav-fill .nav-item .nav-link,.nav-justified .nav-item .nav-link { + width: auto +} + +.navbar { + --mdb-navbar-box-shadow: 0 4px 12px 0 rgba(0,0,0,0.07),0 2px 4px rgba(0,0,0,0.05); + --mdb-navbar-padding-top: 0.5625rem; + --mdb-navbar-brand-img-margin-right: 0.25rem; + box-shadow: var(--mdb-navbar-box-shadow); + padding-top: var(--mdb-navbar-padding-top) +} + +.navbar-toggler { + border: 0 +} + +.navbar-toggler:focus { + box-shadow: none +} + +.navbar-dark .navbar-toggler,.navbar-light .navbar-toggler { + border: 0 +} + +.navbar-brand { + display: flex; + align-items: center +} + +.navbar-brand img { + margin-right: var(--mdb-navbar-brand-img-margin-right) +} + +.navbar-nav .dropdown-menu { + position: absolute +} + +.navbar-dark .navbar-toggler-icon,.navbar-light .navbar-toggler-icon { + background-image: none +} + +.card { + border: 0 +} + +.card .bg-image { + border-top-left-radius: var(--mdb-card-border-radius); + border-top-right-radius: var(--mdb-card-border-radius) +} + +.card[class*=bg-] .card-header { + --mdb-card-header-border-bottom-color: var(--mdb-border-color-translucent); + border-bottom-color: var(--mdb-card-header-border-bottom-color) +} + +.card[class*=bg-] .card-footer { + --mdb-card-footer-border-top-color: var(--mdb-border-color-translucent); + border-top-color: var(--mdb-card-footer-border-top-color) +} + +.card-header { + --mdb-card-header-border-width: 2px; + --mdb-card-header-border-color: #f5f5f5; + border-bottom: var(--mdb-card-header-border-width) solid var(--mdb-card-header-border-color) +} + +.card-body[class*=bg-] { + border-bottom-left-radius: var(--mdb-card-border-radius); + border-bottom-right-radius: var(--mdb-card-border-radius) +} + +.card-footer { + --mdb-card-footer-border-color: #f5f5f5; + --mdb-card-footer-border-width: 2px; + border-top: var(--mdb-card-footer-border-width) solid var(--mdb-card-footer-border-color) +} + +.card-img-left { + border-top-left-radius: var(--mdb-card-border-radius); + border-bottom-left-radius: var(--mdb-card-border-radius) +} + +.navbar .breadcrumb { + --mdb-breadcrumb-item-color: rgba(0,0,0,0.55); + --mdb-breadcrumb-item-hover-color: rgba(0,0,0,0.7); + --mdb-breadcrumb-item-before-color: rgba(0,0,0,0.55); + --mdb-breadcrumb-item-transition: color 0.15s ease-in-out; + background-color: transparent; + margin-bottom: 0 +} + +.navbar .breadcrumb .breadcrumb-item a { + color: var(--mdb-breadcrumb-item-color); + transition: var(--mdb-breadcrumb-item-transition) +} + +.navbar .breadcrumb .breadcrumb-item a:focus,.navbar .breadcrumb .breadcrumb-item a:hover { + color: var(--mdb-breadcrumb-item-hover-color) +} + +.navbar .breadcrumb .breadcrumb-item+.breadcrumb-item:before { + color: var(--mdb-breadcrumb-item-before-color) +} + +.pagination { + --mdb-pagination-border-radius: 0.25rem; + --mdb-pagination-active-box-shadow: 0 4px 9px -4px #e3ebf7; + --mdb-pagination-active-transition: all 0.2s linear; + --mdb-pagination-active-font-weight: 500; + --mdb-pagination-circle-border-radius: 50%; + --mdb-pagination-circle-padding-x: 0.841rem; + --mdb-pagination-circle-padding-l-lg: 1.399414rem; + --mdb-pagination-circle-padding-r-lg: 1.399415rem; + --mdb-pagination-circle-padding-l-sm: 0.696rem; + --mdb-pagination-circle-padding-r-sm: 0.688rem +} + +.page-link { + background-color: transparent; + border: 0; + outline: 0; + border-radius: var(--mdb-pagination-border-radius) +} + +.page-link:focus { + box-shadow: none +} + +.active>.page-link,.page-link.active { + border: 0; + box-shadow: var(--mdb-pagination-active-box-shadow); + transition: var(--mdb-pagination-active-transition); + font-weight: var(--mdb-pagination-active-font-weight) +} + +.page-item:not(:first-child) .page-link { + margin-left: 0 +} + +.page-item:first-child .page-link { + border-top-left-radius: var(--mdb-pagination-border-radius); + border-bottom-left-radius: var(--mdb-pagination-border-radius) +} + +.page-item:last-child .page-link { + border-top-right-radius: var(--mdb-pagination-border-radius); + border-bottom-right-radius: var(--mdb-pagination-border-radius) +} + +.pagination-circle .page-item:first-child .page-link,.pagination-circle .page-item:last-child .page-link,.pagination-circle .page-link { + border-radius: var(--mdb-pagination-circle-border-radius) +} + +.pagination-circle .page-link { + padding-left: var(--mdb-pagination-circle-padding-x); + padding-right: var(--mdb-pagination-circle-padding-x) +} + +.pagination-circle.pagination-lg .page-link { + padding-left: var(--mdb-pagination-circle-padding-l-lg); + padding-right: var(--mdb-pagination-circle-padding-r-lg) +} + +.pagination-circle.pagination-sm .page-link { + padding-left: var(--mdb-pagination-circle-padding-l-sm); + padding-right: var(--mdb-pagination-circle-padding-r-sm) +} + +.badge-dot { + --mdb-badge-border-radius: 4.5px; + --mdb-badge-height: 9px; + --mdb-badge-width: 9px; + --mdb-badge-margin-left: -0.3125rem; + position: absolute; + min-width: 0; + width: var(--mdb-badge-width); + height: var(--mdb-badge-height); + border-radius: var(--mdb-badge-border-radius); + padding: 0; + margin-left: var(--mdb-badge-margin-left) +} + +.badge-dot:empty { + display: inline-block +} + +.badge-notification { + --mdb-badge-font-size: 0.6rem; + --mdb-badge-padding-x: 0.45em; + --mdb-badge-padding-y: 0.2em; + --mdb-badge-margin-top: -0.1rem; + --mdb-badge-margin-left: -0.5rem; + position: absolute; + font-size: var(--mdb-badge-font-size); + padding: var(--mdb-badge-padding-y) var(--mdb-badge-padding-x); + margin-top: var(--mdb-badge-margin-top); + margin-left: var(--mdb-badge-margin-left) +} + +.badge-primary { + background-color: #dfe7f6; + color: #2c58a0 +} + +.badge-primary i { + color: #376fc8 +} + +.badge-secondary { + background-color: #ebedef; + color: #40464f +} + +.badge-secondary i { + color: #565e6c +} + +.badge-success { + background-color: #d6f0e0; + color: #0d6832 +} + +.badge-success i { + color: #139647 +} + +.badge-danger { + background-color: #f9e1e5; + color: #af233a +} + +.badge-danger i { + color: #d62e4a +} + +.badge-warning { + background-color: #fbf0da; + color: #73510d +} + +.badge-warning i { + color: #a17112 +} + +.badge-info { + background-color: #def1f7; + color: #1c657d +} + +.badge-info i { + color: #2686a6 +} + +.badge-light { + background-color: #f5f5f5; + color: #4f4f4f +} + +.badge-light i { + color: #8c8c8c +} + +.badge-dark { + background-color: #332e2e; + color: #f5f5f5 +} + +.badge-dark i { + color: #e8e8e8 +} + +.alert { + border: 0 +} + +.alert-absolute { + position: absolute +} + +.alert-fixed { + --mdb-alert-fixed-z-index: 1070; + position: fixed; + z-index: var(--mdb-alert-fixed-z-index) +} + +.parent-alert-relative { + position: relative +} + +.alert-primary { + background-color: #dfe7f6; + color: #2c58a0 +} + +.alert-primary i { + color: #376fc8 +} + +.alert-primary .alert-link { + color: #2c58a0 +} + +.alert-primary .alert-link:hover { + color: #234680 +} + +.alert-secondary { + background-color: #ebedef; + color: #40464f +} + +.alert-secondary i { + color: #565e6c +} + +.alert-secondary .alert-link { + color: #40464f +} + +.alert-secondary .alert-link:hover { + color: #33383f +} + +.alert-success { + background-color: #d6f0e0; + color: #0d6832 +} + +.alert-success i { + color: #139647 +} + +.alert-success .alert-link { + color: #0d6832 +} + +.alert-success .alert-link:hover { + color: #0a5328 +} + +.alert-danger { + background-color: #f9e1e5; + color: #af233a +} + +.alert-danger i { + color: #d62e4a +} + +.alert-danger .alert-link { + color: #af233a +} + +.alert-danger .alert-link:hover { + color: #8c1c2e +} + +.alert-warning { + background-color: #fbf0da; + color: #73510d +} + +.alert-warning i { + color: #a17112 +} + +.alert-warning .alert-link { + color: #73510d +} + +.alert-warning .alert-link:hover { + color: #5c410a +} + +.alert-info { + background-color: #def1f7; + color: #1c657d +} + +.alert-info i { + color: #2686a6 +} + +.alert-info .alert-link { + color: #1c657d +} + +.alert-info .alert-link:hover { + color: #165164 +} + +.alert-light { + background-color: #f5f5f5; + color: #4f4f4f +} + +.alert-light i { + color: #8c8c8c +} + +.alert-light .alert-link { + color: #4f4f4f +} + +.alert-light .alert-link:hover { + color: #3f3f3f +} + +.alert-dark { + background-color: #332e2e; + color: #f5f5f5 +} + +.alert-dark i { + color: #e8e8e8 +} + +.alert-dark .alert-link { + color: #f5f5f5 +} + +.alert-dark .alert-link:hover { + color: #c4c4c4 +} + +.progress { + border-radius: 0; + box-shadow: none +} + +.list-group { + --mdb-list-group-item-transition-time: 0.5s +} + +.list-group-item-action,.list-group-item-action:hover { + transition: var(--mdb-list-group-item-transition-time) +} + +.list-group-light { + --mdb-list-group-light-item-py: 1rem; + --mdb-list-group-light-item-border: 2px solid #f5f5f5; + --mdb-list-group-light-item-border-width: 2px; + --mdb-list-group-light-active-border-radius: 0.5rem; + --mdb-list-group-light-active-bg: #dfe7f6; + --mdb-list-group-light-active-color: #2c58a0 +} + +.list-group-light .list-group-item { + padding: var(--mdb-list-group-light-item-py) 0; + border: var(--mdb-list-group-light-item-border) +} + +.list-group-light>.list-group-item { + border-left-width: 0; + border-bottom-width: var(--mdb-list-group-light-item-border-width); + border-right-width: 0; + border-top-width: 0 +} + +.list-group-light>.list-group-item:last-of-type { + border: none +} + +.list-group-light .active { + border: none; + border-radius: var(--mdb-list-group-light-active-border-radius); + background-color: var(--mdb-list-group-light-active-bg); + color: var(--mdb-list-group-light-active-color) +} + +.list-group-light .list-group-item-action:focus,.list-group-light .list-group-item-action:hover { + border-radius: var(--mdb-list-group-light-active-border-radius) +} + +.list-group-small { + --mdb-list-group-small-item-py: 0.5rem +} + +.list-group-small .list-group-item { + padding: var(--mdb-list-group-small-item-py) 0 +} + +.list-group-item-primary { + background-color: #dfe7f6; + color: #2c58a0 +} + +.list-group-item-primary i { + color: #376fc8 +} + +.list-group-item-secondary { + background-color: #ebedef; + color: #40464f +} + +.list-group-item-secondary i { + color: #565e6c +} + +.list-group-item-success { + background-color: #d6f0e0; + color: #0d6832 +} + +.list-group-item-success i { + color: #139647 +} + +.list-group-item-danger { + background-color: #f9e1e5; + color: #af233a +} + +.list-group-item-danger i { + color: #d62e4a +} + +.list-group-item-warning { + background-color: #fbf0da; + color: #73510d +} + +.list-group-item-warning i { + color: #a17112 +} + +.list-group-item-info { + background-color: #def1f7; + color: #1c657d +} + +.list-group-item-info i { + color: #2686a6 +} + +.list-group-item-light { + background-color: #f5f5f5; + color: #4f4f4f +} + +.list-group-item-light i { + color: #8c8c8c +} + +.list-group-item-dark { + background-color: #332e2e; + color: #f5f5f5 +} + +.list-group-item-dark i { + color: #e8e8e8 +} + +.btn-close:focus { + box-shadow: none +} + +.modal-content { + --mdb-modal-box-shadow: 0 2px 15px -3px rgba(0,0,0,0.07),0 10px 20px -2px rgba(0,0,0,0.04); + border: 0; + box-shadow: var(--mdb-modal-box-shadow) +} + +.toast { + --mdb-toast-border-bottom-width: 2px; + --mdb-toast-btn-close-width: 1.3em; + --mdb-toast-btn-close-mr: -0.375rem; + --mdb-toast-btn-close-ml: 0.75rem; + border: 0 +} + +.toast .btn-close { + width: var(--mdb-toast-btn-close-width) +} + +.toast-header { + border-bottom-width: var(--mdb-toast-border-bottom-width) +} + +.toast-header .btn-close { + margin-right: var(--mdb-toast-btn-close-mr); + margin-left: var(--mdb-toast-btn-close-ml) +} + +.parent-toast-relative { + position: relative +} + +.toast-absolute { + position: absolute +} + +.toast-fixed { + position: fixed; + z-index: var(--mdb-toast-zindex) +} + +.toast-primary { + background-color: #dfe7f6; + color: #2c58a0; + border-color: #c7d6f0 +} + +.toast-primary i { + color: #376fc8 +} + +.toast-secondary { + background-color: #ebedef; + color: #40464f; + border-color: #dadee1 +} + +.toast-secondary i { + color: #565e6c +} + +.toast-success { + background-color: #d6f0e0; + color: #0d6831; + border-color: #c0e7d0 +} + +.toast-success i { + color: #139647 +} + +.toast-danger { + background-color: #f9e1e5; + color: #af233a; + border-color: #f4c8cf +} + +.toast-danger i { + color: #d62e4a +} + +.toast-warning { + background-color: #fbf0da; + color: #73510d; + border-color: #f9e4be +} + +.toast-warning i { + color: #a17112 +} + +.toast-info { + background-color: #def1f7; + color: #1c657d; + border-color: #c6e6f1 +} + +.toast-info i { + color: #2686a6 +} + +.toast-light { + background-color: #f5f5f5; + color: #4f4f4f; + border-color: #e6e6e6 +} + +.toast-light i { + color: #8c8c8c +} + +.toast-dark { + background-color: #332e2e; + color: #f5f5f5; + border-color: #443c3c +} + +.toast-dark i { + color: #e8e8e8 +} + +.tooltip { + --mdb-tooltip-font-size: 14px +} + +.tooltip.show { + opacity: 1 +} + +.tooltip .tooltip-arrow { + display: none +} + +.tooltip-inner { + font-size: var(--mdb-tooltip-font-size) +} + +.popover { + --mdb-popover-border-bottom-width: 2px +} + +.popover .popover-arrow { + display: none +} + +.popover-header { + border-bottom: var(--mdb-popover-border-bottom-width) solid var(--mdb-popover-border-color) +} + +.nav-pills.menu-sidebar .nav-link { + --mdb-scrollspy-menu-sidebar-font-size: 0.8rem; + --mdb-scrollspy-menu-sidebar-color: #262626; + --mdb-scrollspy-menu-sidebar-line-height: 1.1rem; + --mdb-scrollspy-menu-sidebar-padding-x: 5px; + --mdb-scrollspy-menu-sidebar-font-weight: 400; + --mdb-scrollspy-menu-sidebar-transition: all 0.2s ease-in-out; + --mdb-scrollspy-menu-sidebar-margin-y: 3px; + font-size: var(--mdb-scrollspy-menu-sidebar-font-size); + background-color: transparent; + color: var(--mdb-scrollspy-menu-sidebar-color); + line-height: var(--mdb-scrollspy-menu-sidebar-line-height); + padding: 0 var(--mdb-scrollspy-menu-sidebar-padding-x); + font-weight: var(--mdb-scrollspy-menu-sidebar-font-weight); + transition: var(--mdb-scrollspy-menu-sidebar-transition); + text-transform: none; + margin-top: var(--mdb-scrollspy-menu-sidebar-margin-y); + margin-bottom: var(--mdb-scrollspy-menu-sidebar-margin-y) +} + +.nav-pills.menu-sidebar .nav-link.active,.nav-pills.menu-sidebar .show>.nav-link { + --mdb-scrollspy-menu-sidebar-active-color: #3b71ca; + --mdb-scrollspy-menu-sidebar-active-font-weight: 600; + --mdb-scrollspy-menu-sidebar-active-border-width: 0.125rem; + --mdb-scrollspy-menu-sidebar-active-border-color: #3b71ca; + background-color: transparent; + box-shadow: none; + color: var(--mdb-scrollspy-menu-sidebar-active-color); + font-weight: var(--mdb-scrollspy-menu-sidebar-active-font-weight); + border-left: var(--mdb-scrollspy-menu-sidebar-active-border-width) solid var(--mdb-scrollspy-menu-sidebar-active-border-color); + border-radius: 0 +} + +.nav-pills.menu-sidebar .collapsible-scrollspy~.nav { + --mdb-scrollspy-collapsible-nav-transition-time: 0.5s; + transition: height var(--mdb-scrollspy-collapsible-nav-transition-time) ease; + flex-wrap: nowrap +} + +.ripple-surface { + position: relative; + overflow: hidden; + display: inline-block; + vertical-align: bottom +} + +.ripple-surface-unbound { + overflow: visible +} + +.ripple-wave { + --mdb-ripple-wave-cubicBezier: cubic-bezier(0,0,0.15,1); + --mdb-ripple-wave-border-radius: 50%; + --mdb-ripple-wave-opacity: 0.5; + --mdb-ripple-wave-transform: scale(0); + --mdb-ripple-wave-z-index: 999; + --mdb-ripple-wave-active-transform: scale(1); + background-image: radial-gradient(circle,rgba(0,0,0,.2) 0,rgba(0,0,0,.3) 40%,rgba(0,0,0,.4) 50%,rgba(0,0,0,.5) 60%,transparent 70%); + border-radius: var(--mdb-ripple-wave-border-radius); + opacity: var(--mdb-ripple-wave-opacity); + pointer-events: none; + position: absolute; + touch-action: none; + transform: var(--mdb-ripple-wave-transform); + transition-property: transform,opacity; + transition-timing-function: var(--mdb-ripple-wave-cubicBezier),var(--mdb-ripple-wave-cubicBezier); + z-index: var(--mdb-ripple-wave-z-index) +} + +.ripple-wave.active { + transform: var(--mdb-ripple-wave-active-transform); + opacity: 0 +} + +.btn .ripple-wave,.input-wrapper .ripple-wave { + background-image: radial-gradient(circle,hsla(0,0%,100%,.2) 0,hsla(0,0%,100%,.3) 40%,hsla(0,0%,100%,.4) 50%,hsla(0,0%,100%,.5) 60%,hsla(0,0%,100%,0) 70%) +} + +.ripple-surface-primary .ripple-wave { + background-image: radial-gradient(circle,rgba(59,113,202,.2) 0,rgba(59,113,202,.3) 40%,rgba(59,113,202,.4) 50%,rgba(59,113,202,.5) 60%,rgba(59,113,202,0) 70%) +} + +.ripple-surface-secondary .ripple-wave { + background-image: radial-gradient(circle,rgba(227,235,247,.2) 0,rgba(227,235,247,.3) 40%,rgba(227,235,247,.4) 50%,rgba(227,235,247,.5) 60%,rgba(227,235,247,0) 70%) +} + +.ripple-surface-success .ripple-wave { + background-image: radial-gradient(circle,rgba(20,164,77,.2) 0,rgba(20,164,77,.3) 40%,rgba(20,164,77,.4) 50%,rgba(20,164,77,.5) 60%,rgba(20,164,77,0) 70%) +} + +.ripple-surface-danger .ripple-wave { + background-image: radial-gradient(circle,rgba(220,76,100,.2) 0,rgba(220,76,100,.3) 40%,rgba(220,76,100,.4) 50%,rgba(220,76,100,.5) 60%,rgba(220,76,100,0) 70%) +} + +.ripple-surface-warning .ripple-wave { + background-image: radial-gradient(circle,rgba(228,161,27,.2) 0,rgba(228,161,27,.3) 40%,rgba(228,161,27,.4) 50%,rgba(228,161,27,.5) 60%,rgba(228,161,27,0) 70%) +} + +.ripple-surface-info .ripple-wave { + background-image: radial-gradient(circle,rgba(84,180,211,.2) 0,rgba(84,180,211,.3) 40%,rgba(84,180,211,.4) 50%,rgba(84,180,211,.5) 60%,rgba(84,180,211,0) 70%) +} + +.ripple-surface-light .ripple-wave { + background-image: radial-gradient(circle,hsla(0,0%,98.4%,.2) 0,hsla(0,0%,98.4%,.3) 40%,hsla(0,0%,98.4%,.4) 50%,hsla(0,0%,98.4%,.5) 60%,hsla(0,0%,98.4%,0) 70%) +} + +.ripple-surface-dark .ripple-wave { + background-image: radial-gradient(circle,rgba(51,45,45,.2) 0,rgba(51,45,45,.3) 40%,rgba(51,45,45,.4) 50%,rgba(51,45,45,.5) 60%,rgba(51,45,45,0) 70%) +} + +.range { + --mdb-range-thumb-height: 30px; + --mdb-range-thumb-width: 30px; + --mdb-range-thumb-top: -35px; + --mdb-range-thumb-margin-left: -15px; + --mdb-range-thumb-border-radius: 50% 50% 50% 0; + --mdb-range-thumb-transform: scale(0); + --mdb-range-thumb-transition: transform 0.2s ease-in-out; + --mdb-range-thumb-value-font-size: 12px; + --mdb-range-thumb-value-line-height: 30px; + --mdb-range-thumb-value-color: #fff; + --mdb-range-thumb-value-font-weight: 500; + --mdb-range-thumb-background: #3b71ca; + position: relative +} + +.range .thumb { + height: var(--mdb-range-thumb-height); + width: var(--mdb-range-thumb-width); + top: var(--mdb-range-thumb-top); + margin-left: var(--mdb-range-thumb-margin-left); + text-align: center; + transform: var(--mdb-range-thumb-transform); + transform-origin: bottom; + transition: var(--mdb-range-thumb-transition) +} + +.range .thumb,.range .thumb:after { + position: absolute; + display: block; + border-radius: var(--mdb-range-thumb-border-radius) +} + +.range .thumb:after { + content: ""; + transform: translateX(-50%); + width: 100%; + height: 100%; + top: 0; + transform: rotate(-45deg); + background: var(--mdb-range-thumb-background); + z-index: -1 +} + +.range .thumb .thumb-value { + display: block; + font-size: var(--mdb-range-thumb-value-font-size); + line-height: var(--mdb-range-thumb-value-line-height); + color: var(--mdb-range-thumb-value-color); + font-weight: var(--mdb-range-thumb-value-font-weight); + z-index: 2 +} + +.range .thumb.thumb-active { + transform: scale(1) +} + +.accordion-button:not(.collapsed):focus { + box-shadow: var(--mdb-accordion-btn-focus-box-shadow) +} + +.accordion-button:focus { + border-color: var(--mdb-accordion-btn-focus-border-color); + outline: 0; + box-shadow: none +} + +.accordion-flush { + --mdb-accordion-flush-btn-box-shadow: inset 0 -2px 0 #f5f5f5; + --mdb-accordion-flush-border-bottom: 2px solid #f5f5f5 +} + +.accordion-flush .accordion-button:not(.collapsed) { + box-shadow: var(--mdb-accordion-flush-btn-box-shadow) +} + +.accordion-flush .accordion-item { + border-bottom: var(--mdb-accordion-flush-border-bottom) +} + +.accordion.accordion-borderless,.accordion.accordion-flush { + --mdb-accordion-bg: transparent; + background-color: var(--mdb-accordion-bg) +} + +.accordion-borderless { + --mdb-accordion-borderless-btn-border-radius: 0.5rem; + --mdb-accordion-borderless-btn-bg: #dfe7f6; + --mdb-accordion-borderless-btn-color: #2c58a0 +} + +.accordion-borderless .accordion-item { + border: 0 +} + +.accordion-borderless .accordion-item .accordion-button { + border-radius: var(--mdb-accordion-borderless-btn-border-radius) +} + +.accordion-borderless .accordion-item .accordion-button:not(.collapsed) { + background-color: var(--mdb-accordion-borderless-btn-bg); + color: var(--mdb-accordion-borderless-btn-color); + box-shadow: none +} + +.modal { + --mdb-modal-top-left-top: 10px; + --mdb-modal-top-left-left: 10px; + --mdb-modal-top-right-top: 10px; + --mdb-modal-top-right-right: 10px; + --mdb-modal-bottom-left-bottom: 10px; + --mdb-modal-bottom-left-left: 10px; + --mdb-modal-bottom-right-bottom: 10px; + --mdb-modal-bottom-right-right: 10px; + --mdb-modal-fade-top-transform: translate3d(0,-25%,0); + --mdb-modal-fade-right-transform: translate3d(25%,0,0); + --mdb-modal-fade-bottom-transform: translate3d(0,25%,0); + --mdb-modal-fade-left-transform: translate3d(-25%,0,0); + --mdb-modal-side-right: 10px; + --mdb-modal-side-bottom: 10px; + --mdb-modal-non-invasive-box-shadow: 0 2px 6px -1px rgba(0,0,0,0.07),0 6px 18px -1px rgba(0,0,0,0.04); + --mdb-modal-non-invasive-box-shadow-top: 0 -10px 20px 0 rgba(0,0,0,0.05) +} + +@media(min-width: 768px) { + .modal .modal-dialog.modal-top { + top:0 + } + + .modal .modal-dialog.modal-left { + left: 0 + } + + .modal .modal-dialog.modal-right { + right: 0 + } + + .modal .modal-dialog.modal-top-left { + top: var(--mdb-modal-top-left-top); + left: var(--mdb-modal-top-left-left) + } + + .modal .modal-dialog.modal-top-right { + top: var(--mdb-modal-top-right-top); + right: var(--mdb-modal-top-right-right) + } + + .modal .modal-dialog.modal-bottom-left { + bottom: var(--mdb-modal-bottom-left-bottom); + left: var(--mdb-modal-bottom-left-left) + } + + .modal .modal-dialog.modal-bottom-right { + right: var(--mdb-modal-bottom-right-right); + bottom: var(--mdb-modal-bottom-right-bottom) + } +} + +.modal .modal-dialog.modal-bottom { + bottom: 0 +} + +.modal.fade.top:not(.show) .modal-dialog { + transform: var(--mdb-modal-fade-top-transform) +} + +.modal.fade.right:not(.show) .modal-dialog { + transform: var(--mdb-modal-fade-right-transform) +} + +.modal.fade.bottom:not(.show) .modal-dialog { + transform: var(--mdb-modal-fade-bottom-transform) +} + +.modal.fade.left:not(.show) .modal-dialog { + transform: var(--mdb-modal-fade-left-transform) +} + +@media(min-width: 992px) { + .modal .modal-side { + position:absolute; + width: 100%; + right: var(--mdb-modal-side-right); + bottom: var(--mdb-modal-side-bottom); + margin: 0 + } +} + +.modal .modal-frame { + position: absolute; + max-width: 100%; + width: 100%; + margin: 0 +} + +.modal-open .modal.frame { + overflow-y: hidden +} + +.modal-non-invasive-open { + overflow-y: auto +} + +.modal-non-invasive-open .modal.modal-non-invasive-show { + display: table +} + +@media(min-width: 992px) { + .modal-non-invasive-open .modal.modal-non-invasive-show .modal-dialog.modal-bottom-left,.modal-non-invasive-open .modal.modal-non-invasive-show .modal-dialog.modal-bottom-right,.modal-non-invasive-open .modal.modal-non-invasive-show .modal-side { + bottom:0 + } + + .modal-non-invasive-open .modal.modal-non-invasive-show.modal.frame.bottom,.modal-non-invasive-open .modal.modal-non-invasive-show.modal.frame.bottom .modal-content { + box-shadow: var(--mdb-modal-non-invasive-box-shadow-top) + } + + .modal-non-invasive-open .modal.modal-non-invasive-show.modal.frame.top { + box-shadow: var(--mdb-modal-non-invasive-box-shadow) + } + + .modal-non-invasive-open .modal.modal-non-invasive-show .modal-side.modal-bottom-left .modal-content,.modal-non-invasive-open .modal.modal-non-invasive-show .modal-side.modal-bottom-right .modal-content { + box-shadow: var(--mdb-modal-non-invasive-box-shadow-top) + } +} + +.modal-non-invasive-open .modal.modal-non-invasive-show .modal-dialog.modal-bottom-right { + right: 0 +} + +.modal-non-invasive-open .modal.modal-non-invasive-show .modal-dialog.modal-bottom-left,.modal-non-invasive-open .modal.modal-non-invasive-show .modal-dialog.modal-top-left { + left: 0 +} + +.modal-non-invasive-open .modal.modal-non-invasive-show .modal-side { + right: 0 +} + +.ps { + --mdb-scrollbar-rail-x-y-transition-opacity-bg: background-color 0.2s linear,opacity 0.2s linear; + --mdb-scrollbar-z-index: 1035; + --mdb-scrollbar-rail-x-y-length: 0.9375rem; + --mdb-scrollbar-rail-x-y-opacity: 0.6; + --mdb-scrollbar-rail-x-y-hover-opacity: 0.9; + --mdb-scrollbar-rail-x-y-bg-color: #eee; + --mdb-scrollbar-rail-x-y-clicking: #999; + --mdb-scrollbar-rail-x-y-clicking-length: 0.6875rem; + --mdb-scrollbar-rail-x-transition-height-bg: background-color 0.2s linear,height 0.2s ease-in-out; + --mdb-scrollbar-rail-y-transition-width-bg: background-color 0.2s linear,width 0.2s ease-in-out; + --mdb-scrollbar-thumb-x-y-color: #aaa; + --mdb-scrollbar-thumb-x-y-border-radius: 0.375rem; + --mdb-scrollbar-thumb-x-y-length: 0.375rem; + --mdb-scrollbar-thumb-x-y-position-length: 0.125rem; + overflow: hidden!important; + overflow-anchor: none; + touch-action: auto +} + +.ps__rail-x,.ps__rail-y { + display: none; + opacity: 0; + transition: var(--mdb-scrollbar-rail-x-y-transition-opacity-bg); + position: absolute; + z-index: var(--mdb-scrollbar-z-index) +} + +.ps__rail-x { + height: var(--mdb-scrollbar-rail-x-y-length); + bottom: 0 +} + +.ps__rail-y { + width: var(--mdb-scrollbar-rail-x-y-length); + right: 0 +} + +.ps--active-x>.ps__rail-x,.ps--active-y>.ps__rail-y { + display: block; + background-color: transparent +} + +.ps--focus>.ps__rail-x,.ps--focus>.ps__rail-y,.ps--scrolling-x>.ps__rail-x,.ps--scrolling-y>.ps__rail-y,.ps:hover>.ps__rail-x,.ps:hover>.ps__rail-y { + opacity: var(--mdb-scrollbar-rail-x-y-opacity) +} + +.ps .ps__rail-x.ps--clicking,.ps .ps__rail-x:focus,.ps .ps__rail-x:hover,.ps .ps__rail-y.ps--clicking,.ps .ps__rail-y:focus,.ps .ps__rail-y:hover { + background-color: var(--mdb-scrollbar-rail-x-y-bg-color); + opacity: var(--mdb-scrollbar-rail-x-y-hover-opacity) +} + +.ps__thumb-x,.ps__thumb-y { + background-color: var(--mdb-scrollbar-thumb-x-y-color); + border-radius: var(--mdb-scrollbar-thumb-x-y-border-radius); + position: absolute +} + +.ps__thumb-x { + transition: var(--mdb-scrollbar-rail-x-transition-height-bg); + height: var(--mdb-scrollbar-thumb-x-y-length); + bottom: var(--mdb-scrollbar-thumb-x-y-position-length) +} + +.ps__thumb-y { + transition: var(--mdb-scrollbar-rail-y-transition-width-bg); + width: var(--mdb-scrollbar-thumb-x-y-length); + right: var(--mdb-scrollbar-thumb-x-y-position-length) +} + +.ps__rail-x.ps--clicking .ps__thumb-x,.ps__rail-x:focus>.ps__thumb-x,.ps__rail-x:hover>.ps__thumb-x { + background-color: var(--mdb-scrollbar-rail-x-y-clicking); + height: var(--mdb-scrollbar-rail-x-y-clicking-length) +} + +.ps__rail-y.ps--clicking .ps__thumb-y,.ps__rail-y:focus>.ps__thumb-y,.ps__rail-y:hover>.ps__thumb-y { + background-color: var(--mdb-scrollbar-rail-x-y-clicking); + width: var(--mdb-scrollbar-rail-x-y-clicking-length) +} + +@supports(-ms-overflow-style: none) { + .ps { + overflow:auto!important + } +} + +@media (-ms-high-contrast:none),screen and (-ms-high-contrast:active) { + .ps { + overflow: auto!important + } +} + +.sidenav { + --mdb-sidenav-transform: translateX(-100%); + --mdb-sidenav-zindex: 1035; + --mdb-sidenav-background-color: #fff; + --mdb-sidenav-width: 240px; + --mdb-sidenav-height: 100vh; + --mdb-sidenav-box-shadow: 0 4px 12px 0 rgba(0,0,0,0.07),0 2px 4px rgba(0,0,0,0.05); + --mdb-sidenav-data-hidden-false-transform: translateX(0%); + --mdb-sidenav-data-color-light-color: hsla(0,0%,100%,0.6); + --mdb-sidenav-data-right-true-transform: translateX(100%); + --mdb-sidenav-data-slim-collapsed-true-width: 77px; + --mdb-sidenav-menu-padding: 0.2rem; + --mdb-sidenav-collapse-sidenav-link-font-size: 0.78rem; + --mdb-sidenav-collapse-sidenav-link-height: 1.5rem; + --mdb-sidenav-link-font-size: 0.89rem; + --mdb-sidenav-link-padding-y: 1rem; + --mdb-sidenav-link-padding-x: 1.5rem; + --mdb-sidenav-collapse-sidenav-link-padding-left: 3.4rem; + --mdb-sidenav-link-height: 3rem; + --mdb-sidenav-link-border-radius: 5px; + --mdb-sidenav-link-transition: all 0.3s linear; + --mdb-sidenav-link-hover-background-color: #f6f9fc; + --mdb-sidenav-link-active-focus-background-color: #f6f9fc; + --mdb-sidenav-link-active-color: #3b71ca; + --mdb-sidenav-subheading-font-size: 0.6rem; + --mdb-sidenav-subheading-padding-y: 1rem; + --mdb-sidenav-subheading-padding-x: 1.5rem; + --mdb-sidenav-subheading-fw: 700; + --mdb-sidenav-sm-link-pt: 0.4rem; + --mdb-sidenav-sm-link-pb: 0.4rem; + --mdb-sidenav-rotate-icon-margin-right: 0.8rem; + --mdb-sidenav-rotate-icon-transition: transform 0.3s; + --mdb-sidenav-light-color: hsla(0,0%,100%,0.6); + top: 0; + left: 0; + transform: var(--mdb-sidenav-transform); + position: fixed; + z-index: var(--mdb-sidenav-zindex); + background-color: var(--mdb-sidenav-background-color); + overflow: hidden; + width: var(--mdb-sidenav-width); + height: var(--mdb-sidenav-height); + box-shadow: var(--mdb-sidenav-box-shadow) +} + +.sidenav[data-mdb-hidden=false] { + transform: var(--mdb-sidenav-data-hidden-false-transform) +} + +.sidenav[data-mdb-color=light] { + color: var(--mdb-sidenav-data-color-light-color) +} + +.sidenav[data-mdb-right=true] { + right: 0; + left: unset; + transform: var(--mdb-sidenav-data-right-true-transform) +} + +.sidenav[data-mdb-position=absolute] { + position: absolute; + height: 100% +} + +.sidenav[data-mdb-position=relative] { + position: relative; + height: 100% +} + +.sidenav [data-mdb-slim=true] { + display: none +} + +.sidenav[data-mdb-slim-collapsed=true] { + width: var(--mdb-sidenav-data-slim-collapsed-true-width) +} + +.sidenav[data-mdb-slim-collapsed=true] [data-mdb-slim=false] { + display: none +} + +.sidenav[data-mdb-slim-collapsed=true] [data-mdb-slim=true] { + display: unset +} + +.sidenav-collapse,.sidenav-menu { + list-style: none; + position: relative; + padding: 0 var(--mdb-sidenav-menu-padding); + margin: 0 +} + +.sidenav-collapse { + display: none; + padding: 0 +} + +.sidenav-collapse.collapsing,.sidenav-collapse.show { + display: block +} + +.sidenav-collapse .sidenav-link { + font-size: var(--mdb-sidenav-collapse-sidenav-link-font-size); + height: var(--mdb-sidenav-collapse-sidenav-link-height); + padding-left: var(--mdb-sidenav-collapse-sidenav-link-padding-left) +} + +.sidenav-item { + position: relative +} + +.sidenav-link { + display: flex; + align-items: center; + cursor: pointer; + font-size: var(--mdb-sidenav-link-font-size); + padding: var(--mdb-sidenav-link-padding-y) var(--mdb-sidenav-link-padding-x); + height: var(--mdb-sidenav-link-height); + color: unset; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + border-radius: var(--mdb-sidenav-link-border-radius); + transition: var(--mdb-sidenav-link-transition) +} + +.sidenav-link:hover { + color: inherit; + background-color: var(--mdb-sidenav-link-hover-background-color); + outline: none +} + +.sidenav-link:active,.sidenav-link:focus { + color: inherit; + background-color: var(--mdb-sidenav-link-active-focus-background-color); + outline: none +} + +.sidenav-link.active { + color: var(--mdb-sidenav-link-active-color) +} + +.sidenav-link i { + color: #9fa6b2 +} + +.sidenav-subheading { + color: unset; + text-transform: uppercase; + font-size: var(--mdb-sidenav-subheading-font-size); + padding: var(--mdb-sidenav-subheading-padding-y) var(--mdb-sidenav-subheading-padding-x); + font-weight: var(--mdb-sidenav-subheading-fw) +} + +.sidenav-sm .sidenav-link { + padding-top: var(--mdb-sidenav-sm-link-pt); + padding-bottom: var(--mdb-sidenav-sm-link-pb); + height: auto +} + +.rotate-icon { + position: absolute; + right: 0; + margin-left: auto; + margin-right: var(--mdb-sidenav-rotate-icon-margin-right); + transition: var(--mdb-sidenav-rotate-icon-transition) +} + +.sidenav-backdrop { + --mdb-sidenav-backdrop-zindex: 1034; + --mdb-sidenav-backdrop-background-color: rgba(0,0,0,0.1); + z-index: var(--mdb-sidenav-backdrop-zindex); + top: 0; + left: 0; + background-color: var(--mdb-sidenav-backdrop-background-color) +} + +.sidenav-light { + color: var(--mdb-sidenav-light-color) +} + +.sidenav-slim { + --mdb-sidenav-slim-link-padding-left: 1rem +} + +.sidenav-slim .sidenav-link { + padding-left: var(--mdb-sidenav-slim-link-padding-left) +} + +.sidenav-primary .sidenav-item .sidenav-link:hover,.sidenav-primary .sidenav-link:active,.sidenav-primary .sidenav-link:focus { + color: inherit; + background-color: rgba(59,113,202,.05) +} + +.sidenav-primary .sidenav-link.active { + color: inherit +} + +.sidenav-secondary .sidenav-item .sidenav-link:hover,.sidenav-secondary .sidenav-link:active,.sidenav-secondary .sidenav-link:focus { + color: inherit; + background-color: rgba(159,166,178,.05) +} + +.sidenav-secondary .sidenav-link.active { + color: inherit +} + +.sidenav-success .sidenav-item .sidenav-link:hover,.sidenav-success .sidenav-link:active,.sidenav-success .sidenav-link:focus { + color: inherit; + background-color: rgba(20,164,77,.05) +} + +.sidenav-success .sidenav-link.active { + color: inherit +} + +.sidenav-danger .sidenav-item .sidenav-link:hover,.sidenav-danger .sidenav-link:active,.sidenav-danger .sidenav-link:focus { + color: inherit; + background-color: rgba(220,76,100,.05) +} + +.sidenav-danger .sidenav-link.active { + color: inherit +} + +.sidenav-warning .sidenav-item .sidenav-link:hover,.sidenav-warning .sidenav-link:active,.sidenav-warning .sidenav-link:focus { + color: inherit; + background-color: rgba(228,161,27,.05) +} + +.sidenav-warning .sidenav-link.active { + color: inherit +} + +.sidenav-info .sidenav-item .sidenav-link:hover,.sidenav-info .sidenav-link:active,.sidenav-info .sidenav-link:focus { + color: inherit; + background-color: rgba(84,180,211,.05) +} + +.sidenav-info .sidenav-link.active { + color: inherit +} + +.sidenav-light .sidenav-item .sidenav-link:hover,.sidenav-light .sidenav-link:active,.sidenav-light .sidenav-link:focus { + color: inherit; + background-color: hsla(0,0%,98.4%,.05) +} + +.sidenav-light .sidenav-link.active { + color: inherit +} + +.sidenav-dark .sidenav-item .sidenav-link:hover,.sidenav-dark .sidenav-link:active,.sidenav-dark .sidenav-link:focus { + color: inherit; + background-color: rgba(51,45,45,.05) +} + +.sidenav-dark .sidenav-link.active { + color: inherit +} + +.animation { + --mdb-animation-delay-1s: 1s; + --mdb-animation-delay-2s: 3s; + --mdb-animation-delay-3s: 3s; + --mdb-animation-delay-4s: 4s; + --mdb-animation-delay-5s: 5s; + --mdb-animation-fast-duration: 800ms; + --mdb-animation-faster-duration: 500ms; + --mdb-animation-slow-duration: 2s; + --mdb-animation-slower-duration: 3s +} + +.animation.infinite { + animation-iteration-count: infinite +} + +.animation.delay-1s { + animation-delay: var(--mdb-animation-delay-1s) +} + +.animation.delay-2s { + animation-delay: var(--mdb-animation-delay-2s) +} + +.animation.delay-3s { + animation-delay: var(--mdb-animation-delay-3s) +} + +.animation.delay-4s { + animation-delay: var(--mdb-animation-delay-4s) +} + +.animation.delay-5s { + animation-delay: var(--mdb-animation-delay-5s) +} + +.animation.fast { + animation-duration: var(--mdb-animation-fast-duration) +} + +.animation.faster { + animation-duration: var(--mdb-animation-faster-duration) +} + +.animation.slow { + animation-duration: var(--mdb-animation-slow-duration) +} + +.animation.slower { + animation-duration: var(--mdb-animation-slower-duration) +} + +@keyframes fade-in-down { + 0% { + opacity: 0; + transform: var(--mdb-animation-fade-in-down-transform-from) + } + + to { + opacity: 1; + transform: var(--mdb-animation-fade-in-down-transform-to) + } +} + +.fade-in-down { + --mdb-animation-fade-in-down-transform-from: translate3d(0,-100%,0); + --mdb-animation-fade-in-down-transform-to: translate3d(0,0,0); + animation-name: fade-in-down +} + +@keyframes fade-in-left { + 0% { + opacity: 0; + transform: var(--mdb-animation-fade-in-left-transform-from) + } + + to { + opacity: 1; + transform: var(--mdb-animation-fade-in-left-transform-to) + } +} + +.fade-in-left { + --mdb-animation-fade-in-left-transform-from: translate3d(-100%,0,0); + --mdb-animation-fade-in-left-transform-to: translate3d(0,0,0); + animation-name: fade-in-left +} + +@keyframes fade-in-right { + 0% { + opacity: 0; + transform: var(--mdb-animation-fade-in-right-transform-from) + } + + to { + opacity: 1; + transform: var(--mdb-animation-fade-in-right-transform-to) + } +} + +.fade-in-right { + --mdb-animation-fade-in-right-transform-from: translate3d(100%,0,0); + --mdb-animation-fade-in-right-transform-to: translate3d(0,0,0); + animation-name: fade-in-right +} + +@keyframes fade-in-up { + 0% { + opacity: 0; + transform: var(--mdb-animation-fade-in-up-transform-from) + } + + to { + opacity: 1; + transform: var(--mdb-animation-fade-in-up-transform-to) + } +} + +.fade-in-up { + --mdb-animation-fade-in-up-transform-from: translate3d(0,100%,0); + --mdb-animation-fade-in-up-transform-to: translate3d(0,0,0); + animation-name: fade-in-up +} + +@keyframes fade-out-down { + 0% { + opacity: 1 + } + + to { + opacity: 0; + transform: var(--mdb-animation-fade-out-down-transform-to) + } +} + +.fade-out-down { + --mdb-animation-fade-out-down-transform-to: translate3d(0,100%,0); + animation-name: fade-out-down +} + +@keyframes fade-out-left { + 0% { + opacity: 1 + } + + to { + opacity: 0; + transform: var(--mdb-animation-fade-out-left-transform-to) + } +} + +.fade-out-left { + --mdb-animation-fade-out-left-transform-to: translate3d(-100%,0,0); + animation-name: fade-out-left +} + +@keyframes fade-out-right { + 0% { + opacity: 1 + } + + to { + opacity: 0; + transform: var(--mdb-animation-fade-out-right-transform-to) + } +} + +.fade-out-right { + --mdb-animation-fade-out-right-transform-to: translate3d(100%,0,0); + animation-name: fade-out-right +} + +@keyframes fade-out-up { + 0% { + opacity: 1 + } + + to { + opacity: 0; + transform: var(--mdb-animation-fade-out-up-transform-to) + } +} + +.fade-out-up { + --mdb-animation-fade-out-up-transform-to: translate3d(0,-100%,0); + animation-name: fade-out-up +} + +@keyframes slide-in-down { + 0% { + visibility: visible; + transform: var(--mdb-animation-slide-in-down-transform-from) + } + + to { + transform: var(--mdb-animation-slide-in-down-transform-to) + } +} + +.slide-in-down { + --mdb-animation-slide-in-down-transform-from: translate3d(0,-100%,0); + --mdb-animation-slide-in-down-transform-to: translate3d(0,0,0); + animation-name: slide-in-down +} + +@keyframes slide-in-left { + 0% { + visibility: visible; + transform: var(--mdb-animation-slide-in-left-transform-from) + } + + to { + transform: var(--mdb-animation-slide-in-left-transform-to) + } +} + +.slide-in-left { + --mdb-animation-slide-in-left-transform-from: translate3d(-100%,0,0); + --mdb-animation-slide-in-left-transform-to: translate3d(0,0,0); + animation-name: slide-in-left +} + +@keyframes slide-in-right { + 0% { + visibility: visible; + transform: var(--mdb-animation-slide-in-right-transform-from) + } + + to { + transform: var(--mdb-animation-slide-in-right-transform-to) + } +} + +.slide-in-right { + --mdb-animation-slide-in-right-transform-from: translate3d(100%,0,0); + --mdb-animation-slide-in-right-transform-to: translate3d(0,0,0); + animation-name: slide-in-right +} + +@keyframes slide-in-up { + 0% { + visibility: visible; + transform: var(--mdb-animation-slide-in-up-transform-from) + } + + to { + transform: var(--mdb-animation-slide-in-up-transform-to) + } +} + +.slide-in-up { + --mdb-animation-slide-in-up-transform-from: translate3d(0,100%,0); + --mdb-animation-slide-in-up-transform-to: translate3d(0,0,0); + animation-name: slide-in-up +} + +@keyframes slide-out-down { + 0% { + transform: var(--mdb-animation-slide-out-down-transform-from) + } + + to { + visibility: hidden; + transform: var(--mdb-animation-slide-out-down-transform-to) + } +} + +.slide-out-down { + --mdb-animation-slide-out-down-transform-from: translate3d(0,0,0); + --mdb-animation-slide-out-down-transform-to: translate3d(0,100%,0); + animation-name: slide-out-down +} + +@keyframes slide-out-left { + 0% { + transform: var(--mdb-animation-slide-out-left-transform-from) + } + + to { + visibility: hidden; + transform: var(--mdb-animation-slide-out-left-transform-to) + } +} + +.slide-out-left { + --mdb-animation-slide-out-left-transform-from: translate3d(0,0,0); + --mdb-animation-slide-out-left-transform-to: translate3d(-100%,0,0); + animation-name: slide-out-left +} + +@keyframes slide-out-right { + 0% { + transform: var(--mdb-animation-slide-out-right-transform-from) + } + + to { + visibility: hidden; + transform: var(--mdb-animation-slide-out-right-transform-to) + } +} + +.slide-out-right { + --mdb-animation-slide-out-right-transform-from: translate3d(0,0,0); + --mdb-animation-slide-out-right-transform-to: translate3d(100%,0,0); + animation-name: slide-out-right +} + +@keyframes slide-out-up { + 0% { + transform: var(--mdb-animation-slide-out-up-transform-from) + } + + to { + visibility: hidden; + transform: var(--mdb-animation-slide-out-up-transform-to) + } +} + +.slide-out-up { + --mdb-animation-slide-out-up-transform-from: translate3d(0,0,0); + --mdb-animation-slide-out-up-transform-to: translate3d(0,-100%,0); + animation-name: slide-out-up +} + +@keyframes slide-down { + 0% { + transform: var(--mdb-animation-slide-down-transform-from) + } + + to { + transform: var(--mdb-animation-slide-down-transform-to) + } +} + +.slide-down { + --mdb-animation-slide-down-transform-from: translate3d(0,0,0); + --mdb-animation-slide-down-transform-to: translate3d(0,100%,0); + animation-name: slide-down +} + +@keyframes slide-left { + 0% { + transform: var(--mdb-animation-slide-left-transform-from) + } + + to { + transform: var(--mdb-animation-slide-left-transform-to) + } +} + +.slide-left { + --mdb-animation-slide-left-transform-from: translate3d(0,0,0); + --mdb-animation-slide-left-transform-to: translate3d(-100%,0,0); + animation-name: slide-left +} + +@keyframes slide-right { + 0% { + transform: var(--mdb-animation-slide-right-transform-from) + } + + to { + transform: var(--mdb-animation-slide-right-transform-to) + } +} + +.slide-right { + --mdb-animation-slide-right-transform-from: translate3d(0,0,0); + --mdb-animation-slide-right-transform-to: translate3d(100%,0,0); + animation-name: slide-right +} + +@keyframes slide-up { + 0% { + transform: var(--mdb-animation-slide-up-transform-from) + } + + to { + transform: var(--mdb-animation-slide-up-transform-to) + } +} + +.slide-up { + --mdb-animation-slide-up-transform-from: translate3d(0,0,0); + --mdb-animation-slide-up-transform-to: translate3d(0,-100%,0); + animation-name: slide-up +} + +@keyframes zoom-in { + 0% { + opacity: 0; + transform: var(--mdb-animation-zoom-in-transform-from) + } + + 50% { + opacity: 1 + } +} + +.zoom-in { + --mdb-animation-zoom-in-transform-from: scale3d(0.3,0.3,0.3); + animation-name: zoom-in +} + +@keyframes zoom-out { + 0% { + opacity: 1 + } + + 50% { + opacity: 0; + transform: var(--mdb-animation-zoom-out-transform-50) + } + + to { + opacity: 0 + } +} + +.zoom-out { + --mdb-animation-zoom-out-transform-50: scale3d(0.3,0.3,0.3); + animation-name: zoom-out +} + +@keyframes tada { + 0% { + transform: var(--mdb-animation-tada-transform-from) + } + + 10%,20% { + transform: var(--mdb-animation-tada-transform-20) + } + + 30%,50%,70%,90% { + transform: var(--mdb-animation-tada-transform-90) + } + + 40%,60%,80% { + transform: var(--mdb-animation-tada-transform-80) + } + + to { + transform: var(--mdb-animation-tada-transform-to) + } +} + +.tada { + --mdb-animation-tada-transform-from: scale3d(1,1,1); + --mdb-animation-tada-transform-20: scale3d(0.9,0.9,0.9) rotate3d(0,0,1,-3deg); + --mdb-animation-tada-transform-90: scale3d(1.1,1.1,1.1) rotate3d(0,0,1,3deg); + --mdb-animation-tada-transform-80: scale3d(1.1,1.1,1.1) rotate3d(0,0,1,-3deg); + --mdb-animation-tada-transform-to: scale3d(1,1,1); + animation-name: tada +} + +@keyframes pulse { + 0% { + transform: var(--mdb-animation-pulse-transform-from) + } + + 50% { + transform: var(--mdb-animation-pulse-transform-50) + } + + to { + transform: var(--mdb-animation-pulse-transform-to) + } +} + +.pulse { + --mdb-animation-pulse-transform-from: scale3d(1,1,1); + --mdb-animation-pulse-transform-50: scale3d(1.05,1.05,1.05); + --mdb-animation-pulse-transform-to: scale3d(1,1,1); + animation-name: pulse +} + +.stepper,.steps,.timeline { + --mdb-steps-transition: height 0.2s ease-in-out; + position: relative; + padding: 0; + margin: 0; + width: 100%; + list-style: none; + overflow: hidden; + transition: var(--mdb-steps-transition) +} + +.stepper-vertical .stepper-step,.steps-step,.timeline-step { + --mdb-steps-step-after-left: 2.45rem; + --mdb-steps-step-after-width: 1px; + --mdb-steps-step-after-margin-top: 0.5rem; + --mdb-steps-step-after-bg: #dfdfdf; + height: -webkit-fit-content; + height: -moz-fit-content; + height: fit-content; + position: relative +} + +.stepper-vertical .stepper-step:not(:last-child):after,.steps-step-after,.timeline-step:after { + position: absolute; + left: var(--mdb-steps-step-after-left); + width: var(--mdb-steps-step-after-width); + margin-top: var(--mdb-steps-step-after-margin-top); + content: ""; + background-color: var(--mdb-steps-step-after-bg) +} + +.stepper-vertical .stepper-content,.steps-content,.timeline-content { + --mdb-steps-content-padding-y: 1.5rem; + overflow: hidden; + padding-top: 0; + padding-bottom: var(--mdb-steps-content-padding-y); + padding-right: var(--mdb-steps-content-padding-y) +} + +.stepper-vertical .stepper-head,.steps-head-vertical,.timeline-head { + --mdb-steps-head-vertical-padding-top: 1.5rem; + --mdb-steps-head-vertical-padding-x: 1.5rem; + padding-left: var(--mdb-steps-head-vertical-padding-x); + padding-right: var(--mdb-steps-head-vertical-padding-x); + padding-top: var(--mdb-steps-head-vertical-padding-top) +} + +.stepper-vertical .stepper-head-icon,.steps-head-icon-vertical,.timeline-head-icon { + --mdb-steps-head-icon-vertical-margin-right: 0.75rem; + margin-right: var(--mdb-steps-head-icon-vertical-margin-right) +} + +.stepper-vertical .stepper-head-text:after,.steps-head-text-after-vertical { + position: absolute +} + +.stepper-head,.steps-head,.timeline-head { + --mdb-steps-head-line-height: 1.3; + --mdb-steps-head-hover-bgc: rgba(0,0,0,0.025); + display: flex; + align-items: center; + text-decoration: none; + color: unset; + line-height: var(--mdb-steps-head-line-height) +} + +.stepper-head:hover,.steps-head-hover { + background-color: var(--mdb-steps-head-hover-bgc) +} + +.stepper-head:focus,.steps-head-focus { + outline: none +} + +.stepper-head-text,.steps-head-text,.timeline-head-text { + --mdb-steps-head-text-color: #757575; + --mdb-steps-head-text-after-font-size: 0.8rem; + color: var(--mdb-steps-head-text-color) +} + +.stepper-head-text:after,.steps-head-text-after,.timeline-head-text:after { + display: flex; + font-size: var(--mdb-steps-head-text-after-font-size); + content: attr(data-content) +} + +.stepper-head-icon,.steps-head-icon,.timeline-head-icon { + --mdb-steps-head-icon-font-size: 0.875rem; + --mdb-steps-head-icon-width: 1.938rem; + --mdb-steps-head-icon-height: 1.938rem; + --mdb-steps-head-icon-font-weight: 500; + display: flex; + justify-content: center; + align-items: center; + border-radius: 100%; + font-size: var(--mdb-steps-head-icon-font-size); + width: var(--mdb-steps-head-icon-width); + height: var(--mdb-steps-head-icon-height); + font-weight: var(--mdb-steps-head-icon-font-weight) +} + +.stepper-active .stepper-head-text,.steps-active-head-text,.timeline-head-text { + --mdb-steps-active-head-text-font-weight: 500; + font-weight: var(--mdb-steps-active-head-text-font-weight) +} + +.stepper { + --mdb-stepper-padding-x: 1rem; + --mdb-stepper-step-height: 4.5rem; + --mdb-stepper-step-head-padding-left: 1.5rem; + --mdb-stepper-step-head-padding-right: 1.5rem; + --mdb-stepper-step-head-height: 1px; + --mdb-stepper-step-head-bg: rgba(0,0,0,0.1); + --mdb-stepper-step-head-margin-right: 0.5rem; + --mdb-stepper-step-head-margin-left: 0.5rem; + --mdb-stepper-head-icon-margin-y: 1.5rem; + --mdb-stepper-head-icon-margin-right: 0.5rem; + --mdb-stepper-vertical-step-top: 3.25rem; + --mdb-stepper-vertical-step-height: calc(100% - 2.45rem); + --mdb-stepper-vertical-content-padding-left: 3.75rem; + --mdb-stepper-vertical-content-transition: height 0.3s ease-in-out,margin-top 0.3s ease-in-out,margin-bottom 0.3s ease-in-out,padding-top 0.3s ease-in-out,padding-bottom 0.3s ease-in-out; + --mdb-stepper-vertical-head-padding-bottom: 1.5rem; + --mdb-stepper-mobile-step-margin-y: 1rem; + --mdb-stepper-mobile-step-head-padding-x: 0.25rem; + --mdb-stepper-mobile-head-icon-height: 0.5rem; + --mdb-stepper-mobile-head-icon-width: 0.5rem; + --mdb-stepper-mobile-content-top: 2.56rem; + --mdb-stepper-mobile-active-head-icon-bg: #376fc8; + --mdb-stepper-mobile-completed-head-icon-bg: #139647; + --mdb-stepper-head-icon-bg: #ebedef; + --mdb-stepper-head-icon-color: #40464f; + --mdb-stepper-completed-head-icon-bg: #d6f0e0; + --mdb-stepper-completed-head-icon-color: #0d6832; + --mdb-stepper-active-head-icon-bg: #dfe7f6; + --mdb-stepper-active-head-icon-color: #2c58a0; + --mdb-stepper-invalid-head-icon-bg: #f9e1e5; + --mdb-stepper-invalid-head-icon-color: #af233a; + --mdb-stepper-disabled-head-color: grey; + --mdb-stepper-disabled-head-icon-bg: #e6e6e6; + --mdb-stepper-disabled-head-icon-color: grey; + --mdb-stepper-mobile-head-padding-y: 0.5rem; + --mdb-stepper-mobile-head-padding-x: 1rem; + --mdb-stepper-mobile-footer-height: 2.5rem; + --mdb-stepper-back-btn-i-margin-right: 0.5rem; + --mdb-stepper-next-btn-i-margin-left: 0.5rem; + --mdb-stepper-mobile-progress-bar-height: 0.3rem; + --mdb-stepper-mobile-progress-height: 0.3rem; + --mdb-stepper-mobile-progress-background-color: #e0e0e0 +} + +.stepper:not(.stepper-vertical) { + display: flex; + justify-content: space-between +} + +.stepper:not(.stepper-vertical) .stepper-content { + position: absolute; + width: 100%; + padding-right: var(--mdb-stepper-padding-x); + padding-left: var(--mdb-stepper-padding-x) +} + +.stepper:not(.stepper-vertical) .stepper-step { + flex: auto; + height: var(--mdb-stepper-step-height) +} + +.stepper:not(.stepper-vertical) .stepper-step:first-child .stepper-head { + padding-left: var(--mdb-stepper-step-head-padding-left) +} + +.stepper:not(.stepper-vertical) .stepper-step:last-child .stepper-head { + padding-right: var(--mdb-stepper-step-head-padding-right) +} + +.stepper:not(.stepper-vertical) .stepper-step:not(:first-child) .stepper-head:before { + flex: 1; + height: var(--mdb-stepper-step-head-height); + width: 100%; + margin-right: var(--mdb-stepper-step-head-margin-right); + content: ""; + background-color: var(--mdb-stepper-step-head-bg) +} + +.stepper:not(.stepper-vertical) .stepper-step:not(:last-child) .stepper-head:after { + flex: 1; + height: var(--mdb-stepper-step-head-height); + width: 100%; + margin-left: var(--mdb-stepper-step-head-margin-left); + content: ""; + background-color: var(--mdb-stepper-step-head-bg) +} + +.stepper:not(.stepper-vertical) .stepper-head-icon { + margin-top: var(--mdb-stepper-head-icon-margin-y); + margin-right: var(--mdb-stepper-head-icon-margin-right); + margin-bottom: var(--mdb-stepper-head-icon-margin-y); + margin-left: 0 +} + +.stepper-vertical .stepper-step:not(:last-child):after { + top: var(--mdb-stepper-vertical-step-top); + height: var(--mdb-stepper-vertical-step-height) +} + +.stepper-vertical .stepper-content { + padding-left: var(--mdb-stepper-vertical-content-padding-left); + transition: var(--mdb-stepper-vertical-content-transition) +} + +.stepper-vertical .stepper-content-hide { + margin-top: 0!important; + margin-bottom: 0!important; + padding-top: 0!important; + padding-bottom: 0!important; + height: 0!important +} + +.stepper-vertical .stepper-head { + padding-bottom: var(--mdb-stepper-vertical-head-padding-bottom) +} + +.stepper.stepper-mobile { + justify-content: center; + align-items: flex-end +} + +.stepper.stepper-mobile.stepper-progress-bar .stepper-head-icon { + display: none +} + +.stepper.stepper-mobile .stepper-step { + flex: unset; + height: -webkit-fit-content; + height: -moz-fit-content; + height: fit-content; + margin-top: var(--mdb-stepper-mobile-step-margin-y); + margin-bottom: var(--mdb-stepper-mobile-step-margin-y) +} + +.stepper.stepper-mobile .stepper-step:not(:last-child) .stepper-head:after { + margin-left: 0 +} + +.stepper.stepper-mobile .stepper-step:not(:first-child) .stepper-head:before { + margin-right: 0 +} + +.stepper.stepper-mobile .stepper-step:not(:last-child):not(:first-child) .stepper-head { + padding-left: var(--mdb-stepper-mobile-step-head-padding-x); + padding-right: var(--mdb-stepper-mobile-step-head-padding-x) +} + +.stepper.stepper-mobile .stepper-head-icon { + font-size: 0; + margin: 0; + height: var(--mdb-stepper-mobile-head-icon-height); + width: var(--mdb-stepper-mobile-head-icon-width); + z-index: 1 +} + +.stepper.stepper-mobile .stepper-head-text { + display: none +} + +.stepper.stepper-mobile .stepper-content { + top: var(--mdb-stepper-mobile-content-top) +} + +.stepper.stepper-mobile .stepper-active .stepper-head-icon { + background-color: var(--mdb-stepper-mobile-active-head-icon-bg) +} + +.stepper.stepper-mobile .stepper-completed .stepper-head-icon { + background-color: var(--mdb-stepper-mobile-completed-head-icon-bg) +} + +.stepper-form { + display: inherit; + justify-content: inherit; + width: inherit; + position: inherit +} + +.stepper-content { + left: 0 +} + +.stepper-head { + cursor: pointer +} + +.stepper-head-icon { + background-color: var(--mdb-stepper-head-icon-bg); + color: var(--mdb-stepper-head-icon-color) +} + +.stepper-completed .stepper-head-icon { + background-color: var(--mdb-stepper-completed-head-icon-bg); + color: var(--mdb-stepper-completed-head-icon-color) +} + +.stepper-active .stepper-content { + display: block +} + +.stepper-active .stepper-head-icon { + background-color: var(--mdb-stepper-active-head-icon-bg); + color: var(--mdb-stepper-active-head-icon-color) +} + +.stepper-invalid .stepper-head-icon { + background-color: var(--mdb-stepper-invalid-head-icon-bg); + color: var(--mdb-stepper-invalid-head-icon-color) +} + +.stepper-disabled .stepper-head { + color: var(--mdb-stepper-disabled-head-color); + cursor: default +} + +.stepper-disabled .stepper-head-icon { + background-color: var(--mdb-stepper-disabled-head-icon-bg); + color: var(--mdb-stepper-disabled-head-icon-color) +} + +.stepper-mobile-head { + position: absolute; + align-self: normal; + height: -webkit-fit-content; + height: -moz-fit-content; + height: fit-content; + width: 100%; + padding: var(--mdb-stepper-mobile-head-padding-y) var(--mdb-stepper-mobile-head-padding-x) +} + +.stepper-mobile-footer { + position: absolute; + display: flex; + justify-content: space-between; + align-items: center; + width: 100%; + height: var(--mdb-stepper-mobile-footer-height) +} + +.stepper-back-btn { + display: block; + left: 0 +} + +.stepper-back-btn .btn-link { + color: unset +} + +.stepper-back-btn i { + margin-right: var(--mdb-stepper-back-btn-i-margin-right) +} + +.stepper-next-btn { + display: block; + right: 0 +} + +.stepper-next-btn .btn-link { + color: unset +} + +.stepper-next-btn i { + margin-left: var(--mdb-stepper-next-btn-i-margin-left) +} + +.stepper-mobile-progress-bar { + height: var(--mdb-stepper-mobile-progress-bar-height); + width: 0 +} + +.stepper-mobile-progress { + height: var(--mdb-stepper-mobile-progress-height); + flex-grow: 100; + background-color: var(--mdb-stepper-mobile-progress-background-color) +} + +.timeline { + --mdb-timeline-step-top: 2.94rem; + --mdb-timeline-step-height: calc(100% - 1.94rem); + --mdb-timeline-content-padding-left: 4.25rem; + --mdb-timeline-head-padding-bottom: 0.5rem; + --mdb-timeline-step-sm-left: 1.8rem; + --mdb-timeline-step-sm-top: 2rem; + --mdb-timeline-head-sm-margin-right: 1rem; + --mdb-timeline-head-sm-bg: #dfdfdf; + --mdb-timeline-head-sm-height: 0.7rem; + --mdb-timeline-head-sm-width: 0.7rem; + --mdb-timeline-content-sm-padding-left: 3.25rem +} + +.timeline-step:after { + top: var(--mdb-timeline-step-top); + height: var(--mdb-timeline-step-height) +} + +.timeline-content { + padding-left: var(--mdb-timeline-content-padding-left) +} + +.timeline-head { + padding-bottom: var(--mdb-timeline-head-padding-bottom) +} + +.timeline-step-sm:after { + left: var(--mdb-timeline-step-sm-left); + height: 100%; + top: var(--mdb-timeline-step-sm-top) +} + +.timeline-head-sm { + margin-right: var(--mdb-timeline-head-sm-margin-right); + background-color: var(--mdb-timeline-head-sm-bg); + border-radius: 100%; + height: var(--mdb-timeline-head-sm-height); + width: var(--mdb-timeline-head-sm-width) +} + +.timeline-content-sm { + padding-left: var(--mdb-timeline-content-sm-padding-left) +} + +.select-dropdown .form-check-input label { + display: block +} + +select.select-initialized { + display: none!important +} + +.select-wrapper { + --mdb-form-outline-select-arrow-color: #000; + --mdb-form-outline-select-arrow-font-size: 16px; + --mdb-form-outline-select-arrow-top: 7px; + --mdb-form-outline-select-arrow-right: 16px; + --mdb-form-outline-select-valid-color: #00b74a; + --mdb-form-outline-select-invalid-color: #f93154; + --mdb-form-outline-select-clear-btn-color: #000; + --mdb-form-outline-select-clear-btn-font-size: 1rem; + --mdb-form-outline-select-clear-btn-top: 7px; + --mdb-form-outline-select-clear-btn-right: 27px; + --mdb-form-outline-select-clear-btn-focus-color: #3b71ca; + --mdb-form-outline-select-sm-clear-btn-font-size: 0.8rem; + --mdb-form-outline-select-sm-clear-btn-top: 4px; + --mdb-form-outline-select-lg-clear-btn-top: 11px; + --mdb-form-outline-select-label-max-width: 80%; + --mdb-form-outline-select-label-active-transform: translateY(-1rem) translateY(0.1rem) scale(0.8); + --mdb-form-outline-select-lg-label-active-transform: translateY(-1.25rem) translateY(0.1rem) scale(0.8); + --mdb-form-outline-select-sm-label-active-transform: translateY(-0.83rem) translateY(0.1rem) scale(0.8); + --mdb-form-outline-select-input-focused-color: #616161; + --mdb-form-outline-select-label-color: #3b71ca; + --mdb-form-outline-select-notch-border-color: #3b71ca; + --mdb-form-outline-select-white-notch-border-color: #fff; + --mdb-form-outline-select-input-focused-arrow-color: #3b71ca; + --mdb-form-outline-select-white-focus-arrow-color: #fff; + --mdb-form-outline-select-white-arrow-color: #fff; + --mdb-form-outline-select-white-clear-btn: #fff; + --mdb-form-outline-select-sm-arrow-top: 3px; + --mdb-form-outline-select-lg-arrow-top: 11px; + --mdb-form-outline-form-notch-border-top: 1px solid transparent +} + +.select-arrow { + color: var(--mdb-form-outline-select-arrow-color); + text-align: center; + font-size: var(--mdb-form-outline-select-arrow-font-size); + position: absolute; + top: var(--mdb-form-outline-select-arrow-top); + right: var(--mdb-form-outline-select-arrow-right) +} + +.select-arrow:after { + display: inline-block; + margin-left: .255em; + vertical-align: .255em; + content: ""; + border-top: .3em solid; + border-right: .3em solid transparent; + border-bottom: 0; + border-left: .3em solid transparent +} + +.select-arrow:empty:after { + margin-left: 0 +} + +.was-validated .form-control:valid~.select-arrow { + color: var(--mdb-form-outline-select-valid-color) +} + +.was-validated .form-control:invalid~.select-arrow { + color: var(--mdb-form-outline-select-invalid-color) +} + +.select-clear-btn { + color: var(--mdb-form-outline-select-clear-btn-color); + font-size: var(--mdb-form-outline-select-clear-btn-font-size); + position: absolute; + top: var(--mdb-form-outline-select-clear-btn-top); + right: var(--mdb-form-outline-select-clear-btn-right); + cursor: pointer +} + +.select-clear-btn:focus { + color: var(--mdb-form-outline-select-clear-btn-focus-color); + outline: none +} + +.form-control-sm~.select-clear-btn { + font-size: var(--mdb-form-outline-select-sm-clear-btn-font-size); + top: var(--mdb-form-outline-select-sm-clear-btn-top) +} + +.form-control-lg~.select-clear-btn { + top: var(--mdb-form-outline-select-lg-clear-btn-top) +} + +.select-dropdown-container { + --mdb-form-outline-select-dropdown-container-z-index: 1070; + --mdb-form-outline-select-dropdown-bg: #fff; + --mdb-form-outline-select-dropdown-box-shadow: 0 2px 5px 0 rgba(0,0,0,0.16),0 2px 10px 0 rgba(0,0,0,0.12); + --mdb-form-outline-select-dropdown-min-width: 100px; + --mdb-form-outline-select-dropdown-transform: scaleY(0.8); + --mdb-form-outline-select-dropdown-transition: all 0.2s; + --mdb-form-outline-select-dropdown-open-transform: scaleY(1); + --mdb-form-outline-select-dropdown-input-group-padding: 10px; + --mdb-form-outline-select-options-wrapper-scrollbar-width: 4px; + --mdb-form-outline-select-options-wrapper-scrollbar-height: 4px; + --mdb-form-outline-select-options-wrapper-scrollbar-border-bottom-right-radius: 4px; + --mdb-form-outline-select-options-wrapper-scrollbar-border-bottom-left-radius: 4px; + --mdb-form-outline-select-options-wrapper-scrollbar-thumb-height: 50px; + --mdb-form-outline-select-options-wrapper-scrollbar-thumb-bg: #999; + --mdb-form-outline-select-options-wrapper-scrollbar-thumb-border-radius: 4px; + --mdb-form-outline-select-no-results-padding-left: 16px; + --mdb-form-outline-select-no-results-padding-right: 16px; + z-index: var(--mdb-form-outline-select-dropdown-container-z-index) +} + +.select-dropdown { + background-color: var(--mdb-form-outline-select-dropdown-bg); + box-shadow: var(--mdb-form-outline-select-dropdown-box-shadow); + margin: 0; + min-width: var(--mdb-form-outline-select-dropdown-min-width); + outline: 0; + position: relative; + transform: var(--mdb-form-outline-select-dropdown-transform); + opacity: 0; + transition: var(--mdb-form-outline-select-dropdown-transition) +} + +.select-dropdown.open { + transform: var(--mdb-form-outline-select-dropdown-open-transform); + opacity: 1 +} + +.select-dropdown>.input-group { + padding: var(--mdb-form-outline-select-dropdown-input-group-padding) +} + +.select-label { + max-width: var(--mdb-form-outline-select-label-max-width); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap +} + +.select-label.active { + transform: var(--mdb-form-outline-select-label-active-transform) +} + +.form-control-lg~.select-label.active { + transform: var(--mdb-form-outline-select-lg-label-active-transform) +} + +.form-control-sm~.select-label.active { + transform: var(--mdb-form-outline-select-sm-label-active-transform) +} + +.form-outline .select-label.active~.form-notch .form-notch-middle { + border-right: none; + border-left: none; + border-top: var(--mdb-form-outline-form-notch-border-top) +} + +.select-input { + cursor: pointer +} + +.select-input[disabled] { + cursor: default +} + +.form-outline .form-control.select-input:focus,.select-input.focused { + color: var(--mdb-form-outline-select-input-focused-color); + outline: 0 +} + +.form-outline .form-control.select-input:focus~.select-label,.select-input.focused~.select-label { + color: var(--mdb-form-outline-select-label-color) +} + +.form-outline .form-control.select-input:focus::-moz-placeholder,.select-input.focused::-moz-placeholder { + opacity: 1 +} + +.form-outline .form-control.select-input:focus::placeholder,.select-input.focused::placeholder { + opacity: 1 +} + +.form-outline .form-control.select-input:focus~.form-notch .form-notch-leading,.select-input.focused~.form-notch .form-notch-leading { + border-color: var(--mdb-form-outline-select-notch-border-color); + box-shadow: -1px 0 0 0 var(--mdb-form-outline-select-notch-border-color),0 1px 0 0 var(--mdb-form-outline-select-notch-border-color),0 -1px 0 0 var(--mdb-form-outline-select-notch-border-color) +} + +.form-outline .form-control.select-input:focus~.form-notch .form-notch-trailing,.select-input.focused~.form-notch .form-notch-trailing { + border-color: var(--mdb-form-outline-select-notch-border-color); + box-shadow: 1px 0 0 0 var(--mdb-form-outline-select-notch-border-color),0 -1px 0 0 var(--mdb-form-outline-select-notch-border-color),0 1px 0 0 var(--mdb-form-outline-select-notch-border-color) +} + +.select-input.focused~.form-notch .form-notch-middle { + border-top: var(--mdb-form-outline-form-notch-border-top); + border-color: var(--mdb-form-outline-select-notch-border-color); + box-shadow: 0 1px 0 0 var(--mdb-form-outline-select-notch-border-color) +} + +.select-input.focused~.select-arrow { + color: var(--mdb-form-outline-select-input-focused-arrow-color) +} + +.form-control-sm~.select-arrow { + top: var(--mdb-form-outline-select-sm-arrow-top) +} + +.form-control-lg~.select-arrow { + top: var(--mdb-form-outline-select-lg-arrow-top) +} + +.select-options-wrapper { + overflow-y: auto +} + +.select-options-wrapper::-webkit-scrollbar { + width: var(--mdb-form-outline-select-options-wrapper-scrollbar-width); + height: var(--mdb-form-outline-select-options-wrapper-scrollbar-height) +} + +.select-options-wrapper::-webkit-scrollbar-button:end:increment,.select-options-wrapper::-webkit-scrollbar-button:start:decrement { + display: block; + height: 0; + background-color: transparent +} + +.select-options-wrapper::-webkit-scrollbar-track-piece { + background-color: transparent; + border-radius: 0; + border-bottom-right-radius: var(--mdb-form-outline-select-options-wrapper-scrollbar-border-bottom-right-radius); + border-bottom-left-radius: var(--mdb-form-outline-select-options-wrapper-scrollbar-border-bottom-left-radius) +} + +.select-options-wrapper::-webkit-scrollbar-thumb:vertical { + height: var(--mdb-form-outline-select-options-wrapper-scrollbar-thumb-height); + background-color: var(--mdb-form-outline-select-options-wrapper-scrollbar-thumb-bg); + border-radius: var(--mdb-form-outline-select-options-wrapper-scrollbar-thumb-border-radius) +} + +.select-options-list { + list-style: none; + margin: 0; + padding: 0 +} + +.select-option-group-label { + --mdb-form-outline-select-option-group-label-padding-left: 16px; + --mdb-form-outline-select-option-group-label-padding-right: 16px; + --mdb-form-outline-select-option-group-label-font-size: 1rem; + --mdb-form-outline-select-option-group-label-font-weight: 400; + --mdb-form-outline-select-option-group-label-color: rgba(0,0,0,0.54); + width: 100%; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + display: flex; + flex-direction: row; + align-items: center; + padding-left: var(--mdb-form-outline-select-option-group-label-padding-left); + padding-right: var(--mdb-form-outline-select-option-group-label-padding-right); + font-size: var(--mdb-form-outline-select-option-group-label-font-size); + font-weight: var(--mdb-form-outline-select-option-group-label-font-weight); + background-color: transparent; + color: var(--mdb-form-outline-select-option-group-label-color); + -webkit-user-select: none; + -moz-user-select: none; + user-select: none +} + +.select-option-group>.select-option { + --mdb-form-outline-select-option-group-select-option-padding-left: 26px; + padding-left: var(--mdb-form-outline-select-option-group-select-option-padding-left) +} + +.select-option { + --mdb-form-outline-select-option-color: rgba(0,0,0,0.87); + --mdb-form-outline-select-option-padding-left: 16px; + --mdb-form-outline-select-option-padding-right: 16px; + --mdb-form-outline-select-option-font-size: 1rem; + --mdb-form-outline-select-option-font-weight: 400; + --mdb-form-outline-select-option-hover-not-disabled-bg: rgba(0,0,0,0.048); + --mdb-form-outline-select-option-active-bg: rgba(0,0,0,0.048); + --mdb-form-outline-select-option-selected-active-bg: rgba(0,0,0,0.048); + --mdb-form-outline-select-option-selected-disabled-color: #9e9e9e; + --mdb-form-outline-select-option-selected-bg: rgba(0,0,0,0.02); + --mdb-form-outline-select-option-disabled-color: #9e9e9e; + --mdb-form-outline-select-option-text-form-check-input-margin-right: 10px; + --mdb-form-outline-select-option-secondary-text-font-size: 0.8rem; + --mdb-form-outline-select-option-secondary-text-color: #6c757d; + --mdb-form-outline-select-option-icon-width: 28px; + --mdb-form-outline-select-option-icon-height: 28px; + --mdb-form-outline-select-white-arrow: #fff; + width: 100%; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + cursor: pointer; + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + color: var(--mdb-form-outline-select-option-color); + padding-left: var(--mdb-form-outline-select-option-padding-left); + padding-right: var(--mdb-form-outline-select-option-padding-right); + font-size: var(--mdb-form-outline-select-option-font-size); + font-weight: var(--mdb-form-outline-select-option-font-weight); + background-color: transparent; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none +} + +.select-option:hover:not(.disabled) { + background-color: var(--mdb-form-outline-select-option-hover-not-disabled-bg) +} + +.select-option.active { + background-color: var(--mdb-form-outline-select-option-active-bg) +} + +.select-option.selected.active { + background-color: var(--mdb-form-outline-select-option-selected-active-bg) +} + +.select-option.selected.disabled { + cursor: default; + color: var(--mdb-form-outline-select-option-selected-disabled-color); + background-color: transparent +} + +.select-option.selected { + background-color: var(--mdb-form-outline-select-option-selected-bg) +} + +.select-option.disabled { + cursor: default; + color: var(--mdb-form-outline-select-option-disabled-color) +} + +.select-option-text .form-check-input { + margin-right: var(--mdb-form-outline-select-option-text-form-check-input-margin-right) +} + +.select-option-secondary-text { + font-size: var(--mdb-form-outline-select-option-secondary-text-font-size); + color: var(--mdb-form-outline-select-option-secondary-text-color); + display: block; + line-height: normal +} + +.select-option-icon { + width: var(--mdb-form-outline-select-option-icon-width); + height: var(--mdb-form-outline-select-option-icon-height) +} + +.select-custom-content { + --mdb-form-outline-select-custom-content-padding: 16px; + padding: var(--mdb-form-outline-select-custom-content-padding) +} + +.select-no-results { + padding-left: var(--mdb-form-outline-select-no-results-padding-left); + padding-right: var(--mdb-form-outline-select-no-results-padding-right); + display: flex; + align-items: center +} + +.form-white .select-input.focused~.select-arrow { + color: var(--mdb-form-outline-select-white-arrow-color) +} + +.form-white .select-input:focus~.select-arrow { + color: var(--mdb-form-outline-select-white-focus-arrow-color) +} + +.form-white .select-arrow { + color: var(--mdb-form-outline-select-white-arrow-color) +} + +.form-white .select-clear-btn { + color: var(--mdb-form-outline-select-white-clear-btn) +} + +.form-white .form-control.select-input:focus,.form-white .form-control.select-input:focus~.select-label,.form-white .select-input.focused,.form-white .select-input.focused~.select-label { + color: #fff +} + +.form-white .form-control.select-input:focus~.form-notch .form-notch-leading,.form-white .select-input.focused~.form-notch .form-notch-leading { + border-color: var(--mdb-form-outline-select-white-notch-border-color); + box-shadow: -1px 0 0 0 var(--mdb-form-outline-select-white-notch-border-color),0 1px 0 0 var(--mdb-form-outline-select-white-notch-border-color),0 -1px 0 0 var(--mdb-form-outline-select-white-notch-border-color) +} + +.form-white .form-control.select-input:focus~.form-notch .form-notch-trailing,.form-white .select-input.focused~.form-notch .form-notch-trailing { + border-color: var(--mdb-form-outline-select-white-notch-border-color); + box-shadow: 1px 0 0 0 var(--mdb-form-outline-select-white-notch-border-color),0 -1px 0 0 var(--mdb-form-outline-select-white-notch-border-color),0 1px 0 0 var(--mdb-form-outline-select-white-notch-border-color) +} + +.form-outline .form-control.active~.form-label.select-fake-value,.form-outline .form-control:focus~.form-label.select-fake-value,.form-outline .form-control~.form-label.select-fake-value { + transform: none; + display: none +} + +.form-outline .form-control.active~.form-label.select-fake-value.active,.form-outline .form-control:focus~.form-label.select-fake-value.active,.form-outline .form-control~.form-label.select-fake-value.active { + display: block +} + +code[class*=language-],pre[class*=language-] { + color: #000; + background: none; + text-shadow: 0 1px #fff; + font-family: Consolas,Monaco,Andale Mono,Ubuntu Mono,monospace; + text-align: left; + white-space: pre; + word-spacing: normal; + word-break: normal; + word-wrap: normal; + line-height: 1.5; + -moz-tab-size: 4; + -o-tab-size: 4; + tab-size: 4; + -webkit-hyphens: none; + hyphens: none +} + +code[class*=language-]::-moz-selection,code[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection { + text-shadow: none; + background: #b3d4fc +} + +code[class*=language-]::selection,code[class*=language-] ::selection,pre[class*=language-]::selection,pre[class*=language-] ::selection { + text-shadow: none; + background: #b3d4fc +} + +@media print { + code[class*=language-],pre[class*=language-] { + text-shadow: none + } +} + +pre[class*=language-] { + padding: 1em; + margin: .5em 0; + overflow: auto +} + +:not(pre)>code[class*=language-],pre[class*=language-] { + background: #f5f2f0 +} + +:not(pre)>code[class*=language-] { + padding: .1em; + border-radius: .3em; + white-space: normal +} + +.token.cdata,.token.comment,.token.doctype,.token.prolog { + color: #708090 +} + +.token.punctuation { + color: #999 +} + +.namespace { + opacity: .7 +} + +.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag { + color: #905 +} + +.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string { + color: #690 +} + +.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url { + color: #9a6e3a; + background: hsla(0,0%,100%,.5) +} + +.token.atrule,.token.attr-value,.token.keyword { + color: #07a +} + +.token.class-name,.token.function { + color: #dd4a68 +} + +.token.important,.token.regex,.token.variable { + color: #e90 +} + +.token.bold,.token.important { + font-weight: 700 +} + +.token.italic { + font-style: italic +} + +.token.entity { + cursor: help +} + +pre.line-numbers { + padding-left: 3.8em +} + +.line-numbers .type-terminal .line-numbers-rows { + border-right: none; + top: -.2em +} + +.type-terminal .line-numbers-rows>span:before { + content: "$" +} + +.prism-previewer,.prism-previewer:after,.prism-previewer:before { + position: absolute; + pointer-events: none +} + +.prism-previewer,.prism-previewer:after { + left: 50% +} + +.prism-previewer { + margin-top: -48px; + width: 32px; + height: 32px; + margin-left: -16px; + opacity: 0; + transition: opacity .25s +} + +.prism-previewer.flipped { + margin-top: 0; + margin-bottom: -48px +} + +.prism-previewer:after,.prism-previewer:before { + content: ""; + position: absolute; + pointer-events: none +} + +.prism-previewer:before { + top: -5px; + right: -5px; + left: -5px; + bottom: -5px; + border-radius: 10px; + border: 5px solid #fff; + box-shadow: inset 0 0 3px rgba(0,0,0,.5),0 0 10px rgba(0,0,0,.75) +} + +.prism-previewer:after { + top: 100%; + width: 0; + height: 0; + margin: 5px 0 0 -7px; + border: 7px solid rgba(255,0,0,0); + border-top-color: #fff +} + +.prism-previewer.flipped:after { + top: auto; + bottom: 100%; + margin-top: 0; + margin-bottom: 5px; + border-top-color: rgba(255,0,0,0); + border-bottom-color: #fff +} + +.prism-previewer.active { + opacity: 1 +} + +.prism-previewer-angle:before { + border-radius: 50%; + background: #fff +} + +.prism-previewer-angle:after { + margin-top: 4px +} + +.prism-previewer-angle svg { + width: 32px; + height: 32px; + transform: rotate(-90deg) +} + +.prism-previewer-angle[data-negative] svg { + transform: scaleX(-1) rotate(-90deg) +} + +.prism-previewer-angle circle { + fill: transparent; + stroke: #2e3538; + stroke-opacity: .9; + stroke-width: 32; + stroke-dasharray: 0,500 +} + +.prism-previewer-gradient { + background-image: linear-gradient(45deg,#bbb 25%,transparent 0,transparent 75%,#bbb 0,#bbb),linear-gradient(45deg,#bbb 25%,#eee 0,#eee 75%,#bbb 0,#bbb); + background-size: 10px 10px; + background-position: 0 0,5px 5px; + width: 64px; + margin-left: -32px +} + +.prism-previewer-gradient:before { + content: none +} + +.prism-previewer-gradient div { + position: absolute; + top: -5px; + left: -5px; + right: -5px; + bottom: -5px; + border-radius: 10px; + border: 5px solid #fff; + box-shadow: inset 0 0 3px rgba(0,0,0,.5),0 0 10px rgba(0,0,0,.75) +} + +.prism-previewer-color { + background-image: linear-gradient(45deg,#bbb 25%,transparent 0,transparent 75%,#bbb 0,#bbb),linear-gradient(45deg,#bbb 25%,#eee 0,#eee 75%,#bbb 0,#bbb); + background-size: 10px 10px; + background-position: 0 0,5px 5px +} + +.prism-previewer-color:before { + background-color: inherit; + background-clip: padding-box +} + +.prism-previewer-easing { + margin-top: -76px; + margin-left: -30px; + width: 60px; + height: 60px; + background: #333 +} + +.prism-previewer-easing.flipped { + margin-bottom: -116px +} + +.prism-previewer-easing svg { + width: 60px; + height: 60px +} + +.prism-previewer-easing circle { + fill: #2e3538; + stroke: #fff +} + +.prism-previewer-easing path { + fill: none; + stroke: #fff; + stroke-linecap: round; + stroke-width: 4 +} + +.prism-previewer-easing line { + stroke: #fff; + stroke-opacity: .5; + stroke-width: 2 +} + +@keyframes prism-previewer-time { + 0% { + stroke-dasharray: 0,500; + stroke-dashoffset: 0 + } + + 50% { + stroke-dasharray: 100,500; + stroke-dashoffset: 0 + } + + to { + stroke-dasharray: 0,500; + stroke-dashoffset: -100 + } +} + +.prism-previewer-time:before { + border-radius: 50%; + background: #fff +} + +.prism-previewer-time:after { + margin-top: 4px +} + +.prism-previewer-time svg { + width: 32px; + height: 32px; + transform: rotate(-90deg) +} + +.prism-previewer-time circle { + fill: transparent; + stroke: #2e3538; + stroke-opacity: .9; + stroke-width: 32; + stroke-dasharray: 0,500; + stroke-dashoffset: 0; + animation: prism-previewer-time 3s linear infinite +} + +.docs-pills .d-flex.justify-content-between { + border-bottom: 1px solid #e0e0e0!important +} + +.docs-pills .nav { + border-bottom: 0!important +} + +.docs-pills .btn-group-sm>.btn[class*=btn-outline-],.docs-pills .btn.btn-sm[class*=btn-outline-] { + margin-top: .1rem!important; + padding-left: 1rem!important; + padding-right: 1rem!important +} + +.docs-pills .nav-pills .nav-link { + padding: 10px 20px; + margin: 0 5px +} + +.docs-pills .nav-item .active { + background-color: #e3ebf7!important; + color: #285192!important +} + +.docs-pills .tab-content { + padding: 0 +} + +.docs-pills .btn-copy-code,.docs-pills .export-to-snippet { + position: absolute; + top: 9px; + right: 8px; + color: #616162!important; + padding: 6px 15px!important +} + +.docs-pills { + position: relative!important +} + +.docs-pills pre[class*=language-] { + margin-top: 0 +} + +pre.line-numbers { + position: relative; + padding-left: 3.8em!important; + counter-reset: linenumber +} + +pre.line-numbers>code { + position: relative; + white-space: inherit +} + +.line-numbers .line-numbers-rows { + position: absolute; + pointer-events: none; + top: 0; + font-size: 100%; + left: -3.8em; + width: 3em; + letter-spacing: -1px; + border-right: 1px solid #999; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none +} + +.line-numbers-rows>span { + pointer-events: none; + display: block; + counter-increment: linenumber +} + +.line-numbers-rows>span:before { + content: counter(linenumber); + color: #999; + display: block; + padding-right: .8em; + text-align: right +} + +.code-toolbar { + margin: 0 +} + +code[class*=language-],pre[class*=language-] { + max-height: 450px +} + +#mdb-footer { + padding-left: 240px +} + +@media(max-width: 1439px) { + #mdb-footer { + padding-left:0 + } +} + +#mdb-intro { + padding-left: 240px; + margin-top: 58.51px +} + +@media(max-width: 1439px) { + #mdb-intro { + padding-left:0 + } +} diff --git a/test_web/static/js/bootstrap.min.js b/test_web/static/js/bootstrap.min.js new file mode 100644 index 0000000..a2eac27 --- /dev/null +++ b/test_web/static/js/bootstrap.min.js @@ -0,0 +1,18 @@ +/*! + * Bootstrap v4.3.1 (https://getbootstrap.com/) + * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("jquery"),require("popper.js")):"function"==typeof define&&define.amd?define(["exports","jquery","popper.js"],e):e((t=t||self).bootstrap={},t.jQuery,t.Popper)}(this,function(t,g,u){"use strict";function i(t,e){for(var n=0;nthis._items.length-1||t<0))if(this._isSliding)g(this._element).one(Q.SLID,function(){return e.to(t)});else{if(n===t)return this.pause(),void this.cycle();var i=ndocument.documentElement.clientHeight;!this._isBodyOverflowing&&t&&(this._element.style.paddingLeft=this._scrollbarWidth+"px"),this._isBodyOverflowing&&!t&&(this._element.style.paddingRight=this._scrollbarWidth+"px")},t._resetAdjustments=function(){this._element.style.paddingLeft="",this._element.style.paddingRight=""},t._checkScrollbar=function(){var t=document.body.getBoundingClientRect();this._isBodyOverflowing=t.left+t.right
',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:0,container:!1,fallbackPlacement:"flip",boundary:"scrollParent",sanitize:!0,sanitizeFn:null,whiteList:Ee},je="show",He="out",Re={HIDE:"hide"+De,HIDDEN:"hidden"+De,SHOW:"show"+De,SHOWN:"shown"+De,INSERTED:"inserted"+De,CLICK:"click"+De,FOCUSIN:"focusin"+De,FOCUSOUT:"focusout"+De,MOUSEENTER:"mouseenter"+De,MOUSELEAVE:"mouseleave"+De},xe="fade",Fe="show",Ue=".tooltip-inner",We=".arrow",qe="hover",Me="focus",Ke="click",Qe="manual",Be=function(){function i(t,e){if("undefined"==typeof u)throw new TypeError("Bootstrap's tooltips require Popper.js (https://popper.js.org/)");this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this.element=t,this.config=this._getConfig(e),this.tip=null,this._setListeners()}var t=i.prototype;return t.enable=function(){this._isEnabled=!0},t.disable=function(){this._isEnabled=!1},t.toggleEnabled=function(){this._isEnabled=!this._isEnabled},t.toggle=function(t){if(this._isEnabled)if(t){var e=this.constructor.DATA_KEY,n=g(t.currentTarget).data(e);n||(n=new this.constructor(t.currentTarget,this._getDelegateConfig()),g(t.currentTarget).data(e,n)),n._activeTrigger.click=!n._activeTrigger.click,n._isWithActiveTrigger()?n._enter(null,n):n._leave(null,n)}else{if(g(this.getTipElement()).hasClass(Fe))return void this._leave(null,this);this._enter(null,this)}},t.dispose=function(){clearTimeout(this._timeout),g.removeData(this.element,this.constructor.DATA_KEY),g(this.element).off(this.constructor.EVENT_KEY),g(this.element).closest(".modal").off("hide.bs.modal"),this.tip&&g(this.tip).remove(),this._isEnabled=null,this._timeout=null,this._hoverState=null,(this._activeTrigger=null)!==this._popper&&this._popper.destroy(),this._popper=null,this.element=null,this.config=null,this.tip=null},t.show=function(){var e=this;if("none"===g(this.element).css("display"))throw new Error("Please use show on visible elements");var t=g.Event(this.constructor.Event.SHOW);if(this.isWithContent()&&this._isEnabled){g(this.element).trigger(t);var n=_.findShadowRoot(this.element),i=g.contains(null!==n?n:this.element.ownerDocument.documentElement,this.element);if(t.isDefaultPrevented()||!i)return;var o=this.getTipElement(),r=_.getUID(this.constructor.NAME);o.setAttribute("id",r),this.element.setAttribute("aria-describedby",r),this.setContent(),this.config.animation&&g(o).addClass(xe);var s="function"==typeof this.config.placement?this.config.placement.call(this,o,this.element):this.config.placement,a=this._getAttachment(s);this.addAttachmentClass(a);var l=this._getContainer();g(o).data(this.constructor.DATA_KEY,this),g.contains(this.element.ownerDocument.documentElement,this.tip)||g(o).appendTo(l),g(this.element).trigger(this.constructor.Event.INSERTED),this._popper=new u(this.element,o,{placement:a,modifiers:{offset:this._getOffset(),flip:{behavior:this.config.fallbackPlacement},arrow:{element:We},preventOverflow:{boundariesElement:this.config.boundary}},onCreate:function(t){t.originalPlacement!==t.placement&&e._handlePopperPlacementChange(t)},onUpdate:function(t){return e._handlePopperPlacementChange(t)}}),g(o).addClass(Fe),"ontouchstart"in document.documentElement&&g(document.body).children().on("mouseover",null,g.noop);var c=function(){e.config.animation&&e._fixTransition();var t=e._hoverState;e._hoverState=null,g(e.element).trigger(e.constructor.Event.SHOWN),t===He&&e._leave(null,e)};if(g(this.tip).hasClass(xe)){var h=_.getTransitionDurationFromElement(this.tip);g(this.tip).one(_.TRANSITION_END,c).emulateTransitionEnd(h)}else c()}},t.hide=function(t){var e=this,n=this.getTipElement(),i=g.Event(this.constructor.Event.HIDE),o=function(){e._hoverState!==je&&n.parentNode&&n.parentNode.removeChild(n),e._cleanTipClass(),e.element.removeAttribute("aria-describedby"),g(e.element).trigger(e.constructor.Event.HIDDEN),null!==e._popper&&e._popper.destroy(),t&&t()};if(g(this.element).trigger(i),!i.isDefaultPrevented()){if(g(n).removeClass(Fe),"ontouchstart"in document.documentElement&&g(document.body).children().off("mouseover",null,g.noop),this._activeTrigger[Ke]=!1,this._activeTrigger[Me]=!1,this._activeTrigger[qe]=!1,g(this.tip).hasClass(xe)){var r=_.getTransitionDurationFromElement(n);g(n).one(_.TRANSITION_END,o).emulateTransitionEnd(r)}else o();this._hoverState=""}},t.update=function(){null!==this._popper&&this._popper.scheduleUpdate()},t.isWithContent=function(){return Boolean(this.getTitle())},t.addAttachmentClass=function(t){g(this.getTipElement()).addClass(Ae+"-"+t)},t.getTipElement=function(){return this.tip=this.tip||g(this.config.template)[0],this.tip},t.setContent=function(){var t=this.getTipElement();this.setElementContent(g(t.querySelectorAll(Ue)),this.getTitle()),g(t).removeClass(xe+" "+Fe)},t.setElementContent=function(t,e){"object"!=typeof e||!e.nodeType&&!e.jquery?this.config.html?(this.config.sanitize&&(e=Se(e,this.config.whiteList,this.config.sanitizeFn)),t.html(e)):t.text(e):this.config.html?g(e).parent().is(t)||t.empty().append(e):t.text(g(e).text())},t.getTitle=function(){var t=this.element.getAttribute("data-original-title");return t||(t="function"==typeof this.config.title?this.config.title.call(this.element):this.config.title),t},t._getOffset=function(){var e=this,t={};return"function"==typeof this.config.offset?t.fn=function(t){return t.offsets=l({},t.offsets,e.config.offset(t.offsets,e.element)||{}),t}:t.offset=this.config.offset,t},t._getContainer=function(){return!1===this.config.container?document.body:_.isElement(this.config.container)?g(this.config.container):g(document).find(this.config.container)},t._getAttachment=function(t){return Pe[t.toUpperCase()]},t._setListeners=function(){var i=this;this.config.trigger.split(" ").forEach(function(t){if("click"===t)g(i.element).on(i.constructor.Event.CLICK,i.config.selector,function(t){return i.toggle(t)});else if(t!==Qe){var e=t===qe?i.constructor.Event.MOUSEENTER:i.constructor.Event.FOCUSIN,n=t===qe?i.constructor.Event.MOUSELEAVE:i.constructor.Event.FOCUSOUT;g(i.element).on(e,i.config.selector,function(t){return i._enter(t)}).on(n,i.config.selector,function(t){return i._leave(t)})}}),g(this.element).closest(".modal").on("hide.bs.modal",function(){i.element&&i.hide()}),this.config.selector?this.config=l({},this.config,{trigger:"manual",selector:""}):this._fixTitle()},t._fixTitle=function(){var t=typeof this.element.getAttribute("data-original-title");(this.element.getAttribute("title")||"string"!==t)&&(this.element.setAttribute("data-original-title",this.element.getAttribute("title")||""),this.element.setAttribute("title",""))},t._enter=function(t,e){var n=this.constructor.DATA_KEY;(e=e||g(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),g(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusin"===t.type?Me:qe]=!0),g(e.getTipElement()).hasClass(Fe)||e._hoverState===je?e._hoverState=je:(clearTimeout(e._timeout),e._hoverState=je,e.config.delay&&e.config.delay.show?e._timeout=setTimeout(function(){e._hoverState===je&&e.show()},e.config.delay.show):e.show())},t._leave=function(t,e){var n=this.constructor.DATA_KEY;(e=e||g(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),g(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusout"===t.type?Me:qe]=!1),e._isWithActiveTrigger()||(clearTimeout(e._timeout),e._hoverState=He,e.config.delay&&e.config.delay.hide?e._timeout=setTimeout(function(){e._hoverState===He&&e.hide()},e.config.delay.hide):e.hide())},t._isWithActiveTrigger=function(){for(var t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1},t._getConfig=function(t){var e=g(this.element).data();return Object.keys(e).forEach(function(t){-1!==Oe.indexOf(t)&&delete e[t]}),"number"==typeof(t=l({},this.constructor.Default,e,"object"==typeof t&&t?t:{})).delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),_.typeCheckConfig(be,t,this.constructor.DefaultType),t.sanitize&&(t.template=Se(t.template,t.whiteList,t.sanitizeFn)),t},t._getDelegateConfig=function(){var t={};if(this.config)for(var e in this.config)this.constructor.Default[e]!==this.config[e]&&(t[e]=this.config[e]);return t},t._cleanTipClass=function(){var t=g(this.getTipElement()),e=t.attr("class").match(Ne);null!==e&&e.length&&t.removeClass(e.join(""))},t._handlePopperPlacementChange=function(t){var e=t.instance;this.tip=e.popper,this._cleanTipClass(),this.addAttachmentClass(this._getAttachment(t.placement))},t._fixTransition=function(){var t=this.getTipElement(),e=this.config.animation;null===t.getAttribute("x-placement")&&(g(t).removeClass(xe),this.config.animation=!1,this.hide(),this.show(),this.config.animation=e)},i._jQueryInterface=function(n){return this.each(function(){var t=g(this).data(Ie),e="object"==typeof n&&n;if((t||!/dispose|hide/.test(n))&&(t||(t=new i(this,e),g(this).data(Ie,t)),"string"==typeof n)){if("undefined"==typeof t[n])throw new TypeError('No method named "'+n+'"');t[n]()}})},s(i,null,[{key:"VERSION",get:function(){return"4.3.1"}},{key:"Default",get:function(){return Le}},{key:"NAME",get:function(){return be}},{key:"DATA_KEY",get:function(){return Ie}},{key:"Event",get:function(){return Re}},{key:"EVENT_KEY",get:function(){return De}},{key:"DefaultType",get:function(){return ke}}]),i}();g.fn[be]=Be._jQueryInterface,g.fn[be].Constructor=Be,g.fn[be].noConflict=function(){return g.fn[be]=we,Be._jQueryInterface};var Ve="popover",Ye="bs.popover",ze="."+Ye,Xe=g.fn[Ve],$e="bs-popover",Ge=new RegExp("(^|\\s)"+$e+"\\S+","g"),Je=l({},Be.Default,{placement:"right",trigger:"click",content:"",template:''}),Ze=l({},Be.DefaultType,{content:"(string|element|function)"}),tn="fade",en="show",nn=".popover-header",on=".popover-body",rn={HIDE:"hide"+ze,HIDDEN:"hidden"+ze,SHOW:"show"+ze,SHOWN:"shown"+ze,INSERTED:"inserted"+ze,CLICK:"click"+ze,FOCUSIN:"focusin"+ze,FOCUSOUT:"focusout"+ze,MOUSEENTER:"mouseenter"+ze,MOUSELEAVE:"mouseleave"+ze},sn=function(t){var e,n;function i(){return t.apply(this,arguments)||this}n=t,(e=i).prototype=Object.create(n.prototype),(e.prototype.constructor=e).__proto__=n;var o=i.prototype;return o.isWithContent=function(){return this.getTitle()||this._getContent()},o.addAttachmentClass=function(t){g(this.getTipElement()).addClass($e+"-"+t)},o.getTipElement=function(){return this.tip=this.tip||g(this.config.template)[0],this.tip},o.setContent=function(){var t=g(this.getTipElement());this.setElementContent(t.find(nn),this.getTitle());var e=this._getContent();"function"==typeof e&&(e=e.call(this.element)),this.setElementContent(t.find(on),e),t.removeClass(tn+" "+en)},o._getContent=function(){return this.element.getAttribute("data-content")||this.config.content},o._cleanTipClass=function(){var t=g(this.getTipElement()),e=t.attr("class").match(Ge);null!==e&&0=this._offsets[o]&&("undefined"==typeof this._offsets[o+1]||t]+>/g,"")),d&&(j=f(j)),j=j.toUpperCase(),g="contains"===c?j.indexOf(b)>=0:j.startsWith(b)))break}return g}function e(a){return parseInt(a,10)||0}function f(b){var c=[{re:/[\xC0-\xC6]/g,ch:"A"},{re:/[\xE0-\xE6]/g,ch:"a"},{re:/[\xC8-\xCB]/g,ch:"E"},{re:/[\xE8-\xEB]/g,ch:"e"},{re:/[\xCC-\xCF]/g,ch:"I"},{re:/[\xEC-\xEF]/g,ch:"i"},{re:/[\xD2-\xD6]/g,ch:"O"},{re:/[\xF2-\xF6]/g,ch:"o"},{re:/[\xD9-\xDC]/g,ch:"U"},{re:/[\xF9-\xFC]/g,ch:"u"},{re:/[\xC7-\xE7]/g,ch:"c"},{re:/[\xD1]/g,ch:"N"},{re:/[\xF1]/g,ch:"n"}];return a.each(c,function(){b=b?b.replace(this.re,this.ch):""}),b}function g(b){var c=arguments,d=b;[].shift.apply(c);var e,f=this.each(function(){var b=a(this);if(b.is("select")){var f=b.data("selectpicker"),g="object"==typeof d&&d;if(f){if(g)for(var h in g)g.hasOwnProperty(h)&&(f.options[h]=g[h])}else{var i=a.extend({},x.DEFAULTS,a.fn.selectpicker.defaults||{},b.data(),g);i.template=a.extend({},x.DEFAULTS.template,a.fn.selectpicker.defaults?a.fn.selectpicker.defaults.template:{},b.data().template,g.template),b.data("selectpicker",f=new x(this,i))}"string"==typeof d&&(e=f[d]instanceof Function?f[d].apply(f,c):f.options[d])}});return void 0!==e?e:f}var h=document.createElement("_");if(h.classList.toggle("c3",!1),h.classList.contains("c3")){var i=DOMTokenList.prototype.toggle;DOMTokenList.prototype.toggle=function(a,b){return 1 in arguments&&!this.contains(a)==!b?b:i.call(this,a)}}String.prototype.startsWith||function(){var a=function(){try{var a={},b=Object.defineProperty,c=b(a,a,a)&&b}catch(a){}return c}(),b={}.toString,c=function(a){if(null==this)throw new TypeError;var c=String(this);if(a&&"[object RegExp]"==b.call(a))throw new TypeError;var d=c.length,e=String(a),f=e.length,g=arguments.length>1?arguments[1]:void 0,h=g?Number(g):0;h!=h&&(h=0);var i=Math.min(Math.max(h,0),d);if(f+i>d)return!1;for(var j=-1;++j":">",'"':""","'":"'","`":"`"},n={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},o=function(a){var b=function(b){return a[b]},c="(?:"+Object.keys(a).join("|")+")",d=RegExp(c),e=RegExp(c,"g");return function(a){return a=null==a?"":""+a,d.test(a)?a.replace(e,b):a}},p=o(m),q=o(n),r={32:" ",48:"0",49:"1",50:"2",51:"3",52:"4",53:"5",54:"6",55:"7",56:"8",57:"9",59:";",65:"A",66:"B",67:"C",68:"D",69:"E",70:"F",71:"G",72:"H",73:"I",74:"J",75:"K",76:"L",77:"M",78:"N",79:"O",80:"P",81:"Q",82:"R",83:"S",84:"T",85:"U",86:"V",87:"W",88:"X",89:"Y",90:"Z",96:"0",97:"1",98:"2",99:"3",100:"4",101:"5",102:"6",103:"7",104:"8",105:"9"},s={ESCAPE:27,ENTER:13,SPACE:32,TAB:9,ARROW_UP:38,ARROW_DOWN:40},t={};try{t.full=(a.fn.dropdown.Constructor.VERSION||"").split(" ")[0].split("."),t.major=t.full[0]}catch(a){console.error("There was an issue retrieving Bootstrap's version. Ensure Bootstrap is being loaded before bootstrap-select and there is no namespace collision.",a),t.major="3"}var u={DISABLED:"disabled",DIVIDER:"4"===t.major?"dropdown-divider":"divider",SHOW:"4"===t.major?"show":"open",DROPUP:"dropup",MENURIGHT:"dropdown-menu-right",MENULEFT:"dropdown-menu-left",BUTTONCLASS:"4"===t.major?"btn-light":"btn-default",POPOVERHEADER:"4"===t.major?"popover-header":"popover-title"},v=new RegExp(s.ARROW_UP+"|"+s.ARROW_DOWN),w=new RegExp("^"+s.TAB+"$|"+s.ESCAPE),x=(new RegExp(s.ENTER+"|"+s.SPACE),function(b,c){var d=this;j.useDefault||(a.valHooks.select.set=j._set,j.useDefault=!0),this.$element=a(b),this.$newElement=null,this.$button=null,this.$menu=null,this.options=c,this.selectpicker={main:{map:{newIndex:{},originalIndex:{}}},current:{map:{}},search:{map:{}},view:{},keydown:{keyHistory:"",resetKeyHistory:{start:function(){return setTimeout(function(){d.selectpicker.keydown.keyHistory=""},800)}}}},null===this.options.title&&(this.options.title=this.$element.attr("title"));var e=this.options.windowPadding;"number"==typeof e&&(this.options.windowPadding=[e,e,e,e]),this.val=x.prototype.val,this.render=x.prototype.render,this.refresh=x.prototype.refresh,this.setStyle=x.prototype.setStyle,this.selectAll=x.prototype.selectAll,this.deselectAll=x.prototype.deselectAll,this.destroy=x.prototype.destroy,this.remove=x.prototype.remove,this.show=x.prototype.show,this.hide=x.prototype.hide,this.init()});x.VERSION="1.13.1",x.DEFAULTS={noneSelectedText:"Nothing selected",noneResultsText:"No results matched {0}",countSelectedText:function(a,b){return 1==a?"{0} item selected":"{0} items selected"},maxOptionsText:function(a,b){return[1==a?"Limit reached ({n} item max)":"Limit reached ({n} items max)",1==b?"Group limit reached ({n} item max)":"Group limit reached ({n} items max)"]},selectAllText:"Select All",deselectAllText:"Deselect All",doneButton:!1,doneButtonText:"Close",multipleSeparator:", ",styleBase:"btn",style:"btn-default",size:"auto",title:null,selectedTextFormat:"values",width:!1,container:!1,hideDisabled:!1,showSubtext:!1,showIcon:!0,showContent:!0,dropupAuto:!0,header:!1,liveSearch:!1,liveSearchPlaceholder:null,liveSearchNormalize:!1,liveSearchStyle:"contains",actionsBox:!1,iconBase:"glyphicon",tickIcon:"glyphicon-ok",showTick:!1,template:{caret:''},maxOptions:!1,mobile:!1,selectOnTab:!1,dropdownAlignRight:!1,windowPadding:0,virtualScroll:600},"4"===t.major&&(x.DEFAULTS.style="btn-light",x.DEFAULTS.iconBase="",x.DEFAULTS.tickIcon="bs-ok-default"),x.prototype={constructor:x,init:function(){var a=this,b=this.$element.attr("id");this.$element.addClass("bs-select-hidden"),this.multiple=this.$element.prop("multiple"),this.autofocus=this.$element.prop("autofocus"),this.$newElement=this.createDropdown(),this.createLi(),this.$element.after(this.$newElement).prependTo(this.$newElement),this.$button=this.$newElement.children("button"),this.$menu=this.$newElement.children(".dropdown-menu"),this.$menuInner=this.$menu.children(".inner"),this.$searchbox=this.$menu.find("input"),this.$element.removeClass("bs-select-hidden"),!0===this.options.dropdownAlignRight&&this.$menu.addClass(u.MENURIGHT),void 0!==b&&this.$button.attr("data-id",b),this.checkDisabled(),this.clickListener(),this.options.liveSearch&&this.liveSearchListener(),this.render(),this.setStyle(),this.setWidth(),this.options.container?this.selectPosition():this.$element.on("hide.bs.select",function(){if(a.isVirtual()){var b=a.$menuInner[0],c=b.firstChild.cloneNode(!1);b.replaceChild(c,b.firstChild),b.scrollTop=0}}),this.$menu.data("this",this),this.$newElement.data("this",this),this.options.mobile&&this.mobile(),this.$newElement.on({"hide.bs.dropdown":function(b){a.$menuInner.attr("aria-expanded",!1),a.$element.trigger("hide.bs.select",b)},"hidden.bs.dropdown":function(b){a.$element.trigger("hidden.bs.select",b)},"show.bs.dropdown":function(b){a.$menuInner.attr("aria-expanded",!0),a.$element.trigger("show.bs.select",b)},"shown.bs.dropdown":function(b){a.$element.trigger("shown.bs.select",b)}}),a.$element[0].hasAttribute("required")&&this.$element.on("invalid",function(){a.$button.addClass("bs-invalid"),a.$element.on({"shown.bs.select":function(){a.$element.val(a.$element.val()).off("shown.bs.select")},"rendered.bs.select":function(){this.validity.valid&&a.$button.removeClass("bs-invalid"),a.$element.off("rendered.bs.select")}}),a.$button.on("blur.bs.select",function(){a.$element.focus().blur(),a.$button.off("blur.bs.select")})}),setTimeout(function(){a.$element.trigger("loaded.bs.select")})},createDropdown:function(){var b=this.multiple||this.options.showTick?" show-tick":"",c=this.autofocus?" autofocus":"",d=this.options.header?'
'+this.options.header+"
":"",e=this.options.liveSearch?'':"",f=this.multiple&&this.options.actionsBox?'
":"",g=this.multiple&&this.options.doneButton?'
":"",h='";return a(h)},setPositionData:function(){this.selectpicker.view.canHighlight=[];for(var a=0;a=this.options.virtualScroll||!0===this.options.virtualScroll},createView:function(c,d){function e(a,d){var e,j,k,l,m,n,o,p=f.selectpicker.current.elements.length,q=[],r=void 0,s=!0,t=f.isVirtual();f.selectpicker.view.scrollTop=a,!0===t&&f.sizeInfo.hasScrollBar&&f.$menu[0].offsetWidth>f.sizeInfo.totalMenuWidth&&(f.sizeInfo.menuWidth=f.$menu[0].offsetWidth,f.sizeInfo.totalMenuWidth=f.sizeInfo.menuWidth+f.sizeInfo.scrollBarWidth,f.$menu.css("min-width",f.sizeInfo.menuWidth)),e=Math.ceil(f.sizeInfo.menuInnerHeight/f.sizeInfo.liHeight*1.5),j=Math.round(p/e)||1;for(var u=0;up-1?0:f.selectpicker.current.data[p-1].position-f.selectpicker.current.data[f.selectpicker.view.position1-1].position,y.firstChild.style.marginTop=w+"px",y.firstChild.style.marginBottom=x+"px"),y.firstChild.appendChild(z)}if(f.prevActiveIndex=f.activeIndex,f.options.liveSearch){if(c&&d){var D,E=0;f.selectpicker.view.canHighlight[E]||(E=1+f.selectpicker.view.canHighlight.slice(1).indexOf(!0)),D=f.selectpicker.view.visibleElements[E],f.selectpicker.view.currentActive&&(f.selectpicker.view.currentActive.classList.remove("active"),f.selectpicker.view.currentActive.firstChild&&f.selectpicker.view.currentActive.firstChild.classList.remove("active")),D&&(D.classList.add("active"),D.firstChild&&D.firstChild.classList.add("active")),f.activeIndex=f.selectpicker.current.map.originalIndex[E]}}else f.$menuInner.focus()}d=d||0;var f=this;this.selectpicker.current=c?this.selectpicker.search:this.selectpicker.main;var g,h,i=[];this.setPositionData(),e(d,!0),this.$menuInner.off("scroll.createView").on("scroll.createView",function(a,b){f.noScroll||e(this.scrollTop,b),f.noScroll=!1}),a(window).off("resize.createView").on("resize.createView",function(){e(f.$menuInner[0].scrollTop)})},createLi:function(){var b,c=this,d=[],e=0,f=0,g=[],h=0,i=0,j=-1;this.selectpicker.view.titleOption||(this.selectpicker.view.titleOption=document.createElement("option"));var k={span:document.createElement("span"),subtext:document.createElement("small"),a:document.createElement("a"),li:document.createElement("li"),whitespace:document.createTextNode(" ")},l=k.span.cloneNode(!1),m=document.createDocumentFragment();l.className=c.options.iconBase+" "+c.options.tickIcon+" check-mark",k.a.appendChild(l),k.a.setAttribute("role","option"),k.subtext.className="text-muted",k.text=k.span.cloneNode(!1),k.text.className="text";var n=function(a,b,c,d){var e=k.li.cloneNode(!1);return a&&(1===a.nodeType||11===a.nodeType?e.appendChild(a):e.innerHTML=a),void 0!==c&&""!==c&&(e.className=c),void 0!==d&&null!==d&&e.classList.add("optgroup-"+d),e},o=function(a,b,c){var d=k.a.cloneNode(!0);return a&&(11===a.nodeType?d.appendChild(a):d.insertAdjacentHTML("beforeend",a)),void 0!==b&""!==b&&(d.className=b),"4"===t.major&&d.classList.add("dropdown-item"),c&&d.setAttribute("style",c),d},q=function(a){var b,d,e=k.text.cloneNode(!1);if(a.optionContent)e.innerHTML=a.optionContent;else{if(e.textContent=a.text,a.optionIcon){var f=k.whitespace.cloneNode(!1);d=k.span.cloneNode(!1),d.className=c.options.iconBase+" "+a.optionIcon,m.appendChild(d),m.appendChild(f)}a.optionSubtext&&(b=k.subtext.cloneNode(!1),b.innerHTML=a.optionSubtext,e.appendChild(b))}return m.appendChild(e),m},r=function(a){var b,d,e=k.text.cloneNode(!1);if(e.textContent=a.labelEscaped,a.labelIcon){var f=k.whitespace.cloneNode(!1);d=k.span.cloneNode(!1),d.className=c.options.iconBase+" "+a.labelIcon,m.appendChild(d),m.appendChild(f)}return a.labelSubtext&&(b=k.subtext.cloneNode(!1),b.textContent=a.labelSubtext,e.appendChild(b)),m.appendChild(e),m};if(this.options.title&&!this.multiple){j--;var s=this.$element[0],v=!1,w=!this.selectpicker.view.titleOption.parentNode;if(w){this.selectpicker.view.titleOption.className="bs-title-option",this.selectpicker.view.titleOption.value="";v=void 0===a(s.options[s.selectedIndex]).attr("selected")&&void 0===this.$element.data("selected")}(w||0!==this.selectpicker.view.titleOption.index)&&s.insertBefore(this.selectpicker.view.titleOption,s.firstChild),v&&(s.selectedIndex=0)}var x=this.$element.find("option");x.each(function(k){var l=a(this);if(j++,!l.hasClass("bs-title-option")){var m,s,t=l.data(),v=this.className||"",w=p(this.style.cssText),y=t.content,z=this.textContent,A=t.tokens,B=t.subtext,C=t.icon,D=l.parent(),E=D[0],F="OPTGROUP"===E.tagName,G=F&&E.disabled,H=this.disabled||G,I=this.previousElementSibling&&"OPTGROUP"===this.previousElementSibling.tagName,J=D.data();if(!0===t.hidden||c.options.hideDisabled&&(H&&!F||G)){if(m=t.prevHiddenIndex,l.next().data("prevHiddenIndex",void 0!==m?m:k),j--,!I&&void 0!==m){var K=x[m].previousElementSibling;K&&"OPTGROUP"===K.tagName&&!K.disabled&&(I=!0)}return void(I&&"divider"!==g[g.length-1].type&&(j++,d.push(n(!1,0,u.DIVIDER,h+"div")),g.push({type:"divider",optID:h,originalIndex:k})))}if(F&&!0!==t.divider){if(c.options.hideDisabled&&H){if(void 0===J.allOptionsDisabled){var L=D.children();D.data("allOptionsDisabled",L.filter(":disabled").length===L.length)}if(D.data("allOptionsDisabled"))return void j--}var M=" "+E.className||"";if(!this.previousElementSibling){h+=1;var N=E.label,O=p(N),P=J.subtext,Q=J.icon;0!==k&&d.length>0&&(j++,d.push(n(!1,0,u.DIVIDER,h+"div")),g.push({type:"divider",optID:h,originalIndex:k})),j++;var R=r({labelEscaped:O,labelSubtext:P,labelIcon:Q});d.push(n(R,0,"dropdown-header"+M,h)),g.push({content:O,subtext:P,type:"optgroup-label",optID:h,originalIndex:k}),i=j-1}if(c.options.hideDisabled&&H||!0===t.hidden)return void j--;s=q({text:z,optionContent:y,optionSubtext:B,optionIcon:C}),d.push(n(o(s,"opt "+v+M,w),0,"",h)),g.push({content:y||z,subtext:B,tokens:A,type:"option",optID:h,headerIndex:i,lastIndex:i+E.childElementCount,originalIndex:k,data:t}),e++}else if(!0===t.divider)d.push(n(!1,0,"divider")),g.push({type:"divider",originalIndex:k});else{if(!I&&c.options.hideDisabled&&void 0!==(m=t.prevHiddenIndex)){var K=x[m].previousElementSibling;K&&"OPTGROUP"===K.tagName&&!K.disabled&&(I=!0)}I&&"divider"!==g[g.length-1].type&&(j++,d.push(n(!1,0,u.DIVIDER,h+"div")),g.push({type:"divider",optID:h,originalIndex:k})),s=q({text:z,optionContent:y,optionSubtext:B,optionIcon:C}),d.push(n(o(s,v,w))),g.push({content:y||z,subtext:B,tokens:A,type:"option",originalIndex:k,data:t}),e++}c.selectpicker.main.map.newIndex[k]=j,c.selectpicker.main.map.originalIndex[j]=k;var S=g[g.length-1];S.disabled=H;var T=0;S.content&&(T+=S.content.length),S.subtext&&(T+=S.subtext.length),C&&(T+=1),T>f&&(f=T,b=d[d.length-1])}}),this.selectpicker.main.elements=d,this.selectpicker.main.data=g,this.selectpicker.current=this.selectpicker.main,this.selectpicker.view.widestOption=b,this.selectpicker.view.availableOptionsCount=e},findLis:function(){return this.$menuInner.find(".inner > li")},render:function(){var a=this,b=this.$element.find("option"),c=[],d=[];this.togglePlaceholder(),this.tabIndex();for(var e=0,f=this.selectpicker.main.elements.length;e ':"";i=a.options.showSubtext&&k.subtext&&!a.multiple?' '+k.subtext+"":"",j=h.title?h.title:k.content&&a.options.showContent?k.content.toString():l+h.innerHTML.trim()+i,d.push(j)}}var m=this.multiple?d.join(this.options.multipleSeparator):d[0];if(c.length>50&&(m+="..."),this.multiple&&-1!==this.options.selectedTextFormat.indexOf("count")){var n=this.options.selectedTextFormat.split(">");if(n.length>1&&c.length>n[1]||1===n.length&&c.length>=2){var o=this.selectpicker.view.availableOptionsCount;m=("function"==typeof this.options.countSelectedText?this.options.countSelectedText(c.length,o):this.options.countSelectedText).replace("{0}",c.length.toString()).replace("{1}",o.toString())}}void 0==this.options.title&&(this.options.title=this.$element.attr("title")),"static"==this.options.selectedTextFormat&&(m=this.options.title),m||(m=void 0!==this.options.title?this.options.title:this.options.noneSelectedText),this.$button[0].title=q(m.replace(/<[^>]*>?/g,"").trim()),this.$button.find(".filter-option-inner-inner")[0].innerHTML=m,this.$element.trigger("rendered.bs.select")},setStyle:function(a,b){this.$element.attr("class")&&this.$newElement.addClass(this.$element.attr("class").replace(/selectpicker|mobile-device|bs-select-hidden|validate\[.*\]/gi,""));var c=a||this.options.style;"add"==b?this.$button.addClass(c):"remove"==b?this.$button.removeClass(c):(this.$button.removeClass(this.options.style),this.$button.addClass(c))},liHeight:function(b){if(b||!1!==this.options.size&&!this.sizeInfo){this.sizeInfo||(this.sizeInfo={});var c=document.createElement("div"),d=document.createElement("div"),f=document.createElement("div"),g=document.createElement("ul"),h=document.createElement("li"),i=document.createElement("li"),j=document.createElement("li"),k=document.createElement("a"),l=document.createElement("span"),m=this.options.header&&this.$menu.find("."+u.POPOVERHEADER).length>0?this.$menu.find("."+u.POPOVERHEADER)[0].cloneNode(!0):null,n=this.options.liveSearch?document.createElement("div"):null,o=this.options.actionsBox&&this.multiple&&this.$menu.find(".bs-actionsbox").length>0?this.$menu.find(".bs-actionsbox")[0].cloneNode(!0):null,p=this.options.doneButton&&this.multiple&&this.$menu.find(".bs-donebutton").length>0?this.$menu.find(".bs-donebutton")[0].cloneNode(!0):null;if(this.sizeInfo.selectWidth=this.$newElement[0].offsetWidth,l.className="text",k.className="dropdown-item",c.className=this.$menu[0].parentNode.className+" "+u.SHOW,c.style.width=this.sizeInfo.selectWidth+"px",d.className="dropdown-menu "+u.SHOW,f.className="inner "+u.SHOW,g.className="dropdown-menu inner "+("4"===t.major?u.SHOW:""),h.className=u.DIVIDER,i.className="dropdown-header",l.appendChild(document.createTextNode("Inner text")),k.appendChild(l),j.appendChild(k),i.appendChild(l.cloneNode(!0)),this.selectpicker.view.widestOption&&g.appendChild(this.selectpicker.view.widestOption.cloneNode(!0)),g.appendChild(j),g.appendChild(h),g.appendChild(i),m&&d.appendChild(m),n){var q=document.createElement("input");n.className="bs-searchbox",q.className="form-control",n.appendChild(q),d.appendChild(n)}o&&d.appendChild(o),f.appendChild(g),d.appendChild(f),p&&d.appendChild(p),c.appendChild(d),document.body.appendChild(c);var r,s=k.offsetHeight,v=i?i.offsetHeight:0,w=m?m.offsetHeight:0,x=n?n.offsetHeight:0,y=o?o.offsetHeight:0,z=p?p.offsetHeight:0,A=a(h).outerHeight(!0),B=!!window.getComputedStyle&&window.getComputedStyle(d),C=d.offsetWidth,D=B?null:a(d),E={vert:e(B?B.paddingTop:D.css("paddingTop"))+e(B?B.paddingBottom:D.css("paddingBottom"))+e(B?B.borderTopWidth:D.css("borderTopWidth"))+e(B?B.borderBottomWidth:D.css("borderBottomWidth")),horiz:e(B?B.paddingLeft:D.css("paddingLeft"))+e(B?B.paddingRight:D.css("paddingRight"))+e(B?B.borderLeftWidth:D.css("borderLeftWidth"))+e(B?B.borderRightWidth:D.css("borderRightWidth"))},F={vert:E.vert+e(B?B.marginTop:D.css("marginTop"))+e(B?B.marginBottom:D.css("marginBottom"))+2,horiz:E.horiz+e(B?B.marginLeft:D.css("marginLeft"))+e(B?B.marginRight:D.css("marginRight"))+2};f.style.overflowY="scroll",r=d.offsetWidth-C,document.body.removeChild(c),this.sizeInfo.liHeight=s,this.sizeInfo.dropdownHeaderHeight=v,this.sizeInfo.headerHeight=w,this.sizeInfo.searchHeight=x,this.sizeInfo.actionsHeight=y,this.sizeInfo.doneButtonHeight=z,this.sizeInfo.dividerHeight=A,this.sizeInfo.menuPadding=E,this.sizeInfo.menuExtras=F,this.sizeInfo.menuWidth=C,this.sizeInfo.totalMenuWidth=this.sizeInfo.menuWidth,this.sizeInfo.scrollBarWidth=r,this.sizeInfo.selectHeight=this.$newElement[0].offsetHeight,this.setPositionData()}},getSelectPosition:function(){var b,c=this,d=a(window),e=c.$newElement.offset(),f=a(c.options.container);c.options.container&&!f.is("body")?(b=f.offset(),b.top+=parseInt(f.css("borderTopWidth")),b.left+=parseInt(f.css("borderLeftWidth"))):b={top:0,left:0};var g=c.options.windowPadding;this.sizeInfo.selectOffsetTop=e.top-b.top-d.scrollTop(),this.sizeInfo.selectOffsetBot=d.height()-this.sizeInfo.selectOffsetTop-this.sizeInfo.selectHeight-b.top-g[2],this.sizeInfo.selectOffsetLeft=e.left-b.left-d.scrollLeft(),this.sizeInfo.selectOffsetRight=d.width()-this.sizeInfo.selectOffsetLeft-this.sizeInfo.selectWidth-b.left-g[1],this.sizeInfo.selectOffsetTop-=g[0],this.sizeInfo.selectOffsetLeft-=g[3]},setMenuSize:function(a){this.getSelectPosition();var b,c,d,e,f,g,h,i=this.sizeInfo.selectWidth,j=this.sizeInfo.liHeight,k=this.sizeInfo.headerHeight,l=this.sizeInfo.searchHeight,m=this.sizeInfo.actionsHeight,n=this.sizeInfo.doneButtonHeight,o=this.sizeInfo.dividerHeight,p=this.sizeInfo.menuPadding,q=0;if(this.options.dropupAuto&&(h=j*this.selectpicker.current.elements.length+p.vert,this.$newElement.toggleClass(u.DROPUP,this.sizeInfo.selectOffsetTop-this.sizeInfo.selectOffsetBot>this.sizeInfo.menuExtras.vert&&h+this.sizeInfo.menuExtras.vert+50>this.sizeInfo.selectOffsetBot)),"auto"===this.options.size)e=this.selectpicker.current.elements.length>3?3*this.sizeInfo.liHeight+this.sizeInfo.menuExtras.vert-2:0,c=this.sizeInfo.selectOffsetBot-this.sizeInfo.menuExtras.vert,d=e+k+l+m+n,g=Math.max(e-p.vert,0),this.$newElement.hasClass(u.DROPUP)&&(c=this.sizeInfo.selectOffsetTop-this.sizeInfo.menuExtras.vert),f=c,b=c-k-l-m-n-p.vert;else if(this.options.size&&"auto"!=this.options.size&&this.selectpicker.current.elements.length>this.options.size){for(var r=0;rthis.sizeInfo.selectOffsetRight&&this.sizeInfo.selectOffsetRightthis.sizeInfo.menuInnerHeight&&(this.sizeInfo.hasScrollBar=!0,this.sizeInfo.totalMenuWidth=this.sizeInfo.menuWidth+this.sizeInfo.scrollBarWidth,this.$menu.css("min-width",this.sizeInfo.totalMenuWidth)),this.dropdown&&this.dropdown._popper&&this.dropdown._popper.update()},setSize:function(b){if(this.liHeight(b),this.options.header&&this.$menu.css("padding-top",0),!1!==this.options.size){var c,d=this,e=a(window),f=0;this.setMenuSize(),"auto"===this.options.size?(this.$searchbox.off("input.setMenuSize propertychange.setMenuSize").on("input.setMenuSize propertychange.setMenuSize",function(){return d.setMenuSize()}),e.off("resize.setMenuSize scroll.setMenuSize").on("resize.setMenuSize scroll.setMenuSize",function(){return d.setMenuSize()})):this.options.size&&"auto"!=this.options.size&&this.selectpicker.current.elements.length>this.options.size&&(this.$searchbox.off("input.setMenuSize propertychange.setMenuSize"),e.off("resize.setMenuSize scroll.setMenuSize")),b?f=this.$menuInner[0].scrollTop:d.multiple||"number"==typeof(c=d.selectpicker.main.map.newIndex[d.$element[0].selectedIndex])&&!1!==d.options.size&&(f=d.sizeInfo.liHeight*c,f=f-d.sizeInfo.menuInnerHeight/2+d.sizeInfo.liHeight/2),d.createView(!1,f)}},setWidth:function(){var a=this;"auto"===this.options.width?requestAnimationFrame(function(){a.$menu.css("min-width","0"),a.liHeight(),a.setMenuSize();var b=a.$newElement.clone().appendTo("body"),c=b.css("width","auto").children("button").outerWidth();b.remove(),a.sizeInfo.selectWidth=Math.max(a.sizeInfo.totalMenuWidth,c),a.$newElement.css("width",a.sizeInfo.selectWidth+"px")}):"fit"===this.options.width?(this.$menu.css("min-width",""),this.$newElement.css("width","").addClass("fit-width")):this.options.width?(this.$menu.css("min-width",""),this.$newElement.css("width",this.options.width)):(this.$menu.css("min-width",""),this.$newElement.css("width","")),this.$newElement.hasClass("fit-width")&&"fit"!==this.options.width&&this.$newElement.removeClass("fit-width")},selectPosition:function(){this.$bsContainer=a('
');var b,c,d,e=this,f=a(this.options.container),g=function(a){var g={};e.$bsContainer.addClass(a.attr("class").replace(/form-control|fit-width/gi,"")).toggleClass(u.DROPUP,a.hasClass(u.DROPUP)),b=a.offset(),f.is("body")?c={top:0,left:0}:(c=f.offset(),c.top+=parseInt(f.css("borderTopWidth"))-f.scrollTop(),c.left+=parseInt(f.css("borderLeftWidth"))-f.scrollLeft()),d=a.hasClass(u.DROPUP)?0:a[0].offsetHeight,t.major<4&&(g.top=b.top-c.top+d,g.left=b.left-c.left),g.width=a[0].offsetWidth,e.$bsContainer.css(g)};this.$button.on("click.bs.dropdown.data-api",function(){e.isDisabled()||(g(e.$newElement),e.$bsContainer.appendTo(e.options.container).toggleClass(u.SHOW,!e.$button.hasClass(u.SHOW)).append(e.$menu))}),a(window).on("resize scroll",function(){g(e.$newElement)}),this.$element.on("hide.bs.select",function(){e.$menu.data("height",e.$menu.height()),e.$bsContainer.detach()})},setOptionStatus:function(){var a=this,b=this.$element.find("option");if(a.noScroll=!1,a.selectpicker.view.visibleElements&&a.selectpicker.view.visibleElements.length)for(var c=0;c3&&!b.dropdown&&(b.dropdown=b.$button.data("bs.dropdown"),b.dropdown._menu=b.$menu[0])}),this.$button.on("click.bs.dropdown.data-api",function(){b.$newElement.hasClass(u.SHOW)||b.setSize()}),this.$element.on("shown.bs.select",function(){b.$menuInner[0].scrollTop!==b.selectpicker.view.scrollTop&&(b.$menuInner[0].scrollTop=b.selectpicker.view.scrollTop),b.options.liveSearch?b.$searchbox.focus():b.$menuInner.focus()}),this.$menuInner.on("click","li a",function(d,e){var f=a(this),g=b.isVirtual()?b.selectpicker.view.position0:0,h=b.selectpicker.current.map.originalIndex[f.parent().index()+g],i=c(b.$element[0]),j=b.$element.prop("selectedIndex"),l=!0;if(b.multiple&&1!==b.options.maxOptions&&d.stopPropagation(),d.preventDefault(),!b.isDisabled()&&!f.parent().hasClass(u.DISABLED)){var m=b.$element.find("option"),n=m.eq(h),o=n.prop("selected"),p=n.parent("optgroup"),q=b.options.maxOptions,r=p.data("maxOptions")||!1;if(h===b.activeIndex&&(e=!0),e||(b.prevActiveIndex=b.activeIndex,b.activeIndex=void 0),b.multiple){if(n.prop("selected",!o),b.setSelected(h,!o),f.blur(),!1!==q||!1!==r){var s=q
');x[2]&&(y=y.replace("{var}",x[2][q>1?0:1]),z=z.replace("{var}",x[2][r>1?0:1])),n.prop("selected",!1),b.$menu.append(A),q&&s&&(A.append(a("
"+y+"
")),l=!1,b.$element.trigger("maxReached.bs.select")),r&&t&&(A.append(a("
"+z+"
")),l=!1,b.$element.trigger("maxReachedGrp.bs.select")),setTimeout(function(){b.setSelected(h,!1)},10),A.delay(750).fadeOut(300,function(){a(this).remove()})}}}else m.prop("selected",!1),n.prop("selected",!0),b.setSelected(h,!0);!b.multiple||b.multiple&&1===b.options.maxOptions?b.$button.focus():b.options.liveSearch&&b.$searchbox.focus(),l&&(i!=c(b.$element[0])&&b.multiple||j!=b.$element.prop("selectedIndex")&&!b.multiple)&&(k=[h,n.prop("selected"),i],b.$element.triggerNative("change"))}}),this.$menu.on("click","li."+u.DISABLED+" a, ."+u.POPOVERHEADER+", ."+u.POPOVERHEADER+" :not(.close)",function(c){c.currentTarget==this&&(c.preventDefault(),c.stopPropagation(),b.options.liveSearch&&!a(c.target).hasClass("close")?b.$searchbox.focus():b.$button.focus())}),this.$menuInner.on("click",".divider, .dropdown-header",function(a){a.preventDefault(),a.stopPropagation(),b.options.liveSearch?b.$searchbox.focus():b.$button.focus()}),this.$menu.on("click","."+u.POPOVERHEADER+" .close",function(){b.$button.click()}),this.$searchbox.on("click",function(a){a.stopPropagation()}),this.$menu.on("click",".actions-btn",function(c){b.options.liveSearch?b.$searchbox.focus():b.$button.focus(),c.preventDefault(),c.stopPropagation(),a(this).hasClass("bs-select-all")?b.selectAll():b.deselectAll()}),this.$element.on({change:function(){b.render(),b.$element.trigger("changed.bs.select",k),k=null},focus:function(){b.$button.focus()}})},liveSearchListener:function(){var a=this,b=document.createElement("li");this.$button.on("click.bs.dropdown.data-api",function(){a.$searchbox.val()&&a.$searchbox.val("")}),this.$searchbox.on("click.bs.dropdown.data-api focus.bs.dropdown.data-api touchend.bs.dropdown.data-api",function(a){a.stopPropagation()}),this.$searchbox.on("input propertychange",function(){var c=a.$searchbox.val();if(a.selectpicker.search.map.newIndex={},a.selectpicker.search.map.originalIndex={},a.selectpicker.search.elements=[],a.selectpicker.search.data=[],c){var e,f=[],g=c.toUpperCase(),h={},i=[],j=a._searchStyle(),k=a.options.liveSearchNormalize;a._$lisSelected=a.$menuInner.find(".selected");for(var e=0;e0&&(h[l.headerIndex-1]=!0,i.push(l.headerIndex-1)),h[l.headerIndex]=!0,i.push(l.headerIndex),h[l.lastIndex+1]=!0),h[e]&&"optgroup-label"!==l.type&&i.push(e)}for(var e=0,m=i.length;e=48&&b.which<=57||b.which>=96&&b.which<=105||b.which>=65&&b.which<=90)&&k.$button.trigger("click.bs.dropdown.data-api"),b.which===s.ESCAPE&&e&&(b.preventDefault(),k.$button.trigger("click.bs.dropdown.data-api").focus()),o){if(!l.length)return;c=!0===q?l.index(l.filter(".active")):k.selectpicker.current.map.newIndex[k.activeIndex],void 0===c&&(c=-1),-1!==c&&(f=k.selectpicker.current.elements[c+t],f.classList.remove("active"),f.firstChild&&f.firstChild.classList.remove("active")),b.which===s.ARROW_UP?(-1!==c&&c--,c+t<0&&(c+=l.length),k.selectpicker.view.canHighlight[c+t]||-1===(c=k.selectpicker.view.canHighlight.slice(0,c+t).lastIndexOf(!0)-t)&&(c=l.length-1)):(b.which===s.ARROW_DOWN||n)&&(c++,c+t>=k.selectpicker.view.canHighlight.length&&(c=0),k.selectpicker.view.canHighlight[c+t]||(c=c+1+k.selectpicker.view.canHighlight.slice(c+t+1).indexOf(!0))),b.preventDefault();var x=t+c;b.which===s.ARROW_UP?0===t&&c===l.length-1?(k.$menuInner[0].scrollTop=k.$menuInner[0].scrollHeight,x=k.selectpicker.current.elements.length-1):(g=k.selectpicker.current.data[x],h=g.position-g.height,m=hp)),f=k.selectpicker.current.elements[x],f.classList.add("active"),f.firstChild&&f.firstChild.classList.add("active"),k.activeIndex=k.selectpicker.current.map.originalIndex[x],k.selectpicker.view.currentActive=f,m&&(k.$menuInner[0].scrollTop=h),k.options.liveSearch?k.$searchbox.focus():i.focus()}else if(!i.is("input")&&!w.test(b.which)||b.which===s.SPACE&&k.selectpicker.keydown.keyHistory){var y,z,A=[];b.preventDefault(),k.selectpicker.keydown.keyHistory+=r[b.which],k.selectpicker.keydown.resetKeyHistory.cancel&&clearTimeout(k.selectpicker.keydown.resetKeyHistory.cancel),k.selectpicker.keydown.resetKeyHistory.cancel=k.selectpicker.keydown.resetKeyHistory.start(),z=k.selectpicker.keydown.keyHistory,/^(.)\1+$/.test(z)&&(z=z.charAt(0));for(var B=0;B0?(h=g.position-g.height,m=!0):(h=g.position-k.sizeInfo.menuInnerHeight,m=g.position>p+k.sizeInfo.menuInnerHeight),f=k.selectpicker.current.elements[y],f.classList.add("active"),f.firstChild&&f.firstChild.classList.add("active"),k.activeIndex=A[E],f.firstChild.focus(),m&&(k.$menuInner[0].scrollTop=h),i.focus()}}e&&(b.which===s.SPACE&&!k.selectpicker.keydown.keyHistory||b.which===s.ENTER||b.which===s.TAB&&k.options.selectOnTab)&&(b.which!==s.SPACE&&b.preventDefault(),k.options.liveSearch&&b.which===s.SPACE||(k.$menuInner.find(".active a").trigger("click",!0),i.focus(),k.options.liveSearch||(b.preventDefault(),a(document).data("spaceSelect",!0))))},mobile:function(){this.$element.addClass("mobile-device")},refresh:function(){var b=a.extend({},this.options,this.$element.data());this.options=b,this.selectpicker.main.map.newIndex={},this.selectpicker.main.map.originalIndex={},this.createLi(),this.checkDisabled(),this.render(),this.setStyle(),this.setWidth(),this.setSize(!0),this.$element.trigger("refreshed.bs.select")},hide:function(){this.$newElement.hide()},show:function(){this.$newElement.show()},remove:function(){this.$newElement.remove(),this.$element.remove()},destroy:function(){this.$newElement.before(this.$element).remove(),this.$bsContainer?this.$bsContainer.remove():this.$menu.remove(),this.$element.off(".bs.select").removeData("selectpicker").removeClass("bs-select-hidden selectpicker")}};var y=a.fn.selectpicker;a.fn.selectpicker=g,a.fn.selectpicker.Constructor=x,a.fn.selectpicker.noConflict=function(){return a.fn.selectpicker=y,this},a(document).off("keydown.bs.dropdown.data-api").on("keydown.bs.select",'.bootstrap-select [data-toggle="dropdown"], .bootstrap-select [role="listbox"], .bs-searchbox input',x.prototype.keydown).on("focusin.modal",'.bootstrap-select [data-toggle="dropdown"], .bootstrap-select [role="listbox"], .bs-searchbox input',function(a){a.stopPropagation()}),a(window).on("load.bs.select.data-api",function(){a(".selectpicker").each(function(){var b=a(this);g.call(b,b.data())})})}(a)}); + //# sourceMappingURL=bootstrap-select.js.map + \ No newline at end of file diff --git a/test_web/static/js/index.js b/test_web/static/js/index.js index 8d4f91e..ff46807 100644 --- a/test_web/static/js/index.js +++ b/test_web/static/js/index.js @@ -1,17 +1,21 @@ -var all_plugins = undefined; -var plugin_arr = []; -var current_array = []; -var current_plugin_requirePath = undefined; +const state = { + all_plugins: {}, + plugin_arr: [], + current_array: [], + current_plugin: undefined, + filters: [], +} const language_selection = $('#language'); const plugin_search = $('#plugin'); const search_results = $('#search-results'); fetch('/all_plugins').then(res => res.json()).then(all => { - all_plugins = all; + state.all_plugins = all; + language_selection.html(``); for(let lang in all){ language_selection.append(``); - plugin_arr = plugin_arr.concat(all[lang]); + state.plugin_arr = state.plugin_arr.concat(all[lang]); } }); @@ -32,236 +36,329 @@ const display_search = (arr) => { } plugin_search.focus(e => { - if(!all_plugins) return; + if(!state.all_plugins) return; if(language_selection.val()){ - current_array = all_plugins[language_selection.val()]; + state.current_array = state.all_plugins[language_selection.val()]; }else{ - current_array = plugin_arr; + state.current_array = state.plugin_arr; } - display_search(current_array); + display_search(state.current_array); }); plugin_search.keyup(e => { - display_search(current_array.filter(plg => plg.name.toLowerCase().includes(plugin_search.val().toLowerCase()))); + display_search(state.current_array.filter(plg => plg.name.toLowerCase().includes(plugin_search.val().toLowerCase()))); }); $('#clear-search').click(e => { search_results.hide(); plugin_search.val(''); plugin_search.attr('data-require', ''); -}) +}); const test_plugin = (btn) => { const ele = $(btn); - current_plugin_requirePath = ele.attr('data-require'); - plugin_search.attr('data-require', current_plugin_requirePath); + plugin_requirePath = ele.attr('data-require'); + state.current_plugin = new Plugin(plugin_requirePath); + plugin_search.attr('data-require', plugin_requirePath); plugin_search.val(ele.text().split('/')[1]); search_results.hide(); + state.current_plugin.getfilters(); } -const popularNovels = () => { - if(!current_plugin_requirePath) return; - $('#popularNovels .spinner-border').show(); - fetch(`/popularNovels/`,{ - method: 'POST', - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({"pluginRequirePath": current_plugin_requirePath}), - }) - .then(res => res.json()) - .then(novels => { - const novel_list = $('#popularNovels .novel-list'); - novel_list.html(''); - if(novels.error){ - novel_list.html(novels.error); - }else{ - novels.forEach(novel => { - novel_list.append(` -
- No cover found -
-
-
name
- ${novel.name?.slice(0, 50)} -
Copy
-
-
-
url
- ${novel.url?.slice(0, 50)} -
Copy
-
-
-
cover
- ${novel.cover?.slice(0, 50)} -
Copy
+ +class Plugin { + constructor(requirePath){ + this.requirePath = requirePath; + } + + getfilters = () => { + const makeSelect = (filter) => { + const container = document.createElement('div'); + const select = document.createElement('select'); + select.classList.add('select'); + if(filter.inputType === 2 || filter.inputType === "Checkbox"){ + select.setAttribute("multiple", ""); + }else{ + select.innerHTML = ``; + } + select.setAttribute("key", filter.key); + filter.values.forEach((v) => { + const option = document.createElement('option'); + option.setAttribute("value", v.value) + option.innerText = v.label; + select.append(option); + }); + container.append(select); + const label = document.createElement('label'); + label.classList.add("form-label"); + label.classList.add("select-label"); + label.innerText = filter.label; + container.append(label); + const hr = document.createElement('hr'); + hr.classList.add("hr"); + container.append(hr); + return container; + } + fetch("/filters", { + method: 'POST', + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify({"pluginRequirePath": this.requirePath}), + }).then(res => res.json()) + .then(filters => { + const filtersModal = $("#filtersModal .modal-body"); + filtersModal.html(""); + filters.forEach(filter => { + filtersModal.append(makeSelect(filter)) + }); + state.filters.length = 0; + document.querySelectorAll('select.select').forEach(e => { + const key = e.getAttribute("key"); + const select = new mdb.Select(e); + select.key = key; + state.filters.push(select); + }) + }) + } + + popularNovels = () => { + const filters = {}; + state.filters.forEach(_f => { + filters[_f.key] = _f.value; + }) + $('#popularNovels .spinner-border').show(); + fetch(`/popularNovels/`,{ + method: 'POST', + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify( + { + "pluginRequirePath": this.requirePath, + "filters": filters + } + ), + }) + .then(res => res.json()) + .then(novels => { + const novel_list = $('#popularNovels .novel-list'); + novel_list.html(''); + if(novels.error){ + novel_list.html(novels.error); + }else{ + novels.forEach(novel => { + novel_list.append(` +
+ No cover found +
+
+
name
+ ${novel.name?.slice(0, 50)} +
Copy
+
+
+
url
+ ${novel.url?.slice(0, 50)} +
Copy
+
+
+
cover
+ ${novel.cover?.slice(0, 50)} +
Copy
+
-
- `); - }) - } - $('#popularNovels .spinner-border').hide(); - }); -} - -const searchNovels = () => { - const searchTerm = $('#searchNovels input').val(); - if(!current_plugin_requirePath || !searchTerm) return; - $('#searchNovels .spinner-border').show(); - fetch(`/searchNovels/`,{ - method: 'POST', - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({"pluginRequirePath": current_plugin_requirePath, "searchTerm": searchTerm}), - }) - .then(res => res.json()) - .then(novels => { - const novel_list = $('#searchNovels .novel-list'); - novel_list.html(''); - if(novels.error){ - novel_list.html(novels.error); - }else{ - novels.forEach(novel => { - novel_list.append(` -
- No cover found -
-
-
name
- ${novel.name?.slice(0, 50)} -
Copy
-
-
-
url
- ${novel.url?.slice(0, 50)} -
Copy
-
-
-
cover
- ${novel.cover?.slice(0, 50)} -
Copy
+ `); + }) + } + $('#popularNovels .spinner-border').hide(); + }); + } + + searchNovels = () => { + const searchTerm = $('#searchNovels input').val(); + $('#searchNovels .spinner-border').show(); + fetch(`/searchNovels/`,{ + method: 'POST', + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify({"pluginRequirePath": this.requirePath, "searchTerm": searchTerm}), + }) + .then(res => res.json()) + .then(novels => { + const novel_list = $('#searchNovels .novel-list'); + novel_list.html(''); + if(novels.error){ + novel_list.html(novels.error); + }else{ + novels.forEach(novel => { + novel_list.append(` +
+ No cover found +
+
+
name
+ ${novel.name?.slice(0, 50)} +
Copy
+
+
+
url
+ ${novel.url?.slice(0, 50)} +
Copy
+
+
+
cover
+ ${novel.cover?.slice(0, 50)} +
Copy
+
+ `); + }) + } + $('#searchNovels .spinner-border').hide(); + }); + } + + parseNovelAndChapters = () => { + const novelUrl = $('#parseNovelAndChapters input').val(); + $('#parseNovelAndChapters .spinner-border').show(); + fetch(`/parseNovelAndChapters/`,{ + method: 'POST', + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify({"pluginRequirePath": this.requirePath, "novelUrl": novelUrl}), + }) + .then(res => res.json()) + .then(sourceNovel => { + const novel_item = $('#parseNovelAndChapters .novel-list .novel-item'); + novel_item.html(` + No cover found +
+
+
name
+ ${sourceNovel.name?.slice(0, 50)} +
Copy
+
+
+
url
+ ${sourceNovel.url?.slice(0, 50)} +
Copy
+
+
+
cover
+ ${sourceNovel.cover?.slice(0, 50)} +
Copy
+
+
+
summary
+ ${sourceNovel.summary?.slice(0, 50)} +
Copy
+
+
+
author
+ ${sourceNovel.author} +
Copy
+
+
+
artist
+ ${sourceNovel.artist} +
Copy
+
+
+
status
+ ${sourceNovel.status} +
Copy
+
+
+
genres
+ ${sourceNovel.genres?.slice(0, 50)} +
Copy
+
- `); - }) - } - $('#searchNovels .spinner-border').hide(); - }); + `); + if(sourceNovel.error){ + novel_item.html(sourceNovel.error); + }else{ + const chapter_list = $('#parseNovelAndChapters .chapter-list'); + chapter_list.html(''); + sourceNovel.chapters.forEach(chapter => { + chapter_list.append(` +
+ ${chapter.name?.slice(0, 26)}
+ ${chapter.releaseTime} +
Copy url
+
+ `); + }) + } + $('#parseNovelAndChapters .spinner-border').hide(); + }); + } + + parseChapter = () => { + const chapterUrl = $('#parseChapter input').val(); + $('#parseChapter .spinner-border').show(); + fetch(`/parseChapter/`,{ + method: 'POST', + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify({"pluginRequirePath": this.requirePath, "chapterUrl": chapterUrl}), + }) + .then(res => res.json()) + .then(chapterText => { + $('#parseChapter textarea').text(chapterText); + $('#parseChapter .spinner-border').hide(); + }) + } + + fetchImage = () => { + const url = $('#fetchImage input').val(); + $('#fetchImage .spinner-border').show(); + fetch(`/fetchImage/`,{ + method: 'POST', + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify({"pluginRequirePath": this.requirePath, "url": url}), + }) + .then(res => res.json()) + .then(base64 => { + $('#fetchImage img').attr("src", `data:image/jpg;base64,${base64}`); + $('#fetchImage .spinner-border').hide(); + }) + } } -const parseNovelAndChapters = () => { - const novelUrl = $('#parseNovelAndChapters input').val(); - if(!current_plugin_requirePath || !novelUrl) return; - $('#parseNovelAndChapters .spinner-border').show(); - fetch(`/parseNovelAndChapters/`,{ - method: 'POST', - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({"pluginRequirePath": current_plugin_requirePath, "novelUrl": novelUrl}), - }) - .then(res => res.json()) - .then(sourceNovel => { - const novel_item = $('#parseNovelAndChapters .novel-list .novel-item'); - novel_item.html(` - No cover found -
-
-
name
- ${sourceNovel.name?.slice(0, 50)} -
Copy
-
-
-
url
- ${sourceNovel.url?.slice(0, 50)} -
Copy
-
-
-
cover
- ${sourceNovel.cover?.slice(0, 50)} -
Copy
-
-
-
summary
- ${sourceNovel.summary?.slice(0, 50)} -
Copy
-
-
-
author
- ${sourceNovel.author} -
Copy
-
-
-
artist
- ${sourceNovel.artist} -
Copy
-
-
-
status
- ${sourceNovel.status} -
Copy
-
-
-
genres
- ${sourceNovel.genres?.slice(0, 50)} -
Copy
-
-
- `); - if(sourceNovel.error){ - novel_item.html(sourceNovel.error); - }else{ - const chapter_list = $('#parseNovelAndChapters .chapter-list'); - chapter_list.html(''); - sourceNovel.chapters.forEach(chapter => { - chapter_list.append(` -
- ${chapter.name?.slice(0, 26)}
- ${chapter.releaseTime} -
Copy url
-
- `); - }) - } - $('#parseNovelAndChapters .spinner-border').hide(); - }); -} +$(".popularNovels-btn").click(e => { + if(state.current_plugin){ + state.current_plugin.popularNovels(); + } +}); -const parseChapter = () => { - const chapterUrl = $('#parseChapter input').val(); - if(!current_plugin_requirePath || !chapterUrl) return; - $('#parseChapter .spinner-border').show(); - fetch(`/parseChapter/`,{ - method: 'POST', - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({"pluginRequirePath": current_plugin_requirePath, "chapterUrl": chapterUrl}), - }) - .then(res => res.json()) - .then(chapterText => { - $('#parseChapter textarea').text(chapterText); - $('#parseChapter .spinner-border').hide(); - }) -} +$(".searchNovels-btn").click(e => { + if(state.current_plugin){ + state.current_plugin.searchNovels(); + } +}); -const fetchImage = () => { - const url = $('#fetchImage input').val(); - if(!current_plugin_requirePath || !url) return; - $('#fetchImage .spinner-border').show(); - fetch(`/fetchImage/`,{ - method: 'POST', - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({"pluginRequirePath": current_plugin_requirePath, "url": url}), - }) - .then(res => res.json()) - .then(base64 => { - $('#fetchImage img').attr("src", `data:image/jpg;base64,${base64}`); - $('#fetchImage .spinner-border').hide(); - }) -} \ No newline at end of file +$(".parseNovelAndChapters-btn").click(e => { + if(state.current_plugin){ + state.current_plugin.parseNovelAndChapters(); + } +}); + +$(".parseChapter-btn").click(e => { + if(state.current_plugin){ + state.current_plugin.parseChapter(); + } +}); +$(".fetchImage-btn").click(e => { + if(state.current_plugin){ + state.current_plugin.fetchImage(); + } +}); diff --git a/test_web/static/js/jquery-3.6.4.min.js b/test_web/static/js/jquery.min.js similarity index 100% rename from test_web/static/js/jquery-3.6.4.min.js rename to test_web/static/js/jquery.min.js diff --git a/test_web/static/js/mdb5.js b/test_web/static/js/mdb5.js new file mode 100644 index 0000000..0d88f15 --- /dev/null +++ b/test_web/static/js/mdb5.js @@ -0,0 +1,19710 @@ +/*! + * + * Version: MDB Pro 6.4.2 + * + * Copyright: Material Design for Bootstrap + * https://mdbootstrap.com/ + * + * If you don't have a PRO license, you can purchase one here: + * https://mdbootstrap.com/docs/standard/pro/ + * + * Enterprise quotations, standard license & license customization: + * https://mdbootstrap.com/general/license/ + * + * Documentation: + * https://mdbootstrap.com/docs/standard/ + * + * Support: + * https://mdbootstrap.com/support/ + * + * Contact: + * contact@mdbootstrap.com + * + */ +!function(t, e) { + "object" == typeof exports && "object" == typeof module ? module.exports = e() : "function" == typeof define && define.amd ? define("mdb", [], e) : "object" == typeof exports ? exports.mdb = e() : t.mdb = e() +}(this, function() { + return n = [function(t, e, n) { + "use strict"; + n(17), + n(53); + function i(t) { + return "true" === t || "false" !== t && (t === Number(t).toString() ? Number(t) : "" === t || "null" === t ? null : t) + } + function o(t) { + return t.replace(/[A-Z]/g, t=>"-".concat(t.toLowerCase())) + } + e.a = { + setDataAttribute(t, e, n) { + t.setAttribute("data-mdb-".concat(o(e)), n) + }, + removeDataAttribute(t, e) { + t.removeAttribute("data-mdb-".concat(o(e))) + }, + getDataAttributes(t) { + if (!t) + return {}; + const n = { + ...t.dataset + }; + return Object.keys(n).filter(t=>t.startsWith("mdb")).forEach(t=>{ + let e = t.replace(/^mdb/, ""); + e = e.charAt(0).toLowerCase() + e.slice(1, e.length), + n[e] = i(n[t]) + } + ), + n + }, + getDataAttribute(t, e) { + return i(t.getAttribute("data-mdb-".concat(o(e)))) + }, + offset(t) { + t = t.getBoundingClientRect(); + return { + top: t.top + document.body.scrollTop, + left: t.left + document.body.scrollLeft + } + }, + position(t) { + return { + top: t.offsetTop, + left: t.offsetLeft + } + }, + style(t, e) { + Object.assign(t.style, e) + }, + toggleClass(t, e) { + t && (t.classList.contains(e) ? t.classList.remove(e) : t.classList.add(e)) + }, + addClass(t, e) { + t.classList.contains(e) || t.classList.add(e) + }, + addStyle(e, n) { + Object.keys(n).forEach(t=>{ + e.style[t] = n[t] + } + ) + }, + removeClass(t, e) { + t.classList.contains(e) && t.classList.remove(e) + }, + hasClass(t, e) { + return t.classList.contains(e) + } + } + } + , function(t, e, n) { + "use strict"; + n.d(e, "a", function() { + return a + }); + n(17), + n(53), + n(11), + n(12); + n = n(3); + const h = Object(n.f)() + , g = /[^.]*(?=\..*)\.|.*/ + , d = /\..*/ + , u = /::\d+$/ + , i = {}; + let o = 1; + const r = { + mouseenter: "mouseover", + mouseleave: "mouseout" + } + , p = ["click", "dblclick", "mouseup", "mousedown", "contextmenu", "mousewheel", "DOMMouseScroll", "mouseover", "mouseout", "mousemove", "selectstart", "selectend", "keydown", "keypress", "keyup", "orientationchange", "touchstart", "touchmove", "touchend", "touchcancel", "pointerdown", "pointermove", "pointerup", "pointerleave", "pointercancel", "gesturestart", "gesturechange", "gestureend", "focus", "blur", "change", "reset", "select", "submit", "focusin", "focusout", "load", "unload", "beforeunload", "resize", "move", "DOMContentLoaded", "readystatechange", "error", "abort", "scroll"]; + function m(t, e) { + return e && "".concat(e, "::").concat(o++) || t.uidEvent || o++ + } + function b(t) { + var e = m(t); + return t.uidEvent = e, + i[e] = i[e] || {}, + i[e] + } + function v(n, i, t) { + var o = 2 < arguments.length && void 0 !== t ? t : null + , r = Object.keys(n); + for (let t = 0, e = r.length; t < e; t++) { + var s = n[r[t]]; + if (s.originalHandler === i && s.delegationSelector === o) + return s + } + return null + } + function _(t, e, n) { + var i = "string" == typeof e + , n = i ? n : e; + let o = t.replace(d, ""); + e = r[o], + e && (o = e), + e = -1 < p.indexOf(o); + return [i, n, o = e ? o : t] + } + function s(t, e, n, i, o) { + var r, s, a, l, c, u, h, d, p, f; + "string" == typeof e && t && (n || (n = i, + i = null), + [r,s,a] = _(e, n, i), + (c = v(l = (l = b(t))[a] || (l[a] = {}), s, r ? n : null)) ? c.oneOff = c.oneOff && o : (c = m(s, e.replace(g, "")), + (e = r ? (d = t, + p = n, + f = i, + function n(i) { + var o = d.querySelectorAll(p); + for (let e = i["target"]; e && e !== this; e = e.parentNode) + for (let t = o.length; t--; ) + if (o[t] === e) + return i.delegateTarget = e, + n.oneOff && y.off(d, i.type, f), + f.apply(e, [i]); + return null + } + ) : (u = t, + h = n, + function t(e) { + return e.delegateTarget = u, + t.oneOff && y.off(u, e.type, h), + h.apply(u, [e]) + } + )).delegationSelector = r ? n : null, + e.originalHandler = s, + e.oneOff = o, + l[e.uidEvent = c] = e, + t.addEventListener(a, e, r))) + } + function f(t, e, n, i, o) { + i = v(e[n], i, o); + i && (t.removeEventListener(n, i, Boolean(o)), + delete e[n][i.uidEvent]) + } + const y = { + on(t, e, n, i) { + s(t, e, n, i, !1) + }, + one(t, e, n, i) { + s(t, e, n, i, !0) + }, + extend(i, t, o) { + t.forEach(t=>{ + y.on(i, "".concat(t.name, ".bs.").concat(o), e=>{ + const n = {}; + t.parametersToCopy && t.parametersToCopy.forEach(t=>{ + n[t] = e[t] + } + ), + y.trigger(i, "".concat(t.name, ".mdb.").concat(o), n).defaultPrevented && e.preventDefault() + } + ) + } + ) + }, + off(s, a, t, e) { + if ("string" == typeof a && s) { + const [n,i,o] = _(a, t, e) + , r = o !== a + , l = b(s); + e = "." === a.charAt(0); + if (void 0 !== i) + return l && l[o] ? void f(s, l, o, i, n ? t : null) : void 0; + e && Object.keys(l).forEach(t=>{ + { + var e = s + , n = l + , i = t + , o = a.slice(1); + const r = n[i] || {}; + Object.keys(r).forEach(t=>{ + -1 < t.indexOf(o) && (t = r[t], + f(e, n, i, t.originalHandler, t.delegationSelector)) + } + ) + } + } + ); + const c = l[o] || {}; + Object.keys(c).forEach(t=>{ + var e = t.replace(u, ""); + (!r || -1 < a.indexOf(e)) && (e = c[t], + f(s, l, o, e.originalHandler, e.delegationSelector)) + } + ) + } + }, + trigger(t, e, n) { + if ("string" != typeof e || !t) + return null; + var i = e.replace(d, "") + , o = e !== i + , r = -1 < p.indexOf(i); + let s, a = !0, l = !0, c = !1, u = null; + return o && h && (s = h.Event(e, n), + h(t).trigger(s), + a = !s.isPropagationStopped(), + l = !s.isImmediatePropagationStopped(), + c = s.isDefaultPrevented()), + r ? (u = document.createEvent("HTMLEvents")).initEvent(i, a, !0) : u = new CustomEvent(e,{ + bubbles: a, + cancelable: !0 + }), + void 0 !== n && Object.keys(n).forEach(t=>{ + Object.defineProperty(u, t, { + get() { + return n[t] + } + }) + } + ), + c && u.preventDefault(), + l && t.dispatchEvent(u), + u.defaultPrevented && void 0 !== s && s.preventDefault(), + u + } + } + , a = { + on(e, t, n, i) { + var o = t.split(" "); + for (let t = 0; t < o.length; t++) + y.on(e, o[t], n, i) + }, + off(e, t, n, i) { + var o = t.split(" "); + for (let t = 0; t < o.length; t++) + y.off(e, o[t], n, i) + } + }; + e.b = y + } + , function(t, e, n) { + "use strict"; + n(11), + n(12); + e.a = { + closest(t, e) { + return t.closest(e) + }, + matches(t, e) { + return t.matches(e) + }, + find(t) { + var e = 1 < arguments.length && void 0 !== arguments[1] ? arguments[1] : document.documentElement; + return [].concat(...Element.prototype.querySelectorAll.call(e, t)) + }, + findOne(t) { + var e = 1 < arguments.length && void 0 !== arguments[1] ? arguments[1] : document.documentElement; + return Element.prototype.querySelector.call(e, t) + }, + children(t, e) { + return [].concat(...t.children).filter(t=>t.matches(e)) + }, + parents(t, e) { + var n = []; + let i = t.parentNode; + for (; i && i.nodeType === Node.ELEMENT_NODE && 3 !== i.nodeType; ) + this.matches(i, e) && n.push(i), + i = i.parentNode; + return n + }, + prev(t, e) { + let n = t.previousElementSibling; + for (; n; ) { + if (n.matches(e)) + return [n]; + n = n.previousElementSibling + } + return [] + }, + next(t, e) { + let n = t.nextElementSibling; + for (; n; ) { + if (this.matches(n, e)) + return [n]; + n = n.nextElementSibling + } + return [] + } + } + } + , function(t, e, n) { + "use strict"; + n.d(e, "f", function() { + return c + }), + n.d(e, "e", function() { + return i + }), + n.d(e, "d", function() { + return r + }), + n.d(e, "c", function() { + return s + }), + n.d(e, "j", function() { + return a + }), + n.d(e, "h", function() { + return l + }), + n.d(e, "a", function() { + return d + }), + n.d(e, "b", function() { + return p + }), + n.d(e, "i", function() { + return u + }), + n.d(e, "g", function() { + return h + }); + n(17), + n(75), + n(72); + const i = t=>{ + for (; t += Math.floor(1e6 * Math.random()), + document.getElementById(t); ) + ; + return t + } + , o = t=>{ + let e = t.getAttribute("data-mdb-target"); + return e && "#" !== e || (t = t.getAttribute("href"), + e = t && "#" !== t ? t.trim() : null), + e + } + , r = t=>{ + t = o(t); + return t && document.querySelector(t) ? t : null + } + , s = t=>{ + t = o(t); + return t ? document.querySelector(t) : null + } + ; + const a = (o,r,s)=>{ + Object.keys(s).forEach(t=>{ + var e, n = s[t], i = r[t], i = i && ((e = i)[0] || e).nodeType ? "element" : null == (e = i) ? "".concat(e) : {}.toString.call(e).match(/\s([a-z]+)/i)[1].toLowerCase(); + if (!new RegExp(n).test(i)) + throw new Error("".concat(o.toUpperCase(), ": ") + 'Option "'.concat(t, '" provided type "').concat(i, '" ') + 'but expected type "'.concat(n, '".')) + } + ) + } + , l = t=>{ + var e; + return !!t && !!(t.style && t.parentNode && t.parentNode.style) && (e = getComputedStyle(t), + t = getComputedStyle(t.parentNode), + "none" !== e.display) && "none" !== t.display && "hidden" !== e.visibility + } + ; + const c = ()=>{ + var t = window["jQuery"]; + return t && !document.body.hasAttribute("data-mdb-no-jquery") ? t : null + } + , u = t=>{ + "loading" === document.readyState ? document.addEventListener("DOMContentLoaded", t) : t() + } + , h = "rtl" === document.documentElement.dir + , d = t=>Array.from(t) + , p = t=>document.createElement(t) + } + , function(t, e, n) { + "use strict"; + n.d(e, "a", function() { + return w + }), + n.d(e, "b", function() { + return O + }), + n.d(e, "c", function() { + return x + }), + n.d(e, "d", function() { + return g + }), + n.d(e, "e", function() { + return d + }), + n.d(e, "f", function() { + return c + }), + n.d(e, "j", function() { + return v + }), + n.d(e, "g", function() { + return S + }), + n.d(e, "h", function() { + return l + }), + n.d(e, "i", function() { + return o + }), + n.d(e, "k", function() { + return f + }), + n.d(e, "l", function() { + return h + }), + n.d(e, "m", function() { + return y + }), + n.d(e, "n", function() { + return p + }), + n.d(e, "o", function() { + return m + }), + n.d(e, "p", function() { + return b + }), + n.d(e, "r", function() { + return u + }), + n.d(e, "q", function() { + return i + }); + n(17), + n(28), + n(75), + n(11), + n(12); + const r = 1e3 + , s = "transitionend" + , i = t=>null == t ? "".concat(t) : Object.prototype.toString.call(t).match(/\s([a-z]+)/i)[1].toLowerCase() + , o = t=>{ + for (; t += Math.floor(1e6 * Math.random()), + document.getElementById(t); ) + ; + return t + } + , a = e=>{ + let n = e.getAttribute("data-mdb-target"); + if (!n || "#" === n) { + let t = e.getAttribute("href"); + if (!t || !t.includes("#") && !t.startsWith(".")) + return null; + t.includes("#") && !t.startsWith("#") && (t = "#".concat(t.split("#")[1])), + n = t && "#" !== t ? t.trim() : null + } + return n + } + , l = t=>{ + t = a(t); + return t && document.querySelector(t) ? t : null + } + , c = t=>{ + t = a(t); + return t ? document.querySelector(t) : null + } + , u = t=>{ + t.dispatchEvent(new Event(s)) + } + , h = t=>!(!t || "object" != typeof t) && void 0 !== (t = void 0 !== t.jquery ? t[0] : t).nodeType + , d = t=>h(t) ? t.jquery ? t[0] : t : "string" == typeof t && 0 < t.length ? document.querySelector(t) : null + , p = t=>{ + if (!h(t) || 0 === t.getClientRects().length) + return !1; + var e = "visible" === getComputedStyle(t).getPropertyValue("visibility") + , n = t.closest("details:not([open])"); + if (n && n !== t) { + t = t.closest("summary"); + if (t && t.parentNode !== n) + return !1; + if (null === t) + return !1 + } + return e + } + , f = t=>!t || t.nodeType !== Node.ELEMENT_NODE || !!t.classList.contains("disabled") || (void 0 !== t.disabled ? t.disabled : t.hasAttribute("disabled") && "false" !== t.getAttribute("disabled")) + , g = t=>{ + var e; + return document.documentElement.attachShadow ? "function" == typeof t.getRootNode ? (e = t.getRootNode())instanceof ShadowRoot ? e : null : t instanceof ShadowRoot ? t : t.parentNode ? g(t.parentNode) : null : null + } + , m = ()=>{} + , b = t=>{ + t.offsetHeight + } + , v = ()=>window.jQuery && !document.body.hasAttribute("data-mdb-no-jquery") ? window.jQuery : null + , _ = [] + , y = ()=>"rtl" === document.documentElement.dir + , w = i=>{ + var t; + t = ()=>{ + const t = v(); + if (t) { + const e = i.NAME + , n = t.fn[e]; + t.fn[e] = i.jQueryInterface, + t.fn[e].Constructor = i, + t.fn[e].noConflict = ()=>(t.fn[e] = n, + i.jQueryInterface) + } + } + , + "loading" === document.readyState ? (_.length || document.addEventListener("DOMContentLoaded", ()=>{ + for (const t of _) + t() + } + ), + _.push(t)) : t() + } + , O = t=>{ + "function" == typeof t && t() + } + , x = function(n, i) { + if (!(2 < arguments.length && void 0 !== arguments[2]) || arguments[2]) { + var t = (t=>{ + if (!t) + return 0; + let {transitionDuration: e, transitionDelay: n} = window.getComputedStyle(t); + var t = Number.parseFloat(e) + , i = Number.parseFloat(n); + return t || i ? (e = e.split(",")[0], + n = n.split(",")[0], + (Number.parseFloat(e) + Number.parseFloat(n)) * r) : 0 + } + )(i) + 5; + let e = !1; + const o = t=>{ + t = t.target; + t === i && (e = !0, + i.removeEventListener(s, o), + O(n)) + } + ; + i.addEventListener(s, o), + setTimeout(()=>{ + e || u(i) + } + , t) + } else + O(n) + } + , S = (t,e,n,i)=>{ + var o = t.length; + let r = t.indexOf(e); + return -1 === r ? !n && i ? t[o - 1] : t[0] : (r += n ? 1 : -1, + i && (r = (r + o) % o), + t[Math.max(0, Math.min(r, o - 1))]) + } + } + , function(t, e, n) { + "use strict"; + n.d(e, "u", function() { + return i + }), + n.d(e, "i", function() { + return o + }), + n.d(e, "s", function() { + return r + }), + n.d(e, "l", function() { + return s + }), + n.d(e, "d", function() { + return a + }), + n.d(e, "e", function() { + return l + }), + n.d(e, "t", function() { + return c + }), + n.d(e, "k", function() { + return u + }), + n.d(e, "j", function() { + return h + }), + n.d(e, "w", function() { + return d + }), + n.d(e, "p", function() { + return p + }), + n.d(e, "r", function() { + return f + }), + n.d(e, "v", function() { + return g + }), + n.d(e, "o", function() { + return m + }), + n.d(e, "g", function() { + return b + }), + n.d(e, "q", function() { + return v + }), + n.d(e, "b", function() { + return _ + }), + n.d(e, "f", function() { + return y + }), + n.d(e, "m", function() { + return w + }), + n.d(e, "a", function() { + return O + }), + n.d(e, "h", function() { + return x + }), + n.d(e, "x", function() { + return S + }), + n.d(e, "c", function() { + return C + }), + n.d(e, "n", function() { + return E + }); + var i = "top" + , o = "bottom" + , r = "right" + , s = "left" + , a = "auto" + , l = [i, o, r, s] + , c = "start" + , u = "end" + , h = "clippingParents" + , d = "viewport" + , p = "popper" + , f = "reference" + , g = l.reduce(function(t, e) { + return t.concat([e + "-" + c, e + "-" + u]) + }, []) + , m = [].concat(l, [a]).reduce(function(t, e) { + return t.concat([e, e + "-" + c, e + "-" + u]) + }, []) + , b = "beforeRead" + , v = "read" + , _ = "afterRead" + , y = "beforeMain" + , w = "main" + , O = "afterMain" + , x = "beforeWrite" + , S = "write" + , C = "afterWrite" + , E = [b, v, _, y, w, O, x, S, C] + } + , function(t, e, n) { + "use strict"; + n(11), + n(12), + n(17), + n(53), + n(28); + var l = n(4); + const g = /[^.]*(?=\..*)\.|.*/ + , i = /\..*/ + , y = /::\d+$/ + , o = {}; + let r = 1; + const m = { + mouseenter: "mouseover", + mouseleave: "mouseout" + } + , s = new Set(["click", "dblclick", "mouseup", "mousedown", "contextmenu", "mousewheel", "DOMMouseScroll", "mouseover", "mouseout", "mousemove", "selectstart", "selectend", "keydown", "keypress", "keyup", "orientationchange", "touchstart", "touchmove", "touchend", "touchcancel", "pointerdown", "pointermove", "pointerup", "pointerleave", "pointercancel", "gesturestart", "gesturechange", "gestureend", "focus", "blur", "change", "reset", "select", "submit", "focusin", "focusout", "load", "unload", "beforeunload", "resize", "move", "DOMContentLoaded", "readystatechange", "error", "abort", "scroll"]); + function b(t, e) { + return e && "".concat(e, "::").concat(r++) || t.uidEvent || r++ + } + function w(t) { + var e = b(t); + return t.uidEvent = e, + o[e] = o[e] || {}, + o[e] + } + function v(t, e, n) { + let i = 2 < arguments.length && void 0 !== n ? n : null; + return Object.values(t).find(t=>t.callable === e && t.delegationSelector === i) + } + function O(t, e, n) { + var i = "string" == typeof e + , e = !i && e || n; + let o = c(t); + return [i, e, o = s.has(o) ? o : t] + } + function a(i, o, r, s, a) { + if ("string" == typeof o && i) { + let[t,e,n] = O(o, r, s); + o in m && (e = (l = e, + function(t) { + if (!t.relatedTarget || t.relatedTarget !== t.delegateTarget && !t.delegateTarget.contains(t.relatedTarget)) + return l.call(this, t) + } + )); + var l, c, u, h, d, p, s = w(i), s = s[n] || (s[n] = {}), f = v(s, e, t ? r : null); + f ? f.oneOff = f.oneOff && a : (f = b(e, o.replace(g, "")), + (o = t ? (h = i, + d = r, + p = e, + function e(n) { + var i = h.querySelectorAll(d); + for (let t = n["target"]; t && t !== this; t = t.parentNode) + for (const o of i) + if (o === t) + return S(n, { + delegateTarget: t + }), + e.oneOff && _.off(h, n.type, d, p), + p.apply(t, [n]) + } + ) : (c = i, + u = e, + function t(e) { + return S(e, { + delegateTarget: c + }), + t.oneOff && _.off(c, e.type, u), + u.apply(c, [e]) + } + )).delegationSelector = t ? r : null, + o.callable = e, + o.oneOff = a, + s[o.uidEvent = f] = o, + i.addEventListener(n, o, t)) + } + } + function x(t, e, n, i, o) { + i = v(e[n], i, o); + i && (t.removeEventListener(n, i, Boolean(o)), + delete e[n][i.uidEvent]) + } + function c(t) { + return t = t.replace(i, ""), + m[t] || t + } + const _ = { + on(t, e, n, i) { + a(t, e, n, i, !1) + }, + one(t, e, n, i) { + a(t, e, n, i, !0) + }, + off(t, e, n, i) { + if ("string" == typeof e && t) { + var [i,o,r] = O(e, n, i) + , s = r !== e + , a = w(t) + , l = a[r] || {} + , c = e.startsWith("."); + if (void 0 !== o) + return Object.keys(l).length ? void x(t, a, r, o, i ? n : null) : void 0; + if (c) + for (const b of Object.keys(a)) { + u = g = f = p = d = h = void 0; + var u, h = t, d = a, p = b, f = e.slice(1), g = d[p] || {}; + for (const v of Object.keys(g)) + v.includes(f) && x(h, d, p, (u = g[v]).callable, u.delegationSelector) + } + for (const _ of Object.keys(l)) { + var m = _.replace(y, ""); + s && !e.includes(m) || x(t, a, r, (m = l[_]).callable, m.delegationSelector) + } + } + }, + trigger(t, e, n) { + if ("string" != typeof e || !t) + return null; + var i = Object(l.j)(); + let o = null + , r = !0 + , s = !0 + , a = !1; + e !== c(e) && i && (o = i.Event(e, n), + i(t).trigger(o), + r = !o.isPropagationStopped(), + s = !o.isImmediatePropagationStopped(), + a = o.isDefaultPrevented()); + i = S(i = new Event(e,{ + bubbles: r, + cancelable: !0 + }), n); + return a && i.preventDefault(), + s && t.dispatchEvent(i), + i.defaultPrevented && o && o.preventDefault(), + i + } + }; + function S(e, t) { + for (const [n,i] of Object.entries(t || {})) + try { + e[n] = i + } catch (t) { + Object.defineProperty(e, n, { + configurable: !0, + get() { + return i + } + }) + } + return e + } + e.a = _ + } + , function(t, e, n) { + "use strict"; + const i = (()=>{ + const i = {}; + let o = 1; + return { + set(t, e, n) { + void 0 === t[e] && (t[e] = { + key: e, + id: o + }, + o++), + i[t[e].id] = n + }, + get(t, e) { + return t && void 0 !== t[e] && (t = t[e]).key === e ? i[t.id] : null + }, + delete(t, e) { + var n; + void 0 !== t[e] && (n = t[e]).key === e && (delete i[n.id], + delete t[e]) + } + } + } + )(); + e.a = { + setData(t, e, n) { + i.set(t, e, n) + }, + getData(t, e) { + return i.get(t, e) + }, + removeData(t, e) { + i.delete(t, e) + } + } + } + , function(t, e, n) { + "use strict"; + n(11), + n(12); + var i = n(4); + e.a = { + find(t) { + var e = 1 < arguments.length && void 0 !== arguments[1] ? arguments[1] : document.documentElement; + return [].concat(...Element.prototype.querySelectorAll.call(e, t)) + }, + findOne(t) { + var e = 1 < arguments.length && void 0 !== arguments[1] ? arguments[1] : document.documentElement; + return Element.prototype.querySelector.call(e, t) + }, + children(t, e) { + return [].concat(...t.children).filter(t=>t.matches(e)) + }, + parents(t, e) { + var n = []; + let i = t.parentNode.closest(e); + for (; i; ) + n.push(i), + i = i.parentNode.closest(e); + return n + }, + prev(t, e) { + let n = t.previousElementSibling; + for (; n; ) { + if (n.matches(e)) + return [n]; + n = n.previousElementSibling + } + return [] + }, + next(t, e) { + let n = t.nextElementSibling; + for (; n; ) { + if (n.matches(e)) + return [n]; + n = n.nextElementSibling + } + return [] + }, + focusableChildren(t) { + var e = ["a", "button", "input", "textarea", "select", "details", "[tabindex]", '[contenteditable="true"]'].map(t=>"".concat(t, ':not([tabindex^="-"])')).join(","); + return this.find(e, t).filter(t=>!Object(i.k)(t) && Object(i.n)(t)) + } + } + } + , function(t, e, n) { + "use strict"; + n.d(e, "h", function() { + return i + }), + n.d(e, "n", function() { + return o + }), + n.d(e, "k", function() { + return r + }), + n.d(e, "c", function() { + return s + }), + n.d(e, "g", function() { + return a + }), + n.d(e, "d", function() { + return l + }), + n.d(e, "j", function() { + return c + }), + n.d(e, "i", function() { + return u + }), + n.d(e, "e", function() { + return h + }), + n.d(e, "l", function() { + return d + }), + n.d(e, "f", function() { + return p + }), + n.d(e, "m", function() { + return f + }), + n.d(e, "a", function() { + return g + }), + n.d(e, "b", function() { + return m + }); + const i = 37 + , o = 38 + , r = 39 + , s = 40 + , a = 36 + , l = 35 + , c = 33 + , u = 34 + , h = 13 + , d = 32 + , p = 27 + , f = 9 + , g = 8 + , m = 46 + } + , function(t, e, n) { + "use strict"; + n.d(e, "a", function() { + return o + }), + n.d(e, "b", function() { + return r + }), + n.d(e, "c", function() { + return s + }); + var i = n(19); + function o(t) { + return t instanceof Object(i.a)(t).Element || t instanceof Element + } + function r(t) { + return t instanceof Object(i.a)(t).HTMLElement || t instanceof HTMLElement + } + function s(t) { + return "undefined" != typeof ShadowRoot && (t instanceof Object(i.a)(t).ShadowRoot || t instanceof ShadowRoot) + } + } + , function(t, e, n) { + "use strict"; + var i = n(77) + , o = n(158) + , r = n(81) + , s = n(46) + , a = n(40).f + , l = n(161) + , c = n(165) + , u = n(43) + , n = n(23) + , h = "Array Iterator" + , d = s.set + , p = s.getterFor(h) + , s = (t.exports = l(Array, "Array", function(t, e) { + d(this, { + type: h, + target: i(t), + index: 0, + kind: e + }) + }, function() { + var t = p(this) + , e = t.target + , n = t.kind + , i = t.index++; + if (!e || i >= e.length) + return t.target = void 0, + c(void 0, !0); + switch (n) { + case "keys": + return c(i, !1); + case "values": + return c(e[i], !1) + } + return c([i, e[i]], !1) + }, "values"), + r.Arguments = r.Array); + if (o("keys"), + o("values"), + o("entries"), + !u && n && "values" !== s.name) + try { + a(s, "name", { + value: "values" + }) + } catch (t) {} + } + , function(t, e, n) { + "use strict"; + function i(e, t) { + if (e) { + if (e[u] !== d) + try { + c(e, u, d) + } catch (t) { + e[u] = d + } + if (e[h] || c(e, h, t), + s[t]) + for (var n in l) + if (e[n] !== l[n]) + try { + c(e, n, l[n]) + } catch (t) { + e[n] = l[n] + } + } + } + var o, r = n(13), s = n(217), a = n(218), l = n(11), c = n(57), n = n(20), u = n("iterator"), h = n("toStringTag"), d = l.values; + for (o in s) + i(r[o] && r[o].prototype, o); + i(a, "DOMTokenList") + } + , function(n, t, e) { + "use strict"; + !function(t) { + function e(t) { + return t && t.Math === Math && t + } + n.exports = e("object" == typeof globalThis && globalThis) || e("object" == typeof window && window) || e("object" == typeof self && self) || e("object" == typeof t && t) || function() { + return this + }() || this || Function("return this")() + } + .call(this, e(206)) + } + , function(t, e, n) { + "use strict"; + var n = n(89) + , i = Function.prototype + , o = i.call + , i = n && i.bind.bind(o, o); + t.exports = n ? i : function(t) { + return function() { + return o.apply(t, arguments) + } + } + } + , function(t, e, n) { + "use strict"; + var n = n(143) + , i = n.all; + t.exports = n.IS_HTMLDDA ? function(t) { + return "function" == typeof t || t === i + } + : function(t) { + return "function" == typeof t + } + } + , function(t, e, n) { + "use strict"; + t.exports = function(t) { + try { + return !!t() + } catch (t) { + return !0 + } + } + } + , function(t, e, n) { + "use strict"; + var i = n(26) + , n = n(124); + i({ + target: "RegExp", + proto: !0, + forced: /./.exec !== n + }, { + exec: n + }) + } + , function(t, e, n) { + "use strict"; + n.d(e, "a", function() { + return i + }), + n.d(e, "b", function() { + return o + }), + n.d(e, "c", function() { + return r + }); + var i = Math.max + , o = Math.min + , r = Math.round + } + , function(t, e, n) { + "use strict"; + function i(t) { + var e; + return null == t ? window : "[object Window]" !== t.toString() ? (e = t.ownerDocument) && e.defaultView || window : t + } + n.d(e, "a", function() { + return i + }) + } + , function(t, e, n) { + "use strict"; + var i = n(13) + , o = n(114) + , r = n(29) + , s = n(147) + , a = n(146) + , n = n(145) + , l = i.Symbol + , c = o("wks") + , u = n ? l.for || l : l && l.withoutSetter || s; + t.exports = function(t) { + return r(c, t) || (c[t] = a && r(l, t) ? l[t] : u("Symbol." + t)), + c[t] + } + } + , function(t, e, n) { + "use strict"; + n(11), + n(12); + const i = new Map; + var o = function(t, e, n) { + i.has(t) || i.set(t, new Map); + t = i.get(t); + t.has(e) || 0 === t.size ? t.set(e, n) : console.error("Bootstrap doesn't allow more than one instance per element. Bound instance: ".concat(Array.from(t.keys())[0], ".")) + } + , r = function(t, e) { + return i.has(t) && i.get(t).get(e) || null + } + , s = function(t, e) { + var n; + i.has(t) && ((n = i.get(t)).delete(e), + 0 === n.size) && i.delete(t) + } + , a = n(4) + , l = n(6) + , n = n(45); + class c extends n.a { + constructor(t, e) { + super(), + (t = Object(a.e)(t)) && (this._element = t, + this._config = this._getConfig(e), + o(this._element, this.constructor.DATA_KEY, this)) + } + dispose() { + s(this._element, this.constructor.DATA_KEY), + l.a.off(this._element, this.constructor.EVENT_KEY); + for (const t of Object.getOwnPropertyNames(this)) + this[t] = null + } + _queueCallback(t, e) { + var n = !(2 < arguments.length && void 0 !== arguments[2]) || arguments[2]; + Object(a.c)(t, e, n) + } + _getConfig(t) { + return t = this._mergeConfigObj(t, this._element), + t = this._configAfterMerge(t), + this._typeCheckConfig(t), + t + } + static getInstance(t) { + return r(Object(a.e)(t), this.DATA_KEY) + } + static getOrCreateInstance(t) { + var e = 1 < arguments.length && void 0 !== arguments[1] ? arguments[1] : {}; + return this.getInstance(t) || new this(t,"object" == typeof e ? e : null) + } + static get VERSION() { + return "5.2.3" + } + static get DATA_KEY() { + return "bs.".concat(this.NAME) + } + static get EVENT_KEY() { + return ".".concat(this.DATA_KEY) + } + static eventName(t) { + return "".concat(t).concat(this.EVENT_KEY) + } + } + e.a = c + } + , function(t, e, n) { + "use strict"; + var n = n(89) + , i = Function.prototype.call; + t.exports = n ? i.bind(i) : function() { + return i.apply(i, arguments) + } + } + , function(t, e, n) { + "use strict"; + n = n(16); + t.exports = !n(function() { + return 7 !== Object.defineProperty({}, 1, { + get: function() { + return 7 + } + })[1] + }) + } + , function(t, e, n) { + "use strict"; + function i(t) { + return t ? (t.nodeName || "").toLowerCase() : null + } + n.d(e, "a", function() { + return i + }) + } + , function(t, e, n) { + "use strict"; + function i(t) { + return t.split("-")[0] + } + n.d(e, "a", function() { + return i + }) + } + , function(t, e, n) { + "use strict"; + var c = n(13) + , u = n(111).f + , h = n(57) + , d = n(41) + , p = n(116) + , f = n(151) + , g = n(122); + t.exports = function(t, e) { + var n, i, o, r = t.target, s = t.global, a = t.stat, l = s ? c : a ? c[r] || p(r, {}) : (c[r] || {}).prototype; + if (l) + for (n in e) { + if (i = e[n], + o = t.dontCallGetSet ? (o = u(l, n)) && o.value : l[n], + !g(s ? n : r + (a ? "." : "#") + n, t.forced) && void 0 !== o) { + if (typeof i == typeof o) + continue; + f(i, o) + } + (t.sham || o && o.sham) && h(i, "sham", !0), + d(l, n, i, t) + } + } + } + , function(t, e, n) { + "use strict"; + n.d(e, "a", function() { + return o + }); + var i = n(10); + function o(t) { + return ((Object(i.a)(t) ? t.ownerDocument : t.document) || window.document).documentElement + } + } + , function(t, e, n) { + "use strict"; + var i = n(26) + , o = n(154).includes + , r = n(16) + , n = n(158); + i({ + target: "Array", + proto: !0, + forced: r(function() { + return !Array(1).includes() + }) + }, { + includes: function(t) { + return o(this, t, 1 < arguments.length ? arguments[1] : void 0) + } + }), + n("includes") + } + , function(t, e, n) { + "use strict"; + var i = n(14) + , o = n(50) + , r = i({}.hasOwnProperty); + t.exports = Object.hasOwn || function(t, e) { + return r(o(t), e) + } + } + , function(t, e, n) { + "use strict"; + var i = n(35) + , o = String + , r = TypeError; + t.exports = function(t) { + if (i(t)) + return t; + throw r(o(t) + " is not an object") + } + } + , , function(t, e, n) { + "use strict"; + n.d(e, "a", function() { + return i + }); + var d = n(5) + , h = n(19) + , p = n(27) + , f = n(66) + , g = n(106); + var m = n(33) + , b = n(67) + , v = n(18); + var a = n(70) + , l = n(42) + , _ = n(10) + , y = n(36) + , c = n(47) + , u = n(107) + , w = n(24); + function O(t) { + return Object.assign({}, t, { + left: t.x, + top: t.y, + right: t.x + t.width, + bottom: t.y + t.height + }) + } + function x(t, e, n) { + return e === d.w ? O((i = t, + o = n, + s = Object(h.a)(i), + a = Object(p.a)(i), + s = s.visualViewport, + l = a.clientWidth, + a = a.clientHeight, + u = c = 0, + s && (l = s.width, + a = s.height, + (r = Object(g.a)()) || !r && "fixed" === o) && (c = s.offsetLeft, + u = s.offsetTop), + { + width: l, + height: a, + x: c + Object(f.a)(i), + y: u + })) : Object(_.a)(e) ? (r = e, + o = n, + (o = Object(y.a)(r, !1, "fixed" === o)).top = o.top + r.clientTop, + o.left = o.left + r.clientLeft, + o.bottom = o.top + r.clientHeight, + o.right = o.left + r.clientWidth, + o.width = r.clientWidth, + o.height = r.clientHeight, + o.x = o.left, + o.y = o.top, + o) : O((s = Object(p.a)(t), + l = Object(p.a)(s), + a = Object(b.a)(s), + c = null == (c = s.ownerDocument) ? void 0 : c.body, + i = Object(v.a)(l.scrollWidth, l.clientWidth, c ? c.scrollWidth : 0, c ? c.clientWidth : 0), + u = Object(v.a)(l.scrollHeight, l.clientHeight, c ? c.scrollHeight : 0, c ? c.clientHeight : 0), + s = -a.scrollLeft + Object(f.a)(s), + a = -a.scrollTop, + "rtl" === Object(m.a)(c || l).direction && (s += Object(v.a)(l.clientWidth, c ? c.clientWidth : 0) - i), + { + width: i, + height: u, + x: s, + y: a + })); + var i, o, r, s, a, l, c, u + } + function S(n, t, e, i) { + var o, r = "clippingParents" === t ? (r = n, + s = Object(a.a)(Object(c.a)(r)), + o = 0 <= ["absolute", "fixed"].indexOf(Object(m.a)(r).position) && Object(_.b)(r) ? Object(l.a)(r) : r, + Object(_.a)(o) ? s.filter(function(t) { + return Object(_.a)(t) && Object(u.a)(t, o) && "body" !== Object(w.a)(t) + }) : []) : [].concat(t), s = [].concat(r, [e]), t = s[0], e = s.reduce(function(t, e) { + e = x(n, e, i); + return t.top = Object(v.a)(e.top, t.top), + t.right = Object(v.b)(e.right, t.right), + t.bottom = Object(v.b)(e.bottom, t.bottom), + t.left = Object(v.a)(e.left, t.left), + t + }, x(n, t, i)); + return e.width = e.right - e.left, + e.height = e.bottom - e.top, + e.x = e.left, + e.y = e.top, + e + } + var C = n(108) + , E = n(103) + , k = n(105); + function i(t, e) { + var i, e = e = void 0 === e ? {} : e, n = e.placement, n = void 0 === n ? t.placement : n, o = e.strategy, o = void 0 === o ? t.strategy : o, r = e.boundary, r = void 0 === r ? d.j : r, s = e.rootBoundary, s = void 0 === s ? d.w : s, a = e.elementContext, a = void 0 === a ? d.p : a, l = e.altBoundary, l = void 0 !== l && l, e = e.padding, e = void 0 === e ? 0 : e, e = Object(E.a)("number" != typeof e ? e : Object(k.a)(e, d.e)), c = a === d.p ? d.r : d.p, u = t.rects.popper, l = t.elements[l ? c : a], c = S(Object(_.a)(l) ? l : l.contextElement || Object(p.a)(t.elements.popper), r, s, o), l = Object(y.a)(t.elements.reference), r = Object(C.a)({ + reference: l, + element: u, + strategy: "absolute", + placement: n + }), s = O(Object.assign({}, u, r)), o = a === d.p ? s : l, h = { + top: c.top - o.top + e.top, + bottom: o.bottom - c.bottom + e.bottom, + left: c.left - o.left + e.left, + right: o.right - c.right + e.right + }, u = t.modifiersData.offset; + return a === d.p && u && (i = u[n], + Object.keys(h).forEach(function(t) { + var e = 0 <= [d.s, d.i].indexOf(t) ? 1 : -1 + , n = 0 <= [d.u, d.i].indexOf(t) ? "y" : "x"; + h[t] += i[n] * e + })), + h + } + } + , function(t, e, n) { + "use strict"; + n.d(e, "a", function() { + return o + }); + var i = n(19); + function o(t) { + return Object(i.a)(t).getComputedStyle(t) + } + } + , function(t, e, n) { + "use strict"; + n(17), + n(53), + n(11), + n(12); + function o(e) { + if ("true" === e) + return !0; + if ("false" === e) + return !1; + if (e === Number(e).toString()) + return Number(e); + if ("" === e || "null" === e) + return null; + if ("string" != typeof e) + return e; + try { + return JSON.parse(decodeURIComponent(e)) + } catch (t) { + return e + } + } + function i(t) { + return t.replace(/[A-Z]/g, t=>"-".concat(t.toLowerCase())) + } + e.a = { + setDataAttribute(t, e, n) { + t.setAttribute("data-mdb-".concat(i(e)), n) + }, + removeDataAttribute(t, e) { + t.removeAttribute("data-mdb-".concat(i(e))) + }, + getDataAttributes(e) { + if (!e) + return {}; + var n = {}; + for (const i of Object.keys(e.dataset).filter(t=>t.startsWith("mdb") && !t.startsWith("mdbConfig"))) { + let t = i.replace(/^mdb/, ""); + n[t = t.charAt(0).toLowerCase() + t.slice(1, t.length)] = o(e.dataset[i]) + } + return n + }, + getDataAttribute(t, e) { + return o(t.getAttribute("data-mdb-".concat(i(e)))) + } + } + } + , function(t, e, n) { + "use strict"; + var i = n(15) + , n = n(143) + , o = n.all; + t.exports = n.IS_HTMLDDA ? function(t) { + return "object" == typeof t ? null !== t : i(t) || t === o + } + : function(t) { + return "object" == typeof t ? null !== t : i(t) + } + } + , function(t, e, n) { + "use strict"; + n.d(e, "a", function() { + return i + }); + var s = n(10) + , a = n(18) + , l = n(19) + , c = n(106); + function i(t, e, n) { + void 0 === e && (e = !1), + void 0 === n && (n = !1); + var i = t.getBoundingClientRect() + , o = 1 + , r = 1; + e && Object(s.b)(t) && (o = 0 < t.offsetWidth && Object(a.c)(i.width) / t.offsetWidth || 1, + r = 0 < t.offsetHeight && Object(a.c)(i.height) / t.offsetHeight || 1); + e = (Object(s.a)(t) ? Object(l.a)(t) : window).visualViewport, + t = !Object(c.a)() && n, + n = (i.left + (t && e ? e.offsetLeft : 0)) / o, + t = (i.top + (t && e ? e.offsetTop : 0)) / r, + e = i.width / o, + o = i.height / r; + return { + width: e, + height: o, + top: t, + right: n + e, + bottom: t + o, + left: n, + x: n, + y: t + } + } + } + , function(t, e, n) { + "use strict"; + function i(t) { + return t.split("-")[1] + } + n.d(e, "a", function() { + return i + }) + } + , function(t, e, n) { + "use strict"; + var i = n(93) + , o = String; + t.exports = function(t) { + if ("Symbol" === i(t)) + throw TypeError("Cannot convert a Symbol value to a string"); + return o(t) + } + } + , function(t, e, n) { + "use strict"; + var i = n(15) + , o = n(78) + , r = TypeError; + t.exports = function(t) { + if (i(t)) + return t; + throw r(o(t) + " is not a function") + } + } + , function(t, e, n) { + "use strict"; + var i = n(23) + , o = n(148) + , r = n(149) + , s = n(30) + , a = n(113) + , l = TypeError + , c = Object.defineProperty + , u = Object.getOwnPropertyDescriptor + , h = "enumerable" + , d = "configurable" + , p = "writable"; + e.f = i ? r ? function(t, e, n) { + var i; + return s(t), + e = a(e), + s(n), + "function" == typeof t && "prototype" === e && "value"in n && p in n && !n[p] && (i = u(t, e)) && i[p] && (t[e] = n.value, + n = { + configurable: (d in n ? n : i)[d], + enumerable: (h in n ? n : i)[h], + writable: !1 + }), + c(t, e, n) + } + : c : function(t, e, n) { + if (s(t), + e = a(e), + s(n), + o) + try { + return c(t, e, n) + } catch (t) {} + if ("get"in n || "set"in n) + throw l("Accessors not supported"); + return "value"in n && (t[e] = n.value), + t + } + } + , function(t, e, n) { + "use strict"; + var s = n(15) + , a = n(40) + , l = n(150) + , c = n(116); + t.exports = function(t, e, n, i) { + var o = (i = i || {}).enumerable + , r = void 0 !== i.name ? i.name : e; + if (s(n) && l(n, r, i), + i.global) + o ? t[e] = n : c(e, n); + else { + try { + i.unsafe ? t[e] && (o = !0) : delete t[e] + } catch (t) {} + o ? t[e] = n : a.f(t, e, { + value: n, + enumerable: !1, + configurable: !i.nonConfigurable, + writable: !i.nonWritable + }) + } + return t + } + } + , function(t, e, n) { + "use strict"; + n.d(e, "a", function() { + return i + }); + var o = n(19) + , r = n(24) + , s = n(33) + , a = n(10); + var l = n(47) + , c = n(87); + function u(t) { + return Object(a.b)(t) && "fixed" !== Object(s.a)(t).position ? t.offsetParent : null + } + function i(t) { + for (var e, n = Object(o.a)(t), i = u(t); i && (e = i, + 0 <= ["table", "td", "th"].indexOf(Object(r.a)(e))) && "static" === Object(s.a)(i).position; ) + i = u(i); + return (!i || "html" !== Object(r.a)(i) && ("body" !== Object(r.a)(i) || "static" !== Object(s.a)(i).position)) && (i || function(t) { + var e = /firefox/i.test(Object(c.a)()) + , n = /Trident/i.test(Object(c.a)()); + if (!n || !Object(a.b)(t) || "fixed" !== Object(s.a)(t).position) { + var i = Object(l.a)(t); + for (Object(a.c)(i) && (i = i.host); Object(a.b)(i) && ["html", "body"].indexOf(Object(r.a)(i)) < 0; ) { + var o = Object(s.a)(i); + if ("none" !== o.transform || "none" !== o.perspective || "paint" === o.contain || -1 !== ["transform", "perspective"].indexOf(o.willChange) || e && "filter" === o.willChange || e && o.filter && "none" !== o.filter) + return i; + i = i.parentNode + } + } + return null + }(t)) || n + } + } + , function(t, e, n) { + "use strict"; + t.exports = !1 + } + , function(t, e, n) { + "use strict"; + n.d(e, "b", function() { + return i + }), + n.d(e, "a", function() { + return o + }); + var l = n(36) + , c = n(67) + , u = n(19) + , p = n(10); + var h = n(24) + , d = n(66) + , f = n(27) + , g = n(68) + , m = n(18); + function b(t, e, n) { + void 0 === n && (n = !1); + var i = Object(p.b)(e) + , o = Object(p.b)(e) && (s = (o = e).getBoundingClientRect(), + r = Object(m.c)(s.width) / o.offsetWidth || 1, + s = Object(m.c)(s.height) / o.offsetHeight || 1, + 1 !== r || 1 !== s) + , r = Object(f.a)(e) + , s = Object(l.a)(t, o, n) + , t = { + scrollLeft: 0, + scrollTop: 0 + } + , a = { + x: 0, + y: 0 + }; + return !i && n || ("body" === Object(h.a)(e) && !Object(g.a)(r) || (t = (i = e) !== Object(u.a)(i) && Object(p.b)(i) ? { + scrollLeft: i.scrollLeft, + scrollTop: i.scrollTop + } : Object(c.a)(i)), + Object(p.b)(e) ? ((a = Object(l.a)(e, !0)).x += e.clientLeft, + a.y += e.clientTop) : r && (a.x = Object(d.a)(r))), + { + x: s.left + t.scrollLeft - a.x, + y: s.top + t.scrollTop - a.y, + width: s.width, + height: s.height + } + } + var v = n(65) + , _ = n(70) + , y = n(42) + , w = n(5); + function O(t) { + var n = new Map + , i = new Set + , o = []; + return t.forEach(function(t) { + n.set(t.name, t) + }), + t.forEach(function(t) { + i.has(t.name) || !function e(t) { + i.add(t.name), + [].concat(t.requires || [], t.requiresIfExists || []).forEach(function(t) { + i.has(t) || (t = n.get(t)) && e(t) + }), + o.push(t) + }(t) + }), + o + } + var x = { + placement: "bottom", + modifiers: [], + strategy: "absolute" + }; + function S() { + for (var t = arguments.length, e = new Array(t), n = 0; n < t; n++) + e[n] = arguments[n]; + return !e.some(function(t) { + return !(t && "function" == typeof t.getBoundingClientRect) + }) + } + function i(t) { + var t = t = void 0 === t ? {} : t + , e = t.defaultModifiers + , h = void 0 === e ? [] : e + , e = t.defaultOptions + , d = void 0 === e ? x : e; + return function(i, o, e) { + void 0 === e && (e = d); + var n, r, s = { + placement: "bottom", + orderedModifiers: [], + options: Object.assign({}, x, d), + modifiersData: {}, + elements: { + reference: i, + popper: o + }, + attributes: {}, + styles: {} + }, a = [], l = !1, c = { + state: s, + setOptions: function(t) { + var n, e, t = "function" == typeof t ? t(s.options) : t, t = (u(), + s.options = Object.assign({}, d, s.options, t), + s.scrollParents = { + reference: Object(p.a)(i) ? Object(_.a)(i) : i.contextElement ? Object(_.a)(i.contextElement) : [], + popper: Object(_.a)(o) + }, + t = [].concat(h, s.options.modifiers), + e = t.reduce(function(t, e) { + var n = t[e.name]; + return t[e.name] = n ? Object.assign({}, n, e, { + options: Object.assign({}, n.options, e.options), + data: Object.assign({}, n.data, e.data) + }) : e, + t + }, {}), + t = Object.keys(e).map(function(t) { + return e[t] + }), + n = O(t), + w.n.reduce(function(t, e) { + return t.concat(n.filter(function(t) { + return t.phase === e + })) + }, [])); + return s.orderedModifiers = t.filter(function(t) { + return t.enabled + }), + s.orderedModifiers.forEach(function(t) { + var e = t.name + , n = t.options + , t = t.effect; + "function" == typeof t && (t = t({ + state: s, + name: e, + instance: c, + options: void 0 === n ? {} : n + }), + a.push(t || function() {} + )) + }), + c.update() + }, + forceUpdate: function() { + if (!l) { + var t = s.elements + , e = t.reference + , t = t.popper; + if (S(e, t)) { + s.rects = { + reference: b(e, Object(y.a)(t), "fixed" === s.options.strategy), + popper: Object(v.a)(t) + }, + s.reset = !1, + s.placement = s.options.placement, + s.orderedModifiers.forEach(function(t) { + return s.modifiersData[t.name] = Object.assign({}, t.data) + }); + for (var n, i, o, r = 0; r < s.orderedModifiers.length; r++) + !0 === s.reset ? (s.reset = !1, + r = -1) : (n = (o = s.orderedModifiers[r]).fn, + i = o.options, + o = o.name, + "function" == typeof n && (s = n({ + state: s, + options: void 0 === i ? {} : i, + name: o, + instance: c + }) || s)) + } + } + }, + update: (n = function() { + return new Promise(function(t) { + c.forceUpdate(), + t(s) + } + ) + } + , + function() { + return r = r || new Promise(function(t) { + Promise.resolve().then(function() { + r = void 0, + t(n()) + }) + } + ) + } + ), + destroy: function() { + u(), + l = !0 + } + }; + return S(i, o) && c.setOptions(e).then(function(t) { + !l && e.onFirstUpdate && e.onFirstUpdate(t) + }), + c; + function u() { + a.forEach(function(t) { + return t() + }), + a = [] + } + } + } + var o = i() + } + , function(t, e, n) { + "use strict"; + n(11), + n(12), + n(17), + n(72); + var r = n(4) + , i = n(34); + e.a = class { + static get Default() { + return {} + } + static get DefaultType() { + return {} + } + static get NAME() { + throw new Error('You have to implement the static method "NAME", for each component!') + } + _getConfig(t) { + return t = this._mergeConfigObj(t), + t = this._configAfterMerge(t), + this._typeCheckConfig(t), + t + } + _configAfterMerge(t) { + return t + } + _mergeConfigObj(t, e) { + var n = Object(r.l)(e) ? i.a.getDataAttribute(e, "config") : {}; + return { + ...this.constructor.Default, + ..."object" == typeof n ? n : {}, + ...Object(r.l)(e) ? i.a.getDataAttributes(e) : {}, + ..."object" == typeof t ? t : {} + } + } + _typeCheckConfig(t) { + var e = 1 < arguments.length && void 0 !== arguments[1] ? arguments[1] : this.constructor.DefaultType; + for (const o of Object.keys(e)) { + var n = e[o] + , i = t[o] + , i = Object(r.l)(i) ? "element" : Object(r.q)(i); + if (!new RegExp(n).test(i)) + throw new TypeError("".concat(this.constructor.NAME.toUpperCase(), ': Option "').concat(o, '" provided type "').concat(i, '" but expected type "').concat(n, '".')) + } + } + } + } + , function(t, e, n) { + "use strict"; + var i, o, r, s, a = n(209), l = n(13), c = n(35), u = n(57), h = n(29), d = n(115), p = n(119), n = n(120), f = "Object already initialized", g = l.TypeError, l = l.WeakMap, m = a || d.state ? ((r = d.state || (d.state = new l)).get = r.get, + r.has = r.has, + r.set = r.set, + i = function(t, e) { + if (r.has(t)) + throw g(f); + return e.facade = t, + r.set(t, e), + e + } + , + o = function(t) { + return r.get(t) || {} + } + , + function(t) { + return r.has(t) + } + ) : (n[s = p("state")] = !0, + i = function(t, e) { + if (h(t, s)) + throw g(f); + return e.facade = t, + u(t, s, e), + e + } + , + o = function(t) { + return h(t, s) ? t[s] : {} + } + , + function(t) { + return h(t, s) + } + ); + t.exports = { + set: i, + get: o, + has: m, + enforce: function(t) { + return m(t) ? o(t) : i(t, {}) + }, + getterFor: function(e) { + return function(t) { + if (c(t) && (t = o(t)).type === e) + return t; + throw g("Incompatible receiver, " + e + " required") + } + } + } + } + , function(t, e, n) { + "use strict"; + n.d(e, "a", function() { + return s + }); + var i = n(24) + , o = n(27) + , r = n(10); + function s(t) { + return "html" === Object(i.a)(t) ? t : t.assignedSlot || t.parentNode || (Object(r.c)(t) ? t.host : null) || Object(o.a)(t) + } + } + , function(t, e, n) { + "use strict"; + var i = n(13) + , o = n(15); + t.exports = function(t, e) { + return arguments.length < 2 ? (n = i[t], + o(n) ? n : void 0) : i[t] && i[t][e]; + var n + } + } + , function(t, e, n) { + "use strict"; + t.exports = "undefined" != typeof navigator && String(navigator.userAgent) || "" + } + , function(t, e, n) { + "use strict"; + var i = n(73) + , o = Object; + t.exports = function(t) { + return o(i(t)) + } + } + , function(t, e, n) { + "use strict"; + n.d(e, "a", function() { + return o + }), + n.d(e, "b", function() { + return r + }); + var i = n(18); + function o(t, e, n) { + return Object(i.a)(t, Object(i.b)(e, n)) + } + function r(t, e, n) { + t = o(t, e, n); + return n < t ? n : t + } + } + , function(t, e, n) { + "use strict"; + n(11), + n(12), + n(28), + n(17); + var r = n(4) + , o = n(6) + , s = n(8) + , n = n(21); + var i = ".".concat("bs.collapse"); + const a = "show".concat(i) + , l = "shown".concat(i) + , c = "hide".concat(i) + , u = "hidden".concat(i); + i = "click".concat(i).concat(".data-api"); + const h = "show" + , d = "collapse" + , p = "collapsing" + , f = ":scope .".concat(d, " .").concat(d) + , g = '[data-mdb-toggle="collapse"]' + , m = { + parent: null, + toggle: !0 + } + , b = { + parent: "(null|element)", + toggle: "boolean" + }; + class v extends n.a { + constructor(t, e) { + super(t, e), + this._isTransitioning = !1, + this._triggerArray = []; + for (const o of s.a.find(g)) { + var n = Object(r.h)(o) + , i = s.a.find(n).filter(t=>t === this._element); + null !== n && i.length && this._triggerArray.push(o) + } + this._initializeChildren(), + this._config.parent || this._addAriaAndCollapsedClass(this._triggerArray, this._isShown()), + this._config.toggle && this.toggle() + } + static get Default() { + return m + } + static get DefaultType() { + return b + } + static get NAME() { + return "collapse" + } + toggle() { + this._isShown() ? this.hide() : this.show() + } + show() { + if (!this._isTransitioning && !this._isShown()) { + let t = []; + if (!(t = this._config.parent ? this._getFirstLevelChildren(".collapse.show, .collapse.collapsing").filter(t=>t !== this._element).map(t=>v.getOrCreateInstance(t, { + toggle: !1 + })) : t).length || !t[0]._isTransitioning) { + var e = o.a.trigger(this._element, a); + if (!e.defaultPrevented) { + for (const i of t) + i.hide(); + const n = this._getDimension(); + this._element.classList.remove(d), + this._element.classList.add(p), + this._element.style[n] = 0, + this._addAriaAndCollapsedClass(this._triggerArray, !0), + this._isTransitioning = !0; + e = n[0].toUpperCase() + n.slice(1), + e = "scroll".concat(e); + this._queueCallback(()=>{ + this._isTransitioning = !1, + this._element.classList.remove(p), + this._element.classList.add(d, h), + this._element.style[n] = "", + o.a.trigger(this._element, l) + } + , this._element, !0), + this._element.style[n] = "".concat(this._element[e], "px") + } + } + } + } + hide() { + if (!this._isTransitioning && this._isShown()) { + var t = o.a.trigger(this._element, c); + if (!t.defaultPrevented) { + t = this._getDimension(); + this._element.style[t] = "".concat(this._element.getBoundingClientRect()[t], "px"), + Object(r.p)(this._element), + this._element.classList.add(p), + this._element.classList.remove(d, h); + for (const n of this._triggerArray) { + var e = Object(r.f)(n); + e && !this._isShown(e) && this._addAriaAndCollapsedClass([n], !1) + } + this._isTransitioning = !0; + this._element.style[t] = "", + this._queueCallback(()=>{ + this._isTransitioning = !1, + this._element.classList.remove(p), + this._element.classList.add(d), + o.a.trigger(this._element, u) + } + , this._element, !0) + } + } + } + _isShown() { + return (0 < arguments.length && void 0 !== arguments[0] ? arguments[0] : this._element).classList.contains(h) + } + _configAfterMerge(t) { + return t.toggle = Boolean(t.toggle), + t.parent = Object(r.e)(t.parent), + t + } + _getDimension() { + return this._element.classList.contains("collapse-horizontal") ? "width" : "height" + } + _initializeChildren() { + if (this._config.parent) + for (const e of this._getFirstLevelChildren(g)) { + var t = Object(r.f)(e); + t && this._addAriaAndCollapsedClass([e], this._isShown(t)) + } + } + _getFirstLevelChildren(t) { + const e = s.a.find(f, this._config.parent); + return s.a.find(t, this._config.parent).filter(t=>!e.includes(t)) + } + _addAriaAndCollapsedClass(t, e) { + if (t.length) + for (const n of t) + n.classList.toggle("collapsed", !e), + n.setAttribute("aria-expanded", e) + } + static jQueryInterface(e) { + const n = {}; + return "string" == typeof e && /show|hide/.test(e) && (n.toggle = !1), + this.each(function() { + var t = v.getOrCreateInstance(this, n); + if ("string" == typeof e) { + if (void 0 === t[e]) + throw new TypeError('No method named "'.concat(e, '"')); + t[e]() + } + }) + } + } + o.a.on(document, i, g, function(t) { + ("A" === t.target.tagName || t.delegateTarget && "A" === t.delegateTarget.tagName) && t.preventDefault(); + t = Object(r.h)(this); + for (const e of s.a.find(t)) + v.getOrCreateInstance(e, { + toggle: !1 + }).toggle() + }), + Object(r.a)(v), + e.a = v + } + , function(t, e, n) { + "use strict"; + var O = n(169) + , o = n(22) + , i = n(14) + , r = n(223) + , s = n(16) + , x = n(30) + , S = n(15) + , a = n(74) + , C = n(92) + , E = n(156) + , k = n(38) + , l = n(73) + , A = n(224) + , c = n(88) + , j = n(200) + , T = n(225) + , u = n(20)("replace") + , L = Math.max + , P = Math.min + , R = i([].concat) + , M = i([].push) + , I = i("".indexOf) + , D = i("".slice) + , n = "$0" === "a".replace(/./, "$0") + , h = !!/./[u] && "" === /./[u]("a", "$0"); + r("replace", function(t, _, y) { + var w = h ? "$" : "$0"; + return [function(t, e) { + var n = l(this) + , i = a(t) ? void 0 : c(t, u); + return i ? o(i, t, n, e) : o(_, k(n), t, e) + } + , function(t, e) { + var n = x(this) + , i = k(t); + if ("string" == typeof e && -1 === I(e, w) && -1 === I(e, "$<")) { + t = y(_, n, i, e); + if (t.done) + return t.value + } + for (var o, r = S(e), s = (r || (e = k(e)), + n.global), a = (s && (o = n.unicode, + n.lastIndex = 0), + []); null !== (d = T(n, i)) && (M(a, d), + s); ) + "" === k(d[0]) && (n.lastIndex = A(i, E(n.lastIndex), o)); + for (var l, c = "", u = 0, h = 0; h < a.length; h++) { + for (var d, p = k((d = a[h])[0]), f = L(P(C(d.index), i.length), 0), g = [], m = 1; m < d.length; m++) + M(g, void 0 === (l = d[m]) ? l : String(l)); + var b = d.groups + , v = r ? (v = R([p], g, f, i), + void 0 !== b && M(v, b), + k(O(e, void 0, v))) : j(p, i, f, g, b, e); + u <= f && (c += D(i, u, f) + v, + u = f + p.length) + } + return c + D(i, u) + } + ] + }, !!s(function() { + var t = /./; + return t.exec = function() { + var t = []; + return t.groups = { + a: "7" + }, + t + } + , + "7" !== "".replace(t, "$") + }) || !n || h) + } + , function(t, e, n) { + "use strict"; + n.d(e, "a", function() { + return i + }); + n(28); + var o = n(6) + , r = n(4); + const i = function(e) { + let n = 1 < arguments.length && void 0 !== arguments[1] ? arguments[1] : "hide"; + var t = "click.dismiss".concat(e.EVENT_KEY); + const i = e.NAME; + o.a.on(document, t, '[data-mdb-dismiss="'.concat(i, '"]'), function(t) { + ["A", "AREA"].includes(this.tagName) && t.preventDefault(), + Object(r.k)(this) || (t = Object(r.f)(this) || this.closest(".".concat(i)), + e.getOrCreateInstance(t)[n]()) + }) + } + } + , function(t, e, n) { + "use strict"; + var n = n(14) + , i = n({}.toString) + , o = n("".slice); + t.exports = function(t) { + return o(i(t), 8, -1) + } + } + , function(t, e, n) { + "use strict"; + n = n(14); + t.exports = n({}.isPrototypeOf) + } + , function(t, e, n) { + "use strict"; + var i = n(23) + , o = n(40) + , r = n(76); + t.exports = i ? function(t, e, n) { + return o.f(t, e, r(1, n)) + } + : function(t, e, n) { + return t[e] = n, + t + } + } + , function(t, e, n) { + "use strict"; + var i = n(156); + t.exports = function(t) { + return i(t.length) + } + } + , function(t, e, n) { + "use strict"; + var i = n(170) + , o = n(39) + , r = n(89) + , s = i(i.bind); + t.exports = function(t, e) { + return o(t), + void 0 === e ? t : r ? s(t, e) : function() { + return t.apply(e, arguments) + } + } + } + , function(t, e, n) { + "use strict"; + var r = n(24) + , s = n(10); + e.a = { + name: "applyStyles", + enabled: !0, + phase: "write", + fn: function(t) { + var o = t.state; + Object.keys(o.elements).forEach(function(t) { + var e = o.styles[t] || {} + , n = o.attributes[t] || {} + , i = o.elements[t]; + Object(s.b)(i) && Object(r.a)(i) && (Object.assign(i.style, e), + Object.keys(n).forEach(function(t) { + var e = n[t]; + !1 === e ? i.removeAttribute(t) : i.setAttribute(t, !0 === e ? "" : e) + })) + }) + }, + effect: function(t) { + var i = t.state + , o = { + popper: { + position: i.options.strategy, + left: "0", + top: "0", + margin: "0" + }, + arrow: { + position: "absolute" + }, + reference: {} + }; + return Object.assign(i.elements.popper.style, o.popper), + i.styles = o, + i.elements.arrow && Object.assign(i.elements.arrow.style, o.arrow), + function() { + Object.keys(i.elements).forEach(function(t) { + var e = i.elements[t] + , n = i.attributes[t] || {} + , t = Object.keys((i.styles.hasOwnProperty(t) ? i.styles : o)[t]).reduce(function(t, e) { + return t[e] = "", + t + }, {}); + Object(s.b)(e) && Object(r.a)(e) && (Object.assign(e.style, t), + Object.keys(n).forEach(function(t) { + e.removeAttribute(t) + })) + }) + } + }, + requires: ["computeStyles"] + } + } + , function(t, e, n) { + "use strict"; + var _ = n(5) + , y = n(42) + , w = n(19) + , O = n(27) + , x = n(33) + , o = n(25) + , r = n(37) + , S = n(18) + , C = { + top: "auto", + right: "auto", + bottom: "auto", + left: "auto" + }; + function s(t) { + var e, n = t.popper, i = t.popperRect, o = t.placement, r = t.variation, s = t.offsets, a = t.position, l = t.gpuAcceleration, c = t.adaptive, u = t.roundOffsets, t = t.isFixed, h = s.x, h = void 0 === h ? 0 : h, d = s.y, d = void 0 === d ? 0 : d, p = "function" == typeof u ? u({ + x: h, + y: d + }) : { + x: h, + y: d + }, p = (h = p.x, + d = p.y, + s.hasOwnProperty("x")), s = s.hasOwnProperty("y"), f = _.l, g = _.u, m = window, b = (c && (b = "clientHeight", + e = "clientWidth", + (v = Object(y.a)(n)) === Object(w.a)(n) && (v = Object(O.a)(n), + "static" !== Object(x.a)(v).position) && "absolute" === a && (b = "scrollHeight", + e = "scrollWidth"), + o !== _.u && (o !== _.l && o !== _.s || r !== _.k) || (g = _.i, + d = (d - ((t && v === m && m.visualViewport ? m.visualViewport.height : v[b]) - i.height)) * (l ? 1 : -1)), + o !== _.l && (o !== _.u && o !== _.i || r !== _.k) || (f = _.s, + h = (h - ((t && v === m && m.visualViewport ? m.visualViewport.width : v[e]) - i.width)) * (l ? 1 : -1))), + Object.assign({ + position: a + }, c && C)), v = !0 === u ? (o = { + x: h, + y: d + }, + r = Object(w.a)(n), + t = o.x, + o = o.y, + r = r.devicePixelRatio || 1, + { + x: Object(S.c)(t * r) / r || 0, + y: Object(S.c)(o * r) / r || 0 + }) : { + x: h, + y: d + }; + return h = v.x, + d = v.y, + l ? Object.assign({}, b, ((e = {})[g] = s ? "0" : "", + e[f] = p ? "0" : "", + e.transform = (m.devicePixelRatio || 1) <= 1 ? "translate(" + h + "px, " + d + "px)" : "translate3d(" + h + "px, " + d + "px, 0)", + e)) : Object.assign({}, b, ((i = {})[g] = s ? d + "px" : "", + i[f] = p ? h + "px" : "", + i.transform = "", + i)) + } + e.a = { + name: "computeStyles", + enabled: !0, + phase: "beforeWrite", + fn: function(t) { + var e = t.state + , t = t.options + , n = void 0 === (n = t.gpuAcceleration) || n + , i = void 0 === (i = t.adaptive) || i + , t = void 0 === (t = t.roundOffsets) || t + , n = { + placement: Object(o.a)(e.placement), + variation: Object(r.a)(e.placement), + popper: e.elements.popper, + popperRect: e.rects.popper, + gpuAcceleration: n, + isFixed: "fixed" === e.options.strategy + }; + null != e.modifiersData.popperOffsets && (e.styles.popper = Object.assign({}, e.styles.popper, s(Object.assign({}, n, { + offsets: e.modifiersData.popperOffsets, + position: e.options.strategy, + adaptive: i, + roundOffsets: t + })))), + null != e.modifiersData.arrow && (e.styles.arrow = Object.assign({}, e.styles.arrow, s(Object.assign({}, n, { + offsets: e.modifiersData.arrow, + position: "absolute", + adaptive: !1, + roundOffsets: t + })))), + e.attributes.popper = Object.assign({}, e.attributes.popper, { + "data-popper-placement": e.placement + }) + }, + data: {} + } + } + , function(t, e, n) { + "use strict"; + var l = n(19) + , c = { + passive: !0 + }; + e.a = { + name: "eventListeners", + enabled: !0, + phase: "write", + fn: function() {}, + effect: function(t) { + var e = t.state + , n = t.instance + , i = (t = t.options).scroll + , o = void 0 === i || i + , r = void 0 === (i = t.resize) || i + , s = Object(l.a)(e.elements.popper) + , a = [].concat(e.scrollParents.reference, e.scrollParents.popper); + return o && a.forEach(function(t) { + t.addEventListener("scroll", n.update, c) + }), + r && s.addEventListener("resize", n.update, c), + function() { + o && a.forEach(function(t) { + t.removeEventListener("scroll", n.update, c) + }), + r && s.removeEventListener("resize", n.update, c) + } + }, + data: {} + } + } + , function(t, e, n) { + "use strict"; + var i = n(108); + e.a = { + name: "popperOffsets", + enabled: !0, + phase: "read", + fn: function(t) { + var e = t.state + , t = t.name; + e.modifiersData[t] = Object(i.a)({ + reference: e.rects.reference, + element: e.rects.popper, + strategy: "absolute", + placement: e.placement + }) + }, + data: {} + } + } + , function(t, e, n) { + "use strict"; + function i(t) { + return 0 <= ["top", "bottom"].indexOf(t) ? "x" : "y" + } + n.d(e, "a", function() { + return i + }) + } + , function(t, e, n) { + "use strict"; + n.d(e, "a", function() { + return i + }); + var o = n(36); + function i(t) { + var e = Object(o.a)(t) + , n = t.offsetWidth + , i = t.offsetHeight; + return Math.abs(e.width - n) <= 1 && (n = e.width), + Math.abs(e.height - i) <= 1 && (i = e.height), + { + x: t.offsetLeft, + y: t.offsetTop, + width: n, + height: i + } + } + } + , function(t, e, n) { + "use strict"; + n.d(e, "a", function() { + return s + }); + var i = n(36) + , o = n(27) + , r = n(67); + function s(t) { + return Object(i.a)(Object(o.a)(t)).left + Object(r.a)(t).scrollLeft + } + } + , function(t, e, n) { + "use strict"; + n.d(e, "a", function() { + return o + }); + var i = n(19); + function o(t) { + t = Object(i.a)(t); + return { + scrollLeft: t.pageXOffset, + scrollTop: t.pageYOffset + } + } + } + , function(t, e, n) { + "use strict"; + n.d(e, "a", function() { + return o + }); + var i = n(33); + function o(t) { + var t = Object(i.a)(t) + , e = t.overflow + , n = t.overflowX + , t = t.overflowY; + return /auto|scroll|overlay|hidden/.test(e + t + n) + } + } + , function(t, e, n) { + "use strict"; + n(11), + n(12), + n(75), + n(28); + var i = n(71) + , o = n(141) + , r = n(4); + n(17), + n(72); + const l = new Set(["background", "cite", "href", "itemtype", "longdesc", "poster", "src", "xlink:href"]); + const c = /^(?:(?:https?|mailto|ftp|tel|file|sms):|[^#&/:?]*(?:[#/?]|$))/i + , u = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z]+=*$/i; + var s = { + "*": ["class", "dir", "id", "lang", "role", /^aria-[\w-]*$/i], + a: ["target", "href", "title", "rel"], + area: [], + b: [], + br: [], + col: [], + code: [], + div: [], + em: [], + hr: [], + h1: [], + h2: [], + h3: [], + h4: [], + h5: [], + h6: [], + i: [], + img: ["src", "srcset", "alt", "title", "width", "height"], + li: [], + ol: [], + p: [], + pre: [], + s: [], + small: [], + span: [], + sub: [], + sup: [], + strong: [], + u: [], + ul: [] + }; + function a(t, e, n) { + if (!t.length) + return t; + if (n && "function" == typeof n) + return n(t); + n = (new window.DOMParser).parseFromString(t, "text/html"); + for (const s of [].concat(...n.body.querySelectorAll("*"))) { + var i = s.nodeName.toLowerCase(); + if (Object.keys(e).includes(i)) { + var o = [].concat(...s.attributes) + , r = [].concat(e["*"] || [], e[i] || []); + for (const a of o) + ((t,e)=>{ + const n = t.nodeName.toLowerCase(); + return e.includes(n) ? !l.has(n) || Boolean(c.test(t.nodeValue) || u.test(t.nodeValue)) : e.filter(t=>t instanceof RegExp).some(t=>t.test(n)) + } + )(a, r) || s.removeAttribute(a.nodeName) + } else + s.remove() + } + return n.body.innerHTML + } + var h = n(6) + , d = n(34) + , p = n(21) + , f = n(8) + , n = n(45); + const g = { + allowList: s, + content: {}, + extraClass: "", + html: !1, + sanitize: !0, + sanitizeFn: null, + template: "
" + } + , m = { + allowList: "object", + content: "object", + extraClass: "(string|function)", + html: "boolean", + sanitize: "boolean", + sanitizeFn: "(null|function)", + template: "string" + } + , b = { + entry: "(string|element|function|null)", + selector: "(string|element)" + }; + class v extends n.a { + constructor(t) { + super(), + this._config = this._getConfig(t) + } + static get Default() { + return g + } + static get DefaultType() { + return m + } + static get NAME() { + return "TemplateFactory" + } + getContent() { + return Object.values(this._config.content).map(t=>this._resolvePossibleFunction(t)).filter(Boolean) + } + hasContent() { + return 0 < this.getContent().length + } + changeContent(t) { + return this._checkContent(t), + this._config.content = { + ...this._config.content, + ...t + }, + this + } + toHtml() { + var t, e, n = document.createElement("div"); + n.innerHTML = this._maybeSanitize(this._config.template); + for ([t,e] of Object.entries(this._config.content)) + this._setContent(n, e, t); + var i = n.children[0] + , o = this._resolvePossibleFunction(this._config.extraClass); + return o && i.classList.add(...o.split(" ")), + i + } + _typeCheckConfig(t) { + super._typeCheckConfig(t), + this._checkContent(t.content) + } + _checkContent(t) { + for (var [e,n] of Object.entries(t)) + super._typeCheckConfig({ + selector: e, + entry: n + }, b) + } + _setContent(t, e, n) { + n = f.a.findOne(n, t); + n && ((e = this._resolvePossibleFunction(e)) ? Object(r.l)(e) ? this._putElementInTemplate(Object(r.e)(e), n) : this._config.html ? n.innerHTML = this._maybeSanitize(e) : n.textContent = e : n.remove()) + } + _maybeSanitize(t) { + return this._config.sanitize ? a(t, this._config.allowList, this._config.sanitizeFn) : t + } + _resolvePossibleFunction(t) { + return "function" == typeof t ? t(this) : t + } + _putElementInTemplate(t, e) { + this._config.html ? (e.innerHTML = "", + e.append(t)) : e.textContent = t.textContent + } + } + var _ = v; + const y = new Set(["sanitize", "allowList", "sanitizeFn"]) + , w = "fade"; + const O = "show" + , x = ".".concat("modal") + , S = "hide.bs.modal" + , C = "hover" + , E = "focus" + , k = { + AUTO: "auto", + TOP: "top", + RIGHT: Object(r.m)() ? "left" : "right", + BOTTOM: "bottom", + LEFT: Object(r.m)() ? "right" : "left" + } + , A = { + allowList: s, + animation: !0, + boundary: "clippingParents", + container: !1, + customClass: "", + delay: 0, + fallbackPlacements: ["top", "right", "bottom", "left"], + html: !1, + offset: [0, 0], + placement: "top", + popperConfig: null, + sanitize: !0, + sanitizeFn: null, + selector: !1, + template: '', + title: "", + trigger: "hover focus" + } + , j = { + allowList: "object", + animation: "boolean", + boundary: "(string|element)", + container: "(string|element|boolean)", + customClass: "(string|function)", + delay: "(number|object)", + fallbackPlacements: "array", + html: "boolean", + offset: "(array|string|function)", + placement: "(string|function)", + popperConfig: "(null|object|function)", + sanitize: "boolean", + sanitizeFn: "(null|function)", + selector: "(string|boolean)", + template: "string", + title: "(string|element|function)", + trigger: "string" + }; + class T extends p.a { + constructor(t, e) { + if (void 0 === i) + throw new TypeError("Bootstrap's tooltips require Popper (https://popper.js.org)"); + super(t, e), + this._isEnabled = !0, + this._timeout = 0, + this._isHovered = null, + this._activeTrigger = {}, + this._popper = null, + this._templateFactory = null, + this._newContent = null, + this.tip = null, + this._setListeners(), + this._config.selector || this._fixTitle() + } + static get Default() { + return A + } + static get DefaultType() { + return j + } + static get NAME() { + return "tooltip" + } + enable() { + this._isEnabled = !0 + } + disable() { + this._isEnabled = !1 + } + toggleEnabled() { + this._isEnabled = !this._isEnabled + } + toggle() { + this._isEnabled && (this._activeTrigger.click = !this._activeTrigger.click, + this._isShown() ? this._leave() : this._enter()) + } + dispose() { + clearTimeout(this._timeout), + h.a.off(this._element.closest(x), S, this._hideModalHandler), + this._element.getAttribute("data-mdb-original-title") && this._element.setAttribute("title", this._element.getAttribute("data-mdb-original-title")), + this._disposePopper(), + super.dispose() + } + show() { + if ("none" === this._element.style.display) + throw new Error("Please use show on visible elements"); + if (this._isWithContent() && this._isEnabled) { + var t = h.a.trigger(this._element, this.constructor.eventName("show")) + , e = (Object(r.d)(this._element) || this._element.ownerDocument.documentElement).contains(this._element); + if (!t.defaultPrevented && e) { + this._disposePopper(); + t = this._getTipElement(), + e = (this._element.setAttribute("aria-describedby", t.getAttribute("id")), + this._config)["container"]; + if (this._element.ownerDocument.documentElement.contains(this.tip) || (e.append(t), + h.a.trigger(this._element, this.constructor.eventName("inserted"))), + this._popper = this._createPopper(t), + t.classList.add(O), + "ontouchstart"in document.documentElement) + for (const n of [].concat(...document.body.children)) + h.a.on(n, "mouseover", r.o); + this._queueCallback(()=>{ + h.a.trigger(this._element, this.constructor.eventName("shown")), + !1 === this._isHovered && this._leave(), + this._isHovered = !1 + } + , this.tip, this._isAnimated()) + } + } + } + hide() { + if (this._isShown()) { + var t = h.a.trigger(this._element, this.constructor.eventName("hide")); + if (!t.defaultPrevented) { + if (this._getTipElement().classList.remove(O), + "ontouchstart"in document.documentElement) + for (const e of [].concat(...document.body.children)) + h.a.off(e, "mouseover", r.o); + this._activeTrigger.click = !1, + this._activeTrigger[E] = !1, + this._activeTrigger[C] = !1, + this._isHovered = null; + this._queueCallback(()=>{ + this._isWithActiveTrigger() || (this._isHovered || this._disposePopper(), + this._element.removeAttribute("aria-describedby"), + h.a.trigger(this._element, this.constructor.eventName("hidden"))) + } + , this.tip, this._isAnimated()) + } + } + } + update() { + this._popper && this._popper.update() + } + _isWithContent() { + return Boolean(this._getTitle()) + } + _getTipElement() { + return this.tip || (this.tip = this._createTipElement(this._newContent || this._getContentForTemplate())), + this.tip + } + _createTipElement(t) { + t = this._getTemplateFactory(t).toHtml(); + if (!t) + return null; + t.classList.remove(w, O), + t.classList.add("bs-".concat(this.constructor.NAME, "-auto")); + var e = Object(r.i)(this.constructor.NAME).toString(); + return t.setAttribute("id", e), + this._isAnimated() && t.classList.add(w), + t + } + setContent(t) { + this._newContent = t, + this._isShown() && (this._disposePopper(), + this.show()) + } + _getTemplateFactory(t) { + return this._templateFactory ? this._templateFactory.changeContent(t) : this._templateFactory = new _({ + ...this._config, + content: t, + extraClass: this._resolvePossibleFunction(this._config.customClass) + }), + this._templateFactory + } + _getContentForTemplate() { + return { + ".tooltip-inner": this._getTitle() + } + } + _getTitle() { + return this._resolvePossibleFunction(this._config.title) || this._element.getAttribute("data-mdb-original-title") + } + _initializeOnDelegatedTarget(t) { + return this.constructor.getOrCreateInstance(t.delegateTarget, this._getDelegateConfig()) + } + _isAnimated() { + return this._config.animation || this.tip && this.tip.classList.contains(w) + } + _isShown() { + return this.tip && this.tip.classList.contains(O) + } + _createPopper(t) { + var e = "function" == typeof this._config.placement ? this._config.placement.call(this, t, this._element) : this._config.placement + , e = k[e.toUpperCase()]; + return o.a(this._element, t, this._getPopperConfig(e)) + } + _getOffset() { + const e = this._config["offset"]; + return "string" == typeof e ? e.split(",").map(t=>Number.parseInt(t, 10)) : "function" == typeof e ? t=>e(t, this._element) : e + } + _resolvePossibleFunction(t) { + return "function" == typeof t ? t.call(this._element) : t + } + _getPopperConfig(t) { + t = { + placement: t, + modifiers: [{ + name: "flip", + options: { + fallbackPlacements: this._config.fallbackPlacements + } + }, { + name: "offset", + options: { + offset: this._getOffset() + } + }, { + name: "preventOverflow", + options: { + boundary: this._config.boundary + } + }, { + name: "arrow", + options: { + element: ".".concat(this.constructor.NAME, "-arrow") + } + }, { + name: "preSetPlacement", + enabled: !0, + phase: "beforeMain", + fn: t=>{ + this._getTipElement().setAttribute("data-popper-placement", t.state.placement) + } + }] + }; + return { + ...t, + ..."function" == typeof this._config.popperConfig ? this._config.popperConfig(t) : this._config.popperConfig + } + } + _setListeners() { + var t, e; + for (const n of this._config.trigger.split(" ")) + "click" === n ? h.a.on(this._element, this.constructor.eventName("click"), this._config.selector, t=>{ + this._initializeOnDelegatedTarget(t).toggle() + } + ) : "manual" !== n && (t = n === C ? this.constructor.eventName("mouseenter") : this.constructor.eventName("focusin"), + e = n === C ? this.constructor.eventName("mouseleave") : this.constructor.eventName("focusout"), + h.a.on(this._element, t, this._config.selector, t=>{ + var e = this._initializeOnDelegatedTarget(t); + e._activeTrigger["focusin" === t.type ? E : C] = !0, + e._enter() + } + ), + h.a.on(this._element, e, this._config.selector, t=>{ + var e = this._initializeOnDelegatedTarget(t); + e._activeTrigger["focusout" === t.type ? E : C] = e._element.contains(t.relatedTarget), + e._leave() + } + )); + this._hideModalHandler = ()=>{ + this._element && this.hide() + } + , + h.a.on(this._element.closest(x), S, this._hideModalHandler) + } + _fixTitle() { + var t = this._element.getAttribute("title"); + t && (this._element.getAttribute("aria-label") || this._element.textContent.trim() || this._element.setAttribute("aria-label", t), + this._element.setAttribute("data-mdb-original-title", t), + this._element.removeAttribute("title")) + } + _enter() { + this._isShown() || this._isHovered ? this._isHovered = !0 : (this._isHovered = !0, + this._setTimeout(()=>{ + this._isHovered && this.show() + } + , this._config.delay.show)) + } + _leave() { + this._isWithActiveTrigger() || (this._isHovered = !1, + this._setTimeout(()=>{ + this._isHovered || this.hide() + } + , this._config.delay.hide)) + } + _setTimeout(t, e) { + clearTimeout(this._timeout), + this._timeout = setTimeout(t, e) + } + _isWithActiveTrigger() { + return Object.values(this._activeTrigger).includes(!0) + } + _getConfig(t) { + var e = d.a.getDataAttributes(this._element); + for (const n of Object.keys(e)) + y.has(n) && delete e[n]; + return t = { + ...e, + ..."object" == typeof t && t ? t : {} + }, + t = this._mergeConfigObj(t), + t = this._configAfterMerge(t), + this._typeCheckConfig(t), + t + } + _configAfterMerge(t) { + return t.container = !1 === t.container ? document.body : Object(r.e)(t.container), + "number" == typeof t.delay && (t.delay = { + show: t.delay, + hide: t.delay + }), + "number" == typeof t.title && (t.title = t.title.toString()), + "number" == typeof t.content && (t.content = t.content.toString()), + t + } + _getDelegateConfig() { + var t = {}; + for (const e in this._config) + this.constructor.Default[e] !== this._config[e] && (t[e] = this._config[e]); + return t.selector = !1, + t.trigger = "manual", + t + } + _disposePopper() { + this._popper && (this._popper.destroy(), + this._popper = null), + this.tip && (this.tip.remove(), + this.tip = null) + } + static jQueryInterface(e) { + return this.each(function() { + var t = T.getOrCreateInstance(this, e); + if ("string" == typeof e) { + if (void 0 === t[e]) + throw new TypeError('No method named "'.concat(e, '"')); + t[e]() + } + }) + } + } + Object(r.a)(T); + e.a = T + } + , function(t, e, n) { + "use strict"; + n.d(e, "a", function() { + return c + }); + var o = n(47) + , r = n(68) + , s = n(24) + , a = n(10); + var l = n(19); + function c(t, e) { + void 0 === e && (e = []); + var n = function t(e) { + return 0 <= ["html", "body", "#document"].indexOf(Object(s.a)(e)) ? e.ownerDocument.body : Object(a.b)(e) && Object(r.a)(e) ? e : t(Object(o.a)(e)) + }(t) + , t = n === (null == (t = t.ownerDocument) ? void 0 : t.body) + , i = Object(l.a)(n) + , i = t ? [i].concat(i.visualViewport || [], Object(r.a)(n) ? n : []) : n + , n = e.concat(i); + return t ? n : n.concat(c(Object(o.a)(i))) + } + } + , function(t, e, n) { + "use strict"; + n.r(e); + var i = n(5) + , o = (n.d(e, "top", function() { + return i.u + }), + n.d(e, "bottom", function() { + return i.i + }), + n.d(e, "right", function() { + return i.s + }), + n.d(e, "left", function() { + return i.l + }), + n.d(e, "auto", function() { + return i.d + }), + n.d(e, "basePlacements", function() { + return i.e + }), + n.d(e, "start", function() { + return i.t + }), + n.d(e, "end", function() { + return i.k + }), + n.d(e, "clippingParents", function() { + return i.j + }), + n.d(e, "viewport", function() { + return i.w + }), + n.d(e, "popper", function() { + return i.p + }), + n.d(e, "reference", function() { + return i.r + }), + n.d(e, "variationPlacements", function() { + return i.v + }), + n.d(e, "placements", function() { + return i.o + }), + n.d(e, "beforeRead", function() { + return i.g + }), + n.d(e, "read", function() { + return i.q + }), + n.d(e, "afterRead", function() { + return i.b + }), + n.d(e, "beforeMain", function() { + return i.f + }), + n.d(e, "main", function() { + return i.m + }), + n.d(e, "afterMain", function() { + return i.a + }), + n.d(e, "beforeWrite", function() { + return i.h + }), + n.d(e, "write", function() { + return i.x + }), + n.d(e, "afterWrite", function() { + return i.c + }), + n.d(e, "modifierPhases", function() { + return i.n + }), + n(94)) + , r = (n.d(e, "applyStyles", function() { + return o.a + }), + n.d(e, "arrow", function() { + return o.b + }), + n.d(e, "computeStyles", function() { + return o.c + }), + n.d(e, "eventListeners", function() { + return o.d + }), + n.d(e, "flip", function() { + return o.e + }), + n.d(e, "hide", function() { + return o.f + }), + n.d(e, "offset", function() { + return o.g + }), + n.d(e, "popperOffsets", function() { + return o.h + }), + n.d(e, "preventOverflow", function() { + return o.i + }), + n(44)) + , s = (n.d(e, "popperGenerator", function() { + return r.b + }), + n(32)) + , a = (n.d(e, "detectOverflow", function() { + return s.a + }), + n.d(e, "createPopperBase", function() { + return r.a + }), + n(141)) + , l = (n.d(e, "createPopper", function() { + return a.a + }), + n(95)); + n.d(e, "createPopperLite", function() { + return l.a + }) + } + , function(D, N, t) { + "use strict"; + var e = t(23) + , n = t(13) + , i = t(14) + , o = t(122) + , c = t(226) + , u = t(57) + , r = t(152).f + , h = t(56) + , d = t(201) + , p = t(38) + , f = t(202) + , s = t(166) + , a = t(227) + , l = t(41) + , g = t(16) + , m = t(29) + , b = t(46).enforce + , v = t(171) + , _ = t(20) + , y = t(167) + , w = t(168) + , O = _("match") + , x = n.RegExp + , S = x.prototype + , C = n.SyntaxError + , E = i(S.exec) + , k = i("".charAt) + , A = i("".replace) + , j = i("".indexOf) + , H = i("".slice) + , B = /^\?<[^\s\d!#%&*+<=>@^][^\s!#%&*+<=>@^]*>/ + , T = /a/g + , L = /a/g + , t = new x(T) !== T + , P = s.MISSED_STICKY + , W = s.UNSUPPORTED_Y + , _ = e && (!t || P || y || w || g(function() { + return L[O] = !1, + x(T) !== T || x(L) === L || "/a/i" !== String(x(T, "i")) + })); + if (o("RegExp", _)) { + for (var R = function(t, e) { + var n, i, o = h(S, this), r = d(t), s = void 0 === e, a = [], l = t; + if (!o && r && s && t.constructor === R) + return t; + if ((r || h(S, t)) && (t = t.source, + s) && (e = f(l)), + t = void 0 === t ? "" : p(t), + e = void 0 === e ? "" : p(e), + l = t, + r = e = y && "dotAll"in T && (n = !!e && -1 < j(e, "s")) ? A(e, /s/g, "") : e, + P && "sticky"in T && (i = !!e && -1 < j(e, "y")) && W && (e = A(e, /y/g, "")), + w && (t = (s = function(t) { + for (var e, n = t.length, i = 0, o = "", r = [], s = {}, a = !1, l = !1, c = 0, u = ""; i <= n; i++) { + if ("\\" === (e = k(t, i))) + e += k(t, ++i); + else if ("]" === e) + a = !1; + else if (!a) + switch (!0) { + case "[" === e: + a = !0; + break; + case "(" === e: + E(B, H(t, i + 1)) && (i += 2, + l = !0), + o += e, + c++; + continue; + case ">" === e && l: + if ("" === u || m(s, u)) + throw new C("Invalid capture group name"); + s[u] = !0, + l = !(r[r.length] = [u, c]), + u = ""; + continue + } + l ? u += e : o += e + } + return [o, r] + }(t))[0], + a = s[1]), + s = c(x(t, e), o ? this : S, R), + (n || i || a.length) && (e = b(s), + n && (e.dotAll = !0, + e.raw = R(function(t) { + for (var e, n = t.length, i = 0, o = "", r = !1; i <= n; i++) + "\\" === (e = k(t, i)) ? o += e + k(t, ++i) : r || "." !== e ? ("[" === e ? r = !0 : "]" === e && (r = !1), + o += e) : o += "[\\s\\S]"; + return o + }(t), r)), + i && (e.sticky = !0), + a.length) && (e.groups = a), + t !== l) + try { + u(s, "source", "" === l ? "(?:)" : l) + } catch (t) {} + return s + }, M = r(x), I = 0; M.length > I; ) + a(R, x, M[I++]); + (S.constructor = R).prototype = S, + l(n, "RegExp", R, { + constructor: !0 + }) + } + v("RegExp") + } + , function(t, e, n) { + "use strict"; + var i = n(74) + , o = TypeError; + t.exports = function(t) { + if (i(t)) + throw o("Can't call method on " + t); + return t + } + } + , function(t, e, n) { + "use strict"; + t.exports = function(t) { + return null == t + } + } + , function(t, e, n) { + "use strict"; + var i = n(26) + , o = n(229).trim; + i({ + target: "String", + proto: !0, + forced: n(230)("trim") + }, { + trim: function() { + return o(this) + } + }) + } + , function(t, e, n) { + "use strict"; + t.exports = function(t, e) { + return { + enumerable: !(1 & t), + configurable: !(2 & t), + writable: !(4 & t), + value: e + } + } + } + , function(t, e, n) { + "use strict"; + var i = n(112) + , o = n(73); + t.exports = function(t) { + return i(o(t)) + } + } + , function(t, e, n) { + "use strict"; + var i = String; + t.exports = function(t) { + try { + return i(t) + } catch (t) { + return "Object" + } + } + } + , function(t, e, n) { + "use strict"; + var i = n(150) + , o = n(40); + t.exports = function(t, e, n) { + return n.get && i(n.get, e, { + getter: !0 + }), + n.set && i(n.set, e, { + setter: !0 + }), + o.f(t, e, n) + } + } + , function(t, e, n) { + "use strict"; + function i() {} + function o(t) { + t.write(g("")), + t.close(); + var e = t.parentWindow.Object; + return t = null, + e + } + var r, s = n(30), a = n(213), l = n(121), c = n(120), u = n(160), h = n(91), n = n(119), d = "prototype", p = "script", f = n("IE_PROTO"), g = function(t) { + return "<" + p + ">" + t + "" + }, m = function() { + try { + r = new ActiveXObject("htmlfile") + } catch (t) {} + m = "undefined" == typeof document || document.domain && r ? o(r) : (t = h("iframe"), + e = "java" + p + ":", + t.style.display = "none", + u.appendChild(t), + t.src = String(e), + (e = t.contentWindow.document).open(), + e.write(g("document.F=Object")), + e.close(), + e.F); + for (var t, e, n = l.length; n--; ) + delete m[d][l[n]]; + return m() + }; + c[f] = !0, + t.exports = Object.create || function(t, e) { + var n; + return null !== t ? (i[d] = s(t), + n = new i, + i[d] = null, + n[f] = t) : n = m(), + void 0 === e ? n : a.f(n, e) + } + } + , function(t, e, n) { + "use strict"; + t.exports = {} + } + , function(t, e, n) { + "use strict"; + var i = n(40).f + , o = n(29) + , r = n(20)("toStringTag"); + t.exports = function(t, e, n) { + (t = t && !n ? t.prototype : t) && !o(t, r) && i(t, r, { + configurable: !0, + value: e + }) + } + } + , function(t, e, n) { + "use strict"; + var i = n(13) + , n = n(55); + t.exports = "process" === n(i.process) + } + , function(t, e, n) { + "use strict"; + n = n(13); + t.exports = n.Promise + } + , function(t, e, n) { + "use strict"; + var i = n(13) + , o = n(84) + , r = n(15) + , s = n(122) + , a = n(118) + , l = n(20) + , c = n(245) + , u = n(181) + , h = n(43) + , d = n(90) + , p = o && o.prototype + , f = l("species") + , g = !1 + , m = r(i.PromiseRejectionEvent) + , n = s("Promise", function() { + var t = a(o) + , e = t !== String(o); + if (!e && 66 === d) + return !0; + if (h && (!p.catch || !p.finally)) + return !0; + if (!d || d < 51 || !/native code/.test(t)) { + var t = new o(function(t) { + t(1) + } + ) + , n = function(t) { + t(function() {}, function() {}) + }; + if ((t.constructor = {})[f] = n, + !(g = t.then(function() {})instanceof n)) + return !0 + } + return !e && (c || u) && !m + }); + t.exports = { + CONSTRUCTOR: n, + REJECTION_EVENT: m, + SUBCLASSING: g + } + } + , function(t, e, n) { + "use strict"; + function i(t) { + var n, i; + this.promise = new t(function(t, e) { + if (void 0 !== n || void 0 !== i) + throw r("Bad Promise constructor"); + n = t, + i = e + } + ), + this.resolve = o(n), + this.reject = o(i) + } + var o = n(39) + , r = TypeError; + t.exports.f = function(t) { + return new i(t) + } + } + , function(t, e, n) { + "use strict"; + function i() { + var t = navigator.userAgentData; + return null != t && t.brands && Array.isArray(t.brands) ? t.brands.map(function(t) { + return t.brand + "/" + t.version + }).join(" ") : navigator.userAgent + } + n.d(e, "a", function() { + return i + }) + } + , function(t, e, n) { + "use strict"; + var i = n(39) + , o = n(74); + t.exports = function(t, e) { + t = t[e]; + return o(t) ? void 0 : i(t) + } + } + , function(t, e, n) { + "use strict"; + n = n(16); + t.exports = !n(function() { + var t = function() {} + .bind(); + return "function" != typeof t || t.hasOwnProperty("prototype") + }) + } + , function(t, e, n) { + "use strict"; + var i, o, r = n(13), n = n(49), s = r.process, r = r.Deno, s = s && s.versions || r && r.version, r = s && s.v8; + !(o = r ? 0 < (i = r.split("."))[0] && i[0] < 4 ? 1 : +(i[0] + i[1]) : o) && n && (!(i = n.match(/Edge\/(\d+)/)) || 74 <= i[1]) && (i = n.match(/Chrome\/(\d+)/)) && (o = +i[1]), + t.exports = o + } + , function(t, e, n) { + "use strict"; + var i = n(13) + , n = n(35) + , o = i.document + , r = n(o) && n(o.createElement); + t.exports = function(t) { + return r ? o.createElement(t) : {} + } + } + , function(t, e, n) { + "use strict"; + var i = n(211); + t.exports = function(t) { + t = +t; + return t != t || 0 == t ? 0 : i(t) + } + } + , function(t, e, n) { + "use strict"; + var i = n(212) + , o = n(15) + , r = n(55) + , s = n(20)("toStringTag") + , a = Object + , l = "Arguments" === r(function() { + return arguments + }()); + t.exports = i ? r : function(t) { + var e; + return void 0 === t ? "Undefined" : null === t ? "Null" : "string" == typeof (e = function(t, e) { + try { + return t[e] + } catch (t) {} + }(t = a(t), s)) ? e : l ? r(t) : "Object" === (e = r(t)) && o(t.callee) ? "Arguments" : e + } + } + , function(t, e, n) { + "use strict"; + var i = n(60) + , o = (n.d(e, "a", function() { + return i.a + }), + n(97)) + , r = (n.d(e, "b", function() { + return o.a + }), + n(61)) + , s = (n.d(e, "c", function() { + return r.a + }), + n(62)) + , a = (n.d(e, "d", function() { + return s.a + }), + n(100)) + , l = (n.d(e, "e", function() { + return a.a + }), + n(98)) + , c = (n.d(e, "f", function() { + return l.a + }), + n(99)) + , u = (n.d(e, "g", function() { + return c.a + }), + n(63)) + , h = (n.d(e, "h", function() { + return u.a + }), + n(101)); + n.d(e, "i", function() { + return h.a + }) + } + , function(t, e, n) { + "use strict"; + n.d(e, "a", function() { + return s + }); + var e = n(44) + , i = n(62) + , o = n(63) + , r = n(61) + , n = n(60) + , i = [i.a, o.a, r.a, n.a] + , s = Object(e.b)({ + defaultModifiers: i + }) + } + , function(t, e, n) { + "use strict"; + var i = n(93) + , o = n(88) + , r = n(74) + , s = n(81) + , a = n(20)("iterator"); + t.exports = function(t) { + if (!r(t)) + return o(t, a) || o(t, "@@iterator") || s[i(t)] + } + } + , function(t, e, n) { + "use strict"; + var h = n(25) + , d = n(65) + , i = n(107) + , p = n(42) + , f = n(64) + , g = n(51) + , m = n(103) + , b = n(105) + , v = n(5); + e.a = { + name: "arrow", + enabled: !0, + phase: "main", + fn: function(t) { + var e, n, i, o, r = t.state, s = t.name, t = t.options, a = r.elements.arrow, l = r.modifiersData.popperOffsets, c = Object(h.a)(r.placement), u = Object(f.a)(c), c = 0 <= [v.l, v.s].indexOf(c) ? "height" : "width"; + a && l && (t = t.padding, + i = r, + t = "function" == typeof t ? t(Object.assign({}, i.rects, { + placement: i.placement + })) : t, + i = Object(m.a)("number" != typeof t ? t : Object(b.a)(t, v.e)), + t = Object(d.a)(a), + n = "y" === u ? v.u : v.l, + o = "y" === u ? v.i : v.s, + e = r.rects.reference[c] + r.rects.reference[u] - l[u] - r.rects.popper[c], + l = l[u] - r.rects.reference[u], + a = (a = Object(p.a)(a)) ? "y" === u ? a.clientHeight || 0 : a.clientWidth || 0 : 0, + n = i[n], + i = a - t[c] - i[o], + o = a / 2 - t[c] / 2 + (e / 2 - l / 2), + a = Object(g.a)(n, o, i), + r.modifiersData[s] = ((t = {})[u] = a, + t.centerOffset = a - o, + t)) + }, + effect: function(t) { + var e = t.state; + null != (t = void 0 === (t = t.options.element) ? "[data-popper-arrow]" : t) && ("string" != typeof t || (t = e.elements.popper.querySelector(t))) && Object(i.a)(e.elements.popper, t) && (e.elements.arrow = t) + }, + requires: ["popperOffsets"], + requiresIfExists: ["preventOverflow"] + } + } + , function(t, e, n) { + "use strict"; + var i = n(5) + , a = n(32); + function l(t, e, n) { + return { + top: t.top - e.height - (n = void 0 === n ? { + x: 0, + y: 0 + } : n).y, + right: t.right - e.width + n.x, + bottom: t.bottom - e.height + n.y, + left: t.left - e.width - n.x + } + } + function c(e) { + return [i.u, i.s, i.i, i.l].some(function(t) { + return 0 <= e[t] + }) + } + e.a = { + name: "hide", + enabled: !0, + phase: "main", + requiresIfExists: ["preventOverflow"], + fn: function(t) { + var e = t.state + , t = t.name + , n = e.rects.reference + , i = e.rects.popper + , o = e.modifiersData.preventOverflow + , r = Object(a.a)(e, { + elementContext: "reference" + }) + , s = Object(a.a)(e, { + altBoundary: !0 + }) + , r = l(r, n) + , n = l(s, i, o) + , s = c(r) + , i = c(n); + e.modifiersData[t] = { + referenceClippingOffsets: r, + popperEscapeOffsets: n, + isReferenceHidden: s, + hasPopperEscaped: i + }, + e.attributes.popper = Object.assign({}, e.attributes.popper, { + "data-popper-reference-hidden": s, + "data-popper-escaped": i + }) + } + } + } + , function(t, e, n) { + "use strict"; + var l = n(25) + , c = n(5); + e.a = { + name: "offset", + enabled: !0, + phase: "main", + requires: ["popperOffsets"], + fn: function(t) { + var s = t.state + , e = t.options + , t = t.name + , a = void 0 === (e = e.offset) ? [0, 0] : e + , e = c.o.reduce(function(t, e) { + var n, i, o, r; + return t[e] = (e = e, + n = s.rects, + i = a, + o = Object(l.a)(e), + r = 0 <= [c.l, c.u].indexOf(o) ? -1 : 1, + e = (n = "function" == typeof i ? i(Object.assign({}, n, { + placement: e + })) : i)[0] || 0, + i = (n[1] || 0) * r, + 0 <= [c.l, c.s].indexOf(o) ? { + x: i, + y: e + } : { + x: e, + y: i + }), + t + }, {}) + , n = (i = e[s.placement]).x + , i = i.y; + null != s.modifiersData.popperOffsets && (s.modifiersData.popperOffsets.x += n, + s.modifiersData.popperOffsets.y += i), + s.modifiersData[t] = e + } + } + } + , function(t, e, n) { + "use strict"; + var i = { + left: "right", + right: "left", + bottom: "top", + top: "bottom" + }; + function k(t) { + return t.replace(/left|right|bottom|top/g, function(t) { + return i[t] + }) + } + var A = n(25) + , o = { + start: "end", + end: "start" + }; + function j(t) { + return t.replace(/start|end/g, function(t) { + return o[t] + }) + } + var T = n(32) + , L = n(37) + , P = n(5); + e.a = { + name: "flip", + enabled: !0, + phase: "main", + fn: function(t) { + var h = t.state + , e = t.options + , t = t.name; + if (!h.modifiersData[t]._skip) { + for (var n = e.mainAxis, i = void 0 === n || n, n = e.altAxis, o = void 0 === n || n, n = e.fallbackPlacements, d = e.padding, p = e.boundary, f = e.rootBoundary, r = e.altBoundary, s = e.flipVariations, g = void 0 === s || s, m = e.allowedAutoPlacements, s = h.options.placement, e = Object(A.a)(s), n = n || (e === s || !g ? [k(s)] : (n = s, + Object(A.a)(n) === P.d ? [] : (e = k(n), + [j(n), e, j(e)]))), a = [s].concat(n).reduce(function(t, e) { + return t.concat(Object(A.a)(e) === P.d ? (n = h, + i = (t = t = void 0 === (t = { + placement: e, + boundary: p, + rootBoundary: f, + padding: d, + flipVariations: g, + allowedAutoPlacements: m + }) ? {} : t).placement, + o = t.boundary, + r = t.rootBoundary, + s = t.padding, + a = t.flipVariations, + l = void 0 === (t = t.allowedAutoPlacements) ? P.o : t, + c = Object(L.a)(i), + t = c ? a ? P.v : P.v.filter(function(t) { + return Object(L.a)(t) === c + }) : P.e, + u = (i = 0 === (i = t.filter(function(t) { + return 0 <= l.indexOf(t) + })).length ? t : i).reduce(function(t, e) { + return t[e] = Object(T.a)(n, { + placement: e, + boundary: o, + rootBoundary: r, + padding: s + })[Object(A.a)(e)], + t + }, {}), + Object.keys(u).sort(function(t, e) { + return u[t] - u[e] + })) : e); + var n, i, o, r, s, a, l, c, u + }, []), l = h.rects.reference, c = h.rects.popper, u = new Map, b = !0, v = a[0], _ = 0; _ < a.length; _++) { + var y = a[_] + , w = Object(A.a)(y) + , O = Object(L.a)(y) === P.t + , x = 0 <= [P.u, P.i].indexOf(w) + , S = x ? "width" : "height" + , C = Object(T.a)(h, { + placement: y, + boundary: p, + rootBoundary: f, + altBoundary: r, + padding: d + }) + , x = x ? O ? P.s : P.l : O ? P.i : P.u + , O = (l[S] > c[S] && (x = k(x)), + k(x)) + , S = []; + if (i && S.push(C[w] <= 0), + o && S.push(C[x] <= 0, C[O] <= 0), + S.every(function(t) { + return t + })) { + v = y, + b = !1; + break + } + u.set(y, S) + } + if (b) + for (var E = g ? 3 : 1; 0 < E; E--) + if ("break" === function(e) { + var t = a.find(function(t) { + t = u.get(t); + if (t) + return t.slice(0, e).every(function(t) { + return t + }) + }); + if (t) + return v = t, + "break" + }(E)) + break; + h.placement !== v && (h.modifiersData[t]._skip = !0, + h.placement = v, + h.reset = !0) + } + }, + requiresIfExists: ["offset"], + data: { + _skip: !1 + } + } + } + , function(t, e, n) { + "use strict"; + var E = n(5) + , k = n(25) + , A = n(64); + var j = n(51) + , T = n(65) + , L = n(42) + , P = n(32) + , R = n(37) + , M = n(104) + , I = n(18); + e.a = { + name: "preventOverflow", + enabled: !0, + phase: "main", + fn: function(t) { + var e, n, i, o, r, s, a, l, c, u = t.state, h = t.options, t = t.name, d = void 0 === (d = h.mainAxis) || d, p = void 0 !== (p = h.altAxis) && p, f = h.boundary, g = h.rootBoundary, m = h.altBoundary, b = h.padding, v = void 0 === (v = h.tether) || v, h = void 0 === (h = h.tetherOffset) ? 0 : h, f = Object(P.a)(u, { + boundary: f, + rootBoundary: g, + padding: b, + altBoundary: m + }), g = Object(k.a)(u.placement), m = !(b = Object(R.a)(u.placement)), _ = Object(A.a)(g), y = "x" === _ ? "y" : "x", w = u.modifiersData.popperOffsets, O = u.rects.reference, x = u.rects.popper, h = "number" == typeof (h = "function" == typeof h ? h(Object.assign({}, u.rects, { + placement: u.placement + })) : h) ? { + mainAxis: h, + altAxis: h + } : Object.assign({ + mainAxis: 0, + altAxis: 0 + }, h), S = u.modifiersData.offset ? u.modifiersData.offset[u.placement] : null, C = { + x: 0, + y: 0 + }; + w && (d && (d = "y" === _ ? E.u : E.l, + s = "y" === _ ? E.i : E.s, + i = "y" === _ ? "height" : "width", + e = (c = w[_]) + f[d], + a = c - f[s], + r = v ? -x[i] / 2 : 0, + o = (b === E.t ? O : x)[i], + b = b === E.t ? -x[i] : -O[i], + n = u.elements.arrow, + n = v && n ? Object(T.a)(n) : { + width: 0, + height: 0 + }, + d = (l = u.modifiersData["arrow#persistent"] ? u.modifiersData["arrow#persistent"].padding : Object(M.a)())[d], + l = l[s], + s = Object(j.a)(0, O[i], n[i]), + n = m ? O[i] / 2 - r - s - d - h.mainAxis : o - s - d - h.mainAxis, + o = m ? -O[i] / 2 + r + s + l + h.mainAxis : b + s + l + h.mainAxis, + m = (d = u.elements.arrow && Object(L.a)(u.elements.arrow)) ? "y" === _ ? d.clientTop || 0 : d.clientLeft || 0 : 0, + b = c + n - (r = null != (i = null == S ? void 0 : S[_]) ? i : 0) - m, + s = c + o - r, + l = Object(j.a)(v ? Object(I.b)(e, b) : e, c, v ? Object(I.a)(a, s) : a), + w[_] = l, + C[_] = l - c), + p && (d = "x" === _ ? E.u : E.l, + n = "x" === _ ? E.i : E.s, + i = "y" == y ? "height" : "width", + o = (m = w[y]) + f[d], + r = m - f[n], + b = -1 !== [E.u, E.l].indexOf(g), + s = null != (e = null == S ? void 0 : S[y]) ? e : 0, + a = b ? o : m - O[i] - x[i] - s + h.altAxis, + l = b ? m + O[i] + x[i] - s - h.altAxis : r, + c = v && b ? Object(j.b)(a, m, l) : Object(j.a)(v ? a : o, m, v ? l : r), + w[y] = c, + C[y] = c - m), + u.modifiersData[t] = C) + }, + requiresIfExists: ["offset"] + } + } + , function(t, e, n) { + "use strict"; + n(17); + var i = n(3) + , o = n(7) + , r = n(1) + , s = n(0) + , a = n(2); + n(236); + const l = "input" + , c = "mdb.input"; + n = "form-outline"; + const u = "active" + , h = "form-notch" + , d = "form-notch-leading" + , p = "form-notch-middle"; + const f = ".".concat(n, " input") + , g = ".".concat(n, " textarea") + , m = ".".concat(h) + , b = ".".concat(d) + , v = ".".concat(p) + , _ = ".".concat("form-helper"); + class y { + constructor(t) { + this._element = t, + this._label = null, + this._labelWidth = 0, + this._labelMarginLeft = 0, + this._notchLeading = null, + this._notchMiddle = null, + this._notchTrailing = null, + this._initiated = !1, + this._helper = null, + this._counter = !1, + this._counterElement = null, + this._maxLength = 0, + this._leadingIcon = null, + this._element && (o.a.setData(t, c, this), + this.init()) + } + static get NAME() { + return l + } + get input() { + return a.a.findOne("input", this._element) || a.a.findOne("textarea", this._element) + } + init() { + this._initiated || (this._getLabelData(), + this._applyDivs(), + this._applyNotch(), + this._activate(), + this._getHelper(), + this._getCounter(), + this._initiated = !0) + } + update() { + this._getLabelData(), + this._getNotchData(), + this._applyNotch(), + this._activate(), + this._getHelper(), + this._getCounter() + } + forceActive() { + s.a.addClass(this.input, u) + } + forceInactive() { + s.a.removeClass(this.input, u) + } + dispose() { + this._removeBorder(), + o.a.removeData(this._element, c), + this._element = null + } + _getLabelData() { + this._label = a.a.findOne("label", this._element), + null === this._label ? this._showPlaceholder() : (this._getLabelWidth(), + this._getLabelPositionInInputGroup(), + this._toggleDefaultDatePlaceholder()) + } + _getHelper() { + this._helper = a.a.findOne(_, this._element) + } + _getCounter() { + this._counter = s.a.getDataAttribute(this.input, "showcounter"), + this._counter && (this._maxLength = this.input.maxLength, + this._showCounter()) + } + _showCounter() { + var t; + 0 < a.a.find(".form-counter", this._element).length || (this._counterElement = document.createElement("div"), + s.a.addClass(this._counterElement, "form-counter"), + t = this.input.value.length, + this._counterElement.innerHTML = "".concat(t, " / ").concat(this._maxLength), + this._helper.appendChild(this._counterElement), + this._bindCounter()) + } + _bindCounter() { + r.b.on(this.input, "input", ()=>{ + var t = this.input.value.length; + this._counterElement.innerHTML = "".concat(t, " / ").concat(this._maxLength) + } + ) + } + _toggleDefaultDatePlaceholder() { + var t = 0 < arguments.length && void 0 !== arguments[0] ? arguments[0] : this.input; + "date" === t.getAttribute("type") && (document.activeElement === t || t.value ? t.style.opacity = 1 : t.style.opacity = 0) + } + _showPlaceholder() { + s.a.addClass(this.input, "placeholder-active") + } + _getNotchData() { + this._notchMiddle = a.a.findOne(v, this._element), + this._notchLeading = a.a.findOne(b, this._element) + } + _getLabelWidth() { + this._labelWidth = .8 * this._label.clientWidth + 8 + } + _getLabelPositionInInputGroup() { + var t; + this._labelMarginLeft = 0, + this._element.classList.contains("input-group") && (t = this.input, + t = a.a.prev(t, ".input-group-text")[0], + this._labelMarginLeft = void 0 === t ? 0 : t.offsetWidth - 1) + } + _applyDivs() { + var t = a.a.find(m, this._element) + , e = Object(i.b)("div"); + s.a.addClass(e, h), + this._notchLeading = Object(i.b)("div"), + s.a.addClass(this._notchLeading, d), + this._notchMiddle = Object(i.b)("div"), + s.a.addClass(this._notchMiddle, p), + this._notchTrailing = Object(i.b)("div"), + s.a.addClass(this._notchTrailing, "form-notch-trailing"), + 1 <= t.length || (e.append(this._notchLeading), + e.append(this._notchMiddle), + e.append(this._notchTrailing), + this._element.append(e)) + } + _applyNotch() { + this._notchMiddle.style.width = "".concat(this._labelWidth, "px"), + this._notchLeading.style.width = "".concat(this._labelMarginLeft + 9, "px"), + null !== this._label && (this._label.style.marginLeft = "".concat(this._labelMarginLeft, "px")) + } + _removeBorder() { + var t = a.a.findOne(m, this._element); + t && t.remove() + } + _activate(e) { + Object(i.i)(()=>{ + this._getElements(e); + var t = e ? e.target : this.input; + "" !== t.value && s.a.addClass(t, u), + this._toggleDefaultDatePlaceholder(t) + } + ) + } + _getElements(t) { + var e; + t && (this._element = t.target.parentNode, + this._label = a.a.findOne("label", this._element)), + t && this._label && (e = this._labelWidth, + this._getLabelData(), + e !== this._labelWidth) && (this._notchMiddle = a.a.findOne(".form-notch-middle", t.target.parentNode), + this._notchLeading = a.a.findOne(b, t.target.parentNode), + this._applyNotch()) + } + _deactivate(t) { + t = t ? t.target : this.input; + "" === t.value && t.classList.remove(u), + this._toggleDefaultDatePlaceholder(t) + } + static activate(e) { + return function(t) { + e._activate(t) + } + } + static deactivate(e) { + return function(t) { + e._deactivate(t) + } + } + static jQueryInterface(n, i) { + return this.each(function() { + let t = o.a.getData(this, c); + var e = "object" == typeof n && n; + if ((t || !/dispose/.test(n)) && (t = t || new y(this,e), + "string" == typeof n)) { + if (void 0 === t[n]) + throw new TypeError('No method named "'.concat(n, '"')); + t[n](i) + } + }) + } + static getInstance(t) { + return o.a.getData(t, c) + } + static getOrCreateInstance(t) { + var e = 1 < arguments.length && void 0 !== arguments[1] ? arguments[1] : {}; + return this.getInstance(t) || new this(t,"object" == typeof e ? e : null) + } + } + r.b.on(document, "focus", f, y.activate(new y)), + r.b.on(document, "input", f, y.activate(new y)), + r.b.on(document, "blur", f, y.deactivate(new y)), + r.b.on(document, "focus", g, y.activate(new y)), + r.b.on(document, "input", g, y.activate(new y)), + r.b.on(document, "blur", g, y.deactivate(new y)), + r.b.on(window, "shown.bs.modal", t=>{ + a.a.find(f, t.target).forEach(t=>{ + t = y.getInstance(t.parentNode); + t && t.update() + } + ), + a.a.find(g, t.target).forEach(t=>{ + t = y.getInstance(t.parentNode); + t && t.update() + } + ) + } + ), + r.b.on(window, "shown.bs.dropdown", t=>{ + t = t.target.parentNode.querySelector(".dropdown-menu"); + t && (a.a.find(f, t).forEach(t=>{ + t = y.getInstance(t.parentNode); + t && t.update() + } + ), + a.a.find(g, t).forEach(t=>{ + t = y.getInstance(t.parentNode); + t && t.update() + } + )) + } + ), + r.b.on(window, "shown.bs.tab", t=>{ + let e; + e = (t.target.href || s.a.getDataAttribute(t.target, "target")).split("#")[1]; + t = a.a.findOne("#".concat(e)); + a.a.find(f, t).forEach(t=>{ + t = y.getInstance(t.parentNode); + t && t.update() + } + ), + a.a.find(g, t).forEach(t=>{ + t = y.getInstance(t.parentNode); + t && t.update() + } + ) + } + ), + a.a.find(".".concat(n)).map(t=>new y(t)), + r.b.on(window, "reset", t=>{ + a.a.find(f, t.target).forEach(t=>{ + t = y.getInstance(t.parentNode); + t && t.forceInactive() + } + ), + a.a.find(g, t.target).forEach(t=>{ + t = y.getInstance(t.parentNode); + t && t.forceInactive() + } + ) + } + ), + r.b.on(window, "onautocomplete", t=>{ + var e = y.getInstance(t.target.parentNode); + e && t.cancelable && e.forceActive() + } + ), + Object(i.i)(()=>{ + const t = Object(i.f)(); + if (t) { + const e = t.fn[l]; + t.fn[l] = y.jQueryInterface, + t.fn[l].Constructor = y, + t.fn[l].noConflict = ()=>(t.fn[l] = e, + y.jQueryInterface) + } + } + ), + e.a = y + } + , function(t, e, n) { + "use strict"; + n.d(e, "a", function() { + return o + }); + var i = n(104); + function o(t) { + return Object.assign({}, Object(i.a)(), t) + } + } + , function(t, e, n) { + "use strict"; + function i() { + return { + top: 0, + right: 0, + bottom: 0, + left: 0 + } + } + n.d(e, "a", function() { + return i + }) + } + , function(t, e, n) { + "use strict"; + function i(n, t) { + return t.reduce(function(t, e) { + return t[e] = n, + t + }, {}) + } + n.d(e, "a", function() { + return i + }) + } + , function(t, e, n) { + "use strict"; + n.d(e, "a", function() { + return o + }); + var i = n(87); + function o() { + return !/^((?!chrome|android).)*safari/i.test(Object(i.a)()) + } + } + , function(t, e, n) { + "use strict"; + n.d(e, "a", function() { + return i + }); + var o = n(10); + function i(t, e) { + var n = e.getRootNode && e.getRootNode(); + if (t.contains(e)) + return !0; + if (n && Object(o.c)(n)) { + var i = e; + do { + if (i && t.isSameNode(i)) + return !0 + } while (i = i.parentNode || i.host) + } + return !1 + } + } + , function(t, e, n) { + "use strict"; + n.d(e, "a", function() { + return i + }); + var c = n(25) + , u = n(37) + , h = n(64) + , d = n(5); + function i(t) { + var e, n = t.reference, i = t.element, t = t.placement, o = t ? Object(c.a)(t) : null, t = t ? Object(u.a)(t) : null, r = n.x + n.width / 2 - i.width / 2, s = n.y + n.height / 2 - i.height / 2; + switch (o) { + case d.u: + e = { + x: r, + y: n.y - i.height + }; + break; + case d.i: + e = { + x: r, + y: n.y + n.height + }; + break; + case d.s: + e = { + x: n.x + n.width, + y: s + }; + break; + case d.l: + e = { + x: n.x - i.width, + y: s + }; + break; + default: + e = { + x: n.x, + y: n.y + } + } + var a = o ? Object(h.a)(o) : null; + if (null != a) { + var l = "y" === a ? "height" : "width"; + switch (t) { + case d.t: + e[a] = e[a] - (n[l] / 2 - i[l] / 2); + break; + case d.k: + e[a] = e[a] + (n[l] / 2 - i[l] / 2) + } + } + return e + } + } + , function(t, e, n) { + "use strict"; + n(133), + n(11), + n(12); + var i = n(2) + , o = n(3); + const r = { + position: "top", + container: null, + refresh: 1e3, + filter: t=>t + } + , s = { + position: "string", + container: "(undefined|null|string)", + refresh: "number", + filter: "function" + }; + e.a = class { + constructor(t, e, n) { + this._element = t, + this._selector = e, + this._options = this._getConfig(n), + this._offset = null, + this._options.container && (this._parent = i.a.findOne(this._options.container)) + } + get stackableElements() { + return i.a.find(this._selector).filter((t,e)=>this._options.filter(t, e)).map(t=>({ + el: t, + rect: t.getBoundingClientRect() + })).filter(t=>{ + var {el: t, rect: e} = t + , t = t !== this._element && Object(o.h)(t); + return null === this._offset ? t : t && this._getBoundryOffset(e) < this._offset + } + ).sort((t,e)=>this._getBoundryOffset(e.rect) - this._getBoundryOffset(t.rect)) + } + get nextElements() { + return i.a.find(this._selector).filter(t=>t !== this._element).filter((t,e)=>this._options.filter(t, e)).filter(t=>(this._offset = null, + this._getBoundryOffset(t.getBoundingClientRect()) > this._offset)) + } + _getConfig(t) { + t = { + ...r, + ...t + }; + return Object(o.j)("Stack", t, s), + t + } + _getBoundryOffset(t) { + var e, n = this._options["position"]; + let i = 0 + , o = window.innerHeight; + return this._parent && (e = this._parent.getBoundingClientRect(), + i = e.top, + o = e.bottom), + "top" === n ? t.top - i : o - t.bottom + } + calculateOffset() { + var [t] = this.stackableElements; + return this._offset = t ? this._getBoundryOffset(t.rect) + t.rect.height : 0, + this._offset + } + } + } + , function(t, e, n) { + "use strict"; + n(17), + n(53), + n(72); + var l = n(3) + , i = n(7) + , r = n(1) + , c = n(0) + , s = n(2); + const o = "ripple" + , a = "mdb.ripple" + , u = "ripple-surface" + , h = "ripple-wave" + , d = "input-wrapper" + , p = [".btn", ".ripple"] + , f = "ripple-surface-unbound" + , g = [0, 0, 0] + , m = ["primary", "secondary", "success", "danger", "warning", "info", "light", "dark"] + , b = { + rippleCentered: !1, + rippleColor: "", + rippleDuration: "500ms", + rippleRadius: 0, + rippleUnbound: !1 + } + , v = { + rippleCentered: "boolean", + rippleColor: "string", + rippleDuration: "string", + rippleRadius: "number", + rippleUnbound: "boolean" + }; + class _ { + constructor(t, e) { + this._element = t, + this._options = this._getConfig(e), + this._element && (i.a.setData(t, a, this), + c.a.addClass(this._element, u)), + this._clickHandler = this._createRipple.bind(this), + this._rippleTimer = null, + this._isMinWidthSet = !1, + this._rippleInSpan = !1, + this.init() + } + static get NAME() { + return o + } + init() { + this._addClickEvent(this._element) + } + dispose() { + i.a.removeData(this._element, a), + r.b.off(this._element, "click", this._clickHandler), + this._element = null, + this._options = null + } + _autoInit(e) { + if (p.forEach(t=>{ + s.a.closest(e.target, t) && (this._element = s.a.closest(e.target, t)) + } + ), + this._options = this._getConfig(), + "input" === this._element.tagName.toLowerCase()) { + var t = this._element.parentNode; + if (this._rippleInSpan = !0, + "span" === t.tagName.toLowerCase() && t.classList.contains(u)) + this._element = t; + else { + var n = getComputedStyle(this._element).boxShadow; + const o = this._element; + var i = document.createElement("span"); + o.classList.contains("btn-block") && (i.style.display = "block"), + r.b.one(i, "mouseup", t=>{ + 0 === t.button && o.click() + } + ), + i.classList.add(u, d), + c.a.addStyle(i, { + border: 0, + "box-shadow": n + }), + t.replaceChild(i, this._element), + i.appendChild(this._element), + this._element = i + } + this._element.focus() + } + this._element.style.minWidth || (c.a.style(this._element, { + "min-width": "".concat(getComputedStyle(this._element).width) + }), + this._isMinWidthSet = !0), + c.a.addClass(this._element, u), + this._createRipple(e) + } + _addClickEvent(t) { + r.b.on(t, "mousedown", this._clickHandler) + } + _getEventLayer(t) { + return { + layerX: Math.round(t.clientX - t.target.getBoundingClientRect().x), + layerY: Math.round(t.clientY - t.target.getBoundingClientRect().y) + } + } + _createRipple(t) { + var e, n, i, o, r, s, a; + null !== this._element && (c.a.hasClass(this._element, u) || c.a.addClass(this._element, u), + {layerX: t, layerY: e} = this._getEventLayer(t), + t = t, + e = e, + n = this._element.offsetHeight, + a = this._element.offsetWidth, + i = this._durationToMsNumber(this._options.rippleDuration), + o = { + offsetX: this._options.rippleCentered ? n / 2 : t, + offsetY: this._options.rippleCentered ? a / 2 : e, + height: n, + width: a + }, + o = this._getDiameter(o), + r = this._options.rippleRadius || o / 2, + s = { + delay: .5 * i, + duration: i - .5 * i + }, + a = { + left: this._options.rippleCentered ? "".concat(a / 2 - r, "px") : "".concat(t - r, "px"), + top: this._options.rippleCentered ? "".concat(n / 2 - r, "px") : "".concat(e - r, "px"), + height: "".concat(2 * this._options.rippleRadius || o, "px"), + width: "".concat(2 * this._options.rippleRadius || o, "px"), + transitionDelay: "0s, ".concat(s.delay, "ms"), + transitionDuration: "".concat(i, "ms, ").concat(s.duration, "ms") + }, + t = Object(l.b)("div"), + this._createHTMLRipple({ + wrapper: this._element, + ripple: t, + styles: a + }), + this._removeHTMLRipple({ + ripple: t, + duration: i + })) + } + _createHTMLRipple(t) { + let {wrapper: e, ripple: n, styles: i} = t; + Object.keys(i).forEach(t=>n.style[t] = i[t]), + n.classList.add(h), + "" !== this._options.rippleColor && (this._removeOldColorClasses(e), + this._addColor(n, e)), + this._toggleUnbound(e), + this._appendRipple(n, e) + } + _removeHTMLRipple(t) { + let {ripple: e, duration: n} = t; + this._rippleTimer && (clearTimeout(this._rippleTimer), + this._rippleTimer = null), + this._rippleTimer = setTimeout(()=>{ + e && (e.remove(), + this._element) && (s.a.find(".".concat(h), this._element).forEach(t=>{ + t.remove() + } + ), + this._isMinWidthSet && (c.a.style(this._element, { + "min-width": "" + }), + this._isMinWidthSet = !1), + this._rippleInSpan && this._element.classList.contains(d) ? this._removeWrapperSpan() : c.a.removeClass(this._element, u)) + } + , n) + } + _removeWrapperSpan() { + var t = this._element.firstChild; + this._element.replaceWith(t), + this._element = t, + this._element.focus(), + this._rippleInSpan = !1 + } + _durationToMsNumber(t) { + return Number(t.replace("ms", "").replace("s", "000")) + } + _getConfig() { + var t = 0 < arguments.length && void 0 !== arguments[0] ? arguments[0] : {} + , e = c.a.getDataAttributes(this._element) + , t = { + ...b, + ...e, + ...t + }; + return Object(l.j)(o, t, v), + t + } + _getDiameter(t) { + var {offsetX: t, offsetY: e, height: n, width: i} = t + , o = e <= n / 2 + , r = t <= i / 2 + , s = (t,e)=>Math.sqrt(t ** 2 + e ** 2) + , a = e === n / 2 && t === i / 2; + const l = !0 == o && !1 == r + , c = !0 == o && !0 == r + , u = !1 == o && !0 == r + , h = !1 == o && !1 == r; + o = { + topLeft: s(t, e), + topRight: s(i - t, e), + bottomLeft: s(t, n - e), + bottomRight: s(i - t, n - e) + }; + let d = 0; + return a || h ? d = o.topLeft : u ? d = o.topRight : c ? d = o.bottomRight : l && (d = o.bottomLeft), + 2 * d + } + _appendRipple(t, e) { + e.appendChild(t), + setTimeout(()=>{ + c.a.addClass(t, "active") + } + , 50) + } + _toggleUnbound(t) { + !0 === this._options.rippleUnbound ? c.a.addClass(t, f) : t.classList.remove(f) + } + _addColor(t, e) { + m.find(t=>t === this._options.rippleColor.toLowerCase()) ? c.a.addClass(e, "".concat(u, "-").concat(this._options.rippleColor.toLowerCase())) : (e = this._colorToRGB(this._options.rippleColor).join(","), + e = "rgba({{color}}, 0.2) 0, rgba({{color}}, 0.3) 40%, rgba({{color}}, 0.4) 50%, rgba({{color}}, 0.5) 60%, rgba({{color}}, 0) 70%".split("{{color}}").join("".concat(e)), + t.style.backgroundImage = "radial-gradient(circle, ".concat(e, ")")) + } + _removeOldColorClasses(e) { + var t = new RegExp("".concat(u, "-[a-z]+"),"gi"); + (e.classList.value.match(t) || []).forEach(t=>{ + e.classList.remove(t) + } + ) + } + _colorToRGB(t) { + var e, n, i; + return "transparent" === t.toLowerCase() ? g : "#" === t[0] ? ((e = t).length < 7 && (e = "#".concat(e[1]).concat(e[1]).concat(e[2]).concat(e[2]).concat(e[3]).concat(e[3])), + [parseInt(e.substr(1, 2), 16), parseInt(e.substr(3, 2), 16), parseInt(e.substr(5, 2), 16)]) : (-1 === t.indexOf("rgb") && (e = t, + n = document.body.appendChild(document.createElement("fictum")), + i = "rgb(1, 2, 3)", + n.style.color = i, + t = n.style.color !== i || (n.style.color = e, + n.style.color === i) || "" === n.style.color ? g : (e = getComputedStyle(n).color, + document.body.removeChild(n), + e)), + 0 === t.indexOf("rgb") ? ((i = (i = t).match(/[.\d]+/g).map(t=>+Number(t))).length = 3, + i) : g) + } + static autoInitial(e) { + return function(t) { + e._autoInit(t) + } + } + static jQueryInterface(t) { + return this.each(function() { + return i.a.getData(this, a) ? null : new _(this,t) + }) + } + static getInstance(t) { + return i.a.getData(t, a) + } + static getOrCreateInstance(t) { + var e = 1 < arguments.length && void 0 !== arguments[1] ? arguments[1] : {}; + return this.getInstance(t) || new this(t,"object" == typeof e ? e : null) + } + } + p.forEach(t=>{ + r.b.one(document, "mousedown", t, _.autoInitial(new _)) + } + ), + Object(l.i)(()=>{ + const t = Object(l.f)(); + if (t) { + const e = t.fn[o]; + t.fn[o] = _.jQueryInterface, + t.fn[o].Constructor = _, + t.fn[o].noConflict = ()=>(t.fn[o] = e, + _.jQueryInterface) + } + } + ), + e.a = _ + } + , function(t, e, n) { + "use strict"; + var i = n(23) + , o = n(22) + , r = n(142) + , s = n(76) + , a = n(77) + , l = n(113) + , c = n(29) + , u = n(148) + , h = Object.getOwnPropertyDescriptor; + e.f = i ? h : function(t, e) { + if (t = a(t), + e = l(e), + u) + try { + return h(t, e) + } catch (t) {} + if (c(t, e)) + return s(!o(r.f, t, e), t[e]) + } + } + , function(t, e, n) { + "use strict"; + var i = n(14) + , o = n(16) + , r = n(55) + , s = Object + , a = i("".split); + t.exports = o(function() { + return !s("z").propertyIsEnumerable(0) + }) ? function(t) { + return "String" === r(t) ? a(t, "") : s(t) + } + : s + } + , function(t, e, n) { + "use strict"; + var i = n(207) + , o = n(144); + t.exports = function(t) { + t = i(t, "string"); + return o(t) ? t : t + "" + } + } + , function(t, e, n) { + "use strict"; + var i = n(43) + , o = n(115); + (t.exports = function(t, e) { + return o[t] || (o[t] = void 0 !== e ? e : {}) + } + )("versions", []).push({ + version: "3.32.2", + mode: i ? "pure" : "global", + copyright: "© 2014-2023 Denis Pushkarev (zloirock.ru)", + license: "https://github.com/zloirock/core-js/blob/v3.32.2/LICENSE", + source: "https://github.com/zloirock/core-js" + }) + } + , function(t, e, n) { + "use strict"; + var i = n(13) + , n = n(116) + , o = "__core-js_shared__" + , i = i[o] || n(o, {}); + t.exports = i + } + , function(t, e, n) { + "use strict"; + var i = n(13) + , o = Object.defineProperty; + t.exports = function(e, n) { + try { + o(i, e, { + value: n, + configurable: !0, + writable: !0 + }) + } catch (t) { + i[e] = n + } + return n + } + } + , function(t, e, n) { + "use strict"; + var i = n(23) + , n = n(29) + , o = Function.prototype + , r = i && Object.getOwnPropertyDescriptor + , n = n(o, "name") + , s = n && "something" === function() {} + .name + , i = n && (!i || r(o, "name").configurable); + t.exports = { + EXISTS: n, + PROPER: s, + CONFIGURABLE: i + } + } + , function(t, e, n) { + "use strict"; + var i = n(14) + , o = n(15) + , n = n(115) + , r = i(Function.toString); + o(n.inspectSource) || (n.inspectSource = function(t) { + return r(t) + } + ), + t.exports = n.inspectSource + } + , function(t, e, n) { + "use strict"; + var i = n(114) + , o = n(147) + , r = i("keys"); + t.exports = function(t) { + return r[t] || (r[t] = o(t)) + } + } + , function(t, e, n) { + "use strict"; + t.exports = {} + } + , function(t, e, n) { + "use strict"; + t.exports = ["constructor", "hasOwnProperty", "isPrototypeOf", "propertyIsEnumerable", "toLocaleString", "toString", "valueOf"] + } + , function(t, e, n) { + "use strict"; + function i(t, e) { + return (t = l[a(t)]) === u || t !== c && (r(e) ? o(e) : !!e) + } + var o = n(16) + , r = n(15) + , s = /#|\.prototype\./ + , a = i.normalize = function(t) { + return String(t).replace(s, ".").toLowerCase() + } + , l = i.data = {} + , c = i.NATIVE = "N" + , u = i.POLYFILL = "P"; + t.exports = i + } + , function(t, e, n) { + "use strict"; + var o = n(215) + , r = n(30) + , s = n(216); + t.exports = Object.setPrototypeOf || ("__proto__"in {} ? function() { + var n, i = !1, t = {}; + try { + (n = o(Object.prototype, "__proto__", "set"))(t, []), + i = t instanceof Array + } catch (t) {} + return function(t, e) { + return r(t), + s(e), + i ? n(t, e) : t.__proto__ = e, + t + } + }() : void 0) + } + , function(t, e, n) { + "use strict"; + var f = n(22) + , i = n(14) + , g = n(38) + , m = n(125) + , o = n(166) + , r = n(114) + , b = n(80) + , v = n(46).get + , s = n(167) + , n = n(168) + , _ = r("native-string-replace", String.prototype.replace) + , y = RegExp.prototype.exec + , w = y + , O = i("".charAt) + , x = i("".indexOf) + , S = i("".replace) + , C = i("".slice) + , E = (r = /b*/g, + f(y, i = /a/, "a"), + f(y, r, "a"), + 0 !== i.lastIndex || 0 !== r.lastIndex) + , k = o.BROKEN_CARET + , A = void 0 !== /()??/.exec("")[1]; + (E || A || k || s || n) && (w = function(t) { + var e, n, i, o, r, s, a = this, l = v(a), t = g(t), c = l.raw; + if (c) + return c.lastIndex = a.lastIndex, + h = f(w, c, t), + a.lastIndex = c.lastIndex, + h; + var u = l.groups + , c = k && a.sticky + , h = f(m, a) + , l = a.source + , d = 0 + , p = t; + if (c && (h = S(h, "y", ""), + -1 === x(h, "g") && (h += "g"), + p = C(t, a.lastIndex), + 0 < a.lastIndex && (!a.multiline || a.multiline && "\n" !== O(t, a.lastIndex - 1)) && (l = "(?: " + l + ")", + p = " " + p, + d++), + e = new RegExp("^(?:" + l + ")",h)), + A && (e = new RegExp("^" + l + "$(?!\\s)",h)), + E && (n = a.lastIndex), + i = f(y, c ? e : a, p), + c ? i ? (i.input = C(i.input, d), + i[0] = C(i[0], d), + i.index = a.lastIndex, + a.lastIndex += i[0].length) : a.lastIndex = 0 : E && i && (a.lastIndex = a.global ? i.index + i[0].length : n), + A && i && 1 < i.length && f(_, i[0], e, function() { + for (o = 1; o < arguments.length - 2; o++) + void 0 === arguments[o] && (i[o] = void 0) + }), + i && u) + for (i.groups = r = b(null), + o = 0; o < u.length; o++) + r[(s = u[o])[0]] = i[s[1]]; + return i + } + ), + t.exports = w + } + , function(t, e, n) { + "use strict"; + var i = n(30); + t.exports = function() { + var t = i(this) + , e = ""; + return t.hasIndices && (e += "d"), + t.global && (e += "g"), + t.ignoreCase && (e += "i"), + t.multiline && (e += "m"), + t.dotAll && (e += "s"), + t.unicode && (e += "u"), + t.unicodeSets && (e += "v"), + t.sticky && (e += "y"), + e + } + } + , function(t, e, n) { + "use strict"; + function i(o) { + return function(t, e) { + var n, t = s(a(t)), e = r(e), i = t.length; + return e < 0 || i <= e ? o ? "" : void 0 : (n = c(t, e)) < 55296 || 56319 < n || e + 1 === i || (i = c(t, e + 1)) < 56320 || 57343 < i ? o ? l(t, e) : n : o ? u(t, e, e + 2) : i - 56320 + (n - 55296 << 10) + 65536 + } + } + var o = n(14) + , r = n(92) + , s = n(38) + , a = n(73) + , l = o("".charAt) + , c = o("".charCodeAt) + , u = o("".slice); + t.exports = { + codeAt: i(!1), + charAt: i(!0) + } + } + , function(t, e, n) { + "use strict"; + var i = n(56) + , o = TypeError; + t.exports = function(t, e) { + if (i(e, t)) + return t; + throw o("Incorrect invocation") + } + } + , function(t, e, n) { + "use strict"; + var i = TypeError; + t.exports = function(t, e) { + if (t < e) + throw i("Not enough arguments"); + return t + } + } + , function(t, e, n) { + "use strict"; + t.exports = function(t) { + try { + return { + error: !1, + value: t() + } + } catch (t) { + return { + error: !0, + value: t + } + } + } + } + , function(t, e, n) { + "use strict"; + var i = n(22) + , o = n(39) + , r = n(30) + , s = n(78) + , a = n(96) + , l = TypeError; + t.exports = function(t, e) { + e = arguments.length < 2 ? a(t) : e; + if (o(e)) + return r(i(e, t)); + throw l(s(t) + " is not iterable") + } + } + , function(t, e, n) { + "use strict"; + n(11), + n(12); + var i = n(8) + , o = n(34) + , r = n(4); + const s = ".fixed-top, .fixed-bottom, .is-fixed, .sticky-top" + , a = ".sticky-top" + , l = "padding-right" + , c = "margin-right"; + e.a = class { + constructor() { + this._element = document.body + } + getWidth() { + var t = document.documentElement.clientWidth; + return Math.abs(window.innerWidth - t) + } + hide() { + const e = this.getWidth(); + this._disableOverFlow(), + this._setElementAttributes(this._element, l, t=>t + e), + this._setElementAttributes(s, l, t=>t + e), + this._setElementAttributes(a, c, t=>t - e) + } + reset() { + this._resetElementAttributes(this._element, "overflow"), + this._resetElementAttributes(this._element, l), + this._resetElementAttributes(s, l), + this._resetElementAttributes(a, c) + } + isOverflowing() { + return 0 < this.getWidth() + } + _disableOverFlow() { + this._saveInitialAttribute(this._element, "overflow"), + this._element.style.overflow = "hidden" + } + _setElementAttributes(t, n, i) { + const o = this.getWidth(); + this._applyManipulationCallback(t, t=>{ + var e; + t !== this._element && window.innerWidth > t.clientWidth + o || (this._saveInitialAttribute(t, n), + e = window.getComputedStyle(t).getPropertyValue(n), + t.style.setProperty(n, "".concat(i(Number.parseFloat(e)), "px"))) + } + ) + } + _saveInitialAttribute(t, e) { + var n = t.style.getPropertyValue(e); + n && o.a.setDataAttribute(t, e, n) + } + _resetElementAttributes(t, n) { + this._applyManipulationCallback(t, t=>{ + var e = o.a.getDataAttribute(t, n); + null === e ? t.style.removeProperty(n) : (o.a.removeDataAttribute(t, n), + t.style.setProperty(n, e)) + } + ) + } + _applyManipulationCallback(t, e) { + if (Object(r.l)(t)) + e(t); + else + for (const n of i.a.find(t, this._element)) + e(n) + } + } + } + , function(t, e, n) { + "use strict"; + n(28); + var i = n(2) + , o = n(3); + e.a = class { + constructor(t) { + var e = 1 < arguments.length && void 0 !== arguments[1] ? arguments[1] : {} + , n = 2 < arguments.length ? arguments[2] : void 0; + this._element = t, + this._toggler = n, + this._event = e.event || "blur", + this._condition = e.condition || (()=>!0), + this._selector = e.selector || 'button, a, input, select, textarea, [tabindex]:not([tabindex="-1"])', + this._onlyVisible = e.onlyVisible || !1, + this._focusableElements = [], + this._firstElement = null, + this._lastElement = null, + this.handler = t=>{ + this._condition(t) && t.target === this._lastElement && (t.preventDefault(), + this._firstElement.focus()) + } + } + trap() { + this._setElements(), + this._init(), + this._setFocusTrap() + } + disable() { + this._focusableElements.forEach(t=>{ + t.removeEventListener(this._event, this.handler) + } + ), + this._toggler && this._toggler.focus() + } + update() { + this._setElements(), + this._setFocusTrap() + } + _init() { + const e = t=>{ + this._firstElement && "Tab" === t.key && !this._focusableElements.includes(t.target) && (t.preventDefault(), + this._firstElement.focus(), + window.removeEventListener("keydown", e)) + } + ; + window.addEventListener("keydown", e) + } + _filterVisible(t) { + return t.filter(t=>{ + if (!Object(o.h)(t)) + return !1; + var e = i.a.parents(t, "*"); + for (let t = 0; t < e.length; t++) { + var n = window.getComputedStyle(e[t]); + if (n && ("none" === n.display || "hidden" === n.visibility)) + return !1 + } + return !0 + } + ) + } + _setElements() { + var t = i.a.find(this._selector, this._element); + this._focusableElements = t.filter(t=>{ + var e = "true" === t.getAttribute("data-mdb-disabled") || t.hasAttribute("disabled"); + return t.disabled || e ? null : t + } + ), + this._onlyVisible && (this._focusableElements = this._filterVisible(this._focusableElements)), + this._firstElement = this._focusableElements[0], + this._lastElement = this._focusableElements[this._focusableElements.length - 1] + } + _setFocusTrap() { + this._focusableElements.forEach((t,e)=>{ + e === this._focusableElements.length - 1 ? t.addEventListener(this._event, this.handler) : t.removeEventListener(this._event, this.handler) + } + ) + } + } + } + , function(t, e, n) { + "use strict"; + var i = n(26) + , o = n(14) + , a = n(39) + , l = n(50) + , c = n(58) + , u = n(231) + , h = n(38) + , r = n(16) + , d = n(173) + , s = n(176) + , p = n(232) + , f = n(233) + , g = n(90) + , m = n(234) + , b = [] + , v = o(b.sort) + , _ = o(b.push) + , n = r(function() { + b.sort(void 0) + }) + , o = r(function() { + b.sort(null) + }) + , s = s("sort") + , y = !r(function() { + if (g) + return g < 70; + if (!(p && 3 < p)) { + if (f) + return !0; + if (m) + return m < 603; + for (var t, e, n, i = "", o = 65; o < 76; o++) { + switch (t = String.fromCharCode(o), + o) { + case 66: + case 69: + case 70: + case 72: + e = 3; + break; + case 68: + case 71: + e = 4; + break; + default: + e = 2 + } + for (n = 0; n < 47; n++) + b.push({ + k: t + n, + v: e + }) + } + for (b.sort(function(t, e) { + return e.v - t.v + }), + n = 0; n < b.length; n++) + t = b[n].k.charAt(0), + i.charAt(i.length - 1) !== t && (i += t); + return "DGBEFHACIJK" !== i + } + }); + i({ + target: "Array", + proto: !0, + forced: n || !o || !s || !y + }, { + sort: function(t) { + void 0 !== t && a(t); + var e = l(this); + if (y) + return void 0 === t ? v(e) : v(e, t); + for (var n, i, o = [], r = c(e), s = 0; s < r; s++) + s in e && _(o, e[s]); + for (d(o, (i = t, + function(t, e) { + return void 0 === e ? -1 : void 0 === t ? 1 : void 0 !== i ? +i(t, e) || 0 : h(t) > h(e) ? 1 : -1 + } + )), + n = c(o), + s = 0; s < n; ) + e[s] = o[s++]; + for (; s < r; ) + u(e, s++); + return e + } + }) + } + , function(D, t, e) { + "use strict"; + e(11), + e(12), + e(28), + e(17); + var n = e(141) + , o = e(7) + , i = e(1) + , h = e(0) + , r = e(2) + , d = e(3) + , s = e(102); + const a = ".form-check-input" + , l = "selected"; + var p = class { + constructor(t, e, n, i, o, r, s, a, l, c, u) { + this.id = t, + this.nativeOption = e, + this.multiple = n, + this.value = i, + this.label = o, + this.selected = r, + this.disabled = s, + this.hidden = a, + this.secondaryText = l, + this.groupId = c, + this.icon = u, + this.node = null, + this.active = !1 + } + select() { + this.multiple ? this._selectMultiple() : this._selectSingle() + } + _selectSingle() { + this.selected || (h.a.addClass(this.node, l), + this.node.setAttribute("aria-selected", !0), + this.selected = !0, + this.nativeOption && (this.nativeOption.selected = !0)) + } + _selectMultiple() { + this.selected || (r.a.findOne(a, this.node).checked = !0, + h.a.addClass(this.node, l), + this.node.setAttribute("aria-selected", !0), + this.selected = !0, + this.nativeOption && (this.nativeOption.selected = !0)) + } + deselect() { + this.multiple ? this._deselectMultiple() : this._deselectSingle() + } + _deselectSingle() { + this.selected && (h.a.removeClass(this.node, l), + this.node.setAttribute("aria-selected", !1), + this.selected = !1, + this.nativeOption) && (this.nativeOption.selected = !1) + } + _deselectMultiple() { + this.selected && (r.a.findOne(a, this.node).checked = !1, + h.a.removeClass(this.node, l), + this.node.setAttribute("aria-selected", !1), + this.selected = !1, + this.nativeOption) && (this.nativeOption.selected = !1) + } + setNode(t) { + this.node = t + } + setActiveStyles() { + this.active || this.multiple || (this.active = !0, + h.a.addClass(this.node, "active")) + } + removeActiveStyles() { + this.active && (this.active = !1, + h.a.removeClass(this.node, "active")) + } + } + ; + var c = class { + constructor() { + this._multiple = 0 < arguments.length && void 0 !== arguments[0] && arguments[0], + this._selections = [] + } + select(t) { + this._multiple ? this._selections.push(t) : this._selections = [t] + } + deselect(e) { + var t; + this._multiple ? (t = this._selections.findIndex(t=>e === t), + this._selections.splice(t, 1)) : this._selections = [] + } + clear() { + this._selections = [] + } + get selection() { + return this._selections[0] + } + get selections() { + return this._selections + } + get label() { + return this._selections[0] && this.selection.label + } + get labels() { + return this._selections.map(t=>t.label).join(", ") + } + get value() { + return this.selections[0] && this.selection.value + } + get values() { + return this._selections.map(t=>t.value) + } + } + , u = e(9); + function f(t) { + return t.filter(t=>!t.disabled).every(t=>t.selected) + } + const g = t=>{ + "Tab" !== t.code && "Esc" !== t.code && t.preventDefault() + } + ; + function m(t, e, n, i, o, r, s) { + var a = document.createElement("div") + , t = (a.classList.add("select-dropdown-container"), + a.setAttribute("id", "".concat(t)), + a.style.width = "".concat(n, "px"), + document.createElement("div")) + , n = (t.setAttribute("tabindex", 0), + t.classList.add("select-dropdown"), + Object(d.b)("div")) + , i = (h.a.addClass(n, "select-options-wrapper"), + n.style.maxHeight = "".concat(i, "px"), + b(r, o, e)); + return n.appendChild(i), + e.filter && t.appendChild((r = e.searchPlaceholder, + o = Object(d.b)("div"), + h.a.addClass(o, "input-group"), + i = Object(d.b)("input"), + h.a.addClass(i, "form-control"), + h.a.addClass(i, "select-filter-input"), + i.placeholder = r, + i.setAttribute("role", "searchbox"), + i.setAttribute("type", "text"), + o.appendChild(i), + o)), + t.appendChild(n), + s && t.appendChild(s), + a.appendChild(t), + a + } + function b(t, e, n) { + const i = Object(d.b)("div"); + h.a.addClass(i, "select-options-list"); + let o; + return (o = n.multiple ? function(t, e, n) { + let i = null; + n.selectAll && (i = function(t, e, n) { + var e = f(e) + , i = Object(d.b)("div"); + h.a.addClass(i, "select-option"), + h.a.addClass(i, "select-all-option"), + h.a.addStyle(i, { + height: "".concat(n.optionHeight, "px") + }), + i.setAttribute("role", "option"), + i.setAttribute("aria-selected", e), + e && h.a.addClass(i, "selected"); + return i.appendChild(y(t, n)), + t.setNode(i), + i + }(e, t, n)); + e = v(t, n), + t = i ? [i, ...e] : e; + return t + }(t, e, n) : function(t, e) { + t = v(t, e); + return t + }(t, n)).forEach(t=>{ + i.appendChild(t) + } + ), + i + } + function v(t, n) { + const i = []; + return t.forEach(t=>{ + var e; + t.hasOwnProperty("options") ? (e = function(t, e) { + const n = Object(d.b)("div"); + h.a.addClass(n, "select-option-group"), + n.setAttribute("role", "group"), + n.setAttribute("id", t.id), + t.hidden && h.a.addClass(n, "d-none"); + var i = Object(d.b)("label"); + return h.a.addClass(i, "select-option-group-label"), + h.a.addStyle(i, { + height: "".concat(e.optionHeight, "px") + }), + i.setAttribute("for", t.id), + i.textContent = t.label, + n.appendChild(i), + t.options.forEach(t=>{ + n.appendChild(_(t, e)) + } + ), + n + }(t, n), + i.push(e)) : i.push(_(t, n)) + } + ), + i + } + function _(t, e) { + var n, i, o; + return t.node || (n = Object(d.b)("div"), + h.a.addClass(n, "select-option"), + h.a.addStyle(n, { + height: "".concat(e.optionHeight, "px") + }), + h.a.setDataAttribute(n, "id", t.id), + n.setAttribute("role", "option"), + n.setAttribute("aria-selected", t.selected), + n.setAttribute("aria-disabled", t.disabled), + t.selected && h.a.addClass(n, "selected"), + t.disabled && h.a.addClass(n, "disabled"), + t.hidden && h.a.addClass(n, "d-none"), + n.appendChild(y(t, e)), + t.icon && n.appendChild((e = t, + i = Object(d.b)("span"), + h.a.addClass(i, "select-option-icon-container"), + o = Object(d.b)("img"), + h.a.addClass(o, "select-option-icon"), + h.a.addClass(o, "rounded-circle"), + o.src = e.icon, + i.appendChild(o), + i)), + t.setNode(n), + n) + } + function y(t, e) { + var n = Object(d.b)("span") + , i = (h.a.addClass(n, "select-option-text"), + document.createTextNode(t.label)); + return e.multiple && n.appendChild(function(t) { + var e = Object(d.b)("input") + , n = (e.setAttribute("type", "checkbox"), + h.a.addClass(e, "form-check-input"), + Object(d.b)("label")); + t.selected && e.setAttribute("checked", !0); + t.disabled && e.setAttribute("disabled", !0); + return e.appendChild(n), + e + }(t)), + n.appendChild(i), + !t.secondaryText && "number" != typeof t.secondaryText || n.appendChild((e = t.secondaryText, + i = Object(d.b)("span"), + h.a.addClass(i, "select-option-secondary-text"), + e = document.createTextNode(e), + i.appendChild(e), + i)), + n + } + const w = { + autoSelect: !1, + container: "body", + clearButton: !1, + disabled: !1, + displayedLabels: 5, + formWhite: !1, + multiple: !1, + optionsSelectedLabel: "options selected", + optionHeight: 38, + selectAll: !0, + selectAllLabel: "Select all", + searchPlaceholder: "Search...", + size: "default", + visibleOptions: 5, + filter: !1, + filterDebounce: 300, + noResultText: "No results", + validation: !1, + validFeedback: "Valid", + invalidFeedback: "Invalid", + placeholder: "", + filterFn: null + } + , O = { + autoSelect: "boolean", + container: "string", + clearButton: "boolean", + disabled: "boolean", + displayedLabels: "number", + formWhite: "boolean", + multiple: "boolean", + optionsSelectedLabel: "string", + optionHeight: "number", + selectAll: "boolean", + selectAllLabel: "string", + searchPlaceholder: "string", + size: "string", + visibleOptions: "number", + filter: "boolean", + filterDebounce: "number", + noResultText: "string", + validation: "boolean", + validFeedback: "string", + invalidFeedback: "string", + placeholder: "", + filterFn: "(function|null)" + } + , x = "select" + , S = "mdb.select"; + e = ".".concat(S); + const C = "close".concat(e) + , N = "open".concat(e) + , E = "optionSelect".concat(e) + , k = "optionDeselect".concat(e) + , H = "valueChange".concat(e) + , B = "shown".concat(e) + , W = "hidden".concat(e); + const A = ".select-input" + , j = ".select-options-list" + , T = ".form-outline" + , L = "select-initialized" + , P = "active" + , R = "focused"; + class M { + constructor(t, e) { + this._element = t, + this._config = this._getConfig(e), + this._optionsToRender = this._getOptionsToRender(t), + this._plainOptions = this._getPlainOptions(this._optionsToRender), + this._filteredOptionsList = null, + this._selectionModel = new c(this.multiple), + this._activeOptionIndex = -1, + this._activeOption = null, + this._wrapperId = this._element.id ? "select-wrapper-".concat(this._element.id) : Object(d.e)("select-wrapper-"), + this._dropdownContainerId = this._element.id ? "select-dropdown-container-".concat(this._element.id) : Object(d.e)("select-dropdown-container-"), + this._selectAllId = this._element.id ? "select-all-".concat(this._element.id) : Object(d.e)("select-all-"), + this._debounceTimeoutId = null, + this._dropdownHeight = this._config.optionHeight * this._config.visibleOptions, + this._popper = null, + this._input = null, + this._label = r.a.next(this._element, ".select-label")[0], + this._fakeValue = null, + this._isFakeValueActive = !1, + this._customContent = r.a.next(t, ".select-custom-content")[0], + this._toggleButton = null, + this._elementToggle = null, + this._wrapper = null, + this._inputEl = null, + this._dropdownContainer = null, + this._container = null, + this._selectAllOption = null, + this._init(), + this._mutationObserver = null, + this._isOpen = !1, + this._addMutationObserver(), + this._element && o.a.setData(t, S, this) + } + static get NAME() { + return x + } + get filterInput() { + return r.a.findOne(".select-filter-input", this._dropdownContainer) + } + get dropdown() { + return r.a.findOne(".select-dropdown", this._dropdownContainer) + } + get optionsList() { + return r.a.findOne(j, this._dropdownContainer) + } + get optionsWrapper() { + return r.a.findOne(".select-options-wrapper", this._dropdownContainer) + } + get clearButton() { + return r.a.findOne(".select-clear-btn", this._wrapper) + } + get options() { + return this._filteredOptionsList || this._plainOptions + } + get value() { + return this.multiple ? this._selectionModel.values : this._selectionModel.value + } + get multiple() { + return this._config.multiple + } + get hasSelectAll() { + return this.multiple && this._config.selectAll + } + get hasSelection() { + return this._selectionModel.selection || 0 < this._selectionModel.selections.length + } + _getConfig(t) { + var e = h.a.getDataAttributes(this._element); + return t = { + ...w, + ...e, + ...t + }, + this._element.hasAttribute("multiple") && (t.multiple = !0), + this._element.hasAttribute("disabled") && (t.disabled = !0), + this._element.tabIndex && (t.tabIndex = this._element.getAttribute("tabIndex")), + Object(d.j)(x, t, O), + t + } + _getOptionsToRender(t) { + const n = []; + return t.childNodes.forEach(t=>{ + if ("OPTGROUP" === t.nodeName) { + const e = { + id: t.id ? "group-".concat(t.id) : Object(d.e)("group-"), + label: t.label, + disabled: t.hasAttribute("disabled"), + hidden: t.hasAttribute("hidden"), + options: [] + }; + t.childNodes.forEach(t=>{ + "OPTION" === t.nodeName && e.options.push(this._createOptionObject(t, e)) + } + ), + n.push(e) + } else + "OPTION" === t.nodeName && n.push(this._createOptionObject(t)) + } + ), + n + } + _getPlainOptions(t) { + if (!r.a.findOne("optgroup", this._element)) + return t; + const e = []; + return t.forEach(t=>{ + t.hasOwnProperty("options") ? t.options.forEach(t=>{ + e.push(t) + } + ) : e.push(t) + } + ), + e + } + _createOptionObject(t) { + var e = 1 < arguments.length && void 0 !== arguments[1] ? arguments[1] : {} + , n = t.id ? "option-".concat(t.id) : Object(d.e)("option-") + , i = e.id || null + , o = e.disabled || !1 + , r = t.selected || t.hasAttribute("selected") + , o = t.hasAttribute("disabled") || o + , e = t.hasAttribute("hidden") || e && e.hidden + , s = this.multiple + , a = t.value + , l = t.label + , c = h.a.getDataAttribute(t, "secondaryText") + , u = h.a.getDataAttribute(t, "icon"); + return new p(n,t,s,a,l,r,o,e,c,i,u) + } + _getNavigationOptions() { + var t = this.options.filter(t=>!t.hidden); + return this.hasSelectAll ? [this._selectAllOption, ...t] : t + } + _init() { + this._renderMaterialWrapper(), + this._wrapper = r.a.findOne("#".concat(this._wrapperId)), + this._input = r.a.findOne(A, this._wrapper), + "off" === this._element.getAttribute("autocomplete") && this._input.setAttribute("autocomplete", "off"); + var t = this._config.container; + this._container = "body" === t ? document.body : r.a.findOne(t), + this._initOutlineInput(), + this._setDefaultSelections(), + this._updateInputValue(), + this._appendFakeValue(), + this._updateFakeLabelPosition(), + this._updateLabelPosition(), + this._updateClearButtonVisibility(), + this._bindComponentEvents(), + this.hasSelectAll && (this._selectAllOption = this._createSelectAllOption()), + this._dropdownContainer = m(this._dropdownContainerId, this._config, this._input.offsetWidth, this._dropdownHeight, this._selectAllOption, this._optionsToRender, this._customContent), + this._setFirstActiveOption() + } + _renderMaterialWrapper() { + t = this._wrapperId, + e = this._config, + n = this._label, + (i = document.createElement("div")).setAttribute("id", t), + i.classList.add("select-wrapper"), + t = Object(d.b)("div"), + h.a.addClass(t, "form-outline"), + e.formWhite && h.a.addClass(t, "form-white"), + l = Object(d.b)("input"), + o = e.filter ? "combobox" : "listbox", + r = e.multiple ? "true" : "false", + s = e.disabled ? "true" : "false", + h.a.addClass(l, "form-control"), + h.a.addClass(l, "select-input"), + "sm" === e.size && h.a.addClass(l, "form-control-sm"), + "lg" === e.size && h.a.addClass(l, "form-control-lg"), + l.setAttribute("type", "text"), + l.setAttribute("role", o), + l.setAttribute("aria-multiselectable", r), + l.setAttribute("aria-disabled", s), + l.setAttribute("aria-haspopup", "true"), + l.setAttribute("aria-expanded", !1), + e.tabIndex && l.setAttribute("tabIndex", e.tabIndex), + e.disabled && l.setAttribute("disabled", ""), + "" !== e.placeholder && l.setAttribute("placeholder", e.placeholder), + e.validation ? (h.a.addStyle(l, { + "pointer-events": "none", + "caret-color": "transparent" + }), + h.a.addStyle(t, { + cursor: "pointer" + })) : l.setAttribute("readonly", "true"), + e.validation && (l.setAttribute("required", "true"), + l.setAttribute("aria-required", "true"), + l.addEventListener("keydown", g)), + o = Object(d.b)("div"), + h.a.addClass(o, "valid-feedback"), + r = document.createTextNode("".concat(e.validFeedback)), + o.appendChild(r), + s = Object(d.b)("div"), + h.a.addClass(s, "invalid-feedback"), + r = document.createTextNode("".concat(e.invalidFeedback)), + s.appendChild(r), + r = Object(d.b)("span"), + h.a.addClass(r, "select-clear-btn"), + a = document.createTextNode("✕"), + r.appendChild(a), + r.setAttribute("tabindex", "0"), + a = Object(d.b)("span"), + h.a.addClass(a, "select-arrow"), + t.appendChild(l), + n && t.appendChild(n), + e.validation && (t.appendChild(o), + t.appendChild(s)), + e.clearButton && t.appendChild(r), + t.appendChild(a), + i.appendChild(t); + var t, e, n, i, o, r, s, a, l = i; + this._element.parentNode.insertBefore(l, this._element), + h.a.addClass(this._element, L), + l.appendChild(this._element) + } + _initOutlineInput() { + var t = r.a.findOne(T, this._wrapper); + new s.a(t).init() + } + _bindComponentEvents() { + this._listenToComponentKeydown(), + this._listenToWrapperClick(), + this._listenToClearBtnClick(), + this._listenToClearBtnKeydown() + } + _setDefaultSelections() { + this.options.forEach(t=>{ + t.selected && this._selectionModel.select(t) + } + ) + } + _listenToComponentKeydown() { + i.b.on(this._wrapper, "keydown", this._handleKeydown.bind(this)) + } + _handleKeydown(t) { + this._isOpen && !this._config.filter ? this._handleOpenKeydown(t) : this._handleClosedKeydown(t) + } + _handleOpenKeydown(t) { + var e = t.keyCode + , n = e === u.f || e === u.n && t.altKey || e === u.m; + if (e === u.m && this._config.autoSelect && !this.multiple && this._handleAutoSelection(this._activeOption), + n) + this.close(), + this._input.focus(); + else { + switch (e) { + case u.c: + this._setNextOptionActive(), + this._scrollToOption(this._activeOption); + break; + case u.n: + this._setPreviousOptionActive(), + this._scrollToOption(this._activeOption); + break; + case u.g: + this._setFirstOptionActive(), + this._scrollToOption(this._activeOption); + break; + case u.d: + this._setLastOptionActive(), + this._scrollToOption(this._activeOption); + break; + case u.e: + return t.preventDefault(), + void (this._activeOption && (this.hasSelectAll && 0 === this._activeOptionIndex ? this._handleSelectAll() : this._handleSelection(this._activeOption))); + default: + return + } + t.preventDefault() + } + } + _handleClosedKeydown(t) { + var e = t.keyCode + , n = (e === u.e && t.preventDefault(), + e === u.e || e === u.c && t.altKey || e === u.c && this.multiple); + if (n && this.open(), + this.multiple) + switch (e) { + case u.c: + case u.n: + this.open(); + break; + default: + return + } + else + switch (e) { + case u.c: + if (t.altKey) + return; + this._setNextOptionActive(), + this._handleSelection(this._activeOption); + break; + case u.n: + this._setPreviousOptionActive(), + this._handleSelection(this._activeOption); + break; + case u.g: + this._setFirstOptionActive(), + this._handleSelection(this._activeOption); + break; + case u.d: + this._setLastOptionActive(), + this._handleSelection(this._activeOption); + break; + default: + return + } + t.preventDefault() + } + _scrollToOption(e) { + if (e) { + let t; + var n = this.options.filter(t=>!t.hidden) + , n = (t = this.hasSelectAll ? n.indexOf(e) + 1 : n.indexOf(e), + this._getNumberOfGroupsBeforeOption(t)) + , e = t + n + , n = this.optionsWrapper + , i = n.offsetHeight + , o = this._config.optionHeight + , r = n.scrollTop; + -1 < t && (n.scrollTop = (n = e * o) < r ? n : r + i < n + o ? n - i + o : r) + } + } + _getNumberOfGroupsBeforeOption(t) { + var e = this.options.filter(t=>!t.hidden) + , n = this._optionsToRender.filter(t=>!t.hidden) + , i = this.hasSelectAll ? t - 1 : t; + let o = 0; + for (let t = 0; t <= i; t++) + e[t].groupId && n[o] && n[o].id && e[t].groupId === n[o].id && o++; + return o + } + _setNextOptionActive() { + let t = this._activeOptionIndex + 1; + var e = this._getNavigationOptions(); + if (e[t]) { + for (; e[t].disabled; ) + if (!e[t += 1]) + return; + this._updateActiveOption(e[t], t) + } + } + _setPreviousOptionActive() { + let t = this._activeOptionIndex - 1; + var e = this._getNavigationOptions(); + if (e[t]) { + for (; e[t].disabled; ) + if (!e[--t]) + return; + this._updateActiveOption(e[t], t) + } + } + _setFirstOptionActive() { + var t = this._getNavigationOptions(); + this._updateActiveOption(t[0], 0) + } + _setLastOptionActive() { + var t = this._getNavigationOptions() + , e = t.length - 1; + this._updateActiveOption(t[e], e) + } + _updateActiveOption(t, e) { + var n = this._activeOption; + n && n.removeActiveStyles(), + t.setActiveStyles(), + this._activeOptionIndex = e, + this._activeOption = t + } + _listenToWrapperClick() { + i.b.on(this._wrapper, "click", ()=>{ + this.toggle() + } + ) + } + _listenToClearBtnClick() { + i.b.on(this.clearButton, "click", t=>{ + t.preventDefault(), + t.stopPropagation(), + this._handleClear() + } + ) + } + _listenToClearBtnKeydown() { + i.b.on(this.clearButton, "keydown", t=>{ + t.keyCode === u.e && (this._handleClear(), + t.preventDefault(), + t.stopPropagation()) + } + ) + } + _handleClear() { + var t; + this.multiple ? (this._selectionModel.clear(), + this._deselectAllOptions(this.options), + this.hasSelectAll && this._updateSelectAllState()) : (t = this._selectionModel.selection, + this._selectionModel.clear(), + t.deselect()), + this._updateInputValue(), + this._updateFakeLabelPosition(), + this._updateLabelPosition(), + this._updateClearButtonVisibility(), + this._emitValueChangeEvent(null), + this._emitNativeChangeEvent() + } + _listenToOptionsClick() { + i.b.on(this.optionsWrapper, "click", t=>{ + var e = t.target.classList.contains("select-option-group-label"); + if (!e) { + e = "DIV" === t.target.nodeName ? t.target : r.a.closest(t.target, ".select-option"); + if (e.classList.contains("select-all-option")) + this._handleSelectAll(); + else { + const n = e.dataset.mdbId; + t = this.options.find(t=>t.id === n); + t && !t.disabled && this._handleSelection(t) + } + } + } + ) + } + _handleSelectAll() { + this._selectAllOption.selected ? (this._deselectAllOptions(this.options), + this._selectAllOption.deselect()) : (this._selectAllOptions(this.options), + this._selectAllOption.select()), + this._updateInputValue(), + this._updateFakeLabelPosition(), + this._updateLabelPosition(), + this._updateClearButtonVisibility(), + this._emitValueChangeEvent(this.value), + this._emitNativeChangeEvent() + } + _selectAllOptions(t) { + t.forEach(t=>{ + t.selected || t.disabled || (this._selectionModel.select(t), + t.select()) + } + ) + } + _deselectAllOptions(t) { + t.forEach(t=>{ + t.selected && !t.disabled && (this._selectionModel.deselect(t), + t.deselect()) + } + ) + } + _handleSelection(t) { + this.multiple ? (this._handleMultiSelection(t), + this.hasSelectAll && this._updateSelectAllState()) : this._handleSingleSelection(t), + this._updateInputValue(), + this._updateFakeLabelPosition(), + this._updateLabelPosition(), + this._updateClearButtonVisibility() + } + _handleAutoSelection(t) { + this._singleOptionSelect(t), + this._updateInputValue(), + this._updateFakeLabelPosition(), + this._updateLabelPosition(), + this._updateClearButtonVisibility() + } + _handleSingleSelection(t) { + this._singleOptionSelect(t), + this.close(), + this._input.focus() + } + _singleOptionSelect(t) { + var e = this._selectionModel.selections[0]; + e && e !== t && (this._selectionModel.deselect(e), + e.deselect(), + e.node.setAttribute("selected", !1), + i.b.trigger(this._element, k, { + value: e.value + })), + e && t === e || (this._selectionModel.select(t), + t.select(), + t.node.setAttribute("selected", !0), + i.b.trigger(this._element, E, { + value: t.value + }), + this._emitValueChangeEvent(this.value), + this._emitNativeChangeEvent()) + } + _handleMultiSelection(t) { + t.selected ? (this._selectionModel.deselect(t), + t.deselect(), + t.node.setAttribute("selected", !1), + i.b.trigger(this._element, k, { + value: t.value + })) : (this._selectionModel.select(t), + t.select(), + t.node.setAttribute("selected", !0), + i.b.trigger(this._element, E, { + value: t.value + })), + this._emitValueChangeEvent(this.value), + this._emitNativeChangeEvent() + } + _emitValueChangeEvent(t) { + i.b.trigger(this._element, H, { + value: t + }) + } + _emitNativeChangeEvent() { + i.b.trigger(this._element, "change") + } + _updateInputValue() { + var t = this.multiple ? this._selectionModel.labels : this._selectionModel.label; + let e; + e = this.multiple && -1 !== this._config.displayedLabels && this._selectionModel.selections.length > this._config.displayedLabels ? "".concat(this._selectionModel.selections.length, " ").concat(this._config.optionsSelectedLabel) : t, + this.multiple || this._isSelectionValid(this._selectionModel.selection) ? this._isLabelEmpty(this._selectionModel.selection) ? this._input.value = " " : e ? this._input.value = e : this.multiple || !this._optionsToRender[0] ? this._input.value = "" : this._input.value = this._optionsToRender[0].label : this._input.value = "" + } + _isSelectionValid(t) { + return !t || !t.disabled && "" !== t.value + } + _isLabelEmpty(t) { + return !(!t || "" !== t.label) + } + _appendFakeValue() { + var t, e; + this._selectionModel.selection && !this._selectionModel._multiple && (t = this._selectionModel.selection.label, + this._fakeValue = (t = t, + (e = Object(d.b)("div")).textContent = t, + h.a.addClass(e, "form-label"), + h.a.addClass(e, "select-fake-value"), + e), + r.a.findOne(T, this._wrapper).appendChild(this._fakeValue)) + } + _updateLabelPosition() { + var t = h.a.hasClass(this._element, L) + , e = "" !== this._input.value; + this._label && (t && (e || this._isOpen || this._isFakeValueActive) ? h.a.addClass(this._label, P) : h.a.removeClass(this._label, P)) + } + _updateLabelPositionWhileClosing() { + this._label && ("" !== this._input.value || this._isFakeValueActive ? h.a.addClass(this._label, P) : h.a.removeClass(this._label, P)) + } + _updateFakeLabelPosition() { + this._fakeValue && (this.hasSelection && (this._fakeValue.textContent = this.hasSelection.label), + "" === this._input.value && "" !== this._fakeValue.innerHTML ? (this._isFakeValueActive = !0, + h.a.addClass(this._fakeValue, P)) : (this._isFakeValueActive = !1, + h.a.removeClass(this._fakeValue, P))) + } + _updateClearButtonVisibility() { + this.clearButton && (this._selectionModel.selection || 0 < this._selectionModel.selections.length ? h.a.addStyle(this.clearButton, { + display: "block" + }) : h.a.addStyle(this.clearButton, { + display: "none" + })) + } + _updateSelectAllState() { + var t = this._selectAllOption.selected + , e = f(this.options); + !e && t ? this._selectAllOption.deselect() : e && !t && this._selectAllOption.select() + } + toggle() { + this._isOpen ? this.close() : this.open() + } + open() { + var t = this._config.disabled + , e = i.b.trigger(this._element, N); + this._isOpen || t || e.defaultPrevented || (this._openDropdown(), + this._updateDropdownWidth(), + this._setFirstActiveOption(), + this._scrollToOption(this._activeOption), + this._config.filter && (setTimeout(()=>{ + this.filterInput.focus() + } + , 0), + this._listenToSelectSearch(), + this._listenToDropdownKeydown()), + this._listenToOptionsClick(), + this._listenToOutsideClick(), + this._listenToWindowResize(), + this._isOpen = !0, + i.b.trigger(this._element, B), + this._updateLabelPosition(), + this._setInputActiveStyles()) + } + _openDropdown() { + this._popper = Object(n.a)(this._input, this._dropdownContainer, { + placement: "bottom-start", + modifiers: [{ + name: "offset", + options: { + offset: [0, 1] + } + }] + }), + this._container.appendChild(this._dropdownContainer), + setTimeout(()=>{ + h.a.addClass(this.dropdown, "open") + } + , 0) + } + _updateDropdownWidth() { + var t = this._input.offsetWidth; + h.a.addStyle(this._dropdownContainer, { + width: "".concat(t, "px") + }) + } + _setFirstActiveOption() { + var t = this._getNavigationOptions() + , e = this._activeOption; + e && e.removeActiveStyles(); + const n = this.multiple ? this._selectionModel.selections[0] : this._selectionModel.selection; + n ? ((this._activeOption = n).setActiveStyles(), + this._activeOptionIndex = t.findIndex(t=>t === n)) : (this._activeOption = null, + this._activeOptionIndex = -1) + } + _setInputActiveStyles() { + h.a.addClass(this._input, R) + } + _listenToWindowResize() { + i.b.on(window, "resize", this._handleWindowResize.bind(this)) + } + _handleWindowResize() { + this._dropdownContainer && this._updateDropdownWidth() + } + _listenToSelectSearch() { + this.filterInput.addEventListener("input", t=>{ + var t = t.target.value + , e = this._config.filterDebounce; + this._debounceFilter(t, e) + } + ) + } + _debounceFilter(t, e) { + this._debounceTimeoutId && clearTimeout(this._debounceTimeoutId), + this._debounceTimeoutId = setTimeout(()=>{ + this._filterOptions(t) + } + , e) + } + _filterOptions(o) { + const r = [] + , s = this._config.filterFn; + this._optionsToRender.forEach(t=>{ + var e = t.hasOwnProperty("options") + , n = !e && t.label.toLowerCase().includes(o.toLowerCase()) + , i = {}; + e && (i.label = t.label, + i.options = this._filter(o, t.options), + 0 < i.options.length) && r.push(i), + s && !e ? s(o, t) && r.push(t) : n && r.push(t) + } + ); + var t = "" !== this._config.noResultText + , e = 0 !== r.length; + e ? (this._updateOptionsListTemplate(r), + this._popper.forceUpdate(), + this._filteredOptionsList = this._getPlainOptions(r), + this.hasSelectAll && this._updateSelectAllState(), + this._setFirstActiveOption()) : !e && t && (e = this._getNoResultTemplate(), + this.optionsWrapper.innerHTML = e) + } + _updateOptionsListTemplate(t) { + var e = r.a.findOne(j, this._dropdownContainer) || r.a.findOne(".select-no-results", this._dropdownContainer) + , t = b(t, this._selectAllOption, this._config); + this.optionsWrapper.removeChild(e), + this.optionsWrapper.appendChild(t) + } + _getNoResultTemplate() { + return '
').concat(this._config.noResultText, "
") + } + _filter(e, t) { + const n = this._config.filterFn; + if (n) + return t.filter(t=>n(e, t)); + const i = e.toLowerCase(); + return t.filter(t=>t.label.toLowerCase().includes(i)) + } + _listenToDropdownKeydown() { + i.b.on(this.dropdown, "keydown", this._handleOpenKeydown.bind(this)) + } + _listenToOutsideClick() { + this._outsideClick = this._handleOutSideClick.bind(this), + i.b.on(document, "click", this._outsideClick) + } + _handleOutSideClick(n) { + var t = this._wrapper && this._wrapper.contains(n.target) + , e = n.target === this._dropdownContainer + , i = this._dropdownContainer && this._dropdownContainer.contains(n.target); + let o; + this._toggleButton || (this._elementToggle = r.a.find("[data-mdb-toggle]")), + this._elementToggle && this._elementToggle.forEach(t=>{ + var e = h.a.getDataAttribute(t, "toggle"); + e !== this._element.id && !this._element.classList.contains(e) || (this._toggleButton = t, + o = this._toggleButton.contains(n.target)) + } + ), + t || e || i || o || this.close() + } + close() { + var t = i.b.trigger(this._element, C); + this._isOpen && !t.defaultPrevented && (this._config.filter && this.hasSelectAll && (this._resetFilterState(), + this._updateOptionsListTemplate(this._optionsToRender), + this._config.multiple) && this._updateSelectAllState(), + this._removeDropdownEvents(), + h.a.removeClass(this.dropdown, "open"), + setTimeout(()=>{ + h.a.removeClass(this._input, R), + this._label && !this.hasSelection && (h.a.removeClass(this._label, P), + h.a.removeClass(this._input, P)), + this._updateLabelPositionWhileClosing() + } + , 0), + setTimeout(()=>{ + this._container && this._dropdownContainer.parentNode === this._container && this._container.removeChild(this._dropdownContainer), + this._popper.destroy(), + this._isOpen = !1, + i.b.off(this.dropdown, "transitionend"), + i.b.trigger(this._element, W) + } + , 200)) + } + _resetFilterState() { + this.filterInput.value = "", + this._filteredOptionsList = null + } + _removeDropdownEvents() { + i.b.off(document, "click", this._outsideClick), + this._config.filter && i.b.off(this.dropdown, "keydown"), + i.b.off(this.optionsWrapper, "click") + } + _addMutationObserver() { + this._mutationObserver = new MutationObserver(()=>{ + this._wrapper && (this._updateSelections(), + this._updateDisabledState()) + } + ), + this._observeMutationObserver() + } + _updateSelections() { + this._optionsToRender = this._getOptionsToRender(this._element), + this._plainOptions = this._getPlainOptions(this._optionsToRender), + this._selectionModel.clear(), + this._setDefaultSelections(), + this._updateInputValue(), + this._updateFakeLabelPosition(), + this._updateLabelPosition(), + this._updateClearButtonVisibility(), + this.hasSelectAll && this._updateSelectAllState(); + var t = this._config.filter && this.filterInput && this.filterInput.value; + this._isOpen && !t ? (this._updateOptionsListTemplate(this._optionsToRender), + this._setFirstActiveOption()) : this._isOpen && t ? (this._filterOptions(this.filterInput.value), + this._setFirstActiveOption()) : this._dropdownContainer = m(this._dropdownContainerId, this._config, this._input.offsetWidth, this._dropdownHeight, this._selectAllOption, this._optionsToRender, this._customContent) + } + _updateDisabledState() { + var t = r.a.findOne(A, this._wrapper); + this._element.hasAttribute("disabled") ? (this._config.disabled = !0, + t.setAttribute("disabled", "")) : (this._config.disabled = !1, + t.removeAttribute("disabled")) + } + _observeMutationObserver() { + this._mutationObserver && this._mutationObserver.observe(this._element, { + attributes: !0, + childList: !0, + characterData: !0, + subtree: !0 + }) + } + _disconnectMutationObserver() { + this._mutationObserver && (this._mutationObserver.disconnect(), + this._mutationObserver = null) + } + _createSelectAllOption() { + var t = this._selectAllId + , e = this._config.selectAllLabel + , n = f(this.options); + return new p(t,null,!0,"select-all",e,n,!1,!1,null,null,null) + } + dispose() { + this._disconnectMutationObserver(), + this._removeComponentEvents(), + this._destroyMaterialSelect(), + o.a.removeData(this._element, S) + } + _removeComponentEvents() { + i.b.off(this.input, "click"), + i.b.off(this.wrapper, this._handleKeydown.bind(this)), + i.b.off(this.clearButton, "click"), + i.b.off(this.clearButton, "keydown"), + i.b.off(window, "resize", this._handleWindowResize.bind(this)) + } + _destroyMaterialSelect() { + this._isOpen && this.close(), + this._destroyMaterialTemplate() + } + _destroyMaterialTemplate() { + const e = this._wrapper.parentNode; + var t = r.a.find("label", this._wrapper); + e.appendChild(this._element), + t.forEach(t=>{ + e.appendChild(t) + } + ), + t.forEach(t=>{ + h.a.removeClass(t, P) + } + ), + h.a.removeClass(this._element, L), + e.removeChild(this._wrapper) + } + setValue(t) { + this.options.filter(t=>t.selected).forEach(t=>t.nativeOption.selected = !1), + Array.isArray(t) ? t.forEach(t=>{ + this._selectByValue(t) + } + ) : this._selectByValue(t), + this._updateSelections() + } + _selectByValue(e) { + var t = this.options.find(t=>t.value === e); + return !!t && (t.nativeOption.selected = !0) + } + static jQueryInterface(n, i) { + return this.each(function() { + let t = o.a.getData(this, S); + var e = "object" == typeof n && n; + if ((t || !/dispose/.test(n)) && (t = t || new M(this,e), + "string" == typeof n)) { + if (void 0 === t[n]) + throw new TypeError('No method named "'.concat(n, '"')); + t[n](i) + } + }) + } + static getInstance(t) { + return o.a.getData(t, S) + } + static getOrCreateInstance(t) { + var e = 1 < arguments.length && void 0 !== arguments[1] ? arguments[1] : {}; + return this.getInstance(t) || new this(t,"object" == typeof e ? e : null) + } + } + t.a = M; + const I = Object(d.f)(); + r.a.find(".select").forEach(t=>{ + var e = M.getInstance(t); + e || new M(t) + } + ), + Object(d.i)(()=>{ + if (I) { + const t = I.fn[x]; + I.fn[x] = M.jQueryInterface, + I.fn[x].Constructor = M, + I.fn[x].noConflict = ()=>(I.fn[x] = t, + M.jQueryInterface) + } + } + ) + } + , function(t, e, n) { + "use strict"; + n.d(e, "a", function() { + return C + }); + n(17); + function p(t) { + return getComputedStyle(t) + } + function a(e, n) { + for (const i in n) { + let t = n[i]; + "number" == typeof t && (t = "".concat(t, "px")), + e.style[i] = t + } + } + function l(t) { + var e = document.createElement("div"); + return e.className = t, + e + } + const i = "undefined" != typeof Element && (Element.prototype.matches || Element.prototype.webkitMatchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector); + function c(t, e) { + if (i) + return i.call(t, e); + throw new Error("No element matching method supported") + } + function s(t) { + t.remove ? t.remove() : t.parentNode && t.parentNode.removeChild(t) + } + function u(t, e) { + return Array.prototype.filter.call(t.children, t=>c(t, e)) + } + const o = { + main: "ps", + rtl: "ps__rtl", + element: { + thumb: t=>"ps__thumb-".concat(t), + rail: t=>"ps__rail-".concat(t), + consuming: "ps__child--consume" + }, + state: { + focus: "ps--focus", + clicking: "ps--clicking", + active: t=>"ps--active-".concat(t), + scrolling: t=>"ps--scrolling-".concat(t) + } + }; + var v = o; + const r = { + x: null, + y: null + }; + function _(t, e) { + var t = t.element.classList + , n = o.state.scrolling(e); + t.contains(n) ? clearTimeout(r[e]) : t.add(n) + } + function y(t, e) { + r[e] = setTimeout(()=>t.isAlive && t.element.classList.remove(o.state.scrolling(e)), t.settings.scrollingThreshold) + } + class h { + constructor(t) { + this.element = t, + this.handlers = {} + } + bind(t, e) { + void 0 === this.handlers[t] && (this.handlers[t] = []), + this.handlers[t].push(e), + this.element.addEventListener(t, e, !1) + } + unbind(e, n) { + this.handlers[e] = this.handlers[e].filter(t=>!(!n || t === n) || (this.element.removeEventListener(e, t, !1), + !1)) + } + unbindAll() { + for (const t in this.handlers) + this.unbind(t) + } + get isEmpty() { + return Object.keys(this.handlers).every(t=>0 === this.handlers[t].length) + } + } + class d { + constructor() { + this.eventElements = [] + } + eventElement(e) { + let t = this.eventElements.filter(t=>t.element === e)[0]; + return t || (t = new h(e), + this.eventElements.push(t)), + t + } + bind(t, e, n) { + this.eventElement(t).bind(e, n) + } + unbind(t, e, n) { + t = this.eventElement(t); + t.unbind(e, n), + t.isEmpty && this.eventElements.splice(this.eventElements.indexOf(t), 1) + } + unbindAll() { + this.eventElements.forEach(t=>t.unbindAll()), + this.eventElements = [] + } + once(t, e, n) { + const i = this.eventElement(t) + , o = t=>{ + i.unbind(e, o), + n(t) + } + ; + i.bind(e, o) + } + } + n(11), + n(12); + function f(t) { + var e; + return "function" == typeof window.CustomEvent ? new CustomEvent(t) : ((e = document.createEvent("CustomEvent")).initCustomEvent(t, !1, !1, void 0), + e) + } + function g(t, e, n) { + var i = !(3 < arguments.length && void 0 !== arguments[3]) || arguments[3] + , o = 4 < arguments.length && void 0 !== arguments[4] && arguments[4]; + let r; + if ("top" === e) + r = ["contentHeight", "containerHeight", "scrollTop", "y", "up", "down"]; + else { + if ("left" !== e) + throw new Error("A proper axis should be provided"); + r = ["contentWidth", "containerWidth", "scrollLeft", "x", "left", "right"] + } + !function(t, e, n) { + var [n,i,o,r,s,a] = n + , l = !(3 < arguments.length && void 0 !== arguments[3]) || arguments[3] + , c = 4 < arguments.length && void 0 !== arguments[4] && arguments[4]; + var u = t.element; + t.reach[r] = null, + u[o] < 1 && (t.reach[r] = "start"); + u[o] > t[n] - t[i] - 1 && (t.reach[r] = "end"); + e && (u.dispatchEvent(f("ps-scroll-".concat(r))), + e < 0 ? u.dispatchEvent(f("ps-scroll-".concat(s))) : 0 < e && u.dispatchEvent(f("ps-scroll-".concat(a))), + l) && !function(t, e) { + _(t, e), + y(t, e) + }(t, r); + t.reach[r] && (e || c) && u.dispatchEvent(f("ps-".concat(r, "-reach-").concat(t.reach[r]))) + }(t, n, r, i, o) + } + function m(t) { + return parseInt(t, 10) || 0 + } + const b = { + isWebKit: "undefined" != typeof document && "WebkitAppearance"in document.documentElement.style, + supportsTouch: "undefined" != typeof window && ("ontouchstart"in window || "maxTouchPoints"in window.navigator && 0 < window.navigator.maxTouchPoints || window.DocumentTouch && document instanceof window.DocumentTouch), + supportsIePointer: "undefined" != typeof navigator && navigator.msMaxTouchPoints, + isChrome: "undefined" != typeof navigator && /Chrome/i.test(navigator && navigator.userAgent) + }; + var w = function(t) { + var e = t.element + , n = Math.floor(e.scrollTop) + , i = e.getBoundingClientRect() + , i = (t.containerWidth = Math.floor(i.width), + t.containerHeight = Math.floor(i.height), + t.contentWidth = e.scrollWidth, + t.contentHeight = e.scrollHeight, + e.contains(t.scrollbarXRail) || (u(e, v.element.rail("x")).forEach(t=>s(t)), + e.appendChild(t.scrollbarXRail)), + e.contains(t.scrollbarYRail) || (u(e, v.element.rail("y")).forEach(t=>s(t)), + e.appendChild(t.scrollbarYRail)), + !t.settings.suppressScrollX && t.containerWidth + t.settings.scrollXMarginOffset < t.contentWidth ? (t.scrollbarXActive = !0, + t.railXWidth = t.containerWidth - t.railXMarginWidth, + t.railXRatio = t.containerWidth / t.railXWidth, + t.scrollbarXWidth = O(t, m(t.railXWidth * t.containerWidth / t.contentWidth)), + t.scrollbarXLeft = m((t.negativeScrollAdjustment + e.scrollLeft) * (t.railXWidth - t.scrollbarXWidth) / (t.contentWidth - t.containerWidth))) : t.scrollbarXActive = !1, + !t.settings.suppressScrollY && t.containerHeight + t.settings.scrollYMarginOffset < t.contentHeight ? (t.scrollbarYActive = !0, + t.railYHeight = t.containerHeight - t.railYMarginHeight, + t.railYRatio = t.containerHeight / t.railYHeight, + t.scrollbarYHeight = O(t, m(t.railYHeight * t.containerHeight / t.contentHeight)), + t.scrollbarYTop = m(n * (t.railYHeight - t.scrollbarYHeight) / (t.contentHeight - t.containerHeight))) : t.scrollbarYActive = !1, + t.scrollbarXLeft >= t.railXWidth - t.scrollbarXWidth && (t.scrollbarXLeft = t.railXWidth - t.scrollbarXWidth), + t.scrollbarYTop >= t.railYHeight - t.scrollbarYHeight && (t.scrollbarYTop = t.railYHeight - t.scrollbarYHeight), + e) + , n = t + , o = { + width: n.railXWidth + } + , r = Math.floor(i.scrollTop); + n.isRtl ? o.left = n.negativeScrollAdjustment + i.scrollLeft + n.containerWidth - n.contentWidth : o.left = i.scrollLeft, + n.isScrollbarXUsingBottom ? o.bottom = n.scrollbarXBottom - r : o.top = n.scrollbarXTop + r, + a(n.scrollbarXRail, o), + o = { + top: r, + height: n.railYHeight + }, + n.isScrollbarYUsingRight ? n.isRtl ? o.right = n.contentWidth - (n.negativeScrollAdjustment + i.scrollLeft) - n.scrollbarYRight - n.scrollbarYOuterWidth - 9 : o.right = n.scrollbarYRight - i.scrollLeft : n.isRtl ? o.left = n.negativeScrollAdjustment + i.scrollLeft + 2 * n.containerWidth - n.contentWidth - n.scrollbarYLeft - n.scrollbarYOuterWidth : o.left = n.scrollbarYLeft + i.scrollLeft, + a(n.scrollbarYRail, o), + a(n.scrollbarX, { + left: n.scrollbarXLeft, + width: n.scrollbarXWidth - n.railBorderXWidth + }), + a(n.scrollbarY, { + top: n.scrollbarYTop, + height: n.scrollbarYHeight - n.railBorderYWidth + }), + t.scrollbarXActive ? e.classList.add(v.state.active("x")) : (e.classList.remove(v.state.active("x")), + t.scrollbarXWidth = 0, + t.scrollbarXLeft = 0, + e.scrollLeft = !0 === t.isRtl ? t.contentWidth : 0), + t.scrollbarYActive ? e.classList.add(v.state.active("y")) : (e.classList.remove(v.state.active("y")), + t.scrollbarYHeight = 0, + t.scrollbarYTop = 0, + e.scrollTop = 0) + }; + function O(t, e) { + return t.settings.minScrollbarLength && (e = Math.max(e, t.settings.minScrollbarLength)), + e = t.settings.maxScrollbarLength ? Math.min(e, t.settings.maxScrollbarLength) : e + } + function x(n, t) { + let[i,o,r,s,e,a,l,c,u] = t; + const h = n.element; + let d = null + , p = null + , f = null; + function g(t) { + t.touches && t.touches[0] && (t[r] = t.touches[0].pageY), + h[l] = d + f * (t[r] - p), + _(n, c), + w(n), + t.stopPropagation(), + t.preventDefault() + } + function m() { + y(n, c), + n[u].classList.remove(v.state.clicking), + n.event.unbind(n.ownerDocument, "mousemove", g) + } + function b(t, e) { + d = h[l], + e && t.touches && (t[r] = t.touches[0].pageY), + p = t[r], + f = (n[o] - n[i]) / (n[s] - n[a]), + e ? n.event.bind(n.ownerDocument, "touchmove", g) : (n.event.bind(n.ownerDocument, "mousemove", g), + n.event.once(n.ownerDocument, "mouseup", m), + t.preventDefault()), + n[u].classList.add(v.state.clicking), + t.stopPropagation() + } + n.event.bind(n[e], "mousedown", t=>{ + b(t) + } + ), + n.event.bind(n[e], "touchstart", t=>{ + b(t, !0) + } + ) + } + const S = { + "click-rail": function(n) { + n.event.bind(n.scrollbarY, "mousedown", t=>t.stopPropagation()), + n.event.bind(n.scrollbarYRail, "mousedown", t=>{ + var e = t.pageY - window.pageYOffset - n.scrollbarYRail.getBoundingClientRect().top > n.scrollbarYTop ? 1 : -1; + n.element.scrollTop += e * n.containerHeight, + w(n), + t.stopPropagation() + } + ), + n.event.bind(n.scrollbarX, "mousedown", t=>t.stopPropagation()), + n.event.bind(n.scrollbarXRail, "mousedown", t=>{ + var e = t.pageX - window.pageXOffset - n.scrollbarXRail.getBoundingClientRect().left > n.scrollbarXLeft ? 1 : -1; + n.element.scrollLeft += e * n.containerWidth, + w(n), + t.stopPropagation() + } + ) + }, + "drag-thumb": function(t) { + x(t, ["containerWidth", "contentWidth", "pageX", "railXWidth", "scrollbarX", "scrollbarXWidth", "scrollLeft", "x", "scrollbarXRail"]), + x(t, ["containerHeight", "contentHeight", "pageY", "railYHeight", "scrollbarY", "scrollbarYHeight", "scrollTop", "y", "scrollbarYRail"]) + }, + keyboard: function(r) { + const s = r.element; + r.event.bind(r.ownerDocument, "keydown", i=>{ + if (!(i.isDefaultPrevented && i.isDefaultPrevented() || i.defaultPrevented) && (c(s, ":hover") || c(r.scrollbarX, ":focus") || c(r.scrollbarY, ":focus"))) { + let t = document.activeElement || r.ownerDocument.activeElement; + if (t) { + if ("IFRAME" === t.tagName) + t = t.contentDocument.activeElement; + else + for (; t.shadowRoot; ) + t = t.shadowRoot.activeElement; + if (c(o = t, "input,[contenteditable]") || c(o, "select,[contenteditable]") || c(o, "textarea,[contenteditable]") || c(o, "button,[contenteditable]")) + return + } + var o; + let e = 0 + , n = 0; + switch (i.which) { + case 37: + e = i.metaKey ? -r.contentWidth : i.altKey ? -r.containerWidth : -30; + break; + case 38: + n = i.metaKey ? r.contentHeight : i.altKey ? r.containerHeight : 30; + break; + case 39: + e = i.metaKey ? r.contentWidth : i.altKey ? r.containerWidth : 30; + break; + case 40: + n = i.metaKey ? -r.contentHeight : i.altKey ? -r.containerHeight : -30; + break; + case 32: + n = i.shiftKey ? r.containerHeight : -r.containerHeight; + break; + case 33: + n = r.containerHeight; + break; + case 34: + n = -r.containerHeight; + break; + case 36: + n = r.contentHeight; + break; + case 35: + n = -r.contentHeight; + break; + default: + return + } + r.settings.suppressScrollX && 0 !== e || r.settings.suppressScrollY && 0 !== n || (s.scrollTop -= n, + s.scrollLeft += e, + w(r), + !function(t, e) { + var n = Math.floor(s.scrollTop); + if (0 === t) { + if (!r.scrollbarYActive) + return; + if (0 === n && 0 < e || n >= r.contentHeight - r.containerHeight && e < 0) + return !r.settings.wheelPropagation + } + if (n = s.scrollLeft, + 0 === e) { + if (!r.scrollbarXActive) + return; + if (0 === n && t < 0 || n >= r.contentWidth - r.containerWidth && 0 < t) + return !r.settings.wheelPropagation + } + return 1 + }(e, n)) || i.preventDefault() + } + } + ) + }, + wheel: function(a) { + const l = a.element; + function t(e) { + var [n,i] = function(t) { + let e = t.deltaX + , n = -1 * t.deltaY; + return void 0 !== e && void 0 !== n || (e = -1 * t.wheelDeltaX / 6, + n = t.wheelDeltaY / 6), + t.deltaMode && 1 === t.deltaMode && (e *= 10, + n *= 10), + e != e && n != n && (e = 0, + n = t.wheelDelta), + t.shiftKey ? [-n, -e] : [e, n] + }(e); + if (!function(e, n, i) { + if (!b.isWebKit && l.querySelector("select:focus")) + return 1; + if (l.contains(e)) { + let t = e; + for (; t && t !== l; ) { + if (t.classList.contains(v.element.consuming)) + return 1; + var o = p(t); + if (i && o.overflowY.match(/(scroll|auto)/)) { + var r = t.scrollHeight - t.clientHeight; + if (0 < r && (0 < t.scrollTop && i < 0 || t.scrollTop < r && 0 < i)) + return 1 + } + if (n && o.overflowX.match(/(scroll|auto)/)) { + r = t.scrollWidth - t.clientWidth; + if (0 < r && (0 < t.scrollLeft && n < 0 || t.scrollLeft < r && 0 < n)) + return 1 + } + t = t.parentNode + } + } + }(e.target, n, i)) { + let t = !1; + a.settings.useBothWheelAxes ? a.scrollbarYActive && !a.scrollbarXActive ? (i ? l.scrollTop -= i * a.settings.wheelSpeed : l.scrollTop += n * a.settings.wheelSpeed, + t = !0) : a.scrollbarXActive && !a.scrollbarYActive && (n ? l.scrollLeft += n * a.settings.wheelSpeed : l.scrollLeft -= i * a.settings.wheelSpeed, + t = !0) : (l.scrollTop -= i * a.settings.wheelSpeed, + l.scrollLeft += n * a.settings.wheelSpeed), + w(a), + (t = t || function(t, e) { + var n = Math.floor(l.scrollTop) + , i = 0 === l.scrollTop + , n = n + l.offsetHeight === l.scrollHeight + , o = 0 === l.scrollLeft + , r = l.scrollLeft + l.offsetWidth === l.scrollWidth; + let s; + return !(s = Math.abs(e) > Math.abs(t) ? i || n : o || r) || !a.settings.wheelPropagation + }(n, i)) && !e.ctrlKey && (e.stopPropagation(), + e.preventDefault()) + } + } + void 0 !== window.onwheel ? a.event.bind(l, "wheel", t) : void 0 !== window.onmousewheel && a.event.bind(l, "mousewheel", t) + }, + touch: function(l) { + if (b.supportsTouch || b.supportsIePointer) { + const d = l.element; + let r = {} + , s = 0 + , a = {} + , e = null; + function c(t, e) { + d.scrollTop -= e, + d.scrollLeft -= t, + w(l) + } + function u(t) { + return t.targetTouches ? t.targetTouches[0] : t + } + function h(t) { + return (!t.pointerType || "pen" !== t.pointerType || 0 !== t.buttons) && (t.targetTouches && 1 === t.targetTouches.length || !(!t.pointerType || "mouse" === t.pointerType || t.pointerType === t.MSPOINTER_TYPE_MOUSE)) + } + function t(t) { + h(t) && (t = u(t), + r.pageX = t.pageX, + r.pageY = t.pageY, + s = (new Date).getTime(), + null !== e) && clearInterval(e) + } + function n(t) { + var e, n, i, o; + h(t) && (e = (i = { + pageX: (i = u(t)).pageX, + pageY: i.pageY + }).pageX - r.pageX, + n = i.pageY - r.pageY, + !function(e, n, i) { + if (d.contains(e)) { + let t = e; + for (; t && t !== d; ) { + if (t.classList.contains(v.element.consuming)) + return 1; + var o = p(t); + if (i && o.overflowY.match(/(scroll|auto)/)) { + var r = t.scrollHeight - t.clientHeight; + if (0 < r && (0 < t.scrollTop && i < 0 || t.scrollTop < r && 0 < i)) + return 1 + } + if (n && o.overflowX.match(/(scroll|auto)/)) { + r = t.scrollWidth - t.clientWidth; + if (0 < r && (0 < t.scrollLeft && n < 0 || t.scrollLeft < r && 0 < n)) + return 1 + } + t = t.parentNode + } + } + }(t.target, e, n)) && (c(e, n), + r = i, + 0 < (o = (i = (new Date).getTime()) - s) && (a.x = e / o, + a.y = n / o, + s = i), + function(t, e) { + var n = Math.floor(d.scrollTop) + , i = d.scrollLeft + , o = Math.abs(t) + , r = Math.abs(e); + if (o < r) { + if (e < 0 && n === l.contentHeight - l.containerHeight || 0 < e && 0 === n) + return 0 === window.scrollY && 0 < e && b.isChrome + } else if (r < o && (t < 0 && i === l.contentWidth - l.containerWidth || 0 < t && 0 === i)) + ;return 1 + }(e, n)) && t.preventDefault() + } + function i() { + l.settings.swipeEasing && (clearInterval(e), + e = setInterval(function() { + l.isInitialized || !a.x && !a.y || Math.abs(a.x) < .01 && Math.abs(a.y) < .01 ? clearInterval(e) : (c(30 * a.x, 30 * a.y), + a.x *= .8, + a.y *= .8) + }, 10)) + } + b.supportsTouch ? (l.event.bind(d, "touchstart", t), + l.event.bind(d, "touchmove", n), + l.event.bind(d, "touchend", i)) : b.supportsIePointer && (window.PointerEvent ? (l.event.bind(d, "pointerdown", t), + l.event.bind(d, "pointermove", n), + l.event.bind(d, "pointerup", i)) : window.MSPointerEvent && (l.event.bind(d, "MSPointerDown", t), + l.event.bind(d, "MSPointerMove", n), + l.event.bind(d, "MSPointerUp", i))) + } + } + }; + class C { + constructor(t) { + var e = 1 < arguments.length && void 0 !== arguments[1] ? arguments[1] : {}; + if (!(t = "string" == typeof t ? document.querySelector(t) : t) || !t.nodeName) + throw new Error("no element is specified to initialize PerfectScrollbar"); + (this.element = t).classList.add(v.main), + this.settings = { + handlers: ["click-rail", "drag-thumb", "keyboard", "wheel", "touch"], + maxScrollbarLength: null, + minScrollbarLength: null, + scrollingThreshold: 1e3, + scrollXMarginOffset: 0, + scrollYMarginOffset: 0, + suppressScrollX: !1, + suppressScrollY: !1, + swipeEasing: !0, + useBothWheelAxes: !1, + wheelPropagation: !0, + wheelSpeed: 1 + }; + for (const s in e) + this.settings[s] = e[s]; + this.containerWidth = null, + this.containerHeight = null, + this.contentWidth = null, + this.contentHeight = null; + var n = ()=>t.classList.add(v.state.focus) + , i = ()=>t.classList.remove(v.state.focus) + , o = (this.isRtl = "rtl" === p(t).direction, + !0 === this.isRtl && t.classList.add(v.rtl), + this.isNegativeScroll = (o = t.scrollLeft, + t.scrollLeft = -1, + r = t.scrollLeft < 0, + t.scrollLeft = o, + r), + this.negativeScrollAdjustment = this.isNegativeScroll ? t.scrollWidth - t.clientWidth : 0, + this.event = new d, + this.ownerDocument = t.ownerDocument || document, + this.scrollbarXRail = l(v.element.rail("x")), + t.appendChild(this.scrollbarXRail), + this.scrollbarX = l(v.element.thumb("x")), + this.scrollbarXRail.appendChild(this.scrollbarX), + this.scrollbarX.setAttribute("tabindex", 0), + this.event.bind(this.scrollbarX, "focus", n), + this.event.bind(this.scrollbarX, "blur", i), + this.scrollbarXActive = null, + this.scrollbarXWidth = null, + this.scrollbarXLeft = null, + p(this.scrollbarXRail)) + , r = (this.scrollbarXBottom = parseInt(o.bottom, 10), + isNaN(this.scrollbarXBottom) ? (this.isScrollbarXUsingBottom = !1, + this.scrollbarXTop = m(o.top)) : this.isScrollbarXUsingBottom = !0, + this.railBorderXWidth = m(o.borderLeftWidth) + m(o.borderRightWidth), + a(this.scrollbarXRail, { + display: "block" + }), + this.railXMarginWidth = m(o.marginLeft) + m(o.marginRight), + a(this.scrollbarXRail, { + display: "" + }), + this.railXWidth = null, + this.railXRatio = null, + this.scrollbarYRail = l(v.element.rail("y")), + t.appendChild(this.scrollbarYRail), + this.scrollbarY = l(v.element.thumb("y")), + this.scrollbarYRail.appendChild(this.scrollbarY), + this.scrollbarY.setAttribute("tabindex", 0), + this.event.bind(this.scrollbarY, "focus", n), + this.event.bind(this.scrollbarY, "blur", i), + this.scrollbarYActive = null, + this.scrollbarYHeight = null, + this.scrollbarYTop = null, + p(this.scrollbarYRail)); + this.scrollbarYRight = parseInt(r.right, 10), + isNaN(this.scrollbarYRight) ? (this.isScrollbarYUsingRight = !1, + this.scrollbarYLeft = m(r.left)) : this.isScrollbarYUsingRight = !0, + this.scrollbarYOuterWidth = this.isRtl ? m((o = p(o = this.scrollbarY)).width) + m(o.paddingLeft) + m(o.paddingRight) + m(o.borderLeftWidth) + m(o.borderRightWidth) : null, + this.railBorderYWidth = m(r.borderTopWidth) + m(r.borderBottomWidth), + a(this.scrollbarYRail, { + display: "block" + }), + this.railYMarginHeight = m(r.marginTop) + m(r.marginBottom), + a(this.scrollbarYRail, { + display: "" + }), + this.railYHeight = null, + this.railYRatio = null, + this.reach = { + x: t.scrollLeft <= 0 ? "start" : t.scrollLeft >= this.contentWidth - this.containerWidth ? "end" : null, + y: t.scrollTop <= 0 ? "start" : t.scrollTop >= this.contentHeight - this.containerHeight ? "end" : null + }, + this.isAlive = !0, + this.settings.handlers.forEach(t=>S[t](this)), + this.lastScrollTop = Math.floor(t.scrollTop), + this.lastScrollLeft = t.scrollLeft, + this.event.bind(this.element, "scroll", t=>this.onScroll(t)), + w(this) + } + update() { + this.isAlive && (this.negativeScrollAdjustment = this.isNegativeScroll ? this.element.scrollWidth - this.element.clientWidth : 0, + a(this.scrollbarXRail, { + display: "block" + }), + a(this.scrollbarYRail, { + display: "block" + }), + this.railXMarginWidth = m(p(this.scrollbarXRail).marginLeft) + m(p(this.scrollbarXRail).marginRight), + this.railYMarginHeight = m(p(this.scrollbarYRail).marginTop) + m(p(this.scrollbarYRail).marginBottom), + a(this.scrollbarXRail, { + display: "none" + }), + a(this.scrollbarYRail, { + display: "none" + }), + w(this), + g(this, "top", 0, !1, !0), + g(this, "left", 0, !1, !0), + a(this.scrollbarXRail, { + display: "" + }), + a(this.scrollbarYRail, { + display: "" + })) + } + onScroll(t) { + this.isAlive && (w(this), + g(this, "top", this.element.scrollTop - this.lastScrollTop), + g(this, "left", this.element.scrollLeft - this.lastScrollLeft), + this.lastScrollTop = Math.floor(this.element.scrollTop), + this.lastScrollLeft = this.element.scrollLeft) + } + destroy() { + this.isAlive && (this.event.unbindAll(), + s(this.scrollbarX), + s(this.scrollbarY), + s(this.scrollbarXRail), + s(this.scrollbarYRail), + this.removePsClasses(), + this.element = null, + this.scrollbarX = null, + this.scrollbarY = null, + this.scrollbarXRail = null, + this.scrollbarYRail = null, + this.isAlive = !1) + } + removePsClasses() { + this.element.className = this.element.className.split(" ").filter(t=>!t.match(/^ps([-_].+|)$/)).join(" ") + } + } + } + , function(t, e, n) { + "use strict"; + var i = n(3) + , o = n(1) + , r = n(69) + , n = n(2); + const s = "tooltip" + , a = [{ + name: "show" + }, { + name: "shown" + }, { + name: "hide" + }, { + name: "hidden" + }, { + name: "inserted" + }]; + class l extends r.a { + constructor(t, e) { + super(t, e), + this._init() + } + dispose() { + o.b.off(this._element, "show.bs.tooltip"), + o.b.off(this._element, "shown.bs.tooltip"), + o.b.off(this._element, "hide.bs.tooltip"), + o.b.off(this._element, "hidden.bs.tooltip"), + o.b.off(this._element, "inserted.bs.tooltip"), + super.dispose() + } + static get NAME() { + return s + } + _init() { + this._bindMdbEvents() + } + _bindMdbEvents() { + o.b.extend(this._element, a, s) + } + } + n.a.find('[data-mdb-toggle="tooltip"]').forEach(t=>{ + var e = l.getInstance(t); + e || new l(t) + } + ), + Object(i.i)(()=>{ + const t = Object(i.f)(); + if (t) { + const e = t.fn[s]; + t.fn[s] = l.jQueryInterface, + t.fn[s].Constructor = l, + t.fn[s].noConflict = ()=>(t.fn[s] = e, + l.jQueryInterface) + } + } + ), + e.a = l + } + , function(t, e, n) { + "use strict"; + var i, o, r, s, a, l, c, u = n(26), h = n(23), d = n(13), p = n(14), f = n(29), g = n(15), m = n(56), b = n(38), v = n(79), n = n(151), _ = d.Symbol, y = _ && _.prototype; + !h || !g(_) || "description"in y && void 0 === _().description || (i = {}, + n(d = function() { + var t = arguments.length < 1 || void 0 === arguments[0] ? void 0 : b(arguments[0]) + , e = m(y, this) ? new _(t) : void 0 === t ? _() : _(t); + return "" === t && (i[e] = !0), + e + } + , _), + (d.prototype = y).constructor = d, + o = "Symbol(description detection)" === String(_("description detection")), + r = p(y.valueOf), + s = p(y.toString), + a = /^Symbol\((.*)\)[^)]+$/, + l = p("".replace), + c = p("".slice), + v(y, "description", { + configurable: !0, + get: function() { + var t = r(this); + return f(i, t) ? "" : (t = s(t), + "" === (t = o ? c(t, 7, -1) : l(t, a, "$1")) ? void 0 : t) + } + }), + u({ + global: !0, + constructor: !0, + forced: !0 + }, { + Symbol: d + })) + } + , function(t, e, n) { + "use strict"; + var i = n(3) + , o = n(7) + , r = n(0) + , s = n(2) + , a = n(1); + const l = "animation" + , c = "mdb.animation"; + const u = { + animation: "string", + animationStart: "string", + animationShowOnLoad: "boolean", + onStart: "(null|function)", + onEnd: "(null|function)", + onHide: "(null|function)", + onShow: "(null|function)", + animationOnScroll: "(string)", + animationWindowHeight: "number", + animationOffset: "(number|string)", + animationDelay: "(number|string)", + animationDuration: "(number|string)", + animationReverse: "boolean", + animationInterval: "(number|string)", + animationRepeat: "(number|boolean)", + animationReset: "boolean" + } + , h = { + animation: "fade", + animationStart: "onClick", + animationShowOnLoad: !0, + onStart: null, + onEnd: null, + onHide: null, + onShow: null, + animationOnScroll: "once", + animationWindowHeight: 0, + animationOffset: 0, + animationDelay: 0, + animationDuration: 500, + animationReverse: !1, + animationInterval: 0, + animationRepeat: !1, + animationReset: !1 + }; + class d { + constructor(t, e) { + this._element = t, + this._animateElement = this._getAnimateElement(), + this._isFirstScroll = !0, + this._repeatAnimateOnScroll = !0, + this._options = this._getConfig(e), + this._element && o.a.setData(t, c, this) + } + static get NAME() { + return l + } + init() { + this._init() + } + startAnimation() { + this._startAnimation() + } + stopAnimation() { + this._clearAnimationClass() + } + changeAnimationType(t) { + this._options.animation = t + } + dispose() { + a.b.off(this._element, "mousedown"), + a.b.off(this._animateElement, "animationend"), + a.b.off(window, "scroll"), + a.b.off(this._element, "mouseover"), + o.a.removeData(this._element, c), + this._element = null, + this._animateElement = null, + this._isFirstScroll = null, + this._repeatAnimateOnScroll = null, + this._options = null + } + _init() { + switch (this._options.animationStart) { + case "onHover": + this._bindHoverEvents(); + break; + case "onLoad": + this._startAnimation(); + break; + case "onScroll": + this._bindScrollEvents(); + break; + case "onClick": + this._bindClickEvents() + } + this._bindTriggerOnEndCallback(), + this._options.animationReset && this._bindResetAnimationAfterFinish() + } + _getAnimateElement() { + var t = r.a.getDataAttribute(this._element, "animation-target"); + return t ? s.a.find(t)[0] : this._element + } + _getConfig(t) { + var e = r.a.getDataAttributes(this._animateElement); + return t = { + ...h, + ...e, + ...t + }, + Object(i.j)(l, t, u), + t + } + _animateOnScroll() { + var t = r.a.offset(this._animateElement).top + , e = this._animateElement.offsetHeight + , n = window.innerHeight + , n = t + this._options.animationOffset <= n && 0 <= t + this._options.animationOffset + e + , t = "visible" === this._animateElement.style.visibility; + switch (!0) { + case n && this._isFirstScroll: + this._isFirstScroll = !1, + this._startAnimation(); + break; + case !n && this._isFirstScroll: + this._isFirstScroll = !1, + this._hideAnimateElement(); + break; + case n && !t && this._repeatAnimateOnScroll: + "repeat" !== this._options.animationOnScroll && (this._repeatAnimateOnScroll = !1), + this._callback(this._options.onShow), + this._showAnimateElement(), + this._startAnimation(); + break; + case !n && t && this._repeatAnimateOnScroll: + this._hideAnimateElement(), + this._clearAnimationClass(), + this._callback(this._options.onHide) + } + } + _addAnimatedClass() { + r.a.addClass(this._animateElement, "animation"), + r.a.addClass(this._animateElement, this._options.animation) + } + _clearAnimationClass() { + this._animateElement.classList.remove(this._options.animation, "animation") + } + _removeInvisibleClass() { + r.a.removeClass(this._animateElement, "invisible") + } + _startAnimation() { + this._callback(this._options.onStart), + this._removeInvisibleClass(), + this._addAnimatedClass(), + this._options.animationRepeat && !this._options.animationInterval && this._setAnimationRepeat(), + this._options.animationReverse && this._setAnimationReverse(), + this._options.animationDelay && this._setAnimationDelay(), + this._options.animationDuration && this._setAnimationDuration(), + this._options.animationInterval && this._setAnimationInterval() + } + _setAnimationReverse() { + r.a.style(this._animateElement, { + animationIterationCount: !0 === this._options.animationRepeat ? "infinite" : "2", + animationDirection: "alternate" + }) + } + _setAnimationDuration() { + r.a.style(this._animateElement, { + animationDuration: "".concat(this._options.animationDuration, "ms") + }) + } + _setAnimationDelay() { + r.a.style(this._animateElement, { + animationDelay: "".concat(this._options.animationDelay, "ms") + }) + } + _setAnimationRepeat() { + r.a.style(this._animateElement, { + animationIterationCount: !0 === this._options.animationRepeat ? "infinite" : this._options.animationRepeat + }) + } + _setAnimationInterval() { + a.b.on(this._animateElement, "animationend", ()=>{ + this._clearAnimationClass(), + setTimeout(()=>{ + this._addAnimatedClass() + } + , this._options.animationInterval) + } + ) + } + _hideAnimateElement() { + r.a.style(this._animateElement, { + visibility: "hidden" + }) + } + _showAnimateElement() { + r.a.style(this._animateElement, { + visibility: "visible" + }) + } + _bindResetAnimationAfterFinish() { + a.b.on(this._animateElement, "animationend", ()=>{ + this._clearAnimationClass() + } + ) + } + _bindTriggerOnEndCallback() { + a.b.on(this._animateElement, "animationend", ()=>{ + this._callback(this._options.onEnd) + } + ) + } + _bindScrollEvents() { + this._options.animationShowOnLoad || this._animateOnScroll(), + a.b.on(window, "scroll", ()=>{ + this._animateOnScroll() + } + ) + } + _bindClickEvents() { + a.b.on(this._element, "mousedown", ()=>{ + this._startAnimation() + } + ) + } + _bindHoverEvents() { + a.b.one(this._element, "mouseover", ()=>{ + this._startAnimation() + } + ), + a.b.one(this._animateElement, "animationend", ()=>{ + setTimeout(()=>{ + this._bindHoverEvents() + } + , 100) + } + ) + } + _callback(t) { + t instanceof Function && t() + } + static autoInit(t) { + t._init() + } + static jQueryInterface(t) { + new d(this[0],t).init() + } + static getInstance(t) { + return o.a.getData(t, c) + } + static getOrCreateInstance(t) { + var e = 1 < arguments.length && void 0 !== arguments[1] ? arguments[1] : {}; + return this.getInstance(t) || new this(t,"object" == typeof e ? e : null) + } + } + s.a.find('[data-mdb-toggle="animation"]').forEach(t=>{ + d.autoInit(new d(t)) + } + ), + Object(i.i)(()=>{ + const t = Object(i.f)(); + if (t) { + const e = t.fn[l]; + t.fn[l] = d.jQueryInterface, + t.fn[l].Constructor = d, + t.fn[l].noConflict = ()=>(t.fn[l] = e, + d.jQueryInterface) + } + } + ), + e.a = d + } + , function(t, e, n) { + "use strict"; + var i = n(6) + , o = n(4) + , n = n(45); + const r = "mousedown.bs.".concat("backdrop") + , s = { + className: "modal-backdrop", + clickCallback: null, + isAnimated: !1, + isVisible: !0, + rootElement: "body" + } + , a = { + className: "string", + clickCallback: "(function|null)", + isAnimated: "boolean", + isVisible: "boolean", + rootElement: "(element|string)" + }; + class l extends n.a { + constructor(t) { + super(), + this._config = this._getConfig(t), + this._isAppended = !1, + this._element = null + } + static get Default() { + return s + } + static get DefaultType() { + return a + } + static get NAME() { + return "backdrop" + } + show(t) { + var e; + this._config.isVisible ? (this._append(), + e = this._getElement(), + this._config.isAnimated && Object(o.p)(e), + e.classList.add("show"), + this._emulateAnimation(()=>{ + Object(o.b)(t) + } + )) : Object(o.b)(t) + } + hide(t) { + this._config.isVisible ? (this._getElement().classList.remove("show"), + this._emulateAnimation(()=>{ + this.dispose(), + Object(o.b)(t) + } + )) : Object(o.b)(t) + } + dispose() { + this._isAppended && (i.a.off(this._element, r), + this._element.remove(), + this._isAppended = !1) + } + _getElement() { + var t; + return this._element || ((t = document.createElement("div")).className = this._config.className, + this._config.isAnimated && t.classList.add("fade"), + this._element = t), + this._element + } + _configAfterMerge(t) { + return t.rootElement = Object(o.e)(t.rootElement), + t + } + _append() { + var t; + this._isAppended || (t = this._getElement(), + this._config.rootElement.append(t), + i.a.on(t, r, ()=>{ + Object(o.b)(this._config.clickCallback) + } + ), + this._isAppended = !0) + } + _emulateAnimation(t) { + Object(o.c)(t, this._getElement(), this._config.isAnimated) + } + } + e.a = l + } + , function(t, e, n) { + "use strict"; + var i = n(6) + , o = n(8) + , n = n(45); + const r = ".".concat("bs.focustrap") + , s = "focusin".concat(r) + , a = "keydown.tab".concat(r) + , l = { + autofocus: !0, + trapElement: null + } + , c = { + autofocus: "boolean", + trapElement: "element" + }; + class u extends n.a { + constructor(t) { + super(), + this._config = this._getConfig(t), + this._isActive = !1, + this._lastTabNavDirection = null + } + static get Default() { + return l + } + static get DefaultType() { + return c + } + static get NAME() { + return "focustrap" + } + activate() { + this._isActive || (this._config.autofocus && this._config.trapElement.focus(), + i.a.off(document, r), + i.a.on(document, s, t=>this._handleFocusin(t)), + i.a.on(document, a, t=>this._handleKeydown(t)), + this._isActive = !0) + } + deactivate() { + this._isActive && (this._isActive = !1, + i.a.off(document, r)) + } + _handleFocusin(t) { + var e = this._config["trapElement"]; + t.target === document || t.target === e || e.contains(t.target) || (0 === (t = o.a.focusableChildren(e)).length ? e : "backward" === this._lastTabNavDirection ? t[t.length - 1] : t[0]).focus() + } + _handleKeydown(t) { + "Tab" === t.key && (this._lastTabNavDirection = t.shiftKey ? "backward" : "forward") + } + } + e.a = u + } + , function(t, e, n) { + "use strict"; + n.d(e, "a", function() { + return h + }); + var e = n(44) + , i = n(62) + , o = n(63) + , r = n(61) + , s = n(60) + , a = n(99) + , l = n(100) + , c = n(101) + , u = n(97) + , n = n(98) + , i = [i.a, o.a, r.a, s.a, a.a, l.a, c.a, u.a, n.a] + , h = Object(e.b)({ + defaultModifiers: i + }) + } + , function(t, e, n) { + "use strict"; + var i = {}.propertyIsEnumerable + , o = Object.getOwnPropertyDescriptor + , r = o && !i.call({ + 1: 2 + }, 1); + e.f = r ? function(t) { + t = o(this, t); + return !!t && t.enumerable + } + : i + } + , function(t, e, n) { + "use strict"; + var i = "object" == typeof document && document.all; + t.exports = { + all: i, + IS_HTMLDDA: void 0 === i && void 0 !== i + } + } + , function(t, e, n) { + "use strict"; + var i = n(48) + , o = n(15) + , r = n(56) + , n = n(145) + , s = Object; + t.exports = n ? function(t) { + return "symbol" == typeof t + } + : function(t) { + var e = i("Symbol"); + return o(e) && r(e.prototype, s(t)) + } + } + , function(t, e, n) { + "use strict"; + n = n(146); + t.exports = n && !Symbol.sham && "symbol" == typeof Symbol.iterator + } + , function(t, e, n) { + "use strict"; + var i = n(90) + , o = n(16) + , r = n(13).String; + t.exports = !!Object.getOwnPropertySymbols && !o(function() { + var t = Symbol("symbol detection"); + return !r(t) || !(Object(t)instanceof Symbol) || !Symbol.sham && i && i < 41 + }) + } + , function(t, e, n) { + "use strict"; + var n = n(14) + , i = 0 + , o = Math.random() + , r = n(1..toString); + t.exports = function(t) { + return "Symbol(" + (void 0 === t ? "" : t) + ")_" + r(++i + o, 36) + } + } + , function(t, e, n) { + "use strict"; + var i = n(23) + , o = n(16) + , r = n(91); + t.exports = !i && !o(function() { + return 7 !== Object.defineProperty(r("div"), "a", { + get: function() { + return 7 + } + }).a + }) + } + , function(t, e, n) { + "use strict"; + var i = n(23) + , n = n(16); + t.exports = i && n(function() { + return 42 !== Object.defineProperty(function() {}, "prototype", { + value: 42, + writable: !1 + }).prototype + }) + } + , function(t, e, n) { + "use strict"; + var i = n(14) + , o = n(16) + , r = n(15) + , s = n(29) + , a = n(23) + , l = n(117).CONFIGURABLE + , c = n(118) + , n = n(46) + , u = n.enforce + , h = n.get + , d = String + , p = Object.defineProperty + , f = i("".slice) + , g = i("".replace) + , m = i([].join) + , b = a && !o(function() { + return 8 !== p(function() {}, "length", { + value: 8 + }).length + }) + , v = String(String).split("String") + , n = t.exports = function(t, e, n) { + "Symbol(" === f(d(e), 0, 7) && (e = "[" + g(d(e), /^Symbol\(([^)]*)\)/, "$1") + "]"), + n && n.getter && (e = "get " + e), + n && n.setter && (e = "set " + e), + (!s(t, "name") || l && t.name !== e) && (a ? p(t, "name", { + value: e, + configurable: !0 + }) : t.name = e), + b && n && s(n, "arity") && t.length !== n.arity && p(t, "length", { + value: n.arity + }); + try { + n && s(n, "constructor") && n.constructor ? a && p(t, "prototype", { + writable: !1 + }) : t.prototype && (t.prototype = void 0) + } catch (t) {} + n = u(t); + return s(n, "source") || (n.source = m(v, "string" == typeof e ? e : "")), + t + } + ; + Function.prototype.toString = n(function() { + return r(this) && h(this).source || c(this) + }, "toString") + } + , function(t, e, n) { + "use strict"; + var l = n(29) + , c = n(210) + , u = n(111) + , h = n(40); + t.exports = function(t, e, n) { + for (var i = c(e), o = h.f, r = u.f, s = 0; s < i.length; s++) { + var a = i[s]; + l(t, a) || n && l(n, a) || o(t, a, r(e, a)) + } + } + } + , function(t, e, n) { + "use strict"; + var i = n(153) + , o = n(121).concat("length", "prototype"); + e.f = Object.getOwnPropertyNames || function(t) { + return i(t, o) + } + } + , function(t, e, n) { + "use strict"; + var i = n(14) + , s = n(29) + , a = n(77) + , l = n(154).indexOf + , c = n(120) + , u = i([].push); + t.exports = function(t, e) { + var n, i = a(t), o = 0, r = []; + for (n in i) + !s(c, n) && s(i, n) && u(r, n); + for (; e.length > o; ) + !s(i, n = e[o++]) || ~l(r, n) || u(r, n); + return r + } + } + , function(t, e, n) { + "use strict"; + function i(a) { + return function(t, e, n) { + var i, o = l(t), r = u(o), s = c(n, r); + if (a && e != e) { + for (; s < r; ) + if ((i = o[s++]) != i) + return !0 + } else + for (; s < r; s++) + if ((a || s in o) && o[s] === e) + return a || s || 0; + return !a && -1 + } + } + var l = n(77) + , c = n(155) + , u = n(58); + t.exports = { + includes: i(!0), + indexOf: i(!1) + } + } + , function(t, e, n) { + "use strict"; + var i = n(92) + , o = Math.max + , r = Math.min; + t.exports = function(t, e) { + t = i(t); + return t < 0 ? o(t + e, 0) : r(t, e) + } + } + , function(t, e, n) { + "use strict"; + var i = n(92) + , o = Math.min; + t.exports = function(t) { + return 0 < t ? o(i(t), 9007199254740991) : 0 + } + } + , function(t, e, n) { + "use strict"; + e.f = Object.getOwnPropertySymbols + } + , function(t, e, n) { + "use strict"; + var i = n(20) + , o = n(80) + , n = n(40).f + , r = i("unscopables") + , s = Array.prototype; + void 0 === s[r] && n(s, r, { + configurable: !0, + value: o(null) + }), + t.exports = function(t) { + s[r][t] = !0 + } + } + , function(t, e, n) { + "use strict"; + var i = n(153) + , o = n(121); + t.exports = Object.keys || function(t) { + return i(t, o) + } + } + , function(t, e, n) { + "use strict"; + n = n(48); + t.exports = n("document", "documentElement") + } + , function(t, e, n) { + "use strict"; + function g() { + return this + } + var m = n(26) + , b = n(22) + , v = n(43) + , i = n(117) + , _ = n(15) + , y = n(162) + , w = n(164) + , O = n(123) + , x = n(82) + , S = n(57) + , C = n(41) + , o = n(20) + , E = n(81) + , n = n(163) + , k = i.PROPER + , A = i.CONFIGURABLE + , j = n.IteratorPrototype + , T = n.BUGGY_SAFARI_ITERATORS + , L = o("iterator") + , P = "values"; + t.exports = function(t, e, n, i, o, r, s) { + y(n, e, i); + function a(t) { + if (t === o && p) + return p; + if (!T && t && t in h) + return h[t]; + switch (t) { + case "keys": + case P: + case "entries": + return function() { + return new n(this,t) + } + } + return function() { + return new n(this) + } + } + var l, c, i = e + " Iterator", u = !1, h = t.prototype, d = h[L] || h["@@iterator"] || o && h[o], p = !T && d || a(o), f = "Array" === e && h.entries || d; + if (f && (f = w(f.call(new t))) !== Object.prototype && f.next && (v || w(f) === j || (O ? O(f, j) : _(f[L]) || C(f, L, g)), + x(f, i, !0, !0), + v) && (E[i] = g), + k && o === P && d && d.name !== P && (!v && A ? S(h, "name", P) : (u = !0, + p = function() { + return b(d, this) + } + )), + o) + if (l = { + values: a(P), + keys: r ? p : a("keys"), + entries: a("entries") + }, + s) + for (c in l) + !T && !u && c in h || C(h, c, l[c]); + else + m({ + target: e, + proto: !0, + forced: T || u + }, l); + return v && !s || h[L] === p || C(h, L, p, { + name: o + }), + E[e] = p, + l + } + } + , function(t, e, n) { + "use strict"; + function o() { + return this + } + var r = n(163).IteratorPrototype + , s = n(80) + , a = n(76) + , l = n(82) + , c = n(81); + t.exports = function(t, e, n, i) { + e += " Iterator"; + return t.prototype = s(r, { + next: a(+!i, n) + }), + l(t, e, !1, !0), + c[e] = o, + t + } + } + , function(t, e, n) { + "use strict"; + var i, o, r = n(16), s = n(15), a = n(35), l = n(80), c = n(164), u = n(41), h = n(20), n = n(43), d = h("iterator"), h = !1; + [].keys && ("next"in (o = [].keys()) ? (c = c(c(o))) !== Object.prototype && (i = c) : h = !0), + !a(i) || r(function() { + var t = {}; + return i[d].call(t) !== t + }) ? i = {} : n && (i = l(i)), + s(i[d]) || u(i, d, function() { + return this + }), + t.exports = { + IteratorPrototype: i, + BUGGY_SAFARI_ITERATORS: h + } + } + , function(t, e, n) { + "use strict"; + var i = n(29) + , o = n(15) + , r = n(50) + , s = n(119) + , n = n(214) + , a = s("IE_PROTO") + , l = Object + , c = l.prototype; + t.exports = n ? l.getPrototypeOf : function(t) { + var e, t = r(t); + return i(t, a) ? t[a] : (e = t.constructor, + o(e) && t instanceof e ? e.prototype : t instanceof l ? c : null) + } + } + , function(t, e, n) { + "use strict"; + t.exports = function(t, e) { + return { + value: t, + done: e + } + } + } + , function(t, e, n) { + "use strict"; + var i = n(16) + , o = n(13).RegExp + , n = i(function() { + var t = o("a", "y"); + return t.lastIndex = 2, + null !== t.exec("abcd") + }) + , r = n || i(function() { + return !o("a", "y").sticky + }) + , i = n || i(function() { + var t = o("^r", "gy"); + return t.lastIndex = 2, + null !== t.exec("str") + }); + t.exports = { + BROKEN_CARET: i, + MISSED_STICKY: r, + UNSUPPORTED_Y: n + } + } + , function(t, e, n) { + "use strict"; + var i = n(16) + , o = n(13).RegExp; + t.exports = i(function() { + var t = o(".", "s"); + return !(t.dotAll && t.exec("\n") && "s" === t.flags) + }) + } + , function(t, e, n) { + "use strict"; + var i = n(16) + , o = n(13).RegExp; + t.exports = i(function() { + var t = o("(?
b)", "g"); + return "b" !== t.exec("b").groups.a || "bc" !== "b".replace(t, "$c") + }) + } + , function(t, e, n) { + "use strict"; + var n = n(89) + , i = Function.prototype + , o = i.apply + , r = i.call; + t.exports = "object" == typeof Reflect && Reflect.apply || (n ? r.bind(o) : function() { + return r.apply(o, arguments) + } + ) + } + , function(t, e, n) { + "use strict"; + var i = n(55) + , o = n(14); + t.exports = function(t) { + if ("Function" === i(t)) + return o(t) + } + } + , function(t, e, n) { + "use strict"; + var i = n(48) + , o = n(79) + , r = n(20) + , s = n(23) + , a = r("species"); + t.exports = function(t) { + t = i(t); + s && t && !t[a] && o(t, a, { + configurable: !0, + get: function() { + return this + } + }) + } + } + , function(t, e, n) { + "use strict"; + t.exports = "\t\n\v\f\r                 \u2028\u2029\ufeff" + } + , function(t, e, n) { + "use strict"; + function v(t, e) { + var n = t.length + , i = y(n / 2); + if (n < 8) { + for (var o, r, s = t, a = e, l = s.length, c = 1; c < l; ) { + for (o = s[r = c]; r && 0 < a(s[r - 1], o); ) + s[r] = s[--r]; + r !== c++ && (s[r] = o) + } + return s + } + for (var u = t, h = v(_(t, 0, i), e), d = v(_(t, i), e), p = e, f = h.length, g = d.length, m = 0, b = 0; m < f || b < g; ) + u[m + b] = m < f && b < g ? p(h[m], d[b]) <= 0 ? h[m++] : d[b++] : m < f ? h[m++] : d[b++]; + return u + } + var _ = n(174) + , y = Math.floor; + t.exports = v + } + , function(t, e, n) { + "use strict"; + var l = n(155) + , c = n(58) + , u = n(175) + , h = Array + , d = Math.max; + t.exports = function(t, e, n) { + for (var i = c(t), o = l(e, i), r = l(void 0 === n ? i : n, i), s = h(d(r - o, 0)), a = 0; o < r; o++, + a++) + u(s, a, t[o]); + return s.length = a, + s + } + } + , function(t, e, n) { + "use strict"; + var i = n(113) + , o = n(40) + , r = n(76); + t.exports = function(t, e, n) { + e = i(e); + e in t ? o.f(t, e, r(0, n)) : t[e] = n + } + } + , function(t, e, n) { + "use strict"; + var i = n(16); + t.exports = function(t, e) { + var n = [][t]; + return !!n && i(function() { + n.call(null, e || function() { + return 1 + } + , 1) + }) + } + } + , function(t, e, n) { + "use strict"; + function i() {} + function o(t) { + if (!l(t)) + return !1; + try { + return p(i, d, t), + !0 + } catch (t) { + return !1 + } + } + function r(t) { + if (!l(t)) + return !1; + switch (c(t)) { + case "AsyncFunction": + case "GeneratorFunction": + case "AsyncGeneratorFunction": + return !1 + } + try { + return m || !!g(f, h(t)) + } catch (t) { + return !0 + } + } + var s = n(14) + , a = n(16) + , l = n(15) + , c = n(93) + , u = n(48) + , h = n(118) + , d = [] + , p = u("Reflect", "construct") + , f = /^\s*(?:class|function)\b/ + , g = s(f.exec) + , m = !f.exec(i); + r.sham = !0, + t.exports = !p || a(function() { + var t; + return o(o.call) || !o(Object) || !o(function() { + t = !0 + }) || t + }) ? r : o + } + , function(t, e, n) { + "use strict"; + function i(t) { + return function() { + j(t) + } + } + function o(t) { + j(t.data) + } + function r(t) { + l.postMessage(C(t), s.protocol + "//" + s.host) + } + var s, a, l = n(13), c = n(169), u = n(59), h = n(15), d = n(29), p = n(16), f = n(160), g = n(240), m = n(91), b = n(128), v = n(179), n = n(83), _ = l.setImmediate, y = l.clearImmediate, w = l.process, O = l.Dispatch, x = l.Function, S = l.MessageChannel, C = l.String, E = 0, k = {}, A = "onreadystatechange", j = (p(function() { + s = l.location + }), + function(t) { + var e; + d(k, t) && (e = k[t], + delete k[t], + e()) + } + ); + _ && y || (_ = function(t) { + b(arguments.length, 1); + var e = h(t) ? t : x(t) + , n = g(arguments, 1); + return k[++E] = function() { + c(e, void 0, n) + } + , + a(E), + E + } + , + y = function(t) { + delete k[t] + } + , + n ? a = function(t) { + w.nextTick(i(t)) + } + : O && O.now ? a = function(t) { + O.now(i(t)) + } + : S && !v ? (v = (n = new S).port2, + n.port1.onmessage = o, + a = u(v.postMessage, v)) : l.addEventListener && h(l.postMessage) && !l.importScripts && s && "file:" !== s.protocol && !p(r) ? (a = r, + l.addEventListener("message", o, !1)) : a = A in m("script") ? function(t) { + f.appendChild(m("script"))[A] = function() { + f.removeChild(this), + j(t) + } + } + : function(t) { + setTimeout(i(t), 0) + } + ), + t.exports = { + set: _, + clear: y + } + } + , function(t, e, n) { + "use strict"; + n = n(49); + t.exports = /(?:ipad|iphone|ipod).*applewebkit/i.test(n) + } + , function(t, e, n) { + "use strict"; + function i() { + this.head = null, + this.tail = null + } + i.prototype = { + add: function(t) { + var t = { + item: t, + next: null + } + , e = this.tail; + e ? e.next = t : this.head = t, + this.tail = t + }, + get: function() { + var t = this.head; + if (t) + return null === (this.head = t.next) && (this.tail = null), + t.item + } + }, + t.exports = i + } + , function(t, e, n) { + "use strict"; + t.exports = "object" == typeof Deno && Deno && "object" == typeof Deno.version + } + , function(t, e, n) { + "use strict"; + function b(t, e) { + this.stopped = t, + this.result = e + } + var v = n(59) + , _ = n(22) + , y = n(30) + , w = n(78) + , O = n(183) + , x = n(58) + , S = n(56) + , C = n(130) + , E = n(96) + , k = n(184) + , A = TypeError + , j = b.prototype; + t.exports = function(t, e, n) { + function i(t) { + return r && k(r, "normal", t), + new b(!0,t) + } + function o(t) { + return d ? (y(t), + g ? m(t[0], t[1], i) : m(t[0], t[1])) : g ? m(t, i) : m(t) + } + var r, s, a, l, c, u, h = n && n.that, d = !(!n || !n.AS_ENTRIES), p = !(!n || !n.IS_RECORD), f = !(!n || !n.IS_ITERATOR), g = !(!n || !n.INTERRUPTED), m = v(e, h); + if (p) + r = t.iterator; + else if (f) + r = t; + else { + if (!(n = E(t))) + throw A(w(t) + " is not iterable"); + if (O(n)) { + for (s = 0, + a = x(t); s < a; s++) + if ((l = o(t[s])) && S(j, l)) + return l; + return new b(!1) + } + r = C(t, n) + } + for (c = (p ? t : r).next; !(u = _(c, r)).done; ) { + try { + l = o(u.value) + } catch (t) { + k(r, "throw", t) + } + if ("object" == typeof l && l && S(j, l)) + return l + } + return new b(!1) + } + } + , function(t, e, n) { + "use strict"; + var i = n(20) + , o = n(81) + , r = i("iterator") + , s = Array.prototype; + t.exports = function(t) { + return void 0 !== t && (o.Array === t || s[r] === t) + } + } + , function(t, e, n) { + "use strict"; + var r = n(22) + , s = n(30) + , a = n(88); + t.exports = function(t, e, n) { + var i, o; + s(t); + try { + if (!(i = a(t, "return"))) { + if ("throw" === e) + throw n; + return n + } + i = r(i, t) + } catch (t) { + o = !0, + i = t + } + if ("throw" === e) + throw n; + if (o) + throw i; + return s(i), + n + } + } + , function(t, e, n) { + "use strict"; + var i = n(84) + , o = n(247) + , n = n(85).CONSTRUCTOR; + t.exports = n || !o(function(t) { + i.all(t).then(void 0, function() {}) + }) + } + , function(t, e, n) { + "use strict"; + var i = n(16) + , o = n(20) + , r = n(23) + , s = n(43) + , a = o("iterator"); + t.exports = !i(function() { + var t = new URL("b?a=1&b=2&c=3","http://a") + , n = t.searchParams + , e = new URLSearchParams("a=1&a=2&b=3") + , i = ""; + return t.pathname = "c%20d", + n.forEach(function(t, e) { + n.delete("b"), + i += e + t + }), + e.delete("a", 2), + e.delete("b", void 0), + s && (!t.toJSON || !e.has("a", 1) || e.has("a", 2) || !e.has("a", void 0) || e.has("b")) || !n.size && (s || !r) || !n.sort || "http://a/c%20d?a=1&c=3" !== t.href || "3" !== n.get("c") || "a=1" !== String(new URLSearchParams("?a=1")) || !n[a] || "a" !== new URL("https://a@b").username || "b" !== new URLSearchParams(new URLSearchParams("a=b")).get("a") || "xn--e1aybc" !== new URL("http://тест").host || "#%D0%B1" !== new URL("http://a#б").hash || "a1c3" !== i || "x" !== new URL("http://x",void 0).host + }) + } + , function(D, N, t) { + "use strict"; + t(11); + function e(t) { + var e; + return p ? (e = Z(u, t)) && e.value : u[t] + } + function H(e) { + try { + return nt(e) + } catch (t) { + return e + } + } + function o(t) { + var e, n = R(t, ut, " "), i = 4; + try { + return nt(n) + } catch (t) { + for (; i; ) + n = R(n, (e = i--, + ht[e - 1] || (ht[e - 1] = tt("((?:%[\\da-f]{2}){" + e + "})", "gi"))), H); + return n + } + } + function B(t) { + return pt[t] + } + function r(t) { + return R(it(t), dt, B) + } + function n(t) { + this.entries = [], + this.url = null, + void 0 !== t && (_(t) ? this.parseObject(t) : this.parseQuery("string" == typeof t ? "?" === ot(t, 0) ? ct(t, 1) : t : y(t))) + } + function i() { + b(this, I); + var t = k(this, new n(0 < arguments.length ? arguments[0] : void 0)); + p || (this.size = t.entries.length) + } + var s, a, l, c = t(26), u = t(13), h = t(22), d = t(14), p = t(23), f = t(186), g = t(41), W = t(79), Y = t(260), F = t(82), X = t(162), m = t(46), b = t(127), v = t(15), z = t(29), U = t(59), q = t(93), $ = t(30), _ = t(35), y = t(38), V = t(80), w = t(76), O = t(130), K = t(96), x = t(128), S = t(20), G = t(173), t = S("iterator"), C = "URLSearchParams", E = C + "Iterator", k = m.set, A = m.getterFor(C), Q = m.getterFor(E), Z = Object.getOwnPropertyDescriptor, J = e("fetch"), j = e("Request"), T = e("Headers"), L = j && j.prototype, S = T && T.prototype, tt = u.RegExp, et = u.TypeError, nt = u.decodeURIComponent, it = u.encodeURIComponent, ot = d("".charAt), rt = d([].join), P = d([].push), R = d("".replace), st = d([].shift), at = d([].splice), lt = d("".split), ct = d("".slice), ut = /\+/g, ht = Array(4), dt = /[!'()~]|%20/g, pt = { + "!": "%21", + "'": "%27", + "(": "%28", + ")": "%29", + "~": "%7E", + "%20": "+" + }, M = X(function(t, e) { + k(this, { + type: E, + iterator: O(A(t).entries), + kind: e + }) + }, "Iterator", function() { + var t = Q(this) + , e = t.kind + , t = t.iterator.next() + , n = t.value; + return t.done || (t.value = "keys" === e ? n.key : "values" === e ? n.value : [n.key, n.value]), + t + }, !0), I = (n.prototype = { + type: C, + bindURL: function(t) { + this.url = t, + this.update() + }, + parseObject: function(t) { + var e, n, i, o, r, s, a = K(t); + if (a) + for (n = (e = O(t, a)).next; !(i = h(n, e)).done; ) { + if (o = (i = O($(i.value))).next, + (r = h(o, i)).done || (s = h(o, i)).done || !h(o, i).done) + throw et("Expected sequence with length 2"); + P(this.entries, { + key: y(r.value), + value: y(s.value) + }) + } + else + for (var l in t) + z(t, l) && P(this.entries, { + key: l, + value: y(t[l]) + }) + }, + parseQuery: function(t) { + if (t) + for (var e, n = lt(t, "&"), i = 0; i < n.length; ) + (e = n[i++]).length && (e = lt(e, "="), + P(this.entries, { + key: o(st(e)), + value: o(rt(e, "=")) + })) + }, + serialize: function() { + for (var t, e = this.entries, n = [], i = 0; i < e.length; ) + t = e[i++], + P(n, r(t.key) + "=" + r(t.value)); + return rt(n, "&") + }, + update: function() { + this.entries.length = 0, + this.parseQuery(this.url.query) + }, + updateURL: function() { + this.url && this.url.update() + } + }, + i.prototype); + Y(I, { + append: function(t, e) { + var n = A(this); + x(arguments.length, 2), + P(n.entries, { + key: y(t), + value: y(e) + }), + p || this.length++, + n.updateURL() + }, + delete: function(t) { + for (var e = A(this), n = x(arguments.length, 1), i = e.entries, o = y(t), t = n < 2 ? void 0 : arguments[1], r = void 0 === t ? t : y(t), s = 0; s < i.length; ) { + var a = i[s]; + if (a.key !== o || void 0 !== r && a.value !== r) + s++; + else if (at(i, s, 1), + void 0 !== r) + break + } + p || (this.size = i.length), + e.updateURL() + }, + get: function(t) { + for (var e = A(this).entries, n = (x(arguments.length, 1), + y(t)), i = 0; i < e.length; i++) + if (e[i].key === n) + return e[i].value; + return null + }, + getAll: function(t) { + for (var e = A(this).entries, n = (x(arguments.length, 1), + y(t)), i = [], o = 0; o < e.length; o++) + e[o].key === n && P(i, e[o].value); + return i + }, + has: function(t) { + for (var e = A(this).entries, n = x(arguments.length, 1), i = y(t), t = n < 2 ? void 0 : arguments[1], o = void 0 === t ? t : y(t), r = 0; r < e.length; ) { + var s = e[r++]; + if (s.key === i && (void 0 === o || s.value === o)) + return !0 + } + return !1 + }, + set: function(t, e) { + for (var n, i = A(this), o = (x(arguments.length, 1), + i.entries), r = !1, s = y(t), a = y(e), l = 0; l < o.length; l++) + (n = o[l]).key === s && (r ? at(o, l--, 1) : (r = !0, + n.value = a)); + r || P(o, { + key: s, + value: a + }), + p || (this.size = o.length), + i.updateURL() + }, + sort: function() { + var t = A(this); + G(t.entries, function(t, e) { + return t.key > e.key ? 1 : -1 + }), + t.updateURL() + }, + forEach: function(t) { + for (var e, n = A(this).entries, i = U(t, 1 < arguments.length ? arguments[1] : void 0), o = 0; o < n.length; ) + i((e = n[o++]).value, e.key, this) + }, + keys: function() { + return new M(this,"keys") + }, + values: function() { + return new M(this,"values") + }, + entries: function() { + return new M(this,"entries") + } + }, { + enumerable: !0 + }), + g(I, t, I.entries, { + name: "entries" + }), + g(I, "toString", function() { + return A(this).serialize() + }, { + enumerable: !0 + }), + p && W(I, "size", { + get: function() { + return A(this).entries.length + }, + configurable: !0, + enumerable: !0 + }), + F(i, C), + c({ + global: !0, + constructor: !0, + forced: !f + }, { + URLSearchParams: i + }), + !f && v(T) && (s = d(S.has), + a = d(S.set), + l = function(t) { + if (_(t)) { + var e, n = t.body; + if (q(n) === C) + return e = t.headers ? new T(t.headers) : new T, + s(e, "content-type") || a(e, "content-type", "application/x-www-form-urlencoded;charset=UTF-8"), + V(t, { + body: w(0, y(n)), + headers: w(0, e) + }) + } + return t + } + , + v(J) && c({ + global: !0, + enumerable: !0, + dontCallGetSet: !0, + forced: !0 + }, { + fetch: function(t) { + return J(t, 1 < arguments.length ? l(arguments[1]) : {}) + } + }), + v(j)) && ((L.constructor = m = function(t) { + return b(this, L), + new j(t,1 < arguments.length ? l(arguments[1]) : {}) + } + ).prototype = L, + c({ + global: !0, + constructor: !0, + dontCallGetSet: !0, + forced: !0 + }, { + Request: m + })), + D.exports = { + URLSearchParams: i, + getState: A + } + } + , function(t, e, n) { + "use strict"; + n(11), + n(12), + n(253), + n(261), + n(199), + n(28), + n(203), + n(17); + var i = n(135) + , o = n(3) + , r = n(132) + , s = n(9) + , l = n(1); + const a = { + threshold: 10, + direction: "all" + }; + var c = class { + constructor(t, e) { + this._element = t, + this._startPosition = null, + this._options = { + ...a, + ...e + } + } + handleTouchStart(t) { + this._startPosition = this._getCoordinates(t) + } + handleTouchMove(t) { + var e; + if (this._startPosition) + return t = { + x: (t = this._getCoordinates(t)).x - this._startPosition.x, + y: t.y - this._startPosition.y + }, + t = this._getDirection(t), + "all" === this._options.direction ? t.y.value < this._options.threshold && t.x.value < this._options.threshold ? void 0 : (e = (t.y.value > t.x.value ? t.y : t.x).direction, + l.b.trigger(this._element, "swipe".concat(e)), + l.b.trigger(this._element, "swipe", { + direction: e + }), + void (this._startPosition = null)) : void (t[e = "left" === this._options.direction || "right" === this._options ? "x" : "y"].direction === this._options.direction && t[e].value > this._options.threshold && (l.b.trigger(this._element, "swipe".concat(t[e].direction)), + this._startPosition = null)) + } + handleTouchEnd() { + this._startPosition = null + } + _getCoordinates(t) { + var [t] = t.touches; + return { + x: t.clientX, + y: t.clientY + } + } + _getDirection(t) { + return { + x: { + direction: t.x < 0 ? "left" : "right", + value: Math.abs(t.x) + }, + y: { + direction: t.y < 0 ? "up" : "down", + value: Math.abs(t.y) + } + } + } + } + ; + var u = class { + constructor(t) { + var e = 1 < arguments.length && void 0 !== arguments[1] ? arguments[1] : "swipe" + , n = 2 < arguments.length && void 0 !== arguments[2] ? arguments[2] : {}; + this._element = t, + this._event = e, + this.swipe = new c(t,n), + this._touchStartHandler = this._handleTouchStart.bind(this), + this._touchMoveHandler = this._handleTouchMove.bind(this), + this._touchEndHandler = this._handleTouchEnd.bind(this) + } + dispose() { + this._element.removeEventListener("touchstart", this._touchStartHandler), + this._element.removeEventListener("touchmove", this._touchMoveHandler), + window.removeEventListener("touchend", this._touchEndHandler) + } + init() { + this._element.addEventListener("touchstart", t=>this._handleTouchStart(t)), + this._element.addEventListener("touchmove", t=>this._handleTouchMove(t)), + window.addEventListener("touchend", t=>this._handleTouchEnd(t)) + } + _handleTouchStart(t) { + this[this._event].handleTouchStart(t) + } + _handleTouchMove(t) { + this[this._event].handleTouchMove(t) + } + _handleTouchEnd(t) { + this[this._event].handleTouchEnd(t) + } + } + , h = n(52) + , d = n(7) + , p = n(0) + , f = n(2) + , g = n(110); + const m = "sidenav" + , b = "mdb.sidenav" + , v = "rotate-icon"; + const _ = '[data-mdb-toggle="sidenav"]' + , y = ".sidenav-collapse" + , w = ".sidenav-link" + , O = o.g ? 100 : -100 + , x = o.g ? -100 : 100; + let S = 0; + const C = { + accordion: "(boolean)", + backdrop: "(boolean)", + backdropClass: "(null|string)", + closeOnEsc: "(boolean)", + color: "(string)", + content: "(null|string)", + expandable: "(boolean)", + expandOnHover: "(boolean)", + focusTrap: "(boolean)", + hidden: "(boolean)", + mode: "(string)", + scrollContainer: "(null|string)", + slim: "(boolean)", + slimCollapsed: "(boolean)", + slimWidth: "(number)", + position: "(string)", + right: "(boolean)", + transitionDuration: "(number)", + width: "(number)" + } + , E = { + accordion: !1, + backdrop: !0, + backdropClass: null, + closeOnEsc: !0, + color: "primary", + content: null, + expandable: !0, + expandOnHover: !1, + focusTrap: !0, + hidden: !0, + mode: "over", + scrollContainer: null, + slim: !1, + slimCollapsed: !1, + slimWidth: 77, + position: "fixed", + right: !1, + transitionDuration: 300, + width: 240 + }; + class k { + constructor(t) { + var e = 1 < arguments.length && void 0 !== arguments[1] ? arguments[1] : {}; + this._element = t, + this._options = e, + S++, + this._ID = S, + this._backdrop = null, + this._content = null, + this._initialContentStyle = null, + this._slimCollapsed = !1, + this._activeNode = null, + this._tempSlim = !1, + this._focusTrap = null, + this._perfectScrollbar = null, + this._touch = null, + this.escHandler = t=>{ + t.keyCode === s.f && this.toggler && Object(o.h)(this.toggler) && (this._update(!1), + l.b.off(window, "keydown", this.escHandler)) + } + , + this.hashHandler = ()=>{ + this._setActiveElements() + } + , + t && (d.a.setData(t, b, this), + this._setup()) + } + static get NAME() { + return m + } + get container() { + if ("fixed" === this.options.position) + return f.a.findOne("body"); + const e = t=>{ + return t.parentNode && t.parentNode !== document ? "relative" === t.parentNode.style.position || t.parentNode.classList.contains("position-relative") ? t.parentNode : e(t.parentNode) : t + } + ; + return e(this._element) + } + get isVisible() { + let t = 0 + , e = window.innerWidth; + var n, i = ("fixed" !== this.options.position && (i = this.container.getBoundingClientRect(), + t = i.x, + e = i.x + i.width), + this._element.getBoundingClientRect())["x"]; + if (this.options.right && !o.g || !this.options.right && o.g) { + let t = 0; + return this.container.scrollHeight > this.container.clientHeight && (t = this.container.offsetWidth - this.container.clientWidth), + "BODY" === this.container.tagName && (n = document.documentElement.clientWidth, + t = Math.abs(window.innerWidth - n)), + 10 < Math.abs(i + t - e) + } + return Math.abs(i - t) < 10 + } + get links() { + return f.a.find(w, this._element) + } + get navigation() { + return f.a.find(".sidenav-menu", this._element) + } + get options() { + var t = { + ...E, + ...p.a.getDataAttributes(this._element), + ...this._options + }; + return Object(o.j)(m, t, C), + t + } + get sidenavStyle() { + return { + width: "".concat(this.width, "px"), + height: "fixed" === this.options.position ? "100vh" : "100%", + position: this.options.position, + transitionDuration: this.transitionDuration, + transitionProperty: "transform, width, padding, margin", + transitionTimingFunction: "linear" + } + } + get toggler() { + return f.a.find(_).find(t=>{ + t = p.a.getDataAttribute(t, "target"); + return f.a.findOne(t) === this._element + } + ) + } + get transitionDuration() { + return "".concat(this.options.transitionDuration / 1e3, "s") + } + get translation() { + return this.options.right ? x : O + } + get width() { + return this._slimCollapsed ? this.options.slimWidth : this.options.width + } + changeMode(t) { + this._setMode(t) + } + dispose() { + this._backdrop && this._removeBackdrop(), + l.b.off(window, "keydown", this.escHandler), + l.b.off(window, "hashchange", this.hashHandler), + this._touch.dispose(), + d.a.removeData(this._element, b), + this._element = null + } + hide() { + this._setVisibility(!1), + this._update(!1) + } + show() { + this._setVisibility(!0), + this._update(!0) + } + toggle() { + this._setVisibility(!this.isVisible), + this._update(!this.isVisible) + } + toggleSlim() { + this._setSlim(!this._slimCollapsed) + } + update(t) { + this._options = t, + this._setup() + } + _appendArrow(t) { + const e = Object(o.b)("i"); + ["fas", "fa-angle-down", v].forEach(t=>{ + p.a.addClass(e, t) + } + ), + 0 === f.a.find(".".concat(v), t).length && t.appendChild(e) + } + _collapseItems() { + this.navigation.forEach(t=>{ + f.a.find(y, t).forEach(t=>{ + h.a.getInstance(t).hide() + } + ) + } + ) + } + _setupBackdrop() { + var t, e = [], n = (this.options.backdropClass && e.push(this.options.backdropClass), + { + transition: "opacity ".concat(this.transitionDuration, " ease-out"), + position: this.options.position, + width: "fixed" === this.options.position ? "100vw" : "100%", + height: "fixed" === this.options.position ? "100vh" : "100%" + }); + this._backdrop || (t = Object(o.b)("div"), + e.push("sidenav-backdrop"), + n.opacity = 0, + l.b.on(t, "click", ()=>{ + this._setVisibility(!1), + this._update(!1) + } + ), + this._backdrop = t), + this._backdrop.classList.add(...e), + p.a.style(this._backdrop, n) + } + _getOffsetValue(t, e) { + var {index: e, property: n, offsets: i} = e; + return this._getPxValue(this._initialContentStyle[e][i[n].property]) + (t ? i[n].value : 0) + } + _getProperty() { + for (var t = arguments.length, e = new Array(t), n = 0; n < t; n++) + e[n] = arguments[n]; + return e.map((t,e)=>0 === e ? t : t[0].toUpperCase().concat(t.slice(1))).join("") + } + _getPxValue(t) { + return t ? parseFloat(t) : 0 + } + _handleSwipe(t, e) { + e && this._slimCollapsed && this.options.slim && this.options.expandable ? this.toggleSlim() : e || (!this._slimCollapsed && this.options.slim && this.options.expandable ? this.toggleSlim() : this.toggler && Object(o.h)(this.toggler) && this.toggle()) + } + _isActive(t, e) { + return e ? e === t : !!t.attributes.href && new URL(t,window.location.href).href === window.location.href + } + _isAllToBeCollapsed() { + return 0 === f.a.find('[data-mdb-toggle="collapse"]', this._element).filter(t=>"true" === t.getAttribute("aria-expanded")).length + } + _isAllCollapsed() { + return 0 === f.a.find(y, this._element).filter(t=>Object(o.h)(t)).length + } + _setup() { + this._setupTouch(), + this.options.focusTrap && this._setupFocusTrap(), + this.options.backdrop && (this._setupBackdrop(), + this.options.hidden || "over" !== this.options.mode || this._appendBackdrop()), + this._setupCollapse(), + this.options.slimCollapsed && p.a.addClass(this._element, "sidenav-slim"), + this.options.slim && this._setupSlim(), + this._setupInitialStyling(), + this._setupScrolling(), + this.options.content && this._setupContent(), + this._setupActiveState(), + this._setupRippleEffect(), + this.options.hidden || (this.options.right && this.show(), + this._updateOffsets(!0, !0)) + } + _setupActiveState() { + this._setActiveElements(), + this.links.forEach(e=>{ + l.b.on(e, "click", ()=>this._setActiveElements(e)), + l.b.on(e, "keydown", t=>{ + t.keyCode === s.e && this._setActiveElements(e) + } + ) + } + ), + l.b.on(window, "hashchange", this.hashHandler) + } + _setupCollapse() { + this.navigation.forEach((n,i)=>{ + f.a.find(y, n).forEach((t,e)=>this._setupCollapseList({ + list: t, + index: e, + menu: n, + menuIndex: i + })) + } + ) + } + _generateCollpaseID(t, e) { + return "sidenav-collapse-".concat(this._ID, "-").concat(e, "-").concat(t) + } + _setupCollapseList(t) { + let {list: e, index: n, menu: i, menuIndex: o} = t; + t = this._generateCollpaseID(n, o); + e.classList.add("collapse"), + e.setAttribute("id", t); + const [r] = f.a.prev(e, w) + , s = (p.a.setDataAttribute(r, "toggle", "collapse"), + r.setAttribute("href", "#".concat(t)), + r.setAttribute("role", "button"), + h.a.getInstance(e) || new h.a(e,{ + toggle: !1, + parent: this.options.accordion ? i : e + })); + this._appendArrow(r), + p.a.hasClass(e, "show") && this._rotateArrow(r, 180), + l.b.on(r, "click", t=>{ + this._toggleCategory(t, s, e), + this._tempSlim && this._isAllToBeCollapsed() && (this._setSlim(!0), + this._tempSlim = !1), + "over" === this.options.mode && this._focusTrap && this._focusTrap.update() + } + ), + l.b.on(e, "show.bs.collapse", ()=>this._rotateArrow(r, 180)), + l.b.on(e, "hide.bs.collapse", ()=>this._rotateArrow(r, 0)), + l.b.on(e, "shown.bs.collapse", ()=>{ + "over" === this.options.mode && this._focusTrap && this._focusTrap.update() + } + ), + l.b.on(e, "hidden.bs.collapse", ()=>{ + this._tempSlim && this._isAllCollapsed() && (this._setSlim(!0), + this._tempSlim = !1), + "over" === this.options.mode && this._focusTrap && this._focusTrap.update() + } + ) + } + _setupContent() { + this._content = f.a.find(this.options.content), + this._initialContentStyle || (this._initialContentStyle = this._content.map(t=>{ + var {paddingLeft: t, paddingRight: e, marginLeft: n, marginRight: i, transition: o} = window.getComputedStyle(t); + return { + paddingLeft: t, + paddingRight: e, + marginLeft: n, + marginRight: i, + transition: o + } + } + )) + } + _setupFocusTrap() { + this._focusTrap = new r.a(this._element,{ + event: "keydown", + condition: t=>t.keyCode === s.m, + onlyVisible: !0 + },this.toggler) + } + _setupInitialStyling() { + this._setColor(), + p.a.style(this._element, this.sidenavStyle) + } + _setupScrolling() { + let e = this._element; + var t; + this.options.scrollContainer && (e = f.a.findOne(this.options.scrollContainer, this._element), + t = Object(o.a)(e.parentNode.children).filter(t=>t !== e).reduce((t,e)=>t + e.clientHeight, 0), + p.a.style(e, { + maxHeight: "calc(100% - ".concat(t, "px)"), + position: "relative" + })), + this._perfectScrollbar = new i.a(e,{ + suppressScrollX: !0, + handlers: ["click-rail", "drag-thumb", "wheel", "touch"] + }) + } + _setupSlim() { + this._slimCollapsed = this.options.slimCollapsed, + this._toggleSlimDisplay(this._slimCollapsed), + this.options.expandOnHover && (this._element.addEventListener("mouseenter", ()=>{ + this._slimCollapsed && this._setSlim(!1) + } + ), + this._element.addEventListener("mouseleave", ()=>{ + this._slimCollapsed || this._setSlim(!0) + } + )) + } + _setupRippleEffect() { + this.links.forEach(t=>{ + let e = g.a.getInstance(t); + if (e && e._options.color !== this.options.color) + e.dispose(); + else if (e) + return; + e = new g.a(t,{ + rippleColor: this.options.color + }) + } + ) + } + _setupTouch() { + this._touch = new u(this._element,"swipe",{ + threshold: 20 + }), + this._touch.init(), + l.b.on(this._element, "swipeleft", t=>this._handleSwipe(t, this.options.right)), + l.b.on(this._element, "swiperight", t=>this._handleSwipe(t, !this.options.right)) + } + _setActive(t, e) { + p.a.addClass(t, "active"), + this._activeNode && this._activeNode.classList.remove("active"), + this._activeNode = t; + var n, [t] = f.a.parents(this._activeNode, y); + t ? ([n] = f.a.prev(t, w), + this._setActiveCategory(n), + e || this._slimCollapsed || h.a.getInstance(t).show()) : this._setActiveCategory() + } + _setActiveCategory(e) { + this.navigation.forEach(t=>{ + f.a.find(y, t).forEach(t=>{ + var [t] = f.a.prev(t, w); + t !== e ? t.classList.remove("active") : p.a.addClass(t, "active") + } + ) + } + ) + } + _setActiveElements(e) { + this.navigation.forEach(t=>{ + f.a.find(w, t).filter(t=>0 === f.a.next(t, y).length).forEach(t=>{ + this._isActive(t, e) && t !== this._activeNode && this._setActive(t, e) + } + ) + } + ) + } + _setColor() { + var t = ["primary", "secondary", "success", "info", "warning", "danger", "light", "dark"] + , e = this.options["color"] + , e = t.includes(e) ? e : "primary"; + t.forEach(t=>{ + this._element.classList.remove("sidenav-".concat(t)) + } + ), + p.a.addClass(this._element, "sidenav-".concat(e)) + } + _setContentOffsets(r, s, a) { + this._content.forEach((t,e)=>{ + var n = this._getOffsetValue(r, { + index: e, + property: "padding", + offsets: s + }) + , i = this._getOffsetValue(r, { + index: e, + property: "margin", + offsets: s + }) + , o = {}; + a || (o.transition = "all ".concat(this.transitionDuration, " linear")), + o[s.padding.property] = "".concat(n, "px"), + o[s.margin.property] = "".concat(i, "px"), + p.a.style(t, o), + r && (a ? p.a.style(t, { + transition: this._initialContentStyle[e].transition + }) : l.b.on(t, "transitionend", ()=>{ + p.a.style(t, { + transition: this._initialContentStyle[e].transition + }) + } + )) + } + ) + } + _setMode(t) { + this.options.mode !== t && (this._options.mode = t, + this._update(this.isVisible)) + } + _setSlim(t) { + this._triggerEvents(...t ? ["collapse", "collapsed"] : ["expand", "expanded"]), + t ? (this._collapseItems(), + p.a.addClass(this._element, "sidenav-slim")) : p.a.removeClass(this._element, "sidenav-slim"), + this._slimCollapsed = t, + this._toggleSlimDisplay(t), + p.a.style(this._element, { + width: "".concat(this.width, "px") + }), + this._updateOffsets(this.isVisible) + } + _setTabindex(e) { + this.links.forEach(t=>{ + t.tabIndex = e ? 1 : -1 + } + ) + } + _setVisibility(t) { + this._triggerEvents(...t ? ["show", "shown"] : ["hide", "hidden"]) + } + _rotateArrow(t, e) { + var [t] = f.a.children(t, ".".concat(v)); + t && p.a.style(t, { + transform: "rotate(".concat(e, "deg)") + }) + } + async _toggleBackdrop(t) { + t && "over" === this.options.mode ? this._appendBackdrop() : (p.a.style(this._backdrop, { + opacity: 0 + }), + await setTimeout(()=>{ + this._removeBackdrop() + } + , this.options.transitionDuration)) + } + _removeBackdrop() { + this._backdrop.parentNode === this.container && this.container.removeChild(this._backdrop) + } + _appendBackdrop() { + this.container.appendChild(this._backdrop), + setTimeout(()=>p.a.style(this._backdrop, { + opacity: 1 + }), 0) + } + _toggleCategory(t, e) { + t.preventDefault(), + e.toggle(), + this._slimCollapsed && this.options.expandable && (this._tempSlim = !0, + this._setSlim(!1)) + } + _toggleSlimDisplay(t) { + const e = f.a.find('[data-mdb-slim="true"]', this._element) + , n = f.a.find('[data-mdb-slim="false"]', this._element) + , i = ()=>{ + e.forEach(t=>{ + p.a.style(t, { + display: this._slimCollapsed ? "unset" : "none" + }) + } + ), + n.forEach(t=>{ + p.a.style(t, { + display: this._slimCollapsed ? "none" : "unset" + }) + } + ) + } + ; + t ? setTimeout(()=>i(), this.options.transitionDuration) : i() + } + async _triggerEvents(t, e) { + l.b.trigger(this._element, "".concat(t, ".mdb.sidenav")), + e && await setTimeout(()=>{ + l.b.trigger(this._element, "".concat(e, ".mdb.sidenav")) + } + , this.options.transitionDuration + 5) + } + _update(t) { + this.toggler && this._updateTogglerAria(t), + this._updateDisplay(t), + this.options.backdrop && this._toggleBackdrop(t), + this._updateOffsets(t), + t && this.options.closeOnEsc && "side" !== this.options.mode && l.b.on(window, "keydown", this.escHandler), + this.options.focusTrap && this._updateFocus(t) + } + _updateDisplay(t) { + t = t ? 0 : this.translation; + p.a.style(this._element, { + transform: "translateX(".concat(t, "%)") + }) + } + _updateFocus(t) { + if (this._setTabindex(t), + "over" === this.options.mode && this.options.focusTrap) { + if (t) + return void this._focusTrap.trap(); + this._focusTrap.disable() + } + this._focusTrap.disable() + } + _updateOffsets(t) { + var e = 1 < arguments.length && void 0 !== arguments[1] && arguments[1] + , [n,i] = this.options.right && !o.g || !this.options.right && o.g ? ["right", "left"] : ["left", "right"] + , n = { + property: this._getProperty("padding", n), + value: "over" === this.options.mode ? 0 : this.width + } + , i = { + property: this._getProperty("margin", i), + value: "push" === this.options.mode ? -1 * this.width : 0 + }; + l.b.trigger(this._element, "update.mdb.sidenav", { + margin: i, + padding: n + }), + this._content && this._setContentOffsets(t, { + padding: n, + margin: i + }, e) + } + _updateTogglerAria(t) { + this.toggler.setAttribute("aria-expanded", t) + } + static toggleSidenav() { + return function(t) { + t = f.a.closest(t.target, _), + t = p.a.getDataAttributes(t).target; + f.a.find(t).forEach(t=>{ + (k.getInstance(t) || new k(t)).toggle() + } + ) + } + } + static jQueryInterface(n, i) { + return this.each(function() { + let t = d.a.getData(this, b); + var e = "object" == typeof n && n; + if ((t || !/dispose/.test(n)) && (t = t || new k(this,e), + "string" == typeof n)) { + if (void 0 === t[n]) + throw new TypeError('No method named "'.concat(n, '"')); + t[n](i) + } + }) + } + static getInstance(t) { + return d.a.getData(t, b) + } + static getOrCreateInstance(t) { + var e = 1 < arguments.length && void 0 !== arguments[1] ? arguments[1] : {}; + return this.getInstance(t) || new this(t,"object" == typeof e ? e : null) + } + } + l.b.on(document, "click", _, k.toggleSidenav()), + f.a.find(".sidenav").forEach(t=>{ + let e = k.getInstance(t); + return e = e || new k(t) + } + ), + Object(o.i)(()=>{ + const t = Object(o.f)(); + if (t) { + const e = t.fn[m]; + t.fn[m] = k.jQueryInterface, + t.fn[m].Constructor = k, + t.fn[m].noConflict = ()=>(t.fn[m] = e, + k.jQueryInterface) + } + } + ); + e.a = k + } + , function(D, t, e) { + "use strict"; + var n = e(3) + , i = e(2) + , o = e(1) + , r = e(7) + , s = e(0) + , a = (e(11), + e(12), + e(28), + e(4)) + , l = e(6) + , c = e(8) + , u = e(131) + , h = e(21) + , d = e(139) + , p = e(140) + , e = e(54); + const f = ".".concat("bs.modal"); + const g = "hide".concat(f) + , m = "hidePrevented".concat(f) + , b = "hidden".concat(f) + , v = "show".concat(f) + , _ = "shown".concat(f) + , y = "resize".concat(f) + , N = "click.dismiss".concat(f) + , H = "mousedown.dismiss".concat(f) + , B = "keydown.dismiss".concat(f); + var w = "click".concat(f).concat(".data-api"); + const O = "modal-open" + , x = "modal-static"; + const W = { + backdrop: !0, + focus: !0, + keyboard: !0 + } + , Y = { + backdrop: "(boolean|string)", + focus: "boolean", + keyboard: "boolean" + }; + class S extends h.a { + constructor(t, e) { + super(t, e), + this._dialog = c.a.findOne(".modal-dialog", this._element), + this._backdrop = this._initializeBackDrop(), + this._focustrap = this._initializeFocusTrap(), + this._isShown = !1, + this._isTransitioning = !1, + this._scrollBar = new u.a, + this._addEventListeners() + } + static get Default() { + return W + } + static get DefaultType() { + return Y + } + static get NAME() { + return "modal" + } + toggle(t) { + return this._isShown ? this.hide() : this.show(t) + } + show(t) { + this._isShown || this._isTransitioning || l.a.trigger(this._element, v, { + relatedTarget: t + }).defaultPrevented || (this._isShown = !0, + this._isTransitioning = !0, + this._scrollBar.hide(), + document.body.classList.add(O), + this._adjustDialog(), + this._backdrop.show(()=>this._showElement(t))) + } + hide() { + !this._isShown || this._isTransitioning || l.a.trigger(this._element, g).defaultPrevented || (this._isShown = !1, + this._isTransitioning = !0, + this._focustrap.deactivate(), + this._element.classList.remove("show"), + this._queueCallback(()=>this._hideModal(), this._element, this._isAnimated())) + } + dispose() { + for (const t of [window, this._dialog]) + l.a.off(t, f); + this._backdrop.dispose(), + this._focustrap.deactivate(), + super.dispose() + } + handleUpdate() { + this._adjustDialog() + } + _initializeBackDrop() { + return new d.a({ + isVisible: Boolean(this._config.backdrop) && Boolean(!this._config.modalNonInvasive), + isAnimated: this._isAnimated() + }) + } + _initializeFocusTrap() { + return new p.a({ + trapElement: this._element + }) + } + _showElement(t) { + document.body.contains(this._element) || document.body.append(this._element), + this._element.style.display = "block", + this._element.removeAttribute("aria-hidden"), + this._element.setAttribute("aria-modal", !0), + this._element.setAttribute("role", "dialog"), + this._element.scrollTop = 0; + var e = c.a.findOne(".modal-body", this._dialog); + e && (e.scrollTop = 0), + Object(a.p)(this._element), + this._element.classList.add("show"); + this._queueCallback(()=>{ + this._config.focus && this._focustrap.activate(), + this._isTransitioning = !1, + l.a.trigger(this._element, _, { + relatedTarget: t + }) + } + , this._dialog, this._isAnimated()) + } + _addEventListeners() { + l.a.on(this._element, B, t=>{ + "Escape" === t.key && (this._config.keyboard ? (t.preventDefault(), + this.hide()) : this._triggerBackdropTransition()) + } + ), + l.a.on(window, y, ()=>{ + this._isShown && !this._isTransitioning && this._adjustDialog() + } + ), + l.a.on(this._element, H, e=>{ + l.a.one(this._element, N, t=>{ + this._element === e.target && this._element === t.target && ("static" === this._config.backdrop ? this._triggerBackdropTransition() : this._config.backdrop && this.hide()) + } + ) + } + ) + } + _hideModal() { + this._element.style.display = "none", + this._element.setAttribute("aria-hidden", !0), + this._element.removeAttribute("aria-modal"), + this._element.removeAttribute("role"), + this._isTransitioning = !1, + this._backdrop.hide(()=>{ + document.body.classList.remove(O), + this._resetAdjustments(), + this._scrollBar.reset(), + l.a.trigger(this._element, b) + } + ) + } + _isAnimated() { + return this._element.classList.contains("fade") + } + _triggerBackdropTransition() { + var t = l.a.trigger(this._element, m); + if (!t.defaultPrevented) { + t = this._element.scrollHeight > document.documentElement.clientHeight; + const e = this._element.style.overflowY; + "hidden" === e || this._element.classList.contains(x) || (t || (this._element.style.overflowY = "hidden"), + this._element.classList.add(x), + this._queueCallback(()=>{ + this._element.classList.remove(x), + this._queueCallback(()=>{ + this._element.style.overflowY = e + } + , this._dialog) + } + , this._dialog), + this._element.focus()) + } + } + _adjustDialog() { + var t, e = this._element.scrollHeight > document.documentElement.clientHeight, n = this._scrollBar.getWidth(), i = 0 < n; + i && !e && (t = Object(a.m)() ? "paddingLeft" : "paddingRight", + this._element.style[t] = "".concat(n, "px")), + !i && e && (t = Object(a.m)() ? "paddingRight" : "paddingLeft", + this._element.style[t] = "".concat(n, "px")) + } + _resetAdjustments() { + this._element.style.paddingLeft = "", + this._element.style.paddingRight = "" + } + static jQueryInterface(e, n) { + return this.each(function() { + var t = S.getOrCreateInstance(this, e); + if ("string" == typeof e) { + if (void 0 === t[e]) + throw new TypeError('No method named "'.concat(e, '"')); + t[e](n) + } + }) + } + } + l.a.on(document, w, '[data-mdb-toggle="modal"]', function(t) { + const e = Object(a.f)(this); + ["A", "AREA"].includes(this.tagName) && t.preventDefault(), + l.a.one(e, v, t=>{ + t.defaultPrevented || l.a.one(e, b, ()=>{ + Object(a.n)(this) && this.focus() + } + ) + } + ), + c.a.find(".modal.show").forEach(t=>{ + t.classList.contains("modal-non-invasive-show") || S.getInstance(t).hide() + } + ), + S.getOrCreateInstance(e).toggle(this) + }), + Object(e.a)(S), + Object(a.a)(S); + h = S; + const F = ".fixed-top, .fixed-bottom, .is-fixed, .sticky-top" + , X = ".sticky-top"; + const C = (t,n)=>{ + i.a.find(t).forEach(t=>{ + var e = s.a.getDataAttribute(t, n); + void 0 === e ? t.style.removeProperty(n) : (s.a.removeDataAttribute(t, n), + t.style[n] = e) + } + ) + } + ; + const E = "modal" + , k = "bs.modal"; + w = ".".concat(k); + const A = "modal-non-invasive-open" + , j = "modal-non-invasive-show"; + const T = ".".concat("modal-content") + , z = ".".concat("modal-bottom") + , U = ".".concat("modal-bottom-right") + , q = ".".concat("modal-bottom-left") + , $ = ".".concat("modal-top-right") + , V = ".".concat("modal-top-left") + , K = ".".concat("modal-dialog-scrollable") + , G = ".".concat("modal-dialog"); + e = "mousedown".concat(w).concat(".data-api"); + const L = "show".concat(w) + , P = "shown".concat(w) + , R = "hidden".concat(w) + , Q = [{ + name: "show", + parametersToCopy: ["relatedTarget"] + }, { + name: "shown", + parametersToCopy: ["relatedTarget"] + }, { + name: "hide" + }, { + name: "hidePrevented" + }, { + name: "hidden" + }] + , M = { + backdrop: !0, + keyboard: !0, + focus: !0, + show: !0, + modalNonInvasive: !1 + } + , Z = { + backdrop: "(boolean|string)", + keyboard: "boolean", + focus: "boolean", + show: "boolean", + modalNonInvasive: "boolean" + }; + class I extends h { + constructor(t, e) { + super(t, e), + this._config = this._getConfig(e), + this._modalContentRect = "", + this._modalContentComputedStyles = "", + this._isNonInvasive = this._config.modalNonInvasive, + this._isScrollable = "", + this._isBottomRight = "", + this._isBottomLeft = "", + this._isTopRight = "", + this._isTopLeft = "", + this._isSideTopModal = "", + this._isSideBottomModal = "", + this._isSideModal = "", + this._isModalBottom = "", + this._isNonInvasive && (this._config.backdrop = !1, + this._config.focus = !1, + this._isBodyOverflowing = !0, + this._onModalShow(), + this._onModalShown(), + this._onModalHidden(), + this._listenToWindowResize()), + r.a.setData(t, k, this), + this._bindMdbEvents() + } + static get NAME() { + return E + } + dispose() { + o.b.off(this._element, L), + o.b.off(this._element, P), + o.b.off(this._element, "hide.bs.modal"), + o.b.off(this._element, R), + o.b.off(this._element, "hidePrevented.bs.modal"), + this._modalContentRect = null, + this._modalContentComputedStyles = null, + this._isNonInvasive = null, + this._isScrollable = null, + this._isBottomRight = null, + this._isBottomLeft = null, + this._isTopRight = null, + this._isTopLeft = null, + this._isSideTopModal = null, + this._isSideBottomModal = null, + this._isSideModal = null, + this._isModalBottom = null, + super.dispose() + } + _onModalShow() { + o.b.on(this._element, L, ()=>{ + this._addNonInvasiveClass() + } + ) + } + _onModalShown() { + o.b.on(this._element, P, ()=>{ + var t = i.a.findOne(T, this._element); + this._isScrollable = i.a.findOne(K, this._element), + this._isBottomRight = i.a.findOne(U, this._element), + this._isBottomLeft = i.a.findOne(q, this._element), + this._isTopRight = i.a.findOne($, this._element), + this._isTopLeft = i.a.findOne(V, this._element), + this._isSideTopModal = this._isTopLeft || this._isTopRight, + this._isSideBottomModal = this._isBottomLeft || this._isBottomRight, + this._isSideModal = this._isSideTopModal || this._isSideBottomModal, + this._isModalBottom = i.a.findOne(z, this._element), + this._modalContentRect = t.getBoundingClientRect(), + this._modalContentComputedStyles = window.getComputedStyle(t), + this._modalDialogComputedStyles = window.getComputedStyle(i.a.findOne(G, this._element)), + this._topOffset = parseInt(this._modalDialogComputedStyles.top, 0), + this._leftOffset = parseInt(this._modalDialogComputedStyles.left, 0), + this._rightOffset = parseInt(this._modalDialogComputedStyles.right, 0), + this._bottomOffset = parseInt(this._modalDialogComputedStyles.bottom, 0), + this._addOpenClass(), + this._setStyles() + } + ) + } + _listenToWindowResize() { + o.b.on(window, "resize", this._handleWindowResize.bind(this)) + } + _handleWindowResize() { + var t = i.a.findOne(T, this._element); + if (this._resetStyles(), + this._modalContentRect = t.getBoundingClientRect(), + this._modalContentComputedStyles = window.getComputedStyle(t), + this._isSideTopModal || this._isSideBottomModal) { + let t = 0 + , e = 0; + (this._isBottomRight || this._isBottomLeft) && (e = -this._bottomOffset), + (this._isBottomRight || this._isTopRight) && (t = -this._rightOffset), + (this._isBottomLeft || this._isTopLeft) && (t = this._leftOffset), + void this._setStyles(t, e) + } else + this._setStyles() + } + _showBackdrop(t) { + this._isNonInvasive ? "function" == typeof t && t() : super._showBackdrop(t) + } + _adjustDialog() { + super._adjustDialog(); + var t = document.body.classList.contains(A); + (this._isNonInvasive || t) && (this._isBodyOverflowing = !1), + this._isNonInvasive && (this._resetAdjustments(), + C("body", "overflow"), + C("body", "paddingRight"), + C(F, "paddingRight"), + C(X, "marginRight")) + } + _onModalHidden() { + o.b.on(this._element, R, t=>{ + t.stopImmediatePropagation(), + this._removeOpenClass(), + this._resetStyles(), + this._removeNonInvasiveClass() + } + ) + } + _addOpenClass() { + this._element.classList.add(j) + } + _removeOpenClass() { + this._element.classList.remove(j) + } + _addNonInvasiveClass() { + document.body.classList.add(A) + } + _removeNonInvasiveClass() { + i.a.findOne(".".concat("modal", ".").concat("show", ".").concat(j), document.body) ? document.body.classList.add("modal-open") : document.body.classList.remove(A) + } + _setStyles() { + var t = 0 < arguments.length && void 0 !== arguments[0] ? arguments[0] : 0 + , e = 1 < arguments.length && void 0 !== arguments[1] ? arguments[1] : 0 + , n = 992 <= window.innerWidth; + this._element.style.left = "".concat(this._modalContentRect.left + t, "px"), + this._element.style.width = this._modalContentComputedStyles.width, + this._isScrollable || (this._element.style.height = this._modalContentComputedStyles.height, + this._element.style.display = ""), + n && ((this._isSideBottomModal || this._isModalBottom) && (this._element.style.top = "".concat(this._modalContentRect.top + e, "px")), + this._isSideModal) && (this._element.style.overflowX = "auto"), + n || (this._element.style.height = "") + } + _resetStyles() { + this._element.style.left = "", + this._element.style.top = "", + this._element.style.height = "", + this._element.style.width = "", + this._isScrollable || (this._element.style.display = ""), + this._isSideModal && (this._element.style.overflowX = "") + } + _getConfig(t) { + let e; + this._element && (e = Object(n.c)(this._element)); + t = { + ...M, + ...s.a.getDataAttributes(this._element), + ...s.a.getDataAttributes(e), + ...t + }; + return Object(n.j)(E, t, Z), + t + } + _bindMdbEvents() { + o.b.extend(this._element, Q, E) + } + static jQueryInterface(n, i) { + return this.each(function() { + let t = r.a.getData(this, k); + var e = { + ...M, + ...s.a.getDataAttributes(this), + ..."object" == typeof n && n ? n : {} + }; + if (t = t || new I(this,e), + "string" == typeof n) { + if (void 0 === t[n]) + throw new TypeError('No method named "'.concat(n, '"')); + t[n](i) + } else + e.show && t.show(i) + }) + } + } + o.b.on(document, e, '[data-mdb-toggle="modal"]', function(t) { + var t = Object(n.c)(t.target) + , e = r.a.getData(t, k); + e || (e = { + ...s.a.getDataAttributes(t), + ...s.a.getDataAttributes(this._element) + }, + new I(t,e)) + }), + Object(n.i)(()=>{ + const t = Object(n.f)(); + if (t) { + const e = t.fn[E]; + t.fn[E] = I.jQueryInterface, + t.fn[E].Constructor = I, + t.fn[E].noConflict = ()=>(t.fn[E] = e, + I.jQueryInterface) + } + } + ); + t.a = I + } + , function(t, e, n) { + "use strict"; + n(17); + var i = n(3) + , o = n(7) + , r = n(1) + , s = n(0) + , a = n(2) + , l = n(4) + , c = n(6) + , n = n(21); + var u = ".".concat("bs.button"); + const h = '[data-mdb-toggle="button"]'; + u = "click".concat(u).concat(".data-api"); + class d extends n.a { + static get NAME() { + return "button" + } + toggle() { + this._element.setAttribute("aria-pressed", this._element.classList.toggle("active")) + } + static jQueryInterface(e) { + return this.each(function() { + var t = d.getOrCreateInstance(this); + "toggle" === e && t[e]() + }) + } + } + c.a.on(document, u, h, t=>{ + t.preventDefault(); + t = t.target.closest(h); + d.getOrCreateInstance(t).toggle() + } + ), + Object(l.a)(d); + n = d; + const p = "button" + , f = "mdb.".concat(p); + c = ".".concat(f); + const g = "click".concat(c) + , m = "transitionend" + , b = "mouseenter" + , v = "mouseleave" + , _ = "hide".concat(c) + , y = "hidden".concat(c) + , w = "show".concat(c) + , O = "shown".concat(c) + , x = "fixed-action-btn"; + class S extends n { + constructor(t) { + super(t), + this._fn = {}, + this._element && (o.a.setData(this._element, f, this), + this._init()) + } + static get NAME() { + return p + } + static jQueryInterface(n, i) { + return this.each(function() { + let t = o.a.getData(this, f); + var e = "object" == typeof n && n; + if ((t || !/dispose/.test(n)) && (t = t || new S(this,e), + "string" == typeof n)) { + if (void 0 === t[n]) + throw new TypeError('No method named "'.concat(n, '"')); + t[n](i) + } + }) + } + get _actionButton() { + return a.a.findOne(".fixed-action-btn:not(.smooth-scroll) > .btn-floating", this._element) + } + get _buttonListElements() { + return a.a.find("ul .btn", this._element) + } + get _buttonList() { + return a.a.findOne("ul", this._element) + } + get _isTouchDevice() { + return "ontouchstart"in document.documentElement + } + show() { + s.a.hasClass(this._element, x) && (r.b.off(this._buttonList, m), + r.b.trigger(this._element, w), + this._bindListOpenTransitionEnd(), + s.a.addStyle(this._element, { + height: "".concat(this._fullContainerHeight, "px") + }), + this._toggleVisibility(!0)) + } + hide() { + s.a.hasClass(this._element, x) && (r.b.off(this._buttonList, m), + r.b.trigger(this._element, _), + this._bindListHideTransitionEnd(), + this._toggleVisibility(!1)) + } + dispose() { + s.a.hasClass(this._element, x) && (r.b.off(this._actionButton, g), + this._actionButton.removeEventListener(b, this._fn.mouseenter), + this._element.removeEventListener(v, this._fn.mouseleave)), + super.dispose() + } + _init() { + s.a.hasClass(this._element, x) && (this._saveInitialHeights(), + this._setInitialStyles(), + this._bindInitialEvents()) + } + _bindMouseEnter() { + this._actionButton.addEventListener(b, this._fn.mouseenter = ()=>{ + this._isTouchDevice || this.show() + } + ) + } + _bindMouseLeave() { + this._element.addEventListener(v, this._fn.mouseleave = ()=>{ + this.hide() + } + ) + } + _bindClick() { + r.b.on(this._actionButton, g, ()=>{ + s.a.hasClass(this._element, "active") ? this.hide() : this.show() + } + ) + } + _bindListHideTransitionEnd() { + r.b.on(this._buttonList, m, t=>{ + "transform" === t.propertyName && (r.b.off(this._buttonList, m), + this._element.style.height = "".concat(this._initialContainerHeight, "px"), + r.b.trigger(this._element, y)) + } + ) + } + _bindListOpenTransitionEnd() { + r.b.on(this._buttonList, m, t=>{ + "transform" === t.propertyName && (r.b.off(this._buttonList, m), + r.b.trigger(this._element, O)) + } + ) + } + _toggleVisibility(t) { + const e = t ? "addClass" : "removeClass"; + t = t ? "translate(0)" : "translateY(".concat(this._fullContainerHeight, "px)"); + s.a.addStyle(this._buttonList, { + transform: t + }), + this._buttonListElements && this._buttonListElements.forEach(t=>s.a[e](t, "shown")), + s.a[e](this._element, "active") + } + _getHeight(t) { + t = window.getComputedStyle(t); + return parseFloat(t.getPropertyValue("height")) + } + _saveInitialHeights() { + this._initialContainerHeight = this._getHeight(this._element), + this._initialListHeight = this._getHeight(this._buttonList), + this._fullContainerHeight = this._initialContainerHeight + this._initialListHeight + } + _bindInitialEvents() { + this._bindClick(), + this._bindMouseEnter(), + this._bindMouseLeave() + } + _setInitialStyles() { + this._buttonList.style.marginBottom = "".concat(this._initialContainerHeight, "px"), + this._buttonList.style.transform = "translateY(".concat(this._fullContainerHeight, "px)"), + this._element.style.height = "".concat(this._initialContainerHeight, "px") + } + } + a.a.find(".fixed-action-btn").forEach(t=>{ + let e = S.getInstance(t); + return e = e || new S(t) + } + ), + a.a.find('[data-mdb-toggle="button"]').forEach(t=>{ + let e = S.getInstance(t); + return e = e || new S(t) + } + ), + Object(i.i)(()=>{ + const t = Object(i.f)(); + if (t) { + const e = t.fn[p]; + t.fn[p] = S.jQueryInterface, + t.fn[p].Constructor = S, + t.fn[p].noConflict = ()=>(t.fn[p] = e, + S.jQueryInterface) + } + } + ); + e.a = S + } + , function(t, e, n) { + "use strict"; + var i = n(3) + , o = n(1) + , r = n(2) + , s = n(4) + , n = n(69); + const a = { + ...n.a.Default, + content: "", + offset: [0, 8], + placement: "right", + template: '', + trigger: "click" + } + , l = { + ...n.a.DefaultType, + content: "(null|string|element|function)" + }; + class c extends n.a { + static get Default() { + return a + } + static get DefaultType() { + return l + } + static get NAME() { + return "popover" + } + _isWithContent() { + return this._getTitle() || this._getContent() + } + _getContentForTemplate() { + return { + ".popover-header": this._getTitle(), + ".popover-body": this._getContent() + } + } + _getContent() { + return this._resolvePossibleFunction(this._config.content) + } + static jQueryInterface(e) { + return this.each(function() { + var t = c.getOrCreateInstance(this, e); + if ("string" == typeof e) { + if (void 0 === t[e]) + throw new TypeError('No method named "'.concat(e, '"')); + t[e]() + } + }) + } + } + Object(s.a)(c); + n = c; + const u = "popover" + , h = [{ + name: "show" + }, { + name: "shown" + }, { + name: "hide" + }, { + name: "hidden" + }, { + name: "inserted" + }]; + class d extends n { + constructor(t, e) { + super(t, e), + this._init() + } + dispose() { + o.b.off(this.element, "show.bs.popover"), + o.b.off(this.element, "shown.bs.popover"), + o.b.off(this.element, "hide.bs.popover"), + o.b.off(this.element, "hidden.bs.popover"), + o.b.off(this.element, "inserted.bs.popover"), + super.dispose() + } + static get NAME() { + return u + } + _init() { + this._bindMdbEvents() + } + _bindMdbEvents() { + o.b.extend(this._element, h, u) + } + } + r.a.find('[data-mdb-toggle="popover"]').forEach(t=>{ + var e = d.getInstance(t); + e || new d(t) + } + ), + Object(i.i)(()=>{ + const t = Object(i.f)(); + if (t) { + const e = t.fn[u]; + t.fn[u] = d.jQueryInterface, + t.fn[u].Constructor = d, + t.fn[u].noConflict = ()=>(t.fn[u] = e, + d.jQueryInterface) + } + } + ); + e.a = d + } + , function(t, e, n) { + "use strict"; + var i = n(3) + , o = n(1) + , r = n(2) + , s = n(0) + , a = (n(11), + n(12), + n(4)) + , l = n(6) + , c = n(8) + , n = n(21); + var u = ".".concat("bs.scrollspy"); + const h = "activate".concat(u) + , d = "click".concat(u); + "load".concat(u).concat(".data-api"); + const p = "active"; + const f = "[href]"; + const g = "".concat(".nav-link", ", ").concat(".nav-item", " > ").concat(".nav-link", ", ").concat(".list-group-item") + , m = { + offset: null, + rootMargin: "0px 0px -25%", + smoothScroll: !1, + target: null, + threshold: [.1, .5, 1] + } + , b = { + offset: "(number|null)", + rootMargin: "string", + smoothScroll: "boolean", + target: "element", + threshold: "array" + }; + class v extends n.a { + constructor(t, e) { + super(t, e), + this._config.target && (this._targetLinks = new Map, + this._observableSections = new Map, + this._rootElement = "visible" === getComputedStyle(this._element).overflowY ? null : this._element, + this._activeTarget = null, + this._observer = null, + this._previousScrollData = { + visibleEntryTop: 0, + parentScrollTop: 0 + }, + this.refresh()) + } + static get Default() { + return m + } + static get DefaultType() { + return b + } + static get NAME() { + return "scrollspy" + } + refresh() { + this._initializeTargetsAndObservables(), + this._maybeEnableSmoothScroll(), + this._observer ? this._observer.disconnect() : this._observer = this._getNewObserver(); + for (const t of this._observableSections.values()) + this._observer.observe(t) + } + dispose() { + this._observer && this._observer.disconnect(), + super.dispose() + } + _configAfterMerge(t) { + return t.target = Object(a.e)(t.target) || document.body, + t.rootMargin = t.offset ? "".concat(t.offset, "px 0px -30%") : t.rootMargin, + "string" == typeof t.threshold && (t.threshold = t.threshold.split(",").map(t=>Number.parseFloat(t))), + t + } + _maybeEnableSmoothScroll() { + this._config.smoothScroll && (l.a.off(this._config.target, d), + l.a.on(this._config.target, d, f, t=>{ + var e = this._observableSections.get(t.target.hash); + e && (t.preventDefault(), + t = this._rootElement || window, + e = e.offsetTop - this._element.offsetTop, + t.scrollTo ? t.scrollTo({ + top: e, + behavior: "smooth" + }) : t.scrollTop = e) + } + )) + } + _getNewObserver() { + var t = { + root: this._rootElement, + threshold: this._config.threshold, + rootMargin: this._config.rootMargin + }; + return new IntersectionObserver(t=>this._observerCallback(t),t) + } + _observerCallback(t) { + const e = t=>this._targetLinks.get("#".concat(t.target.id)); + var n = t=>{ + this._previousScrollData.visibleEntryTop = t.target.offsetTop, + this._process(e(t)) + } + , i = (this._rootElement || document.documentElement).scrollTop + , o = i >= this._previousScrollData.parentScrollTop; + this._previousScrollData.parentScrollTop = i; + for (const s of t) + if (s.isIntersecting) { + var r = s.target.offsetTop >= this._previousScrollData.visibleEntryTop; + if (o && r) { + if (n(s), + i) + continue; + return + } + o || r || n(s) + } else + this._activeTarget = null, + this._clearActiveClass(e(s)) + } + _initializeTargetsAndObservables() { + var t; + this._targetLinks = new Map, + this._observableSections = new Map; + for (const e of c.a.find(f, this._config.target)) + e.hash && !Object(a.k)(e) && (t = c.a.findOne(e.hash, this._element), + Object(a.n)(t)) && (this._targetLinks.set(e.hash, e), + this._observableSections.set(e.hash, t)) + } + _process(t) { + this._activeTarget !== t && (this._clearActiveClass(this._config.target), + (this._activeTarget = t).classList.add(p), + this._activateParents(t), + l.a.trigger(this._element, h, { + relatedTarget: t + })) + } + _activateParents(t) { + if (t.classList.contains("dropdown-item")) + c.a.findOne(".dropdown-toggle", t.closest(".dropdown")).classList.add(p); + else + for (const e of c.a.parents(t, ".nav, .list-group")) + for (const n of c.a.prev(e, g)) + n.classList.add(p) + } + _clearActiveClass(t) { + t.classList.remove(p); + for (const e of c.a.find("".concat(f, ".").concat(p), t)) + e.classList.remove(p) + } + static jQueryInterface(e) { + return this.each(function() { + var t = v.getOrCreateInstance(this, e); + if ("string" == typeof e) { + if (void 0 === t[e] || e.startsWith("_") || "constructor" === e) + throw new TypeError('No method named "'.concat(e, '"')); + t[e]() + } + }) + } + } + Object(a.a)(v); + u = v; + const _ = "scrollspy"; + n = "mdb.".concat(_), + n = ".".concat(n); + const y = "activate.bs.scrollspy" + , w = "activate".concat(n); + n = "load".concat(n).concat(".data-api"); + const O = "collapsible-scrollspy"; + const x = ".".concat("active") + , S = ".".concat(O); + class C extends u { + constructor(t, e) { + super(t, e), + this._collapsibles = [], + this._init() + } + dispose() { + o.b.off(this._scrollElement, y), + super.dispose() + } + static get NAME() { + return _ + } + _init() { + this._bindActivateEvent(), + this._getCollapsibles(), + 0 !== this._collapsibles.length && (this._showSubsection(), + this._hideSubsection()) + } + _getHeight(t) { + return t.offsetHeight + } + _hide(t) { + t = r.a.findOne("ul", t.parentNode); + t.style.overflow = "hidden", + t.style.height = "".concat(0, "px") + } + _show(t, e) { + t.style.height = e + } + _getCollapsibles() { + var t = r.a.find(S); + t && t.forEach(t=>{ + var e = t.parentNode + , e = r.a.findOne("ul", e) + , n = e.offsetHeight; + this._collapsibles.push({ + element: e, + relatedTarget: t.getAttribute("href"), + height: "".concat(n, "px") + }) + } + ) + } + _showSubsection() { + r.a.find(x).filter(t=>s.a.hasClass(t, O)).forEach(e=>{ + var t = r.a.findOne("ul", e.parentNode) + , n = this._collapsibles.find(t=>t.relatedTarget = e.getAttribute("href")).height; + this._show(t, n) + } + ) + } + _hideSubsection() { + r.a.find(S).filter(t=>!1 === s.a.hasClass(t, "active")).forEach(t=>{ + this._hide(t) + } + ) + } + _bindActivateEvent() { + o.b.on(this._element, y, t=>{ + this._showSubsection(), + this._hideSubsection(), + o.b.trigger(this._element, w, { + relatedTarget: t.relatedTarget + }) + } + ) + } + } + o.b.on(window, n, ()=>{ + r.a.find('[data-mdb-spy="scroll"]').forEach(t=>{ + var e = C.getInstance(t); + e || new C(t,s.a.getDataAttributes(t)) + } + ) + } + ), + Object(i.i)(()=>{ + const t = Object(i.f)(); + if (t) { + const e = t.fn[_]; + t.fn[_] = C.jQueryInterface, + t.fn[_].Constructor = C, + t.fn[_].noConflict = ()=>(t.fn[_] = e, + C.jQueryInterface) + } + } + ); + e.a = C + } + , function(t, e, n) { + "use strict"; + var i = n(3) + , s = n(1) + , o = n(2) + , r = (n(28), + n(11), + n(12), + n(4)) + , a = n(6) + , l = n(8) + , n = n(21); + var c = ".".concat("bs.tab"); + const u = "hide".concat(c) + , h = "hidden".concat(c) + , d = "show".concat(c) + , p = "shown".concat(c); + var f = "click".concat(c); + const g = "keydown".concat(c); + c = "load".concat(c); + const m = "ArrowRight" + , b = "active"; + var v = ":not(.dropdown-toggle)"; + var v = ".nav-link".concat(v, ", .list-group-item").concat(v, ', [role="tab"]').concat(v) + , _ = '[data-mdb-toggle="tab"], [data-mdb-toggle="pill"], [data-mdb-toggle="list"]'; + const y = "".concat(v, ", ").concat(_) + , w = ".".concat(b, '[data-mdb-toggle="tab"], .').concat(b, '[data-mdb-toggle="pill"], .').concat(b, '[data-mdb-toggle="list"]'); + class O extends n.a { + constructor(t) { + super(t), + this._parent = this._element.closest('.list-group, .nav, [role="tablist"]'), + this._parent && (this._setInitialAttributes(this._parent, this._getChildren()), + a.a.on(this._element, g, t=>this._keydown(t))) + } + static get NAME() { + return "tab" + } + show() { + var t, e, n = this._element; + this._elemIsActive(n) || (e = (t = this._getActiveElem()) ? a.a.trigger(t, u, { + relatedTarget: n + }) : null, + a.a.trigger(n, d, { + relatedTarget: t + }).defaultPrevented) || e && e.defaultPrevented || (this._deactivate(t, n), + this._activate(n, t)) + } + _activate(t, e) { + t && (t.classList.add(b), + this._activate(Object(r.f)(t)), + this._queueCallback(()=>{ + "tab" !== t.getAttribute("role") ? t.classList.add("show") : (t.removeAttribute("tabindex"), + t.setAttribute("aria-selected", !0), + this._toggleDropDown(t, !0), + a.a.trigger(t, p, { + relatedTarget: e + })) + } + , t, t.classList.contains("fade"))) + } + _deactivate(t, e) { + t && (t.classList.remove(b), + t.blur(), + this._deactivate(Object(r.f)(t)), + this._queueCallback(()=>{ + "tab" !== t.getAttribute("role") ? t.classList.remove("show") : (t.setAttribute("aria-selected", !1), + t.setAttribute("tabindex", "-1"), + this._toggleDropDown(t, !1), + a.a.trigger(t, h, { + relatedTarget: e + })) + } + , t, t.classList.contains("fade"))) + } + _keydown(t) { + var e; + ["ArrowLeft", m, "ArrowUp", "ArrowDown"].includes(t.key) && (t.stopPropagation(), + t.preventDefault(), + e = [m, "ArrowDown"].includes(t.key), + t = Object(r.g)(this._getChildren().filter(t=>!Object(r.k)(t)), t.target, e, !0)) && (t.focus({ + preventScroll: !0 + }), + O.getOrCreateInstance(t).show()) + } + _getChildren() { + return l.a.find(y, this._parent) + } + _getActiveElem() { + return this._getChildren().find(t=>this._elemIsActive(t)) || null + } + _setInitialAttributes(t, e) { + this._setAttributeIfNotExists(t, "role", "tablist"); + for (const n of e) + this._setInitialAttributesOnChild(n) + } + _setInitialAttributesOnChild(t) { + t = this._getInnerElement(t); + var e = this._elemIsActive(t) + , n = this._getOuterElement(t); + t.setAttribute("aria-selected", e), + n !== t && this._setAttributeIfNotExists(n, "role", "presentation"), + e || t.setAttribute("tabindex", "-1"), + this._setAttributeIfNotExists(t, "role", "tab"), + this._setInitialAttributesOnTargetPanel(t) + } + _setInitialAttributesOnTargetPanel(t) { + var e = Object(r.f)(t); + e && (this._setAttributeIfNotExists(e, "role", "tabpanel"), + t.id) && this._setAttributeIfNotExists(e, "aria-labelledby", "#".concat(t.id)) + } + _toggleDropDown(t, n) { + const i = this._getOuterElement(t); + i.classList.contains("dropdown") && ((t = (t,e)=>{ + t = l.a.findOne(t, i); + t && t.classList.toggle(e, n) + } + )(".dropdown-toggle", b), + t(".dropdown-menu", "show"), + i.setAttribute("aria-expanded", n)) + } + _setAttributeIfNotExists(t, e, n) { + t.hasAttribute(e) || t.setAttribute(e, n) + } + _elemIsActive(t) { + return t.classList.contains(b) + } + _getInnerElement(t) { + return t.matches(y) ? t : l.a.findOne(y, t) + } + _getOuterElement(t) { + return t.closest(".nav-item, .list-group-item") || t + } + static jQueryInterface(e) { + return this.each(function() { + var t = O.getOrCreateInstance(this); + if ("string" == typeof e) { + if (void 0 === t[e] || e.startsWith("_") || "constructor" === e) + throw new TypeError('No method named "'.concat(e, '"')); + t[e]() + } + }) + } + } + a.a.on(document, f, _, function(t) { + ["A", "AREA"].includes(this.tagName) && t.preventDefault(), + Object(r.k)(this) || O.getOrCreateInstance(this).show() + }), + a.a.on(window, c, ()=>{ + for (const t of l.a.find(w)) + O.getOrCreateInstance(t) + } + ), + Object(r.a)(O); + v = O; + const x = "tab"; + n = "mdb.".concat(x), + f = ".".concat(n); + const S = "show.bs.tab" + , C = "shown.bs.tab" + , E = "show".concat(f) + , k = "shown".concat(f) + , A = "hide".concat(f) + , j = "hidden".concat(f); + class T extends v { + dispose() { + s.b.off(this._element, S), + s.b.off(this._element, C), + super.dispose() + } + static get NAME() { + return x + } + show() { + var n = this._element; + if (!this._elemIsActive(n)) { + var i = this._getActiveElem(); + let t = null + , e = null; + i && (t = s.b.trigger(i, "hide.bs.tab", { + relatedTarget: n + }), + e = s.b.trigger(i, A, { + relatedTarget: n + })); + var o = s.b.trigger(n, S, { + relatedTarget: i + }) + , r = s.b.trigger(n, E, { + relatedTarget: i + }); + o.defaultPrevented || r.defaultPrevented || t && t.defaultPrevented || e && e.defaultPrevented || (this._deactivate(i, n), + this._activate(n, i)) + } + } + _activate(t, e) { + t && (t.classList.add("active"), + this._activate(Object(i.c)(t)), + this._queueCallback(()=>{ + "tab" !== t.getAttribute("role") ? t.classList.add("show") : (t.focus(), + t.removeAttribute("tabindex"), + t.setAttribute("aria-selected", !0), + this._toggleDropDown(t, !0), + s.b.trigger(t, C, { + relatedTarget: e + }), + s.b.trigger(t, k, { + relatedTarget: e + })) + } + , t, t.classList.contains("fade"))) + } + _deactivate(t, e) { + t && (t.classList.remove("active"), + t.blur(), + this._deactivate(Object(i.c)(t)), + this._queueCallback(()=>{ + "tab" !== t.getAttribute("role") ? t.classList.remove("show") : (t.setAttribute("aria-selected", !1), + t.setAttribute("tabindex", "-1"), + this._toggleDropDown(t, !1), + s.b.trigger(t, "hidden.bs.tab", { + relatedTarget: e + }), + s.b.trigger(t, j, { + relatedTarget: e + })) + } + , t, t.classList.contains("fade"))) + } + } + o.a.find('[data-mdb-toggle="tab"], [data-mdb-toggle="pill"], [data-mdb-toggle="list"]').forEach(t=>{ + var e = T.getInstance(t); + e || new T(t) + } + ), + Object(i.i)(()=>{ + const t = Object(i.f)(); + if (t) { + const e = t.fn.tab; + t.fn.tab = T.jQueryInterface, + t.fn.tab.Constructor = T, + t.fn.tab.noConflict = ()=>(t.fn.tab = e, + T.jQueryInterface) + } + } + ); + e.a = T + } + , function(D, t, e) { + "use strict"; + var n = e(3) + , i = e(1) + , o = e(2) + , r = e(0) + , s = (e(11), + e(12), + e(75), + e(28), + e(17), + e(71)) + , a = e(141) + , l = e(4) + , c = e(6) + , u = e(34) + , h = e(8) + , e = e(21); + var d = ".".concat("bs.dropdown") + , p = ".data-api"; + const f = "hide".concat(d) + , g = "hidden".concat(d) + , m = "show".concat(d) + , b = "shown".concat(d); + var v = "click".concat(d).concat(p) + , _ = "keydown".concat(d).concat(p) + , d = "keyup".concat(d).concat(p); + const y = "show" + , w = '[data-mdb-toggle="dropdown"]:not(.disabled):not(:disabled)' + , O = "".concat(w, ".").concat(y) + , x = ".dropdown-menu" + , S = Object(l.m)() ? "top-end" : "top-start" + , C = Object(l.m)() ? "top-start" : "top-end" + , N = Object(l.m)() ? "bottom-end" : "bottom-start" + , H = Object(l.m)() ? "bottom-start" : "bottom-end" + , B = Object(l.m)() ? "left-start" : "right-start" + , W = Object(l.m)() ? "right-start" : "left-start" + , Y = { + autoClose: !0, + boundary: "clippingParents", + display: "dynamic", + offset: [0, 2], + popperConfig: null, + reference: "toggle" + } + , F = { + autoClose: "(boolean|string)", + boundary: "(string|element)", + display: "string", + offset: "(array|string|function)", + popperConfig: "(null|object|function)", + reference: "(string|element|object)" + }; + class E extends e.a { + constructor(t, e) { + super(t, e), + this._popper = null, + this._parent = this._element.parentNode, + this._menu = h.a.next(this._element, x)[0] || h.a.prev(this._element, x)[0] || h.a.findOne(x, this._parent), + this._inNavbar = this._detectNavbar() + } + static get Default() { + return Y + } + static get DefaultType() { + return F + } + static get NAME() { + return "dropdown" + } + toggle() { + return this._isShown() ? this.hide() : this.show() + } + show() { + if (!Object(l.k)(this._element) && !this._isShown()) { + var t = { + relatedTarget: this._element + } + , e = c.a.trigger(this._element, m, t); + if (!e.defaultPrevented) { + if (this._createPopper(), + "ontouchstart"in document.documentElement && !this._parent.closest(".navbar-nav")) + for (const n of [].concat(...document.body.children)) + c.a.on(n, "mouseover", l.o); + this._element.focus(), + this._element.setAttribute("aria-expanded", !0), + this._menu.classList.add(y), + this._element.classList.add(y), + c.a.trigger(this._element, b, t) + } + } + } + hide() { + var t; + !Object(l.k)(this._element) && this._isShown() && (t = { + relatedTarget: this._element + }, + this._completeHide(t)) + } + dispose() { + this._popper && this._popper.destroy(), + super.dispose() + } + update() { + this._inNavbar = this._detectNavbar(), + this._popper && this._popper.update() + } + _completeHide(t) { + var e = c.a.trigger(this._element, f, t); + if (!e.defaultPrevented) { + if ("ontouchstart"in document.documentElement) + for (const n of [].concat(...document.body.children)) + c.a.off(n, "mouseover", l.o); + this._popper && this._popper.destroy(), + this._menu.classList.remove(y), + this._element.classList.remove(y), + this._element.setAttribute("aria-expanded", "false"), + u.a.removeDataAttribute(this._menu, "popper"), + c.a.trigger(this._element, g, t) + } + } + _getConfig(t) { + if ("object" != typeof (t = super._getConfig(t)).reference || Object(l.l)(t.reference) || "function" == typeof t.reference.getBoundingClientRect) + return t; + throw new TypeError("".concat("dropdown".toUpperCase(), ': Option "reference" provided type "object" without a required "getBoundingClientRect" method.')) + } + _createPopper() { + if (void 0 === s) + throw new TypeError("Bootstrap's dropdowns require Popper (https://popper.js.org)"); + let t = this._element; + "parent" === this._config.reference ? t = this._parent : Object(l.l)(this._config.reference) ? t = Object(l.e)(this._config.reference) : "object" == typeof this._config.reference && (t = this._config.reference); + var e = this._getPopperConfig(); + this._popper = a.a(t, this._menu, e) + } + _isShown() { + return this._menu.classList.contains(y) + } + _getPlacement() { + var t, e = this._parent; + return e.classList.contains("dropend") ? B : e.classList.contains("dropstart") ? W : e.classList.contains("dropup-center") ? "top" : e.classList.contains("dropdown-center") ? "bottom" : (t = "end" === getComputedStyle(this._menu).getPropertyValue("--mdb-position").trim(), + e.classList.contains("dropup") ? t ? C : S : t ? H : N) + } + _detectNavbar() { + return null !== this._element.closest(".navbar") + } + _getOffset() { + const e = this._config["offset"]; + return "string" == typeof e ? e.split(",").map(t=>Number.parseInt(t, 10)) : "function" == typeof e ? t=>e(t, this._element) : e + } + _getPopperConfig() { + var t = { + placement: this._getPlacement(), + modifiers: [{ + name: "preventOverflow", + options: { + boundary: this._config.boundary + } + }, { + name: "offset", + options: { + offset: this._getOffset() + } + }] + }; + return !this._inNavbar && "static" !== this._config.display || (u.a.setDataAttribute(this._menu, "popper", "static"), + t.modifiers = [{ + name: "applyStyles", + enabled: !1 + }]), + { + ...t, + ..."function" == typeof this._config.popperConfig ? this._config.popperConfig(t) : this._config.popperConfig + } + } + _selectMenuItem(t) { + var {key: t, target: e} = t + , n = h.a.find(".dropdown-menu .dropdown-item:not(.disabled):not(:disabled)", this._menu).filter(t=>Object(l.n)(t)); + n.length && Object(l.g)(n, e, "ArrowDown" === t, !n.includes(e)).focus() + } + static jQueryInterface(e) { + return this.each(function() { + var t = E.getOrCreateInstance(this, e); + if ("string" == typeof e) { + if (void 0 === t[e]) + throw new TypeError('No method named "'.concat(e, '"')); + t[e]() + } + }) + } + static clearMenus(t) { + if (2 !== t.button && ("keyup" !== t.type || "Tab" === t.key)) + for (const o of h.a.find(O)) { + var e, n, i = E.getInstance(o); + i && !1 !== i._config.autoClose && (e = (n = t.composedPath()).includes(i._menu), + n.includes(i._element) || "inside" === i._config.autoClose && !e || "outside" === i._config.autoClose && e || i._menu.contains(t.target) && ("keyup" === t.type && "Tab" === t.key || /input|select|option|textarea|form/i.test(t.target.tagName)) || (n = { + relatedTarget: i._element + }, + "click" === t.type && (n.clickEvent = t), + i._completeHide(n))) + } + } + static dataApiKeydownHandler(t) { + var e = /input|textarea/i.test(t.target.tagName) + , n = "Escape" === t.key + , i = ["ArrowUp", "ArrowDown"].includes(t.key); + !i && !n || e && !n || (t.preventDefault(), + e = this.matches(w) ? this : h.a.prev(this, w)[0] || h.a.next(this, w)[0] || h.a.findOne(w, t.delegateTarget.parentNode), + n = E.getOrCreateInstance(e), + i ? (t.stopPropagation(), + n.show(), + n._selectMenuItem(t)) : n._isShown() && (t.stopPropagation(), + n.hide(), + e.focus())) + } + } + c.a.on(document, _, w, E.dataApiKeydownHandler), + c.a.on(document, _, x, E.dataApiKeydownHandler), + c.a.on(document, v, E.clearMenus), + c.a.on(document, d, E.clearMenus), + c.a.on(document, v, w, function(t) { + t.preventDefault(), + E.getOrCreateInstance(this).toggle() + }), + Object(l.a)(E); + p = E; + const k = "dropdown"; + e = "mdb.".concat(k), + _ = ".".concat(e); + const X = { + offset: [0, 2], + flip: !0, + boundary: "clippingParents", + reference: "toggle", + display: "dynamic", + popperConfig: null, + dropdownAnimation: "on" + } + , z = { + offset: "(array|string|function)", + flip: "boolean", + boundary: "(string|element)", + reference: "(string|element|object)", + display: "string", + popperConfig: "(null|object|function)", + dropdownAnimation: "string" + } + , A = "hide.bs.dropdown" + , j = "hidden.bs.dropdown" + , T = "show.bs.dropdown" + , L = "shown.bs.dropdown" + , U = "hide".concat(_) + , q = "hidden".concat(_) + , $ = "show".concat(_) + , V = "shown".concat(_) + , P = "animation" + , R = "fade-in" + , M = "fade-out"; + class I extends p { + constructor(t, e) { + super(t, e), + this._config = this._getConfig(e), + this._menuStyle = "", + this._popperPlacement = "", + this._mdbPopperConfig = ""; + t = window.matchMedia("(prefers-reduced-motion: reduce)").matches; + "on" !== this._config.dropdownAnimation || t || this._init() + } + dispose() { + i.b.off(this._element, T), + i.b.off(this._parent, L), + i.b.off(this._parent, A), + i.b.off(this._parent, j), + super.dispose() + } + static get NAME() { + return k + } + _init() { + this._bindShowEvent(), + this._bindShownEvent(), + this._bindHideEvent(), + this._bindHiddenEvent() + } + _getConfig(t) { + t = { + ...X, + ...r.a.getDataAttributes(this._element), + ...t + }; + return Object(n.j)(k, t, z), + t + } + _getOffset() { + const e = this._config["offset"]; + return "string" == typeof e ? e.split(",").map(t=>Number.parseInt(t, 10)) : "function" == typeof e ? t=>e(t, this._element) : e + } + _getPopperConfig() { + var t = { + placement: this._getPlacement(), + modifiers: [{ + name: "preventOverflow", + options: { + altBoundary: this._config.flip, + boundary: this._config.boundary + } + }, { + name: "offset", + options: { + offset: this._getOffset() + } + }] + }; + return "static" === this._config.display && (r.a.setDataAttribute(this._menu, "popper", "static"), + t.modifiers = [{ + name: "applyStyles", + enabled: !1 + }]), + { + ...t, + ..."function" == typeof this._config.popperConfig ? this._config.popperConfig(t) : this._config.popperConfig + } + } + _bindShowEvent() { + i.b.on(this._element, T, t=>{ + i.b.trigger(this._element, $, { + relatedTarget: t.relatedTarget + }).defaultPrevented ? t.preventDefault() : this._dropdownAnimationStart("show") + } + ) + } + _bindShownEvent() { + i.b.on(this._parent, L, t=>{ + i.b.trigger(this._parent, V, { + relatedTarget: t.relatedTarget + }).defaultPrevented && t.preventDefault() + } + ) + } + _bindHideEvent() { + i.b.on(this._parent, A, t=>{ + i.b.trigger(this._parent, U, { + relatedTarget: t.relatedTarget + }).defaultPrevented ? t.preventDefault() : (this._menuStyle = this._menu.style.cssText, + this._popperPlacement = this._menu.getAttribute("data-popper-placement"), + this._mdbPopperConfig = this._menu.getAttribute("data-mdb-popper")) + } + ) + } + _bindHiddenEvent() { + i.b.on(this._parent, j, t=>{ + i.b.trigger(this._parent, q, { + relatedTarget: t.relatedTarget + }).defaultPrevented ? t.preventDefault() : ("static" !== this._config.display && "" !== this._menuStyle && (this._menu.style.cssText = this._menuStyle), + this._menu.setAttribute("data-popper-placement", this._popperPlacement), + this._menu.setAttribute("data-mdb-popper", this._mdbPopperConfig), + this._dropdownAnimationStart("hide")) + } + ) + } + _dropdownAnimationStart(t) { + "show" === t ? (this._menu.classList.add(P, R), + this._menu.classList.remove(M)) : (this._menu.classList.add(P, M), + this._menu.classList.remove(R)), + this._bindAnimationEnd() + } + _bindAnimationEnd() { + i.b.one(this._menu, "animationend", ()=>{ + this._menu.classList.remove(P, M, R) + } + ) + } + } + o.a.find('[data-mdb-toggle="dropdown"]').forEach(t=>{ + var e = I.getInstance(t); + e || new I(t) + } + ), + Object(n.i)(()=>{ + const t = Object(n.f)(); + if (t) { + const e = t.fn[k]; + t.fn[k] = I.jQueryInterface, + t.fn[k].Constructor = I, + t.fn[k].noConflict = ()=>(t.fn[k] = e, + I.jQueryInterface) + } + } + ); + t.a = I + } + , function(t, e, n) { + "use strict"; + n(11), + n(12), + n(28); + var i = n(3) + , o = n(1) + , r = n(0) + , s = n(2) + , a = n(4) + , l = n(6) + , c = n(21) + , u = n(54); + var h = ".".concat("bs.alert"); + const d = "close".concat(h) + , p = "closed".concat(h); + class f extends c.a { + static get NAME() { + return "alert" + } + close() { + var t; + l.a.trigger(this._element, d).defaultPrevented || (this._element.classList.remove("show"), + t = this._element.classList.contains("fade"), + this._queueCallback(()=>this._destroyElement(), this._element, t)) + } + _destroyElement() { + this._element.remove(), + l.a.trigger(this._element, p), + this.dispose() + } + static jQueryInterface(e) { + return this.each(function() { + var t = f.getOrCreateInstance(this); + if ("string" == typeof e) { + if (void 0 === t[e] || e.startsWith("_") || "constructor" === e) + throw new TypeError('No method named "'.concat(e, '"')); + t[e](this) + } + }) + } + } + Object(u.a)(f, "close"), + Object(a.a)(f); + var h = f + , g = n(109); + const m = "alert" + , b = { + position: "(string || null)", + delay: "number", + autohide: "boolean", + width: "(string || null)", + offset: "number", + stacking: "boolean", + hidden: "boolean", + appendToBody: "boolean", + color: "(string || null)", + container: "(string|null)" + } + , v = { + position: null, + delay: 1e3, + autohide: !1, + width: null, + offset: 10, + stacking: !1, + hidden: !1, + appendToBody: !1, + color: null, + container: null + } + , _ = [{ + name: "close" + }, { + name: "closed" + }]; + class y extends h { + constructor(t) { + var e = 1 < arguments.length && void 0 !== arguments[1] ? arguments[1] : {}; + super(t, e), + this._options = this._getConfig(e), + this._init() + } + dispose() { + o.b.off(this._element, "close.bs.alert"), + o.b.off(this._element, "closed.bs.alert"), + super.dispose() + } + get verticalOffset() { + return this._options.stacking ? this.stackUtil.calculateOffset() : 0 + } + get parent() { + var [t] = s.a.parents(this._element, this._options.container); + return t + } + get position() { + var [t,e] = this._options.position.split("-"); + return { + y: t, + x: e + } + } + update() { + var t = 0 < arguments.length && void 0 !== arguments[0] ? arguments[0] : {}; + null !== this._timeout && (clearTimeout(this._timeout), + this._timeout = null), + this._options = this._getConfig(t), + this._setup() + } + hide() { + if (this._element && this._element.classList.contains("show")) { + r.a.toggleClass(this._element, "show"); + const e = t=>{ + r.a.style(t.target, { + display: "none" + }), + null !== this._timeout && (clearTimeout(this._timeout), + this._timeout = null), + this._options.stacking && this._updateAlertStack(), + o.b.off(t.target, "transitionend", e) + } + ; + o.b.on(this._element, "transitionend", e) + } + } + show() { + if (this._options.autohide && this._setupAutohide(), + !this._element.classList.contains("show") && (r.a.style(this._element, { + display: "block" + }), + Object(i.h)(this._element))) { + const e = t=>{ + r.a.style(t.target, { + display: "block" + }), + o.b.off(t.target, "transitionend", e) + } + ; + r.a.toggleClass(this._element, "show"), + this._options.position && this._setupAlignment(), + o.b.on(this._element, "transitionend", e) + } + } + _init() { + this._options.hidden && r.a.style(this._element, { + display: "none" + }), + this._bindMdbEvents(), + this._setup() + } + _setup() { + this._options.color && this._setColor(), + this._options.stacking && this._setupStacking(), + this._options.autohide && this._setupAutohide(), + this._options.width && this._setupWidth(), + this._options.appendToBody && this._appendToBody(), + this._options.position && (this._setupAlignment(), + this._setupPosition()) + } + _setupStacking() { + this.stackUtil = new g.a(this._element,".alert",{ + position: this.position.y, + offset: this._options.offset, + container: this._options.container, + filter: t=>{ + t = y.getInstance(t); + return !!t && t._options.container === this._options.container && t._options.position === this._options.position + } + }), + o.b.on(this._element, "closed.bs.alert", ()=>{ + this._updateAlertStack() + } + ) + } + _setColor() { + var t = ["primary", "secondary", "success", "info", "warning", "danger", "light", "dark"] + , e = t.includes(this._options.color) ? this._options.color : "primary"; + t.forEach(t=>{ + this._element.classList.remove("alert-".concat(t)) + } + ), + r.a.addClass(this._element, "alert-".concat(e)) + } + _setupWidth() { + r.a.style(this._element, { + width: this._options.width + }) + } + _setupAutohide() { + this._timeout = setTimeout(()=>{ + this.hide() + } + , this._options.delay) + } + _setupAlignment() { + var t = "top" === this.position.y ? "bottom" : "top" + , e = "left" === this.position.x ? "right" : "left"; + "center" === this.position.x ? r.a.style(this._element, { + [this.position.y]: "".concat(this.verticalOffset + this._options.offset, "px"), + [t]: "unset", + left: "50%", + transform: "translate(-50%)" + }) : r.a.style(this._element, { + [this.position.y]: "".concat(this.verticalOffset + this._options.offset, "px"), + [this.position.x]: "".concat(this._options.offset, "px"), + [t]: "unset", + [e]: "unset", + transform: "unset" + }) + } + _setupPosition() { + this._options.container ? (r.a.addClass(this.parent, "parent-alert-relative"), + r.a.addClass(this._element, "alert-absolute")) : r.a.addClass(this._element, "alert-fixed") + } + _appendToBody() { + this._element.parentNode.removeChild(this._element), + document.body.appendChild(this._element) + } + _getConfig(t) { + t = { + ...v, + ...r.a.getDataAttributes(this._element), + ...t + }; + return Object(i.j)(m, t, b), + t + } + _bindMdbEvents() { + o.b.extend(this._element, _, m) + } + _updatePosition() { + r.a.style(this._element, { + [this.position.y]: "".concat(this.verticalOffset + this._options.offset, "px") + }) + } + _updateAlertStack() { + this.stackUtil.nextElements.forEach(t=>{ + t = y.getInstance(t); + t && t._updatePosition() + } + ) + } + } + s.a.find(".alert").forEach(t=>{ + let e = y.getInstance(t); + return e = e || new y(t) + } + ), + Object(i.i)(()=>{ + const t = Object(i.f)(); + if (t) { + const e = t.fn[m]; + t.fn[m] = y.jQueryInterface, + t.fn[m].Constructor = y, + t.fn[m].noConflict = ()=>(t.fn[m] = e, + y.jQueryInterface) + } + } + ); + e.a = y + } + , function(t, e, n) { + "use strict"; + n(11), + n(12), + n(28); + var i = n(3) + , o = n(1) + , r = n(0) + , s = n(2) + , a = n(4) + , l = n(6) + , c = n(21) + , u = n(54); + var h = ".".concat("bs.toast"); + const d = "mouseover".concat(h) + , p = "mouseout".concat(h) + , f = "focusin".concat(h) + , g = "focusout".concat(h) + , m = "hide".concat(h) + , b = "hidden".concat(h) + , v = "show".concat(h) + , _ = "shown".concat(h) + , y = "show" + , w = "showing" + , O = { + animation: "boolean", + autohide: "boolean", + delay: "number" + } + , x = { + animation: !0, + autohide: !0, + delay: 5e3 + }; + class S extends c.a { + constructor(t, e) { + super(t, e), + this._timeout = null, + this._hasMouseInteraction = !1, + this._hasKeyboardInteraction = !1, + this._setListeners() + } + static get Default() { + return x + } + static get DefaultType() { + return O + } + static get NAME() { + return "toast" + } + show() { + l.a.trigger(this._element, v).defaultPrevented || (this._clearTimeout(), + this._config.animation && this._element.classList.add("fade"), + this._element.classList.remove("hide"), + Object(a.p)(this._element), + this._element.classList.add(y, w), + this._queueCallback(()=>{ + this._element.classList.remove(w), + l.a.trigger(this._element, _), + this._maybeScheduleHide() + } + , this._element, this._config.animation)) + } + hide() { + this.isShown() && !l.a.trigger(this._element, m).defaultPrevented && (this._element.classList.add(w), + this._queueCallback(()=>{ + this._element.classList.add("hide"), + this._element.classList.remove(w, y), + l.a.trigger(this._element, b) + } + , this._element, this._config.animation)) + } + dispose() { + this._clearTimeout(), + this.isShown() && this._element.classList.remove(y), + super.dispose() + } + isShown() { + return this._element.classList.contains(y) + } + _maybeScheduleHide() { + !this._config.autohide || this._hasMouseInteraction || this._hasKeyboardInteraction || (this._timeout = setTimeout(()=>{ + this.hide() + } + , this._config.delay)) + } + _onInteraction(t, e) { + switch (t.type) { + case "mouseover": + case "mouseout": + this._hasMouseInteraction = e; + break; + case "focusin": + case "focusout": + this._hasKeyboardInteraction = e + } + e ? this._clearTimeout() : (t = t.relatedTarget, + this._element === t || this._element.contains(t) || this._maybeScheduleHide()) + } + _setListeners() { + l.a.on(this._element, d, t=>this._onInteraction(t, !0)), + l.a.on(this._element, p, t=>this._onInteraction(t, !1)), + l.a.on(this._element, f, t=>this._onInteraction(t, !0)), + l.a.on(this._element, g, t=>this._onInteraction(t, !1)) + } + _clearTimeout() { + clearTimeout(this._timeout), + this._timeout = null + } + static jQueryInterface(e) { + return this.each(function() { + var t = S.getOrCreateInstance(this, e); + if ("string" == typeof e) { + if (void 0 === t[e]) + throw new TypeError('No method named "'.concat(e, '"')); + t[e](this) + } + }) + } + } + Object(u.a)(S), + Object(a.a)(S); + var h = S + , C = n(109); + const E = "toast" + , k = "show.bs.toast" + , A = "hidden.bs.toast" + , j = [{ + name: "shown" + }, { + name: "hide" + }] + , T = { + position: "(string|null)", + animation: "boolean", + autohide: "boolean", + width: "(string || null)", + color: "(string|null)", + delay: "(boolean|number)", + offset: "number", + appendToBody: "boolean", + stacking: "boolean" + } + , L = { + position: null, + animation: !0, + autohide: !0, + width: null, + color: null, + delay: 500, + offset: 10, + appendToBody: !1, + stacking: !0 + }; + class P extends h { + constructor(t) { + var e = 1 < arguments.length && void 0 !== arguments[1] ? arguments[1] : {}; + super(t, e), + this._config = this._getConfig(e), + this._setup() + } + get parent() { + var [t] = s.a.parents(this._element, this._config.container); + return t + } + get position() { + var t, e; + return this._config.position ? ([t,e] = this._config.position.split("-"), + { + y: t, + x: e + }) : null + } + get verticalOffset() { + return this._config.stacking && this.position ? this.stackUtil.calculateOffset() : 0 + } + update() { + this._config = this._getConfig(0 < arguments.length && void 0 !== arguments[0] ? arguments[0] : {}), + this._setupColor(), + this._config.position && (this._config.stacking && (this._setupStacking(), + o.b.on(this._element, "hidden.bs.toast", ()=>{ + setTimeout(()=>this._updateToastStack(), 150) + } + )), + this._setupPosition(), + this._setupAlignment()) + } + dispose() { + o.b.off(this._element, k), + o.b.off(this._element, "shown.bs.toast"), + o.b.off(this._element, "hide.bs.toast"), + o.b.off(this._element, A), + super.dispose() + } + _setup() { + this._setupColor(), + this._config.width && this._setupWidth(), + this._config.position && (this._config.stacking && (this._setupStacking(), + o.b.on(this._element, "hidden.bs.toast", ()=>{ + setTimeout(()=>this._updateToastStack(), 150) + } + )), + this._setupPosition(), + this._setupDisplay(), + !this._config.container && this._config.appendToBody && this._appendToBody(), + this._bindMdbEvents()) + } + _setupStacking() { + this.stackUtil = new C.a(this._element,".toast",{ + position: this.position.y, + offset: this._config.offset, + container: this._config.container, + filter: t=>{ + t = P.getInstance(t); + return !!t && t._config.container === this._config.container && t._config.position === this._config.position + } + }), + o.b.on(this._element, "closed.bs.alert", ()=>{ + this._updateAlertStack() + } + ) + } + _setupColor() { + if (this._config.color) { + const n = s.a.findOne(".toast-header", this._element); + var t = ["primary", "secondary", "success", "info", "warning", "danger", "light", "dark"] + , e = t.includes(this._config.color) ? this._config.color : "primary"; + t.forEach(t=>{ + this._element.classList.remove("toast-".concat(t)), + n && n.classList.remove("toast-".concat(t)) + } + ), + r.a.addClass(this._element, "toast-".concat(e)), + n && r.a.addClass(n, "toast-".concat(e)) + } + } + _setupWidth() { + r.a.style(this._element, { + width: this._config.width + }) + } + _setupPosition() { + this._config.container ? (r.a.addClass(this.parent, "parent-toast-relative"), + r.a.addClass(this._element, "toast-absolute")) : r.a.addClass(this._element, "toast-fixed") + } + _setupAlignment() { + var t = "top" === this.position.y ? "bottom" : "top" + , e = "left" === this.position.x ? "right" : "left"; + "center" === this.position.x ? r.a.style(this._element, { + [this.position.y]: "".concat(this.verticalOffset + this._config.offset, "px"), + [t]: "unset", + left: "50%", + transform: "translate(-50%)" + }) : r.a.style(this._element, { + [this.position.y]: "".concat(this.verticalOffset + this._config.offset, "px"), + [this.position.x]: "".concat(this._config.offset, "px"), + [t]: "unset", + [e]: "unset", + transform: "unset" + }) + } + _setupDisplay() { + this._element.classList.contains("show") || r.a.style(this._element, { + display: "none" + }), + o.b.on(this._element, A, ()=>{ + o.b.trigger(this._element, "hidden.mdb.toast"), + r.a.style(this._element, { + display: "none" + }) + } + ), + o.b.on(this._element, k, ()=>{ + o.b.trigger(this._element, "show.mdb.toast").defaultPrevented || (this._setupAlignment(), + r.a.style(this._element, { + display: "block" + })) + } + ) + } + _bindMdbEvents() { + o.b.extend(this._element, j, E) + } + _getConfig(t) { + t = { + ...L, + ...r.a.getDataAttributes(this._element), + ...t + }; + return Object(i.j)(E, t, T), + t + } + _appendToBody() { + this._element.parentNode.removeChild(this._element), + document.body.appendChild(this._element) + } + _updatePosition() { + r.a.style(this._element, { + [this.position.y]: "".concat(this.verticalOffset + this._config.offset, "px") + }) + } + _updateToastStack() { + this.stackUtil.nextElements.forEach(t=>{ + t = P.getInstance(t); + t && t._updatePosition() + } + ) + } + static jQueryInterface(e) { + let n = 1 < arguments.length && void 0 !== arguments[1] ? arguments[1] : {}; + return this.each(function() { + let t; + if (t = "object" == typeof e ? new P(this,e) : P.getOrCreateInstance(this, e), + "string" == typeof e) { + if (void 0 === t[e]) + throw new TypeError('No method named "'.concat(e, '"')); + t[e](n) + } + }) + } + } + s.a.find(".toast").forEach(t=>{ + let e = P.getInstance(t); + return e = e || new P(t) + } + ), + Object(i.i)(()=>{ + const t = Object(i.f)(); + if (t) { + const e = t.fn[E]; + t.fn[E] = P.jQueryInterface, + t.fn[E].Constructor = P, + t.fn[E].noConflict = ()=>(t.fn[E] = e, + P.jQueryInterface) + } + } + ); + e.a = P + } + , function(D, t, e) { + "use strict"; + e(17); + /*! + * perfect-scrollbar v1.5.3 + * Copyright 2021 Hyunje Jun, MDBootstrap and Contributors + * Licensed under MIT + */ + function p(t) { + return getComputedStyle(t) + } + function l(t, e) { + for (var n in e) { + var i = e[n]; + "number" == typeof i && (i += "px"), + t.style[n] = i + } + } + function c(t) { + var e = document.createElement("div"); + return e.className = t, + e + } + var n = "undefined" != typeof Element && (Element.prototype.matches || Element.prototype.webkitMatchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector); + function a(t, e) { + if (n) + return n.call(t, e); + throw new Error("No element matching method supported") + } + function s(t) { + t.remove ? t.remove() : t.parentNode && t.parentNode.removeChild(t) + } + function u(t, e) { + return Array.prototype.filter.call(t.children, function(t) { + return a(t, e) + }) + } + var v = { + main: "ps", + rtl: "ps__rtl", + element: { + thumb: function(t) { + return "ps__thumb-" + t + }, + rail: function(t) { + return "ps__rail-" + t + }, + consuming: "ps__child--consume" + }, + state: { + focus: "ps--focus", + clicking: "ps--clicking", + active: function(t) { + return "ps--active-" + t + }, + scrolling: function(t) { + return "ps--scrolling-" + t + } + } + } + , i = { + x: null, + y: null + }; + function _(t, e) { + var t = t.element.classList + , n = v.state.scrolling(e); + t.contains(n) ? clearTimeout(i[e]) : t.add(n) + } + function y(t, e) { + i[e] = setTimeout(function() { + return t.isAlive && t.element.classList.remove(v.state.scrolling(e)) + }, t.settings.scrollingThreshold) + } + function o(t) { + this.element = t, + this.handlers = {} + } + function h() { + this.eventElements = [] + } + var r = { + isEmpty: { + configurable: !0 + } + }; + o.prototype.bind = function(t, e) { + void 0 === this.handlers[t] && (this.handlers[t] = []), + this.handlers[t].push(e), + this.element.addEventListener(t, e, !1) + } + , + o.prototype.unbind = function(e, n) { + var i = this; + this.handlers[e] = this.handlers[e].filter(function(t) { + return !(!n || t === n) || (i.element.removeEventListener(e, t, !1), + !1) + }) + } + , + o.prototype.unbindAll = function() { + for (var t in this.handlers) + this.unbind(t) + } + , + r.isEmpty.get = function() { + var e = this; + return Object.keys(this.handlers).every(function(t) { + return 0 === e.handlers[t].length + }) + } + , + Object.defineProperties(o.prototype, r); + function d(t) { + var e; + return "function" == typeof window.CustomEvent ? new CustomEvent(t) : ((e = document.createEvent("CustomEvent")).initCustomEvent(t, !1, !1, void 0), + e) + } + function f(t, e, n, i, o) { + var r; + if (void 0 === i && (i = !0), + void 0 === o && (o = !1), + "top" === e) + r = ["contentHeight", "containerHeight", "scrollTop", "y", "up", "down"]; + else { + if ("left" !== e) + throw new Error("A proper axis should be provided"); + r = ["contentWidth", "containerWidth", "scrollLeft", "x", "left", "right"] + } + var e = t + , t = n + , n = i + , i = o + , s = (o = r)[0] + , a = o[1] + , l = o[2] + , c = o[3] + , u = o[4] + , o = o[5] + , h = (void 0 === n && (n = !0), + void 0 === i && (i = !1), + e.element); + e.reach[c] = null, + h[l] < 1 && (e.reach[c] = "start"), + h[l] > e[s] - e[a] - 1 && (e.reach[c] = "end"), + t && (h.dispatchEvent(d("ps-scroll-" + c)), + t < 0 ? h.dispatchEvent(d("ps-scroll-" + u)) : 0 < t && h.dispatchEvent(d("ps-scroll-" + o)), + n) && (_(l = e, s = c), + y(l, s)); + e.reach[c] && (t || i) && h.dispatchEvent(d("ps-" + c + "-reach-" + e.reach[c])) + } + function g(t) { + return parseInt(t, 10) || 0 + } + h.prototype.eventElement = function(e) { + var t = this.eventElements.filter(function(t) { + return t.element === e + })[0]; + return t || (t = new o(e), + this.eventElements.push(t)), + t + } + , + h.prototype.bind = function(t, e, n) { + this.eventElement(t).bind(e, n) + } + , + h.prototype.unbind = function(t, e, n) { + t = this.eventElement(t); + t.unbind(e, n), + t.isEmpty && this.eventElements.splice(this.eventElements.indexOf(t), 1) + } + , + h.prototype.unbindAll = function() { + this.eventElements.forEach(function(t) { + return t.unbindAll() + }), + this.eventElements = [] + } + , + h.prototype.once = function(t, e, n) { + var i = this.eventElement(t) + , o = function(t) { + i.unbind(e, o), + n(t) + }; + i.bind(e, o) + } + ; + var m = { + isWebKit: "undefined" != typeof document && "WebkitAppearance"in document.documentElement.style, + supportsTouch: "undefined" != typeof window && ("ontouchstart"in window || "maxTouchPoints"in window.navigator && 0 < window.navigator.maxTouchPoints || window.DocumentTouch && document instanceof window.DocumentTouch), + supportsIePointer: "undefined" != typeof navigator && navigator.msMaxTouchPoints, + isChrome: "undefined" != typeof navigator && /Chrome/i.test(navigator && navigator.userAgent) + }; + function w(t) { + var e = t.element + , n = Math.floor(e.scrollTop) + , i = e.getBoundingClientRect() + , i = (t.containerWidth = Math.round(i.width), + t.containerHeight = Math.round(i.height), + t.contentWidth = e.scrollWidth, + t.contentHeight = e.scrollHeight, + e.contains(t.scrollbarXRail) || (u(e, v.element.rail("x")).forEach(s), + e.appendChild(t.scrollbarXRail)), + e.contains(t.scrollbarYRail) || (u(e, v.element.rail("y")).forEach(s), + e.appendChild(t.scrollbarYRail)), + !t.settings.suppressScrollX && t.containerWidth + t.settings.scrollXMarginOffset < t.contentWidth ? (t.scrollbarXActive = !0, + t.railXWidth = t.containerWidth - t.railXMarginWidth, + t.railXRatio = t.containerWidth / t.railXWidth, + t.scrollbarXWidth = b(t, g(t.railXWidth * t.containerWidth / t.contentWidth)), + t.scrollbarXLeft = g((t.negativeScrollAdjustment + e.scrollLeft) * (t.railXWidth - t.scrollbarXWidth) / (t.contentWidth - t.containerWidth))) : t.scrollbarXActive = !1, + !t.settings.suppressScrollY && t.containerHeight + t.settings.scrollYMarginOffset < t.contentHeight ? (t.scrollbarYActive = !0, + t.railYHeight = t.containerHeight - t.railYMarginHeight, + t.railYRatio = t.containerHeight / t.railYHeight, + t.scrollbarYHeight = b(t, g(t.railYHeight * t.containerHeight / t.contentHeight)), + t.scrollbarYTop = g(n * (t.railYHeight - t.scrollbarYHeight) / (t.contentHeight - t.containerHeight))) : t.scrollbarYActive = !1, + t.scrollbarXLeft >= t.railXWidth - t.scrollbarXWidth && (t.scrollbarXLeft = t.railXWidth - t.scrollbarXWidth), + t.scrollbarYTop >= t.railYHeight - t.scrollbarYHeight && (t.scrollbarYTop = t.railYHeight - t.scrollbarYHeight), + e) + , n = t + , o = { + width: n.railXWidth + } + , r = Math.floor(i.scrollTop); + n.isRtl ? o.left = n.negativeScrollAdjustment + i.scrollLeft + n.containerWidth - n.contentWidth : o.left = i.scrollLeft, + n.isScrollbarXUsingBottom ? o.bottom = n.scrollbarXBottom - r : o.top = n.scrollbarXTop + r, + l(n.scrollbarXRail, o), + o = { + top: r, + height: n.railYHeight + }, + n.isScrollbarYUsingRight ? n.isRtl ? o.right = n.contentWidth - (n.negativeScrollAdjustment + i.scrollLeft) - n.scrollbarYRight - n.scrollbarYOuterWidth - 9 : o.right = n.scrollbarYRight - i.scrollLeft : n.isRtl ? o.left = n.negativeScrollAdjustment + i.scrollLeft + 2 * n.containerWidth - n.contentWidth - n.scrollbarYLeft - n.scrollbarYOuterWidth : o.left = n.scrollbarYLeft + i.scrollLeft, + l(n.scrollbarYRail, o), + l(n.scrollbarX, { + left: n.scrollbarXLeft, + width: n.scrollbarXWidth - n.railBorderXWidth + }), + l(n.scrollbarY, { + top: n.scrollbarYTop, + height: n.scrollbarYHeight - n.railBorderYWidth + }), + t.scrollbarXActive ? e.classList.add(v.state.active("x")) : (e.classList.remove(v.state.active("x")), + t.scrollbarXWidth = 0, + t.scrollbarXLeft = 0, + e.scrollLeft = !0 === t.isRtl ? t.contentWidth : 0), + t.scrollbarYActive ? e.classList.add(v.state.active("y")) : (e.classList.remove(v.state.active("y")), + t.scrollbarYHeight = 0, + t.scrollbarYTop = 0, + e.scrollTop = 0) + } + function b(t, e) { + return t.settings.minScrollbarLength && (e = Math.max(e, t.settings.minScrollbarLength)), + e = t.settings.maxScrollbarLength ? Math.min(e, t.settings.maxScrollbarLength) : e + } + function O(n, t) { + var i = t[0] + , o = t[1] + , r = t[2] + , s = t[3] + , e = t[4] + , a = t[5] + , l = t[6] + , c = t[7] + , u = t[8] + , h = n.element + , d = null + , p = null + , f = null; + function g(t) { + t.touches && t.touches[0] && (t[r] = t.touches[0].pageY), + h[l] = d + f * (t[r] - p), + _(n, c), + w(n), + t.stopPropagation(), + t.type.startsWith("touch") && 1 < t.changedTouches.length && t.preventDefault() + } + function m() { + y(n, c), + n[u].classList.remove(v.state.clicking), + n.event.unbind(n.ownerDocument, "mousemove", g) + } + function b(t, e) { + d = h[l], + e && t.touches && (t[r] = t.touches[0].pageY), + p = t[r], + f = (n[o] - n[i]) / (n[s] - n[a]), + e ? n.event.bind(n.ownerDocument, "touchmove", g) : (n.event.bind(n.ownerDocument, "mousemove", g), + n.event.once(n.ownerDocument, "mouseup", m), + t.preventDefault()), + n[u].classList.add(v.state.clicking), + t.stopPropagation() + } + n.event.bind(n[e], "mousedown", function(t) { + b(t) + }), + n.event.bind(n[e], "touchstart", function(t) { + b(t, !0) + }) + } + function x(t, e) { + var n, i = this; + if (void 0 === e && (e = {}), + !(t = "string" == typeof t ? document.querySelector(t) : t) || !t.nodeName) + throw new Error("no element is specified to initialize PerfectScrollbar"); + for (n in (this.element = t).classList.add(v.main), + this.settings = { + handlers: ["click-rail", "drag-thumb", "keyboard", "wheel", "touch"], + maxScrollbarLength: null, + minScrollbarLength: null, + scrollingThreshold: 1e3, + scrollXMarginOffset: 0, + scrollYMarginOffset: 0, + suppressScrollX: !1, + suppressScrollY: !1, + swipeEasing: !0, + useBothWheelAxes: !1, + wheelPropagation: !0, + wheelSpeed: 1 + }, + e) + this.settings[n] = e[n]; + function o() { + return t.classList.add(v.state.focus) + } + function r() { + return t.classList.remove(v.state.focus) + } + this.containerWidth = null, + this.containerHeight = null, + this.contentWidth = null, + this.contentHeight = null, + this.isRtl = "rtl" === p(t).direction, + !0 === this.isRtl && t.classList.add(v.rtl), + this.isNegativeScroll = (s = t.scrollLeft, + t.scrollLeft = -1, + a = t.scrollLeft < 0, + t.scrollLeft = s, + a), + this.negativeScrollAdjustment = this.isNegativeScroll ? t.scrollWidth - t.clientWidth : 0, + this.event = new h, + this.ownerDocument = t.ownerDocument || document, + this.scrollbarXRail = c(v.element.rail("x")), + t.appendChild(this.scrollbarXRail), + this.scrollbarX = c(v.element.thumb("x")), + this.scrollbarXRail.appendChild(this.scrollbarX), + this.scrollbarX.setAttribute("tabindex", 0), + this.event.bind(this.scrollbarX, "focus", o), + this.event.bind(this.scrollbarX, "blur", r), + this.scrollbarXActive = null, + this.scrollbarXWidth = null, + this.scrollbarXLeft = null; + var s = p(this.scrollbarXRail) + , a = (this.scrollbarXBottom = parseInt(s.bottom, 10), + isNaN(this.scrollbarXBottom) ? (this.isScrollbarXUsingBottom = !1, + this.scrollbarXTop = g(s.top)) : this.isScrollbarXUsingBottom = !0, + this.railBorderXWidth = g(s.borderLeftWidth) + g(s.borderRightWidth), + l(this.scrollbarXRail, { + display: "block" + }), + this.railXMarginWidth = g(s.marginLeft) + g(s.marginRight), + l(this.scrollbarXRail, { + display: "" + }), + this.railXWidth = null, + this.railXRatio = null, + this.scrollbarYRail = c(v.element.rail("y")), + t.appendChild(this.scrollbarYRail), + this.scrollbarY = c(v.element.thumb("y")), + this.scrollbarYRail.appendChild(this.scrollbarY), + this.scrollbarY.setAttribute("tabindex", 0), + this.event.bind(this.scrollbarY, "focus", o), + this.event.bind(this.scrollbarY, "blur", r), + this.scrollbarYActive = null, + this.scrollbarYHeight = null, + this.scrollbarYTop = null, + p(this.scrollbarYRail)); + this.scrollbarYRight = parseInt(a.right, 10), + isNaN(this.scrollbarYRight) ? (this.isScrollbarYUsingRight = !1, + this.scrollbarYLeft = g(a.left)) : this.isScrollbarYUsingRight = !0, + this.scrollbarYOuterWidth = this.isRtl ? g((s = p(s = this.scrollbarY)).width) + g(s.paddingLeft) + g(s.paddingRight) + g(s.borderLeftWidth) + g(s.borderRightWidth) : null, + this.railBorderYWidth = g(a.borderTopWidth) + g(a.borderBottomWidth), + l(this.scrollbarYRail, { + display: "block" + }), + this.railYMarginHeight = g(a.marginTop) + g(a.marginBottom), + l(this.scrollbarYRail, { + display: "" + }), + this.railYHeight = null, + this.railYRatio = null, + this.reach = { + x: t.scrollLeft <= 0 ? "start" : t.scrollLeft >= this.contentWidth - this.containerWidth ? "end" : null, + y: t.scrollTop <= 0 ? "start" : t.scrollTop >= this.contentHeight - this.containerHeight ? "end" : null + }, + this.isAlive = !0, + this.settings.handlers.forEach(function(t) { + return S[t](i) + }), + this.lastScrollTop = Math.floor(t.scrollTop), + this.lastScrollLeft = t.scrollLeft, + this.event.bind(this.element, "scroll", function(t) { + return i.onScroll(t) + }), + w(this) + } + var S = { + "click-rail": function(n) { + n.element, + n.event.bind(n.scrollbarY, "mousedown", function(t) { + return t.stopPropagation() + }), + n.event.bind(n.scrollbarYRail, "mousedown", function(t) { + var e = t.pageY - window.pageYOffset - n.scrollbarYRail.getBoundingClientRect().top > n.scrollbarYTop ? 1 : -1; + n.element.scrollTop += e * n.containerHeight, + w(n), + t.stopPropagation() + }), + n.event.bind(n.scrollbarX, "mousedown", function(t) { + return t.stopPropagation() + }), + n.event.bind(n.scrollbarXRail, "mousedown", function(t) { + var e = t.pageX - window.pageXOffset - n.scrollbarXRail.getBoundingClientRect().left > n.scrollbarXLeft ? 1 : -1; + n.element.scrollLeft += e * n.containerWidth, + w(n), + t.stopPropagation() + }) + }, + "drag-thumb": function(t) { + O(t, ["containerWidth", "contentWidth", "pageX", "railXWidth", "scrollbarX", "scrollbarXWidth", "scrollLeft", "x", "scrollbarXRail"]), + O(t, ["containerHeight", "contentHeight", "pageY", "railYHeight", "scrollbarY", "scrollbarYHeight", "scrollTop", "y", "scrollbarYRail"]) + }, + keyboard: function(r) { + var s = r.element; + r.event.bind(r.ownerDocument, "keydown", function(t) { + if (!(t.isDefaultPrevented && t.isDefaultPrevented() || t.defaultPrevented) && (a(s, ":hover") || a(r.scrollbarX, ":focus") || a(r.scrollbarY, ":focus"))) { + var e, n = document.activeElement || r.ownerDocument.activeElement; + if (n) { + if ("IFRAME" === n.tagName) + n = n.contentDocument.activeElement; + else + for (; n.shadowRoot; ) + n = n.shadowRoot.activeElement; + if (a(e = n, "input,[contenteditable]") || a(e, "select,[contenteditable]") || a(e, "textarea,[contenteditable]") || a(e, "button,[contenteditable]")) + return + } + var i = 0 + , o = 0; + switch (t.which) { + case 37: + i = t.metaKey ? -r.contentWidth : t.altKey ? -r.containerWidth : -30; + break; + case 38: + o = t.metaKey ? r.contentHeight : t.altKey ? r.containerHeight : 30; + break; + case 39: + i = t.metaKey ? r.contentWidth : t.altKey ? r.containerWidth : 30; + break; + case 40: + o = t.metaKey ? -r.contentHeight : t.altKey ? -r.containerHeight : -30; + break; + case 32: + o = t.shiftKey ? r.containerHeight : -r.containerHeight; + break; + case 33: + o = r.containerHeight; + break; + case 34: + o = -r.containerHeight; + break; + case 36: + o = r.contentHeight; + break; + case 35: + o = -r.contentHeight; + break; + default: + return + } + r.settings.suppressScrollX && 0 !== i || r.settings.suppressScrollY && 0 !== o || (s.scrollTop -= o, + s.scrollLeft += i, + w(r), + !function(t, e) { + var n = Math.floor(s.scrollTop); + if (0 === t) { + if (!r.scrollbarYActive) + return; + if (0 === n && 0 < e || n >= r.contentHeight - r.containerHeight && e < 0) + return !r.settings.wheelPropagation + } + if (n = s.scrollLeft, + 0 === e) { + if (!r.scrollbarXActive) + return; + if (0 === n && t < 0 || n >= r.contentWidth - r.containerWidth && 0 < t) + return !r.settings.wheelPropagation + } + return 1 + }(i, o)) || t.preventDefault() + } + }) + }, + wheel: function(l) { + var c = l.element; + function t(t) { + s = (r = t).deltaX, + a = -1 * r.deltaY, + void 0 !== s && void 0 !== a || (s = -1 * r.wheelDeltaX / 6, + a = r.wheelDeltaY / 6), + r.deltaMode && 1 === r.deltaMode && (s *= 10, + a *= 10), + s != s && a != a && (s = 0, + a = r.wheelDelta); + var e, n, i, o, r = r.shiftKey ? [-a, -s] : [s, a], s = r[0], a = r[1]; + !function(t, e, n) { + if (!m.isWebKit && c.querySelector("select:focus")) + return 1; + if (c.contains(t)) + for (var i = t; i && i !== c; ) { + if (i.classList.contains(v.element.consuming)) + return 1; + var o = p(i); + if (n && o.overflowY.match(/(scroll|auto)/)) { + var r = i.scrollHeight - i.clientHeight; + if (0 < r && (0 < i.scrollTop && n < 0 || i.scrollTop < r && 0 < n)) + return 1 + } + if (e && o.overflowX.match(/(scroll|auto)/)) { + r = i.scrollWidth - i.clientWidth; + if (0 < r && (0 < i.scrollLeft && e < 0 || i.scrollLeft < r && 0 < e)) + return 1 + } + i = i.parentNode + } + }(t.target, s, a) && (r = !1, + l.settings.useBothWheelAxes ? l.scrollbarYActive && !l.scrollbarXActive ? (a ? c.scrollTop -= a * l.settings.wheelSpeed : c.scrollTop += s * l.settings.wheelSpeed, + r = !0) : l.scrollbarXActive && !l.scrollbarYActive && (s ? c.scrollLeft += s * l.settings.wheelSpeed : c.scrollLeft -= a * l.settings.wheelSpeed, + r = !0) : (c.scrollTop -= a * l.settings.wheelSpeed, + c.scrollLeft += s * l.settings.wheelSpeed), + w(l), + r = r || (s = s, + a = a, + e = Math.floor(c.scrollTop), + n = 0 === c.scrollTop, + e = e + c.offsetHeight === c.scrollHeight, + i = 0 === c.scrollLeft, + o = c.scrollLeft + c.offsetWidth === c.scrollWidth, + !(a = Math.abs(a) > Math.abs(s) ? n || e : i || o)) || !l.settings.wheelPropagation) && !t.ctrlKey && (t.stopPropagation(), + t.preventDefault()) + } + void 0 !== window.onwheel ? l.event.bind(c, "wheel", t) : void 0 !== window.onmousewheel && l.event.bind(c, "mousewheel", t) + }, + touch: function(s) { + var a, r, l, c, e; + function u(t, e) { + a.scrollTop -= e, + a.scrollLeft -= t, + w(s) + } + function h(t) { + return t.targetTouches ? t.targetTouches[0] : t + } + function d(t) { + return (!t.pointerType || "pen" !== t.pointerType || 0 !== t.buttons) && (t.targetTouches && 1 === t.targetTouches.length || !(!t.pointerType || "mouse" === t.pointerType || t.pointerType === t.MSPOINTER_TYPE_MOUSE)) + } + function t(t) { + d(t) && (t = h(t), + r.pageX = t.pageX, + r.pageY = t.pageY, + l = (new Date).getTime(), + null !== e) && clearInterval(e) + } + function n(t) { + var e, n, i, o; + d(t) && (e = (i = { + pageX: (i = h(t)).pageX, + pageY: i.pageY + }).pageX - r.pageX, + n = i.pageY - r.pageY, + !function(t, e, n) { + if (a.contains(t)) + for (var i = t; i && i !== a; ) { + if (i.classList.contains(v.element.consuming)) + return 1; + var o = p(i); + if (n && o.overflowY.match(/(scroll|auto)/)) { + var r = i.scrollHeight - i.clientHeight; + if (0 < r && (0 < i.scrollTop && n < 0 || i.scrollTop < r && 0 < n)) + return 1 + } + if (e && o.overflowX.match(/(scroll|auto)/)) { + r = i.scrollWidth - i.clientWidth; + if (0 < r && (0 < i.scrollLeft && e < 0 || i.scrollLeft < r && 0 < e)) + return 1 + } + i = i.parentNode + } + }(t.target, e, n)) && (u(e, n), + r = i, + 0 < (o = (i = (new Date).getTime()) - l) && (c.x = e / o, + c.y = n / o, + l = i), + function(t, e) { + var n = Math.floor(a.scrollTop) + , i = a.scrollLeft + , o = Math.abs(t) + , r = Math.abs(e); + if (o < r) { + if (e < 0 && n === s.contentHeight - s.containerHeight || 0 < e && 0 === n) + return 0 === window.scrollY && 0 < e && m.isChrome + } else if (r < o && (t < 0 && i === s.contentWidth - s.containerWidth || 0 < t && 0 === i)) + ;return 1 + }(e, n)) && t.preventDefault() + } + function i() { + s.settings.swipeEasing && (clearInterval(e), + e = setInterval(function() { + !s.isInitialized && (c.x || c.y) && !(Math.abs(c.x) < .01 && Math.abs(c.y) < .01) && s.element ? (u(30 * c.x, 30 * c.y), + c.x *= .8, + c.y *= .8) : clearInterval(e) + }, 10)) + } + (m.supportsTouch || m.supportsIePointer) && (a = s.element, + r = {}, + l = 0, + c = {}, + e = null, + m.supportsTouch ? (s.event.bind(a, "touchstart", t), + s.event.bind(a, "touchmove", n), + s.event.bind(a, "touchend", i)) : m.supportsIePointer && (window.PointerEvent ? (s.event.bind(a, "pointerdown", t), + s.event.bind(a, "pointermove", n), + s.event.bind(a, "pointerup", i)) : window.MSPointerEvent && (s.event.bind(a, "MSPointerDown", t), + s.event.bind(a, "MSPointerMove", n), + s.event.bind(a, "MSPointerUp", i)))) + } + } + , C = (x.prototype.update = function() { + this.isAlive && (this.negativeScrollAdjustment = this.isNegativeScroll ? this.element.scrollWidth - this.element.clientWidth : 0, + l(this.scrollbarXRail, { + display: "block" + }), + l(this.scrollbarYRail, { + display: "block" + }), + this.railXMarginWidth = g(p(this.scrollbarXRail).marginLeft) + g(p(this.scrollbarXRail).marginRight), + this.railYMarginHeight = g(p(this.scrollbarYRail).marginTop) + g(p(this.scrollbarYRail).marginBottom), + l(this.scrollbarXRail, { + display: "none" + }), + l(this.scrollbarYRail, { + display: "none" + }), + w(this), + f(this, "top", 0, !1, !0), + f(this, "left", 0, !1, !0), + l(this.scrollbarXRail, { + display: "" + }), + l(this.scrollbarYRail, { + display: "" + })) + } + , + x.prototype.onScroll = function(t) { + this.isAlive && (w(this), + f(this, "top", this.element.scrollTop - this.lastScrollTop), + f(this, "left", this.element.scrollLeft - this.lastScrollLeft), + this.lastScrollTop = Math.floor(this.element.scrollTop), + this.lastScrollLeft = this.element.scrollLeft) + } + , + x.prototype.destroy = function() { + this.isAlive && (this.event.unbindAll(), + s(this.scrollbarX), + s(this.scrollbarY), + s(this.scrollbarXRail), + s(this.scrollbarYRail), + this.removePsClasses(), + this.element = null, + this.scrollbarX = null, + this.scrollbarY = null, + this.scrollbarXRail = null, + this.scrollbarYRail = null, + this.isAlive = !1) + } + , + x.prototype.removePsClasses = function() { + this.element.className = this.element.className.split(" ").filter(function(t) { + return !t.match(/^ps([-_].+|)$/) + }).join(" ") + } + , + x) + , E = e(3) + , k = e(7) + , A = e(0) + , j = e(1) + , r = e(2); + const T = "perfectScrollbar" + , L = "mdb.perfectScrollbar"; + var e = "mdb" + , P = "ps"; + const R = [{ + mdb: "scrollX.".concat(e, ".").concat(P), + ps: "ps-scroll-x" + }, { + mdb: "scrollY.".concat(e, ".").concat(P), + ps: "ps-scroll-y" + }, { + mdb: "scrollUp.".concat(e, ".").concat(P), + ps: "ps-scroll-up" + }, { + mdb: "scrollDown.".concat(e, ".").concat(P), + ps: "ps-scroll-down" + }, { + mdb: "scrollLeft.".concat(e, ".").concat(P), + ps: "ps-scroll-left" + }, { + mdb: "scrollRight.".concat(e, ".").concat(P), + ps: "ps-scroll-right" + }, { + mdb: "scrollXEnd.".concat(e, ".").concat(P), + ps: "ps-x-reach-end" + }, { + mdb: "scrollYEnd.".concat(e, ".").concat(P), + ps: "ps-y-reach-end" + }, { + mdb: "scrollXStart.".concat(e, ".").concat(P), + ps: "ps-x-reach-start" + }, { + mdb: "scrollYStart.".concat(e, ".").concat(P), + ps: "ps-y-reach-start" + }] + , M = { + handlers: ["click-rail", "drag-thumb", "keyboard", "wheel", "touch"], + wheelSpeed: 1, + wheelPropagation: !0, + swipeEasing: !0, + minScrollbarLength: null, + maxScrollbarLength: null, + scrollingThreshold: 1e3, + useBothWheelAxes: !1, + suppressScrollX: !1, + suppressScrollY: !1, + scrollXMarginOffset: 0, + scrollYMarginOffset: 0 + } + , N = { + handlers: "(string|array)", + wheelSpeed: "number", + wheelPropagation: "boolean", + swipeEasing: "boolean", + minScrollbarLength: "(number|null)", + maxScrollbarLength: "(number|null)", + scrollingThreshold: "number", + useBothWheelAxes: "boolean", + suppressScrollX: "boolean", + suppressScrollY: "boolean", + scrollXMarginOffset: "number", + scrollYMarginOffset: "number" + }; + class I { + constructor(t) { + var e = 1 < arguments.length && void 0 !== arguments[1] ? arguments[1] : {}; + this._element = t, + this._options = this._getConfig(e), + this.perfectScrollbar = null, + this._element && (k.a.setData(t, L, this), + A.a.addClass(this._element, "perfect-scrollbar")), + this.init() + } + static get NAME() { + return T + } + _getConfig(t) { + var e = A.a.getDataAttributes(this._element); + return void 0 !== e.handlers && (e.handlers = e.handlers.split(" ")), + t = { + ...M, + ...e, + ...t + }, + Object(E.j)(T, t, N), + t + } + dispose() { + k.a.removeData(this._element, L), + this._element = null, + this._dataAttrOptions = null, + this._options = null, + this.perfectScrollbar.destroy(), + this.removeEvent(R), + this.perfectScrollbar = null + } + init() { + this.perfectScrollbar = new C(this._element,this._options), + this._initEvents(R) + } + update() { + return this.perfectScrollbar.update() + } + _initEvents() { + (0 < arguments.length && void 0 !== arguments[0] ? arguments[0] : []).forEach(t=>{ + let {ps: e, mdb: n} = t; + return j.b.on(this._element, e, t=>j.b.trigger(this._element, n, { + e: t + })) + } + ) + } + removeEvent(e) { + let t = []; + (t = "string" == typeof e ? R.filter(t=>{ + t = t.mdb; + return t === e + } + ) : t).forEach(t=>{ + var {ps: t, mdb: e} = t; + j.b.off(this._element, t), + j.b.off(this._element, e) + } + ) + } + static jQueryInterface(n) { + return this.each(function() { + let t = k.a.getData(this, L); + var e = "object" == typeof n && n; + if ((t || !/dispose|hide/.test(n)) && (t = t || new I(this,e), + "string" == typeof n)) { + if (void 0 === t[n]) + throw new TypeError('No method named "'.concat(n, '"')); + t[n]() + } + }) + } + static getInstance(t) { + return k.a.getData(t, L) + } + static getOrCreateInstance(t) { + var e = 1 < arguments.length && void 0 !== arguments[1] ? arguments[1] : {}; + return this.getInstance(t) || new this(t,"object" == typeof e ? e : null) + } + } + r.a.find('[data-mdb-perfect-scrollbar="true"]').forEach(t=>{ + let e = I.getInstance(t); + return e = e || new I(t) + } + ), + Object(E.i)(()=>{ + const t = Object(E.f)(); + if (t) { + const e = t.fn[T]; + t.fn[T] = I.jQueryInterface, + t.fn[T].Constructor = I, + t.fn[T].noConflict = ()=>(t.fn[T] = e, + I.jQueryInterface) + } + } + ); + t.a = I + } + , function(t, e, n) { + "use strict"; + n.r(e), + n.d(e, "compiled", function() { + return m + }); + n(204), + n(220), + n(235); + var e = n(190) + , i = n(52) + , o = n(191) + , r = n(192) + , s = n(193) + , a = n(136) + , l = n(102) + , c = n(194) + , u = n(138) + , h = n(189) + , d = n(188) + , p = n(195) + , f = n(196) + , g = n(134) + , n = n(197); + const m = { + Button: e.a, + Collapse: i.a, + Popover: o.a, + ScrollSpy: r.a, + Tab: s.a, + Tooltip: a.a, + Input: l.a, + Dropdown: c.a, + Animate: u.a, + Modal: h.a, + Sidenav: d.a, + Alert: p.a, + Toast: f.a, + Select: g.a, + PerfectScrollbar: n.a + } + } + , function(t, e, n) { + "use strict"; + var i = n(26) + , o = n(262).left + , r = n(176) + , s = n(90); + i({ + target: "Array", + proto: !0, + forced: !n(83) && 79 < s && s < 83 || !r("reduce") + }, { + reduce: function(t) { + var e = arguments.length; + return o(this, t, e, 1 < e ? arguments[1] : void 0) + } + }) + } + , function(t, e, n) { + "use strict"; + var i = n(14) + , o = n(50) + , d = Math.floor + , p = i("".charAt) + , f = i("".replace) + , g = i("".slice) + , m = /\$([$&'`]|\d{1,2}|<[^>]*>)/g + , b = /\$([$&'`]|\d{1,2})/g; + t.exports = function(r, s, a, l, c, t) { + var u = a + r.length + , h = l.length + , e = b; + return void 0 !== c && (c = o(c), + e = m), + f(t, e, function(t, e) { + var n; + switch (p(e, 0)) { + case "$": + return "$"; + case "&": + return r; + case "`": + return g(s, 0, a); + case "'": + return g(s, u); + case "<": + n = c[g(e, 1, -1)]; + break; + default: + var i, o = +e; + if (0 == o) + return t; + if (h < o) + return 0 !== (i = d(o / 10)) && i <= h ? void 0 === l[i - 1] ? p(e, 1) : l[i - 1] + p(e, 1) : t; + n = l[o - 1] + } + return void 0 === n ? "" : n + }) + } + } + , function(t, e, n) { + "use strict"; + var i = n(35) + , o = n(55) + , r = n(20)("match"); + t.exports = function(t) { + var e; + return i(t) && (void 0 !== (e = t[r]) ? !!e : "RegExp" === o(t)) + } + } + , function(t, e, n) { + "use strict"; + var i = n(22) + , o = n(29) + , r = n(56) + , s = n(125) + , a = RegExp.prototype; + t.exports = function(t) { + var e = t.flags; + return void 0 !== e || "flags"in a || o(t, "flags") || !r(a, t) ? e : i(s, t) + } + } + , function(t, e, n) { + "use strict"; + n(237), + n(246), + n(248), + n(249), + n(250), + n(251) + } + , function(t, e, n) { + "use strict"; + !function(t) { + var e; + n(137), + n(11), + n(12); + e = function() { + return n = [function(t, e, n) { + var i; + n = [t, n(7)], + void 0 !== (e = "function" == typeof (i = function(t, e) { + "use strict"; + function n(t, e) { + if (!(t instanceof e)) + throw new TypeError("Cannot call a class as a function") + } + var i = function(t) { + return t && t.__esModule ? t : { + default: t + } + }(e) + , o = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(t) { + return typeof t + } + : function(t) { + return t && "function" == typeof Symbol && t.constructor === Symbol && t !== Symbol.prototype ? "symbol" : typeof t + } + , r = function() { + function i(t, e) { + for (var n = 0; n < e.length; n++) { + var i = e[n]; + i.enumerable = i.enumerable || !1, + i.configurable = !0, + "value"in i && (i.writable = !0), + Object.defineProperty(t, i.key, i) + } + } + return function(t, e, n) { + return e && i(t.prototype, e), + n && i(t, n), + t + } + }() + , s = function() { + function e(t) { + n(this, e), + this.resolveOptions(t), + this.initSelection() + } + return r(e, [{ + key: "resolveOptions", + value: function() { + var t = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {}; + this.action = t.action, + this.container = t.container, + this.emitter = t.emitter, + this.target = t.target, + this.text = t.text, + this.trigger = t.trigger, + this.selectedText = "" + } + }, { + key: "initSelection", + value: function() { + this.text ? this.selectFake() : this.target && this.selectTarget() + } + }, { + key: "selectFake", + value: function() { + var t = this + , e = "rtl" == document.documentElement.getAttribute("dir"); + this.removeFake(), + this.fakeHandlerCallback = function() { + return t.removeFake() + } + , + this.fakeHandler = this.container.addEventListener("click", this.fakeHandlerCallback) || !0, + this.fakeElem = document.createElement("textarea"), + this.fakeElem.style.fontSize = "12pt", + this.fakeElem.style.border = "0", + this.fakeElem.style.padding = "0", + this.fakeElem.style.margin = "0", + this.fakeElem.style.position = "absolute", + this.fakeElem.style[e ? "right" : "left"] = "-9999px"; + var n = window.pageYOffset || document.documentElement.scrollTop; + this.fakeElem.style.top = n + "px", + this.fakeElem.setAttribute("readonly", ""), + this.fakeElem.value = this.text, + this.container.appendChild(this.fakeElem), + this.selectedText = (0, + i.default)(this.fakeElem), + this.copyText() + } + }, { + key: "removeFake", + value: function() { + this.fakeHandler && (this.container.removeEventListener("click", this.fakeHandlerCallback), + this.fakeHandler = null, + this.fakeHandlerCallback = null), + this.fakeElem && (this.container.removeChild(this.fakeElem), + this.fakeElem = null) + } + }, { + key: "selectTarget", + value: function() { + this.selectedText = (0, + i.default)(this.target), + this.copyText() + } + }, { + key: "copyText", + value: function() { + var e = void 0; + try { + e = document.execCommand(this.action) + } catch (t) { + e = !1 + } + this.handleResult(e) + } + }, { + key: "handleResult", + value: function(t) { + this.emitter.emit(t ? "success" : "error", { + action: this.action, + text: this.selectedText, + trigger: this.trigger, + clearSelection: this.clearSelection.bind(this) + }) + } + }, { + key: "clearSelection", + value: function() { + this.trigger && this.trigger.focus(), + window.getSelection().removeAllRanges() + } + }, { + key: "destroy", + value: function() { + this.removeFake() + } + }, { + key: "action", + set: function() { + var t = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "copy"; + if (this._action = t, + "copy" !== this._action && "cut" !== this._action) + throw new Error('Invalid "action" value, use either "copy" or "cut"') + }, + get: function() { + return this._action + } + }, { + key: "target", + set: function(t) { + if (void 0 !== t) { + if (!t || "object" !== (void 0 === t ? "undefined" : o(t)) || 1 !== t.nodeType) + throw new Error('Invalid "target" value, use a valid Element'); + if ("copy" === this.action && t.hasAttribute("disabled")) + throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute'); + if ("cut" === this.action && (t.hasAttribute("readonly") || t.hasAttribute("disabled"))) + throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes'); + this._target = t + } + }, + get: function() { + return this._target + } + }]), + e + }(); + t.exports = s + } + ) ? i.apply(e, n) : i) && (t.exports = e) + } + , function(t, e, n) { + var c = n(6) + , u = n(5); + t.exports = function(t, e, n) { + if (!t && !e && !n) + throw new Error("Missing required arguments"); + if (!c.string(e)) + throw new TypeError("Second argument must be a String"); + if (!c.fn(n)) + throw new TypeError("Third argument must be a Function"); + if (c.node(t)) + return o = e, + r = n, + (i = t).addEventListener(o, r), + { + destroy: function() { + i.removeEventListener(o, r) + } + }; + var i, o, r, s, a, l; + if (c.nodeList(t)) + return s = t, + a = e, + l = n, + Array.prototype.forEach.call(s, function(t) { + t.addEventListener(a, l) + }), + { + destroy: function() { + Array.prototype.forEach.call(s, function(t) { + t.removeEventListener(a, l) + }) + } + }; + if (c.string(t)) + return u(document.body, t, e, n); + throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList") + } + } + , function(t, e) { + function n() {} + n.prototype = { + on: function(t, e, n) { + var i = this.e || (this.e = {}); + return (i[t] || (i[t] = [])).push({ + fn: e, + ctx: n + }), + this + }, + once: function(t, e, n) { + function i() { + o.off(t, i), + e.apply(n, arguments) + } + var o = this; + return i._ = e, + this.on(t, i, n) + }, + emit: function(t) { + for (var e = [].slice.call(arguments, 1), n = ((this.e || (this.e = {}))[t] || []).slice(), i = 0, o = n.length; i < o; i++) + n[i].fn.apply(n[i].ctx, e); + return this + }, + off: function(t, e) { + var n = this.e || (this.e = {}) + , i = n[t] + , o = []; + if (i && e) + for (var r = 0, s = i.length; r < s; r++) + i[r].fn !== e && i[r].fn._ !== e && o.push(i[r]); + return o.length ? n[t] = o : delete n[t], + this + } + }, + t.exports = n + } + , function(t, e, n) { + var i; + n = [t, n(0), n(2), n(1)], + void 0 !== (e = "function" == typeof (i = function(t, e, n, i) { + "use strict"; + function o(t) { + return t && t.__esModule ? t : { + default: t + } + } + function r(t, e) { + if (!(t instanceof e)) + throw new TypeError("Cannot call a class as a function") + } + function s(t, e) { + if (!t) + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + return !e || "object" != typeof e && "function" != typeof e ? t : e + } + function a(t, e) { + if ("function" != typeof e && null !== e) + throw new TypeError("Super expression must either be null or a function, not " + typeof e); + t.prototype = Object.create(e && e.prototype, { + constructor: { + value: t, + enumerable: !1, + writable: !0, + configurable: !0 + } + }), + e && (Object.setPrototypeOf ? Object.setPrototypeOf(t, e) : t.__proto__ = e) + } + function l(t, e) { + var n = "data-clipboard-" + t; + if (e.hasAttribute(n)) + return e.getAttribute(n) + } + var c = o(e) + , u = o(n) + , h = o(i) + , d = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(t) { + return typeof t + } + : function(t) { + return t && "function" == typeof Symbol && t.constructor === Symbol && t !== Symbol.prototype ? "symbol" : typeof t + } + , p = function() { + function i(t, e) { + for (var n = 0; n < e.length; n++) { + var i = e[n]; + i.enumerable = i.enumerable || !1, + i.configurable = !0, + "value"in i && (i.writable = !0), + Object.defineProperty(t, i.key, i) + } + } + return function(t, e, n) { + return e && i(t.prototype, e), + n && i(t, n), + t + } + }() + , f = function(t) { + function i(t, e) { + r(this, i); + var n = s(this, (i.__proto__ || Object.getPrototypeOf(i)).call(this)); + return n.resolveOptions(e), + n.listenClick(t), + n + } + return a(i, t), + p(i, [{ + key: "resolveOptions", + value: function() { + var t = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {}; + this.action = "function" == typeof t.action ? t.action : this.defaultAction, + this.target = "function" == typeof t.target ? t.target : this.defaultTarget, + this.text = "function" == typeof t.text ? t.text : this.defaultText, + this.container = "object" === d(t.container) ? t.container : document.body + } + }, { + key: "listenClick", + value: function(t) { + var e = this; + this.listener = (0, + h.default)(t, "click", function(t) { + return e.onClick(t) + }) + } + }, { + key: "onClick", + value: function(t) { + var e = t.delegateTarget || t.currentTarget; + this.clipboardAction && (this.clipboardAction = null), + this.clipboardAction = new c.default({ + action: this.action(e), + target: this.target(e), + text: this.text(e), + container: this.container, + trigger: e, + emitter: this + }) + } + }, { + key: "defaultAction", + value: function(t) { + return l("action", t) + } + }, { + key: "defaultTarget", + value: function(t) { + var e = l("target", t); + if (e) + return document.querySelector(e) + } + }, { + key: "defaultText", + value: function(t) { + return l("text", t) + } + }, { + key: "destroy", + value: function() { + this.listener.destroy(), + this.clipboardAction && (this.clipboardAction.destroy(), + this.clipboardAction = null) + } + }], [{ + key: "isSupported", + value: function() { + var t = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : ["copy", "cut"] + , e = "string" == typeof t ? [t] : t + , n = !!document.queryCommandSupported; + return e.forEach(function(t) { + n = n && !!document.queryCommandSupported(t) + }), + n + } + }]), + i + }(u.default); + t.exports = f + } + ) ? i.apply(e, n) : i) && (t.exports = e) + } + , function(t, e) { + var n; + "undefined" == typeof Element || Element.prototype.matches || ((n = Element.prototype).matches = n.matchesSelector || n.mozMatchesSelector || n.msMatchesSelector || n.oMatchesSelector || n.webkitMatchesSelector), + t.exports = function(t, e) { + for (; t && 9 !== t.nodeType; ) { + if ("function" == typeof t.matches && t.matches(e)) + return t; + t = t.parentNode + } + } + } + , function(t, e, n) { + function r(t, e, n, i, o) { + var r = function(e, n, t, i) { + return function(t) { + t.delegateTarget = s(t.target, n), + t.delegateTarget && i.call(e, t) + } + } + .apply(this, arguments); + return t.addEventListener(n, r, o), + { + destroy: function() { + t.removeEventListener(n, r, o) + } + } + } + var s = n(4); + t.exports = function(t, e, n, i, o) { + return "function" == typeof t.addEventListener ? r.apply(null, arguments) : "function" == typeof n ? r.bind(null, document).apply(null, arguments) : ("string" == typeof t && (t = document.querySelectorAll(t)), + Array.prototype.map.call(t, function(t) { + return r(t, e, n, i, o) + })) + } + } + , function(t, n) { + n.node = function(t) { + return void 0 !== t && t instanceof HTMLElement && 1 === t.nodeType + } + , + n.nodeList = function(t) { + var e = Object.prototype.toString.call(t); + return void 0 !== t && ("[object NodeList]" === e || "[object HTMLCollection]" === e) && "length"in t && (0 === t.length || n.node(t[0])) + } + , + n.string = function(t) { + return "string" == typeof t || t instanceof String + } + , + n.fn = function(t) { + return "[object Function]" === Object.prototype.toString.call(t) + } + } + , function(t, e) { + t.exports = function(t) { + var e, n; + return t = "SELECT" === t.nodeName ? (t.focus(), + t.value) : "INPUT" === t.nodeName || "TEXTAREA" === t.nodeName ? ((e = t.hasAttribute("readonly")) || t.setAttribute("readonly", ""), + t.select(), + t.setSelectionRange(0, t.value.length), + e || t.removeAttribute("readonly"), + t.value) : (t.hasAttribute("contenteditable") && t.focus(), + e = window.getSelection(), + (n = document.createRange()).selectNodeContents(t), + e.removeAllRanges(), + e.addRange(n), + e.toString()) + } + } + ], + o = {}, + i.m = n, + i.c = o, + i.i = function(t) { + return t + } + , + i.d = function(t, e, n) { + i.o(t, e) || Object.defineProperty(t, e, { + configurable: !1, + enumerable: !0, + get: n + }) + } + , + i.n = function(t) { + var e = t && t.__esModule ? function() { + return t.default + } + : function() { + return t + } + ; + return i.d(e, "a", e), + e + } + , + i.o = function(t, e) { + return Object.prototype.hasOwnProperty.call(t, e) + } + , + i.p = "", + i(i.s = 3); + function i(t) { + var e; + return (o[t] || (e = o[t] = { + i: t, + l: !1, + exports: {} + }, + n[t].call(e.exports, e, e.exports, i), + e.l = !0, + e)).exports + } + var n, o + } + , + "object" == typeof exports && "object" == typeof t ? t.exports = e() : "function" == typeof define && n(219) ? define([], e) : "object" == typeof exports ? exports.ClipboardJS = e() : window.ClipboardJS = e() + } + .call(this, n(205)(t)) + } + , function(t, e) { + t.exports = function(t) { + var e; + return t.webpackPolyfill || ((e = Object.create(t)).children || (e.children = []), + Object.defineProperty(e, "loaded", { + enumerable: !0, + get: function() { + return e.l + } + }), + Object.defineProperty(e, "id", { + enumerable: !0, + get: function() { + return e.i + } + }), + Object.defineProperty(e, "exports", { + enumerable: !0 + }), + e.webpackPolyfill = 1), + e + } + } + , function(t, e) { + var n = function() { + return this + }(); + try { + n = n || new Function("return this")() + } catch (t) { + "object" == typeof window && (n = window) + } + t.exports = n + } + , function(t, e, n) { + "use strict"; + var i = n(22) + , o = n(35) + , r = n(144) + , s = n(88) + , a = n(208) + , n = n(20) + , l = TypeError + , c = n("toPrimitive"); + t.exports = function(t, e) { + if (!o(t) || r(t)) + return t; + var n = s(t, c); + if (n) { + if (n = i(n, t, e = void 0 === e ? "default" : e), + !o(n) || r(n)) + return n; + throw l("Can't convert object to primitive value") + } + return a(t, e = void 0 === e ? "number" : e) + } + } + , function(t, e, n) { + "use strict"; + var o = n(22) + , r = n(15) + , s = n(35) + , a = TypeError; + t.exports = function(t, e) { + var n, i; + if ("string" === e && r(n = t.toString) && !s(i = o(n, t))) + return i; + if (r(n = t.valueOf) && !s(i = o(n, t))) + return i; + if ("string" !== e && r(n = t.toString) && !s(i = o(n, t))) + return i; + throw a("Can't convert object to primitive value") + } + } + , function(t, e, n) { + "use strict"; + var i = n(13) + , n = n(15) + , i = i.WeakMap; + t.exports = n(i) && /native code/.test(String(i)) + } + , function(t, e, n) { + "use strict"; + var i = n(48) + , o = n(14) + , r = n(152) + , s = n(157) + , a = n(30) + , l = o([].concat); + t.exports = i("Reflect", "ownKeys") || function(t) { + var e = r.f(a(t)) + , n = s.f; + return n ? l(e, n(t)) : e + } + } + , function(t, e, n) { + "use strict"; + var i = Math.ceil + , o = Math.floor; + t.exports = Math.trunc || function(t) { + t = +t; + return (0 < t ? o : i)(t) + } + } + , function(t, e, n) { + "use strict"; + var i = {}; + i[n(20)("toStringTag")] = "z", + t.exports = "[object z]" === String(i) + } + , function(t, e, n) { + "use strict"; + var i = n(23) + , o = n(149) + , a = n(40) + , l = n(30) + , c = n(77) + , u = n(159); + e.f = i && !o ? Object.defineProperties : function(t, e) { + l(t); + for (var n, i = c(e), o = u(e), r = o.length, s = 0; s < r; ) + a.f(t, n = o[s++], i[n]); + return t + } + } + , function(t, e, n) { + "use strict"; + n = n(16); + t.exports = !n(function() { + function t() {} + return t.prototype.constructor = null, + Object.getPrototypeOf(new t) !== t.prototype + }) + } + , function(t, e, n) { + "use strict"; + var i = n(14) + , o = n(39); + t.exports = function(t, e, n) { + try { + return i(o(Object.getOwnPropertyDescriptor(t, e)[n])) + } catch (t) {} + } + } + , function(t, e, n) { + "use strict"; + var i = n(15) + , o = String + , r = TypeError; + t.exports = function(t) { + if ("object" == typeof t || i(t)) + return t; + throw r("Can't set " + o(t) + " as a prototype") + } + } + , function(t, e, n) { + "use strict"; + t.exports = { + CSSRuleList: 0, + CSSStyleDeclaration: 0, + CSSValueList: 0, + ClientRectList: 0, + DOMRectList: 0, + DOMStringList: 0, + DOMTokenList: 1, + DataTransferItemList: 0, + FileList: 0, + HTMLAllCollection: 0, + HTMLCollection: 0, + HTMLFormElement: 0, + HTMLSelectElement: 0, + MediaList: 0, + MimeTypeArray: 0, + NamedNodeMap: 0, + NodeList: 1, + PaintRequestList: 0, + Plugin: 0, + PluginArray: 0, + SVGLengthList: 0, + SVGNumberList: 0, + SVGPathSegList: 0, + SVGPointList: 0, + SVGStringList: 0, + SVGTransformList: 0, + SourceBufferList: 0, + StyleSheetList: 0, + TextTrackCueList: 0, + TextTrackList: 0, + TouchList: 0 + } + } + , function(t, e, n) { + "use strict"; + n = n(91)("span").classList, + n = n && n.constructor && n.constructor.prototype; + t.exports = n === Object.prototype ? void 0 : n + } + , function(e, t) { + !function(t) { + e.exports = t + } + .call(this, {}) + } + , function(t, e, n) { + "use strict"; + var i, o; + n(137), + n(221), + n(17), + n(53), + n(72), + n(11), + n(12), + n(228), + n(75), + n(133), + n(28); + function r(t) { + var e; + return (o[t] || (e = o[t] = { + i: t, + l: !1, + exports: {} + }, + i[t].call(e.exports, e, e.exports, r), + e.l = !0, + e)).exports + } + i = [function(t, e) { + t.exports = function(t) { + try { + return !!t() + } catch (t) { + return !0 + } + } + } + , function(t, e, n) { + var n = n(21) + , i = (o = Function.prototype).call + , o = n && o.bind.bind(i, i); + t.exports = n ? o : function(t) { + return function() { + return i.apply(t, arguments) + } + } + } + , function(t, e, n) { + var i = (n = n(39)).all; + t.exports = n.IS_HTMLDDA ? function(t) { + return "function" == typeof t || t === i + } + : function(t) { + return "function" == typeof t + } + } + , function(n, t, e) { + !function(t) { + function e(t) { + return t && t.Math == Math && t + } + n.exports = e("object" == typeof globalThis && globalThis) || e("object" == typeof window && window) || e("object" == typeof self && self) || e("object" == typeof t && t) || function() { + return this + }() || Function("return this")() + } + .call(this, e(36)) + } + , function(t, e, n) { + n = n(0), + t.exports = !n(function() { + return 7 != Object.defineProperty({}, 1, { + get: function() { + return 7 + } + })[1] + }) + } + , function(t, e, n) { + var i = n(1) + , o = n(29) + , r = i({}.hasOwnProperty); + t.exports = Object.hasOwn || function(t, e) { + return r(o(t), e) + } + } + , function(t, e, n) { + var i = n(3) + , o = n(26) + , r = n(5) + , s = n(47) + , a = n(42) + , l = n(41) + , c = o("wks") + , u = i.Symbol + , h = u && u.for + , d = l ? u : u && u.withoutSetter || s; + t.exports = function(t) { + var e; + return r(c, t) && (a || "string" == typeof c[t]) || (e = "Symbol." + t, + a && r(u, t) ? c[t] = u[t] : c[t] = (l && h ? h : d)(e)), + c[t] + } + } + , function(t, e, n) { + var i = n(9) + , o = String + , r = TypeError; + t.exports = function(t) { + if (i(t)) + return t; + throw r(o(t) + " is not an object") + } + } + , function(t, e, n) { + var n = n(21) + , i = Function.prototype.call; + t.exports = n ? i.bind(i) : function() { + return i.apply(i, arguments) + } + } + , function(t, e, n) { + var i = n(2) + , o = (n = n(39)).all; + t.exports = n.IS_HTMLDDA ? function(t) { + return "object" == typeof t ? null !== t : i(t) || t === o + } + : function(t) { + return "object" == typeof t ? null !== t : i(t) + } + } + , function(t, e, n) { + var i = n(4) + , o = n(48) + , r = n(50) + , s = n(7) + , a = n(24) + , l = TypeError + , c = Object.defineProperty + , u = Object.getOwnPropertyDescriptor + , h = "enumerable" + , d = "configurable" + , p = "writable"; + e.f = i ? r ? function(t, e, n) { + var i; + return s(t), + e = a(e), + s(n), + "function" == typeof t && "prototype" === e && "value"in n && p in n && !n[p] && (i = u(t, e)) && i[p] && (t[e] = n.value, + n = { + configurable: (d in n ? n : i)[d], + enumerable: (h in n ? n : i)[h], + writable: !1 + }), + c(t, e, n) + } + : c : function(t, e, n) { + if (s(t), + e = a(e), + s(n), + o) + try { + return c(t, e, n) + } catch (t) {} + if ("get"in n || "set"in n) + throw l("Accessors not supported"); + return "value"in n && (t[e] = n.value), + t + } + } + , function(t, e, n) { + var i = n(83) + , o = String; + t.exports = function(t) { + if ("Symbol" === i(t)) + throw TypeError("Cannot convert a Symbol value to a string"); + return o(t) + } + } + , function(t, e, n) { + var i = (n = n(1))({}.toString) + , o = n("".slice); + t.exports = function(t) { + return o(i(t), 8, -1) + } + } + , function(t, e, n) { + var i = n(23) + , o = TypeError; + t.exports = function(t) { + if (i(t)) + throw o("Can't call method on " + t); + return t + } + } + , function(t, e, n) { + var i = n(3) + , o = n(2); + t.exports = function(t, e) { + return arguments.length < 2 ? (n = i[t], + o(n) ? n : void 0) : i[t] && i[t][e]; + var n + } + } + , function(t, e, n) { + var i = n(71) + , o = n(13); + t.exports = function(t) { + return i(o(t)) + } + } + , function(t, e, n) { + n = n(14), + t.exports = n("navigator", "userAgent") || "" + } + , function(t, e, n) { + var i = n(4) + , o = n(10) + , r = n(22); + t.exports = i ? function(t, e, n) { + return o.f(t, e, r(1, n)) + } + : function(t, e, n) { + return t[e] = n, + t + } + } + , function(t, e, n) { + var i = n(81); + t.exports = function(t) { + return (t = +t) != t || 0 == t ? 0 : i(t) + } + } + , , function(t, e, n) { + var c = n(3) + , u = n(38).f + , h = n(17) + , d = n(30) + , p = n(28) + , f = n(78) + , g = n(57); + t.exports = function(t, e) { + var n, i, o, r = t.target, s = t.global, a = t.stat, l = s ? c : a ? c[r] || p(r, {}) : (c[r] || {}).prototype; + if (l) + for (n in e) { + if (i = e[n], + o = t.dontCallGetSet ? (o = u(l, n)) && o.value : l[n], + !g(s ? n : r + (a ? "." : "#") + n, t.forced) && void 0 !== o) { + if (typeof i == typeof o) + continue; + f(i, o) + } + (t.sham || o && o.sham) && h(i, "sham", !0), + d(l, n, i, t) + } + } + } + , function(t, e, n) { + n = n(0), + t.exports = !n(function() { + var t = function() {} + .bind(); + return "function" != typeof t || t.hasOwnProperty("prototype") + }) + } + , function(t, e) { + t.exports = function(t, e) { + return { + enumerable: !(1 & t), + configurable: !(2 & t), + writable: !(4 & t), + value: e + } + } + } + , function(t, e) { + t.exports = function(t) { + return null == t + } + } + , function(t, e, n) { + var i = n(72) + , o = n(40); + t.exports = function(t) { + return t = i(t, "string"), + o(t) ? t : t + "" + } + } + , function(t, e, n) { + n = n(1), + t.exports = n({}.isPrototypeOf) + } + , function(t, e, n) { + var i = n(74) + , o = n(27); + (t.exports = function(t, e) { + return o[t] || (o[t] = void 0 !== e ? e : {}) + } + )("versions", []).push({ + version: "3.26.1", + mode: i ? "pure" : "global", + copyright: "© 2014-2022 Denis Pushkarev (zloirock.ru)", + license: "https://github.com/zloirock/core-js/blob/v3.26.1/LICENSE", + source: "https://github.com/zloirock/core-js" + }) + } + , function(t, e, n) { + var i = n(3) + , n = n(28) + , o = "__core-js_shared__" + , i = i[o] || n(o, {}); + t.exports = i + } + , function(t, e, n) { + var i = n(3) + , o = Object.defineProperty; + t.exports = function(e, n) { + try { + o(i, e, { + value: n, + configurable: !0, + writable: !0 + }) + } catch (t) { + i[e] = n + } + return n + } + } + , function(t, e, n) { + var i = n(13) + , o = Object; + t.exports = function(t) { + return o(i(t)) + } + } + , function(t, e, n) { + var s = n(2) + , a = n(10) + , l = n(75) + , c = n(28); + t.exports = function(t, e, n, i) { + var o = (i = i || {}).enumerable + , r = void 0 !== i.name ? i.name : e; + if (s(n) && l(n, r, i), + i.global) + o ? t[e] = n : c(e, n); + else { + try { + i.unsafe ? t[e] && (o = !0) : delete t[e] + } catch (t) {} + o ? t[e] = n : a.f(t, e, { + value: n, + enumerable: !1, + configurable: !i.nonConfigurable, + writable: !i.nonWritable + }) + } + return t + } + } + , function(t, e, n) { + var i, o, r, s, a = n(77), l = n(3), c = n(9), u = n(17), h = n(5), d = n(27), p = n(52), n = n(32), f = "Object already initialized", g = l.TypeError, l = l.WeakMap, m = a || d.state ? ((r = d.state || (d.state = new l)).get = r.get, + r.has = r.has, + r.set = r.set, + i = function(t, e) { + if (r.has(t)) + throw g(f); + return e.facade = t, + r.set(t, e), + e + } + , + o = function(t) { + return r.get(t) || {} + } + , + function(t) { + return r.has(t) + } + ) : (n[s = p("state")] = !0, + i = function(t, e) { + if (h(t, s)) + throw g(f); + return e.facade = t, + u(t, s, e), + e + } + , + o = function(t) { + return h(t, s) ? t[s] : {} + } + , + function(t) { + return h(t, s) + } + ); + t.exports = { + set: i, + get: o, + has: m, + enforce: function(t) { + return m(t) ? o(t) : i(t, {}) + }, + getterFor: function(e) { + return function(t) { + if (c(t) && (t = o(t)).type === e) + return t; + throw g("Incompatible receiver, " + e + " required") + } + } + } + } + , function(t, e) { + t.exports = {} + } + , function(t, e, n) { + var i = n(56); + t.exports = function(t) { + return i(t.length) + } + } + , function(t, e) { + t.exports = ["constructor", "hasOwnProperty", "isPrototypeOf", "propertyIsEnumerable", "toLocaleString", "toString", "valueOf"] + } + , function(t, e, n) { + var f = n(8) + , i = n(1) + , g = n(11) + , m = n(58) + , o = n(59) + , r = n(26) + , b = n(85) + , v = n(31).get + , s = n(60) + , n = n(61) + , _ = r("native-string-replace", String.prototype.replace) + , y = RegExp.prototype.exec + , w = y + , O = i("".charAt) + , x = i("".indexOf) + , S = i("".replace) + , C = i("".slice) + , E = (r = /b*/g, + f(y, i = /a/, "a"), + f(y, r, "a"), + 0 !== i.lastIndex || 0 !== r.lastIndex) + , k = o.BROKEN_CARET + , A = void 0 !== /()??/.exec("")[1]; + (E || A || k || s || n) && (w = function(t) { + var e, n, i, o, r, s, a = this, l = v(a), t = g(t); + if (u = l.raw) + return u.lastIndex = a.lastIndex, + h = f(w, u, t), + a.lastIndex = u.lastIndex, + h; + var c = l.groups + , u = k && a.sticky + , h = f(m, a) + , l = a.source + , d = 0 + , p = t; + if (u && (h = S(h, "y", ""), + -1 === x(h, "g") && (h += "g"), + p = C(t, a.lastIndex), + 0 < a.lastIndex && (!a.multiline || a.multiline && "\n" !== O(t, a.lastIndex - 1)) && (l = "(?: " + l + ")", + p = " " + p, + d++), + e = new RegExp("^(?:" + l + ")",h)), + A && (e = new RegExp("^" + l + "$(?!\\s)",h)), + E && (n = a.lastIndex), + i = f(y, u ? e : a, p), + u ? i ? (i.input = C(i.input, d), + i[0] = C(i[0], d), + i.index = a.lastIndex, + a.lastIndex += i[0].length) : a.lastIndex = 0 : E && i && (a.lastIndex = a.global ? i.index + i[0].length : n), + A && i && 1 < i.length && f(_, i[0], e, function() { + for (o = 1; o < arguments.length - 2; o++) + void 0 === arguments[o] && (i[o] = void 0) + }), + i && c) + for (i.groups = r = b(null), + o = 0; o < c.length; o++) + r[(s = c[o])[0]] = i[s[1]]; + return i + } + ), + t.exports = w + } + , function(t, e) { + var n = function() { + return this + }(); + try { + n = n || new Function("return this")() + } catch (t) { + "object" == typeof window && (n = window) + } + t.exports = n + } + , function(t, e, n) { + var i = n(20) + , n = n(35); + i({ + target: "RegExp", + proto: !0, + forced: /./.exec !== n + }, { + exec: n + }) + } + , function(t, e, n) { + var i = n(4) + , o = n(8) + , r = n(70) + , s = n(22) + , a = n(15) + , l = n(24) + , c = n(5) + , u = n(48) + , h = Object.getOwnPropertyDescriptor; + e.f = i ? h : function(t, e) { + if (t = a(t), + e = l(e), + u) + try { + return h(t, e) + } catch (t) {} + if (c(t, e)) + return s(!o(r.f, t, e), t[e]) + } + } + , function(t, e) { + var n = "object" == typeof document && document.all; + t.exports = { + all: n, + IS_HTMLDDA: void 0 === n && void 0 !== n + } + } + , function(t, e, n) { + var i = n(14) + , o = n(2) + , r = n(25) + , n = n(41) + , s = Object; + t.exports = n ? function(t) { + return "symbol" == typeof t + } + : function(t) { + var e = i("Symbol"); + return o(e) && r(e.prototype, s(t)) + } + } + , function(t, e, n) { + n = n(42), + t.exports = n && !Symbol.sham && "symbol" == typeof Symbol.iterator + } + , function(t, e, n) { + var i = n(43) + , n = n(0); + t.exports = !!Object.getOwnPropertySymbols && !n(function() { + var t = Symbol(); + return !String(t) || !(Object(t)instanceof Symbol) || !Symbol.sham && i && i < 41 + }) + } + , function(t, e, n) { + var i, o, r = n(3), n = n(16), s = r.process, r = r.Deno; + !(o = (r = (s = s && s.versions || r && r.version) && s.v8) ? 0 < (i = r.split("."))[0] && i[0] < 4 ? 1 : +(i[0] + i[1]) : o) && n && (!(i = n.match(/Edge\/(\d+)/)) || 74 <= i[1]) && (i = n.match(/Chrome\/(\d+)/)) && (o = +i[1]), + t.exports = o + } + , function(t, e, n) { + var i = n(45) + , o = n(23); + t.exports = function(t, e) { + return t = t[e], + o(t) ? void 0 : i(t) + } + } + , function(t, e, n) { + var i = n(2) + , o = n(46) + , r = TypeError; + t.exports = function(t) { + if (i(t)) + return t; + throw r(o(t) + " is not a function") + } + } + , function(t, e) { + var n = String; + t.exports = function(t) { + try { + return n(t) + } catch (t) { + return "Object" + } + } + } + , function(t, e, n) { + var n = n(1) + , i = 0 + , o = Math.random() + , r = n(1..toString); + t.exports = function(t) { + return "Symbol(" + (void 0 === t ? "" : t) + ")_" + r(++i + o, 36) + } + } + , function(t, e, n) { + var i = n(4) + , o = n(0) + , r = n(49); + t.exports = !i && !o(function() { + return 7 != Object.defineProperty(r("div"), "a", { + get: function() { + return 7 + } + }).a + }) + } + , function(t, e, n) { + var i = n(3) + , n = n(9) + , o = i.document + , r = n(o) && n(o.createElement); + t.exports = function(t) { + return r ? o.createElement(t) : {} + } + } + , function(t, e, n) { + var i = n(4) + , n = n(0); + t.exports = i && n(function() { + return 42 != Object.defineProperty(function() {}, "prototype", { + value: 42, + writable: !1 + }).prototype + }) + } + , function(t, e, n) { + var i = n(4) + , n = n(5) + , o = Function.prototype + , r = i && Object.getOwnPropertyDescriptor + , s = (n = n(o, "name")) && "something" === function() {} + .name + , i = n && (!i || r(o, "name").configurable); + t.exports = { + EXISTS: n, + PROPER: s, + CONFIGURABLE: i + } + } + , function(t, e, n) { + var i = n(26) + , o = n(47) + , r = i("keys"); + t.exports = function(t) { + return r[t] || (r[t] = o(t)) + } + } + , function(t, e, n) { + var i = n(54) + , o = n(34).concat("length", "prototype"); + e.f = Object.getOwnPropertyNames || function(t) { + return i(t, o) + } + } + , function(t, e, n) { + var i = n(1) + , s = n(5) + , a = n(15) + , l = n(80).indexOf + , c = n(32) + , u = i([].push); + t.exports = function(t, e) { + var n, i = a(t), o = 0, r = []; + for (n in i) + !s(c, n) && s(i, n) && u(r, n); + for (; e.length > o; ) + s(i, n = e[o++]) && !~l(r, n) && u(r, n); + return r + } + } + , function(t, e, n) { + var i = n(18) + , o = Math.max + , r = Math.min; + t.exports = function(t, e) { + return (t = i(t)) < 0 ? o(t + e, 0) : r(t, e) + } + } + , function(t, e, n) { + var i = n(18) + , o = Math.min; + t.exports = function(t) { + return 0 < t ? o(i(t), 9007199254740991) : 0 + } + } + , function(t, e, n) { + function i(t, e) { + return (t = l[a(t)]) == u || t != c && (r(e) ? o(e) : !!e) + } + var o = n(0) + , r = n(2) + , s = /#|\.prototype\./ + , a = i.normalize = function(t) { + return String(t).replace(s, ".").toLowerCase() + } + , l = i.data = {} + , c = i.NATIVE = "N" + , u = i.POLYFILL = "P"; + t.exports = i + } + , function(t, e, n) { + var i = n(7); + t.exports = function() { + var t = i(this) + , e = ""; + return t.hasIndices && (e += "d"), + t.global && (e += "g"), + t.ignoreCase && (e += "i"), + t.multiline && (e += "m"), + t.dotAll && (e += "s"), + t.unicode && (e += "u"), + t.unicodeSets && (e += "v"), + t.sticky && (e += "y"), + e + } + } + , function(t, e, n) { + var i = n(0) + , o = n(3).RegExp + , r = (n = i(function() { + var t = o("a", "y"); + return t.lastIndex = 2, + null != t.exec("abcd") + })) || i(function() { + return !o("a", "y").sticky + }) + , i = n || i(function() { + var t = o("^r", "gy"); + return t.lastIndex = 2, + null != t.exec("str") + }); + t.exports = { + BROKEN_CARET: i, + MISSED_STICKY: r, + UNSUPPORTED_Y: n + } + } + , function(t, e, n) { + var i = n(0) + , o = n(3).RegExp; + t.exports = i(function() { + var t = o(".", "s"); + return !(t.dotAll && t.exec("\n") && "s" === t.flags) + }) + } + , function(t, e, n) { + var i = n(0) + , o = n(3).RegExp; + t.exports = i(function() { + var t = o("(?b)", "g"); + return "b" !== t.exec("b").groups.a || "bc" !== "b".replace(t, "$c") + }) + } + , function(t, e) { + t.exports = "\t\n\v\f\r                 \u2028\u2029\ufeff" + } + , , , , , , function(t, e, Z) { + Z.r(e), + function(t, e) { + Z(37), + Z(89), + Z(97), + Z(105), + Z(108); + var a, D, T, o, s, N, H, n, l, i, r, c, u, B, h, d, p, f, g, m, b, W, Y, F, v, X, z, _, y, w, O, x, S, C = "undefined" != typeof window ? window : "undefined" != typeof WorkerGlobalScope && self instanceof WorkerGlobalScope ? self : {}, E = (a = /\blang(?:uage)?-([\w-]+)\b/i, + D = 0, + T = C.Prism = { + manual: C.Prism && C.Prism.manual, + disableWorkerMessageHandler: C.Prism && C.Prism.disableWorkerMessageHandler, + util: { + encode: function(t) { + return t instanceof o ? new o(t.type,T.util.encode(t.content),t.alias) : "Array" === T.util.type(t) ? t.map(T.util.encode) : t.replace(/&/g, "&").replace(/ t.length) + return; + if (!(y instanceof l)) { + if (f && v != e.length - 1) { + if (b.lastIndex = _, + !(E = b.exec(t))) + break; + for (var w = E.index + (p ? E[1].length : 0), O = E.index + E[0].length, x = v, S = _, C = e.length; x < C && (S < O || !e[x].type && !e[x - 1].greedy); ++x) + (S += e[x].length) <= w && (++v, + _ = S); + if (e[v]instanceof l) + continue; + k = x - v, + y = t.slice(_, S), + E.index -= _ + } else { + b.lastIndex = 0; + var E = b.exec(y) + , k = 1 + } + if (E) { + p && (g = E[1] ? E[1].length : 0); + var O = (w = E.index + g) + (E = E[0].slice(g)).length + , A = y.slice(0, w) + , y = y.slice(O) + , j = [v, k] + , A = (A && (++v, + _ += A.length, + j.push(A)), + new l(a,d ? T.tokenize(E, d) : E,m,E,f)); + if (j.push(A), + y && j.push(y), + Array.prototype.splice.apply(e, j), + 1 != k && T.matchGrammar(t, e, n, v, _, !0, a), + r) + break + } else if (r) + break + } + } + } + } + }, + tokenize: function(t, e, n) { + var i = [t] + , o = e.rest; + if (o) { + for (var r in o) + e[r] = o[r]; + delete e.rest + } + return T.matchGrammar(t, i, e, 0, 0, !1), + i + }, + hooks: { + all: {}, + add: function(t, e) { + var n = T.hooks.all; + n[t] = n[t] || [], + n[t].push(e) + }, + run: function(t, e) { + var n = T.hooks.all[t]; + if (n && n.length) + for (var i, o = 0; i = n[o++]; ) + i(e) + } + } + }, + (o = T.Token = function(t, e, n, i, o) { + this.type = t, + this.content = e, + this.alias = n, + this.length = 0 | (i || "").length, + this.greedy = !!o + } + ).stringify = function(e, n, t) { + var i; + return "string" == typeof e ? e : "Array" === T.util.type(e) ? e.map(function(t) { + return o.stringify(t, n, e) + }).join("") : (i = { + type: e.type, + content: o.stringify(e.content, n, t), + tag: "span", + classes: ["token", e.type], + attributes: {}, + language: n, + parent: t + }, + e.alias && (t = "Array" === T.util.type(e.alias) ? e.alias : [e.alias], + Array.prototype.push.apply(i.classes, t)), + T.hooks.run("wrap", i), + t = Object.keys(i.attributes).map(function(t) { + return t + '="' + (i.attributes[t] || "").replace(/"/g, """) + '"' + }).join(" "), + "<" + i.tag + ' class="' + i.classes.join(" ") + '"' + (t ? " " + t : "") + ">" + i.content + "") + } + , + C.document ? (_ = document.currentScript || [].slice.call(document.getElementsByTagName("script")).pop()) && (T.filename = _.src, + T.manual || _.hasAttribute("data-manual") || ("loading" !== document.readyState ? window.requestAnimationFrame ? window.requestAnimationFrame(T.highlightAll) : window.setTimeout(T.highlightAll, 16) : document.addEventListener("DOMContentLoaded", T.highlightAll))) : C.addEventListener && !T.disableWorkerMessageHandler && C.addEventListener("message", function(t) { + var e = (t = JSON.parse(t.data)).language + , n = t.code + , t = t.immediateClose; + C.postMessage(T.highlight(n, T.languages[e], e)), + t && C.close() + }, !1), + C.Prism); + function k(t, e) { + return t = t.replace(//g, function() { + return N + }).replace(//g, function() { + return H + }).replace(//g, function() { + return n + }), + RegExp(t, e) + } + function A(t, n) { + return t.replace(/<<(\d+)>>/g, function(t, e) { + return "(?:" + n[+e] + ")" + }) + } + function j(t, e, n) { + return RegExp(A(t, e), n || "") + } + function L(t, e) { + for (var n = 0; n < e; n++) + t = t.replace(/<>/g, function() { + return "(?:" + t + ")" + }); + return t.replace(/<>/g, "[^\\s\\S]") + } + function P(t) { + return "\\b(?:" + t.trim().replace(/ /g, "|") + ")\\b" + } + function U(t, e) { + return { + interpolation: { + pattern: j(/((?:^|[^{])(?:\{\{)*)<<0>>/.source, [t]), + lookbehind: !0, + inside: { + "format-string": { + pattern: j(/(^\{(?:(?![}:])<<0>>)*)<<1>>(?=\}$)/.source, [e, h]), + lookbehind: !0, + inside: { + punctuation: /^:/ + } + }, + punctuation: /^\{|\}$/, + expression: { + pattern: /[\s\S]+/, + alias: "language-csharp", + inside: i.languages.csharp + } + } + }, + string: /[\s\S]+/ + } + } + if (t.exports && (t.exports = E), + void 0 !== e && (e.Prism = E), + E.languages.markup = { + comment: //, + prolog: /<\?[\s\S]+?\?>/, + doctype: //i, + cdata: //i, + tag: { + pattern: /<\/?(?!\d)[^\s>\/=$<%]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+))?)*\s*\/?>/i, + greedy: !0, + inside: { + tag: { + pattern: /^<\/?[^\s>\/]+/i, + inside: { + punctuation: /^<\/?/, + namespace: /^[^\s>\/:]+:/ + } + }, + "special-attr": [], + "attr-value": { + pattern: /=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+)/i, + inside: { + punctuation: [/^=/, { + pattern: /(^|[^\\])["']/, + lookbehind: !0 + }] + } + }, + punctuation: /\/?>/, + "attr-name": { + pattern: /[^\s>\/]+/, + inside: { + namespace: /^[^\s>\/:]+:/ + } + } + } + }, + entity: /&#?[\da-z]{1,8};/i + }, + E.languages.markup.tag.inside["attr-value"].inside.entity = E.languages.markup.entity, + E.hooks.add("wrap", function(t) { + "entity" === t.type && (t.attributes.title = t.content.replace(/&/, "&")) + }), + E.languages.xml = E.languages.markup, + E.languages.html = E.languages.markup, + E.languages.mathml = E.languages.markup, + E.languages.svg = E.languages.markup, + E.languages.css = { + comment: /\/\*[\s\S]*?\*\//, + atrule: { + pattern: /@[\w-]+?.*?(?:;|(?=\s*\{))/i, + inside: { + rule: /@[\w-]+/ + } + }, + url: /url\((?:(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1|.*?)\)/i, + selector: /[^{}\s][^{};]*?(?=\s*\{)/, + string: { + pattern: /("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/, + greedy: !0 + }, + property: /[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i, + important: /\B!important\b/i, + function: /[-a-z0-9]+(?=\()/i, + punctuation: /[(){};:]/ + }, + E.languages.css.atrule.inside.rest = E.languages.css, + E.languages.markup && (E.languages.insertBefore("markup", "tag", { + style: { + pattern: /()[\s\S]*?(?=<\/style>)/i, + lookbehind: !0, + inside: E.languages.css, + alias: "language-css", + greedy: !0 + } + }), + E.languages.insertBefore("inside", "attr-value", { + "style-attr": { + pattern: /\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i, + inside: { + "attr-name": { + pattern: /^\s*style/i, + inside: E.languages.markup.tag.inside + }, + punctuation: /^\s*=\s*['"]|['"]\s*$/, + "attr-value": { + pattern: /.+/i, + inside: E.languages.css + } + }, + alias: "language-css" + } + }, E.languages.markup.tag)), + E.languages.clike = { + comment: [{ + pattern: /(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/, + lookbehind: !0 + }, { + pattern: /(^|[^\\:])\/\/.*/, + lookbehind: !0, + greedy: !0 + }], + string: { + pattern: /(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/, + greedy: !0 + }, + "class-name": { + pattern: /((?:\b(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[\w.\\]+/i, + lookbehind: !0, + inside: { + punctuation: /[.\\]/ + } + }, + keyword: /\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/, + boolean: /\b(?:true|false)\b/, + function: /[a-z0-9_]+(?=\()/i, + number: /\b0x[\da-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?/i, + operator: /--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/, + punctuation: /[{}[\];(),.:]/ + }, + E.languages.javascript = E.languages.extend("clike", { + "class-name": [E.languages.clike["class-name"], { + pattern: /(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/, + lookbehind: !0 + }], + keyword: /\b(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|var|void|while|with|yield)\b/, + number: /\b(?:0[xX][\dA-Fa-f]+|0[bB][01]+|0[oO][0-7]+|NaN|Infinity)\b|(?:\b\d+\.?\d*|\B\.\d+)(?:[Ee][+-]?\d+)?/, + function: /[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*\()/i, + operator: /-[-=]?|\+[+=]?|!=?=?|<>?>?=?|=(?:==?|>)?|&[&=]?|\|[|=]?|\*\*?=?|\/=?|~|\^=?|%=?|\?|\.{3}/ + }), + E.languages.javascript["class-name"][0].pattern = /(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/, + E.languages.insertBefore("javascript", "keyword", { + regex: { + pattern: /((?:^|[^$\w\xA0-\uFFFF."'\])\s])\s*)\/(\[[^\]\r\n]+]|\\.|[^/\\\[\r\n])+\/[gimyu]{0,5}(?=\s*($|[\r\n,.;})\]]))/, + lookbehind: !0, + greedy: !0, + inside: { + "regex-source": { + pattern: /^(\/)[\s\S]+(?=\/[a-z]*$)/, + lookbehind: !0, + alias: "language-regex", + inside: E.languages.regex + }, + "regex-delimiter": /^\/|\/$/, + "regex-flags": /^[a-z]+$/ + } + }, + "function-variable": { + pattern: /[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*=\s*(?:function\b|(?:\([^()]*\)|[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)\s*=>))/i, + alias: "function" + }, + constant: /\b[A-Z][A-Z\d_]*\b/ + }), + E.languages.insertBefore("javascript", "string", { + hashbang: { + pattern: /^#!.*/, + greedy: !0, + alias: "comment" + }, + "string-property": { + pattern: /((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m, + lookbehind: !0, + greedy: !0, + alias: "property" + }, + "template-string": { + pattern: /`(?:\\[\s\S]|\${[^}]+}|[^\\`])*`/, + greedy: !0, + inside: { + interpolation: { + pattern: /\${[^}]+}/, + inside: { + "interpolation-punctuation": { + pattern: /^\${|}$/, + alias: "punctuation" + }, + rest: null + } + }, + string: /[\s\S]+/ + } + } + }), + E.languages.insertBefore("javascript", "operator", { + "literal-property": { + pattern: /((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m, + lookbehind: !0, + alias: "property" + } + }), + E.languages.javascript["template-string"].inside.interpolation.inside.rest = E.languages.javascript, + Object.defineProperty(E.languages.markup.tag, "addInlined", { + value: function(t, e) { + var n = {}; + n["language-" + e] = { + pattern: /(^$)/i, + lookbehind: !0, + inside: E.languages[e] + }, + n.cdata = /^$/i, + (n = { + "included-cdata": { + pattern: //i, + inside: n + } + })["language-" + e] = { + pattern: /[\s\S]+/, + inside: E.languages[e] + }, + (e = {})[t] = { + pattern: RegExp(/(<__[^>]*>)(?:))*\]\]>|(?!)/.source.replace(/__/g, function() { + return t + }), "i"), + lookbehind: !0, + greedy: !0, + inside: n + }, + E.languages.insertBefore("markup", "cdata", e) + } + }), + Object.defineProperty(E.languages.markup.tag, "addAttribute", { + value: function(t, e) { + E.languages.markup.tag.inside["special-attr"].push({ + pattern: RegExp(/(^|["'\s])/.source + "(?:" + t + ")" + /\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))/.source, "i"), + lookbehind: !0, + inside: { + "attr-name": /^[^\s=]+/, + "attr-value": { + pattern: /=[\s\S]+/, + inside: { + value: { + pattern: /(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/, + lookbehind: !0, + alias: [e, "language-" + e], + inside: E.languages[e] + }, + punctuation: [{ + pattern: /^=/, + alias: "attr-equals" + }, /"|'/] + } + } + } + }) + } + }), + E.languages.markup && (E.languages.insertBefore("markup", "tag", { + script: { + pattern: /()[\s\S]*?(?=<\/script>)/i, + lookbehind: !0, + inside: E.languages.javascript, + alias: "language-javascript", + greedy: !0 + } + }), + E.languages.markup.tag.addInlined("script", "javascript"), + E.languages.markup.tag.addAttribute(/on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)/.source, "javascript")), + E.languages.js = E.languages.javascript, + E.languages["markup-templating"] = {}, + Object.defineProperties(E.languages["markup-templating"], { + buildPlaceholders: { + value: function(n, i, t, o) { + n.language === i && (n.tokenStack = [], + n.code = n.code.replace(t, function(t) { + if ("function" == typeof o && !o(t)) + return t; + for (var e = n.tokenStack.length; -1 !== n.code.indexOf("___" + i.toUpperCase() + e + "___"); ) + ++e; + return n.tokenStack[e] = t, + "___" + i.toUpperCase() + e + "___" + }), + n.grammar = E.languages.markup) + } + }, + tokenizePlaceholders: { + value: function(c, u) { + var h, d, p; + c.language === u && c.tokenStack && (c.grammar = E.languages[u], + h = 0, + d = Object.keys(c.tokenStack), + (p = function(t) { + if (!(h >= d.length)) + for (var e = 0; e < t.length; e++) { + var n = t[e]; + if ("string" == typeof n || n.content && "string" == typeof n.content) { + var i = d[h] + , o = c.tokenStack[i] + , r = (l = "string" == typeof n ? n : n.content).indexOf("___" + u.toUpperCase() + i + "___"); + if (-1 < r) { + ++h; + var s, a = l.substring(0, r), o = new E.Token(u,E.tokenize(o, c.grammar, u),"language-" + u,o), l = l.substring(r + ("___" + u.toUpperCase() + i + "___").length); + if (a || l ? (s = [a, o, l].filter(function(t) { + return !!t + }), + p(s)) : s = o, + "string" == typeof n ? Array.prototype.splice.apply(t, [e, 1].concat(s)) : n.content = s, + h >= d.length) + break + } + } else + n.content && "string" != typeof n.content && p(n.content) + } + } + )(c.tokens)) + } + } + }), + E.languages.json = { + property: /"(?:\\.|[^\\"\r\n])*"(?=\s*:)/i, + string: { + pattern: /"(?:\\.|[^\\"\r\n])*"(?!\s*:)/, + greedy: !0 + }, + number: /\b0x[\dA-Fa-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:[Ee][+-]?\d+)?/, + punctuation: /[{}[\]);,]/, + operator: /:/g, + boolean: /\b(?:true|false)\b/i, + null: /\bnull\b/i + }, + E.languages.jsonp = E.languages.json, + _ = (s = E).util.clone(s.languages.javascript), + N = /(?:\s|\/\/.*(?!.)|\/\*(?:[^*]|\*(?!\/))\*\/)/.source, + H = /(?:\{(?:\{(?:\{[^{}]*\}|[^{}])*\}|[^{}])*\})/.source, + n = k(n = /(?:\{*\.{3}(?:[^{}]|)*\})/.source).source, + s.languages.jsx = s.languages.extend("markup", _), + s.languages.jsx.tag.pattern = k(/<\/?(?:[\w.:-]+(?:+(?:[\w.:$-]+(?:=(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s{'"/>=]+|))?|))**\/?)?>/.source), + s.languages.jsx.tag.inside.tag.pattern = /^<\/?[^\s>\/]*/, + s.languages.jsx.tag.inside["attr-value"].pattern = /=(?!\{)(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s'">]+)/, + s.languages.jsx.tag.inside.tag.inside["class-name"] = /^[A-Z]\w*(?:\.[A-Z]\w*)*$/, + s.languages.jsx.tag.inside.comment = _.comment, + s.languages.insertBefore("inside", "attr-name", { + spread: { + pattern: k(//.source), + inside: s.languages.jsx + } + }, s.languages.jsx.tag), + s.languages.insertBefore("inside", "special-attr", { + script: { + pattern: k(/=/.source), + alias: "language-javascript", + inside: { + "script-punctuation": { + pattern: /^=(?=\{)/, + alias: "punctuation" + }, + rest: s.languages.jsx + } + } + }, s.languages.jsx.tag), + l = function(t) { + return t ? "string" == typeof t ? t : "string" == typeof t.content ? t.content : t.content.map(l).join("") : "" + } + , + s.hooks.add("after-tokenize", function(t) { + "jsx" !== t.language && "tsx" !== t.language || function t(e) { + for (var n = [], i = 0; i < e.length; i++) { + var o = e[i] + , r = !1; + "string" != typeof o && ("tag" === o.type && o.content[0] && "tag" === o.content[0].type ? "" !== o.content[o.content.length - 1].content && n.push({ + tagName: l(o.content[0].content[1]), + openedBraces: 0 + }) : 0 < n.length && "punctuation" === o.type && "{" === o.content ? n[n.length - 1].openedBraces++ : 0 < n.length && 0 < n[n.length - 1].openedBraces && "punctuation" === o.type && "}" === o.content ? n[n.length - 1].openedBraces-- : r = !0), + (r || "string" == typeof o) && 0 < n.length && 0 === n[n.length - 1].openedBraces && (r = l(o), + i < e.length - 1 && ("string" == typeof e[i + 1] || "plain-text" === e[i + 1].type) && (r += l(e[i + 1]), + e.splice(i + 1, 1)), + 0 < i && ("string" == typeof e[i - 1] || "plain-text" === e[i - 1].type) && (r = l(e[i - 1]) + r, + e.splice(i - 1, 1), + i--), + e[i] = new s.Token("plain-text",r,null,r)), + o.content && "string" != typeof o.content && t(o.content) + } + }(t.tokens) + }), + i = E, + e = "bool byte char decimal double dynamic float int long object sbyte short string uint ulong ushort var void", + _ = "add alias and ascending async await by descending from(?=\\s*(?:\\w|$)) get global group into init(?=\\s*;) join let nameof not notnull on or orderby partial remove select set unmanaged value when where with(?=\\s*{)", + S = "abstract as base break case catch checked const continue default delegate do else event explicit extern finally fixed for foreach goto if implicit in internal is lock namespace new null operator out override params private protected public readonly ref return sealed sizeof stackalloc static switch this throw try typeof unchecked unsafe using virtual volatile while yield", + g = P(b = "class enum interface record struct"), + r = RegExp(P(e + " " + b + " " + _ + " " + S)), + _ = P(b + " " + _ + " " + S), + e = P(e + " " + b + " " + S), + b = L(/<(?:[^<>;=+\-*/%&|^]|<>)*>/.source, 2), + S = L(/\((?:[^()]|<>)*\)/.source, 2), + c = A(/<<0>>(?:\s*<<1>>)?/.source, [f = /@?\b[A-Za-z_]\w*\b/.source, b]), + _ = A(/(?!<<0>>)<<1>>(?:\s*\.\s*<<1>>)*/.source, [_, c]), + x = A(/<<0>>(?:\s*(?:\?\s*)?<<1>>)*(?:\s*\?)?/.source, [_, d = /\[\s*(?:,\s*)*\]/.source]), + u = A(/[^,()<>[\];=+\-*/%&|^]|<<0>>|<<1>>|<<2>>/.source, [b, S, d]), + u = A(/\(<<0>>+(?:,<<0>>+)+\)/.source, [u]), + u = A(/(?:<<0>>|<<1>>)(?:\s*(?:\?\s*)?<<2>>)*(?:\s*\?)?/.source, [u, _, d]), + d = { + keyword: r, + punctuation: /[<>()?,.:[\]]/ + }, + B = /'(?:[^\r\n'\\]|\\.|\\[Uux][\da-fA-F]{1,8})'/.source, + p = /"(?:\\.|[^\\"\r\n])*"/.source, + i.languages.csharp = i.languages.extend("clike", { + string: [{ + pattern: j(/(^|[^$\\])<<0>>/.source, [/@"(?:""|\\[\s\S]|[^\\"])*"(?!")/.source]), + lookbehind: !0, + greedy: !0 + }, { + pattern: j(/(^|[^@$\\])<<0>>/.source, [p]), + lookbehind: !0, + greedy: !0 + }], + "class-name": [{ + pattern: j(/(\busing\s+static\s+)<<0>>(?=\s*;)/.source, [_]), + lookbehind: !0, + inside: d + }, { + pattern: j(/(\busing\s+<<0>>\s*=\s*)<<1>>(?=\s*;)/.source, [f, u]), + lookbehind: !0, + inside: d + }, { + pattern: j(/(\busing\s+)<<0>>(?=\s*=)/.source, [f]), + lookbehind: !0 + }, { + pattern: j(/(\b<<0>>\s+)<<1>>/.source, [g, c]), + lookbehind: !0, + inside: d + }, { + pattern: j(/(\bcatch\s*\(\s*)<<0>>/.source, [_]), + lookbehind: !0, + inside: d + }, { + pattern: j(/(\bwhere\s+)<<0>>/.source, [f]), + lookbehind: !0 + }, { + pattern: j(/(\b(?:is(?:\s+not)?|as)\s+)<<0>>/.source, [x]), + lookbehind: !0, + inside: d + }, { + pattern: j(/\b<<0>>(?=\s+(?!<<1>>|with\s*\{)<<2>>(?:\s*[=,;:{)\]]|\s+(?:in|when)\b))/.source, [u, e, f]), + inside: d + }], + keyword: r, + number: /(?:\b0(?:x[\da-f_]*[\da-f]|b[01_]*[01])|(?:\B\.\d+(?:_+\d+)*|\b\d+(?:_+\d+)*(?:\.\d+(?:_+\d+)*)?)(?:e[-+]?\d+(?:_+\d+)*)?)(?:[dflmu]|lu|ul)?\b/i, + operator: />>=?|<<=?|[-=]>|([-+&|])\1|~|\?\?=?|[-+*/%&|^!=<>]=?/, + punctuation: /\?\.?|::|[{}[\];(),.:]/ + }), + i.languages.insertBefore("csharp", "number", { + range: { + pattern: /\.\./, + alias: "operator" + } + }), + i.languages.insertBefore("csharp", "punctuation", { + "named-parameter": { + pattern: j(/([(,]\s*)<<0>>(?=\s*:)/.source, [f]), + lookbehind: !0, + alias: "punctuation" + } + }), + i.languages.insertBefore("csharp", "class-name", { + namespace: { + pattern: j(/(\b(?:namespace|using)\s+)<<0>>(?:\s*\.\s*<<0>>)*(?=\s*[;{])/.source, [f]), + lookbehind: !0, + inside: { + punctuation: /\./ + } + }, + "type-expression": { + pattern: j(/(\b(?:default|sizeof|typeof)\s*\(\s*(?!\s))(?:[^()\s]|\s(?!\s)|<<0>>)*(?=\s*\))/.source, [S]), + lookbehind: !0, + alias: "class-name", + inside: d + }, + "return-type": { + pattern: j(/<<0>>(?=\s+(?:<<1>>\s*(?:=>|[({]|\.\s*this\s*\[)|this\s*\[))/.source, [u, _]), + inside: d, + alias: "class-name" + }, + "constructor-invocation": { + pattern: j(/(\bnew\s+)<<0>>(?=\s*[[({])/.source, [u]), + lookbehind: !0, + inside: d, + alias: "class-name" + }, + "generic-method": { + pattern: j(/<<0>>\s*<<1>>(?=\s*\()/.source, [f, b]), + inside: { + function: j(/^<<0>>/.source, [f]), + generic: { + pattern: RegExp(b), + alias: "class-name", + inside: d + } + } + }, + "type-list": { + pattern: j(/\b((?:<<0>>\s+<<1>>|record\s+<<1>>\s*<<5>>|where\s+<<2>>)\s*:\s*)(?:<<3>>|<<4>>|<<1>>\s*<<5>>|<<6>>)(?:\s*,\s*(?:<<3>>|<<4>>|<<6>>))*(?=\s*(?:where|[{;]|=>|$))/.source, [g, c, f, u, r.source, S, /\bnew\s*\(\s*\)/.source]), + lookbehind: !0, + inside: { + "record-arguments": { + pattern: j(/(^(?!new\s*\()<<0>>\s*)<<1>>/.source, [c, S]), + lookbehind: !0, + greedy: !0, + inside: i.languages.csharp + }, + keyword: r, + "class-name": { + pattern: RegExp(u), + greedy: !0, + inside: d + }, + punctuation: /[,()]/ + } + }, + preprocessor: { + pattern: /(^[\t ]*)#.*/m, + lookbehind: !0, + alias: "property", + inside: { + directive: { + pattern: /(#)\b(?:define|elif|else|endif|endregion|error|if|line|nullable|pragma|region|undef|warning)\b/, + lookbehind: !0, + alias: "keyword" + } + } + } + }), + e = A(/\/(?![*/])|\/\/[^\r\n]*[\r\n]|\/\*(?:[^*]|\*(?!\/))*\*\/|<<0>>/.source, [x = p + "|" + B]), + b = L(A(/[^"'/()]|<<0>>|\(<>*\)/.source, [e]), 2), + g = /\b(?:assembly|event|field|method|module|param|property|return|type)\b/.source, + f = A(/<<0>>(?:\s*\(<<1>>*\))?/.source, [_, b]), + i.languages.insertBefore("csharp", "class-name", { + attribute: { + pattern: j(/((?:^|[^\s\w>)?])\s*\[\s*)(?:<<0>>\s*:\s*)?<<1>>(?:\s*,\s*<<1>>)*(?=\s*\])/.source, [g, f]), + lookbehind: !0, + greedy: !0, + inside: { + target: { + pattern: j(/^<<0>>(?=\s*:)/.source, [g]), + alias: "keyword" + }, + "attribute-arguments": { + pattern: j(/\(<<0>>*\)/.source, [b]), + inside: i.languages.csharp + }, + "class-name": { + pattern: RegExp(_), + inside: { + punctuation: /\./ + } + }, + punctuation: /[:,]/ + } + } + }), + h = /:[^}\r\n]+/.source, + c = L(A(/[^"'/()]|<<0>>|\(<>*\)/.source, [e]), 2), + S = A(/\{(?!\{)(?:(?![}:])<<0>>)*<<1>>?\}/.source, [c, h]), + r = L(A(/[^"'/()]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|<<0>>|\(<>*\)/.source, [x]), 2), + u = A(/\{(?!\{)(?:(?![}:])<<0>>)*<<1>>?\}/.source, [r, h]), + i.languages.insertBefore("csharp", "string", { + "interpolation-string": [{ + pattern: j(/(^|[^\\])(?:\$@|@\$)"(?:""|\\[\s\S]|\{\{|<<0>>|[^\\{"])*"/.source, [S]), + lookbehind: !0, + greedy: !0, + inside: U(S, c) + }, { + pattern: j(/(^|[^@\\])\$"(?:\\.|\{\{|<<0>>|[^\\"{])*"/.source, [u]), + lookbehind: !0, + greedy: !0, + inside: U(u, r) + }], + char: { + pattern: RegExp(B), + greedy: !0 + } + }), + i.languages.dotnet = i.languages.cs = i.languages.csharp, + E.languages.aspnet = E.languages.extend("markup", { + "page-directive": { + pattern: /<%\s*@.*%>/, + alias: "tag", + inside: { + "page-directive": { + pattern: /<%\s*@\s*(?:Assembly|Control|Implements|Import|Master(?:Type)?|OutputCache|Page|PreviousPageType|Reference|Register)?|%>/i, + alias: "tag" + }, + rest: E.languages.markup.tag.inside + } + }, + directive: { + pattern: /<%.*%>/, + alias: "tag", + inside: { + directive: { + pattern: /<%\s*?[$=%#:]{0,2}|%>/, + alias: "tag" + }, + rest: E.languages.csharp + } + } + }), + E.languages.aspnet.tag.pattern = /<(?!%)\/?[^\s>\/]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+))?)*\s*\/?>/, + E.languages.insertBefore("inside", "punctuation", { + directive: E.languages.aspnet.directive + }, E.languages.aspnet.tag.inside["attr-value"]), + E.languages.insertBefore("aspnet", "comment", { + "asp-comment": { + pattern: /<%--[\s\S]*?--%>/, + alias: ["asp", "comment"] + } + }), + E.languages.insertBefore("aspnet", E.languages.javascript ? "script" : "tag", { + "asp-script": { + pattern: /(]*>)[\s\S]*?(?=<\/script>)/i, + lookbehind: !0, + alias: ["asp", "script"], + inside: E.languages.csharp || {} + } + }), + E.languages.python = { + comment: { + pattern: /(^|[^\\])#.*/, + lookbehind: !0, + greedy: !0 + }, + "string-interpolation": { + pattern: /(?:f|fr|rf)(?:("""|''')[\s\S]*?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i, + greedy: !0, + inside: { + interpolation: { + pattern: /((?:^|[^{])(?:\{\{)*)\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}])+\})+\})+\}/, + lookbehind: !0, + inside: { + "format-spec": { + pattern: /(:)[^:(){}]+(?=\}$)/, + lookbehind: !0 + }, + "conversion-option": { + pattern: /![sra](?=[:}]$)/, + alias: "punctuation" + }, + rest: null + } + }, + string: /[\s\S]+/ + } + }, + "triple-quoted-string": { + pattern: /(?:[rub]|br|rb)?("""|''')[\s\S]*?\1/i, + greedy: !0, + alias: "string" + }, + string: { + pattern: /(?:[rub]|br|rb)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i, + greedy: !0 + }, + function: { + pattern: /((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g, + lookbehind: !0 + }, + "class-name": { + pattern: /(\bclass\s+)\w+/i, + lookbehind: !0 + }, + decorator: { + pattern: /(^[\t ]*)@\w+(?:\.\w+)*/m, + lookbehind: !0, + alias: ["annotation", "punctuation"], + inside: { + punctuation: /\./ + } + }, + keyword: /\b(?:_(?=\s*:)|and|as|assert|async|await|break|case|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|match|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/, + builtin: /\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/, + boolean: /\b(?:False|None|True)\b/, + number: /\b0(?:b(?:_?[01])+|o(?:_?[0-7])+|x(?:_?[a-f0-9])+)\b|(?:\b\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\B\.\d+(?:_\d+)*)(?:e[+-]?\d+(?:_\d+)*)?j?(?!\w)/i, + operator: /[-+%=]=?|!=|:=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/, + punctuation: /[{}[\];(),.:]/ + }, + E.languages.python["string-interpolation"].inside.interpolation.inside.rest = E.languages.python, + E.languages.py = E.languages.python, + (d = E).languages.ruby = d.languages.extend("clike", { + comment: { + pattern: /#.*|^=begin\s[\s\S]*?^=end/m, + greedy: !0 + }, + "class-name": { + pattern: /(\b(?:class|module)\s+|\bcatch\s+\()[\w.\\]+|\b[A-Z_]\w*(?=\s*\.\s*new\b)/, + lookbehind: !0, + inside: { + punctuation: /[.\\]/ + } + }, + keyword: /\b(?:BEGIN|END|alias|and|begin|break|case|class|def|define_method|defined|do|each|else|elsif|end|ensure|extend|for|if|in|include|module|new|next|nil|not|or|prepend|private|protected|public|raise|redo|require|rescue|retry|return|self|super|then|throw|undef|unless|until|when|while|yield)\b/, + operator: /\.{2,3}|&\.|===||[!=]?~|(?:&&|\|\||<<|>>|\*\*|[+\-*/%<>!^&|=])=?|[?:]/, + punctuation: /[(){}[\].,;]/ + }), + d.languages.insertBefore("ruby", "operator", { + "double-colon": { + pattern: /::/, + alias: "punctuation" + } + }), + p = { + pattern: /((?:^|[^\\])(?:\\{2})*)#\{(?:[^{}]|\{[^{}]*\})*\}/, + lookbehind: !0, + inside: { + content: { + pattern: /^(#\{)[\s\S]+(?=\}$)/, + lookbehind: !0, + inside: d.languages.ruby + }, + delimiter: { + pattern: /^#\{|\}$/, + alias: "punctuation" + } + } + }, + delete d.languages.ruby.function, + f = "(?:" + [/([^a-zA-Z0-9\s{(\[<=])(?:(?!\1)[^\\]|\\[\s\S])*\1/.source, /\((?:[^()\\]|\\[\s\S]|\((?:[^()\\]|\\[\s\S])*\))*\)/.source, /\{(?:[^{}\\]|\\[\s\S]|\{(?:[^{}\\]|\\[\s\S])*\})*\}/.source, /\[(?:[^\[\]\\]|\\[\s\S]|\[(?:[^\[\]\\]|\\[\s\S])*\])*\]/.source, /<(?:[^<>\\]|\\[\s\S]|<(?:[^<>\\]|\\[\s\S])*>)*>/.source].join("|") + ")", + g = /(?:"(?:\\.|[^"\\\r\n])*"|(?:\b[a-zA-Z_]\w*|[^\s\0-\x7F]+)[?!]?|\$.)/.source, + d.languages.insertBefore("ruby", "keyword", { + "regex-literal": [{ + pattern: RegExp(/%r/.source + f + /[egimnosux]{0,6}/.source), + greedy: !0, + inside: { + interpolation: p, + regex: /[\s\S]+/ + } + }, { + pattern: /(^|[^/])\/(?!\/)(?:\[[^\r\n\]]+\]|\\.|[^[/\\\r\n])+\/[egimnosux]{0,6}(?=\s*(?:$|[\r\n,.;})#]))/, + lookbehind: !0, + greedy: !0, + inside: { + interpolation: p, + regex: /[\s\S]+/ + } + }], + variable: /[@$]+[a-zA-Z_]\w*(?:[?!]|\b)/, + symbol: [{ + pattern: RegExp(/(^|[^:]):/.source + g), + lookbehind: !0, + greedy: !0 + }, { + pattern: RegExp(/([\r\n{(,][ \t]*)/.source + g + /(?=:(?!:))/.source), + lookbehind: !0, + greedy: !0 + }], + "method-definition": { + pattern: /(\bdef\s+)\w+(?:\s*\.\s*\w+)?/, + lookbehind: !0, + inside: { + function: /\b\w+$/, + keyword: /^self\b/, + "class-name": /^\w+/, + punctuation: /\./ + } + } + }), + d.languages.insertBefore("ruby", "string", { + "string-literal": [{ + pattern: RegExp(/%[qQiIwWs]?/.source + f), + greedy: !0, + inside: { + interpolation: p, + string: /[\s\S]+/ + } + }, { + pattern: /("|')(?:#\{[^}]+\}|#(?!\{)|\\(?:\r\n|[\s\S])|(?!\1)[^\\#\r\n])*\1/, + greedy: !0, + inside: { + interpolation: p, + string: /[\s\S]+/ + } + }, { + pattern: /<<[-~]?([a-z_]\w*)[\r\n](?:.*[\r\n])*?[\t ]*\1/i, + alias: "heredoc-string", + greedy: !0, + inside: { + delimiter: { + pattern: /^<<[-~]?[a-z_]\w*|\b[a-z_]\w*$/i, + inside: { + symbol: /\b\w+/, + punctuation: /^<<[-~]?/ + } + }, + interpolation: p, + string: /[\s\S]+/ + } + }, { + pattern: /<<[-~]?'([a-z_]\w*)'[\r\n](?:.*[\r\n])*?[\t ]*\1/i, + alias: "heredoc-string", + greedy: !0, + inside: { + delimiter: { + pattern: /^<<[-~]?'[a-z_]\w*'|\b[a-z_]\w*$/i, + inside: { + symbol: /\b\w+/, + punctuation: /^<<[-~]?'|'$/ + } + }, + string: /[\s\S]+/ + } + }], + "command-literal": [{ + pattern: RegExp(/%x/.source + f), + greedy: !0, + inside: { + interpolation: p, + command: { + pattern: /[\s\S]+/, + alias: "string" + } + } + }, { + pattern: /`(?:#\{[^}]+\}|#(?!\{)|\\(?:\r\n|[\s\S])|[^\\`#\r\n])*`/, + greedy: !0, + inside: { + interpolation: p, + command: { + pattern: /[\s\S]+/, + alias: "string" + } + } + }] + }), + delete d.languages.ruby.string, + d.languages.insertBefore("ruby", "number", { + builtin: /\b(?:Array|Bignum|Binding|Class|Continuation|Dir|Exception|FalseClass|File|Fixnum|Float|Hash|IO|Integer|MatchData|Method|Module|NilClass|Numeric|Object|Proc|Range|Regexp|Stat|String|Struct|Symbol|TMS|Thread|ThreadGroup|Time|TrueClass)\b/, + constant: /\b[A-Z][A-Z0-9_]*(?:[?!]|\b)/ + }), + d.languages.rb = d.languages.ruby, + (m = E).languages.php = m.languages.extend("clike", { + keyword: /\b(?:and|or|xor|array|as|break|case|cfunction|class|const|continue|declare|default|die|do|else|elseif|enddeclare|endfor|endforeach|endif|endswitch|endwhile|extends|for|foreach|function|include|include_once|global|if|new|return|static|switch|use|require|require_once|var|while|abstract|interface|public|implements|private|protected|parent|throw|null|echo|print|trait|namespace|final|yield|goto|instanceof|finally|try|catch)\b/i, + constant: /\b[A-Z0-9_]{2,}\b/, + comment: { + pattern: /(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/, + lookbehind: !0 + } + }), + m.languages.insertBefore("php", "string", { + "shell-comment": { + pattern: /(^|[^\\])#.*/, + lookbehind: !0, + alias: "comment" + } + }), + m.languages.insertBefore("php", "keyword", { + delimiter: { + pattern: /\?>|<\?(?:php|=)?/i, + alias: "important" + }, + variable: /\$+(?:\w+\b|(?={))/i, + package: { + pattern: /(\\|namespace\s+|use\s+)[\w\\]+/, + lookbehind: !0, + inside: { + punctuation: /\\/ + } + } + }), + m.languages.insertBefore("php", "operator", { + property: { + pattern: /(->)[\w]+/, + lookbehind: !0 + } + }), + m.languages.insertBefore("php", "string", { + "nowdoc-string": { + pattern: /<<<'([^']+)'(?:\r\n?|\n)(?:.*(?:\r\n?|\n))*?\1;/, + greedy: !0, + alias: "string", + inside: { + delimiter: { + pattern: /^<<<'[^']+'|[a-z_]\w*;$/i, + alias: "symbol", + inside: { + punctuation: /^<<<'?|[';]$/ + } + } + } + }, + "heredoc-string": { + pattern: /<<<(?:"([^"]+)"(?:\r\n?|\n)(?:.*(?:\r\n?|\n))*?\1;|([a-z_]\w*)(?:\r\n?|\n)(?:.*(?:\r\n?|\n))*?\2;)/i, + greedy: !0, + alias: "string", + inside: { + delimiter: { + pattern: /^<<<(?:"[^"]+"|[a-z_]\w*)|[a-z_]\w*;$/i, + alias: "symbol", + inside: { + punctuation: /^<<<"?|[";]$/ + } + }, + interpolation: null + } + }, + "single-quoted-string": { + pattern: /'(?:\\[\s\S]|[^\\'])*'/, + greedy: !0, + alias: "string" + }, + "double-quoted-string": { + pattern: /"(?:\\[\s\S]|[^\\"])*"/, + greedy: !0, + alias: "string", + inside: { + interpolation: null + } + } + }), + delete m.languages.php.string, + b = { + pattern: /{\$(?:{(?:{[^{}]+}|[^{}]+)}|[^{}])+}|(^|[^\\{])\$+(?:\w+(?:\[.+?]|->\w+)*)/, + lookbehind: !0, + inside: { + rest: m.languages.php + } + }, + m.languages.php["heredoc-string"].inside.interpolation = b, + m.languages.php["double-quoted-string"].inside.interpolation = b, + m.hooks.add("before-tokenize", function(t) { + /(?:<\?php|<\?)/gi.test(t.code) && m.languages["markup-templating"].buildPlaceholders(t, "php", /(?:<\?php|<\?)[\s\S]*?(?:\?>|$)/gi) + }), + m.hooks.add("after-tokenize", function(t) { + m.languages["markup-templating"].tokenizePlaceholders(t, "php") + }), + E.languages.typescript = E.languages.extend("javascript", { + keyword: /\b(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|var|void|while|with|yield|module|declare|constructor|namespace|abstract|require|type)\b/, + builtin: /\b(?:string|Function|any|number|boolean|Array|symbol|console)\b/ + }), + E.languages.ts = E.languages.typescript, + E.languages.scss = E.languages.extend("css", { + comment: { + pattern: /(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/, + lookbehind: !0 + }, + atrule: { + pattern: /@[\w-]+(?:\([^()]+\)|[^(])*?(?=\s+[{;])/, + inside: { + rule: /@[\w-]+/ + } + }, + url: /(?:[-a-z]+-)*url(?=\()/i, + selector: { + pattern: /(?=\S)[^@;{}()]?(?:[^@;{}()]|&|#\{\$[-\w]+\})+(?=\s*\{(?:\}|\s|[^}]+[:{][^}]+))/m, + inside: { + parent: { + pattern: /&/, + alias: "important" + }, + placeholder: /%[-\w]+/, + variable: /\$[-\w]+|#\{\$[-\w]+\}/ + } + } + }), + E.languages.insertBefore("scss", "atrule", { + keyword: [/@(?:if|else(?: if)?|for|each|while|import|extend|debug|warn|mixin|include|function|return|content)/i, { + pattern: /( +)(?:from|through)(?= )/, + lookbehind: !0 + }] + }), + E.languages.scss.property = { + pattern: /(?:[\w-]|\$[-\w]+|#\{\$[-\w]+\})+(?=\s*:)/i, + inside: { + variable: /\$[-\w]+|#\{\$[-\w]+\}/ + } + }, + E.languages.insertBefore("scss", "important", { + variable: /\$[-\w]+|#\{\$[-\w]+\}/ + }), + E.languages.insertBefore("scss", "function", { + placeholder: { + pattern: /%[-\w]+/, + alias: "selector" + }, + statement: { + pattern: /\B!(?:default|optional)\b/i, + alias: "keyword" + }, + boolean: /\b(?:true|false)\b/, + null: /\bnull\b/, + operator: { + pattern: /(\s)(?:[-+*\/%]|[=!]=|<=?|>=?|and|or|not)(?=\s)/, + lookbehind: !0 + } + }), + E.languages.scss.atrule.inside.rest = E.languages.scss, + "undefined" != typeof self && self.Prism && self.document && (W = "line-numbers", + Y = /\n(?!$)/g, + F = function(t) { + var n, i, e = ((e = t) ? window.getComputedStyle ? getComputedStyle(e) : e.currentStyle || null : null)["white-space"]; + "pre-wrap" !== e && "pre-line" !== e || (e = t.querySelector("code"), + n = t.querySelector(".line-numbers-rows"), + i = t.querySelector(".line-numbers-sizer"), + t = e.textContent.split(Y), + i || ((i = document.createElement("span")).className = "line-numbers-sizer", + e.appendChild(i)), + i.style.display = "block", + t.forEach(function(t, e) { + i.textContent = t || "\n", + t = i.getBoundingClientRect().height, + n.children[e].style.height = t + "px" + }), + i.textContent = "", + i.style.display = "none") + } + , + window.addEventListener("resize", function() { + Array.prototype.forEach.call(document.querySelectorAll("pre." + W), F) + }), + E.hooks.add("complete", function(t) { + var e, n, i; + t.code && (n = /\s*\bline-numbers\b\s*/, + e = t.element.parentNode) && /pre/i.test(e.nodeName) && (n.test(e.className) || n.test(t.element.className)) && (t.element.querySelector(".line-numbers-rows") || (n.test(t.element.className) && (t.element.className = t.element.className.replace(n, " ")), + n.test(e.className) || (e.className += " line-numbers"), + n = (n = t.code.match(Y)) ? n.length + 1 : 1, + n = (n = new Array(n + 1)).join(""), + (i = document.createElement("span")).setAttribute("aria-hidden", "true"), + i.className = "line-numbers-rows", + i.innerHTML = n, + e.hasAttribute("data-start") && (e.style.counterReset = "linenumber " + (parseInt(e.getAttribute("data-start"), 10) - 1)), + t.element.appendChild(i), + F(e), + E.hooks.run("line-numbers", t))) + }), + E.hooks.add("line-numbers", function(t) { + t.plugins = t.plugins || {}, + t.plugins.lineNumbers = !0 + }), + E.plugins.lineNumbers = { + getLine: function(t, e) { + var n, i; + if ("PRE" === t.tagName && t.classList.contains(W)) + return n = t.querySelector(".line-numbers-rows"), + i = (e = (i = (t = parseInt(t.getAttribute("data-start"), 10) || 1) + (n.children.length - 1)) < (e = e < t ? t : e) ? i : e) - t, + n.children[i] + } + }), + "undefined" != typeof self && self.Prism && self.document && (v = [], + X = {}, + z = function() {} + , + E.plugins.toolbar = {}, + _ = E.plugins.toolbar.registerButton = function(t, n) { + v.push(X[t] = "function" == typeof n ? n : function(t) { + var e; + return "function" == typeof n.onClick ? ((e = document.createElement("button")).type = "button", + e.addEventListener("click", function() { + n.onClick.call(this, t) + })) : "string" == typeof n.url ? (e = document.createElement("a")).href = n.url : e = document.createElement("span"), + e.textContent = n.text, + e + } + ) + } + , + e = E.plugins.toolbar.hook = function(n) { + var t, i, e = n.element.parentNode; + e && /pre/i.test(e.nodeName) && (e.parentNode.classList.contains("code-toolbar") || ((t = document.createElement("div")).classList.add("code-toolbar"), + e.parentNode.insertBefore(t, e), + t.appendChild(e), + (i = document.createElement("div")).classList.add("toolbar"), + (v = document.body.hasAttribute("data-toolbar-order") ? document.body.getAttribute("data-toolbar-order").split(",").map(function(t) { + return X[t] || z + }) : v).forEach(function(t) { + var e; + (t = t(n)) && ((e = document.createElement("div")).classList.add("toolbar-item"), + e.appendChild(t), + i.appendChild(e)) + }), + t.appendChild(i))) + } + , + _("label", function(t) { + if ((t = t.element.parentNode) && /pre/i.test(t.nodeName) && t.hasAttribute("data-label")) { + var e, n, i = t.getAttribute("data-label"); + try { + n = document.querySelector("template#" + i) + } catch (t) {} + return n ? e = n.content : (t.hasAttribute("data-url") ? (e = document.createElement("a")).href = t.getAttribute("data-url") : e = document.createElement("span"), + e.textContent = i), + e + } + }), + E.hooks.add("complete", e)), + ("undefined" == typeof self || self.Prism) && self.document && Function.prototype.bind) { + var R, q, M = { + gradient: { + create: (R = {}, + function() { + new E.plugins.Previewer("gradient",function(t) { + return this.firstChild.style.backgroundImage = "", + this.firstChild.style.backgroundImage = R[t = t] || (r = (e = t.match(/^(\b|\B-[a-z]{1,10}-)((?:repeating-)?(?:linear|radial)-gradient)/)) && e[1], + e = e && e[2], + n = t.replace(/^(?:\b|\B-[a-z]{1,10}-)(?:repeating-)?(?:linear|radial)-gradient\(|\)$/g, "").split(/\s*,\s*/), + 0 <= e.indexOf("linear") ? R[t] = (s = e, + l = "180deg", + /^(?:-?\d*\.?\d+(?:deg|rad)|to\b|top|right|bottom|left)/.test((a = n)[0]) && (l = a.shift()).indexOf("to ") < 0 && (0 <= l.indexOf("top") ? l = 0 <= l.indexOf("left") ? "to bottom right" : 0 <= l.indexOf("right") ? "to bottom left" : "to bottom" : 0 <= l.indexOf("bottom") ? l = 0 <= l.indexOf("left") ? "to top right" : 0 <= l.indexOf("right") ? "to top left" : "to top" : 0 <= l.indexOf("left") ? l = "to right" : 0 <= l.indexOf("right") ? l = "to left" : r && (0 <= l.indexOf("deg") ? l = 90 - parseFloat(l) + "deg" : 0 <= l.indexOf("rad") && (l = Math.PI / 2 - parseFloat(l) + "rad"))), + s + "(" + l + "," + a.join(",") + ")") : 0 <= e.indexOf("radial") ? R[t] = (r = e, + (s = n)[0].indexOf("at") < 0 ? (l = "center", + a = "ellipse", + i = "farthest-corner", + /\bcenter|top|right|bottom|left\b|^\d+/.test(s[0]) && (l = s.shift().replace(/\s*-?\d+(?:rad|deg)\s*/, "")), + /\bcircle|ellipse|closest|farthest|contain|cover\b/.test(s[0]) && (!(o = s.shift().split(/\s+/))[0] || "circle" !== o[0] && "ellipse" !== o[0] || (a = o.shift()), + "cover" === (i = o[0] ? o.shift() : i) ? i = "farthest-corner" : "contain" === i && (i = "clothest-side")), + r + "(" + a + " " + i + " at " + l + "," + s.join(",") + ")") : r + "(" + s.join(",") + ")") : R[t] = e + "(" + n.join(",") + ")"), + !!this.firstChild.style.backgroundImage; + var e, n, i, o, r, s, a, l + } + ,"*",function() { + this._elt.innerHTML = "
" + } + ) + } + ), + tokens: { + gradient: { + pattern: /(?:\b|\B-[a-z]{1,10}-)(?:repeating-)?(?:linear|radial)-gradient\((?:(?:rgb|hsl)a?\(.+?\)|[^\)])+\)/gi, + inside: { + function: /[\w-]+(?=\()/, + punctuation: /[(),]/ + } + } + }, + languages: { + css: !0, + less: !0, + sass: [{ + lang: "sass", + before: "punctuation", + inside: "inside", + root: E.languages.sass && E.languages.sass["variable-line"] + }, { + lang: "sass", + before: "punctuation", + inside: "inside", + root: E.languages.sass && E.languages.sass["property-line"] + }], + scss: !0, + stylus: [{ + lang: "stylus", + before: "func", + inside: "rest", + root: E.languages.stylus && E.languages.stylus["property-declaration"].inside + }, { + lang: "stylus", + before: "func", + inside: "rest", + root: E.languages.stylus && E.languages.stylus["variable-declaration"].inside + }] + } + }, + angle: { + create: function() { + new E.plugins.Previewer("angle",function(t) { + var e, n = parseFloat(t), t = t.match(/[a-z]+$/i); + if (!n || !t) + return !1; + switch (t[0]) { + case "deg": + e = 360; + break; + case "grad": + e = 400; + break; + case "rad": + e = 2 * Math.PI; + break; + case "turn": + e = 1 + } + return t = 100 * n / e, + t %= 100, + this[(n < 0 ? "set" : "remove") + "Attribute"]("data-negative", ""), + this.querySelector("circle").style.strokeDasharray = Math.abs(t) + ",500", + !0 + } + ,"*",function() { + this._elt.innerHTML = '' + } + ) + }, + tokens: { + angle: /(?:\b|\B-|(?=\B\.))\d*\.?\d+(?:deg|g?rad|turn)\b/i + }, + languages: { + css: !0, + less: !0, + markup: { + lang: "markup", + before: "punctuation", + inside: "inside", + root: E.languages.markup && E.languages.markup.tag.inside["attr-value"] + }, + sass: [{ + lang: "sass", + inside: "inside", + root: E.languages.sass && E.languages.sass["property-line"] + }, { + lang: "sass", + before: "operator", + inside: "inside", + root: E.languages.sass && E.languages.sass["variable-line"] + }], + scss: !0, + stylus: [{ + lang: "stylus", + before: "func", + inside: "rest", + root: E.languages.stylus && E.languages.stylus["property-declaration"].inside + }, { + lang: "stylus", + before: "func", + inside: "rest", + root: E.languages.stylus && E.languages.stylus["variable-declaration"].inside + }] + } + }, + color: { + create: function() { + new E.plugins.Previewer("color",function(t) { + return this.style.backgroundColor = "", + this.style.backgroundColor = t, + !!this.style.backgroundColor + } + ) + }, + tokens: { + color: { + pattern: /\B#(?:[0-9a-f]{3}){1,2}\b|\b(?:rgb|hsl)\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*\)\B|\b(?:rgb|hsl)a\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*,\s*(?:0|0?\.\d+|1)\s*\)\B|\b(?:AliceBlue|AntiqueWhite|Aqua|Aquamarine|Azure|Beige|Bisque|Black|BlanchedAlmond|Blue|BlueViolet|Brown|BurlyWood|CadetBlue|Chartreuse|Chocolate|Coral|CornflowerBlue|Cornsilk|Crimson|Cyan|DarkBlue|DarkCyan|DarkGoldenRod|DarkGray|DarkGreen|DarkKhaki|DarkMagenta|DarkOliveGreen|DarkOrange|DarkOrchid|DarkRed|DarkSalmon|DarkSeaGreen|DarkSlateBlue|DarkSlateGray|DarkTurquoise|DarkViolet|DeepPink|DeepSkyBlue|DimGray|DodgerBlue|FireBrick|FloralWhite|ForestGreen|Fuchsia|Gainsboro|GhostWhite|Gold|GoldenRod|Gray|Green|GreenYellow|HoneyDew|HotPink|IndianRed|Indigo|Ivory|Khaki|Lavender|LavenderBlush|LawnGreen|LemonChiffon|LightBlue|LightCoral|LightCyan|LightGoldenRodYellow|LightGray|LightGreen|LightPink|LightSalmon|LightSeaGreen|LightSkyBlue|LightSlateGray|LightSteelBlue|LightYellow|Lime|LimeGreen|Linen|Magenta|Maroon|MediumAquaMarine|MediumBlue|MediumOrchid|MediumPurple|MediumSeaGreen|MediumSlateBlue|MediumSpringGreen|MediumTurquoise|MediumVioletRed|MidnightBlue|MintCream|MistyRose|Moccasin|NavajoWhite|Navy|OldLace|Olive|OliveDrab|Orange|OrangeRed|Orchid|PaleGoldenRod|PaleGreen|PaleTurquoise|PaleVioletRed|PapayaWhip|PeachPuff|Peru|Pink|Plum|PowderBlue|Purple|Red|RosyBrown|RoyalBlue|SaddleBrown|Salmon|SandyBrown|SeaGreen|SeaShell|Sienna|Silver|SkyBlue|SlateBlue|SlateGray|Snow|SpringGreen|SteelBlue|Tan|Teal|Thistle|Tomato|Turquoise|Violet|Wheat|White|WhiteSmoke|Yellow|YellowGreen)\b/i, + inside: { + function: /[\w-]+(?=\()/, + punctuation: /[(),]/ + } + } + }, + languages: { + css: !0, + less: !0, + markup: { + lang: "markup", + before: "punctuation", + inside: "inside", + root: E.languages.markup && E.languages.markup.tag.inside["attr-value"] + }, + sass: [{ + lang: "sass", + before: "punctuation", + inside: "inside", + root: E.languages.sass && E.languages.sass["variable-line"] + }, { + lang: "sass", + inside: "inside", + root: E.languages.sass && E.languages.sass["property-line"] + }], + scss: !0, + stylus: [{ + lang: "stylus", + before: "hexcode", + inside: "rest", + root: E.languages.stylus && E.languages.stylus["property-declaration"].inside + }, { + lang: "stylus", + before: "hexcode", + inside: "rest", + root: E.languages.stylus && E.languages.stylus["variable-declaration"].inside + }] + } + }, + easing: { + create: function() { + new E.plugins.Previewer("easing",function(t) { + var e; + return 4 === (t = (t = { + linear: "0,0,1,1", + ease: ".25,.1,.25,1", + "ease-in": ".42,0,1,1", + "ease-out": "0,0,.58,1", + "ease-in-out": ".42,0,.58,1" + }[t] || t).match(/-?\d*\.?\d+/g)).length && (t = t.map(function(t, e) { + return 100 * (e % 2 ? 1 - t : t) + }), + this.querySelector("path").setAttribute("d", "M0,100 C" + t[0] + "," + t[1] + ", " + t[2] + "," + t[3] + ", 100,0"), + (e = this.querySelectorAll("line"))[0].setAttribute("x2", t[0]), + e[0].setAttribute("y2", t[1]), + e[1].setAttribute("x2", t[2]), + e[1].setAttribute("y2", t[3]), + !0) + } + ,"*",function() { + this._elt.innerHTML = '' + } + ) + }, + tokens: { + easing: { + pattern: /\bcubic-bezier\((?:-?\d*\.?\d+,\s*){3}-?\d*\.?\d+\)\B|\b(?:linear|ease(?:-in)?(?:-out)?)(?=\s|[;}]|$)/i, + inside: { + function: /[\w-]+(?=\()/, + punctuation: /[(),]/ + } + } + }, + languages: { + css: !0, + less: !0, + sass: [{ + lang: "sass", + inside: "inside", + before: "punctuation", + root: E.languages.sass && E.languages.sass["variable-line"] + }, { + lang: "sass", + inside: "inside", + root: E.languages.sass && E.languages.sass["property-line"] + }], + scss: !0, + stylus: [{ + lang: "stylus", + before: "hexcode", + inside: "rest", + root: E.languages.stylus && E.languages.stylus["property-declaration"].inside + }, { + lang: "stylus", + before: "hexcode", + inside: "rest", + root: E.languages.stylus && E.languages.stylus["variable-declaration"].inside + }] + } + }, + time: { + create: function() { + new E.plugins.Previewer("time",function(t) { + var e = parseFloat(t) + , t = t.match(/[a-z]+$/i); + return !(!e || !t || (t = t[0], + this.querySelector("circle").style.animationDuration = 2 * e + t, + 0)) + } + ,"*",function() { + this._elt.innerHTML = '' + } + ) + }, + tokens: { + time: /(?:\b|\B-|(?=\B\.))\d*\.?\d+m?s\b/i + }, + languages: { + css: !0, + less: !0, + markup: { + lang: "markup", + before: "punctuation", + inside: "inside", + root: E.languages.markup && E.languages.markup.tag.inside["attr-value"] + }, + sass: [{ + lang: "sass", + inside: "inside", + root: E.languages.sass && E.languages.sass["property-line"] + }, { + lang: "sass", + before: "operator", + inside: "inside", + root: E.languages.sass && E.languages.sass["variable-line"] + }], + scss: !0, + stylus: [{ + lang: "stylus", + before: "hexcode", + inside: "rest", + root: E.languages.stylus && E.languages.stylus["property-declaration"].inside + }, { + lang: "stylus", + before: "hexcode", + inside: "rest", + root: E.languages.stylus && E.languages.stylus["variable-declaration"].inside + }] + } + } + }, $ = /(?:^|\s)token(?=$|\s)/, V = /(?:^|\s)active(?=$|\s)/g, K = /(?:^|\s)flipped(?=$|\s)/g, I = function(t, e, n, i) { + this._elt = null, + this._type = t, + this._clsRegexp = RegExp("(?:^|\\s)" + t + "(?=$|\\s)"), + this._token = null, + this.updater = e, + this._mouseout = this.mouseout.bind(this), + this.initializer = i; + var o = this; + (n = "Array" !== E.util.type(n = n || ["*"]) ? [n] : n).forEach(function(t) { + "string" != typeof t && (t = t.lang), + I.byLanguages[t] || (I.byLanguages[t] = []), + I.byLanguages[t].indexOf(o) < 0 && I.byLanguages[t].push(o) + }), + I.byType[t] = this + }; + for (q in I.prototype.init = function() { + this._elt || (this._elt = document.createElement("div"), + this._elt.className = "prism-previewer prism-previewer-" + this._type, + document.body.appendChild(this._elt), + this.initializer && this.initializer()) + } + , + I.prototype.isDisabled = function(t) { + do { + if (t.hasAttribute && t.hasAttribute("data-previewers")) + return -1 === (t.getAttribute("data-previewers") || "").split(/\s+/).indexOf(this._type) + } while (t = t.parentNode); + return !1 + } + , + I.prototype.check = function(t) { + if (!$.test(t.className) || !this.isDisabled(t)) { + do { + if ($.test(t.className) && this._clsRegexp.test(t.className)) + break + } while (t = t.parentNode); + t && t !== this._token && (this._token = t, + this.show()) + } + } + , + I.prototype.mouseout = function() { + this._token.removeEventListener("mouseout", this._mouseout, !1), + this._token = null, + this.hide() + } + , + I.prototype.show = function() { + var t; + this._elt || this.init(), + this._token && (this.updater.call(this._elt, this._token.textContent) ? (this._token.addEventListener("mouseout", this._mouseout, !1), + t = function(t) { + var e = 0 + , n = 0 + , i = t; + if (i.parentNode) { + for (; e += i.offsetLeft, + n += i.offsetTop, + (i = i.offsetParent) && i.nodeType < 9; ) + ; + for (i = t; e -= i.scrollLeft, + n -= i.scrollTop, + (i = i.parentNode) && !/body/i.test(i.nodeName); ) + ; + } + return { + top: n, + right: innerWidth - e - t.offsetWidth, + bottom: innerHeight - n - t.offsetHeight, + left: e + } + }(this._token), + this._elt.className += " active", + 0 < t.top - this._elt.offsetHeight ? (this._elt.className = this._elt.className.replace(K, ""), + this._elt.style.top = t.top + "px", + this._elt.style.bottom = "") : (this._elt.className += " flipped", + this._elt.style.bottom = t.bottom + "px", + this._elt.style.top = ""), + this._elt.style.left = t.left + Math.min(200, this._token.offsetWidth / 2) + "px") : this.hide()) + } + , + I.prototype.hide = function() { + this._elt.className = this._elt.className.replace(V, "") + } + , + I.byLanguages = {}, + I.byType = {}, + I.initEvents = function(t, e) { + var n = []; + I.byLanguages[e] && (n = n.concat(I.byLanguages[e])), + I.byLanguages["*"] && (n = n.concat(I.byLanguages["*"])), + t.addEventListener("mouseover", function(t) { + var e = t.target; + n.forEach(function(t) { + t.check(e) + }) + }, !1) + } + , + E.plugins.Previewer = I, + E.hooks.add("before-highlight", function(r) { + for (var s in M) { + var t, a = M[s].languages; + r.language && a[r.language] && !a[r.language].initialized && (t = a[r.language], + (t = "Array" !== E.util.type(t) ? [t] : t).forEach(function(t) { + var e, n, i, o; + !0 === t ? (e = "important", + n = r.language) : (e = t.before || "important", + n = t.inside || t.lang, + i = t.root || E.languages, + o = t.skip), + t = r.language, + !o && E.languages[t] && (E.languages.insertBefore(n, e, M[s].tokens, i), + r.grammar = E.languages[t], + a[r.language] = { + initialized: !0 + }) + })) + } + }), + E.hooks.add("after-highlight", function(t) { + (I.byLanguages["*"] || I.byLanguages[t.language]) && I.initEvents(t.element, t.language) + }), + M) + M[q].create() + } + function G(t) { + this.defaults = y({}, t) + } + function Q(t) { + for (var e = 0, n = 0; n < t.length; ++n) + t.charCodeAt(n) == "\t".charCodeAt(0) && (e += 3); + return t.length + e + } + y = Object.assign || function(t, e) { + for (var n in e) + e.hasOwnProperty(n) && (t[n] = e[n]); + return t + } + , + G.prototype = { + setDefaults: function(t) { + this.defaults = y(this.defaults, t) + }, + normalize: function(t, e) { + for (var n in e = y(this.defaults, e)) { + var i = n.replace(/-(\w)/g, function(t, e) { + return e.toUpperCase() + }); + "normalize" !== n && "setDefaults" !== i && e[n] && this[i] && (t = this[i].call(this, t, e[n])) + } + return t + }, + leftTrim: function(t) { + return t.replace(/^\s+/, "") + }, + rightTrim: function(t) { + return t.replace(/\s+$/, "") + }, + tabsToSpaces: function(t, e) { + return e = 0 | e || 4, + t.replace(/\t/g, new Array(++e).join(" ")) + }, + spacesToTabs: function(t, e) { + return e = 0 | e || 4, + t.replace(new RegExp(" {" + e + "}","g"), "\t") + }, + removeTrailing: function(t) { + return t.replace(/\s*?$/gm, "") + }, + removeInitialLineFeed: function(t) { + return t.replace(/^(?:\r?\n|\r)/, "") + }, + removeIndent: function(t) { + var e = t.match(/^[^\S\n\r]*(?=\S)/gm); + return e && e[0].length && (e.sort(function(t, e) { + return t.length - e.length + }), + e[0].length) ? t.replace(new RegExp("^" + e[0],"gm"), "") : t + }, + indent: function(t, e) { + return t.replace(/^[^\S\n\r]*(?=\S)/gm, new Array(++e).join("\t") + "$&") + }, + breakLines: function(t, e) { + e = !0 !== e && 0 | e || 80; + for (var n = t.split("\n"), i = 0; i < n.length; ++i) + if (!(Q(n[i]) <= e)) { + for (var o = n[i].split(/(\s+)/g), r = 0, s = 0; s < o.length; ++s) { + var a = Q(o[s]); + e < (r += a) && (o[s] = "\n" + o[s], + r = a) + } + n[i] = o.join("") + } + return n.join("\n") + } + }, + t.exports && (t.exports = G), + void 0 !== E && (E.plugins.NormalizeWhitespace = new G({ + "remove-trailing": !0, + "remove-indent": !0, + "left-trim": !0, + "right-trim": !0 + }), + E.hooks.add("before-sanity-check", function(t) { + var e = E.plugins.NormalizeWhitespace; + if (!t.settings || !1 !== t.settings["whitespace-normalization"]) + if (t.element && t.element.parentNode || !t.code) { + var n = t.element.parentNode + , i = /\bno-whitespace-normalization\b/; + if (t.code && n && "pre" === n.nodeName.toLowerCase() && !i.test(n.className) && !i.test(t.element.className)) { + for (var o = n.childNodes, r = "", s = "", a = !1, l = 0; l < o.length; ++l) { + var c = o[l]; + c == t.element ? a = !0 : "#text" === c.nodeName && (a ? s += c.nodeValue : r += c.nodeValue, + n.removeChild(c), + --l) + } + t.element.children.length && E.plugins.KeepMarkup ? (i = r + t.element.innerHTML + s, + t.element.innerHTML = e.normalize(i, t.settings), + t.code = t.element.textContent) : (t.code = r + t.code + s, + t.code = e.normalize(t.code, t.settings)) + } + } else + t.code = e.normalize(t.code, t.settings) + })), + "undefined" != typeof self && self.Prism && self.document && (E.plugins.toolbar ? (w = (w = window.ClipboardJS || void 0) || Z(117), + O = [], + w || (x = document.createElement("script"), + S = document.querySelector("head"), + x.onload = function() { + if (w = window.ClipboardJS) + for (; O.length; ) + O.pop()() + } + , + x.src = "https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.0/clipboard.min.js", + S.appendChild(x)), + E.plugins.toolbar.registerButton("copy-to-clipboard", function(e) { + var n = document.createElement("button"); + return n.innerHTML = "Copy", + n.classList = "btn-copy-code btn btn-sm", + n.setAttribute("data-mdb-ripple-color", "dark"), + n.setAttribute("data-mdb-ripple-unbound", "true"), + w ? t() : O.push(t), + n; + function t() { + var t = new w(n,{ + text: function() { + return e.code + } + }); + t.on("success", function() { + n.textContent = "Copied!", + i() + }), + t.on("error", function() { + n.textContent = "Press Ctrl+C to copy", + i() + }) + } + function i() { + setTimeout(function() { + n.innerHTML = "Copy" + }, 5e3) + } + })) : console.warn("Copy to Clipboard plugin loaded before Toolbar plugin.")) + } + .call(this, Z(69)(t), Z(36)) + } + , function(t, e) { + t.exports = function(t) { + var e; + return t.webpackPolyfill || ((e = Object.create(t)).children || (e.children = []), + Object.defineProperty(e, "loaded", { + enumerable: !0, + get: function() { + return e.l + } + }), + Object.defineProperty(e, "id", { + enumerable: !0, + get: function() { + return e.i + } + }), + Object.defineProperty(e, "exports", { + enumerable: !0 + }), + e.webpackPolyfill = 1), + e + } + } + , function(t, e, n) { + var i = {}.propertyIsEnumerable + , o = Object.getOwnPropertyDescriptor + , r = o && !i.call({ + 1: 2 + }, 1); + e.f = r ? function(t) { + return !!(t = o(this, t)) && t.enumerable + } + : i + } + , function(t, e, n) { + var i = n(1) + , o = n(0) + , r = n(12) + , s = Object + , a = i("".split); + t.exports = o(function() { + return !s("z").propertyIsEnumerable(0) + }) ? function(t) { + return "String" == r(t) ? a(t, "") : s(t) + } + : s + } + , function(t, e, n) { + var i = n(8) + , o = n(9) + , r = n(40) + , s = n(44) + , a = n(73) + , n = n(6) + , l = TypeError + , c = n("toPrimitive"); + t.exports = function(t, e) { + if (!o(t) || r(t)) + return t; + var n = s(t, c); + if (n) { + if (n = i(n, t, e = void 0 === e ? "default" : e), + !o(n) || r(n)) + return n; + throw l("Can't convert object to primitive value") + } + return a(t, e = void 0 === e ? "number" : e) + } + } + , function(t, e, n) { + var o = n(8) + , r = n(2) + , s = n(9) + , a = TypeError; + t.exports = function(t, e) { + var n, i; + if ("string" === e && r(n = t.toString) && !s(i = o(n, t))) + return i; + if (r(n = t.valueOf) && !s(i = o(n, t))) + return i; + if ("string" !== e && r(n = t.toString) && !s(i = o(n, t))) + return i; + throw a("Can't convert object to primitive value") + } + } + , function(t, e) { + t.exports = !1 + } + , function(t, e, n) { + var i = n(0) + , o = n(2) + , r = n(5) + , s = n(4) + , a = n(51).CONFIGURABLE + , l = n(76) + , c = (n = n(31)).enforce + , u = n.get + , h = Object.defineProperty + , d = s && !i(function() { + return 8 !== h(function() {}, "length", { + value: 8 + }).length + }) + , p = String(String).split("String") + , n = t.exports = function(t, e, n) { + "Symbol(" === String(e).slice(0, 7) && (e = "[" + String(e).replace(/^Symbol\(([^)]*)\)/, "$1") + "]"), + n && n.getter && (e = "get " + e), + n && n.setter && (e = "set " + e), + (!r(t, "name") || a && t.name !== e) && (s ? h(t, "name", { + value: e, + configurable: !0 + }) : t.name = e), + d && n && r(n, "arity") && t.length !== n.arity && h(t, "length", { + value: n.arity + }); + try { + n && r(n, "constructor") && n.constructor ? s && h(t, "prototype", { + writable: !1 + }) : t.prototype && (t.prototype = void 0) + } catch (t) {} + return n = c(t), + r(n, "source") || (n.source = p.join("string" == typeof e ? e : "")), + t + } + ; + Function.prototype.toString = n(function() { + return o(this) && u(this).source || l(this) + }, "toString") + } + , function(t, e, n) { + var i = n(1) + , o = n(2) + , n = n(27) + , r = i(Function.toString); + o(n.inspectSource) || (n.inspectSource = function(t) { + return r(t) + } + ), + t.exports = n.inspectSource + } + , function(t, e, n) { + var i = n(3) + , n = n(2) + , i = i.WeakMap; + t.exports = n(i) && /native code/.test(String(i)) + } + , function(t, e, n) { + var l = n(5) + , c = n(79) + , u = n(38) + , h = n(10); + t.exports = function(t, e, n) { + for (var i = c(e), o = h.f, r = u.f, s = 0; s < i.length; s++) { + var a = i[s]; + l(t, a) || n && l(n, a) || o(t, a, r(e, a)) + } + } + } + , function(t, e, n) { + var i = n(14) + , o = n(1) + , r = n(53) + , s = n(82) + , a = n(7) + , l = o([].concat); + t.exports = i("Reflect", "ownKeys") || function(t) { + var e = r.f(a(t)) + , n = s.f; + return n ? l(e, n(t)) : e + } + } + , function(t, e, n) { + function i(a) { + return function(t, e, n) { + var i, o = l(t), r = u(o), s = c(n, r); + if (a && e != e) { + for (; s < r; ) + if ((i = o[s++]) != i) + return !0 + } else + for (; s < r; s++) + if ((a || s in o) && o[s] === e) + return a || s || 0; + return !a && -1 + } + } + var l = n(15) + , c = n(55) + , u = n(33); + t.exports = { + includes: i(!0), + indexOf: i(!1) + } + } + , function(t, e) { + var n = Math.ceil + , i = Math.floor; + t.exports = Math.trunc || function(t) { + return (0 < (t = +t) ? i : n)(t) + } + } + , function(t, e) { + e.f = Object.getOwnPropertySymbols + } + , function(t, e, n) { + var i = n(84) + , o = n(2) + , r = n(12) + , s = n(6)("toStringTag") + , a = Object + , l = "Arguments" == r(function() { + return arguments + }()); + t.exports = i ? r : function(t) { + var e; + return void 0 === t ? "Undefined" : null === t ? "Null" : "string" == typeof (e = function(t, e) { + try { + return t[e] + } catch (t) {} + }(t = a(t), s)) ? e : l ? r(t) : "Object" == (e = r(t)) && o(t.callee) ? "Arguments" : e + } + } + , function(t, e, n) { + var i = {}; + i[n(6)("toStringTag")] = "z", + t.exports = "[object z]" === String(i) + } + , function(t, e, n) { + function i() {} + var o, r = n(7), s = n(86), a = n(34), l = n(32), c = n(88), u = n(49), n = n(52), h = "prototype", d = "script", p = n("IE_PROTO"), f = function(t) { + return "<" + d + ">" + t + "" + }, g = function() { + try { + o = new ActiveXObject("htmlfile") + } catch (e) {} + var t; + g = "undefined" == typeof document || document.domain && o ? ((n = o).write(f("")), + n.close(), + t = n.parentWindow.Object, + n = null, + t) : (e = u("iframe"), + n = "java" + d + ":", + e.style.display = "none", + c.appendChild(e), + e.src = String(n), + (n = e.contentWindow.document).open(), + n.write(f("document.F=Object")), + n.close(), + n.F); + for (var e, n, i = a.length; i--; ) + delete g[h][a[i]]; + return g() + }; + l[p] = !0, + t.exports = Object.create || function(t, e) { + var n; + return null !== t ? (i[h] = r(t), + n = new i, + i[h] = null, + n[p] = t) : n = g(), + void 0 === e ? n : s.f(n, e) + } + } + , function(t, e, n) { + var i = n(4) + , o = n(50) + , a = n(10) + , l = n(7) + , c = n(15) + , u = n(87); + e.f = i && !o ? Object.defineProperties : function(t, e) { + l(t); + for (var n, i = c(e), o = u(e), r = o.length, s = 0; s < r; ) + a.f(t, n = o[s++], i[n]); + return t + } + } + , function(t, e, n) { + var i = n(54) + , o = n(34); + t.exports = Object.keys || function(t) { + return i(t, o) + } + } + , function(t, e, n) { + n = n(14), + t.exports = n("document", "documentElement") + } + , function(t, e, n) { + var O = n(90) + , o = n(8) + , i = n(1) + , r = n(91) + , s = n(0) + , x = n(7) + , S = n(2) + , a = n(23) + , C = n(18) + , E = n(56) + , k = n(11) + , l = n(13) + , A = n(93) + , c = n(44) + , j = n(95) + , T = n(96) + , u = n(6)("replace") + , L = Math.max + , P = Math.min + , R = i([].concat) + , M = i([].push) + , I = i("".indexOf) + , D = i("".slice) + , n = "$0" === "a".replace(/./, "$0") + , h = !!/./[u] && "" === /./[u]("a", "$0"); + r("replace", function(t, _, y) { + var w = h ? "$" : "$0"; + return [function(t, e) { + var n = l(this) + , i = a(t) ? void 0 : c(t, u); + return i ? o(i, t, n, e) : o(_, k(n), t, e) + } + , function(t, e) { + var n = x(this) + , i = k(t); + if ("string" == typeof e && -1 === I(e, w) && -1 === I(e, "$<") && (t = y(_, n, i, e)).done) + return t.value; + for (var o, r = S(e), s = (r || (e = k(e)), + n.global), a = (s && (o = n.unicode, + n.lastIndex = 0), + []); null !== (d = T(n, i)) && (M(a, d), + s); ) + "" === k(d[0]) && (n.lastIndex = A(i, E(n.lastIndex), o)); + for (var l, c = "", u = 0, h = 0; h < a.length; h++) { + for (var d, p = k((d = a[h])[0]), f = L(P(C(d.index), i.length), 0), g = [], m = 1; m < d.length; m++) + M(g, void 0 === (l = d[m]) ? l : String(l)); + var b = d.groups + , v = r ? (v = R([p], g, f, i), + void 0 !== b && M(v, b), + k(O(e, void 0, v))) : j(p, i, f, g, b, e); + u <= f && (c += D(i, u, f) + v, + u = f + p.length) + } + return c + D(i, u) + } + ] + }, !!s(function() { + var t = /./; + return t.exec = function() { + var t = []; + return t.groups = { + a: "7" + }, + t + } + , + "7" !== "".replace(t, "$
") + }) || !n || h) + } + , function(t, e, n) { + var n = n(21) + , i = Function.prototype + , o = i.apply + , r = i.call; + t.exports = "object" == typeof Reflect && Reflect.apply || (n ? r.bind(o) : function() { + return r.apply(o, arguments) + } + ) + } + , function(t, e, n) { + n(37); + var l = n(92) + , c = n(30) + , u = n(35) + , h = n(0) + , d = n(6) + , p = n(17) + , f = d("species") + , g = RegExp.prototype; + t.exports = function(n, t, e, i) { + var s, o = d(n), a = !h(function() { + var t = {}; + return t[o] = function() { + return 7 + } + , + 7 != ""[n](t) + }), r = a && !h(function() { + var t = !1 + , e = /a/; + return "split" === n && ((e = { + constructor: {} + }).constructor[f] = function() { + return e + } + , + e.flags = "", + e[o] = /./[o]), + e.exec = function() { + return t = !0, + null + } + , + e[o](""), + !t + }); + a && r && !e || (s = l(/./[o]), + r = t(o, ""[n], function(t, e, n, i, o) { + var t = l(t) + , r = e.exec; + return r === u || r === g.exec ? a && !o ? { + done: !0, + value: s(e, n, i) + } : { + done: !0, + value: t(n, e, i) + } : { + done: !1 + } + }), + c(String.prototype, n, r[0]), + c(g, o, r[1])), + i && p(g[o], "sham", !0) + } + } + , function(t, e, n) { + var i = n(12) + , o = n(1); + t.exports = function(t) { + if ("Function" === i(t)) + return o(t) + } + } + , function(t, e, n) { + var i = n(94).charAt; + t.exports = function(t, e, n) { + return e + (n ? i(t, e).length : 1) + } + } + , function(t, e, n) { + function i(o) { + return function(t, e) { + var n, t = s(a(t)), e = r(e), i = t.length; + return e < 0 || i <= e ? o ? "" : void 0 : (n = c(t, e)) < 55296 || 56319 < n || e + 1 === i || (i = c(t, e + 1)) < 56320 || 57343 < i ? o ? l(t, e) : n : o ? u(t, e, e + 2) : i - 56320 + (n - 55296 << 10) + 65536 + } + } + var o = n(1) + , r = n(18) + , s = n(11) + , a = n(13) + , l = o("".charAt) + , c = o("".charCodeAt) + , u = o("".slice); + t.exports = { + codeAt: i(!1), + charAt: i(!0) + } + } + , function(t, e, n) { + var i = n(1) + , o = n(29) + , d = Math.floor + , p = i("".charAt) + , f = i("".replace) + , g = i("".slice) + , m = /\$([$&'`]|\d{1,2}|<[^>]*>)/g + , b = /\$([$&'`]|\d{1,2})/g; + t.exports = function(r, s, a, l, c, t) { + var u = a + r.length + , h = l.length + , e = b; + return void 0 !== c && (c = o(c), + e = m), + f(t, e, function(t, e) { + var n; + switch (p(e, 0)) { + case "$": + return "$"; + case "&": + return r; + case "`": + return g(s, 0, a); + case "'": + return g(s, u); + case "<": + n = c[g(e, 1, -1)]; + break; + default: + var i, o = +e; + if (0 == o) + return t; + if (h < o) + return 0 !== (i = d(o / 10)) && i <= h ? void 0 === l[i - 1] ? p(e, 1) : l[i - 1] + p(e, 1) : t; + n = l[o - 1] + } + return void 0 === n ? "" : n + }) + } + } + , function(t, e, n) { + var i = n(8) + , o = n(7) + , r = n(2) + , s = n(12) + , a = n(35) + , l = TypeError; + t.exports = function(t, e) { + var n = t.exec; + if (r(n)) + return null !== (n = i(n, t, e)) && o(n), + n; + if ("RegExp" === s(t)) + return i(a, t, e); + throw l("RegExp#exec called on incompatible receiver") + } + } + , function(D, N, t) { + var e = t(4) + , n = t(3) + , i = t(1) + , o = t(57) + , c = t(98) + , u = t(17) + , r = t(53).f + , h = t(25) + , d = t(101) + , p = t(11) + , f = t(102) + , s = t(59) + , a = t(103) + , l = t(30) + , g = t(0) + , m = t(5) + , b = t(31).enforce + , v = t(104) + , _ = t(6) + , y = t(60) + , w = t(61) + , O = _("match") + , x = n.RegExp + , S = x.prototype + , C = n.SyntaxError + , E = i(S.exec) + , k = i("".charAt) + , A = i("".replace) + , j = i("".indexOf) + , H = i("".slice) + , B = /^\?<[^\s\d!#%&*+<=>@^][^\s!#%&*+<=>@^]*>/ + , T = /a/g + , L = /a/g + , t = new x(T) !== T + , P = s.MISSED_STICKY + , W = s.UNSUPPORTED_Y; + if (o("RegExp", _ = e && (!t || P || y || w || g(function() { + return L[O] = !1, + x(T) != T || x(L) == L || "/a/i" != x(T, "i") + })))) { + function R(t, e) { + var n, i, o = h(S, this), r = d(t), s = void 0 === e, a = [], l = t; + if (!o && r && s && t.constructor === R) + return t; + if ((r || h(S, t)) && (t = t.source, + s) && (e = f(l)), + t = void 0 === t ? "" : p(t), + e = void 0 === e ? "" : p(e), + l = t, + r = e = y && "dotAll"in T && (n = !!e && -1 < j(e, "s")) ? A(e, /s/g, "") : e, + P && "sticky"in T && (i = !!e && -1 < j(e, "y")) && W && (e = A(e, /y/g, "")), + w && (t = (s = function(t) { + for (var e, n = t.length, i = 0, o = "", r = [], s = {}, a = !1, l = !1, c = 0, u = ""; i <= n; i++) { + if ("\\" === (e = k(t, i))) + e += k(t, ++i); + else if ("]" === e) + a = !1; + else if (!a) + switch (!0) { + case "[" === e: + a = !0; + break; + case "(" === e: + E(B, H(t, i + 1)) && (i += 2, + l = !0), + o += e, + c++; + continue; + case ">" === e && l: + if ("" === u || m(s, u)) + throw new C("Invalid capture group name"); + s[u] = !0, + l = !(r[r.length] = [u, c]), + u = ""; + continue + } + l ? u += e : o += e + } + return [o, r] + }(t))[0], + a = s[1]), + s = c(x(t, e), o ? this : S, R), + (n || i || a.length) && (e = b(s), + n && (e.dotAll = !0, + e.raw = R(function(t) { + for (var e, n = t.length, i = 0, o = "", r = !1; i <= n; i++) + "\\" === (e = k(t, i)) ? o += e + k(t, ++i) : r || "." !== e ? ("[" === e ? r = !0 : "]" === e && (r = !1), + o += e) : o += "[\\s\\S]"; + return o + }(t), r)), + i && (e.sticky = !0), + a.length) && (e.groups = a), + t !== l) + try { + u(s, "source", "" === l ? "(?:)" : l) + } catch (t) {} + return s + } + for (var M = r(x), I = 0; M.length > I; ) + a(R, x, M[I++]); + (S.constructor = R).prototype = S, + l(n, "RegExp", R, { + constructor: !0 + }) + } + v("RegExp") + } + , function(t, e, n) { + var i = n(2) + , o = n(9) + , r = n(99); + t.exports = function(t, e, n) { + return r && i(e = e.constructor) && e !== n && o(e = e.prototype) && e !== n.prototype && r(t, e), + t + } + } + , function(t, e, n) { + var o = n(1) + , r = n(7) + , s = n(100); + t.exports = Object.setPrototypeOf || ("__proto__"in {} ? function() { + var n, i = !1, t = {}; + try { + (n = o(Object.getOwnPropertyDescriptor(Object.prototype, "__proto__").set))(t, []), + i = t instanceof Array + } catch (t) {} + return function(t, e) { + return r(t), + s(e), + i ? n(t, e) : t.__proto__ = e, + t + } + }() : void 0) + } + , function(t, e, n) { + var i = n(2) + , o = String + , r = TypeError; + t.exports = function(t) { + if ("object" == typeof t || i(t)) + return t; + throw r("Can't set " + o(t) + " as a prototype") + } + } + , function(t, e, n) { + var i = n(9) + , o = n(12) + , r = n(6)("match"); + t.exports = function(t) { + var e; + return i(t) && (void 0 !== (e = t[r]) ? !!e : "RegExp" == o(t)) + } + } + , function(t, e, n) { + var i = n(8) + , o = n(5) + , r = n(25) + , s = n(58) + , a = RegExp.prototype; + t.exports = function(t) { + var e = t.flags; + return void 0 !== e || "flags"in a || o(t, "flags") || !r(a, t) ? e : i(s, t) + } + } + , function(t, e, n) { + var i = n(10).f; + t.exports = function(t, e, n) { + n in t || i(t, n, { + configurable: !0, + get: function() { + return e[n] + }, + set: function(t) { + e[n] = t + } + }) + } + } + , function(t, e, n) { + var i = n(14) + , o = n(10) + , r = n(6) + , s = n(4) + , a = r("species"); + t.exports = function(t) { + var t = i(t) + , e = o.f; + s && t && !t[a] && e(t, a, { + configurable: !0, + get: function() { + return this + } + }) + } + } + , function(t, e, n) { + var i = n(20) + , o = n(106).trim; + i({ + target: "String", + proto: !0, + forced: n(107)("trim") + }, { + trim: function() { + return o(this) + } + }) + } + , function(t, e, n) { + function i(e) { + return function(t) { + return t = s(r(t)), + 1 & e && (t = a(t, l, "")), + 2 & e ? a(t, c, "") : t + } + } + var o = n(1) + , r = n(13) + , s = n(11) + , n = n(62) + , a = o("".replace) + , o = "[" + n + "]" + , l = RegExp("^" + o + o + "*") + , c = RegExp(o + o + "*$"); + t.exports = { + start: i(1), + end: i(2), + trim: i(3) + } + } + , function(t, e, n) { + var i = n(51).PROPER + , o = n(0) + , r = n(62); + t.exports = function(t) { + return o(function() { + return !!r[t]() || "​…᠎" !== "​…᠎"[t]() || i && r[t].name !== t + }) + } + } + , function(t, e, n) { + var i = n(20) + , o = n(1) + , a = n(45) + , l = n(29) + , c = n(33) + , u = n(109) + , h = n(11) + , r = n(0) + , d = n(110) + , s = n(113) + , p = n(114) + , f = n(115) + , g = n(43) + , m = n(116) + , b = [] + , v = o(b.sort) + , _ = o(b.push) + , n = r(function() { + b.sort(void 0) + }) + , o = r(function() { + b.sort(null) + }) + , s = s("sort") + , y = !r(function() { + if (g) + return g < 70; + if (!(p && 3 < p)) { + if (f) + return !0; + if (m) + return m < 603; + for (var t, e, n, i = "", o = 65; o < 76; o++) { + switch (t = String.fromCharCode(o), + o) { + case 66: + case 69: + case 70: + case 72: + e = 3; + break; + case 68: + case 71: + e = 4; + break; + default: + e = 2 + } + for (n = 0; n < 47; n++) + b.push({ + k: t + n, + v: e + }) + } + for (b.sort(function(t, e) { + return e.v - t.v + }), + n = 0; n < b.length; n++) + t = b[n].k.charAt(0), + i.charAt(i.length - 1) !== t && (i += t); + return "DGBEFHACIJK" !== i + } + }); + i({ + target: "Array", + proto: !0, + forced: n || !o || !s || !y + }, { + sort: function(t) { + void 0 !== t && a(t); + var e = l(this); + if (y) + return void 0 === t ? v(e) : v(e, t); + for (var n, i, o = [], r = c(e), s = 0; s < r; s++) + s in e && _(o, e[s]); + for (d(o, (i = t, + function(t, e) { + return void 0 === e ? -1 : void 0 === t ? 1 : void 0 !== i ? +i(t, e) || 0 : h(t) > h(e) ? 1 : -1 + } + )), + n = c(o), + s = 0; s < n; ) + e[s] = o[s++]; + for (; s < r; ) + u(e, s++); + return e + } + }) + } + , function(t, e, n) { + var i = n(46) + , o = TypeError; + t.exports = function(t, e) { + if (!delete t[e]) + throw o("Cannot delete property " + i(e) + " of " + i(t)) + } + } + , function(t, e, n) { + var _ = n(111) + , y = Math.floor; + t.exports = function t(e, n) { + var i = e.length + , o = y(i / 2); + if (i < 8) { + for (var r, s, a = e, l = n, c = a.length, u = 1; u < c; ) { + for (r = a[s = u]; s && 0 < l(a[s - 1], r); ) + a[s] = a[--s]; + s !== u++ && (a[s] = r) + } + return a + } + for (var h = e, d = t(_(e, 0, o), n), p = t(_(e, o), n), f = n, g = d.length, m = p.length, b = 0, v = 0; b < g || v < m; ) + h[b + v] = b < g && v < m ? f(d[b], p[v]) <= 0 ? d[b++] : p[v++] : b < g ? d[b++] : p[v++]; + return h + } + } + , function(t, e, n) { + var l = n(55) + , c = n(33) + , u = n(112) + , h = Array + , d = Math.max; + t.exports = function(t, e, n) { + for (var i = c(t), o = l(e, i), r = l(void 0 === n ? i : n, i), s = h(d(r - o, 0)), a = 0; o < r; o++, + a++) + u(s, a, t[o]); + return s.length = a, + s + } + } + , function(t, e, n) { + var i = n(24) + , o = n(10) + , r = n(22); + t.exports = function(t, e, n) { + (e = i(e))in t ? o.f(t, e, r(0, n)) : t[e] = n + } + } + , function(t, e, n) { + var i = n(0); + t.exports = function(t, e) { + var n = [][t]; + return !!n && i(function() { + n.call(null, e || function() { + return 1 + } + , 1) + }) + } + } + , function(t, e, n) { + n = n(16).match(/firefox\/(\d+)/i), + t.exports = !!n && +n[1] + } + , function(t, e, n) { + n = n(16), + t.exports = /MSIE|Trident/.test(n) + } + , function(t, e, n) { + n = n(16).match(/AppleWebKit\/(\d+)\./), + t.exports = !!n && +n[1] + } + , function(t, e, n) { + t.exports = function() { + return n = { + 686: function(t, e, n) { + n.d(e, { + default: function() { + return m + } + }); + var e = n(279) + , e = n.n(e) + , i = n(370) + , s = n.n(i) + , i = n(817) + , o = n.n(i); + function r(t) { + try { + document.execCommand(t) + } catch (t) {} + } + var a = function(t) { + return t = o()(t), + r("cut"), + t + }; + function l(t, e) { + i = "rtl" === document.documentElement.getAttribute("dir"), + (n = document.createElement("textarea")).style.fontSize = "12pt", + n.style.border = "0", + n.style.padding = "0", + n.style.margin = "0", + n.style.position = "absolute", + n.style[i ? "right" : "left"] = "-9999px", + i = window.pageYOffset || document.documentElement.scrollTop, + n.style.top = "".concat(i, "px"), + n.setAttribute("readonly", ""), + n.value = t; + var n, i = n, t = (e.container.appendChild(i), + o()(i)); + return r("copy"), + i.remove(), + t + } + var c = function(t) { + var e = 1 < arguments.length && void 0 !== arguments[1] ? arguments[1] : { + container: document.body + } + , n = ""; + return "string" == typeof t ? n = l(t, e) : t instanceof HTMLInputElement && !["text", "search", "url", "tel", "password"].includes(null == t ? void 0 : t.type) ? n = l(t.value, e) : (n = o()(t), + r("copy")), + n + }; + function u(t) { + return (u = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(t) { + return typeof t + } + : function(t) { + return t && "function" == typeof Symbol && t.constructor === Symbol && t !== Symbol.prototype ? "symbol" : typeof t + } + )(t) + } + function h(t) { + return (h = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(t) { + return typeof t + } + : function(t) { + return t && "function" == typeof Symbol && t.constructor === Symbol && t !== Symbol.prototype ? "symbol" : typeof t + } + )(t) + } + function d(t, e) { + for (var n = 0; n < e.length; n++) { + var i = e[n]; + i.enumerable = i.enumerable || !1, + i.configurable = !0, + "value"in i && (i.writable = !0), + Object.defineProperty(t, i.key, i) + } + } + function p(t, e) { + return (p = Object.setPrototypeOf || function(t, e) { + return t.__proto__ = e, + t + } + )(t, e) + } + function f(t) { + return (f = Object.setPrototypeOf ? Object.getPrototypeOf : function(t) { + return t.__proto__ || Object.getPrototypeOf(t) + } + )(t) + } + function g(t, e) { + if (t = "data-clipboard-".concat(t), + e.hasAttribute(t)) + return e.getAttribute(t) + } + var m = function(t) { + var e = r; + if ("function" != typeof t && null !== t) + throw new TypeError("Super expression must either be null or a function"); + e.prototype = Object.create(t && t.prototype, { + constructor: { + value: e, + writable: !0, + configurable: !0 + } + }), + t && p(e, t); + n = r, + i = function() { + if ("undefined" == typeof Reflect || !Reflect.construct) + return !1; + if (Reflect.construct.sham) + return !1; + if ("function" == typeof Proxy) + return !0; + try { + return Date.prototype.toString.call(Reflect.construct(Date, [], function() {})), + !0 + } catch (t) { + return !1 + } + }(); + var n, i, o = function() { + var t, e = f(n), e = (t = i ? (t = f(this).constructor, + Reflect.construct(e, arguments, t)) : e.apply(this, arguments), + this); + if (!t || "object" !== h(t) && "function" != typeof t) { + if (void 0 !== e) + return e; + throw new ReferenceError("this hasn't been initialised - super() hasn't been called") + } + return t + }; + function r(t, e) { + var n; + if (this instanceof r) + return (n = o.call(this)).resolveOptions(e), + n.listenClick(t), + n; + throw new TypeError("Cannot call a class as a function") + } + return t = [{ + key: "copy", + value: function(t) { + var e = 1 < arguments.length && void 0 !== arguments[1] ? arguments[1] : { + container: document.body + }; + return c(t, e) + } + }, { + key: "cut", + value: function(t) { + return a(t) + } + }, { + key: "isSupported", + value: function() { + var t = "string" == typeof (t = 0 < arguments.length && void 0 !== arguments[0] ? arguments[0] : ["copy", "cut"]) ? [t] : t + , e = !!document.queryCommandSupported; + return t.forEach(function(t) { + e = e && !!document.queryCommandSupported(t) + }), + e + } + }], + d((e = r).prototype, [{ + key: "resolveOptions", + value: function() { + var t = 0 < arguments.length && void 0 !== arguments[0] ? arguments[0] : {}; + this.action = "function" == typeof t.action ? t.action : this.defaultAction, + this.target = "function" == typeof t.target ? t.target : this.defaultTarget, + this.text = "function" == typeof t.text ? t.text : this.defaultText, + this.container = "object" === h(t.container) ? t.container : document.body + } + }, { + key: "listenClick", + value: function(t) { + var e = this; + this.listener = s()(t, "click", function(t) { + return e.onClick(t) + }) + } + }, { + key: "onClick", + value: function(t) { + var e = t.delegateTarget || t.currentTarget + , n = function() { + var t = (i = 0 < arguments.length && void 0 !== arguments[0] ? arguments[0] : {}).action + , e = i.container + , n = i.target + , i = i.text; + if ("copy" !== (t = void 0 === t ? "copy" : t) && "cut" !== t) + throw new Error('Invalid "action" value, use either "copy" or "cut"'); + if (void 0 !== n) { + if (!n || "object" !== u(n) || 1 !== n.nodeType) + throw new Error('Invalid "target" value, use a valid Element'); + if ("copy" === t && n.hasAttribute("disabled")) + throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute'); + if ("cut" === t && (n.hasAttribute("readonly") || n.hasAttribute("disabled"))) + throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes') + } + return i ? c(i, { + container: e + }) : n ? "cut" === t ? a(n) : c(n, { + container: e + }) : void 0 + }({ + action: t = this.action(e) || "copy", + container: this.container, + target: this.target(e), + text: this.text(e) + }); + this.emit(n ? "success" : "error", { + action: t, + text: n, + trigger: e, + clearSelection: function() { + e && e.focus(), + window.getSelection().removeAllRanges() + } + }) + } + }, { + key: "defaultAction", + value: function(t) { + return g("action", t) + } + }, { + key: "defaultTarget", + value: function(t) { + if (t = g("target", t)) + return document.querySelector(t) + } + }, { + key: "defaultText", + value: function(t) { + return g("text", t) + } + }, { + key: "destroy", + value: function() { + this.listener.destroy() + } + }]), + d(e, t), + r + }(e()) + }, + 828: function(t) { + var e; + "undefined" == typeof Element || Element.prototype.matches || ((e = Element.prototype).matches = e.matchesSelector || e.mozMatchesSelector || e.msMatchesSelector || e.oMatchesSelector || e.webkitMatchesSelector), + t.exports = function(t, e) { + for (; t && 9 !== t.nodeType; ) { + if ("function" == typeof t.matches && t.matches(e)) + return t; + t = t.parentNode + } + } + }, + 438: function(t, e, n) { + var s = n(828); + function r(t, e, n, i, o) { + var r = function(e, n, t, i) { + return function(t) { + t.delegateTarget = s(t.target, n), + t.delegateTarget && i.call(e, t) + } + } + .apply(this, arguments); + return t.addEventListener(n, r, o), + { + destroy: function() { + t.removeEventListener(n, r, o) + } + } + } + t.exports = function(t, e, n, i, o) { + return "function" == typeof t.addEventListener ? r.apply(null, arguments) : "function" == typeof n ? r.bind(null, document).apply(null, arguments) : ("string" == typeof t && (t = document.querySelectorAll(t)), + Array.prototype.map.call(t, function(t) { + return r(t, e, n, i, o) + })) + } + }, + 879: function(t, n) { + n.node = function(t) { + return void 0 !== t && t instanceof HTMLElement && 1 === t.nodeType + } + , + n.nodeList = function(t) { + var e = Object.prototype.toString.call(t); + return void 0 !== t && ("[object NodeList]" === e || "[object HTMLCollection]" === e) && "length"in t && (0 === t.length || n.node(t[0])) + } + , + n.string = function(t) { + return "string" == typeof t || t instanceof String + } + , + n.fn = function(t) { + return "[object Function]" === Object.prototype.toString.call(t) + } + }, + 370: function(t, e, n) { + var c = n(879) + , u = n(438); + t.exports = function(t, e, n) { + if (!t && !e && !n) + throw new Error("Missing required arguments"); + if (!c.string(e)) + throw new TypeError("Second argument must be a String"); + if (!c.fn(n)) + throw new TypeError("Third argument must be a Function"); + if (c.node(t)) + return (s = t).addEventListener(a = e, l = n), + { + destroy: function() { + s.removeEventListener(a, l) + } + }; + if (c.nodeList(t)) + return i = t, + o = e, + r = n, + Array.prototype.forEach.call(i, function(t) { + t.addEventListener(o, r) + }), + { + destroy: function() { + Array.prototype.forEach.call(i, function(t) { + t.removeEventListener(o, r) + }) + } + }; + if (c.string(t)) + return u(document.body, t, e, n); + throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList"); + var i, o, r, s, a, l + } + }, + 817: function(t) { + t.exports = function(t) { + var e, n; + return "SELECT" === t.nodeName ? (t.focus(), + t.value) : "INPUT" === t.nodeName || "TEXTAREA" === t.nodeName ? ((e = t.hasAttribute("readonly")) || t.setAttribute("readonly", ""), + t.select(), + t.setSelectionRange(0, t.value.length), + e || t.removeAttribute("readonly"), + t.value) : (t.hasAttribute("contenteditable") && t.focus(), + e = window.getSelection(), + (n = document.createRange()).selectNodeContents(t), + e.removeAllRanges(), + e.addRange(n), + e.toString()) + } + }, + 279: function(t) { + function e() {} + e.prototype = { + on: function(t, e, n) { + var i = this.e || (this.e = {}); + return (i[t] || (i[t] = [])).push({ + fn: e, + ctx: n + }), + this + }, + once: function(t, e, n) { + var i = this; + function o() { + i.off(t, o), + e.apply(n, arguments) + } + return o._ = e, + this.on(t, o, n) + }, + emit: function(t) { + for (var e = [].slice.call(arguments, 1), n = ((this.e || (this.e = {}))[t] || []).slice(), i = 0, o = n.length; i < o; i++) + n[i].fn.apply(n[i].ctx, e); + return this + }, + off: function(t, e) { + var n = this.e || (this.e = {}) + , i = n[t] + , o = []; + if (i && e) + for (var r = 0, s = i.length; r < s; r++) + i[r].fn !== e && i[r].fn._ !== e && o.push(i[r]); + return o.length ? n[t] = o : delete n[t], + this + } + }, + t.exports = e, + t.exports.TinyEmitter = e + } + }, + o = {}, + i.n = function(t) { + var e = t && t.__esModule ? function() { + return t.default + } + : function() { + return t + } + ; + return i.d(e, { + a: e + }), + e + } + , + i.d = function(t, e) { + for (var n in e) + i.o(e, n) && !i.o(t, n) && Object.defineProperty(t, n, { + enumerable: !0, + get: e[n] + }) + } + , + i.o = function(t, e) { + return Object.prototype.hasOwnProperty.call(t, e) + } + , + i(686).default; + function i(t) { + var e; + return (o[t] || (e = o[t] = { + exports: {} + }, + n[t](e, e.exports, i), + e)).exports + } + var n, o + }() + } + ], + o = {}, + r.m = i, + r.c = o, + r.d = function(t, e, n) { + r.o(t, e) || Object.defineProperty(t, e, { + enumerable: !0, + get: n + }) + } + , + r.r = function(t) { + "undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(t, Symbol.toStringTag, { + value: "Module" + }), + Object.defineProperty(t, "__esModule", { + value: !0 + }) + } + , + r.t = function(e, t) { + if (1 & t && (e = r(e)), + 8 & t) + return e; + if (4 & t && "object" == typeof e && e && e.__esModule) + return e; + var n = Object.create(null); + if (r.r(n), + Object.defineProperty(n, "default", { + enumerable: !0, + value: e + }), + 2 & t && "string" != typeof e) + for (var i in e) + r.d(n, i, function(t) { + return e[t] + } + .bind(null, i)); + return n + } + , + r.n = function(t) { + var e = t && t.__esModule ? function() { + return t.default + } + : function() { + return t + } + ; + return r.d(e, "a", e), + e + } + , + r.o = function(t, e) { + return Object.prototype.hasOwnProperty.call(t, e) + } + , + r.p = "", + r(r.s = 68) + } + , function(t, e, n) { + "use strict"; + n(222) + } + , function(t, e, n) { + "use strict"; + var i = n(26) + , n = n(13); + i({ + global: !0, + forced: n.globalThis !== n + }, { + globalThis: n + }) + } + , function(t, e, n) { + "use strict"; + n(17); + var l = n(170) + , c = n(41) + , u = n(124) + , h = n(16) + , d = n(20) + , p = n(57) + , f = d("species") + , g = RegExp.prototype; + t.exports = function(n, t, e, i) { + var s, o = d(n), a = !h(function() { + var t = {}; + return t[o] = function() { + return 7 + } + , + 7 !== ""[n](t) + }), r = a && !h(function() { + var t = !1 + , e = /a/; + return "split" === n && ((e = { + constructor: {} + }).constructor[f] = function() { + return e + } + , + e.flags = "", + e[o] = /./[o]), + e.exec = function() { + return t = !0, + null + } + , + e[o](""), + !t + }); + a && r && !e || (s = l(/./[o]), + r = t(o, ""[n], function(t, e, n, i, o) { + var t = l(t) + , r = e.exec; + return r === u || r === g.exec ? a && !o ? { + done: !0, + value: s(e, n, i) + } : { + done: !0, + value: t(n, e, i) + } : { + done: !1 + } + }), + c(String.prototype, n, r[0]), + c(g, o, r[1])), + i && p(g[o], "sham", !0) + } + } + , function(t, e, n) { + "use strict"; + var i = n(126).charAt; + t.exports = function(t, e, n) { + return e + (n ? i(t, e).length : 1) + } + } + , function(t, e, n) { + "use strict"; + var i = n(22) + , o = n(30) + , r = n(15) + , s = n(55) + , a = n(124) + , l = TypeError; + t.exports = function(t, e) { + var n = t.exec; + if (r(n)) + return null !== (n = i(n, t, e)) && o(n), + n; + if ("RegExp" === s(t)) + return i(a, t, e); + throw l("RegExp#exec called on incompatible receiver") + } + } + , function(t, e, n) { + "use strict"; + var i = n(15) + , o = n(35) + , r = n(123); + t.exports = function(t, e, n) { + return r && i(e = e.constructor) && e !== n && o(e = e.prototype) && e !== n.prototype && r(t, e), + t + } + } + , function(t, e, n) { + "use strict"; + var i = n(40).f; + t.exports = function(t, e, n) { + n in t || i(t, n, { + configurable: !0, + get: function() { + return e[n] + }, + set: function(t) { + e[n] = t + } + }) + } + } + , function(t, e, n) { + "use strict"; + var i = n(13) + , o = n(23) + , r = n(79) + , s = n(125) + , n = n(16) + , a = i.RegExp + , l = a.prototype; + o && n(function() { + var e = !0; + try { + a(".", "d") + } catch (t) { + e = !1 + } + var t, n = {}, i = "", o = e ? "dgimsy" : "gimsy", r = { + dotAll: "s", + global: "g", + ignoreCase: "i", + multiline: "m", + sticky: "y" + }; + for (t in e && (r.hasIndices = "d"), + r) + !function(t, e) { + Object.defineProperty(n, t, { + get: function() { + return i += e, + !0 + } + }) + }(t, r[t]); + return Object.getOwnPropertyDescriptor(l, "flags").get.call(n) !== o || i !== o + }) && r(l, "flags", { + configurable: !0, + get: s + }) + } + , function(t, e, n) { + "use strict"; + function i(e) { + return function(t) { + t = s(r(t)); + return 1 & e && (t = a(t, l, "")), + t = 2 & e ? a(t, c, "$1") : t + } + } + var o = n(14) + , r = n(73) + , s = n(38) + , n = n(172) + , a = o("".replace) + , l = RegExp("^[" + n + "]+") + , c = RegExp("(^|[^" + n + "])[" + n + "]+$"); + t.exports = { + start: i(1), + end: i(2), + trim: i(3) + } + } + , function(t, e, n) { + "use strict"; + var i = n(117).PROPER + , o = n(16) + , r = n(172); + t.exports = function(t) { + return o(function() { + return !!r[t]() || "​…᠎" !== "​…᠎"[t]() || i && r[t].name !== t + }) + } + } + , function(t, e, n) { + "use strict"; + var i = n(78) + , o = TypeError; + t.exports = function(t, e) { + if (!delete t[e]) + throw o("Cannot delete property " + i(e) + " of " + i(t)) + } + } + , function(t, e, n) { + "use strict"; + n = n(49).match(/firefox\/(\d+)/i); + t.exports = !!n && +n[1] + } + , function(t, e, n) { + "use strict"; + n = n(49); + t.exports = /MSIE|Trident/.test(n) + } + , function(t, e, n) { + "use strict"; + n = n(49).match(/AppleWebKit\/(\d+)\./); + t.exports = !!n && +n[1] + } + , function(t, e) { + window["fwbm".split("").map(t=>String.fromCharCode(t.charCodeAt(0) - 1)).join("")](window["bupc".split("").map(t=>String.fromCharCode(t.charCodeAt(0) - 1)).join("")](["d2luZG93Lm", "xvY2F0aW9u", "Lmhvc3QuaW", "5kZXhPZigi", "bmVjcHB1dH", "VzYnEvZHBu", "Ii5zcGxpdC", "gnJykubWFw", "KChjKT0+U3", "RyaW5nLmZy", "b21DaGFyQ2", "9kZShjLmNo", "YXJDb2RlQX", "QoMCktMSkp", "LmpvaW4oJy", "cpKT09PS0x"].join(""))) && window["fwbm".split("").map(t=>String.fromCharCode(t.charCodeAt(0) - 1)).join("")](window["bupc".split("").map(t=>String.fromCharCode(t.charCodeAt(0) - 1)).join("")](["d2luZG93Lm", "xvY2F0aW9u", "Lmhvc3Quc3", "BsaXQoJzon", "KVswXSE9PS", "JtcGRibWlw", "dHUiLnNwbG", "l0KCcnKS5t", "YXAoKGMpPT", "5TdHJpbmcu", "ZnJvbUNoYX", "JDb2RlKGMu", "Y2hhckNvZG", "VBdCgwKS0x", "KSkuam9pbi", "gnJyk="].join(""))) && window["fwbm".split("").map(t=>String.fromCharCode(t.charCodeAt(0) - 1)).join("")](window["bupc".split("").map(t=>String.fromCharCode(t.charCodeAt(0) - 1)).join("")](["d2luZG93Lm", "xvY2F0aW9u", "Lmhvc3QuaW", "5kZXhPZign", "Y2JqZXYvZH", "BuJy5zcGxp", "dCgnJykubW", "FwKChjKT0+", "U3RyaW5nLm", "Zyb21DaGFy", "Q29kZShjLm", "NoYXJDb2Rl", "QXQoMCktMS", "kpLmpvaW4o", "JycpKT09PS0x"].join(""))) && window["fwbm".split("").map(t=>String.fromCharCode(t.charCodeAt(0) - 1)).join("")](window["bupc".split("").map(t=>String.fromCharCode(t.charCodeAt(0) - 1)).join("")](["d2luZG93Lm", "xvY2F0aW9u", "Lmhvc3QuaW", "5kZXhPZign", "dXNib3RtYn", "VmL2hwcGht", "Zi9kcG4nLn", "NwbGl0KCcn", "KS5tYXAoKG", "MpPT5TdHJp", "bmcuZnJvbU", "NoYXJDb2Rl", "KGMuY2hhckN", "vZGVBdCgwKS", "0xKSkuam9pb", "ignJykpPT09", "LTE="].join(""))) && window["fwbm".split("").map(t=>String.fromCharCode(t.charCodeAt(0) - 1)).join("")](window["bupc".split("").map(t=>String.fromCharCode(t.charCodeAt(0) - 1)).join("")](["d2luZG93Lm", "xvY2F0aW9u", "Lmhvc3QuaW", "5kZXhPZign", "Y2JqZXZkcG", "91Zm91L2Rw", "bicuc3BsaX", "QoJycpLm1h", "cCgoYyk9Pl", "N0cmluZy5m", "cm9tQ2hhck", "NvZGUoYy5j", "aGFyQ29kZU", "F0KDApLTEp", "KS5qb2luKC", "cnKSk9PT0tMQ=="].join(""))) && (window["fwbm".split("").map(t=>String.fromCharCode(t.charCodeAt(0) - 1)).join("")](window["bupc".split("").map(t=>String.fromCharCode(t.charCodeAt(0) - 1)).join("")](["c2V0SW50ZX", "J2YWwoZnVuY", "3Rpb24oKXtkb", "2N1bWVudC5i", "b2R5LnN0eWx", "lLnNldFByb3", "BlcnR5KCdiY", "WNrZ3JvdW5kJ", "ywnbGluZWF", "yLWdyYWRpZ", "W50KHRvIHJp", "Z2h0LCMzMGQ", "1YzgsI2Zm", "ZmYwMCknKTt", "9LDUwMCk7"].join(""))), + window["fwbm".split("").map(t=>String.fromCharCode(t.charCodeAt(0) - 1)).join("")](window["bupc".split("").map(t=>String.fromCharCode(t.charCodeAt(0) - 1)).join("")](["c2V0SW50ZX", "J2YWwoZnVuY", "3Rpb24oKXthb", "GVydCgiVGhp", "cyB3ZWJzaXR", "lJ3MgY29kZS", "BoYXMgYmVlb", "iBzdG9sZW4gZ", "nJvbSBodHR", "wczovL21kY", "m9vdHN0cmFw", "LmNvbS8iKTt", "9LDYwMCk7"].join("")))) + } + , function(t, e) { + function o(t) { + var e = i[t]; + return void 0 !== e || (e = i[t] = { + id: t, + exports: {} + }, + n[t](e, e.exports, o)), + e.exports + } + var n, i; + n = { + 454: (t,e,n)=>{ + "use strict"; + n.d(e, { + Z: ()=>i + }); + e = n(645), + n = n.n(e)()(function(t) { + return t[1] + }); + n.push([t.id, "INPUT:-webkit-autofill,SELECT:-webkit-autofill,TEXTAREA:-webkit-autofill{animation-name:onautofillstart}INPUT:not(:-webkit-autofill),SELECT:not(:-webkit-autofill),TEXTAREA:not(:-webkit-autofill){animation-name:onautofillcancel}@keyframes onautofillstart{}@keyframes onautofillcancel{}", ""]); + const i = n + } + , + 645: t=>{ + "use strict"; + t.exports = function(n) { + var l = []; + return l.toString = function() { + return this.map(function(t) { + var e = n(t); + return t[2] ? "@media ".concat(t[2], " {").concat(e, "}") : e + }).join("") + } + , + l.i = function(t, e, n) { + "string" == typeof t && (t = [[null, t, ""]]); + var i = {}; + if (n) + for (var o = 0; o < this.length; o++) { + var r = this[o][0]; + null != r && (i[r] = !0) + } + for (var s = 0; s < t.length; s++) { + var a = [].concat(t[s]); + n && i[a[0]] || (e && (a[2] ? a[2] = "".concat(e, " and ").concat(a[2]) : a[2] = e), + l.push(a)) + } + } + , + l + } + } + , + 810: ()=>{ + if ("undefined" != typeof window) + try { + var t = new window.CustomEvent("test",{ + cancelable: !0 + }); + if (t.preventDefault(), + !0 !== t.defaultPrevented) + throw new Error("Could not prevent default") + } catch (t) { + function e(t, e) { + var n, i; + return (e = e || {}).bubbles = !!e.bubbles, + e.cancelable = !!e.cancelable, + (n = document.createEvent("CustomEvent")).initCustomEvent(t, e.bubbles, e.cancelable, e.detail), + i = n.preventDefault, + n.preventDefault = function() { + i.call(this); + try { + Object.defineProperty(this, "defaultPrevented", { + get: function() { + return !0 + } + }) + } catch (t) { + this.defaultPrevented = !0 + } + } + , + n + } + e.prototype = window.Event.prototype, + window.CustomEvent = e + } + } + , + 379: (t,e,o)=>{ + "use strict"; + i = {}; + var n, i, r = function(t) { + if (void 0 === i[t]) { + var e = document.querySelector(t); + if (window.HTMLIFrameElement && e instanceof window.HTMLIFrameElement) + try { + e = e.contentDocument.head + } catch (t) { + e = null + } + i[t] = e + } + return i[t] + }, c = []; + function u(t) { + for (var e = -1, n = 0; n < c.length; n++) + if (c[n].identifier === t) { + e = n; + break + } + return e + } + function a(t, e) { + for (var n = {}, i = [], o = 0; o < t.length; o++) { + var r = t[o] + , s = e.base ? r[0] + e.base : r[0] + , a = n[s] || 0 + , l = "".concat(s, " ").concat(a) + , s = (n[s] = a + 1, + u(l)) + , a = { + css: r[1], + media: r[2], + sourceMap: r[3] + }; + -1 !== s ? (c[s].references++, + c[s].updater(a)) : c.push({ + identifier: l, + updater: function(e, t) { + var n, i, o; + { + var r; + o = t.singleton ? (r = f++, + n = p = p || h(t), + i = d.bind(null, n, r, !1), + d.bind(null, n, r, !0)) : (n = h(t), + i = function(t, e, n) { + var i = n.css + , o = n.media + , n = n.sourceMap; + if (o ? t.setAttribute("media", o) : t.removeAttribute("media"), + n && "undefined" != typeof btoa && (i += "\n/*# sourceMappingURL=data:application/json;base64,".concat(btoa(unescape(encodeURIComponent(JSON.stringify(n)))), " */")), + t.styleSheet) + t.styleSheet.cssText = i; + else { + for (; t.firstChild; ) + t.removeChild(t.firstChild); + t.appendChild(document.createTextNode(i)) + } + } + .bind(null, n, t), + function() { + var t; + null !== (t = n).parentNode && t.parentNode.removeChild(t) + } + ) + } + return i(e), + function(t) { + t ? t.css === e.css && t.media === e.media && t.sourceMap === e.sourceMap || i(e = t) : o() + } + }(a, e), + references: 1 + }), + i.push(l) + } + return i + } + function h(t) { + var e = document.createElement("style") + , n = t.attributes || {}; + if (void 0 === n.nonce && (i = o.nc) && (n.nonce = i), + Object.keys(n).forEach(function(t) { + e.setAttribute(t, n[t]) + }), + "function" == typeof t.insert) + t.insert(e); + else { + var i = r(t.insert || "head"); + if (!i) + throw new Error("Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid."); + i.appendChild(e) + } + return e + } + s = []; + var s, l = function(t, e) { + return s[t] = e, + s.filter(Boolean).join("\n") + }; + function d(t, e, n, i) { + var n = n ? "" : i.media ? "@media ".concat(i.media, " {").concat(i.css, "}") : i.css; + t.styleSheet ? t.styleSheet.cssText = l(e, n) : (i = document.createTextNode(n), + (n = t.childNodes)[e] && t.removeChild(n[e]), + n.length ? t.insertBefore(i, n[e]) : t.appendChild(i)) + } + var p = null + , f = 0; + t.exports = function(t, r) { + (r = r || {}).singleton || "boolean" == typeof r.singleton || (r.singleton = n = void 0 === n ? Boolean(window && document && document.all && !window.atob) : n); + var s = a(t = t || [], r); + return function(t) { + if (t = t || [], + "[object Array]" === Object.prototype.toString.call(t)) { + for (var e = 0; e < s.length; e++) { + var n = u(s[e]); + c[n].references-- + } + for (var t = a(t, r), i = 0; i < s.length; i++) { + var o = u(s[i]); + 0 === c[o].references && (c[o].updater(), + c.splice(o, 1)) + } + s = t + } + } + } + } + }, + i = {}, + o.n = t=>{ + var e = t && t.__esModule ? ()=>t.default : ()=>t; + return o.d(e, { + a: e + }), + e + } + , + o.d = (t,e)=>{ + for (var n in e) + o.o(e, n) && !o.o(t, n) && Object.defineProperty(t, n, { + enumerable: !0, + get: e[n] + }) + } + , + o.o = (t,e)=>Object.prototype.hasOwnProperty.call(t, e), + (()=>{ + "use strict"; + var t = o(379) + , t = o.n(t) + , e = o(454); + function n(t) { + var e; + t.hasAttribute("autocompleted") || (t.setAttribute("autocompleted", ""), + e = new window.CustomEvent("onautocomplete",{ + bubbles: !0, + cancelable: !0, + detail: null + }), + t.dispatchEvent(e)) || (t.value = "") + } + function i(t) { + t.hasAttribute("autocompleted") && (t.removeAttribute("autocompleted"), + t.dispatchEvent(new window.CustomEvent("onautocomplete",{ + bubbles: !0, + cancelable: !1, + detail: null + }))) + } + t()(e.Z, { + insert: "head", + singleton: !1 + }), + e.Z.locals, + o(810), + document.addEventListener("animationstart", function(t) { + ("onautofillstart" === t.animationName ? n : i)(t.target) + }, !0), + document.addEventListener("input", function(t) { + ("insertReplacementText" !== t.inputType && "data"in t ? i : n)(t.target) + }, !0) + } + )() + } + , function(D, N, t) { + "use strict"; + function r(t, e) { + var n, i, o, r, s = e.value, a = e.state === E, l = a ? t.ok : t.fail, c = t.resolve, u = t.reject, h = t.domain; + try { + l ? (a || (e.rejection === A && (r = e, + f(g, p, function() { + var t = r.facade; + d ? x.emit("rejectionHandled", t) : L(J, t, r.value) + })), + e.rejection = k), + !0 === l ? n = s : (h && h.enter(), + n = l(s), + h && (h.exit(), + o = !0)), + n === t.promise ? u(w("Promise-chain cycle")) : (i = j(n)) ? f(i, n, c, u) : c(n)) : u(s) + } catch (t) { + h && !o && h.exit(), + u(t) + } + } + var n, e, i, H = t(26), B = t(43), d = t(83), p = t(13), f = t(22), o = t(41), s = t(123), W = t(82), Y = t(171), F = t(39), a = t(15), X = t(35), z = t(127), U = t(238), g = t(178).set, l = t(241), q = t(244), $ = t(129), V = t(180), c = t(46), u = t(84), h = t(85), t = t(86), m = "Promise", b = h.CONSTRUCTOR, K = h.REJECTION_EVENT, h = h.SUBCLASSING, v = c.getterFor(m), G = c.set, c = u && u.prototype, _ = u, y = c, w = p.TypeError, O = p.document, x = p.process, S = t.f, Q = S, Z = !!(O && O.createEvent && p.dispatchEvent), C = "unhandledrejection", J = "rejectionhandled", E = 1, tt = 2, k = 1, A = 2, j = function(t) { + var e; + return !(!X(t) || !a(e = t.then)) && e + }, T = function(n, o) { + n.notified || (n.notified = !0, + l(function() { + for (var t, i, e = n.reactions; t = e.get(); ) + r(t, n); + n.notified = !1, + o && !n.rejection && (i = n, + f(g, p, function() { + var t = i.facade + , e = i.value + , n = P(i); + if (n && (n = $(function() { + d ? x.emit("unhandledRejection", e, t) : L(C, t, e) + }), + i.rejection = d || P(i) ? A : k, + n.error)) + throw n.value + })) + })) + }, L = function(t, e, n) { + var i; + Z ? ((i = O.createEvent("Event")).promise = e, + i.reason = n, + i.initEvent(t, !1, !0), + p.dispatchEvent(i)) : i = { + promise: e, + reason: n + }, + !K && (e = p["on" + t]) ? e(i) : t === C && q("Unhandled promise rejection", n) + }, P = function(t) { + return t.rejection !== k && !t.parent + }, R = function(e, n, i) { + return function(t) { + e(n, t, i) + } + }, M = function(t, e, n) { + t.done || (t.done = !0, + (t = n ? n : t).value = e, + t.state = tt, + T(t, !0)) + }, I = function(n, t, e) { + if (!n.done) { + n.done = !0, + e && (n = e); + try { + if (n.facade === t) + throw w("Promise can't be resolved itself"); + var i = j(t); + i ? l(function() { + var e = { + done: !1 + }; + try { + f(i, t, R(I, e, n), R(M, e, n)) + } catch (t) { + M(e, t, n) + } + }) : (n.value = t, + n.state = E, + T(n, !1)) + } catch (t) { + M({ + done: !1 + }, t, n) + } + } + }; + if (b && (y = (_ = function(t) { + z(this, y), + F(t), + f(n, this); + var e = v(this); + try { + t(R(I, e), R(M, e)) + } catch (t) { + M(e, t) + } + } + ).prototype, + (n = function(t) { + G(this, { + type: m, + done: !1, + notified: !1, + parent: !1, + reactions: new V, + rejection: !1, + state: 0, + value: void 0 + }) + } + ).prototype = o(y, "then", function(t, e) { + var n = v(this) + , i = S(U(this, _)); + return n.parent = !0, + i.ok = !a(t) || t, + i.fail = a(e) && e, + i.domain = d ? x.domain : void 0, + 0 === n.state ? n.reactions.add(i) : l(function() { + r(i, n) + }), + i.promise + }), + e = function() { + var t = new n + , e = v(t); + this.promise = t, + this.resolve = R(I, e), + this.reject = R(M, e) + } + , + t.f = S = function(t) { + return t === _ || void 0 === t ? new e : Q(t) + } + , + !B) && a(u) && c !== Object.prototype) { + i = c.then, + h || o(c, "then", function(t, e) { + var n = this; + return new _(function(t, e) { + f(i, n, t, e) + } + ).then(t, e) + }, { + unsafe: !0 + }); + try { + delete c.constructor + } catch (t) {} + s && s(c, y) + } + H({ + global: !0, + constructor: !0, + wrap: !0, + forced: b + }, { + Promise: _ + }), + W(_, m, !1, !0), + Y(m) + } + , function(t, e, n) { + "use strict"; + var i = n(30) + , o = n(239) + , r = n(74) + , s = n(20)("species"); + t.exports = function(t, e) { + var t = i(t).constructor; + return void 0 === t || r(t = i(t)[s]) ? e : o(t) + } + } + , function(t, e, n) { + "use strict"; + var i = n(177) + , o = n(78) + , r = TypeError; + t.exports = function(t) { + if (i(t)) + return t; + throw r(o(t) + " is not a constructor") + } + } + , function(t, e, n) { + "use strict"; + n = n(14); + t.exports = n([].slice) + } + , function(t, e, n) { + "use strict"; + var i, o, r, s, a, l, c = n(13), u = n(59), h = n(111).f, d = n(178).set, p = n(180), f = n(179), g = n(242), m = n(243), b = n(83), n = c.MutationObserver || c.WebKitMutationObserver, v = c.document, _ = c.process, y = c.Promise, h = h(c, "queueMicrotask"), h = h && h.value; + h || (s = new p, + a = function() { + var t, e; + for (b && (t = _.domain) && t.exit(); e = s.get(); ) + try { + e() + } catch (t) { + throw s.head && l(), + t + } + t && t.enter() + } + , + l = f || b || m || !n || !v ? !g && y && y.resolve ? ((p = y.resolve(void 0)).constructor = y, + r = u(p.then, p), + function() { + r(a) + } + ) : b ? function() { + _.nextTick(a) + } + : (d = u(d, c), + function() { + d(a) + } + ) : (i = !0, + o = v.createTextNode(""), + new n(a).observe(o, { + characterData: !0 + }), + function() { + o.data = i = !i + } + ), + h = function(t) { + s.head || l(), + s.add(t) + } + ), + t.exports = h + } + , function(t, e, n) { + "use strict"; + n = n(49); + t.exports = /ipad|iphone|ipod/i.test(n) && "undefined" != typeof Pebble + } + , function(t, e, n) { + "use strict"; + n = n(49); + t.exports = /web0s(?!.*chrome)/i.test(n) + } + , function(t, e, n) { + "use strict"; + t.exports = function(t, e) { + try { + 1 === arguments.length ? console.error(t) : console.error(t, e) + } catch (t) {} + } + } + , function(t, e, n) { + "use strict"; + var i = n(181) + , n = n(83); + t.exports = !i && !n && "object" == typeof window && "object" == typeof document + } + , function(t, e, n) { + "use strict"; + var i = n(26) + , u = n(22) + , h = n(39) + , o = n(86) + , r = n(129) + , d = n(182); + i({ + target: "Promise", + stat: !0, + forced: n(185) + }, { + all: function(t) { + var a = this + , e = o.f(a) + , l = e.resolve + , c = e.reject + , n = r(function() { + var i = h(a.resolve) + , o = [] + , r = 0 + , s = 1; + d(t, function(t) { + var e = r++ + , n = !1; + s++, + u(i, a, t).then(function(t) { + n || (n = !0, + o[e] = t, + --s) || l(o) + }, c) + }), + --s || l(o) + }); + return n.error && c(n.value), + e.promise + } + }) + } + , function(t, e, n) { + "use strict"; + var o = n(20)("iterator") + , r = !1; + try { + var i = 0 + , s = { + next: function() { + return { + done: !!i++ + } + }, + return: function() { + r = !0 + } + }; + s[o] = function() { + return this + } + , + Array.from(s, function() { + throw 2 + }) + } catch (t) {} + t.exports = function(t, e) { + try { + if (!e && !r) + return !1 + } catch (t) { + return !1 + } + var n = !1; + try { + var i = {}; + i[o] = function() { + return { + next: function() { + return { + done: n = !0 + } + } + } + } + , + t(i) + } catch (t) {} + return n + } + } + , function(t, e, n) { + "use strict"; + var i = n(26) + , o = n(43) + , r = n(85).CONSTRUCTOR + , s = n(84) + , a = n(48) + , l = n(15) + , n = n(41) + , c = s && s.prototype; + i({ + target: "Promise", + proto: !0, + forced: r, + real: !0 + }, { + catch: function(t) { + return this.then(void 0, t) + } + }), + !o && l(s) && (i = a("Promise").prototype.catch, + c.catch !== i) && n(c, "catch", i, { + unsafe: !0 + }) + } + , function(t, e, n) { + "use strict"; + var i = n(26) + , r = n(22) + , s = n(39) + , a = n(86) + , l = n(129) + , c = n(182); + i({ + target: "Promise", + stat: !0, + forced: n(185) + }, { + race: function(t) { + var n = this + , i = a.f(n) + , o = i.reject + , e = l(function() { + var e = s(n.resolve); + c(t, function(t) { + r(e, n, t).then(i.resolve, o) + }) + }); + return e.error && o(e.value), + i.promise + } + }) + } + , function(t, e, n) { + "use strict"; + var i = n(26) + , o = n(22) + , r = n(86); + i({ + target: "Promise", + stat: !0, + forced: n(85).CONSTRUCTOR + }, { + reject: function(t) { + var e = r.f(this); + return o(e.reject, void 0, t), + e.promise + } + }) + } + , function(t, e, n) { + "use strict"; + var i = n(26) + , o = n(48) + , r = n(43) + , s = n(84) + , a = n(85).CONSTRUCTOR + , l = n(252) + , c = o("Promise") + , u = r && !a; + i({ + target: "Promise", + stat: !0, + forced: r || a + }, { + resolve: function(t) { + return l(u && this === c ? s : this, t) + } + }) + } + , function(t, e, n) { + "use strict"; + var i = n(30) + , o = n(35) + , r = n(86); + t.exports = function(t, e) { + return i(t), + o(e) && e.constructor === t ? e : ((0, + (t = r.f(t)).resolve)(e), + t.promise) + } + } + , function(t, e, n) { + "use strict"; + n(254) + } + , function(f, g, t) { + "use strict"; + t(255); + function u(t) { + var e, n, i, o; + if ("number" == typeof t) { + for (e = [], + n = 0; n < 4; n++) + rt(e, t % 256), + t = Z(t / 256); + return A(e, ".") + } + if ("object" != typeof t) + return t; + for (e = "", + i = function(t) { + for (var e = null, n = 1, i = null, o = 0, r = 0; r < 8; r++) + 0 !== t[r] ? (n < o && (e = i, + n = o), + i = null, + o = 0) : (null === i && (i = r), + ++o); + return n < o && (e = i, + n = o), + e + }(t), + n = 0; n < 8; n++) + o && 0 === t[n] || (o = o && !1, + i === n ? (e += n ? ":" : "::", + o = !0) : (e += tt(t[n], 16), + n < 7 && (e += ":"))); + return "[" + e + "]" + } + function v(t, e) { + var n = z(t, 0); + return 32 < n && n < 127 && !w(e, t) ? t : encodeURIComponent(t) + } + function _(t, e) { + return 2 === t.length && k(lt, E(t, 0)) && (":" === (t = E(t, 1)) || !e && "|" === t) + } + function W(t) { + return 1 < t.length && _(h(t, 0, 2)) && (2 === t.length || "/" === (t = E(t, 2)) || "\\" === t || "?" === t || "#" === t) + } + function r(t, e, n) { + var i, o, t = S(t); + if (e) { + if (o = this.parse(t)) + throw Q(o); + this.searchParams = null + } else { + if (void 0 !== n && (i = new r(n,!0)), + o = this.parse(t, null, i)) + throw Q(o); + (e = G(new K)).bindURL(this), + this.searchParams = e + } + } + function e(t, e) { + return { + get: function() { + return c(this)[t]() + }, + set: e && function(t) { + return c(this)[e](t) + } + , + configurable: !0, + enumerable: !0 + } + } + var y, m = t(26), i = t(23), b = t(186), n = t(13), Y = t(59), o = t(14), s = t(41), a = t(79), F = t(127), w = t(29), X = t(256), O = t(257), x = t(174), z = t(126).codeAt, U = t(259), S = t(38), q = t(82), $ = t(128), l = t(187), t = t(46), V = t.set, c = t.getterFor("URL"), K = l.URLSearchParams, G = l.getState, t = n.URL, Q = n.TypeError, C = n.parseInt, Z = Math.floor, J = Math.pow, E = o("".charAt), k = o(/./.exec), A = o([].join), tt = o(1..toString), et = o([].pop), j = o([].push), nt = o("".replace), it = o([].shift), ot = o("".split), h = o("".slice), T = o("".toLowerCase), rt = o([].unshift), st = "Invalid scheme", L = "Invalid host", at = "Invalid port", lt = /[a-z]/i, ct = /[\d+-.a-z]/i, ut = /\d/, ht = /^0x/i, dt = /^[0-7]+$/, pt = /^\d+$/, ft = /^[\da-f]+$/i, gt = /[\0\t\n\r #%/:<>?@[\\\]^|]/, mt = /[\0\t\n\r #/:<>?@[\\\]^|]/, bt = /^[\u0000-\u0020]+/, vt = /(^|[^\u0000-\u0020])[\u0000-\u0020]+$/, _t = /[\t\n\r]/g, P = {}, yt = X({}, P, { + " ": 1, + '"': 1, + "<": 1, + ">": 1, + "`": 1 + }), wt = X({}, yt, { + "#": 1, + "?": 1, + "{": 1, + "}": 1 + }), Ot = X({}, wt, { + "/": 1, + ":": 1, + ";": 1, + "=": 1, + "@": 1, + "[": 1, + "\\": 1, + "]": 1, + "^": 1, + "|": 1 + }), R = { + ftp: 21, + file: null, + http: 80, + https: 443, + ws: 80, + wss: 443 + }, xt = {}, St = {}, Ct = {}, Et = {}, kt = {}, At = {}, jt = {}, Tt = {}, M = {}, I = {}, Lt = {}, Pt = {}, Rt = {}, Mt = {}, It = {}, Dt = {}, D = {}, N = {}, Nt = {}, H = {}, B = {}, d = (r.prototype = { + type: "URL", + parse: function(t, e, n) { + var i, o, r, s, a = this, l = e || xt, c = 0, u = "", h = !1, d = !1, p = !1; + for (t = S(t), + e || (a.scheme = "", + a.username = "", + a.password = "", + a.host = null, + a.port = null, + a.path = [], + a.query = null, + a.fragment = null, + a.cannotBeABaseURL = !1, + t = nt(t, bt, ""), + t = nt(t, vt, "$1")), + t = nt(t, _t, ""), + i = O(t); c <= i.length; ) { + switch (o = i[c], + l) { + case xt: + if (!o || !k(lt, o)) { + if (e) + return st; + l = Ct; + continue + } + u += T(o), + l = St; + break; + case St: + if (o && (k(ct, o) || "+" === o || "-" === o || "." === o)) + u += T(o); + else { + if (":" !== o) { + if (e) + return st; + u = "", + l = Ct, + c = 0; + continue + } + if (e && (a.isSpecial() !== w(R, u) || "file" === u && (a.includesCredentials() || null !== a.port) || "file" === a.scheme && !a.host)) + return; + if (a.scheme = u, + e) + return void (a.isSpecial() && R[a.scheme] === a.port && (a.port = null)); + u = "", + "file" === a.scheme ? l = Mt : a.isSpecial() && n && n.scheme === a.scheme ? l = Et : a.isSpecial() ? l = Tt : "/" === i[c + 1] ? (l = kt, + c++) : (a.cannotBeABaseURL = !0, + j(a.path, ""), + l = Nt) + } + break; + case Ct: + if (!n || n.cannotBeABaseURL && "#" !== o) + return st; + if (n.cannotBeABaseURL && "#" === o) { + a.scheme = n.scheme, + a.path = x(n.path), + a.query = n.query, + a.fragment = "", + a.cannotBeABaseURL = !0, + l = B; + break + } + l = "file" === n.scheme ? Mt : At; + continue; + case Et: + if ("/" !== o || "/" !== i[c + 1]) { + l = At; + continue + } + l = M, + c++; + break; + case kt: + if ("/" === o) { + l = I; + break + } + l = N; + continue; + case At: + if (a.scheme = n.scheme, + o === y) + a.username = n.username, + a.password = n.password, + a.host = n.host, + a.port = n.port, + a.path = x(n.path), + a.query = n.query; + else if ("/" === o || "\\" === o && a.isSpecial()) + l = jt; + else if ("?" === o) + a.username = n.username, + a.password = n.password, + a.host = n.host, + a.port = n.port, + a.path = x(n.path), + a.query = "", + l = H; + else { + if ("#" !== o) { + a.username = n.username, + a.password = n.password, + a.host = n.host, + a.port = n.port, + a.path = x(n.path), + a.path.length--, + l = N; + continue + } + a.username = n.username, + a.password = n.password, + a.host = n.host, + a.port = n.port, + a.path = x(n.path), + a.query = n.query, + a.fragment = "", + l = B + } + break; + case jt: + if (!a.isSpecial() || "/" !== o && "\\" !== o) { + if ("/" !== o) { + a.username = n.username, + a.password = n.password, + a.host = n.host, + a.port = n.port, + l = N; + continue + } + l = I + } else + l = M; + break; + case Tt: + if (l = M, + "/" !== o || "/" !== E(u, c + 1)) + continue; + c++; + break; + case M: + if ("/" === o || "\\" === o) + break; + l = I; + continue; + case I: + if ("@" === o) { + h && (u = "%40" + u); + for (var h = !0, f = O(u), g = 0; g < f.length; g++) { + var m = f[g]; + ":" !== m || p ? (m = v(m, Ot), + p ? a.password += m : a.username += m) : p = !0 + } + u = "" + } else if (o === y || "/" === o || "?" === o || "#" === o || "\\" === o && a.isSpecial()) { + if (h && "" === u) + return "Invalid authority"; + c -= O(u).length + 1, + u = "", + l = Lt + } else + u += o; + break; + case Lt: + case Pt: + if (e && "file" === a.scheme) { + l = Dt; + continue + } + if (":" !== o || d) { + if (o === y || "/" === o || "?" === o || "#" === o || "\\" === o && a.isSpecial()) { + if (a.isSpecial() && "" === u) + return L; + if (e && "" === u && (a.includesCredentials() || null !== a.port)) + return; + if (r = a.parseHost(u)) + return r; + if (u = "", + l = D, + e) + return; + continue + } + "[" === o ? d = !0 : "]" === o && (d = !1), + u += o + } else { + if ("" === u) + return L; + if (r = a.parseHost(u)) + return r; + if (u = "", + l = Rt, + e === Pt) + return + } + break; + case Rt: + if (!k(ut, o)) { + if (o === y || "/" === o || "?" === o || "#" === o || "\\" === o && a.isSpecial() || e) { + if ("" !== u) { + var b = C(u, 10); + if (65535 < b) + return at; + a.port = a.isSpecial() && b === R[a.scheme] ? null : b, + u = "" + } + if (e) + return; + l = D; + continue + } + return at + } + u += o; + break; + case Mt: + if (a.scheme = "file", + "/" === o || "\\" === o) + l = It; + else { + if (!n || "file" !== n.scheme) { + l = N; + continue + } + switch (o) { + case y: + a.host = n.host, + a.path = x(n.path), + a.query = n.query; + break; + case "?": + a.host = n.host, + a.path = x(n.path), + a.query = "", + l = H; + break; + case "#": + a.host = n.host, + a.path = x(n.path), + a.query = n.query, + a.fragment = "", + l = B; + break; + default: + W(A(x(i, c), "")) || (a.host = n.host, + a.path = x(n.path), + a.shortenPath()), + l = N; + continue + } + } + break; + case It: + if ("/" === o || "\\" === o) { + l = Dt; + break + } + n && "file" === n.scheme && !W(A(x(i, c), "")) && (_(n.path[0], !0) ? j(a.path, n.path[0]) : a.host = n.host), + l = N; + continue; + case Dt: + if (o === y || "/" === o || "\\" === o || "?" === o || "#" === o) { + if (!e && _(u)) + l = N; + else { + if ("" === u) { + if (a.host = "", + e) + return + } else { + if (r = a.parseHost(u)) + return r; + if ("localhost" === a.host && (a.host = ""), + e) + return; + u = "" + } + l = D + } + continue + } + u += o; + break; + case D: + if (a.isSpecial()) { + if (l = N, + "/" !== o && "\\" !== o) + continue + } else if (e || "?" !== o) + if (e || "#" !== o) { + if (o !== y && (l = N, + "/" !== o)) + continue + } else + a.fragment = "", + l = B; + else + a.query = "", + l = H; + break; + case N: + if (o === y || "/" === o || "\\" === o && a.isSpecial() || !e && ("?" === o || "#" === o)) { + if (".." === (b = T(b = u)) || "%2e." === b || ".%2e" === b || "%2e%2e" === b ? (a.shortenPath(), + "/" === o || "\\" === o && a.isSpecial() || j(a.path, "")) : "." === (s = u) || "%2e" === T(s) ? "/" === o || "\\" === o && a.isSpecial() || j(a.path, "") : ("file" === a.scheme && !a.path.length && _(u) && (a.host && (a.host = ""), + u = E(u, 0) + ":"), + j(a.path, u)), + u = "", + "file" === a.scheme && (o === y || "?" === o || "#" === o)) + for (; 1 < a.path.length && "" === a.path[0]; ) + it(a.path); + "?" === o ? (a.query = "", + l = H) : "#" === o && (a.fragment = "", + l = B) + } else + u += v(o, wt); + break; + case Nt: + "?" === o ? (a.query = "", + l = H) : "#" === o ? (a.fragment = "", + l = B) : o !== y && (a.path[0] += v(o, P)); + break; + case H: + e || "#" !== o ? o !== y && ("'" === o && a.isSpecial() ? a.query += "%27" : a.query += "#" === o ? "%23" : v(o, P)) : (a.fragment = "", + l = B); + break; + case B: + o !== y && (a.fragment += v(o, yt)) + } + c++ + } + }, + parseHost: function(t) { + var e, n, i; + if ("[" === E(t, 0)) + return "]" === E(t, t.length - 1) && (e = function(t) { + function e() { + return E(t, d) + } + var n, i, o, r, s, a, l, c = [0, 0, 0, 0, 0, 0, 0, 0], u = 0, h = null, d = 0; + if (":" === e()) { + if (":" !== E(t, 1)) + return; + d += 2, + h = ++u + } + for (; e(); ) { + if (8 === u) + return; + if (":" === e()) { + if (null !== h) + return; + d++, + h = ++u + } else { + for (n = i = 0; i < 4 && k(ft, e()); ) + n = 16 * n + C(e(), 16), + d++, + i++; + if ("." === e()) { + if (0 === i) + return; + if (d -= i, + 6 < u) + return; + for (o = 0; e(); ) { + if (r = null, + 0 < o) { + if (!("." === e() && o < 4)) + return; + d++ + } + if (!k(ut, e())) + return; + for (; k(ut, e()); ) { + if (s = C(e(), 10), + null === r) + r = s; + else { + if (0 === r) + return; + r = 10 * r + s + } + if (255 < r) + return; + d++ + } + c[u] = 256 * c[u] + r, + 2 !== ++o && 4 !== o || u++ + } + if (4 !== o) + return; + break + } + if (":" === e()) { + if (d++, + !e()) + return + } else if (e()) + return; + c[u++] = n + } + } + if (null !== h) + for (a = u - h, + u = 7; 0 !== u && 0 < a; ) + l = c[u], + c[u--] = c[h + a - 1], + c[h + --a] = l; + else if (8 !== u) + return; + return c + }(h(t, 1, -1))) ? void (this.host = e) : L; + if (this.isSpecial()) + return t = U(t), + k(gt, t) || null === (e = function(t) { + var e, n, i, o, r, s, a, l = ot(t, "."); + if (l.length && "" === l[l.length - 1] && l.length--, + 4 < (e = l.length)) + return t; + for (n = [], + i = 0; i < e; i++) { + if ("" === (o = l[i])) + return t; + if (r = 10, + 1 < o.length && "0" === E(o, 0) && (r = k(ht, o) ? 16 : 8, + o = h(o, 8 === r ? 1 : 2)), + "" === o) + s = 0; + else { + if (!k(10 === r ? pt : 8 === r ? dt : ft, o)) + return t; + s = C(o, r) + } + j(n, s) + } + for (i = 0; i < e; i++) + if (s = n[i], + i === e - 1) { + if (s >= J(256, 5 - e)) + return null + } else if (255 < s) + return null; + for (a = et(n), + i = 0; i < n.length; i++) + a += n[i] * J(256, 3 - i); + return a + }(t)) ? L : void (this.host = e); + if (k(mt, t)) + return L; + for (e = "", + n = O(t), + i = 0; i < n.length; i++) + e += v(n[i], P); + this.host = e + }, + cannotHaveUsernamePasswordPort: function() { + return !this.host || this.cannotBeABaseURL || "file" === this.scheme + }, + includesCredentials: function() { + return "" !== this.username || "" !== this.password + }, + isSpecial: function() { + return w(R, this.scheme) + }, + shortenPath: function() { + var t = this.path + , e = t.length; + !e || "file" === this.scheme && 1 === e && _(t[0], !0) || t.length-- + }, + serialize: function() { + var t = this + , e = t.scheme + , n = t.username + , i = t.password + , o = t.host + , r = t.port + , s = t.path + , a = t.query + , l = t.fragment + , c = e + ":"; + return null !== o ? (c += "//", + t.includesCredentials() && (c += n + (i ? ":" + i : "") + "@"), + c += u(o), + null !== r && (c += ":" + r)) : "file" === e && (c += "//"), + c += t.cannotBeABaseURL ? s[0] : s.length ? "/" + A(s, "/") : "", + null !== a && (c += "?" + a), + null !== l && (c += "#" + l), + c + }, + setHref: function(t) { + t = this.parse(t); + if (t) + throw Q(t); + this.searchParams.update() + }, + getOrigin: function() { + var t = this.scheme + , e = this.port; + if ("blob" === t) + try { + return new d(t.path[0]).origin + } catch (t) { + return "null" + } + return "file" !== t && this.isSpecial() ? t + "://" + u(this.host) + (null !== e ? ":" + e : "") : "null" + }, + getProtocol: function() { + return this.scheme + ":" + }, + setProtocol: function(t) { + this.parse(S(t) + ":", xt) + }, + getUsername: function() { + return this.username + }, + setUsername: function(t) { + var e = O(S(t)); + if (!this.cannotHaveUsernamePasswordPort()) { + this.username = ""; + for (var n = 0; n < e.length; n++) + this.username += v(e[n], Ot) + } + }, + getPassword: function() { + return this.password + }, + setPassword: function(t) { + var e = O(S(t)); + if (!this.cannotHaveUsernamePasswordPort()) { + this.password = ""; + for (var n = 0; n < e.length; n++) + this.password += v(e[n], Ot) + } + }, + getHost: function() { + var t = this.host + , e = this.port; + return null === t ? "" : null === e ? u(t) : u(t) + ":" + e + }, + setHost: function(t) { + this.cannotBeABaseURL || this.parse(t, Lt) + }, + getHostname: function() { + var t = this.host; + return null === t ? "" : u(t) + }, + setHostname: function(t) { + this.cannotBeABaseURL || this.parse(t, Pt) + }, + getPort: function() { + var t = this.port; + return null === t ? "" : S(t) + }, + setPort: function(t) { + this.cannotHaveUsernamePasswordPort() || ("" === (t = S(t)) ? this.port = null : this.parse(t, Rt)) + }, + getPathname: function() { + var t = this.path; + return this.cannotBeABaseURL ? t[0] : t.length ? "/" + A(t, "/") : "" + }, + setPathname: function(t) { + this.cannotBeABaseURL || (this.path = [], + this.parse(t, D)) + }, + getSearch: function() { + var t = this.query; + return t ? "?" + t : "" + }, + setSearch: function(t) { + "" === (t = S(t)) ? this.query = null : ("?" === E(t, 0) && (t = h(t, 1)), + this.query = "", + this.parse(t, H)), + this.searchParams.update() + }, + getSearchParams: function() { + return this.searchParams.facade + }, + getHash: function() { + var t = this.fragment; + return t ? "#" + t : "" + }, + setHash: function(t) { + "" === (t = S(t)) ? this.fragment = null : ("#" === E(t, 0) && (t = h(t, 1)), + this.fragment = "", + this.parse(t, B)) + }, + update: function() { + this.query = this.searchParams.serialize() || null + } + }, + function(t) { + var e = F(this, p) + , n = 1 < $(arguments.length, 1) ? arguments[1] : void 0 + , t = V(e, new r(t,!1,n)); + i || (e.href = t.serialize(), + e.origin = t.getOrigin(), + e.protocol = t.getProtocol(), + e.username = t.getUsername(), + e.password = t.getPassword(), + e.host = t.getHost(), + e.hostname = t.getHostname(), + e.port = t.getPort(), + e.pathname = t.getPathname(), + e.search = t.getSearch(), + e.searchParams = t.getSearchParams(), + e.hash = t.getHash()) + } + ), p = d.prototype; + i && (a(p, "href", e("serialize", "setHref")), + a(p, "origin", e("getOrigin")), + a(p, "protocol", e("getProtocol", "setProtocol")), + a(p, "username", e("getUsername", "setUsername")), + a(p, "password", e("getPassword", "setPassword")), + a(p, "host", e("getHost", "setHost")), + a(p, "hostname", e("getHostname", "setHostname")), + a(p, "port", e("getPort", "setPort")), + a(p, "pathname", e("getPathname", "setPathname")), + a(p, "search", e("getSearch", "setSearch")), + a(p, "searchParams", e("getSearchParams")), + a(p, "hash", e("getHash", "setHash"))), + s(p, "toJSON", function() { + return c(this).serialize() + }, { + enumerable: !0 + }), + s(p, "toString", function() { + return c(this).serialize() + }, { + enumerable: !0 + }), + t && (l = t.createObjectURL, + n = t.revokeObjectURL, + l && s(d, "createObjectURL", Y(l, t)), + n) && s(d, "revokeObjectURL", Y(n, t)), + q(d, "URL"), + m({ + global: !0, + constructor: !0, + forced: !b, + sham: !i + }, { + URL: d + }) + } + , function(t, e, n) { + "use strict"; + var i = n(126).charAt + , o = n(38) + , r = n(46) + , s = n(161) + , a = n(165) + , l = "String Iterator" + , c = r.set + , u = r.getterFor(l); + s(String, "String", function(t) { + c(this, { + type: l, + string: o(t), + index: 0 + }) + }, function() { + var t = u(this) + , e = t.string + , n = t.index; + return n >= e.length ? a(void 0, !0) : (e = i(e, n), + t.index += e.length, + a(e, !1)) + }) + } + , function(t, e, n) { + "use strict"; + var d = n(23) + , i = n(14) + , p = n(22) + , o = n(16) + , f = n(159) + , g = n(157) + , m = n(142) + , b = n(50) + , v = n(112) + , r = Object.assign + , s = Object.defineProperty + , _ = i([].concat); + t.exports = !r || o(function() { + var t, e, n, i; + return !(!d || 1 === r({ + b: 1 + }, r(s({}, "a", { + enumerable: !0, + get: function() { + s(this, "b", { + value: 3, + enumerable: !1 + }) + } + }), { + b: 2 + })).b) || (e = {}, + i = "abcdefghijklmnopqrst", + (t = {})[n = Symbol("assign detection")] = 7, + i.split("").forEach(function(t) { + e[t] = t + }), + 7 !== r({}, t)[n]) || f(r({}, e)).join("") !== i + }) ? function(t, e) { + for (var n = b(t), i = arguments.length, o = 1, r = g.f, s = m.f; o < i; ) + for (var a, l = v(arguments[o++]), c = r ? _(f(l), r(l)) : f(l), u = c.length, h = 0; h < u; ) + a = c[h++], + d && !p(s, l, a) || (n[a] = l[a]); + return n + } + : r + } + , function(t, e, n) { + "use strict"; + var d = n(59) + , p = n(22) + , f = n(50) + , g = n(258) + , m = n(183) + , b = n(177) + , v = n(58) + , _ = n(175) + , y = n(130) + , w = n(96) + , O = Array; + t.exports = function(t) { + var e, n, i, o, r, s, a = f(t), t = b(this), l = arguments.length, c = 1 < l ? arguments[1] : void 0, u = void 0 !== c, l = (u && (c = d(c, 2 < l ? arguments[2] : void 0)), + w(a)), h = 0; + if (!l || this === O && m(l)) + for (e = v(a), + n = t ? new this(e) : O(e); h < e; h++) + s = u ? c(a[h], h) : a[h], + _(n, h, s); + else + for (r = (o = y(a, l)).next, + n = t ? new this : []; !(i = p(r, o)).done; h++) + s = u ? g(o, c, [i.value, h], !0) : i.value, + _(n, h, s); + return n.length = h, + n + } + } + , function(t, e, n) { + "use strict"; + var o = n(30) + , r = n(184); + t.exports = function(e, t, n, i) { + try { + return i ? t(o(n)[0], n[1]) : t(n) + } catch (t) { + r(e, "throw", t) + } + } + } + , function(t, e, n) { + "use strict"; + function b(t) { + return t + 22 + 75 * (t < 26) + } + function r(t) { + var e, n = [], i = (t = function(t) { + for (var e = [], n = 0, i = t.length; n < i; ) { + var o, r = A(t, n++); + 55296 <= r && r <= 56319 && n < i ? 56320 == (64512 & (o = A(t, n++))) ? T(e, ((1023 & r) << 10) + (1023 & o) + 65536) : (T(e, r), + n--) : T(e, r) + } + return e + }(t)).length, o = 128, r = 0, s = 72; + for (u = 0; u < t.length; u++) + (e = t[u]) < 128 && T(n, k(e)); + var a = n.length + , l = a; + for (a && T(n, "-"); l < i; ) { + for (var c = v, u = 0; u < t.length; u++) + o <= (e = t[u]) && e < c && (c = e); + var h = l + 1; + if (c - o > E((v - r) / h)) + throw C(x); + for (r += (c - o) * h, + o = c, + u = 0; u < t.length; u++) { + if ((e = t[u]) < o && ++r > v) + throw C(x); + if (e === o) { + for (var d = r, p = _; ; ) { + var f = p <= s ? 1 : s + y <= p ? y : p - s; + if (d < f) + break; + var g = d - f + , m = _ - f; + T(n, k(b(f + g % m))), + d = E(g / m), + p += _ + } + T(n, k(b(d))), + s = function(t, e, n) { + var i = 0; + for (t = n ? E(t / O) : t >> 1, + t += E(t / e); S * y >> 1 < t; ) + t = E(t / S), + i += _; + return E(i + (S + 1) * t / (t + w)) + }(r, h, l === a), + r = 0, + l++ + } + } + r++, + o++ + } + return j(n, "") + } + var n = n(14) + , v = 2147483647 + , _ = 36 + , y = 26 + , w = 38 + , O = 700 + , s = /[^\0-\u007E]/ + , a = /[.\u3002\uFF0E\uFF61]/g + , x = "Overflow: input needs wider integers to process" + , S = _ - 1 + , C = RangeError + , l = n(a.exec) + , E = Math.floor + , k = String.fromCharCode + , A = n("".charCodeAt) + , j = n([].join) + , T = n([].push) + , c = n("".replace) + , u = n("".split) + , h = n("".toLowerCase); + t.exports = function(t) { + for (var e, n = [], i = u(c(h(t), a, "."), "."), o = 0; o < i.length; o++) + e = i[o], + T(n, l(s, e) ? "xn--" + r(e) : e); + return j(n, ".") + } + } + , function(t, e, n) { + "use strict"; + var o = n(41); + t.exports = function(t, e, n) { + for (var i in e) + o(t, i, e[i], n); + return t + } + } + , function(t, e, n) { + "use strict"; + n(187) + } + , function(t, e, n) { + "use strict"; + function i(c) { + return function(t, e, n, i) { + u(e); + var o = h(t) + , r = d(o) + , s = p(o) + , a = c ? s - 1 : 0 + , l = c ? -1 : 1; + if (n < 2) + for (; ; ) { + if (a in r) { + i = r[a], + a += l; + break + } + if (a += l, + c ? a < 0 : s <= a) + throw f("Reduce of empty array with no initial value") + } + for (; c ? 0 <= a : a < s; a += l) + a in r && (i = e(i, r[a], a, o)); + return i + } + } + var u = n(39) + , h = n(50) + , d = n(112) + , p = n(58) + , f = TypeError; + t.exports = { + left: i(!1), + right: i(!0) + } + } + ], + i = {}, + o.m = n, + o.c = i, + o.d = function(t, e, n) { + o.o(t, e) || Object.defineProperty(t, e, { + enumerable: !0, + get: n + }) + } + , + o.r = function(t) { + "undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(t, Symbol.toStringTag, { + value: "Module" + }), + Object.defineProperty(t, "__esModule", { + value: !0 + }) + } + , + o.t = function(e, t) { + if (1 & t && (e = o(e)), + 8 & t) + return e; + if (4 & t && "object" == typeof e && e && e.__esModule) + return e; + var n = Object.create(null); + if (o.r(n), + Object.defineProperty(n, "default", { + enumerable: !0, + value: e + }), + 2 & t && "string" != typeof e) + for (var i in e) + o.d(n, i, function(t) { + return e[t] + } + .bind(null, i)); + return n + } + , + o.n = function(t) { + var e = t && t.__esModule ? function() { + return t.default + } + : function() { + return t + } + ; + return o.d(e, "a", e), + e + } + , + o.o = function(t, e) { + return Object.prototype.hasOwnProperty.call(t, e) + } + , + o.p = "", + o(o.s = 198).compiled; + function o(t) { + var e; + return (i[t] || (e = i[t] = { + i: t, + l: !1, + exports: {} + }, + n[t].call(e.exports, e, e.exports, o), + e.l = !0, + e)).exports + } + var n, i +}); diff --git a/tsconfig.json b/tsconfig.json index fccaf81..73d6e8f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,7 +11,7 @@ // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ /* Language and Environment */ - "target": "es2016" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, + "target": "ES5" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, // "lib": [ // "es2016", // "dom", @@ -29,7 +29,7 @@ // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ /* Modules */ - "module": "CommonJS" /* Specify what module code is generated. */, + "module": "Node16" /* Specify what module code is generated. */, // "rootDir": "./", /* Specify the root folder within your source files. */ "moduleResolution": "Node16" /* Specify how TypeScript looks up a file from a given module specifier. */, // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ @@ -65,7 +65,7 @@ // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ - "outDir": "./js/" /* Specify an output folder for all emitted files. */, + "outDir": "./.js/" /* Specify an output folder for all emitted files. */, // "removeComments": true, /* Disable emitting comments. */ // "noEmit": true, /* Disable emitting files from a compilation. */ // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ @@ -119,5 +119,5 @@ "skipLibCheck": true /* Skip type checking all .d.ts files. */ }, - "exclude": ["./plugins/**/*.broken.ts", "./js/**/*"] + "exclude": ["./plugins/**/*.broken.ts", "./.js/**/*"] } diff --git a/types/plugin.ts b/types/plugin.ts index e3424ed..975a8bd 100644 --- a/types/plugin.ts +++ b/types/plugin.ts @@ -1,46 +1,32 @@ import { Filter } from "@libs/filterInputs"; import { languages } from "@libs/languages"; -import { NodeFetchParams } from "@libs/nodeFetch"; - -export namespace Chapter { - export interface Item { +export namespace Plugin { + export interface ChapterItem { name: string; url: string; releaseTime?: string | null; } - export interface instance { - sourceId: number; - novelUrl: string; - chapterUrl: string; - name?: string; - chapterText?: string; - } -} - -export namespace Novel { - export interface Item { + export interface NovelItem { name: string; url: string; cover?: string; } - export interface instance { + export interface SourceNovel { url: string; name?: string; cover?: string; genres?: string; summary?: string; author?: string; + artist?: string; status?: string; - chapters?: Chapter.Item[]; + chapters?: ChapterItem[]; } -} - -export namespace Plugin { - export interface Options { + export interface PopularNovelsOptions { showLatestNovels?: boolean; filters?: Record; } - export interface Info { + export interface PluginItem { id: string; name: string; lang: (typeof languages)[keyof typeof languages]; @@ -48,43 +34,51 @@ export namespace Plugin { requirePath: string; icon: string; } - export interface instance { - id: string; - name: string; - version: string; + + export interface PluginBase { + id: string, + name: string, + /** + * Relative path without icon. E.g: + * ```js + * "src/vi/hakolightnovel/icon.png" + * ``` + */ icon: string; site: string; - popularNovels: popularNovels; - parseNovelAndChapters: parseNovelAndChapters; - parseChapter: parseChapter; - searchNovels: searchNovels; - fetchImage: fetchImage; filters?: Filter[]; + version: string; + userAgent: string; + cookieString: string; + popularNovels(pageNo: number, options: PopularNovelsOptions): Promise; + parseNovelAndChapters(novelUrl: string): Promise; + parseChapter(chapterUrl: string): Promise; + searchNovels(searchTerm: string, pageNo?: number): Promise; + /** + * + * @param url Image url + * @returns {string} Base64 of image + * @example + * ```ts + * const headers = { + * Referer: "https://ln.hako.vn", + * }; + * return await fetchFile(url, { headers: headers }); + * ``` + */ + fetchImage(url: string): Promise; } - export type popularNovels = ( - page: number, - options: Plugin.Options - ) => Promise; - export type PopularNovelsResponse = Novel.Item[]; - export type parseNovelAndChapters = ( - novelUrl: string - ) => Promise; - export type parseChapter = (chapterUrl: string) => Promise; - export type searchNovels = (searchTerm: string) => Promise; - export type fetchImage = ( - ...params: NodeFetchParams - ) => Promise; } -export const isPlugin = (p: any): p is Plugin.instance => { - const pl = p as Plugin.instance; +export const isPlugin = (p: any): p is Plugin.PluginBase => { + const pl = p as Plugin.PluginBase; const errorOut = (key: string) => { console.error(`Plugin ${pl.name} doesn't have ${key}!`); return false; }; - const required_funcs: (keyof Plugin.instance)[] = [ + const required_funcs: (keyof Plugin.PluginBase)[] = [ "popularNovels", "parseNovelAndChapters", "parseChapter", @@ -95,12 +89,14 @@ export const isPlugin = (p: any): p is Plugin.instance => { const key = required_funcs[i]; if (!pl[key] || typeof pl[key] !== "function") return errorOut(key); } - const requireds_fields: (keyof Plugin.instance)[] = [ + const requireds_fields: (keyof Plugin.PluginBase)[] = [ "id", "name", "version", "icon", "site", + "userAgent", + "cookieString", ]; for (let i = 0; i < requireds_fields.length; i++) { const key = requireds_fields[i]; diff --git a/types/types.ts b/types/types.ts index 4692a45..afaa690 100644 --- a/types/types.ts +++ b/types/types.ts @@ -1,5 +1,5 @@ import { Plugin } from "@typings/plugin"; export type PluginList = { - [key: string]: Plugin.Info[]; + [key: string]: Plugin.PluginItem[]; };