From bcc43c3ff528b1fbaca261a502dfcd1c47ab241e Mon Sep 17 00:00:00 2001 From: bvn13 Date: Fri, 19 Jul 2024 00:45:23 +0300 Subject: [PATCH] implemented weather job --- config/newsmaker-prod.json | 3 +++ config/newsmaker.json | 3 +++ requirements.txt | 4 +++- src/bot/bot.py | 33 ++++++++++++++++++++++---- src/bot/message.py | 12 ++++++++++ src/jobs/__init__.py | 11 +++++++++ src/jobs/weather.py | 14 ++++++++++++ src/main.py | 47 +++++++++++++++++++++++++++++++++++--- src/settings/config.py | 14 +++++++++--- version | 2 +- 10 files changed, 131 insertions(+), 12 deletions(-) create mode 100644 src/bot/message.py create mode 100644 src/jobs/__init__.py create mode 100644 src/jobs/weather.py diff --git a/config/newsmaker-prod.json b/config/newsmaker-prod.json index b8a8aae..b2dfa29 100644 --- a/config/newsmaker-prod.json +++ b/config/newsmaker-prod.json @@ -50,5 +50,8 @@ } } ] + }, + "weather": { + "shkolniy": -1001699667908 } } \ No newline at end of file diff --git a/config/newsmaker.json b/config/newsmaker.json index 898947e..4a78827 100644 --- a/config/newsmaker.json +++ b/config/newsmaker.json @@ -23,5 +23,8 @@ } } ] + }, + "weather": { + "shkolniy": -1002184916546 } } \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index b411b09..a55bccd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,5 @@ aiohttp==3.9.5 telethon==1.36.0 -cryptg==0.4.0 \ No newline at end of file +cryptg==0.4.0 +scheduler==0.8.7 +requests-html==0.10.0 \ No newline at end of file diff --git a/src/bot/bot.py b/src/bot/bot.py index 2b1fda4..e5528d2 100644 --- a/src/bot/bot.py +++ b/src/bot/bot.py @@ -1,7 +1,10 @@ +import asyncio from settings import config import logging import re +from queue import Queue, Empty from telethon import TelegramClient, events +from bot.message import WeatherTask logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) @@ -20,6 +23,7 @@ class Bot(): self.__owner_id = owner_id self.__reload() self.__bot = TelegramClient(session_file, api_id, api_hash) + self.__weather_queue = Queue() @self.__bot.on(events.NewMessage(incoming=True, pattern='!whoami')) async def onMessageWhoami(event): @@ -63,10 +67,31 @@ class Bot(): logger.info("Received message in chat {0}, id {1}: {2}".format(chat_id, message.id, message.text if not message == None else "")) await self.__process_message(event, chat_id, message) - def start(self) -> None: - self.__bot.start() - self.__bot.loop.run_until_complete(self.__identity()) - self.__bot.run_until_disconnected() + async def start(self) -> None: + await self.__bot.start() + await self.__identity() + self.__bot.loop.create_task(self.__task_loop()) + await self.__bot.run_until_disconnected() + + def send_weather(self, task: WeatherTask) -> None: + self.__weather_queue.put(task) + + async def __task_loop(self) -> None: + while True: + logger.debug("Looking for weather jobs") + weather_task = None + try: + weather_task = self.__weather_queue.get_nowait() + except Empty: + pass + if weather_task is not None: + await self.__send_weather(weather_task.get_key(), weather_task.get_message()) + await asyncio.sleep(1) + + async def __send_weather(self, key: str, message: str) -> None: + dest_chat_id = self.__config.get_weather_destination_chat_id(key) + if dest_chat_id is not None: + await self.__bot.send_message(dest_chat_id, message, parse_mode='html') def __reload(self) -> None: self.__config = config.Config(filename=self.__config_file) diff --git a/src/bot/message.py b/src/bot/message.py new file mode 100644 index 0000000..11e5d86 --- /dev/null +++ b/src/bot/message.py @@ -0,0 +1,12 @@ + +class WeatherTask: + def __init__(self, key: str, message: str) -> None: + self.__key = key + self.__message = message + + def get_key(self) -> str: + return self.__key + + def get_message(self) -> str: + return self.__message + \ No newline at end of file diff --git a/src/jobs/__init__.py b/src/jobs/__init__.py new file mode 100644 index 0000000..07a2c72 --- /dev/null +++ b/src/jobs/__init__.py @@ -0,0 +1,11 @@ +import sys +import os + +# Get the current script's directory +current_dir = os.path.dirname(os.path.abspath(__file__)) + +# Get the parent directory by going one level up +parent_dir = os.path.dirname(current_dir) + +# Add the parent directory to sys.path +sys.path.append(parent_dir) \ No newline at end of file diff --git a/src/jobs/weather.py b/src/jobs/weather.py new file mode 100644 index 0000000..7fb1a1a --- /dev/null +++ b/src/jobs/weather.py @@ -0,0 +1,14 @@ +from requests_html import HTMLSession + +class Weather: + def __init__(self) -> None: + pass + + def get_shkolniy(self): + url = "https://a-weather.ru/place/ru-shkolnij-12/" + session = HTMLSession() + response = session.get(url) + return "\n".join([ + response.html.find('.weather_about', first=True).text, + response.html.find('.last_update', first=True).text + ]) \ No newline at end of file diff --git a/src/main.py b/src/main.py index 74df295..7bf5b82 100644 --- a/src/main.py +++ b/src/main.py @@ -1,11 +1,19 @@ -import os -from bot.bot import Bot +import asyncio +import datetime as dt import logging +import os +from scheduler import Scheduler +import time +import threading +from bot.bot import Bot +from bot.message import WeatherTask +from jobs.weather import Weather logging.basicConfig(format="%(asctime)s | %(name)s | %(levelname)s | %(message)s") logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) + if __name__ == "__main__": session_file = os.environ['SESSION_FILE'] api_id = os.environ['TG_APP_ID'] @@ -17,4 +25,37 @@ if __name__ == "__main__": api_hash=api_hash, config_file=config_file, owner_id=owner_id) - bot.start() + + def start_bot(): + asyncio.set_event_loop(asyncio.new_event_loop()) + loop = asyncio.get_event_loop() + # Your asyncio code here + loop.run_until_complete(bot.start()) + loop.close() + + def shkolniy_weather_job(): + logger.info("Shkolniy weather job") + weather = Weather() + shkolniy_weather = str(weather.get_shkolniy()) + if shkolniy_weather is None: + logger.warn("Unable to get weather") + rows = shkolniy_weather.split('\n') + n = len(rows)-1 + rows[0] = "{0}".format(rows[0]) + rows[n] = "{0}".format(rows[n]) + shkolniy_weather = '\n\n'.join(rows) + bot.send_weather(WeatherTask('shkolniy', "{0}".format(shkolniy_weather))) + + def scheduled(): + schedule = Scheduler() + # schedule.cyclic(dt.timedelta(seconds=10), shkolniy_weather_job) + schedule.daily(dt.time(hour=0, minute=24), shkolniy_weather_job) + while True: + schedule.exec_jobs() + time.sleep(1) + + + thread = threading.Thread(target=start_bot) + thread.start() + thread2 = threading.Thread(target=scheduled) + thread2.start() diff --git a/src/settings/config.py b/src/settings/config.py index bf12935..6429dfe 100644 --- a/src/settings/config.py +++ b/src/settings/config.py @@ -8,6 +8,10 @@ class Config(): self.__config = {} self.__read() + def read_as_text(self) -> str: + with open(self.__filename, 'r') as f: + return ''.join(f.readlines()) + def get_on_message_for_chat_id(self, chat_id: int) -> Optional[dict]: chat_id_str = str(chat_id) if 'onMessage' in self.__config: @@ -16,9 +20,13 @@ class Config(): return on_message[chat_id_str] return None - def read_as_text(self) -> str: - with open(self.__filename, 'r') as f: - return ''.join(f.readlines()) + def get_weather_destination_chat_id(self, key: str) -> Optional[int]: + key_str = str(key) + if 'weather' in self.__config: + weather = self.__config['weather'] + if key_str in weather: + return weather[key_str] + return None def __read(self) -> None: with open(self.__filename, 'r') as f: diff --git a/version b/version index 7693c96..341cf11 100644 --- a/version +++ b/version @@ -1 +1 @@ -0.1.3 \ No newline at end of file +0.2.0 \ No newline at end of file