
All checks were successful
Local Deploy with Docker / build-and-deploy (push) Successful in 17s
189 lines
8.5 KiB
C#
189 lines
8.5 KiB
C#
using System.Security.Cryptography;
|
||
using Microsoft.Extensions.Configuration;
|
||
using Telegram.Bot;
|
||
using Telegram.Bot.Types;
|
||
using Telegram.Bot.Types.Enums;
|
||
using UserOfTheDayBot.Data;
|
||
using UserOfTheDayBot.Model;
|
||
|
||
namespace UserOfTheDayBot.Services;
|
||
|
||
public class BotService
|
||
{
|
||
private readonly ITelegramBotClient _botClient;
|
||
private readonly IUserRepository _userRepository;
|
||
private readonly IUserOfTheDayRepository _userOfTheDayRepository;
|
||
|
||
public BotService(IConfiguration configuration, IUserRepository userRepository, IUserOfTheDayRepository userOfTheDayRepository)
|
||
{
|
||
_botClient = new TelegramBotClient(configuration["BotSettings:BotToken"] ?? Environment.GetEnvironmentVariable("BotSettings_BotToken"));
|
||
_userRepository = userRepository;
|
||
_userOfTheDayRepository = userOfTheDayRepository;
|
||
}
|
||
|
||
public async Task HandleUpdateAsync(Update update, CancellationToken cancellationToken)
|
||
{
|
||
if (update.Type == UpdateType.Message && update.Message?.Text != null)
|
||
{
|
||
var message = update.Message;
|
||
|
||
if (message.Text.StartsWith("/help"))
|
||
{
|
||
await _botClient.SendTextMessageAsync(message.Chat.Id, "Уйди. Попробуйте /reg", cancellationToken: cancellationToken);
|
||
}
|
||
else if (message.Text.StartsWith("/reg"))
|
||
{
|
||
await RegisterUserAsync(message, cancellationToken);
|
||
}
|
||
else if (message.Text.StartsWith("/useroftheday"))
|
||
{
|
||
await HandleUserOfTheDayCommandAsync(message, UserOfTheDayType.UserOfTheDay, cancellationToken);
|
||
}
|
||
else if (message.Text.StartsWith("/loser"))
|
||
{
|
||
await HandleUserOfTheDayCommandAsync(message, UserOfTheDayType.LoserOfTheDay, cancellationToken);
|
||
}
|
||
else if (message.Text.StartsWith("/stat"))
|
||
{
|
||
await HandleStatCommandAsync(message, cancellationToken);
|
||
}
|
||
else
|
||
{
|
||
await _botClient.SendTextMessageAsync(message.Chat.Id, "Неизвестная команда. Попробуйте /reg", cancellationToken: cancellationToken);
|
||
}
|
||
}
|
||
}
|
||
|
||
private async Task RegisterUserAsync(Message message, CancellationToken cancellationToken)
|
||
{
|
||
try
|
||
{
|
||
int rowsAffected = await _userRepository.RegisterUserAsync(message.Chat.Id, message.From.Id, message.From.FirstName);
|
||
|
||
if (rowsAffected > 0)
|
||
{
|
||
await _botClient.SendTextMessageAsync(message.Chat.Id, "Вы успешно зарегистрированы!", cancellationToken: cancellationToken);
|
||
}
|
||
else
|
||
{
|
||
await _botClient.SendTextMessageAsync(message.Chat.Id, "Вы уже зарегистрированы.", cancellationToken: cancellationToken);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.WriteLine($"Error: {ex.Message}");
|
||
|
||
await _botClient.SendTextMessageAsync(message.Chat.Id, "Произошла ошибка при регистрации. Попробуйте позже.", cancellationToken: cancellationToken);
|
||
}
|
||
}
|
||
|
||
private async Task HandleUserOfTheDayCommandAsync(Message message, UserOfTheDayType type, CancellationToken cancellationToken)
|
||
{
|
||
try
|
||
{
|
||
var today = DateTime.UtcNow.Date;
|
||
var chatId = message.Chat.Id;
|
||
|
||
if (await _userOfTheDayRepository.IsUserOfTheDaySelectedAsync(chatId, today, type))
|
||
{
|
||
var responseMessage = type == UserOfTheDayType.UserOfTheDay ? "Пользователь дня уже выбран." : "Неудачник дня уже выбран.";
|
||
await _botClient.SendTextMessageAsync(chatId, responseMessage, cancellationToken: cancellationToken);
|
||
return;
|
||
}
|
||
|
||
var selectedUser = await SelectUserOfTheDayAsync(chatId, today, type);
|
||
|
||
if (selectedUser.userId is not null)
|
||
{
|
||
var responseMessage = type == UserOfTheDayType.UserOfTheDay ? "Пользователь дня" : "Неудачник дня";
|
||
await _botClient.SendTextMessageAsync(chatId, $"{responseMessage}: {selectedUser.userName}", cancellationToken: cancellationToken);
|
||
}
|
||
else
|
||
{
|
||
await _botClient.SendTextMessageAsync(chatId, "В чате нет зарегистрированных пользователей.", cancellationToken: cancellationToken);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.WriteLine($"Error: {ex.Message}");
|
||
await _botClient.SendTextMessageAsync(message.Chat.Id, "Произошла ошибка при выборе пользователя дня. Попробуйте позже.", cancellationToken: cancellationToken);
|
||
}
|
||
}
|
||
|
||
private async Task<(long? userId, string userName)> SelectUserOfTheDayAsync(long chatId, DateTime date, UserOfTheDayType type)
|
||
{
|
||
var users = (await _userRepository.GetUsersWithNamesAsync(chatId)).ToList();
|
||
|
||
if (users.Any())
|
||
{
|
||
using (var rng = RandomNumberGenerator.Create())
|
||
{
|
||
while (users.Count > 0)
|
||
{
|
||
var randomIndex = GetRandomIndex(users.Count, rng);
|
||
var selectedUser = users[randomIndex];
|
||
|
||
if (!await _userOfTheDayRepository.IsUserAlreadySelectedAsync(chatId, date, selectedUser.userId))
|
||
{
|
||
await _userOfTheDayRepository.RecordUserOfTheDayAsync(chatId, selectedUser.userId, date, type);
|
||
return (selectedUser.userId, selectedUser.userName);
|
||
}
|
||
|
||
users.RemoveAt(randomIndex);
|
||
}
|
||
}
|
||
}
|
||
|
||
return default;
|
||
}
|
||
|
||
private async Task HandleStatCommandAsync(Message message, CancellationToken cancellationToken)
|
||
{
|
||
try
|
||
{
|
||
var chatId = message.Chat.Id;
|
||
var stats = await _userOfTheDayRepository.GetUserStatisticsAsync(chatId);
|
||
|
||
if (stats.Any())
|
||
{
|
||
var userOfTheDaySection = "Пользователь дня:\n";
|
||
var loserOfTheDaySection = "Неудачник дня:\n";
|
||
|
||
var sortedUserOfTheDay = stats.OrderByDescending(x => x.Value.userOfTheDayCount);
|
||
var sortedLoserOfTheDay = stats.OrderByDescending(x => x.Value.loserOfTheDayCount);
|
||
|
||
foreach (var stat in sortedUserOfTheDay)
|
||
{
|
||
userOfTheDaySection += $"{stat.Key.userName}: {stat.Value.userOfTheDayCount} раз(а)\n";
|
||
}
|
||
|
||
foreach (var stat in sortedLoserOfTheDay)
|
||
{
|
||
loserOfTheDaySection += $"{stat.Key.userName}: {stat.Value.loserOfTheDayCount} раз(а)\n";
|
||
}
|
||
|
||
var response = userOfTheDaySection + "\n" + loserOfTheDaySection;
|
||
|
||
await _botClient.SendTextMessageAsync(chatId, response, cancellationToken: cancellationToken);
|
||
}
|
||
else
|
||
{
|
||
await _botClient.SendTextMessageAsync(chatId, "Нет данных о пользователях.", cancellationToken: cancellationToken);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.WriteLine($"Error: {ex.Message}");
|
||
await _botClient.SendTextMessageAsync(message.Chat.Id, "Произошла ошибка при получении статистики. Попробуйте позже.", cancellationToken: cancellationToken);
|
||
}
|
||
}
|
||
|
||
private static int GetRandomIndex(int max, RandomNumberGenerator rng)
|
||
{
|
||
var buffer = new byte[4];
|
||
rng.GetBytes(buffer);
|
||
var randomValue = BitConverter.ToUInt32(buffer, 0);
|
||
return (int)(randomValue % max);
|
||
}
|
||
}
|