mirror of
https://github.com/wolfydw/backup_OBS.git
synced 2026-05-08 06:37:02 +08:00
180 lines
4.9 KiB
Bash
Executable File
180 lines
4.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
|
||
# 统一的 Telegram 通知模块:
|
||
# - 负责消息模板拼装
|
||
# - 负责把动态内容放进代码块,降低 MarkdownV2 出错概率
|
||
# - 供 backup.sh 和 clean_backups.sh 共用
|
||
|
||
tg_code_block() {
|
||
local text="${1-}"
|
||
text="$(printf '%s' "$text" | sed -e 's/\\/\\\\/g' -e 's/`/\\`/g')"
|
||
printf '```text\n%s\n```' "$text"
|
||
}
|
||
|
||
TG_LAST_RESPONSE=""
|
||
|
||
tg_post_with_retry() {
|
||
local api_url="$1"
|
||
local api_label="$2"
|
||
local message="$3"
|
||
local response="" attempt
|
||
|
||
for attempt in 1 2 3; do
|
||
response="$(curl -sS -X POST "$api_url" \
|
||
--connect-timeout 5 \
|
||
--max-time 10 \
|
||
--data-urlencode "chat_id=${TG_USER_ID}" \
|
||
--data-urlencode "parse_mode=MarkdownV2" \
|
||
--data-urlencode "disable_web_page_preview=true" \
|
||
--data-urlencode "text=${message}" 2>&1 || true)"
|
||
|
||
if echo "$response" | grep -q '"ok":true'; then
|
||
TG_LAST_RESPONSE="$response"
|
||
return 0
|
||
fi
|
||
|
||
if (( attempt < 3 )); then
|
||
log "WARN" "Telegram ${api_label} 第 ${attempt} 次发送失败,将重试: $response"
|
||
fi
|
||
done
|
||
|
||
TG_LAST_RESPONSE="$response"
|
||
return 1
|
||
}
|
||
|
||
tg_send_message() {
|
||
local message="${1-}"
|
||
local primary_api fallback_api
|
||
|
||
if [[ -z "${TG_BOT_TOKEN:-}" || -z "${TG_USER_ID:-}" ]]; then
|
||
log "INFO" "未配置Telegram通知,跳过发送"
|
||
return 0
|
||
fi
|
||
|
||
primary_api="https://api.telegram.org/bot${TG_BOT_TOKEN}/sendMessage"
|
||
if tg_post_with_retry "$primary_api" "official" "$message"; then
|
||
log "INFO" "Telegram通知发送成功(official)"
|
||
return 0
|
||
fi
|
||
|
||
log "WARN" "Telegram官方API发送失败: $TG_LAST_RESPONSE"
|
||
|
||
if [[ -z "${TG_API_BASE_FALLBACK:-}" ]]; then
|
||
log "WARN" "未配置Telegram备用API,通知发送失败"
|
||
return 1
|
||
fi
|
||
|
||
fallback_api="${TG_API_BASE_FALLBACK%/}/bot${TG_BOT_TOKEN}/sendMessage"
|
||
if tg_post_with_retry "$fallback_api" "fallback" "$message"; then
|
||
log "INFO" "Telegram通知发送成功(fallback)"
|
||
return 0
|
||
fi
|
||
|
||
log "WARN" "Telegram备用API发送失败: $TG_LAST_RESPONSE"
|
||
log "WARN" "Telegram通知发送失败"
|
||
return 1
|
||
}
|
||
|
||
tg_read_user_excludes() {
|
||
local file="${1-}"
|
||
local out="" rule
|
||
|
||
[[ -f "$file" ]] || {
|
||
printf '无'
|
||
return 0
|
||
}
|
||
|
||
while IFS= read -r rule; do
|
||
[[ -n "$rule" ]] || continue
|
||
[[ "$rule" =~ ^[[:space:]]*# ]] && continue
|
||
out+="${rule}"$'\n'
|
||
done < "$file"
|
||
|
||
if [[ -z "$out" ]]; then
|
||
printf '无'
|
||
else
|
||
printf '%s' "${out%$'\n'}"
|
||
fi
|
||
}
|
||
|
||
tg_backup_success() {
|
||
local label="$1" backup_dirs="$2" user_excludes="$3" backup_size="$4" archive_name="$5" location="$6" pack_time="$7" upload_time="$8" speed="$9"
|
||
local archive_info message
|
||
archive_info=$(
|
||
cat <<EOF
|
||
文件大小: ${backup_size}
|
||
归档名称: ${archive_name}
|
||
存储位置: ${location}
|
||
打包用时: ${pack_time}
|
||
上传用时: ${upload_time}
|
||
平均速率: ${speed}
|
||
EOF
|
||
)
|
||
message="*备份成功*"$'\n\n'
|
||
message+="*主机*"$'\n'"$(tg_code_block "$label")"$'\n'
|
||
message+="*备份内容*"$'\n'"$(tg_code_block "$backup_dirs")"$'\n'
|
||
message+="*用户排除*"$'\n'"$(tg_code_block "$user_excludes")"$'\n'
|
||
message+="*归档信息*"$'\n'"$(tg_code_block "$archive_info")"
|
||
tg_send_message "$message"
|
||
}
|
||
|
||
tg_backup_dryrun() {
|
||
local label="$1" backup_dirs="$2" user_excludes="$3" archive_name="$4" backup_size="$5" pack_time="$6"
|
||
local archive_info message
|
||
archive_info=$(
|
||
cat <<EOF
|
||
归档名称: ${archive_name}
|
||
文件大小: ${backup_size}
|
||
打包用时: ${pack_time}
|
||
EOF
|
||
)
|
||
message="*备份自检*"$'\n\n'
|
||
message+="*主机*"$'\n'"$(tg_code_block "$label")"$'\n'
|
||
message+="*备份内容*"$'\n'"$(tg_code_block "$backup_dirs")"$'\n'
|
||
message+="*用户排除*"$'\n'"$(tg_code_block "$user_excludes")"$'\n'
|
||
message+="*归档信息*"$'\n'"$(tg_code_block "$archive_info")"
|
||
tg_send_message "$message"
|
||
}
|
||
|
||
tg_backup_error() {
|
||
local label="$1" reason="$2" error_log="$3"
|
||
local message
|
||
message="*备份失败*"$'\n\n'
|
||
message+="*主机*"$'\n'"$(tg_code_block "$label")"$'\n'
|
||
message+="*原因*"$'\n'"$(tg_code_block "$reason")"
|
||
if [[ -n "$error_log" ]]; then
|
||
message+=$'\n'"*错误日志*"$'\n'"$(tg_code_block "$error_log")"
|
||
fi
|
||
tg_send_message "$message"
|
||
}
|
||
|
||
tg_clean_success() {
|
||
local label="$1" prefix="$2" retain_days="$3" keep_count="$4" del_ok="$5" del_fail="$6"
|
||
local summary message
|
||
summary=$(
|
||
cat <<EOF
|
||
前缀: ${prefix}
|
||
保留天数: ${retain_days}
|
||
保留对象数: ${keep_count}
|
||
删除成功: ${del_ok}
|
||
删除失败: ${del_fail}
|
||
EOF
|
||
)
|
||
message="*清理完成*"$'\n\n'
|
||
message+="*主机*"$'\n'"$(tg_code_block "$label")"$'\n'
|
||
message+="*结果*"$'\n'"$(tg_code_block "$summary")"
|
||
tg_send_message "$message"
|
||
}
|
||
|
||
tg_clean_error() {
|
||
local label="$1" reason="$2" error_log="$3"
|
||
local message
|
||
message="*清理失败*"$'\n\n'
|
||
message+="*主机*"$'\n'"$(tg_code_block "$label")"$'\n'
|
||
message+="*原因*"$'\n'"$(tg_code_block "$reason")"
|
||
if [[ -n "$error_log" ]]; then
|
||
message+=$'\n'"*错误日志*"$'\n'"$(tg_code_block "$error_log")"
|
||
fi
|
||
tg_send_message "$message"
|
||
}
|