├── .editorconfig ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.yml │ └── config.yml ├── dependabot.yml └── workflows │ ├── ci-alpine-build.yml │ ├── ci-alpine-release.yml │ ├── ci-auto-rerun-failed-jobs-action.yml │ ├── ci-checks.yml │ ├── ci-debian-build.yml │ ├── ci-main-reusable-caller.yml │ └── deploy.yml ├── .gitignore ├── .pre-commit-config.yaml ├── .vscode └── settings.json ├── LICENSE.txt ├── README.md ├── SECURITY.md ├── changelog.md ├── docs ├── .gitignore ├── .vscode │ └── settings.json ├── README.md ├── astro-start.cmd ├── astro-upgrade.cmd ├── astro.config.mjs ├── ec.config.mjs ├── package-lock.json ├── package.json ├── public │ ├── docs_images │ │ ├── github_settings_actions_options.png │ │ ├── reusable_workflow_inputs-debug.png │ │ ├── reusable_workflow_inputs.png │ │ └── script_usage │ │ │ ├── 1.png │ │ │ ├── first-run.png │ │ │ └── help.png │ ├── favicon.ico │ ├── favicon.svg │ ├── icons │ │ ├── danger.svg │ │ ├── important.svg │ │ ├── note-circle.svg │ │ ├── note.svg │ │ ├── png │ │ │ ├── idea.png │ │ │ ├── info.png │ │ │ ├── notes.png │ │ │ ├── post-it.png │ │ │ ├── star.png │ │ │ ├── sticky-note.png │ │ │ ├── sticky-notes.png │ │ │ ├── tips.png │ │ │ └── warning.png │ │ ├── star-tip.svg │ │ ├── tip.svg │ │ └── warning.svg │ ├── logo-alpine.svg │ ├── logo-github.svg │ ├── logo-large-qbittorrent.svg │ ├── logo-musl - Copy.svg │ ├── logo-musl.svg │ ├── logo-qbittorrent.svg │ ├── logo-static - Copy.svg │ └── logo-static.svg ├── src │ ├── charts │ │ ├── example.html │ │ └── radarr.html │ ├── components │ │ ├── Header.astro │ │ ├── advancedButton.astro │ │ ├── advancedMarkdown.astro │ │ ├── buildinfo.astro │ │ ├── charts.astro │ │ ├── details.astro │ │ ├── github-actions.astro │ │ ├── global.jsx │ │ ├── important.astro │ │ ├── modal.astro │ │ └── patchinfo.astro │ ├── content │ │ ├── config.ts │ │ └── docs │ │ │ ├── artifact-attestations.mdx │ │ │ ├── build-help.mdx │ │ │ ├── credits.mdx │ │ │ ├── debugging.mdx │ │ │ ├── github-actions.mdx │ │ │ ├── glossary │ │ │ ├── bash.md │ │ │ ├── buildjet.md │ │ │ ├── crossbuild-essentials.md │ │ │ ├── docker-desktop.md │ │ │ ├── docker.md │ │ │ ├── github-actions.md │ │ │ ├── github-releases.md │ │ │ ├── github-workflows.md │ │ │ ├── github.md │ │ │ ├── glibc.md │ │ │ ├── musl-cross-make.md │ │ │ ├── muslc.md │ │ │ ├── powershell.md │ │ │ ├── qemu.md │ │ │ └── wsl2.md │ │ │ ├── index.mdx │ │ │ ├── install-qbittorrent.mdx │ │ │ ├── introduction.mdx │ │ │ ├── nginx-proxypass.mdx │ │ │ ├── patching.mdx │ │ │ ├── prerequisites.mdx │ │ │ ├── script-installation.mdx │ │ │ ├── script-usage.mdx │ │ │ ├── systemd.mdx │ │ │ └── test.mdx │ ├── env.d.ts │ ├── pages │ │ ├── changelog.astro │ │ └── glossary.astro │ ├── styles │ │ └── custom.css │ └── themes │ │ └── expressive-code │ │ ├── Snazzy-Light-color-theme.json │ │ ├── aura-soft-dark-soft-text-color-theme.json │ │ ├── bearded-theme-coffee-cream.json │ │ └── bridge.json ├── template.md ├── tsconfig.json └── upgrade.ps1 ├── patches ├── double_conversion │ └── 3.3.1 │ │ └── patch ├── libtorrent │ ├── 1.2.16 │ │ └── Jamfile │ ├── 1.2.17 │ │ └── Jamfile │ ├── 2.0.4 │ │ └── patch │ ├── 2.0.5 │ │ └── patch │ ├── 2.0.6 │ │ └── Jamfile │ └── 2.0.7 │ │ └── Jamfile ├── qbittorrent │ ├── 4.4.3.1 │ │ └── patch │ ├── 4.4.4 │ │ └── patch │ ├── 4.5.1 │ │ └── patch │ ├── 4.6.1 │ │ └── patch │ ├── 4.6.7 │ │ └── url │ └── 5.0.4 │ │ └── patch ├── qtbase │ └── 6.7.0-beta1 │ │ └── url └── qttools │ └── 6.7.2 │ ├── patch │ └── url ├── qbittorrent-nox-static.sh ├── qbt-nox-static.bash └── zizmor.yml /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | charset = utf-8 6 | trim_trailing_whitespace = true 7 | insert_final_newline = true 8 | indent_style = tab 9 | indent_size = 4 10 | 11 | [{**.*sh,test/run,**.bats}] 12 | indent_size = 4 13 | indent_style = tab 14 | 15 | shell_variant = bash 16 | binary_next_line = true # like -bn 17 | switch_case_indent = true # like -ci 18 | space_redirects = true # like -sr 19 | keep_padding = false # like -kp 20 | end_of_line = lf 21 | charset = utf-8 22 | trim_trailing_whitespace = true 23 | insert_final_newline = true 24 | 25 | [**.md] 26 | indent_size = 4 27 | indent_style = space 28 | 29 | [**.bats] 30 | indent_style = tab 31 | shell_variant = bats 32 | 33 | [*.{yml,yaml,html}] 34 | indent_style = space 35 | indent_size = 2 36 | 37 | [*.json] 38 | insert_final_newline = false 39 | indent_style = space 40 | indent_size = 2 41 | 42 | [**.astro] 43 | indent_size = 2 44 | indent_style = tab 45 | end_of_line = lf 46 | 47 | [**.css] 48 | indent_size = 4 49 | indent_style = space 50 | end_of_line = lf 51 | 52 | [LICENSE.txt] 53 | indent_style = space 54 | indent_size = 2 55 | 56 | [**.txt] 57 | 58 | [patch] 59 | indent_style = space 60 | indent_size = 0 61 | trim_trailing_whitespace = false 62 | 63 | [url] 64 | insert_final_newline = false 65 | 66 | [patch] 67 | indent_style = space 68 | indent_size = 0 69 | 70 | [Jamfile] 71 | indent_style = tab 72 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * -text 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: Bug Report 2 | description: An issue with the build script. 3 | body: 4 | - type: markdown 5 | attributes: 6 | value: | 7 | ### When to open an issue. 8 | 9 | If you had an issue with the build script i.e. It failed to build or exited with an error. 10 | 11 | Then please make sure you provide the following information: 12 | 13 | - What Host are you building on? It should be Alpine but Debian based for script bugs is ok. 14 | - What method to Build? If it's not Docker it should be. 15 | - What build options you used? The relevant part of the log file from `qbt-build/logs` 16 | 17 | ### When NOT to open an issue. 18 | 19 | If you are having a problem with `qBittorrent` that is nothing to do with the build script. 20 | 21 | - Read the docs https://userdocs.github.io/qbittorrent-nox-static/ for basic configuration and usage post build. 22 | - If that does not help then open a discussion on the [GitHub Discussions](https://github.com/userdocs/qbittorrent-nox-static/discussions/new/choose) instead of an issue. 23 | - Don't open an issue for generic application issues, only for build script issues. 24 | 25 | - type: textarea 26 | attributes: 27 | label: "What's wrong?" 28 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | # Maintain dependencies for GitHub Actions 4 | - package-ecosystem: "github-actions" 5 | directory: "/" 6 | schedule: 7 | interval: "daily" 8 | - package-ecosystem: "npm" 9 | directory: "/docs" 10 | schedule: 11 | interval: "daily" 12 | ignore: 13 | - dependency-name: "*" 14 | -------------------------------------------------------------------------------- /.github/workflows/ci-alpine-build.yml: -------------------------------------------------------------------------------- 1 | # @credits https://github.com/c0re100/qBittorrent-Enhanced-Edition 2 | name: ci - alpine build 3 | 4 | on: 5 | workflow_call: 6 | inputs: 7 | distinct_id: 8 | description: "Distinct id" 9 | required: false 10 | type: string 11 | workflow-files: 12 | description: "Alpine: workflow-files files" 13 | required: true 14 | type: string 15 | icu: 16 | description: "enable icu" 17 | required: true 18 | type: string 19 | debug: 20 | description: "debug builds" 21 | required: true 22 | type: string 23 | script_name: 24 | description: "script name" 25 | required: true 26 | type: string 27 | jobs: 28 | build-alpine: 29 | runs-on: ubuntu-24.04-arm 30 | strategy: 31 | fail-fast: false 32 | matrix: 33 | os_id: [alpine] 34 | os_version_id: [edge] 35 | qbt_cross_name: ["armhf", "armv7", "aarch64", "x86_64", "x86"] 36 | qbt_libtorrent_version: ["1.2", "2.0"] 37 | qbt_build_tool: ["", "qmake"] 38 | include: 39 | - qbt_build_tool: "qmake" 40 | qbt_qt_version_name: "qt5-" 41 | qbt_qt_version: "5" 42 | - qbt_build_tool: "" 43 | qbt_qt_version_name: "" 44 | qbt_qt_version: "6" 45 | 46 | name: "${{ matrix.qbt_cross_name }}-${{ matrix.qbt_qt_version_name }}libtorrent-v${{ matrix.qbt_libtorrent_version }}" 47 | 48 | env: 49 | qbt_build_dir: "qbt-build" 50 | script_name: ${{ inputs.script_name }} 51 | container_name: "multiarch" 52 | 53 | steps: 54 | - name: Checkout ${{ inputs.distinct_id }} 55 | uses: actions/checkout@v4 56 | with: 57 | persist-credentials: false 58 | 59 | - name: Host - Create Docker template env file ${{ inputs.distinct_id }} 60 | env: 61 | set_skip_icu: ${{ inputs.icu }} 62 | set_workflow_files: ${{ inputs.workflow-files }} 63 | set_build_debug: ${{ inputs.debug }} 64 | run: | 65 | printf '%s\n' "qbt_build_dir=${{ env.qbt_build_dir }}" > env.custom 66 | printf '%s\n' "qbt_libtorrent_version=${{ matrix.qbt_libtorrent_version }}" >> env.custom 67 | printf '%s\n' "qbt_qt_version=${{ matrix.qbt_qt_version }}" >> env.custom 68 | printf '%s\n' "qbt_build_tool=${{ matrix.qbt_build_tool }}" >> env.custom 69 | printf '%s\n' "qbt_cross_name=${{ matrix.qbt_cross_name }}" >> env.custom 70 | printf '%s\n' "qbt_patches_url=${{ github.repository }}" >> env.custom 71 | printf '%s\n' "qbt_skip_icu=${set_skip_icu}" >> env.custom 72 | printf '%s\n' "qbt_boost_tag=${{ matrix.qbt_boost_tag }}" >> env.custom 73 | printf '%s\n' "qbt_libtorrent_tag=${{ matrix.qbt_libtorrent_tag }}" >> env.custom 74 | printf '%s\n' "qbt_qt_tag=${{ matrix.qbt_qt_tag }}" >> env.custom 75 | printf '%s\n' "qbt_qbittorrent_tag=${{ matrix.qbt_qbittorrent_tag }}" >> env.custom 76 | printf '%s\n' "qbt_libtorrent_master_jamfile=" >> env.custom 77 | printf '%s\n' "qbt_workflow_files=${set_workflow_files}" >> env.custom 78 | printf '%s\n' "qbt_workflow_artifacts=" >> env.custom 79 | printf '%s\n' "qbt_cache_dir=" >> env.custom 80 | printf '%s\n' "qbt_optimise_strip=" >> env.custom 81 | printf '%s\n' "qbt_build_debug=${set_build_debug}" >> env.custom 82 | printf '%s\n' "qbt_revision_url=${{ github.repository }}" >> env.custom 83 | printf '%s\n' "qbt_standard=" >> env.custom 84 | printf '%s\n' "qbt_static_ish=" >> env.custom 85 | 86 | # - name: Host - Github env to container ${{ inputs.distinct_id }} 87 | # run: env >> env.custom 88 | 89 | - name: Host - check stuff ${{ inputs.distinct_id }} 90 | run: export $(cat env.custom) && bash ${script_name} 91 | 92 | - name: Host - qBittorrent v5 transition ${{ inputs.distinct_id }} 93 | run: | 94 | if [[ -f "${qbt_build_dir}/release_info/disable-qt5" || -f "disable-qt5" ]]; then 95 | printf '%s\n' "disable_qt5=yes" >> $GITHUB_ENV 96 | printf '%s\n' "Found file: \`disable-qt5\` -> setting env: \`disable_qt5=yes\`" >> $GITHUB_STEP_SUMMARY 97 | fi 98 | 99 | - name: Host - phased updates ${{ inputs.distinct_id }} 100 | if: env.disable_qt5 != 'yes' 101 | run: printf '%s\n' 'APT::Get::Always-Include-Phased-Updates "false";' | sudo tee /etc/apt/apt.conf.d/99-phased-updates 102 | 103 | - name: Host - update ${{ inputs.distinct_id }} 104 | if: env.disable_qt5 != 'yes' 105 | run: sudo apt-get update 106 | 107 | # - name: Host - upgrade ${{ inputs.distinct_id }} 108 | # run: sudo apt-get -y upgrade 109 | 110 | - name: Host - set up qemu-user-static binfmt-support ${{ inputs.distinct_id }} 111 | if: env.disable_qt5 != 'yes' 112 | run: sudo apt install libpipeline1 qemu-user-static binfmt-support 113 | 114 | - name: Host - Create docker ${{ env.multiarch }} container ${{ inputs.distinct_id }} 115 | if: env.disable_qt5 != 'yes' 116 | run: | 117 | # We create an Alpine edge container for cross-compilation with a user named gh which has same id as runner 1001 and provide sudo access 118 | # This way we can run commands as a non-root user, avoiding permission issues on host runner. Switching between user and root as needed. 119 | docker run --name ${container_name} -it -d --env-file env.custom -w /home/gh -v ${{ github.workspace }}:/home/gh ${{ matrix.os_id }}:${{ matrix.os_version_id }} 120 | # Create the user gh with the id 1001:1001 which is the same as the runner user id and group id. 121 | docker exec ${container_name} sh -c 'adduser -h /home/gh -Ds /bin/bash -u 1001 gh && apk add sudo' 122 | # Allow the user gh to run sudo without password prompt: docker exec -u gh:gh ${container_name} sudo ls 123 | docker exec ${container_name} sh -c 'printf "%s" "gh ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/gh' 124 | 125 | - name: Host - patches ${{ inputs.distinct_id }} 126 | if: env.disable_qt5 != 'yes' 127 | run: mkdir -p ${qbt_build_dir}/patches && cp -r patches/* ${qbt_build_dir}/patches/ 128 | 129 | - name: Docker - apk update ${{ inputs.distinct_id }} 130 | if: env.disable_qt5 != 'yes' 131 | run: docker exec ${container_name} apk update 132 | 133 | - name: Docker - apk install bash ${{ inputs.distinct_id }} 134 | if: env.disable_qt5 != 'yes' 135 | run: docker exec ${container_name} apk add bash 136 | 137 | - name: Docker - Bootstrap test tools ${{ inputs.distinct_id }} 138 | if: env.disable_qt5 != 'yes' 139 | run: docker exec ${container_name} bash ${script_name} update install_test 140 | 141 | - name: Docker - Bootstrap core deps ${{ inputs.distinct_id }} 142 | if: env.disable_qt5 != 'yes' 143 | run: docker exec ${container_name} bash ${script_name} install_core 144 | 145 | - name: Docker - Bootstrap build ${{ inputs.distinct_id }} 146 | if: env.disable_qt5 != 'yes' 147 | run: docker exec -u gh:gh ${container_name} bash ${script_name} -bs-a 148 | 149 | - name: Docker - zlib-ng ${{ inputs.distinct_id }} 150 | if: env.disable_qt5 != 'yes' 151 | run: docker exec -u gh:gh ${container_name} bash ${script_name} zlib 152 | 153 | - name: Docker - iconv ${{ inputs.distinct_id }} 154 | if: env.disable_qt5 != 'yes' 155 | run: docker exec -u gh:gh ${container_name} bash ${script_name} iconv 156 | 157 | - name: Docker - icu ${{ inputs.distinct_id }} 158 | if: env.disable_qt5 != 'yes' 159 | run: docker exec -u gh:gh ${container_name} bash ${script_name} icu 160 | 161 | - name: Docker - openssl ${{ inputs.distinct_id }} 162 | if: env.disable_qt5 != 'yes' 163 | run: docker exec -u gh:gh ${container_name} bash ${script_name} openssl 164 | 165 | - name: Docker - boost ${{ inputs.distinct_id }} 166 | if: env.disable_qt5 != 'yes' 167 | run: docker exec -u gh:gh ${container_name} bash ${script_name} boost 168 | 169 | - name: Docker - libtorrent ${{ inputs.distinct_id }} 170 | if: env.disable_qt5 != 'yes' 171 | run: docker exec -u gh:gh ${container_name} bash ${script_name} libtorrent 172 | 173 | - name: Docker - double_conversion ${{ inputs.distinct_id }} 174 | if: matrix.qbt_build_tool == '' && env.disable_qt5 != 'yes' 175 | run: docker exec -u gh:gh ${container_name} bash ${script_name} double_conversion 176 | 177 | - name: Docker - qtbase ${{ inputs.distinct_id }} 178 | if: env.disable_qt5 != 'yes' 179 | run: docker exec -u gh:gh ${container_name} bash ${script_name} qtbase 180 | 181 | - name: Docker - qttools ${{ inputs.distinct_id }} 182 | if: env.disable_qt5 != 'yes' 183 | run: docker exec -u gh:gh ${container_name} bash ${script_name} qttools 184 | 185 | - name: Docker - qbittorrent ${{ inputs.distinct_id }} 186 | if: env.disable_qt5 != 'yes' 187 | run: docker exec -u gh:gh ${container_name} bash ${script_name} qbittorrent 188 | 189 | - name: Docker - Set release asset name ${{ inputs.distinct_id }} 190 | if: env.disable_qt5 != 'yes' 191 | run: docker exec -u gh:gh -w /home/gh/${{ env.qbt_build_dir }}/completed ${container_name} mv -f qbittorrent-nox ${{ matrix.qbt_cross_name }}-${{ matrix.qbt_qt_version_name }}qbittorrent-nox 192 | 193 | - name: Generate artifact attestation ${{ inputs.distinct_id }} 194 | if: env.disable_qt5 != 'yes' 195 | uses: actions/attest-build-provenance@v2 196 | with: 197 | subject-path: "${{ env.qbt_build_dir }}/completed/${{ matrix.qbt_cross_name }}-${{ matrix.qbt_qt_version_name }}qbittorrent-nox" 198 | 199 | - name: Docker - Release Info ${{ inputs.distinct_id }} 200 | if: env.disable_qt5 != 'yes' 201 | run: docker exec -u gh:gh -w /home/gh/${{ env.qbt_build_dir }}/release_info ${container_name} bash -c 'mv *.md *.json '/home/gh/${{ env.qbt_build_dir }}/completed'' 202 | 203 | - name: Host - Upload libtorrent-v${{ matrix.qbt_libtorrent_version }}-qbittorrent-nox and release info artifact ${{ inputs.distinct_id }} 204 | if: success() && env.disable_qt5 != 'yes' 205 | uses: actions/upload-artifact@v4 206 | with: 207 | name: libtorrent-v${{ matrix.qbt_libtorrent_version }}-${{ matrix.qbt_cross_name }}-${{ matrix.qbt_qt_version_name }}qbittorrent-nox 208 | path: | 209 | ${{ env.qbt_build_dir }}/completed/* 210 | !${{ env.qbt_build_dir }}/completed/*.png 211 | 212 | - name: Host - Upload cmake graphs artifact ${{ inputs.distinct_id }} 213 | if: success() && matrix.qbt_build_tool == '' && env.disable_qt5 != 'yes' 214 | uses: actions/upload-artifact@v4 215 | with: 216 | name: "${{ matrix.qbt_cross_name }}-libtorrent-v${{ matrix.qbt_libtorrent_version }}-graphs" 217 | path: "${{ env.qbt_build_dir }}/completed/*.png" 218 | 219 | - name: Host - Upload logs on error 220 | if: failure() && env.disable_qt5 != 'yes' 221 | uses: actions/upload-artifact@v4 222 | with: 223 | name: "${{ matrix.qbt_cross_name }}-libtorrent-v${{ matrix.qbt_libtorrent_version }}-logs" 224 | path: "${{ env.qbt_build_dir }}/logs/*" 225 | -------------------------------------------------------------------------------- /.github/workflows/ci-alpine-release.yml: -------------------------------------------------------------------------------- 1 | name: ci - alpine-release 2 | 3 | on: 4 | workflow_call: 5 | inputs: 6 | distinct_id: 7 | description: "Distinct ID for the artifacts" 8 | required: true 9 | type: string 10 | 11 | jobs: 12 | release: 13 | runs-on: ubuntu-24.04-arm 14 | strategy: 15 | fail-fast: false 16 | matrix: 17 | qbt_libtorrent_version: ["1.2", "2.0"] 18 | include: 19 | - qbt_libtorrent_version: "1.2" 20 | preview_release: true 21 | 22 | - qbt_libtorrent_version: "2.0" 23 | preview_release: false 24 | 25 | name: "Publish release libtorrent-v${{ matrix.qbt_libtorrent_version }}" 26 | 27 | env: 28 | qbt_build_dir: "qbt-build" 29 | 30 | steps: 31 | - name: Checkout ${{ inputs.distinct_id }} 32 | uses: actions/checkout@v4 33 | with: 34 | persist-credentials: false 35 | 36 | - name: Pandoc - Bootstrap 37 | run: | 38 | pandoc_git_tag="$(git ls-remote -q -t --refs https://github.com/jgm/pandoc.git | awk '/tags\/[0-9]/{sub("refs/tags/", ""); print $2 }' | awk '!/^$/' | sort -rV | head -n 1)" 39 | curl -sLo- "https://github.com/jgm/pandoc/releases/latest/download/pandoc-${pandoc_git_tag}-linux-$(dpkg --print-architecture).tar.gz" | tar xzf - --strip-components 2 -C "$(pwd)" --exclude="share" 40 | 41 | - name: Host - Download 1.2 qbittorrent-nox artifacts ${{ inputs.distinct_id }} 42 | uses: actions/download-artifact@v4 43 | with: 44 | path: "1.2" 45 | pattern: libtorrent-v1.2-*-qbittorrent-nox 46 | merge-multiple: true 47 | 48 | - name: Host - Download 2.0 qbittorrent-nox artifacts ${{ inputs.distinct_id }} 49 | uses: actions/download-artifact@v4 50 | with: 51 | path: "2.0" 52 | pattern: libtorrent-v2.0-*-qbittorrent-nox 53 | merge-multiple: true 54 | 55 | - name: Host - merge release-info ${{ inputs.distinct_id }} 56 | run: | 57 | if [[ ${{ matrix.qbt_libtorrent_version }} == "1.2" ]]; then 58 | for release in 1\.2/*-release.md; do 59 | [[ -f "${release}" ]] && release+=("${release}") 60 | done 61 | revision="$(jq -r .revision 1\.2/*-dependency-version.json | head -n1)" 62 | boost="$(jq -r .boost 1\.2/*-dependency-version.json | head -n1)" 63 | fi 64 | 65 | if [[ ${{ matrix.qbt_libtorrent_version }} == "2.0" ]]; then 66 | for release in 2\.0/*-release.md; do 67 | [[ -f "${release}" ]] && release+=("${release}") 68 | done 69 | revision="$(jq -r .revision 2\.0/*-dependency-version.json | head -n1)" 70 | boost="$(jq -r .boost 2\.0/*-dependency-version.json | head -n1)" 71 | fi 72 | 73 | readarray -t release_sorted < <(printf '%s\n' "${release[@]}" | sort) 74 | 75 | for dependency_version_files in 1\.2/*-dependency-version.json 2\.0/*-dependency-version.json; do 76 | if [[ -f "${dependency_version_files}" ]]; then 77 | sed -r 's/"boost": (.*)/BOOST_PLACEHOLDER/g' -i "${dependency_version_files}" 78 | sed -r 's/"revision": (.*)/REVISION_PLACEHOLDER/g' -i "${dependency_version_files}" 79 | dependency_version+=("${dependency_version_files}") 80 | fi 81 | done 82 | 83 | readarray -t dependency_version_sorted < <(printf '%s\n' "${dependency_version[@]}" | sort) 84 | 85 | paste -d '\n' "${release_sorted[@]}" | uniq | awk '!(NF && seen[$0]++) || /^>/' > "tmp-release.md" 86 | paste -d '\n' "${dependency_version_sorted[@]}" | uniq | awk '!(NF && seen[$0]++)' > "dependency-version.json" 87 | 88 | sed -i "s|BOOST_PLACEHOLDER|\"boost\": \"${boost}\",|" dependency-version.json 89 | sed -i "s|REVISION_PLACEHOLDER|\"revision\": \"${revision}\"|" dependency-version.json 90 | 91 | ./pandoc --wrap=preserve -f gfm tmp-release.md -t gfm -o release.md 92 | 93 | - name: Host - Bootstrap release tag ${{ inputs.distinct_id }} 94 | run: printf '%s\n' "release_tag=$(cat ${{ matrix.qbt_libtorrent_version }}/tag.md)" >> $GITHUB_ENV 95 | 96 | - name: Host - Bootstrap release title ${{ inputs.distinct_id }} 97 | run: printf '%s\n' "release_title=$(cat ${{ matrix.qbt_libtorrent_version }}/title.md)" >> $GITHUB_ENV 98 | 99 | - name: Host- Create release - tag - assets ${{ inputs.distinct_id }} 100 | uses: ncipollo/release-action@v1 101 | with: 102 | prerelease: "${{ matrix.preview_release }}" 103 | artifacts: "${{ matrix.qbt_libtorrent_version }}/*-qbittorrent-nox,dependency-version.json" 104 | replacesArtifacts: true 105 | tag: "${{ env.release_tag }}" 106 | name: "${{ env.release_title }}" 107 | bodyFile: "release.md" 108 | allowUpdates: true 109 | token: "${{ github.TOKEN }}" 110 | -------------------------------------------------------------------------------- /.github/workflows/ci-auto-rerun-failed-jobs-action.yml: -------------------------------------------------------------------------------- 1 | name: ci - auto rerun failed jobs 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | run_id: 7 | description: "The run id of the workflow to rerun" 8 | required: true 9 | attempts: 10 | description: "The number of attempts to rerun the workflow" 11 | required: true 12 | retries: 13 | description: "The number of retries to rerun the workflow" 14 | required: true 15 | github_repo: 16 | description: "The repository to rerun the workflow" 17 | required: false 18 | distinct_id: 19 | description: "The distinct id of the workflow to rerun" 20 | required: false 21 | 22 | run-name: ci auto rerun failed jobs - attempt ${{ inputs.attempts }} 23 | 24 | jobs: 25 | gh-cli-rerun: 26 | name: rerun - attempt ${{ inputs.attempts }} 27 | permissions: 28 | actions: write 29 | runs-on: ubuntu-24.04-arm 30 | env: 31 | GH_TOKEN: "${{ secrets.AUTO_RERUN || github.token }}" 32 | steps: 33 | - name: Host - Checkout action ${{ inputs.distinct_id }} 34 | uses: actions/checkout@v4 35 | with: 36 | persist-credentials: false 37 | 38 | - uses: userdocs/gh-cli-workflow-reruns/actions/auto-rerun-failed@main 39 | with: 40 | run_id: ${{ inputs.run_id }} 41 | attempts: ${{ inputs.attempts }} 42 | retries: ${{ inputs.retries }} 43 | github_repo: ${{ inputs.github_repo || github.repository }} 44 | distinct_id: ${{ inputs.distinct_id || github.run_id }} 45 | -------------------------------------------------------------------------------- /.github/workflows/ci-checks.yml: -------------------------------------------------------------------------------- 1 | name: ci - checks 2 | on: 3 | push: 4 | pull_request: 5 | workflow_dispatch: 6 | 7 | concurrency: 8 | group: ${{ github.workflow }}-${{ github.ref }} 9 | cancel-in-progress: true 10 | 11 | jobs: 12 | sh-checker: 13 | runs-on: ubuntu-24.04-arm 14 | permissions: 15 | contents: read 16 | steps: 17 | - uses: actions/checkout@v4 18 | with: 19 | persist-credentials: false 20 | 21 | - name: Run the sh-checker 22 | uses: luizm/action-sh-checker@v0.9.0 23 | env: 24 | GITHUB_TOKEN: ${{ github.token }} 25 | SHELLCHECK_OPTS: -e SC2034,SC1091 # It is possible to exclude some shellcheck warnings. 26 | SHFMT_OPTS: -ci -sr -i 0 # It is possible to pass arguments to shftm 27 | with: 28 | sh_checker_comment: true 29 | sh_checker_exclude: "" 30 | 31 | zizmor-checker: 32 | runs-on: ubuntu-24.04-arm 33 | permissions: 34 | contents: read 35 | steps: 36 | - uses: actions/checkout@v4 37 | with: 38 | persist-credentials: false 39 | 40 | - name: Check GitHub Action workflows 41 | shell: bash {0} 42 | run: | 43 | pip install zizmor 44 | 45 | zizmor="$(zizmor . --gh-token "${{ github.token }}")" 46 | exit_code="$?" 47 | 48 | printf '%s\n' "$zizmor" 49 | 50 | printf '%b\n' "\`\`\`" >> $GITHUB_STEP_SUMMARY 51 | printf '%s\n' "$zizmor" >> $GITHUB_STEP_SUMMARY 52 | printf '%b' "\`\`\`" >> $GITHUB_STEP_SUMMARY 53 | 54 | exit "$exit_code" 55 | 56 | editorconfig-checker: 57 | runs-on: ubuntu-24.04-arm 58 | permissions: 59 | contents: read 60 | steps: 61 | - uses: actions/checkout@v4 62 | with: 63 | persist-credentials: false 64 | 65 | - name: editorconfig-checker 66 | env: 67 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 68 | run: | 69 | curl -Lo- "https://github.com/editorconfig-checker/editorconfig-checker/releases/latest/download/ec-linux-amd64.tar.gz" | tar xzf - --strip-components=1 70 | 71 | printf '%b\n' "\`\`\`" >> $GITHUB_STEP_SUMMARY 72 | ./ec-linux-amd64 --exclude '^(docs/.*|patches/.*)$' | sed "s,\x1B\[[0-9;]*[a-zA-Z],,g" >> $GITHUB_STEP_SUMMARY 73 | exit_code=("${PIPESTATUS[0]}") 74 | printf '%b' "\`\`\`" >> $GITHUB_STEP_SUMMARY 75 | 76 | # exit "${exit_code}" 77 | -------------------------------------------------------------------------------- /.github/workflows/ci-debian-build.yml: -------------------------------------------------------------------------------- 1 | name: ci - debian build 2 | 3 | on: 4 | workflow_call: 5 | inputs: 6 | distinct_id: 7 | description: "Distinct id" 8 | required: false 9 | type: string 10 | workflow-files: 11 | description: "Alpine: workflow-files files" 12 | required: true 13 | type: string 14 | icu: 15 | description: "enable icu" 16 | required: true 17 | type: string 18 | debug: 19 | description: "debug builds" 20 | required: true 21 | type: string 22 | script_name: 23 | description: "script name" 24 | required: true 25 | type: string 26 | 27 | jobs: 28 | build: 29 | defaults: 30 | run: 31 | shell: bash 32 | runs-on: ${{ matrix.runs_on }} 33 | strategy: 34 | fail-fast: false 35 | matrix: 36 | runs_on: [ubuntu-24.04, ubuntu-24.04-arm] 37 | container_id: [debian, ubuntu] 38 | container_codename: [bookworm, noble] 39 | qbt_build_tool: ["cmake", "qmake"] 40 | qbt_libtorrent_version: ["1.2", "2.0"] 41 | exclude: 42 | - container_id: debian 43 | container_codename: noble 44 | - container_id: ubuntu 45 | container_codename: bookworm 46 | include: 47 | - qbt_build_tool: "qmake" 48 | qbt_qt_version: "5" 49 | - qbt_build_tool: "cmake" 50 | qbt_qt_version: "6" 51 | - runs_on: ubuntu-24.04 52 | docker_arch: "amd64" 53 | - runs_on: ubuntu-24.04-arm 54 | docker_arch: "arm64v8" 55 | 56 | name: "${{ matrix.docker_arch }}-${{ matrix.container_id }}-${{ matrix.container_codename }}-${{ matrix.qbt_libtorrent_version }}-qt-${{ matrix.qbt_qt_version }}-${{ matrix.qbt_build_tool }}" 57 | 58 | env: # host 59 | qbt_build_dir: "qbt-build" 60 | disable_qt5: "" 61 | artifact_name: "${{ matrix.docker_arch }}-${{ matrix.container_id }}-${{ matrix.container_codename }}-${{ matrix.qbt_libtorrent_version }}-qt-${{ matrix.qbt_qt_version }}-${{ matrix.qbt_build_tool }}-nox" 62 | script_name: ${{ inputs.script_name }} 63 | 64 | container: 65 | image: ${{ matrix.docker_arch }}/${{ matrix.container_id }}:${{ matrix.container_codename }} 66 | env: # container 67 | LANG: C.UTF-8 68 | LC_ALL: C.UTF-8 69 | DEBIAN_FRONTEND: noninteractive 70 | disable_qt5: ${{ env.disable_qt5 }} 71 | qbt_build_dir: ${{ env.qbt_build_dir }} 72 | qbt_libtorrent_version: ${{ matrix.qbt_libtorrent_version }} 73 | qbt_qt_version: ${{ matrix.qbt_qt_version }} 74 | qbt_build_tool: ${{ matrix.qbt_build_tool }} 75 | qbt_cross_name: ${{ matrix.qbt_cross_name }} 76 | qbt_patches_url: ${{ github.repository }} 77 | qbt_skip_icu: ${{ inputs.icu }} 78 | qbt_boost_tag: ${{ matrix.qbt_boost_tag }} 79 | qbt_libtorrent_tag: ${{ matrix.qbt_libtorrent_tag }} 80 | qbt_qt_tag: ${{ matrix.qbt_qt_tag }} 81 | qbt_qbittorrent_tag: ${{ matrix.qbt_qbittorrent_tag }} 82 | qbt_libtorrent_master_jamfile: "" 83 | qbt_workflow_files: ${{ inputs.workflow-files }} 84 | qbt_workflow_artifacts: "" 85 | qbt_cache_dir: "" 86 | qbt_optimise_strip: "" 87 | qbt_build_debug: ${{ inputs.debug }} 88 | qbt_revision_url: ${{ github.repository }} 89 | qbt_standard: "" 90 | qbt_static_ish: "" 91 | steps: 92 | - name: Checkout ${{ inputs.distinct_id }} 93 | uses: actions/checkout@v4 94 | with: 95 | persist-credentials: false 96 | 97 | - name: bootstrap patches ${{ inputs.distinct_id }} 98 | if: env.disable_qt5 != 'yes' 99 | run: mkdir -p ${qbt_build_dir}/patches && cp -r patches/* ${qbt_build_dir}/patches/ 100 | 101 | - name: Bootstrap test tools ${{ inputs.distinct_id }} 102 | run: bash ${script_name} update install_test 103 | 104 | - name: qBittorrent v5 transition ${{ inputs.distinct_id }} 105 | run: | 106 | if [[ -f "${qbt_build_dir}/release_info/disable-qt5" || -f "disable-qt5" ]]; then 107 | printf '%s\n' "disable_qt5=yes" >> $GITHUB_ENV 108 | printf '%s\n' "Found file: \`disable-qt5\` -> setting env: \`disable_qt5=yes\`" >> $GITHUB_STEP_SUMMARY 109 | fi 110 | 111 | - name: Bootstrap core deps ${{ inputs.distinct_id }} 112 | if: env.disable_qt5 != 'yes' 113 | run: bash ${script_name} install_core 114 | 115 | - name: Bootstrap build ${{ inputs.distinct_id }} 116 | if: env.disable_qt5 != 'yes' 117 | run: bash ${script_name} -bs-a 118 | 119 | - name: glibc ${{ inputs.distinct_id }} 120 | if: env.disable_qt5 != 'yes' 121 | run: bash ${script_name} glibc 122 | 123 | - name: zlib ${{ inputs.distinct_id }} 124 | if: env.disable_qt5 != 'yes' 125 | run: bash ${script_name} zlib 126 | 127 | - name: iconv ${{ inputs.distinct_id }} 128 | if: env.disable_qt5 != 'yes' 129 | run: bash ${script_name} iconv 130 | 131 | - name: icu ${{ inputs.distinct_id }} 132 | if: env.disable_qt5 != 'yes' 133 | run: bash ${script_name} icu 134 | 135 | - name: openssl ${{ inputs.distinct_id }} 136 | if: env.disable_qt5 != 'yes' 137 | run: bash ${script_name} openssl 138 | 139 | - name: boost ${{ inputs.distinct_id }} 140 | if: env.disable_qt5 != 'yes' 141 | run: bash ${script_name} boost 142 | 143 | - name: libtorrent ${{ inputs.distinct_id }} 144 | if: env.disable_qt5 != 'yes' 145 | run: bash ${script_name} libtorrent 146 | 147 | - name: double conversion ${{ inputs.distinct_id }} 148 | if: env.disable_qt5 != 'yes' && matrix.qbt_build_tool == 'cmake' 149 | run: bash ${script_name} double_conversion 150 | 151 | - name: qtbase ${{ inputs.distinct_id }} 152 | if: env.disable_qt5 != 'yes' 153 | run: bash ${script_name} qtbase 154 | 155 | - name: qttools ${{ inputs.distinct_id }} 156 | if: env.disable_qt5 != 'yes' 157 | run: bash ${script_name} qttools 158 | 159 | - name: qbittorrent ${{ inputs.distinct_id }} 160 | if: env.disable_qt5 != 'yes' 161 | run: bash ${script_name} qbittorrent 162 | 163 | - name: Upload ${{ env.artifact_name }} artifacts ${{ inputs.distinct_id }} 164 | if: env.disable_qt5 != 'yes' 165 | uses: actions/upload-artifact@v4 166 | with: 167 | name: ${{ env.artifact_name }} 168 | path: ${{ env.qbt_build_dir }}/completed/qbittorrent-nox 169 | 170 | - name: Host - Upload logs on error 171 | if: failure() && env.disable_qt5 != 'yes' 172 | uses: actions/upload-artifact@v4 173 | with: 174 | name: "${{ env.artifact_name }}-logs" 175 | path: "${{ env.qbt_build_dir }}" 176 | -------------------------------------------------------------------------------- /.github/workflows/ci-main-reusable-caller.yml: -------------------------------------------------------------------------------- 1 | # @credits https://github.com/c0re100/qBittorrent-Enhanced-Edition 2 | name: ci - main reusable caller 3 | 4 | on: 5 | workflow_dispatch: 6 | inputs: 7 | script_name: 8 | description: "Which script to run?" 9 | required: true 10 | default: "qbt-nox-static.bash" 11 | type: choice 12 | options: ["qbt-nox-static.bash", "qbittorrent-nox-static.sh"] 13 | debian-build: 14 | description: "Debian: build" 15 | required: true 16 | default: false 17 | type: boolean 18 | alpine-build: 19 | description: "Alpine: build" 20 | required: true 21 | default: true 22 | type: boolean 23 | workflow-files: 24 | description: "Workflow files" 25 | required: true 26 | default: true 27 | type: boolean 28 | icu: 29 | description: "Enable icu" 30 | required: true 31 | default: false 32 | type: boolean 33 | debug: 34 | description: "Debug builds (symbols)" 35 | required: true 36 | default: false 37 | type: boolean 38 | release: 39 | description: "Release assets?" 40 | required: true 41 | default: true 42 | type: boolean 43 | distinct_id: 44 | description: "Distinct id" 45 | required: false 46 | type: string 47 | skip_rerun: 48 | description: "Skip rerun?" 49 | required: true 50 | default: false 51 | type: boolean 52 | retries: 53 | description: "Number of rerun retries" 54 | required: true 55 | default: "1" 56 | type: choice 57 | options: ["1", "2", "3", "4", "5", "6", "7", "8", "9"] 58 | 59 | permissions: {} 60 | 61 | jobs: 62 | ci-debian-build: 63 | if: github.event.inputs.debian-build == 'true' 64 | concurrency: 65 | group: ci-debian-build 66 | cancel-in-progress: true 67 | permissions: 68 | contents: read 69 | uses: ./.github/workflows/ci-debian-build.yml 70 | with: 71 | distinct_id: ${{ github.event.inputs.distinct_id }} 72 | workflow-files: ${{ github.event.inputs.workflow-files == 'true' && 'yes' || 'no' }} 73 | icu: ${{ github.event.inputs.icu == 'true' && 'no' || 'yes' }} 74 | debug: ${{ github.event.inputs.debug == 'true' && 'yes' || 'no' }} 75 | script_name: ${{ github.event.inputs.script_name }} 76 | 77 | ci-alpine-build: 78 | if: github.event.inputs.alpine-build == 'true' 79 | concurrency: 80 | group: ci-alpine-build 81 | cancel-in-progress: true 82 | permissions: 83 | id-token: write 84 | contents: read 85 | attestations: write 86 | uses: ./.github/workflows/ci-alpine-build.yml 87 | with: 88 | distinct_id: ${{ github.event.inputs.distinct_id }} 89 | workflow-files: ${{ github.event.inputs.workflow-files == 'true' && 'yes' || 'no' }} 90 | icu: ${{ github.event.inputs.icu == 'true' && 'no' || 'yes' }} 91 | debug: ${{ github.event.inputs.debug == 'true' && 'yes' || 'no' }} 92 | script_name: ${{ github.event.inputs.script_name }} 93 | 94 | ci-alpine-release: 95 | needs: [ci-alpine-build] 96 | if: github.event.inputs.release == 'true' && contains(needs.*.result, 'success') && !contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled') 97 | concurrency: 98 | group: ci-alpine-release 99 | cancel-in-progress: true 100 | permissions: 101 | contents: write 102 | uses: ./.github/workflows/ci-alpine-release.yml 103 | with: 104 | distinct_id: ${{ github.event.inputs.distinct_id }} 105 | 106 | ci-auto-rerun-failed-jobs: 107 | if: failure() && (github.event.inputs.skip_rerun || 'false') == 'false' 108 | needs: [ci-debian-build, ci-alpine-build, ci-alpine-release] 109 | concurrency: 110 | group: ci-auto-rerun-failed-jobs 111 | cancel-in-progress: true 112 | permissions: 113 | actions: write 114 | runs-on: ubuntu-24.04-arm 115 | env: 116 | GH_TOKEN: "${{ secrets.AUTO_RERUN || github.token }}" 117 | github_repo: "" # To use ci-auto-rerun-failed-jobs.yml hosted in a remote repository else default to the current repository. Requires PAT token AUTO_RERUN 118 | retries: ${{ github.event.inputs.retries || '1' }} 119 | distinct_id: ${{ github.event.inputs.distinct_id }} 120 | steps: 121 | - uses: actions/checkout@v4 122 | with: 123 | persist-credentials: false 124 | - name: ci-auto-rerun-failed-jobs via ${{ env.github_repo || github.repository }} 125 | run: > 126 | gh workflow run ci-auto-rerun-failed-jobs-action.yml 127 | --repo "${github_repo:-$GITHUB_REPOSITORY}" 128 | -f github_repo=${GITHUB_REPOSITORY} 129 | -f run_id=${GITHUB_RUN_ID} 130 | -f attempts=${GITHUB_RUN_ATTEMPT} 131 | -f retries=${retries} 132 | -f distinct_id=${distinct_id} 133 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: Deploy to GitHub Pages 2 | 3 | on: 4 | # Trigger the workflow every time you push to the `main` or `master` branch 5 | # but only if changes occur in the docs/ folder. 6 | push: 7 | branches: [master, main] 8 | paths: 9 | - 'docs/**' 10 | - 'changelog.md' 11 | # Allows you to run this workflow manually from the Actions tab on GitHub. 12 | workflow_dispatch: 13 | 14 | # Allow this job to clone the repo and create a page deployment 15 | 16 | jobs: 17 | build: 18 | runs-on: ubuntu-24.04-arm 19 | permissions: 20 | contents: read 21 | steps: 22 | - name: Checkout your repository using git 23 | uses: actions/checkout@v4 24 | with: 25 | persist-credentials: false 26 | 27 | - name: Install, build, and upload your site 28 | uses: withastro/action@v4 29 | with: 30 | path: ./docs 31 | 32 | deploy: 33 | needs: build 34 | runs-on: ubuntu-24.04-arm 35 | permissions: 36 | pages: write 37 | id-token: write 38 | environment: 39 | name: github-pages 40 | url: ${{ steps.deployment.outputs.page_url }} 41 | steps: 42 | - name: Deploy to GitHub Pages 43 | id: deployment 44 | uses: actions/deploy-pages@v4 45 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | /package-lock.json 3 | /package.json 4 | 5 | # Dependencies 6 | docs/node_modules 7 | 8 | # Production 9 | docs/build 10 | 11 | # Generated files 12 | docs/.docs 13 | docs/.docusaurus 14 | docs/.cache-loader 15 | 16 | # Misc 17 | docs/.DS_Store 18 | docs/.env.local 19 | docs/.env.development.local 20 | docs/.env.test.local 21 | docs/.env.production.local 22 | 23 | docs/npm-debug.log* 24 | docs/yarn-debug.log* 25 | docs/yarn-error.log* 26 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/woodruffw/zizmor-pre-commit 3 | rev: v1.0.1 4 | hooks: 5 | - id: zizmor 6 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "telemetry.enableTelemetry": false, 3 | "telemetry.enableCrashReporter": false, 4 | "cSpell.words": [ 5 | "wolfssl", 6 | "libtorrent" 7 | ], 8 | "shellformat.flag": "-ci -sr -i 0", 9 | "editor.formatOnSave": true, 10 | "editor.formatOnPaste": true, 11 | "editor.formatOnType": true, 12 | "editor.detectIndentation": false, 13 | "editor.insertSpaces": false, 14 | "shellcheck.customArgs": [ 15 | "-x" 16 | ], 17 | "shellcheck.useWorkspaceRootAsCwd": true, 18 | "shellcheck.run": "onType", 19 | "diffEditor.codeLens": true, 20 | "files.defaultLanguage": "shellscript", 21 | "[shellscript]": { 22 | "files.eol": "\n", 23 | "editor.tabSize": 4 24 | }, 25 | "[markdown]": { 26 | "files.eol": "\n", 27 | "editor.tabSize": 4 28 | }, 29 | "[yaml]": { 30 | "files.eol": "\n", 31 | "editor.tabSize": 2, 32 | "editor.insertSpaces": true 33 | }, 34 | "[astro]": { 35 | "files.eol": "\n", 36 | "editor.tabSize": 2, 37 | "editor.insertSpaces": true 38 | }, 39 | "typescript.tsdk": "node_modules/typescript/lib" 40 | } -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # qbittorrent-nox-static 2 | 3 | [![Codacy Badge](https://api.codacy.com/project/badge/Grade/9817ad80d35c480aa9842b53001d55b0)](https://app.codacy.com/gh/userdocs/qbittorrent-nox-static?utm_source=github.com&utm_medium=referral&utm_content=userdocs/qbittorrent-nox-static&utm_campaign=Badge_Grade) 4 | [![CodeFactor](https://www.codefactor.io/repository/github/userdocs/qbittorrent-nox-static/badge)](https://www.codefactor.io/repository/github/userdocs/qbittorrent-nox-static) 5 | [![CI](https://github.com/userdocs/qbittorrent-nox-static/actions/workflows/ci-main-reusable-caller.yml/badge.svg)](https://github.com/userdocs/qbittorrent-nox-static/actions/workflows/ci-main-reusable-caller.yml) 6 | 7 | ## Summary 8 | 9 | The `qbittorrent-nox-static` project is a `bash` build script that compiles a static `qbittorrent-nox` binary using the latest available dependencies from their source. These statically linked binaries can run on any matching CPU architecture and are not OS specific. This means you can run a `x86_64` Alpine edge build on any Linux based OS of like CentOS | Fedora | OpenSuse | Debian | Ubuntu and more. 10 | 11 | > [!TIP] 12 | > You don't need to use the script to access the binaries it creates, just use the [release tag](https://github.com/userdocs/qbittorrent-nox-static/tags) you need or [latest release page](https://github.com/userdocs/qbittorrent-nox-static/releases/latest) 13 | 14 | See here for how to [install the latest release](https://github.com/userdocs/qbittorrent-nox-static?tab=readme-ov-file#install-the-latest-release) 15 | 16 | ## Linked Github repositories 17 | 18 | This build script uses and depends on some related repositories. 19 | 20 | - [qbt-musl-cross-make](https://github.com/userdocs/qbt-musl-cross-make) 21 | - [qbt-workflow-files](https://github.com/userdocs/qbt-workflow-files) 22 | - [qbt-ninja-build](https://github.com/userdocs/qbt-ninja-build) 23 | - [qbt-cmake-ninja-crossbuilds](https://github.com/userdocs/qbt-cmake-ninja-crossbuilds) 24 | 25 | ## Documentation 26 | 27 | > [!TIP] 28 | > Visit the [documentation](https://userdocs.github.io/qbittorrent-nox-static/introduction/) for in depth information on using this project and script usage. 29 | 30 | ## WSL2 31 | 32 | > [!TIP] 33 | > These static builds can be used on WSL2 and accessed via `localhost:8080` using the download instructions below 34 | 35 | ## Install the latest release 36 | 37 | > [!TIP] 38 | > For the most current build visit the [latest release page](https://github.com/userdocs/qbittorrent-nox-static/releases/latest) 39 | 40 | Or uses these commands for your arch: 41 | 42 | ### x86 43 | 44 | ```bash 45 | mkdir -p ~/bin && source ~/.profile 46 | wget -qO ~/bin/qbittorrent-nox https://github.com/userdocs/qbittorrent-nox-static/releases/latest/download/x86-qbittorrent-nox 47 | chmod 700 ~/bin/qbittorrent-nox 48 | ``` 49 | 50 | ### x86_64 51 | 52 | ```bash 53 | mkdir -p ~/bin && source ~/.profile 54 | wget -qO ~/bin/qbittorrent-nox https://github.com/userdocs/qbittorrent-nox-static/releases/latest/download/x86_64-qbittorrent-nox 55 | chmod 700 ~/bin/qbittorrent-nox 56 | ``` 57 | 58 | ### armhf (armv6) 59 | 60 | ```bash 61 | mkdir -p ~/bin && source ~/.profile 62 | wget -qO ~/bin/qbittorrent-nox https://github.com/userdocs/qbittorrent-nox-static/releases/latest/download/armhf-qbittorrent-nox 63 | chmod 700 ~/bin/qbittorrent-nox 64 | ``` 65 | 66 | ### armv7 67 | 68 | ```bash 69 | mkdir -p ~/bin && source ~/.profile 70 | wget -qO ~/bin/qbittorrent-nox https://github.com/userdocs/qbittorrent-nox-static/releases/latest/download/armv7-qbittorrent-nox 71 | chmod 700 ~/bin/qbittorrent-nox 72 | ``` 73 | 74 | ### aarch64 75 | 76 | ```bash 77 | mkdir -p ~/bin && source ~/.profile 78 | wget -qO ~/bin/qbittorrent-nox https://github.com/userdocs/qbittorrent-nox-static/releases/latest/download/aarch64-qbittorrent-nox 79 | chmod 700 ~/bin/qbittorrent-nox 80 | ``` 81 | 82 | ## Libtorrent versions 83 | 84 | > [!IMPORTANT] 85 | > Libtorrent `v1.2` is currently the main branch supported by qBittorrent since a change with the release of [4.4.5](https://www.qbittorrent.org/news.php) 86 | 87 | Libtorrent `v2.0` builds are still released as latest releases as it it does not really matter to this project as it always builds and releases for both `v1.2` and `v2.0`. See the next section for how to get the version you need via the latest release URL. 88 | 89 | > [!TIP] 90 | > You can view the current latest and pre releases and tags here 91 | 92 | ## Getting the Version you want via the latest release URL 93 | 94 | Since this project builds and releases both v1.2 and v2.0 builds simultaneously we can use the commands below to always get the latest version of the related pre release via the latest release `dependency-version.json` asset. 95 | 96 | Using this method it does not matter which version is the latest release or pre release as the commands will provide you the version specific info you need for the twinned latest/pre releases. 97 | 98 | For Libtorrent `v1.2` 99 | 100 | ```bash 101 | jq -r '. | "release-\(.qbittorrent)_v\(.libtorrent_1_2)"' < <(curl -sL https://github.com/userdocs/qbittorrent-nox-static/releases/latest/download/dependency-version.json) 102 | ``` 103 | 104 | For Libtorrent `v2.0` 105 | 106 | ```bash 107 | jq -r '. | "release-\(.qbittorrent)_v\(.libtorrent_2_0)"' < <(curl -sL https://github.com/userdocs/qbittorrent-nox-static/releases/latest/download/dependency-version.json) 108 | ``` 109 | 110 | ## Revisions 111 | 112 | The build has 5 main dependencies tracked that will trigger a rebuild on an update being available. 113 | 114 | - qBittorrent 115 | - Libtorrent 116 | - Qt 117 | - Boost 118 | - Openssl 119 | 120 | When a new build is triggered for updating `qBittorrent` or `Libtorrent` a new release will be generated as the release tags will be updated. 121 | 122 | Since I do not append revision info to tags `Qt` - `Boost` - `Openssl` builds will only update the existing release assets. 123 | 124 | To track these revisions you can use this command. All new releases start at a revision of `0` and increment by `1` per revised build. 125 | 126 | ```bash 127 | jq -r '.revision' < <(curl -sL "https://github.com/userdocs/qbittorrent-nox-static/releases/latest/download/dependency-version.json") 128 | ``` 129 | 130 | ## Dependency json 131 | 132 | From `release-4.4.5` each release contains a `dependency-version.json` file that provide some key version information for that is shared across the latest release and the twinned pre release. This helps to overcome some limitations of the API for consistently and directly accessing this information. 133 | 134 | Downloading the file like this: 135 | 136 | ```bash 137 | curl -sL https://github.com/userdocs/qbittorrent-nox-static/releases/latest/download/dependency-version.json 138 | ``` 139 | 140 | Will output a result like this: 141 | 142 | ```json 143 | { 144 | "openssl": "3.2.0", 145 | "boost": "1.84.0", 146 | "libtorrent_1_2": "1.2.19", 147 | "libtorrent_2_0": "2.0.9", 148 | "qt5": "5.15.12", 149 | "qt6": "6.6.1", 150 | "qbittorrent": "4.6.2", 151 | "revision": "3" 152 | } 153 | ``` 154 | 155 | As demonstrated above by using the latest release URL we can construct the tag of the twinned pre release and therefore the asset URL with no margin for error. 156 | 157 | > [!IMPORTANT] 158 | > From the release of qBittorrent v5 configure based builds will be unsupported and we will only be able to use cmake to build qBittorrent v5 onwards. All releases from that point on will drop Qt5 builds as at this point cmake,Qt6 and v5 should be the default and preferred build combination with Qt5 being a legacy dependency. 159 | 160 | ## gh attestation verify 161 | 162 | Binaries built from the release of release `release-5.0.0_v2.0.10` and `release-5.0.0_v1.2.19` revision `1` use [actions/attest-build-provenance](https://github.com/actions/attest-build-provenance) 163 | 164 | Verify the integrity and provenance of an artifact using its associated cryptographically signed attestations. 165 | 166 | https://cli.github.com/manual/gh_attestation_verify 167 | 168 | For example: 169 | 170 | ```bash 171 | gh attestation verify x86_64-qbittorrent-nox -o userdocs 172 | ``` 173 | 174 | Will give you this result for the `release-5.0.0_v2.0.10` revision `1` binary. 175 | 176 | ```bash 177 | Loaded digest sha256:a656ff57b03ee6218205d858679ea189246caaecbbcc38d4d2b57eb81d8e59bb for file://x86_64-qbittorrent-nox 178 | Loaded 1 attestation from GitHub API 179 | ✓ Verification succeeded! 180 | 181 | sha256:a656ff57b03ee6218205d858679ea189246caaecbbcc38d4d2b57eb81d8e59bb was attested by: 182 | REPO PREDICATE_TYPE WORKFLOW 183 | userdocs/qbittorrent-nox-static https://slsa.dev/provenance/v1 .github/workflows/matrix_multi_build_and_release_qbt_workflow_files.yml@refs/heads/master 184 | ``` 185 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | Find bug? 4 | 5 | [Open issue](https://github.com/userdocs/qbittorrent-nox-static/issues/new/choose) 6 | 7 | Got question? 8 | 9 | [Start discussion](https://github.com/userdocs/qbittorrent-nox-static/discussions/new/choose) 10 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | # build output 2 | dist/ 3 | # generated types 4 | .astro/ 5 | 6 | # dependencies 7 | node_modules/ 8 | 9 | # logs 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | pnpm-debug.log* 14 | 15 | 16 | # environment variables 17 | .env 18 | .env.production 19 | 20 | # macOS-specific files 21 | .DS_Store 22 | -------------------------------------------------------------------------------- /docs/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.tsdk": "node_modules/typescript/lib", 3 | "cSpell.enableFiletypes": [ 4 | "mdx" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Starlight Starter Kit: Basics 2 | 3 | [![Built with Starlight](https://astro.badg.es/v2/built-with-starlight/tiny.svg)](https://starlight.astro.build) 4 | 5 | ``` 6 | npm create astro@latest -- --template starlight 7 | ``` 8 | 9 | [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/starlight/tree/main/examples/basics) 10 | [![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/starlight/tree/main/examples/basics) 11 | [![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fwithastro%2Fstarlight%2Ftree%2Fmain%2Fexamples%2Fbasics&project-name=my-starlight-docs&repository-name=my-starlight-docs) 12 | 13 | > 🧑‍🚀 **Seasoned astronaut?** Delete this file. Have fun! 14 | 15 | ## 🚀 Project Structure 16 | 17 | Inside of your Astro + Starlight project, you'll see the following folders and files: 18 | 19 | ``` 20 | . 21 | ├── public/ 22 | ├── src/ 23 | │ ├── assets/ 24 | │ ├── content/ 25 | │ │ ├── docs/ 26 | │ │ └── config.ts 27 | │ └── env.d.ts 28 | ├── astro.config.mjs 29 | ├── package.json 30 | └── tsconfig.json 31 | ``` 32 | 33 | Starlight looks for `.md` or `.mdx` files in the `src/content/docs/` directory. Each file is exposed as a route based on its file name. 34 | 35 | Images can be added to `src/assets/` and embedded in Markdown with a relative link. 36 | 37 | Static assets, like favicons, can be placed in the `public/` directory. 38 | 39 | ## 🧞 Commands 40 | 41 | All commands are run from the root of the project, from a terminal: 42 | 43 | | Command | Action | 44 | | :------------------------ | :----------------------------------------------- | 45 | | `npm install` | Installs dependencies | 46 | | `npm run dev` | Starts local dev server at `localhost:4321` | 47 | | `npm run build` | Build your production site to `./dist/` | 48 | | `npm run preview` | Preview your build locally, before deploying | 49 | | `npm run astro ...` | Run CLI commands like `astro add`, `astro check` | 50 | | `npm run astro -- --help` | Get help using the Astro CLI | 51 | 52 | ## 👀 Want to learn more? 53 | 54 | Check out [Starlight’s docs](https://starlight.astro.build/), read [the Astro documentation](https://docs.astro.build), or jump into the [Astro Discord server](https://astro.build/chat). 55 | -------------------------------------------------------------------------------- /docs/astro-start.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | powershell.exe -noexit -Command "& {Set-Location -literalPath '%~dp0.'; Invoke-Expression 'npm start'}" 3 | -------------------------------------------------------------------------------- /docs/astro-upgrade.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | powershell.exe -noexit -Command "& {Set-Location -literalPath '%~dp0.'; Invoke-Expression 'npx @astrojs/upgrade'}" 3 | -------------------------------------------------------------------------------- /docs/astro.config.mjs: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "astro/config"; 2 | import starlight from "@astrojs/starlight"; 3 | import starlightImageZoom from "starlight-image-zoom"; 4 | 5 | // https://astro.build/config 6 | export default defineConfig({ 7 | site: "https://userdocs.github.io", 8 | base: "/qbittorrent-nox-static", 9 | integrations: [ 10 | starlight({ 11 | plugins: [starlightImageZoom()], 12 | title: "qbittorrent-nox-static", 13 | logo: { 14 | src: "./public/logo-static.svg", 15 | }, 16 | components: { 17 | Header: "./src/components/Header.astro", 18 | }, 19 | 20 | social: [ 21 | { icon: 'github', label: 'GitHub', href: 'https://github.com/userdocs/qbittorrent-nox-static' }, 22 | ], 23 | 24 | customCss: [ 25 | // Relative path to your custom CSS file 26 | "./src/styles/custom.css", 27 | ], 28 | sidebar: [ 29 | { 30 | label: "Read the docs", 31 | items: [ 32 | // Each item here is one entry in the navigation menu. 33 | { 34 | label: "Introduction", 35 | link: "/introduction", 36 | }, 37 | { 38 | label: "Prerequisites Check List", 39 | link: "/prerequisites", 40 | }, 41 | { 42 | label: "Script Installation", 43 | link: "/script-installation", 44 | }, 45 | { 46 | label: "Script Usage", 47 | link: "/script-usage", 48 | }, 49 | { 50 | label: "Build Help", 51 | link: "/build-help", 52 | }, 53 | { 54 | label: "Patching", 55 | link: "/patching", 56 | }, 57 | { 58 | label: "Debugging", 59 | link: "/debugging", 60 | }, 61 | { 62 | label: "Install qbittorrent", 63 | link: "/install-qbittorrent", 64 | }, 65 | { 66 | label: "Nginx proxypass", 67 | link: "/nginx-proxypass", 68 | }, 69 | { 70 | label: "Systemd", 71 | link: "/systemd", 72 | }, 73 | { 74 | label: "Github - Artifact Attestations", 75 | link: "/artifact-attestations", 76 | }, 77 | { 78 | label: "Github actions", 79 | link: "/github-actions", 80 | }, 81 | { 82 | label: "Change Log", 83 | link: "/changelog", 84 | }, 85 | { 86 | label: "Credits", 87 | link: "/credits", 88 | }, 89 | { 90 | label: "Glossary", 91 | link: "/glossary", 92 | }, 93 | ], 94 | }, 95 | ], 96 | }), 97 | ], 98 | 99 | // https://discord.com/channels/830184174198718474/1070481941863878697/1211398665101516842 100 | vite: { 101 | plugins: [ 102 | { 103 | name: "custom-page-props", 104 | transform: (code, id) => { 105 | if ( 106 | id.includes("@astrojs/starlight/components/Page.astro") 107 | ) { 108 | return code.replace( 109 | / 19 | filePath.includes(path.normalize(allowedPath)) 20 | ); 21 | 22 | if (!isAllowed) { 23 | throw new Error("Access to this directory is not allowed"); 24 | } 25 | 26 | return fs.readFileSync(url, "utf-8"); 27 | } 28 | 29 | const jsoncStringLight = readFileSyncSafe( 30 | new URL( 31 | "./src/themes/expressive-code/Snazzy-Light-color-theme.json", 32 | import.meta.url 33 | ) 34 | ); 35 | 36 | const jsoncStringDark = readFileSyncSafe( 37 | new URL( 38 | "./src/themes/expressive-code/aura-soft-dark-soft-text-color-theme.json", 39 | import.meta.url 40 | ) 41 | ); 42 | 43 | const darkMode = ExpressiveCodeTheme.fromJSONString(jsoncStringDark); 44 | const lightMode = ExpressiveCodeTheme.fromJSONString(jsoncStringLight); 45 | 46 | /** @type {import('@astrojs/starlight/expressive-code').StarlightExpressiveCodeOptions} */ 47 | export default { 48 | // Example: Using a custom plugin (which makes this `ec.config.mjs` file necessary) 49 | plugins: [pluginCollapsibleSections()], 50 | defaultProps: { 51 | collapseStyle: "collapsible-start", 52 | frame: "none", 53 | }, 54 | themes: [darkMode, lightMode], 55 | tabWidth: 0, 56 | styleOverrides: { 57 | borderRadius: "0.1rem", 58 | frames: { 59 | shadowColor: "none", 60 | }, 61 | }, 62 | }; 63 | -------------------------------------------------------------------------------- /docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "proper-plasma", 3 | "type": "module", 4 | "version": "0.0.1", 5 | "scripts": { 6 | "dev": "astro dev", 7 | "start": "astro dev", 8 | "build": "astro build", 9 | "preview": "astro preview", 10 | "astro": "astro" 11 | }, 12 | "dependencies": { 13 | "@astrojs/starlight": "^0.34.3", 14 | "@expressive-code/plugin-collapsible-sections": "^0.41.1", 15 | "astro": "^5.8.1", 16 | "gray-matter": "^4.0.3", 17 | "sharp": "^0.32.5", 18 | "starlight-image-zoom": "^0.9.0" 19 | }, 20 | "devDependencies": { 21 | "sass": "^1.72.0", 22 | "typescript": "^5.4.2" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /docs/public/docs_images/github_settings_actions_options.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/userdocs/qbittorrent-nox-static/7b6215fdb3f5ab11a3ff3c70057591b5be6d7b9b/docs/public/docs_images/github_settings_actions_options.png -------------------------------------------------------------------------------- /docs/public/docs_images/reusable_workflow_inputs-debug.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/userdocs/qbittorrent-nox-static/7b6215fdb3f5ab11a3ff3c70057591b5be6d7b9b/docs/public/docs_images/reusable_workflow_inputs-debug.png -------------------------------------------------------------------------------- /docs/public/docs_images/reusable_workflow_inputs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/userdocs/qbittorrent-nox-static/7b6215fdb3f5ab11a3ff3c70057591b5be6d7b9b/docs/public/docs_images/reusable_workflow_inputs.png -------------------------------------------------------------------------------- /docs/public/docs_images/script_usage/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/userdocs/qbittorrent-nox-static/7b6215fdb3f5ab11a3ff3c70057591b5be6d7b9b/docs/public/docs_images/script_usage/1.png -------------------------------------------------------------------------------- /docs/public/docs_images/script_usage/first-run.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/userdocs/qbittorrent-nox-static/7b6215fdb3f5ab11a3ff3c70057591b5be6d7b9b/docs/public/docs_images/script_usage/first-run.png -------------------------------------------------------------------------------- /docs/public/docs_images/script_usage/help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/userdocs/qbittorrent-nox-static/7b6215fdb3f5ab11a3ff3c70057591b5be6d7b9b/docs/public/docs_images/script_usage/help.png -------------------------------------------------------------------------------- /docs/public/favicon.ico: -------------------------------------------------------------------------------- 1 | 2 | 52 | -------------------------------------------------------------------------------- /docs/public/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 52 | -------------------------------------------------------------------------------- /docs/public/icons/note-circle.svg: -------------------------------------------------------------------------------- 1 | 2 | 46 | 47 | 48 | 54 | -------------------------------------------------------------------------------- /docs/public/icons/png/idea.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/userdocs/qbittorrent-nox-static/7b6215fdb3f5ab11a3ff3c70057591b5be6d7b9b/docs/public/icons/png/idea.png -------------------------------------------------------------------------------- /docs/public/icons/png/info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/userdocs/qbittorrent-nox-static/7b6215fdb3f5ab11a3ff3c70057591b5be6d7b9b/docs/public/icons/png/info.png -------------------------------------------------------------------------------- /docs/public/icons/png/notes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/userdocs/qbittorrent-nox-static/7b6215fdb3f5ab11a3ff3c70057591b5be6d7b9b/docs/public/icons/png/notes.png -------------------------------------------------------------------------------- /docs/public/icons/png/post-it.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/userdocs/qbittorrent-nox-static/7b6215fdb3f5ab11a3ff3c70057591b5be6d7b9b/docs/public/icons/png/post-it.png -------------------------------------------------------------------------------- /docs/public/icons/png/star.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/userdocs/qbittorrent-nox-static/7b6215fdb3f5ab11a3ff3c70057591b5be6d7b9b/docs/public/icons/png/star.png -------------------------------------------------------------------------------- /docs/public/icons/png/sticky-note.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/userdocs/qbittorrent-nox-static/7b6215fdb3f5ab11a3ff3c70057591b5be6d7b9b/docs/public/icons/png/sticky-note.png -------------------------------------------------------------------------------- /docs/public/icons/png/sticky-notes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/userdocs/qbittorrent-nox-static/7b6215fdb3f5ab11a3ff3c70057591b5be6d7b9b/docs/public/icons/png/sticky-notes.png -------------------------------------------------------------------------------- /docs/public/icons/png/tips.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/userdocs/qbittorrent-nox-static/7b6215fdb3f5ab11a3ff3c70057591b5be6d7b9b/docs/public/icons/png/tips.png -------------------------------------------------------------------------------- /docs/public/icons/png/warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/userdocs/qbittorrent-nox-static/7b6215fdb3f5ab11a3ff3c70057591b5be6d7b9b/docs/public/icons/png/warning.png -------------------------------------------------------------------------------- /docs/public/logo-alpine.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/public/logo-github.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 10 | 11 | 17 | -------------------------------------------------------------------------------- /docs/public/logo-large-qbittorrent.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | qbittorrent-new-light 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /docs/public/logo-musl - Copy.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/public/logo-musl.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 26 | -------------------------------------------------------------------------------- /docs/public/logo-qbittorrent.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | qbittorrent-new-light 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /docs/src/components/Header.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import type { Props } from "@astrojs/starlight/props"; 3 | 4 | import LanguageSelect from "@astrojs/starlight/components/LanguageSelect.astro"; 5 | import Search from "@astrojs/starlight/components/Search.astro"; 6 | import SiteTitle from "@astrojs/starlight/components/SiteTitle.astro"; 7 | import SocialIcons from "@astrojs/starlight/components/SocialIcons.astro"; 8 | import ThemeSelect from "@astrojs/starlight/components/ThemeSelect.astro"; 9 | 10 | const shouldRenderSearch = true; 11 | 12 | // import App from "./react/advancedButton.jsx"; 13 | import App from "./advancedButton.astro"; 14 | --- 15 | 16 |
17 |
18 |
19 | 20 |
21 | 22 |
23 |
24 | {shouldRenderSearch && } 25 |
26 |
27 | 30 | 31 | 32 |
33 |
34 | 35 | 101 | -------------------------------------------------------------------------------- /docs/src/components/advancedButton.astro: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | --- 4 | 5 | 9 | 10 | 81 | 82 | 118 | -------------------------------------------------------------------------------- /docs/src/components/advancedMarkdown.astro: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | --- 4 | 5 | 8 | -------------------------------------------------------------------------------- /docs/src/components/buildinfo.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import { Code } from "@astrojs/starlight/components"; 3 | const response = await fetch( 4 | "https://github.com/userdocs/qbt-workflow-files/releases/latest/download/dependency-version.json" 5 | ); 6 | 7 | const data = await response.json(); 8 | 9 | const codeblock = `qBittorrent ${data.qbittorrent || "4.6.3"} was built with the following libraries: 10 | Qt: ${data.qt6 || "6.6.2"} 11 | Libtorrent: ${data.libtorrent_2_0 || "2.0.10"} 12 | Boost: ${data.boost || "1.84.0"} 13 | OpenSSL: ${data.openssl || "3.2.1"} 14 | zlib: ${data.zlib || "1.3.2"}.zlib-ng`; 15 | 16 | // { 17 | // "glibc_2_31": "2.31", 18 | // "glibc_2_38": "2.38", 19 | // "zlib": "1.3.1", 20 | // "iconv": "1.17", 21 | // "icu": "74-2", 22 | // "openssl": "3.2.1", 23 | // "boost": "1.84.0", 24 | // "libtorrent_1_2": "1.2.19", 25 | // "libtorrent_2_0": "2.0.10", 26 | // "double_conversion": "3.3.0", 27 | // "qt5": "5.15.13", 28 | // "qt6": "6.6.2", 29 | // "qbittorrent": "4.6.3" 30 | // } 31 | --- 32 | 33 | 34 | -------------------------------------------------------------------------------- /docs/src/components/charts.astro: -------------------------------------------------------------------------------- 1 | --- 2 | const { class: className, id, summary } = Astro.props; 3 | 4 | import Radarr from "/src/charts/radarr.html?raw"; 5 | import Example from "/src/charts/example.html?raw"; 6 | --- 7 | 8 |
9 |
10 | {summary} 11 |
12 |
16 |
17 |
18 |
19 | -------------------------------------------------------------------------------- /docs/src/components/details.astro: -------------------------------------------------------------------------------- 1 | --- 2 | const { class: className, summary } = Astro.props; 3 | --- 4 | 5 |
6 |
7 | {summary} 8 |
9 | 10 |
11 |
12 |
13 | 14 | 49 | -------------------------------------------------------------------------------- /docs/src/components/github-actions.astro: -------------------------------------------------------------------------------- 1 | --- 2 | const { id } = Astro.props; 3 | import { Code } from "@astrojs/starlight/components"; 4 | 5 | import ci_main_reusable_caller from "../../../.github/workflows/ci-main-reusable-caller.yml?raw"; 6 | import ci_debian_build from "../../../.github/workflows/ci-debian-build.yml?raw"; 7 | import ci_alpine_build from "../../../.github/workflows/ci-alpine-build.yml?raw"; 8 | import ci_alpine_release from "../../../.github/workflows/ci-alpine-release.yml?raw"; 9 | import ci_auto_rerun_failed_jobs_action from "../../../.github/workflows/ci-auto-rerun-failed-jobs-action.yml?raw"; 10 | 11 | const imports = { 12 | ci_main_reusable_caller, 13 | ci_debian_build, 14 | ci_alpine_build, 15 | ci_alpine_release, 16 | ci_auto_rerun_failed_jobs_action, 17 | }; 18 | const code = imports[id]; 19 | --- 20 | 21 | 22 | -------------------------------------------------------------------------------- /docs/src/components/global.jsx: -------------------------------------------------------------------------------- 1 | import Advanced from "/src/components/advancedMarkdown.astro"; 2 | import Charts from "/src/components/charts.astro"; 3 | import Details from "/src/components/details.astro"; 4 | import GithubActions from "/src/components/github-actions.astro"; 5 | import Modal from "/src/components/modal.astro"; 6 | import BuildInfo from "/src/components/buildinfo.astro"; 7 | import PatchInfo from "/src/components/patchinfo.astro"; 8 | 9 | import { Steps, Tabs, TabItem, Card, CardGrid, LinkCard, Aside, Icon, FileTree } from "@astrojs/starlight/components"; 10 | 11 | export { Advanced, BuildInfo, Charts, Details, GithubActions, Modal, Steps, Tabs, TabItem, Card, CardGrid, LinkCard, Aside, Icon, PatchInfo, FileTree }; 12 | -------------------------------------------------------------------------------- /docs/src/components/important.astro: -------------------------------------------------------------------------------- 1 | --- 2 | const { id, alt } = Astro.props; 3 | const basePath = "/" + Astro.url.pathname.split("/")[1]; 4 | --- 5 | 6 |
7 |
8 | {alt} 13 |
14 |
15 | 16 |
17 |
18 | -------------------------------------------------------------------------------- /docs/src/components/modal.astro: -------------------------------------------------------------------------------- 1 | --- 2 | interface GlossaryEntry { 3 | compiledContent: () => Promise; 4 | Content: any; 5 | file: string; 6 | toString: () => string; 7 | } 8 | 9 | const { id, label } = Astro.props; 10 | 11 | if (!id) throw new Error("Modal id parameter is required"); 12 | 13 | const posts = import.meta.glob( 14 | "/src/content/docs/glossary/*.md", 15 | { 16 | eager: true, 17 | } 18 | ); 19 | 20 | const regex = new RegExp(`${id}\\.md$|${id}\\.mdx$`); 21 | const [path, post] = 22 | Object.entries(posts).find(([path]) => regex.test(path)) ?? []; 23 | if (!post) throw new Error(`Glossary entry "${id}" not found`); 24 | 25 | // Extract content safely with type checking 26 | let htmlContent = ""; 27 | try { 28 | const content = await post.compiledContent(); 29 | htmlContent = String(content); 30 | } catch (e) { 31 | throw new Error(`Failed to extract content for "${id}": ${e.message}`); 32 | } 33 | 34 | if (!htmlContent) throw new Error(`Empty content for "${id}"`); 35 | 36 | const htmlSplit = htmlContent.split("
"); 37 | if (!htmlSplit.length) throw new Error(`Invalid content format for "${id}"`); 38 | 39 | const basePath = `/${Astro.url.pathname.split("/")[1]}/`; 40 | const glossaryUrl = `${basePath}glossary/${id}`; 41 | const uniqueId = `modal-${id}-${crypto.randomUUID().slice(0, 6)}`; 42 | --- 43 | 44 | ${htmlSplit[0]}
`} 50 | data-html-more={htmlSplit[1]} 51 | > 52 | {label} 53 |
54 | 55 | 191 | 192 | 279 | -------------------------------------------------------------------------------- /docs/src/components/patchinfo.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import { Code } from "@astrojs/starlight/components"; 3 | const response = await fetch( 4 | "https://github.com/userdocs/qbt-workflow-files/releases/latest/download/dependency-version.json" 5 | ); 6 | 7 | const data = await response.json(); 8 | 9 | const codeblock = ` 10 | qbt-build/patches/zlib/${data.zlib || "1.3.1"} 11 | qbt-build/patches/iconv/${data.iconv || "1.18"} 12 | qbt-build/patches/icu/${data.icu || "76-1"} 13 | qbt-build/patches/openssl/${data.openssl || "3.2.1"} 14 | qbt-build/patches/boost/${data.boost || "1.87.0"} 15 | qbt-build/patches/libtorrent/${data.libtorrent_2_0 || "2.0.10"} 16 | qbt-build/patches/double_conversion/${data.double_conversion || "3.3.0"} 17 | qbt-build/patches/qtbase/${data.qt6 || "6.8.1"} 18 | qbt-build/patches/qttools/${data.qt6 || "6.8.1"} 19 | qbt-build/patches/qbittorrent/${data.qbittorrent || "5.0.3"} 20 | `; 21 | 22 | // { 23 | // "glibc_2_31": "2.31", 24 | // "glibc_2_38": "2.38", 25 | // "zlib": "1.3.1", 26 | // "iconv": "1.18", 27 | // "icu": "76-1", 28 | // "openssl": "3.4.0", 29 | // "boost": "1.87.0", 30 | // "libtorrent_1_2": "1.2.19", 31 | // "libtorrent_2_0": "2.0.10", 32 | // "double_conversion": "3.3.0", 33 | // "qt5": "5.15.16", 34 | // "qt6": "6.8.1", 35 | // "qbittorrent": "5.0.3" 36 | // } 37 | --- 38 | 39 | 40 | -------------------------------------------------------------------------------- /docs/src/content/config.ts: -------------------------------------------------------------------------------- 1 | import { defineCollection } from 'astro:content'; 2 | import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; 3 | 4 | export const collections = { 5 | docs: defineCollection({ schema: docsSchema() }), 6 | i18n: defineCollection({ type: 'data', schema: i18nSchema() }), 7 | }; 8 | -------------------------------------------------------------------------------- /docs/src/content/docs/artifact-attestations.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: artifact attestations 3 | description: artifact attestations 4 | --- 5 | 6 | import { Advanced, Charts, Details, Modal, Steps, Tabs, TabItem, Card, CardGrid, LinkCard, Aside, Icon } from "/src/components/global.jsx" 7 | 8 | From releases after the 03/10/2024 you can use the `artifact_attestations` to verify the provenance of the build. 9 | 10 | https://docs.github.com/en/actions/security-for-github-actions/using-artifact-attestations/using-artifact-attestations-to-establish-provenance-for-builds 11 | 12 | Using `gh` cli you can use this command to verify the provenance of the build: 13 | 14 | For example, using the `x86_64-qbittorrent-nox` build: 15 | 16 | ```bash 17 | gh attestation verify x86_64-qbittorrent-nox -o userdocs 18 | ``` 19 | -------------------------------------------------------------------------------- /docs/src/content/docs/credits.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Credits 3 | hide_title: true 4 | --- 5 | 6 | import { Advanced, Charts, Details, Modal, Steps, Tabs, TabItem, Card, CardGrid, LinkCard, Aside, Icon } from "/src/components/global.jsx" 7 | 8 | 13 | 14 | 15 | 20 | -------------------------------------------------------------------------------- /docs/src/content/docs/debugging.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Debugging 3 | hide_title: true 4 | --- 5 | 6 | import { Advanced, Charts, Details, Modal, Steps, Tabs, TabItem, Card, CardGrid, LinkCard, Aside, Icon } from "/src/components/global.jsx" 7 | 8 | :::note 9 | By default the static builds are built with the debug symbols stripped out to reduce the file size. 10 | ::: 11 | 12 | To properly debug a segfault we need to use a build with libtorrent and qBittorrent debug symbols included. 13 | 14 | Some reasons I don't release them here: 15 | - static builds using `b2` the libtorrent debug symbols can add 100MB to the file size. 16 | - static builds using `cmake` are about 15MB larger and potentially slower. 17 | - It doubles the build time. 18 | - It's not needed for most users. 19 | 20 | The easiest way to get a debug build is to build it yourself by 21 | 22 | - [forking the repo](https://github.com/userdocs/qbittorrent-nox-static/fork) the repo and running the `ci-main-reusable-caller.yml` workflow with the debug flag enabled. 23 | 24 | ![](/qbittorrent-nox-static/docs_images/reusable_workflow_inputs-debug.png) 25 | 26 | :::tip 27 | The builds will be uploaded as artifacts to the workflow run and can be downloaded from there. 28 | ::: 29 | 30 | - Build it yourself locally 31 | 32 | This can be done when building locally by using the `-d` flag or `export qbt_build_debug=on` 33 | 34 | Then you will have a debug build with the debug symbols included to get a stack traces using [gdb](https://www.gnu.org/software/gdb/). 35 | -------------------------------------------------------------------------------- /docs/src/content/docs/github-actions.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Github Actions 3 | hide_title: true 4 | --- 5 | 6 | import { Advanced, Charts, Details, GithubActions, Modal, Steps, Tabs, TabItem, Card, CardGrid, LinkCard, Aside, Icon } from "/src/components/global.jsx" 7 | 8 | This project relies heavily on Github Actions to build and release the binaries. The actions are defined in the `.github/workflows` directory. 9 | 10 | :::note 11 | The jobs can be viewed here: [https://github.com/userdocs/qbittorrent-nox-static/actions](https://github.com/userdocs/qbittorrent-nox-static/actions) 12 | 13 | They workflows are located here: [https://github.com/userdocs/qbittorrent-nox-static/tree/master/.github/workflows](https://github.com/userdocs/qbittorrent-nox-static/tree/master/.github/workflows) 14 | ::: 15 | 16 | ## Github repo Actions settings 17 | 18 | The required permissions for each workflow and job have been configured granularly in the workflows themselves. The permissions are defined in the `permissions` section of the workflow. 19 | 20 | :::tip 21 | They are already configured in the workflows and you should not need to configure any forked repos to use these actions. 22 | ::: 23 | 24 | ## Workflows 25 | 26 | These workflows are using a reusable caller workflow that allows for inputs to be passed to the reusable workflows. This allows for a single workflow to be used to call multiple workflows with different inputs. 27 | 28 | ![](/qbittorrent-nox-static/docs_images/reusable_workflow_inputs.png) 29 | 30 | This is the structure of the workflows: 31 | 32 | ``` 33 | ci-main-reusable-caller 34 | ├─ ci-debian-build 35 | ├─ ci-alpine-build 36 | ├─ ci-alpine-release 37 | └─ ci-auto-rerun-failed-jobs 38 | ``` 39 | 40 |
41 | The primary reusable caller workflow 42 | 43 |
44 | 45 |
46 | The debian build workflow 47 | 48 |
49 | 50 |
51 | The alpine build workflow 52 | 53 |
54 | 55 |
56 | The alpine release workflow 57 | 58 |
59 | 60 |
61 | This workflow automatically reruns any failed jobs. Mostly targeted for the release jobs to ensure the release is created. 62 | 63 |
64 | -------------------------------------------------------------------------------- /docs/src/content/docs/glossary/bash.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Bash Shell 3 | hide_title: true 4 | --- 5 | 6 | 🟦 Bash is the GNU Project's shell—the Bourne Again SHell. This is an sh-compatible shell that incorporates useful features from the Korn shell (ksh) and the C shell (csh). It is intended to conform to the IEEE POSIX P1003.2/ISO 9945.2 Shell and Tools standard. It offers functional improvements over sh for both programming and interactive use. In addition, most sh scripts can be run by Bash without modification. 7 | 8 | --- 9 | 10 | Shells are command interpreters. They are applications that provide users with the ability to give commands to their operating system interactively, or to execute batches of commands quickly. In no way are they required for the execution of programs; they are merely a layer between system function calls and the user. 11 | 12 | Think of a shell as a way for you to speak to your system. Your system doesn't need it for most of its work, but it is an excellent interface between you and what your system can offer. It allows you to perform basic math, run basic tests and execute applications. More importantly, it allows you to combine these operations and connect applications to each other to perform complex and automated tasks. 13 | 14 | BASH is not your operating system. It is not your window manager. It is not your terminal (but it often runs inside your terminal). It does not control your mouse or keyboard. It does not configure your system, activate your screensaver, or open your files when you double-click them. It is generally not involved in launching applications from your window manager or desktop environment. It's important to understand that BASH is only an interface for you to execute statements (using BASH syntax), either at the interactive BASH prompt or via BASH scripts. 15 | 16 | Website: 17 | 18 | - https://www.gnu.org/software/bash/ 19 | 20 | Guides: 21 | 22 | - https://mywiki.wooledge.org/BashGuide 23 | - https://www.gnu.org/software/bash/manual/bash.html 24 | -------------------------------------------------------------------------------- /docs/src/content/docs/glossary/buildjet.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: BuildJet for Github Actions 3 | hide_title: true 4 | --- 5 | 6 | 🟦 A paid for alternative to self hosted runners that allow for native arm runners as well as increased cores for faster build times. 7 | 8 | --- 9 | 10 | If you really need a faster way to build you should consider this integration for your Github workflows. Self hosted runners are a complicated option where this is not. 11 | 12 | [https://buildjet.com/for-github-actions](https://buildjet.com/for-github-actions) 13 | -------------------------------------------------------------------------------- /docs/src/content/docs/glossary/crossbuild-essentials.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Debian Crossbuild-Essentials 3 | hide_title: true 4 | --- 5 | 6 | 🟦 Native Debian and Ubuntu cross build toolchains for cross compiling, used when a supported Debian based OS is the Host. 7 | 8 | --- 9 | 10 | When building on supported Debian based hosts we use the official crossbuild-essential tool chains that are made specifically for cross compiling on these host operating systems. 11 | 12 | On the modern distros like Bullseye and Jammy there is a wide range of supported cross build targets available. 13 | 14 | :::caution 15 | Only Bullseye and Jammy onwards have the full range of support we need to match the Alpine host options. 16 | ::: 17 | 18 | Please look a the links below to see which options are available for which platform and release. 19 | 20 | [Debian cross build essential toolchains](https://packages.debian.org/search?keywords=crossbuild-essential-&searchon=names) 21 | 22 | [Ubuntu cross build essential toolchains](https://packages.ubuntu.com/search?keywords=crossbuild-essential-&searchon=names) 23 | 24 | :::note 25 | Ubuntu provides one additional package over Debian - `crossbuild-essential-riscv64` 26 | ::: 27 | -------------------------------------------------------------------------------- /docs/src/content/docs/glossary/docker-desktop.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Docker Desktop 3 | hide_title: true 4 | --- 5 | 6 | 🟦 Docker Desktop is secure, out-of-the-box containerization software offering developers and teams a robust, hybrid toolkit to build, share, and run applications anywhere. 7 | 8 | --- 9 | 10 | https://www.docker.com/products/docker-desktop/ 11 | -------------------------------------------------------------------------------- /docs/src/content/docs/glossary/docker.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Docker Cli 3 | hide_title: true 4 | --- 5 | 6 | 🟦 Docker is an open platform for developing, shipping, and running applications. Docker enables you to separate your applications from your infrastructure so you can deliver software quickly. With Docker, you can manage your infrastructure in the same ways you manage your applications. By taking advantage of Docker's methodologies for shipping, testing, and deploying code, you can significantly reduce the delay between writing code and running it in production. 7 | 8 | --- 9 | 10 | [Installation Docs](https://docs.docker.com/engine/install/) 11 | -------------------------------------------------------------------------------- /docs/src/content/docs/glossary/github-actions.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Github Actions 3 | hide_title: true 4 | --- 5 | 6 | 🟦 GitHub Actions makes it easy to automate all your software workflows, now with world-class CI/CD. Build, test, and deploy your code right from GitHub. Make code reviews, branch management, and issue triaging work the way you want. 7 | 8 | --- 9 | 10 | Automate, customize, and execute your software development workflows right in your repository with GitHub Actions. You can discover, create, and share actions to perform any job you'd like, including CI/CD, and combine actions in a completely customized workflow. 11 | 12 | https://docs.github.com/en/actions 13 | -------------------------------------------------------------------------------- /docs/src/content/docs/glossary/github-releases.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Github Releases 3 | hide_title: true 4 | --- 5 | 6 | 🟦 Some tooltip info Lorem Ipsum is simply dummy text of the printing and typesetting industry. 7 | 8 | --- 9 | 10 | further reading 11 | -------------------------------------------------------------------------------- /docs/src/content/docs/glossary/github-workflows.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Github Workflows 3 | hide_title: true 4 | --- 5 | 6 | 🟦 A workflow is a configurable automated process that will run one or more jobs. Workflows are defined by a YAML file checked in to your repository and will run when triggered by an event in your repository, or they can be triggered manually, or at a defined schedule. 7 | 8 | --- 9 | 10 | Workflows are defined in the `.github/workflows directory` in a repository, and a repository can have multiple workflows, each of which can perform a different set of tasks. For example, you can have one workflow to build and test pull requests, another workflow to deploy your application every time a release is created, and still another workflow that adds a label every time someone opens a new issue. 11 | 12 | Github workflows are typically stored in the Github as `.github/workflows/workflow-name.yml` in the project repo. 13 | 14 | In a nutshell a workflow is a special syntax to define some tasks you want done on what are called runners like `ubuntu-latest`. 15 | 16 | You use a combination of `yaml` and scripting/shell languages to define the some criteria and then create steps towards completion of a job. 17 | 18 | This project uses them to build and release static binaries and here is an example of on of the files that build releases using the workflow files. 19 | 20 | Action overview for this workflows: [matrix_multi_build_and_release_qbt_workflow_files.yml](https://github.com/userdocs/qbittorrent-nox-static/actions/workflows/matrix_multi_build_and_release_qbt_workflow_files.yml) 21 | 22 | The workflow file itself: [matrix_multi_build_and_release_qbt_workflow_files.yml](https://github.com/userdocs/qbittorrent-nox-static/blob/master/.github/workflows/matrix_multi_build_and_release_qbt_workflow_files.yml) 23 | 24 | If you would like to know more about creating workflows you should read the excellent Github docs. 25 | 26 | https://docs.github.com/en/actions/learn-github-actions/understanding-github-actions 27 | 28 | https://docs.github.com/en/actions/using-workflows/about-workflows 29 | -------------------------------------------------------------------------------- /docs/src/content/docs/glossary/github.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Github website 3 | hide_title: true 4 | --- 5 | 6 | 🟦 Custom musl crossbuild toolchains based on musl.cc, click to know more. 7 | 8 | --- 9 | 10 | https://github.com/userdocs/qbt-musl-cross-make 11 | -------------------------------------------------------------------------------- /docs/src/content/docs/glossary/glibc.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Glibc 3 | hide_title: true 4 | --- 5 | 6 | The GNU C Library - The project provides the core libraries for the GNU system and GNU/Linux systems, as well as many other systems that use Linux as the kernel. These libraries provide critical APIs including ISO C11, POSIX.1-2008, BSD, OS-specific APIs and more. These APIs include such foundational facilities as open, read, write, malloc, printf, getaddrinfo, dlopen, pthread_create, crypt, login, exit and more. 7 | 8 | --- 9 | 10 | [libc](https://www.gnu.org/software/libc/) 11 | -------------------------------------------------------------------------------- /docs/src/content/docs/glossary/musl-cross-make.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Musl Cross Make 3 | hide_title: true 4 | --- 5 | 6 | 🟦 Custom musl crossbuild toolchains based on [musl-cross-make](https://github.com/richfelker/musl-cross-make) 7 | 8 | --- 9 | 10 | The main musl cross make is located here https://github.com/richfelker/musl-cross-make and the tools used here are derived from this. 11 | 12 | [musl.cc](https://musl.cc) is a fork of the original mcm (musl cross make) project and they release and host cross toolchains to be used. The repo for the project is found here [https://git.zv.io/toolchains/musl-cross-make/-/tree/master](https://git.zv.io/toolchains/musl-cross-make/-/tree/master) 13 | 14 | This project uses a hybrid version of the [musl.cc](https://musl.cc) musl cross make tool build tools and [musl.cc](https://github.com/richfelker/musl-cross-make) hosted on Github. 15 | 16 | It uses newer current dependencies, is smaller in size and stays in sync with Alpine target architecture profiles. 17 | 18 | The build process is automated via Github Actions. They can be found here https://github.com/userdocs/qbt-musl-cross-make 19 | 20 | :::note 21 | These are the tool chains used by this project to build static binaries on the Alpine Host, which is the default setup for the github releases. 22 | ::: 23 | -------------------------------------------------------------------------------- /docs/src/content/docs/glossary/muslc.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Musl libc 3 | hide_title: true 4 | --- 5 | 6 | 🟦 Musl (pronounced Mussel) is an implementation of the C standard library built on top of the Linux system call API, including interfaces defined in the base language standard, POSIX, and widely agreed-upon extensions. musl is lightweight, fast, simple, free, and strives to be correct in the sense of standards-conformance and safety. 7 | 8 | --- 9 | 10 | [musl](https://wiki.musl-libc.org/) 11 | -------------------------------------------------------------------------------- /docs/src/content/docs/glossary/powershell.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Powershell 3 | hide_title: true 4 | --- 5 | 6 | 🟦 PowerShell is a cross-platform task automation solution made up of a command-line shell, a scripting language, and a configuration management framework. PowerShell runs on Windows, Linux, and macOS. 7 | 8 | --- 9 | 10 | https://learn.microsoft.com/en-us/powershell/scripting/overview 11 | -------------------------------------------------------------------------------- /docs/src/content/docs/glossary/qemu.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Qemu emulation 3 | hide_title: true 4 | --- 5 | 6 | 🟦 Qemu is a generic and open source machine emulator and virtualize. It's used when cross building so that created binaries and libs can be automatically loaded and used without host arch versions. 7 | 8 | --- 9 | 10 | We use [qemu-user-static](https://packages.ubuntu.com/lunar/qemu-user-static) and [binfmt-support](https://packages.ubuntu.com/lunar/binfmt-support) on the Github `ubuntu-latest` runners, from the [Lunar](https://releases.ubuntu.com/lunar) repo to overcome a bug in older versions. 11 | 12 | For example, when cross compiling Qt6 you they want you to have a have a host version built first and then use loads of special cmake settings. 13 | 14 | The few binaries that are actually needed are not part of the final build so they are emulated as and when needed and it works fine. 15 | 16 | So by having emulation at hand when needed we can easily handle certain cross compilation issues easily. 17 | 18 | Qt5 does not need to do this as `qmake` build the tools for the host first. Apparently it's a cmake limitation. 19 | -------------------------------------------------------------------------------- /docs/src/content/docs/glossary/wsl2.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: WSL2 3 | hide_title: true 4 | --- 5 | 6 | 🟦 Developers can access the power of both Windows and Linux at the same time on a Windows machine. The Windows Subsystem for Linux (WSL) lets developers install a Linux distribution (such as Ubuntu, OpenSUSE, Kali, Debian, Arch Linux, etc) and use Linux applications, utilities, and Bash command-line tools directly on Windows, unmodified, without the overhead of a traditional virtual machine or dualboot setup. 7 | 8 | --- 9 | 10 | https://learn.microsoft.com/en-us/windows/wsl/install 11 | -------------------------------------------------------------------------------- /docs/src/content/docs/index.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: qbittorrent-nox-static 3 | description: Get started building your docs site with Starlight. 4 | template: splash 5 | hero: 6 | tagline: Fully static linux binaries for qbittorrent-nox. 7 | image: 8 | file: /public/logo-static.svg 9 | actions: 10 | - text: Docs 11 | link: /qbittorrent-nox-static/introduction 12 | icon: right-arrow 13 | variant: primary 14 | 15 | - text: Github repo 16 | link: https://github.com/userdocs/qbittorrent-nox-static 17 | icon: right-arrow 18 | variant: secondary 19 | 20 | - text: Latest release 21 | link: https://github.com/userdocs/qbittorrent-nox-static/releases/latest 22 | icon: right-arrow 23 | variant: secondary 24 | - text: Legacy build 25 | link: https://github.com/userdocs/qbittorrent-nox-static-legacy/releases/latest 26 | icon: right-arrow 27 | variant: secondary 28 | --- 29 | 30 | import { Card, CardGrid } from '@astrojs/starlight/components'; 31 | 32 |
33 | 34 | 35 |
36 | 37 |
38 | 39 |
40 |

41 | Making the most of the Github ecosystem by leveraging Github Actions to automate the build process and release new versions as soon as core dependencies are updated and available. 42 |

43 |
44 | 45 |
46 |
47 | 48 |
49 | 50 | 51 |
52 | 53 |
54 | 55 |
56 |

57 | Musl libc to create statically linked binaries than can run on any Linux based OS. It was never supposed to be hard to do this. Musl makes it easy. 58 |

59 |
60 | 61 |
62 |
63 | 64 |
65 | 66 | 67 |
68 | 69 |
70 | 71 |
72 |

73 | The build host - Alpine Linux is a security-oriented, lightweight Linux distribution based on musl libc and busybox. It is designed for security, simplicity, and resource efficiency. 74 |

75 |
76 | 77 |
78 |
79 | 80 |
81 | 82 | 83 |
84 | 85 |
86 | 87 |
88 |

89 | A fully static build of qbittorrent-nox. No need to install any dependencies. Just download and run. Deploy it however you want. Easy to deploy as a binary or as part of a docker solution. 90 |

91 |
92 | 93 |
94 |
95 | 96 | 97 | -------------------------------------------------------------------------------- /docs/src/content/docs/install-qbittorrent.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Installing nox 3 | hide_title: true 4 | --- 5 | 6 | import { Advanced, Charts, Details, Modal, Steps, Tabs, TabItem, Card, CardGrid, LinkCard, Aside, Icon } from "/src/components/global.jsx" 7 | 8 | Once the script has successfully built `qbittorrent-nox` you can install the binary using this command: 9 | 10 | ```bash 11 | bash ~/qbittorrent-nox-static.sh install 12 | ``` 13 | 14 | :::tip 15 | If you built to a custom directory you will need to specify this to the install command using the `-b` argument. 16 | ::: 17 | 18 | ```bash 19 | bash ~/qbittorrent-nox-static.sh -b "/path/to/built/binary" install 20 | ``` 21 | 22 | The default installation path is determined by type of user executing the script. 23 | 24 | 25 | 26 | 27 | Built to - `qbt-build` 28 | 29 | Optionally installed to `/usr/local/bin/qbittorrent-nox` 30 | 31 | 32 | 33 | 34 | Built to - `qbt-build` 35 | 36 | Optionally installed to `$HOME/bin/qbittorrent-nox` 37 | 38 | 39 | 40 | 41 | ## GitHub Releases 42 | 43 | Optionally you can just download the existing prebuilt binaries released using GitHub Actions. 44 | 45 | 46 | 47 | 48 | Without ICU 49 | 50 | ```bash 51 | mkdir -p ~/bin && source ~/.profile 52 | wget -qO ~/bin/qbittorrent-nox https://github.com/userdocs/qbittorrent-nox-static/releases/latest/download/x86_64-qbittorrent-nox 53 | chmod 700 ~/bin/qbittorrent-nox 54 | ``` 55 | 56 | With ICU 57 | 58 | ```bash 59 | mkdir -p ~/bin && source ~/.profile 60 | wget -qO ~/bin/qbittorrent-nox https://github.com/userdocs/qbittorrent-nox-static/releases/latest/download/x86_64-icu-qbittorrent-nox 61 | chmod 700 ~/bin/qbittorrent-nox 62 | ``` 63 | 64 | 65 | 66 | 67 | Without ICU 68 | 69 | ```bash 70 | mkdir -p ~/bin && source ~/.profile 71 | wget -qO ~/bin/qbittorrent-nox https://github.com/userdocs/qbittorrent-nox-static/releases/latest/download/aarch64-qbittorrent-nox 72 | chmod 700 ~/bin/qbittorrent-nox 73 | ``` 74 | 75 | With ICU 76 | 77 | ```bash 78 | mkdir -p ~/bin && source ~/.profile 79 | wget -qO ~/bin/qbittorrent-nox https://github.com/userdocs/qbittorrent-nox-static/releases/latest/download/aarch64-icu-qbittorrent-nox 80 | chmod 700 ~/bin/qbittorrent-nox 81 | ``` 82 | 83 | 84 | 85 | 86 | Without ICU 87 | 88 | ```bash 89 | mkdir -p ~/bin && source ~/.profile 90 | wget -qO ~/bin/qbittorrent-nox https://github.com/userdocs/qbittorrent-nox-static/releases/latest/download/armv7-qbittorrent-nox 91 | chmod 700 ~/bin/qbittorrent-nox 92 | ``` 93 | 94 | With ICU 95 | 96 | ```bash 97 | mkdir -p ~/bin && source ~/.profile 98 | wget -qO ~/bin/qbittorrent-nox https://github.com/userdocs/qbittorrent-nox-static/releases/latest/download/armv7-icu-qbittorrent-nox 99 | chmod 700 ~/bin/qbittorrent-nox 100 | ``` 101 | 102 | 103 | 104 | 105 | Without ICU 106 | 107 | ```bash 108 | mkdir -p ~/bin && source ~/.profile 109 | wget -qO ~/bin/qbittorrent-nox https://github.com/userdocs/qbittorrent-nox-static/releases/latest/download/armhf-qbittorrent-nox 110 | chmod 700 ~/bin/qbittorrent-nox 111 | ``` 112 | 113 | With ICU 114 | 115 | ```bash 116 | mkdir -p ~/bin && source ~/.profile 117 | wget -qO ~/bin/qbittorrent-nox https://github.com/userdocs/qbittorrent-nox-static/releases/latest/download/armhf-icu-qbittorrent-nox 118 | chmod 700 ~/bin/qbittorrent-nox 119 | ``` 120 | 121 | 122 | 123 | 124 | ## Configuring qbittorrent 125 | 126 | If you want to configure qBittorrent before you start it use this method: 127 | 128 | Create the default configuration directory. 129 | 130 | ```bash 131 | mkdir -p ~/.config/qBittorrent 132 | ``` 133 | 134 | Create the configuration file. 135 | 136 | ```bash 137 | touch ~/.config/qBittorrent/qBittorrent.conf 138 | ``` 139 | 140 | Edit the file 141 | 142 | ```bash 143 | nano ~/.config/qBittorrent/qBittorrent.conf 144 | ``` 145 | 146 | Add this. Make sure to change your web ui port. 147 | 148 | ```ini 149 | [LegalNotice] 150 | Accepted=true 151 | 152 | [Preferences] 153 | WebUI\Port=PORT 154 | ``` 155 | 156 | Default login: 157 | 158 | ```bash 159 | username: admin 160 | password: adminadmin 161 | ``` 162 | 163 | Some key start-up arguments to help you along. Using the command above with no arguments will loads the defaults or the settings defined in the `~/.config/qBittorrent/qBittorrent.conf` 164 | 165 | ```plaintext 166 | Usage: 167 | ./qbittorrent-nox [options] [( | )...] 168 | Options: 169 | -v | --version Display program version and exit 170 | -h | --help Display this help message and exit 171 | --webui-port= Change the Web UI port 172 | -d | --daemon Run in daemon-mode (background) 173 | --profile= Store configuration files in 174 | --configuration= Store configuration files in directories 175 | qBittorrent_ 176 | --relative-fastresume Hack into libtorrent fastresume files and make 177 | file paths relative to the profile directory 178 | files or URLs Download the torrents passed by the user 179 | 180 | Options when adding new torrents: 181 | --save-path= Torrent save path 182 | --add-paused= Add torrents as started or paused 183 | --skip-hash-check Skip hash check 184 | --category= Assign torrents to category. If the category 185 | doesn't exist, it will be created. 186 | --sequential Download files in sequential order 187 | --first-and-last Download first and last pieces first 188 | --skip-dialog= Specify whether the "Add New Torrent" dialog 189 | opens when adding a torrent. 190 | 191 | Option values may be supplied via environment variables. For option named 192 | 'parameter-name', environment variable name is 'QBT_PARAMETER_NAME' (in upper 193 | case, '-' replaced with '_'). To pass flag values, set the variable to '1' or 194 | 'TRUE'. For example, to disable the splash screen: 195 | QBT_NO_SPLASH=1 ./qbittorrent-nox 196 | Command line parameters take precedence over environment variables 197 | ``` 198 | 199 | ## Starting qbittorrent 200 | 201 | Now you just run it and enjoy! 202 | 203 | ```bash 204 | ~/bin/qbittorrent-nox 205 | ``` 206 | 207 | ## Web ui 208 | 209 | To get your external IP with the default qbittorrent command use this command: 210 | 211 | ```bash 212 | echo $(wget -qO - icanhazip.com):8080 213 | ``` 214 | 215 | ## Second instance 216 | 217 | When you simply call the binary using `~/qbittorrent-nox ` it will look for it's configuration in `~/.config/qbittorrent`. 218 | 219 | If you would like to run a second instance using another configuration you can do so like this 220 | 221 | ```bash 222 | ~/bin/qbittorrent-nox --configuration=NAME 223 | ``` 224 | 225 | This will create a new configuration directory using this suffix. 226 | 227 | ```bash 228 | ~/.config/qbittorrent_NAME 229 | ``` 230 | 231 | You will also need a custom nginx proxypass and systemd service. 232 | 233 | And you can now configure this instance separately. 234 | -------------------------------------------------------------------------------- /docs/src/content/docs/introduction.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Introduction 3 | description: Introduction 4 | --- 5 | 6 | import { Advanced, BuildInfo, Charts, Details, Modal, Steps, Tabs, TabItem, Card, CardGrid, LinkCard, Aside, Icon } from "/src/components/global.jsx" 7 | 8 | ## What is it? 9 | 10 | `qbittorrent-nox-static.sh™` was originally a simple, amateurish bash script, to build a static `qbittorrent-nox` binary for `x86_64`. The script has grown and evolved since then and now it's a complicated bash script. 11 | 12 | :::note 13 | `qbt-nox-static.bash™` is `v2.1.1` and `qbittorrent-nox-static.sh™` is `v2.0.16`. The former is a fork of the latter, from this version, with changes specific to the dependency handling, which in turn makes breaking changes to the default behavior of the script. Combined with renaming the script to `.bash` from `.sh` as it is not a POSIX compliant script this would effectively have made `qbittorrent-nox-static.sh` unavailable for use. 14 | 15 | So the existence of the two is a transitional change and the `qbittorrent-nox-static.sh` will be deprecated in the future, though any non breaking changes will be backported to the original script. 16 | ::: 17 | 18 | ### What does it do? 19 | 20 | It handles a lot of the nuanced complexity around building various different dependencies on two different host platforms, towards the same outcome and can target these architectures via crossbuilding: 21 | 22 |
23 | `armel` `armhf` `armv7` `aarch64` 24 | 25 | `x86` `x86_64` 26 | 27 | `s390x` 28 | 29 | `powerpc` `ppc64el` 30 | 31 | `mips` `mipsel` `mips64` `mips64el` 32 | 33 | `loongarch64` 34 | 35 | `riscv64` 36 |
37 | 38 | ⭐ On supported host build platforms the `qbittorrent-nox-static.sh` will perform these three main tasks via simple prompt: 39 | 40 | 41 | 42 | 1. Update the system and install the core build dependencies, based on activated options - Requires `root` or `sudo` privileges if any dependencies are missing. 43 | 44 | 2. Download all dependencies locally and build `qbittorrent-nox` with no special privileges required. 45 | 46 | 3. Build a fully static and portable `qbittorrent-nox` binary which built using the latest version of all supported dependencies. 47 | 48 | 49 | 50 | The script is highly configurable and is capable of native and cross building. These more advanced configurations will be discussed later sections of the documentation. 51 | 52 | ### What is the outcome 53 | 54 | ⭐ Here is an example successful default build profile: 55 | 56 | 57 | 58 | 59 | 60 | 61 | The script creates a fully static `qbittorrent-nox` binary using 62 | 63 | The final result will show this when using `ldd` 64 | 65 | ```bash 66 | ldd ~/qbt-build/bin/qbittorrent-nox 67 | ``` 68 | 69 | Gives this result: 70 | 71 | ```bash 72 | not a dynamic executable 73 | ``` 74 | 75 | 76 | 77 | 78 | The script creates a fully static `qbittorrent-nox` binary using 79 | 80 | The final result will show this when using `ldd` 81 | 82 | ```bash 83 | ldd ~/qbt-build/bin/qbittorrent-nox 84 | ``` 85 | 86 | Gives this result: 87 | 88 | ```bash 89 | statically linked 90 | ``` 91 | 92 | 93 | 94 | 95 | ### How do I use it? 96 | 97 | The script can be downloaded locally and run on a supported host or via docker. It has a comprehensive help section built in, available via the `-h` flag, that explains all options and demonstrates dynamic command choices. The best thing to do is read the script installation and usage sections to understand the key features and how to user them. 98 | 99 | :::tip[The hard part is done.] 100 | You always have a easy method available to you to build your own releases, simply by forking the repo and using the available workflows. How to do this will be shown in the sections later on. You can build locally or fork the repo and build and release using CI where the git repo acts as a local environment to the script. 101 | ::: 102 | -------------------------------------------------------------------------------- /docs/src/content/docs/nginx-proxypass.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Nginx proxy 3 | hide_title: true 4 | --- 5 | 6 | import { Advanced, Charts, Details, Modal, Steps, Tabs, TabItem, Card, CardGrid, LinkCard, Aside, Icon } from "/src/components/global.jsx" 7 | 8 | ```nginx 9 | location /qbittorrent/ { 10 | proxy_pass http://127.0.0.1:8080/; 11 | proxy_http_version 1.1; 12 | proxy_set_header X-Forwarded-Host $http_host; 13 | http2_push_preload on; # Enable http2 push 14 | 15 | # The following directives effectively nullify Cross-site request forgery (CSRF) 16 | # protection mechanism in qBittorrent, only use them when you encountered connection problems. 17 | # You should consider disable "Enable Cross-site request forgery (CSRF) protection" 18 | # setting in qBittorrent instead of using these directives to tamper the headers. 19 | # The setting is located under "Options -> WebUI tab" in qBittorrent since v4.1.2. 20 | #proxy_hide_header Referer; 21 | #proxy_hide_header Origin; 22 | #proxy_set_header Referer ''; 23 | #proxy_set_header Origin ''; 24 | 25 | # Not needed since qBittorrent v4.1.0 26 | #add_header X-Frame-Options "SAMEORIGIN"; 27 | } 28 | ``` 29 | -------------------------------------------------------------------------------- /docs/src/content/docs/patching.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Patching 3 | hide_title: true 4 | --- 5 | 6 | import { Advanced, Charts, Details, Modal, Steps, Tabs, TabItem, Card, CardGrid, LinkCard, Aside, Icon, PatchInfo, FileTree } from "/src/components/global.jsx" 7 | 8 | ### Patching summary 9 | 10 | The script supports the automatic patching of all modules when building, providing the prerequisite conditions are met. In summary it works like this: 11 | 12 | - The script will look for a patch file, url file or sources directory in the `patches` sub directory of the build directory. 13 | - If none are found, then the script will check the default online patch directory `userdocs/qbittorrent-nox-static` for a patch or url file to apply (ignoring source files) 14 | - It will compare tag versions of the activated modules and if a match is found it will use an existing local patch or download and apply the patch. 15 | - Order of priorities: 16 | - local - patch file 17 | - local - patch url 18 | - local - sources directory 19 | - remote - patch file 20 | - remote - patch url 21 | 22 | Here is an example local directory structure that the script will use to apply patches to libtorrent `v1.2.19` and qBittorrent `release-5.0.3` 23 | 24 | 25 | - qbittorrent-nox-static.sh 26 | - qbt-build 27 | - patches 28 | - libtorrent/ 29 | - v1.2.19 30 | - patch 31 | - Jamfile 32 | - sources/ 33 | - qbittorrent/ 34 | - 5.0.3 35 | - patch 36 | - sources/src/webui/webui.cpp 37 | 38 | 39 | :::tip 40 | Use the help command to get more information 41 | 42 | ```bash 43 | ./qbittorrent-nox-static.sh -h-pr 44 | ``` 45 | ::: 46 | 47 | :::note 48 | The default remote patch repo if `userdocs/qbittorrent-nox-static` will only store critical patches required to build successfully or apply security fixes. 49 | 50 | There are no customisations or additional patches stored in the default repo. If it applies a remote patch consider that patch essnetial. 51 | ::: 52 | 53 | ### Boot strapping 54 | 55 | By default the script installs to a build directory that is a sub directory relative to the script location. This means that if you clone the git repo and run the script it won't find the local patches. There are few ways to handle this. 56 | 57 | - **Option 1:** Default, the script assumes you will prepare the environment before building by using the bootstrapping feature. This will create the required directory structure, then you copy the patch files to the correct location as needed. 58 | - **Option 2:** Clone the repo and copy the patches to the correct location 59 | 60 | ```bash 61 | git clone --depth 1 https://github.com/userdocs/qbittorrent-nox-static.git 62 | cd qbittorrent-nox-static 63 | mkdir -p qbt-build 64 | cp -r patches qbt-build/ 65 | ``` 66 | 67 | - **Option 3:** You can set the build dir to the root of the github repo and the script will find the patches 68 | 69 | ```bash 70 | export qbt_build_dir="." 71 | ``` 72 | - **Option 4:** 73 | Upload the patches to a remote github repo with the `patches` dir in the repo root and use the `pr` switch or `qbt_patches_url` env to specify the repo URL. The script will download the patches from the remote location and apply them. 74 | - **Option 5:** 75 | Do nothing and the script will use the default remote patch repo `userdocs/qbittorrent-nox-static` to apply patches 76 | 77 | When bootstrapping the script will create the required directory structure using the current defaults and it will look like this: 78 | 79 | 80 | 81 | ## Local patching via example 82 | 83 | In this example we will apply a real patch that can be used with this script from this pinned issue: https://github.com/userdocs/qbittorrent-nox-static/issues/149 84 | 85 | :::note 86 | We will assume you are in folder with the `qbittorrent-nox-static.sh` script. 87 | ::: 88 | 89 | Step 1: Boot strap the patches directory 90 | 91 | ```bash 92 | qbittorrent-nox-static.sh -bs-p 93 | ``` 94 | 95 | Step 2: Clone the qBittorrent repo targeting the specific tag we want to patch - `--branch release-5.0.3` 96 | 97 | ```bash 98 | git clone --branch release-5.0.3 --depth 1 https://github.com/qbittorrent/qBittorrent.git 99 | ``` 100 | 101 | Step 3: Copy the file that we need to edit to our home directory. 102 | 103 | ```bash 104 | cp qBittorrent/src/webui/webui.cpp webui.cpp 105 | ``` 106 | 107 | Step 4: Now edit the `~/webui.cpp` as per this [example of the applied patch](https://github.com/userdocs/qbittorrent-nox-static-test/blob/9b48000c7faa8baabbab57b733eceb20431d5d77/patches/qbittorrent/5.0.3/source/src/webui/webui.cpp#L41-L75) 108 | 109 | Step 5: Once you have finished making your changes you can create a patch file using this command 110 | 111 | ```bash 112 | diff -Naru qBittorrent/src/webui/webui.cpp webui.cpp > ~/patch 113 | ``` 114 | 115 | You will now have a `patch` file that looks like this: [qbittorrent/5.0.3/patch](https://github.com/userdocs/qbittorrent-nox-static-test/blob/main/patches/qbittorrent/5.0.3/patch) 116 | 117 | Step 6: 118 | 119 | The directory structure that will be created will look like this: 120 | 121 | 122 | Place your patch file named `patch` inside the relevant directories. So it would look something like this: 123 | 124 | ```bash 125 | qbt-build/patches/qbittorrent/5.0.3/patch 126 | ``` 127 | 128 | Then the patch file will be automatically matched to the tag used by the script and loaded. 129 | 130 | ### Using custom github tags 131 | 132 | Some modules like libtorrent and qbittorrent have multiple tags that can be used and they can be passed to the script as variables or switches. The script will use the default tags if none are provided. 133 | 134 | Using the `-qt` and -`lt` switches here: 135 | 136 | ```bash 137 | ~/qbittorrent-nox-static.sh -qt master -lt RC_2_0 -bs 138 | ``` 139 | 140 | or 141 | 142 | ```bash 143 | export qbt_qbittorrent_tag=master 144 | export qbt_libtorrent_tag=RC_2_0 145 | ``` 146 | 147 | The bootstrapped directory structure would look like this instead: 148 | 149 | ```bash 150 | qbt-build/patches/qbittorrent/master 151 | qbt-build/patches/libtorrent/RC_2_0 152 | ``` 153 | 154 | :::caution 155 | Remember to provide the same tags via switches when using the build command or the patches won't match the defaults. 156 | 157 | Only the env variables will persist between uses of the script. 158 | ::: 159 | 160 | ```bash 161 | qbittorrent-nox-static.sh -qt master -lt RC_2_0 all 162 | ``` 163 | 164 | ### Git based patching 165 | 166 | Instead of a local patch you can use github hosted patch files. Your patches need to be hosted in the root of the repo like this: 167 | 168 | 169 | 170 | 171 | ```bash 172 | patches/qbittorrent/master/patch 173 | patches/qbittorrent/4.5.0/patch 174 | ``` 175 | 176 | 177 | 178 | 179 | ```bash 180 | patches/libtorrent/RC_2_0/patch 181 | patches/libtorrent/RC_1_2/patch 182 | patches/libtorrent/v1.2.12/patch 183 | ``` 184 | 185 | 186 | 187 | 188 | The all you do is use the `pr` switch when using the script. The repo URL is abbreviated to your username and repo: 189 | 190 | `bash ~/qbittorrent-nox-static.sh all -pr username/repo` 191 | 192 | Then the patch file will be automatically matched to the tag used by the script and loaded. 193 | 194 | ### How to make a patch 195 | 196 | Using qbittorrent as an example we will edit the `src/base/bittorrent/session.cpp` to apply some session defaults. 197 | 198 | Download the relevant git repo: 199 | 200 | ```bash 201 | git clone --no-tags --single-branch --branch release-4.5.0 --shallow-submodules --recurse-submodules --depth 1 https://github.com/qbittorrent/qBittorrent.git 202 | ``` 203 | 204 | Copy the file that we need to edit to our home directory. 205 | 206 | ```bash 207 | cp qBittorrent/src/base/bittorrent/session.cpp ~/session.cpp 208 | ``` 209 | 210 | Now edit the `~/session.cpp`. Once you have finished making your changes you can create a patch file using this command 211 | 212 | ```bash 213 | diff -Naru qBittorrent/src/base/bittorrent/session.cpp ~/session.cpp > ~/patch 214 | ``` 215 | 216 | Then you place that patch file in the matching tag directory. 217 | 218 | ```bash 219 | patches/qbittorrent/4.3.4.1/patch 220 | ``` 221 | 222 | ### Using a Github pull request or commit 223 | 224 | First, it's sensible to make sure the patch that we want to use is from a pull request on the same branch that we are building against. So when using `release-4.5.0` we should use https://github.com/qbittorrent/qBittorrent/tree/v4_5_x 225 | 226 | You can see the branches for qBittorrent here - https://github.com/qbittorrent/qBittorrent/branches 227 | 228 | When you are on a commit or pull request you simply add `.patch` to the end of the url. 229 | 230 | So here we take the pull request or commit URL 231 | 232 | https://github.com/qbittorrent/qBittorrent/pull/18271 233 | 234 | https://github.com/qbittorrent/qBittorrent/commit/c924904308e806db6e1b321da18c1f91c4e8f8bf 235 | 236 | and add `.patch` to it so it becomes this 237 | 238 | https://github.com/qbittorrent/qBittorrent/pull/18271.patch 239 | 240 | https://github.com/qbittorrent/qBittorrent/commit/c924904308e806db6e1b321da18c1f91c4e8f8bf.patch 241 | 242 | You can download these using `curl` or `wget` and use these as patches in custom builds. 243 | 244 | ### Cache folder based patching 245 | 246 | The cache folder system is essentially an offline dependency system that allows you to store source files for modules that you want to patch. 247 | 248 | This allows the cached folder system to serve as a way patch modules. Source folders are stored in the cache folder and they are copied over to the build directory when the script is run. 249 | 250 | This means you can edit the source files in the cache folder and they will be copied over to the build directory when the script is run. 251 | 252 | This method is similar to the `source` directory method but it is more flexible and allows you to store multiple versions of the source files via checking out a specific tag or branch. 253 | -------------------------------------------------------------------------------- /docs/src/content/docs/prerequisites.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Prerequisite Check list 3 | hide_title: true 4 | --- 5 | 6 | import { Advanced, Charts, Details, Modal, Steps, Tabs, TabItem, Card, CardGrid, LinkCard, Aside, Icon } from "/src/components/global.jsx" 7 | 8 | ⭐ The rules of engagement are: 9 | 10 | 11 | 12 | 1. Use Docker - to avoid conflicts with the host system, especially with Qt. Docker is the recommended method. 13 | 14 | 2. Use Alpine - It is the main supported system and Debian is a testing and fallback. You do not need to build on an older host to use these binaries there. 15 | 16 | 3. `sudo` - `root` is not required to run the script, but it is required to install the core dependencies if they are missing. 17 | 18 | 4. Using additional flags and switches can add dependencies, like `-c` for cmake and `-cd` for cache dependencies. 19 | 20 | 5. Executing the script with no arguments will only install the dependencies and configure the build environment. 21 | 22 | 6. Nothing is built until you provide the `all` or a specific module name as a positional parameter to the script. 23 | 24 | 7. The script has a comprehensive built-in help system. Use `bash ~/qbittorrent-nox-static.sh -h` to see the help. 25 | 26 | 8. You can fork the repo and build on Github using Github Actions to create your own custom releases. 27 | 28 | 29 | 30 | 31 | 32 | :::tip[Optional - Paid service for faster build times] 33 | For faster build times you can consider a paid service like to use as self hosted runners with the Github Actions 34 | ::: 35 | 36 | 37 | 38 | ### Prerequisite Check list 39 | 40 | If you want to self host you need to be able to meet these conditions on your host in order to use the script. 41 | 42 | 🟩 Supported host build platforms 43 | - Debian: `Bookworm` 44 | - Ubuntu: `Noble` 45 | - Alpine: `3.15` or greater 46 | 47 | 🟩 Build environment 48 | - via a shell like or 49 | - : `Windows` `MacOS` `WSL2` 50 | - WSL2 51 | - Run directly in the Debian or Ubuntu image ❌ (works but not recommended) 52 | - Via ✅ (recommended method) 53 | - Docker installed in image ✅ (alternative recommendation) 54 | 55 | 56 | 🟩 Bash Shell script 57 | - This is 100% a modern bash shell script and it requires having access to bash to run it. 58 | 59 | 60 | 🟧 Host permissions 61 | 62 | - The script needs to install some system dependencies in order to proceed and if you do not have permission or access to do this or no access to docker to use a container you must find a more suitable host environment. 63 | 64 | 65 | 🟥 Qt6 requirements 66 | 67 | - If you build using Qt6 you will need to have these dependencies installed on the host, 68 | 69 | 70 | 71 | 72 | ```bash 73 | sudo apt install qemu-user-static binfmt-support 74 | ``` 75 | 76 | 77 | 78 | 79 | ```bash 80 | sudo apk add qemu qemu-openrc 81 | ``` 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /docs/src/content/docs/script-installation.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Script Installation 3 | description: Script Installation 4 | --- 5 | 6 | import { Advanced, Charts, Details, Modal, Steps, Tabs, TabItem, Card, CardGrid, LinkCard, Aside, Icon } from "/src/components/global.jsx" 7 | 8 | :::note[Host environment] 9 | The recommended build platform is Alpine Linux and the supported build method is via docker. It will just make things easier. 10 | 11 | We do not support a non docker build environment. If you are not using docker, you are on your own. 12 | ::: 13 | 14 | :::tip[Github Actions] 15 | If you cannot or don't want to use docker, you can use the [Github Actions](/qbittorrent-nox-static/github-actions) to build the project by forking the repository. 16 | ::: 17 | 18 | ## Bootstrapping the container 19 | 20 | 21 | 22 | 23 | Some notes on the dockers method: 24 | 25 | - The script installs the necessary dependencies so there is no docker file needed. 26 | - We use a subdirectory `qbt`, not your `$HOME` directory, to avoid `.bashrc` and `.profile` conflicts. 27 | - A subdirectory is automatically created, named `qbt` by the use of `-v $HOME/qbt:/root` 28 | - The default path will be `HOME/qbt` outside the docker container and `/root/qbt` inside it. 29 | - We use `-e "LANG=C.UTF-8"` with Debian based images to avoid some UTF errors. 30 | 31 | :::tip[env file] 32 | There are multiple ways to pass an env file when using Docker. 33 | 34 | - You can use the `--env-file` switch when creating the docker and provide a file with your [envs](/qbittorrent-nox-static/build-help#env-settings). 35 | - If a `.qbt_env` file is found in the same directory as the script, it will be used automatically. 36 | - Using ENV in a dockerfile is also possible. 37 | ::: 38 | 39 | 40 | 41 | 42 | 43 | :::note[tags] 44 | You use `alpine:edge` `alpine:latest` 45 | ::: 46 | 47 | To bootstrap the container: 48 | 49 | ```bash 50 | docker run -it -w /root -p 8080:8080 -v ~/qbt:/root alpine:edge /bin/ash -c 'apk update && apk add bash curl && bash' 51 | ``` 52 | 53 | If you need to download the script use this command 54 | 55 | ```bash 56 | curl -sLo qbittorrent-nox-static.sh git.io/qbstatic && chmod +x qbittorrent-nox-static.sh 57 | ``` 58 | 59 | 60 | 61 | 62 | 63 | :::note[tags] 64 | You use `debian:bullseye` `debian:bookworm` `debian:latest` or a supported tag 65 | ::: 66 | 67 | To bootstrap the container: 68 | 69 | ```bash 70 | docker run -it -w /root -p 8080:8080 -e "LANG=C.UTF-8" -v ~/qbt:/root debian:latest /bin/bash -c 'apt update && apt install -y curl && bash' 71 | ``` 72 | 73 | If you need to download the script use this command 74 | 75 | ```bash 76 | curl -sLo qbittorrent-nox-static.sh git.io/qbstatic && chmod +x qbittorrent-nox-static.sh 77 | ``` 78 | 79 | 80 | 81 | 82 | :::note[tags] 83 | You use `ubuntu:jammy` `ubuntu:noble` `ubuntu:latest` 84 | ::: 85 | 86 | To bootstrap the container: 87 | 88 | ```bash 89 | docker run -it -w /root -p 8080:8080 -e "LANG=C.UTF-8" -v ~/qbt:/root ubuntu:latest /bin/bash -c 'apt update && apt install -y curl && bash' 90 | ``` 91 | 92 | If you need to download the script use this command 93 | 94 | ```bash 95 | curl -sLo qbittorrent-nox-static.sh git.io/qbstatic && chmod +x qbittorrent-nox-static.sh 96 | ``` 97 | 98 | 99 | 100 | 101 | You are now ready to run the script. 102 | -------------------------------------------------------------------------------- /docs/src/content/docs/script-usage.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Script Usage 3 | hide_title: true 4 | --- 5 | 6 | import { Advanced, Charts, Details, Modal, Steps, Tabs, TabItem, Card, CardGrid, LinkCard, Aside, Icon } from "/src/components/global.jsx" 7 | 8 | :::caution[Assumptions] 9 | The guide will assume you are using docker, with example commands that are either one liners or from within the container. 10 | ::: 11 | 12 | :::danger 13 | Don't run this directly on the host system unless you know what you are doing. It's not recommended and the build will probably fail. 14 | ::: 15 | 16 |
![](/qbittorrent-nox-static/docs_images/script_usage/first-run.png)
17 | 18 | ⭐ When you are familiar with the script you can do most builds you want with a one liner. It's pretty simple to use. 19 | 20 | ### Execute the script 21 | 22 | ```bash 23 | ./qbittorrent-nox-static.sh 24 | ``` 25 | 26 | :::note 27 | Please see the [switches and flags summary](build-help/#switches-and-flags-summarised) to see what options you can pass and how to use them 28 | ::: 29 | 30 | The first thing you should do is to run the script with the `-h` flag to see the help output and the script defaults. 31 | 32 | ```bash 33 | ./qbittorrent-nox-static.sh -h 34 | ``` 35 | 36 | By passing `all` as the first argument, you can build everything based on the default settings. 37 | 38 | ```bash 39 | ./qbittorrent-nox-static.sh all 40 | ``` 41 | 42 | For example, to use `ICU` using `-i`, optimise for the host system CPU using `-o` to set `-march=native` and `-s` to strip the binary and build using libtorrent v1.2.19 43 | 44 | ```bash 45 | ./qbittorrent-nox-static.sh all -i -o -s -lt v1.2.19 46 | ``` 47 | 48 | Same as previous command but using `env` settings 49 | 50 | ```bash 51 | qbt_libtorrent_tag="v1.2.19" qbt_skip_icu="yes" qbt_optimise_strip="yes" qbt_optimize="yes" ./qbittorrent-nox-static.sh all 52 | ``` 53 | 54 | For an older version of qBittorrent, you can specify the version using `-qt` and the libtorrent version using `-lt` 55 | 56 | ```bash 57 | ./qbittorrent-nox-static.sh all -q -qt release-4.1.9.1 -lt libtorrent-1_1_14 -bt boost-1.76.0 58 | ``` 59 | -------------------------------------------------------------------------------- /docs/src/content/docs/systemd.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Systemd 3 | hide_title: true 4 | --- 5 | 6 | import { Advanced, Charts, Details, Modal, Steps, Tabs, TabItem, Card, CardGrid, LinkCard, Aside, Icon } from "/src/components/global.jsx" 7 | 8 | ### Systemd service 9 | 10 | Location for the systemd service file: 11 | 12 | ```bash 13 | /etc/systemd/system/qbittorrent.service 14 | ``` 15 | 16 | Modify the path to the binary and your local username. 17 | 18 | ```ini 19 | [Unit] 20 | Description=qBittorrent-nox service 21 | Wants=network-online.target 22 | After=network-online.target nss-lookup.target 23 | 24 | [Service] 25 | Type=exec 26 | User=qbtuser 27 | ExecStart=/usr/local/bin/qbittorrent-nox 28 | Restart=on-failure 29 | SyslogIdentifier=qbittorrent-nox 30 | 31 | [Install] 32 | WantedBy=multi-user.target 33 | ``` 34 | 35 | After any changes to the services reload using this command. 36 | 37 | ```bash 38 | systemctl daemon-reload 39 | ``` 40 | 41 | Now you can enable the service 42 | 43 | ```bash 44 | systemctl enable --now qbittorrent.service 45 | ``` 46 | 47 | Now you can use these commands 48 | 49 | ```bash 50 | systemctl stop qbittorrent 51 | systemctl start qbittorrent 52 | systemctl restart qbittorrent 53 | ``` 54 | 55 | ### Systemd user service 56 | 57 | You can also use a local systemd service. 58 | 59 | ```bash 60 | ~/.config/systemd/user/qbittorrent.service 61 | ``` 62 | 63 | You can use this configuration with no modification required. 64 | 65 | ```ini 66 | [Unit] 67 | Description=qbittorrent 68 | Wants=network-online.target 69 | After=network-online.target nss-lookup.target 70 | 71 | [Service] 72 | Type=exec 73 | ExecStart=%h/bin/qbittorrent-nox 74 | Restart=on-failure 75 | SyslogIdentifier=qbittorrent-nox 76 | 77 | [Install] 78 | WantedBy=default.target 79 | ``` 80 | 81 | After any changes to the services reload using this command. 82 | 83 | ```bash 84 | systemctl --user daemon-reload 85 | ``` 86 | 87 | Now you can enable the service 88 | 89 | ```bash 90 | systemctl --user enable --now qbittorrent 91 | ``` 92 | 93 | Now you can use these commands 94 | 95 | ```bash 96 | systemctl --user stop qbittorrent 97 | systemctl --user start qbittorrent 98 | systemctl --user restart qbittorrent 99 | ``` 100 | -------------------------------------------------------------------------------- /docs/src/content/docs/test.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: test 3 | hide_title: true 4 | --- 5 | 6 | import { Advanced, Charts, Details, Modal, Steps, Tabs, TabItem, Card, CardGrid, LinkCard, Aside, Icon } from "/src/components/global.jsx" 7 | 8 | 1 2 3 4 5 9 | 6 7 8 9 10 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 |
19 | 20 |
21 | ## 2142121 22 | 23 | ### 5553453 24 | 25 | #### 3343435 26 | 27 | ## 88676776 28 | 29 | ## saafa 30 | 31 | ### affsdgsd 32 | 33 | #### asdfasf 34 | 35 | ## sfsfsaf 36 | 37 |
38 |
39 | 40 |
41 |
42 | -------------------------------------------------------------------------------- /docs/src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | -------------------------------------------------------------------------------- /docs/src/pages/changelog.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import StarlightPage from "@astrojs/starlight/components/StarlightPage.astro"; 3 | import * as myPost from "../../../changelog.md"; 4 | 5 | const headings = myPost.getHeadings().map((heading) => ({ 6 | depth: heading.depth, 7 | slug: heading.slug, 8 | text: heading.text, 9 | })); 10 | --- 11 | 12 | 13 |
14 | 15 | -------------------------------------------------------------------------------- /docs/src/pages/glossary.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import StarlightPage from "@astrojs/starlight/components/StarlightPage.astro"; 3 | 4 | interface GlossaryEntry { 5 | file: string; 6 | frontmatter: { 7 | title: string; 8 | }; 9 | } 10 | 11 | interface File { 12 | fileBase: string; 13 | title: string; 14 | } 15 | 16 | const basePath = `/${Astro.url.pathname.split("/")[1]}`; 17 | 18 | // Get all markdown files 19 | const posts = import.meta.glob( 20 | "/src/content/docs/glossary/*.md", 21 | { 22 | eager: true, 23 | } 24 | ); 25 | 26 | // Convert posts object to array and map to File[] 27 | const files: File[] = Object.entries(posts).map(([path, post]) => { 28 | const fileBase = path.split("/").pop()?.split(".").shift() ?? ""; 29 | return { 30 | fileBase, 31 | title: post.frontmatter.title, 32 | }; 33 | }); 34 | 35 | // Group files by first letter 36 | const sections = files.reduce((acc: { [key: string]: File[] }, file) => { 37 | const firstLetter = file.title.charAt(0).toUpperCase(); 38 | if (!acc[firstLetter]) { 39 | acc[firstLetter] = []; 40 | } 41 | acc[firstLetter].push(file); 42 | return acc; 43 | }, {}); 44 | 45 | // Generate headings for each section 46 | const headings = Object.entries(sections) 47 | .sort(([a], [b]) => a.localeCompare(b)) 48 | .map(([slug]) => ({ 49 | depth: 2, 50 | slug, 51 | text: slug, 52 | })); 53 | --- 54 | 55 | 56 | { 57 | Object.entries(sections).map(([sectionTitle, files]: [string, File[]]) => ( 58 | <> 59 |

{sectionTitle}

60 |
    61 | {files.map(({ fileBase, title }: File) => ( 62 |
  • 63 | {title} 64 |
  • 65 | ))} 66 |
67 | 68 | )) 69 | } 70 |
71 | -------------------------------------------------------------------------------- /docs/src/styles/custom.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --sl-color-accent-low: #002b24; 3 | --sl-color-accent: #bdbdbd; 4 | --sl-color-accent-high: #bdbdbd; 5 | --sl-color-white: #c7a06f; 6 | --sl-color-gray-1: #c17ac8; 7 | --sl-color-gray-1-1: #957497; 8 | --sl-color-gray-2: #b4b4b4; 9 | --sl-color-gray-3: #6d6d6d; 10 | --sl-color-gray-4: #c55858; 11 | --sl-color-gray-5: #bdbdbd; 12 | --sl-color-gray-6: #543768; 13 | --sl-color-black: #15141b; 14 | --sl-button-bg-primary: #347c64; 15 | --sl-button-bg-secondary: #553f64; 16 | --react-toggle-checked: #aa4bb3; 17 | --details-1: #2a2a2c; 18 | --details-2: #543768; 19 | --details-3: #54385f; 20 | --url-colour: #54c59f; 21 | --url-colour-hover: #6cb2c7; 22 | --code-inline-background: #321735; 23 | --code-inline-color: #bdbdbd; 24 | --code-inline-border: #45aa88; 25 | --tab-background-if: #ab94b4; 26 | --tab-background-oof: #54385f; 27 | --tab-color-if: #111011; 28 | --tab-color-oof: #828285; 29 | --steps-border: #aa4bb3; 30 | --modal-url-color: var(--sl-color-black); 31 | --modal-url-hover-color: rgb(255, 255, 255); 32 | --modal-url-bg-color: var(--code-inline-border); 33 | --modal-url-bg-hv-color: rgb(34, 199, 191); 34 | } 35 | 36 | :root[data-theme="light"] { 37 | --sl-color-accent-low: #f5b5ea; 38 | --sl-color-accent: #136454; 39 | --sl-color-accent-high: #003c33; 40 | --sl-color-white: #1d122b; 41 | --sl-color-gray-1: #31154f; 42 | --sl-color-gray-2: #432863; 43 | --sl-color-gray-3: #634987; 44 | --sl-color-gray-4: #977cbf; 45 | --sl-color-gray-5: #c8bbde; 46 | --sl-color-gray-6: #f1e9ff; 47 | --sl-color-gray-7: #dedae6; 48 | --sl-color-black: #e7e6e6; 49 | --sl-button-bg-primary: #c1dad1; 50 | --sl-button-bg-secondary: #beadc9; 51 | --react-toggle-checked: #aa4bb3; 52 | --details-1: #a0b494; 53 | --details-2: #4c0879; 54 | --details-3: #d6d6d6; 55 | --url-colour: #660891 !important; 56 | --url-colour-hover: #14574c !important; 57 | --code-inline-background: #54c59f; 58 | --code-inline-color: #000; 59 | --code-inline-border: #002b24; 60 | --tab-background-if: #ab94b4; 61 | --tab-background-oof: #54385f; 62 | --tab-color-if: #111011; 63 | --tab-color-oof: rgb(210, 210, 214); 64 | --steps-border: #aa4bb3; 65 | --modal-url-color: var(--sl-color-black); 66 | --modal-url-hover-color: rgb(0, 0, 0); 67 | --modal-url-bg-color: var(--code-inline-border); 68 | --modal-url-bg-hv-color: rgb(34, 199, 191); 69 | } 70 | 71 | /* Theme adjustments */ 72 | 73 | .sl-steps li::before { 74 | border: 1px solid var(--steps-border) !important; 75 | box-shadow: none !important; 76 | border-radius: 0% !important; 77 | line-height: 2em !important; 78 | } 79 | 80 | .sl-steps li::after { 81 | border: 1px solid var(--steps-border) !important; 82 | } 83 | 84 | .right-sidebar.astro-67yu43on { 85 | max-width: 100%; 86 | } 87 | 88 | p a { 89 | color: var(--url-colour) !important; 90 | } 91 | 92 | p a:hover { 93 | color: var(--url-colour-hover) !important; 94 | } 95 | 96 | [data-has-sidebar] { 97 | .sl-container { 98 | max-width: 100%; 99 | } 100 | } 101 | 102 | .sl-markdown-content code:not(:where(.not-content *)) { 103 | background-color: var(--code-inline-background); 104 | border-radius: none; 105 | font-size: 0.8em; 106 | color: var(--code-inline-color); 107 | border: 1px solid var(--code-inline-border); 108 | } 109 | 110 | 111 | /* resize the card svg logos */ 112 | 113 | .card-logos-image * { 114 | max-height: 100px; 115 | min-height: 100px; 116 | width: 100%; 117 | } 118 | 119 | /* front page card stuff */ 120 | 121 | .float-container { 122 | padding: 0; 123 | } 124 | 125 | .float-child { 126 | padding: 100px; 127 | } 128 | 129 | .float-child.card-image { 130 | width: 50%; 131 | max-width: 100px; 132 | min-height: 150px; 133 | float: left; 134 | padding: 0; 135 | } 136 | 137 | .float-child.card-text { 138 | margin: auto; 139 | padding: 0; 140 | padding-left: 10px; 141 | } 142 | 143 | /* front page button stuff */ 144 | 145 | .title { 146 | align-items: left !important; 147 | margin-left: 31% !important; 148 | } 149 | 150 | .card-image { 151 | margin-right: 5% !important; 152 | margin-left: 2% !important; 153 | width: 150px !important; 154 | max-width: 150px; 155 | padding: 0; 156 | } 157 | 158 | .sl-flex.actions.astro-jbfsktt5 a { 159 | min-width: 45%; 160 | border: 3px solid var(--sl-color-white); 161 | } 162 | 163 | .sl-flex.action.primary.astro-yjy4zhro { 164 | border-radius: 3px; 165 | background-color: var(--sl-button-bg-primary) !important; 166 | padding: 2px 2px 4px 10px !important; 167 | border-color: var(--sl-button-bg-secondary) !important; 168 | color: var(--sl-color-accent) !important; 169 | } 170 | 171 | .sl-flex.action.secondary.astro-yjy4zhro { 172 | border-radius: 3px !important; 173 | background-color: var(--sl-button-bg-secondary) !important; 174 | padding: 2px 2px 4px 10px !important; 175 | border-color: var(--sl-button-bg-primary) !important; 176 | color: var(---sl-color-accent) !important; 177 | } 178 | 179 | /* tabs stuff start */ 180 | 181 | a[aria-selected="true"] { 182 | border-top: 1px solid var(--sl-color-white) !important; 183 | border-bottom: 1px solid var(--sl-color-white) !important; 184 | color: var(--tab-color-if) !important; 185 | background-color: var(--tab-background-if) !important; 186 | } 187 | 188 | a[tabindex="-1"] { 189 | border-top: 1px solid var(--sl-button-bg-secondary) !important; 190 | border-bottom: 1px solid var(--sl-button-bg-secondary) !important; 191 | background-color: var(--tab-background-oof) !important; 192 | color: var(--tab-color-oof) !important; 193 | } 194 | 195 | /* react toggle start */ 196 | 197 | .toggle-global { 198 | margin: 20px 16px 16px 0; 199 | padding-top: 5px; 200 | padding-left: 5px; 201 | } 202 | 203 | .react-toggle-track-x { 204 | margin: 0 3px 0 0; 205 | padding-bottom: 17px; 206 | } 207 | 208 | .react-toggle-track-check { 209 | margin: 0; 210 | padding-bottom: 16px; 211 | } 212 | 213 | .react-toggle-track { 214 | min-width: 16px; 215 | background-color: #6d6d6d !important; 216 | } 217 | 218 | .react-toggle-thumb { 219 | -webkit-box-shadow: none !important; 220 | -moz-box-shadow: none !important; 221 | box-shadow: none !important; 222 | border: 3px solid !important; 223 | border-color: #54c59f !important; 224 | } 225 | 226 | .react-toggle .react-toggle-thumb { 227 | background-color: #c7a06f !important; 228 | } 229 | 230 | .react-toggle--checked .react-toggle-thumb { 231 | background-color: #8464c6 !important; 232 | } 233 | 234 | .react-toggle--checked .react-toggle-track { 235 | background-color: var(--react-toggle-checked) !important; 236 | } 237 | 238 | 239 | /* react toggle end */ 240 | 241 | /* react tooltip end */ 242 | 243 | .my-tooltip { 244 | padding-bottom: 5px !important; 245 | position: absolute !important; 246 | z-index: 9999 !important; 247 | max-width: 400px; 248 | max-height: 400px; 249 | border: 2px solid var(--react-toggle-checked); 250 | opacity: 1 !important; 251 | } 252 | 253 | /* react tooltip end */ 254 | 255 | /* make sure there is a gap when it is rendered on page */ 256 | 257 | #Advanced-class { 258 | padding-top: 15px; 259 | margin: auto; 260 | } 261 | 262 | /* resized main widows where toc is fml */ 263 | 264 | .main-pane { 265 | min-width: 75% !important; 266 | } 267 | 268 | /* .tooltip-link {} */ 269 | 270 | .tooltip-line { 271 | display: block; 272 | margin-bottom: 2px; 273 | } 274 | 275 | .custom-content .mxgraph { 276 | width: 100% !important; 277 | height: 100% !important; 278 | } 279 | 280 | /* starlight aside stuff */ 281 | 282 | .starlight-aside { 283 | color: var(--sl-color-gray-2) !important; 284 | padding: 1rem; 285 | border-inline-start: 0.25rem solid; 286 | border-left: 1px solid; 287 | border-bottom: 1px solid; 288 | } 289 | 290 | .expressive-code .ec-line { 291 | tab-size: 4; 292 | } 293 | 294 | .starlight-aside__icon { 295 | display: none !important; 296 | } 297 | 298 | .starlight-aside--note .starlight-aside__title::before { 299 | content: ""; 300 | display: inline-block; 301 | width: 1em; 302 | height: 1em; 303 | background-color: rgba(76, 179, 212); 304 | border-radius: 100%; 305 | } 306 | 307 | .starlight-aside--tip .starlight-aside__title::before { 308 | content: ""; 309 | display: inline-block; 310 | width: 1em; 311 | height: 1em; 312 | background-color: rgba(0, 148, 0, 1); 313 | border-radius: 100%; 314 | } 315 | 316 | .starlight-aside--caution .starlight-aside__title::before { 317 | content: ""; 318 | display: inline-block; 319 | width: 1em; 320 | height: 1em; 321 | background-color: rgba(230, 167, 0); 322 | border-radius: 100%; 323 | } 324 | 325 | .starlight-aside--danger .starlight-aside__title::before { 326 | content: ""; 327 | display: inline-block; 328 | width: 1em; 329 | height: 1em; 330 | background-color: rgba(225, 50, 56); 331 | border-radius: 100%; 332 | } 333 | 334 | .starlight-aside--note { 335 | border-color: rgba(76, 179, 212); 336 | background-color: rgba(76, 179, 212, 0.05); 337 | } 338 | 339 | .starlight-aside--tip { 340 | border-color: rgba(0, 148, 0); 341 | background-color: rgba(0, 148, 0, 0.05); 342 | } 343 | 344 | .starlight-aside--caution { 345 | border-color: rgba(230, 167, 0); 346 | background-color: rgba(230, 167, 0, 0.05); 347 | } 348 | 349 | .starlight-aside--danger { 350 | border-color: rgba(225, 50, 56); 351 | background-color: rgba(225, 50, 56, 0.05); 352 | } 353 | 354 | .starlight-aside__title { 355 | margin-top: -8px !important; 356 | margin-left: 0 !important; 357 | margin-bottom: -5px !important; 358 | } 359 | 360 | .starlight-aside__content { 361 | margin-bottom: -10px !important; 362 | padding-bottom: 0 !important; 363 | } 364 | 365 | [class*="starlight-aside--"] { 366 | background-color: transparent !important; 367 | } 368 | 369 | .my-icon-container { 370 | padding: 0 0 10px 10px; 371 | } 372 | 373 | .my-icon-container.star-tip { 374 | border: 3px solid #ffae35; 375 | } 376 | 377 | .my-icon-container.danger { 378 | border: 3px solid #ba1522; 379 | } 380 | 381 | .my-icon-container.warning { 382 | border: 3px solid #ffae35; 383 | } 384 | 385 | .my-icon-container.note { 386 | border: 3px solid #0095ff; 387 | } 388 | 389 | .my-icon-container.tip { 390 | border: 3px solid #1fc6a0; 391 | } 392 | 393 | .my-icon { 394 | width: 100px !important; 395 | max-width: 100px !important; 396 | } 397 | 398 | .my-icon-image { 399 | margin-left: -13px !important; 400 | height: 30px !important; 401 | } 402 | 403 | .my-icon-image.tip { 404 | margin-top: -3.6px !important; 405 | margin-left: -12.5px !important; 406 | } 407 | 408 | .my-icon-image.note { 409 | margin-top: -2.5px !important; 410 | margin-left: -12px !important; 411 | } 412 | 413 | .my-icon-image.star-tip { 414 | margin-top: -2.5px !important; 415 | } 416 | 417 | .my-icon-image.warning { 418 | margin-top: -3.6px !important; 419 | margin-left: -12px !important; 420 | } 421 | 422 | .my-icon-image.danger { 423 | margin-top: -2.5px !important; 424 | margin-left: -12px !important; 425 | } 426 | 427 | .my-icon-text { 428 | margin-top: 0 !important; 429 | width: 100% !important; 430 | } 431 | 432 | /* .tooltip-link {} */ 433 | 434 | .tooltip-line { 435 | display: block; 436 | margin-bottom: 2px; 437 | } 438 | 439 | .tooltippy-line { 440 | margin: 10px 0 5px 0; 441 | } 442 | 443 | .tooltippy-link { 444 | margin: 0 ; 445 | } 446 | 447 | .tooltippy-div { 448 | margin: 5px 0 0 0; 449 | } 450 | 451 | .tippy-box { 452 | border: 4px solid var(--react-toggle-checked); 453 | opacity: 1 !important; 454 | padding: 5px 4px; 455 | margin-bottom: 0; 456 | } 457 | 458 | /* .tippy-content {} */ 459 | 460 | .my-tooltip-url { 461 | color: var(--url-colour) !important; 462 | } 463 | 464 | .my-tooltip-url:hover { 465 | color: var(--url-colour-hover) !important; 466 | cursor: pointer; 467 | } 468 | 469 | .tooltippy-link { 470 | color: var(--url-colour) !important; 471 | } 472 | 473 | .tooltippy-link:hover { 474 | color: var(--url-colour-hover) !important; 475 | cursor: pointer; 476 | } 477 | 478 | .sl-markdown-content details:not(:where(.not-content *)) { 479 | --sl-details-border-color--hover: var(--sl-color-gray-1); 480 | 481 | border-inline-start: 0 solid var(--sl-details-border-color); 482 | padding-inline-start: 0.6rem; 483 | padding-left: 0 !important; 484 | } 485 | 486 | .sl-markdown-content details[open]>summary:not(:where(.not-content *)) { 487 | margin-bottom: 0; 488 | } 489 | -------------------------------------------------------------------------------- /docs/src/themes/expressive-code/aura-soft-dark-soft-text-color-theme.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Aura Soft Dark (Soft Text)", 3 | "type": "dark", 4 | "colors": { 5 | "focusBorder": "#a394f033", 6 | "foreground": "#bdbdbd", 7 | "errorForeground": "#c55858", 8 | "widget.shadow": "#0f0f0f", 9 | "selection.background": "#3d375e7f", 10 | "titleBar.activeBackground": "#121016", 11 | "titleBar.border": "#000000", 12 | "titleBar.inactiveBackground": "#2d2b38", 13 | "statusBar.background": "#1f1a27", 14 | "statusBar.foreground": "#adacae", 15 | "statusBar.border": "#141414", 16 | "statusBar.debuggingForeground": "#21202e", 17 | "statusBar.debuggingBackground": "#a19c77", 18 | "statusBarItem.activeBackground": "#8464c6", 19 | "dropdown.background": "#21202e", 20 | "dropdown.border": "#3b334b", 21 | "dropdown.foreground": "#b4b4b4", 22 | "input.background": "#21202e", 23 | "input.border": "#3b334b", 24 | "input.foreground": "#b4b4b4", 25 | "input.placeholderForeground": "#af8aff7f", 26 | "inputOption.activeBorder": "#8464c6", 27 | "button.background": "#54c59f", 28 | "button.foreground": "#21202e", 29 | "button.hoverBackground": "#49c29a", 30 | "list.activeSelectionBackground": "#2e2b38", 31 | "list.activeSelectionForeground": "#8464c6", 32 | "list.focusBackground": "#3b334b", 33 | "list.focusForeground": "#8464c6", 34 | "list.highlightForeground": "#c7a06f", 35 | "list.hoverBackground": "#3b334b", 36 | "list.hoverForeground": "#bdbdbd", 37 | "list.inactiveSelectionBackground": "#2e2b38", 38 | "list.inactiveSelectionForeground": "#8464c6", 39 | "editor.background": "#21202e", 40 | "editor.foreground": "#bdbdbd", 41 | "editorLineNumber.foreground": "#a394f033", 42 | "editorIndentGuide.activeBackground1": "#6d6d6d", 43 | "editorCursor.foreground": "#8464c6", 44 | "editor.selectionBackground": "#3d375e7f", 45 | "editor.selectionHighlightBackground": "#3d375e7f", 46 | "editor.inactiveSelectionBackground": "#3d375e7f", 47 | "editor.wordHighlightBackground": "#3d375e7f", 48 | "editor.wordHighlightStrongBackground": "#3d375e7f", 49 | "editor.findMatchBackground": "#3d375e7f", 50 | "editor.findMatchHighlightBackground": "#3d375e7f", 51 | "editor.findRangeHighlightBackground": "#3d375e7f", 52 | "editor.lineHighlightBackground": "#a394f033", 53 | "editor.lineHighlightBorder": "#a394f000", 54 | "editor.stackFrameHighlightBackground": "#353424", 55 | "editorInlayHint.background": "#2e2b38", 56 | "editorInlayHint.foreground": "#b4b4b4", 57 | "editorLink.activeForeground": "#8464c6", 58 | "editorWhitespace.foreground": "#444444", 59 | "editorIndentGuide.background1": "#444444", 60 | "editorBracketMatch.border": "#8464c6", 61 | "editorError.foreground": "#c55858", 62 | "editorError.border": "#ffffff00", 63 | "editorWarning.foreground": "#c7a06f", 64 | "editorWarning.border": "#ffffff00", 65 | "editorGutter.modifiedBackground": "#c7a06f", 66 | "editorGutter.addedBackground": "#54c59f", 67 | "editorGutter.deletedBackground": "#c55858", 68 | "editorWidget.background": "#1f1a27", 69 | "editorWidget.border": "#444444", 70 | "editorSuggestWidget.background": "#1f1a27", 71 | "editorSuggestWidget.border": "#444444", 72 | "editorSuggestWidget.foreground": "#b4b4b4", 73 | "editorSuggestWidget.highlightForeground": "#54c59f", 74 | "editorSuggestWidget.selectedBackground": "#4d4d4d", 75 | "editorHoverWidget.background": "#1f1a27", 76 | "editorHoverWidget.border": "#444444", 77 | "editorGroup.border": "#141414", 78 | "editorGroup.dropBackground": "#3d375e7f", 79 | "editorGroupHeader.tabsBackground": "#21202e", 80 | "editorGroupHeader.tabsBorder": "#141414", 81 | "tab.activeBackground": "#00000000", 82 | "tab.activeForeground": "#54c59f", 83 | "tab.border": "#141414", 84 | "tab.inactiveBackground": "#21202e", 85 | "tab.inactiveForeground": "#6d6d6d", 86 | "tab.activeBorderTop": "#54c59f", 87 | "panel.border": "#141414", 88 | "panelTitle.activeBorder": "#54c59f", 89 | "panelTitle.activeForeground": "#b4b4b4", 90 | "activityBar.background": "#21202e", 91 | "activityBar.foreground": "#54c59f", 92 | "activityBar.inactiveForeground": "#525156", 93 | "activityBar.border": "#141414", 94 | "activityBarBadge.background": "#8464c6", 95 | "activityBarBadge.foreground": "#21202e", 96 | "activityBar.activeBorder": "#8464c6", 97 | "badge.foreground": "#21202e", 98 | "badge.background": "#8464c6", 99 | "sideBar.background": "#1c1b22", 100 | "sideBar.foreground": "#b4b4b4", 101 | "sideBar.border": "#141414", 102 | "sideBarTitle.foreground": "#adacae", 103 | "sideBarSectionHeader.background": "#21202e", 104 | "sideBarSectionHeader.foreground": "#adacae", 105 | "progressBar.background": "#54c59f", 106 | "scrollbar.shadow": "#21202e", 107 | "scrollbarSlider.activeBackground": "#3d375e7f", 108 | "scrollbarSlider.background": "#a394f033", 109 | "scrollbarSlider.hoverBackground": "#a394f033", 110 | "terminal.background": "#21202e", 111 | "terminal.foreground": "#b4b4b4", 112 | "terminal.ansiBlack": "#21202e", 113 | "terminal.ansiBlue": "#8464c6", 114 | "terminal.ansiBrightBlack": "#444444", 115 | "terminal.ansiBrightBlue": "#8464c6", 116 | "terminal.ansiBrightCyan": "#54c59f", 117 | "terminal.ansiBrightGreen": "#8464c6", 118 | "terminal.ansiBrightMagenta": "#54c59f", 119 | "terminal.ansiBrightRed": "#c7a06f", 120 | "terminal.ansiBrightWhite": "#bdbdbd", 121 | "terminal.ansiBrightYellow": "#c7a06f", 122 | "terminal.ansiCyan": "#8464c6", 123 | "terminal.ansiGreen": "#54c59f", 124 | "terminal.ansiMagenta": "#54c59f", 125 | "terminal.ansiRed": "#c55858", 126 | "terminal.ansiWhite": "#b4b4b4", 127 | "terminal.ansiYellow": "#c7a06f", 128 | "terminal.selectionBackground": "#3d375e7f", 129 | "terminalCursor.background": "#444444", 130 | "terminalCursor.foreground": "#adacae", 131 | "gitDecoration.modifiedResourceForeground": "#c7a06f", 132 | "gitDecoration.deletedResourceForeground": "#c55858", 133 | "gitDecoration.untrackedResourceForeground": "#54c59f", 134 | "gitDecoration.ignoredResourceForeground": "#4d4d4d", 135 | "gitDecoration.conflictingResourceForeground": "#8464c6", 136 | "diffEditor.insertedTextBackground": "#00d89023", 137 | "diffEditor.removedTextBackground": "#ff474720", 138 | "tree.indentGuidesStroke": "#4d4d4d" 139 | }, 140 | "tokenColors": [ 141 | { 142 | "name": "Accent1", 143 | "scope": [ 144 | "keyword", 145 | "storage", 146 | "support", 147 | "entity.name.tag", 148 | "variable.language", 149 | "keyword.control.flow", 150 | "storage.modifier", 151 | "keyword.operator", 152 | "entity.other.attribute-name.class.css", 153 | "entity.other.keyframe-offset", 154 | "markup.heading", 155 | "markup.underline.link", 156 | "variable.other.env", 157 | "punctuation.definition.list.begin.markdown", 158 | "punctuation.definition.bold.markdown", 159 | "punctuation.definition.italic.markdown", 160 | "punctuation.definition.markdown", 161 | "punctuation.definition.quote.begin.markdown", 162 | "punctuation.definition.raw.markdown", 163 | "constant.length.units.css", 164 | "constant.percentage.units.css" 165 | ], 166 | "settings": { 167 | "foreground": "#8464c6" 168 | } 169 | }, 170 | { 171 | "name": "Accent2", 172 | "scope": [ 173 | "string", 174 | "markup.inserted", 175 | "markup.raw", 176 | "constant", 177 | "source.env", 178 | "support.type.builtin.graphql", 179 | "variable.other.quoted.double", 180 | "markup.inline.raw.string.markdown", 181 | "entity.other.attribute-name.id.css", 182 | "meta.jsx.children", 183 | "JSXNested" 184 | ], 185 | "settings": { 186 | "foreground": "#54c59f" 187 | } 188 | }, 189 | { 190 | "name": "Accent3", 191 | "scope": [ 192 | "markup.changed", 193 | "entity", 194 | "entity.name.function", 195 | "entity.name.function.elixir", 196 | "entity.name.function-call.elixir", 197 | "support.class.component.tsx", 198 | "support.class.component.open.jsx", 199 | "support.class.component.close.jsx", 200 | "meta.function-call.generic.python", 201 | "entity.name.section.markdown", 202 | "storage.type.annotation.dart" 203 | ], 204 | "settings": { 205 | "foreground": "#c7a06f" 206 | } 207 | }, 208 | { 209 | "name": "Accent5", 210 | "scope": [ 211 | "invalid", 212 | "markup.deleted" 213 | ], 214 | "settings": { 215 | "foreground": "#c55858" 216 | } 217 | }, 218 | { 219 | "name": "Accent6", 220 | "scope": [ 221 | "string.unquoted", 222 | "punctuation.separator", 223 | "entity.other.attribute-name", 224 | "meta.object-literal.key", 225 | "variable.object.property", 226 | "variable.other.property", 227 | "variable.other.object.property", 228 | "variable.other.constant.property", 229 | "meta.type.annotation", 230 | "support.type.property-name.css", 231 | "support.type.vendored", 232 | "constant.language.symbol.elixir", 233 | "variable.graphql", 234 | "meta.attribute.python", 235 | "source.dart" 236 | ], 237 | "settings": { 238 | "foreground": "#c17ac8" 239 | } 240 | }, 241 | { 242 | "name": "Accent7", 243 | "scope": [ 244 | "variable", 245 | "markup.list", 246 | "support.constant.property-value.css", 247 | "variable.parameter.keyframe-list.css", 248 | "source.css", 249 | "support.constant.font-name", 250 | "support.constant.vendored.property-value", 251 | "variable.parameter", 252 | "meta.class", 253 | "meta.method.declaration", 254 | "parameter.variable.function.elixir", 255 | "punctuation.definition.tag", 256 | "punctuation.section.embedded", 257 | "meta.embedded.expression", 258 | "punctuation.terminator.dart", 259 | "punctuation.dot.dart" 260 | ], 261 | "settings": { 262 | "foreground": "#bdbdbd" 263 | } 264 | }, 265 | { 266 | "name": "Accent8", 267 | "scope": [ 268 | "comment", 269 | "string.quoted.docstring.multi.python" 270 | ], 271 | "settings": { 272 | "foreground": "#6d6d6d" 273 | } 274 | }, 275 | { 276 | "name": "Accent31", 277 | "scope": [ 278 | "entity.name.function", 279 | "support.function" 280 | ], 281 | "settings": { 282 | "foreground": "#c7a06f" 283 | } 284 | }, 285 | { 286 | "name": "Accent32", 287 | "scope": [ 288 | "entity.name.type", 289 | "entity.name.class", 290 | "support.class.builtin", 291 | "punctuation.definition.template-expression.begin", 292 | "punctuation.definition.template-expression.end", 293 | "punctuation.quasi.element.begin", 294 | "punctuation.quasi.element.end", 295 | "entity.other.inherited-class", 296 | "variable.other.constant.elixir", 297 | "entity.other.attribute-name.class.css", 298 | "support.class.dart" 299 | ], 300 | "settings": { 301 | "foreground": "#6cb2c7" 302 | } 303 | }, 304 | { 305 | "name": "Italics", 306 | "scope": [ 307 | "meta.parameters", 308 | "meta.type.parameters", 309 | "meta.return.type", 310 | "entity.name.type.interface", 311 | "meta.type.annotation", 312 | "meta.function.parameters", 313 | "markup.italic.markdown" 314 | ], 315 | "settings": { 316 | "fontStyle": "italic" 317 | } 318 | }, 319 | { 320 | "name": "Markup Underline", 321 | "scope": "markup.underline", 322 | "settings": { 323 | "fontStyle": "underline" 324 | } 325 | }, 326 | { 327 | "name": "Bold", 328 | "scope": [ 329 | "markup.bold.markdown", 330 | "storage.type.annotation.dart" 331 | ], 332 | "settings": { 333 | "fontStyle": "bold" 334 | } 335 | } 336 | ] 337 | } -------------------------------------------------------------------------------- /docs/template.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: template 3 | hide_title: true 4 | --- 5 | 6 | 🟦 7 | 8 | --- 9 | -------------------------------------------------------------------------------- /docs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "astro/tsconfigs/strict" 3 | } 4 | -------------------------------------------------------------------------------- /docs/upgrade.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Upgrades Astro dependencies using npx. 4 | .DESCRIPTION 5 | This script runs the Astro upgrade tool to update project dependencies. 6 | .NOTES 7 | Requires Node.js and NPM to be installed. 8 | #> 9 | 10 | # Error handling preference 11 | $ErrorActionPreference = 'Stop' 12 | 13 | # Check if npm is installed 14 | if (!(Get-Command npm -ErrorAction SilentlyContinue)) { 15 | Write-Error "Node.js/NPM is not installed. Please install it first." 16 | exit 1 17 | } 18 | 19 | try { 20 | npx @astrojs/upgrade 21 | } catch { 22 | Write-Error "Failed to upgrade Astro: $_" 23 | exit 1 24 | } 25 | -------------------------------------------------------------------------------- /patches/double_conversion/3.3.1/patch: -------------------------------------------------------------------------------- 1 | --- double-conversion/CMakeLists.txt 2025-05-18 09:22:22.672636721 +0100 2 | +++ /home/username/CMakeLists.txt 2025-05-18 09:19:40.099991800 +0100 3 | @@ -1,4 +1,7 @@ 4 | -cmake_minimum_required(VERSION 3.0) 5 | +# This project likely works with older versions, such as 3.5, but that 6 | +# configuration is not tested. 7 | +# When changing the minimum required versions make sure to update the CI. 8 | +cmake_minimum_required(VERSION 3.15...4.0.1) 9 | project(double-conversion VERSION 3.3.0) 10 | 11 | option(BUILD_SHARED_LIBS "Build shared libraries (.dll/.so) instead of static ones (.lib/.a)" OFF) 12 | -------------------------------------------------------------------------------- /patches/libtorrent/2.0.4/patch: -------------------------------------------------------------------------------- 1 | From c7281a6d2fc2cbe34a567bdbe1f08a1fe89bd28a Mon Sep 17 00:00:00 2001 2 | From: arvidn 3 | Date: Thu, 19 Aug 2021 11:54:13 +0200 4 | Subject: [PATCH] bump handler allocation sizes for boost-1.77 (linux) 5 | 6 | --- 7 | include/libtorrent/aux_/allocating_handler.hpp | 10 +++++----- 8 | 1 file changed, 5 insertions(+), 5 deletions(-) 9 | 10 | diff --git a/include/libtorrent/aux_/allocating_handler.hpp b/include/libtorrent/aux_/allocating_handler.hpp 11 | index 9d826d11a1..b24349850e 100644 12 | --- a/include/libtorrent/aux_/allocating_handler.hpp 13 | +++ b/include/libtorrent/aux_/allocating_handler.hpp 14 | @@ -122,14 +122,14 @@ namespace libtorrent { namespace aux { 15 | constexpr std::size_t fuzzer_write_cost = 0; 16 | constexpr std::size_t fuzzer_read_cost = 0; 17 | #endif 18 | - constexpr std::size_t write_handler_max_size = tracking + debug_write_iter + openssl_write_cost + fuzzer_write_cost + 152; 19 | - constexpr std::size_t read_handler_max_size = tracking + debug_read_iter + openssl_read_cost + fuzzer_read_cost + 152; 20 | - constexpr std::size_t udp_handler_max_size = tracking + 144; 21 | - constexpr std::size_t utp_handler_max_size = tracking + 168; 22 | + constexpr std::size_t write_handler_max_size = tracking + debug_write_iter + openssl_write_cost + fuzzer_write_cost + 168; 23 | + constexpr std::size_t read_handler_max_size = tracking + debug_read_iter + openssl_read_cost + fuzzer_read_cost + 168; 24 | + constexpr std::size_t udp_handler_max_size = tracking + 160; 25 | + constexpr std::size_t utp_handler_max_size = tracking + 184; 26 | constexpr std::size_t abort_handler_max_size = tracking + 72; 27 | constexpr std::size_t submit_handler_max_size = tracking + 72; 28 | constexpr std::size_t deferred_handler_max_size = tracking + 80; 29 | - constexpr std::size_t tick_handler_max_size = tracking + 112; 30 | + constexpr std::size_t tick_handler_max_size = tracking + 128; 31 | #endif 32 | 33 | enum HandlerName -------------------------------------------------------------------------------- /patches/libtorrent/2.0.5/patch: -------------------------------------------------------------------------------- 1 | From dace24541cd35fe139c023be5bbc6eef98b4d229 Mon Sep 17 00:00:00 2001 2 | From: arvidn 3 | Date: Sun, 12 Dec 2021 21:52:15 +0100 4 | Subject: [PATCH] update allocator sizes for boost-1.78 5 | 6 | --- 7 | include/libtorrent/aux_/allocating_handler.hpp | 6 +++--- 8 | 1 file changed, 3 insertions(+), 3 deletions(-) 9 | 10 | diff --git a/include/libtorrent/aux_/allocating_handler.hpp b/include/libtorrent/aux_/allocating_handler.hpp 11 | index 726032e085c..560d738fa8b 100644 12 | --- a/include/libtorrent/aux_/allocating_handler.hpp 13 | +++ b/include/libtorrent/aux_/allocating_handler.hpp 14 | @@ -124,12 +124,12 @@ namespace libtorrent { namespace aux { 15 | #endif 16 | constexpr std::size_t write_handler_max_size = tracking + debug_write_iter + openssl_write_cost + fuzzer_write_cost + 168; 17 | constexpr std::size_t read_handler_max_size = tracking + debug_read_iter + openssl_read_cost + fuzzer_read_cost + 168; 18 | - constexpr std::size_t udp_handler_max_size = tracking + 160; 19 | - constexpr std::size_t utp_handler_max_size = tracking + 184; 20 | + constexpr std::size_t udp_handler_max_size = tracking + 168; 21 | + constexpr std::size_t utp_handler_max_size = tracking + 192; 22 | constexpr std::size_t abort_handler_max_size = tracking + 72; 23 | constexpr std::size_t submit_handler_max_size = tracking + 72; 24 | constexpr std::size_t deferred_handler_max_size = tracking + 80; 25 | - constexpr std::size_t tick_handler_max_size = tracking + 128; 26 | + constexpr std::size_t tick_handler_max_size = tracking + 136; 27 | #endif 28 | 29 | enum HandlerName -------------------------------------------------------------------------------- /patches/qbittorrent/4.4.3.1/patch: -------------------------------------------------------------------------------- 1 | --- qBittorrent/src/base/net/downloadhandlerimpl.cpp 2 | +++ /home/username/downloadhandlerimpl.cpp 3 | @@ -34,10 +34,13 @@ 4 | 5 | #include "base/3rdparty/expected.hpp" 6 | #include "base/utils/fs.h" 7 | -#include "base/utils/gzip.h" 8 | #include "base/utils/io.h" 9 | #include "base/utils/misc.h" 10 | 11 | +#ifdef QT_NO_COMPRESS 12 | +#include "base/utils/gzip.h" 13 | +#endif 14 | + 15 | const int MAX_REDIRECTIONS = 20; // the common value for web browsers 16 | 17 | namespace 18 | @@ -121,9 +124,13 @@ 19 | } 20 | 21 | // Success 22 | +#ifdef QT_NO_COMPRESS 23 | m_result.data = (m_reply->rawHeader("Content-Encoding") == "gzip") 24 | ? Utils::Gzip::decompress(m_reply->readAll()) 25 | : m_reply->readAll(); 26 | +#else 27 | + m_result.data = m_reply->readAll(); 28 | +#endif 29 | 30 | if (m_downloadRequest.saveToFile()) 31 | { 32 | --- qBittorrent/src/base/net/downloadmanager.cpp 33 | +++ /home/username/downloadmanager.cpp 34 | @@ -123,8 +123,12 @@ 35 | 36 | // Spoof HTTP Referer to allow adding torrent link from Torcache/KickAssTorrents 37 | request.setRawHeader("Referer", request.url().toEncoded().data()); 38 | - // Accept gzip 39 | +#ifdef QT_NO_COMPRESS 40 | + // The macro "QT_NO_COMPRESS" defined in QT will disable the zlib releated features 41 | + // and reply data auto-decompression in QT will also be disabled. But we can support 42 | + // gzip encoding and manually decompress the reply data. 43 | request.setRawHeader("Accept-Encoding", "gzip"); 44 | +#endif 45 | // Qt doesn't support Magnet protocol so we need to handle redirections manually 46 | request.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::ManualRedirectPolicy); 47 | 48 | -------------------------------------------------------------------------------- /patches/qbittorrent/4.4.4/patch: -------------------------------------------------------------------------------- 1 | From 034fc8aca914f073e5478a46ce9025c862902e72 Mon Sep 17 00:00:00 2001 2 | From: "Vladimir Golovnev (Glassez)" 3 | Date: Wed, 24 Aug 2022 15:28:30 +0300 4 | Subject: [PATCH] Fix missing trackers from magnet link 5 | 6 | --- 7 | src/base/bittorrent/session.cpp | 7 +++++++ 8 | 1 file changed, 7 insertions(+) 9 | 10 | diff --git a/src/base/bittorrent/session.cpp b/src/base/bittorrent/session.cpp 11 | index ece6f6ee8c1..c19d68348c9 100644 12 | --- a/src/base/bittorrent/session.cpp 13 | +++ b/src/base/bittorrent/session.cpp 14 | @@ -4915,7 +4915,14 @@ void Session::handleMetadataReceivedAlert(const lt::metadata_received_alert *p) 15 | 16 | if (downloadedMetadataIter != m_downloadedMetadata.end()) 17 | { 18 | +#if LIBTORRENT_VERSION_NUM >= 20007 19 | + lt::torrent_info nativeInfo = *p->handle.torrent_file(); 20 | + for (const lt::announce_entry &announceEntry : p->handle.trackers()) 21 | + nativeInfo.add_tracker(announceEntry.url, announceEntry.tier); 22 | + const TorrentInfo metadata {nativeInfo}; 23 | +#else 24 | const TorrentInfo metadata {*p->handle.torrent_file()}; 25 | +#endif 26 | 27 | m_downloadedMetadata.erase(downloadedMetadataIter); 28 | --m_extraLimit; 29 | -------------------------------------------------------------------------------- /patches/qbittorrent/4.5.1/patch: -------------------------------------------------------------------------------- 1 | From 3be5273246e9e399041db91892e3dbb281055076 Mon Sep 17 00:00:00 2001 2 | From: Vladimir Golovnev 3 | Date: Mon, 27 Feb 2023 09:08:18 +0300 4 | Subject: [PATCH 1/3] Prevent RSS folder from being moved into itself 5 | 6 | PR #18619. 7 | Closes #18446. 8 | --- 9 | src/base/rss/rss_session.cpp | 5 ++++- 10 | src/gui/rss/feedlistwidget.cpp | 10 ++++++---- 11 | 2 files changed, 10 insertions(+), 5 deletions(-) 12 | 13 | diff --git a/src/base/rss/rss_session.cpp b/src/base/rss/rss_session.cpp 14 | index bbc4d413d12..1d1ed81b1dd 100644 15 | --- a/src/base/rss/rss_session.cpp 16 | +++ b/src/base/rss/rss_session.cpp 17 | @@ -185,8 +185,11 @@ nonstd::expected Session::moveItem(Item *item, const QString &des 18 | if (!result) 19 | return result.get_unexpected(); 20 | 21 | - auto srcFolder = static_cast(m_itemsByPath.value(Item::parentPath(item->path()))); 22 | const auto destFolder = result.value(); 23 | + if (static_cast(destFolder) == item) 24 | + return nonstd::make_unexpected(tr("Couldn't move folder into itself.")); 25 | + 26 | + auto srcFolder = static_cast(m_itemsByPath.value(Item::parentPath(item->path()))); 27 | if (srcFolder != destFolder) 28 | { 29 | srcFolder->removeItem(item); 30 | diff --git a/src/gui/rss/feedlistwidget.cpp b/src/gui/rss/feedlistwidget.cpp 31 | index 8657dcca82e..428fd95463a 100644 32 | --- a/src/gui/rss/feedlistwidget.cpp 33 | +++ b/src/gui/rss/feedlistwidget.cpp 34 | @@ -105,7 +105,8 @@ FeedListWidget::FeedListWidget(QWidget *parent) 35 | m_rssToTreeItemMapping[RSS::Session::instance()->rootFolder()] = invisibleRootItem(); 36 | 37 | m_unreadStickyItem = new FeedListItem(this); 38 | - m_unreadStickyItem->setData(0, Qt::UserRole, QVariant::fromValue(RSS::Session::instance()->rootFolder())); 39 | + m_unreadStickyItem->setData(0, Qt::UserRole, QVariant::fromValue( 40 | + reinterpret_cast(RSS::Session::instance()->rootFolder()))); 41 | m_unreadStickyItem->setText(0, tr("Unread (%1)").arg(RSS::Session::instance()->rootFolder()->unreadCount())); 42 | m_unreadStickyItem->setData(0, Qt::DecorationRole, UIThemeManager::instance()->getIcon(u"mail-inbox"_qs)); 43 | m_unreadStickyItem->setData(0, StickyItemTagRole, true); 44 | @@ -211,9 +212,10 @@ QList FeedListWidget::getAllOpenedFolders(QTreeWidgetItem *pa 45 | 46 | RSS::Item *FeedListWidget::getRSSItem(QTreeWidgetItem *item) const 47 | { 48 | - if (!item) return nullptr; 49 | + if (!item) 50 | + return nullptr; 51 | 52 | - return item->data(0, Qt::UserRole).value(); 53 | + return reinterpret_cast(item->data(0, Qt::UserRole).value()); 54 | } 55 | 56 | QTreeWidgetItem *FeedListWidget::mapRSSItem(RSS::Item *rssItem) const 57 | @@ -275,7 +277,7 @@ QTreeWidgetItem *FeedListWidget::createItem(RSS::Item *rssItem, QTreeWidgetItem 58 | { 59 | auto *item = new FeedListItem; 60 | item->setData(0, Qt::DisplayRole, u"%1 (%2)"_qs.arg(rssItem->name(), QString::number(rssItem->unreadCount()))); 61 | - item->setData(0, Qt::UserRole, QVariant::fromValue(rssItem)); 62 | + item->setData(0, Qt::UserRole, QVariant::fromValue(reinterpret_cast(rssItem))); 63 | m_rssToTreeItemMapping[rssItem] = item; 64 | 65 | QIcon icon; 66 | 67 | From c21c3d230019431ab8f03faa3471474a66590c9c Mon Sep 17 00:00:00 2001 68 | From: Vladimir Golovnev 69 | Date: Mon, 27 Feb 2023 09:09:33 +0300 70 | Subject: [PATCH 2/3] WebAPI: Allow to set read-only directory as torrent 71 | location 72 | 73 | PR #18613. 74 | Closes #18480. 75 | --- 76 | src/webui/api/torrentscontroller.cpp | 4 ---- 77 | 1 file changed, 4 deletions(-) 78 | 79 | diff --git a/src/webui/api/torrentscontroller.cpp b/src/webui/api/torrentscontroller.cpp 80 | index 6ede337e5f0..6080febeae3 100644 81 | --- a/src/webui/api/torrentscontroller.cpp 82 | +++ b/src/webui/api/torrentscontroller.cpp 83 | @@ -1099,10 +1099,6 @@ void TorrentsController::setLocationAction() 84 | if (!Utils::Fs::mkpath(newLocation)) 85 | throw APIError(APIErrorType::Conflict, tr("Cannot make save path")); 86 | 87 | - // check permissions 88 | - if (!Utils::Fs::isWritable(newLocation)) 89 | - throw APIError(APIErrorType::AccessDenied, tr("Cannot write to directory")); 90 | - 91 | applyToTorrents(hashes, [newLocation](BitTorrent::Torrent *const torrent) 92 | { 93 | LogMsg(tr("WebUI Set location: moving \"%1\", from \"%2\" to \"%3\"") 94 | 95 | From 38c0864bf2119183e67fb7f2a1d5a8421f82b99f Mon Sep 17 00:00:00 2001 96 | From: Vladimir Golovnev 97 | Date: Mon, 27 Feb 2023 16:50:50 +0300 98 | Subject: [PATCH 3/3] Reject requests that contain backslash in path 99 | 100 | PR #18626. 101 | Closes #18618. 102 | --- 103 | src/webui/webapplication.cpp | 11 ++++++++--- 104 | 1 file changed, 8 insertions(+), 3 deletions(-) 105 | 106 | diff --git a/src/webui/webapplication.cpp b/src/webui/webapplication.cpp 107 | index f16e6e81220..629639e8a71 100644 108 | --- a/src/webui/webapplication.cpp 109 | +++ b/src/webui/webapplication.cpp 110 | @@ -151,9 +151,14 @@ WebApplication::~WebApplication() 111 | 112 | void WebApplication::sendWebUIFile() 113 | { 114 | - const QStringList pathItems {request().path.split(u'/', Qt::SkipEmptyParts)}; 115 | - if (pathItems.contains(u".") || pathItems.contains(u"..")) 116 | - throw InternalServerErrorHTTPError(); 117 | + if (request().path.contains(u'\\')) 118 | + throw BadRequestHTTPError(); 119 | + 120 | + if (const QList pathItems = QStringView(request().path).split(u'/', Qt::SkipEmptyParts) 121 | + ; pathItems.contains(u".") || pathItems.contains(u"..")) 122 | + { 123 | + throw BadRequestHTTPError(); 124 | + } 125 | 126 | const QString path = (request().path != u"/") 127 | ? request().path 128 | -------------------------------------------------------------------------------- /patches/qbittorrent/4.6.7/url: -------------------------------------------------------------------------------- 1 | https://github.com/qbittorrent/qBittorrent/commit/91943e4815ae40a273b39432340357a4ce879f3b.patch -------------------------------------------------------------------------------- /patches/qbittorrent/5.0.4/patch: -------------------------------------------------------------------------------- 1 | --- qBittorrent/src/base/http/types.h 2025-04-02 12:18:36.006314368 +0100 2 | +++ types.h 2025-03-03 09:24:36.686864000 +0000 3 | @@ -29,9 +29,12 @@ 4 | 5 | #pragma once 6 | 7 | +#include 8 | +#include 9 | #include 10 | +#include 11 | +#include 12 | #include 13 | -#include 14 | 15 | #include "base/global.h" 16 | 17 | @@ -57,6 +60,7 @@ 18 | inline const QString HEADER_X_CONTENT_TYPE_OPTIONS = u"x-content-type-options"_s; 19 | inline const QString HEADER_X_FORWARDED_FOR = u"x-forwarded-for"_s; 20 | inline const QString HEADER_X_FORWARDED_HOST = u"x-forwarded-host"_s; 21 | + inline const QString HEADER_X_FORWARDED_PROTO = u"X-forwarded-proto"_s; 22 | inline const QString HEADER_X_FRAME_OPTIONS = u"x-frame-options"_s; 23 | inline const QString HEADER_X_XSS_PROTECTION = u"x-xss-protection"_s; 24 | 25 | @@ -75,7 +79,7 @@ 26 | inline const QString CONTENT_TYPE_FORM_DATA = u"multipart/form-data"_s; 27 | 28 | // portability: "\r\n" doesn't guarantee mapping to the correct symbol 29 | - inline const char CRLF[] = {0x0D, 0x0A, '\0'}; 30 | + inline const QByteArray CRLF = QByteArrayLiteral("\x0D\x0A"); 31 | 32 | struct Environment 33 | { 34 | @@ -109,7 +113,7 @@ 35 | HeaderMap headers; 36 | QHash query; 37 | QHash posts; 38 | - QVector files; 39 | + QList files; 40 | }; 41 | 42 | struct ResponseStatus 43 | @@ -129,4 +133,4 @@ 44 | { 45 | } 46 | }; 47 | -} 48 | +} 49 | \ No newline at end of file 50 | -------------------------------------------------------------------------------- /patches/qtbase/6.7.0-beta1/url: -------------------------------------------------------------------------------- 1 | https://codereview.qt-project.org/gitweb?p=qt/qtbase.git;a=patch;h=72ee1df260d728a1e699bd4c6e03bf202c929cbd 2 | -------------------------------------------------------------------------------- /patches/qttools/6.7.2/patch: -------------------------------------------------------------------------------- 1 | From 8bb2a0c02b305f8ae8611e501fe7dd3d2b4468a6 Mon Sep 17 00:00:00 2001 2 | From: Joerg Bornemann 3 | Date: Tue, 11 Jun 2024 10:47:18 +0200 4 | Subject: [PATCH] CMake: Re-enable lupdate/lconvert/lrelease in no-gui builds 5 | 6 | This reverts 8dba0e48a0f7d3487b318a74f80f2d8e59c320f9 which disabled the 7 | 'linguist' feature if the 'printsupport' feature wasn't available. 8 | However, the 'linguist' feature controls not only the Qt Linguist 9 | application but also the command line tools lupdate, lconvert, and 10 | lrelease. In no-gui builds, which also disable printsupport, the command 11 | line tools were unexpectedly missing. 12 | 13 | Fix the issue by extending the feature condition in 14 | src/linguist/CMakeLists.txt. As drive-by, fix the FEATURE_png condition 15 | that was still in QMake form from the initial conversion. 16 | 17 | Fixes: QTBUG-126189 18 | Task-number: QTBUG-125066 19 | Change-Id: I59ebb82fd5823165b307ffbc967d7fd89a071ede 20 | Reviewed-by: Alexey Edelev 21 | Reviewed-by: Alexandru Croitor 22 | (cherry picked from commit 4be1823e4d459c89717e791ef27fd463ad04cb2b) 23 | Reviewed-by: Qt Cherry-pick Bot 24 | (cherry picked from commit aa9f8db49db2e7734c187445b8c3c56768f6e546) 25 | --- 26 | configure.cmake | 1 - 27 | src/linguist/CMakeLists.txt | 3 ++- 28 | 2 files changed, 2 insertions(+), 2 deletions(-) 29 | 30 | diff --git a/configure.cmake b/configure.cmake 31 | index 813789e9f7..7d9ab8724f 100644 32 | --- a/configure.cmake 33 | +++ b/configure.cmake 34 | @@ -74,7 +74,6 @@ qt_feature("kmap2qmap" PRIVATE 35 | qt_feature("linguist" PRIVATE 36 | LABEL "Qt Linguist" 37 | PURPOSE "Qt Linguist can be used by translator to translate text in Qt applications." 38 | - CONDITION TARGET Qt::PrintSupport 39 | ) 40 | qt_feature("pixeltool" PRIVATE 41 | LABEL "pixeltool" 42 | diff --git a/src/linguist/CMakeLists.txt b/src/linguist/CMakeLists.txt 43 | index ab2169dec5..20ec247337 100644 44 | --- a/src/linguist/CMakeLists.txt 45 | +++ b/src/linguist/CMakeLists.txt 46 | @@ -14,7 +14,8 @@ add_subdirectory(lrelease) 47 | add_subdirectory(lrelease-pro) 48 | add_subdirectory(lupdate) 49 | add_subdirectory(lupdate-pro) 50 | -if(QT_FEATURE_process AND QT_FEATURE_pushbutton AND QT_FEATURE_toolbutton AND TARGET Qt::Widgets AND NOT no-png) 51 | +if(QT_FEATURE_process AND QT_FEATURE_pushbutton AND QT_FEATURE_toolbutton 52 | + AND QT_FEATURE_png AND QT_FEATURE_printsupport AND TARGET Qt::Widgets) 53 | add_subdirectory(linguist) 54 | endif() 55 | 56 | -- 57 | 2.16.3 58 | 59 | -------------------------------------------------------------------------------- /patches/qttools/6.7.2/url: -------------------------------------------------------------------------------- 1 | https://codereview.qt-project.org/gitweb?p=qt/qttools.git;a=patch;h=8bb2a0c02b305f8ae8611e501fe7dd3d2b4468a6 -------------------------------------------------------------------------------- /zizmor.yml: -------------------------------------------------------------------------------- 1 | rules: 2 | unpinned-uses: # https://woodruffw.github.io/zizmor/audits/#unpinned-uses 3 | config: 4 | policies: 5 | "*": ref-pin 6 | --------------------------------------------------------------------------------