{
  "id": "o9MZ3XaJ5Vyf4kJ9",
  "name": "Momentry Search API - Core v1.2",
  "active": true,
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "search",
        "responseMode": "responseNode",
        "options": {}
      },
      "id": "b5f92603-1071-42e0-85b1-6c1655f9c992",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        -384,
        1408
      ],
      "webhookId": "79d6584e-c37c-49c4-9e83-c72896cef416"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "name": "query",
              "value": "={{$json.body.query || $json.query}}",
              "type": "string",
              "id": "f9a4b19c-b478-4fd3-9969-cd78298d2138"
            },
            {
              "name": "mode",
              "value": "={{ $json.body?.mode || $json.mode || \"mock\" }}",
              "type": "string",
              "id": "59066dec-1e8e-4339-ab5e-ce538c0dc216"
            },
            {
              "name": "request_source",
              "value": "portal",
              "type": "string",
              "id": "1ff615c2-23b2-45af-a580-9d27a6a8d4bc"
            },
            {
              "name": "limit",
              "value": 10,
              "type": "number",
              "id": "16adb464-079b-4a91-bbb9-bd9b44db83ed"
            },
            {
              "id": "d298ad4d-4fab-41f0-a11a-7d089cf78ae3",
              "name": "query_normalized",
              "value": "={{ ($json.body.query || $json.query || \"\").toLowerCase().trim() }}",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "id": "fadff1c5-038b-4aa7-ad18-957440d0942c",
      "name": "Build Search Request",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        -160,
        1408
      ]
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 1
                },
                "conditions": [
                  {
                    "leftValue": "={{$json.query_normalized}}",
                    "rightValue": "sun",
                    "operator": {
                      "type": "string",
                      "operation": "contains"
                    },
                    "id": "54556e33-0dff-4e3d-ada0-81ea89f422c2"
                  }
                ],
                "combinator": "and"
              }
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 1
                },
                "conditions": [
                  {
                    "leftValue": "={{$json.query_normalized}}",
                    "rightValue": "morning",
                    "operator": {
                      "type": "string",
                      "operation": "contains"
                    },
                    "id": "cca4c190-d840-486c-937f-221d62fcf05f"
                  }
                ],
                "combinator": "and"
              }
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 1
                },
                "conditions": [
                  {
                    "id": "88239dfd-773c-4337-9f2e-521e6368305b",
                    "leftValue": "={{$json.query_normalized}}",
                    "rightValue": "error",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              }
            }
          ]
        },
        "options": {
          "fallbackOutput": "extra"
        }
      },
      "id": "613caa5d-d3f7-4099-a5f3-5c642264d32c",
      "name": "Search Adapter (Mock Router)",
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3,
      "position": [
        512,
        1664
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "name": "query",
              "value": "={{$json.query}}",
              "type": "string",
              "id": "7af70495-2dbb-4e7b-aed3-79cd7e970183"
            },
            {
              "name": "search_results",
              "value": "={{[\n  {\n    \"moment_id\": \"m001\",\n    \"video_id\": \"v001\",\n    \"t_start\": 3,\n    \"t_end\": 8,\n    \"title\": \"Sunset moment\",\n    \"snippet\": \"The sun slowly sets over the sea\",\n    \"score\": 0.92,\n    \"video_url\": \"https://wp.momentry.ddns.net/wp-content/uploads/2026/03/H_moment3.mp4\"\n  },\n  {\n    \"moment_id\": \"m002\",\n    \"video_id\": \"v002\",\n    \"t_start\": 3,\n    \"t_end\": 7,\n    \"title\": \"Morning sunlight\",\n    \"snippet\": \"Sunlight enters the room\",\n    \"score\": 0.88,\n    \"video_url\": \"https://wp.momentry.ddns.net/wp-content/uploads/2026/03/O_moment3.mp4\"\n  }\n]}}",
              "type": "array",
              "id": "e504493f-0dec-4a80-b434-7586059159f0"
            }
          ]
        },
        "options": {}
      },
      "id": "38b6c814-3e60-45e1-a31f-b93fcf9b2fd5",
      "name": "Mock Sun Results",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        736,
        1456
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "name": "query",
              "value": "={{$json.query}}",
              "type": "string",
              "id": "137b4cd7-5ef8-41f2-94bc-921c9040e0e5"
            },
            {
              "name": "search_results",
              "value": "={{[\n  {\n    \"moment_id\": \"m002\",\n    \"video_id\": \"v002\",\n    \"t_start\": 3,\n    \"t_end\": 7,\n    \"title\": \"Morning sunlight\",\n    \"snippet\": \"Sunlight enters the room\",\n    \"score\": 0.88,\n    \"video_url\": \"https://wp.momentry.ddns.net/wp-content/uploads/2026/03/H_moment3.mp4\"\n  }\n]}}",
              "type": "array",
              "id": "181df2c1-9469-4d3d-9f23-2ca839091583"
            }
          ]
        },
        "options": {}
      },
      "id": "e0bc4873-b4a7-4cdc-a4e8-01aef82a79b8",
      "name": "Mock Morning Results",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        736,
        1648
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "name": "query",
              "value": "={{$json.query}}",
              "type": "string",
              "id": "be01ea1f-f92f-41c7-8dab-f998e7c07bec"
            },
            {
              "name": "search_results",
              "value": "={{ [] }}",
              "type": "array",
              "id": "21e46d9d-0a35-4641-b936-806713ff021c"
            }
          ]
        },
        "options": {}
      },
      "id": "e7c3a7b0-6cee-4832-b6ad-9cdc30f59131",
      "name": "Mock Empty Results",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        736,
        2032
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "name": "query",
              "value": "={{$json.query}}",
              "type": "string"
            },
            {
              "name": "total",
              "value": "={{$json.search_results.length}}",
              "type": "number"
            },
            {
              "name": "results",
              "value": "={{$json.search_results}}",
              "type": "array"
            }
          ]
        },
        "options": {}
      },
      "id": "e746705c-ddfc-4c6b-904b-a5a8ed5d7420",
      "name": "Format Search Response",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        960,
        1648
      ]
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ { \"query\": $json.query, \"total\": $json.total, \"results\": $json.results } }}",
        "options": {}
      },
      "id": "d7f9806c-ad9f-4e56-bbdc-a943f1d416fd",
      "name": "Respond Search",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1,
      "position": [
        1184,
        1168
      ]
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 3
                },
                "conditions": [
                  {
                    "id": "99d7d111-05ae-42aa-8b86-a5de7a7fdb52",
                    "leftValue": "={{ $json.mode }}",
                    "rightValue": "mock",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "mock"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 3
                },
                "conditions": [
                  {
                    "id": "d24d518d-bd6b-4b99-a4c9-cc98c49027ca",
                    "leftValue": "={{ $json.mode }}",
                    "rightValue": "core_stub",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "core_stub"
            }
          ]
        },
        "options": {
          "fallbackOutput": "none"
        }
      },
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.4,
      "position": [
        64,
        1408
      ],
      "id": "550273ba-8d33-4653-a26b-2b83218ce993",
      "name": "Mode Router"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "c2c253a2-689c-4d8f-92d1-017dacbf1eca",
              "name": "error",
              "value": true,
              "type": "boolean"
            },
            {
              "id": "523b04a9-9843-4542-846d-d027f697ceff",
              "name": "message",
              "value": "mock backend error",
              "type": "string"
            },
            {
              "id": "ef30be3a-cdf7-4461-90b9-6d3ee6a88ba3",
              "name": "query",
              "value": "={{$json.query}}",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        736,
        1840
      ],
      "id": "be069c6a-da6b-4a1b-a930-b535818b9ae2",
      "name": "Mock Error Response"
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ { \"error\": true, \"message\": $json.message, \"query\": $json.query } }}",
        "options": {
          "responseCode": 500
        }
      },
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.5,
      "position": [
        960,
        1888
      ],
      "id": "6777eded-6c8e-426d-82b2-550580f74591",
      "name": "Respond Search Error"
    },
    {
      "parameters": {
        "jsCode": "const query = $json.query ?? \"\";\nconst hits = Array.isArray($json.hits) ? $json.hits : [];\n\nreturn [\n  {\n    json: {\n      query,\n      total: typeof $json.count === \"number\" ? $json.count : hits.length,\n      results: hits.map(hit => ({\n        moment_id: hit.id ?? \"\",\n        video_id: hit.vid ?? \"\",\n        t_start: Number(hit.start ?? 0),\n        t_end: Number(hit.end ?? 0),\n        title: hit.title ?? \"\",\n        snippet: hit.text ?? \"\",\n        score: Number(hit.score ?? 0),\n        video_url: hit.media_url ?? \"\"\n      }))\n    }\n  }\n];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        960,
        1120
      ],
      "id": "34662909-6e7a-4cf4-967b-1f474748777a",
      "name": "Normalize Core Response"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "c51bf73f-e1e0-4811-985c-4de5ec70b9d8",
              "leftValue": "={{ $json.error ? \"yes\" : \"no\" }}",
              "rightValue": "=yes",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        736,
        1168
      ],
      "id": "cb6a5372-05a5-4f1b-ae5e-3b33bf009d4c",
      "name": "Check Core Error"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "fad95504-6182-4d4c-bc95-8927c25c7f31",
              "name": "ok",
              "value": false,
              "type": "boolean"
            },
            {
              "id": "d267371c-90d8-401e-8180-a753e807441b",
              "name": "error_code",
              "value": "={{ $json.error?.code === \"ECONNABORTED\" ? \"SEARCH_TIMEOUT\" : \"SEARCH_BACKEND_ERROR\" }}",
              "type": "string"
            },
            {
              "id": "4992c4d9-e61d-453a-a826-8895374f56b8",
              "name": "message",
              "value": "={{ $json.error?.code === \"ECONNABORTED\" ? \"Search service timeout\" : \"Search service unavailable\" }}",
              "type": "string"
            },
            {
              "id": "56b9fbfa-4c98-4265-b992-498e3edf733b",
              "name": "query",
              "value": "={{ $node[\"Build Search Request\"].json.query || \"unknown\" }}",
              "type": "string"
            },
            {
              "id": "c50010c1-a0c8-47b9-a763-e7212a8db93c",
              "name": "results",
              "value": "={{ [] }}",
              "type": "array"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        960,
        1312
      ],
      "id": "1c811ef9-91da-465c-9121-6247549d16fc",
      "name": "Map Search Error"
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ {\n  \"ok\": $json.ok,\n  \"error_code\": $json.error_code,\n  \"message\": $json.message,\n  \"query\": $json.query,\n  \"results\": $json.results\n} }}",
        "options": {
          "responseCode": 500
        }
      },
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.5,
      "position": [
        1184,
        1360
      ],
      "id": "797824a7-85ac-40d9-bd2b-42ea11dfd1a1",
      "name": "Respond Search Error1"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "c08206fb-5d74-40f0-a682-f2116c290af1",
              "name": "query",
              "value": "={{ $json.query }}",
              "type": "string"
            },
            {
              "id": "85e83fbc-b4f0-4b22-8d37-516609387918",
              "name": "limit",
              "value": "={{ Number($json.limit || 10) }}",
              "type": "number"
            },
            {
              "id": "823706fe-288a-4a71-a498-0ad3daad5081",
              "name": "mode",
              "value": "={{ $json.mode }}",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        288,
        1168
      ],
      "id": "89366f65-c36a-4b19-9970-706a5d729594",
      "name": "Prepare Core Request Context"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.momentry.ddns.net/api/v1/n8n/search",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ {\n  \"query\": $json.query,\n  \"limit\": $json.limit,\n  \"request_query\": $json.query\n} }}",
        "options": {
          "timeout": 3000
        }
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        512,
        1168
      ],
      "id": "d5ea8f1b-5bd7-4c88-9c38-70e5b14ca1d8",
      "name": "Call Momentry Core API",
      "onError": "continueRegularOutput"
    }
  ],
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "Build Search Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Search Request": {
      "main": [
        [
          {
            "node": "Mode Router",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search Adapter (Mock Router)": {
      "main": [
        [
          {
            "node": "Mock Sun Results",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Mock Morning Results",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Mock Error Response",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Mock Empty Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mock Sun Results": {
      "main": [
        [
          {
            "node": "Format Search Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mock Morning Results": {
      "main": [
        [
          {
            "node": "Format Search Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mock Empty Results": {
      "main": [
        [
          {
            "node": "Format Search Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Search Response": {
      "main": [
        [
          {
            "node": "Respond Search",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mode Router": {
      "main": [
        [
          {
            "node": "Search Adapter (Mock Router)",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Prepare Core Request Context",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mock Error Response": {
      "main": [
        [
          {
            "node": "Respond Search Error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalize Core Response": {
      "main": [
        [
          {
            "node": "Respond Search",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Core Error": {
      "main": [
        [
          {
            "node": "Map Search Error",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Normalize Core Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Map Search Error": {
      "main": [
        [
          {
            "node": "Respond Search Error1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Core Request Context": {
      "main": [
        [
          {
            "node": "Call Momentry Core API",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Call Momentry Core API": {
      "main": [
        [
          {
            "node": "Check Core Error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1",
    "availableInMCP": false,
    "binaryMode": "separate"
  },
  "staticData": null,
  "pinData": {
    "Webhook": [
      {
        "json": {
          "headers": {
            "host": "n8n.momentry.ddns.net",
            "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36 Edg/145.0.0.0",
            "content-length": "15",
            "accept": "*/*",
            "accept-encoding": "gzip, deflate, br, zstd",
            "accept-language": "zh-TW,zh;q=0.9,en-US;q=0.8,en;q=0.7,zh-CN;q=0.6,zh-HK;q=0.5",
            "content-type": "application/json",
            "origin": "https://wp.momentry.ddns.net",
            "priority": "u=1, i",
            "referer": "https://wp.momentry.ddns.net/",
            "sec-ch-ua": "\"Not:A-Brand\";v=\"99\", \"Microsoft Edge\";v=\"145\", \"Chromium\";v=\"145\"",
            "sec-ch-ua-mobile": "?0",
            "sec-ch-ua-platform": "\"macOS\"",
            "sec-fetch-dest": "empty",
            "sec-fetch-mode": "cors",
            "sec-fetch-site": "same-site",
            "via": "3.0 Caddy",
            "x-forwarded-for": "111.243.8.96",
            "x-forwarded-host": "n8n.momentry.ddns.net",
            "x-forwarded-proto": "https"
          },
          "params": {},
          "query": {},
          "body": {
            "query": "sun"
          },
          "webhookUrl": "https://n8n.momentry.ddns.net/webhook/search",
          "executionMode": "production"
        },
        "pairedItem": {
          "item": 0
        }
      }
    ]
  },
  "triggerCount": 1,
  "createdAt": "2026-03-23T19:06:43.592+08:00",
  "updatedAt": "2026-03-23T20:06:51.588+08:00"
}
