v2.5.0: add QR import and backup scheduling

This commit is contained in:
Виталий Литвинов
2026-04-25 14:39:56 +03:00
parent c7540a97f7
commit b2ab0dca57
10 changed files with 854 additions and 97 deletions

View File

@@ -27,6 +27,9 @@ create_backup() {
if [ -f "$GOTELEGRAM_DIR/disabled_users.json" ]; then
cp "$GOTELEGRAM_DIR/disabled_users.json" "$tmp_dir/disabled_users.json" 2>/dev/null
fi
if [ -f "$GOTELEGRAM_DIR/backup_schedule.json" ]; then
cp "$GOTELEGRAM_DIR/backup_schedule.json" "$tmp_dir/backup_schedule.json" 2>/dev/null
fi
# Language marker (i18n)
if [ -f "$GOTELEGRAM_DIR/.language" ]; then
@@ -106,7 +109,7 @@ create_backup() {
cat > "$tmp_dir/metadata.json" << EOMETA
{
"backup_version": "1.5",
"backup_version": "1.6",
"gotelegram_version": "$GOTELEGRAM_VERSION",
"created_at": "$(date -Iseconds)",
"hostname": "$(hostname)",
@@ -173,6 +176,7 @@ EOMETA
restore_backup() {
local backup_file="$1"
local password="$2"
local assume_yes="$3"
if [ ! -f "$backup_file" ]; then
if type tf &>/dev/null; then
@@ -218,6 +222,18 @@ restore_backup() {
backup_dir=$(find "$tmp_dir" -maxdepth 1 -type d -name "gotelegram_backup_*" | head -1)
[ -z "$backup_dir" ] && backup_dir="$tmp_dir"
# Legacy bot backups before v2.5.0 stored absolute paths directly in tar:
# opt/gotelegram/config.json and etc/telemt/config.toml.
if [ ! -f "$backup_dir/config.toml" ] && [ -f "$tmp_dir/etc/telemt/config.toml" ]; then
cp "$tmp_dir/etc/telemt/config.toml" "$backup_dir/config.toml" 2>/dev/null || true
fi
if [ ! -f "$backup_dir/gotelegram.json" ] && [ -f "$tmp_dir/opt/gotelegram/config.json" ]; then
cp "$tmp_dir/opt/gotelegram/config.json" "$backup_dir/gotelegram.json" 2>/dev/null || true
fi
if [ ! -f "$backup_dir/disabled_users.json" ] && [ -f "$tmp_dir/opt/gotelegram/disabled_users.json" ]; then
cp "$tmp_dir/opt/gotelegram/disabled_users.json" "$backup_dir/disabled_users.json" 2>/dev/null || true
fi
# Проверяем метаданные
if [ -f "$backup_dir/metadata.json" ]; then
local bk_version bk_mode bk_ip bk_lang bk_date
@@ -233,7 +249,7 @@ restore_backup() {
echo ""
fi
if ! confirm "$(_t_or backup_confirm_restore 'Восстановить конфигурацию? Текущие настройки будут перезаписаны.')"; then
if [ "$assume_yes" != "yes" ] && ! confirm "$(_t_or backup_confirm_restore 'Восстановить конфигурацию? Текущие настройки будут перезаписаны.')"; then
rm -rf "$tmp_dir"
return 0
fi
@@ -261,6 +277,18 @@ restore_backup() {
cp "$backup_dir/disabled_users.json" "$GOTELEGRAM_DIR/disabled_users.json"
chmod 600 "$GOTELEGRAM_DIR/disabled_users.json" 2>/dev/null || true
fi
if [ -f "$backup_dir/backup_schedule.json" ]; then
mkdir -p "$GOTELEGRAM_DIR"
cp "$backup_dir/backup_schedule.json" "$GOTELEGRAM_DIR/backup_schedule.json" 2>/dev/null
chmod 600 "$GOTELEGRAM_DIR/backup_schedule.json" 2>/dev/null || true
if command -v jq >/dev/null 2>&1; then
local restored_schedule
restored_schedule=$(jq -r '.frequency // "off"' "$GOTELEGRAM_DIR/backup_schedule.json" 2>/dev/null || echo "off")
case "$restored_schedule" in
off|daily|weekly|monthly) set_backup_schedule "$restored_schedule" >/dev/null 2>&1 || true ;;
esac
fi
fi
# Восстанавливаем language marker (i18n)
if [ -f "$backup_dir/.language" ]; then
@@ -374,7 +402,7 @@ list_backups() {
echo -e " ${DIM}$(printf '─%.0s' {1..60})${NC}"
local i=1
for f in "$BACKUP_DIR"/gotelegram_backup_*.tar.gz*; do
for f in "$BACKUP_DIR"/*.tar.gz*; do
[ -f "$f" ] || continue
[[ "$f" == *.sha256 ]] && continue
local size date_str name
@@ -393,11 +421,11 @@ list_backups() {
cleanup_old_backups() {
local keep="${1:-5}"
local count
count=$(find "$BACKUP_DIR" -name "gotelegram_backup_*.tar.gz*" ! -name "*.sha256" 2>/dev/null | wc -l)
count=$(find "$BACKUP_DIR" -name "*.tar.gz*" ! -name "*.sha256" 2>/dev/null | wc -l)
if [ "$count" -gt "$keep" ]; then
local to_delete=$((count - keep))
find "$BACKUP_DIR" -name "gotelegram_backup_*.tar.gz*" ! -name "*.sha256" 2>/dev/null | sort | head -n "$to_delete" | while read -r f; do
find "$BACKUP_DIR" -name "*.tar.gz*" ! -name "*.sha256" 2>/dev/null | sort | head -n "$to_delete" | while read -r f; do
rm -f "$f" "${f}.sha256"
done
if type tf &>/dev/null; then
@@ -408,6 +436,84 @@ cleanup_old_backups() {
fi
}
# ── Расписание бекапов ───────────────────────────────────────────────────────
backup_schedule_calendar() {
case "${1:-off}" in
off) echo "" ;;
daily) echo "*-*-* 03:20:00" ;;
weekly) echo "Sun 03:20:00" ;;
monthly) echo "*-*-01 03:20:00" ;;
*) return 1 ;;
esac
}
set_backup_schedule() {
local frequency="${1:-off}"
local calendar
if ! calendar=$(backup_schedule_calendar "$frequency"); then
log_error "Unsupported backup schedule: $frequency"
return 1
fi
mkdir -p "$GOTELEGRAM_DIR" "$BACKUP_DIR"
if [ "$frequency" = "off" ]; then
systemctl disable --now gotelegram-backup.timer >/dev/null 2>&1 || true
rm -f /etc/systemd/system/gotelegram-backup.timer /etc/systemd/system/gotelegram-backup.service
systemctl daemon-reload >/dev/null 2>&1 || true
else
cat > /etc/systemd/system/gotelegram-backup.service << 'EOSVC'
[Unit]
Description=goTelegram Pro backup
Wants=network-online.target
After=network-online.target
[Service]
Type=oneshot
Environment=GOTELEGRAM_BACKUP_KEEP=30
ExecStart=/bin/bash -lc 'source /opt/gotelegram/lib/common.sh; source /opt/gotelegram/lib/i18n.sh; source /opt/gotelegram/lib/telemt.sh; source /opt/gotelegram/lib/website.sh; source /opt/gotelegram/lib/backup.sh; load_language "$(detect_language 2>/dev/null || echo en)"; create_backup ""; cleanup_old_backups "${GOTELEGRAM_BACKUP_KEEP:-30}"'
EOSVC
cat > /etc/systemd/system/gotelegram-backup.timer << EOTIMER
[Unit]
Description=goTelegram Pro scheduled backup
[Timer]
OnCalendar=$calendar
Persistent=true
RandomizedDelaySec=15m
Unit=gotelegram-backup.service
[Install]
WantedBy=timers.target
EOTIMER
systemctl daemon-reload >/dev/null 2>&1 || return 1
systemctl enable --now gotelegram-backup.timer >/dev/null 2>&1 || return 1
fi
cat > "$GOTELEGRAM_DIR/backup_schedule.json" << EOSCHEDULE
{
"frequency": "$frequency",
"calendar": "$calendar",
"keep": 30,
"updated_at": "$(date -Iseconds)"
}
EOSCHEDULE
chmod 600 "$GOTELEGRAM_DIR/backup_schedule.json" 2>/dev/null || true
log_success "Backup schedule: $frequency"
echo "$frequency"
}
backup_schedule_status() {
local frequency="off" calendar=""
if [ -f "$GOTELEGRAM_DIR/backup_schedule.json" ] && command -v jq >/dev/null 2>&1; then
frequency=$(jq -r '.frequency // "off"' "$GOTELEGRAM_DIR/backup_schedule.json" 2>/dev/null || echo "off")
calendar=$(jq -r '.calendar // ""' "$GOTELEGRAM_DIR/backup_schedule.json" 2>/dev/null || echo "")
fi
echo "frequency=$frequency calendar=$calendar"
systemctl list-timers gotelegram-backup.timer --no-pager 2>/dev/null || true
}
# ── Интерактивный бекап ──────────────────────────────────────────────────────
interactive_backup() {
echo ""
@@ -447,7 +553,7 @@ interactive_restore() {
local backup_file=""
if [[ "$choice" =~ ^[0-9]+$ ]]; then
local i=1
for f in "$BACKUP_DIR"/gotelegram_backup_*.tar.gz*; do
for f in "$BACKUP_DIR"/*.tar.gz*; do
[ -f "$f" ] || continue
[[ "$f" == *.sha256 ]] && continue
if [ "$i" -eq "$choice" ]; then