更新 fwd.py
This commit is contained in:
parent
93b67234db
commit
1dec08ec5a
389
fwd.py
389
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() # 确保在启动服务器之前初始化数据库
|
||||
|
||||
Loading…
Reference in New Issue
Block a user