{
  "id": "rbbgcf1n8aIwsPQCyOyMm",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Look up English vocabulary via Telegram and save to Notion",
  "tags": [],
  "nodes": [
    {
      "id": "4a12ebd5-2cbc-465b-9712-c40dfef07d4d",
      "name": "Telegram Trigger",
      "type": "n8n-nodes-base.telegramTrigger",
      "position": [
        6496,
        2304
      ],
      "parameters": {
        "updates": [
          "message"
        ],
        "additionalFields": {}
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "226ad3fb-98ef-4dcb-ae00-9131a2f70d7c",
      "name": "Config \u2014 Edit Me",
      "type": "n8n-nodes-base.set",
      "notes": "Edit all 4 values here before activating the workflow",
      "position": [
        6736,
        2304
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "cfg-001-chat-id",
              "name": "TELEGRAM_CHAT_ID",
              "type": "string",
              "value": "8308632587"
            },
            {
              "id": "cfg-002-bot-token",
              "name": "TELEGRAM_BOT_TOKEN",
              "type": "string",
              "value": "8468012209:AAEal9MCFWnF486JhjSNWzu4JcNx3suPPEU"
            },
            {
              "id": "cfg-003-notion-db",
              "name": "NOTION_VOCABULARY_DB_ID",
              "type": "string",
              "value": "17677348359f80529dabe1fd2acdb75b"
            },
            {
              "id": "cfg-004-lang",
              "name": "TARGET_LANGUAGE",
              "type": "string",
              "value": "Traditional Chinese"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "a5744a26-84d6-4a00-b78d-d8e80a0f5c91",
      "name": "Authorize User",
      "type": "n8n-nodes-base.if",
      "position": [
        6960,
        2304
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "auth-cond-001",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ String($('Telegram Trigger').item.json.message.chat.id) }}",
              "rightValue": "={{ $('Config \u2014 Edit Me').item.json.TELEGRAM_CHAT_ID }}"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "7df16993-db47-4926-b7a8-dcd10660911b",
      "name": "Reject Unauthorized User",
      "type": "n8n-nodes-base.telegram",
      "position": [
        7232,
        2528
      ],
      "parameters": {
        "text": "Sorry, you are not authorized to use this bot.",
        "chatId": "={{ $('Telegram Trigger').item.json.message.chat.id }}",
        "additionalFields": {
          "appendAttribution": false
        }
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "c295ba6a-e7cf-403a-b9f1-86692eadbbaa",
      "name": "Detect Input Type",
      "type": "n8n-nodes-base.switch",
      "position": [
        7344,
        2112
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "text",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "loose"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "switch-cond-text",
                    "operator": {
                      "type": "string",
                      "operation": "notEmpty"
                    },
                    "leftValue": "={{ $('Telegram Trigger').item.json.message.text }}"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "voice",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "loose"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "switch-cond-voice",
                    "operator": {
                      "type": "string",
                      "operation": "notEmpty"
                    },
                    "leftValue": "={{ $('Telegram Trigger').item.json.message.voice?.file_id }}"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "photo",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "loose"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "switch-cond-photo",
                    "operator": {
                      "type": "string",
                      "operation": "notEmpty"
                    },
                    "leftValue": "={{ $('Telegram Trigger').item.json.message.photo?.[0]?.file_id }}"
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {
          "fallbackOutput": "none"
        }
      },
      "typeVersion": 3.2
    },
    {
      "id": "fd8d6328-ff86-47bb-89ab-0605f1f28056",
      "name": "Set Text Input",
      "type": "n8n-nodes-base.set",
      "position": [
        8016,
        1952
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "txt-001",
              "name": "chat_input",
              "type": "string",
              "value": "={{ $('Telegram Trigger').item.json.message.text }}"
            },
            {
              "id": "txt-002",
              "name": "type",
              "type": "string",
              "value": "text"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "fd31e824-1abd-483e-808e-307558859ced",
      "name": "Get Voice File",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        7568,
        2128
      ],
      "parameters": {
        "url": "=https://api.telegram.org/bot{{ $('Config \u2014 Edit Me').item.json.TELEGRAM_BOT_TOKEN }}/getFile?file_id={{ $('Telegram Trigger').item.json.message.voice.file_id }}",
        "options": {}
      },
      "typeVersion": 4.2
    },
    {
      "id": "d3ac2d24-dc59-4fe4-9789-23008455ff03",
      "name": "Download Audio",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        7792,
        2128
      ],
      "parameters": {
        "url": "=https://api.telegram.org/file/bot{{ $('Config \u2014 Edit Me').item.json.TELEGRAM_BOT_TOKEN }}/{{ $json.result.file_path }}",
        "options": {
          "response": {
            "response": {
              "responseFormat": "file"
            }
          }
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "26431ab7-45ee-445f-a880-8ac096a1ceb1",
      "name": "Transcribe Audio (Whisper)",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "notes": "Transcribes voice messages to text",
      "position": [
        8016,
        2128
      ],
      "parameters": {
        "options": {},
        "resource": "audio",
        "operation": "transcribe"
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.8
    },
    {
      "id": "66c4d4c1-706a-43d0-b82f-6bf828d6b076",
      "name": "Set Voice Text",
      "type": "n8n-nodes-base.set",
      "position": [
        8240,
        2128
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "voice-001",
              "name": "chat_input",
              "type": "string",
              "value": "={{ $json.text }}"
            },
            {
              "id": "voice-002",
              "name": "type",
              "type": "string",
              "value": "voice"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "33966da6-f711-4c7f-a354-288b132da6bc",
      "name": "Get Photo File",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        7568,
        2336
      ],
      "parameters": {
        "url": "=https://api.telegram.org/bot{{ $('Config \u2014 Edit Me').item.json.TELEGRAM_BOT_TOKEN }}/getFile?file_id={{ $('Telegram Trigger').item.json.message.photo.at(-1).file_id }}",
        "options": {}
      },
      "typeVersion": 4.2
    },
    {
      "id": "edd2f2e1-589e-4c46-b207-2c4231891051",
      "name": "Download Image",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        7792,
        2336
      ],
      "parameters": {
        "url": "=https://api.telegram.org/file/bot{{ $('Config \u2014 Edit Me').item.json.TELEGRAM_BOT_TOKEN }}/{{ $json.result.file_path }}",
        "options": {
          "response": {
            "response": {
              "responseFormat": "file"
            }
          }
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "a9b1ede7-05d5-465e-9bfb-93aaf28c783b",
      "name": "Fix Image MIME Type",
      "type": "n8n-nodes-base.code",
      "position": [
        8016,
        2336
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\nfor (const item of items) {\n  if (item.binary?.data) {\n    item.binary.data.mimeType = 'image/jpeg';\n    item.binary.data.fileExtension = 'jpg';\n  }\n}\nreturn items;"
      },
      "typeVersion": 2
    },
    {
      "id": "1d3a56c3-5ed2-4e5f-b2c9-7c44946f6444",
      "name": "Analyze Image",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        8240,
        2336
      ],
      "parameters": {
        "text": "Extract any English words or text from this image. Output only the words, no explanations.",
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini",
          "cachedResultName": "GPT-4O-MINI"
        },
        "options": {},
        "resource": "image",
        "inputType": "base64",
        "operation": "analyze"
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.8
    },
    {
      "id": "e0a512ba-913a-4b00-874e-4063c53e5a38",
      "name": "Set Photo Text",
      "type": "n8n-nodes-base.set",
      "position": [
        8448,
        2336
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "photo-001",
              "name": "chat_input",
              "type": "string",
              "value": "={{ $json.content }}"
            },
            {
              "id": "photo-002",
              "name": "type",
              "type": "string",
              "value": "photo"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "f3993415-254f-41fb-a630-b174171b467c",
      "name": "Dictionary Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        8704,
        2144
      ],
      "parameters": {
        "text": "={{ $json.chat_input }}",
        "options": {
          "systemMessage": "=You are a vocabulary assistant. For the English word provided:\n\n1. Check spelling \u2014 if incorrect, identify the most likely intended word (e.g. guibble \u2192 quibble) and look up that corrected word.\n2. If spelling is correct, look up the word directly.\n\nThe 'translation' and 'example_translation' fields must be written in {{ $('Config \u2014 Edit Me').item.json.TARGET_LANGUAGE }}.\n\nReturn structured output only. Do not add any introductory text or commentary. If a field cannot be filled, use 'N/A'."
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 2.2
    },
    {
      "id": "177efefc-488a-48df-85c8-4b3e9c9b916e",
      "name": "OpenAI (Dictionary)",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        8704,
        2368
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "3a80d08a-bf73-40d6-aa4e-1f8da93dac01",
      "name": "Dictionary Output Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        8848,
        2368
      ],
      "parameters": {
        "jsonSchemaExample": "{\n    \"word\": \"phenomenon\",\n    \"definition\": \"something that exists and can be seen, felt, tasted, etc., especially something unusual or interesting\",\n    \"translation\": \"\uff08\u5c24\u6307\u4e0d\u5c0b\u5e38\u7684\u6216\u6709\u8da3\u7684\uff09\u73fe\u8c61\",\n    \"part_of_speech\": \"noun\",\n    \"example_sentence\": \"Gravity is a natural phenomenon.\",\n    \"example_translation\": \"\u91cd\u529b\u662f\u4e00\u7a2e\u81ea\u7136\u73fe\u8c61\u3002\"\n}\n"
      },
      "typeVersion": 1.3
    },
    {
      "id": "6bf8d2c4-5286-40ff-8f51-4a5619b95d57",
      "name": "Send Telegram Reply",
      "type": "n8n-nodes-base.telegram",
      "position": [
        9008,
        2144
      ],
      "parameters": {
        "text": "=\ud83d\udcd6 {{ $json.output.word }}\n\nPart of speech: {{ $json.output.part_of_speech }}\nDefinition: {{ $json.output.definition }}\nTranslation: {{ $json.output.translation }}\n\nExample: {{ $json.output.example_sentence }}\n{{ $json.output.example_translation }}",
        "chatId": "={{ $('Telegram Trigger').item.json.message.chat.id }}",
        "additionalFields": {
          "appendAttribution": false
        }
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "dcf8fea9-2f95-4502-acc9-3e76ad044622",
      "name": "Save Vocabulary to Notion",
      "type": "n8n-nodes-base.notion",
      "position": [
        9184,
        2144
      ],
      "parameters": {
        "title": "={{ $('Dictionary Agent').item.json.output.word }}",
        "simple": false,
        "options": {},
        "resource": "databasePage",
        "databaseId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Config \u2014 Edit Me').item.json.NOTION_VOCABULARY_DB_ID }}"
        },
        "propertiesUi": {
          "propertyValues": [
            {
              "key": "Description|rich_text",
              "textContent": "=Definition: {{ $('Dictionary Agent').item.json.output.definition }}\nTranslation: {{ $('Dictionary Agent').item.json.output.translation }}\nPart of speech: {{ $('Dictionary Agent').item.json.output.part_of_speech }}\nExample: {{ $('Dictionary Agent').item.json.output.example_sentence }}\nExample translation: {{ $('Dictionary Agent').item.json.output.example_translation }}\nWord: {{ $('Dictionary Agent').item.json.output.word }}"
            }
          ]
        }
      },
      "credentials": {
        "notionApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2,
      "alwaysOutputData": false
    },
    {
      "id": "3346999c-b78b-4129-bb5a-269b71a1934a",
      "name": "Sticky Note - Main",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        6416,
        1600
      ],
      "parameters": {
        "width": 680,
        "height": 520,
        "content": "## How it works\n\nThis workflow powers a personal Telegram bot for building English vocabulary. When you send a message \u2014 text, voice, or photo \u2014 the bot detects the input type and processes it: voice messages are transcribed via Whisper, photos are scanned via GPT-4o-mini Vision OCR to extract words. The extracted text is passed to a GPT-4.1-mini agent that checks spelling, then returns the word, definition, translation, part of speech, and an example sentence. The translation language is controlled by `TARGET_LANGUAGE` in the Config node \u2014 set it to any language you need (e.g. Traditional Chinese, Japanese, Spanish). The reply is sent back via Telegram and the entry is saved to Notion for later review.\n\n## Setup steps\n\n1. Open **Config \u2014 Edit Me** and set: `TELEGRAM_CHAT_ID`, `TELEGRAM_BOT_TOKEN`, `NOTION_VOCABULARY_DB_ID`, and `TARGET_LANGUAGE` (e.g. `Traditional Chinese`, `Japanese`, `Spanish`).\n2. Create a bot via [@BotFather](https://t.me/botfather) and copy the token.\n3. Get your chat ID by messaging [@userinfobot](https://t.me/userinfobot).\n4. Add credentials: **Telegram Bot API**, **OpenAI API**, **Notion API**.\n5. Activate the workflow \u2014 the webhook is registered automatically.\n6. Send any English word to your bot to test, for example: `phenomenon`."
      },
      "typeVersion": 1
    },
    {
      "id": "2b504b07-c2a2-4985-9bac-b0848dfc8469",
      "name": "Sticky Note - Group 1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        6384,
        2176
      ],
      "parameters": {
        "color": 7,
        "width": 820,
        "height": 280,
        "content": "## Entry & Security\n\nReceives incoming Telegram messages, loads config values, and checks the sender's chat ID. Only the authorised user continues; others receive a rejection notice."
      },
      "typeVersion": 1
    },
    {
      "id": "0903a7aa-40b3-4097-bf2d-9bb0760dcf43",
      "name": "Sticky Note - Group 2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        7248,
        1792
      ],
      "parameters": {
        "color": 7,
        "width": 1368,
        "height": 700,
        "content": "## Input Detection & Processing\n\nRoutes each message by type: text passes through directly, voice is transcribed via Whisper, and photos are processed via GPT-4o-mini Vision OCR. All paths produce a unified `chat_input` value for the AI agent."
      },
      "typeVersion": 1
    },
    {
      "id": "e03ac732-886c-4959-b802-dd1d0019f496",
      "name": "Sticky Note - Group 3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        8656,
        1920
      ],
      "parameters": {
        "color": 7,
        "width": 760,
        "height": 400,
        "content": "## AI Lookup & Output\n\nA GPT-4.1-mini agent spell-checks the input, then returns structured vocabulary data. The result is sent back as a Telegram reply and saved to the Notion vocabulary database."
      },
      "typeVersion": 1
    },
    {
      "id": "a830db2b-7d9c-4403-a3ab-8d5f506c73e2",
      "name": "Sticky Note - CTA",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        8912,
        1680
      ],
      "parameters": {
        "color": 7,
        "width": 760,
        "height": 200,
        "content": "## Want more automation templates?\n\nCheck out the **Content Automation Bundle** \u2014 6 n8n workflows for AI content creation, social media publishing, and Threads analytics.\n\n\ud83d\udc49 https://jasonchuang0818.gumroad.com/l/n8n-content-automation-bundle"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "8582c029-ae21-414d-baf4-3e1bdc039946",
  "connections": {
    "Analyze Image": {
      "main": [
        [
          {
            "node": "Set Photo Text",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Authorize User": {
      "main": [
        [
          {
            "node": "Detect Input Type",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Reject Unauthorized User",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download Audio": {
      "main": [
        [
          {
            "node": "Transcribe Audio (Whisper)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download Image": {
      "main": [
        [
          {
            "node": "Fix Image MIME Type",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Photo File": {
      "main": [
        [
          {
            "node": "Download Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Voice File": {
      "main": [
        [
          {
            "node": "Download Audio",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Photo Text": {
      "main": [
        [
          {
            "node": "Dictionary Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Text Input": {
      "main": [
        [
          {
            "node": "Dictionary Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Voice Text": {
      "main": [
        [
          {
            "node": "Dictionary Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Dictionary Agent": {
      "main": [
        [
          {
            "node": "Send Telegram Reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Telegram Trigger": {
      "main": [
        [
          {
            "node": "Config \u2014 Edit Me",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Detect Input Type": {
      "main": [
        [
          {
            "node": "Set Text Input",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Get Voice File",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Get Photo File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Config \u2014 Edit Me": {
      "main": [
        [
          {
            "node": "Authorize User",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fix Image MIME Type": {
      "main": [
        [
          {
            "node": "Analyze Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI (Dictionary)": {
      "ai_languageModel": [
        [
          {
            "node": "Dictionary Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Send Telegram Reply": {
      "main": [
        [
          {
            "node": "Save Vocabulary to Notion",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Dictionary Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "Dictionary Agent",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Transcribe Audio (Whisper)": {
      "main": [
        [
          {
            "node": "Set Voice Text",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}