Hide non-manga entries in search on Madara sources (#11304)

* Hide non-manga entries in search on Madara sources.

* Remove deleted method in overrides.

* Remove unused methods and fix final modifier warning.

* Remove commented lines in NS.

* Remove hardcoded selector in old sources.
This commit is contained in:
Alessandro Jean 2022-04-06 08:33:17 -03:00 committed by GitHub
parent 6b3a52ddd7
commit aa9e858dc2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 360 additions and 168 deletions

View File

@ -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<Genre> = 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")
)
}

View File

@ -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 {

View File

@ -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<SChapter> =
super.chapterListParse(response).reversed()

View File

@ -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")
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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<Genre> = emptyList()
// Not used
override fun getFilterList(): FilterList = FilterList()
}

View File

@ -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
}

View File

@ -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<SChapter> {
var chapterList = super.chapterListParse(response)

View File

@ -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"
}

View File

@ -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
}

View File

@ -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"

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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"
}

View File

@ -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
}

View File

@ -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<MangasPage> {
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<Genre>? {
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<Genre> {
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<ShowOnlyMangaFilter>()
.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<GenreList>().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<String> = when (lang) {
"pt-BR" -> arrayOf(
"<selecione>", "Recentes", "A-Z", "Avaliação",
"Relevância", "Recentes", "A-Z", "Avaliação",
"Tendência", "Visualizações", "Novos"
)
else -> arrayOf(
"<select>", "Latest", "A-Z", "Rating",
"Relevance", "Latest", "A-Z", "Rating",
"Trending", "Most Views", "New"
)
}
@ -292,7 +475,7 @@ abstract class Madara(
}
protected open val genreFilterHeader: String = when (lang) {
"pt-BR" -> "O filtro de gêneros pode não funcionar em algumas fontes"
"pt-BR" -> "O filtro de gêneros pode não funcionar"
else -> "Genres filter may not work for all sources"
}
@ -301,9 +484,9 @@ abstract class Madara(
else -> "Genres"
}
protected open val genreFilterResetWarning: String = when (lang) {
"pt-BR" -> "Aperte redefinir para tentar carregar os gêneros"
else -> "Press reset to attempt to fetch genres"
protected open val showOnlyMangaEntriesLabel: String = when (lang) {
"pt-BR" -> "Mostrar somente mangás"
else -> "Show only manga entries"
}
protected class AuthorFilter(title: String) : Filter.Text(title)
@ -312,8 +495,8 @@ abstract class Madara(
protected class StatusFilter(title: String, status: List<Tag>) :
Filter.Group<Tag>(title, status)
protected class OrderByFilter(title: String, options: List<Pair<String, String>>) :
UriPartFilter(title, options.toTypedArray())
protected class OrderByFilter(title: String, options: List<Pair<String, String>>, state: Int = 0) :
UriPartFilter(title, options.toTypedArray(), state)
protected class GenreConditionFilter(title: String, options: Array<String>) : UriPartFilter(
title,
@ -328,34 +511,46 @@ abstract class Madara(
protected class GenreList(title: String, genres: List<Genre>) : Filter.Group<Genre>(title, genres)
class Genre(name: String, val id: String = name) : Filter.CheckBox(name)
private var genresList: List<Genre>? = null
protected class ShowOnlyMangaFilter(label: String) : Filter.CheckBox(label, true)
protected open fun getGenreList(): List<Genre> {
// Filters are fetched immediately once an extension loads
// We're only able to get filters after a loading the manga directory, and resetting
// the filters is the only thing that seems to reinflate the view
return genresList ?: listOf(Genre(genreFilterResetWarning, ""))
private var genresList: List<Genre> = emptyList()
override fun getFilterList(): FilterList {
val filters = mutableListOf(
AuthorFilter(authorFilterTitle),
ArtistFilter(artistFilterTitle),
YearFilter(yearFilterTitle),
StatusFilter(statusFilterTitle, getStatusList()),
OrderByFilter(
orderByFilterTitle,
orderByFilterOptions.zip(orderByFilterOptionsValues),
if (useLoadMoreSearch) 5 else 0
),
AdultContentFilter(adultContentFilterTitle, adultContentFilterOptions)
)
if (useLoadMoreSearch) {
filters.add(ShowOnlyMangaFilter(showOnlyMangaEntriesLabel))
}
if (genresList.isNotEmpty()) {
filters += listOf(
Filter.Separator(),
Filter.Header(genreFilterHeader),
GenreConditionFilter(genreConditionFilterTitle, genreConditionFilterOptions),
GenreList(genreFilterTitle, genresList)
)
}
return FilterList(filters)
}
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())
)
protected fun getStatusList() = statusFilterOptionsValues
.zip(statusFilterOptions)
.map { Tag(it.first, it.second) }
open class UriPartFilter(displayName: String, private val vals: Array<Pair<String, String>>) :
Filter.Select<String>(displayName, vals.map { it.first }.toTypedArray()) {
open class UriPartFilter(displayName: String, private val vals: Array<Pair<String, String>>, state: Int = 0) :
Filter.Select<String>(displayName, vals.map { it.first }.toTypedArray(), state) {
fun toUriPart() = vals[state].second
}
@ -589,7 +784,7 @@ abstract class Madara(
// Added "title" alternative
chapter.date_upload = select("img:not(.thumb)").firstOrNull()?.attr("alt")?.let { parseRelativeDate(it) }
?: select("span a").firstOrNull()?.attr("title")?.let { parseRelativeDate(it) }
?: parseChapterDate(select("span.chapter-release-date").firstOrNull()?.text())
?: parseChapterDate(select("span.chapter-release-date").firstOrNull()?.text())
}
return chapter
@ -755,8 +950,25 @@ abstract class Madara(
runCatching { client.newCall(request).execute().close() }
}
init {
if (fetchGenresOnInit && genresList.isEmpty()) {
Single
.fromCallable {
val genres = runCatching {
client.newCall(GET("$baseUrl/?s=&post_type=wp-manga")).execute()
.use { parseGenres(it.asJsoup()) }
}
genresList = genres.getOrNull().orEmpty()
}
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.subscribe()
}
}
companion object {
const val URL_SEARCH_PREFIX = "SLUG:"
const val URL_SEARCH_PREFIX = "slug:"
}
}

View File

@ -10,7 +10,7 @@ class MadaraGenerator : ThemeSourceGenerator {
override val themeClass = "Madara"
override val baseVersionCode: Int = 17
override val baseVersionCode: Int = 18
override val sources = listOf(
MultiLang("Leviatan Scans", "https://leviatanscans.com", listOf("en", "es"), className = "LeviatanScansFactory", overrideVersionCode = 9),