Files
arch/noctalia-dotfiles/.local/bin/random-anime-wallpaper-noctalia

164 lines
5.0 KiB
Plaintext
Raw Permalink Normal View History

2026-03-31 20:13:15 +08:00
#!/bin/bash
set -euo pipefail
# =============================================================================
# 功能描述:
# 从指定 API 获取随机壁纸,强制转换为 PNG 格式,并使用 noctalia IPC 协议设置为桌面壁纸。
#
# 核心特性:
# 1. 异步下载与长耗时心跳通知。
# 2. 健壮性检查:校验文件大小与 MIME 类型,剔除损坏/无效文件。
# 3. 格式转换:自动将下载的图片(无论原格式)转换为 noctalia 支持的 PNG 格式。
# 4. 资源自清洁:根据配置自动清理历史壁纸,保持存储整洁。
# 5. 解耦设计:更新完毕后触发异步的系统 UI 更新钩子 (matugen, niri等)。
#
# 选项:
# -k: 保留模式,不清理旧壁纸
# -s: 静默模式,关闭桌面通知
# -h: 显示帮助信息
#
# 依赖:
# curl, file, notify-send, ImageMagick (magick 或 convert), qs (noctalia wrapper)
# =============================================================================
# ================= 默认配置 =================
API_URL="https://t.alcy.cc/pc/"
SAVE_DIR="$HOME/Pictures/Wallpapers/api-random-download"
# 自动清理时保留最近多少张图片
KEEP_COUNT=40
# 默认开关状态 (可被参数覆盖)
ENABLE_CLEANUP=true
SILENT_MODE=false
# ================= 参数解析 =================
usage() {
echo "用法: $(basename "$0") [-k] [-s] [-h]"
echo " -k (Keep) 保留模式:不清理旧壁纸"
echo " -s (Silent) 静默模式:不发送任何 notify-send 通知"
echo " -h 帮助信息"
exit 0
}
while getopts "ksh" opt; do
case $opt in
k) ENABLE_CLEANUP=false ;;
s) SILENT_MODE=true ;;
h) usage ;;
*) usage ;;
esac
done
# ================= 辅助函数 =================
# 统一通知函数 (兼容 set -u 处理未传递的 $3)
send_notify() {
if [ "$SILENT_MODE" = false ]; then
notify-send "$1" "$2" ${3:-}
fi
}
# ================= 主逻辑 =================
mkdir -p "$SAVE_DIR"
TIMESTAMP=$(date +%s)
RAW_PATH="${SAVE_DIR}/wall_${TIMESTAMP}_raw.tmp"
FINAL_PATH="${SAVE_DIR}/wall_${TIMESTAMP}.png"
# --- 1. 下载模块 (带心跳通知) ---
if [ "$SILENT_MODE" = false ]; then
(
sleep 8
while true; do
notify-send "Wallpaper" "Downloading is still in progress..." --expire-time=5000 --icon=drive-harddisk --replace-id=999 || true
sleep 8
done
) &
NOTIFY_PID=$!
else
NOTIFY_PID=""
fi
send_notify "Wallpaper" "Downloading from Alcy..." "--expire-time=5000"
USER_AGENT="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
# 执行下载并做严格模式下的安全判断
if ! curl -L -s -A "$USER_AGENT" --connect-timeout 10 -m 120 -o "$RAW_PATH" "$API_URL"; then
[ -n "${NOTIFY_PID:-}" ] && kill "$NOTIFY_PID" 2>/dev/null || true
send_notify "Wallpaper Error" "Download failed (Network/API Error)"
exit 1
fi
# 下载结束,杀掉通知进程
if [ -n "${NOTIFY_PID:-}" ]; then
kill "$NOTIFY_PID" 2>/dev/null || true
fi
# 校验文件 (大小)
if [ ! -f "$RAW_PATH" ] || [ "$(wc -c < "$RAW_PATH")" -lt 20480 ]; then
send_notify "Wallpaper Error" "Download failed (File too small/Invalid)"
rm -f "$RAW_PATH"
exit 1
fi
# 校验文件 (MIME 类型)
FILE_TYPE=$(file --mime-type -b "$RAW_PATH" || echo "unknown")
if [[ "$FILE_TYPE" != image/* ]]; then
send_notify "Wallpaper Error" "Not an image file ($FILE_TYPE)"
rm -f "$RAW_PATH"
exit 1
fi
# --- 2. 格式转换模块 (转为 PNG) ---
# 检查 ImageMagick 是否存在 (兼容新版 magick 和旧版 convert)
if command -v magick > /dev/null 2>&1; then
IMG_TOOL="magick"
elif command -v convert > /dev/null 2>&1; then
IMG_TOOL="convert"
else
send_notify "Wallpaper Error" "ImageMagick not found. Please install it."
rm -f "$RAW_PATH"
exit 1
fi
# 执行转换
if ! $IMG_TOOL "$RAW_PATH" "$FINAL_PATH"; then
send_notify "Wallpaper Error" "Failed to convert image to PNG format"
rm -f "$RAW_PATH" "$FINAL_PATH"
exit 1
fi
# 转换成功,清理原始临时文件
rm -f "$RAW_PATH"
# --- 3. 应用模块 (noctalia ipc call) ---
# 使用 qs 包装器调用 noctalia-shell 的 ipc并将 monitor 参数设为 all
qs -c noctalia-shell ipc call wallpaper set "$FINAL_PATH" all
# --- 4. 钩子与清理 ---
(
if [ -x "$HOME/.config/scripts/matugen-update.sh" ]; then
"$HOME/.config/scripts/matugen-update.sh" "$FINAL_PATH" > /dev/null || true
fi
sleep 0.5
if [ -x "$HOME/.config/scripts/niri_set_overview_blur_dark_bg.sh" ]; then
"$HOME/.config/scripts/niri_set_overview_blur_dark_bg.sh" > /dev/null || true
fi
# 动态清理逻辑
if [ "$ENABLE_CLEANUP" = true ]; then
DELETE_START=$((KEEP_COUNT + 1))
# 这里的命名规范只包含时间戳无特殊字符xargs rm 是安全的
cd "$SAVE_DIR" && ls -t | tail -n +"$DELETE_START" | xargs -I {} rm -- {} 2>/dev/null || true
fi
) &
send_notify "Wallpaper Updated" "PNG applied successfully via Noctalia!"