parent
bb9dc35e48
commit
7bf2d4b256
|
@ -0,0 +1,17 @@
|
||||||
|
apply plugin: 'com.android.application'
|
||||||
|
apply plugin: 'kotlin-android'
|
||||||
|
|
||||||
|
ext {
|
||||||
|
appName = 'Tachiyomi: HQ Now!'
|
||||||
|
pkgNameSuffix = 'pt.hqnow'
|
||||||
|
extClass = '.HQNow'
|
||||||
|
extVersionCode = 1
|
||||||
|
libVersion = '1.2'
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compileOnly 'com.google.code.gson:gson:2.8.2'
|
||||||
|
compileOnly 'com.github.salomonbrys.kotson:kotson:2.5.0'
|
||||||
|
}
|
||||||
|
|
||||||
|
apply from: "$rootDir/common.gradle"
|
Binary file not shown.
After Width: | Height: | Size: 5.7 KiB |
Binary file not shown.
After Width: | Height: | Size: 2.9 KiB |
Binary file not shown.
After Width: | Height: | Size: 8.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
Binary file not shown.
After Width: | Height: | Size: 118 KiB |
|
@ -0,0 +1,187 @@
|
||||||
|
package eu.kanade.tachiyomi.extension.pt.hqnow
|
||||||
|
|
||||||
|
import com.github.salomonbrys.kotson.fromJson
|
||||||
|
import com.github.salomonbrys.kotson.get
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import com.google.gson.JsonObject
|
||||||
|
import eu.kanade.tachiyomi.network.POST
|
||||||
|
import eu.kanade.tachiyomi.source.model.*
|
||||||
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import okhttp3.Request
|
||||||
|
import okhttp3.RequestBody
|
||||||
|
import okhttp3.Response
|
||||||
|
|
||||||
|
class HQNow : HttpSource() {
|
||||||
|
|
||||||
|
override val name = "HQ Now!"
|
||||||
|
|
||||||
|
// Website is http://www.hq-now.com
|
||||||
|
override val baseUrl = "http://admin.hq-now.com/graphql"
|
||||||
|
|
||||||
|
override val lang = "pt-BR"
|
||||||
|
|
||||||
|
override val supportsLatest = true
|
||||||
|
|
||||||
|
override val client: OkHttpClient = network.cloudflareClient
|
||||||
|
|
||||||
|
private val gson = Gson()
|
||||||
|
|
||||||
|
private val jsonHeaders = headersBuilder().add("content-type", "application/json").build()
|
||||||
|
|
||||||
|
private fun mangaFromResponse(response: Response, selector: String, coversAvailable: Boolean = true): List<SManga> {
|
||||||
|
return gson.fromJson<JsonObject>(response.body()!!.string())["data"][selector].asJsonArray
|
||||||
|
.map {
|
||||||
|
SManga.create().apply {
|
||||||
|
url = it["id"].asString
|
||||||
|
title = it["name"].asString
|
||||||
|
if (coversAvailable) thumbnail_url = it["hqCover"].asString
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Popular
|
||||||
|
|
||||||
|
override fun popularMangaRequest(page: Int): Request {
|
||||||
|
return POST(baseUrl, jsonHeaders, RequestBody.create(null, "{\"operationName\":\"getHqsByFilters\",\"variables\":{\"orderByViews\":true,\"loadCovers\":true,\"limit\":30},\"query\":\"query getHqsByFilters(\$orderByViews: Boolean, \$limit: Int, \$publisherId: Int, \$loadCovers: Boolean) {\\n getHqsByFilters(orderByViews: \$orderByViews, limit: \$limit, publisherId: \$publisherId, loadCovers: \$loadCovers) {\\n id\\n name\\n editoraId\\n status\\n publisherName\\n hqCover\\n synopsis\\n updatedAt\\n }\\n}\\n\"}"))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun popularMangaParse(response: Response): MangasPage {
|
||||||
|
return MangasPage(mangaFromResponse(response, "getHqsByFilters"), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Latest
|
||||||
|
|
||||||
|
override fun latestUpdatesRequest(page: Int): Request {
|
||||||
|
return POST(baseUrl, jsonHeaders, RequestBody.create(null, "{\"operationName\":\"getRecentlyUpdatedHqs\",\"variables\":{},\"query\":\"query getRecentlyUpdatedHqs {\\n getRecentlyUpdatedHqs {\\n name\\n hqCover\\n synopsis\\n id\\n updatedAt\\n updatedChapters\\n }\\n}\\n\"}"))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun latestUpdatesParse(response: Response): MangasPage {
|
||||||
|
return MangasPage(mangaFromResponse(response, "getRecentlyUpdatedHqs"), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search
|
||||||
|
|
||||||
|
private var queryIsTitle = true
|
||||||
|
|
||||||
|
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
||||||
|
return if (query.isNotBlank()) {
|
||||||
|
queryIsTitle = true
|
||||||
|
POST(baseUrl, jsonHeaders, RequestBody.create(null, "{\"operationName\":\"getHqsByName\",\"variables\":{\"name\":\"$query\"},\"query\":\"query getHqsByName(\$name: String!) {\\n getHqsByName(name: \$name) {\\n id\\n name\\n editoraId\\n status\\n publisherName\\n impressionsCount\\n }\\n}\\n\"}"))
|
||||||
|
} else {
|
||||||
|
queryIsTitle = false
|
||||||
|
var searchLetter = ""
|
||||||
|
|
||||||
|
filters.forEach { filter ->
|
||||||
|
when (filter) {
|
||||||
|
is LetterFilter -> {
|
||||||
|
searchLetter = filter.toUriPart()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
POST(baseUrl, jsonHeaders, RequestBody.create(null, "{\"operationName\":\"getHqsByNameStartingLetter\",\"variables\":{\"letter\":\"$searchLetter-$searchLetter\"},\"query\":\"query getHqsByNameStartingLetter(\$letter: String!) {\\n getHqsByNameStartingLetter(letter: \$letter) {\\n id\\n name\\n editoraId\\n status\\n publisherName\\n impressionsCount\\n }\\n}\\n\"}"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun searchMangaParse(response: Response): MangasPage {
|
||||||
|
return MangasPage(mangaFromResponse(response, if (queryIsTitle) "getHqsByName" else "getHqsByNameStartingLetter", false), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Details
|
||||||
|
|
||||||
|
override fun mangaDetailsRequest(manga: SManga): Request {
|
||||||
|
return POST(baseUrl, jsonHeaders, RequestBody.create(null, "{\"operationName\":\"getHqsById\",\"variables\":{\"id\":${manga.url}},\"query\":\"query getHqsById(\$id: Int!) {\\n getHqsById(id: \$id) {\\n id\\n name\\n synopsis\\n editoraId\\n status\\n publisherName\\n hqCover\\n impressionsCount\\n capitulos {\\n name\\n id\\n number\\n }\\n }\\n}\\n\"}"))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mangaDetailsParse(response: Response): SManga {
|
||||||
|
return gson.fromJson<JsonObject>(response.body()!!.string())["data"]["getHqsById"][0]
|
||||||
|
.let {
|
||||||
|
SManga.create().apply {
|
||||||
|
title = it["name"].asString
|
||||||
|
thumbnail_url = it["hqCover"].asString
|
||||||
|
description = it["synopsis"].asString
|
||||||
|
author = it["publisherName"].asString
|
||||||
|
status = when (it["status"].asString) {
|
||||||
|
"Concluído" -> SManga.COMPLETED
|
||||||
|
"Em Andamento" -> SManga.ONGOING
|
||||||
|
else -> SManga.UNKNOWN
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Chapters
|
||||||
|
|
||||||
|
override fun chapterListRequest(manga: SManga): Request {
|
||||||
|
return mangaDetailsRequest(manga)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun chapterListParse(response: Response): List<SChapter> {
|
||||||
|
return gson.fromJson<JsonObject>(response.body()!!.string())["data"]["getHqsById"][0]["capitulos"].asJsonArray
|
||||||
|
.map {
|
||||||
|
SChapter.create().apply {
|
||||||
|
url = it["id"].asString
|
||||||
|
name = it["name"].asString.let { jsonName ->
|
||||||
|
if (jsonName.isNotEmpty()) jsonName.trim() else "Capitulo: " + it["number"].asString
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.reversed()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pages
|
||||||
|
|
||||||
|
override fun pageListRequest(chapter: SChapter): Request {
|
||||||
|
return POST(baseUrl, jsonHeaders, RequestBody.create(null, "{\"operationName\":\"getChapterById\",\"variables\":{\"chapterId\":${chapter.url}},\"query\":\"query getChapterById(\$chapterId: Int!) {\\n getChapterById(chapterId: \$chapterId) {\\n name\\n number\\n oneshot\\n pictures {\\n pictureUrl\\n }\\n hq {\\n id\\n name\\n capitulos {\\n id\\n number\\n }\\n }\\n }\\n}\\n\"}"))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun pageListParse(response: Response): List<Page> {
|
||||||
|
return gson.fromJson<JsonObject>(response.body()!!.string())["data"]["getChapterById"]["pictures"].asJsonArray
|
||||||
|
.mapIndexed { i, json -> Page(i, "", json["pictureUrl"].asString) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException("Not used")
|
||||||
|
|
||||||
|
// Filters
|
||||||
|
|
||||||
|
override fun getFilterList() = FilterList(
|
||||||
|
Filter.Header("NOTA: Ignorado se estiver usando"),
|
||||||
|
Filter.Header("a pesquisa de texto!"),
|
||||||
|
Filter.Separator(),
|
||||||
|
LetterFilter()
|
||||||
|
)
|
||||||
|
|
||||||
|
private class LetterFilter : UriPartFilter("Carta", arrayOf(
|
||||||
|
Pair("---","<Selecione>"),
|
||||||
|
Pair("a","A"),
|
||||||
|
Pair("b","B"),
|
||||||
|
Pair("c","C"),
|
||||||
|
Pair("d","D"),
|
||||||
|
Pair("e","E"),
|
||||||
|
Pair("f","F"),
|
||||||
|
Pair("g","G"),
|
||||||
|
Pair("h","H"),
|
||||||
|
Pair("i","I"),
|
||||||
|
Pair("j","J"),
|
||||||
|
Pair("k","K"),
|
||||||
|
Pair("l","L"),
|
||||||
|
Pair("m","M"),
|
||||||
|
Pair("n","N"),
|
||||||
|
Pair("o","O"),
|
||||||
|
Pair("p","P"),
|
||||||
|
Pair("q","Q"),
|
||||||
|
Pair("r","R"),
|
||||||
|
Pair("s","S"),
|
||||||
|
Pair("t","T"),
|
||||||
|
Pair("u","U"),
|
||||||
|
Pair("v","V"),
|
||||||
|
Pair("w","W"),
|
||||||
|
Pair("x","X"),
|
||||||
|
Pair("y","Y"),
|
||||||
|
Pair("z","Z")
|
||||||
|
))
|
||||||
|
|
||||||
|
open class UriPartFilter(displayName: String, private val vals: Array<Pair<String, String>>) :
|
||||||
|
Filter.Select<String>(displayName, vals.map { it.second }.toTypedArray()) {
|
||||||
|
fun toUriPart() = vals[state].first
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue