Optimize the Bruttal code a little (#13651)

* Optimize the Bruttal code a little.

* Update User-Agent string.
This commit is contained in:
Alessandro Jean 2022-09-30 14:11:53 -03:00 committed by GitHub
parent 0710868ecc
commit b08202cf32
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 79 additions and 57 deletions

View File

@ -6,7 +6,7 @@ ext {
extName = 'Bruttal' extName = 'Bruttal'
pkgNameSuffix = 'pt.bruttal' pkgNameSuffix = 'pt.bruttal'
extClass = '.Bruttal' extClass = '.Bruttal'
extVersionCode = 5 extVersionCode = 6
} }
apply from: "$rootDir/common.gradle" apply from: "$rootDir/common.gradle"

View File

@ -12,6 +12,7 @@ import eu.kanade.tachiyomi.source.online.HttpSource
import kotlinx.serialization.decodeFromString import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import okhttp3.Headers import okhttp3.Headers
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
@ -23,7 +24,7 @@ class Bruttal : HttpSource() {
override val name = "Bruttal" override val name = "Bruttal"
override val baseUrl = "https://originals.omelete.com.br" override val baseUrl = BRUTTAL_URL
override val lang = "pt-BR" override val lang = "pt-BR"
@ -44,35 +45,41 @@ class Bruttal : HttpSource() {
.add("Accept", "application/json, text/plain, */*") .add("Accept", "application/json, text/plain, */*")
.build() .build()
return GET("$baseUrl/bruttal/data/home.json", newHeaders) return GET("$baseUrl/data/home.json", newHeaders)
} }
override fun popularMangaParse(response: Response): MangasPage { override fun popularMangaParse(response: Response): MangasPage {
val homeDto = json.decodeFromString<BruttalHomeDto>(response.body!!.string()) val titles = response.parseAs<BruttalHomeDto>().list
.map(BruttalComicBookDto::toSManga)
val titles = homeDto.list.map(::popularMangaFromObject)
return MangasPage(titles, false) return MangasPage(titles, false)
} }
private fun popularMangaFromObject(comicbook: BruttalComicBookDto): SManga = SManga.create().apply { override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
title = comicbook.title val newHeaders = headersBuilder()
thumbnail_url = "$baseUrl/bruttal/" + comicbook.imageMobile.removePrefix("./") .add("Accept", "application/json, text/plain, */*")
url = "/bruttal" + comicbook.url .build()
val jsonUrl = "$baseUrl/data/home.json".toHttpUrl().newBuilder()
.addQueryParameter("q", query)
.toString()
return GET(jsonUrl, newHeaders)
} }
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> { override fun searchMangaParse(response: Response): MangasPage {
return super.fetchSearchManga(page, query, filters) val query = response.request.url.queryParameter("q").orEmpty()
.map { mp ->
val filteredTitles = mp.mangas.filter { it.title.contains(query, true) } var titles = response.parseAs<BruttalHomeDto>().list
MangasPage(filteredTitles, mp.hasNextPage) .map(BruttalComicBookDto::toSManga)
}
if (query.isNotEmpty()) {
titles = titles.filter { it.title.contains(query, ignoreCase = true) }
}
return MangasPage(titles, false)
} }
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request = popularMangaRequest(page)
override fun searchMangaParse(response: Response): MangasPage = popularMangaParse(response)
// Workaround to allow "Open in browser" use the real URL. // Workaround to allow "Open in browser" use the real URL.
override fun fetchMangaDetails(manga: SManga): Observable<SManga> { override fun fetchMangaDetails(manga: SManga): Observable<SManga> {
return client.newCall(mangaDetailsApiRequest(manga)) return client.newCall(mangaDetailsApiRequest(manga))
@ -88,63 +95,45 @@ class Bruttal : HttpSource() {
.set("Referer", baseUrl + manga.url) .set("Referer", baseUrl + manga.url)
.build() .build()
return GET("$baseUrl/bruttal/data/comicbooks.json", newHeaders) return GET("$baseUrl/data/comicbooks.json", newHeaders)
} }
override fun mangaDetailsParse(response: Response): SManga { override fun mangaDetailsParse(response: Response): SManga {
val comicBooks = json.decodeFromString<List<BruttalComicBookDto>>(response.body!!.string())
val comicBookUrl = response.request.header("Referer")!! val comicBookUrl = response.request.header("Referer")!!
.substringAfter("/bruttal") .substringAfter("/bruttal")
val currentComicBook = comicBooks.first { it.url == comicBookUrl }
return SManga.create().apply { return response.parseAs<List<BruttalComicBookDto>>()
title = currentComicBook.title .first { it.url == comicBookUrl }
thumbnail_url = "$baseUrl/bruttal/" + currentComicBook.imageMobile.removePrefix("./") .toSManga()
description = currentComicBook.synopsis +
(if (currentComicBook.soonText.isEmpty()) "" else "\n\n${currentComicBook.soonText}")
artist = currentComicBook.illustrator
author = currentComicBook.author
genre = currentComicBook.keywords.replace("; ", ", ")
status = SManga.ONGOING
}
} }
// Chapters are available in the same url of the manga details. // Chapters are available in the same url of the manga details.
override fun chapterListRequest(manga: SManga): Request = mangaDetailsApiRequest(manga) override fun chapterListRequest(manga: SManga): Request = mangaDetailsApiRequest(manga)
override fun chapterListParse(response: Response): List<SChapter> { override fun chapterListParse(response: Response): List<SChapter> {
val comicBooks = json.decodeFromString<List<BruttalComicBookDto>>(response.body!!.string()) val comicBooks = response.parseAs<List<BruttalComicBookDto>>()
val comicBookUrl = response.request.header("Referer")!! val comicBookUrl = response.request.header("Referer")!!
.substringAfter("/bruttal") .substringAfter("/bruttal")
val currentComicBook = comicBooks.first { it.url == comicBookUrl } val currentComicBook = comicBooks.first { it.url == comicBookUrl }
return currentComicBook.seasons return currentComicBook.seasons
.flatMap { it.chapters } .flatMap(BruttalSeasonDto::chapters)
.map(::chapterFromObject) .map(BruttalChapterDto::toSChapter)
.reversed() .reversed()
} }
private fun chapterFromObject(chapter: BruttalChapterDto): SChapter = SChapter.create().apply {
name = chapter.title
chapter_number = chapter.shareTitle
.removePrefix("Capítulo ")
.toFloatOrNull() ?: -1f
url = "/bruttal" + chapter.url
}
override fun pageListRequest(chapter: SChapter): Request { override fun pageListRequest(chapter: SChapter): Request {
val newHeaders = headersBuilder() val newHeaders = headersBuilder()
.add("Accept", "application/json, text/plain, */*") .add("Accept", "application/json, text/plain, */*")
.set("Referer", baseUrl + chapter.url) .set("Referer", baseUrl + chapter.url)
.build() .build()
return GET("$baseUrl/bruttal/data/comicbooks.json", newHeaders) return GET("$baseUrl/data/comicbooks.json", newHeaders)
} }
override fun pageListParse(response: Response): List<Page> { override fun pageListParse(response: Response): List<Page> {
val comicBooks = json.decodeFromString<List<BruttalComicBookDto>>(response.body!!.string()) val comicBooks = response.parseAs<List<BruttalComicBookDto>>()
val chapterUrl = response.request.header("Referer")!! val chapterUrl = response.request.header("Referer")!!
val comicBookSlug = chapterUrl val comicBookSlug = chapterUrl
@ -164,15 +153,13 @@ class Bruttal : HttpSource() {
} }
return currentChapter.images return currentChapter.images
.mapIndexed { i, bruttalImage -> .mapIndexed { i, imageDto ->
val imageUrl = "$baseUrl/bruttal/" + bruttalImage.image.removePrefix("./") val imageUrl = "$baseUrl/${imageDto.image.removePrefix("./")}"
Page(i, chapterUrl, imageUrl) Page(i, chapterUrl, imageUrl)
} }
} }
override fun fetchImageUrl(page: Page): Observable<String> { override fun fetchImageUrl(page: Page): Observable<String> = Observable.just(page.imageUrl!!)
return Observable.just(page.imageUrl!!)
}
override fun imageUrlParse(response: Response): String = "" override fun imageUrlParse(response: Response): String = ""
@ -185,12 +172,20 @@ class Bruttal : HttpSource() {
return GET(page.imageUrl!!, newHeaders) return GET(page.imageUrl!!, newHeaders)
} }
override fun latestUpdatesRequest(page: Int): Request = throw UnsupportedOperationException("Not used") override fun latestUpdatesRequest(page: Int): Request =
throw UnsupportedOperationException("Not used")
override fun latestUpdatesParse(response: Response): MangasPage = throw UnsupportedOperationException("Not used") override fun latestUpdatesParse(response: Response): MangasPage =
throw UnsupportedOperationException("Not used")
private inline fun <reified T> Response.parseAs(): T = use {
json.decodeFromString(body?.string().orEmpty())
}
companion object { companion object {
const val BRUTTAL_URL = "https://originals.omelete.com.br/bruttal"
private const val USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " + private const val USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " +
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36" "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36"
} }
} }

View File

@ -1,5 +1,7 @@
package eu.kanade.tachiyomi.extension.pt.bruttal package eu.kanade.tachiyomi.extension.pt.bruttal
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@ -19,7 +21,23 @@ data class BruttalComicBookDto(
val synopsis: String, val synopsis: String,
val title: String, val title: String,
val url: String val url: String
) ) {
fun toSManga(): SManga = SManga.create().apply {
title = this@BruttalComicBookDto.title
description = synopsis + (if (soonText.isEmpty()) "" else "\n\n$soonText")
artist = illustrator
author = this@BruttalComicBookDto.author
genre = keywords.split(";")
.map { keyword -> keyword.trim().replaceFirstChar { it.uppercase() } }
.sorted()
.joinToString()
status = SManga.ONGOING
thumbnail_url = "${Bruttal.BRUTTAL_URL}/" + imageMobile.removePrefix("./")
url = this@BruttalComicBookDto.url
initialized = true
}
}
@Serializable @Serializable
data class BruttalSeasonDto( data class BruttalSeasonDto(
@ -34,7 +52,16 @@ data class BruttalChapterDto(
@SerialName("share_title") val shareTitle: String, @SerialName("share_title") val shareTitle: String,
val title: String, val title: String,
val url: String val url: String
) ) {
fun toSChapter(): SChapter = SChapter.create().apply {
name = title
chapter_number = shareTitle
.removePrefix("Capítulo ")
.toFloatOrNull() ?: -1f
url = this@BruttalChapterDto.url
}
}
@Serializable @Serializable
data class BruttalImageDto( data class BruttalImageDto(