diff options
| -rw-r--r-- | formatter/__init__.py | 4 | ||||
| -rwxr-xr-x | main.py | 4 | ||||
| -rw-r--r-- | persistence/__init__.py | 30 | ||||
| -rw-r--r-- | telegram_bot/__init__.py | 12 | ||||
| -rw-r--r-- | telegram_bot/commands.py | 68 | 
5 files changed, 88 insertions, 30 deletions
| diff --git a/formatter/__init__.py b/formatter/__init__.py index edc1aa9..71ea150 100644 --- a/formatter/__init__.py +++ b/formatter/__init__.py @@ -40,10 +40,11 @@ def format_user(user: User):  def format_user_stats_list(stats: typing.List[UserStats]):      stats_formatted = [__format_stats(single_stats) for single_stats in stats]      return formatting.format_text( +        formatting.mbold('Current Fortnite statistics\n'),          '\n\n'.join(stats_formatted),          separator='\n') -def format_user_stats_difference(old_user_stats: typing.List[UserStats], new_user_stats: typing.List[UserStats]): +def format_user_stats_difference(old_user_stats: typing.List[UserStats], new_user_stats: typing.List[UserStats], timeframe_alias: str):      stats_formatted = []      for stats in old_user_stats: @@ -51,6 +52,7 @@ def format_user_stats_difference(old_user_stats: typing.List[UserStats], new_use          stats_formatted.append(__format_stats_difference(stats, matched))      return formatting.format_text( +        formatting.mbold('Fortnite statistics for last {alias}\n'.format(alias = timeframe_alias)),          '\n\n'.join(stats_formatted),          separator='\n') @@ -35,8 +35,8 @@ record_stats_command = RecordStatsCommand(fortnite_client, stats_repository)  telegram_bot.register_command_handler('start', StartCommand(telegram_bot, user_repository))  telegram_bot.register_command_handler('status', GetStatusCommand(telegram_bot))  telegram_bot.register_command_handler('friends', GetFriendsCommand(telegram_bot, fortnite_client)) -telegram_bot.register_command_handler('stats', GetStatsCommand(telegram_bot, fortnite_client)) -telegram_bot.register_command_handler('todaystats', GetTodayStatsCommand(telegram_bot, fortnite_client, stats_repository)) +telegram_bot.register_command_handler('stats', GetStatsCommand(telegram_bot, fortnite_client, stats_repository)) +telegram_bot.register_command_handler('todaystats', GetTodayStatsCommand(telegram_bot))  telegram_bot.register_command_handler('recordstats', record_stats_command)  async def run_tgbot(): diff --git a/persistence/__init__.py b/persistence/__init__.py index 9d9220e..663522e 100644 --- a/persistence/__init__.py +++ b/persistence/__init__.py @@ -1,5 +1,6 @@  import sqlite3, typing  from app_types import * +from datetime import date  class UserRepository: @@ -17,21 +18,21 @@ class UserRepository:      def get_user(self, chat_id):          connection = self.__get_connection()          cur = connection.cursor() -        query = "select * from user where chat_id = {chat_id}".format(chat_id = chat_id) +        query = "SELECT * FROM user WHERE chat_id = {chat_id}".format(chat_id = chat_id)          cur.execute(query)          return cur.fetchone()      def get_all_users(self):          connection = self.__get_connection()          cur = connection.cursor() -        query = "select * from user" +        query = "SELECT * FROM user"          cur.execute(query)          return cur.fetchall()      def remove_chat(self, chat_id):          connection = self.__get_connection()          cur = connection.cursor() -        query = "DELETE FROM user where chat_id = {chat_id}".format( +        query = "DELETE FROM user WHERE chat_id = {chat_id}".format(              chat_id = chat_id)          cur.execute(query)          connection.commit() @@ -57,16 +58,17 @@ class StatsRepository:      def __initialize(self):          cur = self.__get_connection().cursor() -        cur.execute("CREATE TABLE IF NOT EXISTS stats(user_id TEXT, display_name TEXT, level INT, matches_played INT, kills INT, wins INT)") -        cur.execute("CREATE UNIQUE INDEX IF NOT EXISTS user_id_idx ON stats(user_id)") +        cur.execute("CREATE TABLE IF NOT EXISTS stats(user_id TEXT, stats_date DATE, display_name TEXT, level INT, matches_played INT, kills INT, wins INT)") +        cur.execute("CREATE UNIQUE INDEX IF NOT EXISTS user_id_date_idx ON stats(user_id, stats_date)") -    async def put_stats(self, user: User): +    async def put_stats(self, user: User, stats_date: date = date.today()):          stats: UserStats = await user.fetch_stats()          connection = self.__get_connection()          cur = connection.cursor() -        query = "INSERT OR REPLACE INTO stats(user_id, display_name, level, matches_played, kills, wins) VALUES('{user_id}', '{display_name}', {level}, {matches_played}, {kills}, {wins})".format( +        query = "INSERT OR REPLACE INTO stats(user_id, stats_date, display_name, level, matches_played, kills, wins) VALUES('{user_id}', '{stats_date}', '{display_name}', {level}, {matches_played}, {kills}, {wins})".format(              user_id = user.id, +            stats_date = stats_date,              display_name = user.display_name,              level = stats.level,              matches_played = stats.matches_played, @@ -75,10 +77,10 @@ class StatsRepository:          cur.execute(query)          connection.commit() -    def get_stats(self) -> typing.List[UserStats]: +    def get_stats(self, stats_date: date = date.today()) -> typing.List[UserStats]:          connection = self.__get_connection()          cur = connection.cursor() -        query = "SELECT * FROM stats" +        query = "SELECT * FROM stats WHERE stats_date IN (SELECT MIN(stats_date) FROM stats WHERE stats_date >= '{stats_date}')".format(stats_date = stats_date)          cur.execute(query)          result = cur.fetchall()          return [self.__map_from_db(stats) for stats in result] @@ -86,11 +88,11 @@ class StatsRepository:      def __map_from_db(self, record):          user_stats = UserStats()          user_stats.user_id = str(record[0]) -        user_stats.user_display_name = str(record[1]) -        user_stats.level = int(record[2]) -        user_stats.matches_played = int(record[3]) -        user_stats.kills = int(record[4]) -        user_stats.wins = int(record[5]) +        user_stats.user_display_name = str(record[2]) +        user_stats.level = int(record[3]) +        user_stats.matches_played = int(record[4]) +        user_stats.kills = int(record[5]) +        user_stats.wins = int(record[6])          return user_stats  class PresenceRepository: diff --git a/telegram_bot/__init__.py b/telegram_bot/__init__.py index 5e3d455..0818d67 100644 --- a/telegram_bot/__init__.py +++ b/telegram_bot/__init__.py @@ -10,6 +10,10 @@ class CommandHandler:      async def handle(self, message: telebot.types.Message):          pass +class CallbackQueryHandler: +    async def handle(self, call: telebot.types.CallbackQuery): +        pass +  class TelegramBot:      __bot: AsyncTeleBot      __user_repository: UserRepository @@ -35,6 +39,11 @@ class TelegramBot:              command_handler.handle,               commands=[ command ]) +    def register_callback_query(self, callback_query_handler: CallbackQueryHandler, filter: typing.Callable): +        self.__bot.register_callback_query_handler( +            callback=callback_query_handler.handle, +            func=filter) +          async def send_message_to_all(self, message_text: str):          for user in self.__user_repository.get_all_users():              try: @@ -47,8 +56,9 @@ class TelegramBot:                  if 'bot was kicked from the group chat' in str(error):                      self.__user_repository.remove_chat(user[0]) -    async def reply(self, message, message_text): +    async def reply(self, message, message_text, reply_markup = None):          await self.__bot.reply_to(              message,              message_text, +            reply_markup=reply_markup,              parse_mode='MarkdownV2')
\ No newline at end of file diff --git a/telegram_bot/commands.py b/telegram_bot/commands.py index 1e3295b..a1a2888 100644 --- a/telegram_bot/commands.py +++ b/telegram_bot/commands.py @@ -1,10 +1,16 @@  import telebot +from datetime import date, datetime  from telegram_bot import *  from formatter import *  from persistence import *  from fortnite_client import *  from fortnite_status import * +__stats_now__ = 'stats_now' +__stats_day__ = 'stats_day' +__stats_week__ = 'stats_week' +__stats_month__ = 'stats_month' +  class StartCommand(CommandHandler):      __telegram_bot: TelegramBot @@ -48,39 +54,77 @@ class GetFriendsCommand(CommandHandler):              friends = await self.__fortnite_client.get_friends()              await self.__telegram_bot.reply(message, format_users(friends)) - -class GetStatsCommand(CommandHandler): +class GetStatsCallbackQueryHandler(CallbackQueryHandler):      __telegram_bot: TelegramBot      __fortnite_client: FortniteClient +    __stats_repository: StatsRepository -    def __init__(self, telegram_bot: TelegramBot, fortnite_client: FortniteClient): +    def __init__(self, telegram_bot: TelegramBot, fortnite_client: FortniteClient, stats_repository: StatsRepository):          self.__telegram_bot = telegram_bot          self.__fortnite_client = fortnite_client +        self.__stats_repository = stats_repository -    async def handle(self, message: telebot.types.Message): +    async def handle(self, call: telebot.types.CallbackQuery):          if self.__fortnite_client.is_initialized(): +            if call.data == __stats_now__: +                await self.reply_with_today_stats(call.message) +            elif call.data == __stats_day__: +                await self.reply_with_stats_days_difference(call.message, 1, 'day') +            elif call.data == __stats_week__: +                await self.reply_with_stats_days_difference(call.message, 7, 'week') +            elif call.data == __stats_month__: +                await self.reply_with_stats_days_difference(call.message, 30, 'month') + +    async def reply_with_today_stats(self, message): +        friends = await self.__fortnite_client.get_friends() +        stats = [await friend.fetch_stats() for friend in friends] +        await self.__telegram_bot.reply(message, format_user_stats_list(stats)) +     +    async def reply_with_stats_days_difference(self, message, days: int, timeframe_alias: str): +        stats_date = date.today() - datetime.timedelta(days) +        persisted_stats = self.__stats_repository.get_stats(stats_date) +        if len(persisted_stats) > 0:              friends = await self.__fortnite_client.get_friends() -            stats = [await friend.fetch_stats() for friend in friends] -            await self.__telegram_bot.reply(message, format_user_stats_list(stats)) +            current_stats = [await friend.fetch_stats() for friend in friends] +            await self.__telegram_bot.reply(message, format_user_stats_difference(persisted_stats, current_stats, timeframe_alias)) +        else: +            await self.__telegram_bot.reply(message, 'No stats available yet for selected time period') -class GetTodayStatsCommand(CommandHandler): +class GetStatsCommand(CommandHandler):      __telegram_bot: TelegramBot      __fortnite_client: FortniteClient      __stats_repository: StatsRepository +    __reply_markup: any      def __init__(self, telegram_bot: TelegramBot, fortnite_client: FortniteClient, stats_repository: StatsRepository):          self.__telegram_bot = telegram_bot          self.__fortnite_client = fortnite_client          self.__stats_repository = stats_repository +        self.__reply_markup = telebot.types.InlineKeyboardMarkup() +        self.__reply_markup.add(telebot.types.InlineKeyboardButton('Now', callback_data=__stats_now__)) +        self.__reply_markup.add(telebot.types.InlineKeyboardButton('1 day', callback_data=__stats_day__)) +        self.__reply_markup.add(telebot.types.InlineKeyboardButton('1 week', callback_data=__stats_week__)) +        self.__reply_markup.add(telebot.types.InlineKeyboardButton('1 month', callback_data=__stats_month__)) + +        self.__telegram_bot.register_callback_query( +            GetStatsCallbackQueryHandler(self.__telegram_bot, self.__fortnite_client, self.__stats_repository),  +            lambda call: True) +      async def handle(self, message: telebot.types.Message): -        if self.__fortnite_client.is_initialized(): -            persisted_stats = self.__stats_repository.get_stats() -            friends = await self.__fortnite_client.get_friends() -            current_stats = [await friend.fetch_stats() for friend in friends] -            await self.__telegram_bot.reply(message, format_user_stats_difference(persisted_stats, current_stats)) +        await self.__telegram_bot.reply(message, 'Which statistics would you like to see?', reply_markup=self.__reply_markup) + +class GetTodayStatsCommand(CommandHandler): + +    __telegram_bot: TelegramBot + +    def __init__(self, telegram_bot: TelegramBot): +        self.__telegram_bot = telegram_bot + +    async def handle(self, message: telebot.types.Message): +        await self.__telegram_bot.reply(message, 'Use new command /stats, you must, young Padawan')  class RecordStatsCommand(CommandHandler): | 
