From 272d00b3520e75acb56717d51c20d3dd199fc0d0 Mon Sep 17 00:00:00 2001
From: Alessandro Jean <14254807+alessandrojean@users.noreply.github.com>
Date: Sun, 1 May 2022 18:13:08 -0300
Subject: [PATCH] Migrate HC to Madara. (#11689)
---
.../hipercool/res/mipmap-hdpi/ic_launcher.png | Bin
.../hipercool/res/mipmap-mdpi/ic_launcher.png | Bin
.../res/mipmap-xhdpi/ic_launcher.png | Bin
.../res/mipmap-xxhdpi/ic_launcher.png | Bin
.../res/mipmap-xxxhdpi/ic_launcher.png | Bin
.../madara}/hipercool/res/web_hi_res_512.png | Bin
.../madara/hipercool/src/Hipercool.kt | 16 ++
.../multisrc/madara/MadaraGenerator.kt | 1 +
src/pt/hipercool/AndroidManifest.xml | 2 -
src/pt/hipercool/build.gradle | 17 --
.../extension/pt/hipercool/Hipercool.kt | 227 ------------------
.../extension/pt/hipercool/HipercoolDto.kt | 44 ----
12 files changed, 17 insertions(+), 290 deletions(-)
rename {src/pt => multisrc/overrides/madara}/hipercool/res/mipmap-hdpi/ic_launcher.png (100%)
rename {src/pt => multisrc/overrides/madara}/hipercool/res/mipmap-mdpi/ic_launcher.png (100%)
rename {src/pt => multisrc/overrides/madara}/hipercool/res/mipmap-xhdpi/ic_launcher.png (100%)
rename {src/pt => multisrc/overrides/madara}/hipercool/res/mipmap-xxhdpi/ic_launcher.png (100%)
rename {src/pt => multisrc/overrides/madara}/hipercool/res/mipmap-xxxhdpi/ic_launcher.png (100%)
rename {src/pt => multisrc/overrides/madara}/hipercool/res/web_hi_res_512.png (100%)
create mode 100644 multisrc/overrides/madara/hipercool/src/Hipercool.kt
delete mode 100644 src/pt/hipercool/AndroidManifest.xml
delete mode 100644 src/pt/hipercool/build.gradle
delete mode 100644 src/pt/hipercool/src/eu/kanade/tachiyomi/extension/pt/hipercool/Hipercool.kt
delete mode 100644 src/pt/hipercool/src/eu/kanade/tachiyomi/extension/pt/hipercool/HipercoolDto.kt
diff --git a/src/pt/hipercool/res/mipmap-hdpi/ic_launcher.png b/multisrc/overrides/madara/hipercool/res/mipmap-hdpi/ic_launcher.png
similarity index 100%
rename from src/pt/hipercool/res/mipmap-hdpi/ic_launcher.png
rename to multisrc/overrides/madara/hipercool/res/mipmap-hdpi/ic_launcher.png
diff --git a/src/pt/hipercool/res/mipmap-mdpi/ic_launcher.png b/multisrc/overrides/madara/hipercool/res/mipmap-mdpi/ic_launcher.png
similarity index 100%
rename from src/pt/hipercool/res/mipmap-mdpi/ic_launcher.png
rename to multisrc/overrides/madara/hipercool/res/mipmap-mdpi/ic_launcher.png
diff --git a/src/pt/hipercool/res/mipmap-xhdpi/ic_launcher.png b/multisrc/overrides/madara/hipercool/res/mipmap-xhdpi/ic_launcher.png
similarity index 100%
rename from src/pt/hipercool/res/mipmap-xhdpi/ic_launcher.png
rename to multisrc/overrides/madara/hipercool/res/mipmap-xhdpi/ic_launcher.png
diff --git a/src/pt/hipercool/res/mipmap-xxhdpi/ic_launcher.png b/multisrc/overrides/madara/hipercool/res/mipmap-xxhdpi/ic_launcher.png
similarity index 100%
rename from src/pt/hipercool/res/mipmap-xxhdpi/ic_launcher.png
rename to multisrc/overrides/madara/hipercool/res/mipmap-xxhdpi/ic_launcher.png
diff --git a/src/pt/hipercool/res/mipmap-xxxhdpi/ic_launcher.png b/multisrc/overrides/madara/hipercool/res/mipmap-xxxhdpi/ic_launcher.png
similarity index 100%
rename from src/pt/hipercool/res/mipmap-xxxhdpi/ic_launcher.png
rename to multisrc/overrides/madara/hipercool/res/mipmap-xxxhdpi/ic_launcher.png
diff --git a/src/pt/hipercool/res/web_hi_res_512.png b/multisrc/overrides/madara/hipercool/res/web_hi_res_512.png
similarity index 100%
rename from src/pt/hipercool/res/web_hi_res_512.png
rename to multisrc/overrides/madara/hipercool/res/web_hi_res_512.png
diff --git a/multisrc/overrides/madara/hipercool/src/Hipercool.kt b/multisrc/overrides/madara/hipercool/src/Hipercool.kt
new file mode 100644
index 000000000..97fbc938a
--- /dev/null
+++ b/multisrc/overrides/madara/hipercool/src/Hipercool.kt
@@ -0,0 +1,16 @@
+package eu.kanade.tachiyomi.extension.pt.hipercool
+
+import eu.kanade.tachiyomi.lib.ratelimit.RateLimitInterceptor
+import eu.kanade.tachiyomi.multisrc.madara.Madara
+import okhttp3.OkHttpClient
+import java.util.concurrent.TimeUnit
+
+class Hipercool : Madara("HipercooL", "https://hipercool.xyz", "pt-BR") {
+
+ // Migrated from a custom CMS to Madara.
+ override val versionId = 2
+
+ override val client: OkHttpClient = super.client.newBuilder()
+ .addInterceptor(RateLimitInterceptor(1, 2, TimeUnit.SECONDS))
+ .build()
+}
diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/madara/MadaraGenerator.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/madara/MadaraGenerator.kt
index 83172646b..715066468 100644
--- a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/madara/MadaraGenerator.kt
+++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/madara/MadaraGenerator.kt
@@ -131,6 +131,7 @@ class MadaraGenerator : ThemeSourceGenerator {
SingleLang("HentaiZone", "https://hentaizone.xyz", "fr", isNsfw = true),
SingleLang("Hentaidexy", "https://hentaidexy.com", "en", isNsfw = true, overrideVersionCode = 2),
SingleLang("Heroz Scanlation", "https://herozscans.com", "en", overrideVersionCode = 1),
+ SingleLang("HipercooL", "https://hipercool.xyz", "pt-BR", isNsfw = true, className = "Hipercool"),
SingleLang("Hiperdex", "https://hiperdex.com", "en", isNsfw = true, overrideVersionCode = 5),
SingleLang("Hizomanga", "https://hizomanga.com", "ar", overrideVersionCode = 1),
SingleLang("Hscans", "https://hscans.com", "en", overrideVersionCode = 2),
diff --git a/src/pt/hipercool/AndroidManifest.xml b/src/pt/hipercool/AndroidManifest.xml
deleted file mode 100644
index 30deb7f79..000000000
--- a/src/pt/hipercool/AndroidManifest.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
diff --git a/src/pt/hipercool/build.gradle b/src/pt/hipercool/build.gradle
deleted file mode 100644
index bec809c15..000000000
--- a/src/pt/hipercool/build.gradle
+++ /dev/null
@@ -1,17 +0,0 @@
-apply plugin: 'com.android.application'
-apply plugin: 'kotlin-android'
-apply plugin: 'kotlinx-serialization'
-
-ext {
- extName = 'HipercooL'
- pkgNameSuffix = 'pt.hipercool'
- extClass = '.Hipercool'
- extVersionCode = 9
- isNsfw = true
-}
-
-dependencies {
- implementation project(':lib-ratelimit')
-}
-
-apply from: "$rootDir/common.gradle"
diff --git a/src/pt/hipercool/src/eu/kanade/tachiyomi/extension/pt/hipercool/Hipercool.kt b/src/pt/hipercool/src/eu/kanade/tachiyomi/extension/pt/hipercool/Hipercool.kt
deleted file mode 100644
index 2acbc6eb0..000000000
--- a/src/pt/hipercool/src/eu/kanade/tachiyomi/extension/pt/hipercool/Hipercool.kt
+++ /dev/null
@@ -1,227 +0,0 @@
-package eu.kanade.tachiyomi.extension.pt.hipercool
-
-import eu.kanade.tachiyomi.lib.ratelimit.SpecificHostRateLimitInterceptor
-import eu.kanade.tachiyomi.network.GET
-import eu.kanade.tachiyomi.network.POST
-import eu.kanade.tachiyomi.network.asObservableSuccess
-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.HttpSource
-import kotlinx.serialization.decodeFromString
-import kotlinx.serialization.encodeToString
-import kotlinx.serialization.json.Json
-import kotlinx.serialization.json.JsonPrimitive
-import okhttp3.Headers
-import okhttp3.HttpUrl.Companion.toHttpUrl
-import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
-import okhttp3.MediaType.Companion.toMediaType
-import okhttp3.OkHttpClient
-import okhttp3.Request
-import okhttp3.RequestBody.Companion.toRequestBody
-import okhttp3.Response
-import rx.Observable
-import uy.kohesive.injekt.injectLazy
-import java.text.SimpleDateFormat
-import java.util.Locale
-
-class Hipercool : HttpSource() {
-
- // Hardcode the id because the language wasn't specific.
- override val id: Long = 5898568703656160
-
- override val name = "HipercooL"
-
- override val baseUrl = "https://hiper.cool"
-
- override val lang = "pt-BR"
-
- override val supportsLatest = true
-
- override val client: OkHttpClient = network.cloudflareClient.newBuilder()
- .addInterceptor(SpecificHostRateLimitInterceptor(baseUrl.toHttpUrl(), 1, 2))
- .addInterceptor(SpecificHostRateLimitInterceptor(STATIC_URL.toHttpUrl(), 1, 1))
- .build()
-
- override fun headersBuilder(): Headers.Builder = Headers.Builder()
- .add("User-Agent", USER_AGENT)
- .add("Referer", baseUrl)
- .add("X-Requested-With", "XMLHttpRequest")
-
- private val json: Json by injectLazy()
-
- private fun genericMangaListParse(response: Response): MangasPage {
- val chapters = response.parseAs>()
-
- if (chapters.isEmpty())
- return MangasPage(emptyList(), false)
-
- val mangaList = chapters
- .distinctBy { it.book!!.title }
- .map(::genericMangaFromObject)
-
- val hasNextPage = chapters.size == DEFAULT_COUNT
-
- return MangasPage(mangaList, hasNextPage)
- }
-
- private fun genericMangaFromObject(chapter: HipercoolChapterDto): SManga = SManga.create().apply {
- title = chapter.book!!.title
- thumbnail_url = chapter.book.slug.toThumbnailUrl(chapter.book.revision)
- url = "/books/" + chapter.book.slug
- }
-
- // The source does not have popular mangas, so use latest instead.
- override fun popularMangaRequest(page: Int): Request = latestUpdatesRequest(page)
-
- override fun popularMangaParse(response: Response): MangasPage = genericMangaListParse(response)
-
- override fun latestUpdatesRequest(page: Int): Request {
- val start = (page - 1) * DEFAULT_COUNT
- return GET("$baseUrl/api/books/chapters?start=$start&count=$DEFAULT_COUNT", headers)
- }
-
- override fun latestUpdatesParse(response: Response): MangasPage = genericMangaListParse(response)
-
- override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
- val searchPayload = HipercoolSearchDto(
- start = (page - 1) * DEFAULT_COUNT,
- count = DEFAULT_COUNT,
- text = query,
- type = "text"
- )
-
- val body = json.encodeToString(searchPayload).toRequestBody(JSON_MEDIA_TYPE)
-
- return POST("$baseUrl/api/books/chapters/search", headers, body)
- }
-
- override fun searchMangaParse(response: Response): MangasPage = genericMangaListParse(response)
-
- // Workaround to allow "Open in browser" use the real URL.
- override fun fetchMangaDetails(manga: SManga): Observable {
- return client.newCall(mangaDetailsApiRequest(manga))
- .asObservableSuccess()
- .map { response ->
- mangaDetailsParse(response).apply { initialized = true }
- }
- }
-
- private fun mangaDetailsApiRequest(manga: SManga): Request {
- val slug = manga.url.substringAfterLast("/")
-
- return GET("$baseUrl/api/books/$slug", headers)
- }
-
- override fun mangaDetailsParse(response: Response): SManga = SManga.create().apply {
- val book = response.parseAs()
-
- title = book.title
- thumbnail_url = book.slug.toThumbnailUrl(book.revision)
- description = book.synopsis.orEmpty()
- artist = book.fixedTags["artista"].orEmpty().joinToString("; ")
- author = book.fixedTags["autor"].orEmpty().joinToString("; ")
- genre = book.fixedTags["tags"].orEmpty().joinToString()
- }
-
- // Chapters are available in the same url of the manga details.
- override fun chapterListRequest(manga: SManga): Request = mangaDetailsApiRequest(manga)
-
- override fun chapterListParse(response: Response): List {
- val book = response.parseAs()
-
- if (book.chapters is JsonPrimitive)
- return emptyList()
-
- return json.decodeFromString>(book.chapters.toString())
- .map { chapterListItemParse(book, it) }
- .reversed()
- }
-
- private fun chapterListItemParse(book: HipercoolBookDto, chapter: HipercoolChapterDto): SChapter =
- SChapter.create().apply {
- name = "Cap. " + chapter.title
- chapter_number = chapter.title.toFloatOrNull() ?: -1f
- date_upload = chapter.publishedAt.toDate()
- scanlator = book.fixedTags["tradutor"]?.joinToString(" & ")
-
- val fullUrl = "$baseUrl/books".toHttpUrl().newBuilder()
- .addPathSegment(book.slug)
- .addPathSegment(chapter.slug)
- .addQueryParameter("images", chapter.images.toString())
- .addQueryParameter("revision", book.revision.toString())
- .toString()
-
- setUrlWithoutDomain(fullUrl)
- }
-
- override fun fetchPageList(chapter: SChapter): Observable> {
- val chapterUrl = (baseUrl + chapter.url).toHttpUrlOrNull()!!
-
- val bookSlug = chapterUrl.pathSegments[1]
- val chapterSlug = chapterUrl.pathSegments[2]
- val images = chapterUrl.queryParameter("images")!!.toInt()
- val revision = chapterUrl.queryParameter("revision")!!
-
- val pages = List(images) { i ->
- val imageUrl = "$STATIC_URL/books".toHttpUrl().newBuilder()
- .addPathSegment(bookSlug)
- .addPathSegment(chapterSlug)
- .addPathSegment("$bookSlug-chapter-$chapterSlug-page-${i + 1}.jpg")
- .addQueryParameter("revision", revision)
- .toString()
-
- Page(i, chapter.url, imageUrl)
- }
-
- return Observable.just(pages)
- }
-
- override fun pageListParse(response: Response): List =
- throw Exception("This method should not be called!")
-
- override fun fetchImageUrl(page: Page): Observable = Observable.just(page.imageUrl!!)
-
- override fun imageUrlParse(response: Response): String = ""
-
- override fun imageRequest(page: Page): Request {
- val newHeaders = headersBuilder()
- .set("Referer", baseUrl + page.url)
- .build()
-
- return GET(page.imageUrl!!, newHeaders)
- }
-
- private inline fun Response.parseAs(): T = use {
- json.decodeFromString(it.body?.string().orEmpty())
- }
-
- private fun String.toDate(): Long {
- return runCatching { DATE_FORMATTER.parse(this)?.time }
- .getOrNull() ?: 0L
- }
-
- private fun String.toThumbnailUrl(revision: Int): String =
- "$STATIC_URL/books".toHttpUrlOrNull()!!.newBuilder()
- .addPathSegment(this)
- .addPathSegment("$this-cover.jpg")
- .addQueryParameter("revision", revision.toString())
- .toString()
-
- companion object {
- private const val STATIC_URL = "https://static.hiper.cool"
-
- private val JSON_MEDIA_TYPE = "application/json; charset=utf-8".toMediaType()
-
- private const val USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " +
- "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36"
-
- private const val DEFAULT_COUNT = 40
-
- private val DATE_FORMATTER by lazy {
- SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH)
- }
- }
-}
diff --git a/src/pt/hipercool/src/eu/kanade/tachiyomi/extension/pt/hipercool/HipercoolDto.kt b/src/pt/hipercool/src/eu/kanade/tachiyomi/extension/pt/hipercool/HipercoolDto.kt
deleted file mode 100644
index 69fd82e6d..000000000
--- a/src/pt/hipercool/src/eu/kanade/tachiyomi/extension/pt/hipercool/HipercoolDto.kt
+++ /dev/null
@@ -1,44 +0,0 @@
-package eu.kanade.tachiyomi.extension.pt.hipercool
-
-import kotlinx.serialization.SerialName
-import kotlinx.serialization.Serializable
-import kotlinx.serialization.json.JsonElement
-
-@Serializable
-data class HipercoolBookDto(
- val chapters: JsonElement,
- val revision: Int = 1,
- val slug: String,
- val synopsis: String? = null,
- val tags: List = emptyList(),
- val title: String
-) {
- val fixedTags: Map>
- get() = tags
- .groupBy(HipercoolTagDto::slug, HipercoolTagDto::values)
- .mapValues { it.value.flatten().map(HipercoolTagDto::label) }
-}
-
-@Serializable
-data class HipercoolTagDto(
- val label: String,
- val values: List = emptyList(),
- val slug: String
-)
-
-@Serializable
-data class HipercoolChapterDto(
- @SerialName("_book") val book: HipercoolBookDto? = null,
- val images: Int = 0,
- @SerialName("publishied_at") val publishedAt: String,
- val slug: String,
- val title: String
-)
-
-@Serializable
-data class HipercoolSearchDto(
- val start: Int,
- val count: Int,
- val text: String,
- val type: String
-)