init after v1 corruption

This commit is contained in:
2026-01-02 22:48:32 +00:00
parent 305f69836c
commit 166ee1fc73
91 changed files with 15801 additions and 0 deletions

View File

@@ -0,0 +1,454 @@
{
"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
}