@lonnerr

Как дать боту возможность одновременно ждать сообщения от пользователя и проверять время для запланированного вывода сообщения?

Всем привет. У меня есть бот, написанный на python-telegram-bot:
import requests
from bs4 import BeautifulSoup
import time
from telegram.ext import Updater, CommandHandler, MessageHandler
from telegram import Bot
from datetime import datetime

HEADERS = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:71.0) Gecko/20100101 Firefox/71.0',
           'accept': '*/*'}
TOKEN = 'MYTOKEN'
URL = 'https://yandex.ru/pogoda/moscow'
weather_values = []
now_weather_values = {}
IDs = []
IDs_settings = []
bot = Bot(token=TOKEN)


def get_html(url, params=None):
    return requests.get(url, headers=HEADERS, params=params)


def get_weather_values(html):
    soup = BeautifulSoup(html.text, 'html.parser')
    weather_for_day = soup.find('ul', class_='swiper-wrapper').find_all('li')
    for hour in weather_for_day:
        if hour.get('class')[0] == 'fact__hour-separator':
            break
        if hour.find_all('div')[1].get_text().lower() == 'восход' or \
                hour.find_all('div')[1].get_text().lower() == 'закат':
            weather_values.append({
                'time': hour.find_all('div')[0].get_text(),
                'temp': hour.find_all('div')[1].get_text()
            })
        else:
            weather_values.append({
                'time': hour.find_all('div')[0].get_text(),
                'symbol': hour.find('span', class_='fact__hour-elem').get('aria-label'),
                'temp': 'Температура: ' + hour.find_all('div')[1].get_text()
            })


def get_now_weather_value(html):
    global now_weather_values
    soup = BeautifulSoup(html.text, 'html.parser')
    now_weather = soup.find('div', class_='fact__props')
    now_weather_values = {
        'temp': soup.find('div', class_='temp fact__temp fact__temp_size_s').contents[1].get_text(),
        'wind': 'Ветер: ' + now_weather.find('div', class_='fact__wind-speed').get_text(),
        'humidity': 'Влажность: ' + now_weather.find('div', class_='fact__humidity').get_text(),
        'pressure': 'Давление: ' + now_weather.find('div', class_='fact__pressure').get_text()
    }


def start(update, context):
    if update.message.chat_id not in IDs:
        IDs.append(update.message.chat_id)
    update.message.reply_text(f'Привет, {update.message.from_user.first_name}, \n'
                              f'Я - бот, созданный для отправки информации о погоде, курса вылют и новостей, '
                              f'все это я делаю в назначенное время: (по умолчанию) 6:59.\n'
                              f'Для управления моим функационалом пишите следующие команды:\n'
                              f'/weather - чтобы получить информацию о погоде на оставшийся день,\n')


def send_weather_info(update='', context=''):
    get_weather_values(get_html(URL))
    get_now_weather_value(get_html(URL))
    if update != '' and context != '':
        update.message.reply_text("Сейчас:\n"
                                  f"{now_weather_values['temp']}\n"
                                  f"{now_weather_values['wind']}\n"
                                  f"{now_weather_values['humidity']}\n"
                                  f"{now_weather_values['pressure']}")
        for hour in weather_values:
            update.message.reply_text(f"{hour['time']} - {hour['temp']}")
    else:
        for id in IDs:
            bot.send_message(chat_id=id, text="Сейчас:\n"
                                              f"{now_weather_values['temp']}\n"
                                              f"{now_weather_values['wind']}\n"
                                              f"{now_weather_values['humidity']}\n"
                                              f"{now_weather_values['pressure']}")
            for hour in weather_values:
                bot.send_message(chat_id=id, text=f"{hour['time']} - {hour['temp']}")


def main():
    updater = Updater(token=TOKEN, use_context=True)
    dp = updater.dispatcher
    dp.add_handler(CommandHandler('start', start))
    dp.add_handler(CommandHandler('weather', send_weather_info))
    updater.start_polling()

Мне нужно чтобы он выводил каждый день в определенное время выводил информацию о погоде на весь день, но также нужно чтобы он мог принимать команды пользователя (/start и /weather).
Но при запуске main() он будет обрабатывать только сообщения пользователя и он не сможет проверять время для вывода запланированного сообщения.
Как сделать чтобы он мог и проверять время (и если оно совпадает, то выводить сообщение) и ждать сообщение от пользователя?
Заранее спасибо
  • Вопрос задан
  • 135 просмотров
Решения вопроса 1
@RINAMI
Занимаюсь монтажом и дизайном. PSD,AEX,VEG.
Для того чтобы планировать задачи для своего кода, нужен schedule
Пример:
import schedule
def primer():
      #func options
     schedule.every().day.at('8:00').do(primer)
     while True:
            schedule.run_pending()
            time.sleep(3)


Чтобы бот делал все как вы хотите, создайте два потока пример:
import threading
from threading import Thread
def thread2():
      thr2 = Thread(target=primer)
      thr2.start()


В конец кода добавьте:
if __name__ == '__main__':
    thread2()


Итог:
Функции которые вам нужны, будут выполнятся в основном потоке, а в потоке номер 2 будет выполнятся schedule.
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
Если я правильно понял вашу задумку, вам. нужно разделить эти два процесса.. бот ботом - отвечает на запросы, а отдельно по расписанию, с согласия пользователя или всем подряд, рассылает сообщения. Реализовать можно через cron например..
Т.е. есть скрипт бота отвечающего на запрос, а есть отдельный скрипт запускаемый "каждое утро" через cron и рассылающий сообщения
Ответ написан
@Nameisconfidentialinfo
За что-то даже платят
посмотри в сторону apscheduler и celery.
Apscheduler проще для бота, сам юзаю.
Используй таски по-расписанию. Каждый день в 12 например, собирай инфу о погоде. В остальное время общайся с юзером
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы