Files
arch/kde-dotfiles/.config/fish/functions/f.fish
2026-03-31 20:13:15 +08:00

253 lines
9.2 KiB
Fish
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

function f
# ==============================================================================
# 【脚本功能说明】
# 1. 结合 Fastfetch在终端启动时展示随机二次元图片 (支持 SFW / NSFW 模式)。
# 2. 具备静默后台异步下载机制,库存不足时自动补货,绝不阻塞前台终端的启动。
# 3. 具备智能缓存管理机制,自动控制待展示区与已使用区 (used) 的图片数量上限。
# 4. 具备极致的网络环境容错处理,无网或弱网时自动降级 fallback避免死等。
# 5. 具备自动清理 Fastfetch 内部生成的图片转换缓存功能,防止磁盘空间无感膨胀。
# ==============================================================================
# ================= 配置区域 =================
# [开关] 阅后即焚模式 (针对 Fastfetch 内部缓存)
# true = 运行后强力清空 ~/.cache/fastfetch/images/ (防止转码缓存膨胀)
# false = 保留缓存
set -l CLEAN_CACHE_MODE true
# 每次补货下载多少张
set -l DOWNLOAD_BATCH_SIZE 10
# 最大库存上限 (待展示区)
set -l MAX_CACHE_LIMIT 100
# 库存少于多少张时开始补货
set -l MIN_TRIGGER_LIMIT 60
# [新增] used 目录最大存放数量
# 超过此数量将按照时间顺序删除最旧的文件
set -l MAX_USED_LIMIT 50
# ===========================================
# --- 0. 参数解析与模式设置 ---
set -l NSFW_MODE false
# 检查环境变量
if test "$NSFW" = "1"
set NSFW_MODE true
end
set -l ARGS_FOR_FASTFETCH
for arg in $argv
if test "$arg" = "--nsfw"
set NSFW_MODE true
else
set -a ARGS_FOR_FASTFETCH $arg
end
end
# --- 1. 目录配置 ---
# 根据模式区分缓存目录和锁文件
set -l CACHE_DIR
set -l LOCK_FILE
if test "$NSFW_MODE" = true
set CACHE_DIR "$HOME/.cache/fastfetch_waifu_nsfw"
set LOCK_FILE "/tmp/fastfetch_waifu_nsfw.lock"
else
set CACHE_DIR "$HOME/.cache/fastfetch_waifu"
set LOCK_FILE "/tmp/fastfetch_waifu.lock"
end
# 定义已使用目录
set -l USED_DIR "$CACHE_DIR/used"
mkdir -p "$CACHE_DIR"
mkdir -p "$USED_DIR"
# --- 2. 核心函数 ---
# [修复] 抛弃脆弱的 1.1.1.1,使用苹果的全球探针节点,并使用 -I (HEAD请求) 极限提速
function check_network
curl -sI --connect-timeout 2 "http://captive.apple.com/hotspot-detect.html" >/dev/null 2>&1
return $status
end
function get_random_url -V NSFW_MODE
set -l TIMEOUT --connect-timeout 5 --max-time 15
set -l RAND (math (random) % 3 + 1)
if test "$NSFW_MODE" = true
# === NSFW API ===
switch $RAND
case 1
curl -s $TIMEOUT "https://api.waifu.im/images?IncludedTags=waifu&IsNsfw=true" | jq -r '.images[0].url'
case 2
curl -s $TIMEOUT "https://api.waifu.pics/nsfw/waifu" | jq -r '.url'
case 3
curl -s $TIMEOUT "https://api.waifu.pics/nsfw/neko" | jq -r '.url'
end
else
# === SFW (正常) API ===
switch $RAND
case 1
# [修复] IsNsfwfalse 修正为 IsNsfw=false
curl -s $TIMEOUT "https://api.waifu.im/images?IncludedTags=waifu&IsNsfw=false" | jq -r '.images[0].url'
case 2
curl -s $TIMEOUT "https://nekos.best/api/v2/waifu" | jq -r '.results[0].url'
case 3
curl -s $TIMEOUT "https://api.waifu.pics/sfw/waifu" | jq -r '.url'
end
end
end
function download_one_image -V CACHE_DIR
set -l URL (get_random_url)
if string match -qr "^http" -- "$URL"
# 使用带时间戳的随机文件名
set -l FILENAME "waifu_"(date +%s%N)"_"(random)".jpg"
set -l TARGET_PATH "$CACHE_DIR/$FILENAME"
curl -s -L --connect-timeout 5 --max-time 15 -o "$TARGET_PATH" "$URL"
# 简单校验
if test -s "$TARGET_PATH"
if command -v file >/dev/null 2>&1
if not file --mime-type "$TARGET_PATH" | grep -q "image/"
rm -f "$TARGET_PATH"
end
end
else
rm -f "$TARGET_PATH"
end
end
end
function background_job -V CACHE_DIR -V LOCK_FILE -V MIN_TRIGGER_LIMIT -V DOWNLOAD_BATCH_SIZE -V MAX_CACHE_LIMIT -V NSFW_MODE
# 导出函数定义以便在 fish -c 中使用
set -l get_random_url_def (functions get_random_url | string collect)
set -l download_one_image_def (functions download_one_image | string collect)
set -l check_network_def (functions check_network | string collect)
fish -c "
# [核心修复 1] 忽略终端关闭带来的 SIGHUP 信号
trap '' HUP
# 重新定义需要的函数
$get_random_url_def
$download_one_image_def
$check_network_def
# 使用 flock 防止并发
flock -n 200 || exit 1
# [新增] 网络检查,没网就悄悄退出,不占后台资源
if not check_network
exit 0
end
# 导入变量
set CACHE_DIR '$CACHE_DIR'
set NSFW_MODE '$NSFW_MODE'
# 1. 补货检查
set CURRENT_COUNT (find \$CACHE_DIR -maxdepth 1 -name '*.jpg' 2>/dev/null | wc -l)
if test \$CURRENT_COUNT -lt $MIN_TRIGGER_LIMIT
for i in (seq 1 $DOWNLOAD_BATCH_SIZE)
download_one_image
sleep 0.5
end
end
# 2. 清理过多库存 (清理的是下载缓存区,不是 used 区)
set FINAL_COUNT (find \$CACHE_DIR -maxdepth 1 -name '*.jpg' 2>/dev/null | wc -l)
if test \$FINAL_COUNT -gt $MAX_CACHE_LIMIT
set DELETE_START_LINE (math $MAX_CACHE_LIMIT + 1)
ls -tp \$CACHE_DIR/*.jpg 2>/dev/null | tail -n +\$DELETE_START_LINE | xargs -I {} rm -- '{}'
end
" 200>"$LOCK_FILE" &
# [核心修复 2] 将刚才丢入后台的 fish 子进程剥离终端控制
disown
end
# --- 3. 主程序逻辑 ---
set -l FILES $CACHE_DIR/*.jpg
set -l NUM_FILES (count $FILES)
# fish 若无匹配文件,$FILES 可能为空或保留模式字符串,需额外判断
if test "$NUM_FILES" -eq 1; and not test -f "$FILES[1]"
set NUM_FILES 0
set FILES
end
set -l SELECTED_IMG ""
if test "$NUM_FILES" -gt 0
# 有库存,随机选一张
set -l RAND_INDEX (math (random) % $NUM_FILES + 1)
set SELECTED_IMG "$FILES[$RAND_INDEX]"
# 后台补货
background_job >/dev/null 2>&1
else
# 没库存,提示语更改并增加网络连通性容错
echo "库存不够啦!正在去搬运新的图片,请稍等哦..."
if check_network
download_one_image
else
echo "网络好像不太通畅,无法下载新图片 QAQ"
end
set FILES $CACHE_DIR/*.jpg
if test -f "$FILES[1]"
set SELECTED_IMG "$FILES[1]"
background_job >/dev/null 2>&1
end
end
# 运行 Fastfetch
if test -n "$SELECTED_IMG"; and test -f "$SELECTED_IMG"
# 显示图片
fastfetch --logo "$SELECTED_IMG" --logo-preserve-aspect-ratio true $ARGS_FOR_FASTFETCH
# === 逻辑: 移动到 used 目录 ===
mv "$SELECTED_IMG" "$USED_DIR/"
# === 逻辑: 检查 used 目录并清理旧图 ===
# 注意fish 的 glob 展开如果文件太多可能会卡,但这里有 limit 限制所以还好
set -l used_files $USED_DIR/*.jpg
set -l used_count (count $used_files)
# 再次确认 count因为如果没文件 $used_files 可能为空
if test "$used_count" -gt 0; and not test -f "$used_files[1]"
set used_count 0
end
if test "$used_count" -gt "$MAX_USED_LIMIT"
# 计算需要跳过的行数 (保留最新的 N 张)
set -l skip_lines (math "$MAX_USED_LIMIT" + 1)
# 列出所有文件按时间倒序(tp),取尾部(tail),删除(rm)
# 2>/dev/null 防止目录为空时报错
set -l files_to_delete (ls -tp "$USED_DIR"/*.jpg 2>/dev/null | tail -n +$skip_lines)
if test -n "$files_to_delete"
rm -- $files_to_delete
end
end
# 检查是否开启清理 Fastfetch 内部缓存
if test "$CLEAN_CACHE_MODE" = true
# 仅删除缩略图缓存,保留原图
rm -rf "$HOME/.cache/fastfetch/images"
end
else
# 失败提示语更改
echo "图片获取失败了,这次只能先显示默认的 Logo 啦 QAQ"
fastfetch $ARGS_FOR_FASTFETCH
end
end