Files
telegram-bot/modules/Entertainment/Handler/Guess.cs
T
2023-01-18 17:17:28 +02:00

141 lines
4.7 KiB
C#

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using BotFramework.Attributes;
using BotFramework.Enums;
using Kruzya.TelegramBot.Core;
using Kruzya.TelegramBot.Core.Data;
using Kruzya.TelegramBot.Core.Extensions;
using Kruzya.TelegramBot.Core.Service;
using Telegram.Bot;
using Telegram.Bot.Types.Enums;
using Telegram.Bot.Types.ReplyMarkups;
namespace West.Entertainment.Handler;
public class Guess : CommonHandler
{
private readonly IGuessCache _guessCache;
private readonly ThreadSafeRandom _rng;
private readonly IReputation _reputationService;
private readonly CoreContext _db;
public Guess(IGuessCache guessCache, ThreadSafeRandom rng, IReputation reputationService, CoreContext db) : base(db)
{
_guessCache = guessCache;
_rng = rng;
_reputationService = reputationService;
_db = db;
}
[Command(InChat.Public, "guess", CommandParseMode.Both)]
public async Task HandleGuess()
{
var cooldownOption = await _db.UserValues.FindOrCreateOption(Chat.Id, From.Id, "guessCooldown");
var cooldown = cooldownOption.GetValue<DateTime>();
if (cooldown > DateTime.Now)
{
await Reply($"Следующее использование через {cooldown - DateTime.Now:hh\\:mm\\:ss}.");
return;
}
var guessDict = _guessCache.GetOr(Chat.Id, new ConcurrentDictionary<int, GuessData>());
var doesExist = guessDict.Any(pair => pair.Value.UserId == From.Id);
if (doesExist)
{
await Bot.SendTextMessageAsync(Chat, "Вы уже запустили игру.");
return;
}
var messageId = RawUpdate.Message!.MessageId;
var guessedNumber = _rng.Next(1, 4);
// Console.WriteLine(guessedNumber);
var guessData = new GuessData
{
Number = guessedNumber,
UserId = From.Id
};
var keyBoard = new InlineKeyboardMarkup(new List<InlineKeyboardButton>
{
new("1") { CallbackData = $"guess|{From.Id}|answer|1" },
new("2") { CallbackData = $"guess|{From.Id}|answer|2" },
new("3") { CallbackData = $"guess|{From.Id}|answer|3" }
});
var message = await Bot.SendTextMessageAsync(Chat.Id, "Выберите число от 1 до 3.",
replyToMessageId: messageId,
replyMarkup: keyBoard
);
if (!guessDict.TryAdd(message.MessageId, guessData))
{
return;
}
_guessCache.SetValue(Chat.Id, guessDict, -1);
}
[Update(InChat.Public, UpdateFlag.CallbackQuery)]
public async Task HandleGuessResponse()
{
var messageId = CallbackQuery.Message?.MessageId;
if (messageId == null || CallbackQuery.Data == null)
{
return;
}
var fromUser = CallbackQuery.From;
var fromId = fromUser.Id;
var callbackData = CallbackQuery.Data.Split('|');
if (callbackData.Length < 4
|| callbackData[0] != "guess"
|| callbackData[1] != fromId.ToString()
|| callbackData[2] != "answer")
{
return;
}
var guessDict = _guessCache.GetOr(Chat.Id, new ConcurrentDictionary<int, GuessData>());
if (!guessDict.TryGetValue((int) messageId, out var data)
|| fromId != data.UserId)
{
return;
}
if (!int.TryParse(callbackData[3], out var responseNumber))
{
return;
}
await Bot.AnswerCallbackQueryAsync(CallbackQuery.Id);
guessDict.TryRemove((int) messageId, out _);
_guessCache.SetValue(Chat.Id, guessDict, -1);
var now = DateTime.Now;
var nextUse = now.AddHours(1);
var postFix = $"\nЗагаданное число: {data.Number}.\nСледующая попытка через: {nextUse - now:hh\\:mm\\:ss}";
string message;
if (responseNumber == data.Number)
{
await _reputationService.IncrementReputationAsync(Chat, From, 20);
message = $"{fromUser.ToHtml()} угадал! +20 кармы.\n";
}
else
{
message = $"{fromUser.ToHtml()} не угадал!\n\nОтвет: {responseNumber}.";
}
var cooldownOption = await _db.UserValues.FindOrCreateOption(Chat.Id, From.Id, "guessCooldown");
cooldownOption.SetValue(nextUse);
_db.AddOrUpdate(cooldownOption);
await Bot.EditMessageTextAsync(Chat, (int) messageId, message + postFix, parseMode: ParseMode.Html);
}
}