Python Telegram Bot夜间模式如何删除多群组场景下的历史bot消息?
实现思路
你需要的核心能力是按群组独立存储上一条夜间模式通知的消息ID,不要用消息ID自增的逻辑——不同群组的消息ID是独立序列,自增逻辑完全不适用,直接存每个群组对应的上一条通知ID即可。
修改说明
需要调整的核心逻辑如下:
- 新增全局字典存储每个群的上一条通知消息ID,键为群ID,值为消息ID
- 改造定时发送通知的函数,遍历所有授权群组发送,发新通知前先删除该群上一条旧通知
- 捕获删除异常,避免旧消息已被手动删除时报错
修改后完整代码
import logging from telegram import Update from telegram.ext import Updater, MessageHandler, Filters, CallbackContext import datetime as dtm import pytz night_hours = ['22','23','00','01','02','03','04','05','06'] allowed_groups = ['GROUP ID 1','GROUP ID 2','GROUP ID 3'] # 替换为实际群ID LOG_CHANNEL_ID = "LOG CHANNEL ID" # 替换为实际日志频道ID BOT_TOKEN = "BOT KEY" # 替换为实际机器人TOKEN # 存储每个群上一条夜间模式通知的消息ID,格式:{群ID: 消息ID} last_notice_msg = {} # Enable logging logging.basicConfig( format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO ) logger = logging.getLogger(__name__) def error(update, context): """Log Errors caused by Updates.""" logger.warning('Update "%s" caused error "%s"', update, context.error) def start(context: CallbackContext): UK_tz = pytz.timezone('Europe/London') morning_time = dtm.time(hour=7, minute=0, tzinfo=UK_tz) evening_time = dtm.time(hour=22, minute=0, tzinfo=UK_tz) context.job_queue.run_daily(morning_message, morning_time) context.job_queue.run_daily(night_message, evening_time) def log_channel(context: CallbackContext,name,chat_name,message): # markdownv2特殊字符转义 def escape_md(text): escape_chars = r'_*[]()~`>#+-=|{}.!' return ''.join(f'\\{c}' if c in escape_chars else c for c in str(text)) deleted_message = f"Message Deleted from *{escape_md(name)}* in the group *'{escape_md(chat_name)}'*: {escape_md(message)}" context.bot.send_message(chat_id=LOG_CHANNEL_ID, text=deleted_message, disable_notification=True, parse_mode="MARKDOWNV2") print(deleted_message) def morning_message(context: CallbackContext): text = "*NIGHT MODE END:*\n\nMessage sending enabled until 10PM" for group_id in allowed_groups: # 先删除上一条旧通知 if group_id in last_notice_msg: try: context.bot.delete_message(chat_id=group_id, message_id=last_notice_msg[group_id]) except Exception as e: logger.warning(f"删除群{group_id}旧通知失败: {e}") # 发送新通知 msg = context.bot.send_message(chat_id=group_id,text=text, disable_notification=True,parse_mode="MARKDOWNV2") # 存储新消息ID last_notice_msg[group_id] = msg.message_id def night_message(context: CallbackContext): text = "*NIGHT MODE START:*\n\nMessage sending disabled until 7AM" for group_id in allowed_groups: # 先删除上一条旧通知 if group_id in last_notice_msg: try: context.bot.delete_message(chat_id=group_id, message_id=last_notice_msg[group_id]) except Exception as e: logger.warning(f"删除群{group_id}旧通知失败: {e}") # 发送新通知 msg = context.bot.send_message(chat_id=group_id, text=text, disable_notification=True,parse_mode="MARKDOWNV2") # 存储新消息ID last_notice_msg[group_id] = msg.message_id def during_night_mode(update: Update,context: CallbackContext): UK = pytz.timezone('Europe/London') hour = dtm.datetime.now(UK).strftime('%H') chat_id = str(update.message.chat.id) chat_name = update.message.chat.title message_id = update.message.message_id incoming_text = str(update.message.text) message_sender = str(update.message.from_user.first_name) if hour in night_hours and chat_id in allowed_groups: context.bot.delete_message(chat_id,message_id) log_channel(context,message_sender,chat_name,incoming_text) def main() -> None: """Start the bot.""" updater = Updater(BOT_TOKEN) dp = updater.dispatcher dp.add_handler(MessageHandler(Filters.all,during_night_mode)) dp.add_error_handler(error) # Start the Bot updater.start_polling() start(dp) updater.idle() if __name__ == '__main__': main()
额外说明
如果需要机器人重启后仍然能识别上一条通知的ID,可以把last_notice_msg字典序列化存储到本地json文件中,每次启动时读取即可,不需要修改核心逻辑。
内容的提问来源于stack exchange,提问作者avnish9
相关产品推荐
相关产品推荐

