#!/usr/bin/env python3 """ Paid Content Service Health Check Standalone script to check the health of all paid content services. Designed to be run via systemd timer every 4 hours. """ import sys import os import asyncio from datetime import datetime # Add parent directory to path for imports sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from modules.paid_content import ( PaidContentDBAdapter, PaidContentAPIClient, FanslyDirectClient, YouTubeClient, TwitchClient ) from modules.unified_database import UnifiedDatabase def log(message: str, level: str = "info"): """Simple logging to stdout""" timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") print(f"[{timestamp}] [{level.upper()}] {message}") async def check_service_health(service: dict, pc_db: PaidContentDBAdapter) -> dict: """Check health of a single service""" service_id = service['id'] health = {'status': 'unknown', 'message': ''} try: if service_id == 'youtube': youtube = YouTubeClient() if youtube.is_available(): health = {'status': 'healthy', 'message': 'yt-dlp is available'} else: health = {'status': 'down', 'message': 'yt-dlp not found'} elif service_id == 'twitch': twitch = TwitchClient() if twitch.is_available(): health = {'status': 'healthy', 'message': 'yt-dlp is available for Twitch'} else: health = {'status': 'down', 'message': 'yt-dlp not found'} elif service_id == 'fansly_direct': auth_token = service.get('session_cookie') if not auth_token: health = {'status': 'down', 'message': 'Auth token not configured'} else: client = FanslyDirectClient(auth_token=auth_token) try: result = await client.check_auth() if result.get('valid'): health = { 'status': 'healthy', 'message': f"Connected as {result.get('username', 'unknown')}" } else: health = {'status': 'down', 'message': result.get('error', 'Auth failed')} finally: await client.close() else: # Coomer/Kemono services client = PaidContentAPIClient( service_id, session_cookie=service.get('session_cookie'), base_url=service.get('base_url') ) try: health = await client.check_health() finally: await client.close() # Update database pc_db.update_service(service_id, { 'health_status': health.get('status', 'unknown'), 'last_health_check': datetime.now().isoformat() }) return {'service_id': service_id, **health} except Exception as e: log(f"Health check failed for {service_id}: {e}", "error") return {'service_id': service_id, 'status': 'error', 'message': str(e)} async def main(): """Main health check routine""" log("Starting paid content service health check") try: # Initialize database db = UnifiedDatabase() pc_db = PaidContentDBAdapter(db) # Get all services services = pc_db.get_services() if not services: log("No services configured", "warning") return 0 log(f"Checking {len(services)} services...") # Check each service results = [] for service in services: result = await check_service_health(service, pc_db) results.append(result) status_icon = "✓" if result['status'] == 'healthy' else "✗" log(f" {status_icon} {result['service_id']}: {result['status']} - {result.get('message', '')}") # Summary healthy = sum(1 for r in results if r['status'] == 'healthy') total = len(results) log(f"Health check complete: {healthy}/{total} services healthy") return 0 if healthy == total else 1 except Exception as e: log(f"Health check failed: {e}", "error") return 1 if __name__ == "__main__": exit_code = asyncio.run(main()) sys.exit(exit_code)