Compare commits

..

No commits in common. "master" and "v0.3.0" have entirely different histories.

1198 changed files with 2658 additions and 193281 deletions

View file

@ -1,33 +0,0 @@
root=true
[*]
charset=utf-8
end_of_line=lf
indent_size=4
indent_style=space
insert_final_newline=true
max_line_length=120
tab_width=4
trim_trailing_whitespace=true
[{*.ats,*.ts}]
indent_size=2
tab_width=2
[{*.cjs,*.js}]
indent_size=2
tab_width=2
[{*.kts,*.kt}]
indent_size=2
tab_width=2
max_line_length=off
ij_kotlin_allow_trailing_comma=true
ij_kotlin_allow_trailing_comma_on_call_site=true
ktlint_standard_multiline-if-else=disabled
[{*.yml,*.yaml}]
indent_size=2
[{.eslintrc,bowerrc,.prettierrc,.releaserc,jest.config,.stylelintrc,.babelrc,*.jsb3,*.jsb2,*.json}]
indent_size=2

1
.gitattributes vendored
View file

@ -1 +0,0 @@
* text=auto

12
.github/FUNDING.yml vendored
View file

@ -1,12 +0,0 @@
# These are supported funding model platforms
github: gotson # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
# patreon: # Replace with a single Patreon username
open_collective: komga
ko_fi: gotson
# tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
# community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
# liberapay: # Replace with a single Liberapay username
# issuehunt: # Replace with a single IssueHunt username
# otechie: # Replace with a single Otechie username
# custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

View file

@ -1,11 +0,0 @@
blank_issues_enabled: false
contact_links:
- name: 💡Feature idea
url: https://github.com/gotson/komga/discussions/new?category=ideas
about: Suggest a feature to improve Komga
- name: 🖥️ Komga website
url: https://komga.org/docs/faq
about: Guides, troubleshooting, and answers to common questions
- name: ⚠️ Mihon extension
url: https://github.com/keiyoushi/extensions-source
about: Issues and requests about the Mihon extension should be opened in the keiyoushi/extensions repository instead

View file

@ -1,108 +0,0 @@
name: 🐞 Issue report
description: Report an issue in Komga
labels:
- triage
body:
- type: textarea
id: reproduce-steps
attributes:
label: Steps to reproduce
description: Provide an example of the issue.
placeholder: |
Example:
1. First step
2. Second step
3. Issue here
validations:
required: true
- type: textarea
id: expected-behavior
attributes:
label: Expected behavior
description: Explain what you should expect to happen.
placeholder: |
Example:
"This should happen..."
validations:
required: true
- type: textarea
id: actual-behavior
attributes:
label: Actual behavior
description: Explain what actually happens.
placeholder: |
Example:
"This happened instead..."
validations:
required: true
- type: textarea
id: logfile
attributes:
label: Logs
description: |
:warning: **Do not share logs with Kobo Sync information publicly !**
If applicable, add an excerpt of the log file (max 20 lines) _AND_ attach the complete log file or a link to a gist/pastebin containing the log file ([where to find the logs](https://komga.org/docs/faq#where-can-i-find-the-log-files)).
placeholder: |
You can paste the logs in pure text or upload it as an attachment.
- type: input
id: komga-version
attributes:
label: Komga version
description: You can find your Komga version at the bottom of the side bar.
placeholder: |
Example: "1.7.1"
validations:
required: true
- type: input
id: operating-system
attributes:
label: Operating system
placeholder: |
Example: "Windows 11"
validations:
required: true
- type: dropdown
attributes:
label: Installation method
description: How did you install Komga?
multiple: false
options:
- jar
- Docker
- Microsoft Store
- from download.komga.org
- other (please provide more details below)
validations:
required: true
- type: textarea
id: other-details
attributes:
label: Other details
placeholder: |
Additional details and attachments.
- type: checkboxes
id: acknowledgements
attributes:
label: Acknowledgements
description: Read this carefully, we will close and ignore your issue if you skimmed through this.
options:
- label: I have searched the existing issues (open AND closed) and this is a new ticket, **NOT** a duplicate or related to another open issue.
required: true
- label: I have written a short but informative title.
required: true
- label: I have checked the [FAQ](https://komga.org/docs/faq).
required: true
- label: I have updated the app to the latest version.
required: true
- label: I will fill out all of the requested information in this form.
required: true

View file

@ -1,37 +0,0 @@
version: 2
updates:
- package-ecosystem: "npm"
directory: "/komga-webui"
open-pull-requests-limit: 0
commit-message:
prefix: "deps(webui)"
# include: "scope"
schedule:
interval: "weekly"
- package-ecosystem: "gradle"
directory: "/komga"
open-pull-requests-limit: 0
commit-message:
prefix: "deps(komga)"
# include: "scope"
schedule:
interval: "weekly"
- package-ecosystem: "gradle"
directory: "/komga-tray"
open-pull-requests-limit: 0
commit-message:
prefix: "deps(komga-tray)"
# include: "scope"
schedule:
interval: "weekly"
# Maintain dependencies for GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
commit-message:
prefix: "deps(ci)"
# include: "scope"
schedule:
interval: "weekly"

View file

@ -1,13 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="298" height="64" fill="none" viewBox="0 0 298 64">
<defs>
<linearGradient id="a" x1=".850001" x2="62.62" y1="62.72" y2="1.81" gradientUnits="userSpaceOnUse">
<stop stop-color="#FF9419"/>
<stop offset=".43" stop-color="#FF021D"/>
<stop offset=".99" stop-color="#E600FF"/>
</linearGradient>
</defs>
<path fill="#000" d="M86.4844 40.5858c0 .8464-.1792 1.5933-.5377 2.2505-.3585.6573-.8564 1.1651-1.5137 1.5236-.6572.3585-1.3941.5378-2.2406.5378H78v6.1044h5.0787c1.912 0 3.6248-.4282 5.1484-1.2846 1.5236-.8564 2.7186-2.0415 3.585-3.5452.8663-1.5037 1.3045-3.1966 1.3045-5.0886V21.0178h-6.6322v19.568Zm17.8556-1.8224h13.891v-5.6065H104.34v-6.3633h15.355v-5.7758H97.8766v29.9743h22.2464v-5.7757H104.34v-6.453Zm17.865-11.8005h8.882v24.0193h6.633V26.9629h8.842v-5.9451h-24.367v5.9551l.01-.01Zm47.022 9.0022c-.517-.2788-1.085-.4879-1.673-.6472.449-.1295.877-.2888 1.275-.488 1.096-.5676 1.962-1.3643 2.579-2.39.618-1.0257.936-2.2007.936-3.5351 0-1.5237-.418-2.8879-1.244-4.0929-.827-1.195-1.992-2.131-3.486-2.8082-1.494-.6672-3.206-1.0058-5.118-1.0058h-13.315v29.9743h13.574c2.011 0 3.804-.3485 5.387-1.0556 1.573-.707 2.798-1.6829 3.675-2.9476.866-1.2547 1.304-2.6887 1.304-4.302 0-1.4837-.338-2.8082-1.026-3.9833-.687-1.175-1.633-2.0812-2.858-2.7285l-.01.0099Zm-13.603-9.9184h5.886c.816 0 1.533.1494 2.161.4382.627.2888 1.115.707 1.464 1.2547.348.5378.527 1.1751.527 1.9021 0 .7269-.179 1.414-.527 1.9817-.349.5676-.837.9958-1.464 1.3045-.628.3087-1.345.4581-2.161.4581h-5.886v-7.3492.0099Zm10.138 18.134c-.378.5676-.916 1.0058-1.603 1.3145-.697.3087-1.484.4581-2.39.4581h-6.145v-7.6878h6.145c.886 0 1.673.1693 2.37.4979.687.3286 1.235.7867 1.613 1.3842.378.5975.578 1.2747.578 2.0414 0 .7668-.19 1.4241-.568 1.9917Zm29.596-5.3077c1.663-.7967 2.947-1.922 3.864-3.3659.916-1.444 1.374-3.117 1.374-5.0289 0-1.912-.448-3.5253-1.344-4.9592-.897-1.434-2.171-2.5394-3.814-3.3261-1.644-.7867-3.546-1.1751-5.717-1.1751h-13.124v29.9743h6.642V40.0779h4.322l6.084 10.9142h7.578l-6.851-11.7208c.339-.1195.677-.249.996-.3983h-.01Zm-2.151-6.1244c-.369.6274-.896 1.1154-1.583 1.444-.688.3386-1.494.5079-2.42.5079h-5.975v-8.2953h5.975c.926 0 1.732.1693 2.42.4979.687.3287 1.214.8166 1.583 1.434.368.6174.558 1.3544.558 2.1908 0 .8365-.19 1.5734-.558 2.2008v.0199Zm20.594-11.7308-10.706 29.9743h6.742l2.121-6.6122h11.114l2.27 6.6122h6.612L220.99 21.0178h-7.189Zm-.339 18.3431 3.445-10.5756.409-1.922.408 1.922 3.685 10.5756h-7.947Zm20.693 11.6312h6.851V21.0178h-6.851v29.9743Zm31.02-9.6993-12.896-20.275h-6.463v29.9743h6.055V30.7172l12.826 20.2749h6.533V21.0178h-6.055v20.275Zm31.528-3.3559c-.647-1.2448-1.564-2.2904-2.729-3.1369-1.165-.8464-2.509-1.4041-4.023-1.6929l-5.098-1.0456c-.797-.1892-1.434-.5178-1.902-.9958-.469-.478-.708-1.0755-.708-1.7825 0-.6473.17-1.205.518-1.683.339-.478.827-.8464 1.444-1.1153.618-.2689 1.335-.3983 2.151-.3983.817 0 1.554.1394 2.181.4182.627.2788 1.115.6672 1.464 1.1751s.528 1.0755.528 1.7228h6.642c-.04-1.7427-.528-3.2863-1.444-4.6207-.916-1.3443-2.201-2.3899-3.834-3.1468-1.633-.7568-3.505-1.1352-5.597-1.1352-2.091 0-3.943.3884-5.566 1.1751-1.623.7867-2.898 1.8721-3.804 3.2663-.906 1.3941-1.364 2.9775-1.364 4.76 0 1.444.288 2.7485.876 3.9036.587 1.1652 1.414 2.1311 2.479 2.8979 1.076.7668 2.311 1.3045 3.725 1.6033l5.397 1.1153c.886.2091 1.584.5975 2.101 1.1551.518.5577.767 1.2448.767 2.0813 0 .6672-.189 1.2747-.567 1.8025-.379.5277-.907.936-1.584 1.2248-.677.2888-1.474.4282-2.39.4282-.916 0-1.782-.1593-2.529-.478-.747-.3186-1.325-.7767-1.733-1.3742-.418-.5875-.617-1.2747-.617-2.0414h-6.642c.029 1.8721.527 3.5152 1.513 4.9492.976 1.424 2.32 2.5394 4.033 3.336 1.713.7967 3.675 1.195 5.886 1.195 2.21 0 4.202-.4083 5.915-1.2249 1.723-.8165 3.057-1.9418 4.023-3.3758.966-1.434 1.444-3.0572 1.444-4.8696 0-1.4838-.329-2.848-.976-4.1028l.02.01Z"/>
<path fill="url(#a)" d="M20.34 3.66 3.66 20.34C1.32 22.68 0 25.86 0 29.18V59c0 2.76 2.24 5 5 5h29.82c3.32 0 6.49-1.32 8.84-3.66l16.68-16.68c2.34-2.34 3.66-5.52 3.66-8.84V5c0-2.76-2.24-5-5-5H29.18c-3.32 0-6.49 1.32-8.84 3.66Z"/>
<path fill="#000" d="M48 16H8v40h40V16Z"/>
<path fill="#fff" d="M30 47H13v4h17v-4Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 4.1 KiB

View file

@ -1,35 +0,0 @@
name: Update Browserslist database
on:
workflow_dispatch:
schedule:
- cron: '0 2 1 * *'
permissions:
contents: write
pull-requests: write
jobs:
update-browserslist-database:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Configure git
run: |
# Setup for commiting using built-in token. See https://github.com/actions/checkout#push-a-commit-using-the-built-in-token
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
- name: Update Browserslist database and create PR if applies
uses: c2corg/browserslist-update-action@v2
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branch: browserslist-update
base_branch: master
directory: ./komga-webui
commit_message: 'build(webui): update Browserslist db'
title: 'Browserslist database update'
body: Auto-generated by [browserslist-update-action](https://github.com/c2corg/browserslist-update-action/)
labels: 'github_actions'

View file

@ -1,18 +0,0 @@
name: Dispatch events
on:
push:
branches: [ master ]
paths:
- '**/openapi.json'
jobs:
dispatch:
runs-on: ubuntu-latest
steps:
- name: Repository Dispatch
uses: peter-evans/repository-dispatch@v4
with:
token: ${{ secrets.REPO_ACCESS_TOKEN }}
repository: gotson/komga-website
event-type: openapi

View file

@ -1,23 +0,0 @@
name: Update DockerHub description
on:
push:
branches:
- master
paths:
- 'DOCKERHUB.md'
jobs:
update_docker_description:
name: Update DockerHub description
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: DockerHub Description
uses: peter-evans/dockerhub-description@v5.0.0
env:
DOCKERHUB_USERNAME: ${{ secrets.DOCKER_USERNAME }}
DOCKERHUB_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
DOCKERHUB_REPOSITORY: gotson/komga
README_FILEPATH: ./DOCKERHUB.md

View file

@ -1,19 +0,0 @@
name: Lock threads
on:
# Daily
schedule:
- cron: '0 0 * * *'
# Manual trigger
workflow_dispatch:
inputs:
jobs:
lock:
runs-on: ubuntu-latest
steps:
- uses: dessant/lock-threads@v6
with:
github-token: ${{ github.token }}
issue-inactive-days: '30'
pr-inactive-days: '30'

View file

@ -1,253 +0,0 @@
name: Release
on:
workflow_dispatch:
inputs:
release_notes:
description: Release notes (use \n for newlines)
type: string
required: false
bump:
description: 'Bump type'
required: false
default: 'next'
type: choice
options:
- 'next'
- 'major'
- 'minor'
- 'patch'
- 'current'
github_release:
description: 'Create Github Release'
default: true
type: boolean
conveyor-copied-site:
description: 'Conveyor copied site'
default: true
type: boolean
docker_release:
description: 'Push Docker images'
default: true
type: boolean
msstore_release:
description: 'Release to the MS Store'
default: true
type: boolean
jobs:
version:
runs-on: macos-latest
outputs:
version_current: ${{ steps.versions.outputs.version_current }}
version_next: ${{ steps.versions.outputs.version_next }}
should_release: ${{ steps.versions.outputs.should_release }}
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Set up Homebrew
id: set-up-homebrew
uses: Homebrew/actions/setup-homebrew@main
- name: Install svu
run: brew install --cask caarlos0/tap/svu
- name: Compute next version for release
run: |
echo "VERSION_NEXT=`svu ${{ inputs.bump }}`" | tee -a $GITHUB_ENV
echo "VERSION_NEXT_SUFFIX=`svu ${{ inputs.bump }}`" | tee -a $GITHUB_ENV
- name: Set Versions
id: versions
run: |
echo "version_current=`svu current`" >> $GITHUB_OUTPUT
echo "version_next=${{ env.VERSION_NEXT_SUFFIX }}" >> $GITHUB_OUTPUT
[[ `svu current` != ${{ env.VERSION_NEXT }} ]] && echo "should_release=true" >> $GITHUB_OUTPUT || echo
release:
name: Release
runs-on: ubuntu-latest
needs: version
steps:
- name: Remove unnecessary files
run: |
sudo rm -rf /usr/share/dotnet
sudo rm -rf "$AGENT_TOOLSDIRECTORY"
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Display versions
run: |
echo "Current version: ${{ needs.version.outputs.version_current }}, should release: ${{ needs.version.outputs.version_next }}"
- name: Update version in gradle.properties
if: needs.version.outputs.should_release #only redo if the version changed
run: sed -i -e "s/version=.*/version=${{ needs.version.outputs.version_next }}/" gradle.properties
- uses: actions/setup-node@v6
with:
node-version-file: '.nvmrc'
cache: 'npm'
cache-dependency-path: komga-webui/package-lock.json
- name: Setup Java 21
uses: actions/setup-java@v5
with:
java-version: 21
java-package: 'jdk'
distribution: 'temurin'
- name: Set up QEMU
uses: docker/setup-qemu-action@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Login to Docker Hub
uses: docker/login-action@v4
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Login to Docker Hub
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v6
- name: Build
run: ./gradlew :komga:prepareThymeLeaf :komga:bootJar :komga-tray:jar
env:
NODE_OPTIONS: "--max-old-space-size=4096"
- name: Generate OpenAPI docs
if: needs.version.outputs.should_release #only redo if the version changed
run: ./gradlew :komga:generateOpenApiDocs
- name: Create release notes
run: |
mkdir release_notes
echo -e "${{ inputs.release_notes }}" >> release_notes/release_notes.md
echo "Release notes:"
cat release_notes/release_notes.md
echo ""
- name: JReleaser Changelog append
if: needs.version.outputs.should_release #only redo if the version changed
run: ./gradlew jreleaserChangelog
env:
JRELEASER_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: JReleaser Changelog output
if: always() && needs.version.outputs.should_release
uses: actions/upload-artifact@v7
with:
name: jreleaser-changelog
path: |
build/jreleaser/trace.log
build/jreleaser/output.properties
- name: Release commit and push
uses: EndBug/add-and-commit@v10
if: needs.version.outputs.should_release #only redo if the version changed
with:
message: 'chore(release): ${{ needs.version.outputs.version_next }} [skip ci]'
tag: '${{ needs.version.outputs.version_next }}'
default_author: github_actions
- name: Retrieve the Apple private key and decode it to a file
if: inputs.github_release || inputs.conveyor-copied-site
env:
APPLE_PRIVATE_KEY: ${{ secrets.APPLE_PRIVATE_KEY }}
run: |
mkdir ./secret
echo $APPLE_PRIVATE_KEY | base64 --decode > ./secret/apple_private_key.p8
- name: Conveyor make copied-site
uses: hydraulic-software/conveyor/actions/build@v22.0
if: inputs.conveyor-copied-site
with:
command: --cache-limit=2.0 -f conveyor.ci.conf make copied-site -o ./output/site
signing_key: ${{ secrets.CONVEYOR_SIGNING_KEY }}
agree_to_license: 1
env:
APPLE_ISSUER_ID: ${{ secrets.APPLE_ISSUER_ID }}
APPLE_KEY_ID: ${{ secrets.APPLE_KEY_ID }}
AWS_S3_BUCKET: ${{ secrets.B2_BUCKET }}
AWS_S3_ENDPOINT: 'https://s3.us-east-005.backblazeb2.com'
AWS_ACCESS_KEY_ID: ${{ secrets.B2_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.B2_SECRET_ACCESS_KEY }}
- name: Upload Conveyor log
if: always() && inputs.conveyor-copied-site
uses: actions/upload-artifact@v7
with:
name: conveyor-make-copied-site
path: ~/.cache/hydraulic/conveyor/logs/log.latest.txt
- name: JReleaser Release
if: inputs.github_release
run: ./gradlew jreleaserRelease
env:
JRELEASER_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: JReleaser Release output
if: always() && inputs.github_release
uses: actions/upload-artifact@v7
with:
name: jreleaser-release
path: |
build/jreleaser/trace.log
build/jreleaser/output.properties
# Sometimes the workflow will fail because it's out of disk space
- name: Cleanup Conveyor output
run: rm -fr ./output
- name: JReleaser Publish
if: inputs.docker_release
run: ./gradlew jreleaserPublish
env:
JRELEASER_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: JReleaser Publish output
if: always() && inputs.docker_release
uses: actions/upload-artifact@v7
with:
name: jreleaser-publish
path: |
build/jreleaser/trace.log
build/jreleaser/output.properties
- name: Conveyor - publish to Microsoft Store
uses: hydraulic-software/conveyor/actions/build@v22.0
if: inputs.msstore_release
with:
command: --cache-limit=2.0 -f conveyor.msstore.ci.conf make ms-store-release -o ./output/msstore
signing_key: ${{ secrets.CONVEYOR_SIGNING_KEY }}
agree_to_license: 1
env:
CONVEYOR_MSSTORE_CLIENT_ID: ${{ secrets.CONVEYOR_MSSTORE_CLIENT_ID }}
CONVEYOR_MSSTORE_CLIENT_SECRET: ${{ secrets.CONVEYOR_MSSTORE_CLIENT_SECRET }}
CONVEYOR_MSSTORE_TENANT_ID: ${{ secrets.CONVEYOR_MSSTORE_TENANT_ID }}
AWS_S3_BUCKET: ${{ secrets.B2_BUCKET }}
AWS_S3_ENDPOINT: 'https://s3.us-east-005.backblazeb2.com'
AWS_ACCESS_KEY_ID: ${{ secrets.B2_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.B2_SECRET_ACCESS_KEY }}
- name: Upload Conveyor log
if: always() && inputs.msstore_release
uses: actions/upload-artifact@v7
with:
name: conveyor-ms-store-release
path: ~/.cache/hydraulic/conveyor/logs/log.latest.txt
dispatch:
needs: release
runs-on: ubuntu-latest
steps:
- name: Repository Dispatch
uses: peter-evans/repository-dispatch@v4
with:
token: ${{ secrets.REPO_ACCESS_TOKEN }}
repository: gotson/komga-website
event-type: komga-release

View file

@ -1,23 +0,0 @@
name: 'Close stale issues and PRs'
on:
schedule:
- cron: '30 1 * * *'
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v3
with:
stale-issue-message: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
stale-pr-message: >
This pull request has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
days-before-stale: 90
days-before-close: 14
exempt-issue-labels: 'pinned,security,tech debt,enhancement,bug'
exempt-all-assignees: true

View file

@ -1,97 +0,0 @@
name: Tests
on:
pull_request:
paths-ignore:
- 'komga-webui/src/locales/*'
- 'komga-tray/src/main/resources/org/gotson/komga/*'
push:
branches-ignore:
- 'dependabot/**'
workflow_dispatch:
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ ubuntu-latest, macos-latest, windows-latest ]
fail-fast: false
name: Test server - ${{ matrix.os }}
steps:
- uses: actions/checkout@v6
- name: Setup Java 21
uses: actions/setup-java@v5
with:
java-version: 21
java-package: 'jdk'
distribution: 'temurin'
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v6
- name: Build
run: ./gradlew build :komga-tray:jar
- name: Upload Unit Test Results
if: always()
uses: actions/upload-artifact@v7
with:
name: test-results-${{ matrix.os }}
path: komga/build/test-results/
- name: Upload Unit Test Reports
if: always()
uses: actions/upload-artifact@v7
with:
name: test-reports-${{ matrix.os }}
path: komga/build/reports/tests/
- name: Publish Test Report
uses: mikepenz/action-junit-report@v6
if: always()
with:
report_paths: '**/build/test-results/test/TEST-*.xml'
check_name: 'JUnit Test Report: ${{ matrix.os }}'
- name: Conveyor - compute JDK module list
if: github.event_name == 'push' && github.repository_owner == 'gotson' && contains(matrix.os, 'ubuntu')
uses: hydraulic-software/conveyor/actions/build@v22.0
with:
command: -f conveyor.detect.conf -Kapp.machines=mac.aarch64 make processed-jars
signing_key: ${{ secrets.CONVEYOR_SIGNING_KEY }}
agree_to_license: 1
- name: Compare JDK required modules
id: conveyor_compare
if: github.event_name == 'push' && github.repository_owner == 'gotson' && contains(matrix.os, 'ubuntu')
run: diff --unified ./komga-tray/conveyor/required-jdk-modules.txt ./output/required-jdk-modules.txt
- name: Upload JDK required modules
if: steps.conveyor_compare.outcome == 'failure'
uses: actions/upload-artifact@v7
with:
name: conveyor-required-jdk-modules
path: ./output/required-jdk-modules.txt
webui:
runs-on: ubuntu-latest
name: Test webui builds
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version-file: '.nvmrc'
cache: 'npm'
cache-dependency-path: komga-webui/package-lock.json
- name: npm install
working-directory: komga-webui
run: npm install
- name: npm build
working-directory: komga-webui
run: npm run build
env:
NODE_OPTIONS: "--max-old-space-size=4096"
- name: npm test
working-directory: komga-webui
run: npm run test:unit

40
.gitignore vendored
View file

@ -1,26 +1,7 @@
### Gradle
.gradle
!gradle/wrapper/gradle-wrapper.jar
### Kotlin
.kotlin
### NodeJS
node_modules
### Logs
*.log
*.log.*.gz
### Temporary files
*.tmp
*.bak
### SQLite databases
*.sqlite
*.sqlite-journal
### STS
### STS ###
.apt_generated
.classpath
.factorypath
@ -28,18 +9,15 @@ node_modules
.settings
.springBeans
### IntelliJ IDEA
### IntelliJ IDEA ###
!.idea/
.idea/*
!/.idea/codeStyles/
!/.idea/runConfigurations/
*.iws
*.iml
*.ipr
### IntelliJ Fleet
.fleet/
### NetBeans
### NetBeans ###
nbproject/private/
build/
nbbuild/
@ -47,13 +25,3 @@ dist/
nbdist/
.nb-gradle/
### Komga
/komga/src/main/resources/public/
/config-dir/
application-oauth2.yml
/benchmark
/release_notes
### Conveyor
output/
secret/

View file

@ -1,22 +0,0 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<JetCodeStyleSettings>
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
<value />
</option>
<option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="2147483647" />
<option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="2147483647" />
</JetCodeStyleSettings>
<TypeScriptCodeStyleSettings version="0">
<option name="USE_SEMICOLON_AFTER_STATEMENT" value="false" />
<option name="FORCE_SEMICOLON_STYLE" value="true" />
<option name="USE_DOUBLE_QUOTES" value="false" />
<option name="FORCE_QUOTE_STYlE" value="true" />
</TypeScriptCodeStyleSettings>
<codeStyleSettings language="XML">
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions>
</codeStyleSettings>
</code_scheme>
</component>

View file

@ -1,5 +0,0 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
</state>
</component>

View file

@ -7,7 +7,7 @@
</map>
</option>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$/komga" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
@ -20,10 +20,7 @@
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<GradleScriptDebugEnabled>true</GradleScriptDebugEnabled>
<method v="2" />
</configuration>
</component>
</component>

View file

@ -1,13 +1,13 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="komga [bootRun] dev,localdb,noclaim,oauth2" type="GradleRunConfiguration" factoryName="Gradle">
<configuration default="false" name="komga [bootRun] dev,localdb" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="env">
<map>
<entry key="SPRING_PROFILES_ACTIVE" value="dev,localdb,noclaim,oauth2" />
<entry key="SPRING_PROFILES_ACTIVE" value="dev,localdb" />
</map>
</option>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$/komga" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
@ -18,12 +18,9 @@
<option value="bootRun" />
</list>
</option>
<option name="vmOptions" />
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<GradleScriptDebugEnabled>true</GradleScriptDebugEnabled>
<method v="2" />
</configuration>
</component>
</component>

View file

@ -1,13 +1,13 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="komga [bootRun] dev,demo,noclaim" type="GradleRunConfiguration" factoryName="Gradle">
<configuration default="false" name="komga [bootRun] dev,noflyway" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="env">
<map>
<entry key="SPRING_PROFILES_ACTIVE" value="dev,demo,noclaim" />
<entry key="SPRING_PROFILES_ACTIVE" value="dev,noflyway" />
</map>
</option>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$/komga" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
@ -20,10 +20,7 @@
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<GradleScriptDebugEnabled>true</GradleScriptDebugEnabled>
<method v="2" />
</configuration>
</component>
</component>

View file

@ -1,13 +1,13 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="komga [bootRun] dev,noclaim" type="GradleRunConfiguration" factoryName="Gradle">
<configuration default="false" name="komga [bootRun] generatesql" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="env">
<map>
<entry key="SPRING_PROFILES_ACTIVE" value="dev,noclaim" />
<entry key="SPRING_PROFILES_ACTIVE" value="generatesql" />
</map>
</option>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$/komga" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
@ -20,10 +20,7 @@
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<GradleScriptDebugEnabled>true</GradleScriptDebugEnabled>
<method v="2" />
</configuration>
</component>
</component>

1
.nvmrc
View file

@ -1 +0,0 @@
18

View file

@ -1,3 +0,0 @@
tag:
prefix: ''
pattern: '[0-9]*'

41
.travis.yml Normal file
View file

@ -0,0 +1,41 @@
language: java
before_cache:
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
- rm -fr $HOME/.gradle/caches/*/plugin-resolution/
cache:
directories:
- $HOME/.gradle/caches/
- $HOME/.gradle/wrapper/
jdk: openjdk8
before_deploy: echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
deploy:
- provider: script
script: ./gradlew dockerPushBeta
skip_cleanup: true
on:
branch: master
- provider: script
script: ./gradlew dockerPushLatest
skip_cleanup: true
on:
tags: true
condition: $TRAVIS_TAG = latest
- provider: script
script: ./gradlew dockerPushSemVer
skip_cleanup: true
on:
tags: true
condition: $TRAVIS_TAG =~ ^v[0-9]+\.[0-9]+\.[0-9]+
- provider: script
script: ./gradlew githubRelease
skip_cleanup: true
on:
tags: true
condition: $TRAVIS_TAG =~ ^v[0-9]+\.[0-9]+\.[0-9]+

File diff suppressed because it is too large Load diff

View file

@ -1,6 +0,0 @@
1. **Before reporting a new issue, take a look at the [FAQ](https://komga.org/docs/faq/), the [changelog](https://github.com/gotson/komga/blob/master/CHANGELOG.md) and the already opened [issues](https://github.com/gotson/komga/issues).**
1. If you are unsure, ask here: [![Discord](https://img.shields.io/discord/678794935368941569?label=Discord)](https://discord.gg/TdRpkDu)
1. **DO NOT** reply on existing issues to say _"+1"_ or _"I am interested in this"_.
1. **DO** show your enthusiasm for an existing issue by adding a :+1: reaction on the first message in the discussion.
1. **DO NOT** ask for any ETA or roadmap for a feature. This is an open-source projects and contributors work on it on their free time. They don't work for you.
1. Use the issue templates provided and fill all the details.

View file

@ -1,75 +0,0 @@
# Development guidelines
Thanks a lot for contributing to Komga!
## Requirements
You will need:
- Java JDK version 21+
- Nodejs version 18+ (check the `.nvmrc` file)
## Setting up the project
- run `npm install` in the `komga-webui` folder of the project. This will install the necessary tooling for the webui.
## Commit messages
Komga's commit messages follow the [Conventional Commits](https://www.conventionalcommits.org/) standard. This enables automatic versioning, releases, and release notes generation.
## Project organization
Komga is composed of 3 projects:
- `komga`: a Spring Boot backend server that hosts the APIs, but also serves the static assets of the frontend.
- `komga-webui`: a VueJS frontend, built at compile time and served by the backend at runtime.
- `komga-tray`: a thin desktop wrapper that displays a tray-icon
## Backend development
### Spring profiles
Komga uses Spring Profiles extensively:
- `dev`: add more logging, disable periodic scanning, in-memory database, and enable CORS from `localhost:8081` (the frontend dev server)
- `localdb`: a dev profile that stores the database in `./localdb`.
- `noclaim`: will create initial users at startup if none exist and output users and passwords in the standard output
- if `dev` is active, will create `admin@example.org` with password `admin`, and `user@example.org` with password `user`
- if `dev` is not active, will create `admin@example.org` with a random password that will be shown in the logs
### Gradle tasks
The backend project uses `gradle` to run all the necessary tasks. If your IDE does not have `gradle` integration, you can run the tasks from the root directory using `./gradlew <taskName>`.
Here is a list of useful tasks:
- `bootRun`: run the application locally, useful for testing your changes.
- `prepareThymeLeaf`: build the frontend, and copy the bundle to `/resources/public`. You need to run this manually if
you want to test the latest frontend build hosted by Spring.
- `test`: run automated tests. Always run this before committing.
- `jooq-codegen-primary`: generates the jOOQ DSL.
`bootRun` needs to be run with a profile or list of profiles, usually:
- `dev,noclaim`: when testing with a blank database
- `dev,localdb,noclaim`: when testing with an existing database
There are few ways you can run the task with a profile:
- `./gradlew bootRun --args='--spring.profiles.active=dev'`
- On Linux: `SPRING_PROFILES_ACTIVE=dev ./gradlew bootRun`
- On Windows:
```
SET SPRING_PROFILES_ACTIVE=dev
./gradlew bootRun
```
- If you use IntelliJ, some Run Configurations are saved in the repository and available from the Gradle panel
## Frontend development
You can run a live development server with `npm run serve` from `/komga-webui`. The dev server will override the URL to connect to `localhost:25600`, so you can also run `gradle bootRun` to have a backend running, serving the API requests. The frontend will be loaded from `localhost:8081`.
Make sure you start the backend with the `dev` profile, else the frontend requests will be denied because of CORS.
## Docker
To build the Docker image, you need to:
- have the webui built and copied to `/resources/public`. To do so, run `./gradlew prepareThymeLeaf`
- prepare the docker image via JReleaser. To do so, run `./gradlew jreleaserPackage`
- the `Dockerfile` will be available in `komga/build/jreleaser/package/docker/`

View file

@ -1,16 +1,112 @@
[![Open Collective backers and sponsors](https://img.shields.io/opencollective/all/komga?label=OpenCollective%20Sponsors&color=success)](https://opencollective.com/komga) ![GitHub Sponsors](https://img.shields.io/github/sponsors/gotson?label=Github%20Sponsors&color=success)
[![Discord](https://img.shields.io/discord/678794935368941569?label=Discord&color=blue)](https://discord.gg/TdRpkDu)
[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/gotson/komga/ci.yml?branch=master)](https://github.com/gotson/komga/actions?query=workflow%3ACI+branch%3Amaster)
[![Build Status](https://travis-ci.org/gotson/komga.svg?branch=master)](https://travis-ci.org/gotson/komga)
[![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/gotson/komga?color=blue&label=download&sort=semver)](https://github.com/gotson/komga/releases)
[![Docker Pulls](https://img.shields.io/docker/pulls/gotson/komga)](https://hub.docker.com/r/gotson/komga)
[![Translation status](https://hosted.weblate.org/widgets/komga/-/webui/svg-badge.svg)](https://hosted.weblate.org/engage/komga/)
# ![app icon](https://github.com/gotson/komga/raw/master/.github/readme-images/app-icon.png) Komga
[Komga](https://github.com/gotson/komga) is a media server for your comics, mangas, BDs, magazines and eBooks.
[Komga](https://github.com/gotson/komga) is a free and open source comics/mangas server.
## Version tags
This image provides various versions that are available via tags.
|**Tag** |**Description** |
|:------:|------------------------|
|`beta` |build from latest commit|
|`latest`|latest stable release |
|`x.y.z` |version `x.y.z` |
## Usage
Please refer to the [official documentation](https://komga.org/docs/installation/docker).
Here are some example snippets to help you get started creating a container.
### docker
```
docker create \
--name=komga \
--user 1000:1000 \
-p 8080:8080 \
-e KOMGA_USER_PASSWORD=your-user-password
-e KOMGA_ADMIN_PASSWORD=your-admin-password
-v path/to/data:/config \
-v path/to/books:/books \
--restart unless-stopped \
gotson/komga
```
### docker-compose
```
---
version: '3'
services:
komga:
image: gotson/komga
container_name: komga
volumes:
- path/to/data:/config
- path/to/books:/books
- /etc/timezone:/etc/timezone:ro
ports:
- 8080:8080
user: "1000:1000"
environment:
- KOMGA_USER_PASSWORD=your-user-password
- KOMGA_ADMIN_PASSWORD=your-admin-password
restart: unless-stopped
```
## Parameters
Container images are configured using parameters passed at runtime (such as those above).
These parameters are separated by a colon and indicate `external:internal` respectively.
For example, `-p 8080:80` would expose port `80` from inside the container to be accessible from the host's IP on port `8080` outside the container.
| Parameter | Function |
|:-------------------------:|---------------------------------------------------|
| `-p 8080` | The port for the Komga API |
| `--user: 1000:1000` | User:Group identifier - see below for explanation |
| `-v /config` | Database and Komga configs |
| `-v /books` | Location of books library on disk |
| `-e KOMGA_USER_PASSWORD` | Password for the `user` user |
| `-e KOMGA_ADMIN_PASSWORD` | Password for the `admin` user |
## User / Group Identifiers
When using volumes (`-v` flags) permissions issues can arise between the host OS and the container, we avoid this issue by allowing you to specify the user ID and group ID.
Ensure any volume directories on the host are owned by the same user you specify and any permissions issues will vanish like magic.
In this instance `UID=1000` and `GID=1000`, to find yours use id user as below:
```
$ id username
uid=1000(dockeruser) gid=1000(dockergroup) groups=1000(dockergroup)
```
## Support info
- Shell access whilst the container is running: `docker exec -it komga /bin/bash`
- To monitor the logs of the container in realtime: `docker logs -f komga`
## Updating
Below are the instructions for updating containers:
### Via Docker Run/Create
- Update the image: `docker pull gotson/komga`
- Stop the running container: `docker stop komga`
- Delete the container: `docker rm komga`
- Recreate a new container with the same docker create parameters as instructed above (if mapped correctly to a host folder, your `/config` folder and settings will be preserved)
- Start the new container: `docker start komga`
- You can also remove the old dangling images: `docker image prune`
### Via Docker Compose
- Update all images: `docker-compose pull`
- or update a single image: `docker-compose pull komga`
- Let compose update all containers as necessary: `docker-compose up -d`
- or update a single container: `docker-compose up -d komga`
- You can also remove the old dangling images: `docker image prune`

View file

@ -1,45 +0,0 @@
# Error codes
| Code | Description |
|--------------|---------------------------------------------------------|
| ERR_1000 | File could not be accessed during analysis |
| ERR_1001 | Media type is not supported during analysis |
| ERR_1002 | Encrypted RAR archives are not supported |
| ERR_1003 | Solid RAR archives are not supported |
| ERR_1004 | Multi-Volume RAR archives are not supported |
| ERR_1005 | Unknown error while analyzing book |
| ERR_1006 | Book does not contain any page |
| ERR_1007 | Some entries could not be analyzed |
| ERR_1008 | Unknown error while getting book's entries |
| ~~ERR_1009~~ | ~~A read list with that name already exists~~ |
| ~~ERR_1010~~ | ~~No books were matched within the read list request~~ |
| ~~ERR_1011~~ | ~~No unique match for series~~ |
| ~~ERR_1012~~ | ~~No match for series~~ |
| ~~ERR_1013~~ | ~~No unique match for book number within series~~ |
| ~~ERR_1014~~ | ~~No match for book number within series~~ |
| ERR_1015 | Error while deserializing ComicRack ReadingList |
| ERR_1016 | Directory not accessible or not a directory |
| ERR_1017 | Cannot scan folder that is part of an existing library |
| ERR_1018 | File not found |
| ERR_1019 | Cannot import file that is part of an existing library |
| ERR_1020 | Book to upgrade does not belong to provided series |
| ERR_1021 | Destination file already exists |
| ERR_1022 | Newly imported book could not be scanned |
| ERR_1023 | Book already present in ReadingList |
| ERR_1024 | OAuth2 login error: no email attribute |
| ERR_1025 | OAuth2 login error: no local user exist with that email |
| ERR_1026 | OpenIDConnect login error: email not verified |
| ERR_1027 | OpenIDConnect login error: no email_verified attribute |
| ERR_1028 | OpenIDConnect login error: no email attribute |
| ERR_1029 | ComicRack CBL does not contain any Book element |
| ERR_1030 | ComicRack CBL has no Name element |
| ERR_1031 | ComicRack CBL Book is missing series or number |
| ERR_1032 | EPUB file has wrong media type |
| ERR_1033 | Some entries are missing |
| ERR_1034 | An API key with that comment already exists |
| ERR_1035 | Error while getting EPUB TOC |
| ERR_1036 | Error while getting EPUB Landmarks |
| ERR_1037 | Error while getting EPUB page list |
| ERR_1038 | Error while getting EPUB divina pages |
| ERR_1039 | Error while getting EPUB positions |

View file

@ -1,17 +0,0 @@
# Privacy Policy
Komga is a self-hosted application. It does not transmit any data outside the machine hosting it.
## Data collected
Data collected is stored in the local SQLite database required for the application to function, and never leaves your
machine.
### Information provided by the user(s)
- **Email address**: required to create an account
### Information collected automatically
- **IP address and User-Agent of authentication connections**: stored in the local database during authentication
attempts. That information is automatically deleted after one month.

107
README.md
View file

@ -1,61 +1,94 @@
[![Open Collective backers and sponsors](https://img.shields.io/opencollective/all/komga?label=OpenCollective%20Sponsors&color=success)](https://opencollective.com/komga) [![GitHub Sponsors](https://img.shields.io/github/sponsors/gotson?label=Github%20Sponsors&color=success)](https://github.com/sponsors/gotson)
[![Discord](https://img.shields.io/discord/678794935368941569?label=Discord&color=blue)](https://discord.gg/TdRpkDu)
[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/gotson/komga/tests.yml?branch=master)](https://github.com/gotson/komga/actions?query=workflow%3ATests+branch%3Amaster)
[![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/gotson/komga?color=blue&label=download&sort=semver)](https://github.com/gotson/komga/releases) [![GitHub all releases](https://img.shields.io/github/downloads/gotson/komga/total?color=blue&label=github%20downloads)](https://github.com/gotson/komga/releases)
[![Build Status](https://travis-ci.com/gotson/komga.svg?branch=master)](https://travis-ci.com/gotson/komga)
[![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/gotson/komga?color=blue&label=download&sort=semver)](https://github.com/gotson/komga/releases)
[![Docker Pulls](https://img.shields.io/docker/pulls/gotson/komga)](https://hub.docker.com/r/gotson/komga)
[![Translation status](https://hosted.weblate.org/widgets/komga/-/webui/svg-badge.svg)](https://hosted.weblate.org/engage/komga/)
# ![app icon](./.github/readme-images/app-icon.png) Komga
Komga is a media server for your comics, mangas, BDs, magazines and eBooks.
#### Chat on [Discord](https://discord.gg/TdRpkDu)
Komga is a free and open source comics/mangas server.
## Features
- Browse libraries, series and books via a responsive web UI that works on desktop, tablets and phones
- Organize your library with collections and read lists
- Edit metadata for your series and books
- Import embedded metadata automatically
- Webreader with multiple reading modes
- Manage multiple users, with per-library access control, age restrictions, and labels restrictions
- Offers a REST API, many community tools and scripts can interact with Komga
- OPDS v1 and v2 support
- Kobo Sync with your Kobo eReader
- KOReader Sync
- Download book files, whole series, or read lists
- Duplicate files detection
- Duplicate pages detection and removal
- Import books from outside your libraries directly into your series folder
- Import ComicRack `cbl` read lists
Komga just started, and for now it can:
- scan and index a folder containing comic book archives in `cbz` and `cbr` format, as well as `pdf`. Rescan periodically.
- serve the individual pages of those books via an API
- serve the complete file via an API
## Status & vision
The first version is a simple server with only an API and no UI.
It's aimed to work with [Tachiyomi](https://github.com/inorichi/tachiyomi) through an extension.
Future versions may bring:
- support for multiple libraries (multiple folders)
- a web UI to administrate the server
- matching with online metadata sources (like ComicVine) to enrich information like description or genre
The long term vision is to offer something similar to Plex, but for comics!
## What does it do?
Komga will scan your library's root folder for directories containing supported files (at the moment `cbz`, `zip`, `cbr`, `rar` and `pdf`):
- each folder containing comic books will be made as a `Serie`
- each comic book file inside a `Serie` will be made as a `Book`
It works with subfolders too, so if you have a structure like this:
```
-Parent
+--SubFolder
| +file1.cbz
| +file2.cbz
+direct1.cbz
```
Komga will generate:
- a `Serie` called _Parent_, containing a `Book` called _direct1_
- a `Serie` called _SubFolder_, containing two `Book`s called _file1_ and _file2_
On rescans, Komga will update Series and Books, add new ones, and remove the ones for which files don't exist anymore.
Then it will _parse_ each book, which consist of indexing pages (images in the archive), and generating a thumbnail.
Komga offers a REST API, which you can browse using Swagger. It's available at `/swagger-ui.html`. The API offers __file download__ and __page streaming__.
In order to access the API, you will need to authenticate using Basic Authentication, with one of the 2 built-in users (`admin` or `user`).
## Installation
Refer to the [website](https://komga.org/docs/category/installation) for instructions.
The easiest way to install Komga is to use Docker ([instructions on how to use the image](https://hub.docker.com/r/gotson/komga)). You can have a look at the sample [`docker-compose.yml`](./doc/docker-compose.yml).
## Documentation
Alternatively you can run it from the fat `jar` file. You can find them in the [releases](https://github.com/gotson/komga/releases) section.
Head over to our [website](https://komga.org) for more information.
You can also build it yourself by using `gradlew bootJar` to generate it.
## Develop in Komga
## Configuration
Check the [development guidelines](./DEVELOPING.md).
Komga relies heavily on [Spring Boot's configuration](https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html), leveraging `profiles` and configuration `properties`.
## Translation
The easiest way to configure is either via environment variables (a good fit for `docker-compose`) or by using an `application.yml` file located in the same folder as the `jar` file. You can check the sample [`application.yml`](./doc/application.yml).
[![Translation status](https://hosted.weblate.org/widgets/komga/-/webui/horizontal-auto.svg)](https://hosted.weblate.org/engage/komga/)
Each configuration key can have a different format depending if it's from the environment variable, or from the `application.yml` file. In the following section I will provide both format in the form `ENVIRONMENT_VARIABLE` / `application-property`.
## Powered by
### Mandatory configuration
[![Jetbrains_logo](./.github/readme-images/jetbrains.svg)](https://www.jetbrains.com/?from=Komga)
In order to make Komga run, you need to specify some mandatory configuration keys (unless you use Docker, in which case defaults are setup):
Thanks to [JetBrains](https://www.jetbrains.com/?from=Komga) for providing the development environment that helps us develop Komga.
- `SPRING_PROFILES_ACTIVE` / `spring.profiles.active`: `prod` - this will enable the database management and upgrades for new versions.
- `SPRING_DATASOURCE_URL` / `spring.datasource.url`: the path of the database file. For Docker I use `jdbc:h2:/config/database.h2;DB_CLOSE_DELAY=-1`, where `/config/database.h2` is the actual file inside the docker container. You can customize this part if running without docker.
- `KOMGA_ROOT_FOLDER` / `komga.root-folder`: the root folder of your library, this is what Komga will scan.
- `KOMGA_ROOT_FOLDER_SCAN_CRON` / `komga.root-folder-scan-cron`: a [Spring cron expression](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/scheduling/support/CronSequenceGenerator.html) for root folder periodic rescans. `0 0 * * * ?` will rescan every hour. `0 */15 * * * ?` will rescan every 15 minutes.
[![Chromatic logo](https://user-images.githubusercontent.com/321738/84662277-e3db4f80-af1b-11ea-88f5-91d67a5e59f6.png)](https://www.chromatic.com)
### Optional configuration
Thanks to [Chromatic](https://www.chromatic.com/) for providing the visual testing platform that helps us review UI changes and catch visual regressions.
You can also use some optional configuration keys:
- `KOMGA_USER_PASSWORD` / `komga.user-password`: the password for the user `user`. Defaults to `user`.
- `KOMGA_ADMIN_PASSWORD` / `komga.admin-password`: the password for the user `admin`. Defaults to `admin`.
- `KOMGA_THREADS_PARSE` / `komga.threads.parse`: the number of worker threads used for book parsing. Defaults to `2`. You can experiment to get better performance.
## Credits

BIN
apple.cer

Binary file not shown.

View file

@ -1,193 +1,4 @@
import com.github.benmanes.gradle.versions.updates.DependencyUpdatesTask
import org.jreleaser.model.Active
import org.jreleaser.model.Distribution.DistributionType.SINGLE_JAR
import org.jreleaser.model.api.common.Apply
import kotlin.io.path.Path
import kotlin.io.path.exists
plugins {
run {
val kotlinVersion = "2.2.0"
kotlin("jvm") version kotlinVersion
kotlin("plugin.spring") version kotlinVersion
kotlin("kapt") version kotlinVersion
}
id("org.jlleitschuh.gradle.ktlint") version "13.0.0"
id("com.github.ben-manes.versions") version "0.52.0"
id("org.jreleaser") version "1.19.0"
}
fun isNonStable(version: String): Boolean {
val stableKeyword = listOf("RELEASE", "FINAL", "GA").any { version.uppercase().contains(it) }
val unstableKeyword = listOf("ALPHA", "RC").any { version.uppercase().contains(it) }
val regex = "^[0-9,.v-]+(-r)?$".toRegex()
val isStable = stableKeyword || regex.matches(version)
return unstableKeyword || !isStable
}
group = "org.gotson"
allprojects {
repositories {
mavenCentral()
}
apply(plugin = "org.jlleitschuh.gradle.ktlint")
apply(plugin = "com.github.ben-manes.versions")
tasks.named<DependencyUpdatesTask>("dependencyUpdates").configure {
// disallow release candidates as upgradable versions from stable versions
rejectVersionIf {
isNonStable(candidate.version) && !isNonStable(currentVersion)
}
gradleReleaseChannel = "current"
checkConstraints = true
}
configure<org.jlleitschuh.gradle.ktlint.KtlintExtension> {
version = "1.7.1"
filter {
exclude("**/generated-src/**")
exclude("**/generated/**")
}
}
}
tasks.wrapper {
gradleVersion = "8.14.3"
gradleVersion = "5.6.1"
distributionType = Wrapper.DistributionType.ALL
}
jreleaser {
project {
description = "Media server for comics/mangas/BDs with API and OPDS support"
copyright = "Gauthier Roebroeck"
authors.add("Gauthier Roebroeck")
license = "MIT"
links {
homepage = "https://komga.org"
}
}
release {
github {
discussionCategoryName = "Announcements"
skipTag = true
tagName = "{{projectVersion}}"
changelog {
formatted = Active.ALWAYS
preset = "conventional-commits"
skipMergeCommits = true
links = true
content = (if (Path("./release_notes/release_notes.md").exists()) "{{#f_file_read}}{{basedir}}/release_notes/release_notes.md{{/f_file_read}}" else "") +
"""
## Changelog
{{changelogChanges}}
{{changelogContributors}}
""".trimIndent()
format = "- {{#commitIsConventional}}{{#conventionalCommitIsBreakingChange}}🚨 {{/conventionalCommitIsBreakingChange}}{{#conventionalCommitScope}}**{{conventionalCommitScope}}**: {{/conventionalCommitScope}}{{conventionalCommitDescription}}{{#conventionalCommitBreakingChangeContent}}: *{{conventionalCommitBreakingChangeContent}}*{{/conventionalCommitBreakingChangeContent}} ({{commitShortHash}}){{/commitIsConventional}}{{^commitIsConventional}}{{commitTitle}} ({{commitShortHash}}){{/commitIsConventional}}{{#commitHasIssues}}, closes{{#commitIssues}} {{issue}}{{/commitIssues}}{{/commitHasIssues}}"
hide {
uncategorized = true
contributors = listOf("Weblate", "GitHub", "semantic-release-bot", "[bot]", "github-actions")
}
excludeLabels.add("chore")
category {
title = "🏎 Perf"
key = "perf"
labels.add("perf")
order = 25
}
category {
title = "🌐 Translation"
key = "i18n"
labels.add("i18n")
order = 70
}
category {
title = "⚙️ Dependencies"
key = "dependencies"
labels.add("dependencies")
order = 80
}
labeler {
label = "perf"
title = "regex:^(?:perf(?:\\(.*\\))?!?):\\s.*"
order = 120
}
labeler {
label = "i18n"
title = "regex:^(?:i18n(?:\\(.*\\))?!?):\\s.*"
order = 130
}
labeler {
label = "dependencies"
title = "regex:^(?:deps(?:\\(.*\\))?!?):\\s.*"
order = 140
}
extraProperties.put("categorizeScopes", true)
append {
enabled = true
title = "# [{{projectVersion}}]({{repoUrl}}/compare/{{previousTagName}}...{{tagName}}) ({{#f_now}}YYYY-MM-dd{{/f_now}})"
target = rootDir.resolve("CHANGELOG.md")
content =
"""
{{changelogTitle}}
{{changelogChanges}}
""".trimIndent()
}
}
issues {
enabled = true
comment = "🎉 This issue has been resolved in `{{tagName}}` ([Release Notes]({{releaseNotesUrl}}))"
applyMilestone = Apply.ALWAYS
label {
name = "released"
description = "Issue has been released"
color = "#ededed"
}
}
}
}
distributions {
create("komga") {
active = Active.RELEASE
distributionType = SINGLE_JAR
artifact {
path = rootDir.resolve("komga/build/libs/komga-{{projectVersion}}.jar")
}
}
}
packagers {
docker {
active = Active.RELEASE
continueOnError = false
templateDirectory = rootDir.resolve("komga/docker")
repository.active = Active.NEVER
buildArgs = listOf("--cache-from", "gotson/komga:latest")
imageNames =
listOf(
"komga:latest",
"komga:{{projectVersion}}",
"komga:{{projectVersionMajor}}.x",
)
registries {
create("docker.io") { externalLogin = true }
create("ghcr.io") { externalLogin = true }
}
buildx {
enabled = true
createBuilder = false
platforms =
listOf(
"linux/amd64",
"linux/arm/v7",
"linux/arm64/v8",
)
}
}
}
}
}

View file

@ -1,69 +0,0 @@
{
"types": {
"refactor": {
"description": "Changes which neither fix a bug nor add a feature"
},
"fix": {
"description": "Changes which patch a bug"
},
"feat": {
"description": "Changes which introduce a new feature"
},
"build": {
"description": "Changes which affect the build system or external dependencies.<br/>Example scopes: gulp, broccoli, npm"
},
"chore": {
"description": "Changes which aren't user-facing"
},
"style": {
"description": "Changes which don't affect code logic, such as white-spaces, formatting, missing semi-colons"
},
"test": {
"description": "Changes which add missing tests or correct existing tests"
},
"docs": {
"description": "Changes which affect documentation"
},
"perf": {
"description": "Changes which improve performance"
},
"i18n": {
"description": "Changes which affect translation"
},
"deps": {
"description": "Changes which affect dependencies"
},
"ci": {
"description": "Changes which affect CI configuration files and scripts.<br/>Example scopes: travis, circle, browser-stack, sauce-labs"
},
"revert": {
"description": "Changes which revert a previous commit"
}
},
"footerTypes": [
{
"name": "BREAKING-CHANGE",
"description": "The commit introduces breaking API changes"
},
{
"name": "Closes",
"description": "The commit closes issues or pull requests"
},
{
"name": "Implements",
"description": "The commit implements features"
},
{
"name": "Author",
"description": "The commit's author"
},
{
"name": "Co-authored-by",
"description": "The commit is co-authored by another person.<br/>For multiple people use one line each"
},
{
"name": "Refs",
"description": "The commit references other commits by their hash ID.<br/>For multiple hash IDs use a comma as separator"
}
]
}

View file

@ -1,24 +0,0 @@
include required("conveyor.conf")
app {
mac.certificate = apple.cer
mac.notarization {
issuer-id = ${env.APPLE_ISSUER_ID}
key-id = ${env.APPLE_KEY_ID}
# the secret is written to file by CI from Github Secrets
private-key = ./secret/apple_private_key.p8
}
site {
consistency-checks = warn
copy-to = "s3:"${env.AWS_S3_BUCKET}/
s3 {
# Still required by Conveyor even though endpoint is set
region = "unused"
access-key-id = ${env.AWS_ACCESS_KEY_ID}
secret-access-key = ${env.AWS_SECRET_ACCESS_KEY}
endpoint = ${env.AWS_S3_ENDPOINT}
}
}
}

View file

@ -1,71 +0,0 @@
include "#!./gradlew -q :komga-tray:printConveyorConfig"
include required("/stdlib/jdk/23/eclipse.conf")
app {
display-name = Komga
fsname = komga
vcs-url = "https://github.com/gotson/komga"
vendor = "Gotson"
description = "Media server for comics/mangas/BDs with API and OPDS support"
license = MIT
icons = "res/komga_text_as_path.svg"
machines = [
windows.amd64,
mac
]
jvm {
// for NightMonkeys & NightCompress
options += "--enable-native-access=ALL-UNNAMED"
mac.options += "-Dspring.profiles.include=mac"
windows.options += "-Dspring.profiles.include=windows"
modules = [
java.base
java.compiler
java.datatransfer
java.desktop
java.instrument
java.logging
java.management
java.naming
java.net.http
java.prefs
java.rmi
java.scripting
java.security.jgss
java.sql
java.sql.rowset
java.transaction.xa
java.xml
jdk.jfr
jdk.management
jdk.unsupported
]
}
windows {
exe-installer-basename = "KomgaInstaller"
manifests.msix.background-color = transparent
inputs += ./komga-tray/lib/windows/x64/
amd64.inputs += "https://github.com/pgaskin/kepubify/releases/latest/download/kepubify-windows-64bit.exe" -> kepubify.exe
aarch64.inputs += "https://github.com/pgaskin/kepubify/releases/latest/download/kepubify-windows-arm64.exe" -> kepubify.exe
}
mac {
info-plist.LSMinimumSystemVersion = 13
aarch64.inputs += ./komga-tray/lib/mac/aarch64/
aarch64.inputs += "https://github.com/pgaskin/kepubify/releases/latest/download/kepubify-darwin-arm64" -> kepubify
amd64.inputs += ./komga-tray/lib/mac/x64/
amd64.inputs += "https://github.com/pgaskin/kepubify/releases/latest/download/kepubify-darwin-64bit" -> kepubify
}
site {
base-url = "https://download.komga.org"
}
}
conveyor.compatibility-level = 18

View file

@ -1,3 +0,0 @@
include required("conveyor.conf")
app.jvm.modules = detect

View file

@ -1,11 +0,0 @@
include required("conveyor.msstore.conf")
app {
windows {
store {
client-id = ${env.CONVEYOR_MSSTORE_CLIENT_ID}
client-secret = ${env.CONVEYOR_MSSTORE_CLIENT_SECRET}
tenant-id = ${env.CONVEYOR_MSSTORE_TENANT_ID}
}
}
}

View file

@ -1,16 +0,0 @@
include required("conveyor.conf")
app {
fsname = komga-msstore
windows {
manifests.msix.use-update-escape-hatch = false
store {
identity-name = 612Gotson.Komga
publisher = "CN=CF37C563-9649-4277-990F-CDD0CDCB78C1"
publisher-display-name = Gotson
store-id = 9N924KC4S4HG
}
certificate = self signed by ${app.windows.store.publisher}
}
}

10
doc/application.yml Normal file
View file

@ -0,0 +1,10 @@
komga:
root-folder: /your/library/root/directory
root-folder-scan-cron: "* */15 * * * ?" #periodic scan every 15 minutes
user-password: user-password
admin-password: admin-password
spring:
datasource:
url: jdbc:h2:/config/database.h2;DB_CLOSE_DELAY=-1
profiles:
active: prod

17
doc/docker-compose.yml Normal file
View file

@ -0,0 +1,17 @@
---
version: '3'
services:
komga:
image: gotson/komga
container_name: komga
volumes:
- ~/opt/appdata/komga:/config
- /mnt/nas/media/Books/:/books
- /etc/timezone:/etc/timezone:ro
ports:
- 8090:8080
user: "1000:1000"
environment:
- KOMGA_USER_PASSWORD=your-user-password
- KOMGA_ADMIN_PASSWORD=your-admin-password
restart: unless-stopped

View file

@ -1,2 +0,0 @@
version=1.24.4
org.gradle.jvmargs=-Xmx2G

View file

@ -1,10 +0,0 @@
[versions]
sqliteJdbc = "3.50.2.0"
nightmonkeys = "1.0.0"
twelvemonkeys = "3.12.0"
springboot = "3.5.14"
lucene = "9.9.1" # v10 requires JDK 21
jooq = "3.19.32" # should be aligned with the version provided by Spring Boot
[plugins]
gradleGitProperties = {id = "com.gorylenko.gradle-git-properties", version = "2.5.7"}

Binary file not shown.

View file

@ -1,7 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-all.zip
networkTimeout=10000
validateDistributionUrl=true
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.1-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

297
gradlew vendored
View file

@ -1,7 +1,7 @@
#!/bin/sh
#!/usr/bin/env sh
#
# Copyright © 2015-2021 the original authors.
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -15,115 +15,80 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (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
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
MAX_FD="maximum"
warn () {
echo "$*"
} >&2
}
die () {
echo
echo "$*"
echo
exit 1
} >&2
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH="\\\"\\\""
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD=$JAVA_HOME/bin/java
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
@ -132,120 +97,92 @@ Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

62
gradlew.bat vendored
View file

@ -13,10 +13,8 @@
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%"=="" @echo off
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@ -27,14 +25,10 @@
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@ -43,13 +37,13 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
if "%ERRORLEVEL%" == "0" goto init
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 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.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
@ -57,36 +51,48 @@ goto fail
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
if exist "%JAVA_EXE%" goto init
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 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.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
if "%ERRORLEVEL%"=="0" goto mainEnd
: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%
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal

View file

@ -1,56 +0,0 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
plugins {
run {
kotlin("jvm")
kotlin("plugin.spring")
}
alias(libs.plugins.gradleGitProperties)
id("org.jetbrains.compose") version "1.8.2"
id("org.jetbrains.kotlin.plugin.compose") version "2.2.0"
id("dev.hydraulic.conveyor") version "1.12"
application
}
group = "org.gotson"
repositories {
mavenCentral()
google()
}
kotlin {
compilerOptions {
jvmTarget = JvmTarget.JVM_17
}
}
tasks {
withType<JavaCompile> {
sourceCompatibility = "17"
targetCompatibility = "17"
}
}
dependencies {
implementation(project(":komga"))
implementation(compose.desktop.currentOs)
implementation(compose.components.resources)
linuxAmd64(compose.desktop.linux_x64)
macAmd64(compose.desktop.macos_x64)
macAarch64(compose.desktop.macos_arm64)
windowsAmd64(compose.desktop.windows_x64)
}
application {
mainClass = "org.gotson.komga.DesktopApplicationKt"
}
// Work around temporary Compose bugs
configurations.all {
attributes {
attribute(Attribute.of("ui", String::class.java), "awt")
}
}

View file

@ -1,20 +0,0 @@
java.base
java.compiler
java.datatransfer
java.desktop
java.instrument
java.logging
java.management
java.naming
java.net.http
java.prefs
java.rmi
java.scripting
java.security.jgss
java.sql
java.sql.rowset
java.transaction.xa
java.xml
jdk.jfr
jdk.management
jdk.unsupported

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show more