let's not polute the namespace

This commit is contained in:
Aria Moradi
2021-03-30 21:04:06 +04:30
parent 2a3c78d43e
commit 90ae180b3e
13 changed files with 200 additions and 164 deletions

View File

@@ -7,6 +7,7 @@ package ir.armor.tachidesk.impl
* 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/. */
import ir.armor.tachidesk.impl.CategoryManga.removeMangaFromCategory
import ir.armor.tachidesk.model.database.CategoryMangaTable
import ir.armor.tachidesk.model.database.CategoryTable
import ir.armor.tachidesk.model.database.toDataClass
@@ -19,29 +20,29 @@ 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()
if (CategoryTable.select { CategoryTable.name eq name }.firstOrNull() == null)
CategoryTable.insert {
it[CategoryTable.name] = name
it[CategoryTable.order] = count.toInt() + 1
}
}
}
fun updateCategory(categoryId: Int, name: String?, isLanding: Boolean?) {
transaction {
CategoryTable.update({ CategoryTable.id eq categoryId }) {
if (name != null) it[CategoryTable.name] = name
if (isLanding != null) it[CategoryTable.isLanding] = isLanding
object Category {
/**
* The new category will be placed at the end of the list
*/
fun createCategory(name: String) {
transaction {
val count = CategoryTable.selectAll().count()
if (CategoryTable.select { CategoryTable.name eq name }.firstOrNull() == null)
CategoryTable.insert {
it[CategoryTable.name] = name
it[CategoryTable.order] = count.toInt() + 1
}
}
}
fun updateCategory(categoryId: Int, name: String?, isLanding: Boolean?) {
transaction {
CategoryTable.update({ CategoryTable.id eq categoryId }) {
if (name != null) it[CategoryTable.name] = name
if (isLanding != null) it[CategoryTable.isLanding] = isLanding
}
}
}
}
/**
* Move the category from position `from` to `to`
@@ -74,3 +75,4 @@ fun getCategoryList(): List<CategoryDataClass> {
}
}
}
}

View File

@@ -21,6 +21,7 @@ import org.jetbrains.exposed.sql.select
import org.jetbrains.exposed.sql.transactions.transaction
import org.jetbrains.exposed.sql.update
object CategoryManga {
fun addMangaToCategory(mangaId: Int, categoryId: Int) {
transaction {
if (CategoryMangaTable.select { (CategoryMangaTable.category eq categoryId) and (CategoryMangaTable.manga eq mangaId) }.firstOrNull() == null) {
@@ -69,3 +70,4 @@ fun getMangaCategories(mangaId: Int): List<CategoryDataClass> {
}
}
}
}

View File

@@ -9,6 +9,8 @@ package ir.armor.tachidesk.impl
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga
import ir.armor.tachidesk.impl.Manga.getManga
import ir.armor.tachidesk.impl.Source.getHttpSource
import ir.armor.tachidesk.model.database.ChapterTable
import ir.armor.tachidesk.model.database.MangaTable
import ir.armor.tachidesk.model.database.PageTable
@@ -21,121 +23,123 @@ import org.jetbrains.exposed.sql.selectAll
import org.jetbrains.exposed.sql.transactions.transaction
import org.jetbrains.exposed.sql.update
fun getChapterList(mangaId: Int): List<ChapterDataClass> {
val mangaDetails = getManga(mangaId)
val source = getHttpSource(mangaDetails.sourceId.toLong())
object Chapter {
fun getChapterList(mangaId: Int): List<ChapterDataClass> {
val mangaDetails = getManga(mangaId)
val source = getHttpSource(mangaDetails.sourceId.toLong())
val chapterList = source.fetchChapterList(
SManga.create().apply {
title = mangaDetails.title
url = mangaDetails.url
}
).toBlocking().first()
val chapterCount = chapterList.count()
return transaction {
chapterList.reversed().forEachIndexed { index, fetchedChapter ->
val chapterEntry = ChapterTable.select { ChapterTable.url eq fetchedChapter.url }.firstOrNull()
if (chapterEntry == null) {
ChapterTable.insertAndGetId {
it[url] = fetchedChapter.url
it[name] = fetchedChapter.name
it[date_upload] = fetchedChapter.date_upload
it[chapter_number] = fetchedChapter.chapter_number
it[scanlator] = fetchedChapter.scanlator
it[chapterIndex] = index + 1
it[manga] = mangaId
val chapterList = source.fetchChapterList(
SManga.create().apply {
title = mangaDetails.title
url = mangaDetails.url
}
} else {
ChapterTable.update({ ChapterTable.url eq fetchedChapter.url }) {
it[name] = fetchedChapter.name
it[date_upload] = fetchedChapter.date_upload
it[chapter_number] = fetchedChapter.chapter_number
it[scanlator] = fetchedChapter.scanlator
it[chapterIndex] = index + 1
it[manga] = mangaId
}
}
}
// clear any orphaned chapters
val dbChapterCount = transaction { ChapterTable.selectAll().count() }
if (dbChapterCount > chapterCount) { // we got some clean up due
// TODO: delete orphan chapters
}
chapterList.mapIndexed { index, it ->
ChapterDataClass(
ChapterTable.select { ChapterTable.url eq it.url }.firstOrNull()!![ChapterTable.id].value,
it.url,
it.name,
it.date_upload,
it.chapter_number,
it.scanlator,
mangaId,
chapterCount - index,
chapterCount
)
}
}
}
fun getChapter(chapterIndex: Int, mangaId: Int): ChapterDataClass {
return transaction {
val chapterEntry = ChapterTable.select {
ChapterTable.chapterIndex eq chapterIndex and (ChapterTable.manga eq mangaId)
}.firstOrNull()!!
val mangaEntry = MangaTable.select { MangaTable.id eq mangaId }.firstOrNull()!!
val source = getHttpSource(mangaEntry[MangaTable.sourceReference])
val pageList = source.fetchPageList(
SChapter.create().apply {
url = chapterEntry[ChapterTable.url]
name = chapterEntry[ChapterTable.name]
}
).toBlocking().first()
val chapterId = chapterEntry[ChapterTable.id].value
val chapterCount = transaction { ChapterTable.selectAll().count() }
val chapterCount = chapterList.count()
val chapter = ChapterDataClass(
chapterId,
chapterEntry[ChapterTable.url],
chapterEntry[ChapterTable.name],
chapterEntry[ChapterTable.date_upload],
chapterEntry[ChapterTable.chapter_number],
chapterEntry[ChapterTable.scanlator],
mangaId,
chapterEntry[ChapterTable.chapterIndex],
chapterCount.toInt(),
return transaction {
chapterList.reversed().forEachIndexed { index, fetchedChapter ->
val chapterEntry = ChapterTable.select { ChapterTable.url eq fetchedChapter.url }.firstOrNull()
if (chapterEntry == null) {
ChapterTable.insertAndGetId {
it[url] = fetchedChapter.url
it[name] = fetchedChapter.name
it[date_upload] = fetchedChapter.date_upload
it[chapter_number] = fetchedChapter.chapter_number
it[scanlator] = fetchedChapter.scanlator
pageList.count()
)
pageList.forEach { page ->
val pageEntry = transaction { PageTable.select { (PageTable.chapter eq chapterId) and (PageTable.index eq page.index) }.firstOrNull() }
if (pageEntry == null) {
transaction {
PageTable.insert {
it[index] = page.index
it[url] = page.url
it[imageUrl] = page.imageUrl
it[this.chapter] = chapterId
it[chapterIndex] = index + 1
it[manga] = mangaId
}
}
} else {
transaction {
PageTable.update({ (PageTable.chapter eq chapterId) and (PageTable.index eq page.index) }) {
it[url] = page.url
it[imageUrl] = page.imageUrl
} else {
ChapterTable.update({ ChapterTable.url eq fetchedChapter.url }) {
it[name] = fetchedChapter.name
it[date_upload] = fetchedChapter.date_upload
it[chapter_number] = fetchedChapter.chapter_number
it[scanlator] = fetchedChapter.scanlator
it[chapterIndex] = index + 1
it[manga] = mangaId
}
}
}
}
chapter
// clear any orphaned chapters
val dbChapterCount = transaction { ChapterTable.selectAll().count() }
if (dbChapterCount > chapterCount) { // we got some clean up due
// TODO: delete orphan chapters
}
chapterList.mapIndexed { index, it ->
ChapterDataClass(
ChapterTable.select { ChapterTable.url eq it.url }.firstOrNull()!![ChapterTable.id].value,
it.url,
it.name,
it.date_upload,
it.chapter_number,
it.scanlator,
mangaId,
chapterCount - index,
chapterCount
)
}
}
}
}
fun getChapter(chapterIndex: Int, mangaId: Int): ChapterDataClass {
return transaction {
val chapterEntry = ChapterTable.select {
ChapterTable.chapterIndex eq chapterIndex and (ChapterTable.manga eq mangaId)
}.firstOrNull()!!
val mangaEntry = MangaTable.select { MangaTable.id eq mangaId }.firstOrNull()!!
val source = getHttpSource(mangaEntry[MangaTable.sourceReference])
val pageList = source.fetchPageList(
SChapter.create().apply {
url = chapterEntry[ChapterTable.url]
name = chapterEntry[ChapterTable.name]
}
).toBlocking().first()
val chapterId = chapterEntry[ChapterTable.id].value
val chapterCount = transaction { ChapterTable.selectAll().count() }
val chapter = ChapterDataClass(
chapterId,
chapterEntry[ChapterTable.url],
chapterEntry[ChapterTable.name],
chapterEntry[ChapterTable.date_upload],
chapterEntry[ChapterTable.chapter_number],
chapterEntry[ChapterTable.scanlator],
mangaId,
chapterEntry[ChapterTable.chapterIndex],
chapterCount.toInt(),
pageList.count()
)
pageList.forEach { page ->
val pageEntry = transaction { PageTable.select { (PageTable.chapter eq chapterId) and (PageTable.index eq page.index) }.firstOrNull() }
if (pageEntry == null) {
transaction {
PageTable.insert {
it[index] = page.index
it[url] = page.url
it[imageUrl] = page.imageUrl
it[this.chapter] = chapterId
}
}
} else {
transaction {
PageTable.update({ (PageTable.chapter eq chapterId) and (PageTable.index eq page.index) }) {
it[url] = page.url
it[imageUrl] = page.imageUrl
}
}
}
}
chapter
}
}
}

View File

@@ -15,6 +15,7 @@ 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.ExtensionsList.extensionTableAsDataClass
import ir.armor.tachidesk.model.database.ExtensionTable
import ir.armor.tachidesk.model.database.SourceTable
import ir.armor.tachidesk.impl.util.APKExtractor
@@ -37,6 +38,7 @@ import java.net.URLClassLoader
import java.nio.file.Files
import java.nio.file.Path
object Extension {
private val logger = KotlinLogging.logger {}
/**
@@ -205,7 +207,7 @@ fun uninstallExtension(pkgName: String) {
}
fun updateExtension(pkgName: String): Int {
val targetExtension = ExtensionListData.updateMap.remove(pkgName)!!
val targetExtension = ExtensionsList.updateMap.remove(pkgName)!!
uninstallExtension(pkgName)
transaction {
ExtensionTable.update({ ExtensionTable.pkgName eq pkgName }) {
@@ -239,3 +241,4 @@ fun getExtensionIcon(apkName: String): Pair<InputStream, String> {
fun getExtensionIconUrl(apkName: String): String {
return "/api/v1/extension/icon/$apkName"
}
}

View File

@@ -9,6 +9,7 @@ package ir.armor.tachidesk.impl
import eu.kanade.tachiyomi.extension.api.ExtensionGithubApi
import eu.kanade.tachiyomi.extension.model.Extension
import ir.armor.tachidesk.impl.Extension.getExtensionIconUrl
import ir.armor.tachidesk.model.database.ExtensionTable
import ir.armor.tachidesk.model.dataclass.ExtensionDataClass
import kotlinx.coroutines.runBlocking
@@ -21,21 +22,22 @@ import org.jetbrains.exposed.sql.transactions.transaction
import org.jetbrains.exposed.sql.update
import java.util.concurrent.ConcurrentHashMap
object ExtensionsList {
private val logger = KotlinLogging.logger {}
object ExtensionListData {
var lastUpdateCheck: Long = 0
var updateMap = ConcurrentHashMap<String, Extension.Available>()
}
// const val ExtensionUpdateDelayTime = 60 * 1000 // 60,000 milliseconds = 60 seconds
const val ExtensionUpdateDelayTime = 0
fun getExtensionList(): List<ExtensionDataClass> {
// update if {ExtensionUpdateDelayTime} seconds has passed or requested offline and database is empty
if (ExtensionListData.lastUpdateCheck + ExtensionUpdateDelayTime < System.currentTimeMillis()) {
if (lastUpdateCheck + ExtensionUpdateDelayTime < System.currentTimeMillis()) {
logger.debug("Getting extensions list from the internet")
ExtensionListData.lastUpdateCheck = System.currentTimeMillis()
lastUpdateCheck = System.currentTimeMillis()
runBlocking {
val foundExtensions = ExtensionGithubApi.findExtensions()
updateExtensionDatabase(foundExtensions)
@@ -76,7 +78,7 @@ private fun updateExtensionDatabase(foundExtensions: List<Extension.Available>)
ExtensionTable.update({ ExtensionTable.pkgName eq foundExtension.pkgName }) {
it[hasUpdate] = true
}
ExtensionListData.updateMap.putIfAbsent(foundExtension.pkgName, foundExtension)
updateMap.putIfAbsent(foundExtension.pkgName, foundExtension)
} else if (foundExtension.versionCode < extensionRecord[ExtensionTable.versionCode]) {
// some how the user installed an invalid version
ExtensionTable.update({ ExtensionTable.pkgName eq foundExtension.pkgName }) {
@@ -131,3 +133,4 @@ private fun updateExtensionDatabase(foundExtensions: List<Extension.Available>)
}
}
}
}

View File

@@ -7,6 +7,7 @@ package ir.armor.tachidesk.impl
* 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/. */
import ir.armor.tachidesk.impl.Manga.getManga
import ir.armor.tachidesk.model.database.CategoryMangaTable
import ir.armor.tachidesk.model.database.MangaTable
import ir.armor.tachidesk.model.database.toDataClass
@@ -17,6 +18,7 @@ import org.jetbrains.exposed.sql.select
import org.jetbrains.exposed.sql.transactions.transaction
import org.jetbrains.exposed.sql.update
object Library {
// 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`
@@ -51,3 +53,4 @@ fun getLibraryMangas(): List<MangaDataClass> {
}
}
}
}

View File

@@ -9,6 +9,9 @@ package ir.armor.tachidesk.impl
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.source.model.SManga
import ir.armor.tachidesk.impl.MangaList.proxyThumbnailUrl
import ir.armor.tachidesk.impl.Source.getHttpSource
import ir.armor.tachidesk.impl.Source.getSource
import ir.armor.tachidesk.model.database.MangaStatus
import ir.armor.tachidesk.model.database.MangaTable
import ir.armor.tachidesk.model.dataclass.MangaDataClass
@@ -18,6 +21,7 @@ import org.jetbrains.exposed.sql.transactions.transaction
import org.jetbrains.exposed.sql.update
import java.io.InputStream
object Manga {
fun getManga(mangaId: Int, proxyThumbnail: Boolean = true): MangaDataClass {
var mangaEntry = transaction { MangaTable.select { MangaTable.id eq mangaId }.firstOrNull()!! }
@@ -106,3 +110,4 @@ fun getMangaThumbnail(mangaId: Int): Pair<InputStream, String> {
).execute()
}
}
}

View File

@@ -8,6 +8,7 @@ package ir.armor.tachidesk.impl
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import eu.kanade.tachiyomi.source.model.MangasPage
import ir.armor.tachidesk.impl.Source.getHttpSource
import ir.armor.tachidesk.model.database.MangaStatus
import ir.armor.tachidesk.model.database.MangaTable
import ir.armor.tachidesk.model.dataclass.MangaDataClass
@@ -16,6 +17,7 @@ import org.jetbrains.exposed.sql.insertAndGetId
import org.jetbrains.exposed.sql.select
import org.jetbrains.exposed.sql.transactions.transaction
object MangaList {
fun proxyThumbnailUrl(mangaId: Int): String {
return "/api/v1/manga/$mangaId/thumbnail"
}
@@ -96,3 +98,4 @@ fun MangasPage.processEntries(sourceId: Long): PagedMangaListDataClass {
mangasPage.hasNextPage
)
}
}

View File

@@ -9,6 +9,7 @@ package ir.armor.tachidesk.impl
import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.online.HttpSource
import ir.armor.tachidesk.impl.Source.getHttpSource
import ir.armor.tachidesk.model.database.ChapterTable
import ir.armor.tachidesk.model.database.MangaTable
import ir.armor.tachidesk.model.database.PageTable
@@ -21,6 +22,7 @@ import org.jetbrains.exposed.sql.update
import java.io.File
import java.io.InputStream
object Page{
/**
* 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.
@@ -88,3 +90,4 @@ fun getChapterDir(mangaId: Int, chapterId: Int): String {
File(mangaDir).mkdirs()
return mangaDir
}
}

View File

@@ -7,8 +7,11 @@ package ir.armor.tachidesk.impl
* 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/. */
import ir.armor.tachidesk.impl.MangaList.processEntries
import ir.armor.tachidesk.impl.Source.getHttpSource
import ir.armor.tachidesk.model.dataclass.PagedMangaListDataClass
object Search {
// TODO
fun sourceFilters(sourceId: Long) {
val source = getHttpSource(sourceId)
@@ -68,3 +71,4 @@ data class FilterWrapper(
// }
// }
// }
}

View File

@@ -9,6 +9,8 @@ package ir.armor.tachidesk.impl
import eu.kanade.tachiyomi.source.SourceFactory
import eu.kanade.tachiyomi.source.online.HttpSource
import ir.armor.tachidesk.impl.Extension.getExtensionIconUrl
import ir.armor.tachidesk.impl.Extension.loadExtensionInstance
import ir.armor.tachidesk.model.database.ExtensionTable
import ir.armor.tachidesk.model.database.SourceTable
import ir.armor.tachidesk.model.dataclass.SourceDataClass
@@ -19,6 +21,7 @@ import org.jetbrains.exposed.sql.selectAll
import org.jetbrains.exposed.sql.transactions.transaction
import java.util.concurrent.ConcurrentHashMap
object Source {
private val logger = KotlinLogging.logger {}
private val sourceCache = ConcurrentHashMap<Long, HttpSource>()
@@ -82,3 +85,4 @@ fun getSource(sourceId: Long): SourceDataClass {
)
}
}
}