"""
viewer_server.py — Application Entrypoint
This file was refactored from a 2800-line monolith into a clean entrypoint.
All business logic has been moved to the `backend/` package:
backend/
├── __init__.py ← App Factory (create_app)
├── config.py ← All config & environment variables
├── api/ ← Flask Blueprints (routes/controllers)
│ ├── auth.py
│ ├── books.py
│ ├── payment.py
│ ├── translate.py
│ ├── epub.py
│ └── developer.py
├── services/ ← Business logic layer
│ ├── auth_service.py
│ ├── book_service.py
│ ├── payment_service.py
│ ├── email_service.py
│ ├── epub_service.py
│ └── translation.py
├── database/
│ └── db_manager.py ← DB connections, circuit breaker, caches
├── core/
│ ├── security.py ← JWT, bcrypt helpers
│ ├── decorators.py ← @jwt_required, @require_api_key_auth
│ └── rate_limit.py ← IP rate limiters
└── workers/
└── email_worker.py ← Background IMAP/Gmail email polling
To run the server:
python viewer_server.py
Or with gunicorn:
gunicorn -w 4 -b 0.0.0.0:5051 "viewer_server:app"
"""
import logging
import sys
import traceback
from flask import jsonify
from backend.core.logger import setup_logger
logger = setup_logger("server")
from backend import create_app
app = create_app()
@app.errorhandler(Exception)
def handle_exception(e):
"""Global unhandled exception handler to output clean JSON in production."""
# Log the complete stack trace
error_msg = f"Unhandled exception encountered: {str(e)}"
stack_trace = traceback.format_exc()
logger.error(error_msg)
logger.error(stack_trace)
# Trigger asynchronous alert email to Admin
try:
from backend.services.alert_service import send_alert_to_admin
subject = f"Lỗi nghiêm trọng (500 Internal Error): {str(e)[:50]}"
body = f"Đã xảy ra lỗi chưa xử lý trên server:
Lỗi: {str(e)}
Stack Trace:
{stack_trace.replace(chr(10), '
')}"
send_alert_to_admin("critical_error", subject, body)
except Exception as alert_err:
logger.error(f"Failed to trigger alert email for exception: {alert_err}")
# Return JSON response instead of HTML traceback page
return jsonify({
"error": "Internal Server Error. Please contact administrator.",
"success": False
}), 500
@app.route("/api/temp-db-fix", methods=["GET"])
def temp_db_fix():
from flask import request
secret = request.args.get("secret")
if secret != "super_secret_db_fix_2026":
return "Unauthorized", 403
import os
import psycopg2
url = os.environ.get("DATABASE_URL")
if not url:
return "DATABASE_URL environment variable is missing", 500
logs = []
try:
conn = psycopg2.connect(url)
cursor = conn.cursor()
# 1. Clean up user 75
tables_to_clean = [
"refresh_tokens", "bookshelf", "reading_history", "password_reset_tokens",
"api_keys", "api_usage", "translation_history", "vocabulary",
"user_settings", "usage_tracking", "personal_notifications", "login_history"
]
for tbl in tables_to_clean:
try:
cursor.execute(f"DELETE FROM {tbl} WHERE user_id = 75")
logs.append(f"✔ Cleaned {tbl} for user_id = 75")
except Exception as e:
logs.append(f"ℹ Could not clean {tbl} for user_id = 75: {e}")
try:
cursor.execute("DELETE FROM users WHERE id = 75")
logs.append("✔ Deleted user 75 from users table")
except Exception as e:
logs.append(f"❌ Failed to delete user 75: {e}")
# 2. Link VIP user congkx123789 to Gmail
cursor.execute("SELECT id, username, email, vip_status FROM users WHERE username = %s OR id = 100", ("congkx123789",))
vip_user = cursor.fetchone()
if vip_user:
vip_id = vip_user[0]
cursor.execute("""
UPDATE users
SET email = %s,
google_id = NULL,
email_verified = 1
WHERE id = %s
""", ("havucong25@gmail.com", vip_id))
logs.append(f"✔ Linked VIP user {vip_user[1]} (ID {vip_id}) to havucong25@gmail.com")
else:
logs.append("❌ VIP user congkx123789 not found in database")
conn.commit()
conn.close()
return jsonify({"success": True, "logs": logs})
except Exception as e:
return jsonify({"success": False, "error": str(e), "logs": logs})
if __name__ == "__main__":
logger.info("🚀 Server đang khởi động tại: http://localhost:5051")
app.run(host="0.0.0.0", port=5051, debug=False, threaded=True)