Add support to login in AS. (#9759)
This commit is contained in:
parent
e20bff0b61
commit
7b96c41fed
|
@ -6,7 +6,7 @@ ext {
|
||||||
extName = 'Argos Scan'
|
extName = 'Argos Scan'
|
||||||
pkgNameSuffix = 'pt.argosscan'
|
pkgNameSuffix = 'pt.argosscan'
|
||||||
extClass = '.ArgosScan'
|
extClass = '.ArgosScan'
|
||||||
extVersionCode = 16
|
extVersionCode = 17
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.extension.pt.argosscan
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
|
import android.text.InputType
|
||||||
import androidx.preference.EditTextPreference
|
import androidx.preference.EditTextPreference
|
||||||
import androidx.preference.PreferenceScreen
|
import androidx.preference.PreferenceScreen
|
||||||
import eu.kanade.tachiyomi.lib.ratelimit.RateLimitInterceptor
|
import eu.kanade.tachiyomi.lib.ratelimit.RateLimitInterceptor
|
||||||
|
@ -20,6 +21,7 @@ import kotlinx.serialization.json.add
|
||||||
import kotlinx.serialization.json.decodeFromJsonElement
|
import kotlinx.serialization.json.decodeFromJsonElement
|
||||||
import kotlinx.serialization.json.jsonArray
|
import kotlinx.serialization.json.jsonArray
|
||||||
import kotlinx.serialization.json.jsonObject
|
import kotlinx.serialization.json.jsonObject
|
||||||
|
import kotlinx.serialization.json.jsonPrimitive
|
||||||
import okhttp3.Interceptor
|
import okhttp3.Interceptor
|
||||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
|
@ -49,7 +51,7 @@ class ArgosScan : HttpSource(), ConfigurableSource {
|
||||||
override val supportsLatest = true
|
override val supportsLatest = true
|
||||||
|
|
||||||
override val client: OkHttpClient = network.cloudflareClient.newBuilder()
|
override val client: OkHttpClient = network.cloudflareClient.newBuilder()
|
||||||
.addInterceptor(::tokenIntercept)
|
.addInterceptor(::loginIntercept)
|
||||||
.addInterceptor(RateLimitInterceptor(1, 2, TimeUnit.SECONDS))
|
.addInterceptor(RateLimitInterceptor(1, 2, TimeUnit.SECONDS))
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
|
@ -59,6 +61,8 @@ class ArgosScan : HttpSource(), ConfigurableSource {
|
||||||
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
|
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var token: String? = null
|
||||||
|
|
||||||
private fun genericMangaFromObject(project: ArgosProjectDto): SManga = SManga.create().apply {
|
private fun genericMangaFromObject(project: ArgosProjectDto): SManga = SManga.create().apply {
|
||||||
title = project.name!!
|
title = project.name!!
|
||||||
url = "/obras/${project.id}"
|
url = "/obras/${project.id}"
|
||||||
|
@ -234,40 +238,104 @@ class ArgosScan : HttpSource(), ConfigurableSource {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setupPreferenceScreen(screen: PreferenceScreen) {
|
override fun setupPreferenceScreen(screen: PreferenceScreen) {
|
||||||
val tokenPref = EditTextPreference(screen.context).apply {
|
val emailPref = EditTextPreference(screen.context).apply {
|
||||||
key = TOKEN_PREF_KEY
|
key = EMAIL_PREF_KEY
|
||||||
title = TOKEN_PREF_TITLE
|
title = EMAIL_PREF_TITLE
|
||||||
summary = TOKEN_PREF_SUMMARY
|
summary = EMAIL_PREF_SUMMARY
|
||||||
setDefaultValue("")
|
setDefaultValue("")
|
||||||
dialogTitle = TOKEN_PREF_TITLE
|
dialogTitle = EMAIL_PREF_TITLE
|
||||||
dialogMessage = TOKEN_PREF_SUMMARY
|
dialogMessage = EMAIL_PREF_DIALOG
|
||||||
|
|
||||||
|
setOnBindEditTextListener {
|
||||||
|
it.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS
|
||||||
|
}
|
||||||
|
|
||||||
setOnPreferenceChangeListener { _, newValue ->
|
setOnPreferenceChangeListener { _, newValue ->
|
||||||
|
token = null
|
||||||
|
|
||||||
preferences.edit()
|
preferences.edit()
|
||||||
.putString(TOKEN_PREF_KEY, newValue as String)
|
.putString(EMAIL_PREF_KEY, newValue as String)
|
||||||
.commit()
|
.commit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
screen.addPreference(tokenPref)
|
val passwordPref = EditTextPreference(screen.context).apply {
|
||||||
|
key = PASSWORD_PREF_KEY
|
||||||
|
title = PASSWORD_PREF_TITLE
|
||||||
|
summary = PASSWORD_PREF_SUMMARY
|
||||||
|
setDefaultValue("")
|
||||||
|
dialogTitle = PASSWORD_PREF_TITLE
|
||||||
|
dialogMessage = PASSWORD_PREF_DIALOG
|
||||||
|
|
||||||
|
setOnBindEditTextListener {
|
||||||
|
it.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD
|
||||||
|
}
|
||||||
|
|
||||||
|
setOnPreferenceChangeListener { _, newValue ->
|
||||||
|
token = null
|
||||||
|
|
||||||
|
preferences.edit()
|
||||||
|
.putString(PASSWORD_PREF_KEY, newValue as String)
|
||||||
|
.commit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
screen.addPreference(emailPref)
|
||||||
|
screen.addPreference(passwordPref)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun tokenIntercept(chain: Interceptor.Chain): Response {
|
private fun loginIntercept(chain: Interceptor.Chain): Response {
|
||||||
if (chain.request().url.toString().contains("graphql").not()) {
|
if (chain.request().url.toString().contains("graphql").not()) {
|
||||||
return chain.proceed(chain.request())
|
return chain.proceed(chain.request())
|
||||||
}
|
}
|
||||||
|
|
||||||
val token = preferences.getString(TOKEN_PREF_KEY, "")
|
val email = preferences.getString(EMAIL_PREF_KEY, "")
|
||||||
|
val password = preferences.getString(PASSWORD_PREF_KEY, "")
|
||||||
|
|
||||||
if (token.isNullOrEmpty()) {
|
if (!email.isNullOrEmpty() && !password.isNullOrEmpty() && token.isNullOrEmpty()) {
|
||||||
throw IOException(TOKEN_NOT_FOUND)
|
val loginResponse = chain.proceed(loginRequest(email, password))
|
||||||
|
val loginResult = json.parseToJsonElement(loginResponse.body!!.string()).jsonObject
|
||||||
|
|
||||||
|
if (loginResult["errors"] != null) {
|
||||||
|
loginResponse.close()
|
||||||
|
|
||||||
|
val errorMessage = runCatching {
|
||||||
|
loginResult["errors"]!!.jsonArray[0].jsonObject["message"]?.jsonPrimitive?.content
|
||||||
|
}
|
||||||
|
|
||||||
|
throw IOException(errorMessage.getOrNull() ?: REQUEST_ERROR)
|
||||||
|
}
|
||||||
|
|
||||||
|
token = loginResult["data"]!!
|
||||||
|
.jsonObject["login"]!!
|
||||||
|
.jsonObject["token"]!!
|
||||||
|
.jsonPrimitive.content
|
||||||
|
|
||||||
|
loginResponse.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
val newRequest = chain.request().newBuilder()
|
if (!token.isNullOrEmpty()) {
|
||||||
.addHeader("Token", token)
|
val authorizedRequest = chain.request().newBuilder()
|
||||||
|
.addHeader("Authorization", "Bearer $token")
|
||||||
|
.build()
|
||||||
|
|
||||||
|
return chain.proceed(authorizedRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
return chain.proceed(chain.request())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loginRequest(email: String, password: String): Request {
|
||||||
|
val payload = buildLoginMutationQueryPayload(email, password)
|
||||||
|
|
||||||
|
val body = payload.toString().toRequestBody(JSON_MEDIA_TYPE)
|
||||||
|
|
||||||
|
val newHeaders = headersBuilder()
|
||||||
|
.add("Content-Length", body.contentLength().toString())
|
||||||
|
.add("Content-Type", body.contentType().toString())
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
return chain.proceed(newRequest)
|
return POST(GRAPHQL_URL, newHeaders, body)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun String.toDate(): Long {
|
private fun String.toDate(): Long {
|
||||||
|
@ -278,10 +346,16 @@ class ArgosScan : HttpSource(), ConfigurableSource {
|
||||||
companion object {
|
companion object {
|
||||||
private const val GRAPHQL_URL = "https://argosscan.com/graphql"
|
private const val GRAPHQL_URL = "https://argosscan.com/graphql"
|
||||||
|
|
||||||
private const val TOKEN_PREF_KEY = "token"
|
private const val EMAIL_PREF_KEY = "email"
|
||||||
private const val TOKEN_PREF_TITLE = "Token"
|
private const val EMAIL_PREF_TITLE = "E-mail"
|
||||||
private const val TOKEN_PREF_SUMMARY = "Defina o token de acesso ao conteúdo."
|
private const val EMAIL_PREF_SUMMARY = "Defina o e-mail de sua conta no site."
|
||||||
private const val TOKEN_NOT_FOUND = "Token não informado. Defina-o nas configurações da extensão."
|
private const val EMAIL_PREF_DIALOG = "Deixe em branco caso o site torne o login opcional."
|
||||||
|
|
||||||
|
private const val PASSWORD_PREF_KEY = "password"
|
||||||
|
private const val PASSWORD_PREF_TITLE = "Senha"
|
||||||
|
private const val PASSWORD_PREF_SUMMARY = "Defina a senha de sua conta no site."
|
||||||
|
private const val PASSWORD_PREF_DIALOG = EMAIL_PREF_DIALOG
|
||||||
|
|
||||||
private const val REQUEST_ERROR = "Erro na requisição. Tente novamente mais tarde."
|
private const val REQUEST_ERROR = "Erro na requisição. Tente novamente mais tarde."
|
||||||
|
|
||||||
private val JSON_MEDIA_TYPE = "application/json; charset=utf-8".toMediaTypeOrNull()
|
private val JSON_MEDIA_TYPE = "application/json; charset=utf-8".toMediaTypeOrNull()
|
||||||
|
|
|
@ -9,6 +9,25 @@ import kotlinx.serialization.json.putJsonObject
|
||||||
|
|
||||||
private fun buildQuery(queryAction: () -> String) = queryAction().replace("%", "$")
|
private fun buildQuery(queryAction: () -> String) = queryAction().replace("%", "$")
|
||||||
|
|
||||||
|
val LOGIN_MUTATION_QUERY = buildQuery {
|
||||||
|
"""
|
||||||
|
| mutation login(%email: String!, %password: String!) {
|
||||||
|
| login(loginInput: { email: %email, password: %password }) {
|
||||||
|
| token
|
||||||
|
| }
|
||||||
|
| }
|
||||||
|
""".trimMargin()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun buildLoginMutationQueryPayload(email: String, password: String) = buildJsonObject {
|
||||||
|
put("operationName", "login")
|
||||||
|
put("query", LOGIN_MUTATION_QUERY)
|
||||||
|
putJsonObject("variables") {
|
||||||
|
put("email", email)
|
||||||
|
put("password", password)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val POPULAR_QUERY = buildQuery {
|
val POPULAR_QUERY = buildQuery {
|
||||||
"""
|
"""
|
||||||
| query getProjects(
|
| query getProjects(
|
||||||
|
|
Loading…
Reference in New Issue