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:
parent
6b3a52ddd7
commit
aa9e858dc2
|
@ -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")
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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:"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
Loading…
Reference in New Issue