#nullable enable using BotFramework.Attributes; using BotFramework.Enums; using Kruzya.TelegramBot.Core.Data; using Kruzya.TelegramBot.Core.Extensions; using Kruzya.TelegramBot.Core.Handler; using Kruzya.TelegramBot.Core.Service; using Microsoft.Extensions.DependencyInjection; using Telegram.Bot; using Telegram.Bot.Types.Enums; using Telegram.Bot.Types.ReplyMarkups; using West.TelegramBot.ContentStore.Service; namespace West.TelegramBot.ContentStore.Handler; public class Store : CommonHandler { private readonly IReputation? _reputation; private readonly IServiceProvider _provider; private readonly ContentStore _store; public Store(CoreContext db, IServiceProvider provider, ContentStore store) : base(db) { _reputation = provider.GetService(); _provider = provider; _store = store; } [InChat(InChat.Public)] [Command("store", CommandParseMode.Both)] public async Task HandleStore() { if (From.IsBot) { return; } if (_reputation == null) { await Bot.SendTextMessageAsync(Chat.Id, "Reputation is unavailable."); return; } var user = From; var reputation = await _reputation.GetUserReputationAsync(Chat, user); await Bot.SendTextMessageAsync(Chat.Id, $"{user.ToHtml()} ({reputation}), чего пожелаете?", parseMode: ParseMode.Html, replyMarkup: new InlineKeyboardMarkup( _provider.GetServices() .ToAsyncEnumerable() .WhereAwait(async x => await x.CanView(Chat, user)) .OrderBy(x => x.StoreItem.Order) .Select(x => x.StoreItem.ToButton(From.Id)) .ToEnumerable() .Chunk(2) .ToList() ) ); } [InChat(InChat.Public)] [Update(UpdateFlag.CallbackQuery)] public async Task HandleStoreCallback() { var query = CallbackQuery; var queryData = query.Data; if (queryData == null || !queryData.StartsWith("store|") || _reputation == null) { return; } var paramList = queryData.Split('|'); if (!long.TryParse(paramList[1], out var senderId)) { return; } if (senderId != From.Id) { await AnswerQuery(query.Id, "Keyboard called by another user."); return; } var answer = "Unknown action."; if (paramList[2] == "purchase") { var purchaseType = paramList[3]; answer = "Спасибо за покупку"; if (!TryGetMediaService(purchaseType, out var mediaService)) { await AnswerQuery(query.Id, "Unknown purchasable."); return; } var storeItem = mediaService!.StoreItem; var messageId = query.Message!.MessageId; var reputation = await _reputation.GetUserReputationAsync(Chat, From); if (reputation < storeItem.Price) { await Bot.EditMessageTextAsync( Chat.Id, messageId, $"{From.ToHtml()} ({reputation}), продолжай работать и тебе обязательно хватит на покупку.", ParseMode.Html); await AnswerQuery(query.Id); return; } try { await PerformPurchase(mediaService, messageId); } catch (Exception) { answer = "Товар недоступен"; await Bot.EditMessageTextAsync(Chat.Id, messageId, $"{From.ToHtml()} попытался купить \"{storeItem.Name}\", но товара в наличии не оказалось.", ParseMode.Html); await AnswerQuery(query.Id, answer); return; } reputation = await _reputation.SetUserReputationAsync(Chat, From, reputation - storeItem.Price); await Bot.EditMessageTextAsync(Chat.Id, messageId, $"{From.ToHtml()} ({reputation}) купил \"{storeItem.Name}\".", ParseMode.Html); } await AnswerQuery(query.Id, answer); } private async Task PerformPurchase(IRandomMediaService mediaService, int messageId) { var randomMedia = await mediaService!.GetRandomMediaAsync(); var file = randomMedia.File; switch (randomMedia.Type) { case InputMediaType.Photo: await Bot.SendPhotoAsync(Chat.Id, file, caption: randomMedia.Caption, replyToMessageId: messageId, parseMode: ParseMode.Html, hasSpoiler: randomMedia.Nsfw ); break; case InputMediaType.Video: await Bot.SendVideoAsync(Chat.Id, file, caption: randomMedia.Caption, replyToMessageId: messageId, parseMode: ParseMode.Html, hasSpoiler: randomMedia.Nsfw ); break; } } private bool TryGetMediaService(string name, out IRandomMediaService? mediaService) { mediaService = _provider.GetServices() .FirstOrDefault(s => s.StoreItem.Id == name); return mediaService != null; } }