7

Hi i want to send message from bot in specific time (without message from me), for example every Saturday morning at 8:00am. Here is my code:

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)

But ofc that's not working. Tried with

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

but again no result. Have no idea what to do, help please with advice.

Ican
  • 119
  • 2
  • 2
  • 10

3 Answers3

19

I had this same issue and I was able to solve it using the schedule library. I always find examples are the easiest way:

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)))

I hope you find this useful, solved the problem for me :).

Justin Lillico
  • 308
  • 2
  • 5
  • 2
    Thank you! You've been the only person who has been able to answer this question that's been asked so many times. Using threading was the key. – Concept211 May 22 '20 at 18:24
  • 1
    Thankyou for the code example, I have been learning the concepts of threading lately but its hard to connect those concepts with a real world application without some example. I have a question though, you scheduled the job with scheduler and then made a thread, but you didnt call bot.polling? Why is that so. If youre not polling, why would be there a need to thread the schedule anyway? – stuckoverflow Jan 30 '21 at 14:10
  • Finally! Thanks a lot. – Oleg O Mar 14 '21 at 08:22
  • @shy-tan Sorry for the delayed response on this one. If you look at the line `Thread(target=schedule_checker).start()` you will see I create a thread object and then call its start method. This will run the `schedule_checker` in its own thread indefinitely. No need to use `bot.polling` in this case. Hope this helps! – Justin Lillico Dec 21 '21 at 12:34
  • Tried using this in VSCode. Alredy pip install the schedule package, but VSCode said the package is could not be resolve. Can you help me? – curiouscheese Jan 24 '22 at 03:09
6

You could manage the task with cron/at or similar.

Make a script, maybe called 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!')

Then program in cron like this.

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

Happy Coding!!!

stuckoverflow
  • 625
  • 2
  • 7
  • 23
Pjl
  • 1,752
  • 18
  • 21
0

If you want your bot to both schedule a message and also get commands from typing something inside, you need to put Thread in a specific position (took me a while to understand how I can make both polling and threading to work at the same time). By the way, I am using another library here, but it would also work nicely with schedule library.

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!