From 45eb27a9ebca64025d11650b8f5602fbf1814fa1 Mon Sep 17 00:00:00 2001
From: Alessandro Jean <alessandrojean@gmail.com>
Date: Sun, 24 Oct 2021 14:39:54 -0300
Subject: [PATCH] Add token support in AS. (#9599)

---
 src/pt/argosscan/build.gradle                 |  2 +-
 .../extension/pt/argosscan/ArgosScan.kt       | 77 ++++++++++++++++++-
 2 files changed, 77 insertions(+), 2 deletions(-)

diff --git a/src/pt/argosscan/build.gradle b/src/pt/argosscan/build.gradle
index 6404115c9..c7c2213ae 100644
--- a/src/pt/argosscan/build.gradle
+++ b/src/pt/argosscan/build.gradle
@@ -6,7 +6,7 @@ ext {
     extName = 'Argos Scan'
     pkgNameSuffix = 'pt.argosscan'
     extClass = '.ArgosScan'
-    extVersionCode = 15
+    extVersionCode = 16
 }
 
 dependencies {
diff --git a/src/pt/argosscan/src/eu/kanade/tachiyomi/extension/pt/argosscan/ArgosScan.kt b/src/pt/argosscan/src/eu/kanade/tachiyomi/extension/pt/argosscan/ArgosScan.kt
index 7430df985..9970294e7 100644
--- a/src/pt/argosscan/src/eu/kanade/tachiyomi/extension/pt/argosscan/ArgosScan.kt
+++ b/src/pt/argosscan/src/eu/kanade/tachiyomi/extension/pt/argosscan/ArgosScan.kt
@@ -1,9 +1,14 @@
 package eu.kanade.tachiyomi.extension.pt.argosscan
 
+import android.app.Application
+import android.content.SharedPreferences
+import androidx.preference.EditTextPreference
+import androidx.preference.PreferenceScreen
 import eu.kanade.tachiyomi.lib.ratelimit.RateLimitInterceptor
 import eu.kanade.tachiyomi.network.GET
 import eu.kanade.tachiyomi.network.POST
 import eu.kanade.tachiyomi.network.asObservableSuccess
+import eu.kanade.tachiyomi.source.ConfigurableSource
 import eu.kanade.tachiyomi.source.model.FilterList
 import eu.kanade.tachiyomi.source.model.MangasPage
 import eu.kanade.tachiyomi.source.model.Page
@@ -15,18 +20,22 @@ import kotlinx.serialization.json.add
 import kotlinx.serialization.json.decodeFromJsonElement
 import kotlinx.serialization.json.jsonArray
 import kotlinx.serialization.json.jsonObject
+import okhttp3.Interceptor
 import okhttp3.MediaType.Companion.toMediaTypeOrNull
 import okhttp3.OkHttpClient
 import okhttp3.Request
 import okhttp3.RequestBody.Companion.toRequestBody
 import okhttp3.Response
 import rx.Observable
+import uy.kohesive.injekt.Injekt
+import uy.kohesive.injekt.api.get
 import uy.kohesive.injekt.injectLazy
+import java.io.IOException
 import java.text.SimpleDateFormat
 import java.util.Locale
 import java.util.concurrent.TimeUnit
 
-class ArgosScan : HttpSource() {
+class ArgosScan : HttpSource(), ConfigurableSource {
 
     // Website changed from Madara to a custom CMS.
     override val versionId = 2
@@ -40,11 +49,16 @@ class ArgosScan : HttpSource() {
     override val supportsLatest = true
 
     override val client: OkHttpClient = network.cloudflareClient.newBuilder()
+        .addInterceptor(::tokenIntercept)
         .addInterceptor(RateLimitInterceptor(1, 2, TimeUnit.SECONDS))
         .build()
 
     private val json: Json by injectLazy()
 
+    private val preferences: SharedPreferences by lazy {
+        Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
+    }
+
     private fun genericMangaFromObject(project: ArgosProjectDto): SManga = SManga.create().apply {
         title = project.name!!
         url = "/obras/${project.id}"
@@ -67,6 +81,10 @@ class ArgosScan : HttpSource() {
     override fun popularMangaParse(response: Response): MangasPage {
         val result = json.parseToJsonElement(response.body!!.string()).jsonObject
 
+        if (result["errors"] != null) {
+            throw Exception(REQUEST_ERROR)
+        }
+
         val projectList = result["data"]!!.jsonObject["getProjects"]!!
             .let { json.decodeFromJsonElement<ArgosProjectListDto>(it) }
 
@@ -134,6 +152,11 @@ class ArgosScan : HttpSource() {
 
     override fun mangaDetailsParse(response: Response): SManga = SManga.create().apply {
         val result = json.parseToJsonElement(response.body!!.string()).jsonObject
+
+        if (result["errors"] != null) {
+            throw Exception(REQUEST_ERROR)
+        }
+
         val project = result["data"]!!.jsonObject["project"]!!.jsonObject
             .let { json.decodeFromJsonElement<ArgosProjectDto>(it) }
 
@@ -149,6 +172,11 @@ class ArgosScan : HttpSource() {
 
     override fun chapterListParse(response: Response): List<SChapter> {
         val result = json.parseToJsonElement(response.body!!.string()).jsonObject
+
+        if (result["errors"] != null) {
+            throw Exception(REQUEST_ERROR)
+        }
+
         val project = result["data"]!!.jsonObject["project"]!!.jsonObject
             .let { json.decodeFromJsonElement<ArgosProjectDto>(it) }
 
@@ -181,6 +209,10 @@ class ArgosScan : HttpSource() {
     override fun pageListParse(response: Response): List<Page> {
         val result = json.parseToJsonElement(response.body!!.string()).jsonObject
 
+        if (result["errors"] != null) {
+            throw Exception(REQUEST_ERROR)
+        }
+
         val chapterDto = result["data"]!!.jsonObject["getChapters"]!!.jsonObject["chapters"]!!.jsonArray[0]
             .let { json.decodeFromJsonElement<ArgosChapterDto>(it) }
 
@@ -201,6 +233,43 @@ class ArgosScan : HttpSource() {
         return GET(page.imageUrl!!, newHeaders)
     }
 
+    override fun setupPreferenceScreen(screen: PreferenceScreen) {
+        val tokenPref = EditTextPreference(screen.context).apply {
+            key = TOKEN_PREF_KEY
+            title = TOKEN_PREF_TITLE
+            summary = TOKEN_PREF_SUMMARY
+            setDefaultValue("")
+            dialogTitle = TOKEN_PREF_TITLE
+            dialogMessage = TOKEN_PREF_SUMMARY
+
+            setOnPreferenceChangeListener { _, newValue ->
+                preferences.edit()
+                    .putString(TOKEN_PREF_KEY, newValue as String)
+                    .commit()
+            }
+        }
+
+        screen.addPreference(tokenPref)
+    }
+
+    private fun tokenIntercept(chain: Interceptor.Chain): Response {
+        if (chain.request().url.toString().contains("graphql").not()) {
+            return chain.proceed(chain.request())
+        }
+
+        val token = preferences.getString(TOKEN_PREF_KEY, "")
+
+        if (token.isNullOrEmpty()) {
+            throw IOException(TOKEN_NOT_FOUND)
+        }
+
+        val newRequest = chain.request().newBuilder()
+            .addHeader("Token", token)
+            .build()
+
+        return chain.proceed(newRequest)
+    }
+
     private fun String.toDate(): Long {
         return runCatching { DATE_PARSER.parse(this)?.time }
             .getOrNull() ?: 0L
@@ -209,6 +278,12 @@ class ArgosScan : HttpSource() {
     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 REQUEST_ERROR = "Erro na requisição. Tente novamente mais tarde."
+
         private val JSON_MEDIA_TYPE = "application/json; charset=utf-8".toMediaTypeOrNull()
 
         private val DATE_PARSER by lazy {