|
import os |
|
import sys |
|
import locale |
|
from flask import Flask, send_from_directory, request |
|
from flask_cors import CORS |
|
from flask_jwt_extended import JWTManager |
|
|
|
import uuid |
|
from concurrent.futures import ThreadPoolExecutor |
|
|
|
|
|
from backend.config import Config |
|
from backend.utils.database import init_supabase |
|
from backend.utils.cookies import setup_secure_cookies, configure_jwt_with_cookies |
|
|
|
|
|
from backend.celery_app import celery |
|
|
|
def setup_unicode_environment(): |
|
"""Setup Unicode environment for proper character handling.""" |
|
try: |
|
|
|
os.environ['PYTHONIOENCODING'] = 'utf-8' |
|
os.environ['PYTHONUTF8'] = '1' |
|
|
|
|
|
try: |
|
locale.setlocale(locale.LC_ALL, 'C.UTF-8') |
|
except locale.Error: |
|
try: |
|
locale.setlocale(locale.LC_ALL, 'en_US.UTF-8') |
|
except locale.Error: |
|
try: |
|
locale.setlocale(locale.LC_ALL, '') |
|
except locale.Error: |
|
pass |
|
|
|
|
|
if hasattr(sys.stdout, 'reconfigure'): |
|
sys.stdout.reconfigure(encoding='utf-8', errors='replace') |
|
sys.stderr.reconfigure(encoding='utf-8', errors='replace') |
|
|
|
|
|
if 'app' in globals(): |
|
app.logger.info("Unicode environment setup completed") |
|
except Exception as e: |
|
if 'app' in globals(): |
|
app.logger.warning(f"Unicode setup failed: {str(e)}") |
|
|
|
def create_app(): |
|
"""Create and configure the Flask application.""" |
|
|
|
setup_unicode_environment() |
|
|
|
app = Flask(__name__, static_folder='../frontend/dist') |
|
app.config.from_object(Config) |
|
|
|
|
|
app.url_map.strict_slashes = False |
|
|
|
|
|
CORS(app, resources={ |
|
r"/api/*": { |
|
"origins": [ |
|
"http://localhost:3000", |
|
"http://localhost:5000", |
|
"http://127.0.0.1:3000", |
|
"http://127.0.0.1:5000", |
|
"http://192.168.1.4:3000", |
|
"https://zelyanoth-lin-cbfcff2.hf.space" |
|
], |
|
"methods": ["GET", "POST", "PUT", "DELETE", "OPTIONS"], |
|
"allow_headers": ["Content-Type", "Authorization", "X-Requested-With"], |
|
"supports_credentials": True, |
|
"max_age": 86400 |
|
} |
|
}) |
|
|
|
|
|
@app.after_request |
|
def add_cors_headers(response): |
|
"""Add CORS headers to all responses.""" |
|
|
|
origin = request.headers.get('Origin', '') |
|
|
|
|
|
allowed_origins = [ |
|
"http://localhost:3000", |
|
"http://localhost:5000", |
|
"http://127.0.0.1:3000", |
|
"http://127.0.0.1:5000", |
|
"http://192.168.1.4:3000", |
|
"https://zelyanoth-lin-cbfcff2.hf.space" |
|
] |
|
|
|
if origin in allowed_origins: |
|
response.headers.add('Access-Control-Allow-Origin', origin) |
|
response.headers.add('Access-Control-Allow-Credentials', 'true') |
|
response.headers.add('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS') |
|
response.headers.add('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Requested-With') |
|
|
|
return response |
|
|
|
|
|
app = setup_secure_cookies(app) |
|
|
|
|
|
jwt = configure_jwt_with_cookies(app) |
|
|
|
|
|
app.supabase = init_supabase(app.config['SUPABASE_URL'], app.config['SUPABASE_KEY']) |
|
|
|
|
|
|
|
app.job_store = {} |
|
|
|
|
|
|
|
app.executor = ThreadPoolExecutor(max_workers=4) |
|
|
|
|
|
from backend.api.auth import auth_bp |
|
from backend.api.sources import sources_bp |
|
from backend.api.accounts import accounts_bp |
|
from backend.api.posts import posts_bp |
|
from backend.api.schedules import schedules_bp |
|
|
|
app.register_blueprint(auth_bp, url_prefix='/api/auth') |
|
app.register_blueprint(sources_bp, url_prefix='/api/sources') |
|
app.register_blueprint(accounts_bp, url_prefix='/api/accounts') |
|
app.register_blueprint(posts_bp, url_prefix='/api/posts') |
|
app.register_blueprint(schedules_bp, url_prefix='/api/schedules') |
|
|
|
|
|
@app.route('/', defaults={'path': ''}) |
|
@app.route('/<path:path>') |
|
def serve_frontend(path): |
|
|
|
if path != "" and os.path.exists(os.path.join(app.static_folder, path)): |
|
return send_from_directory(app.static_folder, path) |
|
|
|
elif path.startswith('api/'): |
|
return {'error': 'Not found'}, 404 |
|
|
|
else: |
|
return send_from_directory(app.static_folder, 'index.html') |
|
|
|
|
|
@app.route('/health') |
|
def health_check(): |
|
return {'status': 'healthy', 'message': 'Lin backend is running'}, 200 |
|
|
|
|
|
@app.route('/api/health') |
|
def api_health_check(): |
|
"""Enhanced health check that includes database connection.""" |
|
try: |
|
from backend.utils.database import check_database_connection |
|
db_connected = check_database_connection(app.supabase) |
|
return { |
|
'status': 'healthy' if db_connected else 'degraded', |
|
'database': 'connected' if db_connected else 'disconnected', |
|
'message': 'Lin backend is running' if db_connected else 'Database connection issues' |
|
}, 200 if db_connected else 503 |
|
except Exception as e: |
|
return { |
|
'status': 'unhealthy', |
|
'database': 'error', |
|
'message': f'Health check failed: {str(e)}' |
|
}, 503 |
|
|
|
return app |
|
|
|
if __name__ == '__main__': |
|
app = create_app() |
|
app.run( |
|
host='0.0.0.0', |
|
port=int(os.environ.get('PORT', 5000)), |
|
debug=app.config['DEBUG'] |
|
) |