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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.12 19:15:03