mirror of
https://github.com/tachiyomiorg/tachiyomi-extensions-inspector.git
synced 2024-12-27 01:01:48 +01:00
finishing touches of download backend, done @jipfr's requests
This commit is contained in:
parent
b56045e984
commit
d249867c4c
@ -0,0 +1,24 @@
|
|||||||
|
package suwayomi.server.database.migration
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 org.jetbrains.exposed.sql.transactions.TransactionManager
|
||||||
|
import org.jetbrains.exposed.sql.vendors.currentDialect
|
||||||
|
import suwayomi.server.database.migration.lib.Migration
|
||||||
|
|
||||||
|
@Suppress("ClassName", "unused")
|
||||||
|
class M0007_ChapterIsDownloaded : Migration() {
|
||||||
|
/** this migration added IS_DOWNLOADED to CHAPTER */
|
||||||
|
override fun run() {
|
||||||
|
with(TransactionManager.current()) {
|
||||||
|
exec("ALTER TABLE CHAPTER ADD COLUMN IS_DOWNLOADED BOOLEAN DEFAULT FALSE")
|
||||||
|
commit()
|
||||||
|
currentDialect.resetCaches()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
package suwayomi.server.database.migration
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 org.jetbrains.exposed.sql.transactions.TransactionManager
|
||||||
|
import org.jetbrains.exposed.sql.vendors.currentDialect
|
||||||
|
import suwayomi.server.database.migration.lib.Migration
|
||||||
|
|
||||||
|
@Suppress("ClassName", "unused")
|
||||||
|
class M0008_ChapterPageCount : Migration() {
|
||||||
|
/** this migration added PAGE_COUNT to CHAPTER */
|
||||||
|
override fun run() {
|
||||||
|
with(TransactionManager.current()) {
|
||||||
|
exec("ALTER TABLE CHAPTER ADD COLUMN PAGE_COUNT INT DEFAULT -1")
|
||||||
|
commit()
|
||||||
|
currentDialect.resetCaches()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package suwayomi.server.database.migration
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 org.jetbrains.exposed.sql.transactions.TransactionManager
|
||||||
|
import org.jetbrains.exposed.sql.vendors.currentDialect
|
||||||
|
import suwayomi.server.database.migration.lib.Migration
|
||||||
|
|
||||||
|
@Suppress("ClassName", "unused")
|
||||||
|
class M0009_ChapterLastReadAt : Migration() {
|
||||||
|
/** this migration added PAGE_COUNT to CHAPTER */
|
||||||
|
override fun run() {
|
||||||
|
with(TransactionManager.current()) {
|
||||||
|
// BIGINT == Long
|
||||||
|
exec("ALTER TABLE CHAPTER ADD COLUMN LAST_READ_AT BIGINT DEFAULT 0")
|
||||||
|
commit()
|
||||||
|
currentDialect.resetCaches()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -24,6 +24,7 @@ import suwayomi.tachidesk.model.table.ChapterTable
|
|||||||
import suwayomi.tachidesk.model.table.MangaTable
|
import suwayomi.tachidesk.model.table.MangaTable
|
||||||
import suwayomi.tachidesk.model.table.PageTable
|
import suwayomi.tachidesk.model.table.PageTable
|
||||||
import suwayomi.tachidesk.model.table.toDataClass
|
import suwayomi.tachidesk.model.table.toDataClass
|
||||||
|
import java.time.Instant
|
||||||
|
|
||||||
object Chapter {
|
object Chapter {
|
||||||
/** get chapter list when showing a manga */
|
/** get chapter list when showing a manga */
|
||||||
@ -122,9 +123,14 @@ object Chapter {
|
|||||||
dbChapter[ChapterTable.isRead],
|
dbChapter[ChapterTable.isRead],
|
||||||
dbChapter[ChapterTable.isBookmarked],
|
dbChapter[ChapterTable.isBookmarked],
|
||||||
dbChapter[ChapterTable.lastPageRead],
|
dbChapter[ChapterTable.lastPageRead],
|
||||||
|
dbChapter[ChapterTable.lastReadAt],
|
||||||
|
|
||||||
chapterCount - index,
|
chapterCount - index,
|
||||||
chapterList.size
|
dbChapter[ChapterTable.isDownloaded],
|
||||||
|
|
||||||
|
dbChapter[ChapterTable.pageCount],
|
||||||
|
|
||||||
|
chapterList.size,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -136,54 +142,68 @@ object Chapter {
|
|||||||
(ChapterTable.chapterIndex eq chapterIndex) and (ChapterTable.manga eq mangaId)
|
(ChapterTable.chapterIndex eq chapterIndex) and (ChapterTable.manga eq mangaId)
|
||||||
}.first()
|
}.first()
|
||||||
}
|
}
|
||||||
val mangaEntry = transaction { MangaTable.select { MangaTable.id eq mangaId }.first() }
|
|
||||||
val source = getHttpSource(mangaEntry[MangaTable.sourceReference])
|
|
||||||
|
|
||||||
val pageList = source.fetchPageList(
|
return if (!chapterEntry[ChapterTable.isDownloaded]) {
|
||||||
SChapter.create().apply {
|
val mangaEntry = transaction { MangaTable.select { MangaTable.id eq mangaId }.first() }
|
||||||
url = chapterEntry[ChapterTable.url]
|
val source = getHttpSource(mangaEntry[MangaTable.sourceReference])
|
||||||
name = chapterEntry[ChapterTable.name]
|
|
||||||
}
|
|
||||||
).awaitSingle()
|
|
||||||
|
|
||||||
val chapterId = chapterEntry[ChapterTable.id].value
|
val pageList = source.fetchPageList(
|
||||||
val chapterCount = transaction { ChapterTable.select { ChapterTable.manga eq mangaId }.count() }
|
SChapter.create().apply {
|
||||||
|
url = chapterEntry[ChapterTable.url]
|
||||||
|
name = chapterEntry[ChapterTable.name]
|
||||||
|
}
|
||||||
|
).awaitSingle()
|
||||||
|
|
||||||
// update page list for this chapter
|
val chapterId = chapterEntry[ChapterTable.id].value
|
||||||
transaction {
|
val chapterCount = transaction { ChapterTable.select { ChapterTable.manga eq mangaId }.count() }
|
||||||
pageList.forEach { page ->
|
|
||||||
val pageEntry = transaction { PageTable.select { (PageTable.chapter eq chapterId) and (PageTable.index eq page.index) }.firstOrNull() }
|
// update page list for this chapter
|
||||||
if (pageEntry == null) {
|
transaction {
|
||||||
PageTable.insert {
|
pageList.forEach { page ->
|
||||||
it[index] = page.index
|
val pageEntry = transaction { PageTable.select { (PageTable.chapter eq chapterId) and (PageTable.index eq page.index) }.firstOrNull() }
|
||||||
it[url] = page.url
|
if (pageEntry == null) {
|
||||||
it[imageUrl] = page.imageUrl
|
PageTable.insert {
|
||||||
it[chapter] = chapterId
|
it[index] = page.index
|
||||||
}
|
it[url] = page.url
|
||||||
} else {
|
it[imageUrl] = page.imageUrl
|
||||||
PageTable.update({ (PageTable.chapter eq chapterId) and (PageTable.index eq page.index) }) {
|
it[chapter] = chapterId
|
||||||
it[url] = page.url
|
}
|
||||||
it[imageUrl] = page.imageUrl
|
} 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.chapterIndex 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.chapterIndex],
|
||||||
|
chapterEntry[ChapterTable.isDownloaded],
|
||||||
|
pageCount,
|
||||||
|
chapterCount.toInt()
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
ChapterTable.toDataClass(chapterEntry)
|
||||||
}
|
}
|
||||||
|
|
||||||
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.chapterIndex],
|
|
||||||
chapterCount.toInt(),
|
|
||||||
pageList.count()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun modifyChapter(mangaId: Int, chapterIndex: Int, isRead: Boolean?, isBookmarked: Boolean?, markPrevRead: Boolean?, lastPageRead: Int?) {
|
fun modifyChapter(mangaId: Int, chapterIndex: Int, isRead: Boolean?, isBookmarked: Boolean?, markPrevRead: Boolean?, lastPageRead: Int?) {
|
||||||
@ -198,6 +218,7 @@ object Chapter {
|
|||||||
}
|
}
|
||||||
lastPageRead?.also {
|
lastPageRead?.also {
|
||||||
update[ChapterTable.lastPageRead] = it
|
update[ChapterTable.lastPageRead] = it
|
||||||
|
update[ChapterTable.lastReadAt] = Instant.now().epochSecond
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,9 @@ package suwayomi.tachidesk.impl.download
|
|||||||
* 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 kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import org.jetbrains.exposed.sql.and
|
||||||
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
|
import org.jetbrains.exposed.sql.update
|
||||||
import suwayomi.tachidesk.impl.Chapter.getChapter
|
import suwayomi.tachidesk.impl.Chapter.getChapter
|
||||||
import suwayomi.tachidesk.impl.Page.getPageImage
|
import suwayomi.tachidesk.impl.Page.getPageImage
|
||||||
import suwayomi.tachidesk.impl.download.model.DownloadChapter
|
import suwayomi.tachidesk.impl.download.model.DownloadChapter
|
||||||
@ -15,6 +18,7 @@ import suwayomi.tachidesk.impl.download.model.DownloadState.Downloading
|
|||||||
import suwayomi.tachidesk.impl.download.model.DownloadState.Error
|
import suwayomi.tachidesk.impl.download.model.DownloadState.Error
|
||||||
import suwayomi.tachidesk.impl.download.model.DownloadState.Finished
|
import suwayomi.tachidesk.impl.download.model.DownloadState.Finished
|
||||||
import suwayomi.tachidesk.impl.download.model.DownloadState.Queued
|
import suwayomi.tachidesk.impl.download.model.DownloadState.Queued
|
||||||
|
import suwayomi.tachidesk.model.table.ChapterTable
|
||||||
import java.util.concurrent.CopyOnWriteArrayList
|
import java.util.concurrent.CopyOnWriteArrayList
|
||||||
|
|
||||||
class Downloader(private val downloadQueue: CopyOnWriteArrayList<DownloadChapter>, val notifier: () -> Unit) : Thread() {
|
class Downloader(private val downloadQueue: CopyOnWriteArrayList<DownloadChapter>, val notifier: () -> Unit) : Thread() {
|
||||||
@ -49,6 +53,11 @@ class Downloader(private val downloadQueue: CopyOnWriteArrayList<DownloadChapter
|
|||||||
step()
|
step()
|
||||||
}
|
}
|
||||||
download.state = Finished
|
download.state = Finished
|
||||||
|
transaction {
|
||||||
|
ChapterTable.update({ (ChapterTable.manga eq download.mangaId) and (ChapterTable.chapterIndex eq download.chapterIndex) }) {
|
||||||
|
it[isDownloaded] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
step()
|
step()
|
||||||
} catch (e: DownloadShouldStopException) {
|
} catch (e: DownloadShouldStopException) {
|
||||||
println("Downloader was stopped")
|
println("Downloader was stopped")
|
||||||
|
@ -24,12 +24,19 @@ data class ChapterDataClass(
|
|||||||
/** last read page, zero means not read/no data */
|
/** last read page, zero means not read/no data */
|
||||||
val lastPageRead: Int,
|
val lastPageRead: Int,
|
||||||
|
|
||||||
|
/** last read page, zero means not read/no data */
|
||||||
|
val lastReadAt: Long,
|
||||||
|
|
||||||
/** this chapter's index, starts with 1 */
|
/** this chapter's index, starts with 1 */
|
||||||
val index: Int,
|
val index: Int,
|
||||||
|
|
||||||
|
/** is chapter downloaded */
|
||||||
|
val downloaded: Boolean,
|
||||||
|
|
||||||
|
/** used to construct pages in the front-end */
|
||||||
|
val pageCount: Int = -1,
|
||||||
|
|
||||||
/** total chapter count, used to calculate if there's a next and prev chapter */
|
/** total chapter count, used to calculate if there's a next and prev chapter */
|
||||||
val chapterCount: Int? = null,
|
val chapterCount: Int? = null,
|
||||||
|
|
||||||
/** used to construct pages in the front-end */
|
|
||||||
val pageCount: Int? = null,
|
|
||||||
)
|
)
|
||||||
|
@ -9,6 +9,8 @@ package suwayomi.tachidesk.model.table
|
|||||||
|
|
||||||
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
|
||||||
|
import org.jetbrains.exposed.sql.select
|
||||||
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
import suwayomi.tachidesk.model.dataclass.ChapterDataClass
|
import suwayomi.tachidesk.model.dataclass.ChapterDataClass
|
||||||
|
|
||||||
object ChapterTable : IntIdTable() {
|
object ChapterTable : IntIdTable() {
|
||||||
@ -21,10 +23,15 @@ object ChapterTable : IntIdTable() {
|
|||||||
val isRead = bool("read").default(false)
|
val isRead = bool("read").default(false)
|
||||||
val isBookmarked = bool("bookmark").default(false)
|
val isBookmarked = bool("bookmark").default(false)
|
||||||
val lastPageRead = integer("last_page_read").default(0)
|
val lastPageRead = integer("last_page_read").default(0)
|
||||||
|
val lastReadAt = long("last_read_at").default(0)
|
||||||
|
|
||||||
// index is reserved by a function
|
// index is reserved by a function
|
||||||
val chapterIndex = integer("index")
|
val chapterIndex = integer("index")
|
||||||
|
|
||||||
|
val isDownloaded = bool("is_downloaded").default(false)
|
||||||
|
|
||||||
|
val pageCount = integer("page_count").default(-1)
|
||||||
|
|
||||||
val manga = reference("manga", MangaTable)
|
val manga = reference("manga", MangaTable)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,5 +46,9 @@ fun ChapterTable.toDataClass(chapterEntry: ResultRow) =
|
|||||||
chapterEntry[isRead],
|
chapterEntry[isRead],
|
||||||
chapterEntry[isBookmarked],
|
chapterEntry[isBookmarked],
|
||||||
chapterEntry[lastPageRead],
|
chapterEntry[lastPageRead],
|
||||||
|
chapterEntry[lastReadAt],
|
||||||
chapterEntry[chapterIndex],
|
chapterEntry[chapterIndex],
|
||||||
|
chapterEntry[isDownloaded],
|
||||||
|
chapterEntry[pageCount],
|
||||||
|
transaction { ChapterTable.select { ChapterTable.manga eq chapterEntry[manga].value }.count().toInt() },
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user