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

Telegram机器人重复发送图片问题:点击次数对应发送次数

解决Telegram Bot多次点击上传按钮后重复发送图片的问题

问题现象

  • 首次点击「Upload Photo」按钮,机器人正常发送1次图片;
  • 多次点击该按钮后,后续上传图片时,图片发送次数等于之前点击按钮的总次数(包含历史点击次数)。

原代码

const keyboard = {
    reply_markup:{
        keyboard: [
            [{text: 'About Bot'}, {text: 'Upload Photo'}]
        ]
    }
}

bot.onText(/\/start/, async msg => {
    await bot.sendMessage(h.id(msg), `Choose any`,keyboard)
})

bot.on('message', msg => {
    switch (msg.text){
        case 'Upload Photo':
            uploadPhoto(h.id(msg))
            break
        case 'About Bot':
            break
    }
})

const uploadPhoto = async (chatId) => {
    await bot.sendMessage(chatId, 'Send me a photo')
    bot.on('photo', async (msg) => {
        const photo = msg.photo[2].file_id
        await bot.sendPhoto(channelId, photo)
        await bot.sendMessage(chatId, 'Photo is sent')
    })
}

问题根源

每次调用uploadPhoto函数时,都会通过bot.on('photo', ...)注册一个全局的photo事件监听器,这些监听器不会自动销毁。多次点击按钮后,就会堆积多个监听器,当用户发送图片时,所有已注册的监听器都会被触发,导致图片重复发送。

解决方案

方案1:使用一次性监听器(最简单)

用bot.once('photo', ...)替代bot.on,once注册的监听器只会触发一次,触发后自动移除,不会产生堆积:

const keyboard = {
    reply_markup:{
        keyboard: [
            [{text: 'About Bot'}, {text: 'Upload Photo'}]
        ]
    }
}

bot.onText(/\/start/, async msg => {
    await bot.sendMessage(h.id(msg), `Choose any`, keyboard)
})

bot.on('message', msg => {
    switch (msg.text){
        case 'Upload Photo':
            uploadPhoto(h.id(msg))
            break
        case 'About Bot':
            break
    }
})

const uploadPhoto = async (chatId) => {
    await bot.sendMessage(chatId, 'Send me a photo')
    // 使用once替代on,监听器触发一次后自动销毁
    bot.once('photo', async (msg) => {
        const photo = msg.photo[2].file_id
        await bot.sendPhoto(channelId, photo)
        await bot.sendMessage(chatId, 'Photo is sent')
    })
}

方案2:手动移除监听器(更精准)

如果需要只响应当前对话用户的图片,可以定义命名监听器函数,触发后手动移除,同时增加对话ID判断:

const keyboard = {
    reply_markup:{
        keyboard: [
            [{text: 'About Bot'}, {text: 'Upload Photo'}]
        ]
    }
}

bot.onText(/\/start/, async msg => {
    await bot.sendMessage(h.id(msg), `Choose any`, keyboard)
})

bot.on('message', msg => {
    switch (msg.text){
        case 'Upload Photo':
            uploadPhoto(h.id(msg))
            break
        case 'About Bot':
            break
    }
})

const uploadPhoto = async (chatId) => {
    await bot.sendMessage(chatId, 'Send me a photo')
    
    // 定义命名的监听器函数
    async function handlePhoto(msg) {
        // 仅处理当前点击按钮的用户发送的图片
        if (h.id(msg) !== chatId) return;
        
        const photo = msg.photo[2].file_id
        await bot.sendPhoto(channelId, photo)
        await bot.sendMessage(chatId, 'Photo is sent')
        // 触发后移除监听器
        bot.off('photo', handlePhoto)
    }
    
    bot.on('photo', handlePhoto)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 09:55:16