49 lines
3.5 KiB
JSON
49 lines
3.5 KiB
JSON
{
|
|
"flow_config": {
|
|
"name": "YouTube Thumbnail Auto-Population",
|
|
"description": "Automatically extract and populate YouTube thumbnails when media_items are created/updated with YouTube type",
|
|
"status": "active",
|
|
"icon": "smart_display",
|
|
"color": "#FF0000",
|
|
"trigger": {
|
|
"type": "event",
|
|
"event": "items.update",
|
|
"collections": ["media_items"],
|
|
"condition": {
|
|
"$or": [
|
|
{ "type": { "_eq": "youtube_video" } },
|
|
{ "type": { "_eq": "youtube" } }
|
|
]
|
|
}
|
|
},
|
|
"operations": [
|
|
{
|
|
"id": "extract_video_id",
|
|
"type": "exec",
|
|
"operation": "javascript",
|
|
"options": {
|
|
"code": "// Extract YouTube video ID from URL\nfunction extractYouTubeId(url) {\n if (!url) return null;\n \n // Handle different YouTube URL formats\n const patterns = [\n /(?:youtube\\.com\\/watch\\?v=)([a-zA-Z0-9_-]{11})/,\n /(?:youtu\\.be\\/)([a-zA-Z0-9_-]{11})/,\n /(?:youtube\\.com\\/embed\\/)([a-zA-Z0-9_-]{11})/,\n /(?:youtube\\.com\\/v\\/)([a-zA-Z0-9_-]{11})/\n ];\n \n for (const pattern of patterns) {\n const match = url.match(pattern);\n if (match) return match[1];\n }\n \n return null;\n}\n\nconst videoId = extractYouTubeId(payload.url);\nif (!videoId) {\n throw new Error('Could not extract YouTube video ID from URL: ' + payload.url);\n}\n\n// Generate thumbnail URLs with quality fallback\nconst thumbnailUrls = [\n `https://img.youtube.com/vi/${videoId}/maxresdefault.jpg`,\n `https://img.youtube.com/vi/${videoId}/hqdefault.jpg`,\n `https://img.youtube.com/vi/${videoId}/mqdefault.jpg`,\n `https://img.youtube.com/vi/${videoId}/default.jpg`\n];\n\nreturn {\n video_id: videoId,\n thumbnail_urls: thumbnailUrls\n};"
|
|
}
|
|
},
|
|
{
|
|
"id": "download_thumbnail",
|
|
"type": "exec",
|
|
"operation": "javascript",
|
|
"options": {
|
|
"code": "// Download thumbnail and upload to Directus\nasync function downloadAndUploadThumbnail(thumbnailUrls, directus, videoId) {\n const axios = require('axios');\n const FormData = require('form-data');\n \n // Try each thumbnail URL until we find one that works\n for (const url of thumbnailUrls) {\n try {\n // Download thumbnail\n const response = await axios.get(url, { \n responseType: 'arraybuffer',\n timeout: 10000\n });\n \n if (response.status === 200 && response.data.length > 0) {\n // Create form data for file upload\n const formData = new FormData();\n formData.append('file', Buffer.from(response.data), {\n filename: `youtube_${videoId}.jpg`,\n contentType: 'image/jpeg'\n });\n \n // Upload to Directus files\n const uploadResponse = await directus.files.createOne(formData);\n \n return uploadResponse.id; // Return the file ID\n }\n } catch (error) {\n console.log(`Failed to download from ${url}:`, error.message);\n continue; // Try next URL\n }\n }\n \n throw new Error('Failed to download thumbnail from any source');\n}\n\nconst fileId = await downloadAndUploadThumbnail(\n extract_video_id.thumbnail_urls, \n $directus, \n extract_video_id.video_id\n);\n\nreturn { thumbnail_file_id: fileId };"
|
|
}
|
|
},
|
|
{
|
|
"id": "update_item",
|
|
"type": "item-update",
|
|
"collection": "media_items",
|
|
"options": {
|
|
"payload": {
|
|
"youtube_thumbnail": "{{download_thumbnail.thumbnail_file_id}}"
|
|
},
|
|
"key": "{{$trigger.payload.key}}"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
} |