# Copyright (c) 2025-2026 马建军. All rights reserved. """HTTP routes for backup module.""" from __future__ import annotations from datetime import date, datetime from flask import ( Response, flash, jsonify, redirect, render_template, request, send_file, session, stream_with_context, url_for, ) def register(deps) -> None: app = deps.app login_required = deps.login_required require_nav = deps.require_nav get_db = deps.get_db get_setting = deps.get_setting set_setting = deps.set_setting fetch_price = deps.fetch_price send_wechat_msg = deps.send_wechat_msg touch_stats_cache = deps.touch_stats_cache get_stats_data = deps.get_stats_data build_market_quote_payload = deps.build_market_quote_payload today_str = deps.today_str expire_old_plans = deps.expire_old_plans TZ = deps.tz DB_PATH = deps.db_path UPLOAD_DIR = deps.upload_dir OPEN_TYPES = deps.open_types EXIT_TRIGGERS = deps.exit_triggers BEHAVIOR_TAGS = deps.behavior_tags KLINE_PERIODS = deps.kline_periods KLINE_CUTOFFS = deps.kline_cutoffs calc_holding_duration = deps.calc_holding_duration holding_to_minutes = deps.holding_to_minutes classify_close_result = deps.classify_close_result calc_rr_ratio = deps.calc_rr_ratio calc_theoretical_pnl = deps.calc_theoretical_pnl parse_review_date_filter = deps.parse_review_date_filter _trading_mode = deps.trading_mode _ua_is_phone = deps.ua_is_phone _static_asset_v = deps.static_asset_v from modules.backup.db_backup import list_backups, resolve_backup_file @app.route("/api/backup/list") @login_required def api_backup_list(): return jsonify( { "dir": str(backup_dir()), "last_at": get_backup_last_at(get_setting), "running": backup_in_progress(), "items": list_backups(), } ) @app.route("/api/backup/download/") @login_required def api_backup_download(filename): from flask import send_file try: path = resolve_backup_file(filename) except (ValueError, FileNotFoundError) as exc: return jsonify({"error": str(exc)}), 404 return send_file(path, as_attachment=True, download_name=path.name)