176 lines
5.4 KiB
Python
176 lines
5.4 KiB
Python
from flask import Flask, render_template, request, jsonify, session, redirect, url_for, send_from_directory
|
|
import os
|
|
from flask_socketio import SocketIO
|
|
from flask_cors import CORS
|
|
import sys
|
|
|
|
from config import Config
|
|
from auth import infi_login, login_required
|
|
from database import UserManager, ChatManager
|
|
from websocket_handler import WebSocketHandler
|
|
from file_handler import FileHandler
|
|
|
|
app = Flask(__name__)
|
|
app.config.from_object(Config)
|
|
CORS(app)
|
|
|
|
# 初始化SocketIO
|
|
# 在 Windows 上避免使用 eventlet 的 monkey_patch,改用 threading
|
|
use_eventlet = False
|
|
if not sys.platform.startswith('win'):
|
|
try:
|
|
import eventlet
|
|
eventlet.monkey_patch()
|
|
use_eventlet = True
|
|
except Exception:
|
|
use_eventlet = False
|
|
|
|
socketio = SocketIO(app, cors_allowed_origins="*", async_mode='eventlet' if use_eventlet else 'threading')
|
|
|
|
# 初始化管理器
|
|
user_manager = UserManager()
|
|
chat_manager = ChatManager()
|
|
|
|
# 初始化WebSocket处理器
|
|
ws_handler = WebSocketHandler(socketio, user_manager)
|
|
|
|
@app.route('/')
|
|
@login_required
|
|
def index():
|
|
"""主页面"""
|
|
user_account = session.get('user_account')
|
|
user_info = user_manager.get_user(user_account)['user_info']
|
|
return render_template('index.html', user_info=user_info)
|
|
|
|
@app.route('/login', methods=['GET', 'POST'])
|
|
def login():
|
|
"""登录页面"""
|
|
if request.method == 'GET':
|
|
return render_template('login.html')
|
|
|
|
# POST请求处理登录
|
|
data = request.json
|
|
account = data.get('account')
|
|
password = data.get('password')
|
|
|
|
# 检查本地是否已保存用户
|
|
if user_manager.verify_user(account, password):
|
|
session['user_account'] = account
|
|
user_manager.update_user_status(account, online=True)
|
|
return jsonify({'success': True, 'message': '登录成功'})
|
|
|
|
# 使用英飞API登录
|
|
result, error = infi_login(account, password)
|
|
if error:
|
|
return jsonify({'success': False, 'message': error})
|
|
|
|
# 保存用户信息到本地
|
|
user_manager.add_user(account, password, result['token'], result['user_info'])
|
|
|
|
# 设置session
|
|
session['user_account'] = account
|
|
user_manager.update_user_status(account, online=True)
|
|
|
|
return jsonify({'success': True, 'message': '登录成功'})
|
|
|
|
@app.route('/logout')
|
|
def logout():
|
|
"""登出"""
|
|
account = session.get('user_account')
|
|
if account:
|
|
user_manager.update_user_status(account, online=False)
|
|
session.clear()
|
|
return redirect(url_for('login'))
|
|
|
|
@app.route('/api/users')
|
|
@login_required
|
|
def get_users():
|
|
"""获取用户列表"""
|
|
current_user = session.get('user_account')
|
|
users = []
|
|
|
|
for account, data in user_manager.users.items():
|
|
if account != current_user:
|
|
users.append({
|
|
'account': account,
|
|
'name': data['user_info'].get('name', '未知用户'),
|
|
'online': data.get('online', False),
|
|
'org': data['user_info'].get('orgFullList', [{}])[0].get('name', '')
|
|
})
|
|
|
|
return jsonify(users)
|
|
|
|
@app.route('/api/upload', methods=['POST'])
|
|
@login_required
|
|
def upload_file():
|
|
"""文件上传"""
|
|
if 'file' not in request.files:
|
|
return jsonify({'success': False, 'message': '没有文件'})
|
|
|
|
# 检查是否可以上传新文件
|
|
if not chat_manager.can_upload_file():
|
|
return jsonify({'success': False, 'message': '同时最多只能有5个文件存在'})
|
|
|
|
file = request.files['file']
|
|
uploader = session.get('user_account')
|
|
|
|
# 检查文件大小
|
|
file.seek(0, 2) # 移动到文件末尾
|
|
file_size = file.tell()
|
|
file.seek(0) # 重置文件指针
|
|
|
|
if file_size > Config.MAX_CONTENT_LENGTH:
|
|
return jsonify({'success': False, 'message': '文件太大,最大100MB'})
|
|
|
|
# 保存文件
|
|
file_info = FileHandler.save_file(file, uploader)
|
|
if not file_info:
|
|
return jsonify({'success': False, 'message': '不支持的文件类型'})
|
|
|
|
# 添加到活跃文件列表
|
|
chat_manager.add_file(file_info)
|
|
|
|
return jsonify({
|
|
'success': True,
|
|
'filename': file_info.get('filename', file_info.get('original_name')),
|
|
'url': file_info['url']
|
|
})
|
|
|
|
@app.route('/api/files')
|
|
@login_required
|
|
def list_files():
|
|
"""获取文件列表"""
|
|
files = []
|
|
for file_info in chat_manager.active_files:
|
|
files.append({
|
|
'filename': file_info.get('filename', file_info.get('original_name')),
|
|
'uploader': file_info['uploader'],
|
|
'upload_time': file_info['upload_time'].isoformat(),
|
|
'size': file_info['size'],
|
|
'url': file_info['url']
|
|
})
|
|
|
|
return jsonify(files)
|
|
|
|
|
|
@app.route('/favicon.ico')
|
|
def favicon():
|
|
# 从 static/favicon.ico 返回 favicon
|
|
favicon_path = os.path.join(app.root_path, 'static', 'favicon.ico')
|
|
if os.path.exists(favicon_path):
|
|
return send_from_directory(os.path.join(app.root_path, 'static'), 'favicon.ico')
|
|
return ('', 404)
|
|
|
|
if __name__ == '__main__':
|
|
print("Starting Web WeChat server...")
|
|
print(f"Access at: http://localhost:5000")
|
|
socketio.run(app, debug=True, host='::', port=5000)
|
|
|
|
|
|
@app.route('/favicon.ico')
|
|
def favicon():
|
|
# 从 static/favicon.ico 返回 favicon
|
|
favicon_path = os.path.join(app.root_path, 'static', 'favicon.ico')
|
|
if os.path.exists(favicon_path):
|
|
return send_from_directory(os.path.join(app.root_path, 'static'), 'favicon.ico')
|
|
return ('', 404) |