Spaces:
Sleeping
Sleeping
Update flask_app.py
Browse files- flask_app.py +98 -9
flask_app.py
CHANGED
|
@@ -35,20 +35,32 @@ from admin_module import admin_manager, admin_required
|
|
| 35 |
app = Flask(__name__)
|
| 36 |
|
| 37 |
# Configuration for sessions
|
| 38 |
-
app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY', 'dev-key-change-in-production')
|
| 39 |
app.config['SESSION_TYPE'] = 'filesystem'
|
| 40 |
app.config['SESSION_PERMANENT'] = False
|
| 41 |
app.config['SESSION_USE_SIGNER'] = True
|
| 42 |
app.config['SESSION_KEY_PREFIX'] = 'englishhelper:'
|
|
|
|
| 43 |
|
| 44 |
Session(app)
|
| 45 |
|
| 46 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 47 |
def initialize_database():
|
| 48 |
init_db()
|
| 49 |
|
| 50 |
-
#
|
| 51 |
-
initialize_database()
|
| 52 |
|
| 53 |
# Token tracking helper function
|
| 54 |
def track_token_usage(user_id, provider, input_tokens, output_tokens, operation):
|
|
@@ -134,13 +146,23 @@ def tts_proxy():
|
|
| 134 |
text = data.get('text', '')
|
| 135 |
tld = data.get('tld', 'co.uk')
|
| 136 |
if not text: return jsonify({"error": "No text provided"}), 400
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 137 |
try:
|
|
|
|
|
|
|
|
|
|
| 138 |
tts = gTTS(text=text, lang='en', tld=tld)
|
| 139 |
mp3_fp = io.BytesIO()
|
| 140 |
tts.write_to_fp(mp3_fp)
|
| 141 |
mp3_fp.seek(0)
|
|
|
|
| 142 |
return send_file(mp3_fp, mimetype='audio/mpeg')
|
| 143 |
except Exception as e:
|
|
|
|
| 144 |
return jsonify({"error": f"Failed to generate audio via gTTS: {e}"}), 500
|
| 145 |
|
| 146 |
# Primeira função explain_proxy removida - duplicata
|
|
@@ -332,16 +354,51 @@ def register():
|
|
| 332 |
result = create_user(email, password)
|
| 333 |
|
| 334 |
if result['success']:
|
| 335 |
-
#
|
| 336 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 337 |
return jsonify({
|
| 338 |
'message': 'Registration successful! Please check your email to confirm your account.',
|
| 339 |
-
'email_sent': True
|
|
|
|
| 340 |
}), 201
|
| 341 |
else:
|
| 342 |
return jsonify({
|
| 343 |
'message': 'Registration successful! However, we could not send the confirmation email. Please contact support.',
|
| 344 |
-
'email_sent': False
|
|
|
|
| 345 |
}), 201
|
| 346 |
else:
|
| 347 |
return jsonify({'error': result['message']}), 400
|
|
@@ -980,9 +1037,14 @@ def admin_login():
|
|
| 980 |
username = data.get('username')
|
| 981 |
password = data.get('password')
|
| 982 |
|
|
|
|
|
|
|
| 983 |
if admin_manager.login_admin(username, password):
|
|
|
|
|
|
|
| 984 |
return jsonify({'success': True, 'message': 'Admin logged in successfully'})
|
| 985 |
else:
|
|
|
|
| 986 |
return jsonify({'success': False, 'error': 'Invalid credentials'}), 401
|
| 987 |
|
| 988 |
except Exception as e:
|
|
@@ -1005,14 +1067,41 @@ def admin_check():
|
|
| 1005 |
"""Check admin authentication status"""
|
| 1006 |
try:
|
| 1007 |
is_authenticated = admin_manager.is_admin_logged_in()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1008 |
return jsonify({
|
| 1009 |
'authenticated': is_authenticated,
|
| 1010 |
-
'username':
|
|
|
|
|
|
|
| 1011 |
})
|
| 1012 |
except Exception as e:
|
| 1013 |
print(f"Admin check error: {e}")
|
| 1014 |
return jsonify({'authenticated': False})
|
| 1015 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1016 |
@app.route('/admin/dashboard', methods=['GET'])
|
| 1017 |
@admin_required
|
| 1018 |
def admin_dashboard():
|
|
|
|
| 35 |
app = Flask(__name__)
|
| 36 |
|
| 37 |
# Configuration for sessions
|
| 38 |
+
app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY', 'dev-key-change-in-production-hf-spaces')
|
| 39 |
app.config['SESSION_TYPE'] = 'filesystem'
|
| 40 |
app.config['SESSION_PERMANENT'] = False
|
| 41 |
app.config['SESSION_USE_SIGNER'] = True
|
| 42 |
app.config['SESSION_KEY_PREFIX'] = 'englishhelper:'
|
| 43 |
+
app.config['PERMANENT_SESSION_LIFETIME'] = 86400 # 24 hours
|
| 44 |
|
| 45 |
Session(app)
|
| 46 |
|
| 47 |
+
# Print session config for debugging
|
| 48 |
+
print(f"Session config - SECRET_KEY length: {len(app.config['SECRET_KEY'])}")
|
| 49 |
+
print(f"Session config - SESSION_TYPE: {app.config['SESSION_TYPE']}")
|
| 50 |
+
print(f"Session config - Working directory: {os.getcwd()}")
|
| 51 |
+
|
| 52 |
+
# Ensure flask_session directory exists
|
| 53 |
+
import os
|
| 54 |
+
session_dir = 'flask_session'
|
| 55 |
+
if not os.path.exists(session_dir):
|
| 56 |
+
os.makedirs(session_dir)
|
| 57 |
+
print(f"Created session directory: {session_dir}")
|
| 58 |
+
|
| 59 |
+
# Database initialization (handled by app.py)
|
| 60 |
def initialize_database():
|
| 61 |
init_db()
|
| 62 |
|
| 63 |
+
# Note: Database initialization moved to app.py to avoid conflicts
|
|
|
|
| 64 |
|
| 65 |
# Token tracking helper function
|
| 66 |
def track_token_usage(user_id, provider, input_tokens, output_tokens, operation):
|
|
|
|
| 146 |
text = data.get('text', '')
|
| 147 |
tld = data.get('tld', 'co.uk')
|
| 148 |
if not text: return jsonify({"error": "No text provided"}), 400
|
| 149 |
+
|
| 150 |
+
# Validar comprimento do texto (10000 caracteres max)
|
| 151 |
+
if len(text) > 10000:
|
| 152 |
+
return jsonify({"error": "Text is too long. Maximum 10,000 characters allowed."}), 400
|
| 153 |
+
|
| 154 |
try:
|
| 155 |
+
# Log para debug
|
| 156 |
+
print(f"TTS request: {len(text)} characters, tld: {tld}")
|
| 157 |
+
|
| 158 |
tts = gTTS(text=text, lang='en', tld=tld)
|
| 159 |
mp3_fp = io.BytesIO()
|
| 160 |
tts.write_to_fp(mp3_fp)
|
| 161 |
mp3_fp.seek(0)
|
| 162 |
+
|
| 163 |
return send_file(mp3_fp, mimetype='audio/mpeg')
|
| 164 |
except Exception as e:
|
| 165 |
+
print(f"TTS Error: {e}")
|
| 166 |
return jsonify({"error": f"Failed to generate audio via gTTS: {e}"}), 500
|
| 167 |
|
| 168 |
# Primeira função explain_proxy removida - duplicata
|
|
|
|
| 354 |
result = create_user(email, password)
|
| 355 |
|
| 356 |
if result['success']:
|
| 357 |
+
# Try to send confirmation email (non-blocking for HF Spaces)
|
| 358 |
+
email_sent = False
|
| 359 |
+
try:
|
| 360 |
+
# Use a timeout to prevent hanging
|
| 361 |
+
import threading
|
| 362 |
+
import time
|
| 363 |
+
|
| 364 |
+
def send_email_async():
|
| 365 |
+
nonlocal email_sent
|
| 366 |
+
try:
|
| 367 |
+
email_sent = send_confirmation_email(email, result['confirmation_token'])
|
| 368 |
+
except:
|
| 369 |
+
email_sent = False
|
| 370 |
+
|
| 371 |
+
# Start email sending in background with timeout
|
| 372 |
+
email_thread = threading.Thread(target=send_email_async)
|
| 373 |
+
email_thread.daemon = True
|
| 374 |
+
email_thread.start()
|
| 375 |
+
email_thread.join(timeout=5) # 5 second timeout
|
| 376 |
+
|
| 377 |
+
except Exception as e:
|
| 378 |
+
print(f"Email sending timeout or error: {e}")
|
| 379 |
+
email_sent = False
|
| 380 |
+
|
| 381 |
+
# Return success message based on auto-confirmation and email status
|
| 382 |
+
auto_confirmed = result.get('auto_confirmed', False)
|
| 383 |
+
|
| 384 |
+
if auto_confirmed:
|
| 385 |
+
return jsonify({
|
| 386 |
+
'message': 'Registration successful! Your account is ready to use - you can log in immediately.',
|
| 387 |
+
'email_sent': email_sent,
|
| 388 |
+
'auto_confirmed': True,
|
| 389 |
+
'note': 'Email confirmation is disabled in demo mode.'
|
| 390 |
+
}), 201
|
| 391 |
+
elif email_sent:
|
| 392 |
return jsonify({
|
| 393 |
'message': 'Registration successful! Please check your email to confirm your account.',
|
| 394 |
+
'email_sent': True,
|
| 395 |
+
'auto_confirmed': False
|
| 396 |
}), 201
|
| 397 |
else:
|
| 398 |
return jsonify({
|
| 399 |
'message': 'Registration successful! However, we could not send the confirmation email. Please contact support.',
|
| 400 |
+
'email_sent': False,
|
| 401 |
+
'auto_confirmed': False
|
| 402 |
}), 201
|
| 403 |
else:
|
| 404 |
return jsonify({'error': result['message']}), 400
|
|
|
|
| 1037 |
username = data.get('username')
|
| 1038 |
password = data.get('password')
|
| 1039 |
|
| 1040 |
+
print(f"Admin login attempt - Username: {username}")
|
| 1041 |
+
|
| 1042 |
if admin_manager.login_admin(username, password):
|
| 1043 |
+
print(f"Admin login successful - Session ID: {session.get('_id', 'no-id')}")
|
| 1044 |
+
print(f"Session data after login: {dict(session)}")
|
| 1045 |
return jsonify({'success': True, 'message': 'Admin logged in successfully'})
|
| 1046 |
else:
|
| 1047 |
+
print(f"Admin login failed - Invalid credentials for: {username}")
|
| 1048 |
return jsonify({'success': False, 'error': 'Invalid credentials'}), 401
|
| 1049 |
|
| 1050 |
except Exception as e:
|
|
|
|
| 1067 |
"""Check admin authentication status"""
|
| 1068 |
try:
|
| 1069 |
is_authenticated = admin_manager.is_admin_logged_in()
|
| 1070 |
+
username = session.get('admin_username')
|
| 1071 |
+
|
| 1072 |
+
print(f"Admin check - Authenticated: {is_authenticated}, Username: {username}")
|
| 1073 |
+
print(f"Current session data: {dict(session)}")
|
| 1074 |
+
print(f"Session ID: {session.get('_id', 'no-session-id')}")
|
| 1075 |
+
|
| 1076 |
return jsonify({
|
| 1077 |
'authenticated': is_authenticated,
|
| 1078 |
+
'username': username if is_authenticated else None,
|
| 1079 |
+
'session_id': session.get('_id', 'no-session-id'),
|
| 1080 |
+
'debug_session_keys': list(session.keys())
|
| 1081 |
})
|
| 1082 |
except Exception as e:
|
| 1083 |
print(f"Admin check error: {e}")
|
| 1084 |
return jsonify({'authenticated': False})
|
| 1085 |
|
| 1086 |
+
# Debug route to test sessions
|
| 1087 |
+
@app.route('/admin/debug-session', methods=['GET', 'POST'])
|
| 1088 |
+
def debug_session():
|
| 1089 |
+
"""Debug session functionality"""
|
| 1090 |
+
if request.method == 'POST':
|
| 1091 |
+
session['debug_test'] = 'session_working'
|
| 1092 |
+
session.permanent = True
|
| 1093 |
+
return jsonify({
|
| 1094 |
+
'message': 'Session test value set',
|
| 1095 |
+
'session_data': dict(session)
|
| 1096 |
+
})
|
| 1097 |
+
else:
|
| 1098 |
+
test_value = session.get('debug_test', 'not_found')
|
| 1099 |
+
return jsonify({
|
| 1100 |
+
'test_value': test_value,
|
| 1101 |
+
'session_data': dict(session),
|
| 1102 |
+
'session_id': session.get('_id', 'no-session-id')
|
| 1103 |
+
})
|
| 1104 |
+
|
| 1105 |
@app.route('/admin/dashboard', methods=['GET'])
|
| 1106 |
@admin_required
|
| 1107 |
def admin_dashboard():
|