From d6cc447b7525adea811c6b0e110f0c9f198870e5 Mon Sep 17 00:00:00 2001 From: okxlin <61420215+okxlin@users.noreply.github.com> Date: Mon, 31 Aug 2026 17:19:02 +0800 Subject: [PATCH] Update this-week-in-past app Rebuilt-from-PR: #6301 Source-PR: https://github.com/okxlin/appstore/pull/6301 Maintainer-workflow: appstore-pr-maintainer --- apps/this-week-in-past/1.32.45/data.yml | 88 --------------- .../1.32.45/docker-compose.yml | 24 ---- .../this-week-in-past/1.32.45/scripts/init.sh | 64 ----------- .../{1.32.45 => 2.0.1}/.env.sample | 2 +- apps/this-week-in-past/2.0.1/data.yml | 105 ++++++++++++++++++ .../{latest => 2.0.1}/docker-compose.yml | 2 +- apps/this-week-in-past/2.0.1/scripts/init.sh | 84 ++++++++++++++ .../{1.32.45 => 2.0.1}/scripts/uninstall.sh | 0 .../{1.32.45 => 2.0.1}/scripts/upgrade.sh | 0 apps/this-week-in-past/data.yml | 39 ++++--- apps/this-week-in-past/latest/.env.sample | 6 - apps/this-week-in-past/latest/data.yml | 88 --------------- apps/this-week-in-past/latest/scripts/init.sh | 64 ----------- .../latest/scripts/uninstall.sh | 2 - .../latest/scripts/upgrade.sh | 2 - apps/this-week-in-past/logo.png | Bin 4434 -> 4436 bytes 16 files changed, 212 insertions(+), 358 deletions(-) delete mode 100644 apps/this-week-in-past/1.32.45/data.yml delete mode 100644 apps/this-week-in-past/1.32.45/docker-compose.yml delete mode 100755 apps/this-week-in-past/1.32.45/scripts/init.sh rename apps/this-week-in-past/{1.32.45 => 2.0.1}/.env.sample (73%) create mode 100644 apps/this-week-in-past/2.0.1/data.yml rename apps/this-week-in-past/{latest => 2.0.1}/docker-compose.yml (92%) create mode 100755 apps/this-week-in-past/2.0.1/scripts/init.sh rename apps/this-week-in-past/{1.32.45 => 2.0.1}/scripts/uninstall.sh (100%) rename apps/this-week-in-past/{1.32.45 => 2.0.1}/scripts/upgrade.sh (100%) delete mode 100644 apps/this-week-in-past/latest/.env.sample delete mode 100644 apps/this-week-in-past/latest/data.yml delete mode 100755 apps/this-week-in-past/latest/scripts/init.sh delete mode 100755 apps/this-week-in-past/latest/scripts/uninstall.sh delete mode 100755 apps/this-week-in-past/latest/scripts/upgrade.sh diff --git a/apps/this-week-in-past/1.32.45/data.yml b/apps/this-week-in-past/1.32.45/data.yml deleted file mode 100644 index 8ef51797b..000000000 --- a/apps/this-week-in-past/1.32.45/data.yml +++ /dev/null @@ -1,88 +0,0 @@ -additionalProperties: - formFields: - - default: 40829 - edit: true - envKey: PANEL_APP_PORT_HTTP - labelEn: Web Port - labelZh: Web 端口 - label: - en: Web Port - zh: Web 端口 - zh-Hant: Web 連接埠 - ja: Web ポート - ko: Web 포트 - ru: Веб-порт - ms: Port Web - pt-br: Porta Web - required: true - rule: paramPort - type: number - - default: ./data/photos - edit: true - envKey: PHOTO_LIBRARY_PATH - labelEn: Photo Library Directory - labelZh: 照片库目录 - label: - en: Photo Library Directory - zh: 照片库目录 - zh-Hant: 相片庫目錄 - ja: 写真ライブラリーディレクトリ - ko: 사진 라이브러리 디렉터리 - ru: Каталог фототеки - ms: Direktori Pustaka Foto - pt-br: Diretorio da biblioteca de fotos - required: true - type: text - - default: ./data/app - disabled: true - envKey: APP_DATA_DIR - labelEn: Application Data Directory - labelZh: 应用数据目录 - label: - en: Application Data Directory - zh: 应用数据目录 - zh-Hant: 應用程式資料目錄 - ja: アプリケーションデータディレクトリ - ko: 애플리케이션 데이터 디렉터리 - ru: Каталог данных приложения - ms: Direktori Data Aplikasi - pt-br: Diretorio de dados do aplicativo - required: true - type: text - - default: 30 - edit: true - envKey: SLIDESHOW_INTERVAL - labelEn: Slideshow Interval (seconds) - labelZh: 幻灯片间隔(秒) - label: - en: Slideshow Interval (seconds) - zh: 幻灯片间隔(秒) - zh-Hant: 幻燈片間隔(秒) - ja: スライドショー間隔(秒) - ko: 슬라이드쇼 간격(초) - ru: Интервал слайд-шоу (секунды) - ms: Selang Tayangan Slaid (saat) - pt-br: Intervalo da apresentacao (segundos) - required: true - type: number - - default: "false" - edit: true - envKey: RANDOM_SLIDESHOW - labelEn: Random Slideshow - labelZh: 随机幻灯片 - label: - en: Random Slideshow - zh: 随机幻灯片 - zh-Hant: 隨機幻燈片 - ja: ランダムスライドショー - ko: 무작위 슬라이드쇼 - ru: Случайное слайд-шоу - ms: Tayangan Slaid Rawak - pt-br: Apresentacao aleatoria - required: true - type: select - values: - - label: "false" - value: "false" - - label: "true" - value: "true" diff --git a/apps/this-week-in-past/1.32.45/docker-compose.yml b/apps/this-week-in-past/1.32.45/docker-compose.yml deleted file mode 100644 index 467b0e16d..000000000 --- a/apps/this-week-in-past/1.32.45/docker-compose.yml +++ /dev/null @@ -1,24 +0,0 @@ -services: - this-week-in-past: - image: "rouhim/this-week-in-past:1.32.45" - container_name: ${CONTAINER_NAME} - restart: unless-stopped - environment: - - RESOURCE_PATHS=/resources - - DATA_FOLDER=/data - - PORT=8080 - - SLIDESHOW_INTERVAL=${SLIDESHOW_INTERVAL} - - RANDOM_SLIDESHOW=${RANDOM_SLIDESHOW} - ports: - - "${PANEL_APP_PORT_HTTP}:8080" - volumes: - - "${PHOTO_LIBRARY_PATH}:/resources:ro" - - "${APP_DATA_DIR}:/data" - labels: - createdBy: "Apps" - networks: - - 1panel-network - -networks: - 1panel-network: - external: true diff --git a/apps/this-week-in-past/1.32.45/scripts/init.sh b/apps/this-week-in-past/1.32.45/scripts/init.sh deleted file mode 100755 index aa17d67d3..000000000 --- a/apps/this-week-in-past/1.32.45/scripts/init.sh +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)" -ENV_FILE="${ENV_FILE:-$ROOT_DIR/.env}" - -fail() { - printf '%s\n' "$1" >&2 - exit 1 -} - -read_env_value() { - local key="$1" - local value - [[ -f "$ENV_FILE" ]] || return 0 - value="$(sed -n "s/^${key}=//p" "$ENV_FILE" | tail -n 1)" - case "$value" in - \"*\") value="${value#\"}"; value="${value%\"}" ;; - \'*\') value="${value#\'}"; value="${value%\'}" ;; - esac - printf '%s\n' "$value" -} - -configured_value() { - local key="$1" - local default_value="$2" - local value="${!key:-}" - if [[ -z "$value" ]]; then - value="$(read_env_value "$key")" - fi - printf '%s\n' "${value:-$default_value}" -} - -photo_path="$(configured_value PHOTO_LIBRARY_PATH ./data/photos)" -[[ -n "$photo_path" ]] || fail "PHOTO_LIBRARY_PATH must not be empty" -if [[ "$photo_path" = /* ]]; then - resolved_photo_path="$(realpath -m -- "$photo_path")" -else - resolved_photo_path="$(realpath -m -- "$ROOT_DIR/${photo_path#./}")" - case "$resolved_photo_path" in - "$ROOT_DIR"/*) ;; - *) fail "relative PHOTO_LIBRARY_PATH must remain inside the application version directory" ;; - esac -fi -mkdir -p -- "$resolved_photo_path" -[[ -d "$resolved_photo_path" ]] || fail "PHOTO_LIBRARY_PATH must resolve to a directory" - -data_path="$(configured_value APP_DATA_DIR ./data/app)" -[[ -n "$data_path" ]] || fail "APP_DATA_DIR must not be empty" -[[ "$data_path" != /* ]] || fail "APP_DATA_DIR must be relative to the application version directory" -resolved_data_path="$(realpath -m -- "$ROOT_DIR/${data_path#./}")" -case "$resolved_data_path" in - "$ROOT_DIR"/*) ;; - *) fail "APP_DATA_DIR must remain inside the application version directory" ;; -esac -[[ ! -L "$resolved_data_path" ]] || fail "APP_DATA_DIR must not be a symbolic link" -install -d -m 0750 -- "$resolved_data_path" -resolved_data_path="$(realpath -e -- "$resolved_data_path")" -case "$resolved_data_path" in - "$ROOT_DIR"/*) ;; - *) fail "APP_DATA_DIR resolves outside the application version directory" ;; -esac -chown -R --no-dereference 1337:1337 "$resolved_data_path" -chmod 0750 "$resolved_data_path" diff --git a/apps/this-week-in-past/1.32.45/.env.sample b/apps/this-week-in-past/2.0.1/.env.sample similarity index 73% rename from apps/this-week-in-past/1.32.45/.env.sample rename to apps/this-week-in-past/2.0.1/.env.sample index 508d372f7..f6f717b9f 100644 --- a/apps/this-week-in-past/1.32.45/.env.sample +++ b/apps/this-week-in-past/2.0.1/.env.sample @@ -1,6 +1,6 @@ +CONTAINER_NAME=this-week-in-past-compose-check PANEL_APP_PORT_HTTP=40829 PHOTO_LIBRARY_PATH=./data/photos APP_DATA_DIR=./data/app SLIDESHOW_INTERVAL=30 RANDOM_SLIDESHOW=false -CONTAINER_NAME=this-week-in-past diff --git a/apps/this-week-in-past/2.0.1/data.yml b/apps/this-week-in-past/2.0.1/data.yml new file mode 100644 index 000000000..c9fe7da6b --- /dev/null +++ b/apps/this-week-in-past/2.0.1/data.yml @@ -0,0 +1,105 @@ +additionalProperties: + formFields: + - default: 40829 + edit: true + envKey: PANEL_APP_PORT_HTTP + labelEn: Web Port + labelZh: Web 端口 + label: + en: Web Port + zh: Web 端口 + zh-Hant: Web 連接埠 + ja: Web ポート + ko: Web 포트 + ru: Веб-порт + ms: Port Web + pt-br: Porta Web + required: true + rule: paramPort + type: number + - default: ./data/photos + edit: true + envKey: PHOTO_LIBRARY_PATH + labelEn: Photo Library Directory + labelZh: 照片库目录 + label: + en: Photo Library Directory + zh: 照片库目录 + zh-Hant: 相片庫目錄 + ja: 写真ライブラリーディレクトリ + ko: 사진 라이브러리 디렉터리 + ru: Каталог фототеки + ms: Direktori Pustaka Foto + pt-br: Diretorio da biblioteca de fotos + required: true + type: text + - default: ./data/app + disabled: true + envKey: APP_DATA_DIR + labelEn: Application Data Directory + labelZh: 应用数据目录 + label: + en: Application Data Directory + zh: 应用数据目录 + zh-Hant: 應用程式資料目錄 + ja: アプリケーションデータディレクトリ + ko: 애플리케이션 데이터 디렉터리 + ru: Каталог данных приложения + ms: Direktori Data Aplikasi + pt-br: Diretorio de dados do aplicativo + required: true + type: text + edit: true + - default: 30 + edit: true + envKey: SLIDESHOW_INTERVAL + labelEn: Slideshow Interval (seconds) + labelZh: 幻灯片间隔(秒) + label: + en: Slideshow Interval (seconds) + zh: 幻灯片间隔(秒) + zh-Hant: 幻燈片間隔(秒) + ja: スライドショー間隔(秒) + ko: 슬라이드쇼 간격(초) + ru: Интервал слайд-шоу (секунды) + ms: Selang Tayangan Slaid (saat) + pt-br: Intervalo da apresentacao (segundos) + required: true + type: number + - default: 'false' + edit: true + envKey: RANDOM_SLIDESHOW + labelEn: Random Slideshow + labelZh: 随机幻灯片 + label: + en: Random Slideshow + zh: 随机幻灯片 + zh-Hant: 隨機幻燈片 + ja: ランダムスライドショー + ko: 무작위 슬라이드쇼 + ru: Случайное слайд-шоу + ms: Tayangan Slaid Rawak + pt-br: Apresentacao aleatoria + required: true + type: select + values: + - label: 'false' + value: 'false' + - label: 'true' + value: 'true' + - default: Asia/Shanghai + edit: true + envKey: TZ + labelEn: Timezone + labelZh: 时区 + label: + en: Timezone + zh: 时区 + zh-Hant: 時區 + ja: タイムゾーン + ko: 시간대 + ru: Часовой пояс + ms: Zon waktu + pt-br: Fuso horário + required: true + type: text diff --git a/apps/this-week-in-past/latest/docker-compose.yml b/apps/this-week-in-past/2.0.1/docker-compose.yml similarity index 92% rename from apps/this-week-in-past/latest/docker-compose.yml rename to apps/this-week-in-past/2.0.1/docker-compose.yml index 96a817884..4a3171951 100644 --- a/apps/this-week-in-past/latest/docker-compose.yml +++ b/apps/this-week-in-past/2.0.1/docker-compose.yml @@ -1,6 +1,6 @@ services: this-week-in-past: - image: "rouhim/this-week-in-past:latest" + image: "rouhim/this-week-in-past:2.0.1" container_name: ${CONTAINER_NAME} restart: unless-stopped environment: diff --git a/apps/this-week-in-past/2.0.1/scripts/init.sh b/apps/this-week-in-past/2.0.1/scripts/init.sh new file mode 100755 index 000000000..e86cb374a --- /dev/null +++ b/apps/this-week-in-past/2.0.1/scripts/init.sh @@ -0,0 +1,84 @@ +#!/usr/bin/env bash +set -euo pipefail +PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +export PATH + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)" +ENV_FILE="${ENV_FILE:-$ROOT_DIR/.env}" + +fail() { + printf '%s\n' "$1" >&2 + exit 1 +} + +read_env_value() { + local key="$1" + [[ -f "$ENV_FILE" ]] || return 0 + local value + value="$(sed -n "s/^${key}=//p" "$ENV_FILE" | tail -n 1)" + case "$value" in + \"*\") value="${value#\"}"; value="${value%\"}" ;; + \'*\') value="${value#\'}"; value="${value%\'}" ;; + esac + printf '%s\n' "$value" +} + +configured_value() { + local key="$1" + local default_value="$2" + local value + value="${!key:-}" + if [[ -z "$value" ]]; then + value="$(read_env_value "$key")" + fi + printf '%s\n' "${value:-$default_value}" +} + +resolve_app_path() { + local key="$1" + local raw="$2" + local clean candidate resolved current part + local -a parts=() + case "$raw" in + ""|/*|.|..|../*|*/../*|*/..) echo "unsafe ${key} path" >&2; return 1 ;; + esac + if [[ "$raw" =~ [[:cntrl:]] ]]; then + echo "unsafe ${key} path" >&2 + return 1 + fi + clean="${raw#./}" + [[ -n "$clean" ]] || { echo "unsafe ${key} path" >&2; return 1; } + command -v realpath >/dev/null 2>&1 || { echo "realpath is required" >&2; return 1; } + candidate="$ROOT_DIR/$clean" + resolved="$(realpath -m -- "$candidate")" || { echo "unsafe ${key} path" >&2; return 1; } + case "$resolved" in + "$ROOT_DIR"/*) ;; + *) echo "unsafe ${key} path" >&2; return 1 ;; + esac + current="$ROOT_DIR" + IFS='/' read -r -a parts <<< "$clean" + for part in "${parts[@]}"; do + [[ -z "$part" || "$part" == "." ]] && continue + current="$current/$part" + if [[ -L "$current" ]]; then + echo "unsafe ${key} path" >&2 + return 1 + fi + done + printf '%s\n' "$resolved" +} + +ensure_dir() { + local key="$1" + local default_value="$2" + local raw path + raw="$(configured_value "$key" "$default_value")" + path="$(resolve_app_path "$key" "$raw")" + mkdir -p -- "$path" + [[ "$(resolve_app_path "$key" "$raw")" == "$path" ]] || fail "unsafe ${key} path" + chmod 0750 "$path" + chown -R --no-dereference 1337:1337 "$path" +} + +ensure_dir "PHOTO_LIBRARY_PATH" "./data/photos" +ensure_dir "APP_DATA_DIR" "./data/app" diff --git a/apps/this-week-in-past/1.32.45/scripts/uninstall.sh b/apps/this-week-in-past/2.0.1/scripts/uninstall.sh similarity index 100% rename from apps/this-week-in-past/1.32.45/scripts/uninstall.sh rename to apps/this-week-in-past/2.0.1/scripts/uninstall.sh diff --git a/apps/this-week-in-past/1.32.45/scripts/upgrade.sh b/apps/this-week-in-past/2.0.1/scripts/upgrade.sh similarity index 100% rename from apps/this-week-in-past/1.32.45/scripts/upgrade.sh rename to apps/this-week-in-past/2.0.1/scripts/upgrade.sh diff --git a/apps/this-week-in-past/data.yml b/apps/this-week-in-past/data.yml index a189a5d60..960fcde12 100644 --- a/apps/this-week-in-past/data.yml +++ b/apps/this-week-in-past/data.yml @@ -1,33 +1,36 @@ name: This Week in Past tags: - - 多媒体 +- Media title: 展示往年本周照片的自托管幻灯片 description: 展示往年本周照片的自托管幻灯片 additionalProperties: key: this-week-in-past name: This Week in Past tags: - - Media + - Media + type: website + website: https://github.com/RouHim/this-week-in-past + document: https://github.com/RouHim/this-week-in-past/blob/1cbf1e33bc96810d14549daf19e62ac0ecf9eb5d/README.md + github: https://github.com/RouHim/this-week-in-past shortDescZh: 展示往年本周照片的自托管幻灯片 shortDescEn: A self-hosted slideshow of photos taken this week in previous years + crossVersionUpdate: true + limit: 0 + architectures: + - amd64 + - arm64 + - armv7 + - armv6 description: - en: A self-hosted slideshow that finds and displays photos taken during this week in previous years. + en: A self-hosted slideshow that finds and displays photos taken during this week + in previous years. zh: 自托管照片幻灯片,用于查找并展示往年同一周拍摄的照片。 zh-Hant: 自託管相片幻燈片,用於尋找並展示往年同一週拍攝的相片。 ja: 過去の同じ週に撮影した写真を探して表示するセルフホスト型スライドショーです。 ko: 지난 여러 해의 같은 주에 촬영한 사진을 찾아 보여 주는 자체 호스팅 슬라이드쇼입니다. - ru: Самостоятельно размещаемое слайд-шоу из фотографий, снятых на этой неделе в прошлые годы. - ms: Tayangan slaid hos sendiri yang memaparkan foto yang diambil pada minggu ini dalam tahun-tahun lalu. - pt-br: Apresentacao de slides auto-hospedada com fotos tiradas nesta semana em anos anteriores. - type: website - crossVersionUpdate: true - limit: 0 - recommend: 0 - website: https://github.com/RouHim/this-week-in-past - github: https://github.com/RouHim/this-week-in-past - document: https://github.com/RouHim/this-week-in-past/blob/1cbf1e33bc96810d14549daf19e62ac0ecf9eb5d/README.md - architectures: - - amd64 - - arm64 - - armv7 - - armv6 + ru: Самостоятельно размещаемое слайд-шоу из фотографий, снятых на этой неделе + в прошлые годы. + ms: Tayangan slaid hos sendiri yang memaparkan foto yang diambil pada minggu ini + dalam tahun-tahun lalu. + pt-br: Apresentacao de slides auto-hospedada com fotos tiradas nesta semana em + anos anteriores. diff --git a/apps/this-week-in-past/latest/.env.sample b/apps/this-week-in-past/latest/.env.sample deleted file mode 100644 index 508d372f7..000000000 --- a/apps/this-week-in-past/latest/.env.sample +++ /dev/null @@ -1,6 +0,0 @@ -PANEL_APP_PORT_HTTP=40829 -PHOTO_LIBRARY_PATH=./data/photos -APP_DATA_DIR=./data/app -SLIDESHOW_INTERVAL=30 -RANDOM_SLIDESHOW=false -CONTAINER_NAME=this-week-in-past diff --git a/apps/this-week-in-past/latest/data.yml b/apps/this-week-in-past/latest/data.yml deleted file mode 100644 index 8ef51797b..000000000 --- a/apps/this-week-in-past/latest/data.yml +++ /dev/null @@ -1,88 +0,0 @@ -additionalProperties: - formFields: - - default: 40829 - edit: true - envKey: PANEL_APP_PORT_HTTP - labelEn: Web Port - labelZh: Web 端口 - label: - en: Web Port - zh: Web 端口 - zh-Hant: Web 連接埠 - ja: Web ポート - ko: Web 포트 - ru: Веб-порт - ms: Port Web - pt-br: Porta Web - required: true - rule: paramPort - type: number - - default: ./data/photos - edit: true - envKey: PHOTO_LIBRARY_PATH - labelEn: Photo Library Directory - labelZh: 照片库目录 - label: - en: Photo Library Directory - zh: 照片库目录 - zh-Hant: 相片庫目錄 - ja: 写真ライブラリーディレクトリ - ko: 사진 라이브러리 디렉터리 - ru: Каталог фототеки - ms: Direktori Pustaka Foto - pt-br: Diretorio da biblioteca de fotos - required: true - type: text - - default: ./data/app - disabled: true - envKey: APP_DATA_DIR - labelEn: Application Data Directory - labelZh: 应用数据目录 - label: - en: Application Data Directory - zh: 应用数据目录 - zh-Hant: 應用程式資料目錄 - ja: アプリケーションデータディレクトリ - ko: 애플리케이션 데이터 디렉터리 - ru: Каталог данных приложения - ms: Direktori Data Aplikasi - pt-br: Diretorio de dados do aplicativo - required: true - type: text - - default: 30 - edit: true - envKey: SLIDESHOW_INTERVAL - labelEn: Slideshow Interval (seconds) - labelZh: 幻灯片间隔(秒) - label: - en: Slideshow Interval (seconds) - zh: 幻灯片间隔(秒) - zh-Hant: 幻燈片間隔(秒) - ja: スライドショー間隔(秒) - ko: 슬라이드쇼 간격(초) - ru: Интервал слайд-шоу (секунды) - ms: Selang Tayangan Slaid (saat) - pt-br: Intervalo da apresentacao (segundos) - required: true - type: number - - default: "false" - edit: true - envKey: RANDOM_SLIDESHOW - labelEn: Random Slideshow - labelZh: 随机幻灯片 - label: - en: Random Slideshow - zh: 随机幻灯片 - zh-Hant: 隨機幻燈片 - ja: ランダムスライドショー - ko: 무작위 슬라이드쇼 - ru: Случайное слайд-шоу - ms: Tayangan Slaid Rawak - pt-br: Apresentacao aleatoria - required: true - type: select - values: - - label: "false" - value: "false" - - label: "true" - value: "true" diff --git a/apps/this-week-in-past/latest/scripts/init.sh b/apps/this-week-in-past/latest/scripts/init.sh deleted file mode 100755 index aa17d67d3..000000000 --- a/apps/this-week-in-past/latest/scripts/init.sh +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)" -ENV_FILE="${ENV_FILE:-$ROOT_DIR/.env}" - -fail() { - printf '%s\n' "$1" >&2 - exit 1 -} - -read_env_value() { - local key="$1" - local value - [[ -f "$ENV_FILE" ]] || return 0 - value="$(sed -n "s/^${key}=//p" "$ENV_FILE" | tail -n 1)" - case "$value" in - \"*\") value="${value#\"}"; value="${value%\"}" ;; - \'*\') value="${value#\'}"; value="${value%\'}" ;; - esac - printf '%s\n' "$value" -} - -configured_value() { - local key="$1" - local default_value="$2" - local value="${!key:-}" - if [[ -z "$value" ]]; then - value="$(read_env_value "$key")" - fi - printf '%s\n' "${value:-$default_value}" -} - -photo_path="$(configured_value PHOTO_LIBRARY_PATH ./data/photos)" -[[ -n "$photo_path" ]] || fail "PHOTO_LIBRARY_PATH must not be empty" -if [[ "$photo_path" = /* ]]; then - resolved_photo_path="$(realpath -m -- "$photo_path")" -else - resolved_photo_path="$(realpath -m -- "$ROOT_DIR/${photo_path#./}")" - case "$resolved_photo_path" in - "$ROOT_DIR"/*) ;; - *) fail "relative PHOTO_LIBRARY_PATH must remain inside the application version directory" ;; - esac -fi -mkdir -p -- "$resolved_photo_path" -[[ -d "$resolved_photo_path" ]] || fail "PHOTO_LIBRARY_PATH must resolve to a directory" - -data_path="$(configured_value APP_DATA_DIR ./data/app)" -[[ -n "$data_path" ]] || fail "APP_DATA_DIR must not be empty" -[[ "$data_path" != /* ]] || fail "APP_DATA_DIR must be relative to the application version directory" -resolved_data_path="$(realpath -m -- "$ROOT_DIR/${data_path#./}")" -case "$resolved_data_path" in - "$ROOT_DIR"/*) ;; - *) fail "APP_DATA_DIR must remain inside the application version directory" ;; -esac -[[ ! -L "$resolved_data_path" ]] || fail "APP_DATA_DIR must not be a symbolic link" -install -d -m 0750 -- "$resolved_data_path" -resolved_data_path="$(realpath -e -- "$resolved_data_path")" -case "$resolved_data_path" in - "$ROOT_DIR"/*) ;; - *) fail "APP_DATA_DIR resolves outside the application version directory" ;; -esac -chown -R --no-dereference 1337:1337 "$resolved_data_path" -chmod 0750 "$resolved_data_path" diff --git a/apps/this-week-in-past/latest/scripts/uninstall.sh b/apps/this-week-in-past/latest/scripts/uninstall.sh deleted file mode 100755 index 6e877466e..000000000 --- a/apps/this-week-in-past/latest/scripts/uninstall.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail diff --git a/apps/this-week-in-past/latest/scripts/upgrade.sh b/apps/this-week-in-past/latest/scripts/upgrade.sh deleted file mode 100755 index 6e877466e..000000000 --- a/apps/this-week-in-past/latest/scripts/upgrade.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail diff --git a/apps/this-week-in-past/logo.png b/apps/this-week-in-past/logo.png index 8b33d77c72b162d11a743e286f4bcb3678ddd8a7..40db82bf240e8a196b8463c11b6b159df255fdb5 100644 GIT binary patch delta 4080 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