You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js开发Telegram Bot遭遇重复响应循环问题求助

问题描述

我用Node.js开发了一个Telegram Bot,它能根据用户输入发起电话呼叫。第一次运行正常,但多次操作后会陷入奇怪的循环——每次输入内容,消息都会多发送一次,就像代码没跳出switch语句,一直在监听数字输入。

原代码

require("dotenv").config();
const axios = require("axios");
const express = require("express");

const port = 5000;
const app = express();

const Voice = require("@signalwire/realtime-api").Voice;

const { TOKEN, SERVER_URL } = process.env;
const URI = `/webhook/${TOKEN}`;

const TelegramBot = require("node-telegram-bot-api");
const { reset, restart } = require("nodemon");
const nodemon = require("nodemon");
var chatId;

// replace the value below with the Telegram token you receive from @BotFather
const token = "<token>";

// Create a bot that uses 'polling' to fetch new updates
const bot = new TelegramBot(token, { polling: true });

bot.on("message", (msg) => {
  chatId = msg.chat.id;

  if (msg.text == "/call") {
    chooseBank();
  }

  if (msg.text == "/restart") {
    recover();
  }

});

//GIVE OPTION FOR THE CLIENT
function chooseBank() {
  bot.sendMessage(
    chatId,
    "CHOOSE THE BANK: \n\n1 RBC\n2 CIBC\n3 SCOTIA\n4 BMO\n5 NATIONAL\n6 TD\n7 PC-FINANCIAL\n8 DESJARDINS"
  );

  bot.on("message", (msg) => {
    switch (msg.text) {
      case "1":
        bot.sendMessage(
          chatId,
          "ENTER THE CLIENTS NUMBER:\n\nEX: (+15142220000)"
        );
        
        break;
      case "2":
        bot.sendMessage(
          chatId,
          "ENTER THE CLIENTS NUMBER:\n\nEX: (+15142220000)"
        );
        
        break;
      case "3":
        bot.sendMessage(
          chatId,
          "ENTER THE CLIENTS NUMBER:\n\nEX: (+15142220000)"
        );
        
        break;
      case "4":
        bot.sendMessage(
          chatId,
          "ENTER THE CLIENTS NUMBER:\n\nEX: (+15142220000)"
        );
        
        break;
      case "5":
        bot.sendMessage(
          chatId,
          "ENTER THE CLIENTS NUMBER:\n\nEX: (+15142220000)"
        );
        
        break;
      case "6":
        bot.sendMessage(
          chatId,
          "ENTER THE CLIENTS NUMBER:\n\nEX: (+15142220000)"
        );
        
        break;
      case "7":
        bot.sendMessage(
          chatId,
          "ENTER THE CLIENTS NUMBER:\n\nEX: (+15142220000)"
        );
        
        break;
      case "8":
        bot.sendMessage(
          chatId,
          "ENTER THE CLIENTS NUMBER:\n\nEX: (+15142220000)"
        );
        
    }
  });
}

function recover(){
    chooseBank()
}

app.listen(port, () => {
  console.log(`Server started on port ${port}`);
});

问题根源

每次调用chooseBank()时,都会给bot绑定一个新的message事件监听器。第一次调用添加1个监听器,第二次调用再添加1个,以此类推。后续用户发送的每条消息都会被所有已绑定的监听器处理,导致响应次数随操作次数递增。

解决方案

采用状态机模式跟踪用户的操作步骤,所有消息逻辑都在全局的message监听器中处理,避免重复绑定事件。

修正后代码

require("dotenv").config();
const axios = require("axios");
const express = require("express");

const port = 5000;
const app = express();

const Voice = require("@signalwire/realtime-api").Voice;

const { TOKEN, SERVER_URL } = process.env;
const URI = `/webhook/${TOKEN}`;

const TelegramBot = require("node-telegram-bot-api");
const nodemon = require("nodemon");

// 记录每个用户的当前操作状态,key为chatId,value为步骤标识
const userStates = {};

// replace the value below with the Telegram token you receive from @BotFather
const token = "<token>";

// Create a bot that uses 'polling' to fetch new updates
const bot = new TelegramBot(token, { polling: true });

bot.on("message", (msg) => {
  const chatId = msg.chat.id;
  const text = msg.text.trim();

  // 处理命令
  if (text === "/call") {
    userStates[chatId] = "choosing_bank";
    bot.sendMessage(
      chatId,
      "CHOOSE THE BANK: \n\n1 RBC\n2 CIBC\n3 SCOTIA\n4 BMO\n5 NATIONAL\n6 TD\n7 PC-FINANCIAL\n8 DESJARDINS"
    );
    return;
  }

  if (text === "/restart") {
    userStates[chatId] = "choosing_bank";
    bot.sendMessage(
      chatId,
      "CHOOSE THE BANK: \n\n1 RBC\n2 CIBC\n3 SCOTIA\n4 BMO\n5 NATIONAL\n6 TD\n7 PC-FINANCIAL\n8 DESJARDINS"
    );
    return;
  }

  // 根据用户当前状态处理消息
  const currentState = userStates[chatId];
  if (!currentState) return;

  switch (currentState) {
    case "choosing_bank":
      // 验证输入是否为1-8的数字
      if (["1", "2", "3", "4", "5", "6", "7", "8"].includes(text)) {
        userStates[chatId] = "entering_number";
        bot.sendMessage(
          chatId,
          "ENTER THE CLIENTS NUMBER:\n\nEX: (+15142220000)"
        );
      } else {
        bot.sendMessage(chatId, "请输入1-8之间的数字选择银行");
      }
      break;
    case "entering_number":
      // 此处可添加号码格式验证逻辑,随后发起呼叫
      bot.sendMessage(chatId, `已收到号码:${text},即将发起呼叫`);
      // 完成操作后重置用户状态
      delete userStates[chatId];
      break;
  }
});

app.listen(port, () => {
  console.log(`Server started on port ${port}`);
});

方案说明

  1. 使用userStates对象跟踪每个用户的当前操作步骤(如选择银行、输入号码),确保不同用户的操作互不干扰。
  2. 所有消息逻辑集中在全局message监听器中,避免重复绑定事件导致的多次响应问题。
  3. 操作完成后主动重置用户状态,保证流程可以重新开始。

内容的提问来源于stack exchange,提问作者Steven Yee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 16:30:46