Remove Reaper Scans (unoriginal) (#8034)

This commit is contained in:
Smol Ame 2025-03-12 04:33:40 -07:00 committed by Draff
parent d7f03a9caa
commit 13949bc6f3
No known key found for this signature in database
GPG Key ID: E8A89F3211677653
8 changed files with 0 additions and 298 deletions

View File

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

View File

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

View File

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