Add support to login in AS. (#9759)
This commit is contained in:
		
							parent
							
								
									e20bff0b61
								
							
						
					
					
						commit
						7b96c41fed
					
				| @ -6,7 +6,7 @@ ext { | ||||
|     extName = 'Argos Scan' | ||||
|     pkgNameSuffix = 'pt.argosscan' | ||||
|     extClass = '.ArgosScan' | ||||
|     extVersionCode = 16 | ||||
|     extVersionCode = 17 | ||||
| } | ||||
| 
 | ||||
| dependencies { | ||||
|  | ||||
| @ -2,6 +2,7 @@ package eu.kanade.tachiyomi.extension.pt.argosscan | ||||
| 
 | ||||
| import android.app.Application | ||||
| import android.content.SharedPreferences | ||||
| import android.text.InputType | ||||
| import androidx.preference.EditTextPreference | ||||
| import androidx.preference.PreferenceScreen | ||||
| 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.jsonArray | ||||
| import kotlinx.serialization.json.jsonObject | ||||
| import kotlinx.serialization.json.jsonPrimitive | ||||
| import okhttp3.Interceptor | ||||
| import okhttp3.MediaType.Companion.toMediaTypeOrNull | ||||
| import okhttp3.OkHttpClient | ||||
| @ -49,7 +51,7 @@ class ArgosScan : HttpSource(), ConfigurableSource { | ||||
|     override val supportsLatest = true | ||||
| 
 | ||||
|     override val client: OkHttpClient = network.cloudflareClient.newBuilder() | ||||
|         .addInterceptor(::tokenIntercept) | ||||
|         .addInterceptor(::loginIntercept) | ||||
|         .addInterceptor(RateLimitInterceptor(1, 2, TimeUnit.SECONDS)) | ||||
|         .build() | ||||
| 
 | ||||
| @ -59,6 +61,8 @@ class ArgosScan : HttpSource(), ConfigurableSource { | ||||
|         Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000) | ||||
|     } | ||||
| 
 | ||||
|     private var token: String? = null | ||||
| 
 | ||||
|     private fun genericMangaFromObject(project: ArgosProjectDto): SManga = SManga.create().apply { | ||||
|         title = project.name!! | ||||
|         url = "/obras/${project.id}" | ||||
| @ -234,40 +238,104 @@ class ArgosScan : HttpSource(), ConfigurableSource { | ||||
|     } | ||||
| 
 | ||||
|     override fun setupPreferenceScreen(screen: PreferenceScreen) { | ||||
|         val tokenPref = EditTextPreference(screen.context).apply { | ||||
|             key = TOKEN_PREF_KEY | ||||
|             title = TOKEN_PREF_TITLE | ||||
|             summary = TOKEN_PREF_SUMMARY | ||||
|         val emailPref = EditTextPreference(screen.context).apply { | ||||
|             key = EMAIL_PREF_KEY | ||||
|             title = EMAIL_PREF_TITLE | ||||
|             summary = EMAIL_PREF_SUMMARY | ||||
|             setDefaultValue("") | ||||
|             dialogTitle = TOKEN_PREF_TITLE | ||||
|             dialogMessage = TOKEN_PREF_SUMMARY | ||||
|             dialogTitle = EMAIL_PREF_TITLE | ||||
|             dialogMessage = EMAIL_PREF_DIALOG | ||||
| 
 | ||||
|             setOnBindEditTextListener { | ||||
|                 it.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS | ||||
|             } | ||||
| 
 | ||||
|             setOnPreferenceChangeListener { _, newValue -> | ||||
|                 token = null | ||||
| 
 | ||||
|                 preferences.edit() | ||||
|                     .putString(TOKEN_PREF_KEY, newValue as String) | ||||
|                     .putString(EMAIL_PREF_KEY, newValue as String) | ||||
|                     .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()) { | ||||
|             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()) { | ||||
|             throw IOException(TOKEN_NOT_FOUND) | ||||
|         if (!email.isNullOrEmpty() && !password.isNullOrEmpty() && token.isNullOrEmpty()) { | ||||
|             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() | ||||
|             .addHeader("Token", token) | ||||
|         if (!token.isNullOrEmpty()) { | ||||
|             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() | ||||
| 
 | ||||
|         return chain.proceed(newRequest) | ||||
|         return POST(GRAPHQL_URL, newHeaders, body) | ||||
|     } | ||||
| 
 | ||||
|     private fun String.toDate(): Long { | ||||
| @ -278,10 +346,16 @@ class ArgosScan : HttpSource(), ConfigurableSource { | ||||
|     companion object { | ||||
|         private const val GRAPHQL_URL = "https://argosscan.com/graphql" | ||||
| 
 | ||||
|         private const val TOKEN_PREF_KEY = "token" | ||||
|         private const val TOKEN_PREF_TITLE = "Token" | ||||
|         private const val TOKEN_PREF_SUMMARY = "Defina o token de acesso ao conteúdo." | ||||
|         private const val TOKEN_NOT_FOUND = "Token não informado. Defina-o nas configurações da extensão." | ||||
|         private const val EMAIL_PREF_KEY = "email" | ||||
|         private const val EMAIL_PREF_TITLE = "E-mail" | ||||
|         private const val EMAIL_PREF_SUMMARY = "Defina o e-mail de sua conta no site." | ||||
|         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 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("%", "$") | ||||
| 
 | ||||
| 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 { | ||||
|     """ | ||||
|         | query getProjects( | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Alessandro Jean
						Alessandro Jean