diff --git a/AndroidCompat/Config/build.gradle.kts b/AndroidCompat/Config/build.gradle.kts index 18bea3c7..23cda812 100644 --- a/AndroidCompat/Config/build.gradle.kts +++ b/AndroidCompat/Config/build.gradle.kts @@ -1,7 +1,19 @@ plugins { - id(libs.plugins.kotlin.jvm.get().pluginId) - id(libs.plugins.kotlin.serialization.get().pluginId) - id(libs.plugins.ktlint.get().pluginId) + id( + libs.plugins.kotlin.jvm + .get() + .pluginId, + ) + id( + libs.plugins.kotlin.serialization + .get() + .pluginId, + ) + id( + libs.plugins.ktlint + .get() + .pluginId, + ) } dependencies { diff --git a/AndroidCompat/Config/src/main/java/xyz/nulldev/ts/config/ConfigManager.kt b/AndroidCompat/Config/src/main/java/xyz/nulldev/ts/config/ConfigManager.kt index 51877854..3180386f 100644 --- a/AndroidCompat/Config/src/main/java/xyz/nulldev/ts/config/ConfigManager.kt +++ b/AndroidCompat/Config/src/main/java/xyz/nulldev/ts/config/ConfigManager.kt @@ -47,11 +47,10 @@ open class ConfigManager { @Suppress("UNCHECKED_CAST") fun module(type: Class): T = loadedModules[type] as T - private fun getUserConfig(): Config { - return userConfigFile.let { + private fun getUserConfig(): Config = + userConfigFile.let { ConfigFactory.parseFile(it) } - } /** * Load configs @@ -72,7 +71,8 @@ open class ConfigManager { val userConfig = getUserConfig() val config = - ConfigFactory.empty() + ConfigFactory + .empty() .withFallback(baseConfig) .withFallback(userConfig) .withFallback(compatConfig) @@ -153,11 +153,13 @@ open class ConfigManager { } var newUserConfigDoc: ConfigDocument = resetUserConfig(false) - userConfig.entrySet().filter { - serverConfig.hasPath( - it.key, - ) - }.forEach { newUserConfigDoc = newUserConfigDoc.withValue(it.key, it.value) } + userConfig + .entrySet() + .filter { + serverConfig.hasPath( + it.key, + ) + }.forEach { newUserConfigDoc = newUserConfigDoc.withValue(it.key, it.value) } userConfigFile.writeText(newUserConfigDoc.render()) } diff --git a/AndroidCompat/Config/src/main/java/xyz/nulldev/ts/config/ConfigModule.kt b/AndroidCompat/Config/src/main/java/xyz/nulldev/ts/config/ConfigModule.kt index 61d82277..d569bbf1 100644 --- a/AndroidCompat/Config/src/main/java/xyz/nulldev/ts/config/ConfigModule.kt +++ b/AndroidCompat/Config/src/main/java/xyz/nulldev/ts/config/ConfigModule.kt @@ -17,17 +17,25 @@ import kotlin.reflect.KProperty * Abstract config module. */ @Suppress("UNUSED_PARAMETER") -abstract class ConfigModule(getConfig: () -> Config) +abstract class ConfigModule( + getConfig: () -> Config, +) /** * Abstract jvm-commandline-argument-overridable config module. */ -abstract class SystemPropertyOverridableConfigModule(getConfig: () -> Config, moduleName: String) : ConfigModule(getConfig) { +abstract class SystemPropertyOverridableConfigModule( + getConfig: () -> Config, + moduleName: String, +) : ConfigModule(getConfig) { val overridableConfig = SystemPropertyOverrideDelegate(getConfig, moduleName) } /** Defines a config property that is overridable with jvm `-D` commandline arguments prefixed with [CONFIG_PREFIX] */ -class SystemPropertyOverrideDelegate(val getConfig: () -> Config, val moduleName: String) { +class SystemPropertyOverrideDelegate( + val getConfig: () -> Config, + val moduleName: String, +) { inline operator fun getValue( thisRef: R, property: KProperty<*>, diff --git a/AndroidCompat/Config/src/main/java/xyz/nulldev/ts/config/Logging.kt b/AndroidCompat/Config/src/main/java/xyz/nulldev/ts/config/Logging.kt index 7325c4a5..01bb4d52 100644 --- a/AndroidCompat/Config/src/main/java/xyz/nulldev/ts/config/Logging.kt +++ b/AndroidCompat/Config/src/main/java/xyz/nulldev/ts/config/Logging.kt @@ -22,13 +22,12 @@ import org.slf4j.LoggerFactory private fun fileSizeValueOfOrDefault( fileSizeStr: String, default: String, -): FileSize { - return try { +): FileSize = + try { FileSize.valueOf(fileSizeStr) } catch (e: IllegalArgumentException) { FileSize.valueOf(default) } -} private const val FILE_APPENDER_NAME = "SuwayomiDefaultAppender" @@ -73,9 +72,8 @@ private fun createRollingFileAppender( return appender } -private fun getBaseLogger(): ch.qos.logback.classic.Logger { - return (KotlinLogging.logger(Logger.ROOT_LOGGER_NAME).underlyingLogger as ch.qos.logback.classic.Logger) -} +private fun getBaseLogger(): ch.qos.logback.classic.Logger = + (KotlinLogging.logger(Logger.ROOT_LOGGER_NAME).underlyingLogger as ch.qos.logback.classic.Logger) private fun getLogger(name: String): ch.qos.logback.classic.Logger { val context = LoggerFactory.getILoggerFactory() as LoggerContext diff --git a/AndroidCompat/build.gradle.kts b/AndroidCompat/build.gradle.kts index d6d392e4..590285c9 100644 --- a/AndroidCompat/build.gradle.kts +++ b/AndroidCompat/build.gradle.kts @@ -1,7 +1,19 @@ plugins { - id(libs.plugins.kotlin.jvm.get().pluginId) - id(libs.plugins.kotlin.serialization.get().pluginId) - id(libs.plugins.ktlint.get().pluginId) + id( + libs.plugins.kotlin.jvm + .get() + .pluginId, + ) + id( + libs.plugins.kotlin.serialization + .get() + .pluginId, + ) + id( + libs.plugins.ktlint + .get() + .pluginId, + ) } dependencies { diff --git a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/config/ApplicationInfoConfigModule.kt b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/config/ApplicationInfoConfigModule.kt index 1ec0d09d..aff7e702 100644 --- a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/config/ApplicationInfoConfigModule.kt +++ b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/config/ApplicationInfoConfigModule.kt @@ -8,7 +8,9 @@ import xyz.nulldev.ts.config.ConfigModule * Application info config. */ -class ApplicationInfoConfigModule(getConfig: () -> Config) : ConfigModule(getConfig) { +class ApplicationInfoConfigModule( + getConfig: () -> Config, +) : ConfigModule(getConfig) { val packageName: String by getConfig() val debug: Boolean by getConfig() diff --git a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/config/FilesConfigModule.kt b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/config/FilesConfigModule.kt index dca29751..f3d08be7 100644 --- a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/config/FilesConfigModule.kt +++ b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/config/FilesConfigModule.kt @@ -8,7 +8,9 @@ import xyz.nulldev.ts.config.ConfigModule * Files configuration modules. Specifies where to store the Android files. */ -class FilesConfigModule(getConfig: () -> Config) : ConfigModule(getConfig) { +class FilesConfigModule( + getConfig: () -> Config, +) : ConfigModule(getConfig) { val dataDir: String by getConfig() val filesDir: String by getConfig() val noBackupFilesDir: String by getConfig() diff --git a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/config/SystemConfigModule.kt b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/config/SystemConfigModule.kt index e7d04172..20531053 100644 --- a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/config/SystemConfigModule.kt +++ b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/config/SystemConfigModule.kt @@ -4,7 +4,9 @@ import com.typesafe.config.Config import io.github.config4k.getValue import xyz.nulldev.ts.config.ConfigModule -class SystemConfigModule(val getConfig: () -> Config) : ConfigModule(getConfig) { +class SystemConfigModule( + val getConfig: () -> Config, +) : ConfigModule(getConfig) { val isDebuggable: Boolean by getConfig() val propertyPrefix = "properties." diff --git a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/db/ScrollableResultSet.kt b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/db/ScrollableResultSet.kt index 62ae95ab..25d20276 100644 --- a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/db/ScrollableResultSet.kt +++ b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/db/ScrollableResultSet.kt @@ -19,7 +19,9 @@ 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() private val columnCache = mutableMapOf() private var lastReturnWasNull = false @@ -29,9 +31,10 @@ class ScrollableResultSet(val parent: ResultSet) : ResultSet by parent { val parentMetadata = parent.metaData val columnCount = parentMetadata.columnCount val columnLabels = - (1..columnCount).map { - parentMetadata.getColumnLabel(it) - }.toTypedArray() + (1..columnCount) + .map { + parentMetadata.getColumnLabel(it) + }.toTypedArray() init { val columnCount = columnCount @@ -45,20 +48,17 @@ class ScrollableResultSet(val parent: ResultSet) : ResultSet by parent { while (parent.next()) { cachedContent += ResultSetEntry().apply { - for (i in 1..columnCount) + for (i in 1..columnCount) { data += parent.getObject(i) + } } resultSetLength++ } } - private fun notImplemented(): Nothing { - throw UnsupportedOperationException("This class currently does not support this operation!") - } + private fun notImplemented(): Nothing = throw UnsupportedOperationException("This class currently does not support this operation!") - private fun cursorValid(): Boolean { - return isAfterLast || isBeforeFirst - } + private fun cursorValid(): Boolean = isAfterLast || isBeforeFirst private fun internalMove(row: Int) { if (cursor < 0) { @@ -76,22 +76,16 @@ class ScrollableResultSet(val parent: ResultSet) : ResultSet by parent { return obj } - private fun obj(column: String?): Any? { - return obj(cachedFindColumn(column)) - } + private fun obj(column: String?): Any? = obj(cachedFindColumn(column)) private fun cachedFindColumn(column: String?) = columnCache.getOrPut(column!!, { findColumn(column) }) - override fun getNClob(columnIndex: Int): NClob { - return obj(columnIndex) as NClob - } + override fun getNClob(columnIndex: Int): NClob = obj(columnIndex) as NClob - override fun getNClob(columnLabel: String?): NClob { - return obj(columnLabel) as NClob - } + override fun getNClob(columnLabel: String?): NClob = obj(columnLabel) as NClob override fun updateNString( columnIndex: Int, @@ -260,17 +254,11 @@ class ScrollableResultSet(val parent: ResultSet) : ResultSet by parent { notImplemented() } - override fun getBoolean(columnIndex: Int): Boolean { - return obj(columnIndex) as Boolean - } + override fun getBoolean(columnIndex: Int): Boolean = obj(columnIndex) as Boolean - override fun getBoolean(columnLabel: String?): Boolean { - return obj(columnLabel) as Boolean - } + override fun getBoolean(columnLabel: String?): Boolean = obj(columnLabel) as Boolean - override fun isFirst(): Boolean { - return cursor - 1 < resultSetLength - } + override fun isFirst(): Boolean = cursor - 1 < resultSetLength override fun getBigDecimal( columnIndex: Int, @@ -288,13 +276,9 @@ class ScrollableResultSet(val parent: ResultSet) : ResultSet by parent { notImplemented() } - override fun getBigDecimal(columnIndex: Int): BigDecimal { - return obj(columnIndex) as BigDecimal - } + override fun getBigDecimal(columnIndex: Int): BigDecimal = obj(columnIndex) as BigDecimal - override fun getBigDecimal(columnLabel: String?): BigDecimal { - return obj(columnLabel) as BigDecimal - } + override fun getBigDecimal(columnLabel: String?): BigDecimal = obj(columnLabel) as BigDecimal override fun updateBytes( columnIndex: Int, @@ -310,9 +294,7 @@ class ScrollableResultSet(val parent: ResultSet) : ResultSet by parent { notImplemented() } - override fun isLast(): Boolean { - return cursor == resultSetLength - } + override fun isLast(): Boolean = cursor == resultSetLength override fun insertRow() { notImplemented() @@ -351,9 +333,7 @@ class ScrollableResultSet(val parent: ResultSet) : ResultSet by parent { return cursorValid() } - override fun isAfterLast(): Boolean { - return cursor > resultSetLength - } + override fun isAfterLast(): Boolean = cursor > resultSetLength override fun relative(rows: Int): Boolean { internalMove(cursor + rows) @@ -365,8 +345,9 @@ class ScrollableResultSet(val parent: ResultSet) : ResultSet by parent { internalMove(row) } else { last() - for (i in 1..row) + for (i in 1..row) { previous() + } } return cursorValid() } @@ -394,19 +375,13 @@ class ScrollableResultSet(val parent: ResultSet) : ResultSet by parent { return cursorValid() } - override fun getFloat(columnIndex: Int): Float { - return obj(columnIndex) as Float - } + override fun getFloat(columnIndex: Int): Float = obj(columnIndex) as Float - override fun getFloat(columnLabel: String?): Float { - return obj(columnLabel) as Float - } + override fun getFloat(columnLabel: String?): Float = obj(columnLabel) as Float override fun wasNull() = lastReturnWasNull - override fun getRow(): Int { - return cursor - } + override fun getRow(): Int = cursor override fun first(): Boolean { internalMove(1) @@ -459,13 +434,9 @@ class ScrollableResultSet(val parent: ResultSet) : ResultSet by parent { notImplemented() } - override fun getURL(columnIndex: Int): URL { - return obj(columnIndex) as URL - } + override fun getURL(columnIndex: Int): URL = obj(columnIndex) as URL - override fun getURL(columnLabel: String?): URL { - return obj(columnLabel) as URL - } + override fun getURL(columnLabel: String?): URL = obj(columnLabel) as URL override fun updateShort( columnIndex: Int, @@ -643,21 +614,13 @@ class ScrollableResultSet(val parent: ResultSet) : ResultSet by parent { notImplemented() } - override fun getByte(columnIndex: Int): Byte { - return obj(columnIndex) as Byte - } + override fun getByte(columnIndex: Int): Byte = obj(columnIndex) as Byte - override fun getByte(columnLabel: String?): Byte { - return obj(columnLabel) as Byte - } + override fun getByte(columnLabel: String?): Byte = obj(columnLabel) as Byte - override fun getString(columnIndex: Int): String? { - return obj(columnIndex) as String? - } + override fun getString(columnIndex: Int): String? = obj(columnIndex) as String? - override fun getString(columnLabel: String?): String? { - return obj(columnLabel) as String? - } + override fun getString(columnLabel: String?): String? = obj(columnLabel) as String? override fun updateSQLXML( columnIndex: Int, @@ -687,13 +650,9 @@ class ScrollableResultSet(val parent: ResultSet) : ResultSet by parent { notImplemented() } - override fun getObject(columnIndex: Int): Any? { - return obj(columnIndex) - } + override fun getObject(columnIndex: Int): Any? = obj(columnIndex) - override fun getObject(columnLabel: String?): Any? { - return obj(columnLabel) - } + override fun getObject(columnLabel: String?): Any? = obj(columnLabel) override fun getObject( columnIndex: Int, @@ -714,16 +673,12 @@ class ScrollableResultSet(val parent: ResultSet) : ResultSet by parent { override fun getObject( columnIndex: Int, type: Class?, - ): T { - return obj(columnIndex) as T - } + ): T = obj(columnIndex) as T override fun getObject( columnLabel: String?, type: Class?, - ): T { - return obj(columnLabel) as T - } + ): T = obj(columnLabel) as T override fun previous(): Boolean { internalMove(cursor - 1) @@ -756,13 +711,9 @@ class ScrollableResultSet(val parent: ResultSet) : ResultSet by parent { } } - override fun getLong(columnIndex: Int): Long { - return castToLong(obj(columnIndex)) - } + override fun getLong(columnIndex: Int): Long = castToLong(obj(columnIndex)) - override fun getLong(columnLabel: String?): Long { - return castToLong(obj(columnLabel)) - } + override fun getLong(columnLabel: String?): Long = castToLong(obj(columnLabel)) override fun getClob(columnIndex: Int): Clob { // TODO Maybe? @@ -840,13 +791,9 @@ class ScrollableResultSet(val parent: ResultSet) : ResultSet by parent { notImplemented() } - override fun getNString(columnIndex: Int): String { - return obj(columnIndex) as String - } + override fun getNString(columnIndex: Int): String = obj(columnIndex) as String - override fun getNString(columnLabel: String?): String { - return obj(columnLabel) as String - } + override fun getNString(columnLabel: String?): String = obj(columnLabel) as String override fun getArray(columnIndex: Int): Array { // TODO Maybe? @@ -880,17 +827,11 @@ class ScrollableResultSet(val parent: ResultSet) : ResultSet by parent { notImplemented() } - override fun getCharacterStream(columnIndex: Int): Reader { - return getNCharacterStream(columnIndex) - } + override fun getCharacterStream(columnIndex: Int): Reader = getNCharacterStream(columnIndex) - override fun getCharacterStream(columnLabel: String?): Reader { - return getNCharacterStream(columnLabel) - } + override fun getCharacterStream(columnLabel: String?): Reader = getNCharacterStream(columnLabel) - override fun isBeforeFirst(): Boolean { - return cursor - 1 < resultSetLength - } + override fun isBeforeFirst(): Boolean = cursor - 1 < resultSetLength override fun updateBoolean( columnIndex: Int, @@ -926,21 +867,13 @@ class ScrollableResultSet(val parent: ResultSet) : ResultSet by parent { notImplemented() } - override fun getShort(columnIndex: Int): Short { - return obj(columnIndex) as Short - } + override fun getShort(columnIndex: Int): Short = obj(columnIndex) as Short - override fun getShort(columnLabel: String?): Short { - return obj(columnLabel) as Short - } + override fun getShort(columnLabel: String?): Short = obj(columnLabel) as Short - override fun getAsciiStream(columnIndex: Int): InputStream { - return getBinaryStream(columnIndex) - } + override fun getAsciiStream(columnIndex: Int): InputStream = getBinaryStream(columnIndex) - override fun getAsciiStream(columnLabel: String?): InputStream { - return getBinaryStream(columnLabel) - } + override fun getAsciiStream(columnLabel: String?): InputStream = getBinaryStream(columnLabel) override fun updateTime( columnIndex: Int, @@ -1008,13 +941,9 @@ class ScrollableResultSet(val parent: ResultSet) : ResultSet by parent { notImplemented() } - override fun getNCharacterStream(columnIndex: Int): Reader { - return getBinaryStream(columnIndex).reader() - } + override fun getNCharacterStream(columnIndex: Int): Reader = getBinaryStream(columnIndex).reader() - override fun getNCharacterStream(columnLabel: String?): Reader { - return getBinaryStream(columnLabel).reader() - } + override fun getNCharacterStream(columnLabel: String?): Reader = getBinaryStream(columnLabel).reader() override fun updateArray( columnIndex: Int, @@ -1030,45 +959,27 @@ class ScrollableResultSet(val parent: ResultSet) : ResultSet by parent { notImplemented() } - override fun getBytes(columnIndex: Int): ByteArray { - return obj(columnIndex) as ByteArray - } + override fun getBytes(columnIndex: Int): ByteArray = obj(columnIndex) as ByteArray - override fun getBytes(columnLabel: String?): ByteArray { - return obj(columnLabel) as ByteArray - } + override fun getBytes(columnLabel: String?): ByteArray = obj(columnLabel) as ByteArray - override fun getDouble(columnIndex: Int): Double { - return obj(columnIndex) as Double - } + override fun getDouble(columnIndex: Int): Double = obj(columnIndex) as Double - override fun getDouble(columnLabel: String?): Double { - return obj(columnLabel) as Double - } + override fun getDouble(columnLabel: String?): Double = obj(columnLabel) as Double - override fun getUnicodeStream(columnIndex: Int): InputStream { - return getBinaryStream(columnIndex) - } + override fun getUnicodeStream(columnIndex: Int): InputStream = getBinaryStream(columnIndex) - override fun getUnicodeStream(columnLabel: String?): InputStream { - return getBinaryStream(columnLabel) - } + override fun getUnicodeStream(columnLabel: String?): InputStream = getBinaryStream(columnLabel) override fun rowInserted() = false private fun thisIsWrapperFor(iface: Class<*>?) = this.javaClass.isInstance(iface) - override fun isWrapperFor(iface: Class<*>?): Boolean { - return thisIsWrapperFor(iface) || parent.isWrapperFor(iface) - } + override fun isWrapperFor(iface: Class<*>?): Boolean = thisIsWrapperFor(iface) || parent.isWrapperFor(iface) - override fun getInt(columnIndex: Int): Int { - return obj(columnIndex) as Int - } + override fun getInt(columnIndex: Int): Int = obj(columnIndex) as Int - override fun getInt(columnLabel: String?): Int { - return obj(columnLabel) as Int - } + override fun getInt(columnLabel: String?): Int = obj(columnLabel) as Int override fun updateNull(columnIndex: Int) { notImplemented() @@ -1088,8 +999,8 @@ class ScrollableResultSet(val parent: ResultSet) : ResultSet by parent { notImplemented() } - override fun getMetaData(): ResultSetMetaData { - return object : ResultSetMetaData by parentMetadata { + override fun getMetaData(): ResultSetMetaData = + object : ResultSetMetaData by parentMetadata { override fun isReadOnly(column: Int) = true override fun isWritable(column: Int) = false @@ -1098,19 +1009,12 @@ class ScrollableResultSet(val parent: ResultSet) : ResultSet by parent { override fun getColumnCount() = this@ScrollableResultSet.columnCount - override fun getColumnLabel(column: Int): String { - return columnLabels[column - 1] - } + override fun getColumnLabel(column: Int): String = columnLabels[column - 1] } - } - override fun getBinaryStream(columnIndex: Int): InputStream { - return (obj(columnIndex) as ByteArray).inputStream() - } + override fun getBinaryStream(columnIndex: Int): InputStream = (obj(columnIndex) as ByteArray).inputStream() - override fun getBinaryStream(columnLabel: String?): InputStream { - return (obj(columnLabel) as ByteArray).inputStream() - } + override fun getBinaryStream(columnLabel: String?): InputStream = (obj(columnLabel) as ByteArray).inputStream() override fun updateCharacterStream( columnIndex: Int, diff --git a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/info/ApplicationInfoImpl.kt b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/info/ApplicationInfoImpl.kt index 83c0f1d4..6d5d6832 100644 --- a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/info/ApplicationInfoImpl.kt +++ b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/info/ApplicationInfoImpl.kt @@ -8,7 +8,10 @@ import org.kodein.di.instance import xyz.nulldev.androidcompat.config.ApplicationInfoConfigModule import xyz.nulldev.ts.config.ConfigManager -class ApplicationInfoImpl(override val di: DI = DI.global) : ApplicationInfo(), DIAware { +class ApplicationInfoImpl( + override val di: DI = DI.global, +) : ApplicationInfo(), + DIAware { val configManager: ConfigManager by di.instance() val appInfoConfig: ApplicationInfoConfigModule diff --git a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/io/AndroidFiles.kt b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/io/AndroidFiles.kt index ea55b497..91387fc7 100644 --- a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/io/AndroidFiles.kt +++ b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/io/AndroidFiles.kt @@ -8,7 +8,9 @@ import java.io.File /** * Android file constants. */ -class AndroidFiles(val configManager: ConfigManager = GlobalConfigManager) { +class AndroidFiles( + val configManager: ConfigManager = GlobalConfigManager, +) { val filesConfig: FilesConfigModule get() = configManager.module() @@ -30,9 +32,8 @@ class AndroidFiles(val configManager: ConfigManager = GlobalConfigManager) { val packagesDir: File get() = registerFile(filesConfig.packageDir) - fun registerFile(file: String): File { - return File(file).apply { + fun registerFile(file: String): File = + File(file).apply { mkdirs() } - } } diff --git a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/io/sharedprefs/JavaSharedPreferences.kt b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/io/sharedprefs/JavaSharedPreferences.kt index 53f2931e..c48f6d0c 100644 --- a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/io/sharedprefs/JavaSharedPreferences.kt +++ b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/io/sharedprefs/JavaSharedPreferences.kt @@ -30,7 +30,9 @@ import kotlin.io.path.inputStream import kotlin.io.path.outputStream @OptIn(ExperimentalSerializationApi::class, ExperimentalSettingsApi::class) -class JavaSharedPreferences(key: String) : SharedPreferences { +class JavaSharedPreferences( + key: String, +) : SharedPreferences { companion object { private val logger = KotlinLogging.logger {} } @@ -72,20 +74,17 @@ class JavaSharedPreferences(key: String) : SharedPreferences { private val listeners = mutableMapOf Unit>() // TODO: 2021-05-29 Need to find a way to get this working with all pref types - override fun getAll(): MutableMap { - return preferences.keys.associateWith { preferences.getStringOrNull(it) }.toMutableMap() - } + override fun getAll(): MutableMap = preferences.keys.associateWith { preferences.getStringOrNull(it) }.toMutableMap() override fun getString( key: String, defValue: String?, - ): String? { - return if (defValue != null) { + ): String? = + if (defValue != null) { preferences.getString(key, defValue) } else { preferences.getStringOrNull(key) } - } override fun getStringSet( key: String, @@ -105,50 +104,48 @@ class JavaSharedPreferences(key: String) : SharedPreferences { override fun getInt( key: String, defValue: Int, - ): Int { - return preferences.getInt(key, defValue) - } + ): Int = preferences.getInt(key, defValue) override fun getLong( key: String, defValue: Long, - ): Long { - return preferences.getLong(key, defValue) - } + ): Long = preferences.getLong(key, defValue) override fun getFloat( key: String, defValue: Float, - ): Float { - return preferences.getFloat(key, defValue) - } + ): Float = preferences.getFloat(key, defValue) override fun getBoolean( key: String, defValue: Boolean, - ): Boolean { - return preferences.getBoolean(key, defValue) - } + ): Boolean = preferences.getBoolean(key, defValue) - override fun contains(key: String): Boolean { - return key in preferences.keys - } + override fun contains(key: String): Boolean = key in preferences.keys - override fun edit(): SharedPreferences.Editor { - return Editor(preferences) { key -> + override fun edit(): SharedPreferences.Editor = + Editor(preferences) { key -> listeners.forEach { (_, listener) -> listener(key) } } - } - class Editor(private val preferences: Settings, private val notify: (String) -> Unit) : SharedPreferences.Editor { + class Editor( + private val preferences: Settings, + private val notify: (String) -> Unit, + ) : SharedPreferences.Editor { private val actions = mutableListOf() private sealed class Action { - data class Add(val key: String, val value: Any) : Action() + data class Add( + val key: String, + val value: Any, + ) : Action() + + data class Remove( + val key: String, + ) : Action() - data class Remove(val key: String) : Action() data object Clear : Action() } diff --git a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/pm/InstalledPackage.kt b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/pm/InstalledPackage.kt index ebbf7102..11d67ea7 100644 --- a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/pm/InstalledPackage.kt +++ b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/pm/InstalledPackage.kt @@ -14,7 +14,9 @@ import java.io.File import javax.imageio.ImageIO import javax.xml.parsers.DocumentBuilderFactory -data class InstalledPackage(val root: File) { +data class InstalledPackage( + val root: File, +) { val apk = File(root, "package.apk") val jar = File(root, "translated.jar") val icon = File(root, "icon.png") @@ -34,18 +36,21 @@ data class InstalledPackage(val root: File) { Bundle().apply { val appTag = doc.getElementsByTagName("application").item(0) - appTag?.childNodes?.toList()?.filter { - it.nodeType == Node.ELEMENT_NODE - }?.map { - it as Element - }?.filter { - it.tagName == "meta-data" - }?.map { - putString( - it.attributes.getNamedItem("android:name").nodeValue, - it.attributes.getNamedItem("android:value").nodeValue, - ) - } + appTag + ?.childNodes + ?.toList() + ?.filter { + it.nodeType == Node.ELEMENT_NODE + }?.map { + it as Element + }?.filter { + it.tagName == "meta-data" + }?.map { + putString( + it.attributes.getNamedItem("android:name").nodeValue, + it.attributes.getNamedItem("android:value").nodeValue, + ) + } } it.signatures = @@ -53,12 +58,14 @@ data class InstalledPackage(val root: File) { parsed.apkSingers.flatMap { it.certificateMetas } // + parsed.apkV2Singers.flatMap { it.certificateMetas } ) // Blocked by: https://github.com/hsiafan/apk-parser/issues/72 - .map { Signature(it.data) }.toTypedArray() + .map { Signature(it.data) } + .toTypedArray() } fun verify(): Boolean { val res = - ApkVerifier.Builder(apk) + ApkVerifier + .Builder(apk) .build() .verify() @@ -70,11 +77,14 @@ data class InstalledPackage(val root: File) { val icons = ApkFile(apk).allIcons val read = - icons.filter { it.isFile }.map { - it.data.inputStream().use { - ImageIO.read(it) - } - }.sortedByDescending { it.width * it.height }.firstOrNull() ?: return + icons + .filter { it.isFile } + .map { + it.data.inputStream().use { + ImageIO.read(it) + } + }.sortedByDescending { it.width * it.height } + .firstOrNull() ?: return ImageIO.write(read, "png", icon) } catch (e: Exception) { @@ -94,8 +104,9 @@ data class InstalledPackage(val root: File) { fun NodeList.toList(): List { val out = mutableListOf() - for (i in 0 until length) + for (i in 0 until length) { out += item(i) + } return out } diff --git a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/pm/PackageController.kt b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/pm/PackageController.kt index 1b6ecc79..8edf1840 100644 --- a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/pm/PackageController.kt +++ b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/pm/PackageController.kt @@ -57,13 +57,15 @@ class PackageController { } } - fun listInstalled(): List { - return androidFiles.packagesDir.listFiles().orEmpty().filter { - it.isDirectory - }.map { - InstalledPackage(it) - } - } + fun listInstalled(): List = + androidFiles.packagesDir + .listFiles() + .orEmpty() + .filter { + it.isDirectory + }.map { + InstalledPackage(it) + } fun deletePackage(pack: InstalledPackage) { if (!pack.root.exists()) error("Package was never installed!") diff --git a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/pm/PackageUtil.kt b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/pm/PackageUtil.kt index bf4b207a..6a502e2b 100644 --- a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/pm/PackageUtil.kt +++ b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/pm/PackageUtil.kt @@ -6,18 +6,19 @@ import android.content.pm.PackageInfo import net.dongliu.apk.parser.bean.ApkMeta import java.io.File -fun ApkMeta.toPackageInfo(apk: File): PackageInfo { - return PackageInfo().also { +fun ApkMeta.toPackageInfo(apk: File): PackageInfo = + PackageInfo().also { it.packageName = packageName it.versionCode = versionCode.toInt() it.versionName = versionName it.reqFeatures = - usesFeatures.map { - FeatureInfo().apply { - name = it.name - } - }.toTypedArray() + usesFeatures + .map { + FeatureInfo().apply { + name = it.name + } + }.toTypedArray() it.applicationInfo = ApplicationInfo().apply { @@ -26,4 +27,3 @@ fun ApkMeta.toPackageInfo(apk: File): PackageInfo { sourceDir = apk.absolutePath } } -} diff --git a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/res/DrawableResource.kt b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/res/DrawableResource.kt index 490c3b1c..60f7a315 100644 --- a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/res/DrawableResource.kt +++ b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/res/DrawableResource.kt @@ -1,6 +1,8 @@ package xyz.nulldev.androidcompat.res -class DrawableResource(val location: String) : Resource { +class DrawableResource( + val location: String, +) : Resource { override fun getType() = DrawableResource::class.java override fun getValue() = javaClass.getResourceAsStream(location) diff --git a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/res/StringResource.kt b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/res/StringResource.kt index 66c6b31a..5178d7bd 100644 --- a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/res/StringResource.kt +++ b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/res/StringResource.kt @@ -19,7 +19,9 @@ package xyz.nulldev.androidcompat.res /** * String resource. */ -class StringResource(val string: String) : Resource { +class StringResource( + val string: String, +) : Resource { override fun getValue() = string override fun getType() = StringResource::class.java diff --git a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/util/KodeinGlobalHelper.kt b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/util/KodeinGlobalHelper.kt index ceaabfd0..c0dad320 100644 --- a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/util/KodeinGlobalHelper.kt +++ b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/util/KodeinGlobalHelper.kt @@ -29,8 +29,8 @@ object KodeinGlobalHelper { fun instance( type: Class, kodein: DI? = null, - ): T { - return when (type) { + ): T = + when (type) { AndroidFiles::class.java -> { val instance: AndroidFiles by (kodein ?: kodein()).instance() instance as T @@ -61,10 +61,7 @@ object KodeinGlobalHelper { } else -> throw IllegalArgumentException("Kodein instance not found") } - } @JvmStatic - fun instance(type: Class): T { - return instance(type, null) - } + fun instance(type: Class): T = instance(type, null) } diff --git a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/webkit/CookieManagerImpl.kt b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/webkit/CookieManagerImpl.kt index d400327f..95762137 100644 --- a/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/webkit/CookieManagerImpl.kt +++ b/AndroidCompat/src/main/java/xyz/nulldev/androidcompat/webkit/CookieManagerImpl.kt @@ -18,9 +18,7 @@ class CookieManagerImpl : CookieManager() { acceptCookie = accept } - override fun acceptCookie(): Boolean { - return acceptCookie - } + override fun acceptCookie(): Boolean = acceptCookie override fun setAcceptThirdPartyCookies( webview: WebView?, @@ -29,9 +27,7 @@ class CookieManagerImpl : CookieManager() { acceptThirdPartyCookies = accept } - override fun acceptThirdPartyCookies(webview: WebView?): Boolean { - return acceptThirdPartyCookies - } + override fun acceptThirdPartyCookies(webview: WebView?): Boolean = acceptThirdPartyCookies override fun setCookie( url: String, @@ -65,7 +61,8 @@ class CookieManagerImpl : CookieManager() { } else { URI("http://$url") } - return cookieHandler.cookieStore.get(uri) + return cookieHandler.cookieStore + .get(uri) .joinToString("; ") { "${it.name}=${it.value}" } } @@ -87,15 +84,11 @@ class CookieManagerImpl : CookieManager() { callback?.onReceiveValue(removedCookies) } - override fun hasCookies(): Boolean { - return cookieHandler.cookieStore.cookies.isNotEmpty() - } + override fun hasCookies(): Boolean = cookieHandler.cookieStore.cookies.isNotEmpty() override fun flush() {} - override fun allowFileSchemeCookiesImpl(): Boolean { - return allowFileSchemeCookies - } + override fun allowFileSchemeCookiesImpl(): Boolean = allowFileSchemeCookies override fun setAcceptFileSchemeCookiesImpl(accept: Boolean) { allowFileSchemeCookies = acceptCookie diff --git a/server/build.gradle.kts b/server/build.gradle.kts index d01e0977..e682b81c 100644 --- a/server/build.gradle.kts +++ b/server/build.gradle.kts @@ -3,12 +3,28 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile import java.time.Instant plugins { - id(libs.plugins.kotlin.jvm.get().pluginId) - id(libs.plugins.kotlin.serialization.get().pluginId) - id(libs.plugins.ktlint.get().pluginId) + id( + libs.plugins.kotlin.jvm + .get() + .pluginId, + ) + id( + libs.plugins.kotlin.serialization + .get() + .pluginId, + ) + id( + libs.plugins.ktlint + .get() + .pluginId, + ) application alias(libs.plugins.shadowjar) - id(libs.plugins.buildconfig.get().pluginId) + id( + libs.plugins.buildconfig + .get() + .pluginId, + ) } dependencies { diff --git a/server/src/main/kotlin/eu/kanade/tachiyomi/AppModule.kt b/server/src/main/kotlin/eu/kanade/tachiyomi/AppModule.kt index 8fe30c1f..e193c060 100644 --- a/server/src/main/kotlin/eu/kanade/tachiyomi/AppModule.kt +++ b/server/src/main/kotlin/eu/kanade/tachiyomi/AppModule.kt @@ -32,7 +32,9 @@ import uy.kohesive.injekt.api.addSingleton import uy.kohesive.injekt.api.addSingletonFactory import uy.kohesive.injekt.api.get -class AppModule(val app: Application) : InjektModule { +class AppModule( + val app: Application, +) : InjektModule { override fun InjektRegistrar.registerInjectables() { addSingleton(app) diff --git a/server/src/main/kotlin/eu/kanade/tachiyomi/network/MemoryCookieJar.kt b/server/src/main/kotlin/eu/kanade/tachiyomi/network/MemoryCookieJar.kt index 85259119..9b3fa9f6 100644 --- a/server/src/main/kotlin/eu/kanade/tachiyomi/network/MemoryCookieJar.kt +++ b/server/src/main/kotlin/eu/kanade/tachiyomi/network/MemoryCookieJar.kt @@ -49,7 +49,9 @@ class MemoryCookieJar : CookieJar { } } -class WrappedCookie private constructor(val cookie: Cookie) { +class WrappedCookie private constructor( + val cookie: Cookie, +) { fun unwrap() = cookie fun isExpired() = cookie.expiresAt < System.currentTimeMillis() diff --git a/server/src/main/kotlin/eu/kanade/tachiyomi/network/NetworkHelper.kt b/server/src/main/kotlin/eu/kanade/tachiyomi/network/NetworkHelper.kt index 4c71774c..bacfa5e9 100644 --- a/server/src/main/kotlin/eu/kanade/tachiyomi/network/NetworkHelper.kt +++ b/server/src/main/kotlin/eu/kanade/tachiyomi/network/NetworkHelper.kt @@ -30,7 +30,9 @@ import java.net.CookieManager import java.net.CookiePolicy import java.util.concurrent.TimeUnit -class NetworkHelper(context: Context) { +class NetworkHelper( + context: Context, +) { // private val preferences: PreferencesHelper by injectLazy() // private val cacheDir = File(context.cacheDir, "network_cache") @@ -53,9 +55,7 @@ class NetworkHelper(context: Context) { "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", ) - fun defaultUserAgentProvider(): String { - return userAgent.value - } + fun defaultUserAgentProvider(): String = userAgent.value init { @OptIn(DelicateCoroutinesApi::class) @@ -63,14 +63,14 @@ class NetworkHelper(context: Context) { .drop(1) .onEach { GetCatalogueSource.unregisterAllCatalogueSources() // need to reset the headers - } - .launchIn(GlobalScope) + }.launchIn(GlobalScope) } private val baseClientBuilder: OkHttpClient.Builder get() { val builder = - OkHttpClient.Builder() + OkHttpClient + .Builder() .cookieJar(PersistentCookieJar(cookieStore)) .connectTimeout(30, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS) @@ -80,8 +80,7 @@ class NetworkHelper(context: Context) { directory = File.createTempFile("tachidesk_network_cache", null), maxSize = 5L * 1024 * 1024, // 5 MiB ), - ) - .addInterceptor(UncaughtExceptionInterceptor()) + ).addInterceptor(UncaughtExceptionInterceptor()) .addInterceptor(UserAgentInterceptor(::defaultUserAgentProvider)) .addNetworkInterceptor(IgnoreGzipInterceptor()) .addNetworkInterceptor(BrotliInterceptor) diff --git a/server/src/main/kotlin/eu/kanade/tachiyomi/network/OkHttpExtensions.kt b/server/src/main/kotlin/eu/kanade/tachiyomi/network/OkHttpExtensions.kt index 58564134..c2f9dd80 100644 --- a/server/src/main/kotlin/eu/kanade/tachiyomi/network/OkHttpExtensions.kt +++ b/server/src/main/kotlin/eu/kanade/tachiyomi/network/OkHttpExtensions.kt @@ -50,9 +50,7 @@ fun Call.asObservable(): Observable { // call.cancel() } - override fun isUnsubscribed(): Boolean { - return call.isCanceled() - } + override fun isUnsubscribed(): Boolean = call.isCanceled() } subscriber.add(requestArbiter) @@ -60,15 +58,14 @@ fun Call.asObservable(): Observable { } } -fun Call.asObservableSuccess(): Observable { - return asObservable() +fun Call.asObservableSuccess(): Observable = + asObservable() .doOnNext { response -> if (!response.isSuccessful) { response.close() throw HttpException(response.code) } } -} // Based on https://github.com/gildor/kotlin-coroutines-okhttp @OptIn(ExperimentalCoroutinesApi::class) @@ -135,29 +132,28 @@ fun OkHttpClient.newCachelessCallWithProgress( .cache(null) .addNetworkInterceptor { chain -> val originalResponse = chain.proceed(chain.request()) - originalResponse.newBuilder() + originalResponse + .newBuilder() .body(ProgressResponseBody(originalResponse.body, listener)) .build() - } - .build() + }.build() return progressClient.newCall(request) } context(Json) -inline fun Response.parseAs(): T { - return decodeFromJsonResponse(serializer(), this) -} +inline fun Response.parseAs(): T = decodeFromJsonResponse(serializer(), this) context(Json) @OptIn(ExperimentalSerializationApi::class) fun decodeFromJsonResponse( deserializer: DeserializationStrategy, response: Response, -): T { - return response.body.source().use { +): T = + response.body.source().use { decodeFromBufferedSource(deserializer, it) } -} -class HttpException(val code: Int) : IllegalStateException("HTTP error $code") +class HttpException( + val code: Int, +) : IllegalStateException("HTTP error $code") diff --git a/server/src/main/kotlin/eu/kanade/tachiyomi/network/PersistentCookieJar.kt b/server/src/main/kotlin/eu/kanade/tachiyomi/network/PersistentCookieJar.kt index 24013382..4c792cf8 100644 --- a/server/src/main/kotlin/eu/kanade/tachiyomi/network/PersistentCookieJar.kt +++ b/server/src/main/kotlin/eu/kanade/tachiyomi/network/PersistentCookieJar.kt @@ -5,7 +5,9 @@ import okhttp3.CookieJar import okhttp3.HttpUrl // from TachiWeb-Server -class PersistentCookieJar(private val store: PersistentCookieStore) : CookieJar { +class PersistentCookieJar( + private val store: PersistentCookieStore, +) : CookieJar { override fun saveFromResponse( url: HttpUrl, cookies: List, @@ -13,7 +15,5 @@ class PersistentCookieJar(private val store: PersistentCookieStore) : CookieJar store.addAll(url, cookies) } - override fun loadForRequest(url: HttpUrl): List { - return store.get(url) - } + override fun loadForRequest(url: HttpUrl): List = store.get(url) } diff --git a/server/src/main/kotlin/eu/kanade/tachiyomi/network/PersistentCookieStore.kt b/server/src/main/kotlin/eu/kanade/tachiyomi/network/PersistentCookieStore.kt index 15193876..6e012316 100644 --- a/server/src/main/kotlin/eu/kanade/tachiyomi/network/PersistentCookieStore.kt +++ b/server/src/main/kotlin/eu/kanade/tachiyomi/network/PersistentCookieStore.kt @@ -15,7 +15,9 @@ import kotlin.time.Duration.Companion.milliseconds import kotlin.time.Duration.Companion.seconds // from TachiWeb-Server -class PersistentCookieStore(context: Context) : CookieStore { +class PersistentCookieStore( + context: Context, +) : CookieStore { private val cookieMap = ConcurrentHashMap>() private val prefs = context.getSharedPreferences("cookie_store", Context.MODE_PRIVATE) @@ -23,7 +25,8 @@ class PersistentCookieStore(context: Context) : CookieStore { init { val domains = - prefs.all.keys.map { it.substringBeforeLast(".") } + prefs.all.keys + .map { it.substringBeforeLast(".") } .toSet() domains.forEach { domain -> val cookies = prefs.getStringSet(domain, emptySet()) @@ -31,7 +34,8 @@ class PersistentCookieStore(context: Context) : CookieStore { try { val url = "http://$domain".toHttpUrlOrNull() ?: return@forEach val nonExpiredCookies = - cookies.mapNotNull { Cookie.parse(url, it) } + cookies + .mapNotNull { Cookie.parse(url, it) } .filter { !it.hasExpired() } cookieMap[domain] = nonExpiredCookies } catch (e: Exception) { @@ -63,14 +67,13 @@ class PersistentCookieStore(context: Context) : CookieStore { } } - override fun removeAll(): Boolean { - return lock.withLock { + override fun removeAll(): Boolean = + lock.withLock { val wasNotEmpty = cookieMap.isEmpty() prefs.edit().clear().apply() cookieMap.clear() wasNotEmpty } - } fun remove(uri: URI) { val url = uri.toURL() @@ -87,9 +90,7 @@ class PersistentCookieStore(context: Context) : CookieStore { } } - fun get(url: HttpUrl): List { - return get(url.host) - } + fun get(url: HttpUrl): List = get(url.host) override fun add( uri: URI?, @@ -105,19 +106,17 @@ class PersistentCookieStore(context: Context) : CookieStore { } } - override fun getCookies(): List { - return cookieMap.values.flatMap { + override fun getCookies(): List = + cookieMap.values.flatMap { it.map { it.toHttpCookie() } } - } - override fun getURIs(): List { - return cookieMap.keys().toList().map { + override fun getURIs(): List = + cookieMap.keys().toList().map { URI("http://$it") } - } override fun remove( uri: URI?, @@ -145,9 +144,7 @@ class PersistentCookieStore(context: Context) : CookieStore { } } - private fun get(url: String): List { - return cookieMap[url].orEmpty().filter { !it.hasExpired() } - } + private fun get(url: String): List = cookieMap[url].orEmpty().filter { !it.hasExpired() } private fun saveToDisk(url: URL) { // Get cookies to be stored in disk @@ -165,7 +162,8 @@ class PersistentCookieStore(context: Context) : CookieStore { private fun Cookie.hasExpired() = System.currentTimeMillis() >= expiresAt private fun HttpCookie.toCookie(uri: URI) = - Cookie.Builder() + Cookie + .Builder() .name(name) .value(value) .domain(uri.toURL().host) @@ -176,22 +174,19 @@ class PersistentCookieStore(context: Context) : CookieStore { } else { it.expiresAt(Long.MAX_VALUE) } - } - .let { + }.let { if (secure) { it.secure() } else { it } - } - .let { + }.let { if (isHttpOnly) { it.httpOnly() } else { it } - } - .build() + }.build() private fun Cookie.toHttpCookie(): HttpCookie { val it = this diff --git a/server/src/main/kotlin/eu/kanade/tachiyomi/network/ProgressResponseBody.kt b/server/src/main/kotlin/eu/kanade/tachiyomi/network/ProgressResponseBody.kt index c52dd692..36096773 100644 --- a/server/src/main/kotlin/eu/kanade/tachiyomi/network/ProgressResponseBody.kt +++ b/server/src/main/kotlin/eu/kanade/tachiyomi/network/ProgressResponseBody.kt @@ -9,22 +9,19 @@ import okio.Source import okio.buffer import java.io.IOException -class ProgressResponseBody(private val responseBody: ResponseBody, private val progressListener: ProgressListener) : ResponseBody() { +class ProgressResponseBody( + private val responseBody: ResponseBody, + private val progressListener: ProgressListener, +) : ResponseBody() { private val bufferedSource: BufferedSource by lazy { source(responseBody.source()).buffer() } - override fun contentType(): MediaType? { - return responseBody.contentType() - } + override fun contentType(): MediaType? = responseBody.contentType() - override fun contentLength(): Long { - return responseBody.contentLength() - } + override fun contentLength(): Long = responseBody.contentLength() - override fun source(): BufferedSource { - return bufferedSource - } + override fun source(): BufferedSource = bufferedSource private fun source(source: Source): Source { return object : ForwardingSource(source) { diff --git a/server/src/main/kotlin/eu/kanade/tachiyomi/network/Requests.kt b/server/src/main/kotlin/eu/kanade/tachiyomi/network/Requests.kt index 67a6671b..d384dc57 100644 --- a/server/src/main/kotlin/eu/kanade/tachiyomi/network/Requests.kt +++ b/server/src/main/kotlin/eu/kanade/tachiyomi/network/Requests.kt @@ -18,13 +18,13 @@ fun GET( url: String, headers: Headers = DEFAULT_HEADERS, cache: CacheControl = DEFAULT_CACHE_CONTROL, -): Request { - return Request.Builder() +): Request = + Request + .Builder() .url(url) .headers(headers) .cacheControl(cache) .build() -} /** * @since extensions-lib 1.4 @@ -33,52 +33,52 @@ fun GET( url: HttpUrl, headers: Headers = DEFAULT_HEADERS, cache: CacheControl = DEFAULT_CACHE_CONTROL, -): Request { - return Request.Builder() +): Request = + Request + .Builder() .url(url) .headers(headers) .cacheControl(cache) .build() -} fun POST( url: String, headers: Headers = DEFAULT_HEADERS, body: RequestBody = DEFAULT_BODY, cache: CacheControl = DEFAULT_CACHE_CONTROL, -): Request { - return Request.Builder() +): Request = + Request + .Builder() .url(url) .post(body) .headers(headers) .cacheControl(cache) .build() -} fun PUT( url: String, headers: Headers = DEFAULT_HEADERS, body: RequestBody = DEFAULT_BODY, cache: CacheControl = DEFAULT_CACHE_CONTROL, -): Request { - return Request.Builder() +): Request = + Request + .Builder() .url(url) .put(body) .headers(headers) .cacheControl(cache) .build() -} fun DELETE( url: String, headers: Headers = DEFAULT_HEADERS, body: RequestBody = DEFAULT_BODY, cache: CacheControl = DEFAULT_CACHE_CONTROL, -): Request { - return Request.Builder() +): Request = + Request + .Builder() .url(url) .delete(body) .headers(headers) .cacheControl(cache) .build() -} diff --git a/server/src/main/kotlin/eu/kanade/tachiyomi/network/interceptor/CloudflareInterceptor.kt b/server/src/main/kotlin/eu/kanade/tachiyomi/network/interceptor/CloudflareInterceptor.kt index 6a3ba45e..c2025950 100644 --- a/server/src/main/kotlin/eu/kanade/tachiyomi/network/interceptor/CloudflareInterceptor.kt +++ b/server/src/main/kotlin/eu/kanade/tachiyomi/network/interceptor/CloudflareInterceptor.kt @@ -117,12 +117,12 @@ object CFClearance { serverConfig.flareSolverrTimeout .map { timeoutInt -> val timeout = timeoutInt.seconds - network.client.newBuilder() + network.client + .newBuilder() .callTimeout(timeout.plus(10.seconds).toJavaDuration()) .readTimeout(timeout.plus(5.seconds).toJavaDuration()) .build() - } - .stateIn(GlobalScope, SharingStarted.Eagerly, network.client) + }.stateIn(GlobalScope, SharingStarted.Eagerly, network.client) } private val json: Json by injectLazy() private val jsonMediaType = "application/json".toMediaType() @@ -190,26 +190,29 @@ object CFClearance { return with(json) { mutex.withLock { - client.value.newCall( - POST( - url = serverConfig.flareSolverrUrl.value.removeSuffix("/") + "/v1", - body = - Json.encodeToString( - FlareSolverRequest( - "request.get", - originalRequest.url.toString(), - session = serverConfig.flareSolverrSessionName.value, - sessionTtlMinutes = serverConfig.flareSolverrSessionTtl.value, - cookies = - network.cookieStore.get(originalRequest.url).map { - FlareSolverCookie(it.name, it.value) - }, - returnOnlyCookies = onlyCookies, - maxTimeout = timeout.inWholeMilliseconds.toInt(), - ), - ).toRequestBody(jsonMediaType), - ), - ).awaitSuccess().parseAs() + client.value + .newCall( + POST( + url = serverConfig.flareSolverrUrl.value.removeSuffix("/") + "/v1", + body = + Json + .encodeToString( + FlareSolverRequest( + "request.get", + originalRequest.url.toString(), + session = serverConfig.flareSolverrSessionName.value, + sessionTtlMinutes = serverConfig.flareSolverrSessionTtl.value, + cookies = + network.cookieStore.get(originalRequest.url).map { + FlareSolverCookie(it.name, it.value) + }, + returnOnlyCookies = onlyCookies, + maxTimeout = timeout.inWholeMilliseconds.toInt(), + ), + ).toRequestBody(jsonMediaType), + ), + ).awaitSuccess() + .parseAs() } } } @@ -224,7 +227,8 @@ object CFClearance { val cookies = flareSolverResponse.solution.cookies .map { cookie -> - Cookie.Builder() + Cookie + .Builder() .name(cookie.name) .value(cookie.value) .domain(cookie.domain.removePrefix(".")) @@ -233,13 +237,12 @@ object CFClearance { if (cookie.httpOnly != null && cookie.httpOnly) it.httpOnly() if (cookie.secure != null && cookie.secure) it.secure() if (!cookie.path.isNullOrEmpty()) it.path(cookie.path) - } - .build() - } - .groupBy { it.domain } + }.build() + }.groupBy { it.domain } .flatMap { (domain, cookies) -> network.cookieStore.addAll( - HttpUrl.Builder() + HttpUrl + .Builder() .scheme("http") .host(domain.removePrefix(".")) .build(), @@ -254,7 +257,8 @@ object CFClearance { "${it.name}=${it.value}" } logger.trace { "Final cookies\n$finalCookies" } - return originalRequest.newBuilder() + return originalRequest + .newBuilder() .header("Cookie", finalCookies) .header("User-Agent", flareSolverResponse.solution.userAgent) .build() diff --git a/server/src/main/kotlin/eu/kanade/tachiyomi/network/interceptor/UncaughtExceptionInterceptor.kt b/server/src/main/kotlin/eu/kanade/tachiyomi/network/interceptor/UncaughtExceptionInterceptor.kt index 958dcd85..bca10901 100644 --- a/server/src/main/kotlin/eu/kanade/tachiyomi/network/interceptor/UncaughtExceptionInterceptor.kt +++ b/server/src/main/kotlin/eu/kanade/tachiyomi/network/interceptor/UncaughtExceptionInterceptor.kt @@ -13,8 +13,8 @@ import java.io.IOException * See https://square.github.io/okhttp/4.x/okhttp/okhttp3/-interceptor/ */ class UncaughtExceptionInterceptor : Interceptor { - override fun intercept(chain: Interceptor.Chain): Response { - return try { + override fun intercept(chain: Interceptor.Chain): Response = + try { chain.proceed(chain.request()) } catch (e: Exception) { if (e is IOException) { @@ -23,5 +23,4 @@ class UncaughtExceptionInterceptor : Interceptor { throw IOException(e) } } - } } diff --git a/server/src/main/kotlin/eu/kanade/tachiyomi/network/interceptor/UserAgentInterceptor.kt b/server/src/main/kotlin/eu/kanade/tachiyomi/network/interceptor/UserAgentInterceptor.kt index 94683237..63a35958 100644 --- a/server/src/main/kotlin/eu/kanade/tachiyomi/network/interceptor/UserAgentInterceptor.kt +++ b/server/src/main/kotlin/eu/kanade/tachiyomi/network/interceptor/UserAgentInterceptor.kt @@ -3,7 +3,9 @@ package eu.kanade.tachiyomi.network.interceptor import okhttp3.Interceptor import okhttp3.Response -class UserAgentInterceptor(private val userAgentProvider: () -> String) : Interceptor { +class UserAgentInterceptor( + private val userAgentProvider: () -> String, +) : Interceptor { override fun intercept(chain: Interceptor.Chain): Response { val originalRequest = chain.request() diff --git a/server/src/main/kotlin/eu/kanade/tachiyomi/source/CatalogueSource.kt b/server/src/main/kotlin/eu/kanade/tachiyomi/source/CatalogueSource.kt index 76ca73ab..fa6f75dc 100644 --- a/server/src/main/kotlin/eu/kanade/tachiyomi/source/CatalogueSource.kt +++ b/server/src/main/kotlin/eu/kanade/tachiyomi/source/CatalogueSource.kt @@ -23,9 +23,7 @@ interface CatalogueSource : Source { * @param page the page number to retrieve. */ @Suppress("DEPRECATION") - suspend fun getPopularManga(page: Int): MangasPage { - return fetchPopularManga(page).awaitSingle() - } + suspend fun getPopularManga(page: Int): MangasPage = fetchPopularManga(page).awaitSingle() /** * Get a page with a list of manga. @@ -40,9 +38,7 @@ interface CatalogueSource : Source { page: Int, query: String, filters: FilterList, - ): MangasPage { - return fetchSearchManga(page, query, filters).awaitSingle() - } + ): MangasPage = fetchSearchManga(page, query, filters).awaitSingle() /** * Get a page with a list of latest manga updates. @@ -51,9 +47,7 @@ interface CatalogueSource : Source { * @param page the page number to retrieve. */ @Suppress("DEPRECATION") - suspend fun getLatestUpdates(page: Int): MangasPage { - return fetchLatestUpdates(page).awaitSingle() - } + suspend fun getLatestUpdates(page: Int): MangasPage = fetchLatestUpdates(page).awaitSingle() /** * Returns the list of filters for the source. diff --git a/server/src/main/kotlin/eu/kanade/tachiyomi/source/Source.kt b/server/src/main/kotlin/eu/kanade/tachiyomi/source/Source.kt index ba13f0ae..76f2dfe8 100644 --- a/server/src/main/kotlin/eu/kanade/tachiyomi/source/Source.kt +++ b/server/src/main/kotlin/eu/kanade/tachiyomi/source/Source.kt @@ -31,9 +31,7 @@ interface Source { * @return the updated manga. */ @Suppress("DEPRECATION") - suspend fun getMangaDetails(manga: SManga): SManga { - return fetchMangaDetails(manga).awaitSingle() - } + suspend fun getMangaDetails(manga: SManga): SManga = fetchMangaDetails(manga).awaitSingle() /** * Get all the available chapters for a manga. @@ -43,9 +41,7 @@ interface Source { * @return the chapters for the manga. */ @Suppress("DEPRECATION") - suspend fun getChapterList(manga: SManga): List { - return fetchChapterList(manga).awaitSingle() - } + suspend fun getChapterList(manga: SManga): List = fetchChapterList(manga).awaitSingle() /** * Get the list of pages a chapter has. Pages should be returned @@ -56,9 +52,7 @@ interface Source { * @return the pages for the chapter. */ @Suppress("DEPRECATION") - suspend fun getPageList(chapter: SChapter): List { - return fetchPageList(chapter).awaitSingle() - } + suspend fun getPageList(chapter: SChapter): List = fetchPageList(chapter).awaitSingle() @Deprecated( "Use the non-RxJava API instead", diff --git a/server/src/main/kotlin/eu/kanade/tachiyomi/source/local/LocalSource.kt b/server/src/main/kotlin/eu/kanade/tachiyomi/source/local/LocalSource.kt index 42bb2b4d..238ff1c1 100644 --- a/server/src/main/kotlin/eu/kanade/tachiyomi/source/local/LocalSource.kt +++ b/server/src/main/kotlin/eu/kanade/tachiyomi/source/local/LocalSource.kt @@ -59,7 +59,8 @@ import com.github.junrar.Archive as JunrarArchive class LocalSource( private val fileSystem: LocalSourceFileSystem, private val coverManager: LocalCoverManager, -) : CatalogueSource, UnmeteredSource { +) : CatalogueSource, + UnmeteredSource { private val json: Json by injectLazy() private val xml: XML by injectLazy() @@ -93,7 +94,8 @@ class LocalSource( // Filter out files that are hidden and is not a folder .filter { it.isDirectory && !it.name.startsWith('.') } .distinctBy { it.name } - .filter { // Filter by query or last modified + .filter { + // Filter by query or last modified if (lastModifiedLimit == 0L) { it.name.contains(query, ignoreCase = true) } else { @@ -134,7 +136,8 @@ class LocalSource( url = mangaDir.name // Try to find the cover - coverManager.find(mangaDir.name) + coverManager + .find(mangaDir.name) ?.takeIf(File::exists) ?.let { thumbnail_url = it.absolutePath } } @@ -238,7 +241,7 @@ class LocalSource( for (chapter in chapterArchives) { when (Format.valueOf(chapter)) { is Format.Zip -> { - ZipFile(chapter).use { zip: ZipFile -> + ZipFile.builder().setFile(chapter).get().use { zip: ZipFile -> zip.getEntry(COMIC_INFO_FILE)?.let { comicInfoFile -> zip.getInputStream(comicInfoFile).buffered().use { stream -> return copyComicInfoFile(stream, folderPath) @@ -264,13 +267,12 @@ class LocalSource( private fun copyComicInfoFile( comicInfoFileStream: InputStream, folderPath: String?, - ): File { - return File("$folderPath/$COMIC_INFO_FILE").apply { + ): File = + File("$folderPath/$COMIC_INFO_FILE").apply { outputStream().use { outputStream -> comicInfoFileStream.use { it.copyTo(outputStream) } } } - } @OptIn(ExperimentalXmlUtilApi::class) private fun setMangaDetailsFromComicInfoFile( @@ -286,8 +288,9 @@ class LocalSource( } // Chapters - override suspend fun getChapterList(manga: SManga): List { - return fileSystem.getFilesInMangaDirectory(manga.url) + override suspend fun getChapterList(manga: SManga): List = + fileSystem + .getFilesInMangaDirectory(manga.url) // Only keep supported formats .filter { it.isDirectory || Archive.isSupported(it) } .map { chapterFile -> @@ -312,22 +315,21 @@ class LocalSource( } } } - } - .sortedWith { c1, c2 -> + }.sortedWith { c1, c2 -> val c = c2.chapter_number.compareTo(c1.chapter_number) if (c == 0) c2.name.compareToCaseInsensitiveNaturalOrder(c1.name) else c - } - .toList() - } + }.toList() // Filters override fun getFilterList() = FilterList(OrderBy.Popular()) // TODO Fix Memory Leak - override suspend fun getPageList(chapter: SChapter): List { - return when (val format = getFormat(chapter)) { + override suspend fun getPageList(chapter: SChapter): List = + when (val format = getFormat(chapter)) { is Format.Directory -> { - format.file.listFiles().orEmpty() + format.file + .listFiles() + .orEmpty() .filter { !it.isDirectory && ImageUtil.isImage(it.name, it::inputStream) } .sortedWith { f1, f2 -> f1.name.compareToCaseInsensitiveNaturalOrder(f2.name) } .mapIndexed { index, page -> @@ -359,11 +361,11 @@ class LocalSource( pages } } - } fun getFormat(chapter: SChapter): Format { try { - return fileSystem.getBaseDirectories() + return fileSystem + .getBaseDirectories() .map { dir -> File(dir, chapter.url) } .find { it.exists() } ?.let(Format.Companion::valueOf) @@ -378,21 +380,23 @@ class LocalSource( private fun updateCover( chapter: SChapter, manga: SManga, - ): File? { - return try { + ): File? = + try { when (val format = getFormat(chapter)) { is Format.Directory -> { val entry = - format.file.listFiles() + format.file + .listFiles() ?.sortedWith { f1, f2 -> f1.name.compareToCaseInsensitiveNaturalOrder(f2.name) } ?.find { !it.isDirectory && ImageUtil.isImage(it.name) { FileInputStream(it) } } entry?.let { coverManager.update(manga, it.inputStream()) } } is Format.Zip -> { - ZipFile(format.file).use { zip -> + ZipFile.builder().setFile(format.file).get().use { zip -> val entry = - zip.entries.toList() + zip.entries + .toList() .sortedWith { f1, f2 -> f1.name.compareToCaseInsensitiveNaturalOrder(f2.name) } .find { !it.isDirectory && ImageUtil.isImage(it.name) { zip.getInputStream(it) } } @@ -412,7 +416,8 @@ class LocalSource( is Format.Epub -> { EpubFile(format.file).use { epub -> val entry = - epub.getImagesFromPages() + epub + .getImagesFromPages() .firstOrNull() ?.let { epub.getEntry(it) } @@ -424,7 +429,6 @@ class LocalSource( logger.error(e) { "Error updating cover for ${manga.title}" } null } - } companion object { const val ID = 0L diff --git a/server/src/main/kotlin/eu/kanade/tachiyomi/source/local/filter/OrderBy.kt b/server/src/main/kotlin/eu/kanade/tachiyomi/source/local/filter/OrderBy.kt index 68e57ff7..e3a148f4 100644 --- a/server/src/main/kotlin/eu/kanade/tachiyomi/source/local/filter/OrderBy.kt +++ b/server/src/main/kotlin/eu/kanade/tachiyomi/source/local/filter/OrderBy.kt @@ -2,12 +2,14 @@ package eu.kanade.tachiyomi.source.local.filter import eu.kanade.tachiyomi.source.model.Filter -sealed class OrderBy(selection: Selection) : Filter.Sort( - "Order by", - arrayOf("Title", "Date"), - selection, -) { - class Popular() : OrderBy(Selection(0, true)) +sealed class OrderBy( + selection: Selection, +) : Filter.Sort( + "Order by", + arrayOf("Title", "Date"), + selection, + ) { + class Popular : OrderBy(Selection(0, true)) - class Latest() : OrderBy(Selection(1, false)) + class Latest : OrderBy(Selection(1, false)) } diff --git a/server/src/main/kotlin/eu/kanade/tachiyomi/source/local/image/LocalCoverManager.kt b/server/src/main/kotlin/eu/kanade/tachiyomi/source/local/image/LocalCoverManager.kt index afd8e3ed..17fbf882 100644 --- a/server/src/main/kotlin/eu/kanade/tachiyomi/source/local/image/LocalCoverManager.kt +++ b/server/src/main/kotlin/eu/kanade/tachiyomi/source/local/image/LocalCoverManager.kt @@ -11,15 +11,15 @@ private const val DEFAULT_COVER_NAME = "cover.jpg" class LocalCoverManager( private val fileSystem: LocalSourceFileSystem, ) { - fun find(mangaUrl: String): File? { - return fileSystem.getFilesInMangaDirectory(mangaUrl) + fun find(mangaUrl: String): File? = + fileSystem + .getFilesInMangaDirectory(mangaUrl) // Get all file whose names start with 'cover' .filter { it.isFile && it.nameWithoutExtension.equals("cover", ignoreCase = true) } // Get the first actual image .firstOrNull { ImageUtil.isImage(it.name) { it.inputStream() } } - } fun update( manga: SManga, diff --git a/server/src/main/kotlin/eu/kanade/tachiyomi/source/local/io/Format.kt b/server/src/main/kotlin/eu/kanade/tachiyomi/source/local/io/Format.kt index 3a66b152..f1cb8d6a 100644 --- a/server/src/main/kotlin/eu/kanade/tachiyomi/source/local/io/Format.kt +++ b/server/src/main/kotlin/eu/kanade/tachiyomi/source/local/io/Format.kt @@ -3,13 +3,21 @@ package eu.kanade.tachiyomi.source.local.io import java.io.File sealed interface Format { - data class Directory(val file: File) : Format + data class Directory( + val file: File, + ) : Format - data class Zip(val file: File) : Format + data class Zip( + val file: File, + ) : Format - data class Rar(val file: File) : Format + data class Rar( + val file: File, + ) : Format - data class Epub(val file: File) : Format + data class Epub( + val file: File, + ) : Format class UnknownFormatException : Exception() diff --git a/server/src/main/kotlin/eu/kanade/tachiyomi/source/local/io/LocalSourceFileSystem.kt b/server/src/main/kotlin/eu/kanade/tachiyomi/source/local/io/LocalSourceFileSystem.kt index 44b3847d..46acc817 100644 --- a/server/src/main/kotlin/eu/kanade/tachiyomi/source/local/io/LocalSourceFileSystem.kt +++ b/server/src/main/kotlin/eu/kanade/tachiyomi/source/local/io/LocalSourceFileSystem.kt @@ -6,27 +6,22 @@ import java.io.File class LocalSourceFileSystem( private val applicationDirs: ApplicationDirs, ) { - fun getBaseDirectories(): Sequence { - return sequenceOf(File(applicationDirs.localMangaRoot)) - } + fun getBaseDirectories(): Sequence = sequenceOf(File(applicationDirs.localMangaRoot)) - fun getFilesInBaseDirectories(): Sequence { - return getBaseDirectories() + fun getFilesInBaseDirectories(): Sequence = + getBaseDirectories() // Get all the files inside all baseDir .flatMap { it.listFiles().orEmpty().toList() } - } - fun getMangaDirectory(name: String): File? { - return getFilesInBaseDirectories() + fun getMangaDirectory(name: String): File? = + getFilesInBaseDirectories() // Get the first mangaDir or null .firstOrNull { it.isDirectory && it.name == name } - } - fun getFilesInMangaDirectory(name: String): Sequence { - return getFilesInBaseDirectories() + fun getFilesInMangaDirectory(name: String): Sequence = + getFilesInBaseDirectories() // Filter out ones that are not related to the manga and is not a directory .filter { it.isDirectory && it.name == name } // Get all the files inside the filtered folders .flatMap { it.listFiles().orEmpty().toList() } - } } diff --git a/server/src/main/kotlin/eu/kanade/tachiyomi/source/local/loader/EpubPageLoader.kt b/server/src/main/kotlin/eu/kanade/tachiyomi/source/local/loader/EpubPageLoader.kt index d0227b5e..46c5d70d 100644 --- a/server/src/main/kotlin/eu/kanade/tachiyomi/source/local/loader/EpubPageLoader.kt +++ b/server/src/main/kotlin/eu/kanade/tachiyomi/source/local/loader/EpubPageLoader.kt @@ -6,18 +6,20 @@ import java.io.File /** * Loader used to load a chapter from a .epub file. */ -class EpubPageLoader(file: File) : PageLoader { +class EpubPageLoader( + file: File, +) : PageLoader { private val epub = EpubFile(file) - override suspend fun getPages(): List { - return epub.getImagesFromPages() + override suspend fun getPages(): List = + epub + .getImagesFromPages() .mapIndexed { i, path -> val streamFn = { epub.getInputStream(epub.getEntry(path)!!) } ReaderPage(i).apply { stream = streamFn } } - } override fun recycle() { epub.close() diff --git a/server/src/main/kotlin/eu/kanade/tachiyomi/source/local/loader/RarPageLoader.kt b/server/src/main/kotlin/eu/kanade/tachiyomi/source/local/loader/RarPageLoader.kt index 0c161dea..bdde0d9c 100644 --- a/server/src/main/kotlin/eu/kanade/tachiyomi/source/local/loader/RarPageLoader.kt +++ b/server/src/main/kotlin/eu/kanade/tachiyomi/source/local/loader/RarPageLoader.kt @@ -12,20 +12,21 @@ import java.io.PipedOutputStream /** * Loader used to load a chapter from a .rar or .cbr file. */ -class RarPageLoader(file: File) : PageLoader { +class RarPageLoader( + file: File, +) : PageLoader { private val rar = Archive(file) - override suspend fun getPages(): List { - return rar.fileHeaders.asSequence() + override suspend fun getPages(): List = + rar.fileHeaders + .asSequence() .filter { !it.isDirectory && ImageUtil.isImage(it.fileName) { rar.getInputStream(it) } } .sortedWith { f1, f2 -> f1.fileName.compareToCaseInsensitiveNaturalOrder(f2.fileName) } .mapIndexed { i, header -> ReaderPage(i).apply { stream = { getStream(rar, header) } } - } - .toList() - } + }.toList() override fun recycle() { rar.close() diff --git a/server/src/main/kotlin/eu/kanade/tachiyomi/source/local/loader/ZipPageLoader.kt b/server/src/main/kotlin/eu/kanade/tachiyomi/source/local/loader/ZipPageLoader.kt index acd36ac2..e0909514 100644 --- a/server/src/main/kotlin/eu/kanade/tachiyomi/source/local/loader/ZipPageLoader.kt +++ b/server/src/main/kotlin/eu/kanade/tachiyomi/source/local/loader/ZipPageLoader.kt @@ -8,20 +8,21 @@ import java.io.File /** * Loader used to load a chapter from a .zip or .cbz file. */ -class ZipPageLoader(file: File) : PageLoader { - private val zip = ZipFile(file) +class ZipPageLoader( + file: File, +) : PageLoader { + private val zip = ZipFile.builder().setFile(file).get() - override suspend fun getPages(): List { - return zip.entries.asSequence() + override suspend fun getPages(): List = + zip.entries + .asSequence() .filter { !it.isDirectory && ImageUtil.isImage(it.name) { zip.getInputStream(it) } } .sortedWith { f1, f2 -> f1.name.compareToCaseInsensitiveNaturalOrder(f2.name) } .mapIndexed { i, entry -> ReaderPage(i).apply { stream = { zip.getInputStream(entry) } } - } - .toList() - } + }.toList() override fun recycle() { zip.close() diff --git a/server/src/main/kotlin/eu/kanade/tachiyomi/source/local/metadata/ComicInfo.kt b/server/src/main/kotlin/eu/kanade/tachiyomi/source/local/metadata/ComicInfo.kt index e299c24a..22afb967 100644 --- a/server/src/main/kotlin/eu/kanade/tachiyomi/source/local/metadata/ComicInfo.kt +++ b/server/src/main/kotlin/eu/kanade/tachiyomi/source/local/metadata/ComicInfo.kt @@ -17,8 +17,7 @@ fun SManga.copyFromComicInfo(comicInfo: ComicInfo) { comicInfo.genre?.value, comicInfo.tags?.value, comicInfo.categories?.value, - ) - .distinct() + ).distinct() .joinToString(", ") { it.trim() } .takeIf { it.isNotEmpty() } ?.let { genre = it } @@ -29,8 +28,7 @@ fun SManga.copyFromComicInfo(comicInfo: ComicInfo) { comicInfo.colorist?.value, comicInfo.letterer?.value, comicInfo.coverArtist?.value, - ) - .flatMap { it.split(", ") } + ).flatMap { it.split(", ") } .distinct() .joinToString(", ") { it.trim() } .takeIf { it.isNotEmpty() } @@ -202,14 +200,12 @@ enum class ComicInfoPublishingStatus( ; companion object { - fun toComicInfoValue(value: Long): String { - return entries.firstOrNull { it.sMangaModelValue == value.toInt() }?.comicInfoValue + fun toComicInfoValue(value: Long): String = + entries.firstOrNull { it.sMangaModelValue == value.toInt() }?.comicInfoValue ?: UNKNOWN.comicInfoValue - } - fun toSMangaValue(value: String?): Int { - return entries.firstOrNull { it.comicInfoValue == value }?.sMangaModelValue + fun toSMangaValue(value: String?): Int = + entries.firstOrNull { it.comicInfoValue == value }?.sMangaModelValue ?: UNKNOWN.sMangaModelValue - } } } diff --git a/server/src/main/kotlin/eu/kanade/tachiyomi/source/model/Filter.kt b/server/src/main/kotlin/eu/kanade/tachiyomi/source/model/Filter.kt index 1def3d56..78f37cd5 100644 --- a/server/src/main/kotlin/eu/kanade/tachiyomi/source/model/Filter.kt +++ b/server/src/main/kotlin/eu/kanade/tachiyomi/source/model/Filter.kt @@ -2,20 +2,40 @@ package eu.kanade.tachiyomi.source.model // The class is originally sealed, Tachidesk adds new subclasses for serialization // sealed class Filter(val name: String, var state: T) { -open class Filter(val name: String, var state: T) { - open class Header(name: String) : Filter(name, 0) +open class Filter( + val name: String, + var state: T, +) { + open class Header( + name: String, + ) : Filter(name, 0) - open class Separator(name: String = "") : Filter(name, 0) + open class Separator( + name: String = "", + ) : Filter(name, 0) - abstract class Select(name: String, val values: Array, state: Int = 0) : Filter(name, state) { + abstract class Select( + name: String, + val values: Array, + state: Int = 0, + ) : Filter(name, state) { val displayValues get() = values.map { it.toString() } } - abstract class Text(name: String, state: String = "") : Filter(name, state) + abstract class Text( + name: String, + state: String = "", + ) : Filter(name, state) - abstract class CheckBox(name: String, state: Boolean = false) : Filter(name, state) + abstract class CheckBox( + name: String, + state: Boolean = false, + ) : Filter(name, state) - abstract class TriState(name: String, state: Int = STATE_IGNORE) : Filter(name, state) { + abstract class TriState( + name: String, + state: Int = STATE_IGNORE, + ) : Filter(name, state) { fun isIgnored() = state == STATE_IGNORE fun isIncluded() = state == STATE_INCLUDE @@ -29,11 +49,20 @@ open class Filter(val name: String, var state: T) { } } - abstract class Group(name: String, state: List) : Filter>(name, state) + abstract class Group( + name: String, + state: List, + ) : Filter>(name, state) - abstract class Sort(name: String, val values: Array, state: Selection? = null) : - Filter(name, state) { - data class Selection(val index: Int, val ascending: Boolean) + abstract class Sort( + name: String, + val values: Array, + state: Selection? = null, + ) : Filter(name, state) { + data class Selection( + val index: Int, + val ascending: Boolean, + ) } override fun equals(other: Any?): Boolean { diff --git a/server/src/main/kotlin/eu/kanade/tachiyomi/source/model/FilterList.kt b/server/src/main/kotlin/eu/kanade/tachiyomi/source/model/FilterList.kt index c05951fa..699d7774 100644 --- a/server/src/main/kotlin/eu/kanade/tachiyomi/source/model/FilterList.kt +++ b/server/src/main/kotlin/eu/kanade/tachiyomi/source/model/FilterList.kt @@ -1,5 +1,7 @@ package eu.kanade.tachiyomi.source.model -data class FilterList(val list: List>) : List> by list { +data class FilterList( + val list: List>, +) : List> by list { constructor(vararg fs: Filter<*>) : this(if (fs.isNotEmpty()) fs.asList() else emptyList()) } diff --git a/server/src/main/kotlin/eu/kanade/tachiyomi/source/model/MangasPage.kt b/server/src/main/kotlin/eu/kanade/tachiyomi/source/model/MangasPage.kt index a377c36e..cda439bf 100644 --- a/server/src/main/kotlin/eu/kanade/tachiyomi/source/model/MangasPage.kt +++ b/server/src/main/kotlin/eu/kanade/tachiyomi/source/model/MangasPage.kt @@ -1,3 +1,6 @@ package eu.kanade.tachiyomi.source.model -data class MangasPage(val mangas: List, val hasNextPage: Boolean) +data class MangasPage( + val mangas: List, + val hasNextPage: Boolean, +) diff --git a/server/src/main/kotlin/eu/kanade/tachiyomi/source/model/SChapter.kt b/server/src/main/kotlin/eu/kanade/tachiyomi/source/model/SChapter.kt index d1d5243c..5ae70aa2 100644 --- a/server/src/main/kotlin/eu/kanade/tachiyomi/source/model/SChapter.kt +++ b/server/src/main/kotlin/eu/kanade/tachiyomi/source/model/SChapter.kt @@ -24,8 +24,6 @@ interface SChapter : Serializable { } companion object { - fun create(): SChapter { - return SChapterImpl() - } + fun create(): SChapter = SChapterImpl() } } diff --git a/server/src/main/kotlin/eu/kanade/tachiyomi/source/model/SManga.kt b/server/src/main/kotlin/eu/kanade/tachiyomi/source/model/SManga.kt index da53e3db..d4652ac8 100644 --- a/server/src/main/kotlin/eu/kanade/tachiyomi/source/model/SManga.kt +++ b/server/src/main/kotlin/eu/kanade/tachiyomi/source/model/SManga.kt @@ -62,9 +62,7 @@ interface SManga : Serializable { const val CANCELLED = 5 const val ON_HIATUS = 6 - fun create(): SManga { - return SMangaImpl() - } + fun create(): SManga = SMangaImpl() } } diff --git a/server/src/main/kotlin/eu/kanade/tachiyomi/source/online/HttpSource.kt b/server/src/main/kotlin/eu/kanade/tachiyomi/source/online/HttpSource.kt index 88b9dc70..966b67c4 100644 --- a/server/src/main/kotlin/eu/kanade/tachiyomi/source/online/HttpSource.kt +++ b/server/src/main/kotlin/eu/kanade/tachiyomi/source/online/HttpSource.kt @@ -66,9 +66,7 @@ abstract class HttpSource : CatalogueSource { open val client: OkHttpClient get() = network.client - private fun generateId(): Long { - return generateId("${name.lowercase()}/$lang/$versionId") - } + private fun generateId(): Long = generateId("${name.lowercase()}/$lang/$versionId") /** * Generates a unique ID for the source based on the provided [name], [lang] and @@ -121,13 +119,13 @@ abstract class HttpSource : CatalogueSource { * @param page the page number to retrieve. */ @Deprecated("Use the non-RxJava API instead", replaceWith = ReplaceWith("getPopularManga")) - override fun fetchPopularManga(page: Int): Observable { - return client.newCall(popularMangaRequest(page)) + override fun fetchPopularManga(page: Int): Observable = + client + .newCall(popularMangaRequest(page)) .asObservableSuccess() .map { response -> popularMangaParse(response) } - } /** * Returns the request for the popular manga given the page. @@ -156,20 +154,19 @@ abstract class HttpSource : CatalogueSource { page: Int, query: String, filters: FilterList, - ): Observable { - return Observable.defer { - try { - client.newCall(searchMangaRequest(page, query, filters)).asObservableSuccess() - } catch (e: NoClassDefFoundError) { - // RxJava doesn't handle Errors, which tends to happen during global searches - // if an old extension using non-existent classes is still around - throw RuntimeException(e) - } - } - .map { response -> + ): Observable = + Observable + .defer { + try { + client.newCall(searchMangaRequest(page, query, filters)).asObservableSuccess() + } catch (e: NoClassDefFoundError) { + // RxJava doesn't handle Errors, which tends to happen during global searches + // if an old extension using non-existent classes is still around + throw RuntimeException(e) + } + }.map { response -> searchMangaParse(response) } - } /** * Returns the request for the search manga given the page. @@ -197,13 +194,13 @@ abstract class HttpSource : CatalogueSource { * @param page the page number to retrieve. */ @Deprecated("Use the non-RxJava API instead", replaceWith = ReplaceWith("getLatestUpdates")) - override fun fetchLatestUpdates(page: Int): Observable { - return client.newCall(latestUpdatesRequest(page)) + override fun fetchLatestUpdates(page: Int): Observable = + client + .newCall(latestUpdatesRequest(page)) .asObservableSuccess() .map { response -> latestUpdatesParse(response) } - } /** * Returns the request for latest manga given the page. @@ -227,18 +224,16 @@ abstract class HttpSource : CatalogueSource { * @return the updated manga. */ @Suppress("DEPRECATION") - override suspend fun getMangaDetails(manga: SManga): SManga { - return fetchMangaDetails(manga).awaitSingle() - } + override suspend fun getMangaDetails(manga: SManga): SManga = fetchMangaDetails(manga).awaitSingle() @Deprecated("Use the non-RxJava API instead", replaceWith = ReplaceWith("getMangaDetails")) - override fun fetchMangaDetails(manga: SManga): Observable { - return client.newCall(mangaDetailsRequest(manga)) + override fun fetchMangaDetails(manga: SManga): Observable = + client + .newCall(mangaDetailsRequest(manga)) .asObservableSuccess() .map { response -> mangaDetailsParse(response).apply { initialized = true } } - } /** * Returns the request for the details of a manga. Override only if it's needed to change the @@ -246,9 +241,7 @@ abstract class HttpSource : CatalogueSource { * * @param manga the manga to be updated. */ - open fun mangaDetailsRequest(manga: SManga): Request { - return GET(baseUrl + manga.url, headers) - } + open fun mangaDetailsRequest(manga: SManga): Request = GET(baseUrl + manga.url, headers) /** * Parses the response from the site and returns the details of a manga. @@ -275,9 +268,10 @@ abstract class HttpSource : CatalogueSource { } @Deprecated("Use the non-RxJava API instead", replaceWith = ReplaceWith("getChapterList")) - override fun fetchChapterList(manga: SManga): Observable> { - return if (manga.status != SManga.LICENSED) { - client.newCall(chapterListRequest(manga)) + override fun fetchChapterList(manga: SManga): Observable> = + if (manga.status != SManga.LICENSED) { + client + .newCall(chapterListRequest(manga)) .asObservableSuccess() .map { response -> chapterListParse(response) @@ -285,7 +279,6 @@ abstract class HttpSource : CatalogueSource { } else { Observable.error(LicensedMangaChaptersException()) } - } /** * Returns the request for updating the chapter list. Override only if it's needed to override @@ -293,9 +286,7 @@ abstract class HttpSource : CatalogueSource { * * @param manga the manga to look for chapters. */ - protected open fun chapterListRequest(manga: SManga): Request { - return GET(baseUrl + manga.url, headers) - } + protected open fun chapterListRequest(manga: SManga): Request = GET(baseUrl + manga.url, headers) /** * Parses the response from the site and returns a list of chapters. @@ -312,18 +303,16 @@ abstract class HttpSource : CatalogueSource { * @return the pages for the chapter. */ @Suppress("DEPRECATION") - override suspend fun getPageList(chapter: SChapter): List { - return fetchPageList(chapter).awaitSingle() - } + override suspend fun getPageList(chapter: SChapter): List = fetchPageList(chapter).awaitSingle() @Deprecated("Use the non-RxJava API instead", replaceWith = ReplaceWith("getPageList")) - override fun fetchPageList(chapter: SChapter): Observable> { - return client.newCall(pageListRequest(chapter)) + override fun fetchPageList(chapter: SChapter): Observable> = + client + .newCall(pageListRequest(chapter)) .asObservableSuccess() .map { response -> pageListParse(response) } - } /** * Returns the request for getting the page list. Override only if it's needed to override the @@ -331,9 +320,7 @@ abstract class HttpSource : CatalogueSource { * * @param chapter the chapter whose page list has to be fetched. */ - protected open fun pageListRequest(chapter: SChapter): Request { - return GET(baseUrl + chapter.url, headers) - } + protected open fun pageListRequest(chapter: SChapter): Request = GET(baseUrl + chapter.url, headers) /** * Parses the response from the site and returns a list of pages. @@ -350,16 +337,14 @@ abstract class HttpSource : CatalogueSource { * @param page the page whose source image has to be fetched. */ @Suppress("DEPRECATION") - open suspend fun getImageUrl(page: Page): String { - return fetchImageUrl(page).awaitSingle() - } + open suspend fun getImageUrl(page: Page): String = fetchImageUrl(page).awaitSingle() @Deprecated("Use the non-RxJava API instead", replaceWith = ReplaceWith("getImageUrl")) - open fun fetchImageUrl(page: Page): Observable { - return client.newCall(imageUrlRequest(page)) + open fun fetchImageUrl(page: Page): Observable = + client + .newCall(imageUrlRequest(page)) .asObservableSuccess() .map { imageUrlParse(it) } - } /** * Returns the request for getting the url to the source image. Override only if it's needed to @@ -367,9 +352,7 @@ abstract class HttpSource : CatalogueSource { * * @param page the chapter whose page list has to be fetched */ - protected open fun imageUrlRequest(page: Page): Request { - return GET(page.url, headers) - } + protected open fun imageUrlRequest(page: Page): Request = GET(page.url, headers) /** * Parses the response from the site and returns the absolute url to the source image. @@ -385,10 +368,10 @@ abstract class HttpSource : CatalogueSource { * @since extensions-lib 1.5 * @param page the page whose source image has to be downloaded. */ - open suspend fun getImage(page: Page): Response { - return client.newCachelessCallWithProgress(imageRequest(page), page) + open suspend fun getImage(page: Page): Response = + client + .newCachelessCallWithProgress(imageRequest(page), page) .awaitSuccess() - } /** * Returns the request for getting the source image. Override only if it's needed to override @@ -396,9 +379,7 @@ abstract class HttpSource : CatalogueSource { * * @param page the chapter whose page list has to be fetched */ - protected open fun imageRequest(page: Page): Request { - return GET(page.imageUrl!!, headers) - } + protected open fun imageRequest(page: Page): Request = GET(page.imageUrl!!, headers) /** * Assigns the url of the chapter without the scheme and domain. It saves some redundancy from @@ -425,8 +406,8 @@ abstract class HttpSource : CatalogueSource { * * @param orig the full url. */ - private fun getUrlWithoutDomain(orig: String): String { - return try { + private fun getUrlWithoutDomain(orig: String): String = + try { val uri = URI(orig.replace(" ", "%20")) var out = uri.path if (uri.query != null) { @@ -439,7 +420,6 @@ abstract class HttpSource : CatalogueSource { } catch (e: URISyntaxException) { orig } - } /** * Returns the url of the provided manga @@ -448,9 +428,7 @@ abstract class HttpSource : CatalogueSource { * @param manga the manga * @return url of the manga */ - open fun getMangaUrl(manga: SManga): String { - return mangaDetailsRequest(manga).url.toString() - } + open fun getMangaUrl(manga: SManga): String = mangaDetailsRequest(manga).url.toString() /** * Returns the url of the provided chapter @@ -459,9 +437,7 @@ abstract class HttpSource : CatalogueSource { * @param chapter the chapter * @return url of the chapter */ - open fun getChapterUrl(chapter: SChapter): String { - return pageListRequest(chapter).url.toString() - } + open fun getChapterUrl(chapter: SChapter): String = pageListRequest(chapter).url.toString() /** * Called before inserting a new chapter into database. Use it if you need to override chapter diff --git a/server/src/main/kotlin/eu/kanade/tachiyomi/source/online/ParsedHttpSource.kt b/server/src/main/kotlin/eu/kanade/tachiyomi/source/online/ParsedHttpSource.kt index 319a639a..66db603b 100644 --- a/server/src/main/kotlin/eu/kanade/tachiyomi/source/online/ParsedHttpSource.kt +++ b/server/src/main/kotlin/eu/kanade/tachiyomi/source/online/ParsedHttpSource.kt @@ -138,9 +138,7 @@ abstract class ParsedHttpSource : HttpSource() { * * @param response the response from the site. */ - override fun mangaDetailsParse(response: Response): SManga { - return mangaDetailsParse(response.asJsoup()) - } + override fun mangaDetailsParse(response: Response): SManga = mangaDetailsParse(response.asJsoup()) /** * Returns the details of the manga from the given [document]. @@ -176,9 +174,7 @@ abstract class ParsedHttpSource : HttpSource() { * * @param response the response from the site. */ - override fun pageListParse(response: Response): List { - return pageListParse(response.asJsoup()) - } + override fun pageListParse(response: Response): List = pageListParse(response.asJsoup()) /** * Returns a page list from the given document. @@ -192,9 +188,7 @@ abstract class ParsedHttpSource : HttpSource() { * * @param response the response from the site. */ - override fun imageUrlParse(response: Response): String { - return imageUrlParse(response.asJsoup()) - } + override fun imageUrlParse(response: Response): String = imageUrlParse(response.asJsoup()) /** * Returns the absolute url to the source image from the document. diff --git a/server/src/main/kotlin/eu/kanade/tachiyomi/util/JsoupExtensions.kt b/server/src/main/kotlin/eu/kanade/tachiyomi/util/JsoupExtensions.kt index 65245031..b9169076 100644 --- a/server/src/main/kotlin/eu/kanade/tachiyomi/util/JsoupExtensions.kt +++ b/server/src/main/kotlin/eu/kanade/tachiyomi/util/JsoupExtensions.kt @@ -8,25 +8,17 @@ import org.jsoup.nodes.Element fun Element.selectText( css: String, defaultValue: String? = null, -): String? { - return select(css).first()?.text() ?: defaultValue -} +): String? = select(css).first()?.text() ?: defaultValue fun Element.selectInt( css: String, defaultValue: Int = 0, -): Int { - return select(css).first()?.text()?.toInt() ?: defaultValue -} +): Int = select(css).first()?.text()?.toInt() ?: defaultValue -fun Element.attrOrText(css: String): String { - return if (css != "text") attr(css) else text() -} +fun Element.attrOrText(css: String): String = if (css != "text") attr(css) else text() /** * Returns a Jsoup document for this response. * @param html the body of the response. Use only if the body was read before calling this method. */ -fun Response.asJsoup(html: String? = null): Document { - return Jsoup.parse(html ?: body.string(), request.url.toString()) -} +fun Response.asJsoup(html: String? = null): Document = Jsoup.parse(html ?: body.string(), request.url.toString()) diff --git a/server/src/main/kotlin/eu/kanade/tachiyomi/util/chapter/ChapterRecognition.kt b/server/src/main/kotlin/eu/kanade/tachiyomi/util/chapter/ChapterRecognition.kt index 04fcedaa..0e565ceb 100644 --- a/server/src/main/kotlin/eu/kanade/tachiyomi/util/chapter/ChapterRecognition.kt +++ b/server/src/main/kotlin/eu/kanade/tachiyomi/util/chapter/ChapterRecognition.kt @@ -68,15 +68,14 @@ object ChapterRecognition { * @param match result of regex * @return chapter number if found else null */ - private fun getChapterNumberFromMatch(match: MatchResult): Double { - return match.let { + private fun getChapterNumberFromMatch(match: MatchResult): Double = + match.let { val initial = it.groups[1]?.value?.toDouble()!! val subChapterDecimal = it.groups[2]?.value val subChapterAlpha = it.groups[3]?.value val addition = checkForDecimal(subChapterDecimal, subChapterAlpha) initial.plus(addition) } - } /** * Check for decimal in received strings diff --git a/server/src/main/kotlin/eu/kanade/tachiyomi/util/chapter/ChapterSanitizer.kt b/server/src/main/kotlin/eu/kanade/tachiyomi/util/chapter/ChapterSanitizer.kt index 03f4be03..dd4bcfe8 100644 --- a/server/src/main/kotlin/eu/kanade/tachiyomi/util/chapter/ChapterSanitizer.kt +++ b/server/src/main/kotlin/eu/kanade/tachiyomi/util/chapter/ChapterSanitizer.kt @@ -1,11 +1,10 @@ package eu.kanade.tachiyomi.util.chapter object ChapterSanitizer { - fun String.sanitize(title: String): String { - return trim() + fun String.sanitize(title: String): String = + trim() .removePrefix(title) .trim(*CHAPTER_TRIM_CHARS) - } private val CHAPTER_TRIM_CHARS = arrayOf( diff --git a/server/src/main/kotlin/eu/kanade/tachiyomi/util/lang/Hash.kt b/server/src/main/kotlin/eu/kanade/tachiyomi/util/lang/Hash.kt index 8e289b3a..cdb3f17a 100644 --- a/server/src/main/kotlin/eu/kanade/tachiyomi/util/lang/Hash.kt +++ b/server/src/main/kotlin/eu/kanade/tachiyomi/util/lang/Hash.kt @@ -5,29 +5,35 @@ import java.security.MessageDigest object Hash { private val chars = charArrayOf( - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - 'a', 'b', 'c', 'd', 'e', 'f', + '0', + '1', + '2', + '3', + '4', + '5', + '6', + '7', + '8', + '9', + 'a', + 'b', + 'c', + 'd', + 'e', + 'f', ) private val MD5 get() = MessageDigest.getInstance("MD5") private val SHA256 get() = MessageDigest.getInstance("SHA-256") - fun sha256(bytes: ByteArray): String { - return encodeHex(SHA256.digest(bytes)) - } + fun sha256(bytes: ByteArray): String = encodeHex(SHA256.digest(bytes)) - fun sha256(string: String): String { - return sha256(string.toByteArray()) - } + fun sha256(string: String): String = sha256(string.toByteArray()) - fun md5(bytes: ByteArray): String { - return encodeHex(MD5.digest(bytes)) - } + fun md5(bytes: ByteArray): String = encodeHex(MD5.digest(bytes)) - fun md5(string: String): String { - return md5(string.toByteArray()) - } + fun md5(string: String): String = md5(string.toByteArray()) private fun encodeHex(data: ByteArray): String { val l = data.size diff --git a/server/src/main/kotlin/eu/kanade/tachiyomi/util/lang/StringExtensions.kt b/server/src/main/kotlin/eu/kanade/tachiyomi/util/lang/StringExtensions.kt index 52a5a061..eceb6cf9 100644 --- a/server/src/main/kotlin/eu/kanade/tachiyomi/util/lang/StringExtensions.kt +++ b/server/src/main/kotlin/eu/kanade/tachiyomi/util/lang/StringExtensions.kt @@ -10,13 +10,12 @@ import kotlin.math.floor fun String.chop( count: Int, replacement: String = "…", -): String { - return if (length > count) { +): String = + if (length > count) { take(count - replacement.length) + replacement } else { this } -} /** * Replaces the given string to have at most [count] characters using [replacement] near the center. @@ -46,9 +45,7 @@ fun String.compareToCaseInsensitiveNaturalOrder(other: String): Int { /** * Returns the size of the string as the number of bytes. */ -fun String.byteSize(): Int { - return toByteArray(Charsets.UTF_8).size -} +fun String.byteSize(): Int = toByteArray(Charsets.UTF_8).size /** * Returns a string containing the first [n] bytes from this string, or the entire string if this diff --git a/server/src/main/kotlin/eu/kanade/tachiyomi/util/storage/EpubFile.kt b/server/src/main/kotlin/eu/kanade/tachiyomi/util/storage/EpubFile.kt index f72b9455..4270e80a 100644 --- a/server/src/main/kotlin/eu/kanade/tachiyomi/util/storage/EpubFile.kt +++ b/server/src/main/kotlin/eu/kanade/tachiyomi/util/storage/EpubFile.kt @@ -11,11 +11,13 @@ import java.io.InputStream /** * Wrapper over ZipFile to load files in epub format. */ -class EpubFile(file: File) : Closeable { +class EpubFile( + file: File, +) : Closeable { /** * Zip file of this epub. */ - private val zip = ZipFile(file) + private val zip = ZipFile.builder().setFile(file).get() /** * Path separator used by this epub. @@ -32,16 +34,12 @@ class EpubFile(file: File) : Closeable { /** * Returns an input stream for reading the contents of the specified zip file entry. */ - fun getInputStream(entry: ZipArchiveEntry): InputStream { - return zip.getInputStream(entry) - } + fun getInputStream(entry: ZipArchiveEntry): InputStream = zip.getInputStream(entry) /** * Returns the zip file entry for the specified name, or null if not found. */ - fun getEntry(name: String): ZipArchiveEntry? { - return zip.getEntry(name) - } + fun getEntry(name: String): ZipArchiveEntry? = zip.getEntry(name) /** * Returns the path of all the images found in the epub file. @@ -81,7 +79,8 @@ class EpubFile(file: File) : Closeable { */ fun getPagesFromDocument(document: Document): List { val pages = - document.select("manifest > item") + document + .select("manifest > item") .filter { node -> "application/xhtml+xml" == node.attr("media-type") } .associateBy { it.attr("id") } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/global/impl/About.kt b/server/src/main/kotlin/suwayomi/tachidesk/global/impl/About.kt index a125a224..e0b5b1bc 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/global/impl/About.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/global/impl/About.kt @@ -20,8 +20,8 @@ data class AboutDataClass( ) object About { - fun getAbout(): AboutDataClass { - return AboutDataClass( + fun getAbout(): AboutDataClass = + AboutDataClass( BuildConfig.NAME, BuildConfig.VERSION, BuildConfig.REVISION, @@ -30,5 +30,4 @@ object About { BuildConfig.GITHUB, BuildConfig.DISCORD, ) - } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/global/impl/AppUpdate.kt b/server/src/main/kotlin/suwayomi/tachidesk/global/impl/AppUpdate.kt index aa2bac5e..7bd8ce60 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/global/impl/AppUpdate.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/global/impl/AppUpdate.kt @@ -31,18 +31,26 @@ object AppUpdate { suspend fun checkUpdate(): List { val stableJson = - json.parseToJsonElement( - network.client.newCall( - GET(LATEST_STABLE_CHANNEL_URL), - ).await().body.string(), - ).jsonObject + json + .parseToJsonElement( + network.client + .newCall( + GET(LATEST_STABLE_CHANNEL_URL), + ).await() + .body + .string(), + ).jsonObject val previewJson = - json.parseToJsonElement( - network.client.newCall( - GET(LATEST_PREVIEW_CHANNEL_URL), - ).await().body.string(), - ).jsonObject + json + .parseToJsonElement( + network.client + .newCall( + GET(LATEST_PREVIEW_CHANNEL_URL), + ).await() + .body + .string(), + ).jsonObject return listOf( UpdateDataClass( diff --git a/server/src/main/kotlin/suwayomi/tachidesk/global/impl/GlobalMeta.kt b/server/src/main/kotlin/suwayomi/tachidesk/global/impl/GlobalMeta.kt index e4c368f8..caab68ed 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/global/impl/GlobalMeta.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/global/impl/GlobalMeta.kt @@ -38,10 +38,10 @@ object GlobalMeta { } } - fun getMetaMap(): Map { - return transaction { - GlobalMetaTable.selectAll() + fun getMetaMap(): Map = + transaction { + GlobalMetaTable + .selectAll() .associate { it[GlobalMetaTable.key] to it[GlobalMetaTable.value] } } - } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/AsDataFetcherResult.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/AsDataFetcherResult.kt index 76fdeb8e..f1e71d03 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/AsDataFetcherResult.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/AsDataFetcherResult.kt @@ -14,12 +14,14 @@ inline fun asDataFetcherResult(block: () -> T): DataFetcherResult { if (result.isFailure) { logger.error(result.exceptionOrNull()) { "asDataFetcherResult: failed due to" } - return DataFetcherResult.newResult() + return DataFetcherResult + .newResult() .error(result.exceptionOrNull()?.toGraphQLError()) .build() } - return DataFetcherResult.newResult() + return DataFetcherResult + .newResult() .data(result.getOrNull()) .build() } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/cache/CustomCacheMap.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/cache/CustomCacheMap.kt index a6660f6c..742da59a 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/cache/CustomCacheMap.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/cache/CustomCacheMap.kt @@ -10,21 +10,13 @@ class CustomCacheMap : CacheMap { cache = HashMap() } - override fun containsKey(key: K): Boolean { - return cache.containsKey(key) - } + override fun containsKey(key: K): Boolean = cache.containsKey(key) - override fun get(key: K): CompletableFuture { - return cache[key]!! - } + override fun get(key: K): CompletableFuture = cache[key]!! - fun getKeys(): Collection { - return cache.keys.toSet() - } + fun getKeys(): Collection = cache.keys.toSet() - override fun getAll(): Collection> { - return cache.values - } + override fun getAll(): Collection> = cache.values override fun set( key: K, diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/CategoryDataLoader.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/CategoryDataLoader.kt index 190fe634..6261ad2c 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/CategoryDataLoader.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/CategoryDataLoader.kt @@ -30,7 +30,8 @@ class CategoryDataLoader : KotlinDataLoader { transaction { addLogger(Slf4jSqlDebugLogger) val categories = - CategoryTable.select { CategoryTable.id inList ids } + CategoryTable + .select { CategoryTable.id inList ids } .map { CategoryType(it) } .associateBy { it.id } ids.map { categories[it] } @@ -66,7 +67,8 @@ class CategoriesForMangaDataLoader : KotlinDataLoader { transaction { addLogger(Slf4jSqlDebugLogger) val itemsByRef = - CategoryMangaTable.innerJoin(CategoryTable) + CategoryMangaTable + .innerJoin(CategoryTable) .select { CategoryMangaTable.manga inList ids } .map { Pair(it[CategoryMangaTable.manga].value, CategoryType(it)) } .groupBy { it.first } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/ChapterDataLoader.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/ChapterDataLoader.kt index 230772d2..e4e3281c 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/ChapterDataLoader.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/ChapterDataLoader.kt @@ -32,7 +32,8 @@ class ChapterDataLoader : KotlinDataLoader { transaction { addLogger(Slf4jSqlDebugLogger) val chapters = - ChapterTable.select { ChapterTable.id inList ids } + ChapterTable + .select { ChapterTable.id inList ids } .map { ChapterType(it) } .associateBy { it.id } ids.map { chapters[it] } @@ -50,7 +51,8 @@ class ChaptersForMangaDataLoader : KotlinDataLoader { transaction { addLogger(Slf4jSqlDebugLogger) val chaptersByMangaId = - ChapterTable.select { ChapterTable.manga inList ids } + ChapterTable + .select { ChapterTable.manga inList ids } .map { ChapterType(it) } .groupBy { it.mangaId } ids.map { (chaptersByMangaId[it] ?: emptyList()).toNodeList() } @@ -128,7 +130,8 @@ class HasDuplicateChaptersForMangaDataLoader : KotlinDataLoader { transaction { addLogger(Slf4jSqlDebugLogger) val duplicatedChapterCountByMangaId = - ChapterTable.slice(ChapterTable.manga, ChapterTable.chapter_number, ChapterTable.chapter_number.count()) + ChapterTable + .slice(ChapterTable.manga, ChapterTable.chapter_number, ChapterTable.chapter_number.count()) .select { (ChapterTable.manga inList ids) and (ChapterTable.chapter_number greaterEq 0f) } .groupBy(ChapterTable.manga, ChapterTable.chapter_number) .having { ChapterTable.chapter_number.count() greater 1 } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/ExtensionDataLoader.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/ExtensionDataLoader.kt index 6f1433f0..91280f15 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/ExtensionDataLoader.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/ExtensionDataLoader.kt @@ -28,7 +28,8 @@ class ExtensionDataLoader : KotlinDataLoader { transaction { addLogger(Slf4jSqlDebugLogger) val extensions = - ExtensionTable.select { ExtensionTable.pkgName inList ids } + ExtensionTable + .select { ExtensionTable.pkgName inList ids } .map { ExtensionType(it) } .associateBy { it.pkgName } ids.map { extensions[it] } @@ -46,7 +47,8 @@ class ExtensionForSourceDataLoader : KotlinDataLoader { transaction { addLogger(Slf4jSqlDebugLogger) val extensions = - ExtensionTable.innerJoin(SourceTable) + ExtensionTable + .innerJoin(SourceTable) .select { SourceTable.id inList ids } .toList() .map { Triple(it[SourceTable.id].value, it[ExtensionTable.pkgName], it) } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/MangaDataLoader.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/MangaDataLoader.kt index 6cdbe455..df15367d 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/MangaDataLoader.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/MangaDataLoader.kt @@ -33,7 +33,8 @@ class MangaDataLoader : KotlinDataLoader { transaction { addLogger(Slf4jSqlDebugLogger) val manga = - MangaTable.select { MangaTable.id inList ids } + MangaTable + .select { MangaTable.id inList ids } .map { MangaType(it) } .associateBy { it.id } ids.map { manga[it] } @@ -63,7 +64,8 @@ class MangaForCategoryDataLoader : KotlinDataLoader { } else { emptyMap() } + - CategoryMangaTable.innerJoin(MangaTable) + CategoryMangaTable + .innerJoin(MangaTable) .select { CategoryMangaTable.category inList ids } .map { Pair(it[CategoryMangaTable.category].value, MangaType(it)) } .groupBy { it.first } @@ -84,7 +86,8 @@ class MangaForSourceDataLoader : KotlinDataLoader { transaction { addLogger(Slf4jSqlDebugLogger) val mangaBySourceId = - MangaTable.select { MangaTable.sourceReference inList ids } + MangaTable + .select { MangaTable.sourceReference inList ids } .map { MangaType(it) } .groupBy { it.sourceId } ids.map { (mangaBySourceId[it] ?: emptyList()).toNodeList() } @@ -104,7 +107,8 @@ class MangaForIdsDataLoader : KotlinDataLoader, MangaNodeList> { addLogger(Slf4jSqlDebugLogger) val ids = mangaIds.flatten().distinct() val manga = - MangaTable.select { MangaTable.id inList ids } + MangaTable + .select { MangaTable.id inList ids } .map { MangaType(it) } mangaIds.map { mangaIds -> manga.filter { it.id in mangaIds }.toNodeList() diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/MetaDataLoader.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/MetaDataLoader.kt index 94c3426b..9f2de6cc 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/MetaDataLoader.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/MetaDataLoader.kt @@ -28,7 +28,8 @@ class GlobalMetaDataLoader : KotlinDataLoader { transaction { addLogger(Slf4jSqlDebugLogger) val metasByRefId = - GlobalMetaTable.select { GlobalMetaTable.key inList ids } + GlobalMetaTable + .select { GlobalMetaTable.key inList ids } .map { GlobalMetaType(it) } .associateBy { it.key } ids.map { metasByRefId[it] } @@ -46,7 +47,8 @@ class ChapterMetaDataLoader : KotlinDataLoader> { transaction { addLogger(Slf4jSqlDebugLogger) val metasByRefId = - ChapterMetaTable.select { ChapterMetaTable.ref inList ids } + ChapterMetaTable + .select { ChapterMetaTable.ref inList ids } .map { ChapterMetaType(it) } .groupBy { it.chapterId } ids.map { metasByRefId[it].orEmpty() } @@ -64,7 +66,8 @@ class MangaMetaDataLoader : KotlinDataLoader> { transaction { addLogger(Slf4jSqlDebugLogger) val metasByRefId = - MangaMetaTable.select { MangaMetaTable.ref inList ids } + MangaMetaTable + .select { MangaMetaTable.ref inList ids } .map { MangaMetaType(it) } .groupBy { it.mangaId } ids.map { metasByRefId[it].orEmpty() } @@ -82,7 +85,8 @@ class CategoryMetaDataLoader : KotlinDataLoader> { transaction { addLogger(Slf4jSqlDebugLogger) val metasByRefId = - CategoryMetaTable.select { CategoryMetaTable.ref inList ids } + CategoryMetaTable + .select { CategoryMetaTable.ref inList ids } .map { CategoryMetaType(it) } .groupBy { it.categoryId } ids.map { metasByRefId[it].orEmpty() } @@ -100,7 +104,8 @@ class SourceMetaDataLoader : KotlinDataLoader> { transaction { addLogger(Slf4jSqlDebugLogger) val metasByRefId = - SourceMetaTable.select { SourceMetaTable.ref inList ids } + SourceMetaTable + .select { SourceMetaTable.ref inList ids } .map { SourceMetaType(it) } .groupBy { it.sourceId } ids.map { metasByRefId[it].orEmpty() } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/SourceDataLoader.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/SourceDataLoader.kt index eb29de9e..d41a77da 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/SourceDataLoader.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/SourceDataLoader.kt @@ -30,7 +30,8 @@ class SourceDataLoader : KotlinDataLoader { transaction { addLogger(Slf4jSqlDebugLogger) val source = - SourceTable.select { SourceTable.id inList ids } + SourceTable + .select { SourceTable.id inList ids } .mapNotNull { SourceType(it) } .associateBy { it.id } ids.map { source[it] } @@ -49,7 +50,8 @@ class SourcesForExtensionDataLoader : KotlinDataLoader { addLogger(Slf4jSqlDebugLogger) val sourcesByExtensionPkg = - SourceTable.innerJoin(ExtensionTable) + SourceTable + .innerJoin(ExtensionTable) .select { ExtensionTable.pkgName inList ids } .map { Pair(it[ExtensionTable.pkgName], SourceType(it)) } .groupBy { it.first } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/TrackDataLoader.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/TrackDataLoader.kt index 54604866..e1d86555 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/TrackDataLoader.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/TrackDataLoader.kt @@ -89,7 +89,8 @@ class TrackRecordsForMangaIdDataLoader : KotlinDataLoader { transaction { addLogger(Slf4jSqlDebugLogger) val trackRecords = - TrackRecordTable.select { TrackRecordTable.id inList ids } + TrackRecordTable + .select { TrackRecordTable.id inList ids } .toList() .map { it.toTrack() } .associateBy { it.id!! } @@ -128,7 +130,8 @@ class TrackRecordsForTrackerIdDataLoader : KotlinDataLoader { transaction { addLogger(Slf4jSqlDebugLogger) val trackRecordsId = - TrackRecordTable.select { TrackRecordTable.id inList ids } + TrackRecordTable + .select { TrackRecordTable.id inList ids } .map { TrackRecordType(it) } .associateBy { it.id } ids.map { trackRecordsId[it] } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/CategoryMutation.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/CategoryMutation.kt index 25810623..fa1de395 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/CategoryMutation.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/CategoryMutation.kt @@ -38,15 +38,14 @@ class CategoryMutation { val meta: CategoryMetaType, ) - fun setCategoryMeta(input: SetCategoryMetaInput): DataFetcherResult { - return asDataFetcherResult { + fun setCategoryMeta(input: SetCategoryMetaInput): DataFetcherResult = + asDataFetcherResult { val (clientMutationId, meta) = input Category.modifyMeta(meta.categoryId, meta.key, meta.value) SetCategoryMetaPayload(clientMutationId, meta) } - } data class DeleteCategoryMetaInput( val clientMutationId: String? = null, @@ -60,14 +59,15 @@ class CategoryMutation { val category: CategoryType, ) - fun deleteCategoryMeta(input: DeleteCategoryMetaInput): DataFetcherResult { - return asDataFetcherResult { + fun deleteCategoryMeta(input: DeleteCategoryMetaInput): DataFetcherResult = + asDataFetcherResult { val (clientMutationId, categoryId, key) = input val (meta, category) = transaction { val meta = - CategoryMetaTable.select { (CategoryMetaTable.ref eq categoryId) and (CategoryMetaTable.key eq key) } + CategoryMetaTable + .select { (CategoryMetaTable.ref eq categoryId) and (CategoryMetaTable.key eq key) } .firstOrNull() CategoryMetaTable.deleteWhere { (CategoryMetaTable.ref eq categoryId) and (CategoryMetaTable.key eq key) } @@ -86,7 +86,6 @@ class CategoryMutation { DeleteCategoryMetaPayload(clientMutationId, meta, category) } - } data class UpdateCategoryPatch( val name: String? = null, @@ -153,8 +152,8 @@ class CategoryMutation { } } - fun updateCategory(input: UpdateCategoryInput): DataFetcherResult { - return asDataFetcherResult { + fun updateCategory(input: UpdateCategoryInput): DataFetcherResult = + asDataFetcherResult { val (clientMutationId, id, patch) = input updateCategories(listOf(id), patch) @@ -169,10 +168,9 @@ class CategoryMutation { category = category, ) } - } - fun updateCategories(input: UpdateCategoriesInput): DataFetcherResult { - return asDataFetcherResult { + fun updateCategories(input: UpdateCategoriesInput): DataFetcherResult = + asDataFetcherResult { val (clientMutationId, ids, patch) = input updateCategories(ids, patch) @@ -187,7 +185,6 @@ class CategoryMutation { categories = categories, ) } - } data class UpdateCategoryOrderPayload( val clientMutationId: String?, @@ -200,8 +197,8 @@ class CategoryMutation { val position: Int, ) - fun updateCategoryOrder(input: UpdateCategoryOrderInput): DataFetcherResult { - return asDataFetcherResult { + fun updateCategoryOrder(input: UpdateCategoryOrderInput): DataFetcherResult = + asDataFetcherResult { val (clientMutationId, categoryId, position) = input require(position > 0) { "'order' must not be <= 0" @@ -242,7 +239,6 @@ class CategoryMutation { categories = categories, ) } - } data class CreateCategoryInput( val clientMutationId: String? = null, @@ -258,8 +254,8 @@ class CategoryMutation { val category: CategoryType, ) - fun createCategory(input: CreateCategoryInput): DataFetcherResult { - return asDataFetcherResult { + fun createCategory(input: CreateCategoryInput): DataFetcherResult = + asDataFetcherResult { val (clientMutationId, name, order, default, includeInUpdate, includeInDownload) = input transaction { require(CategoryTable.select { CategoryTable.name eq input.name }.isEmpty()) { @@ -305,7 +301,6 @@ class CategoryMutation { CreateCategoryPayload(clientMutationId, category) } - } data class DeleteCategoryInput( val clientMutationId: String? = null, @@ -332,12 +327,14 @@ class CategoryMutation { val (category, mangas) = transaction { val category = - CategoryTable.select { CategoryTable.id eq categoryId } + CategoryTable + .select { CategoryTable.id eq categoryId } .firstOrNull() val mangas = transaction { - MangaTable.innerJoin(CategoryMangaTable) + MangaTable + .innerJoin(CategoryMangaTable) .select { CategoryMangaTable.category eq categoryId } .map { MangaType(it) } } @@ -403,9 +400,10 @@ class CategoryMutation { ids.filter { it != DEFAULT_CATEGORY_ID }.forEach { mangaId -> patch.addToCategories.forEach { categoryId -> val existingMapping = - CategoryMangaTable.select { - (CategoryMangaTable.manga eq mangaId) and (CategoryMangaTable.category eq categoryId) - }.isNotEmpty() + CategoryMangaTable + .select { + (CategoryMangaTable.manga eq mangaId) and (CategoryMangaTable.category eq categoryId) + }.isNotEmpty() if (!existingMapping) { add(mangaId to categoryId) @@ -422,8 +420,8 @@ class CategoryMutation { } } - fun updateMangaCategories(input: UpdateMangaCategoriesInput): DataFetcherResult { - return asDataFetcherResult { + fun updateMangaCategories(input: UpdateMangaCategoriesInput): DataFetcherResult = + asDataFetcherResult { val (clientMutationId, id, patch) = input updateMangas(listOf(id), patch) @@ -438,10 +436,9 @@ class CategoryMutation { manga = manga, ) } - } - fun updateMangasCategories(input: UpdateMangasCategoriesInput): DataFetcherResult { - return asDataFetcherResult { + fun updateMangasCategories(input: UpdateMangasCategoriesInput): DataFetcherResult = + asDataFetcherResult { val (clientMutationId, ids, patch) = input updateMangas(ids, patch) @@ -456,5 +453,4 @@ class CategoryMutation { mangas = mangas, ) } - } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/ChapterMutation.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/ChapterMutation.kt index 5134ff93..0d60f3f4 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/ChapterMutation.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/ChapterMutation.kt @@ -95,8 +95,8 @@ class ChapterMutation { } } - fun updateChapter(input: UpdateChapterInput): DataFetcherResult { - return asDataFetcherResult { + fun updateChapter(input: UpdateChapterInput): DataFetcherResult = + asDataFetcherResult { val (clientMutationId, id, patch) = input updateChapters(listOf(id), patch) @@ -111,10 +111,9 @@ class ChapterMutation { chapter = chapter, ) } - } - fun updateChapters(input: UpdateChaptersInput): DataFetcherResult { - return asDataFetcherResult { + fun updateChapters(input: UpdateChaptersInput): DataFetcherResult = + asDataFetcherResult { val (clientMutationId, ids, patch) = input updateChapters(ids, patch) @@ -129,7 +128,6 @@ class ChapterMutation { chapters = chapters, ) } - } data class FetchChaptersInput( val clientMutationId: String? = null, @@ -150,7 +148,8 @@ class ChapterMutation { val chapters = transaction { - ChapterTable.select { ChapterTable.manga eq mangaId } + ChapterTable + .select { ChapterTable.manga eq mangaId } .orderBy(ChapterTable.sourceOrder) .map { ChapterType(it) } } @@ -173,15 +172,14 @@ class ChapterMutation { val meta: ChapterMetaType, ) - fun setChapterMeta(input: SetChapterMetaInput): DataFetcherResult { - return asDataFetcherResult { + fun setChapterMeta(input: SetChapterMetaInput): DataFetcherResult = + asDataFetcherResult { val (clientMutationId, meta) = input Chapter.modifyChapterMeta(meta.chapterId, meta.key, meta.value) SetChapterMetaPayload(clientMutationId, meta) } - } data class DeleteChapterMetaInput( val clientMutationId: String? = null, @@ -195,14 +193,15 @@ class ChapterMutation { val chapter: ChapterType, ) - fun deleteChapterMeta(input: DeleteChapterMetaInput): DataFetcherResult { - return asDataFetcherResult { + fun deleteChapterMeta(input: DeleteChapterMetaInput): DataFetcherResult = + asDataFetcherResult { val (clientMutationId, chapterId, key) = input val (meta, chapter) = transaction { val meta = - ChapterMetaTable.select { (ChapterMetaTable.ref eq chapterId) and (ChapterMetaTable.key eq key) } + ChapterMetaTable + .select { (ChapterMetaTable.ref eq chapterId) and (ChapterMetaTable.key eq key) } .firstOrNull() ChapterMetaTable.deleteWhere { (ChapterMetaTable.ref eq chapterId) and (ChapterMetaTable.key eq key) } @@ -221,7 +220,6 @@ class ChapterMutation { DeleteChapterMetaPayload(clientMutationId, meta, chapter) } - } data class FetchChapterPagesInput( val clientMutationId: String? = null, diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/DownloadMutation.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/DownloadMutation.kt index 7addd0af..5ff89c43 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/DownloadMutation.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/DownloadMutation.kt @@ -37,7 +37,8 @@ class DownloadMutation { clientMutationId = clientMutationId, chapters = transaction { - ChapterTable.select { ChapterTable.id inList chapters } + ChapterTable + .select { ChapterTable.id inList chapters } .map { ChapterType(it) } }, ) @@ -195,8 +196,8 @@ class DownloadMutation { val downloadStatus: DownloadStatus, ) - fun startDownloader(input: StartDownloaderInput): CompletableFuture> { - return future { + fun startDownloader(input: StartDownloaderInput): CompletableFuture> = + future { asDataFetcherResult { DownloadManager.start() @@ -211,7 +212,6 @@ class DownloadMutation { ) } } - } data class StopDownloaderInput( val clientMutationId: String? = null, @@ -222,8 +222,8 @@ class DownloadMutation { val downloadStatus: DownloadStatus, ) - fun stopDownloader(input: StopDownloaderInput): CompletableFuture> { - return future { + fun stopDownloader(input: StopDownloaderInput): CompletableFuture> = + future { asDataFetcherResult { DownloadManager.stop() @@ -238,7 +238,6 @@ class DownloadMutation { ) } } - } data class ClearDownloaderInput( val clientMutationId: String? = null, @@ -249,8 +248,8 @@ class DownloadMutation { val downloadStatus: DownloadStatus, ) - fun clearDownloader(input: ClearDownloaderInput): CompletableFuture> { - return future { + fun clearDownloader(input: ClearDownloaderInput): CompletableFuture> = + future { asDataFetcherResult { DownloadManager.clear() @@ -265,7 +264,6 @@ class DownloadMutation { ) } } - } data class ReorderChapterDownloadInput( val clientMutationId: String? = null, diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/ExtensionMutation.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/ExtensionMutation.kt index 1e69c8f4..1ff152ab 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/ExtensionMutation.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/ExtensionMutation.kt @@ -48,7 +48,8 @@ class ExtensionMutation { ) { val extensions = transaction { - ExtensionTable.select { ExtensionTable.pkgName inList ids } + ExtensionTable + .select { ExtensionTable.pkgName inList ids } .map { ExtensionType(it) } } @@ -80,7 +81,9 @@ class ExtensionMutation { val extension = transaction { - ExtensionTable.select { ExtensionTable.pkgName eq id }.firstOrNull() + ExtensionTable + .select { ExtensionTable.pkgName eq id } + .firstOrNull() ?.let { ExtensionType(it) } } @@ -101,7 +104,8 @@ class ExtensionMutation { val extensions = transaction { - ExtensionTable.select { ExtensionTable.pkgName inList ids } + ExtensionTable + .select { ExtensionTable.pkgName inList ids } .map { ExtensionType(it) } } @@ -131,7 +135,8 @@ class ExtensionMutation { val extensions = transaction { - ExtensionTable.select { ExtensionTable.name neq LocalSource.EXTENSION_NAME } + ExtensionTable + .select { ExtensionTable.name neq LocalSource.EXTENSION_NAME } .map { ExtensionType(it) } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/InfoMutation.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/InfoMutation.kt index a16a1a00..7880929f 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/InfoMutation.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/InfoMutation.kt @@ -59,8 +59,8 @@ class InfoMutation { } } - fun resetWebUIUpdateStatus(): CompletableFuture> { - return future { + fun resetWebUIUpdateStatus(): CompletableFuture> = + future { asDataFetcherResult { withTimeout(30.seconds) { val isUpdateFinished = WebInterfaceManager.status.value.state != DOWNLOADING @@ -74,5 +74,4 @@ class InfoMutation { } } } - } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/MangaMutation.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/MangaMutation.kt index 6dc041bb..c7f987db 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/MangaMutation.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/MangaMutation.kt @@ -76,7 +76,8 @@ class MangaMutation { // try to initialize uninitialized in library manga to ensure that the expected data is available (chapter list, metadata, ...) val mangas = transaction { - MangaTable.select { (MangaTable.id inList ids) and (MangaTable.initialized eq false) } + MangaTable + .select { (MangaTable.id inList ids) and (MangaTable.initialized eq false) } .map { MangaTable.toDataClass(it) } } @@ -198,7 +199,8 @@ class MangaMutation { val (meta, manga) = transaction { val meta = - MangaMetaTable.select { (MangaMetaTable.ref eq mangaId) and (MangaMetaTable.key eq key) } + MangaMetaTable + .select { (MangaMetaTable.ref eq mangaId) and (MangaMetaTable.key eq key) } .firstOrNull() MangaMetaTable.deleteWhere { (MangaMetaTable.ref eq mangaId) and (MangaMetaTable.key eq key) } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/MetaMutation.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/MetaMutation.kt index 65ee38b4..acc3e25a 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/MetaMutation.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/MetaMutation.kt @@ -48,7 +48,8 @@ class MetaMutation { val meta = transaction { val meta = - GlobalMetaTable.select { GlobalMetaTable.key eq key } + GlobalMetaTable + .select { GlobalMetaTable.key eq key } .firstOrNull() GlobalMetaTable.deleteWhere { GlobalMetaTable.key eq key } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/SettingsMutation.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/SettingsMutation.kt index 58755948..73215c42 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/SettingsMutation.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/SettingsMutation.kt @@ -138,7 +138,9 @@ class SettingsMutation { return SetSettingsPayload(clientMutationId, SettingsType()) } - data class ResetSettingsInput(val clientMutationId: String? = null) + data class ResetSettingsInput( + val clientMutationId: String? = null, + ) data class ResetSettingsPayload( val clientMutationId: String?, diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/SourceMutation.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/SourceMutation.kt index e7c679c5..3a46d0c7 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/SourceMutation.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/SourceMutation.kt @@ -68,14 +68,17 @@ class SourceMutation { val (meta, source) = transaction { val meta = - SourceMetaTable.select { (SourceMetaTable.ref eq sourceId) and (SourceMetaTable.key eq key) } + SourceMetaTable + .select { (SourceMetaTable.ref eq sourceId) and (SourceMetaTable.key eq key) } .firstOrNull() SourceMetaTable.deleteWhere { (SourceMetaTable.ref eq sourceId) and (SourceMetaTable.key eq key) } val source = transaction { - SourceTable.select { SourceTable.id eq sourceId }.firstOrNull() + SourceTable + .select { SourceTable.id eq sourceId } + .firstOrNull() ?.let { SourceType(it) } } @@ -139,7 +142,8 @@ class SourceMutation { val mangas = transaction { - MangaTable.select { MangaTable.id inList mangaIds } + MangaTable + .select { MangaTable.id inList mangaIds } .map { MangaType(it) } }.sortedBy { mangaIds.indexOf(it.id) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/TrackMutation.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/TrackMutation.kt index 1e454618..0bf73467 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/TrackMutation.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/TrackMutation.kt @@ -126,9 +126,10 @@ class TrackMutation { ) val trackRecord = transaction { - TrackRecordTable.select { - TrackRecordTable.mangaId eq mangaId and (TrackRecordTable.trackerId eq trackerId) - }.first() + TrackRecordTable + .select { + TrackRecordTable.mangaId eq mangaId and (TrackRecordTable.trackerId eq trackerId) + }.first() } BindTrackPayload( clientMutationId, @@ -154,9 +155,10 @@ class TrackMutation { Track.refresh(recordId) val trackRecord = transaction { - TrackRecordTable.select { - TrackRecordTable.id eq recordId - }.first() + TrackRecordTable + .select { + TrackRecordTable.id eq recordId + }.first() } FetchTrackPayload( clientMutationId, @@ -184,9 +186,10 @@ class TrackMutation { Track.unbind(recordId, deleteRemoteTrack) val trackRecord = transaction { - TrackRecordTable.select { - TrackRecordTable.id eq recordId - }.firstOrNull() + TrackRecordTable + .select { + TrackRecordTable.id eq recordId + }.firstOrNull() } UnbindTrackPayload( clientMutationId, @@ -213,7 +216,8 @@ class TrackMutation { Track.trackChapter(mangaId) val trackRecords = transaction { - TrackRecordTable.select { TrackRecordTable.mangaId eq mangaId } + TrackRecordTable + .select { TrackRecordTable.mangaId eq mangaId } .toList() } TrackProgressPayload( @@ -241,8 +245,8 @@ class TrackMutation { val trackRecord: TrackRecordType?, ) - fun updateTrack(input: UpdateTrackInput): CompletableFuture { - return future { + fun updateTrack(input: UpdateTrackInput): CompletableFuture = + future { Track.update( Track.UpdateInput( input.recordId, @@ -257,14 +261,14 @@ class TrackMutation { val trackRecord = transaction { - TrackRecordTable.select { - TrackRecordTable.id eq input.recordId - }.firstOrNull() + TrackRecordTable + .select { + TrackRecordTable.id eq input.recordId + }.firstOrNull() } UpdateTrackPayload( input.clientMutationId, trackRecord?.let { TrackRecordType(it) }, ) } - } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/BackupQuery.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/BackupQuery.kt index 30581c9b..4e3e16d9 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/BackupQuery.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/BackupQuery.kt @@ -33,7 +33,5 @@ class BackupQuery { ) } - fun restoreStatus(id: String): BackupRestoreStatus? { - return ProtoBackupImport.getRestoreState(id)?.toStatus() - } + fun restoreStatus(id: String): BackupRestoreStatus? = ProtoBackupImport.getRestoreState(id)?.toStatus() } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/CategoryQuery.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/CategoryQuery.kt index 6243261c..30fc5997 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/CategoryQuery.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/CategoryQuery.kt @@ -45,31 +45,29 @@ class CategoryQuery { fun category( dataFetchingEnvironment: DataFetchingEnvironment, id: Int, - ): CompletableFuture { - return dataFetchingEnvironment.getValueFromDataLoader("CategoryDataLoader", id) - } + ): CompletableFuture = dataFetchingEnvironment.getValueFromDataLoader("CategoryDataLoader", id) - enum class CategoryOrderBy(override val column: Column>) : OrderBy { + enum class CategoryOrderBy( + override val column: Column>, + ) : OrderBy { ID(CategoryTable.id), NAME(CategoryTable.name), ORDER(CategoryTable.order), ; - override fun greater(cursor: Cursor): Op { - return when (this) { + override fun greater(cursor: Cursor): Op = + when (this) { ID -> CategoryTable.id greater cursor.value.toInt() NAME -> greaterNotUnique(CategoryTable.name, CategoryTable.id, cursor, String::toString) ORDER -> greaterNotUnique(CategoryTable.order, CategoryTable.id, cursor, String::toInt) } - } - override fun less(cursor: Cursor): Op { - return when (this) { + override fun less(cursor: Cursor): Op = + when (this) { ID -> CategoryTable.id less cursor.value.toInt() NAME -> lessNotUnique(CategoryTable.name, CategoryTable.id, cursor, String::toString) ORDER -> lessNotUnique(CategoryTable.order, CategoryTable.id, cursor, String::toInt) } - } override fun asCursor(type: CategoryType): Cursor { val value = @@ -113,14 +111,13 @@ class CategoryQuery { override val or: List? = null, override val not: CategoryFilter? = null, ) : Filter { - override fun getOpList(): List> { - return listOfNotNull( + override fun getOpList(): List> = + listOfNotNull( andFilterWithCompareEntity(CategoryTable.id, id), andFilterWithCompare(CategoryTable.order, order), andFilterWithCompareString(CategoryTable.name, name), andFilterWithCompare(CategoryTable.isDefault, default), ) - } } fun categories( diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/ChapterQuery.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/ChapterQuery.kt index 28ead837..9cb989b5 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/ChapterQuery.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/ChapterQuery.kt @@ -54,11 +54,11 @@ class ChapterQuery { fun chapter( dataFetchingEnvironment: DataFetchingEnvironment, id: Int, - ): CompletableFuture { - return dataFetchingEnvironment.getValueFromDataLoader("ChapterDataLoader", id) - } + ): CompletableFuture = dataFetchingEnvironment.getValueFromDataLoader("ChapterDataLoader", id) - enum class ChapterOrderBy(override val column: Column>) : OrderBy { + enum class ChapterOrderBy( + override val column: Column>, + ) : OrderBy { ID(ChapterTable.id), SOURCE_ORDER(ChapterTable.sourceOrder), NAME(ChapterTable.name), @@ -68,8 +68,8 @@ class ChapterQuery { FETCHED_AT(ChapterTable.fetchedAt), ; - override fun greater(cursor: Cursor): Op { - return when (this) { + override fun greater(cursor: Cursor): Op = + when (this) { ID -> ChapterTable.id greater cursor.value.toInt() SOURCE_ORDER -> greaterNotUnique(ChapterTable.sourceOrder, ChapterTable.id, cursor, String::toInt) NAME -> greaterNotUnique(ChapterTable.name, ChapterTable.id, cursor, String::toString) @@ -78,10 +78,9 @@ class ChapterQuery { LAST_READ_AT -> greaterNotUnique(ChapterTable.lastReadAt, ChapterTable.id, cursor, String::toLong) FETCHED_AT -> greaterNotUnique(ChapterTable.fetchedAt, ChapterTable.id, cursor, String::toLong) } - } - override fun less(cursor: Cursor): Op { - return when (this) { + override fun less(cursor: Cursor): Op = + when (this) { ID -> ChapterTable.id less cursor.value.toInt() SOURCE_ORDER -> lessNotUnique(ChapterTable.sourceOrder, ChapterTable.id, cursor, String::toInt) NAME -> lessNotUnique(ChapterTable.name, ChapterTable.id, cursor, String::toString) @@ -90,7 +89,6 @@ class ChapterQuery { LAST_READ_AT -> lessNotUnique(ChapterTable.lastReadAt, ChapterTable.id, cursor, String::toLong) FETCHED_AT -> lessNotUnique(ChapterTable.fetchedAt, ChapterTable.id, cursor, String::toLong) } - } override fun asCursor(type: ChapterType): Cursor { val value = @@ -175,8 +173,8 @@ class ChapterQuery { override val or: List? = null, override val not: ChapterFilter? = null, ) : Filter { - override fun getOpList(): List> { - return listOfNotNull( + override fun getOpList(): List> = + listOfNotNull( andFilterWithCompareEntity(ChapterTable.id, id), andFilterWithCompareString(ChapterTable.url, url), andFilterWithCompareString(ChapterTable.name, name), @@ -194,7 +192,6 @@ class ChapterQuery { andFilterWithCompare(ChapterTable.isDownloaded, isDownloaded), andFilterWithCompare(ChapterTable.pageCount, pageCount), ) - } fun getLibraryOp() = andFilterWithCompare(MangaTable.inLibrary, inLibrary) } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/DownloadQuery.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/DownloadQuery.kt index f799a097..104285fb 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/DownloadQuery.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/DownloadQuery.kt @@ -7,9 +7,8 @@ import suwayomi.tachidesk.server.JavalinSetup.future import java.util.concurrent.CompletableFuture class DownloadQuery { - fun downloadStatus(): CompletableFuture { - return future { + fun downloadStatus(): CompletableFuture = + future { DownloadStatus(DownloadManager.status.first()) } - } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/ExtensionQuery.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/ExtensionQuery.kt index 7d7c2c97..6232a862 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/ExtensionQuery.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/ExtensionQuery.kt @@ -46,31 +46,29 @@ class ExtensionQuery { fun extension( dataFetchingEnvironment: DataFetchingEnvironment, pkgName: String, - ): CompletableFuture { - return dataFetchingEnvironment.getValueFromDataLoader("ExtensionDataLoader", pkgName) - } + ): CompletableFuture = dataFetchingEnvironment.getValueFromDataLoader("ExtensionDataLoader", pkgName) - enum class ExtensionOrderBy(override val column: Column>) : OrderBy { + enum class ExtensionOrderBy( + override val column: Column>, + ) : OrderBy { PKG_NAME(ExtensionTable.pkgName), NAME(ExtensionTable.name), APK_NAME(ExtensionTable.apkName), ; - override fun greater(cursor: Cursor): Op { - return when (this) { + override fun greater(cursor: Cursor): Op = + when (this) { PKG_NAME -> ExtensionTable.pkgName greater cursor.value NAME -> greaterNotUnique(ExtensionTable.name, ExtensionTable.pkgName, cursor, String::toString) APK_NAME -> greaterNotUnique(ExtensionTable.apkName, ExtensionTable.pkgName, cursor, String::toString) } - } - override fun less(cursor: Cursor): Op { - return when (this) { + override fun less(cursor: Cursor): Op = + when (this) { PKG_NAME -> ExtensionTable.pkgName less cursor.value NAME -> lessNotUnique(ExtensionTable.name, ExtensionTable.pkgName, cursor, String::toString) APK_NAME -> lessNotUnique(ExtensionTable.apkName, ExtensionTable.pkgName, cursor, String::toString) } - } override fun asCursor(type: ExtensionType): Cursor { val value = @@ -137,8 +135,8 @@ class ExtensionQuery { override val or: List? = null, override val not: ExtensionFilter? = null, ) : Filter { - override fun getOpList(): List> { - return listOfNotNull( + override fun getOpList(): List> = + listOfNotNull( andFilterWithCompareString(ExtensionTable.repo, repo), andFilterWithCompareString(ExtensionTable.apkName, apkName), andFilterWithCompareString(ExtensionTable.iconUrl, iconUrl), @@ -152,7 +150,6 @@ class ExtensionQuery { andFilterWithCompare(ExtensionTable.hasUpdate, hasUpdate), andFilterWithCompare(ExtensionTable.isObsolete, isObsolete), ) - } } fun extensions( diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/InfoQuery.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/InfoQuery.kt index 5973bd0c..9aa68d07 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/InfoQuery.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/InfoQuery.kt @@ -22,8 +22,8 @@ class InfoQuery { val discord: String, ) - fun aboutServer(): AboutServerPayload { - return AboutServerPayload( + fun aboutServer(): AboutServerPayload = + AboutServerPayload( BuildConfig.NAME, BuildConfig.VERSION, BuildConfig.REVISION, @@ -32,7 +32,6 @@ class InfoQuery { BuildConfig.GITHUB, BuildConfig.DISCORD, ) - } data class CheckForServerUpdatesPayload( /** [channel] mirrors [suwayomi.tachidesk.server.BuildConfig.BUILD_TYPE] */ @@ -41,8 +40,8 @@ class InfoQuery { val url: String, ) - fun checkForServerUpdates(): CompletableFuture> { - return future { + fun checkForServerUpdates(): CompletableFuture> = + future { AppUpdate.checkUpdate().map { CheckForServerUpdatesPayload( channel = it.channel, @@ -51,16 +50,14 @@ class InfoQuery { ) } } - } - fun aboutWebUI(): CompletableFuture { - return future { + fun aboutWebUI(): CompletableFuture = + future { WebInterfaceManager.getAboutInfo() } - } - fun checkForWebUIUpdate(): CompletableFuture { - return future { + fun checkForWebUIUpdate(): CompletableFuture = + future { val (version, updateAvailable) = WebInterfaceManager.isUpdateAvailable(WebUIFlavor.current, raiseError = true) WebUIUpdateCheck( channel = serverConfig.webUIChannel.value, @@ -68,9 +65,6 @@ class InfoQuery { updateAvailable, ) } - } - fun getWebUIUpdateStatus(): WebUIUpdateStatus { - return WebInterfaceManager.status.value - } + fun getWebUIUpdateStatus(): WebUIUpdateStatus = WebInterfaceManager.status.value } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/MangaQuery.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/MangaQuery.kt index a35dcd68..29d7ab67 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/MangaQuery.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/MangaQuery.kt @@ -50,34 +50,32 @@ class MangaQuery { fun manga( dataFetchingEnvironment: DataFetchingEnvironment, id: Int, - ): CompletableFuture { - return dataFetchingEnvironment.getValueFromDataLoader("MangaDataLoader", id) - } + ): CompletableFuture = dataFetchingEnvironment.getValueFromDataLoader("MangaDataLoader", id) - enum class MangaOrderBy(override val column: Column>) : OrderBy { + enum class MangaOrderBy( + override val column: Column>, + ) : OrderBy { ID(MangaTable.id), TITLE(MangaTable.title), IN_LIBRARY_AT(MangaTable.inLibraryAt), LAST_FETCHED_AT(MangaTable.lastFetchedAt), ; - override fun greater(cursor: Cursor): Op { - return when (this) { + override fun greater(cursor: Cursor): Op = + when (this) { ID -> MangaTable.id greater cursor.value.toInt() TITLE -> greaterNotUnique(MangaTable.title, MangaTable.id, cursor, String::toString) IN_LIBRARY_AT -> greaterNotUnique(MangaTable.inLibraryAt, MangaTable.id, cursor, String::toLong) LAST_FETCHED_AT -> greaterNotUnique(MangaTable.lastFetchedAt, MangaTable.id, cursor, String::toLong) } - } - override fun less(cursor: Cursor): Op { - return when (this) { + override fun less(cursor: Cursor): Op = + when (this) { ID -> MangaTable.id less cursor.value.toInt() TITLE -> lessNotUnique(MangaTable.title, MangaTable.id, cursor, String::toString) IN_LIBRARY_AT -> lessNotUnique(MangaTable.inLibraryAt, MangaTable.id, cursor, String::toLong) LAST_FETCHED_AT -> lessNotUnique(MangaTable.lastFetchedAt, MangaTable.id, cursor, String::toLong) } - } override fun asCursor(type: MangaType): Cursor { val value = @@ -197,8 +195,8 @@ class MangaQuery { override val or: List? = null, override val not: MangaFilter? = null, ) : Filter { - override fun getOpList(): List> { - return listOfNotNull( + override fun getOpList(): List> = + listOfNotNull( andFilterWithCompareEntity(MangaTable.id, id), andFilterWithCompare(MangaTable.sourceReference, sourceId), andFilterWithCompareString(MangaTable.url, url), @@ -217,7 +215,6 @@ class MangaQuery { andFilterWithCompare(MangaTable.chaptersLastFetchedAt, chaptersLastFetchedAt), andFilterWithCompareEntity(CategoryMangaTable.category, categoryId), ) - } } fun mangas( @@ -243,11 +240,13 @@ class MangaQuery { val queryResults = transaction { val res = - MangaTable.leftJoin(CategoryMangaTable).slice( - distinctOn(MangaTable.id), - *(MangaTable.columns).toTypedArray(), - *(CategoryMangaTable.columns).toTypedArray(), - ).selectAll() + MangaTable + .leftJoin(CategoryMangaTable) + .slice( + distinctOn(MangaTable.id), + *(MangaTable.columns).toTypedArray(), + *(CategoryMangaTable.columns).toTypedArray(), + ).selectAll() res.applyOps(condition, filter) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/MetaQuery.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/MetaQuery.kt index 1c1dd61d..ef518dc2 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/MetaQuery.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/MetaQuery.kt @@ -41,28 +41,26 @@ class MetaQuery { fun meta( dataFetchingEnvironment: DataFetchingEnvironment, key: String, - ): CompletableFuture { - return dataFetchingEnvironment.getValueFromDataLoader("GlobalMetaDataLoader", key) - } + ): CompletableFuture = dataFetchingEnvironment.getValueFromDataLoader("GlobalMetaDataLoader", key) - enum class MetaOrderBy(override val column: Column>) : OrderBy { + enum class MetaOrderBy( + override val column: Column>, + ) : OrderBy { KEY(GlobalMetaTable.key), VALUE(GlobalMetaTable.value), ; - override fun greater(cursor: Cursor): Op { - return when (this) { + override fun greater(cursor: Cursor): Op = + when (this) { KEY -> GlobalMetaTable.key greater cursor.value VALUE -> greaterNotUnique(GlobalMetaTable.value, GlobalMetaTable.key, cursor, String::toString) } - } - override fun less(cursor: Cursor): Op { - return when (this) { + override fun less(cursor: Cursor): Op = + when (this) { KEY -> GlobalMetaTable.key less cursor.value VALUE -> lessNotUnique(GlobalMetaTable.value, GlobalMetaTable.key, cursor, String::toString) } - } override fun asCursor(type: GlobalMetaType): Cursor { val value = @@ -99,12 +97,11 @@ class MetaQuery { override val or: List? = null, override val not: MetaFilter? = null, ) : Filter { - override fun getOpList(): List> { - return listOfNotNull( + override fun getOpList(): List> = + listOfNotNull( andFilterWithCompareString(GlobalMetaTable.key, key), andFilterWithCompareString(GlobalMetaTable.value, value), ) - } } fun metas( diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/SettingsQuery.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/SettingsQuery.kt index 6be6aafd..6d9481d0 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/SettingsQuery.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/SettingsQuery.kt @@ -3,7 +3,5 @@ package suwayomi.tachidesk.graphql.queries import suwayomi.tachidesk.graphql.types.SettingsType class SettingsQuery { - fun settings(): SettingsType { - return SettingsType() - } + fun settings(): SettingsType = SettingsType() } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/SourceQuery.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/SourceQuery.kt index aa09a905..784f41c7 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/SourceQuery.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/SourceQuery.kt @@ -45,31 +45,29 @@ class SourceQuery { fun source( dataFetchingEnvironment: DataFetchingEnvironment, id: Long, - ): CompletableFuture { - return dataFetchingEnvironment.getValueFromDataLoader("SourceDataLoader", id) - } + ): CompletableFuture = dataFetchingEnvironment.getValueFromDataLoader("SourceDataLoader", id) - enum class SourceOrderBy(override val column: Column>) : OrderBy { + enum class SourceOrderBy( + override val column: Column>, + ) : OrderBy { ID(SourceTable.id), NAME(SourceTable.name), LANG(SourceTable.lang), ; - override fun greater(cursor: Cursor): Op { - return when (this) { + override fun greater(cursor: Cursor): Op = + when (this) { ID -> SourceTable.id greater cursor.value.toLong() NAME -> greaterNotUnique(SourceTable.name, SourceTable.id, cursor, String::toString) LANG -> greaterNotUnique(SourceTable.lang, SourceTable.id, cursor, String::toString) } - } - override fun less(cursor: Cursor): Op { - return when (this) { + override fun less(cursor: Cursor): Op = + when (this) { ID -> SourceTable.id less cursor.value.toLong() NAME -> lessNotUnique(SourceTable.name, SourceTable.id, cursor, String::toString) LANG -> lessNotUnique(SourceTable.lang, SourceTable.id, cursor, String::toString) } - } override fun asCursor(type: SourceType): Cursor { val value = @@ -113,14 +111,13 @@ class SourceQuery { override val or: List? = null, override val not: SourceFilter? = null, ) : Filter { - override fun getOpList(): List> { - return listOfNotNull( + override fun getOpList(): List> = + listOfNotNull( andFilterWithCompareEntity(SourceTable.id, id), andFilterWithCompareString(SourceTable.name, name), andFilterWithCompareString(SourceTable.lang, lang), andFilterWithCompare(SourceTable.isNsfw, isNsfw), ) - } } fun sources( diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/TrackQuery.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/TrackQuery.kt index 9e386ecd..c713a7bc 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/TrackQuery.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/TrackQuery.kt @@ -46,9 +46,7 @@ class TrackQuery { fun tracker( dataFetchingEnvironment: DataFetchingEnvironment, id: Int, - ): CompletableFuture { - return dataFetchingEnvironment.getValueFromDataLoader("TrackerDataLoader", id) - } + ): CompletableFuture = dataFetchingEnvironment.getValueFromDataLoader("TrackerDataLoader", id) enum class TrackerOrderBy { ID, @@ -59,8 +57,8 @@ class TrackQuery { fun greater( tracker: TrackerType, cursor: Cursor, - ): Boolean { - return when (this) { + ): Boolean = + when (this) { ID -> tracker.id > cursor.value.toInt() NAME -> tracker.name > cursor.value IS_LOGGED_IN -> { @@ -68,13 +66,12 @@ class TrackQuery { !value || tracker.isLoggedIn } } - } fun less( tracker: TrackerType, cursor: Cursor, - ): Boolean { - return when (this) { + ): Boolean = + when (this) { ID -> tracker.id < cursor.value.toInt() NAME -> tracker.name < cursor.value IS_LOGGED_IN -> { @@ -82,7 +79,6 @@ class TrackQuery { value || !tracker.isLoggedIn } } - } fun asCursor(type: TrackerType): Cursor { val value = @@ -244,11 +240,12 @@ class TrackQuery { fun trackRecord( dataFetchingEnvironment: DataFetchingEnvironment, id: Int, - ): CompletableFuture { - return dataFetchingEnvironment.getValueFromDataLoader("TrackRecordDataLoader", id) - } + ): CompletableFuture = + dataFetchingEnvironment.getValueFromDataLoader("TrackRecordDataLoader", id) - enum class TrackRecordOrderBy(override val column: Column>) : OrderBy { + enum class TrackRecordOrderBy( + override val column: Column>, + ) : OrderBy { ID(TrackRecordTable.id), MANGA_ID(TrackRecordTable.mangaId), TRACKER_ID(TrackRecordTable.trackerId), @@ -261,8 +258,8 @@ class TrackQuery { FINISH_DATE(TrackRecordTable.finishDate), ; - override fun greater(cursor: Cursor): Op { - return when (this) { + override fun greater(cursor: Cursor): Op = + when (this) { ID -> TrackRecordTable.id greater cursor.value.toInt() MANGA_ID -> greaterNotUnique(TrackRecordTable.mangaId, TrackRecordTable.id, cursor) TRACKER_ID -> greaterNotUnique(TrackRecordTable.trackerId, TrackRecordTable.id, cursor, String::toInt) @@ -274,10 +271,9 @@ class TrackQuery { START_DATE -> greaterNotUnique(TrackRecordTable.startDate, TrackRecordTable.id, cursor, String::toLong) FINISH_DATE -> greaterNotUnique(TrackRecordTable.finishDate, TrackRecordTable.id, cursor, String::toLong) } - } - override fun less(cursor: Cursor): Op { - return when (this) { + override fun less(cursor: Cursor): Op = + when (this) { ID -> TrackRecordTable.id less cursor.value.toInt() MANGA_ID -> lessNotUnique(TrackRecordTable.mangaId, TrackRecordTable.id, cursor) TRACKER_ID -> lessNotUnique(TrackRecordTable.trackerId, TrackRecordTable.id, cursor, String::toInt) @@ -289,7 +285,6 @@ class TrackQuery { START_DATE -> lessNotUnique(TrackRecordTable.startDate, TrackRecordTable.id, cursor, String::toLong) FINISH_DATE -> lessNotUnique(TrackRecordTable.finishDate, TrackRecordTable.id, cursor, String::toLong) } - } override fun asCursor(type: TrackRecordType): Cursor { val value = @@ -367,8 +362,8 @@ class TrackQuery { override val or: List? = null, override val not: TrackRecordFilter? = null, ) : Filter { - override fun getOpList(): List> { - return listOfNotNull( + override fun getOpList(): List> = + listOfNotNull( andFilterWithCompareEntity(TrackRecordTable.id, id), andFilterWithCompareEntity(TrackRecordTable.mangaId, mangaId), andFilterWithCompare(TrackRecordTable.trackerId, trackerId), @@ -383,7 +378,6 @@ class TrackQuery { andFilterWithCompare(TrackRecordTable.startDate, startDate), andFilterWithCompare(TrackRecordTable.finishDate, finishDate), ) - } } fun trackRecords( @@ -484,10 +478,12 @@ class TrackQuery { val query: String, ) - data class SearchTrackerPayload(val trackSearches: List) + data class SearchTrackerPayload( + val trackSearches: List, + ) - fun searchTracker(input: SearchTrackerInput): CompletableFuture { - return future { + fun searchTracker(input: SearchTrackerInput): CompletableFuture = + future { val tracker = requireNotNull(TrackerManager.getTracker(input.trackerId)) { "Tracker not found" @@ -501,5 +497,4 @@ class TrackQuery { }, ) } - } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/UpdateQuery.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/UpdateQuery.kt index 59a7516e..03353655 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/UpdateQuery.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/UpdateQuery.kt @@ -12,13 +12,11 @@ import java.util.concurrent.CompletableFuture class UpdateQuery { private val updater by DI.global.instance() - fun updateStatus(): CompletableFuture { - return future { UpdateStatus(updater.status.first()) } - } + fun updateStatus(): CompletableFuture = future { UpdateStatus(updater.status.first()) } - data class LastUpdateTimestampPayload(val timestamp: Long) + data class LastUpdateTimestampPayload( + val timestamp: Long, + ) - fun lastUpdateTimestamp(): LastUpdateTimestampPayload { - return LastUpdateTimestampPayload(updater.getLastUpdateTimestamp()) - } + fun lastUpdateTimestamp(): LastUpdateTimestampPayload = LastUpdateTimestampPayload(updater.getLastUpdateTimestamp()) } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/filter/Filter.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/filter/Filter.kt index 7ebd9fbc..0713ead8 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/filter/Filter.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/filter/Filter.kt @@ -17,11 +17,16 @@ import org.jetbrains.exposed.sql.or import org.jetbrains.exposed.sql.stringParam import org.jetbrains.exposed.sql.upperCase -class ILikeEscapeOp(expr1: Expression<*>, expr2: Expression<*>, like: Boolean, val escapeChar: Char?) : ComparisonOp( - expr1, - expr2, - if (like) "ILIKE" else "NOT ILIKE", -) { +class ILikeEscapeOp( + expr1: Expression<*>, + expr2: Expression<*>, + like: Boolean, + val escapeChar: Char?, +) : ComparisonOp( + expr1, + expr2, + if (like) "ILIKE" else "NOT ILIKE", + ) { override fun toQueryBuilder(queryBuilder: QueryBuilder) { super.toQueryBuilder(queryBuilder) if (escapeChar != null) { @@ -67,11 +72,15 @@ class ILikeEscapeOp(expr1: Expression<*>, expr2: Expression<*>, like: Boolean, v } } -class DistinctFromOp(expr1: Expression<*>, expr2: Expression<*>, not: Boolean) : ComparisonOp( - expr1, - expr2, - if (not) "IS NOT DISTINCT FROM" else "IS DISTINCT FROM", -) { +class DistinctFromOp( + expr1: Expression<*>, + expr2: Expression<*>, + not: Boolean, +) : ComparisonOp( + expr1, + expr2, + if (not) "IS NOT DISTINCT FROM" else "IS DISTINCT FROM", + ) { companion object { fun distinctFrom( expression: ExpressionWithColumnType, @@ -472,7 +481,9 @@ fun andFilterWithCompareString( return opAnd.op } -class OpAnd(var op: Op? = null) { +class OpAnd( + var op: Op? = null, +) { fun andWhere( value: T?, andPart: SqlExpressionBuilder.(T & Any) -> Op, diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/JavalinGraphQLRequestParser.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/JavalinGraphQLRequestParser.kt index 4f13e0df..4bd917bb 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/JavalinGraphQLRequestParser.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/JavalinGraphQLRequestParser.kt @@ -38,26 +38,29 @@ class JavalinGraphQLRequestParser : GraphQLRequestParser { GraphQLServerRequest::class.java, ) val map = - context.formParam("map")?.let { - context.jsonMapper().fromJsonString( - it, - Map::class.java as Class>>, - ) - }.orEmpty() + context + .formParam("map") + ?.let { + context.jsonMapper().fromJsonString( + it, + Map::class.java as Class>>, + ) + }.orEmpty() val mapItems = - map.flatMap { (key, variables) -> - val file = context.uploadedFile(key) - variables.map { fullVariable -> - val variable = fullVariable.removePrefix("variables.").substringBefore('.') - val listIndex = fullVariable.substringAfterLast('.').toIntOrNull() - MapItem( - variable, - listIndex, - file, - ) - } - }.groupBy { it.variable } + map + .flatMap { (key, variables) -> + val file = context.uploadedFile(key) + variables.map { fullVariable -> + val variable = fullVariable.removePrefix("variables.").substringBefore('.') + val listIndex = fullVariable.substringAfterLast('.').toIntOrNull() + MapItem( + variable, + listIndex, + file, + ) + } + }.groupBy { it.variable } when (request) { is GraphQLRequest -> { @@ -91,8 +94,8 @@ class JavalinGraphQLRequestParser : GraphQLRequestParser { * Example map "{ "0": ["variables.file"] }" * TODO nested objects */ - private fun Map.modifyFiles(map: Map>): Map { - return mapValues { (name, value) -> + private fun Map.modifyFiles(map: Map>): Map = + mapValues { (name, value) -> if (map.containsKey(name)) { val items = map[name].orEmpty() if (items.size > 1) { @@ -110,5 +113,4 @@ class JavalinGraphQLRequestParser : GraphQLRequestParser { value } } - } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/TachideskDataLoaderRegistryFactory.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/TachideskDataLoaderRegistryFactory.kt index 51375020..16313f7d 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/TachideskDataLoaderRegistryFactory.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/TachideskDataLoaderRegistryFactory.kt @@ -46,8 +46,8 @@ import suwayomi.tachidesk.graphql.dataLoaders.UnreadChapterCountForMangaDataLoad class TachideskDataLoaderRegistryFactory { companion object { - fun create(): KotlinDataLoaderRegistryFactory { - return KotlinDataLoaderRegistryFactory( + fun create(): KotlinDataLoaderRegistryFactory = + KotlinDataLoaderRegistryFactory( MangaDataLoader(), ChapterDataLoader(), ChaptersForMangaDataLoader(), @@ -84,6 +84,5 @@ class TachideskDataLoaderRegistryFactory { TrackRecordsForTrackerIdDataLoader(), TrackRecordDataLoader(), ) - } } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/TachideskGraphQLServer.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/TachideskGraphQLServer.kt index 4ca11b6c..2d2d5d96 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/TachideskGraphQLServer.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/TachideskGraphQLServer.kt @@ -34,7 +34,8 @@ class TachideskGraphQLServer( @OptIn(DelicateCoroutinesApi::class) fun handleSubscriptionMessage(context: WsMessageContext) { - subscriptionProtocolHandler.handleMessage(context) + subscriptionProtocolHandler + .handleMessage(context) .map { objectMapper.writeValueAsString(it) } .map { context.send(it) } .launchIn(GlobalScope) @@ -46,7 +47,8 @@ class TachideskGraphQLServer( companion object { private fun getGraphQLObject(): GraphQL = - GraphQL.newGraphQL(schema) + GraphQL + .newGraphQL(schema) .subscriptionExecutionStrategy(FlowSubscriptionExecutionStrategy()) .mutationExecutionStrategy(AsyncExecutionStrategy()) .build() diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/TemporaryFileStorage.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/TemporaryFileStorage.kt index 3129cf1d..37c32c81 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/TemporaryFileStorage.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/TemporaryFileStorage.kt @@ -43,7 +43,5 @@ object TemporaryFileStorage { } } - fun retrieveFile(name: String): Path { - return folder.resolve(name) - } + fun retrieveFile(name: String): Path = folder.resolve(name) } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/primitives/Cursor.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/primitives/Cursor.kt index eac7019f..413c23dd 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/primitives/Cursor.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/primitives/Cursor.kt @@ -12,18 +12,21 @@ import graphql.schema.CoercingSerializeException import graphql.schema.GraphQLScalarType import java.util.Locale -data class Cursor(val value: String) +data class Cursor( + val value: String, +) val GraphQLCursor: GraphQLScalarType = - GraphQLScalarType.newScalar() + GraphQLScalarType + .newScalar() .name( "Cursor", - ).description("A location in a connection that can be used for resuming pagination.").coercing(GraphqlCursorCoercing()).build() + ).description("A location in a connection that can be used for resuming pagination.") + .coercing(GraphqlCursorCoercing()) + .build() private class GraphqlCursorCoercing : Coercing { - private fun toStringImpl(input: Any): String? { - return (input as? Cursor)?.value - } + private fun toStringImpl(input: Any): String? = (input as? Cursor)?.value private fun parseValueImpl( input: Any, @@ -58,54 +61,44 @@ private class GraphqlCursorCoercing : Coercing { return Cursor(input.value) } - private fun valueToLiteralImpl(input: Any): StringValue { - return StringValue.newStringValue(input.toString()).build() - } + private fun valueToLiteralImpl(input: Any): StringValue = StringValue.newStringValue(input.toString()).build() @Deprecated("") - override fun serialize(dataFetcherResult: Any): String { - return toStringImpl(dataFetcherResult) ?: throw CoercingSerializeException( + override fun serialize(dataFetcherResult: Any): String = + toStringImpl(dataFetcherResult) ?: throw CoercingSerializeException( CoercingUtil.i18nMsg( Locale.getDefault(), "String.unexpectedRawValueType", CoercingUtil.typeName(dataFetcherResult), ), ) - } @Throws(CoercingSerializeException::class) override fun serialize( dataFetcherResult: Any, graphQLContext: GraphQLContext, locale: Locale, - ): String { - return toStringImpl(dataFetcherResult) ?: throw CoercingSerializeException( + ): String = + toStringImpl(dataFetcherResult) ?: throw CoercingSerializeException( CoercingUtil.i18nMsg( locale, "String.unexpectedRawValueType", CoercingUtil.typeName(dataFetcherResult), ), ) - } @Deprecated("") - override fun parseValue(input: Any): Cursor { - return parseValueImpl(input, Locale.getDefault()) - } + override fun parseValue(input: Any): Cursor = parseValueImpl(input, Locale.getDefault()) @Throws(CoercingParseValueException::class) override fun parseValue( input: Any, graphQLContext: GraphQLContext, locale: Locale, - ): Cursor { - return parseValueImpl(input, locale) - } + ): Cursor = parseValueImpl(input, locale) @Deprecated("") - override fun parseLiteral(input: Any): Cursor { - return parseLiteralImpl(input, Locale.getDefault()) - } + override fun parseLiteral(input: Any): Cursor = parseLiteralImpl(input, Locale.getDefault()) @Throws(CoercingParseLiteralException::class) override fun parseLiteral( @@ -113,20 +106,14 @@ private class GraphqlCursorCoercing : Coercing { variables: CoercedVariables, graphQLContext: GraphQLContext, locale: Locale, - ): Cursor { - return parseLiteralImpl(input, locale) - } + ): Cursor = parseLiteralImpl(input, locale) @Deprecated("") - override fun valueToLiteral(input: Any): Value<*> { - return valueToLiteralImpl(input) - } + override fun valueToLiteral(input: Any): Value<*> = valueToLiteralImpl(input) override fun valueToLiteral( input: Any, graphQLContext: GraphQLContext, locale: Locale, - ): Value<*> { - return valueToLiteralImpl(input) - } + ): Value<*> = valueToLiteralImpl(input) } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/primitives/LongAsString.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/primitives/LongAsString.kt index ff89c0e8..651c4fb8 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/primitives/LongAsString.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/primitives/LongAsString.kt @@ -13,13 +13,15 @@ import graphql.schema.GraphQLScalarType import java.util.Locale val GraphQLLongAsString: GraphQLScalarType = - GraphQLScalarType.newScalar() - .name("LongString").description("A 64-bit signed integer as a String").coercing(GraphqlLongAsStringCoercing()).build() + GraphQLScalarType + .newScalar() + .name("LongString") + .description("A 64-bit signed integer as a String") + .coercing(GraphqlLongAsStringCoercing()) + .build() private class GraphqlLongAsStringCoercing : Coercing { - private fun toStringImpl(input: Any): String { - return input.toString() - } + private fun toStringImpl(input: Any): String = input.toString() private fun parseValueImpl( input: Any, @@ -54,42 +56,30 @@ private class GraphqlLongAsStringCoercing : Coercing { return input.value.toLong() } - private fun valueToLiteralImpl(input: Any): StringValue { - return StringValue.newStringValue(input.toString()).build() - } + private fun valueToLiteralImpl(input: Any): StringValue = StringValue.newStringValue(input.toString()).build() @Deprecated("") - override fun serialize(dataFetcherResult: Any): String { - return toStringImpl(dataFetcherResult) - } + override fun serialize(dataFetcherResult: Any): String = toStringImpl(dataFetcherResult) @Throws(CoercingSerializeException::class) override fun serialize( dataFetcherResult: Any, graphQLContext: GraphQLContext, locale: Locale, - ): String { - return toStringImpl(dataFetcherResult) - } + ): String = toStringImpl(dataFetcherResult) @Deprecated("") - override fun parseValue(input: Any): Long { - return parseValueImpl(input, Locale.getDefault()) - } + override fun parseValue(input: Any): Long = parseValueImpl(input, Locale.getDefault()) @Throws(CoercingParseValueException::class) override fun parseValue( input: Any, graphQLContext: GraphQLContext, locale: Locale, - ): Long { - return parseValueImpl(input, locale) - } + ): Long = parseValueImpl(input, locale) @Deprecated("") - override fun parseLiteral(input: Any): Long { - return parseLiteralImpl(input, Locale.getDefault()) - } + override fun parseLiteral(input: Any): Long = parseLiteralImpl(input, Locale.getDefault()) @Throws(CoercingParseLiteralException::class) override fun parseLiteral( @@ -97,20 +87,14 @@ private class GraphqlLongAsStringCoercing : Coercing { variables: CoercedVariables, graphQLContext: GraphQLContext, locale: Locale, - ): Long { - return parseLiteralImpl(input, locale) - } + ): Long = parseLiteralImpl(input, locale) @Deprecated("") - override fun valueToLiteral(input: Any): Value<*> { - return valueToLiteralImpl(input) - } + override fun valueToLiteral(input: Any): Value<*> = valueToLiteralImpl(input) override fun valueToLiteral( input: Any, graphQLContext: GraphQLContext, locale: Locale, - ): Value<*> { - return valueToLiteralImpl(input) - } + ): Value<*> = valueToLiteralImpl(input) } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/primitives/OrderBy.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/primitives/OrderBy.kt index 328045f0..2ac1fc4c 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/primitives/OrderBy.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/primitives/OrderBy.kt @@ -27,8 +27,8 @@ interface Order> { val byType: SortOrder? } -fun SortOrder?.maybeSwap(value: Any?): SortOrder { - return if (value != null) { +fun SortOrder?.maybeSwap(value: Any?): SortOrder = + if (value != null) { when (this) { SortOrder.ASC -> SortOrder.DESC SortOrder.DESC -> SortOrder.ASC @@ -41,7 +41,6 @@ fun SortOrder?.maybeSwap(value: Any?): SortOrder { } else { this ?: SortOrder.ASC } -} fun Query.applyBeforeAfter( before: Cursor?, @@ -72,9 +71,7 @@ fun > greaterNotUnique( idColumn: Column>, cursor: Cursor, toValue: (String) -> T, -): Op { - return greaterNotUniqueImpl(column, idColumn, cursor, String::toInt, toValue) -} +): Op = greaterNotUniqueImpl(column, idColumn, cursor, String::toInt, toValue) @JvmName("greaterNotUniqueLongKey") fun > greaterNotUnique( @@ -82,18 +79,14 @@ fun > greaterNotUnique( idColumn: Column>, cursor: Cursor, toValue: (String) -> T, -): Op { - return greaterNotUniqueImpl(column, idColumn, cursor, String::toLong, toValue) -} +): Op = greaterNotUniqueImpl(column, idColumn, cursor, String::toLong, toValue) @JvmName("greaterNotUniqueIntKeyIntValue") fun greaterNotUnique( column: Column>, idColumn: Column>, cursor: Cursor, -): Op { - return greaterNotUniqueImpl(column, idColumn, cursor, String::toInt, String::toInt) -} +): Op = greaterNotUniqueImpl(column, idColumn, cursor, String::toInt, String::toInt) private fun , V : Comparable> greaterNotUniqueImpl( column: Column, @@ -138,9 +131,7 @@ fun > lessNotUnique( idColumn: Column>, cursor: Cursor, toValue: (String) -> T, -): Op { - return lessNotUniqueImpl(column, idColumn, cursor, String::toInt, toValue) -} +): Op = lessNotUniqueImpl(column, idColumn, cursor, String::toInt, toValue) @JvmName("lessNotUniqueLongKey") fun > lessNotUnique( @@ -148,18 +139,14 @@ fun > lessNotUnique( idColumn: Column>, cursor: Cursor, toValue: (String) -> T, -): Op { - return lessNotUniqueImpl(column, idColumn, cursor, String::toLong, toValue) -} +): Op = lessNotUniqueImpl(column, idColumn, cursor, String::toLong, toValue) @JvmName("lessNotUniqueIntKeyIntValue") fun lessNotUnique( column: Column>, idColumn: Column>, cursor: Cursor, -): Op { - return lessNotUniqueImpl(column, idColumn, cursor, String::toInt, String::toInt) -} +): Op = lessNotUniqueImpl(column, idColumn, cursor, String::toInt, String::toInt) private fun , V : Comparable> lessNotUniqueImpl( column: Column, diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/primitives/QueryResults.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/primitives/QueryResults.kt index a3f604f2..27874b7f 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/primitives/QueryResults.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/primitives/QueryResults.kt @@ -2,4 +2,9 @@ package suwayomi.tachidesk.graphql.server.primitives import org.jetbrains.exposed.sql.ResultRow -data class QueryResults(val total: Long, val firstKey: T, val lastKey: T, val results: List) +data class QueryResults( + val total: Long, + val firstKey: T, + val lastKey: T, + val results: List, +) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/primitives/Upload.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/primitives/Upload.kt index 31a2aa6a..bfec99bd 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/primitives/Upload.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/primitives/Upload.kt @@ -10,7 +10,8 @@ import io.javalin.http.UploadedFile import java.util.Locale val GraphQLUpload = - GraphQLScalarType.newScalar() + GraphQLScalarType + .newScalar() .name("Upload") .description("A file part in a multipart request") .coercing(GraphqlUploadCoercing()) @@ -34,35 +35,25 @@ private class GraphqlUploadCoercing : Coercing { } @Deprecated("") - override fun serialize(dataFetcherResult: Any): Void? { - throw CoercingSerializeException("Upload is an input-only type") - } + override fun serialize(dataFetcherResult: Any): Void? = throw CoercingSerializeException("Upload is an input-only type") @Throws(CoercingSerializeException::class) override fun serialize( dataFetcherResult: Any, graphQLContext: GraphQLContext, locale: Locale, - ): Void? { - throw CoercingSerializeException("Upload is an input-only type") - } + ): Void? = throw CoercingSerializeException("Upload is an input-only type") @Deprecated("") - override fun parseValue(input: Any): UploadedFile { - return parseValueImpl(input, Locale.getDefault()) - } + override fun parseValue(input: Any): UploadedFile = parseValueImpl(input, Locale.getDefault()) @Throws(CoercingParseValueException::class) override fun parseValue( input: Any, graphQLContext: GraphQLContext, locale: Locale, - ): UploadedFile { - return parseValueImpl(input, locale) - } + ): UploadedFile = parseValueImpl(input, locale) @Deprecated("") - override fun parseLiteral(input: Any): UploadedFile { - return parseValueImpl(input, Locale.getDefault()) - } + override fun parseLiteral(input: Any): UploadedFile = parseValueImpl(input, Locale.getDefault()) } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/subscriptions/ApolloSubscriptionProtocolHandler.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/subscriptions/ApolloSubscriptionProtocolHandler.kt index 174173fb..25f12949 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/subscriptions/ApolloSubscriptionProtocolHandler.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/subscriptions/ApolloSubscriptionProtocolHandler.kt @@ -99,14 +99,13 @@ class ApolloSubscriptionProtocolHandler( onDisconnect(context) } - private fun convertToMessageOrNull(payload: String): SubscriptionOperationMessage? { - return try { + private fun convertToMessageOrNull(payload: String): SubscriptionOperationMessage? = + try { objectMapper.readValue(payload) } catch (exception: Exception) { logger.error("Error parsing the subscription message", exception) null } - } private fun startSubscription( operationMessage: SubscriptionOperationMessage, @@ -133,15 +132,15 @@ class ApolloSubscriptionProtocolHandler( try { val request = objectMapper.convertValue(payload) - return subscriptionHandler.executeSubscription(request, graphQLContext) + return subscriptionHandler + .executeSubscription(request, graphQLContext) .map { if (it.errors?.isNotEmpty() == true) { SubscriptionOperationMessage(type = GQL_ERROR.type, id = operationMessage.id, payload = it.errors) } else { SubscriptionOperationMessage(type = GQL_NEXT.type, id = operationMessage.id, payload = it) } - } - .onCompletion { if (it == null) emitAll(onComplete(operationMessage)) } + }.onCompletion { if (it == null) emitAll(onComplete(operationMessage)) } .onStart { sessionState.saveOperation(context, operationMessage, currentCoroutineContext().job) } } catch (exception: Exception) { logger.error("Error running graphql subscription", exception) @@ -169,13 +168,10 @@ class ApolloSubscriptionProtocolHandler( /** * Called with the publisher has completed on its own. */ - private fun onComplete(operationMessage: SubscriptionOperationMessage): Flow { - return sessionState.completeOperation(operationMessage) - } + private fun onComplete(operationMessage: SubscriptionOperationMessage): Flow = + sessionState.completeOperation(operationMessage) - private fun onPing(): Flow { - return flowOf(pongMessage) - } + private fun onPing(): Flow = flowOf(pongMessage) private fun onDisconnect(context: WsContext): Flow { logger.debug("Session \"${context.sessionId}\" disconnected") diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/subscriptions/ApolloSubscriptionSessionState.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/subscriptions/ApolloSubscriptionSessionState.kt index 50dff949..05515023 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/subscriptions/ApolloSubscriptionSessionState.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/subscriptions/ApolloSubscriptionSessionState.kt @@ -71,9 +71,7 @@ internal class ApolloSubscriptionSessionState { .onCompletion { removeActiveOperation(operationMessage.id ?: return@onCompletion) } } - private fun getCompleteMessage(): Flow { - return emptyFlow() - } + private fun getCompleteMessage(): Flow = emptyFlow() /** * Remove active running subscription from the cache and cancel if needed diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/subscriptions/SubscriptionOperationMessage.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/subscriptions/SubscriptionOperationMessage.kt index 06c25058..8a30df00 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/subscriptions/SubscriptionOperationMessage.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/subscriptions/SubscriptionOperationMessage.kt @@ -23,18 +23,24 @@ data class SubscriptionOperationMessage( val id: String? = null, val payload: Any? = null, ) { - enum class CommonMessages(val type: String) { + enum class CommonMessages( + val type: String, + ) { GQL_PING("ping"), GQL_PONG("pong"), GQL_COMPLETE("complete"), } - enum class ClientMessages(val type: String) { + enum class ClientMessages( + val type: String, + ) { GQL_CONNECTION_INIT("connection_init"), GQL_SUBSCRIBE("subscribe"), } - enum class ServerMessages(val type: String) { + enum class ServerMessages( + val type: String, + ) { GQL_CONNECTION_ACK("connection_ack"), GQL_NEXT("next"), GQL_ERROR("error"), diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/subscriptions/DownloadSubscription.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/subscriptions/DownloadSubscription.kt index 8a55d5a1..cba69c86 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/subscriptions/DownloadSubscription.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/subscriptions/DownloadSubscription.kt @@ -13,9 +13,8 @@ import suwayomi.tachidesk.graphql.types.DownloadStatus import suwayomi.tachidesk.manga.impl.download.DownloadManager class DownloadSubscription { - fun downloadChanged(): Flow { - return DownloadManager.status.map { downloadStatus -> + fun downloadChanged(): Flow = + DownloadManager.status.map { downloadStatus -> DownloadStatus(downloadStatus) } - } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/subscriptions/InfoSubscription.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/subscriptions/InfoSubscription.kt index 54afc145..a0058fad 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/subscriptions/InfoSubscription.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/subscriptions/InfoSubscription.kt @@ -5,7 +5,5 @@ import suwayomi.tachidesk.graphql.types.WebUIUpdateStatus import suwayomi.tachidesk.server.util.WebInterfaceManager class InfoSubscription { - fun webUIUpdateStatusChange(): Flow { - return WebInterfaceManager.status - } + fun webUIUpdateStatusChange(): Flow = WebInterfaceManager.status } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/subscriptions/UpdateSubscription.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/subscriptions/UpdateSubscription.kt index 9386bbcc..446aed60 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/subscriptions/UpdateSubscription.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/subscriptions/UpdateSubscription.kt @@ -18,9 +18,8 @@ import suwayomi.tachidesk.manga.impl.update.IUpdater class UpdateSubscription { private val updater by DI.global.instance() - fun updateStatusChanged(): Flow { - return updater.status.map { updateStatus -> + fun updateStatusChanged(): Flow = + updater.status.map { updateStatus -> UpdateStatus(updateStatus) } - } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/BackupTypes.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/BackupTypes.kt index 30139e4a..10ab916f 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/BackupTypes.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/BackupTypes.kt @@ -16,8 +16,8 @@ data class BackupRestoreStatus( val mangaProgress: Int, ) -fun ProtoBackupImport.BackupRestoreState.toStatus(): BackupRestoreStatus { - return when (this) { +fun ProtoBackupImport.BackupRestoreState.toStatus(): BackupRestoreStatus = + when (this) { ProtoBackupImport.BackupRestoreState.Idle -> BackupRestoreStatus( state = BackupRestoreState.IDLE, @@ -49,4 +49,3 @@ fun ProtoBackupImport.BackupRestoreState.toStatus(): BackupRestoreStatus { mangaProgress = current, ) } -} diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/CategoryType.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/CategoryType.kt index dcc52b74..b8a159df 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/CategoryType.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/CategoryType.kt @@ -36,13 +36,11 @@ class CategoryType( IncludeOrExclude.fromValue(row[CategoryTable.includeInDownload]), ) - fun mangas(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { - return dataFetchingEnvironment.getValueFromDataLoader("MangaForCategoryDataLoader", id) - } + fun mangas(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture = + dataFetchingEnvironment.getValueFromDataLoader("MangaForCategoryDataLoader", id) - fun meta(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture> { - return dataFetchingEnvironment.getValueFromDataLoader>("CategoryMetaDataLoader", id) - } + fun meta(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture> = + dataFetchingEnvironment.getValueFromDataLoader>("CategoryMetaDataLoader", id) } data class CategoryNodeList( @@ -57,8 +55,8 @@ data class CategoryNodeList( ) : Edge() companion object { - fun List.toNodeList(): CategoryNodeList { - return CategoryNodeList( + fun List.toNodeList(): CategoryNodeList = + CategoryNodeList( nodes = this, edges = getEdges(), pageInfo = @@ -70,7 +68,6 @@ data class CategoryNodeList( ), totalCount = size, ) - } private fun List.getEdges(): List { if (isEmpty()) return emptyList() diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/ChapterType.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/ChapterType.kt index aeeff7b5..3319ceda 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/ChapterType.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/ChapterType.kt @@ -90,13 +90,11 @@ class ChapterType( dataClass.pageCount, ) - fun manga(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { - return dataFetchingEnvironment.getValueFromDataLoader("MangaDataLoader", mangaId) - } + fun manga(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture = + dataFetchingEnvironment.getValueFromDataLoader("MangaDataLoader", mangaId) - fun meta(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture> { - return dataFetchingEnvironment.getValueFromDataLoader>("ChapterMetaDataLoader", id) - } + fun meta(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture> = + dataFetchingEnvironment.getValueFromDataLoader>("ChapterMetaDataLoader", id) } data class ChapterNodeList( @@ -111,8 +109,8 @@ data class ChapterNodeList( ) : Edge() companion object { - fun List.toNodeList(): ChapterNodeList { - return ChapterNodeList( + fun List.toNodeList(): ChapterNodeList = + ChapterNodeList( nodes = this, edges = getEdges(), pageInfo = @@ -124,7 +122,6 @@ data class ChapterNodeList( ), totalCount = size, ) - } private fun List.getEdges(): List { if (isEmpty()) return emptyList() diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/DownloadType.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/DownloadType.kt index 9036579b..a231b447 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/DownloadType.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/DownloadType.kt @@ -100,8 +100,8 @@ data class DownloadNodeList( ) : Edge() companion object { - fun List.toNodeList(): DownloadNodeList { - return DownloadNodeList( + fun List.toNodeList(): DownloadNodeList = + DownloadNodeList( nodes = this, edges = getEdges(), pageInfo = @@ -113,7 +113,6 @@ data class DownloadNodeList( ), totalCount = size, ) - } private fun List.getEdges(): List { if (isEmpty()) return emptyList() diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/ExtensionType.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/ExtensionType.kt index 1962eb45..7c6a3fd7 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/ExtensionType.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/ExtensionType.kt @@ -48,9 +48,8 @@ class ExtensionType( isObsolete = row[ExtensionTable.isObsolete], ) - fun source(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { - return dataFetchingEnvironment.getValueFromDataLoader("SourcesForExtensionDataLoader", pkgName) - } + fun source(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture = + dataFetchingEnvironment.getValueFromDataLoader("SourcesForExtensionDataLoader", pkgName) } data class ExtensionNodeList( @@ -65,8 +64,8 @@ data class ExtensionNodeList( ) : Edge() companion object { - fun List.toNodeList(): ExtensionNodeList { - return ExtensionNodeList( + fun List.toNodeList(): ExtensionNodeList = + ExtensionNodeList( nodes = this, edges = getEdges(), pageInfo = @@ -78,7 +77,6 @@ data class ExtensionNodeList( ), totalCount = size, ) - } private fun List.getEdges(): List { if (isEmpty()) return emptyList() diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/MangaType.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/MangaType.kt index 8cd4dfa0..03448c19 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/MangaType.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/MangaType.kt @@ -62,8 +62,10 @@ class MangaType( val mangaForIdsDataLoader = dataFetchingEnvironment.getDataLoader, MangaNodeList>("MangaForIdsDataLoader") @Suppress("UNCHECKED_CAST") - (mangaForIdsDataLoader.cacheMap as CustomCacheMap, MangaNodeList>).getKeys() - .filter { it.contains(mangaId) }.forEach { mangaForIdsDataLoader.clear(it) } + (mangaForIdsDataLoader.cacheMap as CustomCacheMap, MangaNodeList>) + .getKeys() + .filter { it.contains(mangaId) } + .forEach { mangaForIdsDataLoader.clear(it) } dataFetchingEnvironment.getDataLoader("DownloadedChapterCountForMangaDataLoader").clear(mangaId) dataFetchingEnvironment.getDataLoader("UnreadChapterCountForMangaDataLoader").clear(mangaId) @@ -74,9 +76,10 @@ class MangaType( dataFetchingEnvironment.getDataLoader("LatestFetchedChapterForMangaDataLoader").clear(mangaId) dataFetchingEnvironment.getDataLoader("LatestUploadedChapterForMangaDataLoader").clear(mangaId) dataFetchingEnvironment.getDataLoader("FirstUnreadChapterForMangaDataLoader").clear(mangaId) - dataFetchingEnvironment.getDataLoader( - "ChaptersForMangaDataLoader", - ).clear(mangaId) + dataFetchingEnvironment + .getDataLoader( + "ChaptersForMangaDataLoader", + ).clear(mangaId) dataFetchingEnvironment.getDataLoader>("MangaMetaDataLoader").clear(mangaId) dataFetchingEnvironment.getDataLoader("CategoriesForMangaDataLoader").clear(mangaId) } @@ -124,45 +127,35 @@ class MangaType( dataClass.chaptersLastFetchedAt, ) - fun downloadCount(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { - return dataFetchingEnvironment.getValueFromDataLoader("DownloadedChapterCountForMangaDataLoader", id) - } + fun downloadCount(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture = + dataFetchingEnvironment.getValueFromDataLoader("DownloadedChapterCountForMangaDataLoader", id) - fun unreadCount(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { - return dataFetchingEnvironment.getValueFromDataLoader("UnreadChapterCountForMangaDataLoader", id) - } + fun unreadCount(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture = + dataFetchingEnvironment.getValueFromDataLoader("UnreadChapterCountForMangaDataLoader", id) - fun bookmarkCount(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { - return dataFetchingEnvironment.getValueFromDataLoader("BookmarkedChapterCountForMangaDataLoader", id) - } + fun bookmarkCount(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture = + dataFetchingEnvironment.getValueFromDataLoader("BookmarkedChapterCountForMangaDataLoader", id) - fun hasDuplicateChapters(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { - return dataFetchingEnvironment.getValueFromDataLoader("HasDuplicateChaptersForMangaDataLoader", id) - } + fun hasDuplicateChapters(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture = + dataFetchingEnvironment.getValueFromDataLoader("HasDuplicateChaptersForMangaDataLoader", id) - fun lastReadChapter(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { - return dataFetchingEnvironment.getValueFromDataLoader("LastReadChapterForMangaDataLoader", id) - } + fun lastReadChapter(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture = + dataFetchingEnvironment.getValueFromDataLoader("LastReadChapterForMangaDataLoader", id) - fun latestReadChapter(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { - return dataFetchingEnvironment.getValueFromDataLoader("LatestReadChapterForMangaDataLoader", id) - } + fun latestReadChapter(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture = + dataFetchingEnvironment.getValueFromDataLoader("LatestReadChapterForMangaDataLoader", id) - fun latestFetchedChapter(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { - return dataFetchingEnvironment.getValueFromDataLoader("LatestFetchedChapterForMangaDataLoader", id) - } + fun latestFetchedChapter(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture = + dataFetchingEnvironment.getValueFromDataLoader("LatestFetchedChapterForMangaDataLoader", id) - fun latestUploadedChapter(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { - return dataFetchingEnvironment.getValueFromDataLoader("LatestUploadedChapterForMangaDataLoader", id) - } + fun latestUploadedChapter(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture = + dataFetchingEnvironment.getValueFromDataLoader("LatestUploadedChapterForMangaDataLoader", id) - fun firstUnreadChapter(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { - return dataFetchingEnvironment.getValueFromDataLoader("FirstUnreadChapterForMangaDataLoader", id) - } + fun firstUnreadChapter(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture = + dataFetchingEnvironment.getValueFromDataLoader("FirstUnreadChapterForMangaDataLoader", id) - fun chapters(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { - return dataFetchingEnvironment.getValueFromDataLoader("ChaptersForMangaDataLoader", id) - } + fun chapters(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture = + dataFetchingEnvironment.getValueFromDataLoader("ChaptersForMangaDataLoader", id) fun age(): Long? { if (lastFetchedAt == null) return null @@ -175,21 +168,17 @@ class MangaType( return Instant.now().epochSecond.minus(chaptersLastFetchedAt!!) } - fun meta(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture> { - return dataFetchingEnvironment.getValueFromDataLoader>("MangaMetaDataLoader", id) - } + fun meta(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture> = + dataFetchingEnvironment.getValueFromDataLoader>("MangaMetaDataLoader", id) - fun categories(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { - return dataFetchingEnvironment.getValueFromDataLoader("CategoriesForMangaDataLoader", id) - } + fun categories(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture = + dataFetchingEnvironment.getValueFromDataLoader("CategoriesForMangaDataLoader", id) - fun source(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { - return dataFetchingEnvironment.getValueFromDataLoader("SourceDataLoader", sourceId) - } + fun source(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture = + dataFetchingEnvironment.getValueFromDataLoader("SourceDataLoader", sourceId) - fun trackRecords(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { - return dataFetchingEnvironment.getValueFromDataLoader("TrackRecordsForMangaIdDataLoader", id) - } + fun trackRecords(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture = + dataFetchingEnvironment.getValueFromDataLoader("TrackRecordsForMangaIdDataLoader", id) } data class MangaNodeList( @@ -204,8 +193,8 @@ data class MangaNodeList( ) : Edge() companion object { - fun List.toNodeList(): MangaNodeList { - return MangaNodeList( + fun List.toNodeList(): MangaNodeList = + MangaNodeList( nodes = this, edges = getEdges(), pageInfo = @@ -217,7 +206,6 @@ data class MangaNodeList( ), totalCount = size, ) - } private fun List.getEdges(): List { if (isEmpty()) return emptyList() diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/MetaType.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/MetaType.kt index be7669a7..2687dd43 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/MetaType.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/MetaType.kt @@ -31,9 +31,8 @@ class ChapterMetaType( chapterId = row[ChapterMetaTable.ref].value, ) - fun chapter(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { - return dataFetchingEnvironment.getValueFromDataLoader("ChapterDataLoader", chapterId) - } + fun chapter(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture = + dataFetchingEnvironment.getValueFromDataLoader("ChapterDataLoader", chapterId) } class MangaMetaType( @@ -47,9 +46,8 @@ class MangaMetaType( mangaId = row[MangaMetaTable.ref].value, ) - fun manga(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { - return dataFetchingEnvironment.getValueFromDataLoader("MangaDataLoader", mangaId) - } + fun manga(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture = + dataFetchingEnvironment.getValueFromDataLoader("MangaDataLoader", mangaId) } class CategoryMetaType( @@ -63,9 +61,8 @@ class CategoryMetaType( categoryId = row[CategoryMetaTable.ref].value, ) - fun category(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { - return dataFetchingEnvironment.getValueFromDataLoader("CategoryDataLoader", categoryId) - } + fun category(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture = + dataFetchingEnvironment.getValueFromDataLoader("CategoryDataLoader", categoryId) } class SourceMetaType( @@ -79,9 +76,8 @@ class SourceMetaType( sourceId = row[SourceMetaTable.ref], ) - fun source(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { - return dataFetchingEnvironment.getValueFromDataLoader("SourceDataLoader", sourceId) - } + fun source(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture = + dataFetchingEnvironment.getValueFromDataLoader("SourceDataLoader", sourceId) } class GlobalMetaType( @@ -106,8 +102,8 @@ data class GlobalMetaNodeList( ) : Edge() companion object { - fun List.toNodeList(): GlobalMetaNodeList { - return GlobalMetaNodeList( + fun List.toNodeList(): GlobalMetaNodeList = + GlobalMetaNodeList( nodes = this, edges = getEdges(), pageInfo = @@ -119,7 +115,6 @@ data class GlobalMetaNodeList( ), totalCount = size, ) - } private fun List.getEdges(): List { if (isEmpty()) return emptyList() diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/SourceType.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/SourceType.kt index b00a1594..9c63395e 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/SourceType.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/SourceType.kt @@ -67,25 +67,18 @@ class SourceType( displayName = catalogueSource.toString(), ) - fun manga(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { - return dataFetchingEnvironment.getValueFromDataLoader("MangaForSourceDataLoader", id) - } + fun manga(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture = + dataFetchingEnvironment.getValueFromDataLoader("MangaForSourceDataLoader", id) - fun extension(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { - return dataFetchingEnvironment.getValueFromDataLoader("ExtensionForSourceDataLoader", id) - } + fun extension(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture = + dataFetchingEnvironment.getValueFromDataLoader("ExtensionForSourceDataLoader", id) - fun preferences(): List { - return getSourcePreferencesRaw(id).map { preferenceOf(it) } - } + fun preferences(): List = getSourcePreferencesRaw(id).map { preferenceOf(it) } - fun filters(): List { - return getCatalogueSourceOrStub(id).getFilterList().map { filterOf(it) } - } + fun filters(): List = getCatalogueSourceOrStub(id).getFilterList().map { filterOf(it) } - fun meta(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture> { - return dataFetchingEnvironment.getValueFromDataLoader>("SourceMetaDataLoader", id) - } + fun meta(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture> = + dataFetchingEnvironment.getValueFromDataLoader>("SourceMetaDataLoader", id) } @Suppress("ktlint:standard:function-naming") @@ -118,8 +111,8 @@ data class SourceNodeList( ) : Edge() companion object { - fun List.toNodeList(): SourceNodeList { - return SourceNodeList( + fun List.toNodeList(): SourceNodeList = + SourceNodeList( nodes = this, edges = getEdges(), pageInfo = @@ -131,7 +124,6 @@ data class SourceNodeList( ), totalCount = size, ) - } private fun List.getEdges(): List { if (isEmpty()) return emptyList() @@ -151,15 +143,29 @@ data class SourceNodeList( sealed interface Filter -data class HeaderFilter(val name: String) : Filter +data class HeaderFilter( + val name: String, +) : Filter -data class SeparatorFilter(val name: String) : Filter +data class SeparatorFilter( + val name: String, +) : Filter -data class SelectFilter(val name: String, val values: List, val default: Int) : Filter +data class SelectFilter( + val name: String, + val values: List, + val default: Int, +) : Filter -data class TextFilter(val name: String, val default: String) : Filter +data class TextFilter( + val name: String, + val default: String, +) : Filter -data class CheckBoxFilter(val name: String, val default: Boolean) : Filter +data class CheckBoxFilter( + val name: String, + val default: Boolean, +) : Filter enum class TriState { IGNORE, @@ -167,19 +173,32 @@ enum class TriState { EXCLUDE, } -data class TriStateFilter(val name: String, val default: TriState) : Filter +data class TriStateFilter( + val name: String, + val default: TriState, +) : Filter -data class SortFilter(val name: String, val values: List, val default: SortSelection?) : Filter { - data class SortSelection(val index: Int, val ascending: Boolean) { +data class SortFilter( + val name: String, + val values: List, + val default: SortSelection?, +) : Filter { + data class SortSelection( + val index: Int, + val ascending: Boolean, + ) { constructor(selection: SourceFilter.Sort.Selection) : this(selection.index, selection.ascending) } } -data class GroupFilter(val name: String, val filters: List) : Filter +data class GroupFilter( + val name: String, + val filters: List, +) : Filter -fun filterOf(filter: SourceFilter<*>): Filter { - return when (filter) { +fun filterOf(filter: SourceFilter<*>): Filter = + when (filter) { is SourceFilter.Header -> HeaderFilter(filter.name) is SourceFilter.Separator -> SeparatorFilter(filter.name) is SourceFilter.Select<*> -> SelectFilter(filter.name, filter.displayValues, filter.state) @@ -202,7 +221,6 @@ fun filterOf(filter: SourceFilter<*>): Filter { is SourceFilter.Sort -> SortFilter(filter.name, filter.values.asList(), filter.state?.let(SortFilter::SortSelection)) else -> throw RuntimeException("sealed class cannot have more subtypes!") } -} /*sealed interface FilterChange { val position: Int @@ -372,8 +390,8 @@ data class MultiSelectListPreference( val entryValues: List, ) : Preference -fun preferenceOf(preference: SourcePreference): Preference { - return when (preference) { +fun preferenceOf(preference: SourcePreference): Preference = + when (preference) { is SourceSwitchPreference -> SwitchPreference( preference.key, @@ -430,4 +448,3 @@ fun preferenceOf(preference: SourcePreference): Preference { ) else -> throw RuntimeException("sealed class cannot have more subtypes!") } -} diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/TrackType.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/TrackType.kt index 8fe0f5b9..5dbdde09 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/TrackType.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/TrackType.kt @@ -40,21 +40,17 @@ class TrackerType( tracker.supportsTrackDeletion, ) - fun statuses(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture> { - return dataFetchingEnvironment.getValueFromDataLoader>("TrackerStatusesDataLoader", id) - } + fun statuses(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture> = + dataFetchingEnvironment.getValueFromDataLoader>("TrackerStatusesDataLoader", id) - fun scores(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture> { - return dataFetchingEnvironment.getValueFromDataLoader>("TrackerScoresDataLoader", id) - } + fun scores(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture> = + dataFetchingEnvironment.getValueFromDataLoader>("TrackerScoresDataLoader", id) - fun trackRecords(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { - return dataFetchingEnvironment.getValueFromDataLoader("TrackRecordsForTrackerIdDataLoader", id) - } + fun trackRecords(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture = + dataFetchingEnvironment.getValueFromDataLoader("TrackRecordsForTrackerIdDataLoader", id) - fun isTokenExpired(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { - return dataFetchingEnvironment.getValueFromDataLoader("TrackerTokenExpiredDataLoader", id) - } + fun isTokenExpired(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture = + dataFetchingEnvironment.getValueFromDataLoader("TrackerTokenExpiredDataLoader", id) } class TrackStatusType( @@ -93,17 +89,14 @@ class TrackRecordType( row[TrackRecordTable.finishDate], ) - fun displayScore(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { - return dataFetchingEnvironment.getValueFromDataLoader("DisplayScoreForTrackRecordDataLoader", id) - } + fun displayScore(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture = + dataFetchingEnvironment.getValueFromDataLoader("DisplayScoreForTrackRecordDataLoader", id) - fun manga(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { - return dataFetchingEnvironment.getValueFromDataLoader("MangaDataLoader", mangaId) - } + fun manga(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture = + dataFetchingEnvironment.getValueFromDataLoader("MangaDataLoader", mangaId) - fun tracker(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { - return dataFetchingEnvironment.getValueFromDataLoader("TrackerDataLoader", trackerId) - } + fun tracker(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture = + dataFetchingEnvironment.getValueFromDataLoader("TrackerDataLoader", trackerId) } class TrackSearchType( @@ -133,9 +126,8 @@ class TrackSearchType( row[TrackSearchTable.startDate], ) - fun tracker(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { - return dataFetchingEnvironment.getValueFromDataLoader("TrackerDataLoader", trackerId) - } + fun tracker(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture = + dataFetchingEnvironment.getValueFromDataLoader("TrackerDataLoader", trackerId) } data class TrackRecordNodeList( @@ -150,8 +142,8 @@ data class TrackRecordNodeList( ) : Edge() companion object { - fun List.toNodeList(): TrackRecordNodeList { - return TrackRecordNodeList( + fun List.toNodeList(): TrackRecordNodeList = + TrackRecordNodeList( nodes = this, edges = getEdges(), pageInfo = @@ -163,7 +155,6 @@ data class TrackRecordNodeList( ), totalCount = size, ) - } private fun List.getEdges(): List { if (isEmpty()) return emptyList() @@ -193,8 +184,8 @@ data class TrackerNodeList( ) : Edge() companion object { - fun List.toNodeList(): TrackerNodeList { - return TrackerNodeList( + fun List.toNodeList(): TrackerNodeList = + TrackerNodeList( nodes = this, edges = getEdges(), pageInfo = @@ -206,7 +197,6 @@ data class TrackerNodeList( ), totalCount = size, ) - } private fun List.getEdges(): List { if (isEmpty()) return emptyList() diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/UpdateType.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/UpdateType.kt index dbf691f2..1f455c19 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/UpdateType.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/UpdateType.kt @@ -28,9 +28,10 @@ class UpdateStatus( runningJobs = UpdateStatusType(status.mangaStatusMap[JobStatus.RUNNING]?.map { it.id }.orEmpty()), completeJobs = UpdateStatusType( - status.mangaStatusMap[JobStatus.COMPLETE]?.map { - it.id - }.orEmpty(), + status.mangaStatusMap[JobStatus.COMPLETE] + ?.map { + it.id + }.orEmpty(), JobStatus.COMPLETE, status.running, true, @@ -50,9 +51,8 @@ class UpdateStatusCategoryType( @get:GraphQLIgnore val categoryIds: List, ) { - fun categories(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { - return dataFetchingEnvironment.getValueFromDataLoader("CategoryForIdsDataLoader", categoryIds) - } + fun categories(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture = + dataFetchingEnvironment.getValueFromDataLoader("CategoryForIdsDataLoader", categoryIds) } class UpdateStatusType( diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/controller/SourceController.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/controller/SourceController.kt index 1bba233b..587cd57f 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/controller/SourceController.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/controller/SourceController.kt @@ -247,7 +247,8 @@ object SourceController { description("All source search") } }, - behaviorOf = { ctx, searchTerm -> // TODO + behaviorOf = { ctx, searchTerm -> + // TODO ctx.json(Search.sourceGlobalSearch(searchTerm)) }, withResults = { diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Category.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Category.kt index 9556a0b1..a52fed0b 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Category.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Category.kt @@ -36,10 +36,11 @@ object Category { return transaction { if (CategoryTable.select { CategoryTable.name eq name }.firstOrNull() == null) { val newCategoryId = - CategoryTable.insertAndGetId { - it[CategoryTable.name] = name - it[CategoryTable.order] = Int.MAX_VALUE - }.value + CategoryTable + .insertAndGetId { + it[CategoryTable.name] = name + it[CategoryTable.order] = Int.MAX_VALUE + }.value normalizeCategories() @@ -60,7 +61,8 @@ object Category { transaction { CategoryTable.update({ CategoryTable.id eq categoryId }) { if ( - categoryId != DEFAULT_CATEGORY_ID && name != null && + categoryId != DEFAULT_CATEGORY_ID && + name != null && !name.equals(DEFAULT_CATEGORY_NAME, ignoreCase = true) ) { it[CategoryTable.name] = name @@ -82,9 +84,11 @@ object Category { if (from == 0 || to == 0) return transaction { val categories = - CategoryTable.select { - CategoryTable.id neq DEFAULT_CATEGORY_ID - }.orderBy(CategoryTable.order to SortOrder.ASC).toMutableList() + CategoryTable + .select { + CategoryTable.id neq DEFAULT_CATEGORY_ID + }.orderBy(CategoryTable.order to SortOrder.ASC) + .toMutableList() categories.add(to - 1, categories.removeAt(from - 1)) categories.forEachIndexed { index, cat -> CategoryTable.update({ CategoryTable.id eq cat[CategoryTable.id].value }) { @@ -106,7 +110,8 @@ object Category { /** make sure category order numbers starts from 1 and is consecutive */ fun normalizeCategories() { transaction { - CategoryTable.selectAll() + CategoryTable + .selectAll() .orderBy(CategoryTable.order to SortOrder.ASC) .sortedWith(compareBy({ it[CategoryTable.id].value != 0 }, { it[CategoryTable.order] })) .forEachIndexed { index, cat -> @@ -130,9 +135,10 @@ object Category { const val DEFAULT_CATEGORY_ID = 0 const val DEFAULT_CATEGORY_NAME = "Default" - fun getCategoryList(): List { - return transaction { - CategoryTable.selectAll() + fun getCategoryList(): List = + transaction { + CategoryTable + .selectAll() .orderBy(CategoryTable.order to SortOrder.ASC) .let { if (needsDefaultCategory()) { @@ -140,41 +146,39 @@ object Category { } else { it.andWhere { CategoryTable.id neq DEFAULT_CATEGORY_ID } } - } - .map { + }.map { CategoryTable.toDataClass(it) } } - } - fun getCategoryById(categoryId: Int): CategoryDataClass? { - return transaction { + fun getCategoryById(categoryId: Int): CategoryDataClass? = + transaction { CategoryTable.select { CategoryTable.id eq categoryId }.firstOrNull()?.let { CategoryTable.toDataClass(it) } } - } - fun getCategorySize(categoryId: Int): Int { - return transaction { + fun getCategorySize(categoryId: Int): Int = + transaction { if (categoryId == DEFAULT_CATEGORY_ID) { MangaTable .leftJoin(CategoryMangaTable) .select { MangaTable.inLibrary eq true } .andWhere { CategoryMangaTable.manga.isNull() } } else { - CategoryMangaTable.leftJoin(MangaTable).select { CategoryMangaTable.category eq categoryId } + CategoryMangaTable + .leftJoin(MangaTable) + .select { CategoryMangaTable.category eq categoryId } .andWhere { MangaTable.inLibrary eq true } }.count().toInt() } - } - fun getCategoryMetaMap(categoryId: Int): Map { - return transaction { - CategoryMetaTable.select { CategoryMetaTable.ref eq categoryId } + fun getCategoryMetaMap(categoryId: Int): Map = + transaction { + CategoryMetaTable + .select { CategoryMetaTable.ref eq categoryId } .associate { it[CategoryMetaTable.key] to it[CategoryMetaTable.value] } } - } fun modifyMeta( categoryId: Int, diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/CategoryManga.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/CategoryManga.kt index 1c8b865b..51a6a140 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/CategoryManga.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/CategoryManga.kt @@ -38,9 +38,10 @@ object CategoryManga { if (categoryId == DEFAULT_CATEGORY_ID) return fun notAlreadyInCategory() = - CategoryMangaTable.select { - (CategoryMangaTable.category eq categoryId) and (CategoryMangaTable.manga eq mangaId) - }.isEmpty() + CategoryMangaTable + .select { + (CategoryMangaTable.category eq categoryId) and (CategoryMangaTable.manga eq mangaId) + }.isEmpty() transaction { if (notAlreadyInCategory()) { @@ -69,15 +70,17 @@ object CategoryManga { // Select the required columns from the MangaTable and add the aggregate functions to compute unread, download, and chapter counts val unreadCount = wrapAsExpression( - ChapterTable.slice( - ChapterTable.id.count(), - ).select((ChapterTable.isRead eq false) and (ChapterTable.manga eq MangaTable.id)), + ChapterTable + .slice( + ChapterTable.id.count(), + ).select((ChapterTable.isRead eq false) and (ChapterTable.manga eq MangaTable.id)), ) val downloadedCount = wrapAsExpression( - ChapterTable.slice( - ChapterTable.id.count(), - ).select((ChapterTable.isDownloaded eq true) and (ChapterTable.manga eq MangaTable.id)), + ChapterTable + .slice( + ChapterTable.id.count(), + ).select((ChapterTable.isDownloaded eq true) and (ChapterTable.manga eq MangaTable.id)), ) val chapterCount = ChapterTable.id.count().alias("chapter_count") @@ -119,20 +122,23 @@ object CategoryManga { /** * list of categories that a manga belongs to */ - fun getMangaCategories(mangaId: Int): List { - return transaction { - CategoryMangaTable.innerJoin(CategoryTable).select { - CategoryMangaTable.manga eq mangaId - }.orderBy(CategoryTable.order to SortOrder.ASC).map { - CategoryTable.toDataClass(it) - } + fun getMangaCategories(mangaId: Int): List = + transaction { + CategoryMangaTable + .innerJoin(CategoryTable) + .select { + CategoryMangaTable.manga eq mangaId + }.orderBy(CategoryTable.order to SortOrder.ASC) + .map { + CategoryTable.toDataClass(it) + } } - } - fun getMangasCategories(mangaIDs: List): Map> { - return buildMap { + fun getMangasCategories(mangaIDs: List): Map> = + buildMap { transaction { - CategoryMangaTable.innerJoin(CategoryTable) + CategoryMangaTable + .innerJoin(CategoryTable) .select { CategoryMangaTable.manga inList mangaIDs } .groupBy { it[CategoryMangaTable.manga] } .forEach { @@ -143,5 +149,4 @@ object CategoryManga { } } } - } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Chapter.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Chapter.kt index 43d8d19b..c7937347 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Chapter.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Chapter.kt @@ -50,14 +50,13 @@ import java.util.TreeSet import java.util.concurrent.TimeUnit import kotlin.math.max -private fun List.removeDuplicates(currentChapter: ChapterDataClass): List { - return groupBy { it.chapterNumber } +private fun List.removeDuplicates(currentChapter: ChapterDataClass): List = + groupBy { it.chapterNumber } .map { (_, chapters) -> chapters.find { it.id == currentChapter.id } ?: chapters.find { it.scanlator == currentChapter.scanlator } ?: chapters.first() } -} object Chapter { private val logger = KotlinLogging.logger { } @@ -66,12 +65,13 @@ object Chapter { suspend fun getChapterList( mangaId: Int, onlineFetch: Boolean = false, - ): List { - return if (onlineFetch) { + ): List = + if (onlineFetch) { getSourceChapters(mangaId) } else { transaction { - ChapterTable.select { ChapterTable.manga eq mangaId } + ChapterTable + .select { ChapterTable.manga eq mangaId } .orderBy(ChapterTable.sourceOrder to SortOrder.DESC) .map { ChapterTable.toDataClass(it) @@ -80,18 +80,16 @@ object Chapter { getSourceChapters(mangaId) } } - } - fun getCountOfMangaChapters(mangaId: Int): Int { - return transaction { ChapterTable.select { ChapterTable.manga eq mangaId }.count().toInt() } - } + fun getCountOfMangaChapters(mangaId: Int): Int = transaction { ChapterTable.select { ChapterTable.manga eq mangaId }.count().toInt() } private suspend fun getSourceChapters(mangaId: Int): List { val chapterList = fetchChapterList(mangaId) val dbChapterMap = transaction { - ChapterTable.select { ChapterTable.manga eq mangaId } + ChapterTable + .select { ChapterTable.manga eq mangaId } .associateBy({ it[ChapterTable.url] }, { it }) } @@ -126,7 +124,8 @@ object Chapter { } val map: Cache = - CacheBuilder.newBuilder() + CacheBuilder + .newBuilder() .expireAfterAccess(10, TimeUnit.MINUTES) .build() @@ -173,7 +172,8 @@ object Chapter { val chaptersInDb = transaction { - ChapterTable.select { ChapterTable.manga eq mangaId } + ChapterTable + .select { ChapterTable.manga eq mangaId } .map { ChapterTable.toDataClass(it) } .toList() } @@ -259,39 +259,40 @@ object Chapter { transaction { if (chaptersToInsert.isNotEmpty()) { - ChapterTable.batchInsert(chaptersToInsert) { chapter -> - this[ChapterTable.url] = chapter.url - this[ChapterTable.name] = chapter.name - this[ChapterTable.date_upload] = chapter.uploadDate - this[ChapterTable.chapter_number] = chapter.chapterNumber - this[ChapterTable.scanlator] = chapter.scanlator - this[ChapterTable.sourceOrder] = chapter.index - this[ChapterTable.fetchedAt] = chapter.fetchedAt - this[ChapterTable.manga] = chapter.mangaId - this[ChapterTable.realUrl] = chapter.realUrl - this[ChapterTable.isRead] = false - this[ChapterTable.isBookmarked] = false - this[ChapterTable.isDownloaded] = false + ChapterTable + .batchInsert(chaptersToInsert) { chapter -> + this[ChapterTable.url] = chapter.url + this[ChapterTable.name] = chapter.name + this[ChapterTable.date_upload] = chapter.uploadDate + this[ChapterTable.chapter_number] = chapter.chapterNumber + this[ChapterTable.scanlator] = chapter.scanlator + this[ChapterTable.sourceOrder] = chapter.index + this[ChapterTable.fetchedAt] = chapter.fetchedAt + this[ChapterTable.manga] = chapter.mangaId + this[ChapterTable.realUrl] = chapter.realUrl + this[ChapterTable.isRead] = false + this[ChapterTable.isBookmarked] = false + this[ChapterTable.isDownloaded] = false - // is recognized chapter number - if (chapter.chapterNumber >= 0f && chapter.chapterNumber in deletedChapterNumbers) { - this[ChapterTable.isRead] = chapter.chapterNumber in deletedReadChapterNumbers - this[ChapterTable.isBookmarked] = chapter.chapterNumber in deletedBookmarkedChapterNumbers + // is recognized chapter number + if (chapter.chapterNumber >= 0f && chapter.chapterNumber in deletedChapterNumbers) { + this[ChapterTable.isRead] = chapter.chapterNumber in deletedReadChapterNumbers + this[ChapterTable.isBookmarked] = chapter.chapterNumber in deletedBookmarkedChapterNumbers - // only preserve download status for chapters of the same scanlator, otherwise, - // the downloaded files won't be found anyway - val downloadedChapterInfo = deletedDownloadedChapterNumberInfoMap[chapter.chapterNumber] - val pageCount = downloadedChapterInfo?.get(chapter.scanlator) - if (pageCount != null) { - this[ChapterTable.isDownloaded] = true - this[ChapterTable.pageCount] = pageCount + // only preserve download status for chapters of the same scanlator, otherwise, + // the downloaded files won't be found anyway + val downloadedChapterInfo = deletedDownloadedChapterNumberInfoMap[chapter.chapterNumber] + val pageCount = downloadedChapterInfo?.get(chapter.scanlator) + if (pageCount != null) { + this[ChapterTable.isDownloaded] = true + this[ChapterTable.pageCount] = pageCount + } + // Try to use the fetch date of the original entry to not pollute 'Updates' tab + deletedChapterNumberDateFetchMap[chapter.chapterNumber]?.let { + this[ChapterTable.fetchedAt] = it + } } - // Try to use the fetch date of the original entry to not pollute 'Updates' tab - deletedChapterNumberDateFetchMap[chapter.chapterNumber]?.let { - this[ChapterTable.fetchedAt] = it - } - } - }.forEach { insertedChapters.add(ChapterTable.toDataClass(it)) } + }.forEach { insertedChapters.add(ChapterTable.toDataClass(it)) } } if (chaptersToUpdate.isNotEmpty()) { @@ -531,7 +532,8 @@ object Chapter { if (isRead == true) { val mangaIds = transaction { - ChapterTable.select { condition } + ChapterTable + .select { condition } .map { it[ChapterTable.manga].value } .toSet() } @@ -539,21 +541,21 @@ object Chapter { } } - fun getChaptersMetaMaps(chapterIds: List>): Map, Map> { - return transaction { - ChapterMetaTable.select { ChapterMetaTable.ref inList chapterIds } + fun getChaptersMetaMaps(chapterIds: List>): Map, Map> = + transaction { + ChapterMetaTable + .select { ChapterMetaTable.ref inList chapterIds } .groupBy { it[ChapterMetaTable.ref] } .mapValues { it.value.associate { it[ChapterMetaTable.key] to it[ChapterMetaTable.value] } } .withDefault { emptyMap() } } - } - fun getChapterMetaMap(chapter: EntityID): Map { - return transaction { - ChapterMetaTable.select { ChapterMetaTable.ref eq chapter } + fun getChapterMetaMap(chapter: EntityID): Map = + transaction { + ChapterMetaTable + .select { ChapterMetaTable.ref eq chapter } .associate { it[ChapterMetaTable.key] to it[ChapterMetaTable.value] } } - } fun modifyChapterMeta( mangaId: Int, @@ -563,8 +565,10 @@ object Chapter { ) { transaction { val chapterId = - ChapterTable.select { (ChapterTable.manga eq mangaId) and (ChapterTable.sourceOrder eq chapterIndex) } - .first()[ChapterTable.id].value + ChapterTable + .select { (ChapterTable.manga eq mangaId) and (ChapterTable.sourceOrder eq chapterIndex) } + .first()[ChapterTable.id] + .value modifyChapterMeta(chapterId, key, value) } } @@ -576,7 +580,8 @@ object Chapter { ) { transaction { val meta = - ChapterMetaTable.select { (ChapterMetaTable.ref eq chapterId) and (ChapterMetaTable.key eq key) } + ChapterMetaTable + .select { (ChapterMetaTable.ref eq chapterId) and (ChapterMetaTable.key eq key) } .firstOrNull() if (meta == null) { @@ -599,8 +604,10 @@ object Chapter { ) { transaction { val chapterId = - ChapterTable.select { (ChapterTable.manga eq mangaId) and (ChapterTable.sourceOrder eq chapterIndex) } - .first()[ChapterTable.id].value + ChapterTable + .select { (ChapterTable.manga eq mangaId) and (ChapterTable.sourceOrder eq chapterIndex) } + .first()[ChapterTable.id] + .value ChapterDownloadHelper.delete(mangaId, chapterId) @@ -619,7 +626,8 @@ object Chapter { } else if (input.chapterIndexes != null && mangaId != null) { transaction { val chapterIds = - ChapterTable.slice(ChapterTable.manga, ChapterTable.id) + ChapterTable + .slice(ChapterTable.manga, ChapterTable.id) .select { (ChapterTable.sourceOrder inList input.chapterIndexes) and (ChapterTable.manga eq mangaId) } .map { row -> val chapterId = row[ChapterTable.id].value @@ -637,7 +645,8 @@ object Chapter { fun deleteChapters(chapterIds: List) { transaction { - ChapterTable.slice(ChapterTable.manga, ChapterTable.id) + ChapterTable + .slice(ChapterTable.manga, ChapterTable.id) .select { ChapterTable.id inList chapterIds } .forEach { row -> val chapterMangaId = row[ChapterTable.manga].value @@ -651,8 +660,8 @@ object Chapter { } } - fun getRecentChapters(pageNum: Int): PaginatedList { - return paginatedFrom(pageNum) { + fun getRecentChapters(pageNum: Int): PaginatedList = + paginatedFrom(pageNum) { transaction { (ChapterTable innerJoin MangaTable) .select { (MangaTable.inLibrary eq true) and (ChapterTable.fetchedAt greater MangaTable.inLibraryAt) } @@ -665,5 +674,4 @@ object Chapter { } } } - } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/ChapterDownloadHelper.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/ChapterDownloadHelper.kt index a417f9f8..5d064b34 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/ChapterDownloadHelper.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/ChapterDownloadHelper.kt @@ -16,16 +16,12 @@ object ChapterDownloadHelper { mangaId: Int, chapterId: Int, index: Int, - ): Pair { - return provider(mangaId, chapterId).getImage().execute(index) - } + ): Pair = provider(mangaId, chapterId).getImage().execute(index) fun delete( mangaId: Int, chapterId: Int, - ): Boolean { - return provider(mangaId, chapterId).delete() - } + ): Boolean = provider(mangaId, chapterId).delete() suspend fun download( mangaId: Int, @@ -33,9 +29,7 @@ object ChapterDownloadHelper { download: DownloadChapter, scope: CoroutineScope, step: suspend (DownloadChapter?, Boolean) -> Unit, - ): Boolean { - return provider(mangaId, chapterId).download().execute(download, scope, step) - } + ): Boolean = provider(mangaId, chapterId).download().execute(download, scope, step) // return the appropriate provider based on how the download was saved. For the logic is simple but will evolve when new types of downloads are available private fun provider( diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Library.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Library.kt index f5199bb6..8f9e5ce4 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Library.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Library.kt @@ -30,9 +30,10 @@ object Library { if (!manga.inLibrary) { transaction { val defaultCategories = - CategoryTable.select { - (CategoryTable.isDefault eq true) and (CategoryTable.id neq Category.DEFAULT_CATEGORY_ID) - }.toList() + CategoryTable + .select { + (CategoryTable.isDefault eq true) and (CategoryTable.id neq Category.DEFAULT_CATEGORY_ID) + }.toList() val existingCategories = CategoryMangaTable.select { CategoryMangaTable.manga eq mangaId }.toList() MangaTable.update({ MangaTable.id eq manga.id }) { diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Manga.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Manga.kt index c23c4fc8..76ff75c7 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Manga.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Manga.kt @@ -64,13 +64,12 @@ object Manga { private fun truncate( text: String?, maxLength: Int, - ): String? { - return if (text?.length ?: 0 > maxLength) { + ): String? = + if (text?.length ?: 0 > maxLength) { text?.take(maxLength - 3) + "..." } else { text } - } suspend fun getManga( mangaId: Int, @@ -227,12 +226,12 @@ object Manga { trackers = Track.getTrackRecordsByMangaId(mangaId), ) - fun getMangaMetaMap(mangaId: Int): Map { - return transaction { - MangaMetaTable.select { MangaMetaTable.ref eq mangaId } + fun getMangaMetaMap(mangaId: Int): Map = + transaction { + MangaMetaTable + .select { MangaMetaTable.ref eq mangaId } .associate { it[MangaMetaTable.key] to it[MangaMetaTable.value] } } - } fun modifyMangaMeta( mangaId: Int, @@ -241,7 +240,8 @@ object Manga { ) { transaction { val meta = - MangaMetaTable.select { (MangaMetaTable.ref eq mangaId) and (MangaMetaTable.key eq key) } + MangaMetaTable + .select { (MangaMetaTable.ref eq mangaId) and (MangaMetaTable.key eq key) } .firstOrNull() if (meta == null) { @@ -286,9 +286,10 @@ object Manga { } ?: throw NullPointerException("No thumbnail found") return try { - source.client.newCall( - GET(thumbnailUrl, source.headers, cache = CacheControl.FORCE_NETWORK), - ).awaitSuccess() + source.client + .newCall( + GET(thumbnailUrl, source.headers, cache = CacheControl.FORCE_NETWORK), + ).awaitSuccess() } catch (e: HttpException) { val tryToRefreshUrl = !refreshUrl && @@ -341,9 +342,10 @@ object Manga { val thumbnailUrl = mangaEntry[MangaTable.thumbnail_url] ?: throw NullPointerException("No thumbnail found") - network.client.newCall( - GET(thumbnailUrl, cache = CacheControl.FORCE_NETWORK), - ).await() + network.client + .newCall( + GET(thumbnailUrl, cache = CacheControl.FORCE_NETWORK), + ).await() } else -> throw IllegalArgumentException("Unknown source") @@ -372,19 +374,18 @@ object Manga { clearCachedImage(applicationDirs.thumbnailDownloadsRoot, fileName) } - fun getLatestChapter(mangaId: Int): ChapterDataClass? { - return transaction { + fun getLatestChapter(mangaId: Int): ChapterDataClass? = + transaction { ChapterTable.select { ChapterTable.manga eq mangaId }.maxByOrNull { it[ChapterTable.sourceOrder] } }?.let { ChapterTable.toDataClass(it) } - } - fun getUnreadChapters(mangaId: Int): List { - return transaction { - ChapterTable.select { (ChapterTable.manga eq mangaId) and (ChapterTable.isRead eq false) } + fun getUnreadChapters(mangaId: Int): List = + transaction { + ChapterTable + .select { (ChapterTable.manga eq mangaId) and (ChapterTable.isRead eq false) } .orderBy(ChapterTable.sourceOrder to SortOrder.DESC) .map { ChapterTable.toDataClass(it) } } - } fun isInIncludedDownloadCategory( logContext: KLogger = logger, diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/MangaList.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/MangaList.kt index 5b8961df..1436130a 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/MangaList.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/MangaList.kt @@ -21,9 +21,7 @@ import suwayomi.tachidesk.manga.model.table.toDataClass import java.time.Instant object MangaList { - fun proxyThumbnailUrl(mangaId: Int): String { - return "/api/v1/manga/$mangaId/thumbnail" - } + fun proxyThumbnailUrl(mangaId: Int): String = "/api/v1/manga/$mangaId/thumbnail" suspend fun getMangaList( sourceId: Long, @@ -47,41 +45,44 @@ object MangaList { return mangasPage.processEntries(sourceId) } - fun MangasPage.insertOrUpdate(sourceId: Long): List { - return transaction { + fun MangasPage.insertOrUpdate(sourceId: Long): List = + transaction { val existingMangaUrlsToId = - MangaTable.select { - (MangaTable.sourceReference eq sourceId) and (MangaTable.url inList mangas.map { it.url }) - }.associateBy { it[MangaTable.url] } + MangaTable + .select { + (MangaTable.sourceReference eq sourceId) and (MangaTable.url inList mangas.map { it.url }) + }.associateBy { it[MangaTable.url] } val existingMangaUrls = existingMangaUrlsToId.map { it.key } val mangasToInsert = mangas.filter { !existingMangaUrls.contains(it.url) } val insertedMangaUrlsToId = - MangaTable.batchInsert(mangasToInsert) { - this[MangaTable.url] = it.url - this[MangaTable.title] = it.title + MangaTable + .batchInsert(mangasToInsert) { + this[MangaTable.url] = it.url + this[MangaTable.title] = it.title - this[MangaTable.artist] = it.artist - this[MangaTable.author] = it.author - this[MangaTable.description] = it.description - this[MangaTable.genre] = it.genre - this[MangaTable.status] = it.status - this[MangaTable.thumbnail_url] = it.thumbnail_url - this[MangaTable.updateStrategy] = it.update_strategy.name + this[MangaTable.artist] = it.artist + this[MangaTable.author] = it.author + this[MangaTable.description] = it.description + this[MangaTable.genre] = it.genre + this[MangaTable.status] = it.status + this[MangaTable.thumbnail_url] = it.thumbnail_url + this[MangaTable.updateStrategy] = it.update_strategy.name - this[MangaTable.sourceReference] = sourceId - }.associate { Pair(it[MangaTable.url], it[MangaTable.id].value) } + this[MangaTable.sourceReference] = sourceId + }.associate { Pair(it[MangaTable.url], it[MangaTable.id].value) } // delete thumbnail in case cached data still exists insertedMangaUrlsToId.forEach { (_, id) -> Manga.clearThumbnail(id) } val mangaToUpdate = - mangas.mapNotNull { sManga -> - existingMangaUrlsToId[sManga.url]?.let { sManga to it } - }.filterNot { (_, resultRow) -> - resultRow[MangaTable.inLibrary] - } + mangas + .mapNotNull { sManga -> + existingMangaUrlsToId[sManga.url]?.let { sManga to it } + }.filterNot { (_, resultRow) -> + resultRow[MangaTable.inLibrary] + } if (mangaToUpdate.isNotEmpty()) { BatchUpdateStatement(MangaTable).apply { @@ -116,7 +117,6 @@ object MangaList { ?: throw Exception("MangaList::insertOrGet($sourceId): Something went wrong inserting browsed source mangas") } } - } fun MangasPage.processEntries(sourceId: Long): PagedMangaListDataClass { val mangasPage = this diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Page.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Page.kt index 26d47e4b..343867ec 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Page.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Page.kt @@ -51,17 +51,20 @@ object Page { val source = getCatalogueSourceOrStub(mangaEntry[MangaTable.sourceReference]) val chapterEntry = transaction { - ChapterTable.select { - (ChapterTable.sourceOrder eq chapterIndex) and (ChapterTable.manga eq mangaId) - }.first() + ChapterTable + .select { + (ChapterTable.sourceOrder eq chapterIndex) and (ChapterTable.manga eq mangaId) + }.first() } val chapterId = chapterEntry[ChapterTable.id].value val pageEntry = transaction { - PageTable.select { (PageTable.chapter eq chapterId) } + PageTable + .select { (PageTable.chapter eq chapterId) } .orderBy(PageTable.index to SortOrder.ASC) - .limit(1, index.toLong()).first() + .limit(1, index.toLong()) + .first() } val tachiyomiPage = Page( @@ -114,7 +117,5 @@ object Page { } /** converts 0 to "001" */ - fun getPageName(index: Int): String { - return String.format("%03d", index + 1) - } + fun getPageName(index: Int): String = String.format("%03d", index + 1) } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Search.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Search.kt index e2c07cdf..79d00aaa 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Search.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Search.kt @@ -95,7 +95,10 @@ object Search { private fun Filter.Select<*>.getValuesType(): String = values::class.java.componentType!!.simpleName - class SerializableGroup(name: String, state: List) : Filter>(name, state) + class SerializableGroup( + name: String, + state: List, + ) : Filter>(name, state) data class FilterObject( val type: String, diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Source.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Source.kt index 71a17564..eaf09716 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Source.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Source.kt @@ -97,11 +97,10 @@ object Source { /** * Gets a source's PreferenceScreen, puts the result into [preferenceScreenMap] */ - fun getSourcePreferences(sourceId: Long): List { - return getSourcePreferencesRaw(sourceId).map { + fun getSourcePreferences(sourceId: Long): List = + getSourcePreferencesRaw(sourceId).map { PreferenceObject(it::class.java.simpleName, it) } - } fun getSourcePreferencesRaw(sourceId: Long): List { val source = getCatalogueSourceOrStub(sourceId) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/ThumbnailDownloadHelper.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/ThumbnailDownloadHelper.kt index 7fb04010..55f6d5d3 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/ThumbnailDownloadHelper.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/ThumbnailDownloadHelper.kt @@ -4,20 +4,12 @@ import suwayomi.tachidesk.manga.impl.download.fileProvider.impl.ThumbnailFilePro import java.io.InputStream object ThumbnailDownloadHelper { - fun getImage(mangaId: Int): Pair { - return provider(mangaId).getImage().execute() - } + fun getImage(mangaId: Int): Pair = provider(mangaId).getImage().execute() - fun delete(mangaId: Int): Boolean { - return provider(mangaId).delete() - } + fun delete(mangaId: Int): Boolean = provider(mangaId).delete() - suspend fun download(mangaId: Int): Boolean { - return provider(mangaId).download().execute() - } + suspend fun download(mangaId: Int): Boolean = provider(mangaId).download().execute() // return the appropriate provider based on how the download was saved. For the logic is simple but will evolve when new types of downloads are available - private fun provider(mangaId: Int): ThumbnailFileProvider { - return ThumbnailFileProvider(mangaId) - } + private fun provider(mangaId: Int): ThumbnailFileProvider = ThumbnailFileProvider(mangaId) } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/models/Chapter.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/models/Chapter.kt index fc24246f..3ecb6c61 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/models/Chapter.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/models/Chapter.kt @@ -5,7 +5,9 @@ package suwayomi.tachidesk.manga.impl.backup.models import eu.kanade.tachiyomi.source.model.SChapter import java.io.Serializable -interface Chapter : SChapter, Serializable { +interface Chapter : + SChapter, + Serializable { var id: Long? var manga_id: Long? diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/models/ChapterImpl.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/models/ChapterImpl.kt index 82f743ea..4b7afac9 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/models/ChapterImpl.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/models/ChapterImpl.kt @@ -36,7 +36,5 @@ class ChapterImpl : Chapter { return id == chapter.id } - override fun hashCode(): Int { - return url.hashCode() + id.hashCode() - } + override fun hashCode(): Int = url.hashCode() + id.hashCode() } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/models/Manga.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/models/Manga.kt index 50b868c8..90cca6aa 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/models/Manga.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/models/Manga.kt @@ -41,13 +41,9 @@ interface Manga : SManga { setChapterFlags(order, CHAPTER_SORT_MASK) } - fun sortDescending(): Boolean { - return chapter_flags and CHAPTER_SORT_MASK == CHAPTER_SORT_DESC - } + fun sortDescending(): Boolean = chapter_flags and CHAPTER_SORT_MASK == CHAPTER_SORT_DESC - fun getGenres(): List? { - return genre?.split(", ")?.map { it.trim() } - } + fun getGenres(): List? = genre?.split(", ")?.map { it.trim() } private fun setChapterFlags( flag: Int, diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/models/MangaImpl.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/models/MangaImpl.kt index 45a97bc5..df936905 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/models/MangaImpl.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/models/MangaImpl.kt @@ -63,7 +63,5 @@ open class MangaImpl : Manga { return id == manga.id } - override fun hashCode(): Int { - return url.hashCode() + id.hashCode() - } + override fun hashCode(): Int = url.hashCode() + id.hashCode() } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/proto/ProtoBackupExport.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/proto/ProtoBackupExport.kt index a7691d6b..3bd5989f 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/proto/ProtoBackupExport.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/proto/ProtoBackupExport.kt @@ -93,10 +93,15 @@ object ProtoBackupExport : ProtoBackupBase() { } } - val (hour, minute) = serverConfig.backupTime.value.split(":").map { it.toInt() } + val (hour, minute) = + serverConfig.backupTime.value + .split(":") + .map { it.toInt() } val backupHour = hour.coerceAtLeast(0).coerceAtMost(23) val backupMinute = minute.coerceAtLeast(0).coerceAtMost(59) - val backupInterval = serverConfig.backupInterval.value.days.coerceAtLeast(1.days) + val backupInterval = + serverConfig.backupInterval.value.days + .coerceAtLeast(1.days) // trigger last backup in case the server wasn't running on the scheduled time val lastAutomatedBackup = preferences.getLong(LAST_AUTOMATED_BACKUP_KEY, 0) @@ -161,7 +166,10 @@ object ProtoBackupExport : ProtoBackupBase() { val lastAccessTime = file.lastModified() val isTTLReached = - System.currentTimeMillis() - lastAccessTime >= serverConfig.backupTTL.value.days.coerceAtLeast(1.days).inWholeMilliseconds + System.currentTimeMillis() - lastAccessTime >= + serverConfig.backupTTL.value.days + .coerceAtLeast(1.days) + .inWholeMilliseconds if (isTTLReached) { file.delete() } @@ -185,7 +193,11 @@ object ProtoBackupExport : ProtoBackupBase() { val byteArray = parser.encodeToByteArray(BackupSerializer, backup) val byteStream = ByteArrayOutputStream() - byteStream.sink().gzip().buffer().use { it.write(byteArray) } + byteStream + .sink() + .gzip() + .buffer() + .use { it.write(byteArray) } return byteStream.toByteArray().inputStream() } @@ -193,8 +205,8 @@ object ProtoBackupExport : ProtoBackupBase() { private fun backupManga( databaseManga: Query, flags: BackupFlags, - ): List { - return databaseManga.map { mangaRow -> + ): List = + databaseManga.map { mangaRow -> val backupManga = BackupManga( source = mangaRow[MangaTable.sourceReference], @@ -216,7 +228,8 @@ object ProtoBackupExport : ProtoBackupBase() { if (flags.includeChapters) { val chapters = transaction { - ChapterTable.select { ChapterTable.manga eq mangaId } + ChapterTable + .select { ChapterTable.manga eq mangaId } .orderBy(ChapterTable.sourceOrder to SortOrder.DESC) .map { ChapterTable.toDataClass(it) @@ -277,22 +290,23 @@ object ProtoBackupExport : ProtoBackupBase() { backupManga } - } - private fun backupCategories(): List { - return CategoryTable.selectAll().orderBy(CategoryTable.order to SortOrder.ASC).map { - CategoryTable.toDataClass(it) - }.map { - BackupCategory( - it.name, - it.order, - 0, // not supported in Tachidesk - ) - } - } + private fun backupCategories(): List = + CategoryTable + .selectAll() + .orderBy(CategoryTable.order to SortOrder.ASC) + .map { + CategoryTable.toDataClass(it) + }.map { + BackupCategory( + it.name, + it.order, + 0, // not supported in Tachidesk + ) + } - private fun backupExtensionInfo(mangas: Query): List { - return mangas + private fun backupExtensionInfo(mangas: Query): List = + mangas .asSequence() .map { it[MangaTable.sourceReference] } .distinct() @@ -302,7 +316,5 @@ object ProtoBackupExport : ProtoBackupBase() { sourceRow?.get(SourceTable.name) ?: "", it, ) - } - .toList() - } + }.toList() } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/proto/ProtoBackupImport.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/proto/ProtoBackupImport.kt index ff7a4da4..a1df7706 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/proto/ProtoBackupImport.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/proto/ProtoBackupImport.kt @@ -74,18 +74,22 @@ object ProtoBackupImport : ProtoBackupBase() { data object Failure : BackupRestoreState() - data class RestoringCategories(val totalManga: Int) : BackupRestoreState() + data class RestoringCategories( + val totalManga: Int, + ) : BackupRestoreState() - data class RestoringManga(val current: Int, val totalManga: Int, val title: String) : BackupRestoreState() + data class RestoringManga( + val current: Int, + val totalManga: Int, + val title: String, + ) : BackupRestoreState() } private val backupRestoreIdToState = mutableMapOf() val notifyFlow = MutableSharedFlow(extraBufferCapacity = 1, onBufferOverflow = DROP_OLDEST) - fun getRestoreState(id: String): BackupRestoreState? { - return backupRestoreIdToState[id] - } + fun getRestoreState(id: String): BackupRestoreState? = backupRestoreIdToState[id] private fun updateRestoreState( id: String, @@ -131,8 +135,8 @@ object ProtoBackupImport : ProtoBackupBase() { suspend fun restoreLegacy( sourceStream: InputStream, restoreId: String = "legacy", - ): ValidationResult { - return backupMutex.withLock { + ): ValidationResult = + backupMutex.withLock { try { logger.info { "restore($restoreId): restoring..." } performRestore(restoreId, sourceStream) @@ -151,13 +155,17 @@ object ProtoBackupImport : ProtoBackupBase() { cleanupRestoreState(restoreId) } } - } private fun performRestore( id: String, sourceStream: InputStream, ): ValidationResult { - val backupString = sourceStream.source().gzip().buffer().use { it.readByteArray() } + val backupString = + sourceStream + .source() + .gzip() + .buffer() + .use { it.readByteArray() } val backup = parser.decodeFromByteArray(BackupSerializer, backupString) val validationResult = validate(backup) @@ -174,7 +182,8 @@ object ProtoBackupImport : ProtoBackupBase() { transaction { backup.backupCategories.associate { val dbCategory = - CategoryTable.select { CategoryTable.name eq it.name } + CategoryTable + .select { CategoryTable.name eq it.name } .firstOrNull() val categoryId = dbCategory?.let { categoryResultRow -> @@ -265,7 +274,8 @@ object ProtoBackupImport : ProtoBackupBase() { ) { val dbManga = transaction { - MangaTable.select { (MangaTable.url eq manga.url) and (MangaTable.sourceReference eq manga.source) } + MangaTable + .select { (MangaTable.url eq manga.url) and (MangaTable.sourceReference eq manga.source) } .firstOrNull() } @@ -274,26 +284,27 @@ object ProtoBackupImport : ProtoBackupBase() { transaction { // insert manga to database val mangaId = - MangaTable.insertAndGetId { - it[url] = manga.url - it[title] = manga.title + MangaTable + .insertAndGetId { + it[url] = manga.url + it[title] = manga.title - it[artist] = manga.artist - it[author] = manga.author - it[description] = manga.description - it[genre] = manga.genre - it[status] = manga.status - it[thumbnail_url] = manga.thumbnail_url - it[updateStrategy] = manga.update_strategy.name + it[artist] = manga.artist + it[author] = manga.author + it[description] = manga.description + it[genre] = manga.genre + it[status] = manga.status + it[thumbnail_url] = manga.thumbnail_url + it[updateStrategy] = manga.update_strategy.name - it[sourceReference] = manga.source + it[sourceReference] = manga.source - it[initialized] = manga.description != null + it[initialized] = manga.description != null - it[inLibrary] = manga.favorite + it[inLibrary] = manga.favorite - it[inLibraryAt] = TimeUnit.MILLISECONDS.toSeconds(manga.date_added) - }.value + it[inLibraryAt] = TimeUnit.MILLISECONDS.toSeconds(manga.date_added) + }.value // delete thumbnail in case cached data still exists clearThumbnail(mangaId) @@ -394,34 +405,36 @@ object ProtoBackupImport : ProtoBackupBase() { } val dbTrackRecordsByTrackerId = - Tracker.getTrackRecordsByMangaId(mangaId) + Tracker + .getTrackRecordsByMangaId(mangaId) .mapNotNull { it.record?.toTrack() } .associateBy { it.sync_id } val (existingTracks, newTracks) = - tracks.mapNotNull { backupTrack -> - val track = backupTrack.toTrack(mangaId) + tracks + .mapNotNull { backupTrack -> + val track = backupTrack.toTrack(mangaId) - val isUnsupportedTracker = TrackerManager.getTracker(track.sync_id) == null - if (isUnsupportedTracker) { - return@mapNotNull null - } + val isUnsupportedTracker = TrackerManager.getTracker(track.sync_id) == null + if (isUnsupportedTracker) { + return@mapNotNull null + } - val dbTrack = - dbTrackRecordsByTrackerId[backupTrack.syncId] - ?: // new track - return@mapNotNull track + val dbTrack = + dbTrackRecordsByTrackerId[backupTrack.syncId] + ?: // new track + return@mapNotNull track - if (track.toTrackRecordDataClass().forComparison() == dbTrack.toTrackRecordDataClass().forComparison()) { - return@mapNotNull null - } + if (track.toTrackRecordDataClass().forComparison() == dbTrack.toTrackRecordDataClass().forComparison()) { + return@mapNotNull null + } - dbTrack.also { - it.media_id = track.media_id - it.library_id = track.library_id - it.last_chapter_read = max(dbTrack.last_chapter_read, track.last_chapter_read) - } - }.partition { (it.id ?: -1) > 0 } + dbTrack.also { + it.media_id = track.media_id + it.library_id = track.library_id + it.last_chapter_read = max(dbTrack.last_chapter_read, track.last_chapter_read) + } + }.partition { (it.id ?: -1) > 0 } existingTracks.forEach(Tracker::updateTrackRecord) newTracks.forEach(Tracker::insertTrackRecord) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/proto/ProtoBackupValidator.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/proto/ProtoBackupValidator.kt index 35ecbf87..edba7f90 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/proto/ProtoBackupValidator.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/proto/ProtoBackupValidator.kt @@ -64,7 +64,12 @@ object ProtoBackupValidator { } fun validate(sourceStream: InputStream): ValidationResult { - val backupString = sourceStream.source().gzip().buffer().use { it.readByteArray() } + val backupString = + sourceStream + .source() + .gzip() + .buffer() + .use { it.readByteArray() } val backup = ProtoBackupImport.parser.decodeFromByteArray(BackupSerializer, backupString) return validate(backup) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/proto/models/Backup.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/proto/models/Backup.kt index faa48891..a3a16457 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/proto/models/Backup.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/proto/models/Backup.kt @@ -14,10 +14,9 @@ data class Backup( @ProtoNumber(100) var brokenBackupSources: List = emptyList(), @ProtoNumber(101) var backupSources: List = emptyList(), ) { - fun getSourceMap(): Map { - return (brokenBackupSources.map { BackupSource(it.name, it.sourceId) } + backupSources) + fun getSourceMap(): Map = + (brokenBackupSources.map { BackupSource(it.name, it.sourceId) } + backupSources) .associate { it.sourceId to it.name } - } companion object { fun getBasename(name: String = ""): String { diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/proto/models/BackupChapter.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/proto/models/BackupChapter.kt index 30cc0acd..3e3d4277 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/proto/models/BackupChapter.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/proto/models/BackupChapter.kt @@ -21,8 +21,8 @@ data class BackupChapter( @ProtoNumber(9) var chapterNumber: Float = 0F, @ProtoNumber(10) var sourceOrder: Int = 0, ) { - fun toChapterImpl(): ChapterImpl { - return ChapterImpl().apply { + fun toChapterImpl(): ChapterImpl = + ChapterImpl().apply { url = this@BackupChapter.url name = this@BackupChapter.name chapter_number = this@BackupChapter.chapterNumber @@ -34,5 +34,4 @@ data class BackupChapter( date_upload = this@BackupChapter.dateUpload source_order = this@BackupChapter.sourceOrder } - } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/proto/models/BackupManga.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/proto/models/BackupManga.kt index 0fe37d16..4f76dceb 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/proto/models/BackupManga.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/proto/models/BackupManga.kt @@ -39,8 +39,8 @@ data class BackupManga( @ProtoNumber(104) var history: List = emptyList(), @ProtoNumber(105) var updateStrategy: UpdateStrategy = UpdateStrategy.ALWAYS_UPDATE, ) { - fun getMangaImpl(): MangaImpl { - return MangaImpl().apply { + fun getMangaImpl(): MangaImpl = + MangaImpl().apply { url = this@BackupManga.url title = this@BackupManga.title artist = this@BackupManga.artist @@ -56,23 +56,20 @@ data class BackupManga( chapter_flags = this@BackupManga.chapterFlags update_strategy = this@BackupManga.updateStrategy } - } - fun getChaptersImpl(): List { - return chapters.map { + fun getChaptersImpl(): List = + chapters.map { it.toChapterImpl() } - } - fun getTrackingImpl(): List { - return tracking.map { + fun getTrackingImpl(): List = + tracking.map { it.getTrackingImpl() } - } companion object { - fun copyFrom(manga: Manga): BackupManga { - return BackupManga( + fun copyFrom(manga: Manga): BackupManga = + BackupManga( url = manga.url, title = manga.title, artist = manga.artist, @@ -88,6 +85,5 @@ data class BackupManga( viewer_flags = manga.viewer_flags, chapterFlags = manga.chapter_flags, ) - } } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/proto/models/BackupSource.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/proto/models/BackupSource.kt index d5256ba5..c4586a8f 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/proto/models/BackupSource.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/proto/models/BackupSource.kt @@ -16,11 +16,10 @@ data class BackupSource( @ProtoNumber(2) var sourceId: Long, ) { companion object { - fun copyFrom(source: Source): BackupSource { - return BackupSource( + fun copyFrom(source: Source): BackupSource = + BackupSource( name = source.name, sourceId = source.id, ) - } } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/proto/models/BackupTracking.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/proto/models/BackupTracking.kt index 306c4327..de6a5c30 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/proto/models/BackupTracking.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/backup/proto/models/BackupTracking.kt @@ -28,8 +28,8 @@ data class BackupTracking( @ProtoNumber(11) var finishedReadingDate: Long = 0, @ProtoNumber(100) var mediaId: Long = 0, ) { - fun getTrackingImpl(): TrackImpl { - return TrackImpl().apply { + fun getTrackingImpl(): TrackImpl = + TrackImpl().apply { sync_id = this@BackupTracking.syncId media_id = if (this@BackupTracking.mediaIdInt != 0) { @@ -48,11 +48,10 @@ data class BackupTracking( finished_reading_date = this@BackupTracking.finishedReadingDate tracking_url = this@BackupTracking.trackingUrl } - } companion object { - fun copyFrom(track: Track): BackupTracking { - return BackupTracking( + fun copyFrom(track: Track): BackupTracking = + BackupTracking( syncId = track.sync_id, mediaId = track.media_id, // forced not null so its compatible with 1.x backup system @@ -67,6 +66,5 @@ data class BackupTracking( finishedReadingDate = track.finished_reading_date, trackingUrl = track.tracking_url, ) - } } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/chapter/ChapterForDownload.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/chapter/ChapterForDownload.kt index 946843e4..bc029d55 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/chapter/ChapterForDownload.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/chapter/ChapterForDownload.kt @@ -37,16 +37,12 @@ suspend fun getChapterDownloadReady( return chapter.asDownloadReady() } -suspend fun getChapterDownloadReadyById(chapterId: Int): ChapterDataClass { - return getChapterDownloadReady(chapterId = chapterId) -} +suspend fun getChapterDownloadReadyById(chapterId: Int): ChapterDataClass = getChapterDownloadReady(chapterId = chapterId) suspend fun getChapterDownloadReadyByIndex( chapterIndex: Int, mangaId: Int, -): ChapterDataClass { - return getChapterDownloadReady(chapterIndex = chapterIndex, mangaId = mangaId) -} +): ChapterDataClass = getChapterDownloadReady(chapterIndex = chapterIndex, mangaId = mangaId) private class ChapterForDownload( optChapterId: Int? = null, @@ -101,15 +97,16 @@ private class ChapterForDownload( optChapterIndex: Int? = null, optMangaId: Int? = null, ) = transaction { - ChapterTable.select { - if (optChapterId != null) { - ChapterTable.id eq optChapterId - } else if (optChapterIndex != null && optMangaId != null) { - (ChapterTable.sourceOrder eq optChapterIndex) and (ChapterTable.manga eq optMangaId) - } else { - throw Exception("'optChapterId' or 'optChapterIndex' and 'optMangaId' have to be passed") - } - }.first() + ChapterTable + .select { + if (optChapterId != null) { + ChapterTable.id eq optChapterId + } else if (optChapterIndex != null && optMangaId != null) { + (ChapterTable.sourceOrder eq optChapterIndex) and (ChapterTable.manga eq optMangaId) + } else { + throw Exception("'optChapterId' or 'optChapterIndex' and 'optMangaId' have to be passed") + } + }.first() } private suspend fun fetchPageList(): List { @@ -166,12 +163,11 @@ private class ChapterForDownload( } } - private fun firstPageExists(): Boolean { - return try { + private fun firstPageExists(): Boolean = + try { ChapterDownloadHelper.getImage(mangaId, chapterId, 0).first.close() true } catch (e: Exception) { false } - } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/DownloadManager.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/DownloadManager.kt index 79295ad1..08d8db3b 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/DownloadManager.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/DownloadManager.kt @@ -63,12 +63,17 @@ object DownloadManager { private val sharedPreferences = Injekt.get().getSharedPreferences(DownloadManager::class.jvmName, Context.MODE_PRIVATE) - private fun loadDownloadQueue(): List { - return sharedPreferences.getStringSet(DOWNLOAD_QUEUE_KEY, emptySet())?.mapNotNull { it.toInt() }.orEmpty() - } + private fun loadDownloadQueue(): List = + sharedPreferences + .getStringSet(DOWNLOAD_QUEUE_KEY, emptySet()) + ?.mapNotNull { + it.toInt() + }.orEmpty() private fun saveDownloadQueue() { - sharedPreferences.edit().putStringSet(DOWNLOAD_QUEUE_KEY, downloadQueue.map { it.chapter.id.toString() }.toSet()) + sharedPreferences + .edit() + .putStringSet(DOWNLOAD_QUEUE_KEY, downloadQueue.map { it.chapter.id.toString() }.toSet()) .apply() } @@ -159,8 +164,8 @@ object DownloadManager { } } - private fun getStatus(): DownloadStatus { - return DownloadStatus( + private fun getStatus(): DownloadStatus = + DownloadStatus( if (downloadQueue.none { it.state == Downloading }) { Status.Stopped } else { @@ -168,7 +173,6 @@ object DownloadManager { }, downloadQueue.toList(), ) - } private val downloaderWatch = MutableSharedFlow(extraBufferCapacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST) @@ -201,13 +205,13 @@ object DownloadManager { } if (runningDownloaders.size < serverConfig.maxSourcesInParallel.value) { - availableDownloads.asSequence() + availableDownloads + .asSequence() .map { it.manga.sourceId } .distinct() .minus( runningDownloaders.map { it.sourceId }.toSet(), - ) - .take(serverConfig.maxSourcesInParallel.value - runningDownloaders.size) + ).take(serverConfig.maxSourcesInParallel.value - runningDownloaders.size) .map { getDownloader(it) } .forEach { it.start() @@ -271,7 +275,8 @@ object DownloadManager { val mangas = transaction { - chapters.distinctBy { chapter -> chapter[MangaTable.id] } + chapters + .distinctBy { chapter -> chapter[MangaTable.id] } .map { MangaTable.toDataClass(it) } .associateBy { it.id } } @@ -420,11 +425,12 @@ object DownloadManager { logger.debug { "stop" } coroutineScope { - downloaders.map { (_, downloader) -> - async { - downloader.stop() - } - }.awaitAll() + downloaders + .map { (_, downloader) -> + async { + downloader.stop() + } + }.awaitAll() } notifyAllClients() } @@ -439,7 +445,9 @@ object DownloadManager { } } -enum class DownloaderState(val state: Int) { +enum class DownloaderState( + val state: Int, +) { Stopped(0), Running(1), Paused(2), diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/Downloader.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/Downloader.kt index b3abde53..1a4b7c79 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/Downloader.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/Downloader.kt @@ -69,16 +69,17 @@ class Downloader( fun start() { if (!isActive) { job = - scope.launch { - run() - }.also { job -> - job.invokeOnCompletion { - if (it !is CancellationException) { - logger.debug { "completed" } - onComplete() + scope + .launch { + run() + }.also { job -> + job.invokeOnCompletion { + if (it !is CancellationException) { + logger.debug { "completed" } + onComplete() + } } } - } logger.debug { "started" } notifier(false) } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/fileProvider/ChaptersFilesProvider.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/fileProvider/ChaptersFilesProvider.kt index e746c122..73c8e2ca 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/fileProvider/ChaptersFilesProvider.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/fileProvider/ChaptersFilesProvider.kt @@ -23,12 +23,16 @@ import java.io.File import java.io.InputStream sealed class FileType { - data class RegularFile(val file: File) : FileType() + data class RegularFile( + val file: File, + ) : FileType() - data class ZipFile(val entry: ZipArchiveEntry) : FileType() + data class ZipFile( + val entry: ZipArchiveEntry, + ) : FileType() - fun getName(): String { - return when (this) { + fun getName(): String = + when (this) { is FileType.RegularFile -> { this.file.name } @@ -36,10 +40,9 @@ sealed class FileType { this.entry.name } } - } - fun getExtension(): String { - return when (this) { + fun getExtension(): String = + when (this) { is FileType.RegularFile -> { this.file.extension } @@ -47,13 +50,15 @@ sealed class FileType { this.entry.name.substringAfterLast(".") } } - } } /* * Base class for downloaded chapter files provider, example: Folder, Archive */ -abstract class ChaptersFilesProvider(val mangaId: Int, val chapterId: Int) : DownloadedFilesProvider { +abstract class ChaptersFilesProvider( + val mangaId: Int, + val chapterId: Int, +) : DownloadedFilesProvider { protected abstract fun getImageFiles(): List protected abstract fun getImageInputStream(image: Type): InputStream @@ -71,9 +76,7 @@ abstract class ChaptersFilesProvider(val mangaId: Int, val chap return Pair(getImageInputStream(image).buffered(), "image/$imageFileType") } - override fun getImage(): RetrieveFile1Args { - return RetrieveFile1Args(::getImageImpl) - } + override fun getImage(): RetrieveFile1Args = RetrieveFile1Args(::getImageImpl) /** * Extract the existing download to the base download folder (see [getChapterDownloadPath]) @@ -110,21 +113,22 @@ abstract class ChaptersFilesProvider(val mangaId: Int, val chap } try { - Page.getPageImage( - mangaId = download.mangaId, - chapterIndex = download.chapterIndex, - index = pageNum, - ) { flow -> - pageProgressJob = - flow - .sample(100) - .distinctUntilChanged() - .onEach { - download.progress = (pageNum.toFloat() + (it.toFloat() * 0.01f)) / pageCount - step(null, false) // don't throw on canceled download here since we can't do anything - } - .launchIn(scope) - }.first.close() + Page + .getPageImage( + mangaId = download.mangaId, + chapterIndex = download.chapterIndex, + index = pageNum, + ) { flow -> + pageProgressJob = + flow + .sample(100) + .distinctUntilChanged() + .onEach { + download.progress = (pageNum.toFloat() + (it.toFloat() * 0.01f)) / pageCount + step(null, false) // don't throw on canceled download here since we can't do anything + }.launchIn(scope) + }.first + .close() } finally { // always cancel the page progress job even if it throws an exception to avoid memory leaks pageProgressJob?.cancel() @@ -151,9 +155,8 @@ abstract class ChaptersFilesProvider(val mangaId: Int, val chap return true } - override fun download(): FileDownload3Args Unit> { - return FileDownload3Args(::downloadImpl) - } + override fun download(): FileDownload3Args Unit> = + FileDownload3Args(::downloadImpl) abstract override fun delete(): Boolean } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/fileProvider/DownloadedFilesProvider.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/fileProvider/DownloadedFilesProvider.kt index 0b45f06a..26ea0ba6 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/fileProvider/DownloadedFilesProvider.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/fileProvider/DownloadedFilesProvider.kt @@ -1,5 +1,7 @@ package suwayomi.tachidesk.manga.impl.download.fileProvider -interface DownloadedFilesProvider : FileDownloader, FileRetriever { +interface DownloadedFilesProvider : + FileDownloader, + FileRetriever { fun delete(): Boolean } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/fileProvider/FileDownloader.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/fileProvider/FileDownloader.kt index aaf86e56..6b8f2c1a 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/fileProvider/FileDownloader.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/fileProvider/FileDownloader.kt @@ -7,9 +7,7 @@ fun interface FileDownload { fun interface FileDownload0Args : FileDownload { suspend fun execute(): Boolean - override suspend fun executeDownload(vararg args: Any): Boolean { - return execute() - } + override suspend fun executeDownload(vararg args: Any): Boolean = execute() } @Suppress("UNCHECKED_CAST") @@ -20,9 +18,7 @@ fun interface FileDownload3Args : FileDownload { c: C, ): Boolean - override suspend fun executeDownload(vararg args: Any): Boolean { - return execute(args[0] as A, args[1] as B, args[2] as C) - } + override suspend fun executeDownload(vararg args: Any): Boolean = execute(args[0] as A, args[1] as B, args[2] as C) } fun interface FileDownloader { diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/fileProvider/FileRetriever.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/fileProvider/FileRetriever.kt index b8d881d7..81c09f80 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/fileProvider/FileRetriever.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/fileProvider/FileRetriever.kt @@ -9,18 +9,14 @@ fun interface RetrieveFile { fun interface RetrieveFile0Args : RetrieveFile { fun execute(): Pair - override fun executeGetImage(vararg args: Any): Pair { - return execute() - } + override fun executeGetImage(vararg args: Any): Pair = execute() } @Suppress("UNCHECKED_CAST") fun interface RetrieveFile1Args : RetrieveFile { fun execute(a: A): Pair - override fun executeGetImage(vararg args: Any): Pair { - return execute(args[0] as A) - } + override fun executeGetImage(vararg args: Any): Pair = execute(args[0] as A) } fun interface FileRetriever { diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/fileProvider/impl/ArchiveProvider.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/fileProvider/impl/ArchiveProvider.kt index 2ac29521..91ee981d 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/fileProvider/impl/ArchiveProvider.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/fileProvider/impl/ArchiveProvider.kt @@ -21,15 +21,21 @@ import java.io.InputStream private val applicationDirs by DI.global.instance() -class ArchiveProvider(mangaId: Int, chapterId: Int) : ChaptersFilesProvider(mangaId, chapterId) { +class ArchiveProvider( + mangaId: Int, + chapterId: Int, +) : ChaptersFilesProvider(mangaId, chapterId) { override fun getImageFiles(): List { - val zipFile = ZipFile(getChapterCbzPath(mangaId, chapterId)) + val zipFile = ZipFile.builder().setFile(getChapterCbzPath(mangaId, chapterId)).get() return zipFile.entries.toList().map { FileType.ZipFile(it) } } - override fun getImageInputStream(image: FileType.ZipFile): InputStream { - return ZipFile(getChapterCbzPath(mangaId, chapterId)).getInputStream(image.entry) - } + override fun getImageInputStream(image: FileType.ZipFile): InputStream = + ZipFile + .builder() + .setFile(getChapterCbzPath(mangaId, chapterId)) + .get() + .getInputStream(image.entry) override fun extractExistingDownload() { val outputFile = File(getChapterCbzPath(mangaId, chapterId)) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/fileProvider/impl/FolderProvider.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/fileProvider/impl/FolderProvider.kt index 0386b7b8..aef504f2 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/fileProvider/impl/FolderProvider.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/fileProvider/impl/FolderProvider.kt @@ -17,7 +17,10 @@ private val applicationDirs by DI.global.instance() /* * Provides downloaded files when pages were downloaded into folders * */ -class FolderProvider(mangaId: Int, chapterId: Int) : ChaptersFilesProvider(mangaId, chapterId) { +class FolderProvider( + mangaId: Int, + chapterId: Int, +) : ChaptersFilesProvider(mangaId, chapterId) { override fun getImageFiles(): List { val chapterFolder = File(getChapterDownloadPath(mangaId, chapterId)) @@ -25,12 +28,14 @@ class FolderProvider(mangaId: Int, chapterId: Int) : ChaptersFilesProvider() -class ThumbnailFileProvider(val mangaId: Int) : DownloadedFilesProvider { +class ThumbnailFileProvider( + val mangaId: Int, +) : DownloadedFilesProvider { private fun getFilePath(): String? { val thumbnailDir = applicationDirs.thumbnailDownloadsRoot val fileName = mangaId.toString() @@ -36,9 +38,7 @@ class ThumbnailFileProvider(val mangaId: Int) : DownloadedFilesProvider { return getCachedImageResponse(filePath, filePathWithoutExt) } - override fun getImage(): RetrieveFile0Args { - return RetrieveFile0Args(::getImageImpl) - } + override fun getImage(): RetrieveFile0Args = RetrieveFile0Args(::getImageImpl) private suspend fun downloadImpl(): Boolean { val isExistingFile = getFilePath() != null @@ -55,9 +55,7 @@ class ThumbnailFileProvider(val mangaId: Int) : DownloadedFilesProvider { return true } - override fun download(): FileDownload0Args { - return FileDownload0Args(::downloadImpl) - } + override fun download(): FileDownload0Args = FileDownload0Args(::downloadImpl) override fun delete(): Boolean { val filePath = getFilePath() diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/model/DownloadChapter.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/model/DownloadChapter.kt index 03a5966f..8939ec4b 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/model/DownloadChapter.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/model/DownloadChapter.kt @@ -20,7 +20,6 @@ class DownloadChapter( var progress: Float = 0f, var tries: Int = 0, ) { - override fun toString(): String { - return "${manga.title} ($mangaId) - ${chapter.name} (${chapter.id}) | state= $state, tries= $tries, progress= $progress" - } + override fun toString(): String = + "${manga.title} ($mangaId) - ${chapter.name} (${chapter.id}) | state= $state, tries= $tries, progress= $progress" } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/model/DownloadState.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/model/DownloadState.kt index 61ef7d11..a93618fe 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/model/DownloadState.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/download/model/DownloadState.kt @@ -7,7 +7,9 @@ package suwayomi.tachidesk.manga.impl.download.model * 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/. */ -enum class DownloadState(val state: Int) { +enum class DownloadState( + val state: Int, +) { Queued(0), Downloading(1), Finished(2), diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/extension/Extension.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/extension/Extension.kt index 0b804e5f..da1983c7 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/extension/Extension.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/extension/Extension.kt @@ -78,8 +78,8 @@ object Extension { suspend fun installExternalExtension( inputStream: InputStream, apkName: String, - ): Int { - return installAPK(true) { + ): Int = + installAPK(true) { val savePath = "${applicationDirs.extensionsRoot}/$apkName" logger.debug { "Saving apk at $apkName" } // download apk file @@ -92,7 +92,6 @@ object Extension { } savePath } - } suspend fun installAPK( forceReinstall: Boolean = false, @@ -174,7 +173,10 @@ object Extension { else -> "all" } - val extensionName = packageInfo.applicationInfo.nonLocalizedLabel.toString().substringAfter("Tachiyomi: ") + val extensionName = + packageInfo.applicationInfo.nonLocalizedLabel + .toString() + .substringAfter("Tachiyomi: ") // update extension info transaction { @@ -277,9 +279,10 @@ object Extension { savePath: String, ) { val response = - network.client.newCall( - GET(url, cache = CacheControl.FORCE_NETWORK), - ).await() + network.client + .newCall( + GET(url, cache = CacheControl.FORCE_NETWORK), + ).await() val downloadedFile = File(savePath) downloadedFile.sink().buffer().use { sink -> @@ -355,13 +358,12 @@ object Extension { val cacheSaveDir = "${applicationDirs.extensionsRoot}/icon" return getImageResponse(cacheSaveDir, apkName) { - network.client.newCall( - GET(iconUrl, cache = CacheControl.FORCE_NETWORK), - ).await() + network.client + .newCall( + GET(iconUrl, cache = CacheControl.FORCE_NETWORK), + ).await() } } - fun getExtensionIconUrl(apkName: String): String { - return "/api/v1/extension/icon/$apkName" - } + fun getExtensionIconUrl(apkName: String): String = "/api/v1/extension/icon/$apkName" } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/extension/ExtensionsList.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/extension/ExtensionsList.kt index 7d3f4b7b..489d45c1 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/extension/ExtensionsList.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/extension/ExtensionsList.kt @@ -39,13 +39,14 @@ object ExtensionsList { // update if 60 seconds has passed or requested offline and database is empty val extensions = serverConfig.extensionRepos.value.map { repo -> - kotlin.runCatching { - ExtensionGithubApi.findExtensions(repo.repoUrlReplace()) - }.onFailure { - logger.warn(it) { - "Failed to fetch extensions for repo: $repo" + kotlin + .runCatching { + ExtensionGithubApi.findExtensions(repo.repoUrlReplace()) + }.onFailure { + logger.warn(it) { + "Failed to fetch extensions for repo: $repo" + } } - } } val foundExtensions = extensions.mapNotNull { it.getOrNull() }.flatten() updateExtensionDatabase(foundExtensions) @@ -94,12 +95,15 @@ object ExtensionsList { updateExtensionDatabaseMutex.withLock { transaction { val uniqueExtensions = - foundExtensions.groupBy { it.pkgName }.mapValues { - (_, extension) -> - extension.maxBy { it.versionCode } - }.values + foundExtensions + .groupBy { it.pkgName } + .mapValues { (_, extension) -> + extension.maxBy { it.versionCode } + }.values val installedExtensions = - ExtensionTable.selectAll().toList() + ExtensionTable + .selectAll() + .toList() .associateBy { it[ExtensionTable.pkgName] } val extensionsToUpdate = mutableListOf>() val extensionsToInsert = mutableListOf() @@ -189,7 +193,8 @@ object ExtensionsList { // deal with obsolete extensions val extensionsToRemove = - extensionsToDelete.groupBy { it[ExtensionTable.isInstalled] } + extensionsToDelete + .groupBy { it[ExtensionTable.isInstalled] } .mapValues { (_, extensions) -> extensions.map { it[ExtensionTable.pkgName] } } // not in the repo, so these extensions are obsolete val obsoleteExtensions = extensionsToRemove[true].orEmpty() @@ -207,8 +212,8 @@ object ExtensionsList { } } - private fun String.repoUrlReplace(): String { - return if (contains("github")) { + private fun String.repoUrlReplace(): String = + if (contains("github")) { replace(repoMatchRegex) { "https://raw.githubusercontent.com/${it.groupValues[2]}/${it.groupValues[3]}/" + (it.groupValues.getOrNull(4)?.ifBlank { null } ?: "repo") + @@ -218,7 +223,6 @@ object ExtensionsList { } else { this } - } private val repoMatchRegex = ( diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/extension/github/ExtensionGithubApi.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/extension/github/ExtensionGithubApi.kt index bace24bd..9b6642d6 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/extension/github/ExtensionGithubApi.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/extension/github/ExtensionGithubApi.kt @@ -58,29 +58,27 @@ object ExtensionGithubApi { fun getApkUrl( repo: String, apkName: String, - ): String { - return "${repo}apk/$apkName" - } + ): String = "${repo}apk/$apkName" private val client by lazy { val network: NetworkHelper by injectLazy() - network.client.newBuilder() + network.client + .newBuilder() .addNetworkInterceptor { chain -> val originalResponse = chain.proceed(chain.request()) - originalResponse.newBuilder() + originalResponse + .newBuilder() .header("Content-Type", "application/json") .build() - } - .build() + }.build() } - private fun List.toExtensions(repo: String): List { - return this + private fun List.toExtensions(repo: String): List = + this .filter { val libVersion = it.version.substringBeforeLast('.').toDouble() libVersion in LIB_VERSION_MIN..LIB_VERSION_MAX - } - .map { + }.map { OnlineExtension( repo = repo, name = it.name.substringAfter("Tachiyomi: "), @@ -96,10 +94,9 @@ object ExtensionGithubApi { iconUrl = "${repo}icon/${it.pkg}.png", ) } - } - private fun List.toExtensionSources(): List { - return this.map { + private fun List.toExtensionSources(): List = + this.map { OnlineExtensionSource( name = it.name, lang = it.lang, @@ -107,5 +104,4 @@ object ExtensionGithubApi { baseUrl = it.baseUrl, ) } - } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/Track.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/Track.kt index 94e66dcd..ddf4ef57 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/Track.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/Track.kt @@ -63,9 +63,7 @@ object Track { tracker.logout() } - fun proxyThumbnailUrl(trackerId: Int): String { - return "/api/v1/track/$trackerId/thumbnail" - } + fun proxyThumbnailUrl(trackerId: Int): String = "/api/v1/track/$trackerId/thumbnail" fun getTrackerThumbnail(trackerId: Int): Pair { val tracker = TrackerManager.getTracker(trackerId)!! @@ -76,7 +74,8 @@ object Track { fun getTrackRecordsByMangaId(mangaId: Int): List { val recordMap = transaction { - TrackRecordTable.select { TrackRecordTable.mangaId eq mangaId } + TrackRecordTable + .select { TrackRecordTable.mangaId eq mangaId } .map { it.toTrackRecordDataClass() } }.associateBy { it.trackerId } @@ -138,10 +137,12 @@ object Track { ) { val track = transaction { - TrackSearchTable.select { - TrackSearchTable.trackerId eq trackerId and - (TrackSearchTable.remoteId eq remoteId) - }.first().toTrack(mangaId) + TrackSearchTable + .select { + TrackSearchTable.trackerId eq trackerId and + (TrackSearchTable.remoteId eq remoteId) + }.first() + .toTrack(mangaId) } val tracker = TrackerManager.getTracker(trackerId)!! @@ -160,10 +161,10 @@ object Track { if (track.started_reading_date <= 0) { val oldestChapter = transaction { - ChapterTable.select { - (ChapterTable.manga eq mangaId) and (ChapterTable.isRead eq true) - } - .orderBy(ChapterTable.lastReadAt to SortOrder.ASC) + ChapterTable + .select { + (ChapterTable.manga eq mangaId) and (ChapterTable.isRead eq true) + }.orderBy(ChapterTable.lastReadAt to SortOrder.ASC) .limit(1) .firstOrNull() } @@ -290,14 +291,14 @@ object Track { } } - private fun queryMaxReadChapter(mangaId: Int): ResultRow? { - return transaction { - ChapterTable.select { (ChapterTable.manga eq mangaId) and (ChapterTable.isRead eq true) } + private fun queryMaxReadChapter(mangaId: Int): ResultRow? = + transaction { + ChapterTable + .select { (ChapterTable.manga eq mangaId) and (ChapterTable.isRead eq true) } .orderBy(ChapterTable.chapter_number to SortOrder.DESC) .limit(1) .firstOrNull() } - } private suspend fun trackChapter( mangaId: Int, @@ -305,7 +306,8 @@ object Track { ) { val records = transaction { - TrackRecordTable.select { TrackRecordTable.mangaId eq mangaId } + TrackRecordTable + .select { TrackRecordTable.mangaId eq mangaId } .toList() } @@ -313,7 +315,8 @@ object Track { try { trackChapterForTracker(it, chapterNumber) } catch (e: Exception) { - KotlinLogging.logger("${logger.name}::trackChapter(mangaId= $mangaId, chapterNumber= $chapterNumber)") + KotlinLogging + .logger("${logger.name}::trackChapter(mangaId= $mangaId, chapterNumber= $chapterNumber)") .error(e) { "failed due to" } } } @@ -358,14 +361,14 @@ object Track { } } - fun upsertTrackRecord(track: Track): Int { - return transaction { + fun upsertTrackRecord(track: Track): Int = + transaction { val existingRecord = - TrackRecordTable.select { - (TrackRecordTable.mangaId eq track.manga_id) and - (TrackRecordTable.trackerId eq track.sync_id) - } - .singleOrNull() + TrackRecordTable + .select { + (TrackRecordTable.mangaId eq track.manga_id) and + (TrackRecordTable.trackerId eq track.sync_id) + }.singleOrNull() if (existingRecord != null) { updateTrackRecord(track) @@ -374,7 +377,6 @@ object Track { insertTrackRecord(track) } } - } fun updateTrackRecord(track: Track): Int = transaction { @@ -399,20 +401,21 @@ object Track { fun insertTrackRecord(track: Track): Int = transaction { - TrackRecordTable.insertAndGetId { - it[mangaId] = track.manga_id - it[trackerId] = track.sync_id - it[remoteId] = track.media_id - it[libraryId] = track.library_id - it[title] = track.title - it[lastChapterRead] = track.last_chapter_read.toDouble() - it[totalChapters] = track.total_chapters - it[status] = track.status - it[score] = track.score.toDouble() - it[remoteUrl] = track.tracking_url - it[startDate] = track.started_reading_date - it[finishDate] = track.finished_reading_date - }.value + TrackRecordTable + .insertAndGetId { + it[mangaId] = track.manga_id + it[trackerId] = track.sync_id + it[remoteId] = track.media_id + it[libraryId] = track.library_id + it[title] = track.title + it[lastChapterRead] = track.last_chapter_read.toDouble() + it[totalChapters] = track.total_chapters + it[status] = track.status + it[score] = track.score.toDouble() + it[remoteUrl] = track.tracking_url + it[startDate] = track.started_reading_date + it[finishDate] = track.finished_reading_date + }.value } @Serializable diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/Tracker.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/Tracker.kt index e763a157..896f998a 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/Tracker.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/Tracker.kt @@ -7,7 +7,10 @@ import suwayomi.tachidesk.manga.impl.track.tracker.model.TrackSearch import uy.kohesive.injekt.injectLazy import java.io.IOException -abstract class Tracker(val id: Int, val name: String) { +abstract class Tracker( + val id: Int, + val name: String, +) { val trackPreferences = TrackerPreferences private val networkService: NetworkHelper by injectLazy() @@ -35,9 +38,7 @@ abstract class Tracker(val id: Int, val name: String) { abstract fun getScoreList(): List - open fun indexToScore(index: Int): Float { - return index.toFloat() - } + open fun indexToScore(index: Int): Float = index.toFloat() abstract fun displayScore(track: Track): String @@ -55,9 +56,7 @@ abstract class Tracker(val id: Int, val name: String) { abstract suspend fun refresh(track: Track): Track - open fun authUrl(): String? { - return null - } + open fun authUrl(): String? = null open suspend fun authCallback(url: String) {} @@ -87,9 +86,7 @@ abstract class Tracker(val id: Int, val name: String) { trackPreferences.setTrackCredentials(this, username, password) } - fun getIfAuthExpired(): Boolean { - return trackPreferences.trackAuthExpired(this) - } + fun getIfAuthExpired(): Boolean = trackPreferences.trackAuthExpired(this) fun setAuthExpired() { trackPreferences.setTrackTokenExpired(this) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/TrackerPreferences.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/TrackerPreferences.kt index 4e008dfd..70ddf886 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/TrackerPreferences.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/TrackerPreferences.kt @@ -28,7 +28,8 @@ object TrackerPreferences { password: String, ) { logger.debug { "setTrackCredentials: id=${sync.id} username=$username" } - preferenceStore.edit() + preferenceStore + .edit() .putString(trackUsername(sync.id), username) .putString(trackPassword(sync.id), password) .putBoolean(trackTokenExpired(sync.id), false) @@ -43,12 +44,14 @@ object TrackerPreferences { ) { logger.debug { "setTrackToken: id=${sync.id} token=$token" } if (token == null) { - preferenceStore.edit() + preferenceStore + .edit() .remove(trackToken(sync.id)) .putBoolean(trackTokenExpired(sync.id), false) .apply() } else { - preferenceStore.edit() + preferenceStore + .edit() .putString(trackToken(sync.id), token) .putBoolean(trackTokenExpired(sync.id), false) .apply() @@ -56,7 +59,8 @@ object TrackerPreferences { } fun setTrackTokenExpired(sync: Tracker) { - preferenceStore.edit() + preferenceStore + .edit() .putBoolean(trackTokenExpired(sync.id), true) .apply() } @@ -66,7 +70,8 @@ object TrackerPreferences { fun setScoreType( sync: Tracker, scoreType: String, - ) = preferenceStore.edit() + ) = preferenceStore + .edit() .putString(scoreType(sync.id), scoreType) .apply() diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/anilist/Anilist.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/anilist/Anilist.kt index b32fb3a8..74fac8ed 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/anilist/Anilist.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/anilist/Anilist.kt @@ -12,7 +12,10 @@ import suwayomi.tachidesk.manga.impl.track.tracker.model.TrackSearch import uy.kohesive.injekt.injectLazy import java.io.IOException -class Anilist(id: Int) : Tracker(id, "AniList"), DeletableTrackService { +class Anilist( + id: Int, +) : Tracker(id, "AniList"), + DeletableTrackService { companion object { const val READING = 1 const val COMPLETED = 2 @@ -40,13 +43,9 @@ class Anilist(id: Int) : Tracker(id, "AniList"), DeletableTrackService { private val logger = KotlinLogging.logger {} - override fun getLogo(): String { - return "/static/tracker/anilist.png" - } + override fun getLogo(): String = "/static/tracker/anilist.png" - override fun getStatusList(): List { - return listOf(READING, COMPLETED, ON_HOLD, DROPPED, PLAN_TO_READ, REREADING) - } + override fun getStatusList(): List = listOf(READING, COMPLETED, ON_HOLD, DROPPED, PLAN_TO_READ, REREADING) @StringRes override fun getStatus(status: Int): String? = @@ -66,8 +65,8 @@ class Anilist(id: Int) : Tracker(id, "AniList"), DeletableTrackService { override fun getCompletionStatus(): Int = COMPLETED - override fun getScoreList(): List { - return when (trackPreferences.getScoreType(this)) { + override fun getScoreList(): List = + when (trackPreferences.getScoreType(this)) { // 10 point POINT_10 -> IntRange(0, 10).map(Int::toString) // 100 point @@ -80,10 +79,9 @@ class Anilist(id: Int) : Tracker(id, "AniList"), DeletableTrackService { POINT_10_DECIMAL -> IntRange(0, 100).map { (it / 10f).toString() } else -> throw Exception("Unknown score type") } - } - override fun indexToScore(index: Int): Float { - return when (trackPreferences.getScoreType(this)) { + override fun indexToScore(index: Int): Float = + when (trackPreferences.getScoreType(this)) { // 10 point POINT_10 -> index * 10f // 100 point @@ -104,7 +102,6 @@ class Anilist(id: Int) : Tracker(id, "AniList"), DeletableTrackService { POINT_10_DECIMAL -> index.toFloat() else -> throw Exception("Unknown score type") } - } override fun displayScore(track: Track): String { val score = track.score @@ -125,9 +122,7 @@ class Anilist(id: Int) : Tracker(id, "AniList"), DeletableTrackService { } } - private suspend fun add(track: Track): Track { - return api.addLibManga(track) - } + private suspend fun add(track: Track): Track = api.addLibManga(track) override suspend fun update( track: Track, @@ -190,9 +185,7 @@ class Anilist(id: Int) : Tracker(id, "AniList"), DeletableTrackService { } } - override suspend fun search(query: String): List { - return api.search(query) - } + override suspend fun search(query: String): List = api.search(query) override suspend fun refresh(track: Track): Track { val remoteTrack = api.getLibManga(track, getUsername().toInt()) @@ -202,9 +195,7 @@ class Anilist(id: Int) : Tracker(id, "AniList"), DeletableTrackService { return track } - override fun authUrl(): String { - return AnilistApi.authUrl().toString() - } + override fun authUrl(): String = AnilistApi.authUrl().toString() override suspend fun authCallback(url: String) { val token = url.extractToken("access_token") ?: throw IOException("cannot find token") @@ -241,12 +232,11 @@ class Anilist(id: Int) : Tracker(id, "AniList"), DeletableTrackService { trackPreferences.setTrackToken(this, json.encodeToString(oAuth)) } - fun loadOAuth(): OAuth? { - return try { + fun loadOAuth(): OAuth? = + try { json.decodeFromString(trackPreferences.getTrackToken(this)!!) } catch (e: Exception) { logger.error(e) { "loadOAuth err" } null } - } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/anilist/AnilistApi.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/anilist/AnilistApi.kt index ddc7577e..c26a45b5 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/anilist/AnilistApi.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/anilist/AnilistApi.kt @@ -30,17 +30,21 @@ import java.util.Calendar import kotlin.time.Duration.Companion.days import kotlin.time.Duration.Companion.minutes -class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) { +class AnilistApi( + val client: OkHttpClient, + interceptor: AnilistInterceptor, +) { private val json: Json by injectLazy() private val authClient = - client.newBuilder() + client + .newBuilder() .addInterceptor(interceptor) .rateLimit(permits = 85, period = 1.minutes) .build() - suspend fun addLibManga(track: Track): Track { - return withIOContext { + suspend fun addLibManga(track: Track): Track = + withIOContext { val query = """ |mutation AddManga(${'$'}mangaId: Int, ${'$'}progress: Int, ${'$'}status: MediaListStatus) { @@ -61,25 +65,27 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) { } } with(json) { - authClient.newCall( - POST( - API_URL, - body = payload.toString().toRequestBody(jsonMime), - ), - ) - .awaitSuccess() + authClient + .newCall( + POST( + API_URL, + body = payload.toString().toRequestBody(jsonMime), + ), + ).awaitSuccess() .parseAs() .let { track.library_id = - it["data"]!!.jsonObject["SaveMediaListEntry"]!!.jsonObject["id"]!!.jsonPrimitive.long + it["data"]!! + .jsonObject["SaveMediaListEntry"]!! + .jsonObject["id"]!! + .jsonPrimitive.long track } } } - } - suspend fun updateLibManga(track: Track): Track { - return withIOContext { + suspend fun updateLibManga(track: Track): Track = + withIOContext { val query = """ |mutation UpdateManga( @@ -109,14 +115,14 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) { put("completedAt", createDate(track.finished_reading_date)) } } - authClient.newCall(POST(API_URL, body = payload.toString().toRequestBody(jsonMime))) + authClient + .newCall(POST(API_URL, body = payload.toString().toRequestBody(jsonMime))) .awaitSuccess() track } - } - suspend fun deleteLibManga(track: Track) { - return withIOContext { + suspend fun deleteLibManga(track: Track) = + withIOContext { val query = """ |mutation DeleteManga(${'$'}listId: Int) { @@ -133,13 +139,13 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) { put("listId", track.library_id) } } - authClient.newCall(POST(API_URL, body = payload.toString().toRequestBody(jsonMime))) + authClient + .newCall(POST(API_URL, body = payload.toString().toRequestBody(jsonMime))) .awaitSuccess() } - } - suspend fun search(search: String): List { - return withIOContext { + suspend fun search(search: String): List = + withIOContext { val query = """ |query Search(${'$'}query: String) { @@ -174,13 +180,13 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) { } } with(json) { - authClient.newCall( - POST( - API_URL, - body = payload.toString().toRequestBody(jsonMime), - ), - ) - .awaitSuccess() + authClient + .newCall( + POST( + API_URL, + body = payload.toString().toRequestBody(jsonMime), + ), + ).awaitSuccess() .parseAs() .let { response -> val data = response["data"]!!.jsonObject @@ -191,13 +197,12 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) { } } } - } suspend fun findLibManga( track: Track, userid: Int, - ): Track? { - return withIOContext { + ): Track? = + withIOContext { val query = """ |query (${'$'}id: Int!, ${'$'}manga_id: Int!) { @@ -249,13 +254,13 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) { } } with(json) { - authClient.newCall( - POST( - API_URL, - body = payload.toString().toRequestBody(jsonMime), - ), - ) - .awaitSuccess() + authClient + .newCall( + POST( + API_URL, + body = payload.toString().toRequestBody(jsonMime), + ), + ).awaitSuccess() .parseAs() .let { response -> val data = response["data"]!!.jsonObject @@ -266,21 +271,17 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) { } } } - } suspend fun getLibManga( track: Track, userid: Int, - ): Track { - return findLibManga(track, userid) ?: throw Exception("Could not find manga") - } + ): Track = findLibManga(track, userid) ?: throw Exception("Could not find manga") - fun createOAuth(token: String): OAuth { - return OAuth(token, "Bearer", System.currentTimeMillis() + 365.days.inWholeMilliseconds, 365.days.inWholeMilliseconds) - } + fun createOAuth(token: String): OAuth = + OAuth(token, "Bearer", System.currentTimeMillis() + 365.days.inWholeMilliseconds, 365.days.inWholeMilliseconds) - suspend fun getCurrentUser(): Pair { - return withIOContext { + suspend fun getCurrentUser(): Pair = + withIOContext { val query = """ |query User { @@ -298,13 +299,13 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) { put("query", query) } with(json) { - authClient.newCall( - POST( - API_URL, - body = payload.toString().toRequestBody(jsonMime), - ), - ) - .awaitSuccess() + authClient + .newCall( + POST( + API_URL, + body = payload.toString().toRequestBody(jsonMime), + ), + ).awaitSuccess() .parseAs() .let { val data = it["data"]!!.jsonObject @@ -316,10 +317,9 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) { } } } - } - private fun jsonToALManga(struct: JsonObject): ALManga { - return ALManga( + private fun jsonToALManga(struct: JsonObject): ALManga = + ALManga( struct["id"]!!.jsonPrimitive.long, struct["title"]!!.jsonObject["userPreferred"]!!.jsonPrimitive.content, struct["coverImage"]!!.jsonObject["large"]!!.jsonPrimitive.content, @@ -329,10 +329,9 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) { parseDate(struct, "startDate"), struct["chapters"]!!.jsonPrimitive.intOrNull ?: 0, ) - } - private fun jsonToALUserManga(struct: JsonObject): ALUserManga { - return ALUserManga( + private fun jsonToALUserManga(struct: JsonObject): ALUserManga = + ALUserManga( struct["id"]!!.jsonPrimitive.long, struct["status"]!!.jsonPrimitive.content, struct["scoreRaw"]!!.jsonPrimitive.int, @@ -341,13 +340,12 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) { parseDate(struct, "completedAt"), jsonToALManga(struct["media"]!!.jsonObject), ) - } private fun parseDate( struct: JsonObject, dateKey: String, - ): Long { - return try { + ): Long = + try { val date = Calendar.getInstance() date.set( struct[dateKey]!!.jsonObject["year"]!!.jsonPrimitive.int, @@ -358,7 +356,6 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) { } catch (_: Exception) { 0L } - } private fun createDate(dateValue: Long): JsonObject { if (dateValue == 0L) { @@ -384,12 +381,12 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) { private const val BASE_URL = "https://anilist.co/api/v2/" private const val BASE_MANGA_URL = "https://anilist.co/manga/" - fun mangaUrl(mediaId: Long): String { - return BASE_MANGA_URL + mediaId - } + fun mangaUrl(mediaId: Long): String = BASE_MANGA_URL + mediaId fun authUrl(): Uri = - "${BASE_URL}oauth/authorize".toUri().buildUpon() + "${BASE_URL}oauth/authorize" + .toUri() + .buildUpon() .appendQueryParameter("client_id", CLIENT_ID) .appendQueryParameter("response_type", "token") .build() diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/anilist/AnilistInterceptor.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/anilist/AnilistInterceptor.kt index d4c8cab0..3964cb9f 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/anilist/AnilistInterceptor.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/anilist/AnilistInterceptor.kt @@ -5,7 +5,9 @@ import okhttp3.Response import suwayomi.tachidesk.manga.impl.track.tracker.TokenExpired import java.io.IOException -class AnilistInterceptor(private val anilist: Anilist) : Interceptor { +class AnilistInterceptor( + private val anilist: Anilist, +) : Interceptor { /** * OAuth object used for authenticated requests. * @@ -40,7 +42,8 @@ class AnilistInterceptor(private val anilist: Anilist) : Interceptor { // Add the authorization header to the original request. val authRequest = - originalRequest.newBuilder() + originalRequest + .newBuilder() .addHeader("Authorization", "Bearer ${oauth!!.access_token}") .build() diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/mangaupdates/MangaUpdates.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/mangaupdates/MangaUpdates.kt index 10e22215..639aab84 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/mangaupdates/MangaUpdates.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/mangaupdates/MangaUpdates.kt @@ -9,7 +9,10 @@ import suwayomi.tachidesk.manga.impl.track.tracker.mangaupdates.dto.toTrackSearc import suwayomi.tachidesk.manga.impl.track.tracker.model.Track import suwayomi.tachidesk.manga.impl.track.tracker.model.TrackSearch -class MangaUpdates(id: Int) : Tracker(id, "MangaUpdates"), DeletableTrackService { +class MangaUpdates( + id: Int, +) : Tracker(id, "MangaUpdates"), + DeletableTrackService { companion object { const val READING_LIST = 0 const val WISH_LIST = 1 @@ -39,9 +42,7 @@ class MangaUpdates(id: Int) : Tracker(id, "MangaUpdates"), DeletableTrackService override fun getLogo(): String = "/static/tracker/manga_updates.png" - override fun getStatusList(): List { - return listOf(READING_LIST, COMPLETE_LIST, ON_HOLD_LIST, UNFINISHED_LIST, WISH_LIST) - } + override fun getStatusList(): List = listOf(READING_LIST, COMPLETE_LIST, ON_HOLD_LIST, UNFINISHED_LIST, WISH_LIST) override fun getStatus(status: Int): String? = when (status) { @@ -83,8 +84,8 @@ class MangaUpdates(id: Int) : Tracker(id, "MangaUpdates"), DeletableTrackService override suspend fun bind( track: Track, hasReadChapters: Boolean, - ): Track { - return try { + ): Track = + try { val (series, rating) = api.getSeriesListItem(track) track.copyFrom(series, rating) } catch (e: Exception) { @@ -92,14 +93,13 @@ class MangaUpdates(id: Int) : Tracker(id, "MangaUpdates"), DeletableTrackService api.addSeriesToList(track, hasReadChapters) track } - } - override suspend fun search(query: String): List { - return api.search(query) + override suspend fun search(query: String): List = + api + .search(query) .map { it.toTrackSearch(id) } - } override suspend fun refresh(track: Track): Track { val (series, rating) = api.getSeriesListItem(track) @@ -124,7 +124,5 @@ class MangaUpdates(id: Int) : Tracker(id, "MangaUpdates"), DeletableTrackService interceptor.newAuth(authenticated.sessionToken) } - fun restoreSession(): String? { - return trackPreferences.getTrackPassword(this) - } + fun restoreSession(): String? = trackPreferences.getTrackPassword(this) } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/mangaupdates/MangaUpdatesApi.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/mangaupdates/MangaUpdatesApi.kt index 8ecc132f..2eee9d2b 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/mangaupdates/MangaUpdatesApi.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/mangaupdates/MangaUpdatesApi.kt @@ -39,7 +39,8 @@ class MangaUpdatesApi( private val contentType = "application/vnd.api+json".toMediaType() private val authClient by lazy { - client.newBuilder() + client + .newBuilder() .addInterceptor(interceptor) .build() } @@ -47,7 +48,8 @@ class MangaUpdatesApi( suspend fun getSeriesListItem(track: Track): Pair { val listItem = with(json) { - authClient.newCall(GET("$baseUrl/v1/lists/series/${track.media_id}")) + authClient + .newCall(GET("$baseUrl/v1/lists/series/${track.media_id}")) .awaitSuccess() .parseAs() } @@ -71,13 +73,13 @@ class MangaUpdatesApi( put("list_id", status) } } - authClient.newCall( - POST( - url = "$baseUrl/v1/lists/series", - body = body.toString().toRequestBody(contentType), - ), - ) - .awaitSuccess() + authClient + .newCall( + POST( + url = "$baseUrl/v1/lists/series", + body = body.toString().toRequestBody(contentType), + ), + ).awaitSuccess() .let { if (it.code == 200) { track.status = status @@ -99,13 +101,13 @@ class MangaUpdatesApi( } } } - authClient.newCall( - POST( - url = "$baseUrl/v1/lists/series/update", - body = body.toString().toRequestBody(contentType), - ), - ) - .awaitSuccess() + authClient + .newCall( + POST( + url = "$baseUrl/v1/lists/series/update", + body = body.toString().toRequestBody(contentType), + ), + ).awaitSuccess() updateSeriesRating(track) } @@ -115,26 +117,26 @@ class MangaUpdatesApi( buildJsonArray { add(track.media_id) } - authClient.newCall( - POST( - url = "$baseUrl/v1/lists/series/delete", - body = body.toString().toRequestBody(contentType), - ), - ) - .awaitSuccess() + authClient + .newCall( + POST( + url = "$baseUrl/v1/lists/series/delete", + body = body.toString().toRequestBody(contentType), + ), + ).awaitSuccess() } - private suspend fun getSeriesRating(track: Track): Rating? { - return try { + private suspend fun getSeriesRating(track: Track): Rating? = + try { with(json) { - authClient.newCall(GET("$baseUrl/v1/series/${track.media_id}/rating")) + authClient + .newCall(GET("$baseUrl/v1/series/${track.media_id}/rating")) .awaitSuccess() .parseAs() } } catch (e: Exception) { null } - } private suspend fun updateSeriesRating(track: Track) { if (track.score != 0f) { @@ -142,20 +144,20 @@ class MangaUpdatesApi( buildJsonObject { put("rating", track.score) } - authClient.newCall( - PUT( - url = "$baseUrl/v1/series/${track.media_id}/rating", - body = body.toString().toRequestBody(contentType), - ), - ) - .awaitSuccess() + authClient + .newCall( + PUT( + url = "$baseUrl/v1/series/${track.media_id}/rating", + body = body.toString().toRequestBody(contentType), + ), + ).awaitSuccess() } else { - authClient.newCall( - DELETE( - url = "$baseUrl/v1/series/${track.media_id}/rating", - ), - ) - .awaitSuccess() + authClient + .newCall( + DELETE( + url = "$baseUrl/v1/series/${track.media_id}/rating", + ), + ).awaitSuccess() } } @@ -172,20 +174,19 @@ class MangaUpdatesApi( ) } return with(json) { - client.newCall( - POST( - url = "$baseUrl/v1/series/search", - body = body.toString().toRequestBody(contentType), - ), - ) - .awaitSuccess() + client + .newCall( + POST( + url = "$baseUrl/v1/series/search", + body = body.toString().toRequestBody(contentType), + ), + ).awaitSuccess() .parseAs() .let { obj -> obj["results"]?.jsonArray?.map { element -> json.decodeFromJsonElement(element.jsonObject["record"]!!) } - } - .orEmpty() + }.orEmpty() } } @@ -199,13 +200,13 @@ class MangaUpdatesApi( put("password", password) } return with(json) { - client.newCall( - PUT( - url = "$baseUrl/v1/account/login", - body = body.toString().toRequestBody(contentType), - ), - ) - .awaitSuccess() + client + .newCall( + PUT( + url = "$baseUrl/v1/account/login", + body = body.toString().toRequestBody(contentType), + ), + ).awaitSuccess() .parseAs() .let { obj -> try { diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/mangaupdates/MangaUpdatesInterceptor.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/mangaupdates/MangaUpdatesInterceptor.kt index ce2cb8c7..ba9f5e20 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/mangaupdates/MangaUpdatesInterceptor.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/mangaupdates/MangaUpdatesInterceptor.kt @@ -17,7 +17,8 @@ class MangaUpdatesInterceptor( // Add the authorization header to the original request. val authRequest = - originalRequest.newBuilder() + originalRequest + .newBuilder() .addHeader("Authorization", "Bearer $token") .header("User-Agent", "Suwayomi ${BuildConfig.VERSION} (${BuildConfig.REVISION})") .build() diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/mangaupdates/dto/ListItem.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/mangaupdates/dto/ListItem.kt index e030b59a..00d227a5 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/mangaupdates/dto/ListItem.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/mangaupdates/dto/ListItem.kt @@ -14,9 +14,8 @@ data class ListItem( val priority: Int? = null, ) -fun ListItem.copyTo(track: Track): Track { - return track.apply { +fun ListItem.copyTo(track: Track): Track = + track.apply { this.status = listId ?: READING_LIST this.last_chapter_read = this@copyTo.status?.chapter?.toFloat() ?: 0f } -} diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/mangaupdates/dto/Rating.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/mangaupdates/dto/Rating.kt index 78851715..b8dff45d 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/mangaupdates/dto/Rating.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/mangaupdates/dto/Rating.kt @@ -8,8 +8,7 @@ data class Rating( val rating: Float? = null, ) -fun Rating.copyTo(track: Track): Track { - return track.apply { +fun Rating.copyTo(track: Track): Track = + track.apply { this.score = rating ?: 0f } -} diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/mangaupdates/dto/Record.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/mangaupdates/dto/Record.kt index cc31b1e3..52aef3a2 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/mangaupdates/dto/Record.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/mangaupdates/dto/Record.kt @@ -23,12 +23,10 @@ data class Record( val latestChapter: Int? = null, ) -private fun String.htmlDecode(): String { - return Jsoup.parse(this).wholeText() -} +private fun String.htmlDecode(): String = Jsoup.parse(this).wholeText() -fun Record.toTrackSearch(id: Int): TrackSearch { - return TrackSearch.create(id).apply { +fun Record.toTrackSearch(id: Int): TrackSearch = + TrackSearch.create(id).apply { media_id = this@toTrackSearch.seriesId ?: 0L title = this@toTrackSearch.title?.htmlDecode() ?: "" total_chapters = 0 @@ -39,4 +37,3 @@ fun Record.toTrackSearch(id: Int): TrackSearch { publishing_type = this@toTrackSearch.type.toString() start_date = this@toTrackSearch.year.toString() } -} diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/myanimelist/MyAnimeList.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/myanimelist/MyAnimeList.kt index 799cc833..4faea7cc 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/myanimelist/MyAnimeList.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/myanimelist/MyAnimeList.kt @@ -12,7 +12,10 @@ import suwayomi.tachidesk.manga.impl.track.tracker.model.TrackSearch import uy.kohesive.injekt.injectLazy import java.io.IOException -class MyAnimeList(id: Int) : Tracker(id, "MyAnimeList"), DeletableTrackService { +class MyAnimeList( + id: Int, +) : Tracker(id, "MyAnimeList"), + DeletableTrackService { companion object { const val READING = 1 const val COMPLETED = 2 @@ -36,13 +39,9 @@ class MyAnimeList(id: Int) : Tracker(id, "MyAnimeList"), DeletableTrackService { private val logger = KotlinLogging.logger {} - override fun getLogo(): String { - return "/static/tracker/mal.png" - } + override fun getLogo(): String = "/static/tracker/mal.png" - override fun getStatusList(): List { - return listOf(READING, COMPLETED, ON_HOLD, DROPPED, PLAN_TO_READ, REREADING) - } + override fun getStatusList(): List = listOf(READING, COMPLETED, ON_HOLD, DROPPED, PLAN_TO_READ, REREADING) @StringRes override fun getStatus(status: Int): String? = @@ -62,17 +61,11 @@ class MyAnimeList(id: Int) : Tracker(id, "MyAnimeList"), DeletableTrackService { override fun getCompletionStatus(): Int = COMPLETED - override fun getScoreList(): List { - return IntRange(0, 10).map(Int::toString) - } + override fun getScoreList(): List = IntRange(0, 10).map(Int::toString) - override fun displayScore(track: Track): String { - return track.score.toInt().toString() - } + override fun displayScore(track: Track): String = track.score.toInt().toString() - private suspend fun add(track: Track): Track { - return api.updateItem(track) - } + private suspend fun add(track: Track): Track = api.updateItem(track) override suspend fun update( track: Track, @@ -138,13 +131,9 @@ class MyAnimeList(id: Int) : Tracker(id, "MyAnimeList"), DeletableTrackService { return api.search(query) } - override suspend fun refresh(track: Track): Track { - return api.findListItem(track) ?: add(track) - } + override suspend fun refresh(track: Track): Track = api.findListItem(track) ?: add(track) - override fun authUrl(): String { - return MyAnimeListApi.authUrl().toString() - } + override fun authUrl(): String = MyAnimeListApi.authUrl().toString() override suspend fun authCallback(url: String) { val code = url.extractToken("code") ?: throw IOException("cannot find token") @@ -180,12 +169,11 @@ class MyAnimeList(id: Int) : Tracker(id, "MyAnimeList"), DeletableTrackService { trackPreferences.setTrackToken(this, json.encodeToString(oAuth)) } - fun loadOAuth(): OAuth? { - return try { + fun loadOAuth(): OAuth? = + try { json.decodeFromString(trackPreferences.getTrackToken(this)!!) } catch (e: Exception) { logger.error(e) { "loadOAuth err" } null } - } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/myanimelist/MyAnimeListApi.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/myanimelist/MyAnimeListApi.kt index 93cdf3cb..394ae327 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/myanimelist/MyAnimeListApi.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/myanimelist/MyAnimeListApi.kt @@ -32,79 +32,89 @@ import uy.kohesive.injekt.injectLazy import java.text.SimpleDateFormat import java.util.Locale -class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListInterceptor) { +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 { - return withIOContext { + suspend fun getAccessToken(authCode: String): OAuth = + withIOContext { val formBody: RequestBody = - FormBody.Builder() + FormBody + .Builder() .add("client_id", CLIENT_ID) .add("code", authCode) .add("code_verifier", codeVerifier) .add("grant_type", "authorization_code") .build() with(json) { - client.newCall(POST("$BASE_OAUTH_URL/token", body = formBody)) + client + .newCall(POST("$BASE_OAUTH_URL/token", body = formBody)) .awaitSuccess() .parseAs() } } - } - suspend fun getCurrentUser(): String { - return withIOContext { + suspend fun getCurrentUser(): String = + withIOContext { val request = - Request.Builder() + Request + .Builder() .url("$BASE_API_URL/users/@me") .get() .build() with(json) { - authClient.newCall(request) + authClient + .newCall(request) .awaitSuccess() .parseAs() .let { it["name"]!!.jsonPrimitive.content } } } - } - suspend fun search(query: String): List { - return withIOContext { + suspend fun search(query: String): List = + withIOContext { val url = - "$BASE_API_URL/manga".toUri().buildUpon() + "$BASE_API_URL/manga" + .toUri() + .buildUpon() // MAL API throws a 400 when the query is over 64 characters... .appendQueryParameter("q", query.take(64)) .appendQueryParameter("nsfw", "true") .build() with(json) { - authClient.newCall(GET(url.toString())) + authClient + .newCall(GET(url.toString())) .awaitSuccess() .parseAs() .let { - it["data"]!!.jsonArray + it["data"]!! + .jsonArray .map { data -> data.jsonObject["node"]!!.jsonObject } .map { node -> val id = node["id"]!!.jsonPrimitive.int async { getMangaDetails(id) } - } - .awaitAll() + }.awaitAll() .filter { trackSearch -> !trackSearch.publishing_type.contains("novel") } } } } - } - suspend fun getMangaDetails(id: Int): TrackSearch { - return withIOContext { + suspend fun getMangaDetails(id: Int): TrackSearch = + withIOContext { val url = - "$BASE_API_URL/manga".toUri().buildUpon() + "$BASE_API_URL/manga" + .toUri() + .buildUpon() .appendPath(id.toString()) .appendQueryParameter("fields", "id,title,synopsis,num_chapters,main_picture,status,media_type,start_date") .build() with(json) { - authClient.newCall(GET(url.toString())) + authClient + .newCall(GET(url.toString())) .awaitSuccess() .parseAs() .let { @@ -115,7 +125,11 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI summary = obj["synopsis"]?.jsonPrimitive?.content ?: "" total_chapters = obj["num_chapters"]!!.jsonPrimitive.int cover_url = - obj["main_picture"]?.jsonObject?.get("large")?.jsonPrimitive?.content + obj["main_picture"] + ?.jsonObject + ?.get("large") + ?.jsonPrimitive + ?.content ?: "" tracking_url = "https://myanimelist.net/manga/$media_id" publishing_status = @@ -133,12 +147,12 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI } } } - } - suspend fun updateItem(track: Track): Track { - return withIOContext { + suspend fun updateItem(track: Track): Track = + withIOContext { val formBodyBuilder = - FormBody.Builder() + FormBody + .Builder() .add("status", track.toMyAnimeListStatus() ?: "reading") .add("is_rereading", (track.status == MyAnimeList.REREADING).toString()) .add("score", track.score.toString()) @@ -151,40 +165,45 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI } val request = - Request.Builder() + Request + .Builder() .url(mangaUrl(track.media_id).toString()) .put(formBodyBuilder.build()) .build() with(json) { - authClient.newCall(request) + authClient + .newCall(request) .awaitSuccess() .parseAs() .let { parseMangaItem(it, track) } } } - } - suspend fun deleteItem(track: Track) { - return withIOContext { + suspend fun deleteItem(track: Track) = + withIOContext { val request = - Request.Builder() + Request + .Builder() .url(mangaUrl(track.media_id).toString()) .delete() .build() - authClient.newCall(request) + authClient + .newCall(request) .awaitSuccess() } - } - suspend fun findListItem(track: Track): Track? { - return withIOContext { + suspend fun findListItem(track: Track): Track? = + withIOContext { val uri = - "$BASE_API_URL/manga".toUri().buildUpon() + "$BASE_API_URL/manga" + .toUri() + .buildUpon() .appendPath(track.media_id.toString()) .appendQueryParameter("fields", "num_chapters,my_list_status{start_date,finish_date}") .build() with(json) { - authClient.newCall(GET(uri.toString())) + authClient + .newCall(GET(uri.toString())) .awaitSuccess() .parseAs() .let { obj -> @@ -195,43 +214,50 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI } } } - } suspend fun findListItems( query: String, offset: Int = 0, - ): List { - return withIOContext { + ): List = + withIOContext { val json = getListPage(offset) val obj = json.jsonObject val matches = - obj["data"]!!.jsonArray + obj["data"]!! + .jsonArray .filter { it.jsonObject["node"]!!.jsonObject["title"]!!.jsonPrimitive.content.contains( query, ignoreCase = true, ) - } - .map { - val id = it.jsonObject["node"]!!.jsonObject["id"]!!.jsonPrimitive.int + }.map { + val id = + it.jsonObject["node"]!! + .jsonObject["id"]!! + .jsonPrimitive.int async { getMangaDetails(id) } - } - .awaitAll() + }.awaitAll() // Check next page if there's more - if (!obj["paging"]!!.jsonObject["next"]?.jsonPrimitive?.contentOrNull.isNullOrBlank()) { + if (!obj["paging"]!! + .jsonObject["next"] + ?.jsonPrimitive + ?.contentOrNull + .isNullOrBlank() + ) { matches + findListItems(query, offset + LIST_PAGINATION_AMOUNT) } else { matches } } - } - private suspend fun getListPage(offset: Int): JsonObject { - return withIOContext { + private suspend fun getListPage(offset: Int): JsonObject = + withIOContext { val urlBuilder = - "$BASE_API_URL/users/@me/mangalist".toUri().buildUpon() + "$BASE_API_URL/users/@me/mangalist" + .toUri() + .buildUpon() .appendQueryParameter("fields", "list_status{start_date,finish_date}") .appendQueryParameter("limit", LIST_PAGINATION_AMOUNT.toString()) if (offset > 0) { @@ -239,17 +265,18 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI } val request = - Request.Builder() + Request + .Builder() .url(urlBuilder.build().toString()) .get() .build() with(json) { - authClient.newCall(request) + authClient + .newCall(request) .awaitSuccess() .parseAs() } } - } private fun parseMangaItem( response: JsonObject, @@ -270,9 +297,7 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI } } - private fun parseDate(isoDate: String): Long { - return SimpleDateFormat("yyyy-MM-dd", Locale.US).parse(isoDate)?.time ?: 0L - } + private fun parseDate(isoDate: String): Long = SimpleDateFormat("yyyy-MM-dd", Locale.US).parse(isoDate)?.time ?: 0L private fun convertToIsoDate(epochTime: Long): String? { if (epochTime == 0L) { @@ -297,21 +322,26 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI private var codeVerifier: String = "" fun authUrl(): Uri = - "$BASE_OAUTH_URL/authorize".toUri().buildUpon() + "$BASE_OAUTH_URL/authorize" + .toUri() + .buildUpon() .appendQueryParameter("client_id", CLIENT_ID) .appendQueryParameter("code_challenge", getPkceChallengeCode()) .appendQueryParameter("response_type", "code") .build() fun mangaUrl(id: Long): Uri = - "$BASE_API_URL/manga".toUri().buildUpon() + "$BASE_API_URL/manga" + .toUri() + .buildUpon() .appendPath(id.toString()) .appendPath("my_list_status") .build() fun refreshTokenRequest(oauth: OAuth): Request { val formBody: RequestBody = - FormBody.Builder() + FormBody + .Builder() .add("client_id", CLIENT_ID) .add("refresh_token", oauth.refresh_token) .add("grant_type", "refresh_token") @@ -321,7 +351,8 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI // request is called by the interceptor itself so it doesn't reach // the part where the token is added automatically. val headers = - Headers.Builder() + Headers + .Builder() .add("Authorization", "Bearer ${oauth.access_token}") .build() diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/myanimelist/MyAnimeListInterceptor.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/myanimelist/MyAnimeListInterceptor.kt index bd9ae23d..80ca9929 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/myanimelist/MyAnimeListInterceptor.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/track/tracker/myanimelist/MyAnimeListInterceptor.kt @@ -10,7 +10,9 @@ import suwayomi.tachidesk.manga.impl.track.tracker.TokenRefreshFailed import uy.kohesive.injekt.injectLazy import java.io.IOException -class MyAnimeListInterceptor(private val myanimelist: MyAnimeList) : Interceptor { +class MyAnimeListInterceptor( + private val myanimelist: MyAnimeList, +) : Interceptor { private val json: Json by injectLazy() private var oauth: OAuth? = myanimelist.loadOAuth() @@ -31,7 +33,8 @@ class MyAnimeListInterceptor(private val myanimelist: MyAnimeList) : Interceptor // Add the authorization header to the original request val authRequest = - originalRequest.newBuilder() + originalRequest + .newBuilder() .addHeader("Authorization", "Bearer ${oauth!!.access_token}") .header("User-Agent", "Suwayomi v${AppInfo.getVersionName()}") .build() @@ -72,8 +75,7 @@ class MyAnimeListInterceptor(private val myanimelist: MyAnimeList) : Interceptor response.close() null } - } - .getOrNull() + }.getOrNull() ?.also(::setAuth) ?: throw TokenRefreshFailed() } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/update/UpdateStatus.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/update/UpdateStatus.kt index 323e27c1..292ee2d0 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/update/UpdateStatus.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/update/UpdateStatus.kt @@ -24,7 +24,8 @@ data class UpdateStatus( ) : this( categories, mangaStatusMap = - jobs.groupBy { it.status } + jobs + .groupBy { it.status } .mapValues { entry -> entry.value.map { it.manga } }.plus(Pair(JobStatus.SKIPPED, skippedMangas)), diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/update/Updater.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/update/Updater.kt index 45491870..8e594c3e 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/update/Updater.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/update/Updater.kt @@ -105,9 +105,7 @@ class Updater : IUpdater { ) } - override fun getLastUpdateTimestamp(): Long { - return preferences.getLong(lastUpdateKey, 0) - } + override fun getLastUpdateTimestamp(): Long = preferences.getLong(lastUpdateKey, 0) private fun autoUpdateTask() { try { @@ -139,7 +137,10 @@ class Updater : IUpdater { return } - val updateInterval = serverConfig.globalUpdateInterval.value.hours.coerceAtLeast(6.hours).inWholeMilliseconds + val updateInterval = + serverConfig.globalUpdateInterval.value.hours + .coerceAtLeast(6.hours) + .inWholeMilliseconds val lastAutomatedUpdate = preferences.getLong(lastAutomatedUpdateKey, 0) val timeToNextExecution = (updateInterval - (System.currentTimeMillis() - lastAutomatedUpdate)).mod(updateInterval) @@ -185,26 +186,24 @@ class Updater : IUpdater { notifyFlow.emit(Unit) } - private fun getOrCreateUpdateChannelFor(source: String): Channel { - return updateChannels.getOrPut(source) { + private fun getOrCreateUpdateChannelFor(source: String): Channel = + updateChannels.getOrPut(source) { logger.debug { "getOrCreateUpdateChannelFor: created channel for $source - channels: ${updateChannels.size + 1}" } createUpdateChannel(source) } - } private fun createUpdateChannel(source: String): Channel { val channel = Channel(Channel.UNLIMITED) - channel.consumeAsFlow() + channel + .consumeAsFlow() .onEach { job -> semaphore.withPermit { process(job) } - } - .catch { + }.catch { logger.error(it) { "Error during updates (source: $source)" } handleChannelUpdateFailure(source) - } - .onCompletion { updateChannels.remove(source) } + }.onCompletion { updateChannels.remove(source) } .launchIn(scope) return channel } @@ -301,22 +300,19 @@ class Updater : IUpdater { } else { true } - } - .filter { + }.filter { if (it.initialized && serverConfig.excludeNotStarted.value) { it.lastReadAt != null } else { true } - } - .filter { + }.filter { if (serverConfig.excludeCompleted.value) { it.status != MangaStatus.COMPLETED.name } else { true } - } - .filter { forceAll || !excludedCategories.any { category -> mangasToCategoriesMap[it.id]?.contains(category) == true } } + }.filter { forceAll || !excludedCategories.any { category -> mangasToCategoriesMap[it.id]?.contains(category) == true } } .toList() val skippedMangas = categoriesToUpdateMangas.subtract(mangasToUpdate.toSet()).toList() diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/update/UpdaterSocket.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/update/UpdaterSocket.kt index de8c5428..dca0aee7 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/update/UpdaterSocket.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/update/UpdaterSocket.kt @@ -58,11 +58,9 @@ object UpdaterSocket : Websocket() { } } - fun start(): Job { - return updater.status + fun start(): Job = + updater.status .onEach { notifyAllClients(it) - } - .launchIn(scope) - } + }.launchIn(scope) } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/BytecodeEditor.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/BytecodeEditor.kt index 625eb102..0006939e 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/BytecodeEditor.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/BytecodeEditor.kt @@ -31,7 +31,9 @@ object BytecodeEditor { */ fun fixAndroidClasses(jarFile: Path) { FileSystems.newFileSystem(jarFile, null as ClassLoader?)?.use { - Files.walk(it.getPath("/")).asSequence() + Files + .walk(it.getPath("/")) + .asSequence() .filterNotNull() .filterNot(Files::isDirectory) .mapNotNull(::getClassBytes) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/DirName.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/DirName.kt index cbb7673a..7c36d361 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/DirName.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/DirName.kt @@ -48,34 +48,24 @@ private fun getChapterDir( return getMangaDir(mangaId) + "/$chapterDir" } -fun getThumbnailDownloadPath(mangaId: Int): String { - return applicationDirs.thumbnailDownloadsRoot + "/$mangaId" -} +fun getThumbnailDownloadPath(mangaId: Int): String = applicationDirs.thumbnailDownloadsRoot + "/$mangaId" -fun getMangaDownloadDir(mangaId: Int): String { - return applicationDirs.mangaDownloadsRoot + "/" + getMangaDir(mangaId) -} +fun getMangaDownloadDir(mangaId: Int): String = applicationDirs.mangaDownloadsRoot + "/" + getMangaDir(mangaId) fun getChapterDownloadPath( mangaId: Int, chapterId: Int, -): String { - return applicationDirs.mangaDownloadsRoot + "/" + getChapterDir(mangaId, chapterId) -} +): String = applicationDirs.mangaDownloadsRoot + "/" + getChapterDir(mangaId, chapterId) fun getChapterCbzPath( mangaId: Int, chapterId: Int, -): String { - return getChapterDownloadPath(mangaId, chapterId) + ".cbz" -} +): String = getChapterDownloadPath(mangaId, chapterId) + ".cbz" fun getChapterCachePath( mangaId: Int, chapterId: Int, -): String { - return applicationDirs.tempMangaCacheRoot + "/" + getChapterDir(mangaId, chapterId) -} +): String = applicationDirs.tempMangaCacheRoot + "/" + getChapterDir(mangaId, chapterId) /** return value says if rename/move was successful */ fun updateMangaDownloadDir( @@ -103,6 +93,4 @@ fun updateMangaDownloadDir( } } -private fun getMangaEntry(mangaId: Int): ResultRow { - return transaction { MangaTable.select { MangaTable.id eq mangaId }.first() } -} +private fun getMangaEntry(mangaId: Int): ResultRow = transaction { MangaTable.select { MangaTable.id eq mangaId }.first() } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/GetComicInfo.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/GetComicInfo.kt index 757d18bc..5633b210 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/GetComicInfo.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/GetComicInfo.kt @@ -75,11 +75,14 @@ fun createComicInfoFile( val chapterUrl = chapter[ChapterTable.realUrl].orEmpty() val categories = transaction { - CategoryMangaTable.innerJoin(CategoryTable).select { - CategoryMangaTable.manga eq manga[MangaTable.id] - }.orderBy(CategoryTable.order to SortOrder.ASC).map { - it[CategoryTable.name] - } + CategoryMangaTable + .innerJoin(CategoryTable) + .select { + CategoryMangaTable.manga eq manga[MangaTable.id] + }.orderBy(CategoryTable.order to SortOrder.ASC) + .map { + it[CategoryTable.name] + } }.takeUnless { it.isEmpty() } val comicInfo = getComicInfo(manga, chapter, chapterUrl, categories) // Remove the old file diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/PackageTools.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/PackageTools.kt index 7d54053c..b874c9bd 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/PackageTools.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/PackageTools.kt @@ -104,7 +104,9 @@ object PackageTools { Bundle().apply { val appTag = doc.getElementsByTagName("application").item(0) - appTag?.childNodes?.toList() + appTag + ?.childNodes + ?.toList() .orEmpty() .asSequence() .filter { @@ -126,7 +128,8 @@ object PackageTools { parsed.apkSingers.flatMap { it.certificateMetas } // + parsed.apkV2Singers.flatMap { it.certificateMetas } ) // Blocked by: https://github.com/hsiafan/apk-parser/issues/72 - .map { Signature(it.data) }.toTypedArray() + .map { Signature(it.data) } + .toTypedArray() } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/network/UnzippingInterceptor.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/network/UnzippingInterceptor.kt index 09d42b2c..8727f259 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/network/UnzippingInterceptor.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/network/UnzippingInterceptor.kt @@ -35,7 +35,9 @@ class UnzippingInterceptor : Interceptor { val contentLength: Long = body.contentLength() val responseBody = GzipSource(body.source()) val strippedHeaders: Headers = response.headers.newBuilder().build() - response.newBuilder().headers(strippedHeaders) + response + .newBuilder() + .headers(strippedHeaders) .body(RealResponseBody(body.contentType().toString(), contentLength, responseBody.buffer())) .build() } else { diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/source/GetCatalogueSource.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/source/GetCatalogueSource.kt index aefa4379..6dd989c5 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/source/GetCatalogueSource.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/source/GetCatalogueSource.kt @@ -61,18 +61,15 @@ object GetCatalogueSource { return sourceCache[sourceId]!! } - fun getCatalogueSourceOrNull(sourceId: Long): CatalogueSource? { - return try { + fun getCatalogueSourceOrNull(sourceId: Long): CatalogueSource? = + try { getCatalogueSource(sourceId) } catch (e: Exception) { logger.warn(e) { "getCatalogueSource($sourceId) failed" } null } - } - fun getCatalogueSourceOrStub(sourceId: Long): CatalogueSource { - return getCatalogueSourceOrNull(sourceId) ?: StubSource(sourceId) - } + fun getCatalogueSourceOrStub(sourceId: Long): CatalogueSource = getCatalogueSourceOrNull(sourceId) ?: StubSource(sourceId) fun registerCatalogueSource(sourcePair: Pair) { sourceCache += sourcePair diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/source/StubSource.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/source/StubSource.kt index cf572e2b..a7a5a364 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/source/StubSource.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/source/StubSource.kt @@ -15,58 +15,43 @@ import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SManga import rx.Observable -open class StubSource(override val id: Long) : CatalogueSource { +open class StubSource( + override val id: Long, +) : CatalogueSource { override val lang: String = "other" override val supportsLatest: Boolean = false override val name: String get() = id.toString() @Deprecated("Use the non-RxJava API instead", replaceWith = ReplaceWith("getPopularManga")) - override fun fetchPopularManga(page: Int): Observable { - return Observable.error(getSourceNotInstalledException()) - } + override fun fetchPopularManga(page: Int): Observable = Observable.error(getSourceNotInstalledException()) @Deprecated("Use the non-RxJava API instead", replaceWith = ReplaceWith("getSearchManga")) override fun fetchSearchManga( page: Int, query: String, filters: FilterList, - ): Observable { - return Observable.error(getSourceNotInstalledException()) - } + ): Observable = Observable.error(getSourceNotInstalledException()) @Deprecated("Use the non-RxJava API instead", replaceWith = ReplaceWith("getLatestUpdates")) - override fun fetchLatestUpdates(page: Int): Observable { - return Observable.error(getSourceNotInstalledException()) - } + override fun fetchLatestUpdates(page: Int): Observable = Observable.error(getSourceNotInstalledException()) - override fun getFilterList(): FilterList { - return FilterList() - } + override fun getFilterList(): FilterList = FilterList() @Deprecated("Use the non-RxJava API instead", replaceWith = ReplaceWith("getMangaDetails")) - override fun fetchMangaDetails(manga: SManga): Observable { - return Observable.error(getSourceNotInstalledException()) - } + override fun fetchMangaDetails(manga: SManga): Observable = Observable.error(getSourceNotInstalledException()) @Deprecated("Use the non-RxJava API instead", replaceWith = ReplaceWith("getChapterList")) - override fun fetchChapterList(manga: SManga): Observable> { - return Observable.error(getSourceNotInstalledException()) - } + override fun fetchChapterList(manga: SManga): Observable> = Observable.error(getSourceNotInstalledException()) @Deprecated("Use the non-RxJava API instead", replaceWith = ReplaceWith("getPageList")) - override fun fetchPageList(chapter: SChapter): Observable> { - return Observable.error(getSourceNotInstalledException()) - } + override fun fetchPageList(chapter: SChapter): Observable> = Observable.error(getSourceNotInstalledException()) - override fun toString(): String { - return name - } + override fun toString(): String = name - private fun getSourceNotInstalledException(): SourceNotInstalledException { - return SourceNotInstalledException(id) - } + private fun getSourceNotInstalledException(): SourceNotInstalledException = SourceNotInstalledException(id) - inner class SourceNotInstalledException(val id: Long) : - Exception("Source not installed: $id") + inner class SourceNotInstalledException( + val id: Long, + ) : Exception("Source not installed: $id") } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/storage/ImageResponse.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/storage/ImageResponse.kt index 53326fe1..af9c244f 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/storage/ImageResponse.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/storage/ImageResponse.kt @@ -15,9 +15,7 @@ import java.io.IOException import java.io.InputStream object ImageResponse { - private fun pathToInputStream(path: String): InputStream { - return FileInputStream(path).buffered() - } + private fun pathToInputStream(path: String): InputStream = FileInputStream(path).buffered() /** find file with name when file extension is not known */ fun findFileNameStartingWith( @@ -115,7 +113,5 @@ object ImageResponse { } } - fun clearImages(saveDir: String): Boolean { - return File(saveDir).deleteRecursively() - } + fun clearImages(saveDir: String): Boolean = File(saveDir).deleteRecursively() } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/storage/ImageUtil.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/storage/ImageUtil.kt index c7f2e4f0..6fbede82 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/storage/ImageUtil.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/util/storage/ImageUtil.kt @@ -32,9 +32,7 @@ object ImageUtil { return contentType?.startsWith("image/") ?: false } - fun findImageType(openStream: () -> InputStream): ImageType? { - return openStream().use { findImageType(it) } - } + fun findImageType(openStream: () -> InputStream): ImageType? = openStream().use { findImageType(it) } fun findImageType(stream: InputStream): ImageType? { try { @@ -146,19 +144,19 @@ object ImageUtil { return false } - private fun ByteArray.compareWith(magic: ByteArray): Boolean { - return magic.indices.none { this[it] != magic[it] } - } + private fun ByteArray.compareWith(magic: ByteArray): Boolean = magic.indices.none { this[it] != magic[it] } - private fun charByteArrayOf(vararg bytes: Int): ByteArray { - return ByteArray(bytes.size).apply { + private fun charByteArrayOf(vararg bytes: Int): ByteArray = + ByteArray(bytes.size).apply { for (i in bytes.indices) { set(i, bytes[i].toByte()) } } - } - enum class ImageType(val mime: String, val extension: String) { + enum class ImageType( + val mime: String, + val extension: String, + ) { AVIF("image/avif", "avif"), GIF("image/gif", "gif"), HEIF("image/heif", "heif"), diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/model/dataclass/ChapterDataClass.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/model/dataclass/ChapterDataClass.kt index 9c59b313..85dc8e72 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/model/dataclass/ChapterDataClass.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/model/dataclass/ChapterDataClass.kt @@ -49,8 +49,8 @@ data class ChapterDataClass( fetchedAt: Long, mangaId: Int, realUrl: String?, - ): ChapterDataClass { - return ChapterDataClass( + ): ChapterDataClass = + ChapterDataClass( id = id, url = sChapter.url, name = sChapter.name, @@ -67,6 +67,5 @@ data class ChapterDataClass( lastReadAt = 0, downloaded = false, ) - } } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/model/dataclass/MangaDataClass.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/model/dataclass/MangaDataClass.kt index e5af42d7..9af2eeba 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/model/dataclass/MangaDataClass.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/model/dataclass/MangaDataClass.kt @@ -44,9 +44,7 @@ data class MangaDataClass( val chaptersAge: Long? = if (chaptersLastFetchedAt == null) null else Instant.now().epochSecond.minus(chaptersLastFetchedAt), val trackers: List? = null, ) { - override fun toString(): String { - return "\"$title\" (id= $id) (sourceId= $sourceId)" - } + override fun toString(): String = "\"$title\" (id= $id) (sourceId= $sourceId)" } data class PagedMangaListDataClass( diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/model/table/MangaTable.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/model/table/MangaTable.kt index 9f747228..a4dadd40 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/model/table/MangaTable.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/model/table/MangaTable.kt @@ -69,7 +69,9 @@ fun MangaTable.toDataClass(mangaEntry: ResultRow) = updateStrategy = UpdateStrategy.valueOf(mangaEntry[updateStrategy]), ) -enum class MangaStatus(val value: Int) { +enum class MangaStatus( + val value: Int, +) { UNKNOWN(0), ONGOING(1), COMPLETED(2), diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/model/table/TrackSearchTable.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/model/table/TrackSearchTable.kt index 9f2499d9..29f4dcd2 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/model/table/TrackSearchTable.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/model/table/TrackSearchTable.kt @@ -37,9 +37,10 @@ fun List.insertAll(): List { val remoteIds = map { it.media_id }.toSet() val existing = transaction { - TrackSearchTable.select { - TrackSearchTable.trackerId inList trackerIds and (TrackSearchTable.remoteId inList remoteIds) - }.toList() + TrackSearchTable + .select { + TrackSearchTable.trackerId inList trackerIds and (TrackSearchTable.remoteId inList remoteIds) + }.toList() } val grouped = mutableMapOf>>() @@ -49,7 +50,8 @@ fun List.insertAll(): List { it[TrackSearchTable.trackerId] == trackSearch.sync_id && it[TrackSearchTable.remoteId] == trackSearch.media_id } - grouped.getOrPut(existingRow != null) { mutableListOf() } + grouped + .getOrPut(existingRow != null) { mutableListOf() } .add(existingRow?.get(TrackSearchTable.id)?.value to trackSearch) } val toUpdate = grouped[true] @@ -90,9 +92,11 @@ fun List.insertAll(): List { } val updatedRows = - toUpdate?.mapNotNull { it.first }?.let { ids -> - transaction { TrackSearchTable.select { TrackSearchTable.id inList ids }.toList() } - }.orEmpty() + toUpdate + ?.mapNotNull { it.first } + ?.let { ids -> + transaction { TrackSearchTable.select { TrackSearchTable.id inList ids }.toList() } + }.orEmpty() (insertedRows + updatedRows) .sortedBy { row -> diff --git a/server/src/main/kotlin/suwayomi/tachidesk/server/ConfigAdapters.kt b/server/src/main/kotlin/suwayomi/tachidesk/server/ConfigAdapters.kt index e7668f8d..69ee6cd6 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/server/ConfigAdapters.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/server/ConfigAdapters.kt @@ -5,25 +5,17 @@ interface ConfigAdapter { } object StringConfigAdapter : ConfigAdapter { - override fun toType(configValue: String): String { - return configValue - } + override fun toType(configValue: String): String = configValue } object IntConfigAdapter : ConfigAdapter { - override fun toType(configValue: String): Int { - return configValue.toInt() - } + override fun toType(configValue: String): Int = configValue.toInt() } object BooleanConfigAdapter : ConfigAdapter { - override fun toType(configValue: String): Boolean { - return configValue.toBoolean() - } + override fun toType(configValue: String): Boolean = configValue.toBoolean() } object DoubleConfigAdapter : ConfigAdapter { - override fun toType(configValue: String): Double { - return configValue.toDouble() - } + override fun toType(configValue: String): Double = configValue.toDouble() } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/server/JavalinSetup.kt b/server/src/main/kotlin/suwayomi/tachidesk/server/JavalinSetup.kt index 7fda009c..dbba450f 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/server/JavalinSetup.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/server/JavalinSetup.kt @@ -45,9 +45,7 @@ object JavalinSetup { private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO) - fun future(block: suspend CoroutineScope.() -> T): CompletableFuture { - return scope.future(block = block) - } + fun future(block: suspend CoroutineScope.() -> T): CompletableFuture = scope.future(block = block) fun javalinSetup() { val server = Server() diff --git a/server/src/main/kotlin/suwayomi/tachidesk/server/Migration.kt b/server/src/main/kotlin/suwayomi/tachidesk/server/Migration.kt index 381b504a..b83ce281 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/server/Migration.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/server/Migration.kt @@ -29,13 +29,15 @@ private fun migratePreferences( subNode[it, null]?.ifBlank { null } } - preferences.edit().apply { - items.forEach { (key, value) -> - if (value != null) { - putString(key, value) + preferences + .edit() + .apply { + items.forEach { (key, value) -> + if (value != null) { + putString(key, value) + } } - } - }.apply() + }.apply() migratePreferences(key, subNode) // Recursively migrate sub-level nodes } @@ -45,7 +47,8 @@ const val MIGRATION_VERSION = 1 fun runMigrations(applicationDirs: ApplicationDirs) { val migrationPreferences = - Injekt.get() + Injekt + .get() .getSharedPreferences( "migrations", Context.MODE_PRIVATE, diff --git a/server/src/main/kotlin/suwayomi/tachidesk/server/ServerConfig.kt b/server/src/main/kotlin/suwayomi/tachidesk/server/ServerConfig.kt index 706f0d6f..62f944bb 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/server/ServerConfig.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/server/ServerConfig.kt @@ -31,11 +31,16 @@ val mutableConfigValueScope = CoroutineScope(SupervisorJob() + Dispatchers.Defau const val SERVER_CONFIG_MODULE_NAME = "server" -class ServerConfig(getConfig: () -> Config, val moduleName: String = SERVER_CONFIG_MODULE_NAME) : SystemPropertyOverridableConfigModule( - getConfig, - moduleName, -) { - open inner class OverrideConfigValue(private val configAdapter: ConfigAdapter) { +class ServerConfig( + getConfig: () -> Config, + val moduleName: String = SERVER_CONFIG_MODULE_NAME, +) : SystemPropertyOverridableConfigModule( + getConfig, + moduleName, + ) { + open inner class OverrideConfigValue( + private val configAdapter: ConfigAdapter, + ) { private var flow: MutableStateFlow? = null open fun getValueFromConfig( @@ -57,7 +62,10 @@ class ServerConfig(getConfig: () -> Config, val moduleName: String = SERVER_CONF val stateFlow = MutableStateFlow(value) flow = stateFlow - stateFlow.drop(1).distinctUntilChanged().filter { it != getValueFromConfig(thisRef, property) } + stateFlow + .drop(1) + .distinctUntilChanged() + .filter { it != getValueFromConfig(thisRef, property) } .onEach { GlobalConfigManager.updateValue("$moduleName.${property.name}", it as Any) } .launchIn(mutableConfigValueScope) @@ -65,14 +73,16 @@ class ServerConfig(getConfig: () -> Config, val moduleName: String = SERVER_CONF } } - inner class OverrideConfigValues(private val configAdapter: ConfigAdapter) : OverrideConfigValue(configAdapter) { + inner class OverrideConfigValues( + private val configAdapter: ConfigAdapter, + ) : OverrideConfigValue(configAdapter) { override fun getValueFromConfig( thisRef: ServerConfig, property: KProperty<*>, - ): Any { - return overridableConfig.getValue>(thisRef, property) + ): Any = + overridableConfig + .getValue>(thisRef, property) .map { configAdapter.toType(it) } - } } val ip: MutableStateFlow by OverrideConfigValue(StringConfigAdapter) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/server/ServerSetup.kt b/server/src/main/kotlin/suwayomi/tachidesk/server/ServerSetup.kt index 5801f701..ca695db0 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/server/ServerSetup.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/server/ServerSetup.kt @@ -130,7 +130,9 @@ fun applicationSetup() { logger.debug { "Loaded config:\n" + - GlobalConfigManager.config.root().render(ConfigRenderOptions.concise().setFormatted(true)) + GlobalConfigManager.config + .root() + .render(ConfigRenderOptions.concise().setFormatted(true)) .replace(Regex("(\"basicAuth(?:Username|Password)\"\\s:\\s)(?!\"\")\".*\""), "$1\"******\"") } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0001_Initial.kt b/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0001_Initial.kt index 3f1c9692..bb18c621 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0001_Initial.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0001_Initial.kt @@ -40,7 +40,9 @@ class M0001_Initial : AddTableMigration() { } } - private class SourceTable(extensionTable: ExtensionTable) : IdTable() { + private class SourceTable( + extensionTable: ExtensionTable, + ) : IdTable() { override val id = long("id").entityId() init { @@ -74,7 +76,9 @@ class M0001_Initial : AddTableMigration() { } } - private class ChapterTable(mangaTable: MangaTable) : IntIdTable() { + private class ChapterTable( + mangaTable: MangaTable, + ) : IntIdTable() { init { varchar("url", 2048) varchar("name", 512) @@ -91,7 +95,9 @@ class M0001_Initial : AddTableMigration() { } } - private class PageTable(chapterTable: ChapterTable) : IntIdTable() { + private class PageTable( + chapterTable: ChapterTable, + ) : IntIdTable() { init { integer("index") varchar("url", 2048) @@ -108,7 +114,10 @@ class M0001_Initial : AddTableMigration() { } } - private class CategoryMangaTable(categoryTable: CategoryTable, mangaTable: MangaTable) : IntIdTable() { + private class CategoryMangaTable( + categoryTable: CategoryTable, + mangaTable: MangaTable, + ) : IntIdTable() { init { reference("category", categoryTable) reference("manga", mangaTable) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0002_ChapterTableIndexRename.kt b/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0002_ChapterTableIndexRename.kt index 937ba09e..d0829c7f 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0002_ChapterTableIndexRename.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0002_ChapterTableIndexRename.kt @@ -10,8 +10,9 @@ package suwayomi.tachidesk.server.database.migration import de.neonew.exposed.migrations.helpers.RenameFieldMigration @Suppress("ClassName", "unused") -class M0002_ChapterTableIndexRename : RenameFieldMigration( - "Chapter", - "number_in_list", - "index", -) +class M0002_ChapterTableIndexRename : + RenameFieldMigration( + "Chapter", + "number_in_list", + "index", + ) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0003_DefaultCategory.kt b/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0003_DefaultCategory.kt index 049d4c25..17f5ecf9 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0003_DefaultCategory.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0003_DefaultCategory.kt @@ -10,8 +10,9 @@ package suwayomi.tachidesk.server.database.migration import de.neonew.exposed.migrations.helpers.RenameFieldMigration @Suppress("ClassName", "unused") -class M0003_DefaultCategory : RenameFieldMigration( - "Category", - "is_landing", - "is_default", -) +class M0003_DefaultCategory : + RenameFieldMigration( + "Category", + "is_landing", + "is_default", + ) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0007_ChapterIsDownloaded.kt b/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0007_ChapterIsDownloaded.kt index 72bdba23..2e4ae384 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0007_ChapterIsDownloaded.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0007_ChapterIsDownloaded.kt @@ -10,9 +10,10 @@ package suwayomi.tachidesk.server.database.migration import de.neonew.exposed.migrations.helpers.AddColumnMigration @Suppress("ClassName", "unused") -class M0007_ChapterIsDownloaded : AddColumnMigration( - "Chapter", - "is_downloaded", - "BOOLEAN", - "FALSE", -) +class M0007_ChapterIsDownloaded : + AddColumnMigration( + "Chapter", + "is_downloaded", + "BOOLEAN", + "FALSE", + ) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0008_ChapterPageCount.kt b/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0008_ChapterPageCount.kt index cc220998..787e8358 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0008_ChapterPageCount.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0008_ChapterPageCount.kt @@ -10,9 +10,10 @@ package suwayomi.tachidesk.server.database.migration import de.neonew.exposed.migrations.helpers.AddColumnMigration @Suppress("ClassName", "unused") -class M0008_ChapterPageCount : AddColumnMigration( - "Chapter", - "page_count", - "INT", - "-1", -) +class M0008_ChapterPageCount : + AddColumnMigration( + "Chapter", + "page_count", + "INT", + "-1", + ) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0009_ChapterLastReadAt.kt b/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0009_ChapterLastReadAt.kt index 280aba9b..600e699f 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0009_ChapterLastReadAt.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0009_ChapterLastReadAt.kt @@ -10,9 +10,10 @@ package suwayomi.tachidesk.server.database.migration import de.neonew.exposed.migrations.helpers.AddColumnMigration @Suppress("ClassName", "unused") -class M0009_ChapterLastReadAt : AddColumnMigration( - "Chapter", - "last_read_at", - "BIGINT", // BIGINT == Long - "0", -) +class M0009_ChapterLastReadAt : + AddColumnMigration( + "Chapter", + "last_read_at", + "BIGINT", // BIGINT == Long + "0", + ) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0011_SourceDropPartOfFactorySource.kt b/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0011_SourceDropPartOfFactorySource.kt index fbf57385..728f1253 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0011_SourceDropPartOfFactorySource.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0011_SourceDropPartOfFactorySource.kt @@ -10,7 +10,8 @@ package suwayomi.tachidesk.server.database.migration import de.neonew.exposed.migrations.helpers.DropColumnMigration @Suppress("ClassName", "unused") -class M0011_SourceDropPartOfFactorySource : DropColumnMigration( - "Source", - "part_of_factory_source", -) +class M0011_SourceDropPartOfFactorySource : + DropColumnMigration( + "Source", + "part_of_factory_source", + ) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0012_SourceIsNsfw.kt b/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0012_SourceIsNsfw.kt index fb64a182..75f0e822 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0012_SourceIsNsfw.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0012_SourceIsNsfw.kt @@ -10,9 +10,10 @@ package suwayomi.tachidesk.server.database.migration import de.neonew.exposed.migrations.helpers.AddColumnMigration @Suppress("ClassName", "unused") -class M0012_SourceIsNsfw : AddColumnMigration( - "Source", - "is_nsfw", - "BOOLEAN", - "FALSE", -) +class M0012_SourceIsNsfw : + AddColumnMigration( + "Source", + "is_nsfw", + "BOOLEAN", + "FALSE", + ) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0013_MangaRealUrl.kt b/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0013_MangaRealUrl.kt index 5215cff1..c7417694 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0013_MangaRealUrl.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0013_MangaRealUrl.kt @@ -10,9 +10,10 @@ package suwayomi.tachidesk.server.database.migration import de.neonew.exposed.migrations.helpers.AddColumnMigration @Suppress("ClassName", "unused") -class M0013_MangaRealUrl : AddColumnMigration( - "Manga", - "real_url", - "VARCHAR(2048)", - "NULL", -) +class M0013_MangaRealUrl : + AddColumnMigration( + "Manga", + "real_url", + "VARCHAR(2048)", + "NULL", + ) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0017_ChapterFetchedAt.kt b/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0017_ChapterFetchedAt.kt index 5d8d40a6..be24ccbc 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0017_ChapterFetchedAt.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0017_ChapterFetchedAt.kt @@ -10,9 +10,10 @@ package suwayomi.tachidesk.server.database.migration import de.neonew.exposed.migrations.helpers.AddColumnMigration @Suppress("ClassName", "unused") -class M0017_ChapterFetchedAt : AddColumnMigration( - "Chapter", - "fetched_at", - "BIGINT", - "0", -) +class M0017_ChapterFetchedAt : + AddColumnMigration( + "Chapter", + "fetched_at", + "BIGINT", + "0", + ) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0018_MangaInLibraryAt.kt b/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0018_MangaInLibraryAt.kt index c496dd78..05e5a4ce 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0018_MangaInLibraryAt.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0018_MangaInLibraryAt.kt @@ -10,9 +10,10 @@ package suwayomi.tachidesk.server.database.migration import de.neonew.exposed.migrations.helpers.AddColumnMigration @Suppress("ClassName", "unused") -class M0018_MangaInLibraryAt : AddColumnMigration( - "Manga", - "in_library_at", - "BIGINT", - "0", -) +class M0018_MangaInLibraryAt : + AddColumnMigration( + "Manga", + "in_library_at", + "BIGINT", + "0", + ) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0022_MangaThumbnailLastFetched.kt b/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0022_MangaThumbnailLastFetched.kt index baeebf1f..f795407e 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0022_MangaThumbnailLastFetched.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0022_MangaThumbnailLastFetched.kt @@ -10,9 +10,10 @@ package suwayomi.tachidesk.server.database.migration import de.neonew.exposed.migrations.helpers.AddColumnMigration @Suppress("ClassName", "unused") -class M0022_MangaThumbnailLastFetched : AddColumnMigration( - "Manga", - "thumbnail_url_last_fetched", - "BIGINT", - "0", -) +class M0022_MangaThumbnailLastFetched : + AddColumnMigration( + "Manga", + "thumbnail_url_last_fetched", + "BIGINT", + "0", + ) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0024_MangaUpdateStrategy.kt b/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0024_MangaUpdateStrategy.kt index a4906d28..e3b2618d 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0024_MangaUpdateStrategy.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0024_MangaUpdateStrategy.kt @@ -11,9 +11,10 @@ import de.neonew.exposed.migrations.helpers.AddColumnMigration import eu.kanade.tachiyomi.source.model.UpdateStrategy @Suppress("ClassName", "unused") -class M0024_MangaUpdateStrategy : AddColumnMigration( - "Manga", - "update_strategy", - "VARCHAR(256)", - "'${UpdateStrategy.ALWAYS_UPDATE.name}'", -) +class M0024_MangaUpdateStrategy : + AddColumnMigration( + "Manga", + "update_strategy", + "VARCHAR(256)", + "'${UpdateStrategy.ALWAYS_UPDATE.name}'", + ) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0025_ChapterRealUrl.kt b/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0025_ChapterRealUrl.kt index 5c43c620..68da943b 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0025_ChapterRealUrl.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0025_ChapterRealUrl.kt @@ -10,9 +10,10 @@ package suwayomi.tachidesk.server.database.migration import de.neonew.exposed.migrations.helpers.AddColumnMigration @Suppress("ClassName", "unused") -class M0025_ChapterRealUrl : AddColumnMigration( - "Chapter", - "real_url", - "VARCHAR(2048)", - "NULL", -) +class M0025_ChapterRealUrl : + AddColumnMigration( + "Chapter", + "real_url", + "VARCHAR(2048)", + "NULL", + ) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0026_CategoryIncludeInUpdate.kt b/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0026_CategoryIncludeInUpdate.kt index 95996bc5..38b96f0c 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0026_CategoryIncludeInUpdate.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0026_CategoryIncludeInUpdate.kt @@ -11,9 +11,10 @@ import de.neonew.exposed.migrations.helpers.AddColumnMigration import suwayomi.tachidesk.manga.model.dataclass.IncludeOrExclude @Suppress("ClassName", "unused") -class M0026_CategoryIncludeInUpdate : AddColumnMigration( - "Category", - "include_in_update", - "INT", - IncludeOrExclude.UNSET.value.toString(), -) +class M0026_CategoryIncludeInUpdate : + AddColumnMigration( + "Category", + "include_in_update", + "INT", + IncludeOrExclude.UNSET.value.toString(), + ) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0029_DropMangaDefaultCategory.kt b/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0029_DropMangaDefaultCategory.kt index 3b90d79e..b55199de 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0029_DropMangaDefaultCategory.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0029_DropMangaDefaultCategory.kt @@ -10,7 +10,8 @@ package suwayomi.tachidesk.server.database.migration import de.neonew.exposed.migrations.helpers.DropColumnMigration @Suppress("ClassName", "unused") -class M0029_DropMangaDefaultCategory : DropColumnMigration( - "Manga", - "default_category", -) +class M0029_DropMangaDefaultCategory : + DropColumnMigration( + "Manga", + "default_category", + ) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0031_AddExtensionRepo.kt b/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0031_AddExtensionRepo.kt index 494e9f88..bc836f75 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0031_AddExtensionRepo.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0031_AddExtensionRepo.kt @@ -10,9 +10,10 @@ package suwayomi.tachidesk.server.database.migration import de.neonew.exposed.migrations.helpers.AddColumnMigration @Suppress("ClassName", "unused") -class M0031_AddExtensionRepo : AddColumnMigration( - "Extension", - "repo", - "VARCHAR(1024)", - "NULL", -) +class M0031_AddExtensionRepo : + AddColumnMigration( + "Extension", + "repo", + "VARCHAR(1024)", + "NULL", + ) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0034_CategoryIncludeInDownload.kt b/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0034_CategoryIncludeInDownload.kt index a83e0fee..8ce36e71 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0034_CategoryIncludeInDownload.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/server/database/migration/M0034_CategoryIncludeInDownload.kt @@ -11,9 +11,10 @@ import de.neonew.exposed.migrations.helpers.AddColumnMigration import suwayomi.tachidesk.manga.model.dataclass.IncludeOrExclude @Suppress("ClassName", "unused") -class M0034_CategoryIncludeInDownload : AddColumnMigration( - "Category", - "include_in_download", - "INT", - IncludeOrExclude.UNSET.value.toString(), -) +class M0034_CategoryIncludeInDownload : + AddColumnMigration( + "Category", + "include_in_download", + "INT", + IncludeOrExclude.UNSET.value.toString(), + ) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/server/util/AppExit.kt b/server/src/main/kotlin/suwayomi/tachidesk/server/util/AppExit.kt index 41ca249d..2f2d10a9 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/server/util/AppExit.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/server/util/AppExit.kt @@ -12,7 +12,9 @@ import kotlin.system.exitProcess private val logger = KotlinLogging.logger {} -enum class ExitCode(val code: Int) { +enum class ExitCode( + val code: Int, +) { Success(0), MutexCheckFailedTachideskRunning(1), MutexCheckFailedAnotherAppRunning(2), diff --git a/server/src/main/kotlin/suwayomi/tachidesk/server/util/AppMutex.kt b/server/src/main/kotlin/suwayomi/tachidesk/server/util/AppMutex.kt index ab6813e3..5bb1aebc 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/server/util/AppMutex.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/server/util/AppMutex.kt @@ -25,7 +25,9 @@ import java.util.concurrent.TimeUnit object AppMutex { private val logger = KotlinLogging.logger {} - private enum class AppMutexState(val stat: Int) { + private enum class AppMutexState( + val stat: Int, + ) { Clear(0), TachideskInstanceRunning(1), OtherApplicationRunning(2), @@ -37,7 +39,8 @@ object AppMutex { private fun checkAppMutex(): AppMutexState { val client = - OkHttpClient.Builder() + OkHttpClient + .Builder() .connectTimeout(200, TimeUnit.MILLISECONDS) .build() @@ -48,7 +51,11 @@ object AppMutex { val response = try { - client.newCall(request).execute().body.string() + client + .newCall(request) + .execute() + .body + .string() } catch (e: IOException) { return AppMutexState.Clear } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/server/util/DocumentationDsl.kt b/server/src/main/kotlin/suwayomi/tachidesk/server/util/DocumentationDsl.kt index c15b8ef4..db082052 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/server/util/DocumentationDsl.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/server/util/DocumentationDsl.kt @@ -10,14 +10,13 @@ import io.swagger.v3.oas.models.Operation fun getSimpleParamItem( ctx: Context, param: Param, -): String? { - return when (param) { +): String? = + when (param) { is Param.FormParam -> ctx.formParam(param.key) is Param.PathParam -> ctx.pathParam(param.key) is Param.QueryParam -> ctx.queryParam(param.key) else -> throw IllegalStateException("Invalid param") } -} @Suppress("UNCHECKED_CAST") fun getParam( @@ -83,8 +82,8 @@ inline fun getDocumentation( documentWith: OpenApiDocumentation.() -> Unit, noinline withResults: ResultsBuilder.() -> Unit, vararg params: Param<*>, -): OpenApiDocumentation { - return OpenApiDocumentation().apply(documentWith).apply { +): OpenApiDocumentation = + OpenApiDocumentation().apply(documentWith).apply { applyResults(withResults) params.forEach { when (it) { @@ -95,7 +94,6 @@ inline fun getDocumentation( } } } -} fun OpenApiDocumentation.applyResults(withResults: ResultsBuilder.() -> Unit) { ResultsBuilder().apply(withResults).results.forEach { @@ -110,27 +108,19 @@ fun OpenApiDocumentation.withOperation(block: Operation.() -> Unit) { inline fun formParam( key: String, defaultValue: T? = null, -): Param.FormParam { - return Param.FormParam(key, T::class.java, defaultValue, null is T) -} +): Param.FormParam = Param.FormParam(key, T::class.java, defaultValue, null is T) inline fun queryParam( key: String, defaultValue: T? = null, -): Param.QueryParam { - return Param.QueryParam(key, T::class.java, defaultValue, null is T) -} +): Param.QueryParam = Param.QueryParam(key, T::class.java, defaultValue, null is T) inline fun queryParams( key: String, defaultValue: List = emptyList(), -): Param.QueryParams> { - return Param.QueryParams(key, T::class.java, defaultValue, null is T) -} +): Param.QueryParams> = Param.QueryParams(key, T::class.java, defaultValue, null is T) -inline fun pathParam(key: String): Param.PathParam { - return Param.PathParam(key, T::class.java, null, false) -} +inline fun pathParam(key: String): Param.PathParam = Param.PathParam(key, T::class.java, null, false) sealed class Param { abstract val key: String @@ -201,13 +191,19 @@ class ResultsBuilder { sealed class ResultType { abstract fun applyTo(documentation: OpenApiDocumentation) - data class MimeType(val code: HttpCode, val mime: String, private val clazz: Class<*>) : ResultType() { + data class MimeType( + val code: HttpCode, + val mime: String, + private val clazz: Class<*>, + ) : ResultType() { override fun applyTo(documentation: OpenApiDocumentation) { documentation.result(code.status.toString(), clazz, mime) } } - data class StatusCode(val code: HttpCode) : ResultType() { + data class StatusCode( + val code: HttpCode, + ) : ResultType() { override fun applyTo(documentation: OpenApiDocumentation) { documentation.result(code.status.toString()) } @@ -218,20 +214,19 @@ inline fun handler( documentWith: OpenApiDocumentation.() -> Unit = {}, noinline behaviorOf: (ctx: Context) -> Unit, noinline withResults: ResultsBuilder.() -> Unit, -): DocumentedHandler { - return documented( +): DocumentedHandler = + documented( documentation = getDocumentation(documentWith, withResults), handle = behaviorOf, ) -} inline fun handler( param1: Param, documentWith: OpenApiDocumentation.() -> Unit, noinline behaviorOf: (ctx: Context, P1) -> Unit, noinline withResults: ResultsBuilder.() -> Unit, -): DocumentedHandler { - return documented( +): DocumentedHandler = + documented( documentation = getDocumentation(documentWith, withResults, param1), handle = { behaviorOf( @@ -240,7 +235,6 @@ inline fun handler( ) }, ) -} inline fun handler( param1: Param, @@ -248,8 +242,8 @@ inline fun handler( documentWith: OpenApiDocumentation.() -> Unit = {}, crossinline behaviorOf: (ctx: Context, P1, P2) -> Unit, noinline withResults: ResultsBuilder.() -> Unit, -): DocumentedHandler { - return documented( +): DocumentedHandler = + documented( documentation = getDocumentation(documentWith, withResults, param1, param2), handle = { behaviorOf( @@ -259,7 +253,6 @@ inline fun handler( ) }, ) -} inline fun handler( param1: Param, @@ -268,8 +261,8 @@ inline fun handler( documentWith: OpenApiDocumentation.() -> Unit = {}, crossinline behaviorOf: (ctx: Context, P1, P2, P3) -> Unit, noinline withResults: ResultsBuilder.() -> Unit, -): DocumentedHandler { - return documented( +): DocumentedHandler = + documented( documentation = getDocumentation(documentWith, withResults, param1, param2, param3), handle = { behaviorOf( @@ -280,7 +273,6 @@ inline fun handler( ) }, ) -} inline fun handler( param1: Param, @@ -290,8 +282,8 @@ inline fun handler( documentWith: OpenApiDocumentation.() -> Unit = {}, crossinline behaviorOf: (ctx: Context, P1, P2, P3, P4) -> Unit, noinline withResults: ResultsBuilder.() -> Unit, -): DocumentedHandler { - return documented( +): DocumentedHandler = + documented( documentation = getDocumentation(documentWith, withResults, param1, param2, param3, param4), handle = { behaviorOf( @@ -303,7 +295,6 @@ inline fun handler( ) }, ) -} inline fun handler( param1: Param, @@ -314,8 +305,8 @@ inline fun handler( documentWith: OpenApiDocumentation.() -> Unit = {}, crossinline behaviorOf: (ctx: Context, P1, P2, P3, P4, P5) -> Unit, noinline withResults: ResultsBuilder.() -> Unit, -): DocumentedHandler { - return documented( +): DocumentedHandler = + documented( documentation = getDocumentation( documentWith, @@ -337,7 +328,6 @@ inline fun handler( ) }, ) -} inline fun handler( param1: Param, @@ -349,8 +339,8 @@ inline fun Unit = {}, crossinline behaviorOf: (ctx: Context, P1, P2, P3, P4, P5, P6) -> Unit, noinline withResults: ResultsBuilder.() -> Unit, -): DocumentedHandler { - return documented( +): DocumentedHandler = + documented( documentation = getDocumentation( documentWith, @@ -374,7 +364,6 @@ inline fun handler( +> handler( param1: Param, param2: Param, param3: Param, @@ -395,8 +384,8 @@ inline fun < documentWith: OpenApiDocumentation.() -> Unit = {}, crossinline behaviorOf: (ctx: Context, P1, P2, P3, P4, P5, P6, P7) -> Unit, noinline withResults: ResultsBuilder.() -> Unit, -): DocumentedHandler { - return documented( +): DocumentedHandler = + documented( documentation = getDocumentation( documentWith, @@ -422,7 +411,6 @@ inline fun < ) }, ) -} inline fun < reified P1, @@ -433,7 +421,7 @@ inline fun < reified P6, reified P7, reified P8, - > handler( +> handler( param1: Param, param2: Param, param3: Param, @@ -445,8 +433,8 @@ inline fun < documentWith: OpenApiDocumentation.() -> Unit = {}, crossinline behaviorOf: (ctx: Context, P1, P2, P3, P4, P5, P6, P7, P8) -> Unit, noinline withResults: ResultsBuilder.() -> Unit, -): DocumentedHandler { - return documented( +): DocumentedHandler = + documented( documentation = getDocumentation( documentWith, @@ -474,7 +462,6 @@ inline fun < ) }, ) -} inline fun < reified P1, @@ -486,7 +473,7 @@ inline fun < reified P7, reified P8, reified P9, - > handler( +> handler( param1: Param, param2: Param, param3: Param, @@ -499,8 +486,8 @@ inline fun < documentWith: OpenApiDocumentation.() -> Unit = {}, crossinline behaviorOf: (ctx: Context, P1, P2, P3, P4, P5, P6, P7, P8, P9) -> Unit, noinline withResults: ResultsBuilder.() -> Unit, -): DocumentedHandler { - return documented( +): DocumentedHandler = + documented( documentation = getDocumentation( documentWith, @@ -530,7 +517,6 @@ inline fun < ) }, ) -} inline fun < reified P1, @@ -543,7 +529,7 @@ inline fun < reified P8, reified P9, reified P10, - > handler( +> handler( param1: Param, param2: Param, param3: Param, @@ -557,8 +543,8 @@ inline fun < documentWith: OpenApiDocumentation.() -> Unit = {}, crossinline behaviorOf: (ctx: Context, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10) -> Unit, noinline withResults: ResultsBuilder.() -> Unit, -): DocumentedHandler { - return documented( +): DocumentedHandler = + documented( documentation = getDocumentation( documentWith, @@ -590,4 +576,3 @@ inline fun < ) }, ) -} diff --git a/server/src/main/kotlin/suwayomi/tachidesk/server/util/WebInterfaceManager.kt b/server/src/main/kotlin/suwayomi/tachidesk/server/util/WebInterfaceManager.kt index 857710d8..e18bb35a 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/server/util/WebInterfaceManager.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/server/util/WebInterfaceManager.kt @@ -90,9 +90,7 @@ enum class WebUIChannel { companion object { fun from(channel: String): WebUIChannel = entries.find { it.name.lowercase() == channel.lowercase() } ?: STABLE - fun doesConfigChannelEqual(channel: WebUIChannel): Boolean { - return serverConfig.webUIChannel.value.equals(channel.name, true) - } + fun doesConfigChannelEqual(channel: WebUIChannel): Boolean = serverConfig.webUIChannel.value.equals(channel.name, true) } } @@ -202,8 +200,8 @@ object WebInterfaceManager { version: String = "", state: UpdateState = IDLE, progress: Int = 0, - ): WebUIUpdateStatus { - return WebUIUpdateStatus( + ): WebUIUpdateStatus = + WebUIUpdateStatus( info = WebUIUpdateInfo( channel = serverConfig.webUIChannel.value, @@ -212,7 +210,6 @@ object WebInterfaceManager { state, progress, ) - } fun resetStatus() { emitStatus("", IDLE, 0, immediate = true) @@ -228,13 +225,10 @@ object WebInterfaceManager { preferences.edit().putString(SERVED_WEBUI_FLAVOR_KEY, flavor.uiName).apply() } - private fun getServedWebUIFlavor(): WebUIFlavor { - return WebUIFlavor.from(preferences.getString(SERVED_WEBUI_FLAVOR_KEY, WebUIFlavor.default.uiName)!!) - } + private fun getServedWebUIFlavor(): WebUIFlavor = + WebUIFlavor.from(preferences.getString(SERVED_WEBUI_FLAVOR_KEY, WebUIFlavor.default.uiName)!!) - private fun isAutoUpdateEnabled(): Boolean { - return serverConfig.webUIUpdateCheckInterval.value.toInt() != 0 - } + private fun isAutoUpdateEnabled(): Boolean = serverConfig.webUIUpdateCheckInterval.value.toInt() != 0 @OptIn(DelicateCoroutinesApi::class) private fun scheduleWebUIUpdateCheck() { @@ -245,7 +239,10 @@ object WebInterfaceManager { return } - val updateInterval = serverConfig.webUIUpdateCheckInterval.value.hours.coerceAtLeast(1.hours).coerceAtMost(23.hours) + val updateInterval = + serverConfig.webUIUpdateCheckInterval.value.hours + .coerceAtLeast(1.hours) + .coerceAtMost(23.hours) val lastAutomatedUpdate = preferences.getLong(LAST_WEBUI_UPDATE_CHECK_KEY, System.currentTimeMillis()) val task = { @@ -376,7 +373,8 @@ object WebInterfaceManager { true } catch (e: Exception) { false - } || isLocalWebUIValid + } || + isLocalWebUIValid } // download the latest compatible version for the current selected webUI @@ -466,13 +464,12 @@ object WebInterfaceManager { return "$downloadSpecificVersionBaseUrl/$version" } - private fun getLocalVersion(path: String = applicationDirs.webUIRoot): String { - return try { + private fun getLocalVersion(path: String = applicationDirs.webUIRoot): String = + try { File("$path/revision").readText().trim() } catch (e: Exception) { "r-1" } - } private fun doesLocalWebUIExist(path: String): Boolean { // check if we have webUI installed and is correct version @@ -545,39 +542,51 @@ object WebInterfaceManager { private suspend fun fetchMD5SumFor( flavor: WebUIFlavor, version: String, - ): String { - return try { + ): String = + try { executeWithRetry(KotlinLogging.logger("${logger.name} fetchMD5SumFor(flavor= ${flavor.uiName}, version= $version)"), { - network.client.newCall(GET("${getDownloadUrlFor(flavor, version)}/md5sum")).awaitSuccess().body.string().trim() + network.client + .newCall(GET("${getDownloadUrlFor(flavor, version)}/md5sum")) + .awaitSuccess() + .body + .string() + .trim() }) } catch (e: Exception) { "" } - } private fun extractVersion(versionString: String): Int { // version string is of format "r" return versionString.substring(1).toInt() } - private suspend fun fetchPreviewVersion(flavor: WebUIFlavor): String { - return executeWithRetry(KotlinLogging.logger("${logger.name} fetchPreviewVersion(${flavor.uiName})"), { - val releaseInfoJson = network.client.newCall(GET(flavor.latestReleaseInfoUrl)).awaitSuccess().body.string() + private suspend fun fetchPreviewVersion(flavor: WebUIFlavor): String = + executeWithRetry(KotlinLogging.logger("${logger.name} fetchPreviewVersion(${flavor.uiName})"), { + val releaseInfoJson = + network.client + .newCall(GET(flavor.latestReleaseInfoUrl)) + .awaitSuccess() + .body + .string() Json.decodeFromString(releaseInfoJson)["tag_name"]?.jsonPrimitive?.content ?: throw Exception("Failed to get the preview version tag") }) - } - private suspend fun fetchServerMappingFile(flavor: WebUIFlavor): JsonArray { - return executeWithRetry( + private suspend fun fetchServerMappingFile(flavor: WebUIFlavor): JsonArray = + executeWithRetry( KotlinLogging.logger("$logger fetchServerMappingFile(${flavor.uiName})"), { - json.parseToJsonElement( - network.client.newCall(GET(flavor.versionMappingUrl)).awaitSuccess().body.string(), - ).jsonArray + json + .parseToJsonElement( + network.client + .newCall(GET(flavor.versionMappingUrl)) + .awaitSuccess() + .body + .string(), + ).jsonArray }, ) - } private suspend fun getLatestCompatibleVersion(flavor: WebUIFlavor): String { if (WebUIChannel.doesConfigChannelEqual(WebUIChannel.BUNDLED)) { @@ -603,7 +612,8 @@ object WebInterfaceManager { ?: throw Exception("Invalid mappingFile") val minServerVersionString = webUIToServerVersionEntry["serverVersion"] - ?.jsonPrimitive?.content + ?.jsonPrimitive + ?.content ?: throw Exception("Invalid mappingFile") val minServerVersionNumber = extractVersion(minServerVersionString) @@ -777,8 +787,8 @@ object WebInterfaceManager { flavor: WebUIFlavor, currentVersion: String = getLocalVersion(), raiseError: Boolean = false, - ): Pair { - return try { + ): Pair = + try { val isServedWebUIForCurrentFlavor = flavor.uiName == getServedWebUIFlavor().uiName val latestCompatibleVersion = getLatestCompatibleVersion(flavor) val isVersionUpdateAvailable = latestCompatibleVersion != currentVersion @@ -794,5 +804,4 @@ object WebInterfaceManager { Pair("", false) } - } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/util/HAScheduler.kt b/server/src/main/kotlin/suwayomi/tachidesk/util/HAScheduler.kt index 56d33e36..06001604 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/util/HAScheduler.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/util/HAScheduler.kt @@ -32,15 +32,12 @@ abstract class BaseHATask( abstract fun getTimeToNextExecution(): Long - override fun compareTo(other: BaseHATask): Int { - return getTimeToNextExecution().compareTo(other.getTimeToNextExecution()) - } + override fun compareTo(other: BaseHATask): Int = getTimeToNextExecution().compareTo(other.getTimeToNextExecution()) - override fun toString(): String { - return "Task \"$name\" ($id) " + + override fun toString(): String = + "Task \"$name\" ($id) " + "lastExecution= ${Date(getLastExecutionTime())} " + "nextExecution= ${Date(getNextExecutionTime())}" - } } class HACronTask( @@ -51,29 +48,25 @@ class HACronTask( ) : BaseHATask(id, execute, name) { private val executionTime = ExecutionTime.forCron(cronParser.parse(cronExpr)) - override fun getLastExecutionTime(): Long { - return executionTime.lastExecution(ZonedDateTime.now()) + override fun getLastExecutionTime(): Long = + executionTime + .lastExecution(ZonedDateTime.now()) .get() .toEpochSecond() .seconds .inWholeMilliseconds - } - override fun getNextExecutionTime(): Long { - return executionTime.nextExecution(ZonedDateTime.now()) + override fun getNextExecutionTime(): Long = + executionTime + .nextExecution(ZonedDateTime.now()) .get() .toEpochSecond() .seconds .inWholeMilliseconds - } - override fun getTimeToNextExecution(): Long { - return executionTime.timeToNextExecution(ZonedDateTime.now()).get().toMillis() - } + override fun getTimeToNextExecution(): Long = executionTime.timeToNextExecution(ZonedDateTime.now()).get().toMillis() - override fun toString(): String { - return "${super.toString()} interval= $cronExpr" - } + override fun toString(): String = "${super.toString()} interval= $cronExpr" } class HATask( @@ -105,17 +98,11 @@ class HATask( return lastExecutionTime } - override fun getNextExecutionTime(): Long { - return System.currentTimeMillis() + getTimeToNextExecution() - } + override fun getNextExecutionTime(): Long = System.currentTimeMillis() + getTimeToNextExecution() - override fun getTimeToNextExecution(): Long { - return interval - getElapsedTimeOfCurrentInterval() - } + override fun getTimeToNextExecution(): Long = interval - getElapsedTimeOfCurrentInterval() - override fun toString(): String { - return "${super.toString()} interval= $interval, initialDelay= $initialDelay" - } + override fun toString(): String = "${super.toString()} interval= $interval, initialDelay= $initialDelay" } /** diff --git a/server/src/test/kotlin/masstest/CloudFlareTest.kt b/server/src/test/kotlin/masstest/CloudFlareTest.kt index 62bac77c..e3d01863 100644 --- a/server/src/test/kotlin/masstest/CloudFlareTest.kt +++ b/server/src/test/kotlin/masstest/CloudFlareTest.kt @@ -40,7 +40,8 @@ class CloudFlareTest { } nhentai = - Source.getSourceList() + Source + .getSourceList() .firstNotNullOf { it.id.toLong().takeIf { it == 3122156392225024195L } } .let(GetCatalogueSource::getCatalogueSourceOrNull) as HttpSource } diff --git a/server/src/test/kotlin/masstest/TestExtensionCompatibility.kt b/server/src/test/kotlin/masstest/TestExtensionCompatibility.kt index 0f614a42..5a09e1d0 100644 --- a/server/src/test/kotlin/masstest/TestExtensionCompatibility.kt +++ b/server/src/test/kotlin/masstest/TestExtensionCompatibility.kt @@ -81,23 +81,25 @@ class TestExtensionCompatibility { runBlocking(Dispatchers.Default) { val semaphore = Semaphore(10) val popularCount = AtomicInteger(1) - sources.map { source -> - async { - semaphore.withPermit { - logger.info { "${popularCount.getAndIncrement()} - Now fetching popular manga from $source" } - try { - mangaToFetch += source to ( - repeat { source.getPopularManga(1) } - .mangas.firstOrNull() - ?: throw Exception("Source returned no manga") - ) - } catch (e: Exception) { - logger.warn { "Failed to fetch popular manga from $source: ${e.message}" } - failedToFetch += source to e + sources + .map { source -> + async { + semaphore.withPermit { + logger.info { "${popularCount.getAndIncrement()} - Now fetching popular manga from $source" } + try { + mangaToFetch += source to ( + repeat { source.getPopularManga(1) } + .mangas + .firstOrNull() + ?: throw Exception("Source returned no manga") + ) + } catch (e: Exception) { + logger.warn { "Failed to fetch popular manga from $source: ${e.message}" } + failedToFetch += source to e + } } } - } - }.awaitAll() + }.awaitAll() File("$BASE_PATH/failedToFetch.txt").writeText( failedToFetch.joinToString("\n") { (source, exception) -> "${source.name} (${source.lang.uppercase()}, ${source.id}):" + @@ -107,24 +109,25 @@ class TestExtensionCompatibility { logger.info { "Now fetching manga info from ${mangaToFetch.size} sources" } val mangaCount = AtomicInteger(1) - mangaToFetch.map { (source, manga) -> - async { - semaphore.withPermit { - logger.info { "${mangaCount.getAndIncrement()} - Now fetching manga from $source" } - try { - manga.copyFrom(repeat { source.getMangaDetails(manga) }) - manga.initialized = true - } catch (e: Exception) { - logger.warn { - "Failed to fetch manga info from $source for ${manga.title} (${source.mangaDetailsRequest( - manga, - ).url}): ${e.message}" + mangaToFetch + .map { (source, manga) -> + async { + semaphore.withPermit { + logger.info { "${mangaCount.getAndIncrement()} - Now fetching manga from $source" } + try { + manga.copyFrom(repeat { source.getMangaDetails(manga) }) + manga.initialized = true + } catch (e: Exception) { + logger.warn { + "Failed to fetch manga info from $source for ${manga.title} (${source.mangaDetailsRequest( + manga, + ).url}): ${e.message}" + } + mangaFailedToFetch += Triple(source, manga, e) } - mangaFailedToFetch += Triple(source, manga, e) } } - } - }.awaitAll() + }.awaitAll() File("$BASE_PATH/MangaFailedToFetch.txt").writeText( mangaFailedToFetch.joinToString("\n") { (source, manga, exception) -> "${source.name} (${source.lang}, ${source.id}):" + @@ -135,35 +138,40 @@ class TestExtensionCompatibility { logger.info { "Now fetching manga chapters from ${mangaToFetch.size} sources" } val chapterCount = AtomicInteger(1) - mangaToFetch.filter { it.second.initialized }.map { (source, manga) -> - async { - semaphore.withPermit { - logger.info { "${chapterCount.getAndIncrement()} - Now fetching manga chapters from $source" } - try { - chaptersToFetch += - Triple( - source, - manga, - repeat { source.getChapterList(manga) }.firstOrNull() ?: throw Exception("Source returned no chapters"), - ) - } catch (e: Exception) { - logger.warn { - "Failed to fetch manga chapters from $source for ${manga.title} (${source.mangaDetailsRequest( - manga, - ).url}): ${e.message}" + mangaToFetch + .filter { it.second.initialized } + .map { (source, manga) -> + async { + semaphore.withPermit { + logger.info { "${chapterCount.getAndIncrement()} - Now fetching manga chapters from $source" } + try { + chaptersToFetch += + Triple( + source, + manga, + repeat { + source.getChapterList(manga) + }.firstOrNull() + ?: throw Exception("Source returned no chapters"), + ) + } catch (e: Exception) { + logger.warn { + "Failed to fetch manga chapters from $source for ${manga.title} (${source.mangaDetailsRequest( + manga, + ).url}): ${e.message}" + } + chaptersFailedToFetch += Triple(source, manga, e) + } catch (e: NoClassDefFoundError) { + logger.warn { + "Failed to fetch manga chapters from $source for ${manga.title} (${source.mangaDetailsRequest( + manga, + ).url}): ${e.message}" + } + chaptersFailedToFetch += Triple(source, manga, e) } - chaptersFailedToFetch += Triple(source, manga, e) - } catch (e: NoClassDefFoundError) { - logger.warn { - "Failed to fetch manga chapters from $source for ${manga.title} (${source.mangaDetailsRequest( - manga, - ).url}): ${e.message}" - } - chaptersFailedToFetch += Triple(source, manga, e) } } - } - }.awaitAll() + }.awaitAll() File("$BASE_PATH/ChaptersFailedToFetch.txt").writeText( chaptersFailedToFetch.joinToString("\n") { (source, manga, exception) -> @@ -174,23 +182,24 @@ class TestExtensionCompatibility { ) val pageListCount = AtomicInteger(1) - chaptersToFetch.map { (source, manga, chapter) -> - async { - semaphore.withPermit { - logger.info { "${pageListCount.getAndIncrement()} - Now fetching page list from $source" } - try { - repeat { source.getPageList(chapter) } - } catch (e: Exception) { - logger.warn { - "Failed to fetch manga info from $source for ${manga.title} (${source.mangaDetailsRequest( - manga, - ).url}): ${e.message}" + chaptersToFetch + .map { (source, manga, chapter) -> + async { + semaphore.withPermit { + logger.info { "${pageListCount.getAndIncrement()} - Now fetching page list from $source" } + try { + repeat { source.getPageList(chapter) } + } catch (e: Exception) { + logger.warn { + "Failed to fetch manga info from $source for ${manga.title} (${source.mangaDetailsRequest( + manga, + ).url}): ${e.message}" + } + chaptersPageListFailedToFetch += Triple(source, manga to chapter, e) } - chaptersPageListFailedToFetch += Triple(source, manga to chapter, e) } } - } - }.awaitAll() + }.awaitAll() File("$BASE_PATH/ChapterPageListFailedToFetch.txt").writeText( chaptersPageListFailedToFetch.joinToString("\n") { (source, manga, exception) -> diff --git a/server/src/test/kotlin/suwayomi/tachidesk/graphql/RequestParserTest.kt b/server/src/test/kotlin/suwayomi/tachidesk/graphql/RequestParserTest.kt index aa6daf38..3d4c946a 100644 --- a/server/src/test/kotlin/suwayomi/tachidesk/graphql/RequestParserTest.kt +++ b/server/src/test/kotlin/suwayomi/tachidesk/graphql/RequestParserTest.kt @@ -34,7 +34,11 @@ class RequestParserTest { every { ctx.formParam("map") } returns """{ "0": ["variables.file"] }""" every { ctx.uploadedFile("0") } returns UploadedFile( - ByteArrayInputStream(byteArrayOf()), "", "", "", 0, + ByteArrayInputStream(byteArrayOf()), + "", + "", + "", + 0, ) val test = requestParser.parseRequest(ctx) assertIs(test) @@ -57,7 +61,11 @@ class RequestParserTest { every { ctx.formParam("map") } returns """{ "test": ["variables.file"] }""" every { ctx.uploadedFile("test") } returns UploadedFile( - ByteArrayInputStream(byteArrayOf()), "", "", "", 0, + ByteArrayInputStream(byteArrayOf()), + "", + "", + "", + 0, ) val test = requestParser.parseRequest(ctx) assertIs(test) @@ -83,11 +91,19 @@ class RequestParserTest { """.trimIndent() every { ctx.uploadedFile("test") } returns UploadedFile( - ByteArrayInputStream(byteArrayOf()), "", "", "", 0, + ByteArrayInputStream(byteArrayOf()), + "", + "", + "", + 0, ) every { ctx.uploadedFile("test2") } returns UploadedFile( - ByteArrayInputStream(byteArrayOf()), "", "", "", 0, + ByteArrayInputStream(byteArrayOf()), + "", + "", + "", + 0, ) val test = requestParser.parseRequest(ctx) assertIs(test) diff --git a/server/src/test/kotlin/suwayomi/tachidesk/manga/controller/UpdateControllerTest.kt b/server/src/test/kotlin/suwayomi/tachidesk/manga/controller/UpdateControllerTest.kt index cd150b6a..948d427c 100644 --- a/server/src/test/kotlin/suwayomi/tachidesk/manga/controller/UpdateControllerTest.kt +++ b/server/src/test/kotlin/suwayomi/tachidesk/manga/controller/UpdateControllerTest.kt @@ -63,16 +63,16 @@ internal class UpdateControllerTest : ApplicationTest() { assertEquals(3, updater.status.value.numberOfJobs) } - private fun createLibraryManga(_title: String): Int { - return transaction { - MangaTable.insertAndGetId { - it[title] = _title - it[url] = _title - it[sourceReference] = 1 - it[inLibrary] = true - }.value + private fun createLibraryManga(_title: String): Int = + transaction { + MangaTable + .insertAndGetId { + it[title] = _title + it[url] = _title + it[sourceReference] = 1 + it[inLibrary] = true + }.value } - } @AfterEach internal fun tearDown() { diff --git a/server/src/test/kotlin/suwayomi/tachidesk/manga/impl/SearchTest.kt b/server/src/test/kotlin/suwayomi/tachidesk/manga/impl/SearchTest.kt index b9ee6455..c13f384b 100644 --- a/server/src/test/kotlin/suwayomi/tachidesk/manga/impl/SearchTest.kt +++ b/server/src/test/kotlin/suwayomi/tachidesk/manga/impl/SearchTest.kt @@ -35,7 +35,9 @@ import kotlin.test.assertEquals @TestInstance(TestInstance.Lifecycle.PER_CLASS) class SearchTest : ApplicationTest() { - class FakeSearchableSource(id: Long) : StubSource(id) { + class FakeSearchableSource( + id: Long, + ) : StubSource(id) { var mangas: List = emptyList() @Deprecated("Use the non-RxJava API instead", replaceWith = ReplaceWith("getSearchManga")) @@ -43,9 +45,7 @@ class SearchTest : ApplicationTest() { page: Int, query: String, filters: FilterList, - ): Observable { - return Observable.just(MangasPage(mangas, false)) - } + ): Observable = Observable.just(MangasPage(mangas, false)) } private val sourceId = 1L @@ -77,12 +77,12 @@ class SearchTest : ApplicationTest() { @Suppress("UNCHECKED_CAST") class FilterListTest : ApplicationTest() { - open class EmptyFilterListSource(id: Long) : StubSource(id) { + open class EmptyFilterListSource( + id: Long, + ) : StubSource(id) { open var mFilterList = FilterList() - override fun getFilterList(): FilterList { - return mFilterList - } + override fun getFilterList(): FilterList = mFilterList } @Test @@ -98,18 +98,37 @@ class FilterListTest : ApplicationTest() { ) } - class FilterListSource(id: Long) : EmptyFilterListSource(id) { - class SelectFilter(name: String, values: Array) : Filter.Select(name, values) + class FilterListSource( + id: Long, + ) : EmptyFilterListSource(id) { + class SelectFilter( + name: String, + values: Array, + ) : Filter.Select(name, values) - class TextFilter(name: String) : Filter.Text(name) + class TextFilter( + name: String, + ) : Filter.Text(name) - class TestCheckBox(name: String) : Filter.CheckBox(name, false) + class TestCheckBox( + name: String, + ) : Filter.CheckBox(name, false) - class TriState(name: String, state: Int) : Filter.TriState(name, state) + class TriState( + name: String, + state: Int, + ) : Filter.TriState(name, state) - class Group(name: String, state: List) : Filter.Group(name, state) + class Group( + name: String, + state: List, + ) : Filter.Group(name, state) - class Sort(name: String, values: Array, state: Selection) : Filter.Sort(name, values, state) + class Sort( + name: String, + values: Array, + state: Selection, + ) : Filter.Sort(name, values, state) override var mFilterList = FilterList( @@ -319,14 +338,13 @@ class FilterListTest : ApplicationTest() { companion object { private var sourceCount = 0L - private fun registerSource(sourceClass: KClass<*>): EmptyFilterListSource { - return synchronized(sourceCount) { + private fun registerSource(sourceClass: KClass<*>): EmptyFilterListSource = + synchronized(sourceCount) { val source = sourceClass.primaryConstructor!!.call(sourceCount) as EmptyFilterListSource registerCatalogueSource(sourceCount to source) sourceCount++ source } - } @AfterAll fun teardown() { diff --git a/server/src/test/kotlin/suwayomi/tachidesk/manga/model/PaginatedListTest.kt b/server/src/test/kotlin/suwayomi/tachidesk/manga/model/PaginatedListTest.kt index 120fb24e..43c62e39 100644 --- a/server/src/test/kotlin/suwayomi/tachidesk/manga/model/PaginatedListTest.kt +++ b/server/src/test/kotlin/suwayomi/tachidesk/manga/model/PaginatedListTest.kt @@ -102,7 +102,5 @@ class PaginatedListTest : ApplicationTest() { private fun listIndicesOf( first: Int, last: Int, - ): List { - return (first until last).toList() - } + ): List = (first until last).toList() } diff --git a/server/src/test/kotlin/suwayomi/tachidesk/test/TestUtils.kt b/server/src/test/kotlin/suwayomi/tachidesk/test/TestUtils.kt index bc4554a4..ca107986 100644 --- a/server/src/test/kotlin/suwayomi/tachidesk/test/TestUtils.kt +++ b/server/src/test/kotlin/suwayomi/tachidesk/test/TestUtils.kt @@ -31,25 +31,24 @@ fun setLoggingEnabled(enabled: Boolean = true) { const val BASE_PATH = "build/tmp/TestDesk" -fun createLibraryManga(_title: String): Int { - return transaction { - MangaTable.insertAndGetId { - it[title] = _title - it[url] = _title - it[sourceReference] = 1 - it[inLibrary] = true - }.value +fun createLibraryManga(_title: String): Int = + transaction { + MangaTable + .insertAndGetId { + it[title] = _title + it[url] = _title + it[sourceReference] = 1 + it[inLibrary] = true + }.value } -} -fun createSMangas(count: Int): List { - return (0 until count).map { +fun createSMangas(count: Int): List = + (0 until count).map { SManga.create().apply { title = "Manga $it" url = "https://$title" } } -} fun createChapters( mangaId: Int,