#!/usr/bin/env python3 """ YouTube to Directus Microsite Simple Flask app to add YouTube videos to Directus media_items """ import sys import os import re import json import logging from datetime import datetime from urllib.parse import urlparse, parse_qs from flask import Flask, render_template, request, jsonify, redirect, url_for from flask_cors import CORS # Add parent directories to path for imports import os parent_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) src_dir = os.path.join(parent_dir, 'src') sys.path.insert(0, parent_dir) sys.path.insert(0, src_dir) from config import DIRECTUS_TOKEN, DIRECTUS_URL from directus_client import DirectusClient from youtube_processor import YouTubeProcessor from youtube_metadata import YouTubeMetadataExtractor app = Flask(__name__) app.secret_key = 'youtube-directus-microsite-secret-key' # Enable CORS for all routes CORS(app, origins='*') # Configure logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) # Initialize services directus_client = DirectusClient() youtube_processor = YouTubeProcessor() metadata_extractor = YouTubeMetadataExtractor() def get_smart_video_info(url): """Get comprehensive video information using smart metadata extraction""" try: metadata = metadata_extractor.get_video_metadata(url) return metadata except Exception as e: logger.error(f"Error extracting video metadata: {e}") return None @app.route('/') def index(): """Main page with YouTube URL form""" return render_template('index.html') @app.route('/add_video', methods=['POST']) def add_video(): """Process YouTube URL and add to Directus with smart metadata extraction""" try: youtube_url = request.form.get('youtube_url', '').strip() custom_title = request.form.get('custom_title', '').strip() if not youtube_url: return jsonify({'error': 'YouTube URL is required'}), 400 # Extract comprehensive video metadata logger.info(f"Extracting metadata for URL: {youtube_url}") video_info = get_smart_video_info(youtube_url) if not video_info: return jsonify({'error': 'Invalid YouTube URL or failed to extract metadata'}), 400 # Use custom title if provided, otherwise use extracted title if custom_title: video_info['title'] = custom_title logger.info(f"Processing video: {video_info['video_id']} - {video_info['title']}") # Parse upload date to proper format if available published_date = None if video_info.get('upload_date'): try: # Try to parse ISO format date from dateutil import parser parsed_date = parser.parse(video_info['upload_date']) published_date = parsed_date.strftime('%Y-%m-%d') except: published_date = None # Create metadata JSON with all extra YouTube data metadata_json = { 'duration': video_info.get('duration'), 'duration_formatted': video_info.get('duration_formatted'), 'view_count': video_info.get('view_count'), 'view_count_formatted': video_info.get('view_count_formatted'), 'like_count': video_info.get('like_count'), 'like_count_formatted': video_info.get('like_count_formatted'), 'comment_count': video_info.get('comment_count'), 'comment_count_formatted': video_info.get('comment_count_formatted'), 'channel_id': video_info.get('channel_id'), 'category': video_info.get('category'), 'keywords': video_info.get('keywords', []), 'is_live': video_info.get('is_live', False), 'is_family_safe': video_info.get('is_family_safe', True), 'original_upload_date': video_info.get('upload_date'), 'last_scraped': datetime.now().isoformat() } # Create media item data with correct field mappings media_item_data = { 'title': video_info['title'], 'url': video_info['canonical_url'], 'type': video_info['type'], 'description': video_info.get('description', ''), 'external_id': video_info['video_id'], # Store YouTube video ID 'author': video_info.get('channel_name', ''), # Channel name in author field 'source_platform': 'YouTube', # Always YouTube for this microsite 'metadata': metadata_json, # All extra data in JSON field 'status': 'published' } # Add published date if we successfully parsed it if published_date: media_item_data['published_date'] = published_date # Add to Directus item_id = directus_client.create_media_item(media_item_data) if item_id: logger.info(f"Successfully created media item: {item_id}") # Try to download and add thumbnail immediately thumbnail_success = False try: thumbnail_data, filename = youtube_processor.download_best_thumbnail(video_info['video_id']) if thumbnail_data and filename: file_id = directus_client.upload_file( thumbnail_data, filename, title=f"YouTube Thumbnail - {video_info['video_id']}" ) if file_id: thumbnail_success = directus_client.update_media_item_thumbnail(item_id, file_id) except Exception as e: logger.warning(f"Failed to add thumbnail immediately: {e}") # Prepare response with rich metadata response_data = { 'success': True, 'item_id': item_id, 'video_id': video_info['video_id'], 'title': video_info['title'], 'description': video_info.get('description', '')[:200] + ('...' if len(video_info.get('description', '')) > 200 else ''), 'channel_name': video_info.get('channel_name', ''), 'duration_formatted': video_info.get('duration_formatted', ''), 'view_count_formatted': video_info.get('view_count_formatted', ''), 'thumbnail_added': thumbnail_success, 'message': f"Successfully added: {video_info['title']}" } return jsonify(response_data) else: return jsonify({'error': 'Failed to create media item in Directus'}), 500 except Exception as e: logger.error(f"Error processing video: {e}") return jsonify({'error': f'Processing error: {str(e)}'}), 500 @app.route('/preview') def preview(): """Preview YouTube video information before adding""" youtube_url = request.args.get('url', '').strip() if not youtube_url: return jsonify({'error': 'URL parameter required'}), 400 video_info = get_smart_video_info(youtube_url) if not video_info: return jsonify({'error': 'Invalid YouTube URL or failed to extract metadata'}), 400 return jsonify({ 'success': True, 'video_info': video_info }) @app.route('/status') def status(): """Check service status""" try: # Test Directus connection test_items = directus_client.get_unprocessed_youtube_items(limit=1) directus_status = 'connected' except Exception as e: directus_status = f'error: {str(e)}' return jsonify({ 'service': 'YouTube to Directus Microsite', 'status': 'running', 'directus': directus_status, 'directus_url': DIRECTUS_URL, 'timestamp': datetime.now().isoformat() }) if __name__ == '__main__': print("🎬 YouTube to Directus Microsite") print("================================") print(f"Directus URL: {DIRECTUS_URL}") print(f"Has Token: {'Yes' if DIRECTUS_TOKEN else 'No'}") print("") print("Starting Flask server on http://localhost:5001") app.run(host='0.0.0.0', port=5001, debug=True)