Compare commits

..

42 Commits

Author SHA1 Message Date
Syer10
e4440ad502 Lint 2026-06-27 13:03:53 -04:00
Syer10
e71c94547d Add a index to extesnion table store url 2026-06-27 12:59:16 -04:00
Syer10
84a1789850 Review fixes 2026-06-27 12:44:51 -04:00
Syer10
70a027f6f0 Lint 2026-06-26 11:13:55 -04:00
Syer10
650c075723 Optimize imports 2026-06-26 11:09:39 -04:00
Syer10
a69e29d1a5 Lint 2026-06-26 11:07:08 -04:00
Syer10
eec0951a75 Fix latest Mihon Extension Lib 2026-06-26 11:03:33 -04:00
Syer10
4ace76f508 Update to latest Mihon extension lib 2026-06-23 17:07:25 -04:00
Syer10
cd91b6e6ef Include OkHttp ZSTD 2026-06-22 11:16:22 -04:00
Mitchell Syer
f748bc7f6d Merge branch 'master' into extensions_1.6 2026-06-18 15:02:54 -04:00
Syer10
11ff4bb280 Remove replaceWith and add specific description for GQL APIs 2026-06-18 14:58:19 -04:00
Mitchell Syer
388586f23b Update server/server-config/src/main/kotlin/suwayomi/tachidesk/server/ServerConfig.kt
Co-authored-by: Constantin Piber <59023762+cpiber@users.noreply.github.com>
2026-06-18 14:55:29 -04:00
Syer10
b8ffbebc76 Optimize Imports 2026-06-17 22:39:09 -04:00
Syer10
3048df307d Use syncDbToPrefs in ExtensionStoreMutation 2026-06-17 22:38:46 -04:00
Syer10
3b3770cb3d Exclude ServerConfig.extensionStores from GraphQL 2026-06-17 21:38:30 -04:00
Syer10
9667aeba18 Use a single version of ContentRating 2026-06-17 21:29:14 -04:00
Syer10
6c8a024b0f Add ExtenionStores to the fetchExtensions result since its possible for the stores to change. 2026-06-17 21:17:55 -04:00
Syer10
5b2613dad3 Lint 2026-06-17 21:15:44 -04:00
Constantin Piber
396cfa734a fix: re-sync (#2121) 2026-06-17 17:22:54 -04:00
Syer10
a1fdf6d77a Improve extension store sync 2026-06-17 16:12:51 -04:00
Syer10
07ae17105b Add ContentRatingFilter 2026-06-17 16:02:14 -04:00
Syer10
b8772f60bf Optimize import fixes 2026-06-17 14:49:57 -04:00
Syer10
733b9c9919 Proper extension store queries 2026-06-17 14:47:28 -04:00
Syer10
0b0c056bcb Optimize imports and fix unchecked cast warning 2026-06-17 14:13:57 -04:00
Syer10
aff95bfc37 Lint 2026-06-17 14:06:06 -04:00
Syer10
00bc3e39b6 Lint 2026-06-17 14:04:02 -04:00
Syer10
e9c2cc49a6 Fix SearchTest 2026-06-17 13:57:58 -04:00
Syer10
ea310ba54b No magic numbers for ContentRating, improves safety for future versions of extension api 2026-06-17 13:53:54 -04:00
Syer10
72347f45cc Simplify isNsfw in SourceType 2026-06-17 13:44:02 -04:00
Syer10
1e73e526c6 Simplify ContentRating in Source.kt 2026-06-17 13:43:02 -04:00
Syer10
8fd0fdba08 Simplify deprecated isNsfw in SourceQuery 2026-06-17 13:42:15 -04:00
Syer10
4b61d375ed Fixes 2026-06-17 13:39:53 -04:00
Syer10
3cf4cf6cf8 Improve Fetch Extension Store 2026-06-17 13:31:31 -04:00
Mitchell Syer
74ade8a3a3 Update docs/Configuring-Suwayomi‐Server.md
Co-authored-by: Constantin Piber <59023762+cpiber@users.noreply.github.com>
2026-06-17 13:26:09 -04:00
Syer10
3bb2e4329e Use EMPTY JsonObject 2026-06-17 13:25:31 -04:00
Syer10
33ec15c136 Simplify fetching manga and chapters 2026-06-17 13:24:38 -04:00
Syer10
3a78453a02 Docs 2026-06-16 23:00:06 -04:00
Syer10
b7c259a4cb Test build fix 2026-06-16 22:55:15 -04:00
Syer10
41ef220a0b Implement extension store 2026-06-16 22:38:03 -04:00
Syer10
85fe9802e2 Minor fixes 2026-06-15 20:45:43 -04:00
Syer10
676aed14c0 Changelog 2026-06-15 20:13:18 -04:00
Syer10
ceac5f74c4 Non-Extension Index changes for 1.6 2026-06-15 20:11:55 -04:00
43 changed files with 178 additions and 328 deletions

View File

@@ -42,7 +42,7 @@ body:
label: Suwayomi-Server version label: Suwayomi-Server version
description: You can find your Suwayomi-Server version in **More → About**. description: You can find your Suwayomi-Server version in **More → About**.
placeholder: | placeholder: |
Example: "v2.3.2226" Example: "v2.2.2100"
validations: validations:
required: true required: true
@@ -143,13 +143,11 @@ body:
options: options:
- label: I have searched the existing issues and this is a new ticket, **NOT** a duplicate or related to another open or closed issue. - label: I have searched the existing issues and this is a new ticket, **NOT** a duplicate or related to another open or closed issue.
required: true required: true
- label: I have checked the ongoing preview changelog of **[Suwayomi-WebUI](https://github.com/Suwayomi/Suwayomi-WebUI/blob/master/CHANGELOG.md)** and **[Suwayomi-Server](https://github.com/Suwayomi/Suwayomi-Server/blob/master/CHANGELOG.md)** and this bug has **NOT** been listed as fixed
required: true
- label: I have written a short but informative title (ideally less than ~100 characters). - label: I have written a short but informative title (ideally less than ~100 characters).
required: true required: true
- label: I have tried the troubleshooting guide described in [README.md](https://github.com/Suwayomi/Suwayomi-Server?tab=readme-ov-file#troubleshooting-and-support) - label: I have tried the troubleshooting guide described in [README.md](https://github.com/Suwayomi/Suwayomi-Server?tab=readme-ov-file#troubleshooting-and-support)
required: true required: true
- label: I have updated the (**[Suwayomi-WebUI](https://github.com/suwayomi/suwayomi-webui/releases/latest)** and **[Suwayomi-Server](https://github.com/suwayomi/suwayomi-server/releases/latest)**) to the latest versions - label: I have updated to the **[latest version](https://github.com/suwayomi/suwayomi-server/releases/latest)**.
required: true required: true
- label: I have filled out all of the requested information in this form, including specific version numbers. - label: I have filled out all of the requested information in this form, including specific version numbers.
required: true required: true

View File

@@ -31,7 +31,7 @@ body:
required: true required: true
- label: I have written a short but informative title (ideally less than ~100 characters). - label: I have written a short but informative title (ideally less than ~100 characters).
required: true required: true
- label: I have updated the (**[Suwayomi-WebUI](https://github.com/suwayomi/suwayomi-webui/releases/latest)** and **[Suwayomi-Server](https://github.com/suwayomi/suwayomi-server/releases/latest)**) to the latest versions - label: I have updated to the **[latest version](https://github.com/suwayomi/suwayomi-server/releases/latest)**.
required: true required: true
- label: I have filled out all of the requested information in this form, including specific version numbers. - label: I have filled out all of the requested information in this form, including specific version numbers.
required: true required: true

View File

@@ -6,41 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
## [Unreleased] (Preview) ## [Unreleased] (Preview)
### Added
- .
### Changed
- .
### Fixed
- .
## [v2.3.2226] - 2026-07-01
### Fixed
- (**Extension/API**) Fix GQL handling of extensions without an extension store
- (**Build/Bundler**) Fix build continuing if errors happen
## [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.
This also allows us to move to Mihon's Extension Store system and replace our Extension Repo system. Old Extension Repos are still compatible and will be automatically migrated if they move to the Extension Store system.
> [!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 ### Added
- (**Sync**) Added [SyncYomi](https://github.com/syncyomi/syncyomi) support - (**Sync**) Added [SyncYomi](https://github.com/syncyomi/syncyomi) support
- (**OPDS**) Add option to skip chapter metadata feed providing direct stream/download links - (**OPDS**) Add option to skip chapter metadata feed providing direct stream/download links
- (**Extension/API**) Support Extensions API v1.6 - (**Extension/API**) Support Extensions API v1.6
- (**Tracker/API**) Add mutation to bind existing track record
### Changed ### Changed
- (**Database/H2**) Use the latest H2 database engine - (**Database/H2**) Use the latest H2 database engine
@@ -457,7 +426,6 @@ Huge thanks to @martinek who pulled the most of the weight this release!
<!-- WEBUI LINKS --> <!-- 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: 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: 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 [WebUI: v20250801.01]: https://github.com/Suwayomi/Suwayomi-WebUI/blob/master/CHANGELOG.md#2025080101-r2717---2025-08-01
@@ -484,9 +452,7 @@ Huge thanks to @martinek who pulled the most of the weight this release!
<!-- SERVER LINKS --> <!-- SERVER LINKS -->
[unreleased]: https://github.com/suwayomi/suwayomi-server/compare/v2.3.2226...HEAD [unreleased]: https://github.com/suwayomi/suwayomi-server/compare/v2.2.2100...HEAD
[v2.3.2226]: https://github.com/suwayomi/suwayomi-server/compare/v2.3.2223...v2.3.2226
[v2.3.2223]: https://github.com/suwayomi/suwayomi-server/compare/v2.2.2100...v2.3.2223
[v2.2.2100]: https://github.com/suwayomi/suwayomi-server/compare/v2.1.1867...v2.2.2100 [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.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 [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" const val MainClass = "suwayomi.tachidesk.MainKt"
// should be bumped with each stable release // should be bumped with each stable release
val getTachideskVersion = { "v2.3.${getCommitCount()}" } val getTachideskVersion = { "v2.2.${getCommitCount()}" }
val webUIRevisionTag = "r3147" val webUIRevisionTag = "r3136"
val webviewJbrRelease = "jbr-release-25.0.3b508.4" val webviewJbrRelease = "jbr-release-25.0.3b508.4"

View File

@@ -12,7 +12,7 @@ dex2jar = "2.4.37"
polyglot = "25.0.3" polyglot = "25.0.3"
settings = "1.3.0" settings = "1.3.0"
twelvemonkeys = "3.13.1" twelvemonkeys = "3.13.1"
graphqlkotlin = "10.1.2" graphqlkotlin = "10.0.0"
xmlserialization = "0.91.3" xmlserialization = "0.91.3"
ktlint = "1.8.0" ktlint = "1.8.0"
koin = "4.2.2" koin = "4.2.2"

View File

@@ -26,7 +26,7 @@ main() {
set -- "${POSITIONAL_ARGS[@]}" set -- "${POSITIONAL_ARGS[@]}"
OS="$1" OS="$1"
JAR="$(ls server/build/*.jar | tail -n1)" || error $LINENO "No JAR found in server/build/" 1 JAR="$(ls server/build/*.jar | tail -n1)"
RELEASE_NAME="$(echo "${JAR%.*}" | xargs basename)-$OS" RELEASE_NAME="$(echo "${JAR%.*}" | xargs basename)-$OS"
RELEASE_VERSION=$(echo "$JAR" | grep -oP "v\K[0-9]+\.[0-9]+\.[0-9]+") RELEASE_VERSION=$(echo "$JAR" | grep -oP "v\K[0-9]+\.[0-9]+\.[0-9]+")
#RELEASE_REVISION_NUMBER="$(tmp="${JAR%.*}" && echo "${tmp##*-}" | tr -d r)" #RELEASE_REVISION_NUMBER="$(tmp="${JAR%.*}" && echo "${tmp##*-}" | tr -d r)"
@@ -34,12 +34,12 @@ main() {
# clean temporary directory on function return # clean temporary directory on function return
trap "rm -rf $RELEASE_NAME/" RETURN trap "rm -rf $RELEASE_NAME/" RETURN
mkdir "$RELEASE_NAME/" || error $LINENO "Failed to create release directory" 1 mkdir "$RELEASE_NAME/"
download_launcher download_launcher
if [ ! -f scripts/resources/catch_abort.so ]; then if [ ! -f scripts/resources/catch_abort.so ]; then
gcc -fPIC -shared scripts/resources/catch_abort.c -lpthread -o scripts/resources/catch_abort.so || error $LINENO "Failed to compile catch_abort" 1 gcc -fPIC -shared scripts/resources/catch_abort.c -lpthread -o scripts/resources/catch_abort.so
fi fi
JRE_ZULU="25.34.17_25.0.3" JRE_ZULU="25.34.17_25.0.3"
@@ -67,7 +67,7 @@ main() {
linux-assets) linux-assets)
RELEASE="$RELEASE_NAME.tar.gz" RELEASE="$RELEASE_NAME.tar.gz"
copy_linux_package_assets_to "$RELEASE_NAME/" copy_linux_package_assets_to "$RELEASE_NAME/"
tar -I "gzip -9" -cvf "$RELEASE" "$RELEASE_NAME/" || error $LINENO "Failed to create tar.gz" 1 tar -I "gzip -9" -cvf "$RELEASE" "$RELEASE_NAME/"
move_release_to_output_dir move_release_to_output_dir
;; ;;
linux-x64) linux-x64)
@@ -145,55 +145,52 @@ move_release_to_output_dir() {
if [ -f "$OUTPUT_DIR/$RELEASE" ]; then if [ -f "$OUTPUT_DIR/$RELEASE" ]; then
rm "$OUTPUT_DIR/$RELEASE" rm "$OUTPUT_DIR/$RELEASE"
fi fi
mv "$RELEASE" "$OUTPUT_DIR/" || error $LINENO "Failed to move release to output dir" 1 mv "$RELEASE" "$OUTPUT_DIR/"
} }
download_launcher() { download_launcher() {
LAUNCHER_URL=$(curl -sf "https://api.github.com/repos/Suwayomi/Suwayomi-Launcher/releases/latest" | grep "browser_download_url" | grep ".jar" | head -n 1 | cut -d '"' -f 4) LAUNCHER_URL=$(curl -sf "https://api.github.com/repos/Suwayomi/Suwayomi-Launcher/releases/latest" | grep "browser_download_url" | grep ".jar" | head -n 1 | cut -d '"' -f 4)
if [ -z "$LAUNCHER_URL" ]; then curl -fL "$LAUNCHER_URL" -o "Suwayomi-Launcher.jar"
error $LINENO "Failed to determine launcher URL from GitHub API" 1 mv "Suwayomi-Launcher.jar" "$RELEASE_NAME/Suwayomi-Launcher.jar"
fi
curl -fL "$LAUNCHER_URL" -o "Suwayomi-Launcher.jar" || error $LINENO "Failed to download launcher JAR" 1
mv "Suwayomi-Launcher.jar" "$RELEASE_NAME/Suwayomi-Launcher.jar" || error $LINENO "Failed to move launcher JAR" 1
} }
download_jogamp() { download_jogamp() {
local platform="$1" local platform="$1"
if [ ! -f jogamp-all-platforms.7z ]; then if [ ! -f jogamp-all-platforms.7z ]; then
curl -f "https://jogamp.org/deployment/jogamp-current/archive/jogamp-all-platforms.7z" -o jogamp-all-platforms.7z || error $LINENO "Failed to download jogamp archive" 1 curl -f "https://jogamp.org/deployment/jogamp-current/archive/jogamp-all-platforms.7z" -o jogamp-all-platforms.7z
fi fi
7z x jogamp-all-platforms.7z "jogamp-all-platforms/lib/$platform/" || error $LINENO "Failed to extract jogamp archive" 1 7z x jogamp-all-platforms.7z "jogamp-all-platforms/lib/$platform/"
mkdir -p "$RELEASE_NAME/natives/" mkdir -p "$RELEASE_NAME/natives/"
mv jogamp-all-platforms/lib/* "$RELEASE_NAME/natives/" || error $LINENO "Failed to move natives" 1 mv jogamp-all-platforms/lib/* "$RELEASE_NAME/natives/"
rm -rf jogamp-all-platforms rm -rf jogamp-all-platforms
} }
download_electron() { download_electron() {
if [ ! -f "$ELECTRON" ]; then if [ ! -f "$ELECTRON" ]; then
curl -fL "$ELECTRON_URL" -o "$ELECTRON" || error $LINENO "Failed to download electron" 1 curl -fL "$ELECTRON_URL" -o "$ELECTRON"
fi fi
unzip "$ELECTRON" -d "$RELEASE_NAME/electron/" || error $LINENO "Failed to extract electron" 1 unzip "$ELECTRON" -d "$RELEASE_NAME/electron/"
} }
setup_jre() { setup_jre() {
if [ -d "jre" ]; then if [ -d "jre" ]; then
chmod +x ./jre/bin/java || error $LINENO "Failed to set java executable permission" 1 chmod +x ./jre/bin/java
chmod +x ./jre/lib/jspawnhelper || error $LINENO "Failed to set jspawnhelper executable permission" 1 chmod +x ./jre/lib/jspawnhelper
mv "jre" "$RELEASE_NAME/jre" || error $LINENO "Failed to move jre" 1 mv "jre" "$RELEASE_NAME/jre"
else else
if [ ! -f "$JRE" ]; then if [ ! -f "$JRE" ]; then
curl -fL "$JRE_URL" -o "$JRE" || error $LINENO "Failed to download JRE" 1 curl -fL "$JRE_URL" -o "$JRE"
fi fi
local ext="${JRE##*.}" local ext="${JRE##*.}"
if [ "$ext" = "zip" ]; then if [ "$ext" = "zip" ]; then
unzip "$JRE" || error $LINENO "Failed to extract JRE zip" 1 unzip "$JRE"
else else
tar xvf "$JRE" || error $LINENO "Failed to extract JRE tar" 1 tar xvf "$JRE"
fi fi
mv "$JRE_DIR" "$RELEASE_NAME/jre" || error $LINENO "Failed to move extracted JRE" 1 mv "$JRE_DIR" "$RELEASE_NAME/jre"
fi fi
} }
@@ -201,31 +198,31 @@ copy_linux_package_assets_to() {
local output_dir local output_dir
output_dir="$(readlink -e "$1" || exit 1)" output_dir="$(readlink -e "$1" || exit 1)"
cp "scripts/resources/pkg/suwayomi-server.sh" "$output_dir/" || error $LINENO "Failed to copy server script" 1 cp "scripts/resources/pkg/suwayomi-server.sh" "$output_dir/"
cp "scripts/resources/pkg/suwayomi-server.desktop" "$output_dir/" || error $LINENO "Failed to copy server desktop file" 1 cp "scripts/resources/pkg/suwayomi-server.desktop" "$output_dir/"
cp "scripts/resources/pkg/suwayomi-launcher.sh" "$output_dir/" || error $LINENO "Failed to copy launcher script" 1 cp "scripts/resources/pkg/suwayomi-launcher.sh" "$output_dir/"
cp "scripts/resources/pkg/suwayomi-launcher.desktop" "$output_dir/" || error $LINENO "Failed to copy launcher desktop file" 1 cp "scripts/resources/pkg/suwayomi-launcher.desktop" "$output_dir/"
cp "scripts/resources/pkg/systemd"/* "$output_dir/" || error $LINENO "Failed to copy systemd files" 1 cp "scripts/resources/pkg/systemd"/* "$output_dir/"
cp "server/src/main/resources/icon/faviconlogo-128.png" \ cp "server/src/main/resources/icon/faviconlogo-128.png" \
"$output_dir/suwayomi-server.png" || error $LINENO "Failed to copy icon" 1 "$output_dir/suwayomi-server.png"
} }
make_linux_bundle() { make_linux_bundle() {
mkdir "$RELEASE_NAME/bin" mkdir "$RELEASE_NAME/bin"
cp "$JAR" "$RELEASE_NAME/bin/Suwayomi-Server.jar" || error $LINENO "Failed to copy server jar" 1 cp "$JAR" "$RELEASE_NAME/bin/Suwayomi-Server.jar"
cp "scripts/resources/suwayomi-launcher.sh" "$RELEASE_NAME/" || error $LINENO "Failed to copy launcher script" 1 cp "scripts/resources/suwayomi-launcher.sh" "$RELEASE_NAME/"
cp "scripts/resources/suwayomi-server.sh" "$RELEASE_NAME/" || error $LINENO "Failed to copy server script" 1 cp "scripts/resources/suwayomi-server.sh" "$RELEASE_NAME/"
cp "scripts/resources/catch_abort.so" "$RELEASE_NAME/bin/" || error $LINENO "Failed to copy catch_abort" 1 cp "scripts/resources/catch_abort.so" "$RELEASE_NAME/bin/"
tar -I "gzip -9" -cvf "$RELEASE" "$RELEASE_NAME/" || error $LINENO "Failed to create tar.gz" 1 tar -I "gzip -9" -cvf "$RELEASE" "$RELEASE_NAME/"
} }
make_macos_bundle() { make_macos_bundle() {
mkdir "$RELEASE_NAME/bin" mkdir "$RELEASE_NAME/bin"
cp "$JAR" "$RELEASE_NAME/bin/Suwayomi-Server.jar" || error $LINENO "Failed to copy server jar" 1 cp "$JAR" "$RELEASE_NAME/bin/Suwayomi-Server.jar"
cp "scripts/resources/Suwayomi Launcher.command" "$RELEASE_NAME/" || error $LINENO "Failed to copy launcher command" 1 cp "scripts/resources/Suwayomi Launcher.command" "$RELEASE_NAME/"
tar -I "gzip -9" -cvf "$RELEASE" "$RELEASE_NAME/" || error $LINENO "Failed to create tar.gz" 1 tar -I "gzip -9" -cvf "$RELEASE" "$RELEASE_NAME/"
} }
# https://wiki.debian.org/SimplePackagingTutorial # https://wiki.debian.org/SimplePackagingTutorial
@@ -236,28 +233,28 @@ make_deb_package() {
#behind $RELEASE_VERSION is underscore "_" #behind $RELEASE_VERSION is underscore "_"
local upstream_source="suwayomi-server_$RELEASE_VERSION.orig.tar.gz" local upstream_source="suwayomi-server_$RELEASE_VERSION.orig.tar.gz"
mkdir "$RELEASE_NAME/$source_dir/" || error $LINENO "Failed to create source directory" 1 mkdir "$RELEASE_NAME/$source_dir/"
mv "$RELEASE_NAME/natives" "$RELEASE_NAME/$source_dir/natives" || error $LINENO "Failed to move natives" 1 mv "$RELEASE_NAME/natives" "$RELEASE_NAME/$source_dir/natives"
mv "$RELEASE_NAME/Suwayomi-Launcher.jar" "$RELEASE_NAME/$source_dir/Suwayomi-Launcher.jar" || error $LINENO "Failed to move launcher jar" 1 mv "$RELEASE_NAME/Suwayomi-Launcher.jar" "$RELEASE_NAME/$source_dir/Suwayomi-Launcher.jar"
cp "$JAR" "$RELEASE_NAME/$source_dir/Suwayomi-Server.jar" || error $LINENO "Failed to copy server jar" 1 cp "$JAR" "$RELEASE_NAME/$source_dir/Suwayomi-Server.jar"
copy_linux_package_assets_to "$RELEASE_NAME/$source_dir/" copy_linux_package_assets_to "$RELEASE_NAME/$source_dir/"
cp "scripts/resources/catch_abort.so" "$RELEASE_NAME/$source_dir/" || error $LINENO "Failed to copy catch_abort" 1 cp "scripts/resources/catch_abort.so" "$RELEASE_NAME/$source_dir/"
tar -I "gzip" -C "$RELEASE_NAME/" -cvf "$upstream_source" "$source_dir" || error $LINENO "Failed to create source tar.gz" 1 tar -I "gzip" -C "$RELEASE_NAME/" -cvf "$upstream_source" "$source_dir"
cp -r "scripts/resources/deb/" "$RELEASE_NAME/$source_dir/debian/" || error $LINENO "Failed to copy debian resources" 1 cp -r "scripts/resources/deb/" "$RELEASE_NAME/$source_dir/debian/"
sed -i "s/\$pkgver/$RELEASE_VERSION/" "$RELEASE_NAME/$source_dir/debian/changelog" || error $LINENO "Failed to update changelog" 1 sed -i "s/\$pkgver/$RELEASE_VERSION/" "$RELEASE_NAME/$source_dir/debian/changelog"
sed -i "s/\$pkgrel/1/" "$RELEASE_NAME/$source_dir/debian/changelog" || error $LINENO "Failed to update changelog" 1 sed -i "s/\$pkgrel/1/" "$RELEASE_NAME/$source_dir/debian/changelog"
if [ "${CI:-}" = true ]; then if [ "${CI:-}" = true ]; then
sudo apt update || error $LINENO "Failed to update apt" 1 sudo apt update
sudo apt install devscripts build-essential dh-exec || error $LINENO "Failed to install build deps" 1 sudo apt install devscripts build-essential dh-exec
fi fi
cd "$RELEASE_NAME/$source_dir/" || error $LINENO "Failed to change directory" 1 cd "$RELEASE_NAME/$source_dir/"
dpkg-buildpackage --no-sign --build=all || error $LINENO "Debian package build failed" 1 dpkg-buildpackage --no-sign --build=all
cd - || error $LINENO "Failed to return to previous directory" 1 cd -
local deb="suwayomi-server_$RELEASE_VERSION-1_all.deb" local deb="suwayomi-server_$RELEASE_VERSION-1_all.deb"
mv "$RELEASE_NAME/$deb" "$RELEASE" || error $LINENO "Failed to move resulting .deb" 1 mv "$RELEASE_NAME/$deb" "$RELEASE"
} }
# https://linuxconfig.org/building-a-hello-world-appimage-on-linux # https://linuxconfig.org/building-a-hello-world-appimage-on-linux
@@ -265,20 +262,20 @@ make_appimage() {
local APPIMAGE_URL="https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage" local APPIMAGE_URL="https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage"
local APPIMAGE_TOOLNAME="appimagetool-x86_64.AppImage" local APPIMAGE_TOOLNAME="appimagetool-x86_64.AppImage"
mkdir "$RELEASE_NAME/bin/" mkdir "$RELEASE_NAME/bin/"
cp "$JAR" "$RELEASE_NAME/bin/Suwayomi-Server.jar" || error $LINENO "Failed to copy server jar" 1 cp "$JAR" "$RELEASE_NAME/bin/Suwayomi-Server.jar"
cp "scripts/resources/pkg/suwayomi-server.desktop" "$RELEASE_NAME/suwayomi-server.desktop" || error $LINENO "Failed to copy desktop file" 1 cp "scripts/resources/pkg/suwayomi-server.desktop" "$RELEASE_NAME/suwayomi-server.desktop"
cp "server/src/main/resources/icon/faviconlogo.png" "$RELEASE_NAME/suwayomi-server.png" || error $LINENO "Failed to copy icon" 1 cp "server/src/main/resources/icon/faviconlogo.png" "$RELEASE_NAME/suwayomi-server.png"
cp "scripts/resources/appimage/AppRun" "$RELEASE_NAME/AppRun" || error $LINENO "Failed to copy AppRun" 1 cp "scripts/resources/appimage/AppRun" "$RELEASE_NAME/AppRun"
chmod +x "$RELEASE_NAME/AppRun" || error $LINENO "Failed to make AppRun executable" 1 chmod +x "$RELEASE_NAME/AppRun"
if [ "${CI:-}" = true ]; then if [ "${CI:-}" = true ]; then
sudo apt update || error $LINENO "Failed to update apt" 1 sudo apt update
sudo apt install libfuse2 || error $LINENO "Failed to install libfuse2" 1 sudo apt install libfuse2
fi fi
curl -fL $APPIMAGE_URL -o $APPIMAGE_TOOLNAME || error $LINENO "Failed to download appimagetool" 1 curl -fL $APPIMAGE_URL -o $APPIMAGE_TOOLNAME
chmod +x $APPIMAGE_TOOLNAME || error $LINENO "Failed to make appimagetool executable" 1 chmod +x $APPIMAGE_TOOLNAME
ARCH=x86_64 ./$APPIMAGE_TOOLNAME "$RELEASE_NAME" "$RELEASE" || error $LINENO "AppImage creation failed" 1 ARCH=x86_64 ./$APPIMAGE_TOOLNAME "$RELEASE_NAME" "$RELEASE"
} }
make_windows_bundle() { make_windows_bundle() {
@@ -303,7 +300,7 @@ make_windows_bundle() {
#local rcedit_url="https://github.com/electron/rcedit/releases/download/v0.1.1/$rcedit" #local rcedit_url="https://github.com/electron/rcedit/releases/download/v0.1.1/$rcedit"
## change electron's icon ## change electron's icon
#if [ ! -f "$rcedit" ]; then #if [ ! -f "$rcedit" ]; then
#curl -fL "$rcedit_url" -o "$rcedit" || error $LINENO "Failed to download rcedit" 1 #curl -fL "$rcedit_url" -o "$rcedit"
#fi #fi
#local icon="server/src/main/resources/icon/faviconlogo.ico" #local icon="server/src/main/resources/icon/faviconlogo.ico"
@@ -311,38 +308,38 @@ make_windows_bundle() {
# --set-icon "$icon" # --set-icon "$icon"
mkdir "$RELEASE_NAME/bin" mkdir "$RELEASE_NAME/bin"
cp "$JAR" "$RELEASE_NAME/bin/Suwayomi-Server.jar" || error $LINENO "Failed to copy server jar" 1 cp "$JAR" "$RELEASE_NAME/bin/Suwayomi-Server.jar"
cp "scripts/resources/Suwayomi Launcher.bat" "$RELEASE_NAME" || error $LINENO "Failed to copy launcher bat" 1 cp "scripts/resources/Suwayomi Launcher.bat" "$RELEASE_NAME"
zip -9 -r "$RELEASE" "$RELEASE_NAME" || error $LINENO "Failed to create windows bundle zip" 1 zip -9 -r "$RELEASE" "$RELEASE_NAME"
} }
make_windows_package() { make_windows_package() {
if [ "${CI:-}" = true ]; then if [ "${CI:-}" = true ]; then
sudo apt update || error $LINENO "Failed to update apt" 1 sudo apt update
sudo apt install -y wixl || error $LINENO "Failed to install wixl" 1 sudo apt install -y wixl
fi fi
find "$RELEASE_NAME/jre" \ find "$RELEASE_NAME/jre" \
| wixl-heat --var var.SourceDir -p "$RELEASE_NAME/" \ | wixl-heat --var var.SourceDir -p "$RELEASE_NAME/" \
--directory-ref jre --component-group jre >"$RELEASE_NAME/jre.wxs" || error $LINENO "Failed to heat jre" 1 --directory-ref jre --component-group jre >"$RELEASE_NAME/jre.wxs"
find "$RELEASE_NAME/electron" \ find "$RELEASE_NAME/electron" \
| wixl-heat --var var.SourceDir -p "$RELEASE_NAME/" \ | wixl-heat --var var.SourceDir -p "$RELEASE_NAME/" \
--directory-ref electron --component-group electron >"$RELEASE_NAME/electron.wxs" || error $LINENO "Failed to heat electron" 1 --directory-ref electron --component-group electron >"$RELEASE_NAME/electron.wxs"
find "$RELEASE_NAME/natives" \ find "$RELEASE_NAME/natives" \
| wixl-heat --var var.SourceDir -p "$RELEASE_NAME/" \ | wixl-heat --var var.SourceDir -p "$RELEASE_NAME/" \
--directory-ref natives --component-group natives >"$RELEASE_NAME/natives.wxs" || error $LINENO "Failed to heat natives" 1 --directory-ref natives --component-group natives >"$RELEASE_NAME/natives.wxs"
find "$RELEASE_NAME/bin" \ find "$RELEASE_NAME/bin" \
| wixl-heat --var var.SourceDir -p "$RELEASE_NAME/" \ | wixl-heat --var var.SourceDir -p "$RELEASE_NAME/" \
--directory-ref bin --component-group bin >"$RELEASE_NAME/bin.wxs" || error $LINENO "Failed to heat bin" 1 --directory-ref bin --component-group bin >"$RELEASE_NAME/bin.wxs"
local icon="server/src/main/resources/icon/faviconlogo.ico" local icon="server/src/main/resources/icon/faviconlogo.ico"
local arch=${OS##*-} local arch=${OS##*-}
wixl -D ProductVersion="$RELEASE_VERSION" -D SourceDir="$RELEASE_NAME" \ wixl -D ProductVersion="$RELEASE_VERSION" -D SourceDir="$RELEASE_NAME" \
-D Icon="$icon" --arch "$arch" "scripts/resources/msi/suwayomi-server-$arch.wxs" \ -D Icon="$icon" --arch "$arch" "scripts/resources/msi/suwayomi-server-$arch.wxs" \
"$RELEASE_NAME/jre.wxs" "$RELEASE_NAME/electron.wxs" "$RELEASE_NAME/natives.wxs" "$RELEASE_NAME/bin.wxs" -o "$RELEASE" || error $LINENO "Windows package build failed" 1 "$RELEASE_NAME/jre.wxs" "$RELEASE_NAME/electron.wxs" "$RELEASE_NAME/natives.wxs" "$RELEASE_NAME/bin.wxs" -o "$RELEASE"
} }
# Error handler # Error handler

View File

@@ -8,7 +8,7 @@
<string name="opds_feeds_root">Suwayomi OPDS Katalog</string> <string name="opds_feeds_root">Suwayomi OPDS Katalog</string>
<string name="opds_feeds_chapter_details">%1$s | %2$s | Details</string> <string name="opds_feeds_chapter_details">%1$s | %2$s | Details</string>
<string name="opds_feeds_sources_title">Alle Quellen</string> <string name="opds_feeds_sources_title">Alle Quellen</string>
<string name="opds_feeds_genres_title">Genren</string> <string name="opds_feeds_genres_title">Genres</string>
<string name="opds_feeds_genres_entry_content">Durchsuche Serien nach Genre</string> <string name="opds_feeds_genres_entry_content">Durchsuche Serien nach Genre</string>
<string name="opds_feeds_status_entry_content">Durchsuche Serien nach Publikationsstatus</string> <string name="opds_feeds_status_entry_content">Durchsuche Serien nach Publikationsstatus</string>
<string name="opds_feeds_languages_title">Sprachen</string> <string name="opds_feeds_languages_title">Sprachen</string>
@@ -122,7 +122,4 @@
<string name="webview_label_login_required">Deine Konfiguration erfordert die Anmeldung. Bitte gib Benutzername und Passwort ein.</string> <string name="webview_label_login_required">Deine Konfiguration erfordert die Anmeldung. Bitte gib Benutzername und Passwort ein.</string>
<string name="opds_linktitle_first_page">Erste Seite</string> <string name="opds_linktitle_first_page">Erste Seite</string>
<string name="opds_linktitle_last_page">Letzte Seite</string> <string name="opds_linktitle_last_page">Letzte Seite</string>
<string name="opds_error_chapters_not_found">Keine Kapitel gefunden oder die Quelle ist nicht erreichbar auf Seite %1$d.</string>
<string name="opds_chapter_title_fallback">Kapitel %1$s</string>
<string name="opds_chapter_title_oneshot">Oneshot</string>
</resources> </resources>

View File

@@ -122,6 +122,4 @@
<string name="login_label_login">Σύνδεση</string> <string name="login_label_login">Σύνδεση</string>
<string name="login_placeholder_username">Πληκτρολόγησε όνομα χρήστη...</string> <string name="login_placeholder_username">Πληκτρολόγησε όνομα χρήστη...</string>
<string name="login_placeholder_password">Μυστικό...</string> <string name="login_placeholder_password">Μυστικό...</string>
<string name="opds_error_chapters_not_found">Δεν βρέθηκαν κεφάλαια ή η πηγή είναι μη διαθέσιμη στη σελίδα %1$d.</string>
<string name="opds_chapter_title_fallback">Κεφάλαιο %1$s</string>
</resources> </resources>

View File

@@ -122,6 +122,4 @@
<string name="webview_label_login_required">Su configuración requiere que inicie sesión. Introduzca su nombre de usuario y contraseña.</string> <string name="webview_label_login_required">Su configuración requiere que inicie sesión. Introduzca su nombre de usuario y contraseña.</string>
<string name="opds_linktitle_first_page">Primera página</string> <string name="opds_linktitle_first_page">Primera página</string>
<string name="opds_linktitle_last_page">Última página</string> <string name="opds_linktitle_last_page">Última página</string>
<string name="opds_error_chapters_not_found">No se encontraron capítulos o la fuente no está disponible en la página %1$d.</string>
<string name="opds_chapter_title_fallback">Capítulo %1$s</string>
</resources> </resources>

View File

@@ -122,7 +122,4 @@
<string name="login_label_login">Se connecter</string> <string name="login_label_login">Se connecter</string>
<string name="login_placeholder_username">Tapez le nom d\'utilisateur…</string> <string name="login_placeholder_username">Tapez le nom d\'utilisateur…</string>
<string name="login_placeholder_password">Secret…</string> <string name="login_placeholder_password">Secret…</string>
<string name="opds_error_chapters_not_found">Aucun chapitre trouvé ou la source est inaccessible à la page %1$d.</string>
<string name="opds_chapter_title_fallback">Chapitre %1$s</string>
<string name="opds_chapter_title_oneshot">One shot</string>
</resources> </resources>

View File

@@ -122,6 +122,4 @@
<string name="login_label_login">Accedi</string> <string name="login_label_login">Accedi</string>
<string name="login_placeholder_username">Digita il nome utente...</string> <string name="login_placeholder_username">Digita il nome utente...</string>
<string name="login_placeholder_password">Segreto...</string> <string name="login_placeholder_password">Segreto...</string>
<string name="opds_error_chapters_not_found">Nessun capitolo trovato o la fonte non è raggiungibile alla pagina %1$d.</string>
<string name="opds_chapter_title_fallback">Capitolo %1$s</string>
</resources> </resources>

View File

@@ -60,7 +60,4 @@
<string name="opds_feeds_library_sources_title">ソース</string> <string name="opds_feeds_library_sources_title">ソース</string>
<string name="opds_feeds_library_sources_entry_content">ソース別にライブラリ内のマンガを閲覧</string> <string name="opds_feeds_library_sources_entry_content">ソース別にライブラリ内のマンガを閲覧</string>
<string name="opds_feeds_search_results_title">検索結果</string> <string name="opds_feeds_search_results_title">検索結果</string>
<string name="opds_error_chapters_not_found">ページ %1$d で章が見つからないか、ソースに接続できません。</string>
<string name="opds_chapter_title_oneshot">読み切り</string>
<string name="opds_chapter_title_fallback">第 %1$s 話</string>
</resources> </resources>

View File

@@ -76,6 +76,4 @@
<string name="opds_facet_filter_all">Wszystkie</string> <string name="opds_facet_filter_all">Wszystkie</string>
<string name="opds_facet_filter_downloaded">Pobrane</string> <string name="opds_facet_filter_downloaded">Pobrane</string>
<string name="opds_facet_filter_ongoing">Trwające</string> <string name="opds_facet_filter_ongoing">Trwające</string>
<string name="opds_error_chapters_not_found">Nie znaleziono rozdziałów lub źródło jest nieosiągalne na stronie %1$d.</string>
<string name="opds_chapter_title_fallback">Rozdział %1$s</string>
</resources> </resources>

View File

@@ -122,6 +122,4 @@
<string name="login_label_login">Entrar</string> <string name="login_label_login">Entrar</string>
<string name="login_placeholder_username">Digite o nome de usuário...</string> <string name="login_placeholder_username">Digite o nome de usuário...</string>
<string name="login_placeholder_password">Segredo...</string> <string name="login_placeholder_password">Segredo...</string>
<string name="opds_error_chapters_not_found">Nenhum capítulo encontrado ou a fonte está inacessível na página %1$d.</string>
<string name="opds_chapter_title_fallback">Capítulo %1$s</string>
</resources> </resources>

View File

@@ -122,7 +122,4 @@
<string name="opds_search_description">Ищите тайтлы в каталоге.</string> <string name="opds_search_description">Ищите тайтлы в каталоге.</string>
<string name="opds_error_manga_not_found">Тайтл с ID %1$d не найден.</string> <string name="opds_error_manga_not_found">Тайтл с ID %1$d не найден.</string>
<string name="opds_chapter_details_base">Тайтл: %1$s | %2$s</string> <string name="opds_chapter_details_base">Тайтл: %1$s | %2$s</string>
<string name="opds_error_chapters_not_found">Главы не найдены или источник недоступен на странице %1$d.</string>
<string name="opds_chapter_title_fallback">Глава %1$s</string>
<string name="opds_chapter_title_oneshot">Ваншот</string>
</resources> </resources>

View File

@@ -53,7 +53,4 @@
<string name="opds_chapter_status_unread"></string> <string name="opds_chapter_status_unread"></string>
<string name="opds_chapter_details_base">%1$s | %2$s</string> <string name="opds_chapter_details_base">%1$s | %2$s</string>
<string name="opds_feeds_genre_specific_title">இசைவகை: %1$s</string> <string name="opds_feeds_genre_specific_title">இசைவகை: %1$s</string>
<string name="opds_error_chapters_not_found">பக்கம் %1$d இல் அத்தியாயங்கள் எதுவும் காணப்படவில்லை அல்லது மூலத்தை அணுக முடியவில்லை.</string>
<string name="opds_chapter_title_oneshot">ஒன்-ஷாட்</string>
<string name="opds_chapter_title_fallback">அத்தியாயம் %1$s</string>
</resources> </resources>

View File

@@ -122,6 +122,4 @@
<string name="webview_label_login_required">Cấu hình của bạn yêu cầu bạn phải đăng nhập. Vui lòng nhập tên người dùng và mật khẩu.</string> <string name="webview_label_login_required">Cấu hình của bạn yêu cầu bạn phải đăng nhập. Vui lòng nhập tên người dùng và mật khẩu.</string>
<string name="opds_linktitle_first_page">Trang đầu</string> <string name="opds_linktitle_first_page">Trang đầu</string>
<string name="opds_linktitle_last_page">Trang cuối</string> <string name="opds_linktitle_last_page">Trang cuối</string>
<string name="opds_error_chapters_not_found">Không tìm thấy chương nào hoặc nguồn không thể truy cập tại trang %1$d.</string>
<string name="opds_chapter_title_fallback">Chương %1$s</string>
</resources> </resources>

View File

@@ -122,7 +122,4 @@
<string name="login_placeholder_username">输入用户名…</string> <string name="login_placeholder_username">输入用户名…</string>
<string name="login_placeholder_password">密匙…</string> <string name="login_placeholder_password">密匙…</string>
<string name="label_error">错误</string> <string name="label_error">错误</string>
<string name="opds_error_chapters_not_found">第 %1$d 页未找到任何章节,或图源无法访问。</string>
<string name="opds_chapter_title_fallback">第 %1$s 章</string>
<string name="opds_chapter_title_oneshot">单篇</string>
</resources> </resources>

View File

@@ -22,7 +22,7 @@ import kotlinx.coroutines.flow.onEach
import okhttp3.Cache import okhttp3.Cache
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor import okhttp3.logging.HttpLoggingInterceptor
import suwayomi.tachidesk.manga.impl.util.source.GetSource import suwayomi.tachidesk.manga.impl.util.source.GetCatalogueSource
import java.net.CookieHandler import java.net.CookieHandler
import java.net.CookieManager import java.net.CookieManager
import java.net.CookiePolicy import java.net.CookiePolicy
@@ -62,7 +62,7 @@ class NetworkHelper(
userAgent userAgent
.drop(1) .drop(1)
.onEach { .onEach {
GetSource.unregisterAllSources() // need to reset the headers GetCatalogueSource.unregisterAllCatalogueSources() // need to reset the headers
}.launchIn(GlobalScope) }.launchIn(GlobalScope)
} }

View File

@@ -44,7 +44,7 @@ import org.jetbrains.exposed.v1.jdbc.insert
import org.jetbrains.exposed.v1.jdbc.insertAndGetId import org.jetbrains.exposed.v1.jdbc.insertAndGetId
import org.jetbrains.exposed.v1.jdbc.selectAll import org.jetbrains.exposed.v1.jdbc.selectAll
import org.jetbrains.exposed.v1.jdbc.transactions.transaction import org.jetbrains.exposed.v1.jdbc.transactions.transaction
import suwayomi.tachidesk.manga.impl.util.source.GetSource.registerSource import suwayomi.tachidesk.manga.impl.util.source.GetCatalogueSource.registerCatalogueSource
import suwayomi.tachidesk.manga.impl.util.storage.ImageUtil import suwayomi.tachidesk.manga.impl.util.storage.ImageUtil
import suwayomi.tachidesk.manga.model.table.ExtensionTable import suwayomi.tachidesk.manga.model.table.ExtensionTable
import suwayomi.tachidesk.manga.model.table.SourceTable import suwayomi.tachidesk.manga.model.table.SourceTable
@@ -497,7 +497,7 @@ class LocalSource(
} }
val fs = LocalSourceFileSystem(applicationDirs) val fs = LocalSourceFileSystem(applicationDirs)
registerSource(ID to LocalSource(fs, LocalCoverManager(fs))) registerCatalogueSource(ID to LocalSource(fs, LocalCoverManager(fs)))
} }
} }
} }

View File

@@ -305,7 +305,8 @@ object SyncYomiSyncService {
logger.debug { "Starting merge. Local list size: ${localMangaListSafe.size}, Remote list size: ${remoteMangaListSafe.size}" } logger.debug { "Starting merge. Local list size: ${localMangaListSafe.size}, Remote list size: ${remoteMangaListSafe.size}" }
fun mangaCompositeKey(manga: BackupManga): String = "${manga.source}|${manga.url}" fun mangaCompositeKey(manga: BackupManga): String =
"${manga.source}|${manga.url}|${manga.title.lowercase().trim()}|${manga.author?.lowercase()?.trim()}"
// Create maps using composite keys // Create maps using composite keys
val localMangaMap = localMangaListSafe.associateBy { mangaCompositeKey(it) } val localMangaMap = localMangaListSafe.associateBy { mangaCompositeKey(it) }
@@ -414,7 +415,7 @@ object SyncYomiSyncService {
return remoteChapters // If not syncing chapters, keep remote untouched return remoteChapters // If not syncing chapters, keep remote untouched
} }
fun chapterCompositeKey(chapter: BackupChapter): String = chapter.url fun chapterCompositeKey(chapter: BackupChapter): String = "${chapter.url}|${chapter.name}|${chapter.chapterNumber}"
val localChapterMap = localChapters.associateBy { chapterCompositeKey(it) } val localChapterMap = localChapters.associateBy { chapterCompositeKey(it) }
val remoteChapterMap = remoteChapters.associateBy { chapterCompositeKey(it) } val remoteChapterMap = remoteChapters.associateBy { chapterCompositeKey(it) }

View File

@@ -28,7 +28,7 @@ import suwayomi.tachidesk.graphql.types.preferenceOf
import suwayomi.tachidesk.graphql.types.updateFilterList import suwayomi.tachidesk.graphql.types.updateFilterList
import suwayomi.tachidesk.manga.impl.MangaList.insertOrUpdate import suwayomi.tachidesk.manga.impl.MangaList.insertOrUpdate
import suwayomi.tachidesk.manga.impl.Source import suwayomi.tachidesk.manga.impl.Source
import suwayomi.tachidesk.manga.impl.util.source.GetSource import suwayomi.tachidesk.manga.impl.util.source.GetCatalogueSource
import suwayomi.tachidesk.manga.model.table.MangaTable import suwayomi.tachidesk.manga.model.table.MangaTable
import suwayomi.tachidesk.manga.model.table.SourceMetaTable import suwayomi.tachidesk.manga.model.table.SourceMetaTable
import suwayomi.tachidesk.manga.model.table.SourceTable import suwayomi.tachidesk.manga.model.table.SourceTable
@@ -256,7 +256,7 @@ class SourceMutation {
val (clientMutationId, sourceId, type, page, query, filters) = input val (clientMutationId, sourceId, type, page, query, filters) = input
return future { return future {
val source = GetSource.getSourceOrNull(sourceId)!! val source = GetCatalogueSource.getCatalogueSourceOrNull(sourceId)!!
val mangasPage = val mangasPage =
when (type) { when (type) {
FetchSourceMangaType.SEARCH -> { FetchSourceMangaType.SEARCH -> {

View File

@@ -148,36 +148,6 @@ 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( data class FetchTrackInput(
val clientMutationId: String? = null, val clientMutationId: String? = null,
val recordId: Int, val recordId: Int,

View File

@@ -71,8 +71,8 @@ class ExtensionType(
fun source(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<SourceNodeList> = fun source(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<SourceNodeList> =
dataFetchingEnvironment.getValueFromDataLoader<String, SourceNodeList>("SourcesForExtensionDataLoader", pkgName) dataFetchingEnvironment.getValueFromDataLoader<String, SourceNodeList>("SourcesForExtensionDataLoader", pkgName)
fun extensionStore(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<ExtensionStoreType?> = fun extensionStore(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<ExtensionStoreType> =
dataFetchingEnvironment.getValueFromDataLoader<String, ExtensionStoreType?>("ExtensionStoreDataLoader", storeIndexUrl.orEmpty()) dataFetchingEnvironment.getValueFromDataLoader<String, ExtensionStoreType>("ExtensionStoreDataLoader", storeIndexUrl.orEmpty())
} }
data class ExtensionNodeList( data class ExtensionNodeList(

View File

@@ -9,8 +9,8 @@ package suwayomi.tachidesk.graphql.types
import com.expediagroup.graphql.generator.annotations.GraphQLDeprecated import com.expediagroup.graphql.generator.annotations.GraphQLDeprecated
import com.expediagroup.graphql.server.extensions.getValueFromDataLoader import com.expediagroup.graphql.server.extensions.getValueFromDataLoader
import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.source.ConfigurableSource import eu.kanade.tachiyomi.source.ConfigurableSource
import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.model.FilterList import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.HttpSource
import graphql.schema.DataFetchingEnvironment import graphql.schema.DataFetchingEnvironment
@@ -24,8 +24,8 @@ import suwayomi.tachidesk.graphql.server.primitives.NodeList
import suwayomi.tachidesk.graphql.server.primitives.PageInfo import suwayomi.tachidesk.graphql.server.primitives.PageInfo
import suwayomi.tachidesk.manga.impl.Source.getSourcePreferencesRaw import suwayomi.tachidesk.manga.impl.Source.getSourcePreferencesRaw
import suwayomi.tachidesk.manga.impl.extension.Extension import suwayomi.tachidesk.manga.impl.extension.Extension
import suwayomi.tachidesk.manga.impl.util.source.GetSource import suwayomi.tachidesk.manga.impl.util.source.GetCatalogueSource
import suwayomi.tachidesk.manga.impl.util.source.GetSource.getSourceOrStub import suwayomi.tachidesk.manga.impl.util.source.GetCatalogueSource.getCatalogueSourceOrStub
import suwayomi.tachidesk.manga.model.dataclass.ContentWarning import suwayomi.tachidesk.manga.model.dataclass.ContentWarning
import suwayomi.tachidesk.manga.model.table.ExtensionTable import suwayomi.tachidesk.manga.model.table.ExtensionTable
import suwayomi.tachidesk.manga.model.table.SourceTable import suwayomi.tachidesk.manga.model.table.SourceTable
@@ -53,18 +53,18 @@ class SourceType(
@GraphQLDeprecated("", ReplaceWith("homeUrl")) @GraphQLDeprecated("", ReplaceWith("homeUrl"))
val baseUrl: String?, val baseUrl: String?,
) : Node { ) : Node {
constructor(row: ResultRow, sourceExtension: ResultRow, source: Source) : this( constructor(row: ResultRow, sourceExtension: ResultRow, catalogueSource: CatalogueSource) : this(
id = row[SourceTable.id].value, id = row[SourceTable.id].value,
name = row[SourceTable.name], name = row[SourceTable.name],
lang = row[SourceTable.lang], lang = row[SourceTable.lang],
contentWarning = ContentWarning.valueOf(row[SourceTable.contentWarning]), contentWarning = ContentWarning.valueOf(row[SourceTable.contentWarning]),
iconUrl = Extension.proxyExtensionIconUrl(sourceExtension[ExtensionTable.pkgName]), iconUrl = Extension.proxyExtensionIconUrl(sourceExtension[ExtensionTable.pkgName]),
supportsLatest = source.supportsLatest, supportsLatest = catalogueSource.supportsLatest,
isConfigurable = source is ConfigurableSource, isConfigurable = catalogueSource is ConfigurableSource,
isNsfw = row[SourceTable.contentWarning] >= ContentWarning.MIXED.ordinal, isNsfw = row[SourceTable.contentWarning] >= ContentWarning.MIXED.ordinal,
displayName = source.toString(), displayName = catalogueSource.toString(),
homeUrl = runCatching { (source as? HttpSource)?.getHomeUrl() }.getOrNull(), homeUrl = runCatching { (catalogueSource as? HttpSource)?.getHomeUrl() }.getOrNull(),
baseUrl = runCatching { (source as? HttpSource)?.baseUrl }.getOrNull(), baseUrl = runCatching { (catalogueSource as? HttpSource)?.baseUrl }.getOrNull(),
) )
fun manga(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<MangaNodeList> = fun manga(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<MangaNodeList> =
@@ -75,7 +75,7 @@ class SourceType(
fun preferences(): List<Preference> = getSourcePreferencesRaw(id).map { preferenceOf(it) } fun preferences(): List<Preference> = getSourcePreferencesRaw(id).map { preferenceOf(it) }
fun filters(): List<Filter> = getSourceOrStub(id).getFilterList().map { filterOf(it) } fun filters(): List<Filter> = getCatalogueSourceOrStub(id).getFilterList().map { filterOf(it) }
fun meta(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<List<SourceMetaType>> = fun meta(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<List<SourceMetaType>> =
dataFetchingEnvironment.getValueFromDataLoader<Long, List<SourceMetaType>>("SourceMetaDataLoader", id) dataFetchingEnvironment.getValueFromDataLoader<Long, List<SourceMetaType>>("SourceMetaDataLoader", id)
@@ -84,8 +84,8 @@ class SourceType(
@Suppress("ktlint:standard:function-naming") @Suppress("ktlint:standard:function-naming")
fun SourceType(row: ResultRow): SourceType? { fun SourceType(row: ResultRow): SourceType? {
val catalogueSource = val catalogueSource =
GetSource GetCatalogueSource
.getSourceOrNull(row[SourceTable.id].value) .getCatalogueSourceOrNull(row[SourceTable.id].value)
?: return null ?: return null
val sourceExtension = val sourceExtension =
if (row.hasValue(ExtensionTable.id)) { if (row.hasValue(ExtensionTable.id)) {
@@ -296,7 +296,7 @@ data class FilterChange(
) )
fun updateFilterList( fun updateFilterList(
source: Source, source: CatalogueSource,
changes: List<FilterChange>?, changes: List<FilterChange>?,
): FilterList { ): FilterList {
val filterList = source.getFilterList() val filterList = source.getFilterList()

View File

@@ -7,7 +7,7 @@ package suwayomi.tachidesk.manga.impl
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.model.UpdateStrategy import eu.kanade.tachiyomi.source.model.UpdateStrategy
@@ -38,7 +38,7 @@ import org.jetbrains.exposed.v1.jdbc.update
import suwayomi.tachidesk.manga.impl.download.DownloadManager import suwayomi.tachidesk.manga.impl.download.DownloadManager
import suwayomi.tachidesk.manga.impl.download.DownloadManager.EnqueueInput import suwayomi.tachidesk.manga.impl.download.DownloadManager.EnqueueInput
import suwayomi.tachidesk.manga.impl.track.Track import suwayomi.tachidesk.manga.impl.track.Track
import suwayomi.tachidesk.manga.impl.util.source.GetSource.getSourceOrStub import suwayomi.tachidesk.manga.impl.util.source.GetCatalogueSource.getCatalogueSourceOrStub
import suwayomi.tachidesk.manga.model.dataclass.ChapterDataClass import suwayomi.tachidesk.manga.model.dataclass.ChapterDataClass
import suwayomi.tachidesk.manga.model.dataclass.MangaChapterDataClass import suwayomi.tachidesk.manga.model.dataclass.MangaChapterDataClass
import suwayomi.tachidesk.manga.model.dataclass.PaginatedList import suwayomi.tachidesk.manga.model.dataclass.PaginatedList
@@ -119,7 +119,7 @@ object Chapter {
transaction { transaction {
MangaTable.selectAll().where { MangaTable.id eq mangaId }.first() MangaTable.selectAll().where { MangaTable.id eq mangaId }.first()
} }
val source = getSourceOrStub(mangaEntry[MangaTable.sourceReference]) val source = getCatalogueSourceOrStub(mangaEntry[MangaTable.sourceReference])
val chapters = val chapters =
Manga Manga
@@ -139,7 +139,7 @@ object Chapter {
fun updateChapterListDatabase( fun updateChapterListDatabase(
mangaEntry: ResultRow, mangaEntry: ResultRow,
chapters: List<SChapter>, chapters: List<SChapter>,
source: Source, source: CatalogueSource,
): List<SChapter> { ): List<SChapter> {
val currentLatestChapterNumber = Manga.getLatestChapter(mangaEntry[MangaTable.id].value)?.chapterNumber ?: 0f val currentLatestChapterNumber = Manga.getLatestChapter(mangaEntry[MangaTable.id].value)?.chapterNumber ?: 0f
val numberOfCurrentChapters = getCountOfMangaChapters(mangaEntry[MangaTable.id].value) val numberOfCurrentChapters = getCountOfMangaChapters(mangaEntry[MangaTable.id].value)

View File

@@ -11,7 +11,7 @@ import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.HttpException import eu.kanade.tachiyomi.network.HttpException
import eu.kanade.tachiyomi.network.NetworkHelper import eu.kanade.tachiyomi.network.NetworkHelper
import eu.kanade.tachiyomi.network.awaitSuccess import eu.kanade.tachiyomi.network.awaitSuccess
import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.source.local.LocalSource import eu.kanade.tachiyomi.source.local.LocalSource
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
@@ -41,8 +41,8 @@ import org.jetbrains.exposed.v1.jdbc.transactions.transaction
import org.jetbrains.exposed.v1.jdbc.update import org.jetbrains.exposed.v1.jdbc.update
import suwayomi.tachidesk.manga.impl.download.fileProvider.impl.MissingThumbnailException import suwayomi.tachidesk.manga.impl.download.fileProvider.impl.MissingThumbnailException
import suwayomi.tachidesk.manga.impl.util.network.await import suwayomi.tachidesk.manga.impl.util.network.await
import suwayomi.tachidesk.manga.impl.util.source.GetSource.getSourceOrNull import suwayomi.tachidesk.manga.impl.util.source.GetCatalogueSource.getCatalogueSourceOrNull
import suwayomi.tachidesk.manga.impl.util.source.GetSource.getSourceOrStub import suwayomi.tachidesk.manga.impl.util.source.GetCatalogueSource.getCatalogueSourceOrStub
import suwayomi.tachidesk.manga.impl.util.source.StubSource import suwayomi.tachidesk.manga.impl.util.source.StubSource
import suwayomi.tachidesk.manga.impl.util.storage.ImageResponse.clearCachedImage import suwayomi.tachidesk.manga.impl.util.storage.ImageResponse.clearCachedImage
import suwayomi.tachidesk.manga.impl.util.storage.ImageResponse.getImageResponse import suwayomi.tachidesk.manga.impl.util.storage.ImageResponse.getImageResponse
@@ -91,7 +91,7 @@ object Manga {
suspend fun fetchMangaAndChapters( suspend fun fetchMangaAndChapters(
mangaEntry: ResultRow, mangaEntry: ResultRow,
source: Source, source: CatalogueSource,
fetchDetails: Boolean, fetchDetails: Boolean,
fetchChapters: Boolean, fetchChapters: Boolean,
): SMangaUpdate { ): SMangaUpdate {
@@ -139,7 +139,7 @@ object Manga {
return mangaInfoMutex.get(mangaId) { Mutex() }.withLock { return mangaInfoMutex.get(mangaId) { Mutex() }.withLock {
val mangaEntry = val mangaEntry =
transaction { MangaTable.selectAll().where { MangaTable.id eq mangaId }.first() } transaction { MangaTable.selectAll().where { MangaTable.id eq mangaId }.first() }
val source = getSourceOrNull(mangaEntry[MangaTable.sourceReference]) ?: return null val source = getCatalogueSourceOrNull(mangaEntry[MangaTable.sourceReference]) ?: return null
val sManga = val sManga =
fetchMangaAndChapters( fetchMangaAndChapters(
mangaEntry, mangaEntry,
@@ -161,7 +161,7 @@ object Manga {
var mangaEntry = var mangaEntry =
transaction { MangaTable.selectAll().where { MangaTable.id eq mangaId }.first() } transaction { MangaTable.selectAll().where { MangaTable.id eq mangaId }.first() }
val source = val source =
getSourceOrNull(mangaEntry[MangaTable.sourceReference]) getCatalogueSourceOrNull(mangaEntry[MangaTable.sourceReference])
?: throw NullPointerException("Missing source ${mangaEntry[MangaTable.sourceReference]}") ?: throw NullPointerException("Missing source ${mangaEntry[MangaTable.sourceReference]}")
val mangaUpdate = val mangaUpdate =
fetchMangaAndChapters( fetchMangaAndChapters(
@@ -186,7 +186,7 @@ object Manga {
fun updateMangaDatabase( fun updateMangaDatabase(
mangaEntry: ResultRow, mangaEntry: ResultRow,
source: Source, source: CatalogueSource,
sManga: SManga, sManga: SManga,
): SManga { ): SManga {
transaction { transaction {
@@ -238,7 +238,6 @@ object Manga {
it[MangaTable.lastFetchedAt] = Instant.now().epochSecond it[MangaTable.lastFetchedAt] = Instant.now().epochSecond
it[MangaTable.updateStrategy] = sManga.update_strategy.name it[MangaTable.updateStrategy] = sManga.update_strategy.name
it[MangaTable.memo] = Json.encodeToString(sManga.memo)
} }
} }
@@ -413,7 +412,7 @@ object Manga {
val mangaEntry = transaction { MangaTable.selectAll().where { MangaTable.id eq mangaId }.first() } val mangaEntry = transaction { MangaTable.selectAll().where { MangaTable.id eq mangaId }.first() }
val sourceId = mangaEntry[MangaTable.sourceReference] val sourceId = mangaEntry[MangaTable.sourceReference]
return when (val source = getSourceOrStub(sourceId)) { return when (val source = getCatalogueSourceOrStub(sourceId)) {
is HttpSource -> { is HttpSource -> {
getImageResponse(cacheSaveDir, fileName) { getImageResponse(cacheSaveDir, fileName) {
fetchHttpSourceMangaThumbnail(source, mangaEntry) fetchHttpSourceMangaThumbnail(source, mangaEntry)

View File

@@ -19,7 +19,7 @@ import org.jetbrains.exposed.v1.jdbc.batchInsert
import org.jetbrains.exposed.v1.jdbc.selectAll import org.jetbrains.exposed.v1.jdbc.selectAll
import org.jetbrains.exposed.v1.jdbc.statements.toExecutable import org.jetbrains.exposed.v1.jdbc.statements.toExecutable
import org.jetbrains.exposed.v1.jdbc.transactions.transaction import org.jetbrains.exposed.v1.jdbc.transactions.transaction
import suwayomi.tachidesk.manga.impl.util.source.GetSource.getSourceOrStub import suwayomi.tachidesk.manga.impl.util.source.GetCatalogueSource.getCatalogueSourceOrStub
import suwayomi.tachidesk.manga.model.dataclass.PagedMangaListDataClass import suwayomi.tachidesk.manga.model.dataclass.PagedMangaListDataClass
import suwayomi.tachidesk.manga.model.table.MangaTable import suwayomi.tachidesk.manga.model.table.MangaTable
import suwayomi.tachidesk.manga.model.table.toDataClass import suwayomi.tachidesk.manga.model.table.toDataClass
@@ -36,7 +36,7 @@ object MangaList {
require(pageNum > 0) { require(pageNum > 0) {
"pageNum = $pageNum is not in valid range" "pageNum = $pageNum is not in valid range"
} }
val source = getSourceOrStub(sourceId) val source = getCatalogueSourceOrStub(sourceId)
val mangasPage = val mangasPage =
if (popular) { if (popular) {
source.getPopularManga(pageNum) source.getPopularManga(pageNum)

View File

@@ -21,7 +21,7 @@ import org.jetbrains.exposed.v1.jdbc.transactions.transaction
import org.jetbrains.exposed.v1.jdbc.update import org.jetbrains.exposed.v1.jdbc.update
import suwayomi.tachidesk.graphql.types.DownloadConversion import suwayomi.tachidesk.graphql.types.DownloadConversion
import suwayomi.tachidesk.manga.impl.util.getChapterCachePath import suwayomi.tachidesk.manga.impl.util.getChapterCachePath
import suwayomi.tachidesk.manga.impl.util.source.GetSource.getSourceOrStub import suwayomi.tachidesk.manga.impl.util.source.GetCatalogueSource.getCatalogueSourceOrStub
import suwayomi.tachidesk.manga.impl.util.storage.ImageResponse.getImageResponse import suwayomi.tachidesk.manga.impl.util.storage.ImageResponse.getImageResponse
import suwayomi.tachidesk.manga.impl.util.storage.ImageUtil import suwayomi.tachidesk.manga.impl.util.storage.ImageUtil
import suwayomi.tachidesk.manga.model.table.ChapterTable import suwayomi.tachidesk.manga.model.table.ChapterTable
@@ -118,7 +118,7 @@ object Page {
return imageFile.inputStream() to (ImageUtil.findImageType { imageFile.inputStream() }?.mime ?: "image/jpeg") return imageFile.inputStream() to (ImageUtil.findImageType { imageFile.inputStream() }?.mime ?: "image/jpeg")
} }
val source = getSourceOrStub(mangaEntry[MangaTable.sourceReference]) val source = getCatalogueSourceOrStub(mangaEntry[MangaTable.sourceReference])
source as HttpSource source as HttpSource
if (pageEntry[PageTable.imageUrl] == null) { if (pageEntry[PageTable.imageUrl] == null) {

View File

@@ -7,14 +7,14 @@ package suwayomi.tachidesk.manga.impl
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.source.model.Filter import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.source.model.FilterList import eu.kanade.tachiyomi.source.model.FilterList
import io.javalin.json.JsonMapper import io.javalin.json.JsonMapper
import io.javalin.json.fromJsonString import io.javalin.json.fromJsonString
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import suwayomi.tachidesk.manga.impl.MangaList.processEntries import suwayomi.tachidesk.manga.impl.MangaList.processEntries
import suwayomi.tachidesk.manga.impl.util.source.GetSource.getSourceOrStub import suwayomi.tachidesk.manga.impl.util.source.GetCatalogueSource.getCatalogueSourceOrStub
import suwayomi.tachidesk.manga.model.dataclass.PagedMangaListDataClass import suwayomi.tachidesk.manga.model.dataclass.PagedMangaListDataClass
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
@@ -24,7 +24,7 @@ object Search {
searchTerm: String, searchTerm: String,
pageNum: Int, pageNum: Int,
): PagedMangaListDataClass { ): PagedMangaListDataClass {
val source = getSourceOrStub(sourceId) val source = getCatalogueSourceOrStub(sourceId)
val searchManga = source.getSearchManga(pageNum, searchTerm, getFilterListOf(source)) val searchManga = source.getSearchManga(pageNum, searchTerm, getFilterListOf(source))
return searchManga.processEntries(sourceId) return searchManga.processEntries(sourceId)
} }
@@ -34,7 +34,7 @@ object Search {
pageNum: Int, pageNum: Int,
filter: FilterData, filter: FilterData,
): PagedMangaListDataClass { ): PagedMangaListDataClass {
val source = getSourceOrStub(sourceId) val source = getCatalogueSourceOrStub(sourceId)
val filterList = if (filter.filter != null) buildFilterList(sourceId, filter.filter) else source.getFilterList() val filterList = if (filter.filter != null) buildFilterList(sourceId, filter.filter) else source.getFilterList()
val searchManga = source.getSearchManga(pageNum, filter.searchTerm ?: "", filterList) val searchManga = source.getSearchManga(pageNum, filter.searchTerm ?: "", filterList)
return searchManga.processEntries(sourceId) return searchManga.processEntries(sourceId)
@@ -43,7 +43,7 @@ object Search {
private val filterListCache = mutableMapOf<Long, FilterList>() private val filterListCache = mutableMapOf<Long, FilterList>()
private fun getFilterListOf( private fun getFilterListOf(
source: Source, source: CatalogueSource,
reset: Boolean = false, reset: Boolean = false,
): FilterList { ): FilterList {
if (reset || !filterListCache.containsKey(source.id)) { if (reset || !filterListCache.containsKey(source.id)) {
@@ -56,7 +56,7 @@ object Search {
sourceId: Long, sourceId: Long,
reset: Boolean, reset: Boolean,
): List<FilterObject> { ): List<FilterObject> {
val source = getSourceOrStub(sourceId) val source = getCatalogueSourceOrStub(sourceId)
return getFilterListOf(source, reset).list.map { return getFilterListOf(source, reset).list.map {
FilterObject( FilterObject(
@@ -111,7 +111,7 @@ object Search {
sourceId: Long, sourceId: Long,
changes: List<FilterChange>, changes: List<FilterChange>,
) { ) {
val source = getSourceOrStub(sourceId) val source = getCatalogueSourceOrStub(sourceId)
val filterList = getFilterListOf(source, false) val filterList = getFilterListOf(source, false)
updateFilterList(filterList, changes) updateFilterList(filterList, changes)
} }
@@ -169,7 +169,7 @@ object Search {
sourceId: Long, sourceId: Long,
changes: List<FilterChange>, changes: List<FilterChange>,
): FilterList { ): FilterList {
val source = getSourceOrStub(sourceId) val source = getCatalogueSourceOrStub(sourceId)
val filterList = source.getFilterList() val filterList = source.getFilterList()
return updateFilterList(filterList, changes) return updateFilterList(filterList, changes)
} }

View File

@@ -26,9 +26,9 @@ import org.jetbrains.exposed.v1.jdbc.statements.toExecutable
import org.jetbrains.exposed.v1.jdbc.transactions.transaction import org.jetbrains.exposed.v1.jdbc.transactions.transaction
import suwayomi.tachidesk.manga.impl.Source.preferenceScreenMap import suwayomi.tachidesk.manga.impl.Source.preferenceScreenMap
import suwayomi.tachidesk.manga.impl.extension.Extension.proxyExtensionIconUrl import suwayomi.tachidesk.manga.impl.extension.Extension.proxyExtensionIconUrl
import suwayomi.tachidesk.manga.impl.util.source.GetSource.getSourceOrNull import suwayomi.tachidesk.manga.impl.util.source.GetCatalogueSource.getCatalogueSourceOrNull
import suwayomi.tachidesk.manga.impl.util.source.GetSource.getSourceOrStub import suwayomi.tachidesk.manga.impl.util.source.GetCatalogueSource.getCatalogueSourceOrStub
import suwayomi.tachidesk.manga.impl.util.source.GetSource.unregisterSource import suwayomi.tachidesk.manga.impl.util.source.GetCatalogueSource.unregisterCatalogueSource
import suwayomi.tachidesk.manga.model.dataclass.ContentWarning import suwayomi.tachidesk.manga.model.dataclass.ContentWarning
import suwayomi.tachidesk.manga.model.dataclass.SourceDataClass import suwayomi.tachidesk.manga.model.dataclass.SourceDataClass
import suwayomi.tachidesk.manga.model.table.ExtensionTable import suwayomi.tachidesk.manga.model.table.ExtensionTable
@@ -43,7 +43,7 @@ object Source {
fun getSourceList(): List<SourceDataClass> { fun getSourceList(): List<SourceDataClass> {
return transaction { return transaction {
SourceTable.selectAll().mapNotNull { SourceTable.selectAll().mapNotNull {
val catalogueSource = getSourceOrNull(it[SourceTable.id].value) ?: return@mapNotNull null val catalogueSource = getCatalogueSourceOrNull(it[SourceTable.id].value) ?: return@mapNotNull null
val sourceExtension = ExtensionTable.selectAll().where { ExtensionTable.id eq it[SourceTable.extension] }.first() val sourceExtension = ExtensionTable.selectAll().where { ExtensionTable.id eq it[SourceTable.extension] }.first()
SourceDataClass( SourceDataClass(
@@ -64,7 +64,7 @@ object Source {
fun getSource(sourceId: Long): SourceDataClass? { // all the data extracted fresh form the source instance fun getSource(sourceId: Long): SourceDataClass? { // all the data extracted fresh form the source instance
return transaction { return transaction {
val source = SourceTable.selectAll().where { SourceTable.id eq sourceId }.firstOrNull() ?: return@transaction null val source = SourceTable.selectAll().where { SourceTable.id eq sourceId }.firstOrNull() ?: return@transaction null
val catalogueSource = getSourceOrNull(sourceId) ?: return@transaction null val catalogueSource = getCatalogueSourceOrNull(sourceId) ?: return@transaction null
val extension = ExtensionTable.selectAll().where { ExtensionTable.id eq source[SourceTable.extension] }.first() val extension = ExtensionTable.selectAll().where { ExtensionTable.id eq source[SourceTable.extension] }.first()
SourceDataClass( SourceDataClass(
@@ -107,7 +107,7 @@ object Source {
} }
fun getSourcePreferencesRaw(sourceId: Long): List<Preference> { fun getSourcePreferencesRaw(sourceId: Long): List<Preference> {
val source = getSourceOrStub(sourceId) val source = getCatalogueSourceOrStub(sourceId)
if (source is ConfigurableSource) { if (source is ConfigurableSource) {
val sourceShardPreferences = source.sourcePreferences() val sourceShardPreferences = source.sourcePreferences()
@@ -157,7 +157,7 @@ object Source {
pref.callChangeListener(newValue) pref.callChangeListener(newValue)
// must reload the source because a preference was changed // must reload the source because a preference was changed
unregisterSource(sourceId) unregisterCatalogueSource(sourceId)
} }
fun getSourcesMetaMaps(ids: List<Long>): Map<Long, Map<String, String>> = fun getSourcesMetaMaps(ids: List<Long>): Map<Long, Map<String, String>> =

View File

@@ -8,6 +8,7 @@ package suwayomi.tachidesk.manga.impl.backup.proto.handlers
* 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.UpdateStrategy 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.ResultRow
import org.jetbrains.exposed.v1.core.SortOrder import org.jetbrains.exposed.v1.core.SortOrder
import org.jetbrains.exposed.v1.core.and import org.jetbrains.exposed.v1.core.and
@@ -77,7 +78,7 @@ object BackupMangaHandler {
lastModifiedAt = mangaRow[MangaTable.lastModifiedAt], lastModifiedAt = mangaRow[MangaTable.lastModifiedAt],
version = mangaRow[MangaTable.version], version = mangaRow[MangaTable.version],
initialized = mangaRow[MangaTable.initialized], initialized = mangaRow[MangaTable.initialized],
memo = mangaRow[MangaTable.memo].encodeToByteArray(), memo = Json.encodeToString(mangaRow[MangaTable.memo]).encodeToByteArray(),
) )
val mangaId = mangaRow[MangaTable.id].value val mangaId = mangaRow[MangaTable.id].value
@@ -115,7 +116,6 @@ object BackupMangaHandler {
sourceOrder = chapters.size - it[ChapterTable.sourceOrder], sourceOrder = chapters.size - it[ChapterTable.sourceOrder],
lastModifiedAt = it[ChapterTable.lastModifiedAt], lastModifiedAt = it[ChapterTable.lastModifiedAt],
version = it[ChapterTable.version], version = it[ChapterTable.version],
memo = it[ChapterTable.memo].encodeToByteArray(),
).apply { ).apply {
if (flags.includeClientData) { if (flags.includeClientData) {
this.meta = chapterToMeta[it[ChapterTable.id].value] ?: emptyMap() this.meta = chapterToMeta[it[ChapterTable.id].value] ?: emptyMap()

View File

@@ -39,7 +39,7 @@ data class BackupManga(
@ProtoNumber(106) var lastModifiedAt: Long = 0, @ProtoNumber(106) var lastModifiedAt: Long = 0,
@ProtoNumber(109) var version: Long = 0, @ProtoNumber(109) var version: Long = 0,
@ProtoNumber(111) var initialized: Boolean = false, @ProtoNumber(111) var initialized: Boolean = false,
@ProtoNumber(112) var memo: ByteArray = JsonObjectEmptyBytes, @ProtoNumber(13) var memo: ByteArray = JsonObjectEmptyBytes,
// suwayomi // suwayomi
@ProtoNumber(9000) var meta: Map<String, String> = emptyMap(), @ProtoNumber(9000) var meta: Map<String, String> = emptyMap(),
) )

View File

@@ -23,7 +23,7 @@ import org.jetbrains.exposed.v1.jdbc.selectAll
import org.jetbrains.exposed.v1.jdbc.transactions.transaction import org.jetbrains.exposed.v1.jdbc.transactions.transaction
import org.jetbrains.exposed.v1.jdbc.update import org.jetbrains.exposed.v1.jdbc.update
import suwayomi.tachidesk.manga.impl.ChapterDownloadHelper import suwayomi.tachidesk.manga.impl.ChapterDownloadHelper
import suwayomi.tachidesk.manga.impl.util.source.GetSource.getSourceOrStub import suwayomi.tachidesk.manga.impl.util.source.GetCatalogueSource.getCatalogueSourceOrStub
import suwayomi.tachidesk.manga.model.dataclass.ChapterDataClass import suwayomi.tachidesk.manga.model.dataclass.ChapterDataClass
import suwayomi.tachidesk.manga.model.table.ChapterTable import suwayomi.tachidesk.manga.model.table.ChapterTable
import suwayomi.tachidesk.manga.model.table.MangaTable import suwayomi.tachidesk.manga.model.table.MangaTable
@@ -77,7 +77,7 @@ suspend fun refreshChapterPageList(
return mutex.withLock { return mutex.withLock {
val chapterEntry = existingChapterEntry ?: transaction { ChapterTable.selectAll().where { ChapterTable.id eq chapterId }.first() } val chapterEntry = existingChapterEntry ?: transaction { ChapterTable.selectAll().where { ChapterTable.id eq chapterId }.first() }
val mangaEntry = transaction { MangaTable.selectAll().where { MangaTable.id eq mangaId }.first() } val mangaEntry = transaction { MangaTable.selectAll().where { MangaTable.id eq mangaId }.first() }
val source = getSourceOrStub(mangaEntry[MangaTable.sourceReference]) val source = getCatalogueSourceOrStub(mangaEntry[MangaTable.sourceReference])
val pageList = val pageList =
source source

View File

@@ -10,6 +10,7 @@ package suwayomi.tachidesk.manga.impl.extension
import android.net.Uri import android.net.Uri
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.NetworkHelper import eu.kanade.tachiyomi.network.NetworkHelper
import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.SourceFactory import eu.kanade.tachiyomi.source.SourceFactory
import eu.kanade.tachiyomi.source.local.LocalSource import eu.kanade.tachiyomi.source.local.LocalSource
@@ -40,7 +41,7 @@ import suwayomi.tachidesk.manga.impl.util.PackageTools.dex2jar
import suwayomi.tachidesk.manga.impl.util.PackageTools.getPackageInfo import suwayomi.tachidesk.manga.impl.util.PackageTools.getPackageInfo
import suwayomi.tachidesk.manga.impl.util.PackageTools.loadExtensionSources import suwayomi.tachidesk.manga.impl.util.PackageTools.loadExtensionSources
import suwayomi.tachidesk.manga.impl.util.network.await import suwayomi.tachidesk.manga.impl.util.network.await
import suwayomi.tachidesk.manga.impl.util.source.GetSource import suwayomi.tachidesk.manga.impl.util.source.GetCatalogueSource
import suwayomi.tachidesk.manga.impl.util.storage.ImageResponse.clearCachedImage import suwayomi.tachidesk.manga.impl.util.storage.ImageResponse.clearCachedImage
import suwayomi.tachidesk.manga.impl.util.storage.ImageResponse.getImageResponse import suwayomi.tachidesk.manga.impl.util.storage.ImageResponse.getImageResponse
import suwayomi.tachidesk.manga.impl.util.storage.ImageResponse.saveImage import suwayomi.tachidesk.manga.impl.util.storage.ImageResponse.saveImage
@@ -154,16 +155,7 @@ object Extension {
var contentWarning = packageInfo.applicationInfo.metaData.getInt(METADATA_CONTENT_WARNING) var contentWarning = packageInfo.applicationInfo.metaData.getInt(METADATA_CONTENT_WARNING)
if (contentWarning == 0) { if (contentWarning == 0) {
contentWarning = packageInfo.applicationInfo.metaData contentWarning = packageInfo.applicationInfo.metaData.getInt(METADATA_NSFW)
.getString(METADATA_CONTENT_WARNING)
?.toIntOrNull()
?: 0
if (contentWarning == 0) {
contentWarning = packageInfo.applicationInfo.metaData
.getString(METADATA_NSFW)
?.toIntOrNull()
?: 0
}
} }
val className = val className =
@@ -173,7 +165,7 @@ object Extension {
dex2jar(apkFilePath, jarFilePath, fileNameWithoutType) dex2jar(apkFilePath, jarFilePath, fileNameWithoutType)
extractAssetsFromApk(apkFilePath, jarFilePath) extractAssetsFromApk(apkFilePath, jarFilePath)
extractAndCacheApkIcon(apkFilePath, packageInfo.packageName) extractAndCacheApkIcon(apkFilePath, apkName)
// clean up // clean up
File(apkFilePath).delete() File(apkFilePath).delete()
@@ -181,12 +173,12 @@ object Extension {
try { try {
// collect sources from the extension // collect sources from the extension
val extensionMainClassInstance = loadExtensionSources(jarFilePath, className) val extensionMainClassInstance = loadExtensionSources(jarFilePath, className)
val sources: List<Source> = val sources: List<CatalogueSource> =
when (extensionMainClassInstance) { when (extensionMainClassInstance) {
is Source -> listOf(extensionMainClassInstance) is Source -> listOf(extensionMainClassInstance)
is SourceFactory -> extensionMainClassInstance.createSources() is SourceFactory -> extensionMainClassInstance.createSources()
else -> throw RuntimeException("Unknown source class type! ${extensionMainClassInstance.javaClass}") else -> throw RuntimeException("Unknown source class type! ${extensionMainClassInstance.javaClass}")
} }.map { it as CatalogueSource }
val langs = sources.map { it.lang }.toSet() val langs = sources.map { it.lang }.toSet()
val extensionLang = val extensionLang =
@@ -265,7 +257,7 @@ object Extension {
private fun extractAndCacheApkIcon( private fun extractAndCacheApkIcon(
apkFilePath: String, apkFilePath: String,
pkgName: String, apkName: String,
) { ) {
val iconCacheDir = "${applicationDirs.extensionsRoot}/icon" val iconCacheDir = "${applicationDirs.extensionsRoot}/icon"
try { try {
@@ -278,15 +270,15 @@ object Extension {
?.first ?.first
} }
if (iconData == null) { if (iconData == null) {
logger.warn { "No icon found in APK $pkgName" } logger.warn { "No icon found in APK $apkName" }
return return
} }
File(iconCacheDir).mkdirs() File(iconCacheDir).mkdirs()
clearCachedImage(iconCacheDir, pkgName) clearCachedImage(iconCacheDir, apkName)
saveImage("$iconCacheDir/$pkgName", iconData.inputStream(), null) saveImage("$iconCacheDir/$apkName", iconData.inputStream(), null)
} catch (e: Exception) { } catch (e: Exception) {
logger.warn(e) { "Failed to extract icon from APK $pkgName" } logger.warn(e) { "Failed to extract icon from APK $apkName" }
} }
} }
@@ -379,7 +371,7 @@ object Extension {
SourceTable.deleteWhere { SourceTable.extension eq extensionId } SourceTable.deleteWhere { SourceTable.extension eq extensionId }
if (extensionRecord[ExtensionTable.isObsolete] || extensionRecord[ExtensionTable.apkUrl] == null) { if (extensionRecord[ExtensionTable.isObsolete]) {
ExtensionTable.deleteWhere { ExtensionTable.pkgName eq pkgName } ExtensionTable.deleteWhere { ExtensionTable.pkgName eq pkgName }
} else { } else {
ExtensionTable.update({ ExtensionTable.pkgName eq pkgName }) { ExtensionTable.update({ ExtensionTable.pkgName eq pkgName }) {
@@ -397,7 +389,7 @@ object Extension {
PackageTools.jarLoaderMap.remove(jarPath)?.close() PackageTools.jarLoaderMap.remove(jarPath)?.close()
// clear all loaded sources // clear all loaded sources
sources.forEach { GetSource.unregisterSource(it) } sources.forEach { GetCatalogueSource.unregisterCatalogueSource(it) }
File(jarPath).delete() File(jarPath).delete()
} }

View File

@@ -222,48 +222,6 @@ 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) { suspend fun refresh(recordId: Int) {
val recordDb = val recordDb =
transaction { transaction {
@@ -465,9 +423,9 @@ object Track {
} }
} }
fun updateTrackRecord(track: Track): Int = updateTrackRecords(listOf(track)).first() fun updateTrackRecord(track: Track) = updateTrackRecords(listOf(track))
fun updateTrackRecords(tracks: List<Track>): List<Int> = fun updateTrackRecords(tracks: List<Track>) =
transaction { transaction {
if (tracks.isNotEmpty()) { if (tracks.isNotEmpty()) {
BatchUpdateStatement(TrackRecordTable) BatchUpdateStatement(TrackRecordTable)
@@ -489,8 +447,6 @@ object Track {
}.toExecutable() }.toExecutable()
.execute(this@transaction) .execute(this@transaction)
} }
tracks.map { it.id!! }
} }
fun insertTrackRecord(track: Track): Int = insertTrackRecords(listOf(track)).first() fun insertTrackRecord(track: Track): Int = insertTrackRecords(listOf(track)).first()

View File

@@ -11,7 +11,7 @@ import io.github.oshai.kotlinlogging.KotlinLogging
import org.jetbrains.exposed.v1.core.eq import org.jetbrains.exposed.v1.core.eq
import org.jetbrains.exposed.v1.jdbc.selectAll import org.jetbrains.exposed.v1.jdbc.selectAll
import org.jetbrains.exposed.v1.jdbc.transactions.transaction import org.jetbrains.exposed.v1.jdbc.transactions.transaction
import suwayomi.tachidesk.manga.impl.util.source.GetSource import suwayomi.tachidesk.manga.impl.util.source.GetCatalogueSource
import suwayomi.tachidesk.manga.model.table.ChapterTable import suwayomi.tachidesk.manga.model.table.ChapterTable
import suwayomi.tachidesk.manga.model.table.MangaTable import suwayomi.tachidesk.manga.model.table.MangaTable
import suwayomi.tachidesk.server.ApplicationDirs import suwayomi.tachidesk.server.ApplicationDirs
@@ -37,7 +37,7 @@ private fun getMangaDir(
private fun getMangaDir(mangaId: Int): String = private fun getMangaDir(mangaId: Int): String =
transaction { transaction {
val mangaEntry = MangaTable.selectAll().where { MangaTable.id eq mangaId }.first() val mangaEntry = MangaTable.selectAll().where { MangaTable.id eq mangaId }.first()
val source = GetSource.getSourceOrStub(mangaEntry[MangaTable.sourceReference]) val source = GetCatalogueSource.getCatalogueSourceOrStub(mangaEntry[MangaTable.sourceReference])
getMangaDir(mangaEntry[MangaTable.title], source.toString()) getMangaDir(mangaEntry[MangaTable.title], source.toString())
} }

View File

@@ -7,6 +7,7 @@ package suwayomi.tachidesk.manga.impl.util.source
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.Source
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
@@ -21,14 +22,14 @@ import suwayomi.tachidesk.server.ApplicationDirs
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
object GetSource { object GetCatalogueSource {
private val logger = KotlinLogging.logger { } private val logger = KotlinLogging.logger { }
private val sourceCache = ConcurrentHashMap<Long, Source>() private val sourceCache = ConcurrentHashMap<Long, CatalogueSource>()
private val applicationDirs: ApplicationDirs by injectLazy() private val applicationDirs: ApplicationDirs by injectLazy()
private fun getSource(sourceId: Long): Source? { private fun getCatalogueSource(sourceId: Long): CatalogueSource? {
val cachedResult: Source? = sourceCache[sourceId] val cachedResult: CatalogueSource? = sourceCache[sourceId]
if (cachedResult != null) { if (cachedResult != null) {
return cachedResult return cachedResult
} }
@@ -61,25 +62,25 @@ object GetSource {
return sourceCache[sourceId]!! return sourceCache[sourceId]!!
} }
fun getSourceOrNull(sourceId: Long): Source? = fun getCatalogueSourceOrNull(sourceId: Long): CatalogueSource? =
try { try {
getSource(sourceId) getCatalogueSource(sourceId)
} catch (e: Exception) { } catch (e: Exception) {
logger.warn(e) { "getCatalogueSource($sourceId) failed" } logger.warn(e) { "getCatalogueSource($sourceId) failed" }
null null
} }
fun getSourceOrStub(sourceId: Long): Source = getSourceOrNull(sourceId) ?: StubSource(sourceId) fun getCatalogueSourceOrStub(sourceId: Long): CatalogueSource = getCatalogueSourceOrNull(sourceId) ?: StubSource(sourceId)
fun registerSource(sourcePair: Pair<Long, Source>) { fun registerCatalogueSource(sourcePair: Pair<Long, CatalogueSource>) {
sourceCache += sourcePair sourceCache += sourcePair
} }
fun unregisterSource(sourceId: Long) { fun unregisterCatalogueSource(sourceId: Long) {
sourceCache.remove(sourceId) sourceCache.remove(sourceId)
} }
fun unregisterAllSources() { fun unregisterAllCatalogueSources() {
(sourceCache - 0L).forEach { (id, _) -> (sourceCache - 0L).forEach { (id, _) ->
sourceCache.remove(id) sourceCache.remove(id)
} }

View File

@@ -23,7 +23,7 @@ object ExtensionTable : IntIdTable() {
val name = varchar("name", 128) val name = varchar("name", 128)
val pkgName = varchar("pkg_name", 128) val pkgName = varchar("pkg_name", 128)
val apkUrl = varchar("apk_url", 2048).nullable() val apkUrl = varchar("apk_url", 2048)
val extensionLib = varchar("extension_lib", 16).nullable() val extensionLib = varchar("extension_lib", 16).nullable()
val versionName = varchar("version_name", 16) val versionName = varchar("version_name", 16)
val versionCode = long("version_code") val versionCode = long("version_code")

View File

@@ -22,7 +22,7 @@ import org.jetbrains.exposed.v1.jdbc.andWhere
import org.jetbrains.exposed.v1.jdbc.select import org.jetbrains.exposed.v1.jdbc.select
import org.jetbrains.exposed.v1.jdbc.transactions.transaction import org.jetbrains.exposed.v1.jdbc.transactions.transaction
import suwayomi.tachidesk.manga.impl.MangaList.insertOrUpdate import suwayomi.tachidesk.manga.impl.MangaList.insertOrUpdate
import suwayomi.tachidesk.manga.impl.util.source.GetSource import suwayomi.tachidesk.manga.impl.util.source.GetCatalogueSource
import suwayomi.tachidesk.manga.model.dataclass.toGenreList import suwayomi.tachidesk.manga.model.dataclass.toGenreList
import suwayomi.tachidesk.manga.model.table.CategoryMangaTable import suwayomi.tachidesk.manga.model.table.CategoryMangaTable
import suwayomi.tachidesk.manga.model.table.CategoryTable import suwayomi.tachidesk.manga.model.table.CategoryTable
@@ -231,7 +231,7 @@ object MangaRepository {
pageNum: Int, pageNum: Int,
sort: String, sort: String,
): Pair<List<OpdsMangaAcqEntry>, Boolean> { ): Pair<List<OpdsMangaAcqEntry>, Boolean> {
val source = GetSource.getSourceOrStub(sourceId) val source = GetCatalogueSource.getCatalogueSourceOrStub(sourceId)
val mangasPage: MangasPage = val mangasPage: MangasPage =
if (sort == "latest" && source.supportsLatest) { if (sort == "latest" && source.supportsLatest) {
source.getLatestUpdates(pageNum) source.getLatestUpdates(pageNum)

View File

@@ -14,7 +14,7 @@ import org.koin.core.context.stopKoin
import suwayomi.tachidesk.manga.impl.Source import suwayomi.tachidesk.manga.impl.Source
import suwayomi.tachidesk.manga.impl.extension.Extension import suwayomi.tachidesk.manga.impl.extension.Extension
import suwayomi.tachidesk.manga.impl.extension.ExtensionsList import suwayomi.tachidesk.manga.impl.extension.ExtensionsList
import suwayomi.tachidesk.manga.impl.util.source.GetSource import suwayomi.tachidesk.manga.impl.util.source.GetCatalogueSource
import suwayomi.tachidesk.server.applicationSetup import suwayomi.tachidesk.server.applicationSetup
import suwayomi.tachidesk.server.settings.SettingsRegistry import suwayomi.tachidesk.server.settings.SettingsRegistry
import suwayomi.tachidesk.test.BASE_PATH import suwayomi.tachidesk.test.BASE_PATH
@@ -51,7 +51,7 @@ class CloudFlareTest {
Source Source
.getSourceList() .getSourceList()
.firstNotNullOf { it.id.toLong().takeIf { it == 3122156392225024195L } } .firstNotNullOf { it.id.toLong().takeIf { it == 3122156392225024195L } }
.let(GetSource::getSourceOrNull) as HttpSource .let(GetCatalogueSource::getCatalogueSourceOrNull) as HttpSource
} }
setLoggingEnabled(true) setLoggingEnabled(true)
} }

View File

@@ -28,7 +28,7 @@ import suwayomi.tachidesk.manga.impl.extension.Extension.installExtension
import suwayomi.tachidesk.manga.impl.extension.Extension.uninstallExtension import suwayomi.tachidesk.manga.impl.extension.Extension.uninstallExtension
import suwayomi.tachidesk.manga.impl.extension.Extension.updateExtension import suwayomi.tachidesk.manga.impl.extension.Extension.updateExtension
import suwayomi.tachidesk.manga.impl.extension.ExtensionsList.getExtensionList import suwayomi.tachidesk.manga.impl.extension.ExtensionsList.getExtensionList
import suwayomi.tachidesk.manga.impl.util.source.GetSource.getSourceOrNull import suwayomi.tachidesk.manga.impl.util.source.GetCatalogueSource.getCatalogueSourceOrNull
import suwayomi.tachidesk.manga.model.dataclass.ExtensionDataClass import suwayomi.tachidesk.manga.model.dataclass.ExtensionDataClass
import suwayomi.tachidesk.server.applicationSetup import suwayomi.tachidesk.server.applicationSetup
import suwayomi.tachidesk.server.settings.SettingsRegistry import suwayomi.tachidesk.server.settings.SettingsRegistry
@@ -82,7 +82,7 @@ class TestExtensionCompatibility {
.filter { .filter {
// filter local source // filter local source
it.id.toLong() != 0L it.id.toLong() != 0L
}.map { getSourceOrNull(it.id.toLong())!! as HttpSource } }.map { getCatalogueSourceOrNull(it.id.toLong())!! as HttpSource }
} }
setLoggingEnabled(true) setLoggingEnabled(true)
File("$BASE_PATH/sources.txt").writeText(sources.joinToString("\n") { "${it.name} - ${it.lang.uppercase()} - ${it.id}" }) File("$BASE_PATH/sources.txt").writeText(sources.joinToString("\n") { "${it.name} - ${it.lang.uppercase()} - ${it.id}" })

View File

@@ -24,8 +24,8 @@ import suwayomi.tachidesk.manga.impl.Search.SerializableGroup
import suwayomi.tachidesk.manga.impl.Search.getFilterList import suwayomi.tachidesk.manga.impl.Search.getFilterList
import suwayomi.tachidesk.manga.impl.Search.setFilter import suwayomi.tachidesk.manga.impl.Search.setFilter
import suwayomi.tachidesk.manga.impl.Search.sourceSearch import suwayomi.tachidesk.manga.impl.Search.sourceSearch
import suwayomi.tachidesk.manga.impl.util.source.GetSource.registerSource import suwayomi.tachidesk.manga.impl.util.source.GetCatalogueSource.registerCatalogueSource
import suwayomi.tachidesk.manga.impl.util.source.GetSource.unregisterSource import suwayomi.tachidesk.manga.impl.util.source.GetCatalogueSource.unregisterCatalogueSource
import suwayomi.tachidesk.manga.impl.util.source.StubSource import suwayomi.tachidesk.manga.impl.util.source.StubSource
import suwayomi.tachidesk.test.ApplicationTest import suwayomi.tachidesk.test.ApplicationTest
import suwayomi.tachidesk.test.createSMangas import suwayomi.tachidesk.test.createSMangas
@@ -53,7 +53,7 @@ class SearchTest : ApplicationTest() {
@BeforeAll @BeforeAll
fun setup() { fun setup() {
registerSource(sourceId to source) registerCatalogueSource(sourceId to source)
this.source.mangas = createSMangas(mangasCount) this.source.mangas = createSMangas(mangasCount)
} }
@@ -70,7 +70,7 @@ class SearchTest : ApplicationTest() {
@AfterAll @AfterAll
fun teardown() { fun teardown() {
unregisterSource(this.sourceId) unregisterCatalogueSource(this.sourceId)
} }
} }
@@ -347,7 +347,7 @@ class FilterListTest : ApplicationTest() {
private fun registerSource(sourceClass: KClass<*>): EmptyFilterListSource = private fun registerSource(sourceClass: KClass<*>): EmptyFilterListSource =
synchronized(sourceClass) { synchronized(sourceClass) {
val source = sourceClass.primaryConstructor!!.call(sourceCount) as EmptyFilterListSource val source = sourceClass.primaryConstructor!!.call(sourceCount) as EmptyFilterListSource
registerSource(sourceCount to source) registerCatalogueSource(sourceCount to source)
sourceCount++ sourceCount++
source source
} }
@@ -355,7 +355,7 @@ class FilterListTest : ApplicationTest() {
@AfterAll @AfterAll
@JvmStatic @JvmStatic
fun teardown() { fun teardown() {
(0 until sourceCount).forEach { unregisterSource(it) } (0 until sourceCount).forEach { unregisterCatalogueSource(it) }
} }
} }
} }