Files
n8n-backup-v2/workflows/aS3YcO4RhtvsdH6q.json
2026-01-02 22:48:32 +00:00

454 lines
14 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"id": "aS3YcO4RhtvsdH6q",
"name": "transmission session mgmt",
"nodes": [
{
"parameters": {},
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [
-832,
-256
],
"id": "6a15d79a-58f3-4bd0-8ad7-d78c3d2e1ef8",
"name": "When clicking Execute workflow"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "condition-1",
"leftValue": "={{ $json.exists_in_db }}",
"rightValue": true,
"operator": {
"type": "boolean",
"operation": "equals"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "if-exists-branch",
"name": "Record Exists?",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
1184,
-160
]
},
{
"parameters": {
"jsCode": "// Configure all Transmission servers to manage\n// Add or remove server URLs as needed\n// Credentials are managed by n8n and applied to HTTP requests\n\nconst servers = [\n 'http://seed-1.dfw.ben.io:9091/transmission/rpc',\n 'http://seed-1.rdu.ben.io:9091/transmission/rpc',\n 'http://seed-1.lax.ben.io:9091/transmission/rpc',\n // Add more servers here:\n // 'http://seed-2.dfw.ben.io:9091/transmission/rpc',\n];\n\nreturn servers.map(url => ({\n json: { url }\n}));"
},
"id": "configure-servers-code",
"name": "Configure Servers",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-608,
-160
]
},
{
"parameters": {
"jsCode": "// Match each server with its existing session (if any)\n// Takes servers from Configure Servers and sessions from Get All Stored Sessions\n\nconst servers = $('Configure Servers').all();\nconst sessions = $('Get All Stored Sessions').all();\n\n// Create a lookup map of server_url -> session data\nconst sessionMap = {};\nfor (const session of sessions) {\n sessionMap[session.json.server_url] = session.json;\n}\n\n// Match each server with its session\nconst results = [];\nfor (const server of servers) {\n const url = server.json.url;\n const existingSession = sessionMap[url];\n \n results.push({\n json: {\n url: url,\n session_id: existingSession?.session_id || null,\n has_session: !!existingSession\n }\n });\n}\n\nreturn results;"
},
"id": "match-servers-sessions",
"name": "Match Servers with Sessions",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-160,
-160
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 1
},
"conditions": [
{
"id": "condition-1",
"leftValue": "={{ $json.has_session }}",
"rightValue": true,
"operator": {
"type": "boolean",
"operation": "equals"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "has-existing-session-if",
"name": "Has Existing Session?",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
64,
-160
]
},
{
"parameters": {
"method": "POST",
"url": "={{ $json.url }}",
"authentication": "genericCredentialType",
"genericAuthType": "httpBasicAuth",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "X-Transmission-Session-Id",
"value": "={{ $json.session_id }}"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "{\"method\": \"session-get\"}",
"options": {
"response": {
"response": {
"fullResponse": true,
"neverError": true
}
},
"timeout": 5000
}
},
"id": "validate-session-http",
"name": "Validate Session",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
288,
-240
],
"credentials": {
"httpBasicAuth": {
"id": "iymUPilnVhfL3h5D",
"name": "transmission"
}
},
"onError": "continueErrorOutput"
},
{
"parameters": {
"method": "POST",
"url": "={{ $json.url }}",
"authentication": "genericCredentialType",
"genericAuthType": "httpBasicAuth",
"options": {
"response": {
"response": {
"fullResponse": true,
"neverError": true
}
},
"timeout": 10000
}
},
"id": "get-new-session-http",
"name": "Get New Session ID",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
512,
-160
],
"credentials": {
"httpBasicAuth": {
"id": "iymUPilnVhfL3h5D",
"name": "transmission"
}
},
"onError": "continueErrorOutput"
},
{
"parameters": {
"jsCode": "// Extract the X-Transmission-Session-Id from the 409 error response\n// Transmission returns a 409 error with the session ID in the HTML body\n\nconst items = $input.all();\nconst results = [];\n\n// Get all items from the Get New Session ID node to preserve the URL\nconst httpRequestItems = $('Get New Session ID').all();\n\nfor (let i = 0; i < items.length; i++) {\n const item = items[i];\n let sessionId = null;\n \n // Get the server URL from the corresponding HTTP request input\n let serverUrl = httpRequestItems[i]?.json?.url;\n \n if (!serverUrl) {\n // Fallback: try to get from Match Servers node\n const matchedItems = $('Match Servers with Sessions').all();\n if (matchedItems[i]?.json?.url) {\n serverUrl = matchedItems[i].json.url;\n } else {\n throw new Error('Could not determine server URL from workflow context');\n }\n }\n \n // Try to get session ID from headers first (if available)\n if (item.json?.headers?.['x-transmission-session-id']) {\n sessionId = item.json.headers['x-transmission-session-id'];\n }\n // Check if it's in the response body directly\n else if (item.json?.body && typeof item.json.body === 'string') {\n const match = item.json.body.match(/X-Transmission-Session-Id:\\s*([A-Za-z0-9]+)/i);\n if (match && match[1]) {\n sessionId = match[1];\n }\n }\n // Try to extract from error message HTML\n else if (item.json?.error?.message) {\n const errorMessage = item.json.error.message;\n const match = errorMessage.match(/X-Transmission-Session-Id:\\s*([A-Za-z0-9]+)/i);\n if (match && match[1]) {\n sessionId = match[1];\n }\n }\n // Check error object directly\n else if (item.error?.message) {\n const errorMessage = item.error.message;\n const match = errorMessage.match(/X-Transmission-Session-Id:\\s*([A-Za-z0-9]+)/i);\n if (match && match[1]) {\n sessionId = match[1];\n }\n }\n \n if (sessionId) {\n results.push({\n json: {\n session_id: sessionId,\n server_url: serverUrl\n }\n });\n } else {\n // Debug: Show what data we received\n const debugInfo = {\n hasHeaders: !!item.json?.headers,\n hasBody: !!item.json?.body,\n hasError: !!item.json?.error,\n hasErrorDirect: !!item.error,\n bodyType: typeof item.json?.body,\n statusCode: item.json?.statusCode,\n keys: Object.keys(item.json || {})\n };\n throw new Error(`Could not extract session ID from response for server: ${serverUrl}. Debug: ${JSON.stringify(debugInfo)}`);\n }\n}\n\nreturn results;"
},
"id": "extract-new-session-code",
"name": "Extract Session ID",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
736,
-160
]
},
{
"parameters": {
"jsCode": "// Check if each session already exists in the database\n// This preserves ALL items and adds a database_record field\n\nconst items = $input.all();\nconst allStoredSessions = $('Get All Stored Sessions').all();\n\n// Create a lookup map of server_url -> database record\nconst dbSessionMap = {};\nfor (const session of allStoredSessions) {\n dbSessionMap[session.json.server_url] = session.json;\n}\n\nconst results = [];\nfor (const item of items) {\n const serverUrl = item.json.server_url;\n const dbRecord = dbSessionMap[serverUrl];\n \n results.push({\n json: {\n ...item.json,\n db_record: dbRecord || null,\n exists_in_db: !!dbRecord\n }\n });\n}\n\nreturn results;"
},
"id": "check-db-exists-code",
"name": "Lookup Existing Records",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
960,
-160
]
},
{
"parameters": {
"rule": {
"interval": [
{}
]
}
},
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.2,
"position": [
-832,
-64
],
"id": "d3f1c5f5-2c71-4295-b383-66223212d448",
"name": "Schedule Trigger"
},
{
"parameters": {
"operation": "executeQuery",
"query": "INSERT INTO transmission_sessions (server_url, session_id, last_updated) VALUES ($1, $2, NOW());",
"additionalFields": {
"queryParams": "={{ $json.session_id }}, {{ $json.server_url }}"
}
},
"id": "supabase-create",
"name": "Create New Session (Postgres)",
"type": "n8n-nodes-base.postgres",
"typeVersion": 1,
"position": [
1408,
-64
],
"credentials": {
"postgres": {
"id": "9grzZwW7Br6SzdV8",
"name": "n8n-media"
}
}
},
{
"parameters": {
"operation": "executeQuery",
"query": "UPDATE transmission_sessions SET session_id = $1, last_updated = NOW() WHERE server_url = $2;",
"additionalFields": {
"queryParams": "={{ $json.session_id }}, {{ $json.server_url }}"
}
},
"id": "supabase-update",
"name": "Update Existing Session (Postgres)",
"type": "n8n-nodes-base.postgres",
"typeVersion": 1,
"position": [
1408,
-256
],
"credentials": {
"postgres": {
"id": "9grzZwW7Br6SzdV8",
"name": "n8n-media"
}
}
},
{
"parameters": {
"operation": "executeQuery",
"query": "SELECT * FROM transmission_sessions;",
"additionalFields": {}
},
"id": "get-all-sessions",
"name": "Get All Stored Sessions",
"type": "n8n-nodes-base.postgres",
"typeVersion": 1,
"position": [
-384,
-160
],
"credentials": {
"postgres": {
"id": "9grzZwW7Br6SzdV8",
"name": "n8n-media"
}
}
}
],
"connections": {
"When clicking Execute workflow": {
"main": [
[
{
"node": "Configure Servers",
"type": "main",
"index": 0
}
]
]
},
"Match Servers with Sessions": {
"main": [
[
{
"node": "Has Existing Session?",
"type": "main",
"index": 0
}
]
]
},
"Has Existing Session?": {
"main": [
[
{
"node": "Validate Session",
"type": "main",
"index": 0
}
],
[
{
"node": "Get New Session ID",
"type": "main",
"index": 0
}
]
]
},
"Get New Session ID": {
"main": [
[
{
"node": "Extract Session ID",
"type": "main",
"index": 0
}
],
[
{
"node": "Extract Session ID",
"type": "main",
"index": 0
}
]
]
},
"Extract Session ID": {
"main": [
[
{
"node": "Lookup Existing Records",
"type": "main",
"index": 0
}
]
]
},
"Lookup Existing Records": {
"main": [
[
{
"node": "Record Exists?",
"type": "main",
"index": 0
}
]
]
},
"Validate Session": {
"main": [
[
{
"node": "Get New Session ID",
"type": "main",
"index": 0
}
],
[]
]
},
"Schedule Trigger": {
"main": [
[
{
"node": "Configure Servers",
"type": "main",
"index": 0
}
]
]
},
"Configure Servers": {
"main": [
[
{
"node": "Get All Stored Sessions",
"type": "main",
"index": 0
}
]
]
},
"Record Exists?": {
"main": [
[
{
"node": "Update Existing Session (Postgres)",
"type": "main",
"index": 0
}
],
[
{
"node": "Create New Session (Postgres)",
"type": "main",
"index": 0
}
]
]
},
"Get All Stored Sessions": {
"main": [
[
{
"node": "Match Servers with Sessions",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1",
"callerPolicy": "workflowsFromSameOwner",
"availableInMCP": false
},
"triggerCount": 0,
"versionId": "05f3ebfa-af37-4ebb-a75d-755f54238d2e",
"owner": {
"type": "personal",
"projectId": "FeLO36wNUAcn61Wj",
"projectName": "Ben W <admin@ben.io>",
"personalEmail": "admin@ben.io"
},
"parentFolderId": "kUg4HIPXraph3M0E",
"isArchived": false
}