@@ -44,8 +44,6 @@ dependencies {
|
|||||||
implementation("com.squareup.okhttp3:okhttp:$okhttpVersion")
|
implementation("com.squareup.okhttp3:okhttp:$okhttpVersion")
|
||||||
implementation("io.reactivex:rxjava:1.3.8")
|
implementation("io.reactivex:rxjava:1.3.8")
|
||||||
implementation("org.jsoup:jsoup:1.14.3")
|
implementation("org.jsoup:jsoup:1.14.3")
|
||||||
implementation("com.google.code.gson:gson:2.8.9")
|
|
||||||
implementation("com.github.salomonbrys.kotson:kotson:2.5.0")
|
|
||||||
|
|
||||||
// Sort
|
// Sort
|
||||||
implementation("com.github.gpanther:java-nat-sort:natural-comparator-1.1")
|
implementation("com.github.gpanther:java-nat-sort:natural-comparator-1.1")
|
||||||
|
|||||||
@@ -7,8 +7,6 @@ package eu.kanade.tachiyomi
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
import android.app.Application
|
|
||||||
import com.google.gson.Gson
|
|
||||||
// import eu.kanade.tachiyomi.data.cache.ChapterCache
|
// import eu.kanade.tachiyomi.data.cache.ChapterCache
|
||||||
// import eu.kanade.tachiyomi.data.cache.CoverCache
|
// import eu.kanade.tachiyomi.data.cache.CoverCache
|
||||||
// import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
// import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||||
@@ -17,6 +15,7 @@ import com.google.gson.Gson
|
|||||||
// import eu.kanade.tachiyomi.data.sync.LibrarySyncManager
|
// import eu.kanade.tachiyomi.data.sync.LibrarySyncManager
|
||||||
// import eu.kanade.tachiyomi.data.track.TrackManager
|
// import eu.kanade.tachiyomi.data.track.TrackManager
|
||||||
// import eu.kanade.tachiyomi.extension.ExtensionManager
|
// import eu.kanade.tachiyomi.extension.ExtensionManager
|
||||||
|
import android.app.Application
|
||||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
@@ -53,8 +52,6 @@ class AppModule(val app: Application) : InjektModule {
|
|||||||
//
|
//
|
||||||
// addSingletonFactory { LibrarySyncManager(app) }
|
// addSingletonFactory { LibrarySyncManager(app) }
|
||||||
|
|
||||||
addSingletonFactory { Gson() }
|
|
||||||
|
|
||||||
addSingletonFactory { Json { ignoreUnknownKeys = true } }
|
addSingletonFactory { Json { ignoreUnknownKeys = true } }
|
||||||
|
|
||||||
// Asynchronously init expensive components for a faster cold start
|
// Asynchronously init expensive components for a faster cold start
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
package eu.kanade.tachiyomi.network
|
package eu.kanade.tachiyomi.network
|
||||||
|
|
||||||
// import kotlinx.coroutines.suspendCancellableCoroutine
|
|
||||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
|
import kotlinx.serialization.decodeFromString
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
import okhttp3.Call
|
import okhttp3.Call
|
||||||
import okhttp3.Callback
|
import okhttp3.Callback
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
@@ -11,6 +12,8 @@ import okhttp3.internal.closeQuietly
|
|||||||
import rx.Observable
|
import rx.Observable
|
||||||
import rx.Producer
|
import rx.Producer
|
||||||
import rx.Subscription
|
import rx.Subscription
|
||||||
|
import uy.kohesive.injekt.Injekt
|
||||||
|
import uy.kohesive.injekt.api.fullType
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.util.concurrent.atomic.AtomicBoolean
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
import kotlin.coroutines.resumeWithException
|
import kotlin.coroutines.resumeWithException
|
||||||
@@ -124,3 +127,12 @@ fun OkHttpClient.newCallWithProgress(request: Request, listener: ProgressListene
|
|||||||
|
|
||||||
return progressClient.newCall(request)
|
return progressClient.newCall(request)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline fun <reified T> Response.parseAs(): T {
|
||||||
|
// Avoiding Injekt.get<Json>() due to compiler issues
|
||||||
|
val json = Injekt.getInstance<Json>(fullType<Json>().type)
|
||||||
|
this.use {
|
||||||
|
val responseBody = it.body?.string().orEmpty()
|
||||||
|
return json.decodeFromString(responseBody)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+63
-34
@@ -7,11 +7,10 @@ package suwayomi.tachidesk.manga.impl.extension.github
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
import com.github.salomonbrys.kotson.int
|
|
||||||
import com.github.salomonbrys.kotson.string
|
|
||||||
import com.google.gson.JsonArray
|
|
||||||
import com.google.gson.JsonParser
|
|
||||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||||
|
import eu.kanade.tachiyomi.network.await
|
||||||
|
import eu.kanade.tachiyomi.network.parseAs
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import suwayomi.tachidesk.manga.impl.util.PackageTools.LIB_VERSION_MAX
|
import suwayomi.tachidesk.manga.impl.util.PackageTools.LIB_VERSION_MAX
|
||||||
import suwayomi.tachidesk.manga.impl.util.PackageTools.LIB_VERSION_MIN
|
import suwayomi.tachidesk.manga.impl.util.PackageTools.LIB_VERSION_MIN
|
||||||
@@ -19,34 +18,39 @@ import suwayomi.tachidesk.manga.model.dataclass.ExtensionDataClass
|
|||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
object ExtensionGithubApi {
|
object ExtensionGithubApi {
|
||||||
private const val BASE_URL = "https://raw.githubusercontent.com"
|
private const val REPO_URL_PREFIX = "https://raw.githubusercontent.com/tachiyomiorg/tachiyomi-extensions/repo/"
|
||||||
private const val REPO_URL_PREFIX = "$BASE_URL/tachiyomiorg/tachiyomi-extensions/repo"
|
|
||||||
|
|
||||||
private fun parseResponse(json: JsonArray): List<OnlineExtension> {
|
@Serializable
|
||||||
return json
|
private data class ExtensionJsonObject(
|
||||||
.map { it.asJsonObject }
|
val name: String,
|
||||||
.filter { element ->
|
val pkg: String,
|
||||||
val versionName = element["version"].string
|
val apk: String,
|
||||||
val libVersion = versionName.substringBeforeLast('.').toDouble()
|
val lang: String,
|
||||||
libVersion in LIB_VERSION_MIN..LIB_VERSION_MAX
|
val code: Int,
|
||||||
}
|
val version: String,
|
||||||
.map { element ->
|
val nsfw: Int,
|
||||||
val name = element["name"].string.substringAfter("Tachiyomi: ")
|
val hasReadme: Int = 0,
|
||||||
val pkgName = element["pkg"].string
|
val hasChangelog: Int = 0,
|
||||||
val apkName = element["apk"].string
|
val sources: List<ExtensionSourceJsonObject>?,
|
||||||
val versionName = element["version"].string
|
)
|
||||||
val versionCode = element["code"].int
|
|
||||||
val lang = element["lang"].string
|
|
||||||
val nsfw = element["nsfw"].int == 1
|
|
||||||
val icon = "$REPO_URL_PREFIX/icon/${apkName.replace(".apk", ".png")}"
|
|
||||||
|
|
||||||
OnlineExtension(name, pkgName, versionName, versionCode, lang, nsfw, apkName, icon)
|
@Serializable
|
||||||
}
|
private data class ExtensionSourceJsonObject(
|
||||||
}
|
val name: String,
|
||||||
|
val lang: String,
|
||||||
|
val id: Long,
|
||||||
|
val baseUrl: String
|
||||||
|
)
|
||||||
|
|
||||||
suspend fun findExtensions(): List<OnlineExtension> {
|
suspend fun findExtensions(): List<OnlineExtension> {
|
||||||
val response = getRepo()
|
val request = Request.Builder()
|
||||||
return parseResponse(response)
|
.url("$REPO_URL_PREFIX/index.min.json")
|
||||||
|
.build()
|
||||||
|
|
||||||
|
return client.newCall(request)
|
||||||
|
.await()
|
||||||
|
.parseAs<List<ExtensionJsonObject>>()
|
||||||
|
.toExtensions()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getApkUrl(extension: ExtensionDataClass): String {
|
fun getApkUrl(extension: ExtensionDataClass): String {
|
||||||
@@ -65,12 +69,37 @@ object ExtensionGithubApi {
|
|||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getRepo(): JsonArray {
|
private fun List<ExtensionJsonObject>.toExtensions(): List<OnlineExtension> {
|
||||||
val request = Request.Builder()
|
return this
|
||||||
.url("$REPO_URL_PREFIX/index.min.json")
|
.filter {
|
||||||
.build()
|
val libVersion = it.version.substringBeforeLast('.').toDouble()
|
||||||
|
libVersion in LIB_VERSION_MIN..LIB_VERSION_MAX
|
||||||
|
}
|
||||||
|
.map {
|
||||||
|
OnlineExtension(
|
||||||
|
name = it.name.substringAfter("Tachiyomi: "),
|
||||||
|
pkgName = it.pkg,
|
||||||
|
versionName = it.version,
|
||||||
|
versionCode = it.code,
|
||||||
|
lang = it.lang,
|
||||||
|
isNsfw = it.nsfw == 1,
|
||||||
|
hasReadme = it.hasReadme == 1,
|
||||||
|
hasChangelog = it.hasChangelog == 1,
|
||||||
|
sources = it.sources?.toExtensionSources() ?: emptyList(),
|
||||||
|
apkName = it.apk,
|
||||||
|
iconUrl = "${REPO_URL_PREFIX}icon/${it.apk.replace(".apk", ".png")}"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val response = client.newCall(request).execute().use { response -> response.body!!.string() }
|
private fun List<ExtensionSourceJsonObject>.toExtensionSources(): List<OnlineExtensionSource> {
|
||||||
return JsonParser.parseString(response).asJsonArray
|
return this.map {
|
||||||
|
OnlineExtensionSource(
|
||||||
|
name = it.name,
|
||||||
|
lang = it.lang,
|
||||||
|
id = it.id,
|
||||||
|
baseUrl = it.baseUrl
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-4
@@ -7,13 +7,23 @@ package suwayomi.tachidesk.manga.impl.extension.github
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
data class OnlineExtensionSource(
|
||||||
|
val name: String,
|
||||||
|
val lang: String,
|
||||||
|
val id: Long,
|
||||||
|
val baseUrl: String
|
||||||
|
)
|
||||||
|
|
||||||
data class OnlineExtension(
|
data class OnlineExtension(
|
||||||
val name: String,
|
val name: String,
|
||||||
val pkgName: String,
|
val pkgName: String,
|
||||||
val versionName: String,
|
|
||||||
val versionCode: Int,
|
|
||||||
val lang: String,
|
|
||||||
val isNsfw: Boolean,
|
|
||||||
val apkName: String,
|
val apkName: String,
|
||||||
|
val lang: String,
|
||||||
|
val versionCode: Int,
|
||||||
|
val versionName: String,
|
||||||
|
val isNsfw: Boolean,
|
||||||
|
val hasReadme: Boolean,
|
||||||
|
val hasChangelog: Boolean,
|
||||||
|
val sources: List<OnlineExtensionSource>,
|
||||||
val iconUrl: String
|
val iconUrl: String
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user