File size: 5,130 Bytes
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
141
import os
import sys
import locale
from flask import Flask
from flask_cors import CORS
from flask_jwt_extended import JWTManager
from apscheduler.schedulers.background import BackgroundScheduler
import atexit
# Import for job handling
import uuid
from concurrent.futures import ThreadPoolExecutor

from config import Config
from utils.database import init_supabase
from utils.cookies import setup_secure_cookies, configure_jwt_with_cookies
from scheduler.task_scheduler import init_scheduler

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"],
            "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)
    
    # Initialize scheduler
    if app.config['SCHEDULER_ENABLED']:
        app.scheduler = BackgroundScheduler()
        init_scheduler(app.scheduler, app.supabase)
        app.scheduler.start()
        
        # Shut down the scheduler when exiting the app
        atexit.register(lambda: app.scheduler.shutdown())
    
    # 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']
    )