File size: 4,980 Bytes
25f22bf
 
 
 
 
 
 
 
 
 
b29b905
 
 
 
25f22bf
 
b29b905
25f22bf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
import os
import sys
import locale
from flask import Flask
from flask_cors import CORS
from flask_jwt_extended import JWTManager
# Import for job handling
import uuid
from concurrent.futures import ThreadPoolExecutor

# Use relative import for the Config class to work with Hugging Face Spaces
from backend.config import Config
from backend.utils.database import init_supabase
from backend.utils.cookies import setup_secure_cookies, configure_jwt_with_cookies

# Celery imports
from backend.celery_app import celery

def setup_unicode_environment():
    """Setup Unicode environment for proper character handling."""
    try:
        # Set environment variables for UTF-8 support
        os.environ['PYTHONIOENCODING'] = 'utf-8'
        os.environ['PYTHONUTF8'] = '1'
        
        # Set locale to UTF-8 if available
        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
        
        # Set stdout/stderr encoding to UTF-8 if possible
        if hasattr(sys.stdout, 'reconfigure'):
            sys.stdout.reconfigure(encoding='utf-8', errors='replace')
            sys.stderr.reconfigure(encoding='utf-8', errors='replace')
        
        # Log to app logger instead of print
        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 first
    setup_unicode_environment()
    
    app = Flask(__name__)
    app.config.from_object(Config)
    
    # Disable strict slashes to prevent redirects
    app.url_map.strict_slashes = False
    
    # Initialize CORS with specific configuration
    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.hf.space"
            ],
            "methods": ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
            "allow_headers": ["Content-Type", "Authorization"],
            "supports_credentials": True
        }
    })
    
    # Setup secure cookies
    app = setup_secure_cookies(app)
    
    # Initialize JWT with cookie support
    jwt = configure_jwt_with_cookies(app)
    
    # Initialize Supabase client
    app.supabase = init_supabase(app.config['SUPABASE_URL'], app.config['SUPABASE_KEY'])
    
    # Initialize a simple in-memory job store for tracking async tasks
    # In production, you'd use a database or Redis for this
    app.job_store = {}
    
    # Initialize a ThreadPoolExecutor for running background tasks
    # In production, you'd use a proper task queue like Celery
    app.executor = ThreadPoolExecutor(max_workers=4)
    
    # Register blueprints
    from api.auth import auth_bp
    from api.sources import sources_bp
    from api.accounts import accounts_bp
    from api.posts import posts_bp
    from 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')
    
    # Health check endpoint
    @app.route('/health')
    def health_check():
        return {'status': 'healthy', 'message': 'Lin backend is running'}, 200
    
    # Add database connection check endpoint
    @app.route('/api/health')
    def api_health_check():
        """Enhanced health check that includes database connection."""
        try:
            from 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']
    )