重新整理项目结构

This commit is contained in:
2025-09-09 13:45:04 +08:00
parent 44a4f1bae1
commit 2b5a6740d4
317 changed files with 1391 additions and 45676 deletions

16
backend/.env Normal file
View File

@@ -0,0 +1,16 @@
# InfoGenie 环境变量配置文件
# 请勿将此文件提交到版本控制系统
# 邮件配置
# 请将下面的邮箱地址替换为您的实际QQ邮箱
MAIL_USERNAME=3205788256@qq.com
MAIL_PASSWORD=szcaxvbftusqddhi
# 数据库配置
MONGO_URI=mongodb://shumengya:tyh%4019900420@47.108.90.0:27018/InfoGenie?authSource=admin
# 应用密钥
SECRET_KEY=infogenie-secret-key-2025
# 环境配置
FLASK_ENV=development

Binary file not shown.

Binary file not shown.

View File

@@ -16,11 +16,8 @@ import secrets
# 导入模块
from modules.auth import auth_bp
from modules.api_60s import api_60s_bp
from modules.user_management import user_bp
from modules.email_service import init_mail
from modules.smallgame import smallgame_bp
from modules.aimodelapp import aimodelapp_bp
from config import Config
@@ -43,10 +40,7 @@ def create_app():
# 注册蓝图
app.register_blueprint(auth_bp, url_prefix='/api/auth')
app.register_blueprint(api_60s_bp, url_prefix='/api/60s')
app.register_blueprint(user_bp, url_prefix='/api/user')
app.register_blueprint(smallgame_bp, url_prefix='/api/smallgame')
app.register_blueprint(aimodelapp_bp, url_prefix='/api/aimodelapp')
# 基础路由
@app.route('/')

View File

@@ -27,6 +27,9 @@ class Config:
SESSION_COOKIE_SECURE = False # 开发环境设为False生产环境设为True
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_SAMESITE = 'Lax'
SESSION_COOKIE_DOMAIN = None # 开发环境设为None生产环境设为具体域名
SESSION_COOKIE_PATH = '/'
SESSION_REFRESH_EACH_REQUEST = True # 每次请求刷新会话过期时间
# 邮件配置
MAIL_SERVER = 'smtp.qq.com'

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,78 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
AI应用模块 - 提供AI应用静态文件服务和目录扫描
Created by: 神奇万事通
Date: 2025-09-02
"""
from flask import Blueprint, jsonify
import os
aimodelapp_bp = Blueprint('aimodelapp', __name__)
@aimodelapp_bp.route('/scan-directories', methods=['GET'])
def scan_directories():
"""扫描aimodelapp目录结构"""
try:
# 获取项目根目录
project_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
ai_directory = os.path.join(project_root, 'frontend', 'aimodelapp')
if not os.path.exists(ai_directory):
return jsonify({
'success': False,
'message': 'aimodelapp目录不存在'
}), 404
apps = []
# 颜色渐变配置
gradient_colors = [
'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)',
'linear-gradient(135deg, #4facfe 0%, #00f2fe 100%)',
'linear-gradient(135deg, #43e97b 0%, #38f9d7 100%)',
'linear-gradient(135deg, #fa709a 0%, #fee140 100%)'
]
# 扫描目录
for i, app_name in enumerate(os.listdir(ai_directory)):
app_path = os.path.join(ai_directory, app_name)
index_path = os.path.join(app_path, 'index.html')
if os.path.isdir(app_path) and os.path.exists(index_path) and not app_name.endswith('.txt'):
# 读取HTML文件获取标题
try:
with open(index_path, 'r', encoding='utf-8') as f:
html_content = f.read()
title_match = html_content.find('<title>')
if title_match != -1:
title_end = html_content.find('</title>', title_match)
if title_end != -1:
title = html_content[title_match + 7:title_end].strip()
else:
title = app_name
else:
title = app_name
except:
title = app_name
apps.append({
'title': title,
'description': f'{app_name}AI应用',
'link': f'/aimodelapp/{app_name}/index.html',
'status': 'active',
'color': gradient_colors[i % len(gradient_colors)]
})
return jsonify({
'success': True,
'apps': apps
})
except Exception as e:
return jsonify({
'success': False,
'message': f'扫描目录时出错: {str(e)}'
}), 500

View File

@@ -1,103 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
60s API模块 - 提供各种实时数据接口
Created by: 神奇万事通
Date: 2025-09-02
"""
from flask import Blueprint, jsonify
import os
api_60s_bp = Blueprint('api_60s', __name__)
@api_60s_bp.route('/scan-directories', methods=['GET'])
def scan_directories():
"""扫描60sapi目录结构"""
try:
# 获取项目根目录
project_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
api_directory = os.path.join(project_root, 'frontend', '60sapi')
if not os.path.exists(api_directory):
return jsonify({
'success': False,
'message': '60sapi目录不存在'
}), 404
categories = []
# 定义分类配置
category_config = {
'热搜榜单': {'color': '#66bb6a'},
'日更资讯': {'color': '#4caf50'},
'实用功能': {'color': '#388e3c'},
'娱乐消遣': {'color': '#66bb6a'}
}
# 颜色渐变配置
gradient_colors = [
'linear-gradient(135deg, #81c784 0%, #66bb6a 100%)',
'linear-gradient(135deg, #a5d6a7 0%, #81c784 100%)',
'linear-gradient(135deg, #c8e6c9 0%, #a5d6a7 100%)',
'linear-gradient(135deg, #66bb6a 0%, #4caf50 100%)',
'linear-gradient(135deg, #4caf50 0%, #388e3c 100%)'
]
# 扫描目录
for category_name in os.listdir(api_directory):
category_path = os.path.join(api_directory, category_name)
if os.path.isdir(category_path) and category_name in category_config:
apis = []
# 扫描分类下的模块
for i, module_name in enumerate(os.listdir(category_path)):
module_path = os.path.join(category_path, module_name)
index_path = os.path.join(module_path, 'index.html')
if os.path.isdir(module_path) and os.path.exists(index_path):
# 读取HTML文件获取标题
try:
with open(index_path, 'r', encoding='utf-8') as f:
html_content = f.read()
title_match = html_content.find('<title>')
if title_match != -1:
title_end = html_content.find('</title>', title_match)
if title_end != -1:
title = html_content[title_match + 7:title_end].strip()
else:
title = module_name
else:
title = module_name
except:
title = module_name
# 根据环境获取基础URL
base_url = 'https://infogenie.api.shumengya.top'
apis.append({
'title': title,
'description': f'{module_name}相关功能',
'link': f'{base_url}/60sapi/{category_name}/{module_name}/index.html',
'status': 'active',
'color': gradient_colors[i % len(gradient_colors)]
})
if apis:
categories.append({
'title': category_name,
'color': category_config[category_name]['color'],
'apis': apis
})
return jsonify({
'success': True,
'categories': categories
})
except Exception as e:
return jsonify({
'success': False,
'message': f'扫描目录时出错: {str(e)}'
}), 500

View File

@@ -10,11 +10,53 @@ from flask import Blueprint, request, jsonify, session, current_app
from werkzeug.security import generate_password_hash, check_password_hash
import hashlib
import re
from datetime import datetime
import jwt
from datetime import datetime, timedelta
from functools import wraps
from .email_service import send_verification_email, verify_code, is_qq_email, get_qq_avatar_url
auth_bp = Blueprint('auth', __name__)
def generate_token(user_data):
"""生成JWT token"""
payload = {
'user_id': user_data['user_id'],
'email': user_data['email'],
'username': user_data['username'],
'exp': datetime.utcnow() + timedelta(days=7), # 7天过期
'iat': datetime.utcnow()
}
return jwt.encode(payload, current_app.config['SECRET_KEY'], algorithm='HS256')
def verify_token(token):
"""验证JWT token"""
try:
payload = jwt.decode(token, current_app.config['SECRET_KEY'], algorithms=['HS256'])
return {'success': True, 'data': payload}
except jwt.ExpiredSignatureError:
return {'success': False, 'message': 'Token已过期'}
except jwt.InvalidTokenError:
return {'success': False, 'message': 'Token无效'}
def token_required(f):
"""JWT token验证装饰器"""
@wraps(f)
def decorated(*args, **kwargs):
token = request.headers.get('Authorization')
if not token:
return jsonify({'success': False, 'message': '缺少认证token'}), 401
if token.startswith('Bearer '):
token = token[7:]
result = verify_token(token)
if not result['success']:
return jsonify({'success': False, 'message': result['message']}), 401
request.current_user = result['data']
return f(*args, **kwargs)
return decorated
def validate_qq_email(email):
"""验证QQ邮箱格式"""
return is_qq_email(email)
@@ -313,16 +355,18 @@ def login():
}
)
# 设置会话
session['user_id'] = str(user['_id'])
session['email'] = email
session['username'] = user.get('用户名', '')
session['logged_in'] = True
session.permanent = True
# 生成JWT token
user_data = {
'user_id': str(user['_id']),
'email': email,
'username': user.get('用户名', '')
}
token = generate_token(user_data)
return jsonify({
'success': True,
'message': '登录成功!',
'token': token,
'user': {
'id': str(user['_id']),
'email': email,
@@ -373,17 +417,11 @@ def login():
def logout():
"""用户登出"""
try:
if 'logged_in' in session:
session.clear()
return jsonify({
'success': True,
'message': '已成功登出'
}), 200
else:
return jsonify({
'success': False,
'message': '用户未登录'
}), 401
# JWT是无状态的客户端删除token即可
return jsonify({
'success': True,
'message': '已成功登出'
}), 200
except Exception as e:
return jsonify({
@@ -395,14 +433,26 @@ def logout():
def check_login():
"""检查登录状态"""
try:
if session.get('logged_in') and session.get('user_id'):
token = request.headers.get('Authorization')
if not token:
return jsonify({
'success': True,
'logged_in': False
}), 200
if token.startswith('Bearer '):
token = token[7:]
result = verify_token(token)
if result['success']:
user_data = result['data']
return jsonify({
'success': True,
'logged_in': True,
'user': {
'id': session.get('user_id'),
'email': session.get('email'),
'username': session.get('username')
'id': user_data['user_id'],
'email': user_data['email'],
'username': user_data['username']
}
}), 200
else:

View File

@@ -1,78 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
小游戏模块 - 提供小游戏静态文件服务和目录扫描
Created by: 神奇万事通
Date: 2025-09-02
"""
from flask import Blueprint, jsonify
import os
smallgame_bp = Blueprint('smallgame', __name__)
@smallgame_bp.route('/scan-directories', methods=['GET'])
def scan_directories():
"""扫描smallgame目录结构"""
try:
# 获取项目根目录
project_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
game_directory = os.path.join(project_root, 'frontend', 'smallgame')
if not os.path.exists(game_directory):
return jsonify({
'success': False,
'message': 'smallgame目录不存在'
}), 404
games = []
# 颜色渐变配置
gradient_colors = [
'linear-gradient(135deg, #ff9a9e 0%, #fecfef 100%)',
'linear-gradient(135deg, #a8edea 0%, #fed6e3 100%)',
'linear-gradient(135deg, #ffecd2 0%, #fcb69f 100%)',
'linear-gradient(135deg, #ff8a80 0%, #ffab91 100%)',
'linear-gradient(135deg, #81c784 0%, #aed581 100%)'
]
# 扫描目录
for i, game_name in enumerate(os.listdir(game_directory)):
game_path = os.path.join(game_directory, game_name)
index_path = os.path.join(game_path, 'index.html')
if os.path.isdir(game_path) and os.path.exists(index_path) and not game_name.endswith('.txt'):
# 读取HTML文件获取标题
try:
with open(index_path, 'r', encoding='utf-8') as f:
html_content = f.read()
title_match = html_content.find('<title>')
if title_match != -1:
title_end = html_content.find('</title>', title_match)
if title_end != -1:
title = html_content[title_match + 7:title_end].strip()
else:
title = game_name
else:
title = game_name
except:
title = game_name
games.append({
'title': title,
'description': f'{game_name}小游戏',
'link': f'/smallgame/{game_name}/index.html',
'status': 'active',
'color': gradient_colors[i % len(gradient_colors)]
})
return jsonify({
'success': True,
'games': games
})
except Exception as e:
return jsonify({
'success': False,
'message': f'扫描目录时出错: {str(e)}'
}), 500

View File

@@ -10,6 +10,9 @@ pymongo==4.5.0
# 密码加密
Werkzeug==2.3.7
# JWT认证
PyJWT==2.8.0
# HTTP请求
requests==2.31.0