diff --git a/burgerbot.py b/burgerbot.py index 3fa5948..fe792b9 100644 --- a/burgerbot.py +++ b/burgerbot.py @@ -15,6 +15,7 @@ from telegram.update import Update from parser import Parser, Slot, build_url +from parser2 import Parser2, Alert CHATS_FILE = 'chats.json' @@ -42,13 +43,18 @@ class Message: class User: chat_id: int services: List[int] - def __init__(self, chat_id, services=[120686]): + personal_link: str + def __init__(self, chat_id, services=[120686], personal_link=''): self.chat_id = chat_id self.services = services if len(services) > 0 else [120686] + if len(personal_link) > 0: + self.personal_link = personal_link def marshall_user(self) -> str: self.services = list(set([s for s in self.services if s in list(service_map.keys())])) + if len(self.personal_link) > 0: + self.personal_link = personal_link return asdict(self) @@ -59,6 +65,8 @@ def __init__(self) -> None: self.users = self.__get_chats() self.services = self.__get_uq_services() self.parser = Parser(self.services) + self.personal_link = self.__get_uq_personal_links()[0] + self.parser2 = Parser2(self.personal_link) self.dispatcher = self.updater.dispatcher self.dispatcher.add_handler(CommandHandler('help', self.__help)) self.dispatcher.add_handler(CommandHandler('start', self.__start)) @@ -66,6 +74,8 @@ def __init__(self) -> None: self.dispatcher.add_handler(CommandHandler('add_service', self.__add_service)) self.dispatcher.add_handler(CommandHandler('remove_service', self.__remove_service)) self.dispatcher.add_handler(CommandHandler('services', self.__services)) + self.dispatcher.add_handler(CommandHandler('add_aus', self.__add_aus)) + self.dispatcher.add_handler(CommandHandler('remove_aus', self.__remove_aus)) self.cache: List[Message] = [] @@ -76,6 +86,13 @@ def __get_uq_services(self) -> List[int]: services = filter(lambda x: x in service_map.keys(), services) return list(set(services)) + def __get_uq_personal_links(self) -> List[int]: + personal_links = [] + for u in self.users: + personal_links.extend([u.personal_link]) + personal_links = filter(lambda x: x in service_map.keys(), personal_links) + return list(set(personal_links)) + def __init_chats(self) -> None: if not os.path.exists(CHATS_FILE): with open(CHATS_FILE, "w") as f: @@ -83,7 +100,7 @@ def __init_chats(self) -> None: def __get_chats(self) -> List[User]: with open(CHATS_FILE, 'r') as f: - users = [User(u['chat_id'], u['services']) for u in json.load(f)] + users = [User(u['chat_id'], u['services'], u['personal_link']) for u in json.load(f)] f.close() print(users) return users @@ -118,6 +135,8 @@ def __help(self, update: Update, _: CallbackContext) -> None: /add_service - add service to your list /remove_service - remove service from your list /services - list of available services +/add_aus - add Ausländer personal link +/remove_aus - remove Ausländer personal link """) except Exception as e: logging.error(e) @@ -155,6 +174,29 @@ def __remove_service(self, update: Update, _: CallbackContext) -> None: break update.message.reply_text("Service removed") + def __add_aus(self, update: Update, _: CallbackContext) -> None: + logging.info(f'adding aus {update.message}') + try: + personal_link = int(update.message.text.split(' ')[1]) + for u in self.users: + if u.chat_id == update.message.chat_id: + u.personal_link = personal_link + self.__persist_chats() + break + update.message.reply_text("Aus added") + except Exception as e: + update.message.reply_text("Failed to add aus, have you specified your personal form link?") + logging.error(e) + + def __remove_aus(self, update: Update, _: CallbackContext) -> None: + logging.info(f'removing aus {update.message}') + for u in self.users: + if u.chat_id == update.message.chat_id: + u.personal_link = None + self.__persist_chats() + break + update.message.reply_text("Service removed") + def __poll(self) -> None: self.updater.start_polling() @@ -163,6 +205,9 @@ def __parse(self) -> None: slots = self.parser.parse() for slot in slots: self.__send_message(slot) + alerts = self.parser2.parse() + for alert in alerts: + self.__send_message2(alert) time.sleep(30) @@ -185,6 +230,25 @@ def __send_message(self, slot: Slot) -> None: logging.warning(e) self.__clear_cache() + def __send_message2(self, alert: Alert) -> None: + if self.__msg_in_cache(alert.msg): + logging.info('Notification is cached already. Do not repeat sending') + return + self.__add_msg_to_cache(alert.msg) + md_msg = f"Personal link alert: '{alert.msg}', click [here]({self.personal_link}) to check it out" + users = [u for u in self.users] + for u in users: + logging.debug(f"sending msg to {str(u.chat_id)}") + try: + self.updater.bot.send_message(chat_id=u.chat_id, text=md_msg, parse_mode=ParseMode.MARKDOWN_V2) + except Exception as e: + if 'bot was blocked by the user' in e.__str__(): + logging.info('removing since user blocked bot') + self.__remove_chat(u.chat_id) + else: + logging.warning(e) + self.__clear_cache() + def __msg_in_cache(self, msg: str) -> bool: for m in self.cache: if m.message == msg: diff --git a/parser2.py b/parser2.py new file mode 100644 index 0000000..b6304a9 --- /dev/null +++ b/parser2.py @@ -0,0 +1,51 @@ +import time +import logging +from dataclasses import dataclass +from typing import List +from re import S + +import requests +from bs4 import BeautifulSoup + +@dataclass +class Alert: + msg: str + +class Parser2: + def __init__(self, personal_link: str) -> None: + self.personal_link = personal_link + self.proxy_on: bool = False + self.parse() + + def __get_url(self, url) -> requests.Response: + if self.proxy_on: + return requests.get(url, proxies={'https': 'socks5://127.0.0.1:9050'}) + return requests.get(url) + + def __toggle_proxy(self) -> None: + self.proxy_on = not self.proxy_on + + def __parse_page(self, page) -> List[str]: + try: + if page.status_code == 428: + logging.info('exceeded rate limit. Sleeping for a while') + time.sleep(299) + self.__toggle_proxy() + return None + soup = BeautifulSoup(page.content, 'html.parser2') + errors = soup.find_all('li', class_='errorMessage') + if len(errors) != 0: + logging.info("no luck yet") + return [Alert('no error')] + except Exception as e: ## sometimes shit happens + logging.warn(e) + self.__toggle_proxy() + + def set_personal_link(self, personal_link: str) -> None: + self.personal_link + + def parse(self) -> List[str]: + alerts = [] + page = self.__get_url(self.personal_link) + alerts += self.__parse_page(page) + return alerts