From 9546faa2601c1b314bda0f6a0ee7bdd799a13061 Mon Sep 17 00:00:00 2001 From: Dmitrii Morozov Date: Thu, 28 Mar 2024 19:31:10 +0100 Subject: Async notification for changes in status --- fortniteStatusFormatter.py | 21 ++++++++++++++++++ fortniteStatusWrapper.py | 48 +++++++++++++++++++++++++++++------------ persistence.py | 28 ++++++++++++++++++++---- pythonFortniteStatus | 2 +- tgbot.py | 53 ++++++++++++++-------------------------------- 5 files changed, 97 insertions(+), 55 deletions(-) create mode 100644 fortniteStatusFormatter.py diff --git a/fortniteStatusFormatter.py b/fortniteStatusFormatter.py new file mode 100644 index 0000000..9595304 --- /dev/null +++ b/fortniteStatusFormatter.py @@ -0,0 +1,21 @@ +from telebot import formatting + +def __formatStatus(status): + if (status == True): + return u'\u2705' + else: + return u'\u274c' + +def __formatFortniteServiceStatus(fortniteServiceStatus): + return formatting.format_text( + formatting.mbold(fortniteServiceStatus.serviceName), + __formatStatus(fortniteServiceStatus.status), + separator=': ') + +def formatFortniteStatus(fortniteStatus): + statuses = [__formatFortniteServiceStatus(serviceStatus) for serviceStatus in fortniteStatus.serviceStatuses] + return formatting.format_text( + formatting.mbold("Fortnite status"), + "", + '\n'.join(statuses), + separator='\n') \ No newline at end of file diff --git a/fortniteStatusWrapper.py b/fortniteStatusWrapper.py index 1fd4ece..48618be 100644 --- a/fortniteStatusWrapper.py +++ b/fortniteStatusWrapper.py @@ -1,17 +1,39 @@ from telebot import formatting +import time, threading, schedule +from pythonFortniteStatus.FortniteStatus import * -def formatStatus(status): - if (status == True): - return u'\u2714' - else: - return u'\u274c' +__polling_interval__ = 5 -def formmatFortniteServiceStatus(fortniteServiceStatus): - return formatting.format_text( - formatting.mbold(fortniteServiceStatus.serviceName), - formatStatus(fortniteServiceStatus.status), - separator=': ') +fortniteStatus = FortniteStatus() -def formatFortniteStatus(fortniteStatus): - statuses = [formmatFortniteServiceStatus(serviceStatus) for serviceStatus in fortniteStatus.serviceStatuses] - return '\n'.join(statuses) \ No newline at end of file +class Observer: + def update(self, fortniteStatus) -> None: + pass + +class FortniteStatusWrapper: + + observers = [] + fortniteStatus = None + + def __init__(self): + schedule.every(__polling_interval__).seconds.do(self.__readStatus) + threading.Thread(target=self.__scheduleHandler, name='fortnite_status_scheduler', daemon=True).start() + + def __scheduleHandler(self): + while True: + schedule.run_pending() + time.sleep(1) + + def __readStatus(self): + serviceStatusTmp = fortniteStatus.getStatus() + if serviceStatusTmp != self.fortniteStatus: + self.notify(serviceStatusTmp) + self.fortniteStatus = serviceStatusTmp + + def notify(self, fortniteStatus): + print("Fortnite status changed, notifying observers") + for observer in self.observers: + observer.update(fortniteStatus) + + def attach(self, observer: Observer): + self.observers.append(observer) \ No newline at end of file diff --git a/persistence.py b/persistence.py index eb1903f..d2998e9 100644 --- a/persistence.py +++ b/persistence.py @@ -10,12 +10,32 @@ class UserRepository: def __initialize(self): cur = self.__getConnection().cursor() cur.execute("CREATE TABLE IF NOT EXISTS user(chat_id INT)") + cur.execute("CREATE UNIQUE INDEX IF NOT EXISTS chat_id_idx ON user(chat_id)") def __getConnection(self): return sqlite3.connect('db.sqlite') + def getUser(self, chat_id): + connection = self.__getConnection() + cur = connection.cursor() + query = "select * from user where chat_id = {chat_id}".format(chat_id = chat_id) + cur.execute(query) + return cur.fetchone() + + def getAllUsers(self): + connection = self.__getConnection() + cur = connection.cursor() + query = "select * from user" + cur.execute(query) + return cur.fetchall() + + def putUser(self, chat_id): - cur = self.__getConnection().cursor() - data_tuple = (chat_id) - print(type(chat_id)) - cur.execute("INSERT INTO user(chat_id) VALUES(?)", (chat_id, )) + if not self.getUser(chat_id): + connection = self.__getConnection() + cur = connection.cursor() + query = "INSERT INTO user(chat_id) VALUES({chat_id})".format(chat_id = chat_id) + cur.execute(query) + connection.commit() + else: + print("User {} already exsits, skipping putUser()".format(chat_id)) diff --git a/pythonFortniteStatus b/pythonFortniteStatus index 3069676..657eff0 160000 --- a/pythonFortniteStatus +++ b/pythonFortniteStatus @@ -1 +1 @@ -Subproject commit 30696764787d49c25d90b4241f97cf64523a5678 +Subproject commit 657eff0289301ece411b07751113b6a36c6ce79b diff --git a/tgbot.py b/tgbot.py index 6d4fc52..99d6351 100755 --- a/tgbot.py +++ b/tgbot.py @@ -3,55 +3,34 @@ import os import time, threading, schedule import telebot -from fortniteStatusWrapper import formatFortniteStatus +from fortniteStatusWrapper import * +from fortniteStatusFormatter import * from persistence import UserRepository -from pythonFortniteStatus.FortniteStatus import * if "TELEBOT_BOT_TOKEN" not in os.environ: raise AssertionError("Please configure TELEBOT_BOT_TOKEN as environment variables") bot = telebot.TeleBot(os.environ["TELEBOT_BOT_TOKEN"]) -fortniteStatus = FortniteStatus() userRepository = UserRepository('db.sqlite') +fortniteStatusWrapper = FortniteStatusWrapper() @bot.message_handler(commands = ['start']) def startCommand(message): bot.reply_to(message, "This bot is doing nothing so far..") - print(message.chat.id) userRepository.putUser(message.chat.id) -@bot.message_handler(commands = ['status']) -def fortniteStatusCommand(message): - bot.send_message( - message.chat.id, - formatFortniteStatus(fortniteStatus.getStatus()), - parse_mode='MarkdownV2' - ) - -#bot.polling(none_stop=True, interval=0) - -def beep(chat_id) -> None: - """Send the beep message.""" - bot.send_message(chat_id, text='Beep!') - - -@bot.message_handler(commands=['set']) -def set_timer(message): - args = message.text.split() - if len(args) > 1 and args[1].isdigit(): - sec = int(args[1]) - schedule.every(sec).seconds.do(beep, message.chat.id).tag(message.chat.id) - else: - bot.reply_to(message, 'Usage: /set ') - - -@bot.message_handler(commands=['unset']) -def unset_timer(message): - schedule.clear(message.chat.id) - +class FortniteStatusObserver(Observer): + def update(self, fortniteStatus) -> None: + for user in userRepository.getAllUsers(): + bot.send_message( + user[0], + formatFortniteStatus(fortniteStatus), + parse_mode='MarkdownV2' + ) if __name__ == '__main__': - threading.Thread(target=bot.infinity_polling, name='bot_infinity_polling', daemon=True).start() - while True: - schedule.run_pending() - time.sleep(1) \ No newline at end of file + fortniteStatusWrapper.attach(FortniteStatusObserver()) + + main_thread = threading.Thread(target=bot.infinity_polling, name='bot_infinity_polling', daemon=True) + main_thread.start() + main_thread.join() \ No newline at end of file -- cgit v1.2.3