Remove Reaper Scans (unoriginal) (#8034)
This commit is contained in:
parent
d7f03a9caa
commit
13949bc6f3
@ -1,7 +0,0 @@
|
|||||||
ext {
|
|
||||||
extName = 'Reaper Scans (unoriginal)'
|
|
||||||
extClass = '.ReaperScansUnoriginal'
|
|
||||||
extVersionCode = 33
|
|
||||||
}
|
|
||||||
|
|
||||||
apply from: "$rootDir/common.gradle"
|
|
Binary file not shown.
Before Width: | Height: | Size: 4.2 KiB |
Binary file not shown.
Before Width: | Height: | Size: 2.4 KiB |
Binary file not shown.
Before Width: | Height: | Size: 5.6 KiB |
Binary file not shown.
Before Width: | Height: | Size: 10 KiB |
Binary file not shown.
Before Width: | Height: | Size: 14 KiB |
@ -1,107 +0,0 @@
|
|||||||
package eu.kanade.tachiyomi.extension.en.reaperscansunoriginal
|
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.source.model.Filter
|
|
||||||
import eu.kanade.tachiyomi.source.model.FilterList
|
|
||||||
import okhttp3.HttpUrl
|
|
||||||
|
|
||||||
interface UrlPartFilter {
|
|
||||||
fun addUrlParameter(url: HttpUrl.Builder)
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class SelectFilter(
|
|
||||||
name: String,
|
|
||||||
private val urlParameter: String,
|
|
||||||
private val options: List<Pair<String, String>>,
|
|
||||||
defaultValue: String? = null,
|
|
||||||
) : UrlPartFilter, Filter.Select<String>(
|
|
||||||
name,
|
|
||||||
options.map { it.first }.toTypedArray(),
|
|
||||||
options.indexOfFirst { it.second == defaultValue }.coerceAtLeast(0),
|
|
||||||
) {
|
|
||||||
override fun addUrlParameter(url: HttpUrl.Builder) {
|
|
||||||
url.addQueryParameter(urlParameter, options[state].second)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class CheckBoxFilter(name: String, val value: String) : Filter.CheckBox(name)
|
|
||||||
|
|
||||||
open class CheckBoxGroup(
|
|
||||||
name: String,
|
|
||||||
private val urlParameter: String,
|
|
||||||
options: List<Pair<String, String>>,
|
|
||||||
) : UrlPartFilter, Filter.Group<CheckBoxFilter>(
|
|
||||||
name,
|
|
||||||
options.map { CheckBoxFilter(it.first, it.second) },
|
|
||||||
) {
|
|
||||||
override fun addUrlParameter(url: HttpUrl.Builder) {
|
|
||||||
val checked = state.filter { it.state }.map { it.value }
|
|
||||||
|
|
||||||
if (checked.isNotEmpty()) {
|
|
||||||
checked.forEach { genre ->
|
|
||||||
url.addQueryParameter(urlParameter, genre)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class TypeFilter : CheckBoxGroup(
|
|
||||||
"Status",
|
|
||||||
"type[]",
|
|
||||||
listOf(
|
|
||||||
Pair("Action", "action"),
|
|
||||||
Pair("Adventure", "adventure"),
|
|
||||||
Pair("Fantasy", "fantasy"),
|
|
||||||
Pair("Manga", "manga"),
|
|
||||||
Pair("Manhua", "manhua"),
|
|
||||||
Pair("Manhwa", "manhwa"),
|
|
||||||
Pair("Seinen", "seinen"),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
class GenreFilter(genres: List<Pair<String, String>>) : CheckBoxGroup(
|
|
||||||
"Genres",
|
|
||||||
"genre[]",
|
|
||||||
genres,
|
|
||||||
)
|
|
||||||
|
|
||||||
class YearFilter : CheckBoxGroup(
|
|
||||||
"Status",
|
|
||||||
"release[]",
|
|
||||||
listOf(
|
|
||||||
Pair("2024", "2024"),
|
|
||||||
Pair("2023", "2023"),
|
|
||||||
Pair("2022", "2022"),
|
|
||||||
Pair("2021", "2021"),
|
|
||||||
Pair("2020", "2020"),
|
|
||||||
Pair("2019", "2019"),
|
|
||||||
Pair("2018", "2018"),
|
|
||||||
Pair("2017", "2017"),
|
|
||||||
Pair("2016", "2016"),
|
|
||||||
Pair("2015", "2015"),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
class StatusFilter : CheckBoxGroup(
|
|
||||||
"Status",
|
|
||||||
"status[]",
|
|
||||||
listOf(
|
|
||||||
Pair("Releasing", "on-going"),
|
|
||||||
Pair("Completed", "end"),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
class OrderFilter(default: String? = null) : SelectFilter(
|
|
||||||
"Sort by",
|
|
||||||
"sort",
|
|
||||||
listOf(
|
|
||||||
Pair("", ""),
|
|
||||||
Pair("Popular", "most_viewed"),
|
|
||||||
Pair("Latest", "recently_added"),
|
|
||||||
),
|
|
||||||
default,
|
|
||||||
) {
|
|
||||||
companion object {
|
|
||||||
val POPULAR = FilterList(OrderFilter("most_viewed"))
|
|
||||||
val LATEST = FilterList(OrderFilter("recently_added"))
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,184 +0,0 @@
|
|||||||
package eu.kanade.tachiyomi.extension.en.reaperscansunoriginal
|
|
||||||
|
|
||||||
import android.util.Base64
|
|
||||||
import eu.kanade.tachiyomi.network.GET
|
|
||||||
import eu.kanade.tachiyomi.network.interceptor.rateLimit
|
|
||||||
import eu.kanade.tachiyomi.source.model.Filter
|
|
||||||
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.SChapter
|
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
|
||||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
|
||||||
import eu.kanade.tachiyomi.util.asJsoup
|
|
||||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
|
||||||
import okhttp3.Request
|
|
||||||
import okhttp3.Response
|
|
||||||
import org.jsoup.nodes.Document
|
|
||||||
import org.jsoup.nodes.Element
|
|
||||||
import java.util.Calendar
|
|
||||||
|
|
||||||
class ReaperScansUnoriginal : ParsedHttpSource() {
|
|
||||||
override val baseUrl = "https://reaper-scans.com"
|
|
||||||
|
|
||||||
override val name = "Reaper Scans (unoriginal)"
|
|
||||||
|
|
||||||
override val lang = "en"
|
|
||||||
|
|
||||||
override val supportsLatest = true
|
|
||||||
|
|
||||||
override val client = super.client.newBuilder()
|
|
||||||
.rateLimit(3)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
// Popular
|
|
||||||
override fun popularMangaFromElement(element: Element) = throw UnsupportedOperationException()
|
|
||||||
|
|
||||||
override fun popularMangaNextPageSelector(): String = throw UnsupportedOperationException()
|
|
||||||
|
|
||||||
override fun popularMangaRequest(page: Int) =
|
|
||||||
searchMangaRequest(page, "", OrderFilter.POPULAR)
|
|
||||||
|
|
||||||
override fun popularMangaSelector() = throw UnsupportedOperationException()
|
|
||||||
|
|
||||||
override fun popularMangaParse(response: Response) = searchMangaParse(response)
|
|
||||||
|
|
||||||
// Latest
|
|
||||||
override fun latestUpdatesFromElement(element: Element) = throw UnsupportedOperationException()
|
|
||||||
|
|
||||||
override fun latestUpdatesNextPageSelector() = throw UnsupportedOperationException()
|
|
||||||
|
|
||||||
override fun latestUpdatesRequest(page: Int) =
|
|
||||||
searchMangaRequest(page, "", OrderFilter.LATEST)
|
|
||||||
|
|
||||||
override fun latestUpdatesSelector() = throw UnsupportedOperationException()
|
|
||||||
|
|
||||||
override fun latestUpdatesParse(response: Response) = searchMangaParse(response)
|
|
||||||
|
|
||||||
// Search
|
|
||||||
override fun searchMangaFromElement(element: Element) = SManga.create().apply {
|
|
||||||
thumbnail_url = element.select(".poster-image-wrapper > img").attr("src")
|
|
||||||
title = element.select(".info > a").text()
|
|
||||||
setUrlWithoutDomain(element.selectFirst(".info a")!!.attr("href"))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun searchMangaNextPageSelector() = "a[rel=\"next\"]"
|
|
||||||
|
|
||||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
|
||||||
val url = baseUrl.toHttpUrl().newBuilder().apply {
|
|
||||||
addQueryParameter("post_type", "wp-manga")
|
|
||||||
addQueryParameter("s", query)
|
|
||||||
filters.filterIsInstance<UrlPartFilter>().forEach {
|
|
||||||
it.addUrlParameter(this)
|
|
||||||
}
|
|
||||||
if (page > 1) {
|
|
||||||
addPathSegment("page")
|
|
||||||
addPathSegment(page.toString())
|
|
||||||
}
|
|
||||||
}.build()
|
|
||||||
|
|
||||||
return GET(url, headers)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun searchMangaSelector() = ".inner"
|
|
||||||
|
|
||||||
override fun searchMangaParse(response: Response): MangasPage {
|
|
||||||
if (genres.isEmpty()) {
|
|
||||||
genres = parseGenres(response.asJsoup(response.peekBody(Long.MAX_VALUE).string()))
|
|
||||||
}
|
|
||||||
|
|
||||||
return super.searchMangaParse(response)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Chapter
|
|
||||||
override fun chapterFromElement(element: Element) = SChapter.create().apply {
|
|
||||||
setUrlWithoutDomain(element.attr("href"))
|
|
||||||
name = element.attr("title")
|
|
||||||
date_upload = parseRelativeDate(element.selectFirst("span + span")?.text())
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun parseRelativeDate(date: String?): Long {
|
|
||||||
if (date == null) {
|
|
||||||
return 0L
|
|
||||||
}
|
|
||||||
|
|
||||||
val trimmedDate = date.split(" ")
|
|
||||||
// This means 1hr ago or 20hrs ago
|
|
||||||
if (trimmedDate.size < 3) return 0L
|
|
||||||
val number = trimmedDate[0].toIntOrNull() ?: return 0L
|
|
||||||
val unit = trimmedDate[1].removeSuffix("s") // Remove 's' suffix
|
|
||||||
val now = Calendar.getInstance()
|
|
||||||
|
|
||||||
val javaUnit = when (unit) {
|
|
||||||
"year", "yr" -> Calendar.YEAR
|
|
||||||
"month" -> Calendar.MONTH
|
|
||||||
"week", "wk" -> Calendar.WEEK_OF_MONTH
|
|
||||||
"day" -> Calendar.DAY_OF_MONTH
|
|
||||||
"hour", "hr" -> Calendar.HOUR
|
|
||||||
"minute", "min" -> Calendar.MINUTE
|
|
||||||
"second", "sec" -> Calendar.SECOND
|
|
||||||
else -> return 0L
|
|
||||||
}
|
|
||||||
|
|
||||||
now.add(javaUnit, -number)
|
|
||||||
|
|
||||||
return now.timeInMillis
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun chapterListSelector() = "a.cairo"
|
|
||||||
|
|
||||||
// Details
|
|
||||||
override fun mangaDetailsParse(document: Document) = SManga.create().apply {
|
|
||||||
document.selectFirst("div.serie-info")?.let { info ->
|
|
||||||
description = info.selectFirst("div.description-content")?.text()
|
|
||||||
author = info.selectFirst("span:containsOwn(Author) + span")?.text()
|
|
||||||
artist = info.selectFirst("span:containsOwn(Artist) + span")?.text()
|
|
||||||
status = info.selectFirst("span:containsOwn(Status) + span")?.text().toStatus()
|
|
||||||
genre = info.select("div.genre-link").joinToString { it.text() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun String?.toStatus() = when {
|
|
||||||
this == null -> SManga.UNKNOWN
|
|
||||||
this.contains("Ongoing") -> SManga.ONGOING
|
|
||||||
this.contains("Completed") -> SManga.COMPLETED
|
|
||||||
else -> SManga.UNKNOWN
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pages
|
|
||||||
override fun pageListParse(document: Document): List<Page> {
|
|
||||||
val chapterUrl = document.location()
|
|
||||||
return document.select("div.protected-image-data")
|
|
||||||
.filterNot { it.attr("data-src").isEmpty() }
|
|
||||||
.mapIndexed { i, div ->
|
|
||||||
Page(
|
|
||||||
i,
|
|
||||||
chapterUrl,
|
|
||||||
Base64.decode(div.attr("data-src"), Base64.DEFAULT)
|
|
||||||
.toString(Charsets.UTF_8)
|
|
||||||
.trim(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun imageUrlParse(document: Document) = throw UnsupportedOperationException()
|
|
||||||
|
|
||||||
// Filter
|
|
||||||
override fun getFilterList() = FilterList(
|
|
||||||
TypeFilter(),
|
|
||||||
Filter.Header("Press \"Reset\" to attempt to load genres"),
|
|
||||||
GenreFilter(genres),
|
|
||||||
YearFilter(),
|
|
||||||
StatusFilter(),
|
|
||||||
OrderFilter(),
|
|
||||||
)
|
|
||||||
|
|
||||||
private var genres = emptyList<Pair<String, String>>()
|
|
||||||
|
|
||||||
private fun parseGenres(document: Document): List<Pair<String, String>> {
|
|
||||||
return document.select("li:has(input[name=\"genre[]\"])")
|
|
||||||
.map {
|
|
||||||
Pair(it.selectFirst("label")!!.text(), it.selectFirst("input")!!.attr("value"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user