{ "id": "xXUnt2hL2FKxzOhBnkd3Z", "name": "MAM Series Checker", "nodes": [ { "parameters": { "rule": { "interval": [ {} ] } }, "type": "n8n-nodes-base.scheduleTrigger", "typeVersion": 1.3, "position": [ -832, -16 ], "id": "279ca2c5-3c3e-4cd6-bc97-e43010fb693c", "name": "Schedule Trigger" }, { "parameters": { "options": {} }, "type": "n8n-nodes-base.splitInBatches", "typeVersion": 3, "position": [ -192, -16 ], "id": "2412dfa0-8362-4cc4-8a18-3f233d5338b2", "name": "Loop Over Items" }, { "parameters": { "method": "POST", "url": "https://www.myanonamouse.net/tor/js/loadSearchJSONbasic.php", "authentication": "genericCredentialType", "genericAuthType": "httpHeaderAuth", "sendBody": true, "specifyBody": "json", "jsonBody": "={\n \"dlLink\": \"1\",\n \"tor\": {\n \"text\": \" {{ $json.series_name }} m4b\",\n \"srchIn\": [\n \"title\",\n \"author\",\n \"filenames\",\n \"fileTypes\"\n ],\n \"main_cat\": [\n \"13\"\n ],\n \"searchType\": \"all\",\n \"sortType\": \"seedersDesc\"\n }\n}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.3, "position": [ 48, 0 ], "id": "f387a918-881e-492c-b41a-1dc621e8e822", "name": "HTTP Request", "credentials": { "httpHeaderAuth": { "id": "G8eA8XeS9P5axwJd", "name": "mam cookie auth header" } } }, { "parameters": { "fieldsToAggregate": { "fieldToAggregate": [ { "fieldToAggregate": "book_name" } ] }, "options": {} }, "type": "n8n-nodes-base.aggregate", "typeVersion": 1, "position": [ 816, 0 ], "id": "019177aa-2c4f-4291-90f7-c58750033e77", "name": "Aggregate" }, { "parameters": { "promptType": "define", "text": "=You are a Librarian Agent tasked with reviewing potential new books that have been made available. Provide no commentary or additional information other than what is requested.\n\nWe are reviewing the series: {{ $('Loop Over Items').item.json.series_name }} by {{ $('Loop Over Items').item.json.author }}\n\nOur current library contains the following:\n{{ $json.book_name }}\n\nOur audiobook provider has the following avalible:\n{{ $('Aggregate Available Books').item.json.title }}\n\nProvide a json formatted list of books we are missing. If none, state \"No books missing\".", "batching": {} }, "type": "@n8n/n8n-nodes-langchain.chainLlm", "typeVersion": 1.9, "position": [ 976, 0 ], "id": "aef43627-3228-42ab-a2fe-9f4b50d1a855", "name": "Basic LLM Chain", "onError": "continueErrorOutput" }, { "parameters": { "fieldToSplitOut": "data", "options": { "destinationFieldName": "data" } }, "type": "n8n-nodes-base.splitOut", "typeVersion": 1, "position": [ 256, 0 ], "id": "a857682f-9e3d-4e87-8b06-699b9c8039c2", "name": "Split Out" }, { "parameters": { "model": { "__rl": true, "value": "gemini_cli/gemini-2.5-flash", "mode": "list", "cachedResultName": "gemini_cli/gemini-2.5-flash" }, "responsesApiEnabled": false, "options": { "responseFormat": "json_object", "maxRetries": 2 } }, "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi", "typeVersion": 1.3, "position": [ 976, 208 ], "id": "c4da46be-36bf-463e-bb4a-756ef57d24d5", "name": "OpenAI Chat Model", "credentials": { "openAiApi": { "id": "sxSUdecXdMfKPuTu", "name": "llm-proxy.ben.io" } } }, { "parameters": { "fieldsToAggregate": { "fieldToAggregate": [ { "fieldToAggregate": "data.title" }, { "fieldToAggregate": "=data.dl", "renameField": true }, { "fieldToAggregate": "data.id" }, { "fieldToAggregate": "data.series_info" }, { "fieldToAggregate": "data.author_info" } ] }, "options": {} }, "type": "n8n-nodes-base.aggregate", "typeVersion": 1, "position": [ 464, 0 ], "id": "d6f24deb-4863-41a7-a703-2c31e2363d45", "name": "Aggregate Available Books" }, { "parameters": { "operation": "select", "schema": { "__rl": true, "value": "public", "mode": "list", "cachedResultName": "public" }, "table": { "__rl": true, "value": "followed_series", "mode": "list", "cachedResultName": "followed_series" }, "returnAll": true, "options": {} }, "type": "n8n-nodes-base.postgres", "typeVersion": 2.6, "position": [ -624, -16 ], "id": "e7bc495c-a3e1-46b8-b0f1-ff49286344e7", "name": "Select Series", "credentials": { "postgres": { "id": "9grzZwW7Br6SzdV8", "name": "n8n-media" } } }, { "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": "series_name", "value": "={{ $('Loop Over Items').item.json.series_name }}" } ] }, "options": {} }, "type": "n8n-nodes-base.postgres", "typeVersion": 2.6, "position": [ 656, 0 ], "id": "62be829f-6d74-4142-9420-eb4f6947df09", "name": "Select Book Titles", "executeOnce": true, "credentials": { "postgres": { "id": "9grzZwW7Br6SzdV8", "name": "n8n-media" } } }, { "parameters": { "mode": "combine", "combineBy": "combineByPosition", "options": {} }, "type": "n8n-nodes-base.merge", "typeVersion": 3.2, "position": [ 1328, 0 ], "id": "d8c36a24-7337-453f-b403-f5c631025096", "name": "Merge" }, { "parameters": { "workflowId": { "__rl": true, "value": "kRZyX9H2uDHHncpE", "mode": "list", "cachedResultUrl": "/workflow/kRZyX9H2uDHHncpE", "cachedResultName": "MAM Transmission Manager" }, "workflowInputs": { "mappingMode": "defineBelow", "value": {}, "matchingColumns": [], "schema": [], "attemptToConvertTypes": false, "convertFieldsToString": true }, "mode": "each", "options": {} }, "type": "n8n-nodes-base.executeWorkflow", "typeVersion": 1.3, "position": [ 1728, 0 ], "id": "b6ec81b3-4f62-494e-9437-1a31c82a0299", "name": "Call 'MAM Transmission Manager'" }, { "parameters": { "language": "pythonNative", "pythonCode": "# Output list\nresults = []\n\n# Access the input item\ninput_item = _items[0]['json']\n\n# Extract Lists\nmissing_books = input_item.get('data', [])\navailable_titles = input_item.get('title', [])\navailable_ids = input_item.get('id', [])\navailable_series_info = input_item.get('series_info', [])\navailable_author_info = input_item.get('author_info', [])\navailable_catnames = input_item.get('catname', []) # New: For category detection\navailable_tags = input_item.get('tags', []) # New: For category detection\n\n# 1. Match missing titles to their IDs & Metadata\nfor book_title in missing_books:\n # Normalize the target title\n target_clean = str(book_title).strip()\n \n # Find index\n found_index = -1\n for i, title in enumerate(available_titles):\n if str(title).strip() == target_clean:\n found_index = i\n break\n \n if found_index != -1:\n # Get raw data\n book_id = available_ids[found_index]\n series_raw = available_series_info[found_index]\n author_raw = available_author_info[found_index]\n catname_raw = available_catnames[found_index] if i < len(available_catnames) else \"\"\n tags_raw = available_tags[found_index] if i < len(available_tags) else \"\"\n \n # --- PARSING LOGIC ---\n \n # Parse Series\n meta_series = \"Unknown\"\n meta_book_num = \"0\"\n \n if isinstance(series_raw, str):\n import json\n try:\n series_raw = json.loads(series_raw)\n except:\n pass\n\n if isinstance(series_raw, dict):\n keys = list(series_raw.keys())\n if keys:\n data = series_raw[keys[0]]\n if isinstance(data, list) and len(data) >= 2:\n meta_series = str(data[0]).replace(''', \"'\")\n meta_book_num = str(data[1])\n\n # Parse Author\n meta_author = \"Unknown\"\n \n if isinstance(author_raw, str):\n import json\n try:\n author_raw = json.loads(author_raw)\n except:\n pass\n\n if isinstance(author_raw, dict):\n keys = list(author_raw.keys())\n if keys:\n meta_author = str(author_raw[keys[0]])\n\n # --- CATEGORY DETECTION ---\n # Check if \"Light Novel\" or \"Anime\" appears in category name or tags\n is_anime = \"Light Novel\" in str(catname_raw) or \"anime\" in str(tags_raw).lower()\n category = 'anime' if is_anime else 'general'\n\n # Construct download link\n full_url = f\"https://www.myanonamouse.net/tor/download.php?tid={book_id}\"\n \n results.append({\n \"json\": {\n # Metadata\n \"meta_title\": target_clean,\n \"meta_series\": meta_series,\n \"meta_book_number\": meta_book_num,\n \"meta_author\": meta_author,\n \"mam_id\": book_id,\n \"category\": category, # <--- Sending this to the DB now\n \n # Download Info\n \"dl_link\": full_url,\n \"torrent_hash\": \"PENDING\"\n }\n })\n\nreturn results" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1520, 0 ], "id": "c7496e8c-e307-4659-bdd0-530cd5feeef3", "name": "Create Download Links" } ], "connections": { "Schedule Trigger": { "main": [ [ { "node": "Select Series", "type": "main", "index": 0 } ] ] }, "Loop Over Items": { "main": [ [], [ { "node": "HTTP Request", "type": "main", "index": 0 } ] ] }, "HTTP Request": { "main": [ [ { "node": "Split Out", "type": "main", "index": 0 } ] ] }, "Aggregate": { "main": [ [ { "node": "Basic LLM Chain", "type": "main", "index": 0 } ] ] }, "Split Out": { "main": [ [ { "node": "Aggregate Available Books", "type": "main", "index": 0 } ] ] }, "OpenAI Chat Model": { "ai_languageModel": [ [ { "node": "Basic LLM Chain", "type": "ai_languageModel", "index": 0 } ] ] }, "Aggregate Available Books": { "main": [ [ { "node": "Select Book Titles", "type": "main", "index": 0 }, { "node": "Merge", "type": "main", "index": 1 } ] ] }, "Select Series": { "main": [ [ { "node": "Loop Over Items", "type": "main", "index": 0 } ] ] }, "Select Book Titles": { "main": [ [ { "node": "Aggregate", "type": "main", "index": 0 } ] ] }, "Basic LLM Chain": { "main": [ [ { "node": "Merge", "type": "main", "index": 0 } ], [] ] }, "Merge": { "main": [ [ { "node": "Create Download Links", "type": "main", "index": 0 } ] ] }, "Create Download Links": { "main": [ [ { "node": "Call 'MAM Transmission Manager'", "type": "main", "index": 0 } ] ] }, "Call 'MAM Transmission Manager'": { "main": [ [] ] } }, "settings": { "executionOrder": "v1", "availableInMCP": false }, "triggerCount": 1, "versionId": "8a3af598-bd9e-48e1-a025-cb2059cfebbd", "owner": { "type": "personal", "projectId": "FeLO36wNUAcn61Wj", "projectName": "Ben W ", "personalEmail": "admin@ben.io" }, "parentFolderId": "6tDyZCwqELStb6Ik", "isArchived": false }