Python TeleBot Telegram频道订阅校验逻辑异常排查
Telegram频道订阅校验逻辑修复方案
问题分析
- 订阅状态判断不完整:原代码仅检查用户状态是否为
member,但频道的管理员(administrator)和创建者(creator)也属于已订阅状态,会被误判为未订阅。 - 逻辑错误:
else分支中错误调用了main()函数,导致无论是否订阅都会执行核心逻辑,违背“未订阅则不执行”的需求。 - 命令消息传递问题:
/start命令的消息文本直接传给main(),会导致OpenAI处理无效的prompt内容。 - 潜在权限问题:Bot需要成为频道管理员并拥有查看成员的权限,否则
get_chat_member会抛出异常,导致校验失败。
修复步骤
1. 完善订阅状态判断
将状态判断改为包含所有有效订阅状态:
is_subscribed = bot.get_chat_member(chat_id=channel_id, user_id=user_id).status in ['member', 'administrator', 'creator']
2. 修正分支逻辑
移除else分支中的main()调用,确保仅订阅用户能触发核心服务:
if is_subscribed: bot.send_message(chat_id, '您已订阅频道,欢迎使用!') bot.send_message(chat_id, '请输入您的问题或需求:') else: bot.send_message(chat_id, '您未订阅频道,请先订阅后再使用服务!')
3. 重构消息处理流程
将核心逻辑改为独立的文本消息处理器,仅处理用户订阅后的正常请求,避免/start命令干扰:
@bot.message_handler(content_types=['text']) def handle_user_request(message): # 忽略命令类消息 if message.text.startswith('/'): return # 先校验订阅状态 user_id = message.from_user.id channel_id = '-1001896384318' try: is_subscribed = bot.get_chat_member(chat_id=channel_id, user_id=user_id).status in ['member', 'administrator', 'creator'] except Exception as e: bot.send_message(message.chat.id, '无法验证订阅状态,请确保Bot是频道管理员!') return if not is_subscribed: bot.send_message(message.chat.id, '您未订阅频道,请先订阅后再使用服务!') return # 执行核心生成逻辑 # ...(原main函数内容)
4. 添加异常捕获
为get_chat_member和OpenAI请求添加异常处理,避免Bot崩溃并给出明确提示。
完整修正代码
import telebot from telebot import types import openai from PIL import Image, ImageDraw, ImageFont import textwrap import os width = 1000 height = 1000 color = (255, 255, 255) # (R, G, B) font_size = 24 font = ImageFont.truetype("Roboto-Light.ttf", font_size) telegram_key = 'TOKEN_BOT' openai.api_key = 'TOKEN_OPENAI' bot = telebot.TeleBot(telegram_key) @bot.message_handler(commands=['start']) def start(message): bot.send_message(message.chat.id, "👋 你好!我是人工智能,可以帮你解决习题和问题,适用于学生群体!\n\n🤖 我专为在校学生设计,能在各类问题上提供帮助。") chat_id = message.chat.id user_id = message.from_user.id channel_id = '-1001896384318' try: is_subscribed = bot.get_chat_member(chat_id=channel_id, user_id=user_id).status in ['member', 'administrator', 'creator'] except Exception as e: bot.send_message(chat_id, '无法验证订阅状态,请确保Bot是频道管理员!') return if is_subscribed: bot.send_message(chat_id, '您已订阅频道,欢迎使用!') bot.send_message(chat_id, '请输入您的问题或需求:') else: bot.send_message(chat_id, '您未订阅频道,请先订阅后再使用服务!') @bot.message_handler(content_types=['text']) def handle_user_request(message): # 忽略命令类消息 if message.text.startswith('/'): return user_id = message.from_user.id channel_id = '-1001896384318' try: is_subscribed = bot.get_chat_member(chat_id=channel_id, user_id=user_id).status in ['member', 'administrator', 'creator'] except Exception as e: bot.send_message(message.chat.id, '无法验证订阅状态,请确保Bot是频道管理员!') return if not is_subscribed: bot.send_message(message.chat.id, '您未订阅频道,请先订阅后再使用服务!') return # 执行核心生成逻辑 img = Image.new("RGB", (width, height), color) draw = ImageDraw.Draw(img) reply = '' try: response = openai.Completion.create( engine='text-davinci-003', prompt=message.text, max_tokens=1000, temperature=0.9, n=1, stop=None ) if response and response.choices: reply = response.choices[0].text.strip() txt = textwrap.wrap(reply, width=70) y = 100 for line in txt: draw.text((70, y), line, font=font, fill=(0, 0, 0)) y += 30 img.save('image.jpg') bot.send_photo(message.chat.id, photo=open('image.jpg', 'rb')) os.remove('image.jpg') else: reply = '哎呀...出了点问题。' except Exception as e: reply = f'请求出错:{str(e)}' bot.send_message(message.chat.id, reply) bot.polling(none_stop=True)
内容的提问来源于stack exchange,提问作者Crafters
相关产品推荐
相关产品推荐

