diff --git a/server/build.gradle.kts b/server/build.gradle.kts index 65028a6..b42122e 100644 --- a/server/build.gradle.kts +++ b/server/build.gradle.kts @@ -83,7 +83,7 @@ dependencies { testImplementation(kotlin("test-junit5")) } -val MainClass = "ir.armor.tachidesk.Main" +val MainClass = "ir.armor.tachidesk.MainKt" application { mainClass.set(MainClass) } diff --git a/server/src/main/kotlin/ir/armor/tachidesk/Main.kt b/server/src/main/kotlin/ir/armor/tachidesk/Main.kt index 3d1da5a..c86e7b3 100644 --- a/server/src/main/kotlin/ir/armor/tachidesk/Main.kt +++ b/server/src/main/kotlin/ir/armor/tachidesk/Main.kt @@ -10,13 +10,7 @@ package ir.armor.tachidesk import ir.armor.tachidesk.server.JavalinSetup.javalinSetup import ir.armor.tachidesk.server.applicationSetup -class Main { - companion object { - - @JvmStatic - fun main(args: Array) { - applicationSetup() - javalinSetup() - } - } +fun main() { + applicationSetup() + javalinSetup() } diff --git a/server/src/main/kotlin/ir/armor/tachidesk/model/database/DBMangaer.kt b/server/src/main/kotlin/ir/armor/tachidesk/model/database/DBManager.kt similarity index 95% rename from server/src/main/kotlin/ir/armor/tachidesk/model/database/DBMangaer.kt rename to server/src/main/kotlin/ir/armor/tachidesk/model/database/DBManager.kt index 3ced00f..ed446cb 100644 --- a/server/src/main/kotlin/ir/armor/tachidesk/model/database/DBMangaer.kt +++ b/server/src/main/kotlin/ir/armor/tachidesk/model/database/DBManager.kt @@ -15,7 +15,7 @@ import org.kodein.di.DI import org.kodein.di.conf.global import org.kodein.di.instance -object DBMangaer { +object DBManager { val db by lazy { val applicationDirs by DI.global.instance() Database.connect("jdbc:h2:${applicationDirs.dataRoot}/database", "org.h2.Driver") @@ -24,7 +24,7 @@ object DBMangaer { fun databaseUp() { // must mention db object so the lazy block executes - val db = DBMangaer.db + val db = DBManager.db db.useNestedTransactions = true val migrations = loadMigrationsFrom("ir.armor.tachidesk.model.database.migration") diff --git a/server/src/main/kotlin/ir/armor/tachidesk/model/database/migration/M0001_Initial.kt b/server/src/main/kotlin/ir/armor/tachidesk/model/database/migration/M0001_Initial.kt index bb8c976..a893c75 100644 --- a/server/src/main/kotlin/ir/armor/tachidesk/model/database/migration/M0001_Initial.kt +++ b/server/src/main/kotlin/ir/armor/tachidesk/model/database/migration/M0001_Initial.kt @@ -14,104 +14,121 @@ import org.jetbrains.exposed.dao.id.IntIdTable import org.jetbrains.exposed.sql.SchemaUtils import org.jetbrains.exposed.sql.transactions.transaction +@Suppress("ClassName", "unused") class M0001_Initial : Migration() { - private object ExtensionTable : IntIdTable() { - val apkName = varchar("apk_name", 1024) + private class ExtensionTable : IntIdTable() { + init { + varchar("apk_name", 1024) + // default is the local source icon from tachiyomi + varchar("icon_url", 2048) + .default("https://raw.githubusercontent.com/tachiyomiorg/tachiyomi/64ba127e7d43b1d7e6d58a6f5c9b2bd5fe0543f7/app/src/main/res/mipmap-xxxhdpi/ic_local_source.webp") + varchar("name", 128) + varchar("pkg_name", 128) + varchar("version_name", 16) + integer("version_code") + varchar("lang", 10) + bool("is_nsfw") - // default is the local source icon from tachiyomi - val iconUrl = varchar("icon_url", 2048) - .default("https://raw.githubusercontent.com/tachiyomiorg/tachiyomi/64ba127e7d43b1d7e6d58a6f5c9b2bd5fe0543f7/app/src/main/res/mipmap-xxxhdpi/ic_local_source.webp") + bool("is_installed").default(false) + bool("has_update").default(false) + bool("is_obsolete").default(false) - val name = varchar("name", 128) - val pkgName = varchar("pkg_name", 128) - val versionName = varchar("version_name", 16) - val versionCode = integer("version_code") - val lang = varchar("lang", 10) - val isNsfw = bool("is_nsfw") - - val isInstalled = bool("is_installed").default(false) - val hasUpdate = bool("has_update").default(false) - val isObsolete = bool("is_obsolete").default(false) - - val classFQName = varchar("class_name", 1024).default("") // fully qualified name + varchar("class_name", 1024).default("") // fully qualified name + } } - private object SourceTable : IdTable() { + private class SourceTable(extensionTable: ExtensionTable) : IdTable() { override val id = long("id").entityId() - val name = varchar("name", 128) - val lang = varchar("lang", 10) - val extension = reference("extension", ExtensionTable) - val partOfFactorySource = bool("part_of_factory_source").default(false) + init { + varchar("name", 128) + varchar("lang", 10) + reference("extension", extensionTable) + bool("part_of_factory_source").default(false) + } } - private object MangaTable : IntIdTable() { - val url = varchar("url", 2048) - val title = varchar("title", 512) - val initialized = bool("initialized").default(false) + private class MangaTable : IntIdTable() { + init { + varchar("url", 2048) + varchar("title", 512) + bool("initialized").default(false) - val artist = varchar("artist", 64).nullable() - val author = varchar("author", 64).nullable() - val description = varchar("description", 4096).nullable() - val genre = varchar("genre", 1024).nullable() + varchar("artist", 64).nullable() + varchar("author", 64).nullable() + varchar("description", 4096).nullable() + varchar("genre", 1024).nullable() - // val status = enumeration("status", MangaStatus::class).default(MangaStatus.UNKNOWN) - val status = integer("status").default(SManga.UNKNOWN) - val thumbnail_url = varchar("thumbnail_url", 2048).nullable() + // val status = enumeration("status", MangaStatus::class).default(MangaStatus.UNKNOWN) + integer("status").default(SManga.UNKNOWN) + varchar("thumbnail_url", 2048).nullable() - val inLibrary = bool("in_library").default(false) - val defaultCategory = bool("default_category").default(true) + bool("in_library").default(false) + bool("default_category").default(true) - // source is used by some ancestor of IntIdTable - val sourceReference = long("source") + // source is used by some ancestor of IntIdTable + long("source") + } } - private object ChapterTable : IntIdTable() { - val url = varchar("url", 2048) - val name = varchar("name", 512) - val date_upload = long("date_upload").default(0) - val chapter_number = float("chapter_number").default(-1f) - val scanlator = varchar("scanlator", 128).nullable() + private class ChapterTable(mangaTable: MangaTable) : IntIdTable() { + init { + varchar("url", 2048) + varchar("name", 512) + long("date_upload").default(0) + float("chapter_number").default(-1f) + varchar("scanlator", 128).nullable() - val isRead = bool("read").default(false) - val isBookmarked = bool("bookmark").default(false) - val lastPageRead = integer("last_page_read").default(0) + bool("read").default(false) + bool("bookmark").default(false) + integer("last_page_read").default(0) - val chapterIndex = integer("number_in_list") - - val manga = reference("manga", MangaTable) + integer("number_in_list") + reference("manga", mangaTable) + } } - private object PageTable : IntIdTable() { - val index = integer("index") - val url = varchar("url", 2048) - val imageUrl = varchar("imageUrl", 2048).nullable() - - val chapter = reference("chapter", ChapterTable) + private class PageTable(chapterTable: ChapterTable) : IntIdTable() { + init { + integer("index") + varchar("url", 2048) + varchar("imageUrl", 2048).nullable() + reference("chapter", chapterTable) + } } - private object CategoryTable : IntIdTable() { - val name = varchar("name", 64) - val isLanding = bool("is_landing").default(false) - val order = integer("order").default(0) + private class CategoryTable : IntIdTable() { + init { + varchar("name", 64) + bool("is_landing").default(false) + integer("order").default(0) + } } - private object CategoryMangaTable : IntIdTable() { - val category = reference("category", ir.armor.tachidesk.model.database.table.CategoryTable) - val manga = reference("manga", ir.armor.tachidesk.model.database.table.MangaTable) + private class CategoryMangaTable : IntIdTable() { + init { + reference("category", ir.armor.tachidesk.model.database.table.CategoryTable) + reference("manga", ir.armor.tachidesk.model.database.table.MangaTable) + } } /** initial migration, create all tables */ override fun run() { transaction { + val extensionTable = ExtensionTable() + val sourceTable = SourceTable(extensionTable) + val mangaTable = MangaTable() + val chapterTable = ChapterTable(mangaTable) + val pageTable = PageTable(chapterTable) + val categoryTable = CategoryTable() + val categoryMangaTable = CategoryMangaTable() SchemaUtils.create( - ExtensionTable, - ExtensionTable, - SourceTable, - MangaTable, - ChapterTable, - PageTable, - CategoryTable, - CategoryMangaTable, + extensionTable, + sourceTable, + mangaTable, + chapterTable, + pageTable, + categoryTable, + categoryMangaTable, ) } } diff --git a/server/src/main/kotlin/ir/armor/tachidesk/model/database/migration/M0002_ChapterTableIndexRename.kt b/server/src/main/kotlin/ir/armor/tachidesk/model/database/migration/M0002_ChapterTableIndexRename.kt index 9c5eee0..fbf40f3 100644 --- a/server/src/main/kotlin/ir/armor/tachidesk/model/database/migration/M0002_ChapterTableIndexRename.kt +++ b/server/src/main/kotlin/ir/armor/tachidesk/model/database/migration/M0002_ChapterTableIndexRename.kt @@ -11,6 +11,7 @@ import ir.armor.tachidesk.model.database.migration.lib.Migration import org.jetbrains.exposed.sql.transactions.TransactionManager import org.jetbrains.exposed.sql.vendors.currentDialect +@Suppress("ClassName", "unused") class M0002_ChapterTableIndexRename : Migration() { /** this migration renamed ChapterTable.NUMBER_IN_LIST to ChapterTable.INDEX */ override fun run() { diff --git a/server/src/main/kotlin/ir/armor/tachidesk/model/database/migration/lib/runMigrations.kt b/server/src/main/kotlin/ir/armor/tachidesk/model/database/migration/lib/runMigrations.kt index 4579e90..907a18d 100644 --- a/server/src/main/kotlin/ir/armor/tachidesk/model/database/migration/lib/runMigrations.kt +++ b/server/src/main/kotlin/ir/armor/tachidesk/model/database/migration/lib/runMigrations.kt @@ -54,6 +54,7 @@ fun runMigrations(migrations: List, database: Database = TransactionM logger.info { "Migrations finished successfully" } } +@Suppress("UnstableApiUsage") fun loadMigrationsFrom(classPath: String): List { return ClassPath.from(Thread.currentThread().contextClassLoader) .getTopLevelClasses(classPath) diff --git a/server/src/main/kotlin/ir/armor/tachidesk/model/database/table/CategoryTable.kt b/server/src/main/kotlin/ir/armor/tachidesk/model/database/table/CategoryTable.kt index 3b047a2..1ddee64 100644 --- a/server/src/main/kotlin/ir/armor/tachidesk/model/database/table/CategoryTable.kt +++ b/server/src/main/kotlin/ir/armor/tachidesk/model/database/table/CategoryTable.kt @@ -18,8 +18,8 @@ object CategoryTable : IntIdTable() { } fun CategoryTable.toDataClass(categoryEntry: ResultRow) = CategoryDataClass( - categoryEntry[CategoryTable.id].value, - categoryEntry[CategoryTable.order], - categoryEntry[CategoryTable.name], - categoryEntry[CategoryTable.isLanding], + categoryEntry[this.id].value, + categoryEntry[this.order], + categoryEntry[this.name], + categoryEntry[this.isLanding], ) diff --git a/server/src/main/kotlin/ir/armor/tachidesk/model/database/table/ChapterTable.kt b/server/src/main/kotlin/ir/armor/tachidesk/model/database/table/ChapterTable.kt index 4c34044..404c538 100644 --- a/server/src/main/kotlin/ir/armor/tachidesk/model/database/table/ChapterTable.kt +++ b/server/src/main/kotlin/ir/armor/tachidesk/model/database/table/ChapterTable.kt @@ -30,14 +30,14 @@ object ChapterTable : IntIdTable() { fun ChapterTable.toDataClass(chapterEntry: ResultRow) = ChapterDataClass( - chapterEntry[ChapterTable.url], - chapterEntry[ChapterTable.name], - chapterEntry[ChapterTable.date_upload], - chapterEntry[ChapterTable.chapter_number], - chapterEntry[ChapterTable.scanlator], - chapterEntry[ChapterTable.manga].value, - chapterEntry[ChapterTable.isRead], - chapterEntry[ChapterTable.isBookmarked], - chapterEntry[ChapterTable.lastPageRead], - chapterEntry[ChapterTable.chapterIndex], + chapterEntry[this.url], + chapterEntry[this.name], + chapterEntry[this.date_upload], + chapterEntry[this.chapter_number], + chapterEntry[this.scanlator], + chapterEntry[this.manga].value, + chapterEntry[this.isRead], + chapterEntry[this.isBookmarked], + chapterEntry[this.lastPageRead], + chapterEntry[this.chapterIndex], ) diff --git a/server/src/main/kotlin/ir/armor/tachidesk/model/database/table/MangaTable.kt b/server/src/main/kotlin/ir/armor/tachidesk/model/database/table/MangaTable.kt index fd3fd2b..c422813 100644 --- a/server/src/main/kotlin/ir/armor/tachidesk/model/database/table/MangaTable.kt +++ b/server/src/main/kotlin/ir/armor/tachidesk/model/database/table/MangaTable.kt @@ -36,21 +36,21 @@ object MangaTable : IntIdTable() { fun MangaTable.toDataClass(mangaEntry: ResultRow) = MangaDataClass( - mangaEntry[MangaTable.id].value, - mangaEntry[MangaTable.sourceReference].toString(), + mangaEntry[this.id].value, + mangaEntry[this.sourceReference].toString(), - mangaEntry[MangaTable.url], - mangaEntry[MangaTable.title], - proxyThumbnailUrl(mangaEntry[MangaTable.id].value), + mangaEntry[this.url], + mangaEntry[this.title], + proxyThumbnailUrl(mangaEntry[this.id].value), - mangaEntry[MangaTable.initialized], + mangaEntry[this.initialized], - mangaEntry[MangaTable.artist], - mangaEntry[MangaTable.author], - mangaEntry[MangaTable.description], - mangaEntry[MangaTable.genre], - MangaStatus.valueOf(mangaEntry[MangaTable.status]).name, - mangaEntry[MangaTable.inLibrary] + mangaEntry[this.artist], + mangaEntry[this.author], + mangaEntry[this.description], + mangaEntry[this.genre], + MangaStatus.valueOf(mangaEntry[this.status]).name, + mangaEntry[this.inLibrary] ) enum class MangaStatus(val status: Int) { diff --git a/server/src/main/kotlin/ir/armor/tachidesk/server/JavalinSetup.kt b/server/src/main/kotlin/ir/armor/tachidesk/server/JavalinSetup.kt index a597389..6192df0 100644 --- a/server/src/main/kotlin/ir/armor/tachidesk/server/JavalinSetup.kt +++ b/server/src/main/kotlin/ir/armor/tachidesk/server/JavalinSetup.kt @@ -1,7 +1,6 @@ package ir.armor.tachidesk.server import io.javalin.Javalin -import ir.armor.tachidesk.Main import ir.armor.tachidesk.impl.Category.createCategory import ir.armor.tachidesk.impl.Category.getCategoryList import ir.armor.tachidesk.impl.Category.removeCategory @@ -68,7 +67,7 @@ object JavalinSetup { val app = Javalin.create { config -> try { // if the bellow line throws an exception then webUI is not bundled - Main::class.java.getResource("/react/index.html") + this::class.java.getResource("/react/index.html") // no exception so we can tell javalin to serve webUI hasWebUiBundled = true diff --git a/server/src/main/kotlin/ir/armor/tachidesk/server/ServerSetup.kt b/server/src/main/kotlin/ir/armor/tachidesk/server/ServerSetup.kt index 5e7d2a9..f8ab7be 100644 --- a/server/src/main/kotlin/ir/armor/tachidesk/server/ServerSetup.kt +++ b/server/src/main/kotlin/ir/armor/tachidesk/server/ServerSetup.kt @@ -9,7 +9,6 @@ package ir.armor.tachidesk.server import ch.qos.logback.classic.Level import eu.kanade.tachiyomi.App -import ir.armor.tachidesk.Main import ir.armor.tachidesk.model.database.databaseUp import ir.armor.tachidesk.server.util.systemTray import mu.KotlinLogging @@ -81,7 +80,7 @@ fun applicationSetup() { try { val dataConfFile = File("${applicationDirs.dataRoot}/server.conf") if (!dataConfFile.exists()) { - Main::class.java.getResourceAsStream("/server-reference.conf").use { input -> + JavalinSetup::class.java.getResourceAsStream("/server-reference.conf").use { input -> dataConfFile.outputStream().use { output -> input.copyTo(output) } diff --git a/server/src/main/kotlin/ir/armor/tachidesk/server/util/SystemTray.kt b/server/src/main/kotlin/ir/armor/tachidesk/server/util/SystemTray.kt index 495640d..3e84c09 100644 --- a/server/src/main/kotlin/ir/armor/tachidesk/server/util/SystemTray.kt +++ b/server/src/main/kotlin/ir/armor/tachidesk/server/util/SystemTray.kt @@ -12,8 +12,8 @@ import dorkbox.systemTray.SystemTray import dorkbox.systemTray.SystemTray.TrayType import dorkbox.util.CacheUtil import dorkbox.util.Desktop -import ir.armor.tachidesk.Main import ir.armor.tachidesk.server.BuildConfig +import ir.armor.tachidesk.server.ServerConfig import ir.armor.tachidesk.server.serverConfig import kotlin.system.exitProcess @@ -45,11 +45,11 @@ fun systemTray(): SystemTray? { } ) - val icon = Main::class.java.getResource("/icon/faviconlogo.png") + val icon = ServerConfig::class.java.getResource("/icon/faviconlogo.png") -// systemTray.setTooltip("Tachidesk") + // systemTray.setTooltip("Tachidesk") systemTray.setImage(icon) -// systemTray.status = "No Mail" + // systemTray.status = "No Mail" mainMenu.add( MenuItem("Quit") {