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

Telethon中NewMessage事件的实体参数配置矛盾问题

解决Telethon动态获取Entity并注册NewMessage事件的问题

问题核心在于:装饰器@events.register会在脚本加载阶段立即执行,此时客户端未启动、目标频道Entity也未获取,直接用from_users=desired_channel必然报错。解决思路是将事件注册逻辑延后到获取到Entity之后,动态添加事件处理器。

修改后的完整代码

from telethon import TelegramClient, events
from telegram.api_library import (
    write_in_saved_messages,
    get_entity_data,
)
from user_files.user_settings import (
    USER_SESSION_NAME,
    USER_TELEGRAM_API_HASH,
    USER_TELEGRAM_API_ID,
)

# 修正客户端初始化的闭合括号
telegram_client: TelegramClient = TelegramClient(
    USER_SESSION_NAME, USER_TELEGRAM_API_ID, USER_TELEGRAM_API_HASH
)

async def message_received(event):
    """处理目标频道的新消息"""
    # 修正:获取消息文本而非Message对象本身
    incoming_message_text = event.message.text
    sender_id = (await event.get_input_sender()).channel_id

    print(f"Message from {sender_id}:\n{incoming_message_text}")

async def main():
    """初始化流程:启动提示 → 获取频道Entity → 注册事件"""
    await write_in_saved_messages(telegram_client, "Message Receiver started!")

    # 获取目标频道的Entity
    desired_channel = await get_entity_data(
        telegram_client, "desired_channel_name"
    )

    # 动态注册事件处理器(此时已拿到合法的Entity)
    telegram_client.add_event_handler(
        message_received,
        events.NewMessage(
            incoming=True,
            from_users=desired_channel
        )
    )

def start_receiver():
    """启动接收器"""
    with telegram_client:
        # 确保初始化流程(获取Entity、注册事件)执行完毕后,再进入事件循环
        telegram_client.loop.run_until_complete(main())
        telegram_client.run_until_disconnected()

关键改动说明

  1. 移除装饰器注册:放弃@events.register,改用add_event_handler动态注册事件,确保只有拿到Entity后才配置from_users参数。
  2. 调整执行顺序:将Entity获取、事件注册逻辑放在main函数中,通过run_until_complete确保这些初始化步骤完成后,再启动客户端的事件循环。
  3. 修复代码语法错误:补全了TelegramClient初始化时缺失的闭合括号,修正了消息文本的获取方式(event.message.text而非直接取event.message)。

备选方案(低效率但改动小)

如果不想调整事件注册逻辑,也可以在事件处理函数内部判断发送者是否为目标频道,但这种方式每次收到消息都会重新获取Entity,效率较低:

@events.register(events.NewMessage(incoming=True))
async def message_received(event):
    desired_channel = await get_entity_data(telegram_client, "desired_channel_name")
    sender = await event.get_input_sender()
    # 不是目标频道则直接返回
    if sender.channel_id != desired_channel.id:
        return
    
    # 后续消息处理逻辑
    incoming_message_text = event.message.text
    print(f"Message from {sender.channel_id}:\n{incoming_message_text}")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 19:30:56