diff --git a/multisrc/overrides/madara/cafecomyaoi/src/CafeComYaoi.kt b/multisrc/overrides/madara/cafecomyaoi/src/CafeComYaoi.kt index 5bc9d11e4..9090a02ed 100644 --- a/multisrc/overrides/madara/cafecomyaoi/src/CafeComYaoi.kt +++ b/multisrc/overrides/madara/cafecomyaoi/src/CafeComYaoi.kt @@ -17,41 +17,4 @@ class CafeComYaoi : Madara( override val client: OkHttpClient = super.client.newBuilder() .addInterceptor(RateLimitInterceptor(1, 2, TimeUnit.SECONDS)) .build() - - // [...document.querySelectorAll('input[name="genre[]"]')] - // .map(x => `Genre("${document.querySelector('label[for=' + x.id + ']').innerHTML.trim()}", "${x.value}")`) - // .join(',\n') - override fun getGenreList(): List = listOf( - Genre("Ação", "acao"), - Genre("Aventura", "aventura"), - Genre("BDSM", "bdsm"), - Genre("BL", "bl"), - Genre("Comédia", "comedia"), - Genre("Doujinshi", "doujinshi"), - Genre("Drama", "drama"), - Genre("Fantasia", "fantasia"), - Genre("Gender Bender", "gender-bender"), - Genre("Harem", "harem"), - Genre("Histórico", "historico"), - Genre("Horror", "horror"), - Genre("Máfia", "mafia"), - Genre("Mangá", "manga"), - Genre("Manhua", "manhua"), - Genre("Manhwa", "manhwa"), - Genre("Mature", "mature"), - Genre("Mistério", "misterio"), - Genre("Omegaverse", "omegaverse"), - Genre("One shot", "one-shot"), - Genre("Psicológico", "psicologico"), - Genre("Romance", "romance"), - Genre("School Life", "school-life"), - Genre("Sci-fi", "sci-fi"), - Genre("Shoujo", "shoujo"), - Genre("Slice of Life", "slice-of-life"), - Genre("Smut", "smut"), - Genre("Sobrenatural", "sobrenatural"), - Genre("Tragédia", "tragedia"), - Genre("Triângulo Amoroso", "triangulo-amoroso"), - Genre("Webcomic", "webcomic") - ) } diff --git a/multisrc/overrides/madara/doujinhentai/src/DoujinHentai.kt b/multisrc/overrides/madara/doujinhentai/src/DoujinHentai.kt index 48a7b9daf..859fbe982 100644 --- a/multisrc/overrides/madara/doujinhentai/src/DoujinHentai.kt +++ b/multisrc/overrides/madara/doujinhentai/src/DoujinHentai.kt @@ -11,7 +11,16 @@ import org.jsoup.nodes.Element import java.text.SimpleDateFormat import java.util.Locale -class DoujinHentai : Madara("DoujinHentai", "https://doujinhentai.net", "es", SimpleDateFormat("d MMM. yyyy", Locale.ENGLISH)) { +class DoujinHentai : Madara( + "DoujinHentai", + "https://doujinhentai.net", + "es", + SimpleDateFormat("d MMM. yyyy", Locale.ENGLISH), + fetchGenresOnInit = false +) { + + override val useLoadMoreSearch = false + override fun popularMangaRequest(page: Int): Request = GET("$baseUrl/lista-manga-hentai?orderby=views&page=$page", headers) override fun popularMangaSelector() = "div.col-md-3 a" override fun popularMangaFromElement(element: Element): SManga { diff --git a/multisrc/overrides/madara/egymanga/src/EGYManga.kt b/multisrc/overrides/madara/egymanga/src/EGYManga.kt index ada706412..eebb927e7 100644 --- a/multisrc/overrides/madara/egymanga/src/EGYManga.kt +++ b/multisrc/overrides/madara/egymanga/src/EGYManga.kt @@ -13,11 +13,11 @@ class EGYManga : Madara( SimpleDateFormat("MMMM dd, yyyy", Locale("ar")) ) { - override val pageListParseSelector = "div.separator" + // The website does not flag the content. + override val useLoadMoreSearch = false + override val filterNonMangaItems = false - // The website does not flag the content, so we just use the old selector. - override fun popularMangaSelector() = - "div.page-item-detail:not(:has(a[href*='bilibilicomics.com']))" + override val pageListParseSelector = "div.separator" override fun chapterListParse(response: Response): List = super.chapterListParse(response).reversed() diff --git a/multisrc/overrides/madara/geceninlordu/src/GeceninLordu.kt b/multisrc/overrides/madara/geceninlordu/src/GeceninLordu.kt index 001bb4c87..32abc5287 100644 --- a/multisrc/overrides/madara/geceninlordu/src/GeceninLordu.kt +++ b/multisrc/overrides/madara/geceninlordu/src/GeceninLordu.kt @@ -6,6 +6,16 @@ import eu.kanade.tachiyomi.source.model.FilterList import java.text.SimpleDateFormat import java.util.Locale -class GeceninLordu : Madara("Gecenin Lordu", "https://geceninlordu.com/", "tr", SimpleDateFormat("dd MMM yyyy", Locale("tr"))) { - override fun searchMangaRequest(page: Int, query: String, filters: FilterList) = GET("$baseUrl/?s=$query&post_type=wp-manga") +class GeceninLordu : Madara( + "Gecenin Lordu", + "https://geceninlordu.com/", + "tr", + SimpleDateFormat("dd MMM yyyy", Locale("tr")), + fetchGenresOnInit = false +) { + + override val useLoadMoreSearch = false + + override fun searchMangaRequest(page: Int, query: String, filters: FilterList) = + GET("$baseUrl/?s=$query&post_type=wp-manga") } diff --git a/multisrc/overrides/madara/gemanga/src/Gemanga.kt b/multisrc/overrides/madara/gemanga/src/Gemanga.kt index 5a43c699b..723f70021 100644 --- a/multisrc/overrides/madara/gemanga/src/Gemanga.kt +++ b/multisrc/overrides/madara/gemanga/src/Gemanga.kt @@ -4,6 +4,7 @@ import eu.kanade.tachiyomi.multisrc.madara.Madara class Gemanga : Madara("Gemanga", "https://gemanga.com", "ar") { - // The website does not flag the content, so we just use the old selector. - override fun popularMangaSelector() = "div.page-item-detail:not(:has(a[href*='bilibilicomics.com']))" + // The website does not flag the content. + override val useLoadMoreSearch = false + override val filterNonMangaItems = false } diff --git a/multisrc/overrides/madara/hentaimanga/src/HentaiManga.kt b/multisrc/overrides/madara/hentaimanga/src/HentaiManga.kt index 92bbdf797..43b241091 100644 --- a/multisrc/overrides/madara/hentaimanga/src/HentaiManga.kt +++ b/multisrc/overrides/madara/hentaimanga/src/HentaiManga.kt @@ -11,6 +11,7 @@ class HentaiManga : Madara( dateFormat = SimpleDateFormat("MMM d, yyyy", Locale.US) ) { - // The website does not flag the content, so we just use the old selector. - override fun popularMangaSelector() = "div.page-item-detail:not(:has(a[href*='bilibilicomics.com']))" + // The website does not flag the content. + override val useLoadMoreSearch = false + override val filterNonMangaItems = false } diff --git a/multisrc/overrides/madara/hentaiwebtoon/src/HentaiWebtoon.kt b/multisrc/overrides/madara/hentaiwebtoon/src/HentaiWebtoon.kt index f8f6cbca9..64bcff034 100644 --- a/multisrc/overrides/madara/hentaiwebtoon/src/HentaiWebtoon.kt +++ b/multisrc/overrides/madara/hentaiwebtoon/src/HentaiWebtoon.kt @@ -4,6 +4,7 @@ import eu.kanade.tachiyomi.multisrc.madara.Madara class HentaiWebtoon : Madara("HentaiWebtoon", "https://hentaiwebtoon.com", "en") { - // The website does not flag the content, so we just use the old selector. - override fun popularMangaSelector() = "div.page-item-detail:not(:has(a[href*='bilibilicomics.com']))" + // The website does not flag the content. + override val useLoadMoreSearch = false + override val filterNonMangaItems = false } diff --git a/multisrc/overrides/madara/instamanhwa/src/InstaManhwa.kt b/multisrc/overrides/madara/instamanhwa/src/InstaManhwa.kt index c30dbaa9b..7b81ae19c 100644 --- a/multisrc/overrides/madara/instamanhwa/src/InstaManhwa.kt +++ b/multisrc/overrides/madara/instamanhwa/src/InstaManhwa.kt @@ -18,9 +18,12 @@ class InstaManhwa : Madara( "InstaManhwa", "https://www.instamanhwa.com", "en", - SimpleDateFormat("dd MMMM, yyyy", Locale.US) + SimpleDateFormat("dd MMMM, yyyy", Locale.US), + fetchGenresOnInit = false ) { + override val supportsLatest: Boolean = false + override val useLoadMoreSearch = false override fun latestUpdatesRequest(page: Int): Request = GET("$baseUrl/latest?page=$page", headers) @@ -57,9 +60,6 @@ class InstaManhwa : Madara( return client.newCall(POST("$baseUrl/ajax", headers, body)).execute().asJsoup() } - // Not used - override fun getGenreList(): List = emptyList() - // Not used override fun getFilterList(): FilterList = FilterList() } diff --git a/multisrc/overrides/madara/mangagreat/src/MangaGreat.kt b/multisrc/overrides/madara/mangagreat/src/MangaGreat.kt index 19fa9c17d..f954f43aa 100644 --- a/multisrc/overrides/madara/mangagreat/src/MangaGreat.kt +++ b/multisrc/overrides/madara/mangagreat/src/MangaGreat.kt @@ -4,6 +4,7 @@ import eu.kanade.tachiyomi.multisrc.madara.Madara class MangaGreat : Madara("MangaGreat", "https://mangagreat.com", "en") { - // The website does not flag the content, so we just use the old selector. - override fun popularMangaSelector() = "div.page-item-detail:not(:has(a[href*='bilibilicomics.com']))" + // The website does not flag the content. + override val useLoadMoreSearch = false + override val filterNonMangaItems = false } diff --git a/multisrc/overrides/madara/manhuaes/src/ManhuaES.kt b/multisrc/overrides/madara/manhuaes/src/ManhuaES.kt index 7bc491ee7..1dc8a8926 100644 --- a/multisrc/overrides/madara/manhuaes/src/ManhuaES.kt +++ b/multisrc/overrides/madara/manhuaes/src/ManhuaES.kt @@ -8,10 +8,9 @@ import okhttp3.Response class ManhuaES : Madara("Manhua ES", "https://manhuaes.com", "en") { - // The website is incorrectly flagging a lot of their - // manga content as video and text instead. To bypass this, we - // use the old selector that includes all. - override fun popularMangaSelector() = "div.page-item-detail:not(:has(a[href*='bilibilicomics.com']))" + // The website does not flag the content. + override val useLoadMoreSearch = false + override val filterNonMangaItems = false override fun chapterListParse(response: Response): List { var chapterList = super.chapterListParse(response) diff --git a/multisrc/overrides/madara/manhuaplus/src/ManhuaPlus.kt b/multisrc/overrides/madara/manhuaplus/src/ManhuaPlus.kt index c7ab8cfa2..1f612df65 100644 --- a/multisrc/overrides/madara/manhuaplus/src/ManhuaPlus.kt +++ b/multisrc/overrides/madara/manhuaplus/src/ManhuaPlus.kt @@ -4,10 +4,9 @@ import eu.kanade.tachiyomi.multisrc.madara.Madara class ManhuaPlus : Madara("Manhua Plus", "https://manhuaplus.com", "en") { - // The website is incorrectly flagging a lot of their - // manga content as video instead. To bypass this, we - // use the old selector that includes all. - override fun popularMangaSelector() = "div.page-item-detail:not(:has(a[href*='bilibilicomics.com']))" + // The website does not flag the content. + override val useLoadMoreSearch = false + override val filterNonMangaItems = false override val pageListParseSelector = ".read-container img" } diff --git a/multisrc/overrides/madara/manhuaus/src/ManhuaUS.kt b/multisrc/overrides/madara/manhuaus/src/ManhuaUS.kt index 72da84549..89460a511 100644 --- a/multisrc/overrides/madara/manhuaus/src/ManhuaUS.kt +++ b/multisrc/overrides/madara/manhuaus/src/ManhuaUS.kt @@ -3,10 +3,10 @@ package eu.kanade.tachiyomi.extension.en.manhuaus import eu.kanade.tachiyomi.multisrc.madara.Madara class ManhuaUS : Madara("ManhuaUS", "https://manhuaus.com", "en") { + override val useNewChapterEndpoint: Boolean = true - // The website is incorrectly flagging a lot of their - // manga content as text instead. To bypass this, we - // use the old selector that includes all. - override fun popularMangaSelector() = "div.page-item-detail:not(:has(a[href*='bilibilicomics.com']))" + // The website does not flag the content. + override val useLoadMoreSearch = false + override val filterNonMangaItems = false } diff --git a/multisrc/overrides/madara/manhwa18cc/src/Manhwa18CcFactory.kt b/multisrc/overrides/madara/manhwa18cc/src/Manhwa18CcFactory.kt index 1c9dff8b4..dd92a1932 100644 --- a/multisrc/overrides/madara/manhwa18cc/src/Manhwa18CcFactory.kt +++ b/multisrc/overrides/madara/manhwa18cc/src/Manhwa18CcFactory.kt @@ -30,7 +30,9 @@ abstract class Manhwa18Cc( override val name: String, override val baseUrl: String, lang: String -) : Madara(name, baseUrl, lang) { +) : Madara(name, baseUrl, lang, fetchGenresOnInit = false) { + + override val useLoadMoreSearch = false override fun popularMangaSelector() = "div.manga-item" override val popularMangaUrlSelector = "div.data > h3 > a" diff --git a/multisrc/overrides/madara/manhwa18org/src/Manhwa18Org.kt b/multisrc/overrides/madara/manhwa18org/src/Manhwa18Org.kt index 03acdd5b7..d1ab7bc0b 100644 --- a/multisrc/overrides/madara/manhwa18org/src/Manhwa18Org.kt +++ b/multisrc/overrides/madara/manhwa18org/src/Manhwa18Org.kt @@ -4,6 +4,7 @@ import eu.kanade.tachiyomi.multisrc.madara.Madara class Manhwa18Org : Madara("Manhwa18.org", "https://manhwa18.org", "en") { - // The website does not flag the content, so we just use the old selector. - override fun popularMangaSelector() = "div.page-item-detail:not(:has(a[href*='bilibilicomics.com']))" + // The website does not flag the content. + override val useLoadMoreSearch = false + override val filterNonMangaItems = false } diff --git a/multisrc/overrides/madara/manhwa68/src/Manhwa68.kt b/multisrc/overrides/madara/manhwa68/src/Manhwa68.kt index d3fd7d5e6..266b63191 100644 --- a/multisrc/overrides/madara/manhwa68/src/Manhwa68.kt +++ b/multisrc/overrides/madara/manhwa68/src/Manhwa68.kt @@ -11,6 +11,7 @@ class Manhwa68 : Madara( dateFormat = SimpleDateFormat("MMM d, yyyy", Locale.US) ) { - // The website does not flag the content, so we just use the old selector. - override fun popularMangaSelector() = "div.page-item-detail:not(:has(a[href*='bilibilicomics.com']))" + // The website does not flag the content. + override val useLoadMoreSearch = false + override val filterNonMangaItems = false } diff --git a/multisrc/overrides/madara/manhwatop/src/Manhwatop.kt b/multisrc/overrides/madara/manhwatop/src/Manhwatop.kt index eb15225b6..0176c1e9f 100644 --- a/multisrc/overrides/madara/manhwatop/src/Manhwatop.kt +++ b/multisrc/overrides/madara/manhwatop/src/Manhwatop.kt @@ -4,6 +4,7 @@ import eu.kanade.tachiyomi.multisrc.madara.Madara class Manhwatop : Madara("Manhwatop", "https://manhwatop.com", "en") { - // The website does not flag the content, so we just use the old selector. - override fun popularMangaSelector() = "div.page-item-detail:not(:has(a[href*='bilibilicomics.com']))" + // The website does not flag the content. + override val useLoadMoreSearch = false + override val filterNonMangaItems = false } diff --git a/multisrc/overrides/madara/manytoonme/src/ManyToonMe.kt b/multisrc/overrides/madara/manytoonme/src/ManyToonMe.kt index 82b30f246..3065ab1e2 100644 --- a/multisrc/overrides/madara/manytoonme/src/ManyToonMe.kt +++ b/multisrc/overrides/madara/manytoonme/src/ManyToonMe.kt @@ -6,6 +6,7 @@ class ManyToonMe : Madara("ManyToon.me", "https://manytoon.me", "en") { override val useNewChapterEndpoint: Boolean = true - // The website does not flag the content, so we just use the old selector. - override fun popularMangaSelector() = "div.page-item-detail:not(:has(a[href*='bilibilicomics.com']))" + // The website does not flag the content. + override val useLoadMoreSearch = false + override val filterNonMangaItems = false } diff --git a/multisrc/overrides/madara/neoxscanlator/src/NeoxScanlator.kt b/multisrc/overrides/madara/neoxscanlator/src/NeoxScanlator.kt index 9e9289293..2f9a56664 100644 --- a/multisrc/overrides/madara/neoxscanlator/src/NeoxScanlator.kt +++ b/multisrc/overrides/madara/neoxscanlator/src/NeoxScanlator.kt @@ -11,14 +11,11 @@ import eu.kanade.tachiyomi.multisrc.madara.Madara import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.asObservable import eu.kanade.tachiyomi.source.ConfigurableSource -import eu.kanade.tachiyomi.source.model.FilterList -import eu.kanade.tachiyomi.source.model.MangasPage import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.source.model.SManga import okhttp3.Headers import okhttp3.OkHttpClient import okhttp3.Request -import okhttp3.Response import rx.Observable import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -32,7 +29,7 @@ class NeoxScanlator : "Neox Scanlator", DEFAULT_BASE_URL, "pt-BR", - SimpleDateFormat("MMMMM dd, yyyy", Locale("pt", "BR")) + SimpleDateFormat("dd/MM/yyyy", Locale("pt", "BR")) ), ConfigurableSource { @@ -57,13 +54,6 @@ class NeoxScanlator : .add("Accept-Language", ACCEPT_LANGUAGE) .add("Referer", REFERER) - override fun searchMangaParse(response: Response): MangasPage { - val mangaPage = super.searchMangaParse(response) - val filteredResult = mangaPage.mangas.filter { it.title.contains(NOVEL_REGEX).not() } - - return MangasPage(filteredResult, mangaPage.hasNextPage) - } - // Sometimes the site changes the manga URL. This override will // add an error instead of the HTTP 404 to inform the user to // migrate from Neox to Neox to update the URL. @@ -90,9 +80,6 @@ class NeoxScanlator : return GET(page.imageUrl!!, newHeaders) } - // Only status and order by filter work. - override fun getFilterList(): FilterList = FilterList(super.getFilterList().slice(3..4)) - override fun setupPreferenceScreen(screen: PreferenceScreen) { val baseUrlPref = EditTextPreference(screen.context).apply { key = BASE_URL_PREF_KEY @@ -136,7 +123,5 @@ class NeoxScanlator : "extensão, esta configuração será apagada." private const val RESTART_TACHIYOMI = "Reinicie o Tachiyomi para aplicar as configurações." - - private val NOVEL_REGEX = "novel|livro".toRegex(RegexOption.IGNORE_CASE) } } diff --git a/multisrc/overrides/madara/pojokmanga/src/PojokManga.kt b/multisrc/overrides/madara/pojokmanga/src/PojokManga.kt index 2707f699e..51e9de3c4 100644 --- a/multisrc/overrides/madara/pojokmanga/src/PojokManga.kt +++ b/multisrc/overrides/madara/pojokmanga/src/PojokManga.kt @@ -9,7 +9,17 @@ import okhttp3.Request import java.text.SimpleDateFormat import java.util.Locale -class PojokManga : Madara("Pojok Manga", "https://pojokmanga.com", "id", SimpleDateFormat("MMM dd, yyyy", Locale.US)) { +class PojokManga : Madara( + "Pojok Manga", + "https://pojokmanga.com", + "id", + SimpleDateFormat("MMM dd, yyyy", Locale.US) +) { + + override val useLoadMoreSearch = false + + override val useNewChapterEndpoint = true + override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { var url = "$baseUrl/${searchPage(page)}".toHttpUrlOrNull()!!.newBuilder() url.addQueryParameter("s", query) @@ -76,22 +86,16 @@ class PojokManga : Madara("Pojok Manga", "https://pojokmanga.com", "id", SimpleD ) ) - override fun getFilterList() = FilterList( - AuthorFilter(authorFilterTitle), - ArtistFilter(artistFilterTitle), - YearFilter(yearFilterTitle), - StatusFilter(statusFilterTitle, getStatusList()), - OrderByFilter(orderByFilterTitle, orderByFilterOptions.zip(orderByFilterOptionsValues)), - AdultContentFilter(adultContentFilterTitle, adultContentFilterOptions), - Filter.Separator(), - Filter.Header(genreFilterHeader), - GenreConditionFilter(genreConditionFilterTitle, genreConditionFilterOptions), - GenreList(genreFilterTitle, getGenreList()), - Filter.Separator(), - Filter.Header("NOTE: cant be used with other filter!"), - Filter.Header("$name Project List page"), - ProjectFilter(), - ) + override fun getFilterList(): FilterList { + val filters = super.getFilterList().toMutableList() - override val useNewChapterEndpoint = true + filters += listOf( + Filter.Separator(), + Filter.Header("NOTE: cant be used with other filter!"), + Filter.Header("$name Project List page"), + ProjectFilter() + ) + + return FilterList(filters) + } } diff --git a/multisrc/overrides/madara/shieldmanga/src/ShieldManga.kt b/multisrc/overrides/madara/shieldmanga/src/ShieldManga.kt index eeabdf8ae..66baef10a 100644 --- a/multisrc/overrides/madara/shieldmanga/src/ShieldManga.kt +++ b/multisrc/overrides/madara/shieldmanga/src/ShieldManga.kt @@ -14,9 +14,9 @@ class ShieldManga : Madara("Shield Manga", "https://shieldmanga.io", "en") { .addNetworkInterceptor(rateLimitInterceptor) .build() - // The website does not flag the content, so we just use the old selector. - override fun popularMangaSelector() = - "div.page-item-detail:not(:has(a[href*='bilibilicomics.com']))" + // The website does not flag the content. + override val useLoadMoreSearch = false + override val filterNonMangaItems = false override fun chapterListSelector() = "li.wp-manga-hapter, .version-chap li" } diff --git a/multisrc/overrides/madara/zinmanga/src/Zinmanga.kt b/multisrc/overrides/madara/zinmanga/src/Zinmanga.kt index 9e9e41feb..a06d7c185 100644 --- a/multisrc/overrides/madara/zinmanga/src/Zinmanga.kt +++ b/multisrc/overrides/madara/zinmanga/src/Zinmanga.kt @@ -4,6 +4,7 @@ import eu.kanade.tachiyomi.multisrc.madara.Madara class Zinmanga : Madara("Zinmanga", "https://zinmanga.com", "en") { - // The website does not flag the content, so we just use the old selector. - override fun popularMangaSelector() = "div.page-item-detail:not(:has(a[href*='bilibilicomics.com']))" + // The website does not flag the content. + override val useLoadMoreSearch = false + override val filterNonMangaItems = false } diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/madara/Madara.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/madara/Madara.kt index f0953976d..ef482fb56 100644 --- a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/madara/Madara.kt +++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/madara/Madara.kt @@ -24,6 +24,8 @@ import okhttp3.Response import org.jsoup.nodes.Document import org.jsoup.nodes.Element import rx.Observable +import rx.Single +import rx.schedulers.Schedulers import uy.kohesive.injekt.injectLazy import java.text.ParseException import java.text.SimpleDateFormat @@ -37,7 +39,8 @@ abstract class Madara( override val name: String, override val baseUrl: String, final override val lang: String, - private val dateFormat: SimpleDateFormat = SimpleDateFormat("MMMM dd, yyyy", Locale.US) + private val dateFormat: SimpleDateFormat = SimpleDateFormat("MMMM dd, yyyy", Locale.US), + protected val fetchGenresOnInit: Boolean = true ) : ParsedHttpSource() { override val supportsLatest = true @@ -52,6 +55,12 @@ abstract class Madara( protected open val json: Json by injectLazy() + /** + * If enabled, will remove non-manga items in search. + * Can be disabled if the source incorrectly sets the entry types. + */ + protected open val filterNonMangaItems = true + override fun headersBuilder(): Headers.Builder = Headers.Builder() .add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:77.0) Gecko/20100101 Firefox/78.0$userAgentRandomizer") .add("Referer", baseUrl) @@ -59,7 +68,7 @@ abstract class Madara( // Popular Manga // exclude/filter bilibili manga from list - override fun popularMangaSelector() = "div.page-item-detail.manga:not(:has(a[href*='bilibilicomics.com']))" + override fun popularMangaSelector() = "div.page-item-detail:not(:has(a[href*='bilibilicomics.com']))" open val popularMangaUrlSelector = "div.post-title a" @@ -93,12 +102,22 @@ abstract class Madara( add("vars[order]", "desc") add("vars[sidebar]", if (popular) "full" else "right") add("vars[manga_archives_item_layout]", "big_thumbnail") + + if (filterNonMangaItems) { + add("vars[meta_query][0][key]", "_wp_manga_chapter_type") + add("vars[meta_query][0][value]", "manga") + } } open val formHeaders: Headers by lazy { headersBuilder().build() } override fun popularMangaRequest(page: Int): Request { - return POST("$baseUrl/wp-admin/admin-ajax.php", formHeaders, formBuilder(page, true).build(), CacheControl.FORCE_NETWORK) + return POST( + "$baseUrl/wp-admin/admin-ajax.php", + formHeaders, + formBuilder(page, true).build(), + CacheControl.FORCE_NETWORK + ) } override fun popularMangaNextPageSelector(): String? = "body:not(:has(.no-posts))" @@ -124,18 +143,37 @@ abstract class Madara( return MangasPage(mangas, mp.hasNextPage) } - override fun popularMangaParse(response: Response): MangasPage { - if (genresList == null) - genresList = parseGenres(client.newCall(searchMangaRequest(1, "genre", getFilterList())).execute().asJsoup()) - return super.popularMangaParse(response) - } - // Search Manga open val mangaSubString = "manga" + /** + * If enabled, the search will use the madara_load_more action instead of + * the normal page. This allows more control over the query and will permit + * the filtering of non-manga items such as novels or videos. + */ + open val useLoadMoreSearch = true + + open fun searchFormBuilder(showOnlyManga: Boolean): FormBody.Builder = FormBody.Builder().apply { + add("action", "madara_load_more") + add("page", "0") + add("template", "madara-core/content/content-search") + add("vars[paged]", "1") + add("vars[template]", "archive") + add("vars[sidebar]", "right") + add("vars[post_type]", "wp-manga") + add("vars[post_status]", "publish") + add("vars[manga_archives_item_layout]", "big_thumbnail") + add("vars[post_per_page]", "20") + + if (filterNonMangaItems && showOnlyManga) { + add("vars[meta_query][0][key]", "_wp_manga_chapter_type") + add("vars[meta_query][0][value]", "manga") + } + } + override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable { - if (query.startsWith(URL_SEARCH_PREFIX)) { + if (query.startsWith(URL_SEARCH_PREFIX) && !useLoadMoreSearch) { val mangaUrl = "$baseUrl/$mangaSubString/${query.substringAfter(URL_SEARCH_PREFIX)}" return client.newCall(GET(mangaUrl, headers)) .asObservable().map { response -> @@ -157,21 +195,25 @@ abstract class Madara( } } - override fun searchMangaParse(response: Response): MangasPage { - if (genresList == null) - genresList = parseGenres(response.asJsoup(response.peekBody(Long.MAX_VALUE).string())) - return super.searchMangaParse(response) - } - - private fun parseGenres(document: Document): List? { - return document.selectFirst("div.checkbox-group")?.select("div.checkbox")?.map { li -> - Genre(li.selectFirst("label").text(), li.selectFirst("input[type=checkbox]").`val`()) - } + protected open fun parseGenres(document: Document): List { + return document.selectFirst("div.checkbox-group") + ?.select("div.checkbox") + .orEmpty() + .map { li -> + Genre( + li.selectFirst("label").text(), + li.selectFirst("input[type=checkbox]").`val`() + ) + } } protected open fun searchPage(page: Int): String = "page/$page/" override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { + if (useLoadMoreSearch) { + return searchLoadMoreRequest(page, query, filters) + } + val url = "$baseUrl/${searchPage(page)}".toHttpUrlOrNull()!!.newBuilder() url.addQueryParameter("s", query) url.addQueryParameter("post_type", "wp-manga") @@ -222,6 +264,147 @@ abstract class Madara( return GET(url.toString(), headers) } + protected open fun searchLoadMoreRequest(page: Int, query: String, filters: FilterList): Request { + val showOnlyManga = filters.filterIsInstance() + .firstOrNull()?.state ?: true + + val formBodyBuilder = searchFormBuilder(showOnlyManga).apply { + if (query.startsWith(URL_SEARCH_PREFIX)) { + add("vars[name]", query.removePrefix(URL_SEARCH_PREFIX)) + + return@apply + } + + add("vars[s]", query) + + var metaQueryIdx = if (filterNonMangaItems && showOnlyManga) 1 else 0 + var taxQueryIdx = 0 + val genres = filters.filterIsInstance().firstOrNull()?.state + ?.filter { it.state } + ?.map { it.id } + .orEmpty() + + filters.forEach { filter -> + when (filter) { + is AuthorFilter -> { + if (filter.state.isNotBlank()) { + add("vars[tax_query][$taxQueryIdx][taxonomy]", "wp-manga-author") + add("vars[tax_query][$taxQueryIdx][field]", "name") + add("vars[tax_query][$taxQueryIdx][terms]", filter.state) + + taxQueryIdx++ + } + } + is ArtistFilter -> { + if (filter.state.isNotBlank()) { + add("vars[tax_query][$taxQueryIdx][taxonomy]", "wp-manga-artist") + add("vars[tax_query][$taxQueryIdx][field]", "name") + add("vars[tax_query][$taxQueryIdx][terms]", filter.state) + + taxQueryIdx++ + } + } + is YearFilter -> { + if (filter.state.isNotBlank()) { + add("vars[tax_query][$taxQueryIdx][taxonomy]", "wp-manga-release") + add("vars[tax_query][$taxQueryIdx][field]", "name") + add("vars[tax_query][$taxQueryIdx][terms]", filter.state) + + taxQueryIdx++ + } + } + is StatusFilter -> { + val statuses = filter.state + .filter { it.state } + .map { it.id } + + if (statuses.isNotEmpty()) { + add("vars[meta_query][$metaQueryIdx][key]", "_wp_manga_status") + + statuses.forEachIndexed { i, slug -> + add("vars[meta_query][$metaQueryIdx][value][$i]", slug) + } + + metaQueryIdx++ + } + } + is OrderByFilter -> { + if (filter.state != 0) { + when (filter.toUriPart()) { + "latest" -> { + add("vars[orderby]", "meta_value_num") + add("vars[order]", "DESC") + add("vars[meta_key]", "_latest_update") + } + "alphabet" -> { + add("vars[orderby]", "post_title") + add("vars[order]", "ASC") + } + "rating" -> { + add("vars[orderby][query_average_reviews]", "DESC") + add("vars[orderby][query_total_reviews]", "DESC") + } + "trending" -> { + add("vars[orderby]", "meta_value_num") + add("vars[meta_key]", "_wp_manga_week_views_value") + add("vars[order]", "DESC") + } + "views" -> { + add("vars[orderby]", "meta_value_num") + add("vars[meta_key]", "_wp_manga_views") + add("vars[order]", "DESC") + } + else -> { + add("vars[orderby]", "date") + add("vars[order]", "DESC") + } + } + } + } + is AdultContentFilter -> { + if (filter.state != 0) { + add("vars[meta_query][$metaQueryIdx][key]", "manga_adult_content") + add( + "vars[meta_query][$metaQueryIdx][compare]", + if (filter.state == 1) "not exists" else "exists" + ) + + metaQueryIdx++ + } + } + is GenreConditionFilter -> { + if (filter.state == 1 && genres.isNotEmpty()) { + add("vars[tax_query][$taxQueryIdx][operation]", "AND") + } + } + is GenreList -> { + if (genres.isNotEmpty()) { + add("vars[tax_query][$taxQueryIdx][taxonomy]", "wp-manga-genre") + add("vars[tax_query][$taxQueryIdx][field]", "slug") + + genres.forEachIndexed { i, slug -> + add("vars[tax_query][$taxQueryIdx][terms][$i]", slug) + } + + taxQueryIdx++ + } + } + } + } + } + + val searchHeaders = headersBuilder() + .add("X-Requested-With", "XMLHttpRequest") + .build() + + return POST( + "$baseUrl/wp-admin/admin-ajax.php", + searchHeaders, + formBodyBuilder.build(), + CacheControl.FORCE_NETWORK + ) + } + protected open val authorFilterTitle: String = when (lang) { "pt-BR" -> "Autor" else -> "Author" @@ -258,11 +441,11 @@ abstract class Madara( protected open val orderByFilterOptions: Array = when (lang) { "pt-BR" -> arrayOf( - "", "Recentes", "A-Z", "Avaliação", + "Relevância", "Recentes", "A-Z", "Avaliação", "Tendência", "Visualizações", "Novos" ) else -> arrayOf( - "