From 1dec08ec5a880e2757f2bfe34e56b29a0e40c96f Mon Sep 17 00:00:00 2001 From: coolsd Date: Sun, 22 Sep 2024 11:00:23 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20fwd.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fwd.py | 389 +++++++++++++++++++-------------------------------------- 1 file changed, 128 insertions(+), 261 deletions(-) diff --git a/fwd.py b/fwd.py index 1e3a353..f760c86 100644 --- a/fwd.py +++ b/fwd.py @@ -6,12 +6,9 @@ import sqlite3 from datetime import datetime, timedelta import logging from functools import wraps -import requests -import uuid -import traceback # 设置日志 -logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s') +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') logger = logging.getLogger(__name__) app = Flask(__name__) @@ -19,33 +16,39 @@ app.secret_key = os.urandom(24) # 用于加密 session socketio = SocketIO(app, cors_allowed_origins="*") DB_NAME = 'client_management.db' -UPDATE_SERVER_URL = "https://update.uqdm.com" -# 设置访问密码和令牌 +# 设置访问密码(在实际应用中,你应该使用更安全的方式存储密码) ACCESS_PASSWORD = "131417aa" -ACCESS_TOKEN = "131417" # 这应该是一个安全的随机字符串 + +# 用于存储客户端的最后命令执行状态 +client_command_status = {} def init_db(): conn = sqlite3.connect(DB_NAME) c = conn.cursor() c.execute('''CREATE TABLE IF NOT EXISTS clients - (unique_id TEXT PRIMARY KEY, client_id TEXT, group_name TEXT, last_seen TIMESTAMP, - system_info TEXT, command_status TEXT, program_status TEXT)''') + (id TEXT PRIMARY KEY, group_name TEXT, last_seen TIMESTAMP, + system_info TEXT, program_status TEXT)''') c.execute('''CREATE TABLE IF NOT EXISTS groups (name TEXT PRIMARY KEY)''') c.execute('''CREATE TABLE IF NOT EXISTS configurations (name TEXT PRIMARY KEY, data TEXT)''') c.execute('''CREATE TABLE IF NOT EXISTS command_results - (unique_id TEXT, client_id TEXT, command TEXT, status TEXT, + (client_id TEXT, command TEXT, status TEXT, output TEXT, error TEXT, program_status TEXT, timestamp DATETIME DEFAULT CURRENT_TIMESTAMP)''') - - # 确保默认分组存在 c.execute("INSERT OR IGNORE INTO groups (name) VALUES ('default'), ('离线')") + # 检查并添加新列 + columns_to_check = ['system_info', 'program_status'] + for column in columns_to_check: + c.execute(f"PRAGMA table_info(clients)") + columns = [column_info[1] for column_info in c.fetchall()] + if column not in columns: + c.execute(f"ALTER TABLE clients ADD COLUMN {column} TEXT") + conn.commit() conn.close() - logger.info("数据库初始化完成") # 登录检查装饰器 def login_required(f): @@ -56,16 +59,6 @@ def login_required(f): return f(*args, **kwargs) return decorated_function -# 令牌验证装饰器 -def token_required(f): - @wraps(f) - def decorated_function(*args, **kwargs): - token = request.headers.get('Authorization') - if token != f'Bearer {ACCESS_TOKEN}': - return jsonify({"error": "无效或缺失的令牌"}), 401 - return f(*args, **kwargs) - return decorated_function - @app.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'POST': @@ -88,159 +81,115 @@ def index(): @socketio.on('connect') def on_connect(): - logger.info(f"客户端连接: {request.sid}") + logger.info(f"Client connected: {request.sid}") @socketio.on('disconnect') def on_disconnect(): - logger.info(f"客户端断开连接: {request.sid}") + logger.info(f"Client disconnected: {request.sid}") @socketio.on('register') def on_register(data): client_id = data['client_id'] - unique_id = data.get('unique_id') + group = data.get('group', 'default') system_info = json.dumps(data.get('system_info', {})) conn = sqlite3.connect(DB_NAME) c = conn.cursor() try: - if unique_id: - c.execute("SELECT group_name FROM clients WHERE unique_id = ?", (unique_id,)) - else: - c.execute("SELECT unique_id, group_name FROM clients WHERE client_id = ?", (client_id,)) - existing = c.fetchone() - - if existing: - if unique_id: - existing_group = existing[0] - else: - unique_id, existing_group = existing - c.execute(""" - UPDATE clients - SET last_seen = ?, system_info = ?, command_status = ?, program_status = ?, client_id = ? - WHERE unique_id = ? - """, (datetime.now().isoformat(), system_info, json.dumps({'status': 'N/A'}), 'N/A', client_id, unique_id)) - else: - unique_id = str(uuid.uuid4()) - existing_group = 'default' - c.execute(""" - INSERT INTO clients - (unique_id, client_id, group_name, last_seen, system_info, command_status, program_status) - VALUES (?, ?, ?, ?, ?, ?, ?) - """, (unique_id, client_id, existing_group, datetime.now().isoformat(), system_info, json.dumps({'status': 'N/A'}), 'N/A')) - + c.execute("INSERT OR REPLACE INTO clients (id, group_name, last_seen, system_info, program_status) VALUES (?, ?, ?, ?, ?)", + (client_id, group, datetime.now(), system_info, 'unknown')) conn.commit() - logger.info(f"客户端注册或更新: {client_id}, unique_id: {unique_id}, 分组: {existing_group}") - - # 将客户端加入到以其 unique_id 命名的房间 - socketio.server.enter_room(request.sid, unique_id) - - # 通知客户端其 unique_id 和分组 - socketio.emit('update_client_info', {'unique_id': unique_id, 'group': existing_group}, room=request.sid) - + logger.info(f"Client registered: {client_id}") + # Join the client to a room with its client_id + socketio.server.enter_room(request.sid, client_id) except Exception as e: - logger.error(f"注册客户端 {client_id} 时出错: {e}") + logger.error(f"Error registering client {client_id}: {e}") finally: conn.close() @socketio.on('heartbeat') def on_heartbeat(data): - unique_id = data.get('unique_id') - client_id = data.get('client_id') + client_id = data['client_id'] system_info = json.dumps(data.get('system_info', {})) conn = sqlite3.connect(DB_NAME) c = conn.cursor() try: - if unique_id: - c.execute(""" - UPDATE clients - SET last_seen = ?, system_info = ? - WHERE unique_id = ? - """, (datetime.now().isoformat(), system_info, unique_id)) - elif client_id: - c.execute(""" - UPDATE clients - SET last_seen = ?, system_info = ? - WHERE client_id = ? - """, (datetime.now().isoformat(), system_info, client_id)) - else: - logger.error("收到的心跳数据中没有 unique_id 或 client_id") + c.execute("UPDATE clients SET last_seen = ?, system_info = ? WHERE id = ?", + (datetime.now(), system_info, client_id)) conn.commit() except Exception as e: - logger.error(f"更新心跳时出错: {e}") + logger.error(f"Error updating heartbeat for client {client_id}: {e}") finally: conn.close() @socketio.on('status_update') def on_status_update(data): - unique_id = data.get('unique_id') - client_id = data.get('client_id') - system_info = json.dumps(data.get('system_info', {})) + client_id = data['client_id'] + system_info = json.dumps(data['system_info']) program_status = data.get('program_status', 'unknown') conn = sqlite3.connect(DB_NAME) c = conn.cursor() try: - if unique_id: - c.execute("UPDATE clients SET system_info = ?, program_status = ?, last_seen = ? WHERE unique_id = ?", - (system_info, program_status, datetime.now().isoformat(), unique_id)) - elif client_id: - c.execute("UPDATE clients SET system_info = ?, program_status = ?, last_seen = ? WHERE client_id = ?", - (system_info, program_status, datetime.now().isoformat(), client_id)) - else: - logger.error("收到的状态更新中没有 unique_id 或 client_id") + c.execute("UPDATE clients SET system_info = ?, program_status = ?, last_seen = ? WHERE id = ?", + (system_info, program_status, datetime.now(), client_id)) conn.commit() - logger.info(f"更新了客户端状态: {unique_id or client_id}") - socketio.emit('client_status_updated', { - 'unique_id': unique_id, - 'client_id': client_id, - 'system_info': json.loads(system_info), - 'program_status': program_status - }) + logger.info(f"Status updated for client: {client_id}") except Exception as e: - logger.error(f"更新状态时出错: {e}") + logger.error(f"Error updating status for client {client_id}: {e}") finally: conn.close() - + @app.route('/api/command_results', methods=['GET']) @login_required def get_command_results(): conn = sqlite3.connect(DB_NAME) c = conn.cursor() try: - c.execute("PRAGMA table_info(command_results)") - columns = [column[1] for column in c.fetchall()] c.execute("SELECT * FROM command_results ORDER BY timestamp DESC LIMIT 10") results = c.fetchall() - return jsonify([dict(zip(columns, row)) for row in results]) + return jsonify([{ + 'client_id': r[0], + 'command': r[1], + 'status': r[2], + 'output': r[3], + 'error': r[4], + 'program_status': r[5], + 'timestamp': r[6] + } for r in results]) except sqlite3.OperationalError as e: - logger.error(f"获取命令结果时数据库错误: {e}") - return jsonify({'error': '数据库错误', 'message': str(e)}), 500 + logger.error(f"Database error in get_command_results: {e}") + return jsonify({'error': 'Database error', 'message': str(e)}), 500 except Exception as e: - logger.error(f"获取命令结果时意外错误: {e}") - return jsonify({'error': '意外的服务器错误', 'message': str(e)}), 500 + logger.error(f"Unexpected error in get_command_results: {e}") + return jsonify({'error': 'Unexpected server error', 'message': str(e)}), 500 finally: conn.close() @socketio.on('command_result') def on_command_result(data): - unique_id = data.get('unique_id') client_id = data.get('client_id') command = data.get('command') result = data.get('result', {}) - logger.info(f"收到来自 {client_id} (unique_id: {unique_id}) 的命令结果: {command} - {result}") + logger.info(f"Received command result from {client_id}: {command} - {result}") + + # 更新内存中的命令执行状态 + client_command_status[client_id] = result + conn = sqlite3.connect(DB_NAME) c = conn.cursor() try: - command_status_json = json.dumps(result) - c.execute("UPDATE clients SET command_status = ?, program_status = ? WHERE unique_id = ?", - (command_status_json, result.get('program_status', 'N/A'), unique_id)) + # 更新程序状态 + c.execute("UPDATE clients SET program_status = ? WHERE id = ?", + (result.get('program_status', 'unknown'), client_id)) - c.execute("INSERT INTO command_results (unique_id, client_id, command, status, output, error, program_status) VALUES (?, ?, ?, ?, ?, ?, ?)", - (unique_id, client_id, command, result.get('status'), result.get('output'), result.get('error'), result.get('program_status'))) + # 插入命令结果到 command_results 表 + c.execute("INSERT INTO command_results (client_id, command, status, output, error, program_status) VALUES (?, ?, ?, ?, ?, ?)", + (client_id, command, result.get('status'), result.get('output'), result.get('error'), result.get('program_status'))) conn.commit() - socketio.emit('update_client_status', {'unique_id': unique_id, 'client_id': client_id, 'command_status': result, 'program_status': result.get('program_status', 'N/A')}, broadcast=True) - logger.info(f"广播了客户端 {client_id} (unique_id: {unique_id}) 的状态更新") + socketio.emit('update_client_status', {'client_id': client_id, 'command_status': result, 'program_status': result.get('program_status', 'unknown')}, broadcast=True) + logger.info(f"Broadcasted status update for client {client_id}") except Exception as e: - logger.error(f"更新客户端 {client_id} (unique_id: {unique_id}) 的命令结果时出错: {e}") + logger.error(f"Error updating command result for client {client_id}: {e}") finally: conn.close() @@ -249,33 +198,15 @@ def check_offline_clients(): c = conn.cursor() try: offline_threshold = datetime.now() - timedelta(minutes=5) - c.execute("SELECT unique_id, client_id, group_name, last_seen FROM clients") - offline_clients = [] - for unique_id, client_id, group_name, last_seen in c.fetchall(): - logger.debug(f"检查客户端: {client_id}, last_seen: {last_seen}, group: {group_name}") - if last_seen: - try: - last_seen_date = datetime.fromisoformat(last_seen) - if last_seen_date < offline_threshold: - if group_name != '离线': - c.execute("UPDATE clients SET group_name = '离线' WHERE unique_id = ?", (unique_id,)) - offline_clients.append(client_id) - except ValueError as e: - logger.error(f"解析 last_seen 时出错 (client_id: {client_id}): {e}") - if group_name != '离线': - c.execute("UPDATE clients SET group_name = '离线' WHERE unique_id = ?", (unique_id,)) - offline_clients.append(client_id) - else: - logger.warning(f"客户端 {client_id} 的 last_seen 为 None") - if group_name != '离线': - c.execute("UPDATE clients SET group_name = '离线' WHERE unique_id = ?", (unique_id,)) - offline_clients.append(client_id) + c.execute("SELECT id, group_name FROM clients WHERE last_seen < ?", (offline_threshold,)) + offline_clients = c.fetchall() + for client_id, group_name in offline_clients: + if group_name != '离线': + c.execute("UPDATE clients SET group_name = '离线' WHERE id = ?", (client_id,)) conn.commit() - logger.info(f"检测到 {len(offline_clients)} 个离线客户端") - return offline_clients + return [client_id for client_id, _ in offline_clients] except Exception as e: - logger.error(f"检查离线客户端时出错: {e}") - logger.error(traceback.format_exc()) + logger.error(f"Error checking offline clients: {e}") return [] finally: conn.close() @@ -283,40 +214,25 @@ def check_offline_clients(): @app.route('/api/clients', methods=['GET']) @login_required def get_clients(): + offline_clients = check_offline_clients() + conn = sqlite3.connect(DB_NAME) + c = conn.cursor() try: - offline_clients = check_offline_clients() - conn = sqlite3.connect(DB_NAME) - c = conn.cursor() - c.execute("SELECT unique_id, client_id, group_name, system_info, command_status, program_status FROM clients") + c.execute("SELECT id, group_name, system_info, program_status FROM clients") clients = {} for row in c.fetchall(): - unique_id, client_id, group_name, system_info, command_status, program_status = row - logger.debug(f"处理客户端: {client_id}, group: {group_name}, system_info: {system_info}, command_status: {command_status}, program_status: {program_status}") - - # 添加类型检查 - if not isinstance(unique_id, str): - logger.warning(f"客户端 {client_id} 的 unique_id 不是字符串: {type(unique_id)}") - unique_id = str(unique_id) if unique_id is not None else "" - - if not isinstance(group_name, str): - logger.warning(f"客户端 {client_id} 的 group_name 不是字符串: {type(group_name)}") - group_name = str(group_name) if group_name is not None else "default" - + client_id, group_name, system_info, program_status = row try: system_info_json = json.loads(system_info) if system_info else {} except json.JSONDecodeError: system_info_json = {} - logger.warning(f"客户端 {client_id} 的系统信息 JSON 无效") + logger.warning(f"Invalid system_info JSON for client {client_id}") - try: - command_status_json = json.loads(command_status) if command_status else {'status': 'N/A'} - except json.JSONDecodeError: - command_status_json = {'status': 'N/A'} - logger.warning(f"客户端 {client_id} 的命令状态 JSON 无效") + # 从内存中获取命令执行状态 + command_status_json = client_command_status.get(client_id, {}) clients[client_id] = { - 'unique_id': unique_id, - 'group': group_name or 'default', + 'group': group_name, 'system_info': system_info_json, 'command_status': command_status_json, 'program_status': program_status or 'unknown' @@ -324,21 +240,16 @@ def get_clients(): c.execute("SELECT name FROM groups") groups = [row[0] for row in c.fetchall()] - - logger.info(f"获取到 {len(clients)} 个客户端和 {len(groups)} 个分组") - return jsonify({ 'clients': clients, 'groups': groups, 'offline_clients': offline_clients }) except Exception as e: - logger.error(f"获取客户端时出错: {e}") - logger.error(traceback.format_exc()) - return jsonify({'error': '服务器内部错误', 'message': str(e)}), 500 + logger.error(f"Error getting clients: {e}") + return jsonify({'error': 'Internal server error'}), 500 finally: - if 'conn' in locals(): - conn.close() + conn.close() @app.route('/api/execute_command', methods=['POST']) @login_required @@ -350,45 +261,20 @@ def execute_command(): params = data.get('params', {}) affected_clients = 0 - logger.info(f"执行命令: {command}, 目标客户端: {client_ids}") - logger.info(f"命令参数: {params}") + logger.info(f"Executing command: {command} for clients: {client_ids}") + logger.info(f"Command params: {params}") - if command == 'force_update': + for client_id in client_ids: try: - response = requests.get(f"{UPDATE_SERVER_URL}/check_update/0.0.0") - if response.status_code == 200: - update_info = response.json() - latest_version = update_info.get('latest_version') - if latest_version: - params['update_url'] = f"{UPDATE_SERVER_URL}/download/{latest_version}" - else: - return jsonify({"status": "error", "message": "无法获取最新版本"}), 400 - else: - return jsonify({"status": "error", "message": "无法检查更新"}), 400 - except requests.RequestException as e: - logger.error(f"检查更新时出错: {e}") - return jsonify({"status": "error", "message": "无法检查更新"}), 500 + socketio.emit('execute_command', {'command': command, 'params': params}, room=client_id) + affected_clients += 1 + logger.info(f"Command '{command}' sent to client {client_id}") + except Exception as e: + logger.error(f"Error sending command to client {client_id}: {e}") - conn = sqlite3.connect(DB_NAME) - c = conn.cursor() - try: - for client_id in client_ids: - c.execute("SELECT unique_id FROM clients WHERE client_id = ?", (client_id,)) - result = c.fetchone() - if result: - unique_id = result[0] - socketio.emit('execute_command', {'command': command, 'params': params}, room=unique_id) - affected_clients += 1 - logger.info(f"命令 '{command}' 已发送给客户端 {client_id} (unique_id: {unique_id})") - else: - logger.warning(f"数据库中未找到客户端 {client_id}") - finally: - conn.close() - - return jsonify({"status": "命令已发送", "affected_clients": affected_clients}) + return jsonify({"status": "Command sent", "affected_clients": affected_clients}) except Exception as e: - logger.error(f"执行命令时出错: {e}") - logger.error(traceback.format_exc()) + logger.error(f"Error in execute_command: {e}") return jsonify({"status": "error", "message": str(e)}), 500 @app.route('/api/update_settings', methods=['POST']) @@ -396,7 +282,7 @@ def execute_command(): def update_settings(): data = request.json socketio.emit('update_settings', data, broadcast=True) - return jsonify({"status": "设置已更新"}) + return jsonify({"status": "Settings updated"}) @app.route('/api/update_client_group', methods=['POST']) @login_required @@ -407,16 +293,14 @@ def update_client_group(): conn = sqlite3.connect(DB_NAME) c = conn.cursor() try: - c.execute("INSERT OR IGNORE INTO groups (name) VALUES (?)", (new_group,)) - for client_id in client_ids: - c.execute("UPDATE clients SET group_name = ? WHERE client_id = ?", (new_group, client_id)) + c.execute("UPDATE clients SET group_name = ? WHERE id = ?", (new_group, client_id)) + c.execute("INSERT OR IGNORE INTO groups (name) VALUES (?)", (new_group,)) conn.commit() - return jsonify({"status": "客户端分组已更新"}) + return jsonify({"status": "Client group updated"}) except Exception as e: - logger.error(f"更新客户端分组时出错: {e}") - logger.error(traceback.format_exc()) - return jsonify({'error': '服务器内部错误'}), 500 + logger.error(f"Error updating client group: {e}") + return jsonify({'error': 'Internal server error'}), 500 finally: conn.close() @@ -430,11 +314,10 @@ def add_group(): try: c.execute("INSERT OR IGNORE INTO groups (name) VALUES (?)", (new_group,)) conn.commit() - return jsonify({"status": "分组已添加"}) + return jsonify({"status": "Group added"}) except Exception as e: - logger.error(f"添加分组时出错: {e}") - logger.error(traceback.format_exc()) - return jsonify({'error': '服务器内部错误'}), 500 + logger.error(f"Error adding group: {e}") + return jsonify({'error': 'Internal server error'}), 500 finally: conn.close() @@ -444,18 +327,17 @@ def delete_group(): data = request.json group_to_delete = data['group'] if group_to_delete in ['default', '离线']: - return jsonify({"status": "无法删除默认或离线分组"}), 400 + return jsonify({"status": "Cannot delete default or offline group"}), 400 conn = sqlite3.connect(DB_NAME) c = conn.cursor() try: c.execute("UPDATE clients SET group_name = 'default' WHERE group_name = ?", (group_to_delete,)) c.execute("DELETE FROM groups WHERE name = ?", (group_to_delete,)) conn.commit() - return jsonify({"status": "分组已删除"}) + return jsonify({"status": "Group deleted"}) except Exception as e: - logger.error(f"删除分组时出错: {e}") - logger.error(traceback.format_exc()) - return jsonify({'error': '服务器内部错误'}), 500 + logger.error(f"Error deleting group: {e}") + return jsonify({'error': 'Internal server error'}), 500 finally: conn.close() @@ -470,11 +352,10 @@ def save_config(): try: c.execute("INSERT OR REPLACE INTO configurations (name, data) VALUES (?, ?)", (config_name, config_data)) conn.commit() - return jsonify({"status": "success", "message": "配置已保存"}) + return jsonify({"status": "success", "message": "Configuration saved"}) except Exception as e: - logger.error(f"保存配置时出错: {e}") - logger.error(traceback.format_exc()) - return jsonify({'error': '服务器内部错误'}), 500 + logger.error(f"Error saving configuration: {e}") + return jsonify({'error': 'Internal server error'}), 500 finally: conn.close() @@ -488,9 +369,8 @@ def get_configs(): configs = {row[0]: json.loads(row[1]) for row in c.fetchall()} return jsonify(configs) except Exception as e: - logger.error(f"获取配置时出错: {e}") - logger.error(traceback.format_exc()) - return jsonify({'error': '服务器内部错误'}), 500 + logger.error(f"Error getting configurations: {e}") + return jsonify({'error': 'Internal server error'}), 500 finally: conn.close() @@ -503,11 +383,10 @@ def delete_config(): try: c.execute("DELETE FROM configurations WHERE name = ?", (config_name,)) conn.commit() - return jsonify({"status": "success", "message": "配置已删除"}) + return jsonify({"status": "success", "message": "Configuration deleted"}) except Exception as e: - logger.error(f"删除配置时出错: {e}") - logger.error(traceback.format_exc()) - return jsonify({'error': '服务器内部错误'}), 500 + logger.error(f"Error deleting configuration: {e}") + return jsonify({'error': 'Internal server error'}), 500 finally: conn.close() @@ -519,41 +398,29 @@ def delete_clients(): c = conn.cursor() try: for client_id in client_ids: - c.execute("DELETE FROM clients WHERE client_id = ?", (client_id,)) + c.execute("DELETE FROM clients WHERE id = ?", (client_id,)) + # 同时删除内存中的命令执行状态 + client_command_status.pop(client_id, None) conn.commit() - return jsonify({"status": "success", "message": f"{len(client_ids)} 个客户端已删除"}) + return jsonify({"status": "success", "message": f"{len(client_ids)} clients deleted"}) except Exception as e: - logger.error(f"删除客户端时出错: {e}") - logger.error(traceback.format_exc()) - return jsonify({'error': '服务器内部错误'}), 500 + logger.error(f"Error deleting clients: {e}") + return jsonify({'error': 'Internal server error'}), 500 finally: conn.close() -@app.route('/api/check_db', methods=['GET']) +@app.route('/api/test_db', methods=['GET']) @login_required -def check_db(): - conn = sqlite3.connect(DB_NAME) - c = conn.cursor() +def test_db(): try: - c.execute("SELECT * FROM clients") - clients = c.fetchall() - c.execute("PRAGMA table_info(clients)") - columns = [column[1] for column in c.fetchall()] - - client_data = [dict(zip(columns, client)) for client in clients] - - return jsonify({ - 'status': 'success', - 'client_count': len(clients), - 'columns': columns, - 'sample_data': client_data[:5] if client_data else [] - }) - except Exception as e: - logger.error(f"检查数据库时出错: {e}") - logger.error(traceback.format_exc()) - return jsonify({'error': '服务器内部错误', 'message': str(e)}), 500 - finally: + conn = sqlite3.connect(DB_NAME) + c = conn.cursor() + c.execute("SELECT name FROM sqlite_master WHERE type='table';") + tables = c.fetchall() conn.close() + return jsonify({"status": "success", "tables": [table[0] for table in tables]}) + except Exception as e: + return jsonify({"status": "error", "message": str(e)}), 500 if __name__ == '__main__': init_db() # 确保在启动服务器之前初始化数据库