188 lines
8.4 KiB
C#
188 lines
8.4 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.HasValue)
|
|||
|
{
|
|||
|
var responseMessage = type == UserOfTheDayType.UserOfTheDay ? "Пользователь дня" : "Неудачник дня";
|
|||
|
await _botClient.SendTextMessageAsync(chatId, $"{responseMessage}: {selectedUser.Value}", 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?> 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;
|
|||
|
}
|
|||
|
|
|||
|
users.RemoveAt(randomIndex);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return null;
|
|||
|
}
|
|||
|
|
|||
|
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);
|
|||
|
}
|
|||
|
}
|