mirror of
https://github.com/Suwayomi/Suwayomi-Server.git
synced 2026-07-05 20:04:36 -05:00
Compare commits
42 Commits
renovate/g
...
extensions
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e4440ad502 | ||
|
|
e71c94547d | ||
|
|
84a1789850 | ||
|
|
70a027f6f0 | ||
|
|
650c075723 | ||
|
|
a69e29d1a5 | ||
|
|
eec0951a75 | ||
|
|
4ace76f508 | ||
|
|
cd91b6e6ef | ||
|
|
f748bc7f6d | ||
|
|
11ff4bb280 | ||
|
|
388586f23b | ||
|
|
b8ffbebc76 | ||
|
|
3048df307d | ||
|
|
3b3770cb3d | ||
|
|
9667aeba18 | ||
|
|
6c8a024b0f | ||
|
|
5b2613dad3 | ||
|
|
396cfa734a | ||
|
|
a1fdf6d77a | ||
|
|
07ae17105b | ||
|
|
b8772f60bf | ||
|
|
733b9c9919 | ||
|
|
0b0c056bcb | ||
|
|
aff95bfc37 | ||
|
|
00bc3e39b6 | ||
|
|
e9c2cc49a6 | ||
|
|
ea310ba54b | ||
|
|
72347f45cc | ||
|
|
1e73e526c6 | ||
|
|
8fd0fdba08 | ||
|
|
4b61d375ed | ||
|
|
3cf4cf6cf8 | ||
|
|
74ade8a3a3 | ||
|
|
3bb2e4329e | ||
|
|
33ec15c136 | ||
|
|
3a78453a02 | ||
|
|
b7c259a4cb | ||
|
|
41ef220a0b | ||
|
|
85fe9802e2 | ||
|
|
676aed14c0 | ||
|
|
ceac5f74c4 |
6
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
6
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -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
|
||||||
|
|||||||
2
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
2
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
@@ -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
|
||||||
36
CHANGELOG.md
36
CHANGELOG.md
@@ -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
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) }
|
||||||
|
|||||||
@@ -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 -> {
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>> =
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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(),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
@@ -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")
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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}" })
|
||||||
|
|||||||
@@ -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) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user