mirror of
https://github.com/Suwayomi/Suwayomi-Server.git
synced 2026-07-14 16:24:34 -05:00
Compare commits
36 Commits
76686db6a1
...
renovate/m
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fbfa80f196 | ||
|
|
9d5d88e56c | ||
|
|
d57623fe2e | ||
|
|
c98899d501 | ||
|
|
7654653a25 | ||
|
|
0c1a0ef408 | ||
|
|
e7f2192579 | ||
|
|
5c3b1e0b07 | ||
|
|
6ad59f2e2b | ||
|
|
03dd778fac | ||
|
|
6b833a38d1 | ||
|
|
a83885353c | ||
|
|
10d7c7c06d | ||
|
|
3b575271cb | ||
|
|
5ad92413f3 | ||
|
|
7fbdb39319 | ||
|
|
92abdf7fb7 | ||
|
|
ea0c666cfe | ||
|
|
b5e395a039 | ||
|
|
e530072a07 | ||
|
|
f85cbe1ca5 | ||
|
|
5f9126eb2f | ||
|
|
d77c57ede0 | ||
|
|
02f9a0d1d7 | ||
|
|
53192f56ca | ||
|
|
01d89cbb48 | ||
|
|
be55cb974b | ||
|
|
34c394ed19 | ||
|
|
1433a21abd | ||
|
|
ec28794655 | ||
|
|
72122b7cbf | ||
|
|
392a7990d2 | ||
|
|
0bdcf8b4ba | ||
|
|
8295440bfd | ||
|
|
e52aa6daf4 | ||
|
|
ef067ef5b9 |
2
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
2
.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.1.1867"
|
Example: "v2.2.2100"
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
|
||||||
|
|||||||
36
.github/workflows/build_push.yml
vendored
36
.github/workflows/build_push.yml
vendored
@@ -54,14 +54,14 @@ jobs:
|
|||||||
run: ./gradlew :server:shadowJar --stacktrace
|
run: ./gradlew :server:shadowJar --stacktrace
|
||||||
|
|
||||||
- name: Upload Jar
|
- name: Upload Jar
|
||||||
uses: actions/upload-artifact@v6
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
name: jar
|
name: jar
|
||||||
path: master/server/build/*.jar
|
path: master/server/build/*.jar
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Upload icons
|
- name: Upload icons
|
||||||
uses: actions/upload-artifact@v6
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
name: icon
|
name: icon
|
||||||
path: master/server/src/main/resources/icon
|
path: master/server/src/main/resources/icon
|
||||||
@@ -71,7 +71,7 @@ jobs:
|
|||||||
run: tar -cvzf scripts.tar.gz -C master/ scripts/
|
run: tar -cvzf scripts.tar.gz -C master/ scripts/
|
||||||
|
|
||||||
- name: Upload scripts.tar.gz
|
- name: Upload scripts.tar.gz
|
||||||
uses: actions/upload-artifact@v6
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
name: scripts
|
name: scripts
|
||||||
path: scripts.tar.gz
|
path: scripts.tar.gz
|
||||||
@@ -103,7 +103,7 @@ jobs:
|
|||||||
run: jlink --add-modules java.base,java.compiler,java.datatransfer,java.desktop,java.instrument,java.logging,java.management,java.naming,java.prefs,java.scripting,java.se,java.security.jgss,java.security.sasl,java.sql,java.transaction.xa,java.xml,jdk.attach,jdk.crypto.ec,jdk.jdi,jdk.management,jdk.net,jdk.unsupported,jdk.unsupported.desktop,jdk.zipfs,jdk.accessibility --output suwa --strip-debug --no-man-pages --no-header-files --compress=2
|
run: jlink --add-modules java.base,java.compiler,java.datatransfer,java.desktop,java.instrument,java.logging,java.management,java.naming,java.prefs,java.scripting,java.se,java.security.jgss,java.security.sasl,java.sql,java.transaction.xa,java.xml,jdk.attach,jdk.crypto.ec,jdk.jdi,jdk.management,jdk.net,jdk.unsupported,jdk.unsupported.desktop,jdk.zipfs,jdk.accessibility --output suwa --strip-debug --no-man-pages --no-header-files --compress=2
|
||||||
|
|
||||||
- name: Upload JRE package
|
- name: Upload JRE package
|
||||||
uses: actions/upload-artifact@v6
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
name: ${{ matrix.name }}-jre
|
name: ${{ matrix.name }}-jre
|
||||||
path: suwa
|
path: suwa
|
||||||
@@ -134,26 +134,26 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Download Jar
|
- name: Download Jar
|
||||||
uses: actions/download-artifact@v7
|
uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
name: jar
|
name: jar
|
||||||
path: server/build
|
path: server/build
|
||||||
|
|
||||||
- name: Download JRE
|
- name: Download JRE
|
||||||
uses: actions/download-artifact@v7
|
uses: actions/download-artifact@v8
|
||||||
if: matrix.name != 'linux-assets' && matrix.name != 'debian-all'
|
if: matrix.name != 'linux-assets' && matrix.name != 'debian-all'
|
||||||
with:
|
with:
|
||||||
name: ${{ matrix.jre }}-jre
|
name: ${{ matrix.jre }}-jre
|
||||||
path: jre
|
path: jre
|
||||||
|
|
||||||
- name: Download icons
|
- name: Download icons
|
||||||
uses: actions/download-artifact@v7
|
uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
name: icon
|
name: icon
|
||||||
path: server/src/main/resources/icon
|
path: server/src/main/resources/icon
|
||||||
|
|
||||||
- name: Download scripts.tar.gz
|
- name: Download scripts.tar.gz
|
||||||
uses: actions/download-artifact@v7
|
uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
name: scripts
|
name: scripts
|
||||||
|
|
||||||
@@ -164,7 +164,7 @@ jobs:
|
|||||||
scripts/bundler.sh -o upload/ ${{ matrix.name }}
|
scripts/bundler.sh -o upload/ ${{ matrix.name }}
|
||||||
|
|
||||||
- name: Upload ${{ matrix.name }} release
|
- name: Upload ${{ matrix.name }} release
|
||||||
uses: actions/upload-artifact@v6
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
name: ${{ matrix.name }}
|
name: ${{ matrix.name }}
|
||||||
path: upload/*
|
path: upload/*
|
||||||
@@ -174,35 +174,35 @@ jobs:
|
|||||||
needs: bundle
|
needs: bundle
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/download-artifact@v7
|
- uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
name: jar
|
name: jar
|
||||||
path: release
|
path: release
|
||||||
- uses: actions/download-artifact@v7
|
- uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
name: debian-all
|
name: debian-all
|
||||||
path: release
|
path: release
|
||||||
- uses: actions/download-artifact@v7
|
- uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
name: appimage
|
name: appimage
|
||||||
path: release
|
path: release
|
||||||
- uses: actions/download-artifact@v7
|
- uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
name: linux-assets
|
name: linux-assets
|
||||||
path: release
|
path: release
|
||||||
- uses: actions/download-artifact@v7
|
- uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
name: linux-x64
|
name: linux-x64
|
||||||
path: release
|
path: release
|
||||||
- uses: actions/download-artifact@v7
|
- uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
name: macOS-x64
|
name: macOS-x64
|
||||||
path: release
|
path: release
|
||||||
- uses: actions/download-artifact@v7
|
- uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
name: macOS-arm64
|
name: macOS-arm64
|
||||||
path: release
|
path: release
|
||||||
- uses: actions/download-artifact@v7
|
- uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
name: windows-x64
|
name: windows-x64
|
||||||
path: release
|
path: release
|
||||||
@@ -240,7 +240,7 @@ jobs:
|
|||||||
git push origin $TAG
|
git push origin $TAG
|
||||||
|
|
||||||
- name: Upload Preview Release
|
- name: Upload Preview Release
|
||||||
uses: softprops/action-gh-release@v2
|
uses: softprops/action-gh-release@v3
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.DEPLOY_PREVIEW_TOKEN }}
|
token: ${{ secrets.DEPLOY_PREVIEW_TOKEN }}
|
||||||
repository: "Suwayomi/Suwayomi-Server-preview"
|
repository: "Suwayomi/Suwayomi-Server-preview"
|
||||||
|
|||||||
36
.github/workflows/publish.yml
vendored
36
.github/workflows/publish.yml
vendored
@@ -56,14 +56,14 @@ jobs:
|
|||||||
run: ./gradlew :server:downloadWebUI :server:shadowJar --stacktrace
|
run: ./gradlew :server:downloadWebUI :server:shadowJar --stacktrace
|
||||||
|
|
||||||
- name: Upload Jar
|
- name: Upload Jar
|
||||||
uses: actions/upload-artifact@v6
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
name: jar
|
name: jar
|
||||||
path: master/server/build/*.jar
|
path: master/server/build/*.jar
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Upload icons
|
- name: Upload icons
|
||||||
uses: actions/upload-artifact@v6
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
name: icon
|
name: icon
|
||||||
path: master/server/src/main/resources/icon
|
path: master/server/src/main/resources/icon
|
||||||
@@ -73,7 +73,7 @@ jobs:
|
|||||||
run: tar -cvzf scripts.tar.gz -C master/ scripts/
|
run: tar -cvzf scripts.tar.gz -C master/ scripts/
|
||||||
|
|
||||||
- name: Upload scripts.tar.gz
|
- name: Upload scripts.tar.gz
|
||||||
uses: actions/upload-artifact@v6
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
name: scripts
|
name: scripts
|
||||||
path: scripts.tar.gz
|
path: scripts.tar.gz
|
||||||
@@ -105,7 +105,7 @@ jobs:
|
|||||||
run: jlink --add-modules java.base,java.compiler,java.datatransfer,java.desktop,java.instrument,java.logging,java.management,java.naming,java.prefs,java.scripting,java.se,java.security.jgss,java.security.sasl,java.sql,java.transaction.xa,java.xml,jdk.attach,jdk.crypto.ec,jdk.jdi,jdk.management,jdk.net,jdk.unsupported,jdk.unsupported.desktop,jdk.zipfs,jdk.accessibility --output suwa --strip-debug --no-man-pages --no-header-files --compress=2
|
run: jlink --add-modules java.base,java.compiler,java.datatransfer,java.desktop,java.instrument,java.logging,java.management,java.naming,java.prefs,java.scripting,java.se,java.security.jgss,java.security.sasl,java.sql,java.transaction.xa,java.xml,jdk.attach,jdk.crypto.ec,jdk.jdi,jdk.management,jdk.net,jdk.unsupported,jdk.unsupported.desktop,jdk.zipfs,jdk.accessibility --output suwa --strip-debug --no-man-pages --no-header-files --compress=2
|
||||||
|
|
||||||
- name: Upload JDK package
|
- name: Upload JDK package
|
||||||
uses: actions/upload-artifact@v6
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
name: ${{ matrix.name }}-jre
|
name: ${{ matrix.name }}-jre
|
||||||
path: suwa
|
path: suwa
|
||||||
@@ -136,26 +136,26 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Download Jar
|
- name: Download Jar
|
||||||
uses: actions/download-artifact@v7
|
uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
name: jar
|
name: jar
|
||||||
path: server/build
|
path: server/build
|
||||||
|
|
||||||
- name: Download JRE
|
- name: Download JRE
|
||||||
uses: actions/download-artifact@v7
|
uses: actions/download-artifact@v8
|
||||||
if: matrix.name != 'linux-assets' && matrix.name != 'debian-all'
|
if: matrix.name != 'linux-assets' && matrix.name != 'debian-all'
|
||||||
with:
|
with:
|
||||||
name: ${{ matrix.jre }}-jre
|
name: ${{ matrix.jre }}-jre
|
||||||
path: jre
|
path: jre
|
||||||
|
|
||||||
- name: Download icons
|
- name: Download icons
|
||||||
uses: actions/download-artifact@v7
|
uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
name: icon
|
name: icon
|
||||||
path: server/src/main/resources/icon
|
path: server/src/main/resources/icon
|
||||||
|
|
||||||
- name: Download scripts.tar.gz
|
- name: Download scripts.tar.gz
|
||||||
uses: actions/download-artifact@v7
|
uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
name: scripts
|
name: scripts
|
||||||
|
|
||||||
@@ -166,7 +166,7 @@ jobs:
|
|||||||
scripts/bundler.sh -o upload/ ${{ matrix.name }}
|
scripts/bundler.sh -o upload/ ${{ matrix.name }}
|
||||||
|
|
||||||
- name: Upload ${{ matrix.name }} files
|
- name: Upload ${{ matrix.name }} files
|
||||||
uses: actions/upload-artifact@v6
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
name: ${{ matrix.name }}
|
name: ${{ matrix.name }}
|
||||||
path: upload/*
|
path: upload/*
|
||||||
@@ -177,35 +177,35 @@ jobs:
|
|||||||
needs: bundle
|
needs: bundle
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/download-artifact@v7
|
- uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
name: jar
|
name: jar
|
||||||
path: release
|
path: release
|
||||||
- uses: actions/download-artifact@v7
|
- uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
name: debian-all
|
name: debian-all
|
||||||
path: release
|
path: release
|
||||||
- uses: actions/download-artifact@v7
|
- uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
name: appimage
|
name: appimage
|
||||||
path: release
|
path: release
|
||||||
- uses: actions/download-artifact@v7
|
- uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
name: linux-assets
|
name: linux-assets
|
||||||
path: release
|
path: release
|
||||||
- uses: actions/download-artifact@v7
|
- uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
name: linux-x64
|
name: linux-x64
|
||||||
path: release
|
path: release
|
||||||
- uses: actions/download-artifact@v7
|
- uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
name: macOS-x64
|
name: macOS-x64
|
||||||
path: release
|
path: release
|
||||||
- uses: actions/download-artifact@v7
|
- uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
name: macOS-arm64
|
name: macOS-arm64
|
||||||
path: release
|
path: release
|
||||||
- uses: actions/download-artifact@v7
|
- uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
name: windows-x64
|
name: windows-x64
|
||||||
path: release
|
path: release
|
||||||
@@ -214,7 +214,7 @@ jobs:
|
|||||||
run: cd release && sha256sum * > Checksums.sha256
|
run: cd release && sha256sum * > Checksums.sha256
|
||||||
|
|
||||||
- name: Release
|
- name: Release
|
||||||
uses: softprops/action-gh-release@v2
|
uses: softprops/action-gh-release@v3
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.DEPLOY_RELEASE_TOKEN }}
|
token: ${{ secrets.DEPLOY_RELEASE_TOKEN }}
|
||||||
draft: true
|
draft: true
|
||||||
|
|||||||
35
CHANGELOG.md
35
CHANGELOG.md
@@ -6,6 +6,29 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|||||||
|
|
||||||
## [Unreleased] (Preview)
|
## [Unreleased] (Preview)
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- .
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- .
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- (WebUI) Handle serving non-default webui with "bundled"
|
||||||
|
|
||||||
|
## [v2.2.2100] + [WebUI: v20260508.01] - 2026-05-08
|
||||||
|
|
||||||
|
### Major Changes
|
||||||
|
|
||||||
|
#### Added UI Login Auth Method!
|
||||||
|
We now have another alternative login type! This is our most flexable option as it allows clients and the server to handle it together, it's not an all or nothing authentication method like the others. For example the web-based clients can now use thier own login pages, and the server can add data to the tokens it gives to the clients, improving performance while keeping the security standard high.
|
||||||
|
|
||||||
|
#### PostgreSQL Support!
|
||||||
|
We finally support alternative database types! H2 is a great database, but it has its issues. Using a more widespread database like PostgreSQL can avoid them while keeping the performance high! Note that PostgreSQL will need to be run externally. See our example [docker-compose.yml](https://github.com/Suwayomi/Suwayomi-Server-docker/blob/ffc7f6990e889d0a257efe3d94db085d5e73f420/docker-compose-postgresql.yml)
|
||||||
|
|
||||||
|
#### Remote Image Modification/Conversion
|
||||||
|
We now support remote image modification! This will allow you to use an external server that can change your images however you want, such as converting to JXL or WebP, or applying some upscaling or sharpening to them! This pairs well with our new option to convert images before it serves them to the client.
|
||||||
|
See our [conversion server](https://github.com/Suwayomi/Suwayomi-converter) for an example.
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
- (**Source/API**) Expose "baseUrl" (TYPE "SourceType")
|
- (**Source/API**) Expose "baseUrl" (TYPE "SourceType")
|
||||||
- (**Extension**) Support author notes
|
- (**Extension**) Support author notes
|
||||||
@@ -65,6 +88,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|||||||
- (**Library update**) Fix stale manga data in update subscription status events
|
- (**Library update**) Fix stale manga data in update subscription status events
|
||||||
- (**Cloudflare/flaresolverr**) Fix sending POST requests as GET to flaresolverr
|
- (**Cloudflare/flaresolverr**) Fix sending POST requests as GET to flaresolverr
|
||||||
|
|
||||||
|
### WebUI
|
||||||
|
- [See WebUI changes here][WebUI: v20260508.01]
|
||||||
|
|
||||||
|
### Contributors
|
||||||
|
@cpiber, @Syer10, @lamaxama, @schroda, @AwkwardPeak7, @ItsGlassPlus1, @manti-X, @Youwes09, @renovate[bot], @D-Brox, @weblate, @Micka149, @TheRay82, @UnknownSkyrimPasserby, @KaceyKoo-gif, @333fred, @KolbyML, @Robonau, @ornaras, @SpicyCatGames, @FadedSociety, @ginocic, @zeedif, @CzechuPL, @mrintrepide, @renjfk, @thiagoalcr, @Smileskun, @dejavui, @allrobot
|
||||||
|
|
||||||
## [v2.1.1867] + [WebUI: v20250703.01] - 2025-07-31
|
## [v2.1.1867] + [WebUI: v20250703.01] - 2025-07-31
|
||||||
|
|
||||||
### Webview!
|
### Webview!
|
||||||
@@ -166,7 +195,7 @@ This release has been working on the long awaited tracking support! With the las
|
|||||||
|
|
||||||
@schroda, @Syer10, @RatCornu, @FumoVite
|
@schroda, @Syer10, @RatCornu, @FumoVite
|
||||||
|
|
||||||
## [v1.0.0] + [WebUI: r1409] - 2024-02-23
|
## [v1.0.0] + [WebUI: v1.0.0] - 2024-02-23
|
||||||
|
|
||||||
We've done a lot since our last release over a year ago.
|
We've done a lot since our last release over a year ago.
|
||||||
|
|
||||||
@@ -379,6 +408,7 @@ Huge thanks to @martinek who pulled the most of the weight this release!
|
|||||||
|
|
||||||
<!-- WEBUI LINKS -->
|
<!-- WEBUI LINKS -->
|
||||||
|
|
||||||
|
[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
|
||||||
[WebUI: v20250731.01]: https://github.com/Suwayomi/Suwayomi-WebUI/blob/master/CHANGELOG.md#2025073101-r2715---2025-07-31
|
[WebUI: v20250731.01]: https://github.com/Suwayomi/Suwayomi-WebUI/blob/master/CHANGELOG.md#2025073101-r2715---2025-07-31
|
||||||
@@ -404,7 +434,8 @@ 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.1.1867...HEAD
|
[unreleased]: https://github.com/suwayomi/suwayomi-server/compare/v2.2.2100...HEAD
|
||||||
|
[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
|
||||||
[v1.1.1]: https://github.com/suwayomi/suwayomi-server/compare/v1.1.0...v1.1.1
|
[v1.1.1]: https://github.com/suwayomi/suwayomi-server/compare/v1.1.0...v1.1.1
|
||||||
|
|||||||
@@ -76,9 +76,9 @@ These clients are built-in options, and the server can keep them automatically u
|
|||||||
- [Suwayomi-WebUI](https://github.com/Suwayomi/Suwayomi-WebUI): Web app, PWA
|
- [Suwayomi-WebUI](https://github.com/Suwayomi/Suwayomi-WebUI): Web app, PWA
|
||||||
- [Suwayomi-VUI](https://github.com/Suwayomi/Suwayomi-VUI): Web app, PWA
|
- [Suwayomi-VUI](https://github.com/Suwayomi/Suwayomi-VUI): Web app, PWA
|
||||||
|
|
||||||
##### Other clients (potentially inactive or abondend)
|
##### Other clients (potentially inactive or abandoned)
|
||||||
- [Tachidesk-VaadinUI](https://github.com/Suwayomi/Tachidesk-VaadinUI): Desktop app (windows, linux, mac); UI in the browser, manages its own suwayomi server instance
|
- [Tachidesk-VaadinUI](https://github.com/Suwayomi/Tachidesk-VaadinUI): Desktop app (windows, linux, mac); UI in the browser, manages its own suwayomi server instance
|
||||||
- [Moku](https://github.com/Youwes09/Moku): Desktop app (windows, linux, mac), requires access to a running server
|
- [Moku](https://github.com/Youwes09/Moku): Desktop app (windows, linux, mac), can manage its own suwayomi server instance
|
||||||
- [Tachidesk-JUI](https://github.com/Suwayomi/Tachidesk-JUI): Desktop app (windows, linux, mac); can manage its own suwayomi server instance
|
- [Tachidesk-JUI](https://github.com/Suwayomi/Tachidesk-JUI): Desktop app (windows, linux, mac); can manage its own suwayomi server instance
|
||||||
- [Tachidesk-Sorayomi](https://github.com/Suwayomi/Tachidesk-Sorayomi): Web app; Desktop app (windows, linux, mac); Android app; requires access to a running server
|
- [Tachidesk-Sorayomi](https://github.com/Suwayomi/Tachidesk-Sorayomi): Web app; Desktop app (windows, linux, mac); Android app; requires access to a running server
|
||||||
- [Tachidesk-qtui](https://github.com/Suwayomi/Tachidesk-qtui): Android app; iOS app Desktop app (linux); requires access to a running server
|
- [Tachidesk-qtui](https://github.com/Suwayomi/Tachidesk-qtui): Android app; iOS app Desktop app (linux); requires access to a running server
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ subprojects {
|
|||||||
}
|
}
|
||||||
compilerOptions {
|
compilerOptions {
|
||||||
jvmTarget = JvmTarget.fromTarget(libs.versions.jvmTarget.get())
|
jvmTarget = JvmTarget.fromTarget(libs.versions.jvmTarget.get())
|
||||||
freeCompilerArgs.add("-Xcontext-receivers")
|
freeCompilerArgs.add("-Xcontext-parameters")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.1.${getCommitCount()}" }
|
val getTachideskVersion = { "v2.2.${getCommitCount()}" }
|
||||||
|
|
||||||
val webUIRevisionTag = "r2643"
|
val webUIRevisionTag = "r3136"
|
||||||
|
|
||||||
private val getCommitCount = {
|
private val getCommitCount = {
|
||||||
runCatching {
|
runCatching {
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
[versions]
|
[versions]
|
||||||
kotlin = "2.3.10"
|
kotlin = "2.3.21"
|
||||||
coroutines = "1.10.2"
|
coroutines = "1.11.0"
|
||||||
serialization = "1.10.0"
|
serialization = "1.11.0"
|
||||||
jvmTarget = "21"
|
jvmTarget = "21"
|
||||||
okhttp = "5.3.2" # Major version is locked by Tachiyomi extensions
|
okhttp = "5.3.2" # Major version is locked by Tachiyomi extensions
|
||||||
javalin = "6.7.0"
|
javalin = "7.2.0"
|
||||||
jte = "3.2.3"
|
jte = "3.2.4"
|
||||||
jackson = "2.18.3" # jackson version locked by javalin, ref: `io.javalin.core.util.OptionalDependency`
|
jackson = "3.1.2" # jackson version locked by javalin, ref: `io.javalin.core.util.OptionalDependency`
|
||||||
exposed = "0.61.0"
|
exposed = "0.61.0"
|
||||||
dex2jar = "2.4.34"
|
dex2jar = "2.4.36"
|
||||||
polyglot = "24.2.2"
|
polyglot = "25.0.3"
|
||||||
settings = "1.3.0"
|
settings = "1.3.0"
|
||||||
twelvemonkeys = "3.13.0"
|
twelvemonkeys = "3.13.1"
|
||||||
graphqlkotlin = "8.8.1"
|
graphqlkotlin = "8.9.0"
|
||||||
xmlserialization = "0.91.3"
|
xmlserialization = "0.91.3"
|
||||||
ktlint = "1.8.0"
|
ktlint = "1.8.0"
|
||||||
koin = "4.1.1"
|
koin = "4.2.1"
|
||||||
moko = "0.26.0"
|
moko = "0.26.4"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
# Kotlin
|
# Kotlin
|
||||||
@@ -39,22 +39,22 @@ serialization-xml = { module = "io.github.pdvrieze.xmlutil:serialization-jvm", v
|
|||||||
# Logging
|
# Logging
|
||||||
slf4japi = "org.slf4j:slf4j-api:2.0.17"
|
slf4japi = "org.slf4j:slf4j-api:2.0.17"
|
||||||
logback = "ch.qos.logback:logback-classic:1.5.32"
|
logback = "ch.qos.logback:logback-classic:1.5.32"
|
||||||
kotlinlogging = "io.github.oshai:kotlin-logging-jvm:8.0.01"
|
kotlinlogging = "io.github.oshai:kotlin-logging-jvm:8.0.02"
|
||||||
|
|
||||||
# OkHttp
|
# OkHttp
|
||||||
okhttp-core = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" }
|
okhttp-core = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" }
|
||||||
okhttp-logging = { module = "com.squareup.okhttp3:logging-interceptor", version.ref = "okhttp" }
|
okhttp-logging = { module = "com.squareup.okhttp3:logging-interceptor", version.ref = "okhttp" }
|
||||||
okhttp-dnsoverhttps = { module = "com.squareup.okhttp3:okhttp-dnsoverhttps", version.ref = "okhttp" }
|
okhttp-dnsoverhttps = { module = "com.squareup.okhttp3:okhttp-dnsoverhttps", version.ref = "okhttp" }
|
||||||
okhttp-brotli = { module = "com.squareup.okhttp3:okhttp-brotli", version.ref = "okhttp" }
|
okhttp-brotli = { module = "com.squareup.okhttp3:okhttp-brotli", version.ref = "okhttp" }
|
||||||
okio = "com.squareup.okio:okio:3.16.4"
|
okio = "com.squareup.okio:okio:3.17.0"
|
||||||
|
|
||||||
# Javalin api
|
# Javalin api
|
||||||
javalin-core = { module = "io.javalin:javalin", version.ref = "javalin" }
|
javalin-core = { module = "io.javalin:javalin", version.ref = "javalin" }
|
||||||
javalin-openapi = { module = "io.javalin:javalin-openapi", version.ref = "javalin" }
|
javalin-openapi = { module = "io.javalin:javalin-openapi", version.ref = "javalin" }
|
||||||
javalin-rendering = { module = "io.javalin:javalin-rendering", version.ref = "javalin" }
|
javalin-rendering = { module = "io.javalin:javalin-rendering-jte", version.ref = "javalin" }
|
||||||
jackson-databind = { module = "com.fasterxml.jackson.core:jackson-databind", version.ref = "jackson" }
|
jackson-databind = { module = "tools.jackson.core:jackson-databind", version.ref = "jackson" }
|
||||||
jackson-kotlin = { module = "com.fasterxml.jackson.module:jackson-module-kotlin", version.ref = "jackson" }
|
jackson-kotlin = { module = "tools.jackson.module:jackson-module-kotlin", version.ref = "jackson" }
|
||||||
jackson-annotations = { module = "com.fasterxml.jackson.core:jackson-annotations", version.ref = "jackson" }
|
jackson-annotations = "com.fasterxml.jackson.core:jackson-annotations:2.20"
|
||||||
jte = { module = "gg.jte:jte", version.ref = "jte" }
|
jte = { module = "gg.jte:jte", version.ref = "jte" }
|
||||||
kte = { module = "gg.jte:jte-kotlin", version.ref = "jte" }
|
kte = { module = "gg.jte:jte-kotlin", version.ref = "jte" }
|
||||||
|
|
||||||
@@ -68,7 +68,7 @@ exposed-core = { module = "org.jetbrains.exposed:exposed-core", version.ref = "e
|
|||||||
exposed-dao = { module = "org.jetbrains.exposed:exposed-dao", version.ref = "exposed" }
|
exposed-dao = { module = "org.jetbrains.exposed:exposed-dao", version.ref = "exposed" }
|
||||||
exposed-jdbc = { module = "org.jetbrains.exposed:exposed-jdbc", version.ref = "exposed" }
|
exposed-jdbc = { module = "org.jetbrains.exposed:exposed-jdbc", version.ref = "exposed" }
|
||||||
exposed-javatime = { module = "org.jetbrains.exposed:exposed-java-time", version.ref = "exposed" }
|
exposed-javatime = { module = "org.jetbrains.exposed:exposed-java-time", version.ref = "exposed" }
|
||||||
postgres = "org.postgresql:postgresql:42.7.10"
|
postgres = "org.postgresql:postgresql:42.7.11"
|
||||||
h2 = "com.h2database:h2:1.4.200" # current database driver, can't update to h2 v2 without sql migration
|
h2 = "com.h2database:h2:1.4.200" # current database driver, can't update to h2 v2 without sql migration
|
||||||
hikaricp = "com.zaxxer:HikariCP:7.0.2"
|
hikaricp = "com.zaxxer:HikariCP:7.0.2"
|
||||||
|
|
||||||
@@ -86,10 +86,10 @@ systemtray-desktop = "com.dorkbox:Desktop:1.1" # version locked by SystemTray
|
|||||||
# dependencies of Tachiyomi extensions
|
# dependencies of Tachiyomi extensions
|
||||||
injekt = "com.github.null2264:injekt-koin:ee267b2e27"
|
injekt = "com.github.null2264:injekt-koin:ee267b2e27"
|
||||||
rxjava = "io.reactivex:rxjava:1.3.8"
|
rxjava = "io.reactivex:rxjava:1.3.8"
|
||||||
jsoup = "org.jsoup:jsoup:1.22.1"
|
jsoup = "org.jsoup:jsoup:1.22.2"
|
||||||
|
|
||||||
# Config
|
# Config
|
||||||
config = "com.typesafe:config:1.4.5"
|
config = "com.typesafe:config:1.4.8"
|
||||||
config4k = "io.github.config4k:config4k:0.7.0"
|
config4k = "io.github.config4k:config4k:0.7.0"
|
||||||
|
|
||||||
# Sort
|
# Sort
|
||||||
@@ -105,7 +105,7 @@ dex2jar-tools = { module = "de.femtopedia.dex2jar:dex-tools", version.ref = "dex
|
|||||||
|
|
||||||
# APK
|
# APK
|
||||||
apk-parser = "net.dongliu:apk-parser:2.6.10"
|
apk-parser = "net.dongliu:apk-parser:2.6.10"
|
||||||
apksig = "com.android.tools.build:apksig:9.0.1"
|
apksig = "com.android.tools.build:apksig:9.2.1"
|
||||||
|
|
||||||
# Xml
|
# Xml
|
||||||
xmlpull = "xmlpull:xmlpull:1.1.3.4a"
|
xmlpull = "xmlpull:xmlpull:1.1.3.4a"
|
||||||
@@ -115,13 +115,13 @@ appdirs = "ca.gosyer:kotlin-multiplatform-appdirs:2.0.0"
|
|||||||
cache4k = "io.github.reactivecircus.cache4k:cache4k:0.14.0"
|
cache4k = "io.github.reactivecircus.cache4k:cache4k:0.14.0"
|
||||||
zip4j = "net.lingala.zip4j:zip4j:2.11.6"
|
zip4j = "net.lingala.zip4j:zip4j:2.11.6"
|
||||||
commonscompress = "org.apache.commons:commons-compress:1.28.0"
|
commonscompress = "org.apache.commons:commons-compress:1.28.0"
|
||||||
junrar = "com.github.junrar:junrar:7.5.7"
|
junrar = "com.github.junrar:junrar:7.5.10"
|
||||||
|
|
||||||
# AES/CBC/PKCS7Padding Cypher provider
|
# AES/CBC/PKCS7Padding Cypher provider
|
||||||
bouncycastle = "org.bouncycastle:bcprov-jdk18on:1.83"
|
bouncycastle = "org.bouncycastle:bcprov-jdk18on:1.84"
|
||||||
|
|
||||||
# AndroidX annotations
|
# AndroidX annotations
|
||||||
android-annotations = "androidx.annotation:annotation:1.9.1"
|
android-annotations = "androidx.annotation:annotation:1.10.0"
|
||||||
|
|
||||||
# Substitute for duktape-android
|
# Substitute for duktape-android
|
||||||
polyglot-core = { module = "org.graalvm.polyglot:polyglot", version.ref = "polyglot" }
|
polyglot-core = { module = "org.graalvm.polyglot:polyglot", version.ref = "polyglot" }
|
||||||
@@ -132,7 +132,7 @@ settings-core = { module = "com.russhwolf:multiplatform-settings-jvm", version.r
|
|||||||
settings-serialization = { module = "com.russhwolf:multiplatform-settings-serialization-jvm", version.ref = "settings" }
|
settings-serialization = { module = "com.russhwolf:multiplatform-settings-serialization-jvm", version.ref = "settings" }
|
||||||
|
|
||||||
# ICU4J
|
# ICU4J
|
||||||
icu4j = "com.ibm.icu:icu4j:78.2"
|
icu4j = "com.ibm.icu:icu4j:78.3"
|
||||||
|
|
||||||
# Image Decoding implementation provider
|
# Image Decoding implementation provider
|
||||||
twelvemonkeys-common-lang = { module = "com.twelvemonkeys.common:common-lang", version.ref = "twelvemonkeys" }
|
twelvemonkeys-common-lang = { module = "com.twelvemonkeys.common:common-lang", version.ref = "twelvemonkeys" }
|
||||||
@@ -158,7 +158,7 @@ cronUtils = "com.cronutils:cron-utils:9.2.1"
|
|||||||
kcef = "dev.datlag:kcef:2024.04.20.4"
|
kcef = "dev.datlag:kcef:2024.04.20.4"
|
||||||
|
|
||||||
# User
|
# User
|
||||||
jwt = "com.auth0:java-jwt:4.5.1"
|
jwt = "com.auth0:java-jwt:4.5.2"
|
||||||
|
|
||||||
# lint - used for renovate to update ktlint version
|
# lint - used for renovate to update ktlint version
|
||||||
ktlint = { module = "com.pinterest.ktlint:ktlint-cli", version.ref = "ktlint" }
|
ktlint = { module = "com.pinterest.ktlint:ktlint-cli", version.ref = "ktlint" }
|
||||||
@@ -173,16 +173,16 @@ kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", versi
|
|||||||
kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin"}
|
kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin"}
|
||||||
|
|
||||||
# Linter
|
# Linter
|
||||||
ktlint = { id = "org.jlleitschuh.gradle.ktlint", version = "14.0.1"}
|
ktlint = { id = "org.jlleitschuh.gradle.ktlint", version = "14.2.0"}
|
||||||
|
|
||||||
# Build config
|
# Build config
|
||||||
buildconfig = { id = "com.github.gmazzo.buildconfig", version = "6.0.7"}
|
buildconfig = { id = "com.github.gmazzo.buildconfig", version = "6.0.9"}
|
||||||
|
|
||||||
# Download
|
# Download
|
||||||
download = { id = "de.undercouch.download", version = "5.7.0"}
|
download = { id = "de.undercouch.download", version = "5.7.0"}
|
||||||
|
|
||||||
# ShadowJar
|
# ShadowJar
|
||||||
shadowjar = { id = "com.gradleup.shadow", version = "8.3.9"}
|
shadowjar = { id = "com.gradleup.shadow", version = "8.3.10"}
|
||||||
|
|
||||||
# Moko
|
# Moko
|
||||||
moko = { id = "dev.icerock.mobile.multiplatform-resources", version.ref = "moko" }
|
moko = { id = "dev.icerock.mobile.multiplatform-resources", version.ref = "moko" }
|
||||||
|
|||||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,7 +1,9 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.1-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.0-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
|
retries=0
|
||||||
|
retryBackOffMs=500
|
||||||
validateDistributionUrl=true
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|||||||
2
gradlew
vendored
2
gradlew
vendored
@@ -57,7 +57,7 @@
|
|||||||
# Darwin, MinGW, and NonStop.
|
# Darwin, MinGW, and NonStop.
|
||||||
#
|
#
|
||||||
# (3) This script is generated from the Groovy template
|
# (3) This script is generated from the Groovy template
|
||||||
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
# https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||||
# within the Gradle project.
|
# within the Gradle project.
|
||||||
#
|
#
|
||||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||||
|
|||||||
31
gradlew.bat
vendored
31
gradlew.bat
vendored
@@ -23,8 +23,8 @@
|
|||||||
@rem
|
@rem
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
|
|
||||||
@rem Set local scope for the variables with windows NT shell
|
@rem Set local scope for the variables, and ensure extensions are enabled
|
||||||
if "%OS%"=="Windows_NT" setlocal
|
setlocal EnableExtensions
|
||||||
|
|
||||||
set DIRNAME=%~dp0
|
set DIRNAME=%~dp0
|
||||||
if "%DIRNAME%"=="" set DIRNAME=.
|
if "%DIRNAME%"=="" set DIRNAME=.
|
||||||
@@ -51,7 +51,7 @@ echo. 1>&2
|
|||||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
echo location of your Java installation. 1>&2
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
goto fail
|
"%COMSPEC%" /c exit 1
|
||||||
|
|
||||||
:findJavaFromJavaHome
|
:findJavaFromJavaHome
|
||||||
set JAVA_HOME=%JAVA_HOME:"=%
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
@@ -65,7 +65,7 @@ echo. 1>&2
|
|||||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
echo location of your Java installation. 1>&2
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
goto fail
|
"%COMSPEC%" /c exit 1
|
||||||
|
|
||||||
:execute
|
:execute
|
||||||
@rem Setup the command line
|
@rem Setup the command line
|
||||||
@@ -73,21 +73,10 @@ goto fail
|
|||||||
|
|
||||||
|
|
||||||
@rem Execute Gradle
|
@rem Execute Gradle
|
||||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
@rem endlocal doesn't take effect until after the line is parsed and variables are expanded
|
||||||
|
@rem which allows us to clear the local environment before executing the java command
|
||||||
|
endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel
|
||||||
|
|
||||||
:end
|
:exitWithErrorLevel
|
||||||
@rem End local scope for the variables with windows NT shell
|
@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts
|
||||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
"%COMSPEC%" /c exit %ERRORLEVEL%
|
||||||
|
|
||||||
:fail
|
|
||||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
|
||||||
rem the _cmd.exe /c_ return code!
|
|
||||||
set EXIT_CODE=%ERRORLEVEL%
|
|
||||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
|
||||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
|
||||||
exit /b %EXIT_CODE%
|
|
||||||
|
|
||||||
:mainEnd
|
|
||||||
if "%OS%"=="Windows_NT" endlocal
|
|
||||||
|
|
||||||
:omega
|
|
||||||
|
|||||||
@@ -140,17 +140,16 @@ fun OkHttpClient.newCachelessCallWithProgress(
|
|||||||
return progressClient.newCall(request)
|
return progressClient.newCall(request)
|
||||||
}
|
}
|
||||||
|
|
||||||
context(Json)
|
context(_: Json)
|
||||||
inline fun <reified T> Response.parseAs(): T = decodeFromJsonResponse(serializer(), this)
|
inline fun <reified T> Response.parseAs(): T = decodeFromJsonResponse(serializer(), this)
|
||||||
|
|
||||||
@OptIn(ExperimentalSerializationApi::class)
|
context(json: Json)
|
||||||
context(Json)
|
|
||||||
fun <T> decodeFromJsonResponse(
|
fun <T> decodeFromJsonResponse(
|
||||||
deserializer: DeserializationStrategy<T>,
|
deserializer: DeserializationStrategy<T>,
|
||||||
response: Response,
|
response: Response,
|
||||||
): T =
|
): T =
|
||||||
response.body.source().use {
|
response.body.source().use {
|
||||||
decodeFromBufferedSource(deserializer, it)
|
json.decodeFromBufferedSource(deserializer, it)
|
||||||
}
|
}
|
||||||
|
|
||||||
class HttpException(
|
class HttpException(
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import io.javalin.websocket.WsMessageContext
|
|||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import org.eclipse.jetty.websocket.api.CloseStatus
|
import org.eclipse.jetty.websocket.core.CloseStatus
|
||||||
import suwayomi.tachidesk.manga.impl.update.Websocket
|
import suwayomi.tachidesk.manga.impl.update.Websocket
|
||||||
|
|
||||||
object WebView : Websocket<String>() {
|
object WebView : Websocket<String>() {
|
||||||
|
|||||||
@@ -13,10 +13,14 @@ import com.expediagroup.graphql.server.types.GraphQLRequest
|
|||||||
import com.expediagroup.graphql.server.types.GraphQLServerRequest
|
import com.expediagroup.graphql.server.types.GraphQLServerRequest
|
||||||
import io.javalin.http.Context
|
import io.javalin.http.Context
|
||||||
import io.javalin.http.UploadedFile
|
import io.javalin.http.UploadedFile
|
||||||
|
import io.javalin.json.JavalinJackson
|
||||||
|
import io.javalin.json.fromJsonStream
|
||||||
import io.javalin.json.fromJsonString
|
import io.javalin.json.fromJsonString
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
|
||||||
class JavalinGraphQLRequestParser : GraphQLRequestParser<Context> {
|
class JavalinGraphQLRequestParser : GraphQLRequestParser<Context> {
|
||||||
|
val jsonMapper = JavalinJackson()
|
||||||
|
|
||||||
@Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE")
|
@Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE")
|
||||||
override suspend fun parseRequest(context: Context): GraphQLServerRequest? {
|
override suspend fun parseRequest(context: Context): GraphQLServerRequest? {
|
||||||
return try {
|
return try {
|
||||||
@@ -29,17 +33,17 @@ class JavalinGraphQLRequestParser : GraphQLRequestParser<Context> {
|
|||||||
context.formParam("operations")
|
context.formParam("operations")
|
||||||
?: throw IllegalArgumentException("Cannot find 'operations' body")
|
?: throw IllegalArgumentException("Cannot find 'operations' body")
|
||||||
} else {
|
} else {
|
||||||
return context.bodyAsClass(GraphQLServerRequest::class.java)
|
return context.bodyInputStream().use { jsonMapper.fromJsonStream<GraphQLServerRequest>(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
val request =
|
val request =
|
||||||
context.jsonMapper().fromJsonString<GraphQLServerRequest>(formParam)
|
jsonMapper.fromJsonString<GraphQLServerRequest>(formParam)
|
||||||
|
|
||||||
val map =
|
val map =
|
||||||
context
|
context
|
||||||
.formParam("map")
|
.formParam("map")
|
||||||
?.let {
|
?.let {
|
||||||
context.jsonMapper().fromJsonString<Map<String, List<String>>>(it)
|
jsonMapper.fromJsonString<Map<String, List<String>>>(it)
|
||||||
}.orEmpty()
|
}.orEmpty()
|
||||||
|
|
||||||
val mapItems =
|
val mapItems =
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import kotlinx.coroutines.flow.onCompletion
|
|||||||
import kotlinx.coroutines.flow.onStart
|
import kotlinx.coroutines.flow.onStart
|
||||||
import kotlinx.coroutines.job
|
import kotlinx.coroutines.job
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.eclipse.jetty.websocket.api.CloseStatus
|
import org.eclipse.jetty.websocket.core.CloseStatus
|
||||||
import suwayomi.tachidesk.graphql.server.TachideskGraphQLContextFactory
|
import suwayomi.tachidesk.graphql.server.TachideskGraphQLContextFactory
|
||||||
import suwayomi.tachidesk.graphql.server.subscriptions.SubscriptionOperationMessage.ClientMessages.GQL_CONNECTION_INIT
|
import suwayomi.tachidesk.graphql.server.subscriptions.SubscriptionOperationMessage.ClientMessages.GQL_CONNECTION_INIT
|
||||||
import suwayomi.tachidesk.graphql.server.subscriptions.SubscriptionOperationMessage.ClientMessages.GQL_SUBSCRIBE
|
import suwayomi.tachidesk.graphql.server.subscriptions.SubscriptionOperationMessage.ClientMessages.GQL_SUBSCRIBE
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import kotlinx.coroutines.Job
|
|||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.emptyFlow
|
import kotlinx.coroutines.flow.emptyFlow
|
||||||
import kotlinx.coroutines.flow.onCompletion
|
import kotlinx.coroutines.flow.onCompletion
|
||||||
import org.eclipse.jetty.websocket.api.CloseStatus
|
import org.eclipse.jetty.websocket.core.CloseStatus
|
||||||
import suwayomi.tachidesk.graphql.server.toGraphQLContext
|
import suwayomi.tachidesk.graphql.server.toGraphQLContext
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
import java.util.concurrent.CopyOnWriteArrayList
|
import java.util.concurrent.CopyOnWriteArrayList
|
||||||
|
|||||||
@@ -13,12 +13,14 @@ import io.github.oshai.kotlinlogging.KotlinLogging
|
|||||||
import io.javalin.Javalin
|
import io.javalin.Javalin
|
||||||
import io.javalin.apibuilder.ApiBuilder.after
|
import io.javalin.apibuilder.ApiBuilder.after
|
||||||
import io.javalin.apibuilder.ApiBuilder.path
|
import io.javalin.apibuilder.ApiBuilder.path
|
||||||
|
import io.javalin.config.RoutesConfig
|
||||||
import io.javalin.http.Context
|
import io.javalin.http.Context
|
||||||
import io.javalin.http.HandlerType
|
import io.javalin.http.HandlerType
|
||||||
import io.javalin.http.HttpStatus
|
import io.javalin.http.HttpStatus
|
||||||
import io.javalin.http.NotFoundResponse
|
import io.javalin.http.NotFoundResponse
|
||||||
import io.javalin.http.RedirectResponse
|
import io.javalin.http.RedirectResponse
|
||||||
import io.javalin.http.UnauthorizedResponse
|
import io.javalin.http.UnauthorizedResponse
|
||||||
|
import io.javalin.json.JavalinJackson3
|
||||||
import io.javalin.rendering.template.JavalinJte
|
import io.javalin.rendering.template.JavalinJte
|
||||||
import io.javalin.websocket.WsContext
|
import io.javalin.websocket.WsContext
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
@@ -47,6 +49,7 @@ import java.net.URLEncoder
|
|||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import java.util.concurrent.CompletableFuture
|
import java.util.concurrent.CompletableFuture
|
||||||
import kotlin.concurrent.thread
|
import kotlin.concurrent.thread
|
||||||
|
import kotlin.text.get
|
||||||
import kotlin.time.Duration.Companion.days
|
import kotlin.time.Duration.Companion.days
|
||||||
|
|
||||||
object JavalinSetup {
|
object JavalinSetup {
|
||||||
@@ -58,10 +61,12 @@ object JavalinSetup {
|
|||||||
|
|
||||||
fun javalinSetup() {
|
fun javalinSetup() {
|
||||||
val app =
|
val app =
|
||||||
Javalin.create { config ->
|
Javalin.start { config ->
|
||||||
val templateEngine = TemplateEngine.createPrecompiled(ContentType.Html)
|
val templateEngine = TemplateEngine.createPrecompiled(ContentType.Html)
|
||||||
config.fileRenderer(JavalinJte(templateEngine))
|
config.fileRenderer(JavalinJte(templateEngine))
|
||||||
|
|
||||||
|
config.jsonMapper(JavalinJackson3())
|
||||||
|
|
||||||
WebInterfaceManager.setup(config)
|
WebInterfaceManager.setup(config)
|
||||||
|
|
||||||
// config.registerPlugin(OpenApiPlugin(getOpenApiOptions()))
|
// config.registerPlugin(OpenApiPlugin(getOpenApiOptions()))
|
||||||
@@ -104,7 +109,8 @@ object JavalinSetup {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
config.router.apiBuilder {
|
config.routes.defineCore()
|
||||||
|
config.routes.apiBuilder {
|
||||||
path(ServerSubpath.maybeAddAsPrefix("api/")) {
|
path(ServerSubpath.maybeAddAsPrefix("api/")) {
|
||||||
path("v1/") {
|
path("v1/") {
|
||||||
GlobalAPI.defineEndpoints()
|
GlobalAPI.defineEndpoints()
|
||||||
@@ -117,17 +123,32 @@ object JavalinSetup {
|
|||||||
after { ctx ->
|
after { ctx ->
|
||||||
// If not matched, the request was for an invalid endpoint
|
// If not matched, the request was for an invalid endpoint
|
||||||
// Return a 404 instead of redirecting to the UI for usability
|
// Return a 404 instead of redirecting to the UI for usability
|
||||||
if (ctx.endpointHandlerPath() == "*") {
|
if (ctx.endpoints().lastHttpEndpoint()?.path == "*") {
|
||||||
throw NotFoundResponse()
|
throw NotFoundResponse()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
config.events.serverStarted {
|
||||||
|
if (serverConfig.initialOpenInBrowserEnabled.value) {
|
||||||
|
Browser.openInBrowser()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// when JVM is prompted to shutdown, stop javalin gracefully
|
||||||
|
Runtime.getRuntime().addShutdownHook(
|
||||||
|
thread(start = false) {
|
||||||
|
app.stop()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun RoutesConfig.defineCore() {
|
||||||
val loginPath = ServerSubpath.maybeAddAsPrefix("/login.html")
|
val loginPath = ServerSubpath.maybeAddAsPrefix("/login.html")
|
||||||
|
|
||||||
app.get(loginPath) { ctx ->
|
get(loginPath) { ctx ->
|
||||||
val locale: Locale = LocalizationHelper.ctxToLocale(ctx)
|
val locale: Locale = LocalizationHelper.ctxToLocale(ctx)
|
||||||
ctx.header("content-type", "text/html")
|
ctx.header("content-type", "text/html")
|
||||||
val httpCacheSeconds = 1.days.inWholeSeconds
|
val httpCacheSeconds = 1.days.inWholeSeconds
|
||||||
@@ -141,7 +162,7 @@ object JavalinSetup {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
app.post(loginPath) { ctx ->
|
post(loginPath) { ctx ->
|
||||||
val username = ctx.formParam("user")
|
val username = ctx.formParam("user")
|
||||||
val password = ctx.formParam("pass")
|
val password = ctx.formParam("pass")
|
||||||
val isValid =
|
val isValid =
|
||||||
@@ -174,7 +195,7 @@ object JavalinSetup {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
app.beforeMatched { ctx ->
|
beforeMatched { ctx ->
|
||||||
val isWebManifest =
|
val isWebManifest =
|
||||||
listOf("site.webmanifest", "manifest.json", "login.html").any { ctx.path().endsWith(it) }
|
listOf("site.webmanifest", "manifest.json", "login.html").any { ctx.path().endsWith(it) }
|
||||||
val isPageIcon =
|
val isPageIcon =
|
||||||
@@ -219,60 +240,43 @@ object JavalinSetup {
|
|||||||
ctx.setAttribute(Attribute.TachideskBasic, credentialsValid())
|
ctx.setAttribute(Attribute.TachideskBasic, credentialsValid())
|
||||||
}
|
}
|
||||||
|
|
||||||
app.events { event ->
|
wsBefore {
|
||||||
event.serverStarted {
|
|
||||||
if (serverConfig.initialOpenInBrowserEnabled.value) {
|
|
||||||
Browser.openInBrowser()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
app.wsBefore {
|
|
||||||
it.onConnect { ctx ->
|
it.onConnect { ctx ->
|
||||||
ctx.setAttribute(Attribute.TachideskUser, getUserFromWsContext(ctx))
|
ctx.setAttribute(Attribute.TachideskUser, getUserFromWsContext(ctx))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// when JVM is prompted to shutdown, stop javalin gracefully
|
exception(NullPointerException::class.java) { e, ctx ->
|
||||||
Runtime.getRuntime().addShutdownHook(
|
|
||||||
thread(start = false) {
|
|
||||||
app.stop()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
app.exception(NullPointerException::class.java) { e, ctx ->
|
|
||||||
logger.error(e) { "NullPointerException while handling the request" }
|
logger.error(e) { "NullPointerException while handling the request" }
|
||||||
ctx.status(404)
|
ctx.status(404)
|
||||||
}
|
}
|
||||||
app.exception(NoSuchElementException::class.java) { e, ctx ->
|
exception(NoSuchElementException::class.java) { e, ctx ->
|
||||||
logger.error(e) { "NoSuchElementException while handling the request" }
|
logger.error(e) { "NoSuchElementException while handling the request" }
|
||||||
ctx.status(404)
|
ctx.status(404)
|
||||||
}
|
}
|
||||||
app.exception(IOException::class.java) { e, ctx ->
|
exception(IOException::class.java) { e, ctx ->
|
||||||
logger.error(e) { "IOException while handling the request" }
|
logger.error(e) { "IOException while handling the request" }
|
||||||
ctx.status(500)
|
ctx.status(500)
|
||||||
ctx.result(e.message ?: "Internal Server Error")
|
ctx.result(e.message ?: "Internal Server Error")
|
||||||
}
|
}
|
||||||
|
|
||||||
app.exception(IllegalArgumentException::class.java) { e, ctx ->
|
exception(IllegalArgumentException::class.java) { e, ctx ->
|
||||||
logger.error(e) { "IllegalArgumentException while handling the request" }
|
logger.error(e) { "IllegalArgumentException while handling the request" }
|
||||||
ctx.status(400)
|
ctx.status(400)
|
||||||
ctx.result(e.message ?: "Bad Request")
|
ctx.result(e.message ?: "Bad Request")
|
||||||
}
|
}
|
||||||
|
|
||||||
app.exception(UnauthorizedException::class.java) { e, ctx ->
|
exception(UnauthorizedException::class.java) { e, ctx ->
|
||||||
logger.error(e) { "UnauthorizedException while handling the request" }
|
logger.error(e) { "UnauthorizedException while handling the request" }
|
||||||
ctx.status(HttpStatus.UNAUTHORIZED)
|
ctx.status(HttpStatus.UNAUTHORIZED)
|
||||||
ctx.result(e.message ?: "Unauthorized")
|
ctx.result(e.message ?: "Unauthorized")
|
||||||
}
|
}
|
||||||
|
|
||||||
app.exception(ForbiddenException::class.java) { e, ctx ->
|
exception(ForbiddenException::class.java) { e, ctx ->
|
||||||
logger.error(e) { "ForbiddenException while handling the request" }
|
logger.error(e) { "ForbiddenException while handling the request" }
|
||||||
ctx.status(HttpStatus.FORBIDDEN)
|
ctx.status(HttpStatus.FORBIDDEN)
|
||||||
ctx.result(e.message ?: "Forbidden")
|
ctx.result(e.message ?: "Forbidden")
|
||||||
}
|
}
|
||||||
|
|
||||||
app.start()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// private fun getOpenApiOptions(): OpenApiOptions {
|
// private fun getOpenApiOptions(): OpenApiOptions {
|
||||||
|
|||||||
@@ -71,15 +71,14 @@ fun <T> getParam(
|
|||||||
is Param.FormParam -> ctx.formParamAsClass(param.key, clazz)
|
is Param.FormParam -> ctx.formParamAsClass(param.key, clazz)
|
||||||
is Param.PathParam -> ctx.pathParamAsClass(param.key, clazz)
|
is Param.PathParam -> ctx.pathParamAsClass(param.key, clazz)
|
||||||
is Param.QueryParam -> ctx.queryParamAsClass(param.key, clazz)
|
is Param.QueryParam -> ctx.queryParamAsClass(param.key, clazz)
|
||||||
else -> throw IllegalStateException("Invalid param")
|
|
||||||
}.let {
|
}.let {
|
||||||
if (param.nullable) {
|
if (param.nullable) {
|
||||||
it.allowNullable().get() ?: param.defaultValue
|
it.getOrNull() ?: param.defaultValue
|
||||||
} else {
|
} else {
|
||||||
if (param.defaultValue != null) {
|
if (param.defaultValue != null) {
|
||||||
it.getOrDefault(param.defaultValue!!)
|
it.getOrDefault(param.defaultValue!!)
|
||||||
} else {
|
} else {
|
||||||
it.get()
|
it.required().get()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import io.github.oshai.kotlinlogging.KLogger
|
|||||||
import io.github.oshai.kotlinlogging.KotlinLogging
|
import io.github.oshai.kotlinlogging.KotlinLogging
|
||||||
import io.github.reactivecircus.cache4k.Cache
|
import io.github.reactivecircus.cache4k.Cache
|
||||||
import io.javalin.config.JavalinConfig
|
import io.javalin.config.JavalinConfig
|
||||||
|
import io.javalin.http.staticfiles.AliasCheck
|
||||||
import io.javalin.http.staticfiles.Location
|
import io.javalin.http.staticfiles.Location
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||||
@@ -39,7 +40,6 @@ import kotlinx.serialization.json.jsonArray
|
|||||||
import kotlinx.serialization.json.jsonObject
|
import kotlinx.serialization.json.jsonObject
|
||||||
import kotlinx.serialization.json.jsonPrimitive
|
import kotlinx.serialization.json.jsonPrimitive
|
||||||
import net.lingala.zip4j.ZipFile
|
import net.lingala.zip4j.ZipFile
|
||||||
import org.eclipse.jetty.server.handler.ContextHandler
|
|
||||||
import suwayomi.tachidesk.graphql.types.AboutWebUI
|
import suwayomi.tachidesk.graphql.types.AboutWebUI
|
||||||
import suwayomi.tachidesk.graphql.types.UpdateState
|
import suwayomi.tachidesk.graphql.types.UpdateState
|
||||||
import suwayomi.tachidesk.graphql.types.UpdateState.DOWNLOADING
|
import suwayomi.tachidesk.graphql.types.UpdateState.DOWNLOADING
|
||||||
@@ -180,7 +180,7 @@ object WebInterfaceManager {
|
|||||||
// Use canonical path to avoid Jetty alias issues
|
// Use canonical path to avoid Jetty alias issues
|
||||||
staticFiles.directory = File(applicationDirs.webUIServe).canonicalPath
|
staticFiles.directory = File(applicationDirs.webUIServe).canonicalPath
|
||||||
staticFiles.location = Location.EXTERNAL
|
staticFiles.location = Location.EXTERNAL
|
||||||
staticFiles.aliasCheck = ContextHandler.ApproveAliases()
|
staticFiles.aliasCheck = AliasCheck { _, _ -> true }
|
||||||
}
|
}
|
||||||
|
|
||||||
serveWebUI = {
|
serveWebUI = {
|
||||||
@@ -304,11 +304,25 @@ object WebInterfaceManager {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val flavor = WebUIFlavor.current
|
|
||||||
val servedFlavor = getServedWebUIFlavor()
|
val servedFlavor = getServedWebUIFlavor()
|
||||||
|
|
||||||
val log =
|
val log =
|
||||||
KotlinLogging.logger("${logger.name} setupWebUI(flavor= ${flavor.uiName}, servedFlavor= ${servedFlavor.uiName})")
|
KotlinLogging.logger(
|
||||||
|
"${logger.name} setupWebUI(flavor= ${WebUIFlavor.current.uiName}, servedFlavor= ${servedFlavor.uiName}, channel= ${serverConfig.webUIChannel})",
|
||||||
|
)
|
||||||
|
|
||||||
|
val flavor =
|
||||||
|
if (serverConfig.webUIChannel.value == WebUIChannel.BUNDLED) {
|
||||||
|
if (serverConfig.webUIFlavor.value != WebUIFlavor.default) {
|
||||||
|
log.warn {
|
||||||
|
"Changed flavor to ${WebUIFlavor.default.uiName}. Channel \"${WebUIChannel.BUNDLED}\" only works with the default flavor"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WebUIFlavor.default
|
||||||
|
} else {
|
||||||
|
WebUIFlavor.current
|
||||||
|
}
|
||||||
|
|
||||||
if (doesLocalWebUIExist(applicationDirs.webUIRoot)) {
|
if (doesLocalWebUIExist(applicationDirs.webUIRoot)) {
|
||||||
val currentVersion = getLocalVersion()
|
val currentVersion = getLocalVersion()
|
||||||
|
|||||||
Reference in New Issue
Block a user