{
  "name": "My workflow 1288",
  "nodes": [
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "a4144d15-29fe-4870-ad02-9553ccd3f5ee",
              "leftValue": "={{ $json.query[\"hub.mode\"] }}",
              "rightValue": "subscribe",
              "operator": {
                "type": "string",
                "operation": "equals",
                "name": "filter.operator.equals"
              }
            },
            {
              "id": "e5f35eb3-ab21-4fe2-9b51-aefed012fc98",
              "leftValue": "={{ $json.query[\"hub.verify_token\"] }}",
              "rightValue": "=123456",
              "operator": {
                "type": "string",
                "operation": "equals",
                "name": "filter.operator.equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        -100,
        -3600
      ],
      "id": "921b27a0-96ac-4210-ad4a-eba40d7be733",
      "name": "If"
    },
    {
      "parameters": {
        "content": "## Xác thực facebook app webhook\n**Lưu ý active webhook lên, hoặc đưa ra 1 luồng workflow khác và active lên**",
        "height": 380,
        "width": 680
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -140,
        -3760
      ],
      "typeVersion": 1,
      "id": "b17b78dc-4fd8-4e84-8cab-95f0e8e7796c",
      "name": "Sticky Note"
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "={{ $('MergeMessage').first().json.text.join('\\n') }}",
        "options": {
          "systemMessage": "={{ $json.prompt }}"
        }
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 1.9,
      "position": [
        820,
        -1540
      ],
      "id": "406699ff-3f6f-4d57-9a35-3639479006e4",
      "name": "AI Agent",
      "executeOnce": false,
      "onError": "continueErrorOutput"
    },
    {
      "parameters": {
        "model": {
          "__rl": true,
          "value": "gpt-4o-mini",
          "mode": "list",
          "cachedResultName": "gpt-4o-mini"
        },
        "options": {
          "temperature": 0.2,
          "topP": 0.7
        }
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "typeVersion": 1.2,
      "position": [
        740,
        -1320
      ],
      "id": "5ce80bde-e6e9-4fc1-9e8b-23ef7f36b9ec",
      "name": "OpenAI Chat Model",
      "credentials": {
        "openAiApi": {
          "id": "npnMtU7kA3sNSLyr",
          "name": "OpenAi Chatbot"
        }
      }
    },
    {
      "parameters": {
        "sessionIdType": "customKey",
        "sessionKey": "={{ $('MergeMessage').first().json.page_id }}_{{ $('MergeMessage').first().json.sender_id }}"
      },
      "type": "@n8n/n8n-nodes-langchain.memoryPostgresChat",
      "typeVersion": 1.3,
      "position": [
        880,
        -1320
      ],
      "id": "d4aabd80-f6af-4e52-9d20-fdb1cf9e709b",
      "name": "Postgres Chat Memory",
      "credentials": {
        "postgres": {
          "id": "GLfIWU3rbAidDMPe",
          "name": "Postgres account"
        }
      }
    },
    {
      "parameters": {
        "content": "## Map dữ liệu và Lấy page access token\n- Ta sẽ cấu trúc lại dữ liệu sau đó kiểm tra và lấy ra đúng token của page mà chúng ta đang thao tác (Mục đích là sẽ có nhiều page) ",
        "height": 340,
        "width": 680
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -140,
        -2680
      ],
      "typeVersion": 1,
      "id": "0306a5c3-430d-4fbe-afd6-e897dd49db4f",
      "name": "Sticky Note1"
    },
    {
      "parameters": {
        "content": "## Check trùng và lưu lại tin nhắn vào database\n- Facebook có cơ chế bắn lại tin nhắn nếu request bị false và đôi khi cũng bắn nhầm bắn thừa\n- Vậy nên ta phải check trùng để tránh bị nhận tin nhắn và trả lời 2 lần.\n- Nếu không có tin nhắn nào trùng - false -> ta sẽ ghi lại message và tiếp tục",
        "height": 340,
        "width": 700
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        580,
        -2680
      ],
      "typeVersion": 1,
      "id": "74059f14-eb2f-4886-a242-3f6f318ab5b6",
      "name": "Sticky Note2"
    },
    {
      "parameters": {
        "content": "## Response ngay sau khi nhận được dữ liệu\n- Tại sao phải res ngay sau khi nhận?\n- Facebook sẽ cho rằng false nếu sau 20s mà chưa trả về 200\n- Facebook sẽ bắn lại tin nhắn nếu bị coi là false",
        "height": 300,
        "width": 680
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -140,
        -3360
      ],
      "typeVersion": 1,
      "id": "bdbc1d79-a89b-4a33-9cbc-33f099507045",
      "name": "Sticky Note4"
    },
    {
      "parameters": {
        "multipleMethods": true,
        "path": "fbmessager",
        "responseMode": "responseNode",
        "options": {}
      },
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        -400,
        -3600
      ],
      "id": "908bba84-0650-4b8b-9528-0d06db091960",
      "name": "Webhook",
      "webhookId": "84b7cec3-c047-4f9a-aff2-ca16706d2e66",
      "disabled": true
    },
    {
      "parameters": {
        "respondWith": "text",
        "responseBody": "={{ $json.query[\"hub.challenge\"] }}",
        "options": {
          "responseHeaders": {
            "entries": [
              {
                "name": "Content-Type",
                "value": "text/plain"
              }
            ]
          }
        }
      },
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.2,
      "position": [
        340,
        -3680
      ],
      "id": "cd1f4a6e-9603-4fc8-83a8-d24029b2f5d8",
      "name": "Verify success"
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "{\n  \"error\": true\n}",
        "options": {
          "responseCode": 403
        }
      },
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.2,
      "position": [
        340,
        -3520
      ],
      "id": "bcd2e432-b4e2-4b75-a62c-752ca2651860",
      "name": "Verify fail"
    },
    {
      "parameters": {
        "respondWith": "text",
        "responseBody": "EVENT_RECEIVED",
        "options": {}
      },
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.2,
      "position": [
        -100,
        -3200
      ],
      "id": "bfd5fe56-7990-4921-bfd5-e6a287724821",
      "name": "RECEIVED",
      "alwaysOutputData": true
    },
    {
      "parameters": {
        "documentId": {
          "__rl": true,
          "value": "={{ $('PageAccessToken').first().json.data_sheet }}",
          "mode": "url"
        },
        "sheetName": {
          "__rl": true,
          "value": "data",
          "mode": "name"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.googleSheetsTool",
      "typeVersion": 4.6,
      "position": [
        1000,
        -1320
      ],
      "id": "9dfec5ff-ee95-4f6a-9702-da06ccc22ca0",
      "name": "data",
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "AxWVGvJ75f8LaApa",
          "name": "Google Sheets account"
        }
      }
    },
    {
      "parameters": {
        "tableId": "fb_chats",
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "page_id",
              "fieldValue": "={{ $('StructureData').item.json.page_id }}"
            },
            {
              "fieldId": "sender_id",
              "fieldValue": "={{ $('StructureData').item.json.sender_id }}"
            },
            {
              "fieldId": "recipient_id",
              "fieldValue": "={{ $('StructureData').item.json.recipient_id }}"
            },
            {
              "fieldId": "timestamp",
              "fieldValue": "={{ $('StructureData').item.json.timestamp }}"
            },
            {
              "fieldId": "message_id",
              "fieldValue": "={{ $('StructureData').item.json.message_id }}"
            },
            {
              "fieldId": "text",
              "fieldValue": "={{ $('StructureData').item.json.text }}"
            },
            {
              "fieldId": "status",
              "fieldValue": "pending"
            }
          ]
        }
      },
      "type": "n8n-nodes-base.supabase",
      "typeVersion": 1,
      "position": [
        1120,
        -2500
      ],
      "id": "67c0b989-7bb7-43cf-a79c-f8acf16e7c14",
      "name": "SaveToChats",
      "credentials": {
        "supabaseApi": {
          "id": "XnneQjbtAW4FyfV2",
          "name": "Supabase account"
        }
      }
    },
    {
      "parameters": {
        "operation": "get",
        "tableId": "fb_chats",
        "filters": {
          "conditions": [
            {
              "keyName": "message_id",
              "keyValue": "={{ $('StructureData').first().json.message_id }}"
            }
          ]
        }
      },
      "type": "n8n-nodes-base.supabase",
      "typeVersion": 1,
      "position": [
        640,
        -2500
      ],
      "id": "daf17f32-b7ff-4c13-b020-34bbd9ff9fdf",
      "name": "ExistsMessage",
      "alwaysOutputData": true,
      "credentials": {
        "supabaseApi": {
          "id": "XnneQjbtAW4FyfV2",
          "name": "Supabase account"
        }
      }
    },
    {
      "parameters": {
        "content": "## Kiểm tra danh sách chát với người thật\n- Truy vấn xem có phải người dùng này có trong danh sách chát với người thật không",
        "height": 280,
        "width": 680
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -140,
        -2320
      ],
      "typeVersion": 1,
      "id": "7f449934-1a0f-4cbf-848c-c75bf5bd9aa5",
      "name": "Sticky Note5"
    },
    {
      "parameters": {
        "operation": "get",
        "tableId": "fb_included_users",
        "filters": {
          "conditions": [
            {
              "keyName": "key",
              "keyValue": "={{ $json.page_id }}_{{ $json.sender_id }}"
            }
          ]
        }
      },
      "type": "n8n-nodes-base.supabase",
      "typeVersion": 1,
      "position": [
        -100,
        -2220
      ],
      "id": "686a612f-a411-4ee9-9030-37de6b8a5f38",
      "name": "GetUserIncluded",
      "alwaysOutputData": true,
      "credentials": {
        "supabaseApi": {
          "id": "XnneQjbtAW4FyfV2",
          "name": "Supabase account"
        }
      }
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://graph.facebook.com/v22.0/{{ $('StructureTextOutput').item.json.page_id }}/messages",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "=Bearer {{ $('PageAccessToken').last().json.page_access_token }}"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"recipient\": {\n    \"id\": \"{{ $('StructureTextOutput').item.json.sender_id }}\"\n  },\n  \"message\": {\n    \"text\": {{ $('StructureTextOutput').item.json.output }}\n  }\n}",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1100,
        -1040
      ],
      "id": "f45a8c2c-ac57-4974-88ef-9736a5fb2e47",
      "name": "SendMessage"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://graph.facebook.com/v22.0/{{ $json.page_id }}/messages",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "=Bearer {{ $('PageAccessToken').last().json.page_access_token }}"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"recipient\": {\n    \"id\": {{ $json.sender_id }}\n  },\n  \"sender_action\":\"typing_on\"\n}",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        620,
        -1040
      ],
      "id": "4b5e4f1e-2901-4fc0-bceb-b341337012c3",
      "name": "SendTypingOn",
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "02d72cf3-bcee-4e2a-866d-91a3ff41edaa",
              "leftValue": "={{ $json.id }}",
              "rightValue": "",
              "operator": {
                "type": "number",
                "operation": "exists",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        880,
        -2500
      ],
      "id": "0216470c-cff9-447a-98f2-46628dffe325",
      "name": "NotFoundMessage",
      "alwaysOutputData": false
    },
    {
      "parameters": {
        "fieldToSplitOut": "body.entry",
        "options": {}
      },
      "type": "n8n-nodes-base.splitOut",
      "typeVersion": 1,
      "position": [
        620,
        -3200
      ],
      "id": "541e0261-4d82-44b2-a518-d7b04a2d01e5",
      "name": "Split Out"
    },
    {
      "parameters": {
        "content": "## Tiến hành phân tách dữ liệu từ entry và gửi\n- Tại sao phải phân tách? Hãy xem dữ liệu mà fb trả về ta có gì? Ta thấy rằng có 1 entry với kiểu dữ liệu là 1 mảng, mảng này có id page và 1 mảng messaging.\n- Điều này nghĩa là gì? Nghĩa là fb có thế bắn 1 hook có nhiều entry cho chúng ta. mà 1 entry có thể là 1 page khác nhau.\n- Nên ta phải tách nó ra để không bị nhầm page hoặc bị bỏ sót tin nhắn",
        "height": 300,
        "width": 700
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        580,
        -3360
      ],
      "typeVersion": 1,
      "id": "c79fc6a2-7d00-4b82-b0ed-d651f433aea6",
      "name": "Sticky Note8"
    },
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "8c5196db-15df-470a-8fab-ac384b45b480",
        "responseMode": "responseNode",
        "options": {}
      },
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        -520,
        -2500
      ],
      "id": "56ca0dfe-a0ae-464e-81b3-4a6b7cdc6b85",
      "name": "OnMessage",
      "webhookId": "8c5196db-15df-470a-8fab-ac384b45b480"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "2cedc0a7-8b32-4b46-ab19-6c157e21268b",
              "name": "page_id",
              "value": "={{ $json.body.page_id }}",
              "type": "string"
            },
            {
              "id": "c9b6c3ed-40d0-4c27-b3f4-84661a6c8cee",
              "name": "sender_id",
              "value": "={{ $json.body.sender_id }}",
              "type": "string"
            },
            {
              "id": "d985d779-d0b0-4a56-bdef-15019e8d68ef",
              "name": "recipient_id",
              "value": "={{ $json.body.recipient_id }}",
              "type": "string"
            },
            {
              "id": "29d991a0-5395-4d62-aff3-e5739b0ddf83",
              "name": "timestamp",
              "value": "={{ $json.body.timestamp }}",
              "type": "string"
            },
            {
              "id": "4b38a917-b656-4e5a-be18-a2077557f2cf",
              "name": "message_id",
              "value": "={{ $json.body.message_id }}",
              "type": "string"
            },
            {
              "id": "6c438dce-30b3-479e-a56a-1048c0ec39c9",
              "name": "text",
              "value": "={{ $json.body.text }}",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        -100,
        -2500
      ],
      "id": "475811be-639f-4674-b802-35c1361fba9b",
      "name": "StructureData"
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.2,
      "position": [
        -300,
        -2500
      ],
      "id": "a564ece3-817a-4b67-ac87-756c0e79b445",
      "name": "RespondOnMessage"
    },
    {
      "parameters": {
        "content": "## AI Agent\n- Lấy nội dung trả lời cho người dùng.\n- Nếu không thấy nội dung thì hỏi xem có muốn nhắn với chủ page không",
        "height": 500,
        "width": 700
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        580,
        -1680
      ],
      "typeVersion": 1,
      "id": "f6567076-41a6-4120-bc81-ed67323d1058",
      "name": "Sticky Note10"
    },
    {
      "parameters": {
        "content": "## Structure Lại dữ liệu trước khi gửi trả lời người dùng\n- Node này cấu trúc lại dữ liệu và fix lỗi khi khi gửi bị lỗi JSON error",
        "height": 300,
        "width": 680
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -140,
        -1160
      ],
      "typeVersion": 1,
      "id": "1c6dcda4-a200-4cf0-b2db-ab5c9e345873",
      "name": "Sticky Note11"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "d65dbf39-714b-450d-8a30-384483b5e8aa",
              "name": "output",
              "value": "={{ JSON.stringify($json.output) }}",
              "type": "string"
            },
            {
              "id": "aea834b4-09af-4312-b8a3-7ae64c38e5e7",
              "name": "page_id",
              "value": "={{ $('MergeMessage').first().json.page_id }}",
              "type": "string"
            },
            {
              "id": "df7d9604-23bb-43d6-930f-b562622401e9",
              "name": "sender_id",
              "value": "={{ $('MergeMessage').first().json.sender_id }}",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        -100,
        -1040
      ],
      "id": "d9c9e63f-eef4-4350-8380-ca3a86312193",
      "name": "StructureTextOutput"
    },
    {
      "parameters": {
        "content": "## Typing And Send Message\n- Typing là gì? Chính là tạo dấu ... tạo cảm giác đang trả lời trên fb\n- Để wait 1 giây (Cái này tùy chỉnh) sau đó sẽ trả lời",
        "height": 300,
        "width": 700
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        580,
        -1160
      ],
      "typeVersion": 1,
      "id": "2cfe795f-6d46-4370-b989-269ba2e3c5cb",
      "name": "Sticky Note12"
    },
    {
      "parameters": {
        "amount": 1
      },
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1.1,
      "position": [
        860,
        -1040
      ],
      "id": "0edef7e2-46ad-4ea3-abb4-ea444d2f839f",
      "name": "Wait",
      "webhookId": "378864f4-a530-4017-8285-683a16451d7b"
    },
    {
      "parameters": {
        "documentId": {
          "__rl": true,
          "value": "={{ $('PageAccessToken').first().json.data_sheet }}",
          "mode": "url"
        },
        "sheetName": {
          "__rl": true,
          "value": "prompt",
          "mode": "name"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.6,
      "position": [
        620,
        -1540
      ],
      "id": "d97f0f9a-68b8-4f95-8a75-d297c651418d",
      "name": "PromptSheet",
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "AxWVGvJ75f8LaApa",
          "name": "Google Sheets account"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "6c20825f-4cae-4d4b-9558-4c4a10045d99",
              "leftValue": "={{ $('GetAllMessage').first().json.id }}",
              "rightValue": "",
              "operator": {
                "type": "number",
                "operation": "exists",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        20,
        -1340
      ],
      "id": "41db1974-0f64-466a-86bb-fce93ed55d7c",
      "name": "IFExistsMessage"
    },
    {
      "parameters": {
        "jsCode": "return [\n  {\n    ... $('GetAllMessage').last().json,\n    text: $('GetAllMessage').all().map(m => m.json.text)\n  }\n];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        340,
        -1540
      ],
      "id": "54c95a85-8b39-4530-9a28-2a41f5e7fed2",
      "name": "MergeMessage"
    },
    {
      "parameters": {
        "operation": "update",
        "tableId": "fb_chats",
        "filterType": "string",
        "filterString": "=id=in.({{ $('GetAllMessage').all().map(item => item.json.id) }})",
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "status",
              "fieldValue": "done"
            }
          ]
        }
      },
      "type": "n8n-nodes-base.supabase",
      "typeVersion": 1,
      "position": [
        140,
        -1540
      ],
      "id": "7a6a4fb9-a92c-44a1-8007-ca00789011f3",
      "name": "UpdateDoneMessage",
      "executeOnce": true,
      "credentials": {
        "supabaseApi": {
          "id": "XnneQjbtAW4FyfV2",
          "name": "Supabase account"
        }
      }
    },
    {
      "parameters": {
        "operation": "get",
        "tableId": "fb_chats",
        "filters": {
          "conditions": [
            {
              "keyName": "page_id",
              "keyValue": "={{ $('SaveToChats').item.json.page_id }}"
            },
            {
              "keyName": "sender_id",
              "keyValue": "={{ $('SaveToChats').item.json.sender_id }}"
            },
            {
              "keyName": "status",
              "keyValue": "pending"
            }
          ]
        }
      },
      "type": "n8n-nodes-base.supabase",
      "typeVersion": 1,
      "position": [
        -100,
        -1540
      ],
      "id": "e4c9c209-ece7-4941-84b4-e1b688ba8717",
      "name": "GetAllMessage",
      "credentials": {
        "supabaseApi": {
          "id": "XnneQjbtAW4FyfV2",
          "name": "Supabase account"
        }
      }
    },
    {
      "parameters": {
        "content": "## Gộp tin nhắn và chuẩn hóa đầu vào\n- Ta sẽ dùng cơ chế debounce chờ thời gian x giây để gộp tin nhắn ngắt quãng sau đó chuẩn hóa đầu vào và gộp các tin nhắn lại thành 1 tin để gửi cho AI",
        "height": 500,
        "width": 680
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -140,
        -1680
      ],
      "typeVersion": 1,
      "id": "19f805f2-364b-4617-8298-bd8a9e3b24ae",
      "name": "Sticky Note3"
    },
    {
      "parameters": {
        "table": "fb_n8n_debounce",
        "key": "={{ $('StructureData').first().json.page_id }}_{{ $('StructureData').first().json.sender_id }}",
        "waitTime": 15
      },
      "type": "n8n-nodes-debounce.debouncePostgres",
      "typeVersion": 1,
      "position": [
        -380,
        -1880
      ],
      "id": "cf1f2061-71d6-437f-8d71-1ef73e742f2d",
      "name": "Debounce Postgres",
      "credentials": {
        "postgres": {
          "id": "GLfIWU3rbAidDMPe",
          "name": "Postgres account"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "f279a143-a74d-4cbb-b815-c8443c8626ef",
              "leftValue": "={{ $json.id }}",
              "rightValue": "",
              "operator": {
                "type": "number",
                "operation": "notExists",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        140,
        -2220
      ],
      "id": "ec6f6a84-96ed-44a3-b718-862bff82edd0",
      "name": "IfDoesNotExist",
      "alwaysOutputData": false
    },
    {
      "parameters": {
        "fieldToSplitOut": "messaging",
        "include": "allOtherFields",
        "options": {}
      },
      "type": "n8n-nodes-base.splitOut",
      "typeVersion": 1,
      "position": [
        -100,
        -2860
      ],
      "id": "e9a42272-61eb-4b8d-8c6d-982ea8bed0b7",
      "name": "Split Message"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "2cedc0a7-8b32-4b46-ab19-6c157e21268b",
              "name": "page_id",
              "value": "={{ $json.id }}",
              "type": "string"
            },
            {
              "id": "c9b6c3ed-40d0-4c27-b3f4-84661a6c8cee",
              "name": "sender_id",
              "value": "={{ $json.messaging.sender.id }}",
              "type": "string"
            },
            {
              "id": "d985d779-d0b0-4a56-bdef-15019e8d68ef",
              "name": "recipient_id",
              "value": "={{ $json.messaging.recipient.id }}",
              "type": "string"
            },
            {
              "id": "29d991a0-5395-4d62-aff3-e5739b0ddf83",
              "name": "timestamp",
              "value": "={{ $json.messaging.timestamp }}",
              "type": "string"
            },
            {
              "id": "4b38a917-b656-4e5a-be18-a2077557f2cf",
              "name": "message_id",
              "value": "={{ $json.messaging.message.mid }}",
              "type": "string"
            },
            {
              "id": "6c438dce-30b3-479e-a56a-1048c0ec39c9",
              "name": "text",
              "value": "={{ $json.messaging.message.text }}",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        140,
        -2860
      ],
      "id": "d3890627-baaf-47d7-8f07-4c3d9a636985",
      "name": "Map data"
    },
    {
      "parameters": {
        "content": "## Tiến hành phân tách dữ liệu từ messaging và gửi\n- Tại sao phải phân tách? Dữ liệu mà chúng ta nhận được lại cũng là 1 mảng messaging\n- Vậy nên có thể fb sẽ gửi tới nhiều message 1 lúc với 2 hoặc nhiều người dùng khác nhau\n- Cho nên ta phải tách nó ra để không gửi trả lời nhầm khách và không bị bỏ sót tin nhắn.\n### - **Chú ý:** Nhớ đổi lại url của webhook OnMessage trong sendOnMesage",
        "height": 320,
        "width": 680
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -140,
        -3020
      ],
      "typeVersion": 1,
      "id": "cba6c175-c082-442b-8cc5-9431611fb4a7",
      "name": "Sticky Note13"
    },
    {
      "parameters": {},
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        -80,
        -3960
      ],
      "id": "1245e070-03e2-4491-ae7f-0a8bce6530cb",
      "name": "When clicking ‘Test workflow’"
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "create table public.fb_chats (\n  id bigint generated by default as identity not null,\n  page_id text null,\n  sender_id text null,\n  recipient_id text null,\n  message_id text null,\n  text text null,\n  timestamp bigint null,\n  status character varying null default 'pending'::character varying,\n  created_at timestamp with time zone null default now(),\n  constraint fb_chats_pkey primary key (id),\n  constraint fb_chats_message_id_key unique (message_id)\n) TABLESPACE pg_default;\ncreate table public.fb_included_users (\n  id bigint generated by default as identity not null,\n  page_id text not null,\n  sender_id text null,\n  created_at timestamp with time zone not null default now(),\n  key text not null,\n  constraint fb_included_users_pkey primary key (id),\n  constraint fb_included_users_key_key unique (key),\n  constraint fb_included_users_key_key1 unique (key)\n) TABLESPACE pg_default;\ncreate table public.fb_n8n_debounce (\n  id bigint generated by default as identity not null,\n  key text not null,\n  incr bigint null default '0'::bigint,\n  constraint n8n_debounce_pkey primary key (id),\n  constraint n8n_debounce_key_key unique (key)\n) TABLESPACE pg_default;",
        "options": {}
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.6,
      "position": [
        140,
        -3960
      ],
      "id": "9fb263a5-1fb6-460a-856d-4426b536b919",
      "name": "Postgres",
      "credentials": {
        "postgres": {
          "id": "GLfIWU3rbAidDMPe",
          "name": "Postgres account"
        }
      }
    },
    {
      "parameters": {
        "documentId": {
          "__rl": true,
          "value": "https://docs.google.com/spreadsheets/d/1Cj-Szf6-TdZFREKKtvsWxaoGLzNIoOjkK3oITpOHJZ4/edit?gid=0#gid=0",
          "mode": "url"
        },
        "sheetName": {
          "__rl": true,
          "value": "gid=0",
          "mode": "list",
          "cachedResultName": "Trang",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1Cj-Szf6-TdZFREKKtvsWxaoGLzNIoOjkK3oITpOHJZ4/edit#gid=0"
        },
        "filtersUI": {
          "values": [
            {
              "lookupColumn": "page_id",
              "lookupValue": "={{ $('StructureData').last().json.page_id }}"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.6,
      "position": [
        340,
        -2500
      ],
      "id": "a267b1e0-15aa-4cb2-9df5-7e89946d37da",
      "name": "PageAccessToken",
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "FTFDT8ZBWVzqLvQP",
          "name": "Google Sheets account 2"
        }
      }
    },
    {
      "parameters": {
        "operation": "download",
        "fileId": {
          "__rl": true,
          "value": "={{ $json.image }}",
          "mode": "url"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.googleDrive",
      "typeVersion": 3,
      "position": [
        820,
        -300
      ],
      "id": "91315b5b-3dd2-415c-89c7-df01b93ce740",
      "name": "Google Drive",
      "credentials": {
        "googleDriveOAuth2Api": {
          "id": "qwY2h3fXNNEXEv2I",
          "name": "Google Drive account 2"
        }
      }
    },
    {
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini"
        },
        "options": {
          "temperature": 0.2
        }
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "typeVersion": 1.2,
      "position": [
        -120,
        -580
      ],
      "id": "bbc17f31-76b9-4f2c-9716-0bc4d62b238a",
      "name": "OpenAI Chat Model2",
      "credentials": {
        "openAiApi": {
          "id": "npnMtU7kA3sNSLyr",
          "name": "OpenAi Chatbot"
        }
      }
    },
    {
      "parameters": {
        "schemaType": "manual",
        "inputSchema": "{\n  \"type\": \"array\",\n  \"items\": {\n    \"type\": \"object\",\n    \"properties\": {\n      \"text\": {\n        \"type\": \"string\"\n      },\n      \"image\": {\n        \"type\": \"array\",\n        \"items\": {\n          \"type\": \"string\",\n          \"format\": \"uri\"\n        }\n      }\n    },\n    \"required\": [\"text\", \"image\"]\n  }\n}"
      },
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "typeVersion": 1.2,
      "position": [
        80,
        -580
      ],
      "id": "714c8e28-e017-4bd3-a8ca-2fd58cf5db79",
      "name": "Structured Output Parser"
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "={{ $json.output }}",
        "hasOutputParser": true,
        "messages": {
          "messageValues": [
            {
              "message": "Chuyển đoạn nội dung dưới đây thành mảng JSON theo format: [{ \"text\": \"nd\", \"image\": [\"url1\", \"url2\"] }] Với mỗi mục, \"text\" là phần mô tả của hình ảnh và \"image\" là mảng chứa link các ảnh trong mục đó. Bỏ qua định dạng Markdown, chỉ lấy nội dung và link ảnh."
            }
          ]
        }
      },
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "typeVersion": 1.6,
      "position": [
        -100,
        -740
      ],
      "id": "c8105476-b2e8-4f26-a3d6-f5702d442bd8",
      "name": "Basic LLM Chain",
      "retryOnFail": true
    },
    {
      "parameters": {
        "fieldToSplitOut": "output",
        "options": {}
      },
      "type": "n8n-nodes-base.splitOut",
      "typeVersion": 1,
      "position": [
        320,
        -740
      ],
      "id": "a0dd6b08-6378-476a-86a6-b1d5b5097156",
      "name": "Split Out2"
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "leftValue": "={{ encodeURI($json.image) }}",
                    "rightValue": "/https?:\\/\\/[^\\s]+?\\.(jpg|jpeg|png|gif)(\\?[^\\s]*)?/gi",
                    "operator": {
                      "type": "string",
                      "operation": "regex"
                    },
                    "id": "5bfc1fd6-bf94-4cae-b1fe-266c29502ad6"
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "link"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "4aa7cbe6-2423-490c-8b4d-9bbc8b951b75",
                    "leftValue": "={{ $json.image }}",
                    "rightValue": "https?://(?:drive\\.google\\.com|docs\\.google\\.com)/[^\\s\"']+",
                    "operator": {
                      "type": "string",
                      "operation": "regex"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "driver"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.2,
      "position": [
        620,
        -360
      ],
      "id": "6bdab641-29a2-48d2-a143-7c8db02e8990",
      "name": "Switch"
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 3,
      "position": [
        -320,
        -360
      ],
      "id": "b7b75cd8-aa7c-409f-9576-caccccd054a3",
      "name": "Loop Over Items"
    },
    {
      "parameters": {
        "amount": 1
      },
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1.1,
      "position": [
        -100,
        320
      ],
      "id": "aded66aa-0631-484e-b4a1-ff99adb15e58",
      "name": "Wait1",
      "webhookId": "cd206bd9-4224-42de-b5e2-61ba9bdadf32"
    },
    {
      "parameters": {
        "amount": 1
      },
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1.1,
      "position": [
        -100,
        60
      ],
      "id": "9d6c15e7-0d1d-4b54-9f55-fb27c1d11043",
      "name": "Wait2",
      "webhookId": "6d4c330d-4cc8-4494-85ca-633f206daefa"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://graph.facebook.com/v22.0/{{ $('PageAccessToken').last().json.page_id }}/messages",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "=Bearer {{ $('PageAccessToken').last().json.page_access_token }}"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"recipient\": {\n    \"id\": \"{{ $('MergeMessage').first().json.sender_id }}\"\n  },\n  \"message\": {\n   \"attachment\": {\n      \"type\": \"image\",\n      \"payload\": {\n          \"attachment_id\": \"{{ $json.attachment_id }}\"\n        }\n    }\n  }\n}",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        120,
        60
      ],
      "id": "a2ab7cb2-2215-4801-9d11-dffca263e719",
      "name": "SendAttachment"
    },
    {
      "parameters": {},
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [
        -320,
        -740
      ],
      "id": "1a79171e-05ef-4e88-96c3-ba331409a031",
      "name": "NextProcessLink"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "23d79f11-c9a3-4071-96c4-b3cb29d32fa9",
              "leftValue": "={{ $json.output }}",
              "rightValue": "https?://[^\\s\"']+",
              "operator": {
                "type": "string",
                "operation": "regex"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        -320,
        -1040
      ],
      "id": "3d955ed7-1934-4ea1-a3b8-6022684cc167",
      "name": "IfLinkExists"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://graph.facebook.com/v22.0/{{ $('PageAccessToken').last().json.page_id }}/messages",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "=Bearer {{ $('PageAccessToken').last().json.page_access_token }}"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"recipient\": {\n    \"id\": \"{{ $('MergeMessage').first().json.sender_id }}\"\n  },\n  \"message\": {\n    \"text\": {{ JSON.stringify($('IfExists').item.json.text) }}\n  }\n}",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        120,
        320
      ],
      "id": "a0722eb5-4b02-4b53-98ea-085fe2d17eba",
      "name": "SendMessage2",
      "alwaysOutputData": false,
      "executeOnce": true
    },
    {
      "parameters": {
        "url": "=https://graph.facebook.com/v22.0/{{ $('PageAccessToken').item.json.page_id }}/conversations",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "user_id",
              "value": "={{ $('StructureData').item.json.sender_id }}"
            },
            {
              "name": "limit",
              "value": "1"
            }
          ]
        },
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "=Bearer {{ $('PageAccessToken').last().json.page_access_token }}"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        -100,
        -1880
      ],
      "id": "3974d1c1-c358-4813-9f75-84d298564fcb",
      "name": "GetConversion"
    },
    {
      "parameters": {
        "url": "=https://graph.facebook.com/v22.0/{{ $json.id }}/messages",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "fields",
              "value": "message,from"
            },
            {
              "name": "limit",
              "value": "1"
            }
          ]
        },
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "=Bearer {{ $('PageAccessToken').last().json.page_access_token }}"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        360,
        -1880
      ],
      "id": "6e492dc6-6ebf-4532-9b6f-765e46b31a14",
      "name": "GetOldMessage"
    },
    {
      "parameters": {
        "tableId": "fb_included_users",
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "key",
              "fieldValue": "={{ $('StructureData').item.json.sender_id }}"
            },
            {
              "fieldId": "sender_id",
              "fieldValue": "={{ $('StructureData').item.json.sender_id }}"
            },
            {
              "fieldId": "page_id",
              "fieldValue": "={{ $('StructureData').item.json.page_id }}"
            }
          ]
        }
      },
      "type": "n8n-nodes-base.supabase",
      "typeVersion": 1,
      "position": [
        1160,
        -1880
      ],
      "id": "4384c10a-9c8c-48d5-9dcd-c69206bbd455",
      "name": "InsertToInclude",
      "credentials": {
        "supabaseApi": {
          "id": "XnneQjbtAW4FyfV2",
          "name": "Supabase account"
        }
      }
    },
    {
      "parameters": {
        "fieldToSplitOut": "data",
        "options": {}
      },
      "type": "n8n-nodes-base.splitOut",
      "typeVersion": 1,
      "position": [
        120,
        -1880
      ],
      "id": "26efafc6-8982-40f8-b446-1840041af3d9",
      "name": "Split Out4"
    },
    {
      "parameters": {},
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [
        1320,
        -2660
      ],
      "id": "9041a7e4-de8a-4961-9c1d-81a111a8cc7e",
      "name": "Stop"
    },
    {
      "parameters": {},
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [
        360,
        -2220
      ],
      "id": "e3969ead-1b36-4e98-a88f-76f743fbe37f",
      "name": "Stop. Chờ chủ page trả lời"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "22949b09-770e-431c-8838-6488d9deb41d",
              "leftValue": "={{ $json.id }}",
              "rightValue": "={{ $('StructureData').item.json.page_id+'' }}",
              "operator": {
                "type": "number",
                "operation": "notExists",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        880,
        -1880
      ],
      "id": "5cef1b1e-919e-4058-b47b-20cd1b8c83d5",
      "name": "IfPageReplyExists"
    },
    {
      "parameters": {
        "content": "## Tìm thread và lấy ra các tin nhắn đã gửi nhận\nLấy tin nhắn gửi nhận để kiểm tra xem chủ trang có tham gia chat trực tiếp với khách hay không. nếu chủ trang đã trả lời khách thì stop bot",
        "height": 280,
        "width": 680
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -140,
        -2020
      ],
      "typeVersion": 1,
      "id": "4039e811-bb7e-4475-9699-eeb0fd1a122f",
      "name": "Sticky Note6"
    },
    {
      "parameters": {
        "content": "## Kiểm tra xem có phải chủ Trang đã trả lời tin nhắn\nNếu chủ Trang đã trả lời tin nhắn thì ta đưa sender_id này và danh sách loại trừ để lần sau không cần phải kiểm tra nữa",
        "height": 280,
        "width": 720
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        580,
        -2020
      ],
      "typeVersion": 1,
      "id": "f8c2a213-4312-4040-9c55-0df7f79e7d9e",
      "name": "Sticky Note9"
    },
    {
      "parameters": {
        "content": "## Chờ để gom tin nhắn ngắt quãng hoặc chờ chủ trang trả lời\n",
        "height": 280,
        "width": 380
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -540,
        -2020
      ],
      "typeVersion": 1,
      "id": "14e8513c-ef32-49cc-b3a9-ccb94ea02a02",
      "name": "Sticky Note14"
    },
    {
      "parameters": {
        "content": "## Nếu trong nội dung có link (Ảnh hoặc file)\nSử dụng AI để tách nội dung và link ảnh riêng để phục vụ gửi attachment",
        "height": 380,
        "width": 680
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -140,
        -840
      ],
      "typeVersion": 1,
      "id": "117b5228-7c59-4060-a1f9-a72f8764ba93",
      "name": "Sticky Note15"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "4a008533-4c98-4124-b3b5-e13b3f1e22a9",
              "leftValue": "={{ $json.image }}",
              "rightValue": "",
              "operator": {
                "type": "array",
                "operation": "notEmpty",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        -60,
        -360
      ],
      "id": "bb3f830e-4e28-4d9d-bd66-2b07b4a98aff",
      "name": "IfExists"
    },
    {
      "parameters": {
        "content": "## Tách riêng thành từng link ảnh",
        "height": 300,
        "width": 680
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -140,
        -440
      ],
      "typeVersion": 1,
      "id": "82c18d15-9598-4a3d-a391-f7b3bc48ce7f",
      "name": "Sticky Note16"
    },
    {
      "parameters": {
        "fieldToSplitOut": "image",
        "options": {}
      },
      "type": "n8n-nodes-base.splitOut",
      "typeVersion": 1,
      "position": [
        320,
        -360
      ],
      "id": "1441cf68-1b84-4bb0-9868-3ca42eaaaf70",
      "name": "Split Out3"
    },
    {
      "parameters": {
        "content": "## Xử lý ảnh theo từng loại và upload lên fb\n- Nếu ảnh là link ảnh dạng .jpg thì sử dụng http để download và up lên fb\n- Nếu sử dụng ảnh drive thì ta dùng gg drive để download và up lên fb\n- Có thể tương tự với loại khác",
        "height": 480,
        "width": 700
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        580,
        -620
      ],
      "typeVersion": 1,
      "id": "27673342-45b0-4a4f-a8b3-caa250a34e35",
      "name": "Sticky Note17"
    },
    {
      "parameters": {
        "content": "## Gửi attachment ảnh",
        "height": 280,
        "width": 680
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -140,
        -100
      ],
      "typeVersion": 1,
      "id": "283f84ae-8071-489c-8e20-673bf3a7afae",
      "name": "Sticky Note18"
    },
    {
      "parameters": {
        "content": "## Chạy lệnh tạo cơ sở dữ liệu\n- Xác thực với Postgress ở trên supabase rồi chạy lệnh này để auto tạo sẵn các bảng\n- Sau khi tạo bảng xong thì bạn có thể xóa đoạn flow này đi",
        "height": 300,
        "width": 680
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -140,
        -4080
      ],
      "typeVersion": 1,
      "id": "bd9b1843-05cb-448f-af4e-cea97cb0b4d0",
      "name": "Sticky Note19"
    },
    {
      "parameters": {
        "content": "## Tạo chatbot facebook\nTừng bước cấu hình trong các node, lưu ý bỏ ghim ở node google sheet khi chạy\n![Guide](https://datadex.vn/storage/2025/06/Chatbot-reply-image.png)\n# [🎥 Hướng dẫn 1](https://youtu.be/w2zb47GC9-I)\n# [🎥 Hướng dẫn 2](https://www.youtube.com/watch?v=tiSCqrvqg0g)",
        "height": 700,
        "width": 700
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        580,
        -4080
      ],
      "typeVersion": 1,
      "id": "3899b11d-0871-4d0b-8513-0bfaf35c92bf",
      "name": "Sticky Note7"
    },
    {
      "parameters": {
        "operation": "get",
        "tableId": "fb_chats",
        "filters": {
          "conditions": [
            {
              "keyName": "message_id",
              "keyValue": "={{ $json.data[0].id }}"
            },
            {
              "keyName": "page_id",
              "keyValue": "={{ $('PageAccessToken').item.json.page_id }}"
            }
          ]
        }
      },
      "type": "n8n-nodes-base.supabase",
      "typeVersion": 1,
      "position": [
        620,
        -1880
      ],
      "id": "c949d34b-edb6-42f6-9c1e-1365dfabef1b",
      "name": "ExistsMessage1",
      "alwaysOutputData": true,
      "credentials": {
        "supabaseApi": {
          "id": "XnneQjbtAW4FyfV2",
          "name": "Supabase account"
        }
      }
    },
    {
      "parameters": {
        "tableId": "fb_chats",
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "page_id",
              "fieldValue": "={{ $('StructureData').last().json.page_id }}"
            },
            {
              "fieldId": "sender_id",
              "fieldValue": "={{ $('StructureData').last().json.page_id }}"
            },
            {
              "fieldId": "recipient_id",
              "fieldValue": "={{ $json.recipient_id }}"
            },
            {
              "fieldId": "timestamp",
              "fieldValue": "={{ $('StructureData').last().json.timestamp }}"
            },
            {
              "fieldId": "message_id",
              "fieldValue": "={{ $json.message_id }}"
            },
            {
              "fieldId": "text",
              "fieldValue": "={{ $('StructureTextOutput').item.json.output }}"
            },
            {
              "fieldId": "status",
              "fieldValue": "done"
            }
          ]
        }
      },
      "type": "n8n-nodes-base.supabase",
      "typeVersion": 1,
      "position": [
        1380,
        -1040
      ],
      "id": "7c0d90fb-fea0-4ad3-ac0d-bb3b89a00e1f",
      "name": "SaveToChats2",
      "credentials": {
        "supabaseApi": {
          "id": "XnneQjbtAW4FyfV2",
          "name": "Supabase account"
        }
      }
    },
    {
      "parameters": {
        "tableId": "fb_chats",
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "page_id",
              "fieldValue": "={{ $('StructureData').last().json.page_id }}"
            },
            {
              "fieldId": "sender_id",
              "fieldValue": "={{ $('StructureData').last().json.page_id }}"
            },
            {
              "fieldId": "recipient_id",
              "fieldValue": "={{ $json.recipient_id }}"
            },
            {
              "fieldId": "timestamp",
              "fieldValue": "={{ $('StructureData').last().json.timestamp }}"
            },
            {
              "fieldId": "message_id",
              "fieldValue": "={{ $json.message_id }}"
            },
            {
              "fieldId": "text",
              "fieldValue": "= "
            },
            {
              "fieldId": "status",
              "fieldValue": "done"
            }
          ]
        }
      },
      "type": "n8n-nodes-base.supabase",
      "typeVersion": 1,
      "position": [
        340,
        60
      ],
      "id": "c46d512f-32fc-44eb-acb3-8d2471e266b9",
      "name": "SaveToChats3",
      "credentials": {
        "supabaseApi": {
          "id": "XnneQjbtAW4FyfV2",
          "name": "Supabase account"
        }
      }
    },
    {
      "parameters": {
        "tableId": "fb_chats",
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "page_id",
              "fieldValue": "={{ $('StructureData').last().json.page_id }}"
            },
            {
              "fieldId": "sender_id",
              "fieldValue": "={{ $('StructureData').last().json.page_id }}"
            },
            {
              "fieldId": "recipient_id",
              "fieldValue": "={{ $json.recipient_id }}"
            },
            {
              "fieldId": "timestamp",
              "fieldValue": "={{ $('StructureData').last().json.timestamp }}"
            },
            {
              "fieldId": "message_id",
              "fieldValue": "={{ $json.message_id }}"
            },
            {
              "fieldId": "text",
              "fieldValue": "={{ $('IfExists').item.json.text }}"
            },
            {
              "fieldId": "status",
              "fieldValue": "done"
            }
          ]
        }
      },
      "type": "n8n-nodes-base.supabase",
      "typeVersion": 1,
      "position": [
        340,
        320
      ],
      "id": "a93f3103-8771-4351-ac2e-5d043a6dbb06",
      "name": "SaveToChats4",
      "credentials": {
        "supabaseApi": {
          "id": "XnneQjbtAW4FyfV2",
          "name": "Supabase account"
        }
      }
    },
    {
      "parameters": {},
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [
        -300,
        320
      ],
      "id": "cf3e4538-6fed-481a-a57d-dd103aa9c05c",
      "name": "Nếu không có ảnh"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://graph.facebook.com/v22.0/{{ $('PageAccessToken').last().json.page_id }}/message_attachments",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "=Bearer {{ $('PageAccessToken').last().json.page_access_token }}"
            }
          ]
        },
        "sendBody": true,
        "contentType": "multipart-form-data",
        "bodyParameters": {
          "parameters": [
            {
              "parameterType": "formBinaryData",
              "name": "filedata",
              "inputDataFieldName": "data"
            },
            {
              "name": "message",
              "value": "{\"attachment\":{\"type\":\"image\",\"payload\":{}}}"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1120,
        -300
      ],
      "id": "dddab727-862e-44a9-9498-2eff36875a14",
      "name": "upload_attachments_drive"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://graph.facebook.com/v22.0/{{ $('PageAccessToken').last().json.page_id }}/message_attachments",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "=Bearer {{ $('PageAccessToken').last().json.page_access_token }}"
            }
          ]
        },
        "sendBody": true,
        "contentType": "multipart-form-data",
        "bodyParameters": {
          "parameters": [
            {
              "name": "message",
              "value": "={\"attachment\":{\"type\":\"image\",\"payload\": {url:\"{{ $json.image }}\",is_reusable:true}}}"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1120,
        -480
      ],
      "id": "67bb32d8-c259-4137-96d4-8dce6bf648ea",
      "name": "upload_attachments_link"
    },
    {
      "parameters": {},
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [
        820,
        -480
      ],
      "id": "9a6046a7-f748-449b-a460-3a097c1376af",
      "name": "NextUpload"
    },
    {
      "parameters": {},
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [
        1340,
        -300
      ],
      "id": "b6e1b451-d70d-47dd-bb94-55c7748b70c8",
      "name": "UpAttachmentSuccess"
    },
    {
      "parameters": {
        "content": "## Gửi tin nhắn sau ảnh\nGửi tin nhắn ngay sau ảnh",
        "height": 260,
        "width": 680
      },
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -140,
        240
      ],
      "typeVersion": 1,
      "id": "8eba3ce9-ff26-4f23-8153-da11b299bf37",
      "name": "Sticky Note20"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://dxunek.datadex.vn/webhook/8c5196db-15df-470a-8fab-ac384b45b480",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ $json.toJsonString() }}",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        340,
        -2860
      ],
      "id": "4c1b144b-9597-438b-9eeb-52b1d0b63f75",
      "name": "SendOnMessage"
    }
  ],
  "pinData": {},
  "connections": {
    "If": {
      "main": [
        [
          {
            "node": "Verify success",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Verify fail",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent": {
      "main": [
        [
          {
            "node": "IfLinkExists",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Postgres Chat Memory": {
      "ai_memory": [
        [
          {
            "node": "AI Agent",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "Webhook": {
      "main": [
        [
          {
            "node": "If",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "RECEIVED",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "RECEIVED": {
      "main": [
        [
          {
            "node": "Split Out",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "data": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "SaveToChats": {
      "main": [
        [
          {
            "node": "GetUserIncluded",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "ExistsMessage": {
      "main": [
        [
          {
            "node": "NotFoundMessage",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "GetUserIncluded": {
      "main": [
        [
          {
            "node": "IfDoesNotExist",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "SendMessage": {
      "main": [
        [
          {
            "node": "SaveToChats2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "SendTypingOn": {
      "main": [
        [
          {
            "node": "Wait",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "NotFoundMessage": {
      "main": [
        [
          {
            "node": "Stop",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "SaveToChats",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Out": {
      "main": [
        [
          {
            "node": "Split Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OnMessage": {
      "main": [
        [
          {
            "node": "RespondOnMessage",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "StructureData": {
      "main": [
        [
          {
            "node": "PageAccessToken",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "RespondOnMessage": {
      "main": [
        [
          {
            "node": "StructureData",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "StructureTextOutput": {
      "main": [
        [
          {
            "node": "SendTypingOn",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait": {
      "main": [
        [
          {
            "node": "SendMessage",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "PromptSheet": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IFExistsMessage": {
      "main": [
        [
          {
            "node": "UpdateDoneMessage",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "MergeMessage": {
      "main": [
        [
          {
            "node": "PromptSheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "UpdateDoneMessage": {
      "main": [
        [
          {
            "node": "MergeMessage",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "GetAllMessage": {
      "main": [
        [
          {
            "node": "IFExistsMessage",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Debounce Postgres": {
      "main": [
        [
          {
            "node": "GetConversion",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IfDoesNotExist": {
      "main": [
        [
          {
            "node": "Debounce Postgres",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Stop. Chờ chủ page trả lời",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Message": {
      "main": [
        [
          {
            "node": "Map data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Map data": {
      "main": [
        [
          {
            "node": "SendOnMessage",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When clicking ‘Test workflow’": {
      "main": [
        [
          {
            "node": "Postgres",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "PageAccessToken": {
      "main": [
        [
          {
            "node": "ExistsMessage",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Drive": {
      "main": [
        [
          {
            "node": "upload_attachments_drive",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model2": {
      "ai_languageModel": [
        [
          {
            "node": "Basic LLM Chain",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "Basic LLM Chain",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Basic LLM Chain": {
      "main": [
        [
          {
            "node": "Split Out2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Out2": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Switch": {
      "main": [
        [
          {
            "node": "NextUpload",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Google Drive",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items": {
      "main": [
        [],
        [
          {
            "node": "IfExists",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait1": {
      "main": [
        [
          {
            "node": "SendMessage2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait2": {
      "main": [
        [
          {
            "node": "SendAttachment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "SendAttachment": {
      "main": [
        [
          {
            "node": "SaveToChats3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "NextProcessLink": {
      "main": [
        [
          {
            "node": "Basic LLM Chain",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IfLinkExists": {
      "main": [
        [
          {
            "node": "NextProcessLink",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "StructureTextOutput",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "SendMessage2": {
      "main": [
        [
          {
            "node": "SaveToChats4",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "GetConversion": {
      "main": [
        [
          {
            "node": "Split Out4",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "GetOldMessage": {
      "main": [
        [
          {
            "node": "ExistsMessage1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Out4": {
      "main": [
        [
          {
            "node": "GetOldMessage",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IfPageReplyExists": {
      "main": [
        [
          {
            "node": "InsertToInclude",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "GetAllMessage",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IfExists": {
      "main": [
        [
          {
            "node": "Split Out3",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Nếu không có ảnh",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Out3": {
      "main": [
        [
          {
            "node": "Switch",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "ExistsMessage1": {
      "main": [
        [
          {
            "node": "IfPageReplyExists",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "SaveToChats3": {
      "main": [
        [
          {
            "node": "Wait1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "SaveToChats4": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Nếu không có ảnh": {
      "main": [
        [
          {
            "node": "Wait1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "upload_attachments_drive": {
      "main": [
        [
          {
            "node": "UpAttachmentSuccess",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "upload_attachments_link": {
      "main": [
        [
          {
            "node": "UpAttachmentSuccess",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "NextUpload": {
      "main": [
        [
          {
            "node": "upload_attachments_link",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "UpAttachmentSuccess": {
      "main": [
        [
          {
            "node": "Wait2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "b4bfd55a-293a-42ab-8bb3-133e5e67f0df",
  "meta": {
    "templateCredsSetupCompleted": true,
    "instanceId": "588a021bb54b760204dc9fed657516230744845e005fe72c0f4b0664fd815974"
  },
  "id": "79G0Wig6UiyxNYpU",
  "tags": []
}
