Compare commits

...

4 Commits

Author SHA1 Message Date
Syer10
612768faeb Release v2.3.2223 2026-06-30 15:17:18 -04:00
Syer10
9a1745b626 [skip ci] Add changelog for bind existing track 2026-06-30 14:53:58 -04:00
schroda
323d58717e Add mutation to bind existing track record (#2045)
Makes it possible to copy a bound track record to another manga.
This is necessary during a migration to prevent spamming the actual tracker and causing 429 errors

closes #2033
2026-06-29 14:59:53 -04:00
Mitchell Syer
4d7b7617a9 Fix backup corruption with new extension lib (#2146)
* Fix backup corruption with new extension lib

* Fix missing chapter memo backup
2026-06-29 14:52:37 -04:00
7 changed files with 108 additions and 8 deletions

View File

@@ -42,7 +42,7 @@ body:
label: Suwayomi-Server version
description: You can find your Suwayomi-Server version in **More → About**.
placeholder: |
Example: "v2.2.2100"
Example: "v2.3.2223"
validations:
required: true

View File

@@ -6,10 +6,33 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
## [Unreleased] (Preview)
### Added
- .
### Changed
- .
### Fixed
- .
## [v2.3.2223] + [WebUI: v20260509.01] - 2026-06-30
### Major Changes
#### Added [SyncYomi](https://github.com/syncyomi/syncyomi) support
This allows you to sync your server manga with other Mihon-based forks! As long as the fork supports SyncYomi it can be sync with!
#### Support Extension API v1.6
This update allows Suwayomi to load and use v1.6 extensions, it is a minor improvement over the existing 1.4 extension API that cleans up much of what we had! It is the basis of future extension APIs that will allow for further development.
> [!WARNING]
> Please back up your extension repos, because of the new extension stores system you may lose them in the update process and may need to re-add them.
### Added
- (**Sync**) Added [SyncYomi](https://github.com/syncyomi/syncyomi) support
- (**OPDS**) Add option to skip chapter metadata feed providing direct stream/download links
- (**Extension/API**) Support Extensions API v1.6
- (**Tracker/API**) Add mutation to bind existing track record
### Changed
- (**Database/H2**) Use the latest H2 database engine
@@ -426,6 +449,7 @@ Huge thanks to @martinek who pulled the most of the weight this release!
<!-- WEBUI LINKS -->
[WebUI: v20260509.01]: https://github.com/Suwayomi/Suwayomi-WebUI/blob/master/CHANGELOG.md#2026050901-r3147---2026-05-09
[WebUI: v20260508.01]: https://github.com/Suwayomi/Suwayomi-WebUI/blob/master/CHANGELOG.md#2026050801-r3136---2026-05-08
[WebUI: v20251230.01]: https://github.com/Suwayomi/Suwayomi-WebUI/blob/master/CHANGELOG.md#2025123001-r2937---2025-12-30
[WebUI: v20250801.01]: https://github.com/Suwayomi/Suwayomi-WebUI/blob/master/CHANGELOG.md#2025080101-r2717---2025-08-01
@@ -452,7 +476,8 @@ Huge thanks to @martinek who pulled the most of the weight this release!
<!-- SERVER LINKS -->
[unreleased]: https://github.com/suwayomi/suwayomi-server/compare/v2.2.2100...HEAD
[unreleased]: https://github.com/suwayomi/suwayomi-server/compare/v2.3.2223...HEAD
[v2.3.2223]: https://github.com/suwayomi/suwayomi-server/compare/v2.1.2100...v2.3.2223
[v2.2.2100]: https://github.com/suwayomi/suwayomi-server/compare/v2.1.1867...v2.2.2100
[v2.1.1867]: https://github.com/suwayomi/suwayomi-server/compare/v2.0.1727...v2.1.1867
[v2.0.1727]: https://github.com/suwayomi/suwayomi-server/compare/v1.1.1...v2.0.1727

View File

@@ -10,9 +10,9 @@ import java.io.BufferedReader
const val MainClass = "suwayomi.tachidesk.MainKt"
// should be bumped with each stable release
val getTachideskVersion = { "v2.2.${getCommitCount()}" }
val getTachideskVersion = { "v2.3.${getCommitCount()}" }
val webUIRevisionTag = "r3136"
val webUIRevisionTag = "r3147"
val webviewJbrRelease = "jbr-release-25.0.3b508.4"

View File

@@ -148,6 +148,36 @@ class TrackMutation {
}
}
data class BindTrackRecordInput(
val clientMutationId: String? = null,
val mangaId: Int,
val trackRecordId: Int,
)
data class BindTrackRecordPayload(
val clientMutationId: String?,
val trackRecord: TrackRecordType,
)
@RequireAuth
fun bindTrackRecord(input: BindTrackRecordInput): CompletableFuture<BindTrackRecordPayload?> {
val (clientMutationId, mangaId, trackRecordId) = input
return future {
val boundTrackRecordId = Track.bindTrackRecord(mangaId, trackRecordId)
val trackRecord =
transaction {
TrackRecordTable.selectAll().where { TrackRecordTable.id eq boundTrackRecordId }.first()
}
BindTrackRecordPayload(
clientMutationId,
TrackRecordType(trackRecord),
)
}
}
data class FetchTrackInput(
val clientMutationId: String? = null,
val recordId: Int,

View File

@@ -238,6 +238,7 @@ object Manga {
it[MangaTable.lastFetchedAt] = Instant.now().epochSecond
it[MangaTable.updateStrategy] = sManga.update_strategy.name
it[MangaTable.memo] = Json.encodeToString(sManga.memo)
}
}

View File

@@ -8,7 +8,6 @@ package suwayomi.tachidesk.manga.impl.backup.proto.handlers
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import eu.kanade.tachiyomi.source.model.UpdateStrategy
import kotlinx.serialization.json.Json
import org.jetbrains.exposed.v1.core.ResultRow
import org.jetbrains.exposed.v1.core.SortOrder
import org.jetbrains.exposed.v1.core.and
@@ -78,7 +77,7 @@ object BackupMangaHandler {
lastModifiedAt = mangaRow[MangaTable.lastModifiedAt],
version = mangaRow[MangaTable.version],
initialized = mangaRow[MangaTable.initialized],
memo = Json.encodeToString(mangaRow[MangaTable.memo]).encodeToByteArray(),
memo = mangaRow[MangaTable.memo].encodeToByteArray(),
)
val mangaId = mangaRow[MangaTable.id].value
@@ -116,6 +115,7 @@ object BackupMangaHandler {
sourceOrder = chapters.size - it[ChapterTable.sourceOrder],
lastModifiedAt = it[ChapterTable.lastModifiedAt],
version = it[ChapterTable.version],
memo = it[ChapterTable.memo].encodeToByteArray(),
).apply {
if (flags.includeClientData) {
this.meta = chapterToMeta[it[ChapterTable.id].value] ?: emptyMap()

View File

@@ -222,6 +222,48 @@ object Track {
}
}
fun bindTrackRecord(
mangaId: Int,
trackRecordId: Int,
): Int {
val (trackRecord, existingTrackRecord) =
transaction {
val trackRecord =
TrackRecordTable
.selectAll()
.where {
(TrackRecordTable.id eq trackRecordId)
}.first()
.toTrackRecordDataClass()
val existingTrackRecord =
TrackRecordTable
.selectAll()
.where {
(TrackRecordTable.mangaId eq mangaId) and (TrackRecordTable.trackerId eq trackRecord.trackerId)
}.firstOrNull()
?.toTrackRecordDataClass()
trackRecord to existingTrackRecord
}
val isAlreadyBoundToManga = trackRecord.mangaId == mangaId
if (isAlreadyBoundToManga) {
return trackRecordId
}
val hasRecordForTracker = existingTrackRecord != null
if (hasRecordForTracker) {
val updatedTrack = trackRecord.copy(id = existingTrackRecord.id, mangaId = mangaId).toTrack()
return updateTrackRecord(updatedTrack)
}
val newTrack = trackRecord.copy(mangaId = mangaId).toTrack()
return insertTrackRecord(newTrack)
}
suspend fun refresh(recordId: Int) {
val recordDb =
transaction {
@@ -423,9 +465,9 @@ object Track {
}
}
fun updateTrackRecord(track: Track) = updateTrackRecords(listOf(track))
fun updateTrackRecord(track: Track): Int = updateTrackRecords(listOf(track)).first()
fun updateTrackRecords(tracks: List<Track>) =
fun updateTrackRecords(tracks: List<Track>): List<Int> =
transaction {
if (tracks.isNotEmpty()) {
BatchUpdateStatement(TrackRecordTable)
@@ -447,6 +489,8 @@ object Track {
}.toExecutable()
.execute(this@transaction)
}
tracks.map { it.id!! }
}
fun insertTrackRecord(track: Track): Int = insertTrackRecords(listOf(track)).first()