浏览代码

Shop menu complete

Tigran 4 年之前
父节点
当前提交
55a9632df6
共有 32 个文件被更改,包括 442 次插入49 次删除
  1. 1 0
      CardCollector/Commands/CallbackQuery/BackToFiltersMenu.cs
  2. 43 0
      CardCollector/Commands/CallbackQuery/BuyStickerQuery.cs
  3. 2 0
      CardCollector/Commands/CallbackQuery/CallbackQuery.cs
  4. 3 3
      CardCollector/Commands/CallbackQuery/CountQuery.cs
  5. 2 2
      CardCollector/Commands/ChosenInlineResult/SelectStickerInlineResult.cs
  6. 8 0
      CardCollector/Commands/InlineQuery/InlineQuery.cs
  7. 35 0
      CardCollector/Commands/InlineQuery/ShowAuctionStickers.cs
  8. 36 0
      CardCollector/Commands/InlineQuery/ShowCollectionStickers.cs
  9. 35 0
      CardCollector/Commands/InlineQuery/ShowShopStickers.cs
  10. 7 4
      CardCollector/Commands/InlineQuery/ShowStickersInBotChat.cs
  11. 4 4
      CardCollector/Commands/InlineQuery/ShowStickersInGroup.cs
  12. 36 0
      CardCollector/Commands/InlineQuery/ShowTradersInBotChat.cs
  13. 19 4
      CardCollector/Controllers/AuctionController.cs
  14. 4 3
      CardCollector/Controllers/MessageController.cs
  15. 5 4
      CardCollector/DataBase/Entity/AuctionEntity.cs
  16. 7 16
      CardCollector/DataBase/Entity/UserEntity.cs
  17. 9 0
      CardCollector/DataBase/EntityDao/AuctionDao.cs
  18. 2 1
      CardCollector/DataBase/EntityDao/ShopDao.cs
  19. 7 0
      CardCollector/DataBase/EntityDao/UserDao.cs
  20. 1 1
      CardCollector/DataBase/EntityDao/UserStickerRelationDao.cs
  21. 16 0
      CardCollector/Extensions.cs
  22. 18 1
      CardCollector/Others/Session.cs
  23. 1 1
      CardCollector/Others/StickerInfo.cs
  24. 19 0
      CardCollector/Others/TraderInformation.cs
  25. 27 0
      CardCollector/Resources/Command.Designer.cs
  26. 9 0
      CardCollector/Resources/Command.resx
  27. 1 1
      CardCollector/Resources/Constants.cs
  28. 13 4
      CardCollector/Resources/Keyboard.cs
  29. 27 0
      CardCollector/Resources/Messages.Designer.cs
  30. 9 0
      CardCollector/Resources/Messages.resx
  31. 27 0
      CardCollector/Resources/Text.Designer.cs
  32. 9 0
      CardCollector/Resources/Text.resx

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

@@ -14,6 +14,7 @@ namespace CardCollector.Commands.CallbackQuery
         {
             /* Удаляем пользователя из очереди */
             EnterEmojiMessage.RemoveFromQueue(User.Id);
+            User.Session.SelectedSticker = null;
             /* Очищаем чат, если был передан параметр очистки */
             var clearChat = CallbackData.Contains(Command.clear_chat);
             if (clearChat) await User.ClearChat();

+ 43 - 0
CardCollector/Commands/CallbackQuery/BuyStickerQuery.cs

@@ -0,0 +1,43 @@
+using System.Threading.Tasks;
+using CardCollector.Controllers;
+using CardCollector.DataBase.Entity;
+using CardCollector.DataBase.EntityDao;
+using CardCollector.Resources;
+using Telegram.Bot.Types;
+
+namespace CardCollector.Commands.CallbackQuery
+{
+    public class BuyStickerQuery : CallbackQuery
+    {
+        protected override string CommandText => Command.buy_sticker;
+        public override async Task Execute()
+        {
+            var selectedSticker = User.Session.SelectedSticker;
+            var product = await ShopDao.GetSticker(selectedSticker.Id);
+            if (selectedSticker.Count > product.Count && !product.IsInfinite)
+                await MessageController.AnswerCallbackQuery(User, Update.CallbackQuery!.Id, Messages.not_enougth_stickers);
+            else if (selectedSticker.Count * selectedSticker.PriceCoins > User.Cash.Coins)
+                await MessageController.AnswerCallbackQuery(User, Update.CallbackQuery!.Id, Messages.not_enougth_coins);
+            else if (selectedSticker.Count * selectedSticker.PriceGems > User.Cash.Gems)
+                await MessageController.AnswerCallbackQuery(User, Update.CallbackQuery!.Id, Messages.not_enougth_gems);
+            else
+            {
+                if (!product.IsInfinite) product.Count -= selectedSticker.Count;
+                if (User.Stickers.ContainsKey(selectedSticker.Md5Hash))
+                {
+                    await User.Session.PayOutOne(selectedSticker.Md5Hash);
+                    await MessageController.AnswerCallbackQuery(User, Update.CallbackQuery!.Id, 
+                        $"{Messages.you_collected} {User.Session.IncomeCoins}{Text.coin}/{User.Session.IncomeGems}{Text.gem}");
+                }
+                await UserStickerRelationDao.AddNew(User, selectedSticker, selectedSticker.Count);
+                User.Cash.Coins -= selectedSticker.Count * selectedSticker.PriceCoins;
+                User.Cash.Gems -= selectedSticker.Count * selectedSticker.PriceGems;
+                User.Session.SelectedSticker = null;
+                await User.ClearChat();
+            }
+        }
+
+        public BuyStickerQuery() { }
+        public BuyStickerQuery(UserEntity user, Update update) : base(user, update) { }
+    }
+}

+ 2 - 0
CardCollector/Commands/CallbackQuery/CallbackQuery.cs

@@ -46,6 +46,8 @@ namespace CardCollector.Commands.CallbackQuery
             new CollectIncomeQuery(),
             /* Команда для упралвения количеством стикеров */
             new CountQuery(),
+            /* Команда для покупки стикера */
+            new BuyStickerQuery(),
             
             /* Отмена в момент выбора "значения фильтра", не в самом меню */
             new BackToFiltersMenu(),

+ 3 - 3
CardCollector/Commands/CallbackQuery/CountQuery.cs

@@ -11,7 +11,7 @@ namespace CardCollector.Commands.CallbackQuery
         protected override string CommandText => Command.count;
         public override async Task Execute()
         {
-            var buyPositionCount = User.Session.SelectedSticker.count;
+            var buyPositionCount = User.Session.SelectedSticker.Count;
             var stickerCount = User.Session.State switch
             {
                 UserState.CollectionMenu => User.Stickers[User.Session.SelectedSticker.Md5Hash].Count,
@@ -25,7 +25,7 @@ namespace CardCollector.Commands.CallbackQuery
             {
                 if (buyPositionCount < stickerCount || stickerCount == -1)
                 {
-                    User.Session.SelectedSticker.count++;
+                    User.Session.SelectedSticker.Count++;
                     await MessageController.EditReplyMarkup(User, CallbackMessageId,
                         Keyboard.GetStickerKeyboard(User.Session.SelectedSticker, User.Session.State));
                 }
@@ -36,7 +36,7 @@ namespace CardCollector.Commands.CallbackQuery
             {
                 if (buyPositionCount > 1)
                 {
-                    User.Session.SelectedSticker.count--;
+                    User.Session.SelectedSticker.Count--;
                     await MessageController.EditReplyMarkup(User, CallbackMessageId,
                         Keyboard.GetStickerKeyboard(User.Session.SelectedSticker, User.Session.State));
                 }

+ 2 - 2
CardCollector/Commands/ChosenInlineResult/SelectStickerInlineResult.cs

@@ -27,11 +27,11 @@ namespace CardCollector.Commands.ChosenInlineResult
             messageText += $"\n<<{sticker.Title}>>" +
                            $"\n{Text.emoji}: {sticker.Emoji}" +
                            $"\n{Text.author}: {sticker.Author}" +
-                           $"\n{Text.count}: {stickerCount}" +
+                           $"\n{Text.count}: {(stickerCount != -1 ? stickerCount : "∞")}" +
                            $"\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 stickerInfo = new StickerInfo(sticker) {count = 1};
+            var stickerInfo = new StickerInfo(sticker) {Count = 1};
             User.Session.SelectedSticker = stickerInfo;
             var infoMessage = await MessageController.SendMessage(User, messageText, Keyboard.GetStickerKeyboard(stickerInfo, User.Session.State));
             User.Session.Messages.Add(stickerMessage.MessageId);

+ 8 - 0
CardCollector/Commands/InlineQuery/InlineQuery.cs

@@ -28,6 +28,14 @@ namespace CardCollector.Commands.InlineQuery
         {
             // Показать стикеры в чатах для отправки (кроме личного чата с ботом)
             new ShowStickersInGroup(),
+            // Показать стикеры на аукционе
+            new ShowAuctionStickers(),
+            // Показать стикеры в коллекции
+            new ShowCollectionStickers(),
+            // Показать стикеры в магазине
+            new ShowShopStickers(),
+            // Показать список продавцов
+            new ShowTradersInBotChat(),
             // Показать стикеры в личных сообщениях с ботом для выбора или просмотра информации
             new ShowStickersInBotChat(),
         };

+ 35 - 0
CardCollector/Commands/InlineQuery/ShowAuctionStickers.cs

@@ -0,0 +1,35 @@
+using System.Threading.Tasks;
+using CardCollector.Controllers;
+using CardCollector.DataBase.Entity;
+using CardCollector.Resources;
+using Telegram.Bot.Types;
+
+namespace CardCollector.Commands.InlineQuery
+{
+    public class ShowAuctionStickers : InlineQuery
+    {
+        protected override string CommandText => "";
+        public override async Task Execute()
+        {
+            // Фильтр - введенная пользователем фраза
+            var filter = Update.InlineQuery!.Query;
+            // Получаем список стикеров
+            var stickersList = await AuctionController.GetStickers(filter);
+            var results = User.Session.Filters.ApplyTo(stickersList, User.Session.State).ToTelegramResults(Command.select_sticker);
+            // Посылаем пользователю ответ на его запрос
+            await MessageController.AnswerInlineQuery(InlineQueryId, results);
+        }
+        
+        /* Команда пользователя удовлетворяет условию, если она вызвана
+         в личных сообщениях с ботом и пользователь в меню аукциона и он не выбрал стикер */
+        protected internal override bool IsMatches(string command)
+        {
+            return User == null 
+                ? command.Contains("Sender")
+                : User.Session.State == UserState.AuctionMenu && User.Session.SelectedSticker == null;
+        }
+
+        public ShowAuctionStickers() { }
+        public ShowAuctionStickers(UserEntity user, Update update, string inlineQueryId) : base(user, update, inlineQueryId) { }
+    }
+}

+ 36 - 0
CardCollector/Commands/InlineQuery/ShowCollectionStickers.cs

@@ -0,0 +1,36 @@
+using System.Linq;
+using System.Threading.Tasks;
+using CardCollector.Controllers;
+using CardCollector.DataBase.Entity;
+using CardCollector.Resources;
+using Telegram.Bot.Types;
+
+namespace CardCollector.Commands.InlineQuery
+{
+    public class ShowCollectionStickers : InlineQuery
+    {
+        protected override string CommandText => "";
+        public override async Task Execute()
+        {
+            // Фильтр - введенная пользователем фраза
+            var filter = Update.InlineQuery!.Query;
+            // Получаем список стикеров
+            var stickersList = await User.GetStickersList(filter);
+            var results = User.Session.Filters.ApplyTo(stickersList, User.Session.State).ToTelegramResults(Command.select_sticker);
+            // Посылаем пользователю ответ на его запрос
+            await MessageController.AnswerInlineQuery(InlineQueryId, results);
+        }
+        
+        /* Команда пользователя удовлетворяет условию, если она вызвана
+         в личных сообщениях с ботом и пользователь в меню коллекции */
+        protected internal override bool IsMatches(string command)
+        {
+            return User == null 
+                ? command.Contains("Sender")
+                : User.Session.State == UserState.CollectionMenu;
+        }
+
+        public ShowCollectionStickers() { }
+        public ShowCollectionStickers(UserEntity user, Update update, string inlineQueryId) : base(user, update, inlineQueryId) { }
+    }
+}

+ 35 - 0
CardCollector/Commands/InlineQuery/ShowShopStickers.cs

@@ -0,0 +1,35 @@
+using System.Threading.Tasks;
+using CardCollector.Controllers;
+using CardCollector.DataBase.Entity;
+using CardCollector.Resources;
+using Telegram.Bot.Types;
+
+namespace CardCollector.Commands.InlineQuery
+{
+    public class ShowShopStickers : InlineQuery
+    {
+        protected override string CommandText => "";
+        public override async Task Execute()
+        {
+            // Фильтр - введенная пользователем фраза
+            var filter = Update.InlineQuery!.Query;
+            // Получаем список стикеров
+            var stickersList = await ShopController.GetStickers(filter);
+            var results = User.Session.Filters.ApplyTo(stickersList, User.Session.State).ToTelegramResults(Command.select_sticker);
+            // Посылаем пользователю ответ на его запрос
+            await MessageController.AnswerInlineQuery(InlineQueryId, results);
+        }
+        
+        /* Команда пользователя удовлетворяет условию, если она вызвана
+         в личных сообщениях с ботом и пользователь в меню магазина */
+        protected internal override bool IsMatches(string command)
+        {
+            return User == null 
+                ? command.Contains("Sender")
+                : User.Session.State == UserState.ShopMenu;
+        }
+
+        public ShowShopStickers() { }
+        public ShowShopStickers(UserEntity user, Update update, string inlineQueryId) : base(user, update, inlineQueryId) { }
+    }
+}

+ 7 - 4
CardCollector/Commands/InlineQuery/ShowStickersInBotChat.cs

@@ -18,16 +18,19 @@ namespace CardCollector.Commands.InlineQuery
             // Фильтр - введенная пользователем фраза
             var filter = Update.InlineQuery!.Query;
             // Получаем список стикеров
-            var stickersList = await User.GetStickersList(Command.select_sticker, filter, true);
+            var stickersList = await User.GetStickersList(filter);
+            var results = stickersList.ToTelegramResults(Command.send_sticker);
             // Посылаем пользователю ответ на его запрос
-            await MessageController.AnswerInlineQuery(InlineQueryId, stickersList);
+            await MessageController.AnswerInlineQuery(InlineQueryId, results);
         }
 
         /* Команда пользователя удовлетворяет условию, если она вызвана
-         в личных сообщениях с ботом */
+         в личных сообщениях с ботом и у пользователя нет выбранного стикера */
         protected internal override bool IsMatches(string command)
         {
-            return command.Contains("Sender");
+            return User == null 
+                ? command.Contains("Sender")
+                : User.Session.State == UserState.Default && User.Session.SelectedSticker == null;
         }
 
         public ShowStickersInBotChat() { }

+ 4 - 4
CardCollector/Commands/InlineQuery/ShowStickersInGroup.cs

@@ -18,9 +18,10 @@ namespace CardCollector.Commands.InlineQuery
             // Фильтр - введенная пользователем фраза
             var filter = Update.InlineQuery!.Query;
             // Получаем список стикеров
-            var stickersList = await User.GetStickersList(Command.send_sticker, filter);
+            var stickersList = await User.GetStickersList(filter);
+            var results = stickersList.ToTelegramResults(Command.send_sticker);
             // Посылаем пользователю ответ на его запрос
-            await MessageController.AnswerInlineQuery(InlineQueryId, stickersList);
+            await MessageController.AnswerInlineQuery(InlineQueryId, results);
         }
 
         /* Команда пользователя удовлетворяет условию, если она вызвана
@@ -30,8 +31,7 @@ namespace CardCollector.Commands.InlineQuery
             return command.Contains("Group") || command.Contains("Supergroup") || command.Contains("Private");
         }
 
-        public ShowStickersInGroup(UserEntity user, Update update, string inlineQueryId)
-            : base(user, update, inlineQueryId) { }
         public ShowStickersInGroup() { }
+        public ShowStickersInGroup(UserEntity user, Update update, string inlineQueryId) : base(user, update, inlineQueryId) { }
     }
 }

+ 36 - 0
CardCollector/Commands/InlineQuery/ShowTradersInBotChat.cs

@@ -0,0 +1,36 @@
+using System.Linq;
+using System.Threading.Tasks;
+using CardCollector.Controllers;
+using CardCollector.DataBase.Entity;
+using CardCollector.Resources;
+using Telegram.Bot.Types;
+
+namespace CardCollector.Commands.InlineQuery
+{
+    public class ShowTradersInBotChat : InlineQuery
+    {
+        protected override string CommandText => "";
+        public override async Task Execute()
+        {
+            // Фильтр - введенная пользователем фраза
+            var filter = Update.InlineQuery!.Query;
+            // Получаем список продавцов
+            var traders = await AuctionController.GetTradersList(filter, User.Session.SelectedSticker.Id);
+            var results = traders.ToTelegramResults(Command.buy_sticker);
+            // Посылаем пользователю ответ на его запрос
+            await MessageController.AnswerInlineQuery(InlineQueryId, results);
+        }
+        
+        /* Команда пользователя удовлетворяет условию, если она вызвана
+         в личных сообщениях с ботом и пользователь выбрал стикер в меню аукциона */
+        protected internal override bool IsMatches(string command)
+        {
+            return User == null 
+                ? command.Contains("Sender")
+                : User.Session.SelectedSticker != null && User.Session.State == UserState.AuctionMenu;
+        }
+
+        public ShowTradersInBotChat() { }
+        public ShowTradersInBotChat(UserEntity user, Update update, string inlineQueryId) : base(user, update, inlineQueryId) { }
+    }
+}

+ 19 - 4
CardCollector/Controllers/AuctionController.cs

@@ -1,8 +1,11 @@
 using System.Collections.Generic;
+using System.Linq;
 using System.Threading.Tasks;
 using CardCollector.DataBase.Entity;
 using CardCollector.DataBase.EntityDao;
+using CardCollector.Others;
 using CardCollector.Resources;
+using Telegram.Bot.Types.InlineQueryResults;
 
 namespace CardCollector.Controllers 
 {
@@ -24,14 +27,14 @@ namespace CardCollector.Controllers
              так что можно не передавать хеш код  и количество */
             //подтверждаем действие
             var hash = user.Session.SelectedSticker.Md5Hash;
-            user.Stickers[hash].Count -= user.Session.SelectedSticker.count;
+            user.Stickers[hash].Count -= user.Session.SelectedSticker.Count;
             /* Пока не думаю, что стоит сразу начислять сумму, пускай останется на будущее
             user.Cash.Coins += price * count;*/
             var product = new AuctionEntity
             {
                 PriceCoins = priceCoins,
                 PriceGems = priceGems,
-                Quantity = user.Session.SelectedSticker.count,
+                Quantity = user.Session.SelectedSticker.Count,
                 StickerId = user.Session.SelectedSticker.Id,
                 Trader = user.Id
             };
@@ -57,8 +60,20 @@ namespace CardCollector.Controllers
 
         public static async Task<List<StickerEntity>> GetStickers(string filter)
         {
-            //TODO вернуть список стикеров, имеющихся на аукционе
-            return await StickerDao.GetAll(filter);
+            return (await AuctionDao.GetStickers(filter)).ToList();
+        }
+
+        public static async Task<IEnumerable<TraderInformation>> GetTradersList(string filter, string stickerId)
+        {
+            var result = new List<TraderInformation>();
+            var products = await AuctionDao.GetProducts(stickerId);
+            var users = await UserDao.GetUsersList(filter);
+            foreach (var product in products)
+            {
+                if (users.FirstOrDefault(i => i.Id == product.Trader) is { } user)
+                    result.Add(new TraderInformation(product) {Username = user.Username});
+            }
+            return result;
         }
     }
 }

+ 4 - 3
CardCollector/Controllers/MessageController.cs

@@ -173,12 +173,12 @@ namespace CardCollector.Controllers
             return new TgMessage();
         }
         
-        public static async Task AnswerCallbackQuery(UserEntity user, string callbackQueryId, string text)
+        public static async Task AnswerCallbackQuery(UserEntity user, string callbackQueryId, string text, bool showAlert = false)
         {
             try
             {
                 if (!user.IsBlocked)
-                    await Bot.Client.AnswerCallbackQueryAsync(callbackQueryId, text);
+                    await Bot.Client.AnswerCallbackQueryAsync(callbackQueryId, text, showAlert);
             }
             catch (Exception e)
             {
@@ -189,10 +189,11 @@ namespace CardCollector.Controllers
         /* Метод для удаления сообщения
          user - пользователь, которому необходимо удалить сообщение
          messageId - Id сообщения */
-        public static async Task DeleteMessage(UserEntity user, int messageId)
+        public static async Task DeleteMessage(UserEntity user, int messageId, bool deleteFromList = true)
         {
             try
             {
+                if (deleteFromList) user.Session.Messages.Remove(messageId);
                 if (!user.IsBlocked)
                     await Bot.Client.DeleteMessageAsync(user.ChatId, messageId);
             }

+ 5 - 4
CardCollector/DataBase/Entity/AuctionEntity.cs

@@ -1,5 +1,7 @@
-using System.ComponentModel.DataAnnotations;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
 using System.ComponentModel.DataAnnotations.Schema;
+using Telegram.Bot.Types.InlineQueryResults;
 
 namespace CardCollector.DataBase.Entity
 {
@@ -17,16 +19,15 @@ namespace CardCollector.DataBase.Entity
         /* Разбил на 2 отдельных цены, так как я ранее говорил,
          что можно будет продать стик за 2 валюты одновременно, поле валюты упразднил */
         /* цена в монетах */
-        [Column("price"), MaxLength(32)] public int PriceCoins { get; set; }
+        [Column("price_coins"), MaxLength(32)] public int PriceCoins { get; set; }
         
         /* цена в алмазах */
-        [Column("price"), MaxLength(32)] public int PriceGems { get; set; }
+        [Column("price_gems"), MaxLength(32)] public int PriceGems { get; set; }
         
         /* количество */
         [Column("quantity"), MaxLength(32)] public int Quantity { get; set; }
         
         /* продавец */
         [Column("trader"), MaxLength(127)] public long Trader { get; set; }
-        
     }
 }

+ 7 - 16
CardCollector/DataBase/Entity/UserEntity.cs

@@ -1,6 +1,7 @@
 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;
@@ -45,23 +46,13 @@ namespace CardCollector.DataBase.Entity
             await Session.ClearMessages();
         }
         
-        /* Возвращает стикеры в виде объектов телеграм */
-        public async Task<IEnumerable<InlineQueryResult>> GetStickersList(string command, string filter, bool userFilterEnabled = false)
+        /* Возвращает стикеры пользователя */
+        public async Task<IEnumerable<StickerEntity>> GetStickersList(string filter)
         {
-            var state = Session.State;
-            /* Получаем список стикеров исходя из того, нужно ли для отладки получить бесконечные стикеры */
-            var stickersList = state switch
-                {
-                    UserState.AuctionMenu => await AuctionController.GetStickers(filter),
-                    UserState.ShopMenu => await ShopController.GetStickers(filter),
-                    _ => Constants.UNLIMITED_ALL_STICKERS 
-                        ? await StickerDao.GetAll(filter)
-                        : await Stickers.ToStickers(filter),
-                };
-            /* Если пользовательская сортировка не применена, то возвращаем реультат */
-            if (!userFilterEnabled || state == UserState.Default) 
-                return stickersList.ToTelegramResults(command);
-            return Session.Filters.ApplyTo(stickersList, state).ToTelegramResults(command);
+            if (Constants.UNLIMITED_ALL_STICKERS) return await StickerDao.GetAll(filter);
+            return Stickers.Values
+                .Where(relation => relation.Count > 0)
+                .Select(rel => StickerDao.GetStickerByHash(rel.ShortHash).Result);
         }
 
         public UserEntity()

+ 9 - 0
CardCollector/DataBase/EntityDao/AuctionDao.cs

@@ -26,5 +26,14 @@ namespace CardCollector.DataBase.EntityDao
             return list.Sum(e => e.Quantity);
         }
 
+        public static async Task<IEnumerable<StickerEntity>> GetStickers(string filter)
+        {
+            var entityList = Table
+                .Select(e => e.StickerId)
+                .Distinct()
+                .ToHashSet();
+            var stickersList = await StickerDao.GetAll(filter);
+            return stickersList.Where(e => entityList.Contains(e.Id));
+        }
     }
 }

+ 2 - 1
CardCollector/DataBase/EntityDao/ShopDao.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;

+ 7 - 0
CardCollector/DataBase/EntityDao/UserDao.cs

@@ -1,4 +1,5 @@
 using System.Collections.Generic;
+using System.Linq;
 using System.Threading.Tasks;
 using System.Timers;
 using CardCollector.DataBase.Entity;
@@ -43,6 +44,12 @@ namespace CardCollector.DataBase.EntityDao
             return result;
         }
 
+        /* Получение пользователя по представлению user из Базы данных */
+        public static async Task<List<UserEntity>> GetUsersList(string filter)
+        {
+            return await Table.Where(user => user.Username.Contains(filter)).ToListAsync();
+        }
+
         /* Добавление новго пользователя в систему */
         private static async Task<UserEntity> AddNew(User user)
         {

+ 1 - 1
CardCollector/DataBase/EntityDao/UserStickerRelationDao.cs

@@ -26,7 +26,7 @@ namespace CardCollector.DataBase.EntityDao
         {
             if (user.Stickers.ContainsKey(sticker.Md5Hash))
             {
-                user.Stickers[sticker.Md5Hash].Count++;
+                user.Stickers[sticker.Md5Hash].Count += count;
                 return user.Stickers[sticker.Md5Hash];
             }
             var relation = new UserStickerRelationEntity

+ 16 - 0
CardCollector/Extensions.cs

@@ -4,6 +4,7 @@ using System.Linq;
 using System.Threading.Tasks;
 using CardCollector.DataBase.Entity;
 using CardCollector.DataBase.EntityDao;
+using CardCollector.Others;
 using CardCollector.Resources;
 using Telegram.Bot.Types.InlineQueryResults;
 
@@ -26,6 +27,21 @@ namespace CardCollector
             }
             return result;
         }
+        /* Преобразует список продавцов в список результатов для телеграм */
+        public static IEnumerable<InlineQueryResult> ToTelegramResults
+            (this IEnumerable<TraderInformation> list, string command)
+        {
+            var result = new List<InlineQueryResult>();
+            foreach (var item in list)
+            {
+                result.Add(new InlineQueryResultArticle($"{command}={item.Id}",
+                        $"{item.Username} {item.Quantity}{Text.items}", new InputTextMessageContent("Купить")) 
+                    { Description = $"{item.PriceCoins}{Text.coin}/{item.PriceGems}{Text.gem} {Text.per} 1{Text.items}" });
+                /* Ограничение Telegram API по количеству результатов в 50 шт. */
+                if (result.Count > 49) return result;
+            }
+            return result;
+        }
         
         /* Возвращает все стикеры системы */
         public static async Task<IEnumerable<StickerEntity>> ToStickers

+ 18 - 1
CardCollector/Others/Session.cs

@@ -59,7 +59,7 @@ namespace CardCollector.Others
         public async Task ClearMessages()
         {
             foreach (var messageId in Messages)
-                await MessageController.DeleteMessage(user, messageId);
+                await MessageController.DeleteMessage(user, messageId, false);
             Messages.Clear();
         }
 
@@ -99,6 +99,23 @@ namespace CardCollector.Others
             user.Cash.Gems += IncomeGems;
         }
 
+        public async Task PayOutOne(string hash)
+        {
+            IncomeCoins = 0;
+            IncomeGems = 0;
+            var sticker = user.Stickers[hash];
+            var stickerInfo = await StickerDao.GetStickerByHash(hash);
+            var payoutInterval = DateTime.Now - sticker.Payout;
+            var payoutsCount = (int) (payoutInterval.TotalMinutes / stickerInfo.IncomeTime);
+            if (payoutsCount < 1) return;
+            var multiplier = payoutsCount * sticker.Count;
+            sticker.Payout += new TimeSpan(0, stickerInfo.IncomeTime, 0) * payoutsCount;
+            IncomeCoins += stickerInfo.IncomeCoins * multiplier;
+            IncomeGems += stickerInfo.IncomeGems * multiplier;
+            user.Cash.Coins += IncomeCoins;
+            user.Cash.Gems += IncomeGems;
+        }
+
         public async void EndSession()
         {
             await ClearMessages();

+ 1 - 1
CardCollector/Others/StickerInfo.cs

@@ -21,6 +21,6 @@ namespace CardCollector.Others
             Md5Hash = entity.Md5Hash;
         }
         
-        public int count;
+        public int Count;
     }
 }

+ 19 - 0
CardCollector/Others/TraderInformation.cs

@@ -0,0 +1,19 @@
+using CardCollector.DataBase.Entity;
+
+namespace CardCollector.Others
+{
+    public class TraderInformation : AuctionEntity
+    {
+        public TraderInformation(AuctionEntity entity)
+        {
+            Id = entity.Id;
+            StickerId = entity.StickerId;
+            PriceCoins = entity.PriceCoins;
+            PriceGems = entity.PriceGems;
+            Quantity = entity.Quantity;
+            Trader = entity.Trader;
+        }
+
+        public string Username;
+    }
+}

+ 27 - 0
CardCollector/Resources/Command.Designer.cs

@@ -123,6 +123,24 @@ namespace CardCollector.Resources {
             }
         }
         
+        /// <summary>
+        ///   Looks up a localized string similar to confirm_buying.
+        /// </summary>
+        internal static string confirm_buying {
+            get {
+                return ResourceManager.GetString("confirm_buying", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to confirm_selling.
+        /// </summary>
+        internal static string confirm_selling {
+            get {
+                return ResourceManager.GetString("confirm_selling", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   Looks up a localized string similar to count.
         /// </summary>
@@ -222,6 +240,15 @@ namespace CardCollector.Resources {
             }
         }
         
+        /// <summary>
+        ///   Looks up a localized string similar to show_traders.
+        /// </summary>
+        internal static string show_traders {
+            get {
+                return ResourceManager.GetString("show_traders", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   Looks up a localized string similar to sort.
         /// </summary>

+ 9 - 0
CardCollector/Resources/Command.resx

@@ -81,4 +81,13 @@
     <data name="count" xml:space="preserve">
         <value>count</value>
     </data>
+    <data name="confirm_buying" xml:space="preserve">
+        <value>confirm_buying</value>
+    </data>
+    <data name="confirm_selling" xml:space="preserve">
+        <value>confirm_selling</value>
+    </data>
+    <data name="show_traders" xml:space="preserve">
+        <value>show_traders</value>
+    </data>
 </root>

+ 1 - 1
CardCollector/Resources/Constants.cs

@@ -10,7 +10,7 @@ namespace CardCollector.Resources
         /* Время кэширования результатов @имя_бота команд */
         public const int INLINE_RESULTS_CACHE_TIME = 1;
         /* Включает бесконечные стикеры без наличия их в коллекции */
-        public static readonly bool UNLIMITED_ALL_STICKERS = DEBUG;
+        public static readonly bool UNLIMITED_ALL_STICKERS = !DEBUG;
 
 
         /* Уровни привилегий пользователей системы */

+ 13 - 4
CardCollector/Resources/Keyboard.cs

@@ -177,19 +177,28 @@ namespace CardCollector.Resources
         {
             return state switch
             {
-                UserState.AuctionMenu or UserState.ShopMenu => new InlineKeyboardMarkup(new[] {
+                UserState.ShopMenu => new InlineKeyboardMarkup(new[] {
+                    new[] {InlineKeyboardButton.WithCallbackData($"{Text.buy} ({stickerInfo.Count})", Command.buy_sticker),},
                     new[]
                     {
                         InlineKeyboardButton.WithCallbackData(Text.minus, $"{Command.count}-"),
-                        InlineKeyboardButton.WithCallbackData($"{Text.buy} ({stickerInfo.count})", $"{Command.buy_sticker}={stickerInfo.Md5Hash}"),
                         InlineKeyboardButton.WithCallbackData(Text.plus, $"{Command.count}+"),
                     },
                     new[] {InlineKeyboardButton.WithCallbackData(Text.back, $"{Command.back}={Command.clear_chat}")},
                 }),
+                UserState.AuctionMenu => new InlineKeyboardMarkup(new[] {
+                    new[] {InlineKeyboardButton.WithSwitchInlineQueryCurrentChat(Text.show_traders)},
+                    new[] {InlineKeyboardButton.WithCallbackData(Text.back, $"{Command.back}={Command.clear_chat}")},
+                }),
                 UserState.CollectionMenu => new InlineKeyboardMarkup(new[] {
                     new[] {InlineKeyboardButton.WithSwitchInlineQuery(Text.send_sticker, stickerInfo.Title)},
-                    new[] {InlineKeyboardButton.WithCallbackData(Text.sell_on_auction, $"{Command.sell_on_auction}={stickerInfo.Md5Hash}")},
-                    new[] {InlineKeyboardButton.WithCallbackData(Text.combine, $"{Command.combine}={stickerInfo.Md5Hash}")},
+                    new[] {InlineKeyboardButton.WithCallbackData($"{Text.sell_on_auction} ({stickerInfo.Count})", Command.confirm_selling)},
+                    new[]
+                    {
+                        InlineKeyboardButton.WithCallbackData(Text.minus, $"{Command.count}-"),
+                        InlineKeyboardButton.WithCallbackData(Text.plus, $"{Command.count}+"),
+                    },
+                    new[] {InlineKeyboardButton.WithCallbackData(Text.combine, Command.combine)},
                     new[] {InlineKeyboardButton.WithCallbackData(Text.back, $"{Command.back}={Command.clear_chat}")},
                 }),
                 _ => new InlineKeyboardMarkup(new[] {

+ 27 - 0
CardCollector/Resources/Messages.Designer.cs

@@ -213,6 +213,33 @@ namespace CardCollector.Resources {
             }
         }
         
+        /// <summary>
+        ///   Looks up a localized string similar to Недостаточно монет!.
+        /// </summary>
+        internal static string not_enougth_coins {
+            get {
+                return ResourceManager.GetString("not_enougth_coins", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Недостаточно алмазов!.
+        /// </summary>
+        internal static string not_enougth_gems {
+            get {
+                return ResourceManager.GetString("not_enougth_gems", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Недостаточно стикеров в магазине!.
+        /// </summary>
+        internal static string not_enougth_stickers {
+            get {
+                return ResourceManager.GetString("not_enougth_stickers", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   Looks up a localized string similar to Пожалуйста, введите только эмоцию.
         /// </summary>

+ 9 - 0
CardCollector/Resources/Messages.resx

@@ -111,4 +111,13 @@
     <data name="cant_decrease" xml:space="preserve">
         <value>Невозможно уменьшить количество стикеров!</value>
     </data>
+    <data name="not_enougth_stickers" xml:space="preserve">
+        <value>Недостаточно стикеров в магазине!</value>
+    </data>
+    <data name="not_enougth_coins" xml:space="preserve">
+        <value>Недостаточно монет!</value>
+    </data>
+    <data name="not_enougth_gems" xml:space="preserve">
+        <value>Недостаточно алмазов!</value>
+    </data>
 </root>

+ 27 - 0
CardCollector/Resources/Text.Designer.cs

@@ -231,6 +231,15 @@ namespace CardCollector.Resources {
             }
         }
         
+        /// <summary>
+        ///   Looks up a localized string similar to шт..
+        /// </summary>
+        internal static string items {
+            get {
+                return ResourceManager.GetString("items", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   Looks up a localized string similar to /menu.
         /// </summary>
@@ -276,6 +285,15 @@ namespace CardCollector.Resources {
             }
         }
         
+        /// <summary>
+        ///   Looks up a localized string similar to за.
+        /// </summary>
+        internal static string per {
+            get {
+                return ResourceManager.GetString("per", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   Looks up a localized string similar to +.
         /// </summary>
@@ -357,6 +375,15 @@ namespace CardCollector.Resources {
             }
         }
         
+        /// <summary>
+        ///   Looks up a localized string similar to Показать продавцов.
+        /// </summary>
+        internal static string show_traders {
+            get {
+                return ResourceManager.GetString("show_traders", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   Looks up a localized string similar to Сортировка.
         /// </summary>

+ 9 - 0
CardCollector/Resources/Text.resx

@@ -135,4 +135,13 @@
     <data name="minus" xml:space="preserve">
         <value>-</value>
     </data>
+    <data name="show_traders" xml:space="preserve">
+        <value>Показать продавцов</value>
+    </data>
+    <data name="items" xml:space="preserve">
+        <value>шт.</value>
+    </data>
+    <data name="per" xml:space="preserve">
+        <value>за</value>
+    </data>
 </root>