some refactor and comments

This commit is contained in:
Aria Moradi 2021-03-30 20:39:40 +04:30
parent 5b9219522d
commit addadefeb1
14 changed files with 84 additions and 54 deletions

View File

@ -19,6 +19,10 @@ import org.jetbrains.exposed.sql.selectAll
import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.transactions.transaction
import org.jetbrains.exposed.sql.update import org.jetbrains.exposed.sql.update
/**
* The new category will be placed at the end of the list
*/
fun createCategory(name: String) { fun createCategory(name: String) {
transaction { transaction {
val count = CategoryTable.selectAll().count() 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) { fun reorderCategory(categoryId: Int, from: Int, to: Int) {
transaction { transaction {
val categories = CategoryTable.selectAll().orderBy(CategoryTable.order to SortOrder.ASC).toMutableList() val categories = CategoryTable.selectAll().orderBy(CategoryTable.order to SortOrder.ASC).toMutableList()

View File

@ -47,6 +47,10 @@ fun removeMangaFromCategory(mangaId: Int, categoryId: Int) {
} }
} }
/**
* list of mangas that belong to a category
*/
fun getCategoryMangaList(categoryId: Int): List<MangaDataClass> { fun getCategoryMangaList(categoryId: Int): List<MangaDataClass> {
return transaction { return transaction {
CategoryMangaTable.innerJoin(MangaTable).select { CategoryMangaTable.category eq categoryId }.map { CategoryMangaTable.innerJoin(MangaTable).select { CategoryMangaTable.category eq categoryId }.map {
@ -55,6 +59,9 @@ fun getCategoryMangaList(categoryId: Int): List<MangaDataClass> {
} }
} }
/**
* list of categories that a manga belongs to
*/
fun getMangaCategories(mangaId: Int): List<CategoryDataClass> { fun getMangaCategories(mangaId: Int): List<CategoryDataClass> {
return transaction { return transaction {
CategoryMangaTable.innerJoin(CategoryTable).select { CategoryMangaTable.manga eq mangaId }.orderBy(CategoryTable.order to SortOrder.ASC).map { CategoryMangaTable.innerJoin(CategoryTable).select { CategoryMangaTable.manga eq mangaId }.orderBy(CategoryTable.order to SortOrder.ASC).map {

View File

@ -64,10 +64,10 @@ fun getChapterList(mangaId: Int): List<ChapterDataClass> {
// clear any orphaned chapters // clear any orphaned chapters
val dbChapterCount = transaction { ChapterTable.selectAll().count() } val dbChapterCount = transaction { ChapterTable.selectAll().count() }
if (dbChapterCount > chapterCount) { // we got some clean up due 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( ChapterDataClass(
ChapterTable.select { ChapterTable.url eq it.url }.firstOrNull()!![ChapterTable.id].value, ChapterTable.select { ChapterTable.url eq it.url }.firstOrNull()!![ChapterTable.id].value,
it.url, it.url,
@ -136,6 +136,6 @@ fun getChapter(chapterIndex: Int, mangaId: Int): ChapterDataClass {
} }
} }
return@transaction chapter chapter
} }
} }

View File

@ -15,9 +15,9 @@ import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.NetworkHelper import eu.kanade.tachiyomi.network.NetworkHelper
import eu.kanade.tachiyomi.source.SourceFactory import eu.kanade.tachiyomi.source.SourceFactory
import eu.kanade.tachiyomi.source.online.HttpSource 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.ExtensionTable
import ir.armor.tachidesk.model.database.SourceTable import ir.armor.tachidesk.model.database.SourceTable
import ir.armor.tachidesk.impl.util.APKExtractor
import ir.armor.tachidesk.server.applicationDirs import ir.armor.tachidesk.server.applicationDirs
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import mu.KotlinLogging import mu.KotlinLogging
@ -114,29 +114,29 @@ fun installExtension(pkgName: String): Int {
File(dexFilePath).delete() File(dexFilePath).delete()
// update sources of the extension // update sources of the extension
val instance = loadExtensionInstance(jarFilePath,className) val instance = loadExtensionInstance(jarFilePath, className)
val extensionId = transaction { 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 when (instance) {
val httpSource = instance as HttpSource is HttpSource -> { // single source
transaction { transaction {
if (SourceTable.select { SourceTable.id eq httpSource.id }.count() == 0L) { if (SourceTable.select { SourceTable.id eq instance.id }.count() == 0L) {
SourceTable.insert { SourceTable.insert {
it[this.id] = httpSource.id it[this.id] = instance.id
it[name] = httpSource.name it[name] = instance.name
it[this.lang] = httpSource.lang it[this.lang] = instance.lang
it[extension] = extensionId it[extension] = extensionId
} }
} }
logger.debug("Installed source ${httpSource.name} with id ${httpSource.id}") logger.debug("Installed source ${instance.name} with id ${instance.id}")
} }
} else { // multi source }
val sourceFactory = instance as SourceFactory is SourceFactory -> { // theme source or multi lang
transaction { transaction {
sourceFactory.createSources().forEachIndexed { index, source -> instance.createSources().forEachIndexed { index, source ->
val httpSource = source as HttpSource val httpSource = source as HttpSource
if (SourceTable.select { SourceTable.id eq httpSource.id }.count() == 0L) { if (SourceTable.select { SourceTable.id eq httpSource.id }.count() == 0L) {
SourceTable.insert { SourceTable.insert {
@ -151,6 +151,10 @@ fun installExtension(pkgName: String): Int {
} }
} }
} }
else -> {
throw RuntimeException("Extension content is unexpected")
}
}
// update extension info // update extension info
transaction { transaction {

View File

@ -48,7 +48,7 @@ fun getExtensionList(): List<ExtensionDataClass> {
} }
fun extensionTableAsDataClass() = transaction { fun extensionTableAsDataClass() = transaction {
return@transaction ExtensionTable.selectAll().map { ExtensionTable.selectAll().map {
ExtensionDataClass( ExtensionDataClass(
it[ExtensionTable.name], it[ExtensionTable.name],
it[ExtensionTable.pkgName], it[ExtensionTable.pkgName],

View File

@ -17,6 +17,9 @@ import org.jetbrains.exposed.sql.select
import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.transactions.transaction
import org.jetbrains.exposed.sql.update 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) { fun addMangaToLibrary(mangaId: Int) {
val manga = getManga(mangaId) val manga = getManga(mangaId)
if (!manga.inLibrary) { if (!manga.inLibrary) {

View File

@ -88,7 +88,7 @@ fun getManga(mangaId: Int, proxyThumbnail: Boolean = true): MangaDataClass {
} }
} }
fun getThumbnail(mangaId: Int): Pair<InputStream, String> { fun getMangaThumbnail(mangaId: Int): Pair<InputStream, String> {
val mangaEntry = transaction { MangaTable.select { MangaTable.id eq mangaId }.firstOrNull()!! } val mangaEntry = transaction { MangaTable.select { MangaTable.id eq mangaId }.firstOrNull()!! }
val saveDir = applicationDirs.thumbnailsRoot val saveDir = applicationDirs.thumbnailsRoot
val fileName = mangaId.toString() val fileName = mangaId.toString()

View File

@ -21,6 +21,10 @@ import org.jetbrains.exposed.sql.update
import java.io.File import java.io.File
import java.io.InputStream 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 { fun getTrueImageUrl(page: Page, source: HttpSource): String {
if (page.imageUrl == null) { if (page.imageUrl == null) {
page.imageUrl = source.fetchImageUrl(page).toBlocking().first()!! page.imageUrl = source.fetchImageUrl(page).toBlocking().first()!!
@ -63,6 +67,7 @@ fun getPageImage(mangaId: Int, chapterIndex: Int, index: Int): Pair<InputStream,
} }
} }
// TODO: rewrite this to match tachiyomi
fun getChapterDir(mangaId: Int, chapterId: Int): String { fun getChapterDir(mangaId: Int, chapterId: Int): String {
val mangaEntry = transaction { MangaTable.select { MangaTable.id eq mangaId }.firstOrNull()!! } val mangaEntry = transaction { MangaTable.select { MangaTable.id eq mangaId }.firstOrNull()!! }
val sourceId = mangaEntry[MangaTable.sourceReference] val sourceId = mangaEntry[MangaTable.sourceReference]

View File

@ -9,6 +9,7 @@ package ir.armor.tachidesk.impl
import ir.armor.tachidesk.model.dataclass.PagedMangaListDataClass import ir.armor.tachidesk.model.dataclass.PagedMangaListDataClass
// TODO
fun sourceFilters(sourceId: Long) { fun sourceFilters(sourceId: Long) {
val source = getHttpSource(sourceId) val source = getHttpSource(sourceId)
// source.getFilterList().toItems() // source.getFilterList().toItems()
@ -29,6 +30,9 @@ data class FilterWrapper(
val filter: Any val filter: Any
) )
/**
* Note: Exhentai had a filter serializer (now in SY) that we might be able to steal
*/
// private fun FilterList.toFilterWrapper(): List<FilterWrapper> { // private fun FilterList.toFilterWrapper(): List<FilterWrapper> {
// return mapNotNull { filter -> // return mapNotNull { filter ->
// when (filter) { // when (filter) {

View File

@ -23,7 +23,6 @@ private val logger = KotlinLogging.logger {}
private val sourceCache = ConcurrentHashMap<Long, HttpSource>() private val sourceCache = ConcurrentHashMap<Long, HttpSource>()
fun getHttpSource(sourceId: Long): HttpSource { fun getHttpSource(sourceId: Long): HttpSource {
val cachedResult: HttpSource? = sourceCache[sourceId] val cachedResult: HttpSource? = sourceCache[sourceId]
if (cachedResult != null) { if (cachedResult != null) {
@ -41,10 +40,10 @@ fun getHttpSource(sourceId: Long): HttpSource {
val jarName = apkName.substringBefore(".apk") + ".jar" val jarName = apkName.substringBefore(".apk") + ".jar"
val jarPath = "${applicationDirs.extensionsRoot}/$jarName" val jarPath = "${applicationDirs.extensionsRoot}/$jarName"
val extensionInstance = loadExtensionInstance(jarPath,className) val extensionInstance = loadExtensionInstance(jarPath, className)
if (sourceRecord[SourceTable.partOfFactorySource]) { if (sourceRecord[SourceTable.partOfFactorySource]) {
(extensionInstance as SourceFactory).createSources().forEach{ (extensionInstance as SourceFactory).createSources().forEach {
sourceCache[it.id] = it as HttpSource sourceCache[it.id] = it as HttpSource
} }
} else { } else {
@ -58,7 +57,7 @@ fun getHttpSource(sourceId: Long): HttpSource {
fun getSourceList(): List<SourceDataClass> { fun getSourceList(): List<SourceDataClass> {
return transaction { return transaction {
return@transaction SourceTable.selectAll().map { SourceTable.selectAll().map {
SourceDataClass( SourceDataClass(
it[SourceTable.id].value.toString(), it[SourceTable.id].value.toString(),
it[SourceTable.name], it[SourceTable.name],
@ -74,7 +73,7 @@ fun getSource(sourceId: Long): SourceDataClass {
return transaction { return transaction {
val source = SourceTable.select { SourceTable.id eq sourceId }.firstOrNull() val source = SourceTable.select { SourceTable.id eq sourceId }.firstOrNull()
return@transaction SourceDataClass( SourceDataClass(
sourceId.toString(), sourceId.toString(),
source?.get(SourceTable.name), source?.get(SourceTable.name),
source?.get(SourceTable.lang), source?.get(SourceTable.lang),

View File

@ -165,7 +165,7 @@ object APKExtractor {
break break
} }
} // end of while loop scanning tags and attributes of XML tree } // 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() return finalXML.toString()
} // end of decompressXML } // end of decompressXML

View File

@ -1,4 +1,4 @@
package ir.armor.tachidesk.impl package ir.armor.tachidesk.impl.util
/* /*
* Copyright (C) Contributors to the Suwayomi project * Copyright (C) Contributors to the Suwayomi project
@ -13,6 +13,7 @@ import okhttp3.FormBody
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import java.net.URLEncoder import java.net.URLEncoder
// TODO: finish MangaDex support
class MangaDexHelper(private val mangaDexSource: HttpSource) { class MangaDexHelper(private val mangaDexSource: HttpSource) {
private fun clientBuilder(): OkHttpClient = clientBuilder(0) private fun clientBuilder(): OkHttpClient = clientBuilder(0)

View File

@ -8,8 +8,8 @@ package ir.armor.tachidesk.model.database
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import ir.armor.tachidesk.impl.proxyThumbnailUrl
import ir.armor.tachidesk.model.dataclass.MangaDataClass import ir.armor.tachidesk.model.dataclass.MangaDataClass
import ir.armor.tachidesk.impl.proxyThumbnailUrl
import org.jetbrains.exposed.dao.id.IntIdTable import org.jetbrains.exposed.dao.id.IntIdTable
import org.jetbrains.exposed.sql.ResultRow import org.jetbrains.exposed.sql.ResultRow

View File

@ -18,7 +18,7 @@ import ir.armor.tachidesk.impl.getMangaList
import ir.armor.tachidesk.impl.getPageImage import ir.armor.tachidesk.impl.getPageImage
import ir.armor.tachidesk.impl.getSource import ir.armor.tachidesk.impl.getSource
import ir.armor.tachidesk.impl.getSourceList 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.installExtension
import ir.armor.tachidesk.impl.removeCategory import ir.armor.tachidesk.impl.removeCategory
import ir.armor.tachidesk.impl.removeMangaFromCategory import ir.armor.tachidesk.impl.removeMangaFromCategory
@ -143,7 +143,7 @@ fun javalinSetup() {
// manga thumbnail // manga thumbnail
app.get("api/v1/manga/:mangaId/thumbnail") { ctx -> app.get("api/v1/manga/:mangaId/thumbnail") { ctx ->
val mangaId = ctx.pathParam("mangaId").toInt() val mangaId = ctx.pathParam("mangaId").toInt()
val result = getThumbnail(mangaId) val result = getMangaThumbnail(mangaId)
ctx.result(result.first) ctx.result(result.first)
ctx.header("content-type", result.second) ctx.header("content-type", result.second)