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

如何使用Telegraf.js正确实现Telegram机器人向频道转发消息

问题描述

我遇到了报错,不清楚如何使用Telegraf.js实现Telegram机器人向频道转发消息。我预期在发送第一条消息后再发送第二条,但实际触发操作后只会转发第一条消息。

  • 机器人内的回复内容:机器人回复
  • 频道实际接收到的内容:频道接收内容

我的实现代码如下:

bot.on('message', async (ctx) => {
  const getFilmId = await kinoInfo(ctx.message.text);
  const infoFilm = getFilmId.data.data;
  const id = infoFilm.filmId;

  const name = infoFilm.nameRu;

  ctx.reply(name, {
    reply_markup: {
      inline_keyboard: [
        [{ text: `Watch`, url: 'https://www.instagram.com/' }],
        [{ text: 'Telegram channel 1', callback_data: 'ONE' }],
      ],
    },
  });

  bot.on('callback_query', (ctx) => {
    const data = ctx.update.callback_query.data;
    if (data === 'ONE') {
      postToChannel(ctx);
    }
  });

  const postToChannel = (ctx) => {
    ctx.telegram.sendMessage('@fgdsfsdfsd', name, {
      parse_mode: 'html',
      reply_markup: {
        inline_keyboard: [[{ text: `Watch`, url: 'https://www.instagram.com/' }]],
      },
    });
  };
});

问题原因

你代码的核心错误是将callback_query事件监听放在了message事件的回调内部:

  • 每次收到用户发来的新消息,都会重复注册一个新的回调查询监听器,旧的监听器不会被销毁
  • 每个监听器都会捕获对应message回调作用域内的name变量,触发按钮时所有历史注册的监听器都会执行,最终会出现始终发送最早的第一条消息的异常。

修复方案

将callback_query事件监听移到全局作用域,需要传递的电影名称可以通过callback_data字段携带,避免闭包捕获导致的变量异常。修正后的代码如下:

// 全局注册回调查询监听
bot.on('callback_query', async (ctx) => {
  const data = ctx.update.callback_query.data;
  // 拆分callback_data拿到操作类型和电影名
  const [action, filmName] = data.split(':');
  if (action === 'post_to_channel') {
    await ctx.telegram.sendMessage('@fgdsfsdfsd', filmName, {
      parse_mode: 'html',
      reply_markup: {
        inline_keyboard: [[{ text: `Watch`, url: 'https://www.instagram.com/' }]],
      },
    });
    // 回应用户的回调查询,避免按钮一直处于加载状态
    await ctx.answerCbQuery('已成功转发到频道');
  }
});

bot.on('message', async (ctx) => {
  const getFilmId = await kinoInfo(ctx.message.text);
  const infoFilm = getFilmId.data.data;
  const name = infoFilm.nameRu;

  ctx.reply(name, {
    reply_markup: {
      inline_keyboard: [
        [{ text: `Watch`, url: 'https://www.instagram.com/' }],
        // 将电影名拼接进callback_data传递给回调监听
        [{ text: 'Telegram channel 1', callback_data: `post_to_channel:${name}` }],
      ],
    },
  });
});

注意事项

  • callback_data最大长度为64字节,如果电影名过长建议使用会话存储存储用户当前选中的电影信息,避免超出长度限制。
  • 回调查询触发后必须调用ctx.answerCbQuery()回应用户,否则客户端的按钮会一直处于转圈加载状态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 03:54:03