Как с помощью pyTelegramBotAPI отправлять сообщения в определенное время?

Я делаю бота, на которого можно подписаться и получать прогноз погоды по расписанию. Но я не знаю, как посылать сообщения в определенное время. Я пробовал использовать библиотеку schedule, но что-то не заработало. Можете показать рабочий способ?

Полный код:

import telebot
from telebot import types
import sqlite3
from bs4 import BeautifulSoup as bs
import requests

#setting bot
bot = telebot.AsyncTeleBot('MY_TOKEN', parse_mode = 'html')
current_weather_page = 'https://www.google.com/search?q=spb+weather&oq=SPB+Weather&aqs=chrome.0.0l8.4934j1j4&sourceid=chrome&ie=UTF-8'
current_evening_page = 'https://www.google.com/search?sxsrf=ALeKk02ZsiSTxM9RIA14tT12-b0alvgeBQ%3A1596724225506&ei=ARQsX8OyHuarrgSl_anIAg&q=spbweathertodayevening&oq=spbweathertodayevening&gs_lcp=CgZwc3ktYWIQDDIHCCMQsAIQJzIHCCMQsAIQJzoECAAQR1CIHViwnQFg0agBaABwAngAgAH_AogB0gWSAQcyLjEuMC4xmAEAoAEBqgEHZ3dzLXdpesABAQ&sclient=psy-ab&ved=0ahUKEwiDt4-i5YbrAhXmlYsKHaV-CikQ4dUDCAw'
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36'}
db = sqlite3.connect('weather_bot_subs.db', check_same_thread = False)
sql = db.cursor()

#main menu
main_keyboard = types.ReplyKeyboardMarkup(row_width = 1, resize_keyboard = True)
btn1 = types.KeyboardButton('Погода ⛅️')
btn2 = types.KeyboardButton('Подписка ?')
main_keyboard.add(btn1, btn2)

#turn the bot on
@bot.message_handler(commands = ['start'])
def start(message):
    bot.send_message(message.chat.id, 'Приветствую. Я - <strong> ⛅️SPB-Weather Бот⛅️ </strong>.\n Я всегда подскажу актуальный прогноз погоды в Санкт-Петербурге, чтобы вы оделись потеплее, или не таскали с собой зонтик.\nТакже вы можете оформить подписку, и получать каждый день прогноз по расписанию?.\nУдачного использования!?', reply_markup = main_keyboard)

#All commands here
@bot.message_handler(content_types = ['text'])
def main_sender(message):
    if message.text == 'Погода ⛅️':
        weather_keyboard = types.ReplyKeyboardMarkup(row_width = 2, resize_keyboard = 2)
        current = types.KeyboardButton('Текущая погода ⛅️')
        morning = types.KeyboardButton('Утреняя погода ?')
        day = types.KeyboardButton('Дневная погода ☀️')
        night = types.KeyboardButton('Вечерняя погода ?')
        back = types.KeyboardButton('Назад ⬅️')

        weather_keyboard.add(current,morning,day,night,back)
        bot.send_message(message.chat.id, 'Вы вошли в меню погоды ☀️', reply_markup = weather_keyboard)

    elif message.text == 'Текущая погода ⛅️':
        bot.send_message(message.chat.id, 'Так точно! Начинаю сбор данных ?')
        page_content = requests.get(current_weather_page, headers = headers)
        soup = bs(page_content.content, 'html.parser')

        situation = soup.findAll('span', {'class': 'vk_gy', 'class' : 'vk_sh', 'id' : 'wob_dc'})
        temperature_celsius = soup.findAll('span', {'class': "wob_t", 'id' : 'wob_tm'})
        temperature_fahrenheit = soup.findAll('span', {'id' : "wob_ttm"})
        humidity = soup.findAll('span', {'id' : 'wob_hm'})
        wind_speed = soup.findAll('span', {'class' : 'wob_t', 'id' : 'wob_ws'})
        probability_of_precipitation = soup.findAll('span', {'id' : 'wob_pp'})

        bot.send_message(message.chat.id, 'Готово ✔️\nСейчас в Санкт-Петербурге:\n⛅️ Общая обстановка: ' + str(situation[0].text) + '\n? Температура воздуха: ' + str(temperature_celsius[0].text) + 'C° / ' + str(temperature_fahrenheit[0].text) + 'F°' + '\n☔️ Вероятность осадков: ' + str(probability_of_precipitation[0].text) + '\n? Влажность воздуха: ' + str(humidity[0].text) + '\n? Скорость ветра: ' + str(wind_speed[0].text))
    
    elif message.text == 'Вечерняя погода ?':
        bot.send_message(message.chat.id, 'Так точно! Начинаю сбор данных ?')
        page_content = requests.get(current_evening_page, headers = headers)
        soup = bs(page_content.content, 'html.parser')

        evening_situation = soup.findAll('span', {'class': 'vk_gy', 'class' : 'vk_sh', 'id' : 'wob_dc'})
        evening_temperature_celsius = soup.findAll('span', {'class': "wob_t", 'id' : 'wob_tm'})
        evening_temperature_fahrenheit = soup.findAll('span', {'id' : "wob_ttm"})
        evening_humidity = soup.findAll('span', {'id' : 'wob_hm'})
        evening_wind_speed = soup.findAll('span', {'class' : 'wob_t', 'id' : 'wob_ws'})
        evening_probability_of_precipitation = soup.findAll('span', {'id' : 'wob_pp'})

        bot.send_message(message.chat.id, 'Готово ✔️\nСегодня вечером в Санкт-Петербурге: \n⛅️ Общая обстановка: ' + str(evening_situation[0].text) + '\n? Температура воздуха: ' + str(evening_temperature_celsius[0].text) + 'C° / ' + str(evening_temperature_fahrenheit[0].text) + 'F°' + '\n☔️ Вероятность осадков: ' + str(evening_probability_of_precipitation[0].text) + '\n? Влажность воздуха: ' + str(evening_humidity[0].text) + '\n? Скорость ветра: ' + str(evening_wind_speed[0].text))


    elif message.text == 'Подписка ?':
        sub_menu = types.ReplyKeyboardMarkup(row_width = 2, resize_keyboard = True)
        btn3 = types.KeyboardButton('Подписаться ?')
        btn4 = types.KeyboardButton('Отписаться ❌')
        btn5 = types.KeyboardButton('Назад ⬅️')
        sub_menu.add(btn3,btn4,btn5)
        bot.send_message(message.chat.id, 'Вы вошли в меню подписки ?', reply_markup = sub_menu)

    elif message.text == 'Подписаться ?':
        bot.send_message(message.chat.id, 'Подождите ?\n Подтверждаю вашу подписку...')
        sql.execute(f"SELECT user_id FROM users WHERE user_id ='{str(message.chat.id)}'")
        if sql.fetchone() is None:
            sql.execute("INSERT INTO users (user_id, user_name) VALUES (?, ?)", (str(message.chat.id),str(message.from_user.username),))
            db.commit()
            bot.send_message(message.chat.id, 'Успех ?\nВаша подписка оформлена ✅\nТеперь вы можете получать прогноз в автоматическом режиме.\nВы можете отказаться от подписки в любой момент, зайдя в меню подписки и нажав кнопку "Отписаться"')
        else:
            bot.send_message(message.chat.id, 'Ошибка ⛔️:\nВы уже подписаны!')

    elif message.text == 'Отписаться ❌':
        sql.execute(f"SELECT user_id FROM users WHERE user_id ='{str(message.chat.id)}'")
        if sql.fetchone() is None:
            bot.send_message(message.chat.id, 'Ошибка ⛔️:\nВы не были подписаны!')
        else:
            bot.send_message(message.chat.id, 'Подождите ?\nОтменяю вашу подписку...')
            sql.execute(f"DELETE FROM users WHERE user_id = '{str(message.chat.id)}'")
            db.commit()
            bot.send_message(message.chat.id, 'Вы отменили подписку.\nСпасибо за то, что были с нами?')

    elif message.text == 'Назад ⬅️':
        bot.send_message(message.chat.id, 'Вы вернулись в главное меню', reply_markup = main_keyboard)

#start
bot.polling(none_stop = True)

Ответы (1 шт):

Автор решения: shalor1k

Вы можете использовать time.sleep (seconds). Например:

import time
while True:
    bot.send_message(message.chat.id, 'текст')  # типа отправляешь сообщение
    time.sleep(60)  # останавливает выполнение кода на минуту

Но лучше всего использовать datetime модуль:

import datetime
datetime.datetime.now().time()  # вернет настоящее время

Но лучшее помоему мнению:

import schedule
import time

def job():
    print("I'm working...")

schedule.every(10).minutes.do(job)
schedule.every().hour.do(job)
schedule.every().day.at("10:30").do(job)
schedule.every().monday.do(job)
schedule.every().wednesday.at("13:15").do(job)
schedule.every().minute.at(":17").do(job)

while True:
    schedule.run_pending()
    time.sleep(1)

Оригинал

→ Ссылка