继续完善

This commit is contained in:
2025-09-16 12:57:36 +08:00
parent 249e434b72
commit 17691af8d1
25 changed files with 1981 additions and 83 deletions

View File

@@ -6,15 +6,120 @@ Created by: 神奇万事通
Date: 2025-01-15
"""
from flask import Blueprint, request, jsonify
from flask import Blueprint, request, jsonify, current_app
import requests
import json
import os
from datetime import datetime
from bson import ObjectId
from functools import wraps
# 创建蓝图
aimodelapp_bp = Blueprint('aimodelapp', __name__)
# AI功能萌芽币消耗配置
AI_COST = 100 # 每次调用AI功能消耗的萌芽币数量
# 验证用户萌芽币余额装饰器
def verify_user_coins(f):
"""验证用户萌芽币余额并在调用AI功能后扣除相应数量的萌芽币"""
@wraps(f)
def decorated(*args, **kwargs):
try:
# 获取用户认证信息
token = request.headers.get('Authorization')
if not token:
return jsonify({
'success': False,
'message': '未提供认证信息',
'error_code': 'auth_required'
}), 401
if token.startswith('Bearer '):
token = token[7:]
# 解析JWT token
import jwt
try:
payload = jwt.decode(token, current_app.config['SECRET_KEY'], algorithms=['HS256'])
user_id = payload['user_id']
except Exception as jwt_error:
print(f"JWT解析错误: {str(jwt_error)}")
return jsonify({
'success': False,
'message': '无效的认证信息',
'error_code': 'invalid_token'
}), 401
# 查询用户萌芽币余额
users_collection = current_app.mongo.db.userdata
user = users_collection.find_one({'_id': ObjectId(user_id)})
if not user:
return jsonify({
'success': False,
'message': '用户不存在',
'error_code': 'user_not_found'
}), 404
# 检查萌芽币余额
current_coins = user.get('萌芽币', 0)
if current_coins < AI_COST:
return jsonify({
'success': False,
'message': f'萌芽币余额不足!当前余额: {current_coins}, 需要: {AI_COST}',
'error_code': 'insufficient_coins',
'current_coins': current_coins,
'required_coins': AI_COST
}), 402
# 先扣除萌芽币,确保无论服务是否成功都会扣费
deduct_result = users_collection.update_one(
{'_id': ObjectId(user_id)},
{'$inc': {'萌芽币': -AI_COST}}
)
if deduct_result.modified_count < 1:
print(f"警告: 用户 {user_id} 萌芽币扣除失败")
# 为请求添加用户信息,以便在函数内部使用
request.current_user = {
'user_id': user_id,
'username': user.get('用户名', ''),
'email': user.get('邮箱', '')
}
# 保存API调用类型
api_type = request.path.split('/')[-1]
# 添加使用记录
usage_record = {
'api_type': api_type,
'timestamp': datetime.now().isoformat(),
'cost': AI_COST
}
# 更新用户的AI使用历史记录
users_collection.update_one(
{'_id': ObjectId(user_id)},
{'$push': {'ai_usage_history': usage_record}}
)
# 调用原函数
result = f(*args, **kwargs)
return result
except Exception as e:
print(f"验证萌芽币时发生错误: {str(e)}")
return jsonify({
'success': False,
'message': '处理请求时出错',
'error': str(e)
}), 500
return decorated
#加载AI配置文件
def load_ai_config():
"""加载AI配置文件"""
@@ -126,6 +231,7 @@ def call_kimi_api(messages, model="kimi-k2-0905-preview"):
#统一的AI聊天接口
@aimodelapp_bp.route('/chat', methods=['POST'])
@verify_user_coins
def ai_chat():
"""统一的AI聊天接口"""
try:
@@ -166,6 +272,7 @@ def ai_chat():
#姓名分析专用接口
@aimodelapp_bp.route('/name-analysis', methods=['POST'])
@verify_user_coins
def name_analysis():
"""姓名分析专用接口"""
try:
@@ -228,6 +335,7 @@ def name_analysis():
#变量命名助手接口
@aimodelapp_bp.route('/variable-naming', methods=['POST'])
@verify_user_coins
def variable_naming():
"""变量命名助手接口"""
try:
@@ -329,7 +437,9 @@ def variable_naming():
except Exception as e:
return jsonify({'error': f'变量命名失败: {str(e)}'}), 500
#AI写诗助手接口
@aimodelapp_bp.route('/poetry', methods=['POST'])
@verify_user_coins
def poetry_assistant():
"""AI写诗助手接口"""
try:
@@ -379,7 +489,9 @@ def poetry_assistant():
except Exception as e:
return jsonify({'error': f'诗歌创作失败: {str(e)}'}), 500
#AI语言翻译接口
@aimodelapp_bp.route('/translation', methods=['POST'])
@verify_user_coins
def translation():
"""AI语言翻译接口"""
try:
@@ -468,6 +580,7 @@ def translation():
#现代文转文言文接口
@aimodelapp_bp.route('/classical_conversion', methods=['POST'])
@verify_user_coins
def classical_conversion():
"""现代文转文言文接口"""
try:
@@ -548,6 +661,7 @@ def classical_conversion():
#AI表情制作器接口
@aimodelapp_bp.route('/expression-maker', methods=['POST'])
@verify_user_coins
def expression_maker():
"""AI表情制作器接口"""
try:
@@ -672,6 +786,7 @@ def expression_maker():
#Linux命令生成接口
@aimodelapp_bp.route('/linux-command', methods=['POST'])
@verify_user_coins
def linux_command_generator():
"""Linux命令生成接口"""
try:
@@ -740,6 +855,80 @@ def linux_command_generator():
except Exception as e:
return jsonify({'error': f'Linux命令生成失败: {str(e)}'}), 500
#获取用户萌芽币余额
@aimodelapp_bp.route('/coins', methods=['GET'])
def get_user_coins():
"""获取用户萌芽币余额"""
try:
# 获取用户认证信息
token = request.headers.get('Authorization')
if not token:
return jsonify({
'success': False,
'message': '未提供认证信息',
'error_code': 'auth_required'
}), 401
if token.startswith('Bearer '):
token = token[7:]
# 解析JWT token
import jwt
try:
payload = jwt.decode(token, current_app.config['SECRET_KEY'], algorithms=['HS256'])
user_id = payload['user_id']
except jwt.ExpiredSignatureError:
return jsonify({
'success': False,
'message': 'Token已过期请重新登录',
'error_code': 'token_expired'
}), 401
except Exception as e:
return jsonify({
'success': False,
'message': f'无效的认证信息: {str(e)}',
'error_code': 'invalid_token'
}), 401
# 查询用户萌芽币余额
users_collection = current_app.mongo.db.userdata
user = users_collection.find_one({'_id': ObjectId(user_id)})
if not user:
return jsonify({
'success': False,
'message': '用户不存在',
'error_code': 'user_not_found'
}), 404
# 返回萌芽币信息
current_coins = user.get('萌芽币', 0)
username = user.get('用户名', '用户')
# 增加额外有用信息
ai_usage_history = []
if 'ai_usage_history' in user:
ai_usage_history = user['ai_usage_history'][-5:] # 最近5条使用记录
return jsonify({
'success': True,
'data': {
'coins': current_coins,
'ai_cost': AI_COST,
'can_use_ai': current_coins >= AI_COST,
'username': username,
'usage_count': len(ai_usage_history),
'recent_usage': ai_usage_history
},
'message': f'当前萌芽币余额: {current_coins}'
}), 200
except Exception as e:
return jsonify({
'success': False,
'message': '处理请求时出错',
'error': str(e)
}), 500
#获取可用的AI模型列表
@aimodelapp_bp.route('/models', methods=['GET'])
def get_available_models():

View File

@@ -6,7 +6,7 @@ Created by: 神奇万事通
Date: 2025-09-02
"""
from flask import Blueprint, request, jsonify, session, current_app
from flask import Blueprint, request, jsonify, current_app
from werkzeug.security import generate_password_hash, check_password_hash
import hashlib
import re
@@ -17,6 +17,7 @@ from .email_service import send_verification_email, verify_code, is_qq_email, ge
auth_bp = Blueprint('auth', __name__)
#生成JWT token
def generate_token(user_data):
"""生成JWT token"""
payload = {
@@ -28,6 +29,7 @@ def generate_token(user_data):
}
return jwt.encode(payload, current_app.config['SECRET_KEY'], algorithm='HS256')
#验证JWT token
def verify_token(token):
"""验证JWT token"""
try:
@@ -38,6 +40,7 @@ def verify_token(token):
except jwt.InvalidTokenError:
return {'success': False, 'message': 'Token无效'}
#JWT token验证装饰器
def token_required(f):
"""JWT token验证装饰器"""
@wraps(f)
@@ -57,14 +60,17 @@ def token_required(f):
return f(*args, **kwargs)
return decorated
#验证QQ邮箱格式
def validate_qq_email(email):
"""验证QQ邮箱格式"""
return is_qq_email(email)
#验证密码格式
def validate_password(password):
"""验证密码格式6-20位"""
return 6 <= len(password) <= 20
#发送验证码邮件
@auth_bp.route('/send-verification', methods=['POST'])
def send_verification():
"""发送验证码邮件"""
@@ -120,6 +126,7 @@ def send_verification():
'message': '发送失败,请稍后重试'
}), 500
#验证验证码
@auth_bp.route('/verify-code', methods=['POST'])
def verify_verification_code():
"""验证验证码"""
@@ -150,6 +157,7 @@ def verify_verification_code():
'message': '验证失败,请稍后重试'
}), 500
#用户注册
@auth_bp.route('/register', methods=['POST'])
def register():
"""用户注册(需要先验证邮箱)"""
@@ -253,43 +261,8 @@ def register():
'success': False,
'message': '注册失败,请稍后重试'
}), 500
if existing_user:
return jsonify({
'success': False,
'message': '该账号已被注册'
}), 409
# 创建新用户
password_hash = generate_password_hash(password)
user_data = {
'账号': account,
'密码': password_hash,
'注册时间': datetime.now().isoformat(),
'最后登录': None,
'登录次数': 0,
'用户状态': 'active'
}
result = users_collection.insert_one(user_data)
if result.inserted_id:
return jsonify({
'success': True,
'message': '注册成功!'
}), 201
else:
return jsonify({
'success': False,
'message': '注册失败,请稍后重试'
}), 500
except Exception as e:
return jsonify({
'success': False,
'message': f'服务器错误: {str(e)}'
}), 500
#用户登录
@auth_bp.route('/login', methods=['POST'])
def login():
"""用户登录(支持邮箱+验证码或邮箱+密码)"""
@@ -392,9 +365,10 @@ def login():
}), 500
# 登录成功,创建会话
session['user_id'] = str(user['_id'])
session['account'] = user['账号']
session['logged_in'] = True
hwt = getattr(request, 'hwt', {})
hwt['user_id'] = str(user['_id'])
hwt['account'] = user['账号']
hwt['logged_in'] = True
# 更新登录信息
users_collection.update_one(
@@ -421,6 +395,7 @@ def login():
'message': f'服务器错误: {str(e)}'
}), 500
#用户登出
@auth_bp.route('/logout', methods=['POST'])
def logout():
"""用户登出"""
@@ -437,6 +412,7 @@ def logout():
'message': f'服务器错误: {str(e)}'
}), 500
#检查登录状态
@auth_bp.route('/check', methods=['GET'])
def check_login():
"""检查登录状态"""

View File

@@ -18,15 +18,18 @@ import os
# 验证码存储生产环境建议使用Redis
verification_codes = {}
# 初始化日志
def init_mail(app):
"""初始化邮件配置"""
# 使用smtplib直接发送不需要Flask-Mail
pass
# 生成验证码
def generate_verification_code(length=6):
"""生成验证码"""
return ''.join(random.choices(string.digits, k=length))
# 发送验证邮件
def send_verification_email(email, verification_type='register'):
"""
发送验证邮件
@@ -168,6 +171,7 @@ def send_verification_email(email, verification_type='register'):
'message': '邮件发送失败,请稍后重试'
}
# 验证验证码
def verify_code(email, code):
"""
验证验证码
@@ -221,6 +225,7 @@ def verify_code(email, code):
'type': verification_type
}
# 验证QQ邮箱格式
def is_qq_email(email):
"""
验证是否为QQ邮箱
@@ -239,6 +244,7 @@ def is_qq_email(email):
return domain in qq_domains
# 获取QQ头像URL
def get_qq_avatar_url(email):
"""
根据QQ邮箱获取QQ头像URL
@@ -262,6 +268,7 @@ def get_qq_avatar_url(email):
# 返回QQ头像API URL
return f"http://q1.qlogo.cn/g?b=qq&nk={qq_number}&s=100"
# 清理过期验证码
def cleanup_expired_codes():
"""清理过期的验证码"""
current_time = datetime.now()

View File

@@ -6,7 +6,7 @@ Created by: 神奇万事通
Date: 2025-09-02
"""
from flask import Blueprint, request, jsonify, session, current_app
from flask import Blueprint, request, jsonify, current_app
from datetime import datetime
from bson import ObjectId
import jwt
@@ -14,6 +14,7 @@ from functools import wraps
user_bp = Blueprint('user', __name__)
# 验证JWT token
def verify_token(token):
"""验证JWT token"""
try:
@@ -24,8 +25,9 @@ def verify_token(token):
except jwt.InvalidTokenError:
return {'success': False, 'message': 'Token无效'}
# 登录验证装饰器支持JWT token和hwt
def login_required(f):
"""登录验证装饰器支持JWT token和session"""
"""登录验证装饰器支持JWT token和hwt"""
@wraps(f)
def decorated_function(*args, **kwargs):
# 优先检查JWT token
@@ -38,32 +40,32 @@ def login_required(f):
if result['success']:
request.current_user = result['data']
return f(*args, **kwargs)
# 回退到session验证
if not session.get('logged_in'):
# 回退到hwt验证
hwt = getattr(request, 'hwt', {})
if not hwt.get('logged_in'):
return jsonify({
'success': False,
'message': '请先登录'
}), 401
return f(*args, **kwargs)
return decorated_function
return decorated_function
# 获取用户资料
@user_bp.route('/profile', methods=['GET'])
@login_required
def get_profile():
"""获取用户资料"""
try:
user_id = session.get('user_id')
hwt = getattr(request, 'hwt', {})
user_id = hwt.get('user_id')
users_collection = current_app.mongo.db.userdata
user = users_collection.find_one({'_id': ObjectId(user_id)})
if not user:
return jsonify({
'success': False,
'message': '用户不存在'
}), 404
# 返回用户信息(不包含密码)
profile = {
'account': user['账号'],
@@ -72,18 +74,17 @@ def get_profile():
'login_count': user.get('登录次数', 0),
'status': user.get('用户状态', 'active')
}
return jsonify({
'success': True,
'data': profile
}), 200
except Exception as e:
return jsonify({
'success': False,
'message': f'服务器错误: {str(e)}'
}), 500
# 修改密码
@user_bp.route('/change-password', methods=['POST'])
@login_required
def change_password():
@@ -105,34 +106,28 @@ def change_password():
'message': '新密码长度必须在6-20位之间'
}), 400
user_id = session.get('user_id')
hwt = getattr(request, 'hwt', {})
user_id = hwt.get('user_id')
users_collection = current_app.mongo.db.userdata
user = users_collection.find_one({'_id': ObjectId(user_id)})
if not user:
return jsonify({
'success': False,
'message': '用户不存在'
}), 404
from werkzeug.security import check_password_hash, generate_password_hash
# 验证旧密码
if not check_password_hash(user['密码'], old_password):
return jsonify({
'success': False,
'message': '原密码错误'
}), 401
# 更新密码
new_password_hash = generate_password_hash(new_password)
result = users_collection.update_one(
{'_id': ObjectId(user_id)},
{'$set': {'密码': new_password_hash}}
)
if result.modified_count > 0:
return jsonify({
'success': True,
@@ -143,20 +138,20 @@ def change_password():
'success': False,
'message': '密码修改失败'
}), 500
except Exception as e:
return jsonify({
'success': False,
'message': f'服务器错误: {str(e)}'
}), 500
# 获取用户统计信息
@user_bp.route('/stats', methods=['GET'])
@login_required
def get_user_stats():
"""获取用户统计信息"""
try:
user_id = session.get('user_id')
hwt = getattr(request, 'hwt', {})
user_id = hwt.get('user_id')
# 这里可以添加更多统计信息比如API调用次数等
stats = {
'login_today': 1, # 今日登录次数
@@ -165,18 +160,17 @@ def get_user_stats():
'join_days': 1, # 加入天数
'last_activity': datetime.now().isoformat()
}
return jsonify({
'success': True,
'data': stats
}), 200
except Exception as e:
return jsonify({
'success': False,
'message': f'服务器错误: {str(e)}'
}), 500
# 获取用户游戏数据
@user_bp.route('/game-data', methods=['GET'])
@login_required
def get_user_game_data():
@@ -186,7 +180,8 @@ def get_user_game_data():
if hasattr(request, 'current_user'):
user_id = request.current_user['user_id']
else:
user_id = session.get('user_id')
hwt = getattr(request, 'hwt', {})
user_id = hwt.get('user_id')
users_collection = current_app.mongo.db.userdata
@@ -221,6 +216,7 @@ def get_user_game_data():
'message': f'服务器错误: {str(e)}'
}), 500
# 每日签到
@user_bp.route('/checkin', methods=['POST'])
@login_required
def daily_checkin():
@@ -230,7 +226,8 @@ def daily_checkin():
if hasattr(request, 'current_user'):
user_id = request.current_user['user_id']
else:
user_id = session.get('user_id')
hwt = getattr(request, 'hwt', {})
user_id = hwt.get('user_id')
users_collection = current_app.mongo.db.userdata
@@ -350,6 +347,7 @@ def daily_checkin():
'message': f'服务器错误: {str(e)}'
}), 500
# 删除账户
@user_bp.route('/delete', methods=['POST'])
@login_required
def delete_account():
@@ -364,7 +362,8 @@ def delete_account():
'message': '请输入密码确认删除'
}), 400
user_id = session.get('user_id')
hwt = getattr(request, 'hwt', {})
user_id = hwt.get('user_id')
users_collection = current_app.mongo.db.userdata
user = users_collection.find_one({'_id': ObjectId(user_id)})
@@ -389,7 +388,8 @@ def delete_account():
if result.deleted_count > 0:
# 清除会话
session.clear()
hwt = getattr(request, 'hwt', {})
hwt.clear()
return jsonify({
'success': True,