如何在TelegramBot中指定时间发送消息

7

您好,我想让机器人在特定时间发送信息(无需我的操作),例如每周六早上8:00。以下是我的代码:

import telebot
import config
from datetime import time, date, datetime

bot = telebot.TeleBot(config.bot_token)
chat_id=config.my_id    

@bot.message_handler(commands=['start', 'help'])
def print_hi(message):
    bot.send_message(message.chat.id, 'Hi!')


@bot.message_handler(func=lambda message: False) #cause there is no message
def saturday_message():
    now = datetime.now()
    if (now.date().weekday() == 5) and (now.time() == time(8,0)):
        bot.send_message(chat_id, 'Wake up!')

bot.polling(none_stop=True)

但是显然这样做不起作用。 尝试了以下方法:

urlopen("https://api.telegram.org/bot" +bot_id+ "/sendMessage?chat_id=" +chat_id+ "&text="+msg)

但是仍然没有结果。不知道该怎么做,请帮忙给出建议。


问题出在哪里?是时间问题还是你的机器人根本没有发送任何内容? - user9112752
机器人没有发送消息。 - Ican
它在没有日期检查的情况下工作吗? - user9112752
不好意思,我不知道如何在这里制作循环(如何定期检查条件)。 - Ican
我有同样的问题,但是在C#中。https://stackoverflow.com/questions/64918790/show-message-in-specified-time - mohammad Zeynali
3个回答

19

我曾经遇到过同样的问题,但是我使用了 schedule 库解决了它。我总是觉得例子是最容易理解的方式:

import schedule
import telebot
from threading import Thread
from time import sleep

TOKEN = "Some Token"

bot = telebot.TeleBot(TOKEN)
some_id = 12345 # This is our chat id.

def schedule_checker():
    while True:
        schedule.run_pending()
        sleep(1)

def function_to_run():
    return bot.send_message(some_id, "This is a message to send.")

if __name__ == "__main__":
    # Create the job in schedule.
    schedule.every().saturday.at("07:00").do(function_to_run)

    # Spin up a thread to run the schedule check so it doesn't block your bot.
    # This will take the function schedule_checker which will check every second
    # to see if the scheduled job needs to be ran.
    Thread(target=schedule_checker).start() 

    # And then of course, start your server.
    server.run(host="0.0.0.0", port=int(os.environ.get('PORT', 5000)))

我希望您会发现这篇文章对您有所帮助,它解决了我的问题:)。

2
谢谢!你是唯一一个能够回答这个问题的人,这个问题已经被问了很多次了。使用线程是关键。 - Concept211
1
谢谢你提供的代码示例,最近我一直在学习线程的概念,但是如果没有一些实际的例子来连接这些概念,就很难将其应用到实际中。不过我有一个问题,你使用调度程序安排了作业,然后创建了一个线程,但是你没有调用bot.polling?为什么会这样呢?如果你不进行轮询,那么为什么还需要线程调度呢? - stuckoverflow
终于!非常感谢。 - Oleg O
@shy-tan 对于此问题的迟迟未能回复,深感抱歉。如果您查看以下代码行: Thread(target=schedule_checker).start() 您会发现我创建了一个线程对象,然后调用它的start方法。这将在自己的线程中无限期地运行 schedule_checker。在这种情况下不需要使用 bot.polling。希望这可以帮助到您! - Justin Lillico
尝试在VSCode中使用此功能。已经通过pip安装了schedule包,但是VSCode显示无法解析该包。你能帮我吗? - curiouscheese

6

你可以使用cron/at或类似的工具来管理任务。

写一个脚本,可能叫做alarm_telegram.py

#!/usr/bin/env python
import telebot
import config
    
bot = telebot.TeleBot(config.bot_token)
chat_id=config.my_id
bot.send_message(chat_id, 'Wake up!')

然后在cron中按照以下方式编程。

00 8 * * 6 /path/to/your/script/alarm_telegram.py

祝愉快编码!


1
是的,但那并不有趣 :) 感谢建议。 - Ican
不感兴趣?答案没有解决你的问题吗? - Pjl

0
如果你想让你的机器人既能够安排消息,又能够通过输入命令来获取信息,那么你需要将线程放置在特定的位置(我花了一些时间才明白如何使轮询和线程同时工作)。 顺便说一下,我在这里使用了另一个库,但它也可以很好地与schedule库配合使用。
import telebot
from apscheduler.schedulers.blocking import BlockingScheduler
from threading import Thread

def run_scheduled_task():
    print("I am running")
    bot.send_message(some_id, "This is a message to send.")
    

scheduler = BlockingScheduler(timezone="Europe/Berlin") # You need to add a timezone, otherwise it will give you a warning
scheduler.add_job(run_scheduled_task, "cron", hour=22) # Runs every day at 22:00

def schedule_checker():
    while True:
        scheduler.start()

@bot.message_handler(commands=['start', 'help'])
def print_hi(message):
    bot.send_message(message.chat.id, 'Hi!')

Thread(target=schedule_checker).start() # Notice that you refer to schedule_checker function which starts the job

bot.polling() # Also notice that you need to include polling to allow your bot to get commands from you. But it should happen AFTER threading!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接