mirror of
https://github.com/mihonapp/mihon.git
synced 2025-06-29 04:27:51 +02:00
Remove dependency injection from core module and data module from presentation-widget module
Includes side effects: - No longer need to restart app for user agent string change to take effect - parseAs extension function requires a Json instance in the calling context, which doesn't necessarily need to be the default one provided by Injekt
This commit is contained in:
@ -222,7 +222,7 @@ object SettingsAdvancedScreen : SearchableSettings {
|
||||
Preference.PreferenceItem.TextPreference(
|
||||
title = stringResource(R.string.pref_clear_cookies),
|
||||
onClick = {
|
||||
networkHelper.cookieManager.removeAll()
|
||||
networkHelper.cookieJar.removeAll()
|
||||
context.toast(R.string.cookies_cleared)
|
||||
},
|
||||
),
|
||||
@ -280,7 +280,6 @@ object SettingsAdvancedScreen : SearchableSettings {
|
||||
context.toast(R.string.error_user_agent_string_invalid)
|
||||
return@EditTextPreference false
|
||||
}
|
||||
context.toast(R.string.requires_app_restart)
|
||||
true
|
||||
},
|
||||
),
|
||||
|
@ -118,7 +118,7 @@ class AppModule(val app: Application) : InjektModule {
|
||||
addSingletonFactory { ChapterCache(app) }
|
||||
addSingletonFactory { CoverCache(app) }
|
||||
|
||||
addSingletonFactory { NetworkHelper(app) }
|
||||
addSingletonFactory { NetworkHelper(app, get()) }
|
||||
addSingletonFactory { JavaScriptEngine(app) }
|
||||
|
||||
addSingletonFactory { SourceManager(app, get(), get()) }
|
||||
|
@ -9,6 +9,7 @@ import eu.kanade.tachiyomi.network.awaitSuccess
|
||||
import eu.kanade.tachiyomi.network.interceptor.rateLimit
|
||||
import eu.kanade.tachiyomi.network.jsonMime
|
||||
import eu.kanade.tachiyomi.network.parseAs
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonNull
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.buildJsonObject
|
||||
@ -24,11 +25,14 @@ import kotlinx.serialization.json.putJsonObject
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import tachiyomi.core.util.lang.withIOContext
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.util.Calendar
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
||||
|
||||
private val json: Json by injectLazy()
|
||||
|
||||
private val authClient = client.newBuilder()
|
||||
.addInterceptor(interceptor)
|
||||
.rateLimit(permits = 85, period = 1, unit = TimeUnit.MINUTES)
|
||||
@ -53,19 +57,21 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
||||
put("status", track.toAnilistStatus())
|
||||
}
|
||||
}
|
||||
authClient.newCall(
|
||||
POST(
|
||||
apiUrl,
|
||||
body = payload.toString().toRequestBody(jsonMime),
|
||||
),
|
||||
)
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let {
|
||||
track.library_id =
|
||||
it["data"]!!.jsonObject["SaveMediaListEntry"]!!.jsonObject["id"]!!.jsonPrimitive.long
|
||||
track
|
||||
}
|
||||
with(json) {
|
||||
authClient.newCall(
|
||||
POST(
|
||||
apiUrl,
|
||||
body = payload.toString().toRequestBody(jsonMime),
|
||||
),
|
||||
)
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let {
|
||||
track.library_id =
|
||||
it["data"]!!.jsonObject["SaveMediaListEntry"]!!.jsonObject["id"]!!.jsonPrimitive.long
|
||||
track
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,21 +143,23 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
||||
put("query", search)
|
||||
}
|
||||
}
|
||||
authClient.newCall(
|
||||
POST(
|
||||
apiUrl,
|
||||
body = payload.toString().toRequestBody(jsonMime),
|
||||
),
|
||||
)
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let { response ->
|
||||
val data = response["data"]!!.jsonObject
|
||||
val page = data["Page"]!!.jsonObject
|
||||
val media = page["media"]!!.jsonArray
|
||||
val entries = media.map { jsonToALManga(it.jsonObject) }
|
||||
entries.map { it.toTrack() }
|
||||
}
|
||||
with(json) {
|
||||
authClient.newCall(
|
||||
POST(
|
||||
apiUrl,
|
||||
body = payload.toString().toRequestBody(jsonMime),
|
||||
),
|
||||
)
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let { response ->
|
||||
val data = response["data"]!!.jsonObject
|
||||
val page = data["Page"]!!.jsonObject
|
||||
val media = page["media"]!!.jsonArray
|
||||
val entries = media.map { jsonToALManga(it.jsonObject) }
|
||||
entries.map { it.toTrack() }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -205,21 +213,23 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
||||
put("manga_id", track.media_id)
|
||||
}
|
||||
}
|
||||
authClient.newCall(
|
||||
POST(
|
||||
apiUrl,
|
||||
body = payload.toString().toRequestBody(jsonMime),
|
||||
),
|
||||
)
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let { response ->
|
||||
val data = response["data"]!!.jsonObject
|
||||
val page = data["Page"]!!.jsonObject
|
||||
val media = page["mediaList"]!!.jsonArray
|
||||
val entries = media.map { jsonToALUserManga(it.jsonObject) }
|
||||
entries.firstOrNull()?.toTrack()
|
||||
}
|
||||
with(json) {
|
||||
authClient.newCall(
|
||||
POST(
|
||||
apiUrl,
|
||||
body = payload.toString().toRequestBody(jsonMime),
|
||||
),
|
||||
)
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let { response ->
|
||||
val data = response["data"]!!.jsonObject
|
||||
val page = data["Page"]!!.jsonObject
|
||||
val media = page["mediaList"]!!.jsonArray
|
||||
val entries = media.map { jsonToALUserManga(it.jsonObject) }
|
||||
entries.firstOrNull()?.toTrack()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -247,22 +257,24 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
||||
val payload = buildJsonObject {
|
||||
put("query", query)
|
||||
}
|
||||
authClient.newCall(
|
||||
POST(
|
||||
apiUrl,
|
||||
body = payload.toString().toRequestBody(jsonMime),
|
||||
),
|
||||
)
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let {
|
||||
val data = it["data"]!!.jsonObject
|
||||
val viewer = data["Viewer"]!!.jsonObject
|
||||
Pair(
|
||||
viewer["id"]!!.jsonPrimitive.int,
|
||||
viewer["mediaListOptions"]!!.jsonObject["scoreFormat"]!!.jsonPrimitive.content,
|
||||
)
|
||||
}
|
||||
with(json) {
|
||||
authClient.newCall(
|
||||
POST(
|
||||
apiUrl,
|
||||
body = payload.toString().toRequestBody(jsonMime),
|
||||
),
|
||||
)
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let {
|
||||
val data = it["data"]!!.jsonObject
|
||||
val viewer = data["Viewer"]!!.jsonObject
|
||||
Pair(
|
||||
viewer["id"]!!.jsonPrimitive.int,
|
||||
viewer["mediaListOptions"]!!.jsonObject["scoreFormat"]!!.jsonPrimitive.content,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -118,10 +118,12 @@ class BangumiApi(private val client: OkHttpClient, interceptor: BangumiIntercept
|
||||
|
||||
suspend fun findLibManga(track: Track): Track? {
|
||||
return withIOContext {
|
||||
authClient.newCall(GET("$apiUrl/subject/${track.media_id}"))
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let { jsonToSearch(it) }
|
||||
with(json) {
|
||||
authClient.newCall(GET("$apiUrl/subject/${track.media_id}"))
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let { jsonToSearch(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -155,9 +157,11 @@ class BangumiApi(private val client: OkHttpClient, interceptor: BangumiIntercept
|
||||
|
||||
suspend fun accessToken(code: String): OAuth {
|
||||
return withIOContext {
|
||||
client.newCall(accessTokenRequest(code))
|
||||
.awaitSuccess()
|
||||
.parseAs()
|
||||
with(json) {
|
||||
client.newCall(accessTokenRequest(code))
|
||||
.awaitSuccess()
|
||||
.parseAs()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -181,7 +185,6 @@ class BangumiApi(private val client: OkHttpClient, interceptor: BangumiIntercept
|
||||
private const val loginUrl = "https://bgm.tv/oauth/authorize"
|
||||
|
||||
private const val redirectUrl = "tachiyomi://bangumi-auth"
|
||||
private const val baseMangaUrl = "$apiUrl/mangas"
|
||||
|
||||
fun authUrl(): Uri =
|
||||
loginUrl.toUri().buildUpon()
|
||||
|
@ -6,6 +6,7 @@ import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.network.POST
|
||||
import eu.kanade.tachiyomi.network.awaitSuccess
|
||||
import eu.kanade.tachiyomi.network.parseAs
|
||||
import kotlinx.serialization.json.Json
|
||||
import logcat.LogPriority
|
||||
import okhttp3.Dns
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
@ -13,11 +14,14 @@ import okhttp3.OkHttpClient
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import tachiyomi.core.util.lang.withIOContext
|
||||
import tachiyomi.core.util.system.logcat
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.io.IOException
|
||||
import java.net.SocketTimeoutException
|
||||
|
||||
class KavitaApi(private val client: OkHttpClient, interceptor: KavitaInterceptor) {
|
||||
|
||||
private val json: Json by injectLazy()
|
||||
|
||||
private val authClient = client.newBuilder()
|
||||
.dns(Dns.SYSTEM)
|
||||
.addInterceptor(interceptor)
|
||||
@ -39,18 +43,20 @@ class KavitaApi(private val client: OkHttpClient, interceptor: KavitaInterceptor
|
||||
body = "{}".toRequestBody("application/json; charset=utf-8".toMediaTypeOrNull()),
|
||||
)
|
||||
try {
|
||||
client.newCall(request).execute().use {
|
||||
when (it.code) {
|
||||
200 -> return it.parseAs<AuthenticationDto>().token
|
||||
401 -> {
|
||||
logcat(LogPriority.WARN) { "Unauthorized / api key not valid: Cleaned api URL: $apiUrl, Api key is empty: ${apiKey.isEmpty()}" }
|
||||
throw IOException("Unauthorized / api key not valid")
|
||||
with(json) {
|
||||
client.newCall(request).execute().use {
|
||||
when (it.code) {
|
||||
200 -> return it.parseAs<AuthenticationDto>().token
|
||||
401 -> {
|
||||
logcat(LogPriority.WARN) { "Unauthorized / api key not valid: Cleaned api URL: $apiUrl, Api key is empty: ${apiKey.isEmpty()}" }
|
||||
throw IOException("Unauthorized / api key not valid")
|
||||
}
|
||||
500 -> {
|
||||
logcat(LogPriority.WARN) { "Error fetching JWT token. Cleaned api URL: $apiUrl, Api key is empty: ${apiKey.isEmpty()}" }
|
||||
throw IOException("Error fetching JWT token")
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
500 -> {
|
||||
logcat(LogPriority.WARN) { "Error fetching JWT token. Cleaned api URL: $apiUrl, Api key is empty: ${apiKey.isEmpty()}" }
|
||||
throw IOException("Error fetching JWT token")
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
// Not sure which one to catch
|
||||
@ -86,9 +92,11 @@ class KavitaApi(private val client: OkHttpClient, interceptor: KavitaInterceptor
|
||||
private fun getTotalChapters(url: String): Int {
|
||||
val requestUrl = getApiVolumesUrl(url)
|
||||
try {
|
||||
val listVolumeDto = authClient.newCall(GET(requestUrl))
|
||||
.execute()
|
||||
.parseAs<List<VolumeDto>>()
|
||||
val listVolumeDto = with(json) {
|
||||
authClient.newCall(GET(requestUrl))
|
||||
.execute()
|
||||
.parseAs<List<VolumeDto>>()
|
||||
}
|
||||
var volumeNumber = 0
|
||||
var maxChapterNumber = 0
|
||||
for (volume in listVolumeDto) {
|
||||
@ -110,12 +118,14 @@ class KavitaApi(private val client: OkHttpClient, interceptor: KavitaInterceptor
|
||||
val serieId = getIdFromUrl(url)
|
||||
val requestUrl = "${getApiFromUrl(url)}/Tachiyomi/latest-chapter?seriesId=$serieId"
|
||||
try {
|
||||
authClient.newCall(GET(requestUrl)).execute().use {
|
||||
if (it.code == 200) {
|
||||
return it.parseAs<ChapterDto>().number!!.replace(",", ".").toFloat()
|
||||
}
|
||||
if (it.code == 204) {
|
||||
return 0F
|
||||
with(json) {
|
||||
authClient.newCall(GET(requestUrl)).execute().use {
|
||||
if (it.code == 200) {
|
||||
return it.parseAs<ChapterDto>().number!!.replace(",", ".").toFloat()
|
||||
}
|
||||
if (it.code == 204) {
|
||||
return 0F
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
@ -127,9 +137,11 @@ class KavitaApi(private val client: OkHttpClient, interceptor: KavitaInterceptor
|
||||
|
||||
suspend fun getTrackSearch(url: String): TrackSearch = withIOContext {
|
||||
try {
|
||||
val serieDto: SeriesDto = authClient.newCall(GET(url))
|
||||
.awaitSuccess()
|
||||
.parseAs()
|
||||
val serieDto: SeriesDto = with(json) {
|
||||
authClient.newCall(GET(url))
|
||||
.awaitSuccess()
|
||||
.parseAs()
|
||||
}
|
||||
|
||||
val track = serieDto.toTrack()
|
||||
track.apply {
|
||||
|
@ -8,6 +8,7 @@ import eu.kanade.tachiyomi.network.POST
|
||||
import eu.kanade.tachiyomi.network.awaitSuccess
|
||||
import eu.kanade.tachiyomi.network.jsonMime
|
||||
import eu.kanade.tachiyomi.network.parseAs
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.buildJsonObject
|
||||
import kotlinx.serialization.json.jsonArray
|
||||
@ -24,11 +25,14 @@ import okhttp3.Request
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import tachiyomi.core.util.lang.withIOContext
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.net.URLEncoder
|
||||
import java.nio.charset.StandardCharsets
|
||||
|
||||
class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor) {
|
||||
|
||||
private val json: Json by injectLazy()
|
||||
|
||||
private val authClient = client.newBuilder().addInterceptor(interceptor).build()
|
||||
|
||||
suspend fun addLibManga(track: Track, userId: String): Track {
|
||||
@ -57,22 +61,25 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
||||
}
|
||||
}
|
||||
|
||||
authClient.newCall(
|
||||
POST(
|
||||
"${baseUrl}library-entries",
|
||||
headers = headersOf(
|
||||
"Content-Type",
|
||||
"application/vnd.api+json",
|
||||
with(json) {
|
||||
authClient.newCall(
|
||||
POST(
|
||||
"${baseUrl}library-entries",
|
||||
headers = headersOf(
|
||||
"Content-Type",
|
||||
"application/vnd.api+json",
|
||||
),
|
||||
body = data.toString()
|
||||
.toRequestBody("application/vnd.api+json".toMediaType()),
|
||||
),
|
||||
body = data.toString().toRequestBody("application/vnd.api+json".toMediaType()),
|
||||
),
|
||||
)
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let {
|
||||
track.media_id = it["data"]!!.jsonObject["id"]!!.jsonPrimitive.long
|
||||
track
|
||||
}
|
||||
)
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let {
|
||||
track.media_id = it["data"]!!.jsonObject["id"]!!.jsonPrimitive.long
|
||||
track
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -92,35 +99,41 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
||||
}
|
||||
}
|
||||
|
||||
authClient.newCall(
|
||||
Request.Builder()
|
||||
.url("${baseUrl}library-entries/${track.media_id}")
|
||||
.headers(
|
||||
headersOf(
|
||||
"Content-Type",
|
||||
"application/vnd.api+json",
|
||||
),
|
||||
)
|
||||
.patch(data.toString().toRequestBody("application/vnd.api+json".toMediaType()))
|
||||
.build(),
|
||||
)
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let {
|
||||
track
|
||||
}
|
||||
with(json) {
|
||||
authClient.newCall(
|
||||
Request.Builder()
|
||||
.url("${baseUrl}library-entries/${track.media_id}")
|
||||
.headers(
|
||||
headersOf(
|
||||
"Content-Type",
|
||||
"application/vnd.api+json",
|
||||
),
|
||||
)
|
||||
.patch(
|
||||
data.toString().toRequestBody("application/vnd.api+json".toMediaType()),
|
||||
)
|
||||
.build(),
|
||||
)
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let {
|
||||
track
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun search(query: String): List<TrackSearch> {
|
||||
return withIOContext {
|
||||
authClient.newCall(GET(algoliaKeyUrl))
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let {
|
||||
val key = it["media"]!!.jsonObject["key"]!!.jsonPrimitive.content
|
||||
algoliaSearch(key, query)
|
||||
}
|
||||
with(json) {
|
||||
authClient.newCall(GET(algoliaKeyUrl))
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let {
|
||||
val key = it["media"]!!.jsonObject["key"]!!.jsonPrimitive.content
|
||||
algoliaSearch(key, query)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -130,26 +143,28 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
||||
put("params", "query=${URLEncoder.encode(query, StandardCharsets.UTF_8.name())}$algoliaFilter")
|
||||
}
|
||||
|
||||
client.newCall(
|
||||
POST(
|
||||
algoliaUrl,
|
||||
headers = headersOf(
|
||||
"X-Algolia-Application-Id",
|
||||
algoliaAppId,
|
||||
"X-Algolia-API-Key",
|
||||
key,
|
||||
with(json) {
|
||||
client.newCall(
|
||||
POST(
|
||||
algoliaUrl,
|
||||
headers = headersOf(
|
||||
"X-Algolia-Application-Id",
|
||||
algoliaAppId,
|
||||
"X-Algolia-API-Key",
|
||||
key,
|
||||
),
|
||||
body = jsonObject.toString().toRequestBody(jsonMime),
|
||||
),
|
||||
body = jsonObject.toString().toRequestBody(jsonMime),
|
||||
),
|
||||
)
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let {
|
||||
it["hits"]!!.jsonArray
|
||||
.map { KitsuSearchManga(it.jsonObject) }
|
||||
.filter { it.subType != "novel" }
|
||||
.map { it.toTrack() }
|
||||
}
|
||||
)
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let {
|
||||
it["hits"]!!.jsonArray
|
||||
.map { KitsuSearchManga(it.jsonObject) }
|
||||
.filter { it.subType != "novel" }
|
||||
.map { it.toTrack() }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -159,18 +174,20 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
||||
.encodedQuery("filter[manga_id]=${track.media_id}&filter[user_id]=$userId")
|
||||
.appendQueryParameter("include", "manga")
|
||||
.build()
|
||||
authClient.newCall(GET(url.toString()))
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let {
|
||||
val data = it["data"]!!.jsonArray
|
||||
if (data.size > 0) {
|
||||
val manga = it["included"]!!.jsonArray[0].jsonObject
|
||||
KitsuLibManga(data[0].jsonObject, manga).toTrack()
|
||||
} else {
|
||||
null
|
||||
with(json) {
|
||||
authClient.newCall(GET(url.toString()))
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let {
|
||||
val data = it["data"]!!.jsonArray
|
||||
if (data.size > 0) {
|
||||
val manga = it["included"]!!.jsonArray[0].jsonObject
|
||||
KitsuLibManga(data[0].jsonObject, manga).toTrack()
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -180,18 +197,20 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
||||
.encodedQuery("filter[id]=${track.media_id}")
|
||||
.appendQueryParameter("include", "manga")
|
||||
.build()
|
||||
authClient.newCall(GET(url.toString()))
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let {
|
||||
val data = it["data"]!!.jsonArray
|
||||
if (data.size > 0) {
|
||||
val manga = it["included"]!!.jsonArray[0].jsonObject
|
||||
KitsuLibManga(data[0].jsonObject, manga).toTrack()
|
||||
} else {
|
||||
throw Exception("Could not find manga")
|
||||
with(json) {
|
||||
authClient.newCall(GET(url.toString()))
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let {
|
||||
val data = it["data"]!!.jsonArray
|
||||
if (data.size > 0) {
|
||||
val manga = it["included"]!!.jsonArray[0].jsonObject
|
||||
KitsuLibManga(data[0].jsonObject, manga).toTrack()
|
||||
} else {
|
||||
throw Exception("Could not find manga")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -204,9 +223,11 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
||||
.add("client_id", clientId)
|
||||
.add("client_secret", clientSecret)
|
||||
.build()
|
||||
client.newCall(POST(loginUrl, body = formBody))
|
||||
.awaitSuccess()
|
||||
.parseAs()
|
||||
with(json) {
|
||||
client.newCall(POST(loginUrl, body = formBody))
|
||||
.awaitSuccess()
|
||||
.parseAs()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -215,12 +236,14 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
||||
val url = "${baseUrl}users".toUri().buildUpon()
|
||||
.encodedQuery("filter[self]=true")
|
||||
.build()
|
||||
authClient.newCall(GET(url.toString()))
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let {
|
||||
it["data"]!!.jsonArray[0].jsonObject["id"]!!.jsonPrimitive.content
|
||||
}
|
||||
with(json) {
|
||||
authClient.newCall(GET(url.toString()))
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let {
|
||||
it["data"]!!.jsonArray[0].jsonObject["id"]!!.jsonPrimitive.content
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,25 +26,29 @@ class KomgaApi(private val client: OkHttpClient) {
|
||||
suspend fun getTrackSearch(url: String): TrackSearch =
|
||||
withIOContext {
|
||||
try {
|
||||
val track = if (url.contains(READLIST_API)) {
|
||||
client.newCall(GET(url))
|
||||
.awaitSuccess()
|
||||
.parseAs<ReadListDto>()
|
||||
.toTrack()
|
||||
} else {
|
||||
client.newCall(GET(url))
|
||||
.awaitSuccess()
|
||||
.parseAs<SeriesDto>()
|
||||
.toTrack()
|
||||
val track = with(json) {
|
||||
if (url.contains(READLIST_API)) {
|
||||
client.newCall(GET(url))
|
||||
.awaitSuccess()
|
||||
.parseAs<ReadListDto>()
|
||||
.toTrack()
|
||||
} else {
|
||||
client.newCall(GET(url))
|
||||
.awaitSuccess()
|
||||
.parseAs<SeriesDto>()
|
||||
.toTrack()
|
||||
}
|
||||
}
|
||||
|
||||
val progress = client
|
||||
.newCall(GET("${url.replace("/api/v1/series/", "/api/v2/series/")}/read-progress/tachiyomi"))
|
||||
.awaitSuccess().let {
|
||||
if (url.contains("/api/v1/series/")) {
|
||||
it.parseAs<ReadProgressV2Dto>()
|
||||
} else {
|
||||
it.parseAs<ReadProgressDto>().toV2()
|
||||
with(json) {
|
||||
if (url.contains("/api/v1/series/")) {
|
||||
it.parseAs<ReadProgressV2Dto>()
|
||||
} else {
|
||||
it.parseAs<ReadProgressDto>().toV2()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -47,7 +47,7 @@ class MangaUpdatesApi(
|
||||
}
|
||||
|
||||
suspend fun getSeriesListItem(track: Track): Pair<ListItem, Rating?> {
|
||||
val listItem =
|
||||
val listItem = with(json) {
|
||||
authClient.newCall(
|
||||
GET(
|
||||
url = "$baseUrl/v1/lists/series/${track.media_id}",
|
||||
@ -55,6 +55,7 @@ class MangaUpdatesApi(
|
||||
)
|
||||
.awaitSuccess()
|
||||
.parseAs<ListItem>()
|
||||
}
|
||||
|
||||
val rating = getSeriesRating(track)
|
||||
|
||||
@ -111,13 +112,15 @@ class MangaUpdatesApi(
|
||||
|
||||
suspend fun getSeriesRating(track: Track): Rating? {
|
||||
return try {
|
||||
authClient.newCall(
|
||||
GET(
|
||||
url = "$baseUrl/v1/series/${track.media_id}/rating",
|
||||
),
|
||||
)
|
||||
.awaitSuccess()
|
||||
.parseAs<Rating>()
|
||||
with(json) {
|
||||
authClient.newCall(
|
||||
GET(
|
||||
url = "$baseUrl/v1/series/${track.media_id}/rating",
|
||||
),
|
||||
)
|
||||
.awaitSuccess()
|
||||
.parseAs<Rating>()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
@ -156,20 +159,22 @@ class MangaUpdatesApi(
|
||||
},
|
||||
)
|
||||
}
|
||||
return client.newCall(
|
||||
POST(
|
||||
url = "$baseUrl/v1/series/search",
|
||||
body = body.toString().toRequestBody(contentType),
|
||||
),
|
||||
)
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let { obj ->
|
||||
obj["results"]?.jsonArray?.map { element ->
|
||||
json.decodeFromJsonElement<Record>(element.jsonObject["record"]!!)
|
||||
return with(json) {
|
||||
client.newCall(
|
||||
POST(
|
||||
url = "$baseUrl/v1/series/search",
|
||||
body = body.toString().toRequestBody(contentType),
|
||||
),
|
||||
)
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let { obj ->
|
||||
obj["results"]?.jsonArray?.map { element ->
|
||||
json.decodeFromJsonElement<Record>(element.jsonObject["record"]!!)
|
||||
}
|
||||
}
|
||||
}
|
||||
.orEmpty()
|
||||
.orEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun authenticate(username: String, password: String): Context? {
|
||||
@ -177,21 +182,23 @@ class MangaUpdatesApi(
|
||||
put("username", username)
|
||||
put("password", password)
|
||||
}
|
||||
return client.newCall(
|
||||
PUT(
|
||||
url = "$baseUrl/v1/account/login",
|
||||
body = body.toString().toRequestBody(contentType),
|
||||
),
|
||||
)
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let { obj ->
|
||||
try {
|
||||
json.decodeFromJsonElement<Context>(obj["context"]!!)
|
||||
} catch (e: Exception) {
|
||||
logcat(LogPriority.ERROR, e)
|
||||
null
|
||||
return with(json) {
|
||||
client.newCall(
|
||||
PUT(
|
||||
url = "$baseUrl/v1/account/login",
|
||||
body = body.toString().toRequestBody(contentType),
|
||||
),
|
||||
)
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let { obj ->
|
||||
try {
|
||||
json.decodeFromJsonElement<Context>(obj["context"]!!)
|
||||
} catch (e: Exception) {
|
||||
logcat(LogPriority.ERROR, e)
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ import eu.kanade.tachiyomi.network.parseAs
|
||||
import eu.kanade.tachiyomi.util.PkceUtil
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.boolean
|
||||
import kotlinx.serialization.json.contentOrNull
|
||||
@ -27,11 +28,14 @@ import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.RequestBody
|
||||
import tachiyomi.core.util.lang.withIOContext
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListInterceptor) {
|
||||
|
||||
private val json: Json by injectLazy()
|
||||
|
||||
private val authClient = client.newBuilder().addInterceptor(interceptor).build()
|
||||
|
||||
suspend fun getAccessToken(authCode: String): OAuth {
|
||||
@ -42,9 +46,11 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI
|
||||
.add("code_verifier", codeVerifier)
|
||||
.add("grant_type", "authorization_code")
|
||||
.build()
|
||||
client.newCall(POST("$baseOAuthUrl/token", body = formBody))
|
||||
.awaitSuccess()
|
||||
.parseAs()
|
||||
with(json) {
|
||||
client.newCall(POST("$baseOAuthUrl/token", body = formBody))
|
||||
.awaitSuccess()
|
||||
.parseAs()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,10 +60,12 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI
|
||||
.url("$baseApiUrl/users/@me")
|
||||
.get()
|
||||
.build()
|
||||
authClient.newCall(request)
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let { it["name"]!!.jsonPrimitive.content }
|
||||
with(json) {
|
||||
authClient.newCall(request)
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let { it["name"]!!.jsonPrimitive.content }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -68,19 +76,21 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI
|
||||
.appendQueryParameter("q", query.take(64))
|
||||
.appendQueryParameter("nsfw", "true")
|
||||
.build()
|
||||
authClient.newCall(GET(url.toString()))
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let {
|
||||
it["data"]!!.jsonArray
|
||||
.map { data -> data.jsonObject["node"]!!.jsonObject }
|
||||
.map { node ->
|
||||
val id = node["id"]!!.jsonPrimitive.int
|
||||
async { getMangaDetails(id) }
|
||||
}
|
||||
.awaitAll()
|
||||
.filter { trackSearch -> !trackSearch.publishing_type.contains("novel") }
|
||||
}
|
||||
with(json) {
|
||||
authClient.newCall(GET(url.toString()))
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let {
|
||||
it["data"]!!.jsonArray
|
||||
.map { data -> data.jsonObject["node"]!!.jsonObject }
|
||||
.map { node ->
|
||||
val id = node["id"]!!.jsonPrimitive.int
|
||||
async { getMangaDetails(id) }
|
||||
}
|
||||
.awaitAll()
|
||||
.filter { trackSearch -> !trackSearch.publishing_type.contains("novel") }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,28 +100,34 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI
|
||||
.appendPath(id.toString())
|
||||
.appendQueryParameter("fields", "id,title,synopsis,num_chapters,main_picture,status,media_type,start_date")
|
||||
.build()
|
||||
authClient.newCall(GET(url.toString()))
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let {
|
||||
val obj = it.jsonObject
|
||||
TrackSearch.create(TrackManager.MYANIMELIST).apply {
|
||||
media_id = obj["id"]!!.jsonPrimitive.long
|
||||
title = obj["title"]!!.jsonPrimitive.content
|
||||
summary = obj["synopsis"]?.jsonPrimitive?.content ?: ""
|
||||
total_chapters = obj["num_chapters"]!!.jsonPrimitive.int
|
||||
cover_url = obj["main_picture"]?.jsonObject?.get("large")?.jsonPrimitive?.content ?: ""
|
||||
tracking_url = "https://myanimelist.net/manga/$media_id"
|
||||
publishing_status = obj["status"]!!.jsonPrimitive.content.replace("_", " ")
|
||||
publishing_type = obj["media_type"]!!.jsonPrimitive.content.replace("_", " ")
|
||||
start_date = try {
|
||||
val outputDf = SimpleDateFormat("yyyy-MM-dd", Locale.US)
|
||||
outputDf.format(obj["start_date"]!!)
|
||||
} catch (e: Exception) {
|
||||
""
|
||||
with(json) {
|
||||
authClient.newCall(GET(url.toString()))
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let {
|
||||
val obj = it.jsonObject
|
||||
TrackSearch.create(TrackManager.MYANIMELIST).apply {
|
||||
media_id = obj["id"]!!.jsonPrimitive.long
|
||||
title = obj["title"]!!.jsonPrimitive.content
|
||||
summary = obj["synopsis"]?.jsonPrimitive?.content ?: ""
|
||||
total_chapters = obj["num_chapters"]!!.jsonPrimitive.int
|
||||
cover_url =
|
||||
obj["main_picture"]?.jsonObject?.get("large")?.jsonPrimitive?.content
|
||||
?: ""
|
||||
tracking_url = "https://myanimelist.net/manga/$media_id"
|
||||
publishing_status =
|
||||
obj["status"]!!.jsonPrimitive.content.replace("_", " ")
|
||||
publishing_type =
|
||||
obj["media_type"]!!.jsonPrimitive.content.replace("_", " ")
|
||||
start_date = try {
|
||||
val outputDf = SimpleDateFormat("yyyy-MM-dd", Locale.US)
|
||||
outputDf.format(obj["start_date"]!!)
|
||||
} catch (e: Exception) {
|
||||
""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -133,10 +149,12 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI
|
||||
.url(mangaUrl(track.media_id).toString())
|
||||
.put(formBodyBuilder.build())
|
||||
.build()
|
||||
authClient.newCall(request)
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let { parseMangaItem(it, track) }
|
||||
with(json) {
|
||||
authClient.newCall(request)
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let { parseMangaItem(it, track) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -146,15 +164,17 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI
|
||||
.appendPath(track.media_id.toString())
|
||||
.appendQueryParameter("fields", "num_chapters,my_list_status{start_date,finish_date}")
|
||||
.build()
|
||||
authClient.newCall(GET(uri.toString()))
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let { obj ->
|
||||
track.total_chapters = obj["num_chapters"]!!.jsonPrimitive.int
|
||||
obj.jsonObject["my_list_status"]?.jsonObject?.let {
|
||||
parseMangaItem(it, track)
|
||||
with(json) {
|
||||
authClient.newCall(GET(uri.toString()))
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let { obj ->
|
||||
track.total_chapters = obj["num_chapters"]!!.jsonPrimitive.int
|
||||
obj.jsonObject["my_list_status"]?.jsonObject?.let {
|
||||
parseMangaItem(it, track)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -198,9 +218,11 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI
|
||||
.url(urlBuilder.build().toString())
|
||||
.get()
|
||||
.build()
|
||||
authClient.newCall(request)
|
||||
.awaitSuccess()
|
||||
.parseAs()
|
||||
with(json) {
|
||||
authClient.newCall(request)
|
||||
.awaitSuccess()
|
||||
.parseAs()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,16 @@
|
||||
package eu.kanade.tachiyomi.data.track.myanimelist
|
||||
|
||||
import eu.kanade.tachiyomi.network.parseAs
|
||||
import kotlinx.serialization.json.Json
|
||||
import okhttp3.Interceptor
|
||||
import okhttp3.Response
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.io.IOException
|
||||
|
||||
class MyAnimeListInterceptor(private val myanimelist: MyAnimeList, private var token: String?) : Interceptor {
|
||||
|
||||
private val json: Json by injectLazy()
|
||||
|
||||
private var oauth: OAuth? = null
|
||||
|
||||
override fun intercept(chain: Interceptor.Chain): Response {
|
||||
@ -69,7 +73,7 @@ class MyAnimeListInterceptor(private val myanimelist: MyAnimeList, private var t
|
||||
val oauthResponse = chain.proceed(MyAnimeListApi.refreshTokenRequest(oauth!!))
|
||||
|
||||
if (oauthResponse.isSuccessful) {
|
||||
oauthResponse.parseAs<OAuth>()
|
||||
with(json) { oauthResponse.parseAs<OAuth>() }
|
||||
} else {
|
||||
oauthResponse.close()
|
||||
null
|
||||
|
@ -9,6 +9,7 @@ import eu.kanade.tachiyomi.network.POST
|
||||
import eu.kanade.tachiyomi.network.awaitSuccess
|
||||
import eu.kanade.tachiyomi.network.jsonMime
|
||||
import eu.kanade.tachiyomi.network.parseAs
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonArray
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.buildJsonObject
|
||||
@ -24,9 +25,12 @@ import okhttp3.FormBody
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import tachiyomi.core.util.lang.withIOContext
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
||||
class ShikimoriApi(private val client: OkHttpClient, interceptor: ShikimoriInterceptor) {
|
||||
|
||||
private val json: Json by injectLazy()
|
||||
|
||||
private val authClient = client.newBuilder().addInterceptor(interceptor).build()
|
||||
|
||||
suspend fun addLibManga(track: Track, user_id: String): Track {
|
||||
@ -60,14 +64,16 @@ class ShikimoriApi(private val client: OkHttpClient, interceptor: ShikimoriInter
|
||||
.appendQueryParameter("search", search)
|
||||
.appendQueryParameter("limit", "20")
|
||||
.build()
|
||||
authClient.newCall(GET(url.toString()))
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonArray>()
|
||||
.let { response ->
|
||||
response.map {
|
||||
jsonToSearch(it.jsonObject)
|
||||
with(json) {
|
||||
authClient.newCall(GET(url.toString()))
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonArray>()
|
||||
.let { response ->
|
||||
response.map {
|
||||
jsonToSearch(it.jsonObject)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -81,7 +87,7 @@ class ShikimoriApi(private val client: OkHttpClient, interceptor: ShikimoriInter
|
||||
tracking_url = baseUrl + obj["url"]!!.jsonPrimitive.content
|
||||
publishing_status = obj["status"]!!.jsonPrimitive.content
|
||||
publishing_type = obj["kind"]!!.jsonPrimitive.content
|
||||
start_date = obj.get("aired_on")!!.jsonPrimitive.contentOrNull ?: ""
|
||||
start_date = obj["aired_on"]!!.jsonPrimitive.contentOrNull ?: ""
|
||||
}
|
||||
}
|
||||
|
||||
@ -102,44 +108,52 @@ class ShikimoriApi(private val client: OkHttpClient, interceptor: ShikimoriInter
|
||||
val urlMangas = "$apiUrl/mangas".toUri().buildUpon()
|
||||
.appendPath(track.media_id.toString())
|
||||
.build()
|
||||
val mangas = authClient.newCall(GET(urlMangas.toString()))
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
val mangas = with(json) {
|
||||
authClient.newCall(GET(urlMangas.toString()))
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
}
|
||||
|
||||
val url = "$apiUrl/v2/user_rates".toUri().buildUpon()
|
||||
.appendQueryParameter("user_id", user_id)
|
||||
.appendQueryParameter("target_id", track.media_id.toString())
|
||||
.appendQueryParameter("target_type", "Manga")
|
||||
.build()
|
||||
authClient.newCall(GET(url.toString()))
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonArray>()
|
||||
.let { response ->
|
||||
if (response.size > 1) {
|
||||
throw Exception("Too much mangas in response")
|
||||
with(json) {
|
||||
authClient.newCall(GET(url.toString()))
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonArray>()
|
||||
.let { response ->
|
||||
if (response.size > 1) {
|
||||
throw Exception("Too much mangas in response")
|
||||
}
|
||||
val entry = response.map {
|
||||
jsonToTrack(it.jsonObject, mangas)
|
||||
}
|
||||
entry.firstOrNull()
|
||||
}
|
||||
val entry = response.map {
|
||||
jsonToTrack(it.jsonObject, mangas)
|
||||
}
|
||||
entry.firstOrNull()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getCurrentUser(): Int {
|
||||
return authClient.newCall(GET("$apiUrl/users/whoami"))
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let {
|
||||
it["id"]!!.jsonPrimitive.int
|
||||
}
|
||||
return with(json) {
|
||||
authClient.newCall(GET("$apiUrl/users/whoami"))
|
||||
.awaitSuccess()
|
||||
.parseAs<JsonObject>()
|
||||
.let {
|
||||
it["id"]!!.jsonPrimitive.int
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun accessToken(code: String): OAuth {
|
||||
return withIOContext {
|
||||
client.newCall(accessTokenRequest(code))
|
||||
.awaitSuccess()
|
||||
.parseAs()
|
||||
with(json) {
|
||||
client.newCall(accessTokenRequest(code))
|
||||
.awaitSuccess()
|
||||
.parseAs()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -164,18 +178,12 @@ class ShikimoriApi(private val client: OkHttpClient, interceptor: ShikimoriInter
|
||||
private const val loginUrl = "$baseUrl/oauth/authorize"
|
||||
|
||||
private const val redirectUrl = "tachiyomi://shikimori-auth"
|
||||
private const val baseMangaUrl = "$apiUrl/mangas"
|
||||
|
||||
fun mangaUrl(remoteId: Int): String {
|
||||
return "$baseMangaUrl/$remoteId"
|
||||
}
|
||||
|
||||
fun authUrl() =
|
||||
loginUrl.toUri().buildUpon()
|
||||
.appendQueryParameter("client_id", clientId)
|
||||
.appendQueryParameter("redirect_uri", redirectUrl)
|
||||
.appendQueryParameter("response_type", "code")
|
||||
.build()
|
||||
fun authUrl() = loginUrl.toUri().buildUpon()
|
||||
.appendQueryParameter("client_id", clientId)
|
||||
.appendQueryParameter("redirect_uri", redirectUrl)
|
||||
.appendQueryParameter("response_type", "code")
|
||||
.build()
|
||||
|
||||
fun refreshTokenRequest(token: String) = POST(
|
||||
oauthUrl,
|
||||
|
@ -10,6 +10,7 @@ import eu.kanade.tachiyomi.network.NetworkHelper
|
||||
import eu.kanade.tachiyomi.network.PUT
|
||||
import eu.kanade.tachiyomi.network.awaitSuccess
|
||||
import eu.kanade.tachiyomi.network.parseAs
|
||||
import kotlinx.serialization.json.Json
|
||||
import okhttp3.Credentials
|
||||
import okhttp3.Dns
|
||||
import okhttp3.FormBody
|
||||
@ -23,11 +24,15 @@ import java.nio.charset.Charset
|
||||
import java.security.MessageDigest
|
||||
|
||||
class TachideskApi {
|
||||
private val network by injectLazy<NetworkHelper>()
|
||||
|
||||
private val network: NetworkHelper by injectLazy()
|
||||
private val json: Json by injectLazy()
|
||||
|
||||
val client: OkHttpClient =
|
||||
network.client.newBuilder()
|
||||
.dns(Dns.SYSTEM) // don't use DNS over HTTPS as it breaks IP addressing
|
||||
.build()
|
||||
|
||||
fun headersBuilder(): Headers.Builder = Headers.Builder().apply {
|
||||
if (basePassword.isNotEmpty() && baseLogin.isNotEmpty()) {
|
||||
val credentials = Credentials.basic(baseLogin, basePassword)
|
||||
@ -50,7 +55,11 @@ class TachideskApi {
|
||||
trackUrl
|
||||
}
|
||||
|
||||
val manga = client.newCall(GET("$url/full", headers)).awaitSuccess().parseAs<MangaDataClass>()
|
||||
val manga = with(json) {
|
||||
client.newCall(GET("$url/full", headers))
|
||||
.awaitSuccess()
|
||||
.parseAs<MangaDataClass>()
|
||||
}
|
||||
|
||||
TrackSearch.create(TrackManager.SUWAYOMI).apply {
|
||||
title = manga.title
|
||||
@ -70,7 +79,11 @@ class TachideskApi {
|
||||
|
||||
suspend fun updateProgress(track: Track): Track {
|
||||
val url = track.tracking_url
|
||||
val chapters = client.newCall(GET("$url/chapters", headers)).awaitSuccess().parseAs<List<ChapterDataClass>>()
|
||||
val chapters = with(json) {
|
||||
client.newCall(GET("$url/chapters", headers))
|
||||
.awaitSuccess()
|
||||
.parseAs<List<ChapterDataClass>>()
|
||||
}
|
||||
val lastChapterIndex = chapters.first { it.chapterNumber == track.last_chapter_read }.index
|
||||
|
||||
client.newCall(
|
||||
|
@ -7,6 +7,7 @@ import eu.kanade.tachiyomi.network.NetworkHelper
|
||||
import eu.kanade.tachiyomi.network.awaitSuccess
|
||||
import eu.kanade.tachiyomi.network.parseAs
|
||||
import eu.kanade.tachiyomi.util.system.isInstalledFromFDroid
|
||||
import kotlinx.serialization.json.Json
|
||||
import tachiyomi.core.preference.Preference
|
||||
import tachiyomi.core.preference.PreferenceStore
|
||||
import tachiyomi.core.util.lang.withIOContext
|
||||
@ -18,6 +19,8 @@ class AppUpdateChecker {
|
||||
|
||||
private val networkService: NetworkHelper by injectLazy()
|
||||
private val preferenceStore: PreferenceStore by injectLazy()
|
||||
private val json: Json by injectLazy()
|
||||
|
||||
private val lastAppCheck: Preference<Long> by lazy {
|
||||
preferenceStore.getLong("last_app_check", 0)
|
||||
}
|
||||
@ -29,24 +32,26 @@ class AppUpdateChecker {
|
||||
}
|
||||
|
||||
return withIOContext {
|
||||
val result = networkService.client
|
||||
.newCall(GET("https://api.github.com/repos/$GITHUB_REPO/releases/latest"))
|
||||
.awaitSuccess()
|
||||
.parseAs<GithubRelease>()
|
||||
.let {
|
||||
lastAppCheck.set(Date().time)
|
||||
val result = with(json) {
|
||||
networkService.client
|
||||
.newCall(GET("https://api.github.com/repos/$GITHUB_REPO/releases/latest"))
|
||||
.awaitSuccess()
|
||||
.parseAs<GithubRelease>()
|
||||
.let {
|
||||
lastAppCheck.set(Date().time)
|
||||
|
||||
// Check if latest version is different from current version
|
||||
if (isNewVersion(it.version)) {
|
||||
if (context.isInstalledFromFDroid()) {
|
||||
AppUpdateResult.NewUpdateFdroidInstallation
|
||||
// Check if latest version is different from current version
|
||||
if (isNewVersion(it.version)) {
|
||||
if (context.isInstalledFromFDroid()) {
|
||||
AppUpdateResult.NewUpdateFdroidInstallation
|
||||
} else {
|
||||
AppUpdateResult.NewUpdate(it)
|
||||
}
|
||||
} else {
|
||||
AppUpdateResult.NewUpdate(it)
|
||||
AppUpdateResult.NoNewUpdate
|
||||
}
|
||||
} else {
|
||||
AppUpdateResult.NoNewUpdate
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
when (result) {
|
||||
is AppUpdateResult.NewUpdate -> AppUpdateNotifier(context).promptUpdate(result.release)
|
||||
|
@ -11,6 +11,7 @@ import eu.kanade.tachiyomi.network.NetworkHelper
|
||||
import eu.kanade.tachiyomi.network.awaitSuccess
|
||||
import eu.kanade.tachiyomi.network.parseAs
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.Json
|
||||
import logcat.LogPriority
|
||||
import tachiyomi.core.preference.Preference
|
||||
import tachiyomi.core.preference.PreferenceStore
|
||||
@ -24,10 +25,12 @@ internal class ExtensionGithubApi {
|
||||
|
||||
private val networkService: NetworkHelper by injectLazy()
|
||||
private val preferenceStore: PreferenceStore by injectLazy()
|
||||
private val extensionManager: ExtensionManager by injectLazy()
|
||||
private val json: Json by injectLazy()
|
||||
|
||||
private val lastExtCheck: Preference<Long> by lazy {
|
||||
preferenceStore.getLong("last_ext_check", 0)
|
||||
}
|
||||
private val extensionManager: ExtensionManager by injectLazy()
|
||||
|
||||
private var requiresFallbackSource = false
|
||||
|
||||
@ -53,9 +56,11 @@ internal class ExtensionGithubApi {
|
||||
.awaitSuccess()
|
||||
}
|
||||
|
||||
val extensions = response
|
||||
.parseAs<List<ExtensionJsonObject>>()
|
||||
.toExtensions()
|
||||
val extensions = with(json) {
|
||||
response
|
||||
.parseAs<List<ExtensionJsonObject>>()
|
||||
.toExtensions()
|
||||
}
|
||||
|
||||
// Sanity check - a small number of extensions probably means something broke
|
||||
// with the repo generator
|
||||
|
@ -120,7 +120,7 @@ class ExtensionDetailsScreenModel(
|
||||
|
||||
val cleared = urls.sumOf {
|
||||
try {
|
||||
network.cookieManager.remove(it.toHttpUrl())
|
||||
network.cookieJar.remove(it.toHttpUrl())
|
||||
} catch (e: Exception) {
|
||||
logcat(LogPriority.ERROR, e) { "Failed to clear cookies for $it" }
|
||||
0
|
||||
|
@ -92,7 +92,7 @@ class WebViewActivity : BaseActivity() {
|
||||
}
|
||||
|
||||
private fun clearCookies(url: String) {
|
||||
val cleared = network.cookieManager.remove(url.toHttpUrl())
|
||||
val cleared = network.cookieJar.remove(url.toHttpUrl())
|
||||
logcat { "Cleared $cleared cookies for: $url" }
|
||||
}
|
||||
|
||||
|
@ -47,7 +47,7 @@ class WebViewScreenModel(
|
||||
}
|
||||
|
||||
fun clearCookies(url: String) {
|
||||
val cleared = network.cookieManager.remove(url.toHttpUrl())
|
||||
val cleared = network.cookieJar.remove(url.toHttpUrl())
|
||||
logcat { "Cleared $cleared cookies for: $url" }
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user