mirror of
https://github.com/Suwayomi/Suwayomi-Server.git
synced 2026-07-04 03:14:40 -05:00
Merge branch 'master' into protobuf
This commit is contained in:
@@ -1,5 +0,0 @@
|
|||||||
package kotlinx.coroutines.experimental.android
|
|
||||||
|
|
||||||
import kotlinx.coroutines.GlobalScope
|
|
||||||
|
|
||||||
val UI = GlobalScope.coroutineContext
|
|
||||||
@@ -4,11 +4,21 @@ import java.io.InputStream
|
|||||||
import java.io.Reader
|
import java.io.Reader
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.sql.*
|
|
||||||
import java.sql.Array
|
import java.sql.Array
|
||||||
|
import java.sql.Blob
|
||||||
|
import java.sql.Clob
|
||||||
import java.sql.Date
|
import java.sql.Date
|
||||||
import java.util.*
|
import java.sql.NClob
|
||||||
|
import java.sql.Ref
|
||||||
|
import java.sql.ResultSet
|
||||||
|
import java.sql.ResultSetMetaData
|
||||||
|
import java.sql.RowId
|
||||||
|
import java.sql.SQLXML
|
||||||
|
import java.sql.Time
|
||||||
|
import java.sql.Timestamp
|
||||||
|
import java.util.Calendar
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
class ScrollableResultSet(val parent: ResultSet) : ResultSet by parent {
|
class ScrollableResultSet(val parent: ResultSet) : ResultSet by parent {
|
||||||
|
|
||||||
private val cachedContent = mutableListOf<ResultSetEntry>()
|
private val cachedContent = mutableListOf<ResultSetEntry>()
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ class ServiceSupport {
|
|||||||
|
|
||||||
private val logger = KotlinLogging.logger {}
|
private val logger = KotlinLogging.logger {}
|
||||||
|
|
||||||
fun startService(context: Context, intent: Intent) {
|
fun startService(@Suppress("UNUSED_PARAMETER") context: Context, intent: Intent) {
|
||||||
val name = intentToClassName(intent)
|
val name = intentToClassName(intent)
|
||||||
|
|
||||||
logger.debug { "Starting service: $name" }
|
logger.debug { "Starting service: $name" }
|
||||||
@@ -35,7 +35,7 @@ class ServiceSupport {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun stopService(context: Context, intent: Intent) {
|
fun stopService(@Suppress("UNUSED_PARAMETER") context: Context, intent: Intent) {
|
||||||
val name = intentToClassName(intent)
|
val name = intentToClassName(intent)
|
||||||
stopService(name)
|
stopService(name)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ object KodeinGlobalHelper {
|
|||||||
* Get a dependency
|
* Get a dependency
|
||||||
*/
|
*/
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
fun <T : Any> instance(type: Class<T>, kodein: DI? = null): T {
|
fun <T : Any> instance(type: Class<T>, kodein: DI? = null): T {
|
||||||
return when(type) {
|
return when(type) {
|
||||||
AndroidFiles::class.java -> {
|
AndroidFiles::class.java -> {
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
kotlin("jvm") version "1.4.32"
|
val kotlinVersion = "1.5.21"
|
||||||
kotlin("plugin.serialization") version "1.4.32" apply false
|
|
||||||
|
kotlin("jvm") version kotlinVersion
|
||||||
|
kotlin("plugin.serialization") version kotlinVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
@@ -46,12 +48,12 @@ configure(projects) {
|
|||||||
testImplementation(kotlin("test-junit5"))
|
testImplementation(kotlin("test-junit5"))
|
||||||
|
|
||||||
// coroutines
|
// coroutines
|
||||||
val coroutinesVersion = "1.4.3"
|
val coroutinesVersion = "1.5.0"
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion")
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion")
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:$coroutinesVersion")
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:$coroutinesVersion")
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutinesVersion")
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutinesVersion")
|
||||||
|
|
||||||
val kotlinSerializationVersion = "1.1.0"
|
val kotlinSerializationVersion = "1.2.1"
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$kotlinSerializationVersion")
|
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$kotlinSerializationVersion")
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-protobuf:$kotlinSerializationVersion")
|
implementation("org.jetbrains.kotlinx:kotlinx-serialization-protobuf:$kotlinSerializationVersion")
|
||||||
|
|
||||||
@@ -80,6 +82,7 @@ configure(projects) {
|
|||||||
implementation("net.harawata:appdirs:1.2.1")
|
implementation("net.harawata:appdirs:1.2.1")
|
||||||
|
|
||||||
// dex2jar: https://github.com/DexPatcher/dex2jar/releases/tag/v2.1-20190905-lanchon
|
// dex2jar: https://github.com/DexPatcher/dex2jar/releases/tag/v2.1-20190905-lanchon
|
||||||
|
// note: watch https://github.com/ThexXTURBOXx/dex2jar for future development
|
||||||
implementation("com.github.DexPatcher.dex2jar:dex-tools:v2.1-20190905-lanchon")
|
implementation("com.github.DexPatcher.dex2jar:dex-tools:v2.1-20190905-lanchon")
|
||||||
|
|
||||||
// APK parser
|
// APK parser
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ plugins {
|
|||||||
application
|
application
|
||||||
id("com.github.johnrengelman.shadow") version "7.0.0"
|
id("com.github.johnrengelman.shadow") version "7.0.0"
|
||||||
id("org.jmailen.kotlinter") version "3.4.3"
|
id("org.jmailen.kotlinter") version "3.4.3"
|
||||||
id("de.fuerstenau.buildconfig") version "1.1.8"
|
id("com.github.gmazzo.buildconfig") version "3.0.2"
|
||||||
}
|
}
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
@@ -128,23 +128,29 @@ val tachideskRevision = runCatching {
|
|||||||
}.getOrDefault("r0")
|
}.getOrDefault("r0")
|
||||||
|
|
||||||
buildConfig {
|
buildConfig {
|
||||||
clsName = "BuildConfig"
|
className("BuildConfig")
|
||||||
packageName = "suwayomi.tachidesk.server"
|
packageName("suwayomi.tachidesk.server")
|
||||||
|
|
||||||
|
useKotlinOutput()
|
||||||
|
|
||||||
|
|
||||||
buildConfigField("String", "NAME", rootProject.name)
|
fun str(obj: Any): String {
|
||||||
buildConfigField("String", "VERSION", tachideskVersion)
|
return "\"${obj}\""
|
||||||
buildConfigField("String", "REVISION", tachideskRevision)
|
}
|
||||||
buildConfigField("String", "BUILD_TYPE", if (System.getenv("ProductBuildType") == "Stable") "Stable" else "Preview")
|
|
||||||
|
buildConfigField("String", "NAME", str(rootProject.name))
|
||||||
|
buildConfigField("String", "VERSION", str(tachideskVersion))
|
||||||
|
buildConfigField("String", "REVISION", str(tachideskRevision))
|
||||||
|
buildConfigField("String", "BUILD_TYPE", str(if (System.getenv("ProductBuildType") == "Stable") "Stable" else "Preview"))
|
||||||
buildConfigField("long", "BUILD_TIME", Instant.now().epochSecond.toString())
|
buildConfigField("long", "BUILD_TIME", Instant.now().epochSecond.toString())
|
||||||
|
|
||||||
|
|
||||||
buildConfigField("String", "WEBUI_REPO", "https://github.com/Suwayomi/Tachidesk-WebUI-preview")
|
buildConfigField("String", "WEBUI_REPO", str("https://github.com/Suwayomi/Tachidesk-WebUI-preview"))
|
||||||
buildConfigField("String", "WEBUI_TAG", webUIRevisionTag)
|
buildConfigField("String", "WEBUI_TAG", str(webUIRevisionTag))
|
||||||
|
|
||||||
|
|
||||||
buildConfigField("String", "GITHUB", "https://github.com/Suwayomi/Tachidesk")
|
buildConfigField("String", "GITHUB", str("https://github.com/Suwayomi/Tachidesk"))
|
||||||
buildConfigField("String", "DISCORD", "https://discord.gg/DDZdqZWaHA")
|
buildConfigField("String", "DISCORD", str("https://discord.gg/DDZdqZWaHA"))
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks {
|
tasks {
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ abstract class AnimeHttpSource : AnimeCatalogueSource {
|
|||||||
* Note the generated id sets the sign bit to 0.
|
* Note the generated id sets the sign bit to 0.
|
||||||
*/
|
*/
|
||||||
override val id by lazy {
|
override val id by lazy {
|
||||||
val key = "${name.toLowerCase()}/$lang/$versionId"
|
val key = "${name.lowercase()}/$lang/$versionId"
|
||||||
val bytes = MessageDigest.getInstance("MD5").digest(key.toByteArray())
|
val bytes = MessageDigest.getInstance("MD5").digest(key.toByteArray())
|
||||||
(0..7).map { bytes[it].toLong() and 0xff shl 8 * (7 - it) }.reduce(Long::or) and Long.MAX_VALUE
|
(0..7).map { bytes[it].toLong() and 0xff shl 8 * (7 - it) }.reduce(Long::or) and Long.MAX_VALUE
|
||||||
}
|
}
|
||||||
@@ -80,7 +80,7 @@ abstract class AnimeHttpSource : AnimeCatalogueSource {
|
|||||||
/**
|
/**
|
||||||
* Visible name of the source.
|
* Visible name of the source.
|
||||||
*/
|
*/
|
||||||
override fun toString() = "$name (${lang.toUpperCase()})"
|
override fun toString() = "$name (${lang.uppercase()})"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an observable containing a page with a list of anime. Normally it's not needed to
|
* Returns an observable containing a page with a list of anime. Normally it's not needed to
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import okhttp3.OkHttpClient
|
|||||||
// import uy.kohesive.injekt.injectLazy
|
// import uy.kohesive.injekt.injectLazy
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
@Suppress("UNUSED_PARAMETER")
|
||||||
class NetworkHelper(context: Context) {
|
class NetworkHelper(context: Context) {
|
||||||
|
|
||||||
// private val preferences: PreferencesHelper by injectLazy()
|
// private val preferences: PreferencesHelper by injectLazy()
|
||||||
|
|||||||
@@ -110,6 +110,7 @@ fun Call.asObservableSuccess(): Observable<Response> {
|
|||||||
// return progressClient.newCall(request)
|
// return progressClient.newCall(request)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
@Suppress("UNUSED_PARAMETER")
|
||||||
fun OkHttpClient.newCallWithProgress(request: Request, listener: ProgressListener): Call {
|
fun OkHttpClient.newCallWithProgress(request: Request, listener: ProgressListener): Call {
|
||||||
val progressClient = newBuilder()
|
val progressClient = newBuilder()
|
||||||
// .cache(null)
|
// .cache(null)
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ abstract class HttpSource : CatalogueSource {
|
|||||||
* Note the generated id sets the sign bit to 0.
|
* Note the generated id sets the sign bit to 0.
|
||||||
*/
|
*/
|
||||||
override val id by lazy {
|
override val id by lazy {
|
||||||
val key = "${name.toLowerCase()}/$lang/$versionId"
|
val key = "${name.lowercase()}/$lang/$versionId"
|
||||||
val bytes = MessageDigest.getInstance("MD5").digest(key.toByteArray())
|
val bytes = MessageDigest.getInstance("MD5").digest(key.toByteArray())
|
||||||
(0..7).map { bytes[it].toLong() and 0xff shl 8 * (7 - it) }.reduce(Long::or) and Long.MAX_VALUE
|
(0..7).map { bytes[it].toLong() and 0xff shl 8 * (7 - it) }.reduce(Long::or) and Long.MAX_VALUE
|
||||||
}
|
}
|
||||||
@@ -81,7 +81,7 @@ abstract class HttpSource : CatalogueSource {
|
|||||||
/**
|
/**
|
||||||
* Visible name of the source.
|
* Visible name of the source.
|
||||||
*/
|
*/
|
||||||
override fun toString() = "$name (${lang.toUpperCase()})"
|
override fun toString() = "$name (${lang.uppercase()})"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an observable containing a page with a list of manga. Normally it's not needed to
|
* Returns an observable containing a page with a list of manga. Normally it's not needed to
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ package suwayomi.tachidesk.manga
|
|||||||
* 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 io.javalin.Javalin
|
|
||||||
import io.javalin.apibuilder.ApiBuilder.delete
|
import io.javalin.apibuilder.ApiBuilder.delete
|
||||||
import io.javalin.apibuilder.ApiBuilder.get
|
import io.javalin.apibuilder.ApiBuilder.get
|
||||||
import io.javalin.apibuilder.ApiBuilder.patch
|
import io.javalin.apibuilder.ApiBuilder.patch
|
||||||
@@ -22,7 +21,7 @@ import suwayomi.tachidesk.manga.controller.MangaController
|
|||||||
import suwayomi.tachidesk.manga.controller.SourceController
|
import suwayomi.tachidesk.manga.controller.SourceController
|
||||||
|
|
||||||
object MangaAPI {
|
object MangaAPI {
|
||||||
fun defineEndpoints(app: Javalin) {
|
fun defineEndpoints() {
|
||||||
path("extension") {
|
path("extension") {
|
||||||
get("list", ExtensionController::list)
|
get("list", ExtensionController::list)
|
||||||
|
|
||||||
@@ -82,7 +81,7 @@ object MangaAPI {
|
|||||||
patch(":categoryId", LibraryController::categoryModify)
|
patch(":categoryId", LibraryController::categoryModify)
|
||||||
delete(":categoryId", LibraryController::categoryDelete)
|
delete(":categoryId", LibraryController::categoryDelete)
|
||||||
|
|
||||||
patch(":categoryId/reorder", LibraryController::categoryReorder)
|
patch(":categoryId/reorder", LibraryController::categoryReorder) // TODO: the underlying code doesn't need `:categoryId`, remove it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -54,10 +54,9 @@ object LibraryController {
|
|||||||
|
|
||||||
/** category re-ordering */
|
/** category re-ordering */
|
||||||
fun categoryReorder(ctx: Context) {
|
fun categoryReorder(ctx: Context) {
|
||||||
val categoryId = ctx.pathParam("categoryId").toInt()
|
|
||||||
val from = ctx.formParam("from")!!.toInt()
|
val from = ctx.formParam("from")!!.toInt()
|
||||||
val to = ctx.formParam("to")!!.toInt()
|
val to = ctx.formParam("to")!!.toInt()
|
||||||
Category.reorderCategory(categoryId, from, to)
|
Category.reorderCategory(from, to)
|
||||||
ctx.status(200)
|
ctx.status(200)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ object Category {
|
|||||||
/**
|
/**
|
||||||
* Move the category from position `from` to `to`
|
* Move the category from position `from` to `to`
|
||||||
*/
|
*/
|
||||||
fun reorderCategory(categoryId: Int, from: Int, to: Int) {
|
fun reorderCategory(from: Int, to: Int) {
|
||||||
transaction {
|
transaction {
|
||||||
val categories = CategoryTable.selectAll().orderBy(CategoryTable.order to SortOrder.ASC).toMutableList()
|
val categories = CategoryTable.selectAll().orderBy(CategoryTable.order to SortOrder.ASC).toMutableList()
|
||||||
categories.add(to - 1, categories.removeAt(from - 1))
|
categories.add(to - 1, categories.removeAt(from - 1))
|
||||||
|
|||||||
@@ -20,15 +20,18 @@ object Search {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
|
@Suppress("UNUSED_PARAMETER", "UNUSED_VARIABLE")
|
||||||
fun sourceFilters(sourceId: Long) {
|
fun sourceFilters(sourceId: Long) {
|
||||||
val source = getHttpSource(sourceId)
|
val source = getHttpSource(sourceId)
|
||||||
// source.getFilterList().toItems()
|
// source.getFilterList().toItems()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("UNUSED_PARAMETER")
|
||||||
fun sourceGlobalSearch(searchTerm: String) {
|
fun sourceGlobalSearch(searchTerm: String) {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
data class FilterWrapper(
|
data class FilterWrapper(
|
||||||
val type: String,
|
val type: String,
|
||||||
val filter: Any
|
val filter: Any
|
||||||
|
|||||||
@@ -141,6 +141,7 @@ object LegacyBackupImport : LegacyBackupBase() {
|
|||||||
* @param history history data from json
|
* @param history history data from json
|
||||||
* @param tracks tracking data from json
|
* @param tracks tracking data from json
|
||||||
*/
|
*/
|
||||||
|
@Suppress("UNUSED_PARAMETER")
|
||||||
private suspend fun restoreMangaData(
|
private suspend fun restoreMangaData(
|
||||||
manga: Manga,
|
manga: Manga,
|
||||||
source: Source,
|
source: Source,
|
||||||
@@ -204,6 +205,7 @@ object LegacyBackupImport : LegacyBackupBase() {
|
|||||||
return fetchedManga
|
return fetchedManga
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("UNUSED_PARAMETER") // TODO: remove this suppress when update Chapters is written
|
||||||
private fun updateChapters(source: Source, fetchedManga: SManga, chapters: List<Chapter>) {
|
private fun updateChapters(source: Source, fetchedManga: SManga, chapters: List<Chapter>) {
|
||||||
// TODO("Not yet implemented")
|
// TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,11 +42,11 @@ object LegacyBackupValidator {
|
|||||||
.sorted()
|
.sorted()
|
||||||
}
|
}
|
||||||
|
|
||||||
val trackers = mangas
|
// val trackers = mangas
|
||||||
.filter { it.asJsonObject.has("track") }
|
// .filter { it.asJsonObject.has("track") }
|
||||||
.flatMap { it.asJsonObject["track"].asJsonArray }
|
// .flatMap { it.asJsonObject["track"].asJsonArray }
|
||||||
.map { it.asJsonObject["s"].asInt }
|
// .map { it.asJsonObject["s"].asInt }
|
||||||
.distinct()
|
// .distinct()
|
||||||
|
|
||||||
val missingTrackers = listOf("")
|
val missingTrackers = listOf("")
|
||||||
// val missingTrackers = trackers
|
// val missingTrackers = trackers
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ object BytecodeEditor {
|
|||||||
bytes[2],
|
bytes[2],
|
||||||
bytes[3]
|
bytes[3]
|
||||||
)
|
)
|
||||||
if (cafebabe.toLowerCase() != "cafebabe") {
|
if (cafebabe.lowercase() != "cafebabe") {
|
||||||
// Corrupted class
|
// Corrupted class
|
||||||
return@use null
|
return@use null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ object JavalinSetup {
|
|||||||
app.routes {
|
app.routes {
|
||||||
path("api/v1/") {
|
path("api/v1/") {
|
||||||
GlobalAPI.defineEndpoints()
|
GlobalAPI.defineEndpoints()
|
||||||
MangaAPI.defineEndpoints(app)
|
MangaAPI.defineEndpoints()
|
||||||
AnimeAPI.defineEndpoints(app) // TODO: migrate Anime endpoints
|
AnimeAPI.defineEndpoints(app) // TODO: migrate Anime endpoints
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ class TestExtensions {
|
|||||||
sources = getSourceList().map { getHttpSource(it.id.toLong()) }
|
sources = getSourceList().map { getHttpSource(it.id.toLong()) }
|
||||||
}
|
}
|
||||||
setLoggingEnabled(true)
|
setLoggingEnabled(true)
|
||||||
File("tmp/TestDesk/sources.txt").writeText(sources.joinToString("\n") { "${it.name} - ${it.lang.toUpperCase()} - ${it.id}" })
|
File("tmp/TestDesk/sources.txt").writeText(sources.joinToString("\n") { "${it.name} - ${it.lang.uppercase()} - ${it.id}" })
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -99,7 +99,7 @@ class TestExtensions {
|
|||||||
}.awaitAll()
|
}.awaitAll()
|
||||||
File("tmp/TestDesk/failedToFetch.txt").writeText(
|
File("tmp/TestDesk/failedToFetch.txt").writeText(
|
||||||
failedToFetch.joinToString("\n") { (source, exception) ->
|
failedToFetch.joinToString("\n") { (source, exception) ->
|
||||||
"${source.name} (${source.lang.toUpperCase()}, ${source.id}):" +
|
"${source.name} (${source.lang.uppercase()}, ${source.id}):" +
|
||||||
" ${exception.message}"
|
" ${exception.message}"
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user