Refactor the HiperCool extension. (#3215)

Refactor the HiperCool extension
This commit is contained in:
Alessandro Jean 2020-05-17 18:26:23 -03:00 committed by GitHub
parent efc1877172
commit ccd14d9de5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 69 additions and 67 deletions

View File

@ -5,7 +5,7 @@ ext {
appName = 'Tachiyomi: HipercooL'
pkgNameSuffix = 'pt.hipercool'
extClass = '.Hipercool'
extVersionCode = 3
extVersionCode = 4
libVersion = '1.2'
}

View File

@ -22,7 +22,9 @@ import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.Locale
import okhttp3.Headers
import okhttp3.HttpUrl
import okhttp3.MediaType
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody
import okhttp3.Response
@ -41,54 +43,59 @@ class Hipercool : HttpSource() {
override val supportsLatest = true
override val client: OkHttpClient = network.cloudflareClient
override fun headersBuilder(): Headers.Builder = Headers.Builder()
.add("User-Agent", USER_AGENT)
.add("Referer", baseUrl)
.add("X-Requested-With", "XMLHttpRequest")
private fun generalListMangaParse(obj: JsonObject): SManga {
private fun genericMangaListParse(response: Response): MangasPage {
val result = response.asJsonArray()
if (result.size() == 0)
return MangasPage(emptyList(), false)
val mangaList = result
.map { genericMangaFromObject(it.obj) }
.distinctBy { it.title }
val hasNextPage = result.size() == DEFAULT_COUNT
return MangasPage(mangaList, hasNextPage)
}
private fun genericMangaFromObject(obj: JsonObject): SManga {
val book = obj["_book"].obj
val bookSlug = book["slug"].string
val bookRevision = book["revision"]?.int ?: 1
return SManga.create().apply {
title = book["title"].string
thumbnail_url = getThumbnailUrl(bookSlug, bookRevision)
setUrlWithoutDomain("$baseUrl/books/$bookSlug")
thumbnail_url = bookSlug.toThumbnailUrl(bookRevision)
url = "/books/$bookSlug"
}
}
// 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 = latestUpdatesParse(response)
override fun popularMangaParse(response: Response): MangasPage = genericMangaListParse(response)
override fun latestUpdatesRequest(page: Int): Request {
return GET("$baseUrl/api/books/chapters?start=${(page - 1) * 40}&count=40", headers)
val start = (page - 1) * DEFAULT_COUNT
return GET("$baseUrl/api/books/chapters?start=$start&count=$DEFAULT_COUNT", headers)
}
override fun latestUpdatesParse(response: Response): MangasPage {
val result = response.asJsonArray()
if (result.size() == 0)
return MangasPage(emptyList(), false)
val latestMangas = result
.map { latestMangaItemParse(it.obj) }
.distinctBy { it.title }
return MangasPage(latestMangas, result.size() == 40)
}
private fun latestMangaItemParse(obj: JsonObject): SManga = generalListMangaParse(obj)
override fun latestUpdatesParse(response: Response): MangasPage = genericMangaListParse(response)
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
val mediaType = MediaType.parse("application/json; charset=utf-8")
// Create json body.
val json = jsonObject(
"start" to (page - 1) * 40,
"count" to 40,
"start" to (page - 1) * DEFAULT_COUNT,
"count" to DEFAULT_COUNT,
"text" to query,
"type" to "text"
)
@ -98,20 +105,7 @@ class Hipercool : HttpSource() {
return POST("$baseUrl/api/books/chapters/search", headers, body)
}
override fun searchMangaParse(response: Response): MangasPage {
val result = response.asJsonArray()
if (result.size() == 0)
return MangasPage(emptyList(), false)
val searchMangas = result
.map { searchMangaItemParse(it.obj) }
.distinctBy { it.title }
return MangasPage(searchMangas, result.size() == 40)
}
private fun searchMangaItemParse(obj: JsonObject): SManga = generalListMangaParse(obj)
override fun searchMangaParse(response: Response): MangasPage = genericMangaListParse(response)
// Workaround to allow "Open in browser" use the real URL.
override fun fetchMangaDetails(manga: SManga): Observable<SManga> {
@ -148,7 +142,7 @@ class Hipercool : HttpSource() {
return SManga.create().apply {
title = result["title"].string
thumbnail_url = getThumbnailUrl(result["slug"].string, result["revision"].int)
thumbnail_url = result["slug"].string.toThumbnailUrl(result["revision"].int)
description = result["synopsis"]?.string ?: ""
artist = artists
author = authors
@ -174,29 +168,38 @@ class Hipercool : HttpSource() {
name = obj["title"].string
chapter_number = obj["title"].string.toFloatOrNull() ?: 0f
// The property is written wrong.
date_upload = parseChapterDate(obj["publishied_at"].string)
date_upload = DATE_FORMATTER.tryParseTime(obj["publishied_at"].string)
val bookSlug = book["slug"].string
val chapterSlug = obj["slug"].string
val images = obj["images"].int
val revision = book["revision"].int
setUrlWithoutDomain("$baseUrl/books/$bookSlug/$chapterSlug?images=$images&revision=$revision")
val fullUrl = HttpUrl.parse("$baseUrl/books")!!.newBuilder()
.addPathSegment(book["slug"].string)
.addPathSegment(obj["slug"].string)
.addQueryParameter("images", obj["images"].int.toString())
.addQueryParameter("revision", book["revision"].int.toString())
.toString()
setUrlWithoutDomain(fullUrl)
}
override fun fetchPageList(chapter: SChapter): Observable<List<Page>> {
val regex = CHAPTER_REGEX.toRegex()
val results = regex.find(chapter.url)!!.groupValues
val chapterUrl = HttpUrl.parse(baseUrl + chapter.url)!!
val bookSlug = chapterUrl.pathSegments()[1]
val chapterSlug = chapterUrl.pathSegments()[2]
val images = chapterUrl.queryParameter("images")!!.toInt()
val revision = chapterUrl.queryParameter("revision")!!.toInt()
val bookSlug = results[1]
val chapterSlug = results[2]
val images = results[3].toInt()
val revision = results[4].toInt()
val pages = arrayListOf<Page>()
// Create the pages.
for (i in 1..images) {
val url = getPageUrl(bookSlug, chapterSlug, i, revision)
pages += Page(i - 1, chapter.url, url)
val imageUrl = HttpUrl.parse("$STATIC_URL/books")!!.newBuilder()
.addPathSegment(bookSlug)
.addPathSegment(chapterSlug)
.addPathSegment("$bookSlug-chapter-$chapterSlug-page-$i.jpg")
.addQueryParameter("revision", revision.toString())
.toString()
pages += Page(i - 1, chapter.url, imageUrl)
}
return Observable.just(pages)
@ -211,31 +214,27 @@ class Hipercool : HttpSource() {
override fun imageUrlParse(response: Response): String = ""
override fun imageRequest(page: Page): Request {
val newHeaders = Headers.Builder()
.apply {
add("Referer", page.url)
add("User-Agent", USER_AGENT)
}
val newHeaders = headersBuilder()
.set("Referer", baseUrl + page.url)
.build()
return GET(page.imageUrl!!, newHeaders)
}
private fun parseChapterDate(date: String): Long {
private fun SimpleDateFormat.tryParseTime(date: String): Long {
return try {
SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH)
.parse(date.substringBefore("T"))
.time
parse(date.substringBefore("T")).time
} catch (e: ParseException) {
0L
}
}
private fun getThumbnailUrl(bookSlug: String, revision: Int): String =
"$STATIC_URL/books/$bookSlug/$bookSlug-cover.jpg?revision=$revision"
private fun getPageUrl(bookSlug: String, chapterSlug: String, page: Int, revision: Int): String =
"$STATIC_URL/books/$bookSlug/$chapterSlug/$bookSlug-chapter-$chapterSlug-page-$page.jpg?revision=$revision"
private fun String.toThumbnailUrl(revision: Int): String =
HttpUrl.parse("$STATIC_URL/books")!!.newBuilder()
.addPathSegment(this)
.addPathSegment("$this-cover.jpg")
.addQueryParameter("revision", revision.toString())
.toString()
private fun Response.asJsonObject(): JsonObject = JSON_PARSER.parse(body()!!.string()).obj
@ -243,10 +242,13 @@ class Hipercool : HttpSource() {
companion object {
private const val STATIC_URL = "https://static.hiper.cool"
private const val USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.122 Safari/537.36"
private const val CHAPTER_REGEX = "\\/books\\/(.*)\\/(.*)\\?images=(\\d+)&revision=(\\d+)\$"
private const val USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.141 Safari/537.36"
private const val DEFAULT_COUNT = 40
private val JSON_PARSER by lazy { JsonParser() }
private val DATE_FORMATTER by lazy { SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH) }
}
}