Telegram机器人检测用户是否加入指定频道/群组

(基础)方法1.在每次请求时校验

根据Telegram官方给出的Api,我们看到有这样一个方法

getChatMember

Use this method to get information about a member of a chat. The method is only guaranteed to work for other users if the bot is an administrator in the chat. Returns a ChatMember object on success.

Parameter Type Required Description
chat_id Integer or String Yes Unique identifier for the target chat or username of the target supergroup or channel (in the format @channelusername)
user_id Integer Yes Unique identifier of the target user

根据这个方法,我们可以写出一个方法来检测指定用户是否加入了指定频道/群组
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
async def is_member(userid):
user_follow_channel1, user_follow_channel2 = True, True

api = config.tg_api_url + f'getChatMember?chat_id={config.channel1}&user_id={userid}'
api2 = config.tg_api_url + f'getChatMember?chat_id={config.channel2}&user_id={userid}'

async with aiohttp.ClientSession(connector=TCPConnector(ssl=False)) as session:
response = await asyncio.gather(
fetch(session, api),
fetch(session, api2)
)

if response[0]['result']['status'] == 'left':
# 用户未关注主频道
user_follow_channel1 = False
if response[1]['result']['status'] == 'left':
# 用户未关注副频道
user_follow_channel2 = False
return user_follow_channel1, user_follow_channel2

这是最基本的实现方法,在每次触发机器人操作时,可以先进行校验,来实现强制关注频道。

(进阶)方法2.使用事件处理器(event handler)

这里我使用了python3telethon库进行开发。telethon提供了丰富的事件处理器,属于一种触发器机制,可以理解为“当某个事件发生时自动触发的回调函数”。

我们可以监听 events.ChatAction 事件,从而在用户加入或退出群组/频道时做出响应。例如,记录日志、更新数据库状态、进行权限变更等等。

下面是一个实际的监听用户加入和离开频道的示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@client.on(events.ChatAction)
async def handle_ChatAction(event):
user_left = event.user_left
user_added = event.user_added

if user_left:
if event.chat_id == config.channel1_id:
# 用户离开了主频道
await utils.user_leave_the_channel(event.user_id, config.channel1_id)
elif event.chat_id == config.channel2_id:
# 用户离开了副频道
await utils.user_leave_the_channel(event.user_id, config.channel2_id)
if user_added:
if event.chat_id == config.channel1_id:
# 用户加入了主频道
await utils.user_join_the_channel(event.user_id, config.channel1_id)
elif event.chat_id == config.channel2_id:
# 用户加入了副频道
await utils.user_join_the_channel(event.user_id, config.channel2_id)

在上面的代码中:

  • 使用 @client.on(events.ChatAction) 装饰器注册了一个事件监听器;
  • 当用户加入或离开指定频道时,会自动触发 handle_ChatAction 函数;
  • 函数内部判断了是哪个频道、用户是加入还是退出,并调用相应的处理逻辑(这里封装在 utils 模块中);

这种方式适合在用户行为变化时立即触发相应逻辑,不需要等用户主动发送消息,是一种更加“被动监听”式的方案,非常适合频道/群组的状态同步场景。

接下来,我们只需要在utils.user_leave_the_channelutils.user_join_the_channel中将用户状态保存到表字段中即可。在需要校验时,只需要先向Telegram发送一次请求,并保存到用户表中,再次需要校验时,观察表字段即可,无需向Telegram服务器重复发送请求。

当用户进行了频道操作时,例如加入/退出频道,就会触发handle_ChatAction函数,并对用户状态进行更改,避免了每次校验都请求Telegram的Api。