فهرست منبع

Refactor code

Tigran 4 سال پیش
والد
کامیت
97bdad93fa

+ 5 - 13
CardCollector/Commands/CallbackQuery/BackToFiltersMenu.cs

@@ -18,23 +18,15 @@ namespace CardCollector.Commands.CallbackQuery
             var clearChat = CallbackData.Contains(Command.clear_chat);
             if (clearChat) await User.ClearChat();
             /* Формируем сообщение с имеющимися фильтрами у пользователя */
-            var text = $"{Messages.current_filters}\n" +
-                       $"{Messages.author} {(User.Filters[Command.author].Equals("") ? Messages.all : User.Filters[Command.author])}\n" +
-                       $"{Messages.tier} {(User.Filters[Command.tier].Equals(-1) ? Messages.all : new string('⭐', (int) User.Filters[Command.tier]))}\n" +
-                       $"{Messages.emoji} {(User.Filters[Command.emoji].Equals("") ? Messages.all : User.Filters[Command.emoji])}\n";
-            if (User.State != UserState.CollectionMenu) 
-                text += $"{Messages.price} 💰 {User.Filters[Command.price_coins_from]} -" +
-                        $" {(User.Filters[Command.price_coins_to] is int c && c != 0 ? c : "∞")}\n" +
-                        $"{Messages.price} 💎 {User.Filters[Command.price_gems_from]} -" +
-                        $" {(User.Filters[Command.price_gems_to] is int g && g != 0 ? g : "∞")}\n";
-            text += $"{Messages.sorting} {User.Filters[Command.sort]}\n\n{Messages.select_filter}";
+            var text = User.Session.Filters.ToMessage(User.Session.State);
             /* Редактируем сообщение */
             if (!clearChat) 
-                await MessageController.EditMessage(User, CallbackMessageId, text, Keyboard.GetSortingMenu(User.State));
+                await MessageController.EditMessage(User, CallbackMessageId, 
+                    text, Keyboard.GetSortingMenu(User.Session.State));
             else
             {
-                var message = await MessageController.SendMessage(User, text, Keyboard.GetSortingMenu(User.State));
-                User.Messages.Add(message.MessageId);
+                var message = await MessageController.SendMessage(User, text, Keyboard.GetSortingMenu(User.Session.State));
+                User.Session.Messages.Add(message.MessageId);
             }
         }
         

+ 1 - 1
CardCollector/Commands/CallbackQuery/CancelCallback.cs

@@ -10,7 +10,7 @@ namespace CardCollector.Commands.CallbackQuery
         protected override string CommandText => Command.cancel;
         public override async Task Execute()
         {
-            User.State = UserState.Default;
+            User.Session.State = UserState.Default;
             await User.ClearChat();
         }
 

+ 0 - 1
CardCollector/Commands/CallbackQuery/EmojiCallback.cs

@@ -1,5 +1,4 @@
 using System.Threading.Tasks;
-using CardCollector.Commands.Message;
 using CardCollector.Commands.Message.TextMessage;
 using CardCollector.Controllers;
 using CardCollector.DataBase.Entity;

+ 6 - 6
CardCollector/Commands/CallbackQuery/SetFilterCallback.cs

@@ -1,6 +1,5 @@
 using System;
 using System.Threading.Tasks;
-using CardCollector.Commands.Message;
 using CardCollector.Commands.Message.TextMessage;
 using CardCollector.DataBase.Entity;
 using CardCollector.Resources;
@@ -16,13 +15,14 @@ namespace CardCollector.Commands.CallbackQuery
         {
             EnterEmojiMessage.RemoveFromQueue(User.Id);
             var result = CallbackData.Split('=');
+            var filters = User.Session.Filters;
             /* Команду set мы получаем в виде set=<key>=<value>, соответственно аргументы 1 и 2 это ключ и значение словаря */
-            User.Filters[result[1]] = Convert.ChangeType(result[2], User.Filters[result[1]].GetType());
+            filters[result[1]] = Convert.ChangeType(result[2], filters[result[1]].GetType());
             /* Если левая граница стоимости алмазов или монет больше правой, то меняем правую на бесконечность */
-            if (User.Filters[Command.price_coins_to] is int c && c <= (int) User.Filters[Command.price_coins_from])
-                User.Filters[Command.price_coins_to] = 0;
-            if (User.Filters[Command.price_gems_to] is int g && g <= (int) User.Filters[Command.price_gems_from])
-                User.Filters[Command.price_gems_to] = 0;
+            if (filters[Command.price_coins_to] is int c && c <= (int) filters[Command.price_coins_from])
+                filters[Command.price_coins_to] = 0;
+            if (filters[Command.price_gems_to] is int g && g <= (int) filters[Command.price_gems_from])
+                filters[Command.price_gems_to] = 0;
             /* Возвращаемся в меню фильтров */
             await new BackToFiltersMenu(User, Update).Execute();
         }

+ 4 - 5
CardCollector/Commands/ChosenInlineResult/SelectStickerInlineResult.cs

@@ -1,6 +1,5 @@
 using System.Linq;
 using System.Threading.Tasks;
-using CardCollector.Auction;
 using CardCollector.Controllers;
 using CardCollector.DataBase.Entity;
 using CardCollector.DataBase.EntityDao;
@@ -17,7 +16,7 @@ namespace CardCollector.Commands.ChosenInlineResult
             await User.ClearChat();
             var hash = InlineResult.Split('=')[1];
             var sticker = await StickerDao.GetStickerByHash(hash);
-            var stickerCount = User.State switch
+            var stickerCount = User.Session.State switch
             {
                 UserState.AuctionMenu => await AuctionController.GetStickerCount(sticker.Id),
                 UserState.ShopMenu => await ShopController.GetStickerCount(sticker.Id),
@@ -31,9 +30,9 @@ namespace CardCollector.Commands.ChosenInlineResult
                            $"\n{sticker.IncomeCoins}{Text.coin} / {sticker.IncomeGems}{Text.gem} {sticker.IncomeTime}{Text.time}{Text.minutes}";
             if (sticker.Description != "") messageText += $"\n\n{Text.description}: {sticker.Description}";
             var stickerMessage = await MessageController.SendSticker(User, sticker.Id);
-            var infoMessage = await MessageController.SendMessage(User, messageText, Keyboard.GetStickerKeyboard(User.State, sticker.Md5Hash, sticker.Title));
-            User.Messages.Add(stickerMessage.MessageId);
-            User.Messages.Add(infoMessage.MessageId);
+            var infoMessage = await MessageController.SendMessage(User, messageText, Keyboard.GetStickerKeyboard(User, sticker.Md5Hash, sticker.Title));
+            User.Session.Messages.Add(stickerMessage.MessageId);
+            User.Session.Messages.Add(infoMessage.MessageId);
         }
 
         public SelectStickerInlineResult() { }

+ 2 - 2
CardCollector/Commands/Message/DocumentMessage/UploadFileMessage.cs

@@ -24,7 +24,7 @@ namespace CardCollector.Commands.Message.DocumentMessage
         {
             /* Очищаем чат */
             await User.ClearChat();
-            User.State = UserState.Default;
+            User.Session.State = UserState.Default;
             /* Соообщаем, что начали загрузку файла */
             var message = await MessageController.SendMessage(User, Messages.downloading_file);
             /* Загружаем файл */
@@ -180,7 +180,7 @@ namespace CardCollector.Commands.Message.DocumentMessage
         protected internal override bool IsMatches(string command)
         {
             return User != null 
-                ? User.State == UserState.UploadFile
+                ? User.Session.State == UserState.UploadFile
                 : base.IsMatches(command);
         }
 

+ 1 - 1
CardCollector/Commands/Message/TextMessage/AuctionMessage.cs

@@ -14,7 +14,7 @@ namespace CardCollector.Commands.Message.TextMessage
             /* Очищаем чат с пользователем */
             await User.ClearChat();
             /* Переводим состояние пользователя в меню аукциона */
-            User.State = UserState.AuctionMenu;
+            User.Session.State = UserState.AuctionMenu;
             /* Отображаем сообщение с фильтрами */
             await new ShowFiltersMenu(User, Update).Execute();
         }

+ 1 - 1
CardCollector/Commands/Message/TextMessage/CollectionMessage.cs

@@ -14,7 +14,7 @@ namespace CardCollector.Commands.Message.TextMessage
             /* Очищаем чат с пользователем */
             await User.ClearChat();
             /* Переводим состояние пользователя в меню коллекции */
-            User.State = UserState.CollectionMenu;
+            User.Session.State = UserState.CollectionMenu;
             /* Отображаем сообщение с фильтрами */
             await new ShowFiltersMenu(User, Update).Execute();
         }

+ 2 - 2
CardCollector/Commands/Message/TextMessage/DownloadStickerPackMessage.cs

@@ -12,9 +12,9 @@ namespace CardCollector.Commands.Message.TextMessage
         public override async Task Execute()
         {
             await User.ClearChat();
-            User.State = UserState.UploadFile;
+            User.Session.State = UserState.UploadFile;
             var result = await MessageController.SendMessage(User, Messages.upload_file, Keyboard.CancelKeyboard);
-            User.Messages.Add(result.MessageId);
+            User.Session.Messages.Add(result.MessageId);
         }
 
         protected internal override bool IsMatches(string command)

+ 3 - 12
CardCollector/Commands/Message/TextMessage/EnterEmojiMessage.cs

@@ -30,20 +30,11 @@ namespace CardCollector.Commands.Message.TextMessage
                 await MessageController.EditMessage(User, Queue[User.Id], Messages.enter_only_one_emoji, Keyboard.EmojiOptions);
             else
             {
-                User.Filters[Command.emoji] = input;
+                User.Session.Filters[Command.emoji] = input;
                 /* Формируем сообщение с имеющимися фильтрами у пользователя */
-                var text = $"{Messages.current_filters}\n" +
-                           $"{Messages.author} {(User.Filters[Command.author].Equals("") ? Messages.all : User.Filters[Command.author])}\n" +
-                           $"{Messages.tier} {(User.Filters[Command.tier].Equals(-1) ? Messages.all : new string('⭐', (int) User.Filters[Command.tier]))}\n" +
-                           $"{Messages.emoji} {(User.Filters[Command.emoji].Equals("") ? Messages.all : User.Filters[Command.emoji])}\n";
-                if (User.State != UserState.CollectionMenu) 
-                    text += $"{Messages.price} 💰 {User.Filters[Command.price_coins_from]} -" +
-                            $" {(User.Filters[Command.price_coins_to] is int c && c != 0 ? c : "∞")}\n" +
-                            $"{Messages.price} 💎 {User.Filters[Command.price_gems_from]} -" +
-                            $" {(User.Filters[Command.price_gems_to] is int g && g != 0 ? g : "∞")}\n";
-                text += $"{Messages.sorting} {User.Filters[Command.sort]}\n\n{Messages.select_filter}";
+                var text = User.Session.Filters.ToMessage(User.Session.State);
                 /* Редактируем сообщение */
-                await MessageController.EditMessage(User, Queue[User.Id], text, Keyboard.GetSortingMenu(User.State));
+                await MessageController.EditMessage(User, Queue[User.Id], text, Keyboard.GetSortingMenu(User.Session.State));
                 Queue.Remove(User.Id);
             }
         }

+ 1 - 1
CardCollector/Commands/Message/TextMessage/ShopMessage.cs

@@ -14,7 +14,7 @@ namespace CardCollector.Commands.Message.TextMessage
             /* Очищаем чат с пользователем */
             await User.ClearChat();
             /* Переводим состояние пользователя в меню магазина */
-            User.State = UserState.ShopMenu;
+            User.Session.State = UserState.ShopMenu;
             /* Отображаем сообщение с фильтрами */
             await new ShowFiltersMenu(User, Update).Execute();
         }

+ 3 - 12
CardCollector/Commands/Message/TextMessage/ShowFiltersMenu.cs

@@ -13,20 +13,11 @@ namespace CardCollector.Commands.Message.TextMessage
         public override async Task Execute()
         {
             /* Формируем сообщение с имеющимися фильтрами у пользователя */
-            var text = $"{Messages.current_filters}\n" +
-                       $"{Messages.author} {(User.Filters[Command.author].Equals("") ? Messages.all : User.Filters[Command.author])}\n" +
-                       $"{Messages.tier} {(User.Filters[Command.tier].Equals(-1) ? Messages.all : new string('⭐', (int) User.Filters[Command.tier]))}\n" +
-                       $"{Messages.emoji} {(User.Filters[Command.emoji].Equals("") ? Messages.all : User.Filters[Command.emoji])}\n";
-            if (User.State != UserState.CollectionMenu) 
-                text += $"{Messages.price} 💰 {User.Filters[Command.price_coins_from]} -" +
-                        $" {(User.Filters[Command.price_coins_to] is int c && c != 0 ? c : "∞")}\n" +
-                        $"{Messages.price} 💎 {User.Filters[Command.price_gems_from]} -" +
-                        $" {(User.Filters[Command.price_gems_to] is int g && g != 0 ? g : "∞")}\n";
-            text += $"{Messages.sorting} {User.Filters[Command.sort]}\n\n{Messages.select_filter}";
+            var text = User.Session.Filters.ToMessage(User.Session.State);
             /* Отправляем сообщение */
-            var message = await MessageController.SendMessage(User, text, Keyboard.GetSortingMenu(User.State));
+            var message = await MessageController.SendMessage(User, text, Keyboard.GetSortingMenu(User.Session.State));
             /* Добавляем это сообщение в список для удаления */
-            User.Messages.Add(message.MessageId);
+            User.Session.Messages.Add(message.MessageId);
         }
         
         public ShowFiltersMenu(UserEntity user, Update update) : base(user, update) { }

+ 10 - 2
CardCollector/Auction/AuctionController.cs → CardCollector/Controllers/AuctionController.cs

@@ -1,8 +1,10 @@
-using System.Threading.Tasks;
+using System.Collections.Generic;
+using System.Threading.Tasks;
 using CardCollector.DataBase.Entity;
+using CardCollector.DataBase.EntityDao;
 using CardCollector.Resources;
 
-namespace CardCollector.Auction 
+namespace CardCollector.Controllers 
 {
     /* Контроллер аукциона, управляет всеми транзакциями
      между пользователями */
@@ -38,5 +40,11 @@ namespace CardCollector.Auction
             //TODO вернуть количество стикера на аукционе по его id
             return 0;
         }
+
+        public static async Task<List<StickerEntity>> GetStickers(string filter)
+        {
+            //TODO вернуть список стикеров, имеющихся на аукционе
+            return await StickerDao.GetAll(filter);
+        }
     }
 }

+ 10 - 1
CardCollector/Controllers/ShopController.cs

@@ -1,4 +1,7 @@
-using System.Threading.Tasks;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using CardCollector.DataBase.Entity;
+using CardCollector.DataBase.EntityDao;
 
 namespace CardCollector.Controllers
 {
@@ -9,5 +12,11 @@ namespace CardCollector.Controllers
             //TODO вернуть количество стикеров в магазине по id
             return 0;
         }
+        
+        public static async Task<List<StickerEntity>> GetStickers(string filter)
+        {
+            //TODO вернуть список стикеров, имеющихся в магазине
+            return await StickerDao.GetAll(filter);
+        }
     }
 }

+ 15 - 0
CardCollector/DataBase/Entity/ShopEntity.cs

@@ -0,0 +1,15 @@
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+
+namespace CardCollector.DataBase.Entity
+{
+    [Table("shop")]
+    public class ShopEntity
+    {
+        [Key]
+        [Column("id"), MaxLength(32)] public int Id { get; set; }
+        [Column("sticker_id"), MaxLength(127)] public string StickerId { get; set; }
+        [Column("count"), MaxLength(32)] public int Count { get; set; }
+        [Column("is_infinite"), MaxLength(11)] public bool IsInfinite { get; set; }
+    }
+}

+ 39 - 0
CardCollector/DataBase/Entity/UserEntity.Sesion.cs

@@ -0,0 +1,39 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using CardCollector.Controllers;
+using CardCollector.Resources;
+
+namespace CardCollector.DataBase.Entity
+{
+    public partial class UserEntity
+    {
+        public class UserSession
+        {
+            /* Текущее состояние пользователя */
+            public UserState State = UserState.Default;
+
+            /* Фильтры, примененные пользователем в меню коллекции/магазина/аукциона */
+            public readonly Dictionary<string, object> Filters = new()
+            {
+                {Command.author, ""},
+                {Command.tier, -1},
+                {Command.emoji, ""},
+                {Command.price_coins_from, 0},
+                {Command.price_coins_to, 0},
+                {Command.price_gems_from, 0},
+                {Command.price_gems_to, 0},
+                {Command.sort, SortingTypes.None},
+            };
+            
+            /* Сообщения в чате пользователя */
+            public readonly List<int> Messages = new();
+
+            public async Task ClearMessages(UserEntity user)
+            {
+                foreach (var messageId in Messages)
+                    await MessageController.DeleteMessage(user, messageId);
+                Messages.Clear();
+            }
+        }
+    }
+}

+ 13 - 117
CardCollector/DataBase/Entity/UserEntity.cs

@@ -1,8 +1,6 @@
-using System;
 using System.Collections.Generic;
 using System.ComponentModel.DataAnnotations;
 using System.ComponentModel.DataAnnotations.Schema;
-using System.Linq;
 using System.Threading.Tasks;
 using CardCollector.Controllers;
 using CardCollector.DataBase.EntityDao;
@@ -13,7 +11,7 @@ namespace CardCollector.DataBase.Entity
 {
     /* Этот класс представляет собой строку таблицы users и описывает объект пользователя */
     [Table("users")]
-    public class UserEntity
+    public partial class UserEntity
     {
         /* Id пользователя */
         [Key]
@@ -38,134 +36,32 @@ namespace CardCollector.DataBase.Entity
         
         /* Стикеры пользователя */
         [NotMapped] public Dictionary<string, UserStickerRelationEntity> Stickers { get; set; }
-
-        /* Текущее состояние пользователя */
-        [NotMapped] public UserState State = UserState.Default;
-
-        /* Фильтры, примененные пользователем в меню коллекции/магазина/аукциона */
-        [NotMapped] public readonly Dictionary<string, object> Filters = new()
-        {
-            {Command.author, ""},
-            {Command.tier, -1},
-            {Command.emoji, ""},
-            {Command.price_coins_from, 0},
-            {Command.price_coins_to, 0},
-            {Command.price_gems_from, 0},
-            {Command.price_gems_to, 0},
-            {Command.sort, SortingTypes.None},
-        };
-
-        /* Сообщения в чате пользователя */
-        [NotMapped] public readonly List<int> Messages = new();
+        
+        /* Данные, хранящиеся в рамках одной сессии */
+        [NotMapped] public readonly UserSession Session = new ();
 
         /* Удаляет из чата все сообщения, добавленные в список выше */
         public async Task ClearChat()
         {
-            foreach (var messageId in Messages)
-                await MessageController.DeleteMessage(this, messageId);
-            Messages.Clear();
+            await Session.ClearMessages(this);
         }
         
         /* Возвращает стикеры в виде объектов телеграм */
         public async Task<IEnumerable<InlineQueryResult>> GetStickersList(string command, string filter, bool userFilterEnabled = false)
         {
+            var state = Session.State;
             /* Получаем список стикеров исходя из того, нужно ли для отладки получить бесконечные стикеры */
             var stickersList = Constants.UNLIMITED_ALL_STICKERS
-                ? await GetUnlimitedStickers(filter)
-                : State switch
+                ? await StickerDao.GetAll(filter) : state switch
                 {
-                    UserState.CollectionMenu => await GetUserStickers(filter),
-                    UserState.AuctionMenu => await GetAuctionStickers(filter),
-                    UserState.ShopMenu => await GetShopStickers(filter),
-                    _ => await GetUserStickers(filter)
+                    UserState.AuctionMenu => await AuctionController.GetStickers(filter),
+                    UserState.ShopMenu => await ShopController.GetStickers(filter),
+                    _ => await Stickers.ToStickers(filter),
                 };
             /* Если пользовательская сортировка не применена, то возвращаем реультат */
-            if (!userFilterEnabled || State == UserState.Default) return ToTelegramResults(stickersList, command);
-            /* Фильтруем по автору */
-            if (Filters[Command.author] is not "")
-                stickersList = stickersList.Where(item => item.Author.Contains((string) Filters[Command.author]));
-            /* Фильтруем по тиру */
-            if (Filters[Command.tier] is not -1)
-                stickersList = stickersList.Where(item => item.Tier.Equals((int) Filters[Command.tier]));
-            /* Фильтруем по эмоции */
-            if (Filters[Command.emoji] is not "")
-                stickersList = stickersList.Where(item => item.Emoji.Contains((string) Filters[Command.emoji]));
-            /* Фильтруем по цене монет ОТ если пользователь не в меню коллекции */
-            if (Filters[Command.price_coins_from] is not 0 && State is not UserState.CollectionMenu)
-                stickersList = stickersList.Where(item => item.PriceCoins >= (int)Filters[Command.price_coins_from]);
-            /* Фильтруем по цене монет ДО если пользователь не в меню коллекции */
-            if (Filters[Command.price_coins_to] is not 0 && State is not UserState.CollectionMenu)
-                stickersList = stickersList.Where(item => item.PriceCoins <= (int)Filters[Command.price_coins_to]);
-            /* Фильтруем по цене алмазов ОТ если пользователь не в меню коллекции */
-            if (Filters[Command.price_gems_from] is not 0 && State is not UserState.CollectionMenu)
-                stickersList = stickersList.Where(item => item.PriceGems >= (int)Filters[Command.price_gems_from]);
-            /* Фильтруем по цене адмазов ДО если пользователь не в меню коллекции */
-            if (Filters[Command.price_gems_to] is not 0 && State is not UserState.CollectionMenu)
-                stickersList = stickersList.Where(item => item.PriceGems <= (int)Filters[Command.price_gems_to]);
-            /* Если не установлена сортировка, возвращаем результат */
-            if ((string) Filters[Command.sort] == SortingTypes.None) return ToTelegramResults(stickersList, command);
-            
-            /* Сортируем список, если тип сортировки установлен */
-            /* Сортируем по автору */
-            if ((string) Filters[Command.sort] == SortingTypes.ByAuthor)
-                stickersList = stickersList.OrderBy(item => item.Author);
-            /* Сортируем по названию */
-            if ((string) Filters[Command.sort] == SortingTypes.ByTitle)
-                stickersList = stickersList.OrderBy(item => item.Title);
-            /* Сортируем по увеличению тира */
-            if ((string) Filters[Command.sort] == SortingTypes.ByTierIncrease)
-                stickersList = stickersList.OrderBy(item => item.Tier);
-            /* Сортируем по уменьшению тира */
-            if ((string) Filters[Command.sort] == SortingTypes.ByTierDecrease)
-                stickersList = stickersList.OrderByDescending(item => item.Tier);
-            
-            return ToTelegramResults(stickersList, command);
-        }
-
-        private static async Task<IEnumerable<StickerEntity>> GetShopStickers(string filter)
-        {
-            // TODO return shop stickers
-            return await GetUnlimitedStickers(filter);
-        }
-
-        private static async Task<IEnumerable<StickerEntity>> GetAuctionStickers(string filter)
-        {
-            // TODO return auction stickers
-            return await GetUnlimitedStickers(filter);
-        }
-
-        /* Возвращает все стикеры системы */
-        private static async Task<IEnumerable<StickerEntity>> GetUnlimitedStickers(string filter)
-        {
-            return (await StickerDao.GetAll())
-                .Where(item => item.Title.Contains(filter, StringComparison.OrdinalIgnoreCase));
-        }
-
-        /* Возвращает все стикеры системы */
-        private async Task<IEnumerable<StickerEntity>> GetUserStickers(string filter)
-        {
-            var result = new List<StickerEntity>();
-            foreach (var relation in Stickers.Values.Where(i => i.Count > 0))
-            {
-                var sticker = await StickerDao.GetStickerByHash(relation.StickerId);
-                if (sticker.Title.Contains(filter, StringComparison.OrdinalIgnoreCase)) result.Add(sticker);
-            }
-            return result;
-        }
-
-        /* Преобразует список стикеров в список результатов для телеграм */
-        private static IEnumerable<InlineQueryResult> ToTelegramResults(IEnumerable<StickerEntity> list, string command)
-        {
-            var result = new List<InlineQueryResult>();
-            foreach (var item in list)
-            {
-                result.Add(new InlineQueryResultCachedSticker(
-                        $"{(Constants.UNLIMITED_ALL_STICKERS ? Command.unlimited_stickers : "")}{command}={item.Md5Hash}",
-                        item.Id));
-                /* Ограничение Telegram API по количеству результатов в 50 шт. */
-                if (result.Count > 49) return result;
-            }
-            return result;
+            if (!userFilterEnabled || state == UserState.Default) 
+                return stickersList.ToTelegramResults(command);
+            return Session.Filters.ApplyTo(stickersList, state).ToTelegramResults(command);
         }
     }
 }

+ 6 - 3
CardCollector/DataBase/EntityDao/StickerDao.cs

@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
 using System.Linq;
 using System.Threading.Tasks;
 using CardCollector.DataBase.Entity;
@@ -50,9 +51,11 @@ namespace CardCollector.DataBase.EntityDao
                 .ToListAsync();
         }
 
-        public static async Task<List<StickerEntity>> GetAll()
+        public static async Task<List<StickerEntity>> GetAll(string filter = "")
         {
-            return await Table.ToListAsync();
+            var list = await Table.ToListAsync();
+            return filter == "" ? list : list.Where
+                (item => item.Title.Contains(filter, StringComparison.OrdinalIgnoreCase)).ToList();
         }
 
         public static async Task AddNew(StickerEntity sticker)

+ 104 - 0
CardCollector/Extensions.cs

@@ -0,0 +1,104 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using CardCollector.DataBase.Entity;
+using CardCollector.DataBase.EntityDao;
+using CardCollector.Resources;
+using Telegram.Bot.Types.InlineQueryResults;
+
+namespace CardCollector
+{
+    public static class Extensions
+    {
+        /* Преобразует список стикеров в список результатов для телеграм */
+        public static IEnumerable<InlineQueryResult> ToTelegramResults
+            (this IEnumerable<StickerEntity> list, string command)
+        {
+            var result = new List<InlineQueryResult>();
+            foreach (var item in list)
+            {
+                result.Add(new InlineQueryResultCachedSticker(
+                    $"{(Constants.UNLIMITED_ALL_STICKERS ? Command.unlimited_stickers : "")}{command}={item.Md5Hash}",
+                    item.Id));
+                /* Ограничение Telegram API по количеству результатов в 50 шт. */
+                if (result.Count > 49) return result;
+            }
+            return result;
+        }
+        
+        /* Возвращает все стикеры системы */
+        public static async Task<IEnumerable<StickerEntity>> ToStickers
+            (this Dictionary<string, UserStickerRelationEntity> dict, string filter)
+        {
+            var result = new List<StickerEntity>();
+            foreach (var relation in dict.Values.Where(i => i.Count > 0))
+            {
+                var sticker = await StickerDao.GetStickerByHash(relation.StickerId);
+                if (sticker.Title.Contains(filter, StringComparison.OrdinalIgnoreCase)) result.Add(sticker);
+            }
+            return result;
+        }
+
+        public static IEnumerable<StickerEntity> ApplyTo (this Dictionary<string, object> dict, 
+            IEnumerable<StickerEntity> list, UserState state)
+        {
+            /* Фильтруем по автору */
+            if (dict[Command.author] is string author && author != "")
+                list = list.Where(item => item.Author.Contains(author));
+            /* Фильтруем по тиру */
+            if (dict[Command.tier] is int tier && tier != -1)
+                list = list.Where(item => item.Tier.Equals(tier));
+            /* Фильтруем по эмоции */
+            if (dict[Command.emoji] is string emoji && emoji != "")
+                list = list.Where(item => item.Emoji.Contains(emoji));
+            /* Если пользвователь не находится в меню коллекции, то фильтруем по цене */
+            if (state is not UserState.CollectionMenu){
+                /* Фильтруем по цене монет ОТ */
+                if (dict[Command.price_coins_from] is int PCF && PCF != 0)
+                    list = list.Where(item => item.PriceCoins >= PCF);
+                /* Фильтруем по цене монет ДО */
+                if (dict[Command.price_coins_to] is int PCT && PCT != 0)
+                    list = list.Where(item => item.PriceCoins <= PCT);
+                /* Фильтруем по цене алмазов ОТ */
+                if (dict[Command.price_gems_from] is int PGF && PGF != 0)
+                    list = list.Where(item => item.PriceGems >= PGF);
+                /* Фильтруем по цене адмазов ДО */
+                if (dict[Command.price_gems_to] is int PGT && PGT != 0)
+                    list = list.Where(item => item.PriceGems <= PGT);
+            }
+            /* Сортируем список, если тип сортировки установлен */
+            if (dict[Command.sort] is not string sort || sort == SortingTypes.None) return list;
+            {
+                /* Сортируем по автору */
+                if (sort== SortingTypes.ByAuthor)
+                    list = list.OrderBy(item => item.Author);
+                /* Сортируем по названию */
+                if (sort == SortingTypes.ByTitle)
+                    list = list.OrderBy(item => item.Title);
+                /* Сортируем по увеличению тира */
+                if (sort == SortingTypes.ByTierIncrease)
+                    list = list.OrderBy(item => item.Tier);
+                /* Сортируем по уменьшению тира */
+                if (sort == SortingTypes.ByTierDecrease)
+                    list = list.OrderByDescending(item => item.Tier);
+            }
+            return list;
+        }
+        
+        public static string ToMessage(this Dictionary<string, object> dict, UserState state)
+        {
+            var text = $"{Messages.current_filters}\n" +
+                       $"{Messages.author} {(dict[Command.author] is string author and not "" ? author : Messages.all)}\n" +
+                       $"{Messages.tier} {(dict[Command.tier] is int tier and not -1 ? new string('⭐', tier) : Messages.all)}\n" +
+                       $"{Messages.emoji} {(dict[Command.emoji] is string emoji and not "" ? emoji : Messages.all)}\n";
+            if (state != UserState.CollectionMenu) 
+                text += $"{Messages.price} 💰 {dict[Command.price_coins_from]} -" +
+                        $" {(dict[Command.price_coins_to] is int c and not 0 ? c : "∞")}\n" +
+                        $"{Messages.price} 💎 {dict[Command.price_gems_from]} -" +
+                        $" {(dict[Command.price_gems_to] is int g and not 0 ? g : "∞")}\n";
+            text += $"{Messages.sorting} {dict[Command.sort]}\n\n{Messages.select_filter}";
+            return text;
+        }
+    }
+}

+ 9 - 3
CardCollector/Resources/Keyboard.cs

@@ -1,5 +1,6 @@
 using System.Collections.Generic;
 using System.Linq;
+using CardCollector.DataBase.Entity;
 using Telegram.Bot.Types.ReplyMarkups;
 
 namespace CardCollector.Resources
@@ -177,12 +178,17 @@ namespace CardCollector.Resources
             return new InlineKeyboardMarkup(keyboardList);
         }
 
-        public static InlineKeyboardMarkup GetStickerKeyboard(UserState state, string hash, string query)
+        public static InlineKeyboardMarkup GetStickerKeyboard(UserEntity user, string hash, string query)
         {
-            return state switch
+            return user.Session.State switch
             {
                 UserState.AuctionMenu or UserState.ShopMenu => new InlineKeyboardMarkup(new[] {
-                    new[] {InlineKeyboardButton.WithCallbackData(Text.buy, $"{Command.buy_sticker}={hash}")},
+                    new[]
+                    {
+                        InlineKeyboardButton.WithCallbackData(Text.buy, $"{Command.buy_sticker}={hash}"),
+                        InlineKeyboardButton.WithCallbackData(Text.buy, $"{Command.buy_sticker}={hash}"),
+                        InlineKeyboardButton.WithCallbackData(Text.buy, $"{Command.buy_sticker}={hash}"),
+                    },
                     new[] {InlineKeyboardButton.WithCallbackData(Text.back, $"{Command.back}={Command.clear_chat}")},
                 }),
                 UserState.CollectionMenu => new InlineKeyboardMarkup(new[] {