From b08202cf32b53f5e4b8bcaadf23cbab02e9413f1 Mon Sep 17 00:00:00 2001 From: Alessandro Jean <14254807+alessandrojean@users.noreply.github.com> Date: Fri, 30 Sep 2022 14:11:53 -0300 Subject: [PATCH] Optimize the Bruttal code a little (#13651) * Optimize the Bruttal code a little. * Update User-Agent string. --- src/pt/bruttal/build.gradle | 2 +- .../tachiyomi/extension/pt/bruttal/Bruttal.kt | 103 +++++++++--------- .../extension/pt/bruttal/BruttalDto.kt | 31 +++++- 3 files changed, 79 insertions(+), 57 deletions(-) diff --git a/src/pt/bruttal/build.gradle b/src/pt/bruttal/build.gradle index 2fee25975..6226e5fd6 100644 --- a/src/pt/bruttal/build.gradle +++ b/src/pt/bruttal/build.gradle @@ -6,7 +6,7 @@ ext { extName = 'Bruttal' pkgNameSuffix = 'pt.bruttal' extClass = '.Bruttal' - extVersionCode = 5 + extVersionCode = 6 } apply from: "$rootDir/common.gradle" diff --git a/src/pt/bruttal/src/eu/kanade/tachiyomi/extension/pt/bruttal/Bruttal.kt b/src/pt/bruttal/src/eu/kanade/tachiyomi/extension/pt/bruttal/Bruttal.kt index 159d7d710..f62359d29 100644 --- a/src/pt/bruttal/src/eu/kanade/tachiyomi/extension/pt/bruttal/Bruttal.kt +++ b/src/pt/bruttal/src/eu/kanade/tachiyomi/extension/pt/bruttal/Bruttal.kt @@ -12,6 +12,7 @@ import eu.kanade.tachiyomi.source.online.HttpSource import kotlinx.serialization.decodeFromString import kotlinx.serialization.json.Json import okhttp3.Headers +import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.Response @@ -23,7 +24,7 @@ class Bruttal : HttpSource() { override val name = "Bruttal" - override val baseUrl = "https://originals.omelete.com.br" + override val baseUrl = BRUTTAL_URL override val lang = "pt-BR" @@ -44,35 +45,41 @@ class Bruttal : HttpSource() { .add("Accept", "application/json, text/plain, */*") .build() - return GET("$baseUrl/bruttal/data/home.json", newHeaders) + return GET("$baseUrl/data/home.json", newHeaders) } override fun popularMangaParse(response: Response): MangasPage { - val homeDto = json.decodeFromString(response.body!!.string()) - - val titles = homeDto.list.map(::popularMangaFromObject) + val titles = response.parseAs().list + .map(BruttalComicBookDto::toSManga) return MangasPage(titles, false) } - private fun popularMangaFromObject(comicbook: BruttalComicBookDto): SManga = SManga.create().apply { - title = comicbook.title - thumbnail_url = "$baseUrl/bruttal/" + comicbook.imageMobile.removePrefix("./") - url = "/bruttal" + comicbook.url + override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { + val newHeaders = headersBuilder() + .add("Accept", "application/json, text/plain, */*") + .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 { - return super.fetchSearchManga(page, query, filters) - .map { mp -> - val filteredTitles = mp.mangas.filter { it.title.contains(query, true) } - MangasPage(filteredTitles, mp.hasNextPage) - } + override fun searchMangaParse(response: Response): MangasPage { + val query = response.request.url.queryParameter("q").orEmpty() + + var titles = response.parseAs().list + .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. override fun fetchMangaDetails(manga: SManga): Observable { return client.newCall(mangaDetailsApiRequest(manga)) @@ -88,63 +95,45 @@ class Bruttal : HttpSource() { .set("Referer", baseUrl + manga.url) .build() - return GET("$baseUrl/bruttal/data/comicbooks.json", newHeaders) + return GET("$baseUrl/data/comicbooks.json", newHeaders) } override fun mangaDetailsParse(response: Response): SManga { - val comicBooks = json.decodeFromString>(response.body!!.string()) - val comicBookUrl = response.request.header("Referer")!! .substringAfter("/bruttal") - val currentComicBook = comicBooks.first { it.url == comicBookUrl } - return SManga.create().apply { - title = currentComicBook.title - thumbnail_url = "$baseUrl/bruttal/" + currentComicBook.imageMobile.removePrefix("./") - 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 - } + return response.parseAs>() + .first { it.url == comicBookUrl } + .toSManga() } // 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 comicBooks = json.decodeFromString>(response.body!!.string()) + val comicBooks = response.parseAs>() val comicBookUrl = response.request.header("Referer")!! .substringAfter("/bruttal") val currentComicBook = comicBooks.first { it.url == comicBookUrl } return currentComicBook.seasons - .flatMap { it.chapters } - .map(::chapterFromObject) + .flatMap(BruttalSeasonDto::chapters) + .map(BruttalChapterDto::toSChapter) .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 { val newHeaders = headersBuilder() .add("Accept", "application/json, text/plain, */*") .set("Referer", baseUrl + chapter.url) .build() - return GET("$baseUrl/bruttal/data/comicbooks.json", newHeaders) + return GET("$baseUrl/data/comicbooks.json", newHeaders) } override fun pageListParse(response: Response): List { - val comicBooks = json.decodeFromString>(response.body!!.string()) + val comicBooks = response.parseAs>() val chapterUrl = response.request.header("Referer")!! val comicBookSlug = chapterUrl @@ -164,15 +153,13 @@ class Bruttal : HttpSource() { } return currentChapter.images - .mapIndexed { i, bruttalImage -> - val imageUrl = "$baseUrl/bruttal/" + bruttalImage.image.removePrefix("./") + .mapIndexed { i, imageDto -> + val imageUrl = "$baseUrl/${imageDto.image.removePrefix("./")}" Page(i, chapterUrl, imageUrl) } } - override fun fetchImageUrl(page: Page): Observable { - return Observable.just(page.imageUrl!!) - } + override fun fetchImageUrl(page: Page): Observable = Observable.just(page.imageUrl!!) override fun imageUrlParse(response: Response): String = "" @@ -185,12 +172,20 @@ class Bruttal : HttpSource() { 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 Response.parseAs(): T = use { + json.decodeFromString(body?.string().orEmpty()) + } 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) " + - "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" } } diff --git a/src/pt/bruttal/src/eu/kanade/tachiyomi/extension/pt/bruttal/BruttalDto.kt b/src/pt/bruttal/src/eu/kanade/tachiyomi/extension/pt/bruttal/BruttalDto.kt index c1088eb2d..71432818f 100644 --- a/src/pt/bruttal/src/eu/kanade/tachiyomi/extension/pt/bruttal/BruttalDto.kt +++ b/src/pt/bruttal/src/eu/kanade/tachiyomi/extension/pt/bruttal/BruttalDto.kt @@ -1,5 +1,7 @@ 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.Serializable @@ -19,7 +21,23 @@ data class BruttalComicBookDto( val synopsis: String, val title: 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 data class BruttalSeasonDto( @@ -34,7 +52,16 @@ data class BruttalChapterDto( @SerialName("share_title") val shareTitle: String, val title: 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 data class BruttalImageDto(