Files
Alpha/workflows/o3uM1xDLTAKw4D6E.json

489 lines
15 KiB
JSON

{
"id": "o3uM1xDLTAKw4D6E",
"name": "🎬 Pompeo — Media Library Sync [Schedule]",
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"field": "weeks",
"triggerAtHour": 3
}
]
}
},
"id": "b0ccc657-6f9e-43b7-b31e-e753e7c90c53",
"name": "⏰ Cron",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1,
"position": [
0,
304
]
},
{
"parameters": {
"url": "http://radarr.media.svc.cluster.local:7878/radarr/api/v3/movie?apikey=922d1405ab1147019d98a2997d941765",
"options": {}
},
"id": "4b7a2a61-e7ca-41e4-b6fc-b1d112697306",
"name": "🎬 HTTP Radarr",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 1,
"position": [
224,
192
]
},
{
"parameters": {
"url": "http://sonarr.media.svc.cluster.local:8989/sonarr/api/v3/series?apikey=22140655993a4ff6bf12314813ec6982",
"options": {}
},
"id": "a23916f3-e727-4553-bb62-ad3f2602c1f2",
"name": "📺 HTTP Sonarr",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 1,
"position": [
224,
432
]
},
{
"parameters": {},
"id": "986ab3c1-3474-451a-bfa9-dfbeffbaca91",
"name": "🔀 Merge",
"type": "n8n-nodes-base.merge",
"typeVersion": 2,
"position": [
496,
304
]
},
{
"parameters": {
"jsCode": "const allItems = $input.all();\nconst movies = [];\nconst series = [];\n\nfor (const item of allItems) {\n const d = item.json;\n // d may be a full array response or a single object\n const src = Array.isArray(d) ? d : [d];\n for (const s of src) {\n if (s != null && s.tmdbId !== undefined) {\n movies.push({\n type: 'movie',\n title: s.title,\n year: s.year,\n genres: s.genres || [],\n status: s.hasFile ? 'available' : 'missing',\n source: 'radarr',\n source_id: s.tmdbId,\n monitored: s.monitored\n });\n } else if (s != null && s.tvdbId !== undefined) {\n series.push({\n type: 'series',\n title: s.title,\n year: s.year,\n genres: s.genres || [],\n status: s.monitored ? 'monitored' : 'unmonitored',\n source: 'sonarr',\n source_id: s.tvdbId,\n monitored: s.monitored\n });\n }\n }\n}\n\nconst items = [...movies, ...series];\n\nconst genreMap = {};\nfor (const item of items) {\n for (const genre of (item.genres || [])) {\n if (!genreMap[genre]) genreMap[genre] = [];\n genreMap[genre].push(item.title);\n }\n}\n\nlet library_summary = '';\nfor (const [genre, titles] of Object.entries(genreMap)) {\n library_summary += genre + ': ' + titles.join(', ') + '\\n';\n}\n\nreturn [{ json: { items, library_summary } }];"
},
"id": "a4d4acff-c5b1-450f-8428-402ca6e5969c",
"name": "🔀 Merge Libreria",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
704,
304
]
},
{
"parameters": {
"url": "https://api.github.com/copilot_internal/v2/token",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "httpHeaderAuth",
"options": {}
},
"id": "57d1cfcb-a838-4382-99d9-4e2aff920511",
"name": "🔑 Ottieni Token Copilot",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
928,
304
],
"credentials": {
"httpHeaderAuth": {
"id": "vBwUxlzKrX3oDHyN",
"name": "GitHub Copilot OAuth Token"
}
}
},
{
"parameters": {
"jsCode": "const mergeData = $('🔀 Merge Libreria').first().json;\nconst library_summary = mergeData.library_summary;\n\nconst prompt = 'Analizza questa libreria multimediale personale e restituisci un JSON con:\\n' +\n '{\\n' +\n ' \"top_genres\": [\"lista\", \"dei\", \"generi\", \"preferiti\"],\\n' +\n ' \"preferred_types\": \"movie|series|both\",\\n' +\n ' \"library_stats\": {\"total_movies\": N, \"total_series\": N, \"available_movies\": N},\\n' +\n ' \"taste_summary\": \"frase descrittiva del gusto cinematografico in italiano\",\\n' +\n ' \"notable_patterns\": [\"pattern1\", \"pattern2\"]\\n' +\n '}\\n\\n' +\n 'Libreria:\\n' + library_summary;\n\nreturn [{ json: { prompt } }];"
},
"id": "ee1918af-97fd-4c45-8d22-9e9808a47842",
"name": "📝 Build Prompt LLM",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1136,
304
]
},
{
"parameters": {
"method": "POST",
"url": "https://api.githubcopilot.com/chat/completions",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "={{ 'Bearer ' + $('🔑 Ottieni Token Copilot').first().json.token }}"
},
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "Copilot-Integration-Id",
"value": "vscode-chat"
},
{
"name": "Editor-Version",
"value": "vscode/1.85.0"
}
]
},
"sendBody": true,
"contentType": "raw",
"rawContentType": "application/json",
"body": "={{ JSON.stringify({\"model\":\"gpt-4.1\",\"messages\":[{\"role\":\"system\",\"content\":\"Rispondi SOLO con JSON valido.\"},{\"role\":\"user\",\"content\": $('📝 Build Prompt LLM').first().json.prompt}],\"response_format\":{\"type\":\"json_object\"},\"max_tokens\":2048}) }}",
"options": {}
},
"id": "709416ec-5b5a-4735-a985-9a98822b3910",
"name": "🤖 GPT-4.1 Analisi",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1328,
304
]
},
{
"parameters": {
"jsCode": "const content = $input.first().json.choices[0].message.content;\nreturn [{ json: JSON.parse(content) }];"
},
"id": "e2888c8c-f2cf-4920-bab6-a32bf632b54f",
"name": "🔍 Parse LLM",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1504,
304
]
},
{
"parameters": {
"operation": "executeQuery",
"query": "INSERT INTO memory_facts (user_id, source, category, subject, detail, expires_at, source_ref)\nVALUES (\n 'martin',\n 'media_library',\n 'media_preferences',\n 'Preferenze Media Martin',\n '{{ $json.detail_json }}'::jsonb,\n NOW() + INTERVAL '7 days',\n 'media_preferences_summary'\n)\nON CONFLICT (user_id, source, source_ref) WHERE source_ref IS NOT NULL\nDO UPDATE SET\n detail = EXCLUDED.detail,\n expires_at = EXCLUDED.expires_at,\n created_at = NOW();",
"options": {}
},
"id": "04eb6255-231f-4ed6-bd35-45970280c1cd",
"name": "💾 PG — Upsert Preferenze",
"type": "n8n-nodes-base.postgres",
"typeVersion": 2,
"position": [
1840,
304
],
"credentials": {
"postgres": {
"id": "mRqzxhSboGscolqI",
"name": "Pompeo — PostgreSQL"
}
}
},
{
"parameters": {
"jsCode": "const items = $('🔀 Merge Libreria').first().json.items;\nreturn items.map(item => ({ json: item }));"
},
"id": "3fd8b3f4-f409-40e8-a747-2539248a959a",
"name": "📋 Espandi Items",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
2000,
304
]
},
{
"parameters": {
"options": {}
},
"id": "09919f3a-5ccb-4003-96b0-f096f9c8e802",
"name": "🔁 Loop Items",
"type": "n8n-nodes-base.splitInBatches",
"typeVersion": 3,
"position": [
2208,
304
]
},
{
"parameters": {
"method": "POST",
"url": "http://ollama.ai.svc.cluster.local:11434/api/embeddings",
"sendBody": true,
"contentType": "raw",
"rawContentType": "application/json",
"body": "={{ JSON.stringify({\"model\":\"nomic-embed-text\",\"prompt\": $json.title + \" \" + ($json.year||\"\") + \" \" + ($json.genres||[]).join(\" \") + \" \" + ($json.type||\"\")}) }}",
"options": {}
},
"id": "5b1aabe1-58fe-4290-baa6-8bb02ad144d8",
"name": "🔢 Ollama Embed",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
2448,
128
]
},
{
"parameters": {
"method": "PUT",
"url": "http://qdrant.persistence.svc.cluster.local:6333/collections/media_preferences/points",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "api-key",
"value": "__Montecarlo00!"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"contentType": "raw",
"rawContentType": "application/json",
"body": "={{ $json.qdrant_body }}",
"options": {}
},
"id": "3b04cf16-e00b-4e3d-aef7-beea09153db0",
"name": "🗄️ Qdrant Upsert",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
2688,
320
]
},
{
"parameters": {
"jsCode": "const parsed = $input.first().json;\n// Serialize to JSON and escape single quotes for SQL injection safety\nconst detailJson = JSON.stringify(parsed).split(\"'\").join(\"''\");\nreturn [{ json: { detail_json: detailJson } }];"
},
"id": "bf16855c-423d-4eb7-b483-a54af827036f",
"name": "🔧 Prepara Detail",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1680,
304
]
},
{
"id": "e52627b8-ef32-47e1-94e4-8ecbdf2cc02b",
"name": "🔧 Prepara Qdrant",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
2468,
320
],
"parameters": {
"jsCode": "const item = $('🔁 Loop Items').item.json;\nconst embedding = $('🔢 Ollama Embed').item.json.embedding;\n\n// Use source_id as integer point ID (hash if needed)\nconst rawId = item.source_id;\nlet pointId = Math.abs(parseInt(rawId) || 0) % 2147483647;\nif (pointId === 0) pointId = Math.abs(String(rawId).split('').reduce((a,c) => a + c.charCodeAt(0), 0)) % 2147483647;\n\nconst payload = {\n points: [{\n id: pointId,\n vector: embedding,\n payload: {\n title: item.title || '',\n year: item.year || null,\n type: item.type || '',\n genres: item.genres || [],\n status: item.status || '',\n source: item.source || '',\n source_id: rawId,\n expires_at: new Date(Date.now() + 180 * 24 * 60 * 60 * 1000).toISOString()\n }\n }]\n};\n\nreturn [{ json: { qdrant_body: JSON.stringify(payload) } }];"
}
}
],
"connections": {
"⏰ Cron": {
"main": [
[
{
"node": "🎬 HTTP Radarr",
"type": "main",
"index": 0
},
{
"node": "📺 HTTP Sonarr",
"type": "main",
"index": 0
}
]
]
},
"🎬 HTTP Radarr": {
"main": [
[
{
"node": "🔀 Merge",
"type": "main",
"index": 0
}
]
]
},
"📺 HTTP Sonarr": {
"main": [
[
{
"node": "🔀 Merge",
"type": "main",
"index": 1
}
]
]
},
"🔀 Merge": {
"main": [
[
{
"node": "🔀 Merge Libreria",
"type": "main",
"index": 0
}
]
]
},
"🔀 Merge Libreria": {
"main": [
[
{
"node": "🔑 Ottieni Token Copilot",
"type": "main",
"index": 0
}
]
]
},
"🔑 Ottieni Token Copilot": {
"main": [
[
{
"node": "📝 Build Prompt LLM",
"type": "main",
"index": 0
}
]
]
},
"📝 Build Prompt LLM": {
"main": [
[
{
"node": "🤖 GPT-4.1 Analisi",
"type": "main",
"index": 0
}
]
]
},
"🤖 GPT-4.1 Analisi": {
"main": [
[
{
"node": "🔍 Parse LLM",
"type": "main",
"index": 0
}
]
]
},
"🔍 Parse LLM": {
"main": [
[
{
"node": "🔧 Prepara Detail",
"type": "main",
"index": 0
}
]
]
},
"💾 PG — Upsert Preferenze": {
"main": [
[
{
"node": "📋 Espandi Items",
"type": "main",
"index": 0
}
]
]
},
"📋 Espandi Items": {
"main": [
[
{
"node": "🔁 Loop Items",
"type": "main",
"index": 0
}
]
]
},
"🔁 Loop Items": {
"main": [
[],
[
{
"node": "🔢 Ollama Embed",
"type": "main",
"index": 0
}
]
]
},
"🔢 Ollama Embed": {
"main": [
[
{
"node": "🔧 Prepara Qdrant",
"type": "main",
"index": 0
}
]
]
},
"🗄️ Qdrant Upsert": {
"main": [
[
{
"node": "🔁 Loop Items",
"type": "main",
"index": 0
}
]
]
},
"🔧 Prepara Detail": {
"main": [
[
{
"node": "💾 PG — Upsert Preferenze",
"type": "main",
"index": 0
}
]
]
},
"🔧 Prepara Qdrant": {
"main": [
[
{
"node": "🗄️ Qdrant Upsert",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1",
"callerPolicy": "workflowsFromSameOwner",
"availableInMCP": false
},
"triggerCount": 1,
"versionId": "ef7c42b4-fddc-4e53-913a-47761d08f5a6",
"owner": {
"type": "personal",
"projectId": "Hdttz401OqqtObPo",
"projectName": "Martin Tahiraj <tahiraj.martin@gmail.com>",
"personalEmail": "tahiraj.martin@gmail.com"
},
"parentFolderId": null,
"isArchived": false
}