Compare commits
22 Commits
revert/fbq
...
1cef061e05
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1cef061e05 | ||
|
|
561ef230a9 | ||
|
|
e97b290d70 | ||
|
|
3cff4f015f | ||
|
|
8fe99bf9f7 | ||
|
|
b5002906a7 | ||
|
|
4a2d04144f | ||
|
|
5ced5d1554 | ||
|
|
164facc49f | ||
|
|
67b093681f | ||
|
|
bb4c74a734 | ||
|
|
29bc24ce71 | ||
|
|
138e3ca0d3 | ||
|
|
a85eac8c5f | ||
|
|
35f2041142 | ||
|
|
34eebba154 | ||
|
|
59690b157d | ||
|
|
020d0ca897 | ||
|
|
c8ca11604e | ||
|
|
0f5b646078 | ||
|
|
408eef8a0f | ||
|
|
0997c302ae |
BIN
.github/stargazer_map.png
vendored
|
Before Width: | Height: | Size: 404 KiB After Width: | Height: | Size: 64 KiB |
BIN
.github/stats.png
vendored
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 1.9 KiB |
BIN
.github/stats_addons.png
vendored
|
Before Width: | Height: | Size: 9.9 KiB After Width: | Height: | Size: 4.5 KiB |
2
.github/workflows/daily_ai_fix.yaml
vendored
@@ -125,7 +125,7 @@ jobs:
|
||||
|
||||
- name: Analyse and fix
|
||||
if: steps.batch.outputs.count != '0'
|
||||
uses: anthropics/claude-code-action@dcb57747bfceeaa1fa72638cae52295d1d853d4a # v1
|
||||
uses: anthropics/claude-code-action@a874e9ecd7bb36efdad65429c6b35815f5a08f10 # v1
|
||||
with:
|
||||
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
||||
# Skip the OIDC -> Claude App token exchange. The scheduled path
|
||||
|
||||
4
.github/workflows/lint.yml
vendored
@@ -38,7 +38,7 @@ jobs:
|
||||
run: |
|
||||
set -euo pipefail
|
||||
CHANGED_FILES=$(git diff --name-only "$DIFF_RANGE")
|
||||
UNICODE_SPACES_REGEX=$'[\\u00A0\\u2002\\u2003\\u2007\\u2008\\u2009\\u202F\\u205F\\u3000\\u200B]'
|
||||
UNICODE_SPACES_REGEX='[\x{00A0}\x{2002}\x{2003}\x{2007}\x{2008}\x{2009}\x{202F}\x{205F}\x{3000}\x{200B}]'
|
||||
for file in $CHANGED_FILES; do
|
||||
if [ -f "$file" ]; then
|
||||
MIME_TYPE=$(file --mime-type -b "$file")
|
||||
@@ -89,7 +89,7 @@ jobs:
|
||||
- name: Fix non-printable Unicode spaces in all text files
|
||||
run: |
|
||||
set -euo pipefail
|
||||
UNICODE_SPACES_REGEX=$'[\\u00A0\\u2002\\u2003\\u2007\\u2008\\u2009\\u202F\\u205F\\u3000\\u200B]'
|
||||
UNICODE_SPACES_REGEX='[\x{00A0}\x{2002}\x{2003}\x{2007}\x{2008}\x{2009}\x{202F}\x{205F}\x{3000}\x{200B}]'
|
||||
find . -type f ! -path "./.git/*" | while read -r file; do
|
||||
MIME_TYPE=$(file --mime-type -b "$file")
|
||||
if [[ "$MIME_TYPE" == text/* ]]; then
|
||||
|
||||
2
.github/workflows/on_claude_mention.yml
vendored
@@ -64,7 +64,7 @@ jobs:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Run Claude Code
|
||||
uses: anthropics/claude-code-action@dcb57747bfceeaa1fa72638cae52295d1d853d4a # v1
|
||||
uses: anthropics/claude-code-action@a874e9ecd7bb36efdad65429c6b35815f5a08f10 # v1
|
||||
with:
|
||||
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
||||
# AI_PR_TOKEN, not GITHUB_TOKEN, so a PR Claude opens triggers CI.
|
||||
|
||||
2
.github/workflows/on_issue_approved.yaml
vendored
@@ -135,7 +135,7 @@ jobs:
|
||||
|
||||
- name: Execute the plan
|
||||
if: steps.bundle.outputs.has_plan == 'true'
|
||||
uses: anthropics/claude-code-action@dcb57747bfceeaa1fa72638cae52295d1d853d4a # v1
|
||||
uses: anthropics/claude-code-action@a874e9ecd7bb36efdad65429c6b35815f5a08f10 # v1
|
||||
with:
|
||||
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
||||
# Skip the OIDC -> Claude App token exchange, which 401s whenever
|
||||
|
||||
31
.github/workflows/on_issues_ai_triage.yaml
vendored
@@ -166,7 +166,7 @@ jobs:
|
||||
id: classify
|
||||
if: github.event_name != 'issue_comment' || steps.claim.outputs.go == 'true'
|
||||
continue-on-error: true
|
||||
uses: anthropics/claude-code-action@dcb57747bfceeaa1fa72638cae52295d1d853d4a # v1
|
||||
uses: anthropics/claude-code-action@a874e9ecd7bb36efdad65429c6b35815f5a08f10 # v1
|
||||
with:
|
||||
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
||||
# Without this the action falls back to the OIDC -> Claude App token
|
||||
@@ -362,6 +362,25 @@ jobs:
|
||||
"$EXECUTION_FILE" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
# Did the run die because the Claude credential is bad? The action
|
||||
# reports this uselessly — a revoked token surfaces as "--json-schema
|
||||
# was provided but Claude did not return structured_output", which
|
||||
# points at the schema and not at auth. The execution file carries the
|
||||
# truth: api_retry / result objects with error "authentication_failed"
|
||||
# and a 401. Same array guard and fail-closed posture as above; an
|
||||
# unrecognised shape simply is not an auth failure and falls through
|
||||
# to the generic branch.
|
||||
hit_auth_failure() {
|
||||
[ -n "${EXECUTION_FILE:-}" ] && [ -s "${EXECUTION_FILE:-}" ] || return 1
|
||||
jq -e '(type == "array") and
|
||||
any(.[]?;
|
||||
(type == "object") and
|
||||
(((.error? // "") == "authentication_failed") or
|
||||
((.error_status? // 0) == 401) or
|
||||
((.api_error_status? // 0) == 401)))' \
|
||||
"$EXECUTION_FILE" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
# GATE 1 — did the action itself run? This is checked BEFORE looking
|
||||
# at the payload, because the action can fail *after* having written
|
||||
# a valid structured output: the object would sail through the shape
|
||||
@@ -380,6 +399,16 @@ jobs:
|
||||
if [ "${CLASSIFY_OUTCOME:-}" = "failure" ]; then
|
||||
restore_needs_info
|
||||
|
||||
# Checked before anything else, because it is the one failure with
|
||||
# a specific remedy and it takes down every tier at once — tier 1
|
||||
# cannot label, so tier 2's batch is empty and the whole pipeline
|
||||
# goes quiet while each run still fails in a way that reads like a
|
||||
# per-issue problem. Say plainly what is wrong and what to do.
|
||||
if hit_auth_failure; then
|
||||
echo "::error::CLAUDE_CODE_OAUTH_TOKEN is rejected (HTTP 401 / authentication_failed). This is NOT a problem with issue #$ISSUE — every AI workflow is down until the credential is replaced. Regenerate it with 'claude setup-token' and update the CLAUDE_CODE_OAUTH_TOKEN secret in the CR_PAT environment. Set the AI_DISABLED repo variable to 'true' to silence these runs meanwhile."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ...with one exception. Exhausting the turn budget is NOT a
|
||||
# workflow fault: the action ran fine and this particular issue was
|
||||
# just too tangled to finish inside the turn budget. Treating it as systemic
|
||||
|
||||
2
.github/workflows/on_pr_coderabbit.yml
vendored
@@ -79,7 +79,7 @@ jobs:
|
||||
|
||||
- name: Address CodeRabbit comments
|
||||
if: steps.claim.outputs.go == 'true'
|
||||
uses: anthropics/claude-code-action@dcb57747bfceeaa1fa72638cae52295d1d853d4a # v1
|
||||
uses: anthropics/claude-code-action@a874e9ecd7bb36efdad65429c6b35815f5a08f10 # v1
|
||||
with:
|
||||
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
||||
# Skip the OIDC -> Claude App token exchange, which 401s whenever
|
||||
|
||||
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 1.2 KiB |
BIN
aurral/stats.png
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -1,3 +1,10 @@
|
||||
## 0.12.1 (2026-09-03)
|
||||
|
||||
- Update to Baikal 0.12.1 from 0.10.1 (changelog : <https://github.com/sabre-io/Baikal/releases>). This includes the 0.12.1 fix for an XSS vulnerability that let an authenticated user take over the admin interface by renaming a calendar
|
||||
- ⚠ After the update, open the Baikal web admin once : Baikal asks to confirm the upgrade before it serves calendars again
|
||||
- The application is now taken from the release published by sabre-io instead of from the ckulka/baikal-docker image, which stopped at 0.10.1. The base image still provides nginx, php-fpm and msmtp. Automatic version tracking is enabled again, following sabre-io/Baikal
|
||||
- The Baikal application files in the addon data folder are now replaced on every start instead of being kept. Calendars, contacts, users and the Baikal configuration are untouched ; any manual edit made inside the application folders themselves is lost
|
||||
|
||||
- The Home Assistant project has deprecated support for the armv7, armhf and i386 architectures. Support wil be fully dropped in the upcoming Home Assistant 2025.12 release
|
||||
|
||||
## 0.10.1-hafix4 (2025-11-18)
|
||||
|
||||
@@ -16,7 +16,19 @@
|
||||
|
||||
ARG BUILD_FROM
|
||||
ARG BUILD_VERSION
|
||||
ARG BUILD_UPSTREAM="0.10.1+hafix"
|
||||
ARG BUILD_UPSTREAM="0.12.1"
|
||||
|
||||
# ckulka/baikal-docker, which builds the base image, stopped publishing new
|
||||
# Baikal versions at 0.10.1 : the base image is used for its runtime only
|
||||
# (nginx, php-fpm, msmtp) and the application comes from the release published
|
||||
# by sabre-io itself
|
||||
FROM alpine:3.21 AS baikal
|
||||
ARG BUILD_UPSTREAM
|
||||
RUN apk add --no-cache curl unzip \
|
||||
&& curl -f -s -S -L -o /tmp/baikal.zip "https://github.com/sabre-io/Baikal/releases/download/${BUILD_UPSTREAM}/baikal-${BUILD_UPSTREAM}.zip" \
|
||||
&& unzip -q /tmp/baikal.zip -d / \
|
||||
&& rm /tmp/baikal.zip
|
||||
|
||||
FROM ${BUILD_FROM}
|
||||
|
||||
##################
|
||||
@@ -28,6 +40,24 @@ ENV S6_CMD_WAIT_FOR_SERVICES=1 \
|
||||
S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0 \
|
||||
S6_SERVICES_GRACETIME=0
|
||||
|
||||
# Ship the Baikal release instead of the one bundled in the base image
|
||||
RUN rm -rf /var/www/baikal
|
||||
COPY --from=baikal --chown=nginx:nginx /baikal /var/www/baikal
|
||||
|
||||
# Home Assistant asks for an expanded time range, and Baikal stores
|
||||
# cal:calendar-timezone as a bare timezone name rather than as the VTIMEZONE
|
||||
# object sabre/dav expects, so sabre/dav raises a ParseException and answers
|
||||
# 500 (sabre-io/Baikal#1241 and sabre-io/dav#1318, both still open). Read the
|
||||
# value as a timezone name instead. The two checks turn a release that moved
|
||||
# this code into a failed build rather than into an addon that Home Assistant
|
||||
# cannot read.
|
||||
# hadolint ignore=SC2016
|
||||
RUN \
|
||||
DAVPLUGIN="/var/www/baikal/vendor/sabre/dav/lib/CalDAV/Plugin.php" \
|
||||
&& sed -i '/^ \/\/ This property contains a VCALENDAR with a single$/,/^ \$vtimezoneObj->destroy();$/c\ $calendarTimeZone = new DateTimeZone($tzResult[$tzProp]);' "$DAVPLUGIN" \
|
||||
&& grep -qxF ' $calendarTimeZone = new DateTimeZone($tzResult[$tzProp]);' "$DAVPLUGIN" \
|
||||
&& ! grep -qxF ' $calendarTimeZone = $vtimezoneObj->VTIMEZONE->getTimeZone();' "$DAVPLUGIN"
|
||||
|
||||
# Image specific modifications
|
||||
# hadolint ignore=SC2015, SC2013, SC2086
|
||||
RUN \
|
||||
|
||||
@@ -33,7 +33,9 @@ _Thanks to everyone having starred my repo! To star it click on the image below,
|
||||
---
|
||||
|
||||
[Baikal](https://sabre.io/baikal/) is a lightweight CalDAV+CardDAV server. It offers an extensive web interface with easy management of users, address books and calendars. It is fast and simple to install and only needs a basic php capable server. The data can be stored in a MySQL or a SQLite database.
|
||||
It is based on the docker image : https://github.com/ckulka/baikal-docker
|
||||
It ships the release published by [sabre-io](https://github.com/sabre-io/Baikal/releases), running on the nginx and php-fpm image built by <https://github.com/ckulka/baikal-docker>.
|
||||
|
||||
After an update of Baikal itself, open the web admin once : Baikal asks to confirm the upgrade before it serves calendars again. Calendars, contacts, users and the Baikal configuration are kept, but a manual edit made inside the application folders themselves is replaced on every start.
|
||||
|
||||
## Configuration
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"build_from": {
|
||||
"aarch64": "ghcr.io/mralucarddante/baikal-docker-hass:latest",
|
||||
"amd64": "ghcr.io/mralucarddante/baikal-docker-hass:latest"
|
||||
"aarch64": "ckulka/baikal:nginx-php8.2",
|
||||
"amd64": "ckulka/baikal:nginx-php8.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,5 +84,5 @@ schema:
|
||||
slug: baikal
|
||||
udev: true
|
||||
url: https://github.com/alexbelgium/hassio-addons
|
||||
version: 0.10.1-hafix4
|
||||
version: "0.12.1"
|
||||
webui: "[PROTO:ssl]://[HOST]:[PORT:80]"
|
||||
|
||||
@@ -1,7 +1,21 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Copy data
|
||||
cp -rnf /var/www/baikal/* /data/
|
||||
# Baikal keeps its database in Specific and its configuration in config. The
|
||||
# release ships both as empty folders, so they are created here rather than
|
||||
# copied, and are then left alone : they hold the user's data
|
||||
mkdir -p /data/config /data/Specific/db
|
||||
|
||||
# Everything else is application code, and is replaced on every start so that a
|
||||
# rebuilt image actually replaces the code that is served
|
||||
for item in /var/www/baikal/*; do
|
||||
name="$(basename "$item")"
|
||||
case "$name" in
|
||||
Specific | config) continue ;;
|
||||
esac
|
||||
rm -rf "/data/$name"
|
||||
cp -rf "$item" /data/
|
||||
done
|
||||
|
||||
# Fix permissions
|
||||
chown -R nginx:nginx /data
|
||||
|
||||
BIN
baikal/stats.png
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 1.7 KiB |
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"github_exclude": "+",
|
||||
"last_update": "26-04-2025",
|
||||
"github_beta": "false",
|
||||
"last_update": "2026-09-03",
|
||||
"repository": "alexbelgium/hassio-addons",
|
||||
"slug": "baikal",
|
||||
"source": "github",
|
||||
"upstream_repo": "ckulka/baikal-docker",
|
||||
"upstream_version": "0.10.1"
|
||||
"upstream_repo": "sabre-io/Baikal",
|
||||
"upstream_version": "0.12.1"
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 1.5 KiB |
BIN
bazarr/stats.png
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -1,7 +1,20 @@
|
||||
## 2.8.8 (03-09-2026)
|
||||
|
||||
- Now builds upstream's Simple Mode release instead of the standard one. It leaves out the bentopdf.com marketing pages (nav bar, hero, features, FAQ, footer). Both builds carry the same 130 tool pages and the same LibreOffice WebAssembly payload, so the served payload just gets smaller: about 228 MB, down from about 258 MB.
|
||||
- Breaking: you can no longer reach the marketing UI, and there is no way to bring it back.
|
||||
- Upstream BentoPDF is now v2.8.8: <https://github.com/alam00000/bentopdf/releases/tag/v2.8.8>
|
||||
- That includes the v2.8.7 security fixes (GHSA-wh78-rcw2-hhg9, GHSA-5xjf-rr5x-pcfj, GHSA-cx8x-7rrr-r9x8), which cover every version through v2.8.6
|
||||
- Version mismatch fixed. The image built upstream 2.8.2 while reporting 2.8.4; `ARG BUILD_VERSION` now matches `version`
|
||||
- Added `updater.json` so `addons_updater` now tracks upstream releases automatically
|
||||
|
||||
## 2.8.4 (24-04-2026)
|
||||
|
||||
- Minor bugs fixed
|
||||
|
||||
## 2.8.2 (07-04-2026)
|
||||
|
||||
- Minor bugs fixed
|
||||
|
||||
# Changelog
|
||||
|
||||
## 2.8.2
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
# Global build args — must be declared before the first FROM to be usable in FROM instructions
|
||||
ARG BUILD_FROM=ghcr.io/home-assistant/amd64-base:3.23
|
||||
ARG BUILD_VERSION=2.8.2
|
||||
ARG BUILD_VERSION=2.8.8
|
||||
# Upstream BentoPDF release to fetch. Tracked separately from BUILD_VERSION so
|
||||
# the add-on can carry a local patch counter (e.g. 2.8.8.1) without breaking the
|
||||
# release URLs, which only exist for real upstream tags.
|
||||
ARG BUILD_UPSTREAM=2.8.8
|
||||
|
||||
# Stage 1: Download and extract the BentoPDF dist release (includes bundled WASM)
|
||||
# Stage 1: Download and extract the BentoPDF Simple Mode dist release (includes
|
||||
# bundled WASM). Simple Mode drops the bentopdf.com marketing UI and keeps every
|
||||
# PDF tool, so it is the only build shipped here.
|
||||
FROM alpine:3.21 AS dist
|
||||
ARG BUILD_VERSION
|
||||
ARG BUILD_UPSTREAM
|
||||
# hadolint ignore=DL3018
|
||||
RUN apk add --no-cache curl unzip \
|
||||
&& curl -fsSL "https://github.com/alam00000/bentopdf/releases/download/v${BUILD_VERSION}/dist-${BUILD_VERSION}.zip" \
|
||||
&& curl -fsSL "https://github.com/alam00000/bentopdf/releases/download/v${BUILD_UPSTREAM}/dist-simple-${BUILD_UPSTREAM}.zip" \
|
||||
-o /tmp/bentopdf.zip \
|
||||
&& unzip /tmp/bentopdf.zip -d /tmp/dist
|
||||
|
||||
|
||||
@@ -104,6 +104,12 @@ A privacy-first PDF toolkit running entirely in your browser — no uploads, no
|
||||
|
||||
No other configuration is needed. Drop your files in and go.
|
||||
|
||||
### Simple Mode build
|
||||
|
||||
Upstream publishes two builds per release, and this add-on uses the Simple Mode one. It leaves out the bentopdf.com marketing pages: nav bar, hero, features, FAQ and footer.
|
||||
|
||||
You still get all 130 tool pages and the same LibreOffice WebAssembly payload as the standard build. Dropping those pages also cuts the served payload to about 228 MB, down from about 258 MB.
|
||||
|
||||
---
|
||||
|
||||
## Privacy
|
||||
|
||||
@@ -2,7 +2,7 @@ name: "BentoPDF"
|
||||
slug: bentopdf
|
||||
image: ghcr.io/alexbelgium/bentopdf-{arch}
|
||||
description: "Privacy-first PDF toolkit. 50+ tools, all processing client-side in the browser. Files never leave your device."
|
||||
version: "2.8.4"
|
||||
version: "2.8.8"
|
||||
url: "https://github.com/alexbelgium/hassio-addons/tree/master/bentopdf"
|
||||
arch:
|
||||
- amd64
|
||||
|
||||
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 1.3 KiB |
9
bentopdf/updater.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"last_update": "2026-09-03",
|
||||
"repository": "alexbelgium/hassio-addons",
|
||||
"slug": "bentopdf",
|
||||
"source": "github",
|
||||
"upstream_repo": "alam00000/bentopdf",
|
||||
"upstream_version": "2.8.8",
|
||||
"github_beta": false
|
||||
}
|
||||
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 1.8 KiB |
@@ -1,3 +1,13 @@
|
||||
## 20260901.4 (01-09-2026)
|
||||
- Minor bugs fixed
|
||||
## 20260901.3 (01-09-2026)
|
||||
- Rebuild: live spectrogram in Currently Hearing now uses the same SoX recipe, palette and 2:1 ratio as the detection spectrograms, with a kHz axis overlay (fork PR #61)
|
||||
## 20260901.2 (01-09-2026)
|
||||
- Rebuild: re-merges the open fork PRs, adding a static SoX spectrogram of the chunk being analysed to the Currently Hearing card (fork PR #61)
|
||||
## 20260901.1 (01-09-2026)
|
||||
- Minor bugs fixed
|
||||
## 20260901 (01-09-2026)
|
||||
- Synced with upstream birdnet-go (7 commits, incl. Go 1.27 upgrade); build image bumped to golang:1.27-trixie to match; resolved merge conflict in fork PR #6
|
||||
## 20260829.2 (29-08-2026)
|
||||
- Minor bugs fixed
|
||||
## 20260829.1 (29-08-2026)
|
||||
|
||||
@@ -89,7 +89,7 @@ RUN apk add --no-cache curl && \
|
||||
# 1a Build environment (mirrors tphakala/birdnet-go Docker/Dockerfile) #
|
||||
#########################################################################
|
||||
|
||||
FROM --platform=$BUILDPLATFORM golang:1.26-trixie AS buildenv
|
||||
FROM --platform=$BUILDPLATFORM golang:1.27-trixie AS buildenv
|
||||
ARG BUILD_VERSION
|
||||
ENV BUILD_VERSION=${BUILD_VERSION:-unknown}
|
||||
|
||||
|
||||
@@ -127,5 +127,5 @@ slug: birdnet-go-dev
|
||||
udev: true
|
||||
url: https://github.com/alexbelgium/hassio-addons
|
||||
usb: true
|
||||
version: "20260829.2"
|
||||
version: "20260901.4"
|
||||
video: true
|
||||
|
||||
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -1,4 +1,8 @@
|
||||
|
||||
## 0.6.27.3 (2026-08-30)
|
||||
- Doc: explain in the README that Calibre-Web's optional extras (metadata, kobo, gdrive, gmail, goodreads, ldap, oauth, comics) are already installed by the LinuxServer base image, that `pip install calibreweb[...]` inside the container is useless and not persistent, and that the cover fields on the Edit Metadata page are gated on `Enable Uploads` plus the user's `Upload` permission (https://github.com/alexbelgium/hassio-addons/issues/1143)
|
||||
- Fix: remove the Dockerfile step that claimed to install the Calibre binaries into `/opt/calibre`. There is no `wget` in the image, so the command failed silently and left the layer empty; the binaries are and were provided at start by the default `linuxserver/mods:universal-calibre` docker mod
|
||||
|
||||
## 0.6.27.2 (2026-08-23)
|
||||
- Fix: trust the whole supervisor network range for the ingress auth header instead of the addon's own address, which changes across restarts. The list is only written when that range is missing, so an entry added in the calibre-web admin page is no longer erased on every start (https://github.com/alexbelgium/hassio-addons/pull/3010)
|
||||
|
||||
|
||||
@@ -35,11 +35,9 @@ RUN \
|
||||
&& echo '#!/bin/sh' > /usr/bin/xdg-desktop-menu && chmod +x /usr/bin/xdg-desktop-menu \
|
||||
&& echo '#!/bin/sh' > /usr/bin/xdg-mime && chmod +x /usr/bin/xdg-mime
|
||||
|
||||
# Install calibre binaries (provides calibredb required for book downloads)
|
||||
# hadolint ignore=DL4006
|
||||
RUN \
|
||||
wget -nv -O- https://download.calibre-ebook.com/linux-installer.sh | sh /dev/stdin install_dir=/opt/calibre
|
||||
ENV PATH="/opt/calibre:${PATH}"
|
||||
# By default the calibre binaries (calibredb, ebook-convert, ebook-meta) are installed at start by
|
||||
# the linuxserver/mods:universal-calibre docker mod, set as the default DOCKER_MODS in config.yaml.
|
||||
# The xdg-* stubs above keep its calibre_postinstall step quiet.
|
||||
|
||||
# Global LSIO modifications
|
||||
COPY ha_lsio.sh /ha_lsio.sh
|
||||
|
||||
@@ -97,6 +97,18 @@ This addon supports mounting both local drives and remote SMB shares:
|
||||
- **Local drives**: See [Mounting Local Drives in Addons](https://github.com/alexbelgium/hassio-addons/wiki/Mounting-Local-Drives-in-Addons)
|
||||
- **Remote shares**: See [Mounting Remote Shares in Addons](https://github.com/alexbelgium/hassio-addons/wiki/Mounting-remote-shares-in-Addons)
|
||||
|
||||
### Optional Calibre-Web features
|
||||
|
||||
Calibre-Web documents optional extras that a manual installation adds with `pip install calibreweb[metadata]` and similar. **You do not need to install anything here**: the LinuxServer base image this add-on builds on installs Calibre-Web's `requirements.txt` *and* its full `optional-requirements.txt` into the application's virtualenv, so the gdrive, gmail, goodreads, ldap, oauth, metadata, comics and kobo dependencies are all present already. Running `pip install calibreweb[...]` inside the container is not a supported way to enable them: it installs the PyPI distribution of Calibre-Web over an installation that already has those dependencies, and it can disturb the versions the base image pinned. It is also thrown away, because the Supervisor recreates the add-on container on restart.
|
||||
|
||||
Optional features are switched on in the Calibre-Web web interface, not in the add-on options, under `Admin` -> `Basic Configuration` -> `Feature Configuration` (for example `Enable Uploads`, `Enable Kobo sync`, `Use Goodreads`).
|
||||
|
||||
**Book covers.** The `Fetch Cover from URL` and `Upload Cover from Local Disk` fields only appear on a book's `Edit Metadata` page when `Enable Uploads` is ticked in `Feature Configuration` **and** the logged-in user has the `Upload` permission (`Admin` -> the user -> `Upload`). A missing Python package is not what hides them.
|
||||
|
||||
**Conversion, metadata embedding and the other Calibre integrations** use command-line binaries such as `ebook-convert`, `ebook-meta` and `calibredb`. Those are installed at start by the `linuxserver/mods:universal-calibre` docker mod, which is the shipped default of the `DOCKER_MODS` option. If you set `DOCKER_MODS` yourself, keep `linuxserver/mods:universal-calibre` in the list (mods are separated by `|`) or those binaries disappear.
|
||||
|
||||
**Other compatible Python packages** can be installed from the add-on's custom script (see the section below); `pip` there points at Calibre-Web's own virtualenv. Such a script runs on every start, and it has to, since the container's writable layer does not persist.
|
||||
|
||||
### Custom Scripts and Environment Variables
|
||||
|
||||
This addon supports custom scripts and environment variables:
|
||||
|
||||
@@ -116,5 +116,5 @@ schema:
|
||||
slug: calibre-web
|
||||
udev: true
|
||||
url: https://github.com/alexbelgium/hassio-addons/tree/master/calibre_web
|
||||
version: "0.6.27.2"
|
||||
version: "0.6.27.3"
|
||||
video: true
|
||||
|
||||
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 1.4 KiB |
BIN
codex/stats.png
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 1.7 KiB |
BIN
emby/stats.png
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 1.7 KiB |
BIN
ente/stats.png
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 1.6 KiB |
@@ -1,4 +1,29 @@
|
||||
|
||||
## 1.5.3.3 (2026-08-31)
|
||||
- Complete the iOS companion app fix from 1.5.3.2. The "no preview available"
|
||||
screen -- what you get for a `.zip`, `.bin` or anything else FileBrowser
|
||||
cannot render -- offers its Download and "Open file" buttons as new-tab
|
||||
links, and so does the share list in settings. The app hands every new tab
|
||||
to an external browser, which carries no ingress session, so those answered
|
||||
401. Those two buttons and the settings share links now stay in the panel
|
||||
when running in the companion app, and open a new tab as before in a normal
|
||||
browser -- as does a cmd/ctrl/shift-click anywhere, which is left alone.
|
||||
Download also saves the file instead of displaying it, which 1.5.3.2 only
|
||||
fixed for the download button in the file list. Links the app opens without
|
||||
a link element, such as the public-share sidebar download, are still
|
||||
affected.
|
||||
|
||||
## 1.5.3.2 (2026-08-30)
|
||||
- Fix Download in the Home Assistant iOS companion app (iOS 17 and later),
|
||||
where a file opened and showed its content with no way to save it.
|
||||
FileBrowser downloads by clicking a link that carries no `download`
|
||||
attribute, and the app's WKWebView only turns a click into a real download
|
||||
when that attribute is present, so inside the ingress panel the file was
|
||||
simply rendered. The ingress filter now adds the attribute to FileBrowser's
|
||||
own download link. "Open file" still opens, and the public-share sidebar's
|
||||
own download button is not covered. Desktop browsers already downloaded
|
||||
these and are unchanged, as is direct access on port 8071.
|
||||
|
||||
## 1.5.3.1 (2026-08-29)
|
||||
- Fix "open parent directory" in Tools -> File Size Analyzer under Home
|
||||
Assistant ingress. FileBrowser opened the parent folder in a new tab, which
|
||||
|
||||
@@ -118,4 +118,4 @@ schema:
|
||||
slug: filebrowser_quantum
|
||||
udev: true
|
||||
url: https://github.com/alexbelgium/hassio-addons
|
||||
version: "1.5.3.1"
|
||||
version: "1.5.3.3"
|
||||
|
||||
@@ -13,34 +13,100 @@ server {
|
||||
proxy_read_timeout 30m;
|
||||
proxy_pass %%protocol%%://backend%%subpath%%;
|
||||
|
||||
# Tools -> File Size Analyzer (and the other tool views) open a result's
|
||||
# parent folder with window.open(<absolute url>, '_blank'), because
|
||||
# goToItem() takes its newTab argument from the context menu's
|
||||
# showLimitedOptions flag, which those views always set. Behind ingress
|
||||
# that popup lands on the raw /api/hassio_ingress/<token>/ url with no
|
||||
# Home Assistant frontend around it to keep the ingress session alive,
|
||||
# so the new tab answers 401 instead of showing the folder. Turn that
|
||||
# popup into a navigation of the panel itself.
|
||||
# Two things the ingress panel needs that a plain browser tab does not.
|
||||
# Both are injected into the page's existing nonce-carrying inline script
|
||||
# rather than next to <div id="app">: FileBrowser sends
|
||||
# script-src 'self' 'nonce-<random>', so a standalone inline <script>
|
||||
# would be blocked. If upstream ever drops that
|
||||
# window.__pwaDeferredPrompt line the filter stops matching and both
|
||||
# behaviours revert, which is the state before either fix.
|
||||
#
|
||||
# The context menu's "go to item" action, which search results and the
|
||||
# tool views also offer, hardcodes the same new tab and is fixed too.
|
||||
# 1. Opening a folder. The tool views (Tools -> File Size Analyzer and
|
||||
# the others) always set the context menu's showLimitedOptions flag, and
|
||||
# openParentFolder() hands that same flag to goToItem() as its newTab
|
||||
# argument, so the folder is opened with window.open(<url>, '_blank').
|
||||
# Behind ingress that popup lands on the raw /api/hassio_ingress/<token>/
|
||||
# url with no Home Assistant frontend around it to keep the ingress
|
||||
# session alive, so the new tab answers 401 instead of showing the
|
||||
# folder. Turn it into a navigation of the panel itself. The context
|
||||
# menu's "go to item" action, offered by search results and the tool
|
||||
# views, hardcodes the same new tab and is fixed with it.
|
||||
#
|
||||
# Scoped to the two prefixes goToItem() builds, "files/" and
|
||||
# "public/share/", so the window.open calls that download or preview a
|
||||
# file (they go to api/resources/download) keep their own tab: sending
|
||||
# an inline raw file to location.assign would replace the whole app.
|
||||
# A link out of the add-on keeps its own tab as well, unless a user
|
||||
# points a sidebar link (or a link inside a file open in the editor) at
|
||||
# this same instance's files/ or public/share/ route, which then also
|
||||
# opens in the panel. Same shape as the komga add-on's ingress filter.
|
||||
# an inline raw file to location.assign would replace the whole app. A
|
||||
# link out of the add-on keeps its own tab as well, unless a user points
|
||||
# a sidebar link -- or a link inside a file open in the editor -- at this
|
||||
# same instance's files/ or public/share/ route. Same shape as the komga
|
||||
# add-on's ingress filter.
|
||||
#
|
||||
# Injected into the page's existing nonce-carrying inline script rather
|
||||
# than next to <div id="app">: FileBrowser sends
|
||||
# script-src 'self' 'nonce-<random>', so a standalone inline <script>
|
||||
# would be blocked. If upstream ever drops that
|
||||
# window.__pwaDeferredPrompt line the filter simply stops matching and
|
||||
# the popup behaviour returns, which is the pre-fix state.
|
||||
sub_filter "window.__pwaDeferredPrompt = null;" "window.__pwaDeferredPrompt = null;(function(){var o=window.open;window.open=function(u,n,f){try{var b=(window.globalVars||{}).baseURL;if(u&&n==='_blank'&&!f&&b){if(b.slice(-1)!=='/')b+='/';var t=new URL(u,location.href);if((t.protocol==='http:'||t.protocol==='https:')&&t.origin===location.origin&&(t.pathname.indexOf(b+'files/')===0||t.pathname.indexOf(b+'public/share/')===0)){location.assign(t.href);return window}}}catch(e){}return o.apply(window,arguments)}})();";
|
||||
# 2. Saving and opening a file. FileBrowser downloads by clicking an <a>
|
||||
# that carries no download attribute -- a hidden one it builds itself
|
||||
# (api/resources.js), and two visible ones in the "no preview available"
|
||||
# fallback (views/files/Preview.vue), which are also target="_blank".
|
||||
# Neither works in the Home Assistant companion app:
|
||||
#
|
||||
# - A download happens in its WKWebView only when WebKit turns a
|
||||
# navigation *action* into a WKDownload, which is what the download
|
||||
# attribute does; the app hands that to its own download manager
|
||||
# (WebViewController+WebKitDelegates.swift, navigationAction:didBecome
|
||||
# download:, iOS 17+). Its response policy delegate returns .allow for
|
||||
# every sub-frame and never returns .download, so a plain attachment
|
||||
# navigation in the ingress panel is just rendered: the file opens and
|
||||
# shows its content with no way to save it.
|
||||
# - target="_blank" is worse. The app has no navigationAction policy
|
||||
# delegate, so every new-window request reaches createWebViewWith,
|
||||
# which hands the url to an external browser. That browser carries no
|
||||
# ingress session cookie, so Home Assistant answers 401.
|
||||
#
|
||||
# One capturing click listener covers both, and covers the hidden anchor
|
||||
# too: a programmatic .click() on an anchor that is in the document
|
||||
# dispatches through it exactly like a real one -- same event, button 0,
|
||||
# no modifiers -- and the capture phase runs before the link is followed.
|
||||
# It replaces an earlier wrapper around HTMLAnchorElement.prototype.click,
|
||||
# which reached the hidden anchor but not the two the user clicks. The
|
||||
# wrapper would also have caught a click on a *detached* anchor, which
|
||||
# this cannot; both of FileBrowser's download paths append theirs to the
|
||||
# body first (api/resources.js), so nothing is lost today.
|
||||
#
|
||||
# Only unmodified primary clicks are touched. A cmd/ctrl/shift-click is
|
||||
# an explicit request for a separate context and is left alone, which
|
||||
# matters on desktop and in the Mac Catalyst app.
|
||||
#
|
||||
# Downloads gain the attribute everywhere -- desktop browsers already
|
||||
# saved these on a plain click, and an empty value keeps the filename the
|
||||
# server sends in Content-Disposition. One behaviour does change there:
|
||||
# if the endpoint answers with an error the body is saved as a file
|
||||
# instead of being shown, because the decision is made before the
|
||||
# response exists. Matched on the two exact download endpoints minus
|
||||
# inline=true, which is the fallback's "Open file" link and is meant to
|
||||
# open rather than save. That branch drops target="_blank" in every
|
||||
# browser too: with the attribute present a same-origin link downloads
|
||||
# and never opens a tab (measured), so it changes nothing here, but it
|
||||
# stops the companion app from taking its new-window path before it
|
||||
# considers the download -- an ordering that cannot be tested from
|
||||
# outside iOS.
|
||||
#
|
||||
# Dropping target="_blank" from links that are *not* downloads is limited
|
||||
# to the companion app, identified by the Mobile/HomeAssistant marker it
|
||||
# appends to the user agent
|
||||
# (HAAPI.swift, applicationNameForUserAgent -- it covers iPhone, iPad and
|
||||
# Mac Catalyst). In a real browser a new tab is the better behaviour and
|
||||
# is left alone; in the app it is a 401. It applies to any same-origin
|
||||
# link below the add-on's own base path, which in practice is the
|
||||
# "Open file" button and the share links in settings
|
||||
# (views/settings/Shares.vue). Links to other origins keep their new tab,
|
||||
# and only an exact target="_blank" is matched, so named windows, _parent
|
||||
# and _top are untouched.
|
||||
#
|
||||
# Not covered, and still 401 in the app: anything the app opens with
|
||||
# window.open() rather than an anchor, which is the public-share sidebar
|
||||
# download and absolute sidebar links (components/sidebar/Links.vue); and
|
||||
# links inside a document FileBrowser renders in its own iframe -- the
|
||||
# pdf viewer, the srcdoc markdown/html preview, OnlyOffice -- because a
|
||||
# listener on this document never sees another document's clicks.
|
||||
sub_filter "window.__pwaDeferredPrompt = null;" "window.__pwaDeferredPrompt = null;(function(){var o=window.open;window.open=function(u,n,f){try{var b=(window.globalVars||{}).baseURL;if(u&&n==='_blank'&&!f&&b){if(b.slice(-1)!=='/')b+='/';var t=new URL(u,location.href);if((t.protocol==='http:'||t.protocol==='https:')&&t.origin===location.origin&&(t.pathname.indexOf(b+'files/')===0||t.pathname.indexOf(b+'public/share/')===0)){location.assign(t.href);return window}}}catch(e){}return o.apply(window,arguments)};document.addEventListener('click',function(e){try{if(e.button||e.metaKey||e.ctrlKey||e.shiftKey||e.altKey)return;var a=e.target&&e.target.closest?e.target.closest('a'):null;if(!a||!a.href)return;var b=(window.globalVars||{}).baseURL;if(!b)return;if(b.slice(-1)!=='/')b+='/';var t=new URL(a.href,location.href);if(t.origin!==location.origin)return;if(!a.hasAttribute('download')&&t.searchParams.get('inline')!=='true'&&(t.pathname===b+'api/resources/download'||t.pathname===b+'public/api/resources/download')){a.download='';a.removeAttribute('target');return}if(a.target==='_blank'&&t.pathname.indexOf(b)===0&&navigator.userAgent.indexOf('Mobile/HomeAssistant')!==-1){a.removeAttribute('target')}}catch(err){}},true)})();";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 1.6 KiB |
BIN
gitea/stats.png
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 1.5 KiB |
BIN
grav/stats.png
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 1.5 KiB |
BIN
immich/stats.png
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 1.4 KiB |
BIN
inadyn/stats.png
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 1.3 KiB |
BIN
joal/stats.png
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 1.6 KiB |
BIN
joplin/stats.png
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 1.6 KiB |
BIN
kometa/stats.png
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 1.4 KiB |
BIN
komga/stats.png
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 1.6 KiB |
BIN
lidarr/stats.png
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 1.4 KiB |
BIN
mealie/stats.png
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 1.5 KiB |
BIN
monica/stats.png
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 1.5 KiB |
BIN
mylar3/stats.png
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 1.4 KiB |