diff --git a/lib-multisrc/keyoapp/src/eu/kanade/tachiyomi/multisrc/keyoapp/Keyoapp.kt b/lib-multisrc/keyoapp/src/eu/kanade/tachiyomi/multisrc/keyoapp/Keyoapp.kt index 67ecaf825..d98bf1380 100644 --- a/lib-multisrc/keyoapp/src/eu/kanade/tachiyomi/multisrc/keyoapp/Keyoapp.kt +++ b/lib-multisrc/keyoapp/src/eu/kanade/tachiyomi/multisrc/keyoapp/Keyoapp.kt @@ -191,7 +191,7 @@ abstract class Keyoapp( } } - private fun genresRequest(): Request = GET("$baseUrl/series/", headers) + protected open fun genresRequest(): Request = GET("$baseUrl/series/", headers) /** * Get the genres from the search page document. diff --git a/src/en/ritharscans/build.gradle b/src/en/ritharscans/build.gradle new file mode 100644 index 000000000..2fcc0aab6 --- /dev/null +++ b/src/en/ritharscans/build.gradle @@ -0,0 +1,10 @@ +ext { + extName = 'RitharScans' + extClass = '.RitharScans' + themePkg = 'keyoapp' + baseUrl = 'https://ritharscans.com' + overrideVersionCode = 0 + isNsfw = false +} + +apply from: "$rootDir/common.gradle" diff --git a/src/en/ritharscans/res/mipmap-hdpi/ic_launcher.png b/src/en/ritharscans/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 000000000..a12b99546 Binary files /dev/null and b/src/en/ritharscans/res/mipmap-hdpi/ic_launcher.png differ diff --git a/src/en/ritharscans/res/mipmap-mdpi/ic_launcher.png b/src/en/ritharscans/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 000000000..d082baffe Binary files /dev/null and b/src/en/ritharscans/res/mipmap-mdpi/ic_launcher.png differ diff --git a/src/en/ritharscans/res/mipmap-xhdpi/ic_launcher.png b/src/en/ritharscans/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 000000000..3b3dfe17c Binary files /dev/null and b/src/en/ritharscans/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/src/en/ritharscans/res/mipmap-xxhdpi/ic_launcher.png b/src/en/ritharscans/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..bc23e82e4 Binary files /dev/null and b/src/en/ritharscans/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/src/en/ritharscans/res/mipmap-xxxhdpi/ic_launcher.png b/src/en/ritharscans/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 000000000..69de83d6c Binary files /dev/null and b/src/en/ritharscans/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/src/en/ritharscans/src/eu/kanade/tachiyomi/extension/en/ritharscans/RitharScans.kt b/src/en/ritharscans/src/eu/kanade/tachiyomi/extension/en/ritharscans/RitharScans.kt new file mode 100644 index 000000000..17f595655 --- /dev/null +++ b/src/en/ritharscans/src/eu/kanade/tachiyomi/extension/en/ritharscans/RitharScans.kt @@ -0,0 +1,99 @@ +package eu.kanade.tachiyomi.extension.en.ritharscans + +import eu.kanade.tachiyomi.multisrc.keyoapp.Keyoapp +import eu.kanade.tachiyomi.network.GET +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.util.asJsoup +import keiyoushi.utils.parseAs +import kotlinx.serialization.Serializable +import okhttp3.HttpUrl.Companion.toHttpUrl +import okhttp3.Request +import okhttp3.Response +import org.jsoup.nodes.Document + +class RitharScans : Keyoapp("RitharScans", "https://ritharscans.com", "en") { + + override fun popularMangaParse(response: Response): MangasPage { + val mangas = super.popularMangaParse(response).mangas + .distinctBy { it.url } + + return MangasPage(mangas, false) + } + + override fun genresRequest() = GET("$baseUrl/search/", headers) + + override fun parseGenres(document: Document): List { + return document.select("[x-data*=genre] button").map { + val name = it.text() + val id = it.attr("wire:key") + + Genre(name, id) + } + } + + override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { + val url = baseUrl.toHttpUrl().newBuilder().apply { + addPathSegment("search") + if (query.isNotBlank()) { + addQueryParameter("title", query) + } + filters.firstOrNull { it is GenreList }?.also { + val filter = it as GenreList + filter.state + .filter { it.state } + .forEach { genre -> + addQueryParameter("genre", genre.id) + } + } + }.build() + + return GET(url, headers) + } + + override fun searchMangaSelector() = "[wire:snapshot*=pages.search] button[tags]" + + override fun searchMangaParse(response: Response): MangasPage { + runCatching { fetchGenres() } + + val mangas = response.asJsoup() + .select(searchMangaSelector()) + .map(::searchMangaFromElement) + + return MangasPage(mangas, false) + } + + override val descriptionSelector = "#expand_content" + override val statusSelector = "[alt=Status]" + override val genreSelector = "[alt=Type]" + + override fun pageListParse(document: Document): List { + val (pages, baseLink) = document.selectFirst("[x-data]")!!.attr("x-data") + .replace(spaces, "") + .let { + val pages = pagesRegex.find(it)!!.groupValues[1] + .replace(""", "\"") + .parseAs>() + + val baseLink = linkRegex.find( + it.replace("\"", "'"), + )!!.groupValues[1] + + pages to baseLink + } + + return pages.mapIndexed { i, img -> + Page(i, document.location(), baseLink + img.path) + } + } +} + +private val spaces = Regex("\\s") +private val pagesRegex = Regex("pages:(\\[[^]]+])") +private val linkRegex = Regex("baseLink:'([^']+)'") + +@Serializable +class Path( + val path: String, +)