Skip to content

Commit

Permalink
refactor getChapter (#268)
Browse files Browse the repository at this point in the history
* refactor

* better naming

* fix copytight notice
  • Loading branch information
AriaMoradi authored Dec 1, 2021
1 parent f74f60b commit efff68c
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 102 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import suwayomi.tachidesk.manga.impl.Chapter
import suwayomi.tachidesk.manga.impl.Library
import suwayomi.tachidesk.manga.impl.Manga
import suwayomi.tachidesk.manga.impl.Page
import suwayomi.tachidesk.manga.impl.chapter.getChapterDownloadReady
import suwayomi.tachidesk.manga.model.dataclass.MangaDataClass
import suwayomi.tachidesk.server.JavalinSetup.future
import suwayomi.tachidesk.server.util.handler
Expand Down Expand Up @@ -124,7 +125,7 @@ object MangaController {
fun chapterRetrieve(ctx: Context) {
val chapterIndex = ctx.pathParam("chapterIndex").toInt()
val mangaId = ctx.pathParam("mangaId").toInt()
ctx.future(future { Chapter.getChapter(chapterIndex, mangaId) })
ctx.future(future { getChapterDownloadReady(chapterIndex, mangaId) })
}

/** used to modify a chapter's parameters */
Expand Down
99 changes: 0 additions & 99 deletions server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Chapter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ package suwayomi.tachidesk.manga.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 eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.util.chapter.ChapterRecognition
Expand All @@ -20,11 +19,9 @@ import org.jetbrains.exposed.sql.select
import org.jetbrains.exposed.sql.transactions.transaction
import org.jetbrains.exposed.sql.update
import suwayomi.tachidesk.manga.impl.Manga.getManga
import suwayomi.tachidesk.manga.impl.Page.getPageName
import suwayomi.tachidesk.manga.impl.util.getChapterDir
import suwayomi.tachidesk.manga.impl.util.lang.awaitSingle
import suwayomi.tachidesk.manga.impl.util.source.GetCatalogueSource.getCatalogueSourceOrStub
import suwayomi.tachidesk.manga.impl.util.storage.ImageResponse
import suwayomi.tachidesk.manga.model.dataclass.ChapterDataClass
import suwayomi.tachidesk.manga.model.dataclass.MangaChapterDataClass
import suwayomi.tachidesk.manga.model.dataclass.PaginatedList
Expand Down Expand Up @@ -154,102 +151,6 @@ object Chapter {
}
}

/** used to display a chapter, get a chapter in order to show it's pages */
suspend fun getChapter(chapterIndex: Int, mangaId: Int): ChapterDataClass {
val chapterEntry = transaction {
ChapterTable.select {
(ChapterTable.sourceOrder eq chapterIndex) and (ChapterTable.manga eq mangaId)
}.first()
}

val isPartiallyDownloaded =
!(chapterEntry[ChapterTable.isDownloaded] && firstPageExists(mangaId, chapterEntry[ChapterTable.id].value))

return if (isPartiallyDownloaded) {

// chapter files may have been deleted
transaction {
ChapterTable.update({ (ChapterTable.sourceOrder eq chapterIndex) and (ChapterTable.manga eq mangaId) }) {
it[isDownloaded] = false
}
}

val mangaEntry = transaction { MangaTable.select { MangaTable.id eq mangaId }.first() }
val source = getCatalogueSourceOrStub(mangaEntry[MangaTable.sourceReference])

val pageList = source.fetchPageList(
SChapter.create().apply {
url = chapterEntry[ChapterTable.url]
name = chapterEntry[ChapterTable.name]
}
).awaitSingle()

val chapterId = chapterEntry[ChapterTable.id].value
val chapterCount = transaction { ChapterTable.select { ChapterTable.manga eq mangaId }.count() }

// update page list for this chapter
transaction {
pageList.forEach { page ->
val pageEntry = transaction {
PageTable.select { (PageTable.chapter eq chapterId) and (PageTable.index eq page.index) }
.firstOrNull()
}
if (pageEntry == null) {
PageTable.insert {
it[index] = page.index
it[url] = page.url
it[imageUrl] = page.imageUrl
it[chapter] = chapterId
}
} else {
PageTable.update({ (PageTable.chapter eq chapterId) and (PageTable.index eq page.index) }) {
it[url] = page.url
it[imageUrl] = page.imageUrl
}
}
}
}

val pageCount = pageList.count()

transaction {
ChapterTable.update({ (ChapterTable.manga eq mangaId) and (ChapterTable.sourceOrder eq chapterIndex) }) {
it[ChapterTable.pageCount] = pageCount
}
}
return ChapterDataClass(
chapterEntry[ChapterTable.url],
chapterEntry[ChapterTable.name],
chapterEntry[ChapterTable.date_upload],
chapterEntry[ChapterTable.chapter_number],
chapterEntry[ChapterTable.scanlator],
mangaId,
chapterEntry[ChapterTable.isRead],
chapterEntry[ChapterTable.isBookmarked],
chapterEntry[ChapterTable.lastPageRead],
chapterEntry[ChapterTable.lastReadAt],

chapterEntry[ChapterTable.sourceOrder],
chapterEntry[ChapterTable.fetchedAt],
chapterEntry[ChapterTable.isDownloaded],
pageCount,
chapterCount.toInt(),
getChapterMetaMap(chapterEntry[ChapterTable.id])
)
} else {
ChapterTable.toDataClass(chapterEntry)
}
}

private fun firstPageExists(mangaId: Int, chapterId: Int): Boolean {
val chapterDir = getChapterDir(mangaId, chapterId)

return ImageResponse.findFileNameStartingWith(
chapterDir,
getPageName(1)
) != null
}

fun modifyChapter(
mangaId: Int,
chapterIndex: Int,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
package suwayomi.tachidesk.manga.impl.chapter

/*
* Copyright (C) Contributors to the Suwayomi project
*
* This Source Code Form is subject to the terms of the Mozilla Public
* 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 eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter
import org.jetbrains.exposed.sql.ResultRow
import org.jetbrains.exposed.sql.and
import org.jetbrains.exposed.sql.insert
import org.jetbrains.exposed.sql.select
import org.jetbrains.exposed.sql.transactions.transaction
import org.jetbrains.exposed.sql.update
import suwayomi.tachidesk.manga.impl.Page.getPageName
import suwayomi.tachidesk.manga.impl.util.getChapterDir
import suwayomi.tachidesk.manga.impl.util.lang.awaitSingle
import suwayomi.tachidesk.manga.impl.util.source.GetCatalogueSource.getCatalogueSourceOrStub
import suwayomi.tachidesk.manga.impl.util.storage.ImageResponse
import suwayomi.tachidesk.manga.model.dataclass.ChapterDataClass
import suwayomi.tachidesk.manga.model.table.ChapterTable
import suwayomi.tachidesk.manga.model.table.MangaTable
import suwayomi.tachidesk.manga.model.table.PageTable
import suwayomi.tachidesk.manga.model.table.toDataClass


suspend fun getChapterDownloadReady(chapterIndex: Int, mangaId: Int): ChapterDataClass {
val chapter = ChapterForDownload(chapterIndex, mangaId)

return chapter.asDownloadReady()
}

private class ChapterForDownload(
private val chapterIndex: Int,
private val mangaId: Int
) {
suspend fun asDownloadReady(): ChapterDataClass {

if (isNotCompletelyDownloaded()) {
markAsNotDownloaded()

val pageList = fetchPageList()

updateDatabasePages(pageList)
}

return asDataClass()
}

private fun asDataClass() = ChapterTable.toDataClass(chapterEntry)

var chapterEntry: ResultRow = freshChapterEntry()

private fun freshChapterEntry() = transaction {
ChapterTable.select {
(ChapterTable.sourceOrder eq chapterIndex) and (ChapterTable.manga eq mangaId)
}.first()
}

private suspend fun fetchPageList(): List<Page> {
val mangaEntry = transaction { MangaTable.select { MangaTable.id eq mangaId }.first() }
val source = getCatalogueSourceOrStub(mangaEntry[MangaTable.sourceReference])

return source.fetchPageList(
SChapter.create().apply {
url = chapterEntry[ChapterTable.url]
name = chapterEntry[ChapterTable.name]
}
).awaitSingle()
}

private fun markAsNotDownloaded() {
// chapter may be downloaded but if we are here, then images might be deleted and database data be false
transaction {
ChapterTable.update({ (ChapterTable.sourceOrder eq chapterIndex) and (ChapterTable.manga eq mangaId) }) {
it[isDownloaded] = false
}
}
}

private fun updateDatabasePages(pageList: List<Page>) {
val chapterId = chapterEntry[ChapterTable.id].value
val chapterIndex = chapterEntry[ChapterTable.sourceOrder]
val mangaId = chapterEntry[ChapterTable.manga].value

transaction {
pageList.forEach { page ->
val pageEntry = transaction {
PageTable.select { (PageTable.chapter eq chapterId) and (PageTable.index eq page.index) }
.firstOrNull()
}
if (pageEntry == null) {
PageTable.insert {
it[index] = page.index
it[url] = page.url
it[imageUrl] = page.imageUrl
it[chapter] = chapterId
}
} else {
PageTable.update({ (PageTable.chapter eq chapterId) and (PageTable.index eq page.index) }) {
it[url] = page.url
it[imageUrl] = page.imageUrl
}
}
}
}

updatePageCount(pageList, mangaId, chapterIndex)

// chapter was updated
chapterEntry = freshChapterEntry()
}

private fun updatePageCount(
pageList: List<Page>,
mangaId: Int,
chapterIndex: Int
) {
val pageCount = pageList.count()

transaction {
ChapterTable.update({ (ChapterTable.manga eq mangaId) and (ChapterTable.sourceOrder eq chapterIndex) }) {
it[ChapterTable.pageCount] = pageCount
}
}
}

private fun isNotCompletelyDownloaded(): Boolean {
return !(chapterEntry[ChapterTable.isDownloaded] && firstPageExists())
}

private fun firstPageExists(): Boolean {
val chapterId = chapterEntry[ChapterTable.id].value

val chapterDir = getChapterDir(mangaId, chapterId)

println(chapterDir)
println(getPageName(0))

return ImageResponse.findFileNameStartingWith(
chapterDir,
getPageName(0)
) != null
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import mu.KotlinLogging
import org.jetbrains.exposed.sql.and
import org.jetbrains.exposed.sql.transactions.transaction
import org.jetbrains.exposed.sql.update
import suwayomi.tachidesk.manga.impl.Chapter.getChapter
import suwayomi.tachidesk.manga.impl.Page.getPageImage
import suwayomi.tachidesk.manga.impl.chapter.getChapterDownloadReady
import suwayomi.tachidesk.manga.impl.download.model.DownloadChapter
import suwayomi.tachidesk.manga.impl.download.model.DownloadState.Downloading
import suwayomi.tachidesk.manga.impl.download.model.DownloadState.Error
Expand Down Expand Up @@ -47,7 +47,7 @@ class Downloader(private val downloadQueue: CopyOnWriteArrayList<DownloadChapter
download.state = Downloading
step()

download.chapter = runBlocking { getChapter(download.chapterIndex, download.mangaId) }
download.chapter = runBlocking { getChapterDownloadReady(download.chapterIndex, download.mangaId) }
step()

val pageCount = download.chapter.pageCount
Expand Down

0 comments on commit efff68c

Please sign in to comment.