From addadefeb15eabdca192b3d6e6ede54ebae57cd0 Mon Sep 17 00:00:00 2001 From: Aria Moradi Date: Tue, 30 Mar 2021 20:39:40 +0430 Subject: [PATCH] some refactor and comments --- .../ir/armor/tachidesk/impl/Category.kt | 7 +++ .../ir/armor/tachidesk/impl/CategoryManga.kt | 7 +++ .../kotlin/ir/armor/tachidesk/impl/Chapter.kt | 6 +- .../ir/armor/tachidesk/impl/Extension.kt | 58 ++++++++++--------- .../ir/armor/tachidesk/impl/ExtensionsList.kt | 2 +- .../kotlin/ir/armor/tachidesk/impl/Library.kt | 3 + .../kotlin/ir/armor/tachidesk/impl/Manga.kt | 2 +- .../kotlin/ir/armor/tachidesk/impl/Page.kt | 5 ++ .../kotlin/ir/armor/tachidesk/impl/Search.kt | 4 ++ .../kotlin/ir/armor/tachidesk/impl/Source.kt | 9 ++- .../armor/tachidesk/impl/util/APKExtractor.kt | 26 ++++----- .../impl/{ => util}/MangaDexHelper.kt | 3 +- .../tachidesk/model/database/MangaTable.kt | 2 +- .../ir/armor/tachidesk/server/JavalinSetup.kt | 4 +- 14 files changed, 84 insertions(+), 54 deletions(-) rename server/src/main/kotlin/ir/armor/tachidesk/impl/{ => util}/MangaDexHelper.kt (98%) diff --git a/server/src/main/kotlin/ir/armor/tachidesk/impl/Category.kt b/server/src/main/kotlin/ir/armor/tachidesk/impl/Category.kt index 2624837..b83d7a2 100644 --- a/server/src/main/kotlin/ir/armor/tachidesk/impl/Category.kt +++ b/server/src/main/kotlin/ir/armor/tachidesk/impl/Category.kt @@ -19,6 +19,10 @@ import org.jetbrains.exposed.sql.selectAll import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.update + +/** + * The new category will be placed at the end of the list + */ fun createCategory(name: String) { transaction { val count = CategoryTable.selectAll().count() @@ -39,6 +43,9 @@ fun updateCategory(categoryId: Int, name: String?, isLanding: Boolean?) { } } +/** + * Move the category from position `from` to `to` + */ fun reorderCategory(categoryId: Int, from: Int, to: Int) { transaction { val categories = CategoryTable.selectAll().orderBy(CategoryTable.order to SortOrder.ASC).toMutableList() diff --git a/server/src/main/kotlin/ir/armor/tachidesk/impl/CategoryManga.kt b/server/src/main/kotlin/ir/armor/tachidesk/impl/CategoryManga.kt index 40adaab..866ad30 100644 --- a/server/src/main/kotlin/ir/armor/tachidesk/impl/CategoryManga.kt +++ b/server/src/main/kotlin/ir/armor/tachidesk/impl/CategoryManga.kt @@ -47,6 +47,10 @@ fun removeMangaFromCategory(mangaId: Int, categoryId: Int) { } } + +/** + * list of mangas that belong to a category + */ fun getCategoryMangaList(categoryId: Int): List { return transaction { CategoryMangaTable.innerJoin(MangaTable).select { CategoryMangaTable.category eq categoryId }.map { @@ -55,6 +59,9 @@ fun getCategoryMangaList(categoryId: Int): List { } } +/** + * 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 { diff --git a/server/src/main/kotlin/ir/armor/tachidesk/impl/Chapter.kt b/server/src/main/kotlin/ir/armor/tachidesk/impl/Chapter.kt index 09894f5..d5f9621 100644 --- a/server/src/main/kotlin/ir/armor/tachidesk/impl/Chapter.kt +++ b/server/src/main/kotlin/ir/armor/tachidesk/impl/Chapter.kt @@ -64,10 +64,10 @@ fun getChapterList(mangaId: Int): List { // clear any orphaned chapters val dbChapterCount = transaction { ChapterTable.selectAll().count() } if (dbChapterCount > chapterCount) { // we got some clean up due - // TODO + // TODO: delete orphan chapters } - return@transaction chapterList.mapIndexed { index, it -> + chapterList.mapIndexed { index, it -> ChapterDataClass( ChapterTable.select { ChapterTable.url eq it.url }.firstOrNull()!![ChapterTable.id].value, it.url, @@ -136,6 +136,6 @@ fun getChapter(chapterIndex: Int, mangaId: Int): ChapterDataClass { } } - return@transaction chapter + chapter } } diff --git a/server/src/main/kotlin/ir/armor/tachidesk/impl/Extension.kt b/server/src/main/kotlin/ir/armor/tachidesk/impl/Extension.kt index bcad0e4..bc46788 100644 --- a/server/src/main/kotlin/ir/armor/tachidesk/impl/Extension.kt +++ b/server/src/main/kotlin/ir/armor/tachidesk/impl/Extension.kt @@ -15,9 +15,9 @@ import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.NetworkHelper import eu.kanade.tachiyomi.source.SourceFactory import eu.kanade.tachiyomi.source.online.HttpSource -import ir.armor.tachidesk.impl.util.APKExtractor import ir.armor.tachidesk.model.database.ExtensionTable import ir.armor.tachidesk.model.database.SourceTable +import ir.armor.tachidesk.impl.util.APKExtractor import ir.armor.tachidesk.server.applicationDirs import kotlinx.coroutines.runBlocking import mu.KotlinLogging @@ -114,42 +114,46 @@ fun installExtension(pkgName: String): Int { File(dexFilePath).delete() // update sources of the extension - val instance = loadExtensionInstance(jarFilePath,className) + val instance = loadExtensionInstance(jarFilePath, className) val extensionId = transaction { - return@transaction ExtensionTable.select { ExtensionTable.name eq extensionRecord.name }.first()[ExtensionTable.id] + ExtensionTable.select { ExtensionTable.name eq extensionRecord.name }.firstOrNull()!![ExtensionTable.id] } - if (instance is HttpSource) { // single source - val httpSource = instance as HttpSource - transaction { - if (SourceTable.select { SourceTable.id eq httpSource.id }.count() == 0L) { - SourceTable.insert { - it[this.id] = httpSource.id - it[name] = httpSource.name - it[this.lang] = httpSource.lang - it[extension] = extensionId - } - } - logger.debug("Installed source ${httpSource.name} with id ${httpSource.id}") - } - } else { // multi source - val sourceFactory = instance as SourceFactory - transaction { - sourceFactory.createSources().forEachIndexed { index, source -> - val httpSource = source as HttpSource - if (SourceTable.select { SourceTable.id eq httpSource.id }.count() == 0L) { + when (instance) { + is HttpSource -> { // single source + transaction { + if (SourceTable.select { SourceTable.id eq instance.id }.count() == 0L) { SourceTable.insert { - it[this.id] = httpSource.id - it[name] = httpSource.name - it[this.lang] = httpSource.lang + it[this.id] = instance.id + it[name] = instance.name + it[this.lang] = instance.lang it[extension] = extensionId - it[partOfFactorySource] = true } } - logger.debug("Installed source ${httpSource.name} with id:${httpSource.id}") + logger.debug("Installed source ${instance.name} with id ${instance.id}") } } + is SourceFactory -> { // theme source or multi lang + transaction { + instance.createSources().forEachIndexed { index, source -> + val httpSource = source as HttpSource + if (SourceTable.select { SourceTable.id eq httpSource.id }.count() == 0L) { + SourceTable.insert { + it[this.id] = httpSource.id + it[name] = httpSource.name + it[this.lang] = httpSource.lang + it[extension] = extensionId + it[partOfFactorySource] = true + } + } + logger.debug("Installed source ${httpSource.name} with id:${httpSource.id}") + } + } + } + else -> { + throw RuntimeException("Extension content is unexpected") + } } // update extension info diff --git a/server/src/main/kotlin/ir/armor/tachidesk/impl/ExtensionsList.kt b/server/src/main/kotlin/ir/armor/tachidesk/impl/ExtensionsList.kt index 2c84af0..519b023 100644 --- a/server/src/main/kotlin/ir/armor/tachidesk/impl/ExtensionsList.kt +++ b/server/src/main/kotlin/ir/armor/tachidesk/impl/ExtensionsList.kt @@ -48,7 +48,7 @@ fun getExtensionList(): List { } fun extensionTableAsDataClass() = transaction { - return@transaction ExtensionTable.selectAll().map { + ExtensionTable.selectAll().map { ExtensionDataClass( it[ExtensionTable.name], it[ExtensionTable.pkgName], diff --git a/server/src/main/kotlin/ir/armor/tachidesk/impl/Library.kt b/server/src/main/kotlin/ir/armor/tachidesk/impl/Library.kt index 354ef52..84a762f 100644 --- a/server/src/main/kotlin/ir/armor/tachidesk/impl/Library.kt +++ b/server/src/main/kotlin/ir/armor/tachidesk/impl/Library.kt @@ -17,6 +17,9 @@ import org.jetbrains.exposed.sql.select import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.update +// TODO: `Category.isLanding` is to handle the default categories a new library manga gets, +// ..implement that shit at some time... +// ..also Consider to rename it to `isDefault` fun addMangaToLibrary(mangaId: Int) { val manga = getManga(mangaId) if (!manga.inLibrary) { diff --git a/server/src/main/kotlin/ir/armor/tachidesk/impl/Manga.kt b/server/src/main/kotlin/ir/armor/tachidesk/impl/Manga.kt index bf02e91..bafcc84 100644 --- a/server/src/main/kotlin/ir/armor/tachidesk/impl/Manga.kt +++ b/server/src/main/kotlin/ir/armor/tachidesk/impl/Manga.kt @@ -88,7 +88,7 @@ fun getManga(mangaId: Int, proxyThumbnail: Boolean = true): MangaDataClass { } } -fun getThumbnail(mangaId: Int): Pair { +fun getMangaThumbnail(mangaId: Int): Pair { val mangaEntry = transaction { MangaTable.select { MangaTable.id eq mangaId }.firstOrNull()!! } val saveDir = applicationDirs.thumbnailsRoot val fileName = mangaId.toString() diff --git a/server/src/main/kotlin/ir/armor/tachidesk/impl/Page.kt b/server/src/main/kotlin/ir/armor/tachidesk/impl/Page.kt index 7b4d1d9..55fc99c 100644 --- a/server/src/main/kotlin/ir/armor/tachidesk/impl/Page.kt +++ b/server/src/main/kotlin/ir/armor/tachidesk/impl/Page.kt @@ -21,6 +21,10 @@ import org.jetbrains.exposed.sql.update import java.io.File import java.io.InputStream +/** + * A page might have a imageUrl ready from the get go, or we might need to + * go an extra step and call fetchImageUrl to get it. + */ fun getTrueImageUrl(page: Page, source: HttpSource): String { if (page.imageUrl == null) { page.imageUrl = source.fetchImageUrl(page).toBlocking().first()!! @@ -63,6 +67,7 @@ fun getPageImage(mangaId: Int, chapterIndex: Int, index: Int): Pair { // return mapNotNull { filter -> // when (filter) { diff --git a/server/src/main/kotlin/ir/armor/tachidesk/impl/Source.kt b/server/src/main/kotlin/ir/armor/tachidesk/impl/Source.kt index 69cd4e2..cfc07f9 100644 --- a/server/src/main/kotlin/ir/armor/tachidesk/impl/Source.kt +++ b/server/src/main/kotlin/ir/armor/tachidesk/impl/Source.kt @@ -23,7 +23,6 @@ private val logger = KotlinLogging.logger {} private val sourceCache = ConcurrentHashMap() - fun getHttpSource(sourceId: Long): HttpSource { val cachedResult: HttpSource? = sourceCache[sourceId] if (cachedResult != null) { @@ -41,10 +40,10 @@ fun getHttpSource(sourceId: Long): HttpSource { val jarName = apkName.substringBefore(".apk") + ".jar" val jarPath = "${applicationDirs.extensionsRoot}/$jarName" - val extensionInstance = loadExtensionInstance(jarPath,className) + val extensionInstance = loadExtensionInstance(jarPath, className) if (sourceRecord[SourceTable.partOfFactorySource]) { - (extensionInstance as SourceFactory).createSources().forEach{ + (extensionInstance as SourceFactory).createSources().forEach { sourceCache[it.id] = it as HttpSource } } else { @@ -58,7 +57,7 @@ fun getHttpSource(sourceId: Long): HttpSource { fun getSourceList(): List { return transaction { - return@transaction SourceTable.selectAll().map { + SourceTable.selectAll().map { SourceDataClass( it[SourceTable.id].value.toString(), it[SourceTable.name], @@ -74,7 +73,7 @@ fun getSource(sourceId: Long): SourceDataClass { return transaction { val source = SourceTable.select { SourceTable.id eq sourceId }.firstOrNull() - return@transaction SourceDataClass( + SourceDataClass( sourceId.toString(), source?.get(SourceTable.name), source?.get(SourceTable.lang), diff --git a/server/src/main/kotlin/ir/armor/tachidesk/impl/util/APKExtractor.kt b/server/src/main/kotlin/ir/armor/tachidesk/impl/util/APKExtractor.kt index f964c3e..17a6649 100644 --- a/server/src/main/kotlin/ir/armor/tachidesk/impl/util/APKExtractor.kt +++ b/server/src/main/kotlin/ir/armor/tachidesk/impl/util/APKExtractor.kt @@ -134,8 +134,8 @@ object APKExtractor { // AttrValue StrInd off += 5 * 4 // Skip over the 5 words of an attribute val attrName = compXmlString( - xml, sitOff, stOff, - attrNameSi + xml, sitOff, stOff, + attrNameSi ) val attrValue = if (attrValueSi != -1) compXmlString(xml, sitOff, stOff, attrValueSi) else "resourceID 0x ${Integer.toHexString(attrResId)}" @@ -151,21 +151,21 @@ object APKExtractor { val name = compXmlString(xml, sitOff, stOff, nameSi) finalXML.append("") prtIndent( - indent, - " (line " + startTagLineNo + - "-" + lineNo + ")" + indent, + " (line " + startTagLineNo + + "-" + lineNo + ")" ) // tr.parent(); // Step back up the NobTree } else if (tag0 == endDocTag) { // END OF XML DOC TAG break } else { logger.debug( - " Unrecognized tag code '${Integer.toHexString(tag0)}'' at offset $off" + " Unrecognized tag code '${Integer.toHexString(tag0)}'' at offset $off" ) break } } // end of while loop scanning tags and attributes of XML tree - logger.debug(" end at offset $off"); + logger.debug(" end at offset $off") return finalXML.toString() } // end of decompressXML @@ -197,16 +197,16 @@ object APKExtractor { private fun LEW(arr: ByteArray, off: Int): Int { return (arr[off + 3].toInt() shl 24) and -0x1000000 or - (arr[off + 2].toInt() shl 16 and 0xff0000) or - (arr[off + 1].toInt() shl 8 and 0xff00) or - (arr[off].toInt() and 0xFF) + (arr[off + 2].toInt() shl 16 and 0xff0000) or + (arr[off + 1].toInt() shl 8 and 0xff00) or + (arr[off].toInt() and 0xFF) } // end of LEW @Throws(Exception::class) private fun loadXMLFromString(xml: String?): Document { return DocumentBuilderFactory.newInstance() - .newDocumentBuilder() - .parse(InputSource(StringReader(xml))) + .newDocumentBuilder() + .parse(InputSource(StringReader(xml))) } @Throws(IOException::class) @@ -247,4 +247,4 @@ object APKExtractor { return "" } } -} \ No newline at end of file +} diff --git a/server/src/main/kotlin/ir/armor/tachidesk/impl/MangaDexHelper.kt b/server/src/main/kotlin/ir/armor/tachidesk/impl/util/MangaDexHelper.kt similarity index 98% rename from server/src/main/kotlin/ir/armor/tachidesk/impl/MangaDexHelper.kt rename to server/src/main/kotlin/ir/armor/tachidesk/impl/util/MangaDexHelper.kt index 700bce7..5b36230 100644 --- a/server/src/main/kotlin/ir/armor/tachidesk/impl/MangaDexHelper.kt +++ b/server/src/main/kotlin/ir/armor/tachidesk/impl/util/MangaDexHelper.kt @@ -1,4 +1,4 @@ -package ir.armor.tachidesk.impl +package ir.armor.tachidesk.impl.util /* * Copyright (C) Contributors to the Suwayomi project @@ -13,6 +13,7 @@ import okhttp3.FormBody import okhttp3.OkHttpClient import java.net.URLEncoder +// TODO: finish MangaDex support class MangaDexHelper(private val mangaDexSource: HttpSource) { private fun clientBuilder(): OkHttpClient = clientBuilder(0) diff --git a/server/src/main/kotlin/ir/armor/tachidesk/model/database/MangaTable.kt b/server/src/main/kotlin/ir/armor/tachidesk/model/database/MangaTable.kt index 58faa41..d74b2fd 100644 --- a/server/src/main/kotlin/ir/armor/tachidesk/model/database/MangaTable.kt +++ b/server/src/main/kotlin/ir/armor/tachidesk/model/database/MangaTable.kt @@ -8,8 +8,8 @@ package ir.armor.tachidesk.model.database * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ import eu.kanade.tachiyomi.source.model.SManga -import ir.armor.tachidesk.impl.proxyThumbnailUrl import ir.armor.tachidesk.model.dataclass.MangaDataClass +import ir.armor.tachidesk.impl.proxyThumbnailUrl import org.jetbrains.exposed.dao.id.IntIdTable import org.jetbrains.exposed.sql.ResultRow 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 1d0b60a..5709105 100644 --- a/server/src/main/kotlin/ir/armor/tachidesk/server/JavalinSetup.kt +++ b/server/src/main/kotlin/ir/armor/tachidesk/server/JavalinSetup.kt @@ -18,7 +18,7 @@ import ir.armor.tachidesk.impl.getMangaList import ir.armor.tachidesk.impl.getPageImage import ir.armor.tachidesk.impl.getSource import ir.armor.tachidesk.impl.getSourceList -import ir.armor.tachidesk.impl.getThumbnail +import ir.armor.tachidesk.impl.getMangaThumbnail import ir.armor.tachidesk.impl.installExtension import ir.armor.tachidesk.impl.removeCategory import ir.armor.tachidesk.impl.removeMangaFromCategory @@ -143,7 +143,7 @@ fun javalinSetup() { // manga thumbnail app.get("api/v1/manga/:mangaId/thumbnail") { ctx -> val mangaId = ctx.pathParam("mangaId").toInt() - val result = getThumbnail(mangaId) + val result = getMangaThumbnail(mangaId) ctx.result(result.first) ctx.header("content-type", result.second)