1181 lines
35 KiB
JSON
1181 lines
35 KiB
JSON
{
|
|
"id": "H6TZCHyiYOr1X6Xf",
|
|
"name": "MAM Anime Series List",
|
|
"nodes": [
|
|
{
|
|
"parameters": {},
|
|
"id": "b3487fff-82e0-4b4d-bc57-01163e435ea2",
|
|
"name": "Workflow Trigger",
|
|
"position": [
|
|
48,
|
|
304
|
|
],
|
|
"type": "n8n-nodes-base.executeWorkflowTrigger",
|
|
"typeVersion": 1
|
|
},
|
|
{
|
|
"parameters": {
|
|
"authentication": "privateKey",
|
|
"command": "find /mnt/nas/Anime/Audiobooks -mindepth 2 -maxdepth 2 -type d"
|
|
},
|
|
"id": "ddae105c-cbb9-4747-8176-9df55a98cce5",
|
|
"name": "List General Folders",
|
|
"position": [
|
|
272,
|
|
208
|
|
],
|
|
"type": "n8n-nodes-base.ssh",
|
|
"typeVersion": 1,
|
|
"credentials": {
|
|
"sshPrivateKey": {
|
|
"id": "vOzhicmbOwx1XDF8",
|
|
"name": "seed-0.local.ben.io"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"parameters": {
|
|
"jsCode": "const output = $input.item.json.stdout || \"\";\nconst lines = output.split(String.fromCharCode(10)).filter(l => l.trim());\nreturn lines.map(l => ({\n json: {\n smb_path: l.trim(),\n folder_name: l.split('/').pop()\n }\n}));"
|
|
},
|
|
"id": "4a7486cd-5101-46fc-b1de-698b6c675fc8",
|
|
"name": "Code",
|
|
"position": [
|
|
624,
|
|
128
|
|
],
|
|
"type": "n8n-nodes-base.code",
|
|
"typeVersion": 2
|
|
},
|
|
{
|
|
"parameters": {
|
|
"promptType": "define",
|
|
"text": "=### ROLE\nYou are an expert Data Extraction Specialist for an audiobook library (focus: Light Novels/Anime). You are currently \"blind\" to the book's details and MUST use the provided tools to discover the metadata. You cannot generate the final JSON without data from the tools.\n\n### INPUT DATA\n- **Folder Name:** {{ $json.folder_name }}\n- **SMB Path:** {{ $json.smb_path }}\n\n### STRICT PROCESS\n1. **Analyze Input:**\n - **ASIN Check:** Does 'Folder Name' start with an ASIN (e.g., 'B0...')?\n - **Context Extraction:** Parse the `smb_path`. The folder *above* the current one often holds the **Series Name**. Use this to anchor your search queries.\n\n2. **Execute Tools (Tiered Strategy):**\n *Goal: Identify Title, Author, and ASIN using the most quota-efficient tools first.*\n\n **TIER 1: Direct Lookup (High Confidence)**\n - IF ASIN found in folder: Call `audible_lookup_asin` immediately.\n\n **TIER 2: Primary Search (Google / Brave)**\n - IF NO ASIN: Clean the folder name. Remove text inside brackets `[...]` (e.g., [Yen Audio], [PZG]) and remove \"(Audiobook)\".\n - Construct a query: `\"<Series Name> <Volume Number> Light Novel Audiobook\"`.\n - **Action:** Call `Google Search`, `brave_search`.\n - **Verification:** If the search finds an Audible link or a clear Goodreads/Wikipedia entry, use `audible_search_book` to confirm the ASIN, or `audible_lookup_asin` on a ASIN to confirm match to book you are searching for.\n - **Fallback:** If the first tool yields poor results (no clear match), try the *other* Tier 1 tool (e.g., if Google failed, try Brave).\n\n **TIER 3: Deep Search (Tavily - Low Priority)**\n - **Condition:** Only proceed here if Tier 1 and 2 failed or produced conflicting data.\n - **Action:** Call `tavily_search` with a detailed query.\n - **Extraction:** If an `audible.com/series/` URL was found in previous steps, use `tavily_extract` on that URL to scrape the full book list for accurate volume mapping.\n\n3. **Verify:**\n - Does the tool result match the Author/Series found in the `smb_path` context?\n - Ensure you haven't confused the Manga adaptation for the Light Novel.\n\n4. **Finalize:** Construct the JSON output using strictly the data returned by the tools.\n\n### OUTPUT RULES\n- Your final response must be valid JSON.\n- If all items in template are not filled out, set \"identified\" to `false`.\n\n### JSON TEMPLATE (Fill with TOOL DATA only)\n{\n \"title\": \"<TOOL_RESULT_TITLE>\",\n \"series\": \"<TOOL_RESULT_SERIES_NAME>\",\n \"volume_num\": \"<TOOL_RESULT_SERIES_NUMBER>\",\n \"asin\": \"<TOOL_RESULT_ASIN>\",\n \"author\": \"<TOOL_RESULT_AUTHOR>\",\n \"smb_path\": \"{{ $json.smb_path }}\",\n \"folder_name\": \"{{ $json.folder_name }}\",\n \"identified\": true,\n \"failure_reason\": null\n}",
|
|
"hasOutputParser": true,
|
|
"options": {
|
|
"maxIterations": 10,
|
|
"returnIntermediateSteps": false,
|
|
"enableStreaming": false
|
|
}
|
|
},
|
|
"type": "@n8n/n8n-nodes-langchain.agent",
|
|
"typeVersion": 3,
|
|
"position": [
|
|
1904,
|
|
240
|
|
],
|
|
"id": "9f9c7b50-2fd4-48ac-9080-a74158f58285",
|
|
"name": "Lookup Agent",
|
|
"onError": "continueErrorOutput"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"query": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Query', ``, 'string') }}",
|
|
"options": {
|
|
"topic": "general",
|
|
"search_depth": "basic",
|
|
"max_results": 3,
|
|
"include_domains": [
|
|
"audible.com",
|
|
"amazon.com"
|
|
]
|
|
}
|
|
},
|
|
"type": "@tavily/n8n-nodes-tavily.tavilyTool",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
1952,
|
|
608
|
|
],
|
|
"id": "e2f55ae4-2858-4b74-a355-f33b127396fb",
|
|
"name": "tavily_search",
|
|
"credentials": {
|
|
"tavilyApi": {
|
|
"id": "y1IVnGq2Wiqy3HBf",
|
|
"name": "Tavily account"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"parameters": {
|
|
"operation": "upsert",
|
|
"schema": {
|
|
"__rl": true,
|
|
"mode": "list",
|
|
"value": "public"
|
|
},
|
|
"table": {
|
|
"__rl": true,
|
|
"value": "smb_general_books",
|
|
"mode": "list",
|
|
"cachedResultName": "smb_general_books"
|
|
},
|
|
"columns": {
|
|
"mappingMode": "defineBelow",
|
|
"value": {
|
|
"identified": "={{ $('Merge').item.json.output.identified }}",
|
|
"needs_review": false,
|
|
"volume_num": "={{ $('Merge').item.json.output.volume_num }}",
|
|
"smb_path": "={{ $('Merge').item.json.output.smb_path }}",
|
|
"book_folder": "={{ $('Merge').item.json.output.folder_name }}",
|
|
"author_folder": "={{ $('Merge').item.json.output.author }}",
|
|
"book_name": "={{ $('Merge').item.json.output.title }}",
|
|
"series_name": "={{ $('Merge').item.json.output.series }}",
|
|
"audible_asin": "={{ $('Merge').item.json.output.asin }}",
|
|
"failure_reason": "={{ $('Merge').item.json.output.failure_reason }}",
|
|
"category": "anime",
|
|
"created_at": "={{ $now }}",
|
|
"updated_at": "={{ $now }}"
|
|
},
|
|
"matchingColumns": [
|
|
"smb_path"
|
|
],
|
|
"schema": [
|
|
{
|
|
"id": "id",
|
|
"displayName": "id",
|
|
"required": false,
|
|
"defaultMatch": true,
|
|
"display": true,
|
|
"type": "string",
|
|
"canBeUsedToMatch": true,
|
|
"removed": false
|
|
},
|
|
{
|
|
"id": "smb_path",
|
|
"displayName": "smb_path",
|
|
"required": true,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "string",
|
|
"canBeUsedToMatch": true,
|
|
"removed": false
|
|
},
|
|
{
|
|
"id": "book_folder",
|
|
"displayName": "book_folder",
|
|
"required": true,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "string",
|
|
"canBeUsedToMatch": false
|
|
},
|
|
{
|
|
"id": "author_folder",
|
|
"displayName": "author_folder",
|
|
"required": true,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "string",
|
|
"canBeUsedToMatch": false
|
|
},
|
|
{
|
|
"id": "book_name",
|
|
"displayName": "book_name",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "string",
|
|
"canBeUsedToMatch": false
|
|
},
|
|
{
|
|
"id": "series_name",
|
|
"displayName": "series_name",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "string",
|
|
"canBeUsedToMatch": false
|
|
},
|
|
{
|
|
"id": "audible_asin",
|
|
"displayName": "audible_asin",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "string",
|
|
"canBeUsedToMatch": false
|
|
},
|
|
{
|
|
"id": "identified",
|
|
"displayName": "identified",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "boolean",
|
|
"canBeUsedToMatch": false
|
|
},
|
|
{
|
|
"id": "needs_review",
|
|
"displayName": "needs_review",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "boolean",
|
|
"canBeUsedToMatch": false
|
|
},
|
|
{
|
|
"id": "retry_stage",
|
|
"displayName": "retry_stage",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "string",
|
|
"canBeUsedToMatch": false
|
|
},
|
|
{
|
|
"id": "failure_reason",
|
|
"displayName": "failure_reason",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "string",
|
|
"canBeUsedToMatch": false
|
|
},
|
|
{
|
|
"id": "category",
|
|
"displayName": "category",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "string",
|
|
"canBeUsedToMatch": false
|
|
},
|
|
{
|
|
"id": "volume_num",
|
|
"displayName": "volume_num",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "string",
|
|
"canBeUsedToMatch": false
|
|
},
|
|
{
|
|
"id": "created_at",
|
|
"displayName": "created_at",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "dateTime",
|
|
"canBeUsedToMatch": false
|
|
},
|
|
{
|
|
"id": "updated_at",
|
|
"displayName": "updated_at",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"type": "dateTime",
|
|
"canBeUsedToMatch": false
|
|
}
|
|
],
|
|
"attemptToConvertTypes": false,
|
|
"convertFieldsToString": false
|
|
},
|
|
"options": {}
|
|
},
|
|
"type": "n8n-nodes-base.postgres",
|
|
"typeVersion": 2.6,
|
|
"position": [
|
|
3184,
|
|
224
|
|
],
|
|
"id": "a9cf32b5-56aa-4754-a36a-f6f0f37f6d16",
|
|
"name": "Insert or update rows in a table",
|
|
"credentials": {
|
|
"postgres": {
|
|
"id": "9grzZwW7Br6SzdV8",
|
|
"name": "n8n-media"
|
|
}
|
|
},
|
|
"onError": "continueErrorOutput"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"options": {
|
|
"reset": false
|
|
}
|
|
},
|
|
"type": "n8n-nodes-base.splitInBatches",
|
|
"typeVersion": 3,
|
|
"position": [
|
|
1536,
|
|
208
|
|
],
|
|
"id": "32dc1b6a-c722-412e-b6a3-ce9282501b37",
|
|
"name": "Loop Over Items"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"toolDescription": "google_search accepts title and author and returns the first page of google search results.",
|
|
"method": "POST",
|
|
"url": "https://google.serper.dev/search",
|
|
"sendHeaders": true,
|
|
"headerParameters": {
|
|
"parameters": [
|
|
{
|
|
"name": "X-API-KEY",
|
|
"value": "dea8a4e00208f156de1253b4dc4d32f56a1d72bd"
|
|
}
|
|
]
|
|
},
|
|
"sendBody": true,
|
|
"bodyParameters": {
|
|
"parameters": [
|
|
{
|
|
"name": "q",
|
|
"value": "=site:audible.com {{ $fromAI('query') }}"
|
|
}
|
|
]
|
|
},
|
|
"options": {}
|
|
},
|
|
"type": "n8n-nodes-base.httpRequestTool",
|
|
"typeVersion": 4.3,
|
|
"position": [
|
|
2064,
|
|
752
|
|
],
|
|
"id": "92174474-1946-4ede-a8fa-4df134d46cbf",
|
|
"name": "google_search"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"conditions": {
|
|
"options": {
|
|
"caseSensitive": true,
|
|
"leftValue": "",
|
|
"typeValidation": "strict",
|
|
"version": 3
|
|
},
|
|
"conditions": [
|
|
{
|
|
"id": "b89944ac-44d6-47a6-8824-bc990db96084",
|
|
"leftValue": "={{ $json.smb_path }}",
|
|
"rightValue": "Pack",
|
|
"operator": {
|
|
"type": "string",
|
|
"operation": "notContains"
|
|
}
|
|
},
|
|
{
|
|
"id": "4801810b-0ceb-4c17-893f-4591279754a8",
|
|
"leftValue": "={{ $json.folder_name }}",
|
|
"rightValue": ".@__thumb",
|
|
"operator": {
|
|
"type": "string",
|
|
"operation": "notEquals"
|
|
}
|
|
},
|
|
{
|
|
"id": "fccbabbf-14ab-42fc-9b9c-4941c229c764",
|
|
"leftValue": "={{ $json.smb_path }}",
|
|
"rightValue": "Progressive",
|
|
"operator": {
|
|
"type": "string",
|
|
"operation": "notContains"
|
|
}
|
|
}
|
|
],
|
|
"combinator": "and"
|
|
},
|
|
"options": {}
|
|
},
|
|
"type": "n8n-nodes-base.filter",
|
|
"typeVersion": 2.3,
|
|
"position": [
|
|
1152,
|
|
208
|
|
],
|
|
"id": "04d076e5-c037-431d-b573-e0bfdabaab7d",
|
|
"name": "Filter Unwanted",
|
|
"notesInFlow": true,
|
|
"notes": "- Filter non-book folders\n- Filter Aptiv workout audio"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"mode": "combine",
|
|
"combineBy": "combineByPosition",
|
|
"options": {}
|
|
},
|
|
"type": "n8n-nodes-base.merge",
|
|
"typeVersion": 3.2,
|
|
"position": [
|
|
2448,
|
|
240
|
|
],
|
|
"id": "e91c22e9-b231-4334-8318-c5fa03f89fb5",
|
|
"name": "Merge"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"conditions": {
|
|
"options": {
|
|
"caseSensitive": true,
|
|
"leftValue": "",
|
|
"typeValidation": "strict",
|
|
"version": 3
|
|
},
|
|
"conditions": [
|
|
{
|
|
"id": "0b89f507-1f5c-446b-912c-f94d94320483",
|
|
"leftValue": "={{ $json.status }}",
|
|
"rightValue": "FAIL",
|
|
"operator": {
|
|
"type": "string",
|
|
"operation": "notEquals"
|
|
}
|
|
},
|
|
{
|
|
"id": "d308a2e3-28d8-4922-bfc0-4836a5adc612",
|
|
"leftValue": "={{ $('Merge').item.json.output.identified }}",
|
|
"rightValue": true,
|
|
"operator": {
|
|
"type": "boolean",
|
|
"operation": "equals"
|
|
}
|
|
}
|
|
],
|
|
"combinator": "and"
|
|
},
|
|
"options": {}
|
|
},
|
|
"type": "n8n-nodes-base.if",
|
|
"typeVersion": 2.3,
|
|
"position": [
|
|
2928,
|
|
240
|
|
],
|
|
"id": "540cbeb8-2020-4c64-be9c-07b13ba241b2",
|
|
"name": "verified"
|
|
},
|
|
{
|
|
"parameters": {},
|
|
"type": "n8n-nodes-base.noOp",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
3472,
|
|
736
|
|
],
|
|
"id": "c407ab66-7d47-4246-b9b1-2cc22e9e8aec",
|
|
"name": "Formatting"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"schemaType": "manual",
|
|
"inputSchema": "{\n \"type\": \"object\",\n \"properties\": {\n \"title\": { \"type\": \"string\" },\n \"series\": { \"type\": [\"string\", \"null\"] },\n \"volume_num\": { \n \"type\": [\"string\", \"number\", \"null\"],\n \"description\": \"The volume number (can be string '3' or number 3)\" \n },\n \"asin\": { \"type\": [\"string\", \"null\"] },\n \"author\": { \"type\": \"string\" },\n \"smb_path\": { \"type\": \"string\" },\n \"folder_name\": { \"type\": \"string\" },\n \"identified\": { \"type\": \"boolean\" },\n \"failure_reason\": { \n \"type\": [\"string\", \"null\"],\n \"description\": \"Reason for failure, or null if successful\" \n }\n },\n \"required\": [\n \"title\",\n \"series\",\n \"volume_num\",\n \"asin\",\n \"author\",\n \"smb_path\",\n \"folder_name\",\n \"identified\",\n \"failure_reason\"\n ]\n}",
|
|
"autoFix": true
|
|
},
|
|
"type": "@n8n/n8n-nodes-langchain.outputParserStructured",
|
|
"typeVersion": 1.3,
|
|
"position": [
|
|
2128,
|
|
448
|
|
],
|
|
"id": "190844e8-ad9c-4406-8c29-d9d6f543869e",
|
|
"name": "Structured Output Parser"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"mode": "combine",
|
|
"fieldsToMatchString": "smb_path",
|
|
"joinMode": "keepNonMatches",
|
|
"outputDataFrom": "input1",
|
|
"options": {}
|
|
},
|
|
"id": "f053ed65-f54a-4da2-8f5f-d2d10b8a4dcd",
|
|
"name": "Filter Existing",
|
|
"position": [
|
|
944,
|
|
208
|
|
],
|
|
"type": "n8n-nodes-base.merge",
|
|
"typeVersion": 3.2
|
|
},
|
|
{
|
|
"parameters": {
|
|
"model": {
|
|
"__rl": true,
|
|
"value": "openai/gpt-oss-120b",
|
|
"mode": "list",
|
|
"cachedResultName": "openai/gpt-oss-120b"
|
|
},
|
|
"responsesApiEnabled": false,
|
|
"options": {
|
|
"responseFormat": "json_object",
|
|
"temperature": 0
|
|
}
|
|
},
|
|
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
|
|
"typeVersion": 1.3,
|
|
"position": [
|
|
2208,
|
|
640
|
|
],
|
|
"id": "884680ff-1bc3-4ff5-bb29-47eca4083f4c",
|
|
"name": "Ollama - gpt-oss:20b - Validator",
|
|
"credentials": {
|
|
"openAiApi": {
|
|
"id": "QRBx9RMx4KoFwGgl",
|
|
"name": "Nvidia account"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"parameters": {
|
|
"rule": {
|
|
"interval": [
|
|
{}
|
|
]
|
|
}
|
|
},
|
|
"type": "n8n-nodes-base.scheduleTrigger",
|
|
"typeVersion": 1.3,
|
|
"position": [
|
|
48,
|
|
144
|
|
],
|
|
"id": "240e422b-cb1b-4e78-895c-1e4892bf0036",
|
|
"name": "Schedule Trigger"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"operation": "select",
|
|
"schema": {
|
|
"__rl": true,
|
|
"mode": "list",
|
|
"value": "public"
|
|
},
|
|
"table": {
|
|
"__rl": true,
|
|
"value": "smb_general_books",
|
|
"mode": "list",
|
|
"cachedResultName": "smb_general_books"
|
|
},
|
|
"returnAll": true,
|
|
"where": {
|
|
"values": [
|
|
{
|
|
"column": "category",
|
|
"value": "anime"
|
|
}
|
|
]
|
|
},
|
|
"options": {}
|
|
},
|
|
"type": "n8n-nodes-base.postgres",
|
|
"typeVersion": 2.6,
|
|
"position": [
|
|
592,
|
|
320
|
|
],
|
|
"id": "8b322485-f5bc-4ef5-ac3e-74e8438b7ed1",
|
|
"name": "Select rows from a table",
|
|
"executeOnce": true,
|
|
"credentials": {
|
|
"postgres": {
|
|
"id": "9grzZwW7Br6SzdV8",
|
|
"name": "n8n-media"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"parameters": {
|
|
"description": "Call this tool to retrieve a list of the top brave search results.",
|
|
"workflowId": {
|
|
"__rl": true,
|
|
"value": "VUwFjFF2UhNout2T",
|
|
"mode": "list",
|
|
"cachedResultUrl": "/workflow/VUwFjFF2UhNout2T",
|
|
"cachedResultName": "tool_brave_search"
|
|
},
|
|
"workflowInputs": {
|
|
"mappingMode": "defineBelow",
|
|
"value": {
|
|
"query": "=site:audible.com {{ $fromAI('query') }}"
|
|
},
|
|
"matchingColumns": [
|
|
"query"
|
|
],
|
|
"schema": [
|
|
{
|
|
"id": "query",
|
|
"displayName": "query",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"canBeUsedToMatch": true,
|
|
"type": "string",
|
|
"removed": false
|
|
}
|
|
],
|
|
"attemptToConvertTypes": false,
|
|
"convertFieldsToString": false
|
|
}
|
|
},
|
|
"type": "@n8n/n8n-nodes-langchain.toolWorkflow",
|
|
"typeVersion": 2.2,
|
|
"position": [
|
|
2352,
|
|
672
|
|
],
|
|
"id": "e485683e-6882-4ff5-b739-bd703d109693",
|
|
"name": "brave_search"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"model": {
|
|
"__rl": true,
|
|
"value": "minimax/minimax-m2.1",
|
|
"mode": "list",
|
|
"cachedResultName": "minimax/minimax-m2.1"
|
|
},
|
|
"responsesApiEnabled": false,
|
|
"options": {
|
|
"temperature": 0.1
|
|
}
|
|
},
|
|
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
|
|
"typeVersion": 1.3,
|
|
"position": [
|
|
1760,
|
|
448
|
|
],
|
|
"id": "c12548ff-b760-416d-8f63-f8eb57bb66d8",
|
|
"name": "OpenAI Chat Model",
|
|
"credentials": {
|
|
"openAiApi": {
|
|
"id": "9UFJNgYndzFIHJAf",
|
|
"name": "Nano-GPT"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"parameters": {
|
|
"promptType": "define",
|
|
"text": "=### ROLE\nYou are a Quality Assurance Auditor.\n**Golden Rule:** The folder missing data is never a failure reason.\n\n### INPUTS\n1. **Source Folder:** {{ $json.folder_name }}\n2. **Source Path:** {{ $json.smb_path }}\n3. **Candidate Metadata:**\n{{ JSON.stringify($json.output) }}\n\n### VALIDATION RULES (Pass/Fail Criteria)\nYou must evaluate the Candidate Metadata against the Source Folder on these specific points. If ANY point fails, the entire validation fails.\n\n#### 1. Title & Series Check (Hierarchy Rule)\n - **Series Match:** If the Folder Name significantly matches the **Candidate Series** (e.g. Folder \"Vampire Hunter D\", Candidate Series \"Vampire Hunter D\"), then the **Candidate Title** is ACCEPTED as valid enrichment.\n - **Title Match:** If the Folder Name matches the **Candidate Title**, that is also a PASS.\n - **FAIL Condition:** Fail ONLY if the Folder Name matches *neither* the Candidate Title *nor* the Candidate Series.\n - *Example PASS:* Folder \"Vampire Hunter D Vol 8\", Candidate Series \"Vampire Hunter D\", Candidate Title \"Mysterious Journey\". (Matches Series).\n\n\n3. **Volume/Series Logic (Conflict Check ONLY):**\n - **Enrichment is Allowed:** If the folder does NOT mention a series or volume, but the Candidate DOES, this is ACCEPTABLE. Do not fail.\n - **Volume 1** may not have a volume number in the title, this is always acceptable.\n - **Contradiction Check:** Only fail if the folder *explicitly* lists a number that conflicts with the Candidate.\n - *Example FAIL:* Folder says \"Book 4\", Candidate says \"volume_num: 8\".\n - *Example PASS:* Folder says \"Star Wars\", Candidate says \"Series: Star Wars, Vol: 6\". (Enrichment).\n\n4. **ASIN Presence:**\n - If the folder contains an ASIN (starts with 'B0'), does the candidate ASIN match it exactly?\n - The Candidate Metadata ASIN MUST be present to pass.\n\n### OUTPUT FORMAT\nOutput a single JSON object. Do not output markdown or text.\n\n{\n \"status\": \"PASS\" | \"FAIL\",\n \"reason\": \"Brief explanation of why it failed (or 'Verified' if passed)\",\n}",
|
|
"batching": {}
|
|
},
|
|
"type": "@n8n/n8n-nodes-langchain.chainLlm",
|
|
"typeVersion": 1.7,
|
|
"position": [
|
|
2624,
|
|
240
|
|
],
|
|
"id": "df0e56d2-92ad-4ec9-b7f1-1044b3d9eb72",
|
|
"name": "QA Agent"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"sendTo": "me@ben.io",
|
|
"subject": "Anime Series List Update",
|
|
"message": "=This is an update that your Anime Audiobook Library, we've identified the following new books:\n\n{{ $json.email_summary }}\n\n",
|
|
"options": {
|
|
"appendAttribution": true,
|
|
"senderName": "n8n Anime Series List"
|
|
}
|
|
},
|
|
"type": "n8n-nodes-base.gmail",
|
|
"typeVersion": 2.2,
|
|
"position": [
|
|
2272,
|
|
16
|
|
],
|
|
"id": "6c328083-2cf9-4485-81bb-ba5b5fa3988e",
|
|
"name": "Send a message",
|
|
"webhookId": "d5463123-d50d-4eab-86c9-f71d18587d54",
|
|
"credentials": {
|
|
"gmailOAuth2": {
|
|
"id": "Os1ux3h3zFlC2XkG",
|
|
"name": "Gmail account"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"parameters": {
|
|
"jsCode": "// Get all items from the previous node\nconst items = $input.all();\n\n// Create an HTML list of the books\nconst bookList = items.map(item => {\n return `<li><strong>${item.json.book_name}</strong> by ${item.json.author_folder}</li>`;\n}).join('');\n\n// Return an ARRAY containing the single summary item\nreturn [{\n json: {\n email_summary: `<ul>${bookList}</ul>`,\n count: items.length\n }\n}];"
|
|
},
|
|
"type": "n8n-nodes-base.code",
|
|
"typeVersion": 2,
|
|
"position": [
|
|
2016,
|
|
16
|
|
],
|
|
"id": "9657e35b-b89a-4d94-9ce2-41ba8ee70062",
|
|
"name": "Code in JavaScript"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"conditions": {
|
|
"options": {
|
|
"caseSensitive": true,
|
|
"leftValue": "",
|
|
"typeValidation": "strict",
|
|
"version": 3
|
|
},
|
|
"conditions": [
|
|
{
|
|
"id": "c7daf60b-1af4-4764-a657-a1d66d30e1ee",
|
|
"leftValue": "={{ $json.book_name }}",
|
|
"rightValue": "PASS",
|
|
"operator": {
|
|
"type": "string",
|
|
"operation": "exists",
|
|
"singleValue": true
|
|
}
|
|
}
|
|
],
|
|
"combinator": "and"
|
|
},
|
|
"options": {}
|
|
},
|
|
"type": "n8n-nodes-base.if",
|
|
"typeVersion": 2.3,
|
|
"position": [
|
|
1744,
|
|
64
|
|
],
|
|
"id": "d03ed1a1-1a8f-4863-97f8-2db150e77b68",
|
|
"name": "If"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"description": "Call this tool to lookup an Author and Book Name from Audible.",
|
|
"workflowId": {
|
|
"__rl": true,
|
|
"value": "Z_YHsJaf_pyFQR6e7VuLo",
|
|
"mode": "list",
|
|
"cachedResultUrl": "/workflow/Z_YHsJaf_pyFQR6e7VuLo",
|
|
"cachedResultName": "search_audible"
|
|
},
|
|
"workflowInputs": {
|
|
"mappingMode": "defineBelow",
|
|
"value": {
|
|
"book-name": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('book-name', ``, 'string') }}",
|
|
"author": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('author', ``, 'string') }}"
|
|
},
|
|
"matchingColumns": [],
|
|
"schema": [
|
|
{
|
|
"id": "book-name",
|
|
"displayName": "book-name",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"canBeUsedToMatch": true,
|
|
"type": "string",
|
|
"removed": false
|
|
},
|
|
{
|
|
"id": "author",
|
|
"displayName": "author",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"canBeUsedToMatch": true,
|
|
"type": "string",
|
|
"removed": false
|
|
},
|
|
{
|
|
"id": "asin",
|
|
"displayName": "asin",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"canBeUsedToMatch": true,
|
|
"type": "string",
|
|
"removed": true
|
|
}
|
|
],
|
|
"attemptToConvertTypes": false,
|
|
"convertFieldsToString": false
|
|
}
|
|
},
|
|
"type": "@n8n/n8n-nodes-langchain.toolWorkflow",
|
|
"typeVersion": 2.2,
|
|
"position": [
|
|
1776,
|
|
608
|
|
],
|
|
"id": "81007b3e-3baa-4f95-bcb5-6e73fdcb91a0",
|
|
"name": "audible_search_book"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"description": "Call this tool to lookup an ASIN from Audible.",
|
|
"workflowId": {
|
|
"__rl": true,
|
|
"value": "Z_YHsJaf_pyFQR6e7VuLo",
|
|
"mode": "list",
|
|
"cachedResultUrl": "/workflow/Z_YHsJaf_pyFQR6e7VuLo",
|
|
"cachedResultName": "search_audible"
|
|
},
|
|
"workflowInputs": {
|
|
"mappingMode": "defineBelow",
|
|
"value": {
|
|
"asin": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('asin', ``, 'string') }}"
|
|
},
|
|
"matchingColumns": [],
|
|
"schema": [
|
|
{
|
|
"id": "book-name",
|
|
"displayName": "book-name",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"canBeUsedToMatch": true,
|
|
"type": "string",
|
|
"removed": true
|
|
},
|
|
{
|
|
"id": "author",
|
|
"displayName": "author",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"canBeUsedToMatch": true,
|
|
"type": "string",
|
|
"removed": true
|
|
},
|
|
{
|
|
"id": "asin",
|
|
"displayName": "asin",
|
|
"required": false,
|
|
"defaultMatch": false,
|
|
"display": true,
|
|
"canBeUsedToMatch": true,
|
|
"type": "string",
|
|
"removed": false
|
|
}
|
|
],
|
|
"attemptToConvertTypes": false,
|
|
"convertFieldsToString": false
|
|
}
|
|
},
|
|
"type": "@n8n/n8n-nodes-langchain.toolWorkflow",
|
|
"typeVersion": 2.2,
|
|
"position": [
|
|
1600,
|
|
608
|
|
],
|
|
"id": "dd7f49fd-2bd1-4e06-9402-5087db1c3a1e",
|
|
"name": "audible_lookup_asin"
|
|
}
|
|
],
|
|
"connections": {
|
|
"Code": {
|
|
"main": [
|
|
[
|
|
{
|
|
"index": 0,
|
|
"node": "Filter Existing",
|
|
"type": "main"
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"List General Folders": {
|
|
"main": [
|
|
[
|
|
{
|
|
"index": 0,
|
|
"node": "Code",
|
|
"type": "main"
|
|
},
|
|
{
|
|
"node": "Select rows from a table",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Workflow Trigger": {
|
|
"main": [
|
|
[
|
|
{
|
|
"index": 0,
|
|
"node": "List General Folders",
|
|
"type": "main"
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"tavily_search": {
|
|
"ai_tool": [
|
|
[
|
|
{
|
|
"node": "Lookup Agent",
|
|
"type": "ai_tool",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Lookup Agent": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Merge",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Loop Over Items": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "If",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
],
|
|
[
|
|
{
|
|
"node": "Lookup Agent",
|
|
"type": "main",
|
|
"index": 0
|
|
},
|
|
{
|
|
"node": "Merge",
|
|
"type": "main",
|
|
"index": 1
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"google_search": {
|
|
"ai_tool": [
|
|
[
|
|
{
|
|
"node": "Lookup Agent",
|
|
"type": "ai_tool",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Filter Unwanted": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Loop Over Items",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Merge": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "QA Agent",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"verified": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Insert or update rows in a table",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
],
|
|
[
|
|
{
|
|
"node": "Formatting",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Insert or update rows in a table": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Formatting",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
],
|
|
[
|
|
{
|
|
"node": "Formatting",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Formatting": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Loop Over Items",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Structured Output Parser": {
|
|
"ai_outputParser": [
|
|
[
|
|
{
|
|
"node": "Lookup Agent",
|
|
"type": "ai_outputParser",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Filter Existing": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Filter Unwanted",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Ollama - gpt-oss:20b - Validator": {
|
|
"ai_languageModel": [
|
|
[
|
|
{
|
|
"node": "Structured Output Parser",
|
|
"type": "ai_languageModel",
|
|
"index": 0
|
|
},
|
|
{
|
|
"node": "QA Agent",
|
|
"type": "ai_languageModel",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Schedule Trigger": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "List General Folders",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Select rows from a table": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Filter Existing",
|
|
"type": "main",
|
|
"index": 1
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"brave_search": {
|
|
"ai_tool": [
|
|
[
|
|
{
|
|
"node": "Lookup Agent",
|
|
"type": "ai_tool",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"OpenAI Chat Model": {
|
|
"ai_languageModel": [
|
|
[
|
|
{
|
|
"node": "Lookup Agent",
|
|
"type": "ai_languageModel",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"QA Agent": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "verified",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Code in JavaScript": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Send a message",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"If": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Code in JavaScript",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"audible_search_book": {
|
|
"ai_tool": [
|
|
[
|
|
{
|
|
"node": "Lookup Agent",
|
|
"type": "ai_tool",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"audible_lookup_asin": {
|
|
"ai_tool": [
|
|
[
|
|
{
|
|
"node": "Lookup Agent",
|
|
"type": "ai_tool",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
}
|
|
},
|
|
"settings": {
|
|
"executionOrder": "v1",
|
|
"callerPolicy": "workflowsFromSameOwner",
|
|
"availableInMCP": false
|
|
},
|
|
"triggerCount": 1,
|
|
"versionId": "411aadb2-7f50-46cd-be00-401eef31dfab",
|
|
"owner": {
|
|
"type": "personal",
|
|
"projectId": "FeLO36wNUAcn61Wj",
|
|
"projectName": "Ben W <admin@ben.io>",
|
|
"personalEmail": "admin@ben.io"
|
|
},
|
|
"parentFolderId": "6tDyZCwqELStb6Ik",
|
|
"isArchived": false
|
|
} |