feat(app): add This Week in Past

This commit is contained in:
okxlin
2026-08-01 02:05:15 +08:00
parent 6ab05890ac
commit e76d68814f
15 changed files with 461 additions and 0 deletions
@@ -0,0 +1,6 @@
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
+88
View File
@@ -0,0 +1,88 @@
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"
@@ -0,0 +1,24 @@
services:
this-week-in-past:
image: "rouhim/this-week-in-past:1.32.41"
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
+64
View File
@@ -0,0 +1,64 @@
#!/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"
+2
View File
@@ -0,0 +1,2 @@
#!/usr/bin/env bash
set -euo pipefail
+2
View File
@@ -0,0 +1,2 @@
#!/usr/bin/env bash
set -euo pipefail
+56
View File
@@ -0,0 +1,56 @@
# This Week in Past
## 产品介绍
This Week in Past 会扫描指定的照片库,按拍摄日期找出往年同一周的照片,并在浏览器中生成自动播放的幻灯片。如果本周没有匹配照片,应用会回退到随机照片。
## 主要功能
- 根据照片 EXIF 拍摄日期展示往年本周回忆
- 在没有本周照片时显示随机照片
- 支持浏览器上一张、暂停/继续和下一张操作
- 支持隐藏指定照片,并将隐藏状态保存在 SQLite 数据库中
- 可设置幻灯片播放间隔和随机播放模式
## 安装与访问
- `PHOTO_LIBRARY_PATH` 指向主机上的照片目录,容器只读挂载该目录。
- `APP_DATA_DIR` 保存 SQLite 数据库和应用缓存,默认由应用包管理。
- Web 端口由 `PANEL_APP_PORT_HTTP` 设置,安装后通过 `http://<服务器 IP>:<端口>` 访问。
- 首次索引时间取决于照片数量和存储性能。
## 访问说明
安装完成后,使用 `http://<服务器 IP>:<Web 端口>` 访问应用。应用没有登录认证;从外部网络访问时,请通过 1Panel 反向代理配置 HTTPS 和访问控制。
## 数据与安全
- 照片库始终以只读方式挂载,应用不会修改原始照片。
- `APP_DATA_DIR` 包含隐藏照片列表、索引和缓存,重启或更新时会继续使用。
- 应用本身不提供登录认证。请勿直接暴露到不可信网络;远程访问时应通过 1Panel 反向代理配置 HTTPS 和访问控制。
- 卸载应用不会删除照片库。迁移或清理前请单独备份应用数据目录。
## Introduction
This Week in Past scans a photo library and builds a browser slideshow from photos taken during the same calendar week in previous years. When no matching photos exist, it falls back to random photos.
## Features
- Build weekly memories from photo EXIF capture dates
- Fall back to random photos when the current week has no matches
- Navigate, pause, and resume the slideshow in the browser
- Hide selected photos and persist that state in SQLite
- Configure the slideshow interval and random mode
## Storage and Security
- `PHOTO_LIBRARY_PATH` is mounted read-only at `/resources`; original photos are never modified.
- `APP_DATA_DIR` stores the SQLite database and application cache and survives restarts and updates.
- The application does not include authentication. Do not expose it directly to an untrusted network; use a 1Panel reverse proxy with HTTPS and access control for remote access.
- Uninstalling the application does not delete the photo library.
## Links
- Project: <https://github.com/RouHim/this-week-in-past>
- Docker image: <https://hub.docker.com/r/rouhim/this-week-in-past>
- Frozen Docker documentation: <https://github.com/RouHim/this-week-in-past/blob/1cbf1e33bc96810d14549daf19e62ac0ecf9eb5d/README.md>
+33
View File
@@ -0,0 +1,33 @@
name: This Week in Past
tags:
- 多媒体
title: 展示往年本周照片的自托管幻灯片
description: 展示往年本周照片的自托管幻灯片
additionalProperties:
key: this-week-in-past
name: This Week in Past
tags:
- Media
shortDescZh: 展示往年本周照片的自托管幻灯片
shortDescEn: A self-hosted slideshow of photos taken this week in previous years
description:
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
@@ -0,0 +1,6 @@
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
+88
View File
@@ -0,0 +1,88 @@
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"
@@ -0,0 +1,24 @@
services:
this-week-in-past:
image: "rouhim/this-week-in-past:latest"
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
+64
View File
@@ -0,0 +1,64 @@
#!/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"
+2
View File
@@ -0,0 +1,2 @@
#!/usr/bin/env bash
set -euo pipefail
+2
View File
@@ -0,0 +1,2 @@
#!/usr/bin/env bash
set -euo pipefail
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB