diff --git a/src/en/reaperscansunoriginal/build.gradle b/src/en/reaperscansunoriginal/build.gradle deleted file mode 100644 index ed302dc2f..000000000 --- a/src/en/reaperscansunoriginal/build.gradle +++ /dev/null @@ -1,7 +0,0 @@ -ext { - extName = 'Reaper Scans (unoriginal)' - extClass = '.ReaperScansUnoriginal' - extVersionCode = 33 -} - -apply from: "$rootDir/common.gradle" diff --git a/src/en/reaperscansunoriginal/res/mipmap-hdpi/ic_launcher.png b/src/en/reaperscansunoriginal/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index f6c5fc5a7..000000000 Binary files a/src/en/reaperscansunoriginal/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/src/en/reaperscansunoriginal/res/mipmap-mdpi/ic_launcher.png b/src/en/reaperscansunoriginal/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index e7ffd65f3..000000000 Binary files a/src/en/reaperscansunoriginal/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/src/en/reaperscansunoriginal/res/mipmap-xhdpi/ic_launcher.png b/src/en/reaperscansunoriginal/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index d79fd54e9..000000000 Binary files a/src/en/reaperscansunoriginal/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/src/en/reaperscansunoriginal/res/mipmap-xxhdpi/ic_launcher.png b/src/en/reaperscansunoriginal/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 779d9aea3..000000000 Binary files a/src/en/reaperscansunoriginal/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/src/en/reaperscansunoriginal/res/mipmap-xxxhdpi/ic_launcher.png b/src/en/reaperscansunoriginal/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index 08a0864d9..000000000 Binary files a/src/en/reaperscansunoriginal/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/src/en/reaperscansunoriginal/src/eu/kanade/tachiyomi/extension/en/reaperscansunoriginal/Filters.kt b/src/en/reaperscansunoriginal/src/eu/kanade/tachiyomi/extension/en/reaperscansunoriginal/Filters.kt deleted file mode 100644 index 20083dab0..000000000 --- a/src/en/reaperscansunoriginal/src/eu/kanade/tachiyomi/extension/en/reaperscansunoriginal/Filters.kt +++ /dev/null @@ -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>, - defaultValue: String? = null, -) : UrlPartFilter, Filter.Select( - 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>, -) : UrlPartFilter, Filter.Group( - 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>) : 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")) - } -} diff --git a/src/en/reaperscansunoriginal/src/eu/kanade/tachiyomi/extension/en/reaperscansunoriginal/ReaperScansUnoriginal.kt b/src/en/reaperscansunoriginal/src/eu/kanade/tachiyomi/extension/en/reaperscansunoriginal/ReaperScansUnoriginal.kt deleted file mode 100644 index 8e6fe0c8d..000000000 --- a/src/en/reaperscansunoriginal/src/eu/kanade/tachiyomi/extension/en/reaperscansunoriginal/ReaperScansUnoriginal.kt +++ /dev/null @@ -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().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 { - 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>() - - private fun parseGenres(document: Document): List> { - return document.select("li:has(input[name=\"genre[]\"])") - .map { - Pair(it.selectFirst("label")!!.text(), it.selectFirst("input")!!.attr("value")) - } - } -}