L
L
lonnerr2021-08-02 00:35:12
Python
lonnerr, 2021-08-02 00:35:12

How can I give the bot the ability to simultaneously wait for a message from the user and check the time for the scheduled output of the message?

Hello. I have a bot written in 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()

I need it to output weather information for the whole day at a certain time every day, but I also need it to be able to accept user commands (/start and /weather).
But when main() is run, it will only process the user's messages, and it will not be able to check the time to display the scheduled message.
How to make it able to check the time (and if it matches, then display a message) and wait for a message from the user?
Thanks in advance

Answer the question

In order to leave comments, you need to log in

2 answer(s)
R
RINAMI, 2021-08-02
@lonnerr

In order to schedule tasks for your code, you need schedule
Example:

import schedule
def primer():
      #func options
     schedule.every().day.at('8:00').do(primer)
     while True:
            schedule.run_pending()
            time.sleep(3)

To make the bot do everything as you want, create two threads example:
import threading
from threading import Thread
def thread2():
      thr2 = Thread(target=primer)
      thr2.start()

Add to the end of the code:
if __name__ == '__main__':
    thread2()

Bottom line:
The functions you need will be executed in the main thread, and schedule will be executed in thread number 2.

A
Alexander, 2021-08-02
@SilimAl

If I understand your idea correctly, you. you need to separate these two processes. bot bot - answers requests, and separately according to the schedule, with the consent of the user or everyone in a row, sends messages. You can implement it through cron, for example
. there is a bot script that responds to a request, and there is a separate script that runs "every morning" via cron and sends messages

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question