8
n8n 中文网amn8n.com

AI Telegram 问答机器人(自动生成问题与用户管理)

高级

这是一个Miscellaneous, AI Chatbot领域的自动化工作流,包含 41 个节点。主要使用 If, Code, Merge, NocoDb, Switch 等节点。 具备自动问题生成和用户管理功能的 AI Telegram 问答机器人

前置要求
  • Telegram Bot Token
  • OpenAI API Key
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
  "meta": {
    "instanceId": "c668632f5ca4908ffa76bd7bc9be05dec193c66269ed7a1160909b2e861050b7",
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "d9902b39-9d8d-4109-bfda-0a255c72cf1f",
      "name": "Telegram 触发器",
      "type": "n8n-nodes-base.telegramTrigger",
      "position": [
        -1200,
        -720
      ],
      "webhookId": "689feb2a-dce5-4f9b-b62f-8ed52e510683",
      "parameters": {
        "updates": [
          "message"
        ],
        "additionalFields": {}
      },
      "credentials": {
        "telegramApi": {
          "id": "SlR5McCoTpMXB5Mc",
          "name": "TriviaBot"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "78ac5309-7baa-4002-ab26-10c5c1242cd3",
      "name": "解析 Telegram 数据",
      "type": "n8n-nodes-base.code",
      "position": [
        -1000,
        -720
      ],
      "parameters": {
        "jsCode": "// Parse incoming Telegram data\nconst message = items[0].json.message;\nconst user = message.from;\nconst text = message.text || '';\nconst chatId = message.chat.id;\n\n// Determine message type\nlet messageType = 'text';\nlet command = null;\nlet isCommand = false;\n\nif (text.startsWith('/')) {\n  isCommand = true;\n  command = text.split(' ')[0].toLowerCase();\n  messageType = 'command';\n}\n\n// Extract user info\nconst userData = {\n  telegram_id: user.id,\n  username: user.username || '',\n  first_name: user.first_name || '',\n  last_name: user.last_name || '',\n  chat_id: chatId\n};\n\nreturn [{\n  json: {\n    message_type: messageType,\n    command: command,\n    text: text,\n    user: userData,\n    raw_message: message,\n    is_command: isCommand\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "a98966f7-c63a-4376-bc50-cddf4764009b",
      "name": "检查现有用户",
      "type": "n8n-nodes-base.nocoDb",
      "notes": "Users table",
      "position": [
        -780,
        -720
      ],
      "parameters": {
        "limit": 1,
        "options": {
          "where": "=(telegram_id,like,{{ $('Parse Telegram Data').item.json.user.telegram_id }})"
        },
        "operation": "getAll",
        "authentication": "nocoDbApiToken"
      },
      "credentials": {
        "nocoDbApiToken": {
          "id": "6M0tdo5lEJ6wbxJZ",
          "name": "n8n Token"
        }
      },
      "notesInFlow": true,
      "typeVersion": 3,
      "alwaysOutputData": true
    },
    {
      "id": "e61286d1-94ed-40f5-ba5c-1211fd8247a6",
      "name": "用户存在?",
      "type": "n8n-nodes-base.if",
      "position": [
        -580,
        -720
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "ba1bc824-082e-45f4-be31-3e4186ca7c4c",
              "operator": {
                "type": "number",
                "operation": "exists",
                "singleValue": true
              },
              "leftValue": "={{ $json.Id }}",
              "rightValue": 0
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "77097a18-d05d-4211-9c85-e1bbc821f960",
      "name": "创建新用户",
      "type": "n8n-nodes-base.nocoDb",
      "notes": "Users table",
      "position": [
        -380,
        -520
      ],
      "parameters": {
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldName": "telegram_id",
              "fieldValue": "={{ $('Parse Telegram Data').item.json.user.telegram_id }}"
            },
            {
              "fieldName": "username",
              "fieldValue": "={{ $('Parse Telegram Data').item.json.user.username }}"
            },
            {
              "fieldName": "first_name",
              "fieldValue": "={{ $('Parse Telegram Data').item.json.user.first_name }}"
            },
            {
              "fieldName": "last_name",
              "fieldValue": "={{ $('Parse Telegram Data').item.json.user.last_name }}"
            },
            {
              "fieldName": "score",
              "fieldValue": "0"
            },
            {
              "fieldName": "games_played",
              "fieldValue": "0"
            },
            {
              "fieldName": "correct_answers",
              "fieldValue": "0"
            },
            {
              "fieldName": "game_state",
              "fieldValue": "idle"
            }
          ]
        },
        "operation": "create",
        "authentication": "nocoDbApiToken"
      },
      "credentials": {
        "nocoDbApiToken": {
          "id": "6M0tdo5lEJ6wbxJZ",
          "name": "n8n Token"
        }
      },
      "notesInFlow": true,
      "typeVersion": 3
    },
    {
      "id": "ebfffcd2-1a37-4aa9-9bd3-052552de448f",
      "name": "合并用户数据",
      "type": "n8n-nodes-base.code",
      "position": [
        -180,
        -740
      ],
      "parameters": {
        "jsCode": "// Merge user data from either existing user or newly created user\nconst telegramData = $('Parse Telegram Data').first().json;\nconst existingUser = $('Check Existing User').first().json;\nconst newUser = $input.all().find(item => item.json.id); // From Create New User\nconsole.log(existingUser, 'ovo')\nlet userData;\nif (existingUser) {\n  userData = existingUser;\n} else if (newUser) {\n  userData = newUser.json;\n} else {\n  userData = {\n    telegram_id: telegramData.user.telegram_id,\n    score: 0,\n    game_state: 'idle'\n  };\n}\n\nreturn [{\n  json: {\n    ...telegramData,\n    user_data: userData\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "6803deb8-17bd-42f5-9981-d48f6db3f2e5",
      "name": "是命令?",
      "type": "n8n-nodes-base.if",
      "position": [
        0,
        -740
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "a71cbee3-b6da-4a5a-9a1d-eb58000aa521",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $('Merge User Data').item.json.is_command }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "79f6d733-2f08-4992-a129-7672674bc28d",
      "name": "命令路由器",
      "type": "n8n-nodes-base.switch",
      "position": [
        260,
        -800
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "1a20a83b-ea74-4bff-8d6c-5d0c3a406b96",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $('Merge User Data').item.json.command }}",
                    "rightValue": "/start"
                  }
                ]
              }
            },
            {
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "9168b33d-ad7a-481a-92dc-4d8c3e13c713",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $('Merge User Data').item.json.command }}",
                    "rightValue": "/help"
                  }
                ]
              }
            },
            {
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "2952abe2-754f-4415-a427-702da4aab27e",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $('Merge User Data').item.json.command }}",
                    "rightValue": "/score"
                  }
                ]
              }
            },
            {
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "2349fa37-7742-43a4-a9d9-76e77a044fa2",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $('Merge User Data').item.json.command }}",
                    "rightValue": "/stats"
                  }
                ]
              }
            },
            {
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "6eebbcfd-18bf-4f4e-85b1-2536a88328fa",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $('Merge User Data').item.json.command }}",
                    "rightValue": "/question"
                  }
                ]
              }
            },
            {
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "4da11fe6-2af8-4a18-8b45-8621e5c1ea86",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $('Merge User Data').item.json.command }}",
                    "rightValue": "/leaderboard"
                  }
                ]
              }
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.2
    },
    {
      "id": "e1eeecea-f282-4651-9354-94418aa867e0",
      "name": "处理基本命令",
      "type": "n8n-nodes-base.code",
      "position": [
        1400,
        -900
      ],
      "parameters": {
        "jsCode": "const command = items[0].json.command;\nconst userData = items[0].json.user_data;\nconst userName = userData.first_name || userData.username || 'Player';\n\nlet responseText = '';\n\nswitch(command) {\n  case '/start':\n    responseText = `🎉 Welcome to Trivia Bot, ${userName}!\n\n🧠 Test your knowledge with our trivia questions!\n\nCommands:\n/question - Get a new question\n/score - Check your score\n/leaderboard - View top players\n/stats - Your statistics\n/help - Show this help\n\nGood luck! 🍀`;\n    break;\n    \n  case '/help':\n    responseText = `📚 **Trivia Bot Help**\n\n🎯 **Commands:**\n/question - Get a new trivia question\n/score - Check your current score\n/leaderboard - View top 10 players\n/stats - Your detailed statistics\n/help - Show this help message\n\n🎮 **How to Play:**\n1. Use /question to get a new question\n2. Reply with A, B, C, or D\n3. Earn points for correct answers\n4. Climb the leaderboard!\n\n🏆 **Scoring:**\n- ⭐: 1 point\n- ⭐⭐: 2 points\n- ⭐⭐⭐: 3 points\n- ⭐⭐⭐⭐: 4 points\n- ⭐⭐⭐⭐⭐: 5 points\n\nHave fun! 🎉`;\n    break;\n    \n  case '/score':\n    responseText = `🏆 **Your Score**\n\n📊 Current Score: ${userData.score || 0} points\n🎮 Games Played: ${userData.games_played || 0}\n✅ Correct Answers: ${userData.correct_answers || 0}\n\nKeep playing to improve your score! 💪`;\n    break;\n    \n  case '/stats':\n    const accuracy = userData.games_played > 0 ? \n      Math.round((userData.correct_answers / userData.games_played) * 100) : 0;\n    responseText = `📈 **Your Statistics**\n\n🏆 Total Score: ${userData.score || 0} points\n🎯 Accuracy: ${accuracy}%\n🎮 Games Played: ${userData.games_played || 0}\n✅ Correct Answers: ${userData.correct_answers || 0}\n❌ Wrong Answers: ${(userData.games_played || 0) - (userData.correct_answers || 0)}\n\nYou're doing great! Keep it up! 🚀`;\n    break;\n    \n  default:\n    responseText = `❓ Unknown command: ${command}\n\nUse /help to see available commands.`;\n}\n\nreturn [{\n  json: {\n    chat_id: items[0].json.user.chat_id,\n    response_text: responseText,\n    command: command\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "d5831643-79a8-4671-a90c-c5c01014cb4f",
      "name": "格式化问题",
      "type": "n8n-nodes-base.code",
      "position": [
        1220,
        -760
      ],
      "parameters": {
        "jsCode": "const question = $('Get Random Question').first().json;\nconst userData = $('Merge User Data').first().json.user;\n\nif (!question) {\n  return [{\n    json: {\n      chat_id: userData.chat_id,\n      response_text: \"❌ Sorry, no questions available right now. Please try again later.\"\n    }\n  }];\n}\n\nconst questionText = `🧠 **Trivia Question** (${question.difficulty || 'Medium'})\n\n❓ ${question.question}\n\nA) ${question.option_a}\nB) ${question.option_b}\nC) ${question.option_c}\nD) ${question.option_d}\n\n💡 Reply with A, B, C, or D!`;\n\nreturn [{\n  json: {\n    chat_id: userData.chat_id,\n    response_text: questionText,\n    question_data: question,\n    user_data: userData\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "3e96876a-d775-47e5-85ad-a2d3f221a930",
      "name": "更新用户游戏状态",
      "type": "n8n-nodes-base.nocoDb",
      "notes": "Users",
      "position": [
        1240,
        -480
      ],
      "parameters": {
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldName": "telegram_id",
              "fieldValue": "={{ $('Is Command?').item.json.user.telegram_id }}"
            },
            {
              "fieldName": "Id",
              "fieldValue": "={{ $('Is Command?').item.json.user_data.Id }}"
            },
            {
              "fieldName": "game_state",
              "fieldValue": "waiting_answer"
            },
            {
              "fieldName": "current_question_id",
              "fieldValue": "={{ $json.Id }}"
            }
          ]
        },
        "operation": "update",
        "authentication": "nocoDbApiToken"
      },
      "credentials": {
        "nocoDbApiToken": {
          "id": "6M0tdo5lEJ6wbxJZ",
          "name": "n8n Token"
        }
      },
      "notesInFlow": true,
      "typeVersion": 3,
      "alwaysOutputData": false
    },
    {
      "id": "1e03df0d-5ead-4f82-8565-a1dd9391dcb1",
      "name": "获取排行榜",
      "type": "n8n-nodes-base.nocoDb",
      "notes": "Users",
      "position": [
        660,
        -440
      ],
      "parameters": {
        "limit": 10,
        "options": {
          "sort": {
            "property": [
              {
                "field": "score",
                "direction": "desc"
              }
            ]
          }
        },
        "operation": "getAll",
        "authentication": "nocoDbApiToken"
      },
      "credentials": {
        "nocoDbApiToken": {
          "id": "6M0tdo5lEJ6wbxJZ",
          "name": "n8n Token"
        }
      },
      "notesInFlow": true,
      "typeVersion": 3
    },
    {
      "id": "ea723525-a09e-429e-86b2-c4b13db0f4b6",
      "name": "格式化排行榜",
      "type": "n8n-nodes-base.code",
      "position": [
        1420,
        -280
      ],
      "parameters": {
        "jsCode": "const leaderboard = $input.first().json.leaderboard;\nconst currentUser = $('Merge User Data').item.json.user_data;\n\nif (!leaderboard || leaderboard.length === 0) {\n  return [{\n    json: {\n      chat_id: $('Merge User Data').item.json.user.chat_id,\n      response_text: \"🏆 **Leaderboard**\\n\\nNo players yet! Be the first to play!\"\n    }\n  }];\n}\n\nlet leaderboardText = \"🏆 **Trivia Leaderboard** 🏆\\n\\n\";\n\nleaderboard.forEach((player, index) => {\n  const emoji = index === 0 ? \"🥇\" : index === 1 ? \"🥈\" : index === 2 ? \"🥉\" : \"🔸\";\n  const name = player.first_name || player.username || 'Anonymous';\n  const isCurrentUser = player.telegram_id === currentUser.telegram_id;\n  const marker = isCurrentUser ? \" ← YOU\" : \"\";\n  \n  leaderboardText += `${emoji} ${index + 1}. ${name}: ${player.score || 0} pts${marker}\\n`;\n});\n\n// Find current user's rank if not in top 10\nconst currentUserRank = leaderboard.findIndex(p => p.telegram_id === currentUser.telegram_id);\nif (currentUserRank === -1) {\n  leaderboardText += `\\n🔍 Your rank: Not ranked yet`;\n} else if (currentUserRank >= 10) {\n  leaderboardText += `\\n🔍 Your rank: #${currentUserRank + 1}`;\n}\n\nleaderboardText += \"\\n\\n🎮 Keep playing to climb higher!\";\n\nreturn [{\n  json: {\n    chat_id: $('Merge User Data').item.json.user.chat_id,\n    response_text: leaderboardText\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "4dfc640c-2b70-4265-839c-f9ec296a7982",
      "name": "有效答案?",
      "type": "n8n-nodes-base.if",
      "position": [
        280,
        -280
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "08b095f6-023b-4046-9121-e6d02643961d",
              "operator": {
                "type": "string",
                "operation": "regex"
              },
              "leftValue": "={{ $('Merge User Data').item.json.text.trim().toUpperCase() }}",
              "rightValue": "^[ABCD]$"
            },
            {
              "id": "6a953adb-8f4d-4c5e-9b3c-fd6c9f44c3c0",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $('Merge User Data').item.json.user_data.game_state }}",
              "rightValue": "waiting_answer"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "e7b6d610-667d-4317-83c8-64ae9e1b9e7d",
      "name": "获取当前问题",
      "type": "n8n-nodes-base.nocoDb",
      "notes": "Questions",
      "position": [
        660,
        -260
      ],
      "parameters": {
        "id": "={{ $json.user_data.current_question_id }}",
        "authentication": "nocoDbApiToken"
      },
      "credentials": {
        "nocoDbApiToken": {
          "id": "6M0tdo5lEJ6wbxJZ",
          "name": "n8n Token"
        }
      },
      "notesInFlow": true,
      "typeVersion": 3
    },
    {
      "id": "70cd94a3-d8c6-4a0c-a236-008808887ce8",
      "name": "处理答案",
      "type": "n8n-nodes-base.code",
      "position": [
        880,
        -240
      ],
      "parameters": {
        "jsCode": "const userAnswer = $('Merge User Data').first().json.text.trim().toUpperCase();\nconst question = $('Get Current Question').first().json;\nconst userData = $('Merge User Data').first().json.user_data;\n\nif (!question) {\n  return [{\n    json: {\n      chat_id: $('Merge User Data').first().json.user.chat_id,\n      response_text: \"❌ No active question found. Use /question to start a new one!\"\n    }\n  }];\n}\n\nconst correctAnswer = question.correct_answer.toUpperCase();\nconst isCorrect = userAnswer === correctAnswer;\n\n// Calculate points based on difficulty\nlet points = question.difficulty;\n\nconst responseText = isCorrect ? \n  `✅ **Correct!** 🎉\n\nYou earned ${points} point${points !== 1 ? 's' : ''}!\n\n💡 ${question.explanation || 'Well done!'}\n\nUse /question for another question!` :\n  `❌ **Wrong!** 😔\n\nThe correct answer was: **${correctAnswer}**\n\n💡 ${question.explanation || 'Better luck next time!'}\n\nUse /question to try again!`;\n\nreturn [{\n  json: {\n    chat_id: $('Merge User Data').first().json.user.chat_id,\n    response_text: responseText,\n    is_correct: isCorrect,\n    points_earned: points,\n    user_data: userData,\n    question: question\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "06af6d12-2ce5-4092-9f20-d8a7cb6a1500",
      "name": "更新用户统计",
      "type": "n8n-nodes-base.nocoDb",
      "notes": "Users",
      "position": [
        1060,
        160
      ],
      "parameters": {
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldName": "score",
              "fieldValue": "={{ $('Process Answer').item.json.user_data.score + $('Process Answer').item.json.points_earned }}"
            },
            {
              "fieldName": "Id",
              "fieldValue": "={{ $('Check Existing User').item.json.Id }}"
            },
            {
              "fieldName": "games_played",
              "fieldValue": "={{ $('Process Answer').item.json.user_data.games_played + 1 }}"
            },
            {
              "fieldName": "correct_answers",
              "fieldValue": "={{ $('Process Answer').item.json.user_data.correct_answers + ($('Process Answer').item.json.is_correct ? 1 : 0) }}"
            },
            {
              "fieldName": "game_state",
              "fieldValue": "idle"
            }
          ]
        },
        "operation": "update",
        "authentication": "nocoDbApiToken"
      },
      "credentials": {
        "nocoDbApiToken": {
          "id": "6M0tdo5lEJ6wbxJZ",
          "name": "n8n Token"
        }
      },
      "notesInFlow": true,
      "typeVersion": 3
    },
    {
      "id": "bc1d784f-e937-40f2-ae81-a2e70c0c73fb",
      "name": "处理未知文本",
      "type": "n8n-nodes-base.code",
      "position": [
        1240,
        340
      ],
      "parameters": {
        "jsCode": "// Handle unknown text when not waiting for answer\nconst userData = $input.first().json.user;\nconst text = $input.first().json.text;\n\nlet responseText = `🤔 I didn't understand \"${text}\"\\n\\n`;\n\nif (userData.game_state === 'waiting_answer') {\n  responseText += `You have an active question. Please answer with A, B, C, or D.`;\n} else {\n  responseText += `Available commands:\n/question - Get a trivia question\n/score - Check your score\n/leaderboard - View rankings\n/help - Show all commands`;\n}\n\nreturn [{\n  json: {\n    chat_id: $input.first().json.user.chat_id,\n    response_text: responseText\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "bbf362a8-f2da-4023-bce1-f454263de631",
      "name": "Telegram",
      "type": "n8n-nodes-base.telegram",
      "position": [
        1780,
        -265
      ],
      "webhookId": "105fea17-a486-4d09-9afa-1bdee3611adc",
      "parameters": {
        "text": "={{ $json.response_text }}",
        "chatId": "={{ $('Merge User Data').item.json.user.chat_id }}",
        "additionalFields": {
          "parse_mode": "Markdown"
        }
      },
      "credentials": {
        "telegramApi": {
          "id": "SlR5McCoTpMXB5Mc",
          "name": "TriviaBot"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "1f3c7039-bbd7-43b8-a1f7-23f3aaac84a7",
      "name": "合并",
      "type": "n8n-nodes-base.merge",
      "position": [
        1420,
        -460
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineByPosition"
      },
      "typeVersion": 3.2
    },
    {
      "id": "8986f8aa-6051-4cf8-a1c9-a3c7dfdf0827",
      "name": "OpenAI",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        -640,
        -20
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini",
          "cachedResultName": "GPT-4O-MINI"
        },
        "options": {},
        "messages": {
          "values": [
            {
              "role": "system",
              "content": "You are a trivia question generator. Create exactly 5 high-quality trivia questions for the specified category. Each question must have exactly 4 options (A, B, C, D) with only one correct answer. Include a brief explanation for each answer. Return the response as a JSON array."
            },
            {
              "content": "=Generate 5 trivia questions for category: {{ $json.category }}\nFormat each question as:\n{\n\"question\": \"Your question here?\",\n\"option_a\": \"First option\",\n\"option_b\": \"Second option\",\n\"option_c\": \"Third option\",\n\"option_d\": \"Fourth option\",\n\"correct_answer\": \"A\" (or B, C, D),\n\"difficulty\": \"3\" (number from 1-5),\n\"explanation\": \n\"Brief explanation of the answer\",\n\"category\": \"{{ $json.category }}\",\n\"time_limit\": 15 (difficulty*5)\n}\n\nMake questions varied in difficulty. Ensure facts are accurate. Avoid controversial topics."
            }
          ]
        }
      },
      "credentials": {
        "openAiApi": {
          "id": "1wKkKoKDmyKta6Xv",
          "name": "OpenAi account"
        }
      },
      "typeVersion": 1.8
    },
    {
      "id": "50ef158d-f86a-4292-8c46-967eeb3db772",
      "name": "NocoDB",
      "type": "n8n-nodes-base.nocoDbTool",
      "notes": "Questions table",
      "position": [
        -540,
        200
      ],
      "parameters": {
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldName": "question",
              "fieldValue": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('fieldValues0_Field_Value', ``, 'string') }}"
            },
            {
              "fieldName": "option_a",
              "fieldValue": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('fieldValues1_Field_Value', ``, 'string') }}"
            },
            {
              "fieldName": "option_b",
              "fieldValue": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('fieldValues2_Field_Value', ``, 'string') }}"
            },
            {
              "fieldName": "option_c",
              "fieldValue": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('fieldValues3_Field_Value', ``, 'string') }}"
            },
            {
              "fieldName": "option_d",
              "fieldValue": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('fieldValues4_Field_Value', ``, 'string') }}"
            },
            {
              "fieldName": "correct_answer",
              "fieldValue": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('fieldValues5_Field_Value', ``, 'string') }}"
            },
            {
              "fieldName": "difficulty",
              "fieldValue": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('fieldValues6_Field_Value', ``, 'string') }}"
            },
            {
              "fieldName": "category",
              "fieldValue": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('fieldValues7_Field_Value', ``, 'string') }}"
            },
            {
              "fieldName": "explanation",
              "fieldValue": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('fieldValues8_Field_Value', ``, 'string') }}"
            }
          ]
        },
        "operation": "create",
        "authentication": "nocoDbApiToken"
      },
      "credentials": {
        "nocoDbApiToken": {
          "id": "6M0tdo5lEJ6wbxJZ",
          "name": "n8n Token"
        }
      },
      "notesInFlow": true,
      "typeVersion": 3
    },
    {
      "id": "6efe0704-ce7c-436b-89e7-d783733e5af0",
      "name": "每日问题生成器",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -1080,
        -20
      ],
      "parameters": {
        "rule": {
          "interval": [
            {}
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "a6229303-f5ee-47b5-999d-f634b78a21ac",
      "name": "获取可能的类别",
      "type": "n8n-nodes-base.code",
      "position": [
        -860,
        -20
      ],
      "parameters": {
        "jsCode": "// Define default categories if none exist in DB\nconst categories = [\n  'Science & Nature',\n  'History', \n  'Geography',\n  'Sports',\n  'Movies & TV',\n  'Technology',\n  'Food & Drink',\n  'Art & Literature'\n];\n\n// Create requests for each category (5 questions per category)\nconst generationRequests = categories.map(category => ({\n  category: category,\n  questionsToGenerate: 5,\n  timestamp: new Date().toISOString()\n}));\n\nreturn generationRequests.map(request => ({ json: request }));"
      },
      "typeVersion": 2
    },
    {
      "id": "38f5bce5-9ba9-4b2c-9278-cc42a6cd5ad0",
      "name": "发送新问题可用通知",
      "type": "n8n-nodes-base.telegram",
      "position": [
        -260,
        -20
      ],
      "webhookId": "105fea17-a486-4d09-9afa-1bdee3611adc",
      "parameters": {
        "text": "={{ $json.response_text }}",
        "chatId": "={{ $('Merge User Data').item.json.user.chat_id }}",
        "additionalFields": {
          "parse_mode": "Markdown"
        }
      },
      "credentials": {
        "telegramApi": {
          "id": "SlR5McCoTpMXB5Mc",
          "name": "TriviaBot"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "a6a6a589-515b-4641-8943-8a508f1c56c6",
      "name": "合并1",
      "type": "n8n-nodes-base.merge",
      "position": [
        1400,
        -80
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineByPosition"
      },
      "typeVersion": 3.2
    },
    {
      "id": "84013da6-ddef-47b7-aa81-544fe5c15c16",
      "name": "聚合",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        1260,
        -280
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData",
        "destinationFieldName": "leaderboard"
      },
      "typeVersion": 1
    },
    {
      "id": "7ed0881f-3ca0-4e2e-ad6f-4db3c311cf86",
      "name": "获取用户历史",
      "type": "n8n-nodes-base.nocoDb",
      "notes": "User Question History",
      "position": [
        660,
        -640
      ],
      "parameters": {
        "options": {
          "where": "=(user_telegram_id,like,{{ $json.user.telegram_id }})"
        },
        "operation": "getAll",
        "returnAll": true,
        "authentication": "nocoDbApiToken"
      },
      "credentials": {
        "nocoDbApiToken": {
          "id": "6M0tdo5lEJ6wbxJZ",
          "name": "n8n Token"
        }
      },
      "notesInFlow": true,
      "typeVersion": 3,
      "alwaysOutputData": true
    },
    {
      "id": "6f8e4bee-6aea-421b-96e8-63a4e9c41b2d",
      "name": "将问题标记为已回答",
      "type": "n8n-nodes-base.nocoDb",
      "notes": "User Question History",
      "position": [
        1100,
        -60
      ],
      "parameters": {
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldName": "user_telegram_id",
              "fieldValue": "={{ $json.user_data.telegram_id }}"
            },
            {
              "fieldName": "question_id",
              "fieldValue": "={{ $json.question.Id }}"
            },
            {
              "fieldName": "answered_correctly",
              "fieldValue": "={{ $json.is_correct }}"
            },
            {
              "fieldName": "user_answer",
              "fieldValue": "={{ $('Valid Answer?').item.json.text }}"
            },
            {
              "fieldName": "answered_at",
              "fieldValue": "={{ $now }}"
            },
            {
              "fieldName": "points_earned",
              "fieldValue": "={{ $json.points_earned }}"
            }
          ]
        },
        "operation": "create",
        "authentication": "nocoDbApiToken"
      },
      "credentials": {
        "nocoDbApiToken": {
          "id": "6M0tdo5lEJ6wbxJZ",
          "name": "n8n Token"
        }
      },
      "notesInFlow": true,
      "typeVersion": 3
    },
    {
      "id": "27e9643b-03d4-44f8-b18c-a7991ddac076",
      "name": "聚合1",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        840,
        -640
      ],
      "parameters": {
        "options": {},
        "fieldsToAggregate": {
          "fieldToAggregate": [
            {
              "fieldToAggregate": "question_id"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "1f03aba3-2bd0-4c32-bf17-cf5380c58c54",
      "name": "获取随机问题",
      "type": "n8n-nodes-base.nocoDb",
      "notes": "Questions",
      "position": [
        1020,
        -640
      ],
      "parameters": {
        "limit": 1,
        "options": {
          "where": "=(Id,nanyof,{{ $json.question_id[0] }},{{ $json.question_id.join(',') }})"
        },
        "operation": "getAll",
        "authentication": "nocoDbApiToken"
      },
      "credentials": {
        "nocoDbApiToken": {
          "id": "6M0tdo5lEJ6wbxJZ",
          "name": "n8n Token"
        }
      },
      "notesInFlow": true,
      "typeVersion": 3
    },
    {
      "id": "a8f0472f-25db-470b-8c65-58cadc50b3c3",
      "name": "数据库设置说明",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2000,
        -1240
      ],
      "parameters": {
        "color": 3,
        "width": 600,
        "height": 940,
        "content": "## 📊 **需要设置 NocoDB 数据库**"
      },
      "typeVersion": 1
    },
    {
      "id": "3e6758f9-064a-44fa-bbb3-8ab77fcd12ca",
      "name": "AI 生成系统",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1160,
        200
      ],
      "parameters": {
        "color": 5,
        "width": 480,
        "height": 440,
        "content": "## 🤖 **AI 问题生成系统**"
      },
      "typeVersion": 1
    },
    {
      "id": "022a4501-5b95-4a51-a9b3-cab2e50b9464",
      "name": "消息处理",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1180,
        -520
      ],
      "parameters": {
        "color": 4,
        "width": 400,
        "height": 320,
        "content": "## 📨 **Message Processing Pipeline**\n\n**Step 1**: Telegram webhook receives message\n**Step 2**: Parse user data and message content\n**Step 3**: Check if user exists in database\n**Step 4**: Create new user if needed\n**Step 5**: Merge user data for processing\n\n**Handles**:\n- User registration\n- Message parsing\n- Command detection\n- User state management"
      },
      "typeVersion": 1
    },
    {
      "id": "846f7032-c510-4e5f-b04d-28cc38ea172e",
      "name": "Smart Question System",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        440,
        -1240
      ],
      "parameters": {
        "color": 6,
        "width": 580,
        "height": 380,
        "content": "## 🎮 **Smart Question System**\n\n**Features**:\n✅ **No Repeats**: Users never see correctly answered questions again\n✅ **History Tracking**: Every answer is logged\n✅ **Dynamic Selection**: Always fresh questions available\n\n**Process**:\n1. Get user's question history\n2. Exclude correctly answered questions\n3. Select random question from remaining pool\n4. Track when question is answered\n\n**Fallback**: Shows \"All questions completed\" when user has answered everything"
      },
      "typeVersion": 1
    },
    {
      "id": "68a50473-cab9-4a3a-818f-1b37db782c3a",
      "name": "Leaderboard System",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1680,
        -860
      ],
      "parameters": {
        "color": 3,
        "width": 380,
        "height": 340,
        "content": "## 📊 **Leaderboard System**\n\n**Features**:\n- Top 10 players by score\n- Shows current user's position\n- Real-time ranking updates\n- Emoji medals for top 3\n\n**Display**:\n🥇 1st place\n🥈 2nd place  \n🥉 3rd place\n🔸 Others\n\n**User Marker**: Shows \"← YOU\" for current user"
      },
      "typeVersion": 1
    },
    {
      "id": "5930ed78-fd46-402d-845c-653a680332c4",
      "name": "Answer Processing",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        360,
        -40
      ],
      "parameters": {
        "width": 320,
        "height": 460,
        "content": "## ✅ **Answer Processing Engine**\n\n**Input Validation**:\n- Only accepts A, B, C, D answers\n- Must be in \"waiting_answer\" state\n- Case-insensitive processing\n\n**Scoring System**:\n⭐ = 1 point\n⭐⭐ = 2 points\n⭐⭐⭐ = 3 points\n⭐⭐⭐⭐ = 4 points\n⭐⭐⭐⭐⭐ = 5 points\n\n**Actions**:\n✅ Updates user score & stats\n✅ Records answer in history\n✅ Resets game state to idle\n✅ Provides feedback with explanation"
      },
      "typeVersion": 1
    },
    {
      "id": "7edc0a6b-42a2-4290-b683-99a09e8c764d",
      "name": "Game State Management",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -900,
        -1140
      ],
      "parameters": {
        "color": 2,
        "width": 480,
        "height": 300,
        "content": "## 🔄 **Game State Management**\n\n**States**:\n- `idle` - Ready for new question\n- `waiting_answer` - Question active, awaiting response\n\n**Tracking**:\n- Current question ID\n- When question was asked\n- User's progress through questions\n\n**Safety**: Prevents invalid state transitions"
      },
      "typeVersion": 1
    },
    {
      "id": "0e5219c5-af7a-4c9f-b984-a33abdc2353e",
      "name": "Response System",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1980,
        -400
      ],
      "parameters": {
        "color": 4,
        "width": 340,
        "height": 400,
        "content": "## 📤 **Response System**\n\n**Features**:\n- Markdown formatting for rich messages\n- Emoji integration for visual appeal\n- Consistent message structure\n- Error handling and fallbacks\n\n**Message Types**:\n- Command responses\n- Question displays\n- Answer feedback\n- Leaderboard updates\n- Error messages\n\n**Delivery**: All responses go through single Telegram node"
      },
      "typeVersion": 1
    },
    {
      "id": "8d1c5306-cb5a-4631-9dac-23932f7c7e80",
      "name": "History Tracking System",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -220,
        -1240
      ],
      "parameters": {
        "color": 6,
        "width": 600,
        "height": 380,
        "content": "## 🎲 **Question History Tracking**\n\n**Purpose**: Ensures users never see the same correctly answered question twice\n\n**Process**:\n1. Get user's answer history\n2. Collect all correctly answered question IDs\n3. Use NocoDB's `nanyof` operator to exclude those questions\n4. Return random question from remaining pool\n\n**Benefits**:\n✅ Fresh content for returning users\n✅ Prevents repetition\n✅ Encourages continuous play\n✅ Tracks user progress\n\n**Fallback**: When all questions are answered, shows completion message"
      },
      "typeVersion": 1
    },
    {
      "id": "4ea2a44e-c741-4d5f-ad4b-870ee562c394",
      "name": "Data Flow Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1220,
        -1340
      ],
      "parameters": {
        "color": 4,
        "width": 300,
        "height": 500,
        "content": "## 🔄 **Data Flow Summary**\n\n**Input**: Telegram message\n**Processing**: \n1. Parse & validate user\n2. Route command or answer\n3. Process business logic\n4. Update database\n5. Format response\n\n**Output**: Telegram response\n\n**Error Handling**: \n- Invalid inputs\n- Database failures\n- API timeouts\n- User state conflicts\n\n**Performance**:\n- Concurrent user support\n- Fast response times\n- Efficient database queries"
      },
      "typeVersion": 1
    }
  ],
  "pinData": {},
  "connections": {
    "Merge": {
      "main": [
        [
          {
            "node": "Telegram",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge1": {
      "main": [
        [
          {
            "node": "Telegram",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "NocoDB": {
      "ai_tool": [
        [
          {
            "node": "OpenAI",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI": {
      "main": [
        [
          {
            "node": "Send New Questions Available Notification",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate": {
      "main": [
        [
          {
            "node": "Format Leaderboard",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate1": {
      "main": [
        [
          {
            "node": "Get Random Question",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is Command?": {
      "main": [
        [
          {
            "node": "Command Router",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Valid Answer?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "User Exists?": {
      "main": [
        [
          {
            "node": "Merge User Data",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Create New User",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Valid Answer?": {
      "main": [
        [
          {
            "node": "Get Current Question",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Handle Unknown Text",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Command Router": {
      "main": [
        [
          {
            "node": "Handle Basic Commands",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Handle Basic Commands",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Handle Basic Commands",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Handle Basic Commands",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Get User History",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Get Leaderboard",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Process Answer": {
      "main": [
        [
          {
            "node": "Merge1",
            "type": "main",
            "index": 0
          },
          {
            "node": "Update User Stats",
            "type": "main",
            "index": 0
          },
          {
            "node": "Mark Question As Answered",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create New User": {
      "main": [
        [
          {
            "node": "Merge User Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Question": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Leaderboard": {
      "main": [
        [
          {
            "node": "Aggregate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge User Data": {
      "main": [
        [
          {
            "node": "Is Command?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get User History": {
      "main": [
        [
          {
            "node": "Aggregate1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Telegram Trigger": {
      "main": [
        [
          {
            "node": "Parse Telegram Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update User Stats": {
      "main": [
        [
          {
            "node": "Merge1",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Format Leaderboard": {
      "main": [
        [
          {
            "node": "Telegram",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Existing User": {
      "main": [
        [
          {
            "node": "User Exists?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Random Question": {
      "main": [
        [
          {
            "node": "Format Question",
            "type": "main",
            "index": 0
          },
          {
            "node": "Update User Game State",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Handle Unknown Text": {
      "main": [
        [
          {
            "node": "Telegram",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Telegram Data": {
      "main": [
        [
          {
            "node": "Check Existing User",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Current Question": {
      "main": [
        [
          {
            "node": "Process Answer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Handle Basic Commands": {
      "main": [
        [
          {
            "node": "Telegram",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update User Game State": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Get Possible Categories": {
      "main": [
        [
          {
            "node": "OpenAI",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Daily Question Generator": {
      "main": [
        [
          {
            "node": "Get Possible Categories",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
常见问题

如何使用这个工作流?

复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。

这个工作流适合什么场景?

高级 - 杂项, AI 聊天机器人

需要付费吗?

本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。

工作流信息
难度等级
高级
节点数量41
分类2
节点类型12
难度说明

适合高级用户,包含 16+ 个节点的复杂工作流

外部链接
在 n8n.io 查看

分享此工作流