add Project Filter Page to some source (#7526)

* simplified

* add to wpmangareader source

* add pojokmanga, manhuaID,mangakane

* fix issue

* try rerun

* fix2

* simplified

Co-Authored-By: Carlos <2092019+CarlosEsco@users.noreply.github.com>

* fix filter issue

* add MaidManga, Komiku

Co-authored-by: Carlos <2092019+CarlosEsco@users.noreply.github.com>
This commit is contained in:
Riztard Lanthorn 2021-06-09 04:51:36 +07:00 committed by GitHub
parent 9e112fbc32
commit 6f39cbf575
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 369 additions and 65 deletions

View File

@ -1,7 +1,95 @@
package eu.kanade.tachiyomi.extension.id.pojokmanga package eu.kanade.tachiyomi.extension.id.pojokmanga
import eu.kanade.tachiyomi.multisrc.madara.Madara import eu.kanade.tachiyomi.multisrc.madara.Madara
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.source.model.FilterList
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import okhttp3.Request
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Locale 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 fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
var url = "$baseUrl/${searchPage(page)}".toHttpUrlOrNull()!!.newBuilder()
url.addQueryParameter("s", query)
url.addQueryParameter("post_type", "wp-manga")
filters.forEach { filter ->
when (filter) {
is AuthorFilter -> {
if (filter.state.isNotBlank()) {
url.addQueryParameter("author", filter.state)
}
}
is ArtistFilter -> {
if (filter.state.isNotBlank()) {
url.addQueryParameter("artist", filter.state)
}
}
is YearFilter -> {
if (filter.state.isNotBlank()) {
url.addQueryParameter("release", filter.state)
}
}
is StatusFilter -> {
filter.state.forEach {
if (it.state) {
url.addQueryParameter("status[]", it.id)
}
}
}
is OrderByFilter -> {
if (filter.state != 0) {
url.addQueryParameter("m_orderby", filter.toUriPart())
}
}
is AdultContentFilter -> {
url.addQueryParameter("adult", filter.toUriPart())
}
is GenreConditionFilter -> {
url.addQueryParameter("op", filter.toUriPart())
}
is GenreList -> {
filter.state
.filter { it.state }
.let { list ->
if (list.isNotEmpty()) { list.forEach { genre -> url.addQueryParameter("genre[]", genre.id) } }
}
}
is ProjectFilter -> {
if (filter.toUriPart() == "project-filter-on") {
url = "$baseUrl/project/page/$page".toHttpUrlOrNull()!!.newBuilder()
}
}
}
}
return GET(url.toString(), headers)
}
override fun searchMangaSelector() = "div.c-tabs-item__content, div.page-item-detail"
protected class ProjectFilter : UriPartFilter(
"Filter Project",
arrayOf(
Pair("Show all manga", ""),
Pair("Show only project manga", "project-filter-on")
)
)
override fun getFilterList() = FilterList(
AuthorFilter(),
ArtistFilter(),
YearFilter(),
StatusFilter(getStatusList()),
OrderByFilter(),
AdultContentFilter(),
Filter.Separator(),
Filter.Header("Genres may not work for all sources"),
GenreConditionFilter(),
GenreList(getGenreList()),
Filter.Separator(),
Filter.Header("NOTE: cant be used with other filter!"),
Filter.Header("$name Project List page"),
ProjectFilter(),
)
}

View File

@ -16,4 +16,6 @@ class Kiryuu : WPMangaReader("Kiryuu", "https://kiryuu.id", "id") {
.readTimeout(30, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS)
.addNetworkInterceptor(rateLimitInterceptor) .addNetworkInterceptor(rateLimitInterceptor)
.build() .build()
override val hasProjectPage = true
} }

View File

@ -0,0 +1,7 @@
package eu.kanade.tachiyomi.extension.id.mangakita
import eu.kanade.tachiyomi.multisrc.wpmangareader.WPMangaReader
class MangaKita : WPMangaReader("MangaKita", "https://mangakita.net", "id") {
override val hasProjectPage = true
}

View File

@ -9,4 +9,8 @@ class Ngomik : WPMangaReader("Ngomik", "https://ngomik.net", "id", "/all-komik")
override fun headersBuilder(): Headers.Builder = Headers.Builder() override fun headersBuilder(): Headers.Builder = Headers.Builder()
.add("User-Agent", userAgent) .add("User-Agent", userAgent)
.add("Referer", baseUrl) .add("Referer", baseUrl)
override val projectPageString = "/pj"
override val hasProjectPage = true
} }

View File

@ -13,4 +13,6 @@ class Boosei : WPMangaStream("Boosei", "https://boosei.com", "id") {
.readTimeout(30, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS)
.addNetworkInterceptor(rateLimitInterceptor) .addNetworkInterceptor(rateLimitInterceptor)
.build() .build()
override val hasProjectPage = true
} }

View File

@ -13,4 +13,6 @@ class KaisarKomik : WPMangaStream("Kaisar Komik", "https://kaisarkomik.com", "id
.readTimeout(30, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS)
.addNetworkInterceptor(rateLimitInterceptor) .addNetworkInterceptor(rateLimitInterceptor)
.build() .build()
override val hasProjectPage = true
} }

View File

@ -13,4 +13,6 @@ class KlanKomik : WPMangaStream("KlanKomik", "https://klankomik.com", "id") {
.readTimeout(30, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS)
.addNetworkInterceptor(rateLimitInterceptor) .addNetworkInterceptor(rateLimitInterceptor)
.build() .build()
override val hasProjectPage = true
} }

View File

@ -30,4 +30,6 @@ class KomikAV : WPMangaStream(
override fun imageRequest(page: Page): Request { override fun imageRequest(page: Page): Request {
return GET(page.imageUrl!!, headers) return GET(page.imageUrl!!, headers)
} }
override val hasProjectPage = true
} }

View File

@ -63,7 +63,7 @@ class KomikCast : WPMangaStream("Komik Cast", "https://komikcast.com", "id") {
} }
url.toString() url.toString()
} else { } else {
val url = "$baseUrl/daftar-komik/page/$page".toHttpUrlOrNull()!!.newBuilder() var url = "$baseUrl/daftar-komik/page/$page".toHttpUrlOrNull()!!.newBuilder()
var orderBy: String var orderBy: String
(if (filters.isEmpty()) getFilterList() else filters).forEach { filter -> (if (filters.isEmpty()) getFilterList() else filters).forEach { filter ->
when (filter) { when (filter) {
@ -85,6 +85,11 @@ class KomikCast : WPMangaStream("Komik Cast", "https://komikcast.com", "id") {
orderBy = filter.toUriPart() orderBy = filter.toUriPart()
url.addQueryParameter("order", orderBy) url.addQueryParameter("order", orderBy)
} }
is ProjectFilter -> {
if (filter.toUriPart() == "project-filter-on") {
url = "$baseUrl/project-list/page/$page".toHttpUrlOrNull()!!.newBuilder()
}
}
} }
} }
url.toString() url.toString()
@ -158,6 +163,9 @@ class KomikCast : WPMangaStream("Komik Cast", "https://komikcast.com", "id") {
Filter.Separator(), Filter.Separator(),
StatusFilter(), StatusFilter(),
Filter.Separator(), Filter.Separator(),
GenreListFilter(getGenreList()) GenreListFilter(getGenreList()),
Filter.Header("NOTE: cant be used with other filter!"),
Filter.Header("$name Project List page"),
ProjectFilter()
) )
} }

View File

@ -16,4 +16,6 @@ class KomikindoCo : WPMangaStream("KomikIndo.co", "https://komikindo.co", "id")
.readTimeout(30, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS)
.addNetworkInterceptor(rateLimitInterceptor) .addNetworkInterceptor(rateLimitInterceptor)
.build() .build()
override val hasProjectPage = true
} }

View File

@ -46,4 +46,8 @@ class KomikStation : WPMangaStream("Komik Station", "https://komikstation.com",
return pages return pages
} }
override val projectPageString = "/project-list"
override val hasProjectPage = true
} }

View File

@ -13,4 +13,6 @@ class KumaScans : WPMangaStream("Kuma Scans (Kuma Translation)", "https://kumasc
.readTimeout(30, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS)
.addNetworkInterceptor(rateLimitInterceptor) .addNetworkInterceptor(rateLimitInterceptor)
.build() .build()
override val hasProjectPage = true
} }

View File

@ -13,4 +13,8 @@ class MasterKomik : WPMangaStream("MasterKomik", "https://masterkomik.com", "id"
.readTimeout(30, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS)
.addNetworkInterceptor(rateLimitInterceptor) .addNetworkInterceptor(rateLimitInterceptor)
.build() .build()
override val projectPageString = "/project-list"
override val hasProjectPage = true
} }

View File

@ -13,4 +13,6 @@ class ReadKomik : WPMangaStream("Readkomik", "https://readkomik.com", "en") {
.readTimeout(30, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS)
.addNetworkInterceptor(rateLimitInterceptor) .addNetworkInterceptor(rateLimitInterceptor)
.build() .build()
override val hasProjectPage = true
} }

View File

@ -34,4 +34,6 @@ class SekteKomik : WPMangaStream("Sekte Komik", "https://sektekomik.com", "id")
return GET(page.imageUrl!!, newHeaders) return GET(page.imageUrl!!, newHeaders)
} }
override val hasProjectPage = true
} }

View File

@ -21,4 +21,5 @@ class SheaManga : WPMangaStream(
.addNetworkInterceptor(rateLimitInterceptor) .addNetworkInterceptor(rateLimitInterceptor)
.build() .build()
override val hasProjectPage = true
} }

View File

@ -119,4 +119,6 @@ class WestManga : WPMangaStream("West Manga", "https://westmanga.info", "id") {
Genre("Yaoi", "yaoi"), Genre("Yaoi", "yaoi"),
Genre("Zombies", "377") Genre("Zombies", "377")
) )
override val hasProjectPage = true
} }

View File

@ -4,4 +4,8 @@ import eu.kanade.tachiyomi.multisrc.wpmangastream.WPMangaStream
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Locale import java.util.Locale
class WorldRomanceTranslation : WPMangaStream("World Romance Translation", "https://wrt.my.id/", "id", SimpleDateFormat("MMMM dd, yyyy", Locale("id"))) class WorldRomanceTranslation : WPMangaStream("World Romance Translation", "https://wrt.my.id/", "id", SimpleDateFormat("MMMM dd, yyyy", Locale("id"))) {
override val projectPageString = "/project-wrt"
override val hasProjectPage = true
}

View File

@ -16,4 +16,5 @@ class xCaliBRScans : WPMangaStream("xCaliBR Scans", "https://xcalibrscans.com",
.addNetworkInterceptor(rateLimitInterceptor) .addNetworkInterceptor(rateLimitInterceptor)
.build() .build()
override val hasProjectPage = true
} }

View File

@ -188,12 +188,12 @@ abstract class Madara(
return GET(url.toString(), headers) return GET(url.toString(), headers)
} }
private class AuthorFilter : Filter.Text("Author") protected class AuthorFilter : Filter.Text("Author")
private class ArtistFilter : Filter.Text("Artist") protected class ArtistFilter : Filter.Text("Artist")
private class YearFilter : Filter.Text("Year of Released") protected class YearFilter : Filter.Text("Year of Released")
private class StatusFilter(status: List<Tag>) : Filter.Group<Tag>("Status", status) protected class StatusFilter(status: List<Tag>) : Filter.Group<Tag>("Status", status)
private class OrderByFilter : UriPartFilter( protected class OrderByFilter : UriPartFilter(
"Order By", "Order By",
arrayOf( arrayOf(
Pair("<select>", ""), Pair("<select>", ""),
@ -206,7 +206,7 @@ abstract class Madara(
) )
) )
private class GenreConditionFilter : UriPartFilter( protected class GenreConditionFilter : UriPartFilter(
"Genre condition", "Genre condition",
arrayOf( arrayOf(
Pair("or", ""), Pair("or", ""),
@ -214,7 +214,7 @@ abstract class Madara(
) )
) )
private class AdultContentFilter : UriPartFilter( protected class AdultContentFilter : UriPartFilter(
"Adult Content", "Adult Content",
arrayOf( arrayOf(
Pair("All", ""), Pair("All", ""),
@ -223,7 +223,7 @@ abstract class Madara(
) )
) )
private class GenreList(genres: List<Genre>) : Filter.Group<Genre>("Genres", genres) protected class GenreList(genres: List<Genre>) : Filter.Group<Genre>("Genres", genres)
class Genre(name: String, val id: String = name) : Filter.CheckBox(name) class Genre(name: String, val id: String = name) : Filter.CheckBox(name)
open fun getGenreList() = listOf( open fun getGenreList() = listOf(
@ -301,7 +301,7 @@ abstract class Madara(
GenreList(getGenreList()) GenreList(getGenreList())
) )
private fun getStatusList() = listOf( protected fun getStatusList() = listOf(
Tag("end", "Completed"), Tag("end", "Completed"),
Tag("on-going", "Ongoing"), Tag("on-going", "Ongoing"),
Tag("canceled", "Canceled"), Tag("canceled", "Canceled"),

View File

@ -193,7 +193,7 @@ class MadaraGenerator : ThemeSourceGenerator {
SingleLang("Paean Scans", "https://paeanscans.com", "en", overrideVersionCode = 1), SingleLang("Paean Scans", "https://paeanscans.com", "en", overrideVersionCode = 1),
SingleLang("Painful Nightz Scan", "https://painfulnightzscan.com", "en"), SingleLang("Painful Nightz Scan", "https://painfulnightzscan.com", "en"),
SingleLang("Platinum Crown", "https://platinumscans.com", "en", overrideVersionCode = 1), SingleLang("Platinum Crown", "https://platinumscans.com", "en", overrideVersionCode = 1),
SingleLang("Pojok Manga", "https://pojokmanga.com", "id", overrideVersionCode = 1), SingleLang("Pojok Manga", "https://pojokmanga.com", "id", overrideVersionCode = 2),
SingleLang("PornComix", "https://www.porncomixonline.net", "en", isNsfw = true, overrideVersionCode = 1), SingleLang("PornComix", "https://www.porncomixonline.net", "en", isNsfw = true, overrideVersionCode = 1),
SingleLang("Projeto Scanlator", "https://projetoscanlator.com", "pt-BR", overrideVersionCode = 2), SingleLang("Projeto Scanlator", "https://projetoscanlator.com", "pt-BR", overrideVersionCode = 2),
SingleLang("QueensManga ملكات المانجا", "https://queensmanga.com", "ar", className = "QueensManga"), SingleLang("QueensManga ملكات المانجا", "https://queensmanga.com", "ar", className = "QueensManga"),

View File

@ -113,7 +113,7 @@ abstract class WPMangaReader(
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
val url = "$baseUrl".toHttpUrlOrNull()!!.newBuilder() var url = "$baseUrl".toHttpUrlOrNull()!!.newBuilder()
if (query.isNotEmpty()) { if (query.isNotEmpty()) {
url.addPathSegments("page/$page").addQueryParameter("s", query) url.addPathSegments("page/$page").addQueryParameter("s", query)
} else { } else {
@ -121,12 +121,20 @@ abstract class WPMangaReader(
filters.forEach { filter -> filters.forEach { filter ->
when (filter) { when (filter) {
is UrlEncoded -> filter.encode(url) is UrlEncoded -> filter.encode(url)
// if site has project page, default value "hasProjectPage" = false
is ProjectFilter -> {
if (filter.toUriPart() == "project-filter-on") {
url = "$baseUrl$projectPageString/page/$page".toHttpUrlOrNull()!!.newBuilder()
}
}
} }
} }
} }
return GET("$url") return GET("$url")
} }
open val projectPageString = "/project"
override fun searchMangaParse(response: Response): MangasPage { override fun searchMangaParse(response: Response): MangasPage {
if (genrelist == null) if (genrelist == null)
genrelist = parseGenres(response.asJsoup(response.peekBody(Long.MAX_VALUE).string())) genrelist = parseGenres(response.asJsoup(response.peekBody(Long.MAX_VALUE).string()))
@ -274,14 +282,42 @@ abstract class WPMangaReader(
get() = this.elems.asSequence().filterIndexed { i, _ -> this.state[i].state } get() = this.elems.asSequence().filterIndexed { i, _ -> this.state[i].state }
} }
open val hasProjectPage = false
// filters // filters
override fun getFilterList() = FilterList( override fun getFilterList(): FilterList {
val filters = mutableListOf<Filter<*>>(
Filter.Header("NOTE: Ignored if using text search!"), Filter.Header("NOTE: Ignored if using text search!"),
GenreFilter(), GenreFilter(),
StatusFilter(), StatusFilter(),
TypesFilter(), TypesFilter(),
OrderByFilter(), OrderByFilter(),
) )
if (hasProjectPage) {
filters.addAll(
mutableListOf<Filter<*>>(
Filter.Separator(),
Filter.Header("NOTE: cant be used with other filter!"),
Filter.Header("$name Project List page"),
ProjectFilter(),
)
)
}
return FilterList(filters)
}
protected class ProjectFilter : UriPartFilter(
"Filter Project",
arrayOf(
Pair("Show all manga", ""),
Pair("Show only project manga", "project-filter-on")
)
)
open class UriPartFilter(displayName: String, private val vals: Array<Pair<String, String>>) :
Filter.Select<String>(displayName, vals.map { it.first }.toTypedArray()) {
fun toUriPart() = vals[state].second
}
private fun GenreFilter() = object : MultiSelect<LabeledValue>("Genre", getGenreList()), UrlEncoded { private fun GenreFilter() = object : MultiSelect<LabeledValue>("Genre", getGenreList()), UrlEncoded {
override fun encode(url: HttpUrl.Builder) { override fun encode(url: HttpUrl.Builder) {

View File

@ -12,11 +12,11 @@ class WPMangaReaderGenerator : ThemeSourceGenerator {
override val baseVersionCode: Int = 7 override val baseVersionCode: Int = 7
override val sources = listOf( override val sources = listOf(
SingleLang("Kiryuu", "https://kiryuu.id", "id"), SingleLang("Kiryuu", "https://kiryuu.id", "id", overrideVersionCode = 1),
SingleLang("KomikMama", "https://komikmama.net", "id"), SingleLang("KomikMama", "https://komikmama.net", "id"),
SingleLang("MangaKita", "https://mangakita.net", "id"), SingleLang("MangaKita", "https://mangakita.net", "id", overrideVersionCode = 1),
SingleLang("Martial Manga", "https://martialmanga.com/", "es"), SingleLang("Martial Manga", "https://martialmanga.com/", "es"),
SingleLang("Ngomik", "https://ngomik.net", "id"), SingleLang("Ngomik", "https://ngomik.net", "id", overrideVersionCode = 1),
SingleLang("Sekaikomik", "https://www.sekaikomik.xyz", "id", isNsfw = true, overrideVersionCode = 5), SingleLang("Sekaikomik", "https://www.sekaikomik.xyz", "id", isNsfw = true, overrideVersionCode = 5),
SingleLang("Davey Scans", "https://daveyscans.com/", "id"), SingleLang("Davey Scans", "https://daveyscans.com/", "id"),
SingleLang("Mangasusu", "https://mangasusu.co.in", "id", isNsfw = true), SingleLang("Mangasusu", "https://mangasusu.co.in", "id", isNsfw = true),

View File

@ -88,7 +88,7 @@ abstract class WPMangaStream(
} }
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
val url = "$baseUrl/manga/".toHttpUrlOrNull()!!.newBuilder() var url = "$baseUrl/manga/".toHttpUrlOrNull()!!.newBuilder()
url.addQueryParameter("title", query) url.addQueryParameter("title", query)
url.addQueryParameter("page", page.toString()) url.addQueryParameter("page", page.toString())
filters.forEach { filter -> filters.forEach { filter ->
@ -118,11 +118,19 @@ abstract class WPMangaStream(
.filter { it.state != Filter.TriState.STATE_IGNORE } .filter { it.state != Filter.TriState.STATE_IGNORE }
.forEach { url.addQueryParameter("genre[]", it.id) } .forEach { url.addQueryParameter("genre[]", it.id) }
} }
// if site has project page, default value "hasProjectPage" = false
is ProjectFilter -> {
if (filter.toUriPart() == "project-filter-on") {
url = "$baseUrl$projectPageString/page/$page".toHttpUrlOrNull()!!.newBuilder()
}
}
} }
} }
return GET(url.build().toString(), headers) return GET(url.build().toString(), headers)
} }
open val projectPageString = "/project"
override fun popularMangaSelector() = "div.bs" override fun popularMangaSelector() = "div.bs"
override fun latestUpdatesSelector() = popularMangaSelector() override fun latestUpdatesSelector() = popularMangaSelector()
override fun searchMangaSelector() = popularMangaSelector() override fun searchMangaSelector() = popularMangaSelector()
@ -352,10 +360,21 @@ abstract class WPMangaStream(
) )
) )
protected class ProjectFilter : UriPartFilter(
"Filter Project",
arrayOf(
Pair("Show all manga", ""),
Pair("Show only project manga", "project-filter-on")
)
)
protected class Genre(name: String, val id: String = name) : Filter.TriState(name) protected class Genre(name: String, val id: String = name) : Filter.TriState(name)
protected class GenreListFilter(genres: List<Genre>) : Filter.Group<Genre>("Genre", genres) protected class GenreListFilter(genres: List<Genre>) : Filter.Group<Genre>("Genre", genres)
override fun getFilterList() = FilterList( open val hasProjectPage = false
override fun getFilterList(): FilterList {
val filters = mutableListOf<Filter<*>>(
Filter.Header("NOTE: Ignored if using text search!"), Filter.Header("NOTE: Ignored if using text search!"),
Filter.Header("Genre exclusion not available for all sources"), Filter.Header("Genre exclusion not available for all sources"),
Filter.Separator(), Filter.Separator(),
@ -364,8 +383,20 @@ abstract class WPMangaStream(
StatusFilter(), StatusFilter(),
TypeFilter(), TypeFilter(),
SortByFilter(), SortByFilter(),
GenreListFilter(getGenreList()) GenreListFilter(getGenreList()),
) )
if (hasProjectPage) {
filters.addAll(
mutableListOf<Filter<*>>(
Filter.Separator(),
Filter.Header("NOTE: cant be used with other filter!"),
Filter.Header("$name Project List page"),
ProjectFilter(),
)
)
}
return FilterList(filters)
}
protected open fun getGenreList(): List<Genre> = listOf( protected open fun getGenreList(): List<Genre> = listOf(
Genre("4 Koma", "4-koma"), Genre("4 Koma", "4-koma"),

View File

@ -13,33 +13,33 @@ class WPMangaStreamGenerator : ThemeSourceGenerator {
override val sources = listOf( override val sources = listOf(
SingleLang("Asura Scans", "https://www.asurascans.com", "en", overrideVersionCode = 1), SingleLang("Asura Scans", "https://www.asurascans.com", "en", overrideVersionCode = 1),
SingleLang("KlanKomik", "https://klankomik.com", "id"), SingleLang("KlanKomik", "https://klankomik.com", "id", overrideVersionCode = 1),
SingleLang("MasterKomik", "https://masterkomik.com", "id"), SingleLang("MasterKomik", "https://masterkomik.com", "id", overrideVersionCode = 1),
SingleLang("Kaisar Komik", "https://kaisarkomik.com", "id"), SingleLang("Kaisar Komik", "https://kaisarkomik.com", "id", overrideVersionCode = 1),
SingleLang("Rawkuma", "https://rawkuma.com/", "ja"), SingleLang("Rawkuma", "https://rawkuma.com/", "ja"),
SingleLang("Boosei", "https://boosei.com", "id"), SingleLang("Boosei", "https://boosei.com", "id", overrideVersionCode = 1),
SingleLang("Mangakyo", "https://www.mangakyo.me", "id"), SingleLang("Mangakyo", "https://www.mangakyo.me", "id"),
SingleLang("Sekte Komik", "https://sektekomik.com", "id", overrideVersionCode = 2), SingleLang("Sekte Komik", "https://sektekomik.com", "id", overrideVersionCode = 3),
SingleLang("Komik Station", "https://komikstation.com", "id", overrideVersionCode = 1), SingleLang("Komik Station", "https://komikstation.com", "id", overrideVersionCode = 2),
SingleLang("Non-Stop Scans", "https://www.nonstopscans.com", "en", className = "NonStopScans"), SingleLang("Non-Stop Scans", "https://www.nonstopscans.com", "en", className = "NonStopScans"),
SingleLang("KomikIndo.co", "https://komikindo.co", "id", className = "KomikindoCo"), SingleLang("KomikIndo.co", "https://komikindo.co", "id", className = "KomikindoCo", overrideVersionCode = 1),
SingleLang("Readkomik", "https://readkomik.com", "en", className = "ReadKomik"), SingleLang("Readkomik", "https://readkomik.com", "en", className = "ReadKomik", overrideVersionCode = 1),
SingleLang("MangaIndonesia", "https://mangaindonesia.net", "id"), SingleLang("MangaIndonesia", "https://mangaindonesia.net", "id"),
SingleLang("Liebe Schnee Hiver", "https://www.liebeschneehiver.com", "tr"), SingleLang("Liebe Schnee Hiver", "https://www.liebeschneehiver.com", "tr"),
SingleLang("GURU Komik", "https://gurukomik.com", "id"), SingleLang("GURU Komik", "https://gurukomik.com", "id"),
SingleLang("Shea Manga", "https://sheamanga.my.id", "id"), SingleLang("Shea Manga", "https://sheamanga.my.id", "id", overrideVersionCode = 1),
SingleLang("Komik AV", "https://komikav.com", "id"), SingleLang("Komik AV", "https://komikav.com", "id", overrideVersionCode = 1),
SingleLang("Komik Cast", "https://komikcast.com", "id", overrideVersionCode = 6), SingleLang("Komik Cast", "https://komikcast.com", "id", overrideVersionCode = 7),
SingleLang("West Manga", "https://westmanga.info", "id"), SingleLang("West Manga", "https://westmanga.info", "id", overrideVersionCode = 1),
SingleLang("MangaSwat", "https://mangaswat.com", "ar"), SingleLang("MangaSwat", "https://mangaswat.com", "ar"),
SingleLang("Manga Raw.org", "https://mangaraw.org", "ja", className = "MangaRawOrg", overrideVersionCode = 1), SingleLang("Manga Raw.org", "https://mangaraw.org", "ja", className = "MangaRawOrg", overrideVersionCode = 1),
SingleLang("Manga Pro Z", "https://mangaproz.com", "ar"), SingleLang("Manga Pro Z", "https://mangaproz.com", "ar"),
SingleLang("Silence Scan", "https://silencescan.net", "pt-BR", overrideVersionCode = 2), SingleLang("Silence Scan", "https://silencescan.net", "pt-BR", overrideVersionCode = 2),
SingleLang("Kuma Scans (Kuma Translation)", "https://kumascans.com", "en", className = "KumaScans"), SingleLang("Kuma Scans (Kuma Translation)", "https://kumascans.com", "en", className = "KumaScans", overrideVersionCode = 1),
SingleLang("Tempest Manga", "https://manga.tempestfansub.com", "tr"), SingleLang("Tempest Manga", "https://manga.tempestfansub.com", "tr"),
SingleLang("xCaliBR Scans", "https://xcalibrscans.com", "en", overrideVersionCode = 2), SingleLang("xCaliBR Scans", "https://xcalibrscans.com", "en", overrideVersionCode = 2),
SingleLang("NoxSubs", "https://noxsubs.com", "tr"), SingleLang("NoxSubs", "https://noxsubs.com", "tr"),
SingleLang("World Romance Translation", "https://wrt.my.id/", "id", overrideVersionCode = 1), SingleLang("World Romance Translation", "https://wrt.my.id/", "id", overrideVersionCode = 2),
SingleLang("The Apollo Team", "https://theapollo.team", "en"), SingleLang("The Apollo Team", "https://theapollo.team", "en"),
SingleLang("Sekte Doujin", "https://sektedoujin.xyz", "id", isNsfw = true), SingleLang("Sekte Doujin", "https://sektedoujin.xyz", "id", isNsfw = true),
SingleLang("Lemon Juice Scan", "https://lemonjuicescan.com", "pt-BR", isNsfw = true), SingleLang("Lemon Juice Scan", "https://lemonjuicescan.com", "pt-BR", isNsfw = true),

View File

@ -5,7 +5,7 @@ ext {
extName = 'Komiku' extName = 'Komiku'
pkgNameSuffix = 'id.komiku' pkgNameSuffix = 'id.komiku'
extClass = '.Komiku' extClass = '.Komiku'
extVersionCode = 13 extVersionCode = 14
libVersion = '1.2' libVersion = '1.2'
} }

View File

@ -79,7 +79,7 @@ class Komiku : ParsedHttpSource() {
override fun searchMangaSelector() = popularMangaSelector() override fun searchMangaSelector() = popularMangaSelector()
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
val url = "$baseUrl/pustaka/page/$page/".toHttpUrlOrNull()?.newBuilder()!!.addQueryParameter("s", query) var url = "$baseUrl/pustaka/page/$page/".toHttpUrlOrNull()?.newBuilder()!!.addQueryParameter("s", query)
(if (filters.isEmpty()) getFilterList() else filters).forEach { filter -> (if (filters.isEmpty()) getFilterList() else filters).forEach { filter ->
when (filter) { when (filter) {
is CategoryNames -> { is CategoryNames -> {
@ -102,6 +102,12 @@ class Komiku : ParsedHttpSource() {
val status = filter.values[filter.state] val status = filter.values[filter.state]
url.addQueryParameter("status", status.key) url.addQueryParameter("status", status.key)
} }
is ProjectList -> {
val project = filter.values[filter.state]
if (project.key == "project-filter-on") {
url = ("$baseUrl/pustaka" + if (page > 1) "/page/$page/" else "" + "?tipe=projek").toHttpUrlOrNull()!!.newBuilder()
}
}
} }
} }
return GET(url.toString(), headers) return GET(url.toString(), headers)
@ -140,13 +146,23 @@ class Komiku : ParsedHttpSource() {
private class GenreList1(genres: Array<Genre>) : Filter.Select<Genre>("Genre 1", genres, 0) private class GenreList1(genres: Array<Genre>) : Filter.Select<Genre>("Genre 1", genres, 0)
private class GenreList2(genres: Array<Genre>) : Filter.Select<Genre>("Genre 2", genres, 0) private class GenreList2(genres: Array<Genre>) : Filter.Select<Genre>("Genre 2", genres, 0)
private class StatusList(statuses: Array<Status>) : Filter.Select<Status>("Status", statuses, 0) private class StatusList(statuses: Array<Status>) : Filter.Select<Status>("Status", statuses, 0)
private class ProjectList(project: Array<Status>) : Filter.Select<Status>("Filter Project", project, 0)
override fun getFilterList() = FilterList( override fun getFilterList() = FilterList(
CategoryNames(categoryNames), CategoryNames(categoryNames),
OrderBy(orderBy), OrderBy(orderBy),
GenreList1(genreList), GenreList1(genreList),
GenreList2(genreList), GenreList2(genreList),
StatusList(statusList) StatusList(statusList),
Filter.Separator(),
Filter.Header("NOTE: cant be used with other filter!"),
Filter.Header("$name Project List page"),
ProjectList(ProjectFilter),
)
private val ProjectFilter = arrayOf(
Status("Show all manga", ""),
Status("Show only project manga", "project-filter-on")
) )
private val categoryNames = arrayOf( private val categoryNames = arrayOf(

View File

@ -5,7 +5,7 @@ ext {
extName = 'Maid - Manga' extName = 'Maid - Manga'
pkgNameSuffix = 'id.maidmanga' pkgNameSuffix = 'id.maidmanga'
extClass = '.MaidManga' extClass = '.MaidManga'
extVersionCode = 7 extVersionCode = 8
libVersion = '1.2' libVersion = '1.2'
} }

View File

@ -50,7 +50,7 @@ class MaidManga : ParsedHttpSource() {
override fun popularMangaNextPageSelector() = searchMangaNextPageSelector() override fun popularMangaNextPageSelector() = searchMangaNextPageSelector()
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
val url = "$baseUrl/advanced-search/${pagePathSegment(page)}".toHttpUrlOrNull()!!.newBuilder() var url = "$baseUrl/advanced-search/${pagePathSegment(page)}".toHttpUrlOrNull()!!.newBuilder()
url.addQueryParameter("title", query) url.addQueryParameter("title", query)
(if (filters.isEmpty()) getFilterList() else filters).forEach { filter -> (if (filters.isEmpty()) getFilterList() else filters).forEach { filter ->
when (filter) { when (filter) {
@ -79,6 +79,11 @@ class MaidManga : ParsedHttpSource() {
.filter { it.state } .filter { it.state }
.forEach { url.addQueryParameter("genre[]", it.id) } .forEach { url.addQueryParameter("genre[]", it.id) }
} }
is ProjectFilter -> {
if (filter.toUriPart() == "project-filter-on") {
url = "$baseUrl/project-list/page/$page".toHttpUrlOrNull()!!.newBuilder()
}
}
} }
} }
return GET(url.toString(), headers) return GET(url.toString(), headers)
@ -162,7 +167,19 @@ class MaidManga : ParsedHttpSource() {
StatusFilter(), StatusFilter(),
TypeFilter(), TypeFilter(),
OrderByFilter(), OrderByFilter(),
GenreList(getGenreList()) GenreList(getGenreList()),
Filter.Separator(),
Filter.Header("NOTE: cant be used with other filter!"),
Filter.Header("$name Project List page"),
ProjectFilter(),
)
private class ProjectFilter : UriPartFilter(
"Filter Project",
arrayOf(
Pair("Show all manga", ""),
Pair("Show only project manga", "project-filter-on")
)
) )
private class AuthorFilter : Filter.Text("Author") private class AuthorFilter : Filter.Text("Author")

View File

@ -5,7 +5,7 @@ ext {
extName = 'MangaKane' extName = 'MangaKane'
pkgNameSuffix = 'id.mangakane' pkgNameSuffix = 'id.mangakane'
extClass = '.MangaKane' extClass = '.MangaKane'
extVersionCode = 1 extVersionCode = 2
libVersion = '1.2' libVersion = '1.2'
} }

View File

@ -1,6 +1,7 @@
package eu.kanade.tachiyomi.extension.id.mangakane package eu.kanade.tachiyomi.extension.id.mangakane
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.source.model.FilterList import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
@ -29,9 +30,18 @@ class MangaKane : ParsedHttpSource() {
} }
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
val url = "$baseUrl/page/$page/?".toHttpUrlOrNull()!!.newBuilder() var url = "$baseUrl/page/$page/".toHttpUrlOrNull()!!.newBuilder()
.addQueryParameter("s", query) url.addQueryParameter("s", query)
return GET(url.toString(), headers) filters.forEach { filter ->
when (filter) {
is ProjectFilter -> {
if (filter.toUriPart() == "project-filter-on") {
url = "$baseUrl/project-list/page/$page".toHttpUrlOrNull()!!.newBuilder()
}
}
}
}
return GET(url.build().toString(), headers)
} }
override fun popularMangaSelector() = ".container .flexbox2 .flexbox2-item" override fun popularMangaSelector() = ".container .flexbox2 .flexbox2-item"
@ -99,4 +109,23 @@ class MangaKane : ParsedHttpSource() {
} }
override fun imageUrlParse(document: Document) = "" override fun imageUrlParse(document: Document) = ""
override fun getFilterList() = FilterList(
Filter.Header("NOTE: cant be used with search or other filter!"),
Filter.Header("$name Project List page"),
ProjectFilter(),
)
private class ProjectFilter : UriPartFilter(
"Filter Project",
arrayOf(
Pair("Show all manga", ""),
Pair("Show only project manga", "project-filter-on")
)
)
private open class UriPartFilter(displayName: String, val vals: Array<Pair<String, String>>) :
Filter.Select<String>(displayName, vals.map { it.first }.toTypedArray()) {
fun toUriPart() = vals[state].second
}
} }

View File

@ -5,7 +5,7 @@ ext {
extName = 'ManhuaID' extName = 'ManhuaID'
pkgNameSuffix = 'id.manhuaid' pkgNameSuffix = 'id.manhuaid'
extClass = '.ManhuaID' extClass = '.ManhuaID'
extVersionCode = 6 extVersionCode = 7
libVersion = '1.2' libVersion = '1.2'
} }

View File

@ -1,13 +1,16 @@
package eu.kanade.tachiyomi.extension.id.manhuaid package eu.kanade.tachiyomi.extension.id.manhuaid
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.source.model.FilterList import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response import okhttp3.Response
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
@ -34,7 +37,7 @@ class ManhuaID : ParsedHttpSource() {
override fun popularMangaFromElement(element: Element) = SManga.create().apply { override fun popularMangaFromElement(element: Element) = SManga.create().apply {
setUrlWithoutDomain(element.attr("href")) setUrlWithoutDomain(element.attr("href"))
title = element.select("img").attr("alt") title = element.select("img").attr("alt")
thumbnail_url = element.select("img").attr("src") thumbnail_url = element.select("img").attr("abs:src")
} }
override fun popularMangaNextPageSelector() = "[rel=nofollow]" override fun popularMangaNextPageSelector() = "[rel=nofollow]"
@ -51,11 +54,23 @@ class ManhuaID : ParsedHttpSource() {
// search // search
override fun searchMangaSelector() = popularMangaSelector() override fun searchMangaSelector() = popularMangaSelector()
override fun searchMangaRequest(page: Int, query: String, filters: FilterList) = GET("$baseUrl/search?q=$query", headers) override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
var url = "$baseUrl/search?".toHttpUrlOrNull()!!.newBuilder()
url.addQueryParameter("q", query)
filters.forEach { filter ->
when (filter) {
is ProjectFilter -> {
if (filter.toUriPart() == "project-filter-on") {
url = "$baseUrl/project?page_project=$page".toHttpUrlOrNull()!!.newBuilder()
}
}
}
}
return GET(url.toString(), headers)
}
override fun searchMangaFromElement(element: Element) = popularMangaFromElement(element) override fun searchMangaFromElement(element: Element) = popularMangaFromElement(element)
override fun searchMangaNextPageSelector(): String? = null override fun searchMangaNextPageSelector() = "li:last-child:not(.active) [rel=nofollow]"
// manga details // manga details
override fun mangaDetailsParse(document: Document) = SManga.create().apply { override fun mangaDetailsParse(document: Document) = SManga.create().apply {
@ -114,4 +129,23 @@ class ManhuaID : ParsedHttpSource() {
} }
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not Used") override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not Used")
override fun getFilterList() = FilterList(
Filter.Header("NOTE: cant be used with search or other filter!"),
Filter.Header("$name Project List page"),
ProjectFilter(),
)
private class ProjectFilter : UriPartFilter(
"Filter Project",
arrayOf(
Pair("Show all manga", ""),
Pair("Show only project manga", "project-filter-on")
)
)
private open class UriPartFilter(displayName: String, val vals: Array<Pair<String, String>>) :
Filter.Select<String>(displayName, vals.map { it.first }.toTypedArray()) {
fun toUriPart() = vals[state].second
}
} }