telegram-bot/Program.cs

2319 lines
108 KiB
C#
Raw Normal View History

using System;
2025-03-17 14:53:01 +07:00
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Data.Sqlite;
using Serilog;
using Telegram.Bot;
using Telegram.Bot.Types;
using Telegram.Bot.Types.Enums;
2025-03-19 13:24:38 +07:00
using Telegram.Bot.Types.ReplyMarkups;
class Program
{
private static string _botToken = string.Empty;
private static TelegramBotClient _botClient = null!;
2025-03-17 14:53:01 +07:00
private static Dictionary<long, bool> usersWaitingForReport = new Dictionary<long, bool>(); // Отслеживаем состояние пользователей
2025-03-17 15:33:06 +07:00
private static HashSet<long> admins = new HashSet<long>(); // Хранение списка администраторов
private static string adminPassword = "admin123"; // Простой пароль для администратора
private static Dictionary<long, string> adminFullNames = new Dictionary<long, string>();
private static HashSet<long> superAdmins = new HashSet<long>(); // Хранение списка суперпользователей
private static string superAdminPassword = "superadmin123"; // Пароль для суперпользователя
static async Task Main()
{
// Загружаем конфигурацию из appsettings.json
2025-03-12 22:41:14 +07:00
try
{
Log.Information("Загрузка конфигурации из appsettings.json...");
var config = new ConfigurationBuilder()
.SetBasePath(AppContext.BaseDirectory) // <-- Используем правильный путь
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.Build();
2025-03-12 22:41:14 +07:00
_botToken = config["BotToken"] ?? throw new Exception("BotToken не найден в конфигурации!");
Log.Information("Конфигурация успешно загружена");
2025-03-12 22:41:14 +07:00
}
catch (Exception ex)
{
Log.Error($"Ошибка при загрузке конфигурации: {ex.Message}");
throw;
}
Log.Logger = new LoggerConfiguration()
.WriteTo.Console()
.WriteTo.File("logs/log.txt", rollingInterval: RollingInterval.Day)
.CreateLogger();
Log.Information("Запуск Telegram-бота...");
2025-03-12 22:41:14 +07:00
try
{
_botClient = new TelegramBotClient(_botToken);
var me = await _botClient.GetMe();
2025-03-12 22:41:14 +07:00
Log.Information($"Бот {me.FirstName} запущен! ID: {me.Id}");
}
catch (Exception ex)
{
Log.Error($"Ошибка при подключении к Telegram API: {ex.Message}");
throw;
}
2025-03-17 15:07:41 +07:00
// Создание базы данных и таблицы, если они не существуют
await CreateDatabaseIfNotExists();
Добавлены настройки пользователя и управление уведомлениями В код добавлены новые методы для работы с настройками пользователя, включая создание таблицы `UserSettings`, отображение настроек и изменение состояния уведомлений. Метод `CreateUserSettingsTableIfNotExists` создает таблицу, если она не существует, и обрабатывает возможные ошибки при создании. Метод `ShowUserSettings` загружает текущие настройки пользователя из базы данных и отправляет сообщение с возможностью изменения состояния уведомлений. В обработке обновлений добавлена логика для обработки нажатий на кнопки, связанных с настройками пользователя и переключением уведомлений. Метод `NotifyUserAboutStatusChange` теперь проверяет, включены ли уведомления для пользователя, перед отправкой сообщения о смене статуса заявки. Метод `ToggleNotifications` изменяет состояние уведомлений для пользователя и обновляет соответствующую запись в базе данных, а также отображает обновленные настройки. В меню добавлена кнопка для перехода к настройкам пользователя.
2025-03-20 11:02:41 +07:00
await CreateUserSettingsTableIfNotExists();
2025-03-17 15:07:41 +07:00
// Загрузка списка администраторов из базы данных
await LoadAdminsFromDatabase();
Log.Information($"Загружено {admins.Count} администраторов из базы данных");
var cts = new CancellationTokenSource();
2025-03-12 22:41:14 +07:00
Log.Information("Начало получения обновлений...");
2025-03-12 22:17:34 +07:00
2025-03-12 22:41:14 +07:00
try
{
// Применение StartReceiving для работы с задачами
_botClient.StartReceiving(HandleUpdateAsync, HandleErrorAsync, cancellationToken: cts.Token);
Log.Information("Получение обновлений успешно началось.");
}
catch (Exception ex)
{
Log.Error($"Ошибка при запуске получения обновлений: {ex.Message}");
throw;
}
2025-03-12 22:17:34 +07:00
// Создание TaskCompletionSource для удержания процесса бота
var tcs = new TaskCompletionSource();
await tcs.Task; // Это заставит бота работать до тех пор, пока не будет отменен
// Ожидаем отмены через token
cts.Token.WaitHandle.WaitOne();
}
private static async Task MonitorReportStatus(long reportId, CancellationToken token)
{
// Ждем 1 час перед первой проверкой
2025-03-20 22:55:36 +07:00
await Task.Delay(TimeSpan.FromHours(1), token);
while (!token.IsCancellationRequested)
{
try
{
using (var connection = new SqliteConnection("Data Source=bot.db"))
{
await connection.OpenAsync();
var command = connection.CreateCommand();
command.CommandText = @"
SELECT Status
FROM Reports
WHERE Id = @id";
command.Parameters.AddWithValue("@id", reportId);
var status = (string?)await command.ExecuteScalarAsync();
// Проверяем, существует ли заявка
if (status == null)
{
// Если заявка была удалена, прекращаем мониторинг
Log.Information($"Заявка #{reportId} была удалена, прекращаем мониторинг.");
return;
}
if (status == "в работе" || status == "закрыта")
{
// Если статус изменился на "в работе" или "закрыта", прекращаем мониторинг
return;
}
var getAdminsCommand = connection.CreateCommand();
getAdminsCommand.CommandText = "SELECT ChatId, NotifyOnPendingReports FROM Admins";
using (var reader = await getAdminsCommand.ExecuteReaderAsync())
{
while (await reader.ReadAsync())
{
long adminId = reader.GetInt64(0);
bool notifyOnPendingReports = reader.GetInt32(1) == 1;
if (notifyOnPendingReports)
{
await _botClient.SendMessage(
chatId: adminId,
text: $"⚠️ Заявка #{reportId} остается в статусе 'Ожидает'."
);
}
}
}
}
}
catch (Exception ex)
{
Log.Error($"Ошибка при мониторинге статуса заявки #{reportId}: {ex.Message}");
}
// Ждем 1 час перед следующей проверкой
2025-03-20 22:55:36 +07:00
await Task.Delay(TimeSpan.FromHours(1), token);
}
}
private static async Task DeletePreviousMessage(ITelegramBotClient botClient, long chatId, int messageId)
{
try
{
await botClient.DeleteMessage(chatId, messageId);
}
catch (Exception ex)
{
Log.Error($"Ошибка при удалении сообщения {messageId} в чате {chatId}: {ex.Message}");
}
}
Добавлены настройки пользователя и управление уведомлениями В код добавлены новые методы для работы с настройками пользователя, включая создание таблицы `UserSettings`, отображение настроек и изменение состояния уведомлений. Метод `CreateUserSettingsTableIfNotExists` создает таблицу, если она не существует, и обрабатывает возможные ошибки при создании. Метод `ShowUserSettings` загружает текущие настройки пользователя из базы данных и отправляет сообщение с возможностью изменения состояния уведомлений. В обработке обновлений добавлена логика для обработки нажатий на кнопки, связанных с настройками пользователя и переключением уведомлений. Метод `NotifyUserAboutStatusChange` теперь проверяет, включены ли уведомления для пользователя, перед отправкой сообщения о смене статуса заявки. Метод `ToggleNotifications` изменяет состояние уведомлений для пользователя и обновляет соответствующую запись в базе данных, а также отображает обновленные настройки. В меню добавлена кнопка для перехода к настройкам пользователя.
2025-03-20 11:02:41 +07:00
private static async Task CreateUserSettingsTableIfNotExists()
{
try
{
using (var connection = new SqliteConnection("Data Source=bot.db"))
{
await connection.OpenAsync();
var command = connection.CreateCommand();
command.CommandText = @"
CREATE TABLE IF NOT EXISTS UserSettings (
UserId INTEGER PRIMARY KEY,
NotificationsEnabled INTEGER NOT NULL DEFAULT 1
);";
await command.ExecuteNonQueryAsync();
Log.Information("Таблица UserSettings успешно создана (если её не было).");
}
}
catch (Exception ex)
{
Log.Error($"Ошибка при создании таблицы UserSettings: {ex.Message}");
}
}
private static async Task ViewUserReports(ITelegramBotClient botClient, long chatId)
{
string connectionString = "Data Source=bot.db";
try
{
using (var connection = new SqliteConnection(connectionString))
{
await connection.OpenAsync();
var command = connection.CreateCommand();
command.CommandText = "SELECT Id, Description, Status, Priority FROM Reports WHERE ChatId = @chatId";
command.Parameters.AddWithValue("@chatId", chatId);
var buttons = new List<InlineKeyboardButton[]>();
using (var reader = await command.ExecuteReaderAsync())
{
while (await reader.ReadAsync())
{
long id = reader.GetInt64(0);
string description = reader.GetString(1).Substring(0, Math.Min(20, reader.GetString(1).Length));
string status = reader.GetString(2);
string priority = reader.GetString(3);
string statusEmoji = GetStatusEmoji(status);
string priorityMarker = priority.ToLower() == "высокий" ? "⚠️ " : "";
buttons.Add(new[]
{
InlineKeyboardButton.WithCallbackData(
$"{priorityMarker}#{id} - {statusEmoji} {status} - {description}...",
$"user_report_{id}")
});
}
}
// Добавляем кнопки навигации
buttons.Add(new[]
{
InlineKeyboardButton.WithCallbackData("🏠 Главное меню", "main_menu")
});
await botClient.SendMessage(
chatId: chatId,
text: "Ваши заявки:",
replyMarkup: new InlineKeyboardMarkup(buttons)
);
}
}
catch (Exception ex)
{
Log.Error($"Ошибка: {ex.Message}");
await botClient.SendMessage(chatId, "Ошибка при получении ваших заявок");
}
}
Добавлены настройки пользователя и управление уведомлениями В код добавлены новые методы для работы с настройками пользователя, включая создание таблицы `UserSettings`, отображение настроек и изменение состояния уведомлений. Метод `CreateUserSettingsTableIfNotExists` создает таблицу, если она не существует, и обрабатывает возможные ошибки при создании. Метод `ShowUserSettings` загружает текущие настройки пользователя из базы данных и отправляет сообщение с возможностью изменения состояния уведомлений. В обработке обновлений добавлена логика для обработки нажатий на кнопки, связанных с настройками пользователя и переключением уведомлений. Метод `NotifyUserAboutStatusChange` теперь проверяет, включены ли уведомления для пользователя, перед отправкой сообщения о смене статуса заявки. Метод `ToggleNotifications` изменяет состояние уведомлений для пользователя и обновляет соответствующую запись в базе данных, а также отображает обновленные настройки. В меню добавлена кнопка для перехода к настройкам пользователя.
2025-03-20 11:02:41 +07:00
private static async Task ShowUserSettings(ITelegramBotClient botClient, long chatId)
{
try
{
// Получаем текущие настройки пользователя
bool notificationsEnabled = true; // По умолчанию уведомления включены
Добавлены настройки пользователя и управление уведомлениями В код добавлены новые методы для работы с настройками пользователя, включая создание таблицы `UserSettings`, отображение настроек и изменение состояния уведомлений. Метод `CreateUserSettingsTableIfNotExists` создает таблицу, если она не существует, и обрабатывает возможные ошибки при создании. Метод `ShowUserSettings` загружает текущие настройки пользователя из базы данных и отправляет сообщение с возможностью изменения состояния уведомлений. В обработке обновлений добавлена логика для обработки нажатий на кнопки, связанных с настройками пользователя и переключением уведомлений. Метод `NotifyUserAboutStatusChange` теперь проверяет, включены ли уведомления для пользователя, перед отправкой сообщения о смене статуса заявки. Метод `ToggleNotifications` изменяет состояние уведомлений для пользователя и обновляет соответствующую запись в базе данных, а также отображает обновленные настройки. В меню добавлена кнопка для перехода к настройкам пользователя.
2025-03-20 11:02:41 +07:00
using (var connection = new SqliteConnection("Data Source=bot.db"))
{
await connection.OpenAsync();
var command = connection.CreateCommand();
command.CommandText = "SELECT NotificationsEnabled FROM UserSettings WHERE UserId = @userId";
command.Parameters.AddWithValue("@userId", chatId);
var result = await command.ExecuteScalarAsync();
2025-03-20 11:12:10 +07:00
// Отладочная информация
Log.Information($"[Отладка] Для пользователя {chatId} проверяем настройки уведомлений. Результат из БД: {result}");
Добавлены настройки пользователя и управление уведомлениями В код добавлены новые методы для работы с настройками пользователя, включая создание таблицы `UserSettings`, отображение настроек и изменение состояния уведомлений. Метод `CreateUserSettingsTableIfNotExists` создает таблицу, если она не существует, и обрабатывает возможные ошибки при создании. Метод `ShowUserSettings` загружает текущие настройки пользователя из базы данных и отправляет сообщение с возможностью изменения состояния уведомлений. В обработке обновлений добавлена логика для обработки нажатий на кнопки, связанных с настройками пользователя и переключением уведомлений. Метод `NotifyUserAboutStatusChange` теперь проверяет, включены ли уведомления для пользователя, перед отправкой сообщения о смене статуса заявки. Метод `ToggleNotifications` изменяет состояние уведомлений для пользователя и обновляет соответствующую запись в базе данных, а также отображает обновленные настройки. В меню добавлена кнопка для перехода к настройкам пользователя.
2025-03-20 11:02:41 +07:00
if (result != null && result != DBNull.Value)
{
2025-03-20 11:12:10 +07:00
int dbValue = Convert.ToInt32(result);
notificationsEnabled = dbValue == 1;
Log.Information($"[Отладка] Для пользователя {chatId} настройка уведомлений из БД: {dbValue} => notificationsEnabled={notificationsEnabled}");
Добавлены настройки пользователя и управление уведомлениями В код добавлены новые методы для работы с настройками пользователя, включая создание таблицы `UserSettings`, отображение настроек и изменение состояния уведомлений. Метод `CreateUserSettingsTableIfNotExists` создает таблицу, если она не существует, и обрабатывает возможные ошибки при создании. Метод `ShowUserSettings` загружает текущие настройки пользователя из базы данных и отправляет сообщение с возможностью изменения состояния уведомлений. В обработке обновлений добавлена логика для обработки нажатий на кнопки, связанных с настройками пользователя и переключением уведомлений. Метод `NotifyUserAboutStatusChange` теперь проверяет, включены ли уведомления для пользователя, перед отправкой сообщения о смене статуса заявки. Метод `ToggleNotifications` изменяет состояние уведомлений для пользователя и обновляет соответствующую запись в базе данных, а также отображает обновленные настройки. В меню добавлена кнопка для перехода к настройкам пользователя.
2025-03-20 11:02:41 +07:00
}
else
{
// Если запись для пользователя отсутствует, создаем ее
var insertCommand = connection.CreateCommand();
insertCommand.CommandText = "INSERT INTO UserSettings (UserId, NotificationsEnabled) VALUES (@userId, 1)";
insertCommand.Parameters.AddWithValue("@userId", chatId);
await insertCommand.ExecuteNonQueryAsync();
2025-03-20 11:12:10 +07:00
Log.Information($"[Отладка] Создали запись для пользователя {chatId} с notificationsEnabled=true");
Добавлены настройки пользователя и управление уведомлениями В код добавлены новые методы для работы с настройками пользователя, включая создание таблицы `UserSettings`, отображение настроек и изменение состояния уведомлений. Метод `CreateUserSettingsTableIfNotExists` создает таблицу, если она не существует, и обрабатывает возможные ошибки при создании. Метод `ShowUserSettings` загружает текущие настройки пользователя из базы данных и отправляет сообщение с возможностью изменения состояния уведомлений. В обработке обновлений добавлена логика для обработки нажатий на кнопки, связанных с настройками пользователя и переключением уведомлений. Метод `NotifyUserAboutStatusChange` теперь проверяет, включены ли уведомления для пользователя, перед отправкой сообщения о смене статуса заявки. Метод `ToggleNotifications` изменяет состояние уведомлений для пользователя и обновляет соответствующую запись в базе данных, а также отображает обновленные настройки. В меню добавлена кнопка для перехода к настройкам пользователя.
2025-03-20 11:02:41 +07:00
}
}
// Создаем клавиатуру с настройками
string notificationStatus = notificationsEnabled ? "✅ Включены" : "❌ Отключены";
string toggleAction = notificationsEnabled ? "toggle_off" : "toggle_on";
2025-03-20 11:12:10 +07:00
Log.Information($"[Отладка] Для пользователя {chatId} показываем статус: {notificationStatus}, toggleAction: {toggleAction}");
Добавлены настройки пользователя и управление уведомлениями В код добавлены новые методы для работы с настройками пользователя, включая создание таблицы `UserSettings`, отображение настроек и изменение состояния уведомлений. Метод `CreateUserSettingsTableIfNotExists` создает таблицу, если она не существует, и обрабатывает возможные ошибки при создании. Метод `ShowUserSettings` загружает текущие настройки пользователя из базы данных и отправляет сообщение с возможностью изменения состояния уведомлений. В обработке обновлений добавлена логика для обработки нажатий на кнопки, связанных с настройками пользователя и переключением уведомлений. Метод `NotifyUserAboutStatusChange` теперь проверяет, включены ли уведомления для пользователя, перед отправкой сообщения о смене статуса заявки. Метод `ToggleNotifications` изменяет состояние уведомлений для пользователя и обновляет соответствующую запись в базе данных, а также отображает обновленные настройки. В меню добавлена кнопка для перехода к настройкам пользователя.
2025-03-20 11:02:41 +07:00
var keyboard = new InlineKeyboardMarkup(new[]
{
new[]
{
InlineKeyboardButton.WithCallbackData($"Уведомления: {notificationStatus}", $"notifications_{toggleAction}")
},
new[]
{
InlineKeyboardButton.WithCallbackData("🔙 Назад в меню", "main_menu")
}
});
await botClient.SendMessage(
chatId: chatId,
text: "⚙️ <b>Настройки пользователя</b>\n\n" +
"Здесь вы можете настроить параметры бота:\n\n" +
"Уведомления включают:\n" +
"- Уведомления о смене статуса ваших заявок\n",
Добавлены настройки пользователя и управление уведомлениями В код добавлены новые методы для работы с настройками пользователя, включая создание таблицы `UserSettings`, отображение настроек и изменение состояния уведомлений. Метод `CreateUserSettingsTableIfNotExists` создает таблицу, если она не существует, и обрабатывает возможные ошибки при создании. Метод `ShowUserSettings` загружает текущие настройки пользователя из базы данных и отправляет сообщение с возможностью изменения состояния уведомлений. В обработке обновлений добавлена логика для обработки нажатий на кнопки, связанных с настройками пользователя и переключением уведомлений. Метод `NotifyUserAboutStatusChange` теперь проверяет, включены ли уведомления для пользователя, перед отправкой сообщения о смене статуса заявки. Метод `ToggleNotifications` изменяет состояние уведомлений для пользователя и обновляет соответствующую запись в базе данных, а также отображает обновленные настройки. В меню добавлена кнопка для перехода к настройкам пользователя.
2025-03-20 11:02:41 +07:00
parseMode: ParseMode.Html,
replyMarkup: keyboard
);
}
catch (Exception ex)
{
Log.Error($"Ошибка при отображении настроек пользователя: {ex.Message}");
2025-03-20 11:12:10 +07:00
Log.Error($"StackTrace: {ex.StackTrace}");
Добавлены настройки пользователя и управление уведомлениями В код добавлены новые методы для работы с настройками пользователя, включая создание таблицы `UserSettings`, отображение настроек и изменение состояния уведомлений. Метод `CreateUserSettingsTableIfNotExists` создает таблицу, если она не существует, и обрабатывает возможные ошибки при создании. Метод `ShowUserSettings` загружает текущие настройки пользователя из базы данных и отправляет сообщение с возможностью изменения состояния уведомлений. В обработке обновлений добавлена логика для обработки нажатий на кнопки, связанных с настройками пользователя и переключением уведомлений. Метод `NotifyUserAboutStatusChange` теперь проверяет, включены ли уведомления для пользователя, перед отправкой сообщения о смене статуса заявки. Метод `ToggleNotifications` изменяет состояние уведомлений для пользователя и обновляет соответствующую запись в базе данных, а также отображает обновленные настройки. В меню добавлена кнопка для перехода к настройкам пользователя.
2025-03-20 11:02:41 +07:00
await botClient.SendMessage(chatId, "Произошла ошибка при загрузке настроек.");
}
}
2025-03-20 11:12:10 +07:00
private static async Task HandleUpdateAsync(ITelegramBotClient botClient, Update update, CancellationToken cancellationToken)
{
2025-03-12 22:41:14 +07:00
try
{
2025-03-19 14:14:02 +07:00
// Обработка нажатий на кнопки
if (update.Type == UpdateType.CallbackQuery)
{
var callbackQuery = update.CallbackQuery;
2025-03-19 15:54:05 +07:00
if (callbackQuery?.From != null)
{
long chatId = callbackQuery.From.Id;
string? data = callbackQuery.Data;
if (callbackQuery?.Message?.MessageId != null)
{
int messageId = callbackQuery.Message.MessageId;
await DeletePreviousMessage(botClient, chatId, messageId); // Удаляем предыдущее сообщение
2025-03-19 15:54:05 +07:00
}
2025-03-19 14:14:02 +07:00
if (callbackQuery?.Id != null)
{
await botClient.AnswerCallbackQuery(callbackQuery.Id); // Убираем "часики" у кнопки
}
2025-03-19 14:14:02 +07:00
2025-03-19 15:54:05 +07:00
if (data == "report")
{
usersWaitingForReport[chatId] = true;
userReportSteps[chatId] = 1;
userReports[chatId] = new Report();
var priorityKeyboard = new InlineKeyboardMarkup(new[]
{
2025-03-19 22:01:40 +07:00
new[]
{
InlineKeyboardButton.WithCallbackData("Низкий", "priority_low"),
InlineKeyboardButton.WithCallbackData("Средний", "priority_medium"),
InlineKeyboardButton.WithCallbackData("Высокий", "priority_high")
}
});
await botClient.SendMessage(chatId, "Пожалуйста, выберите приоритет:", replyMarkup: priorityKeyboard);
Log.Information($"Пользователь {chatId} начал создание заявки");
}
2025-03-19 22:01:40 +07:00
else if (data == "admin_settings")
{
if (admins.Contains(chatId))
{
await ShowAdminSettings(botClient, chatId);
}
else
{
await botClient.SendMessage(chatId, "⛔ У вас нет прав для доступа к настройкам администраторов!");
await Task.Delay(2000);
await SendMainMenu(botClient, chatId);
}
}
2025-03-19 22:47:04 +07:00
else if (data == "view_admins")
{
if (admins.Contains(chatId))
{
await ShowAdminsList(botClient, chatId);
}
else
{
await botClient.SendMessage(chatId, "⛔ У вас нет прав для просмотра администраторов!");
await Task.Delay(2000);
await SendMainMenu(botClient, chatId);
}
}
2025-03-19 22:01:40 +07:00
else if (data != null && data.StartsWith("removeadmin_"))
{
long adminIdToRemove = long.Parse(data.Substring(11).Replace("_", ""));
2025-03-19 22:01:40 +07:00
// Проверяем, что пользователь является администратором
if (admins.Contains(chatId))
{
// Проверяем, не пытается ли пользователь удалить себя
if (adminIdToRemove == chatId)
{
var warningMessage = await botClient.SendMessage(
2025-03-19 22:01:40 +07:00
chatId: chatId,
text: "⚠️ Вы не можете удалить себя из администраторов!"
);
await Task.Delay(2000);
await botClient.DeleteMessage(chatId, warningMessage.MessageId);
await ShowAdminsList(botClient, chatId);
2025-03-19 22:01:40 +07:00
}
else
{
await RemoveAdminFromDatabase(adminIdToRemove);
string username = "администратор";
try
{
var user = await botClient.GetChat(adminIdToRemove);
username = user.Username ?? user.FirstName ?? "администратор";
}
catch { }
await botClient.SendMessage(
chatId: chatId,
text: $"✅ Пользователь {username} (ID: {adminIdToRemove}) удален из администраторов."
);
await Task.Delay(2000);
await ShowAdminsList(botClient, chatId);
}
}
else
{
await botClient.SendMessage(chatId, "⛔ У вас нет прав для удаления администраторов!");
await Task.Delay(2000);
await SendMainMenu(botClient, chatId);
}
}
else if (data != null && data.StartsWith("enable_notifications_"))
{
long adminId = long.Parse(data.Substring("enable_notifications_".Length));
await ToggleAdminNotifications(adminId, true);
await ShowAdminSettings(botClient, chatId);
}
else if (data != null && data.StartsWith("disable_notifications_"))
{
long adminId = long.Parse(data.Substring("disable_notifications_".Length));
await ToggleAdminNotifications(adminId, false);
await ShowAdminSettings(botClient, chatId);
}
else if (data == "user_reports")
{
await ViewUserReports(botClient, chatId);
}
else if (data != null && data.StartsWith("user_report_"))
{
long reportId = long.Parse(data.Substring("user_report_".Length));
if (callbackQuery?.Message?.MessageId != null)
{
int messageId = callbackQuery.Message.MessageId;
await ShowReportDetails(botClient, chatId, reportId, messageId);
}
}
else if (data != null && data.StartsWith("delete_"))
{
long reportId = long.Parse(data.Substring(7));
await DeleteReport(botClient, chatId, reportId);
}
else if (data == "leave_admin")
{
bool isSuperUser = superAdmins.Contains(chatId);
await RemoveSelfFromAdmins(chatId);
var message = await botClient.SendMessage(
chatId: chatId,
text: isSuperUser
? "✅ Вы вышли из режима суперпользователя."
: "✅ Вы вышли из режима администратора."
);
await Task.Delay(2000);
await botClient.DeleteMessage(chatId, message.MessageId);
await SendMainMenu(botClient, chatId);
}
else if (data != null && data.StartsWith("removeadmin_"))
{
long adminIdToRemove = long.Parse(data.Substring(11).Replace("_", ""));
// Проверяем, что пользователь является суперпользователем
if (superAdmins.Contains(chatId))
{
// Проверяем, не пытается ли пользователь удалить себя
if (adminIdToRemove == chatId)
{
var warningMessage = await botClient.SendMessage(
chatId: chatId,
text: "⚠️ Вы не можете удалить себя из администраторов через эту функцию. Используйте 'Выйти из режима администратора'!"
);
await Task.Delay(2000);
await botClient.DeleteMessage(chatId, warningMessage.MessageId);
await ShowAdminsList(botClient, chatId);
}
else
{
await RemoveAdminFromDatabase(adminIdToRemove);
string username = "администратор";
try
{
var user = await botClient.GetChat(adminIdToRemove);
username = user.Username ?? user.FirstName ?? "администратор";
}
catch { }
await botClient.SendMessage(
chatId: chatId,
text: $"✅ Пользователь {username} (ID: {adminIdToRemove}) удален из администраторов."
);
await Task.Delay(2000);
await ShowAdminsList(botClient, chatId);
}
}
else
{
await botClient.SendMessage(chatId, "⛔ У вас нет прав для удаления администраторов! Только суперпользователи могут управлять списком администраторов.");
await Task.Delay(2000);
await SendMainMenu(botClient, chatId);
}
}
2025-03-19 22:01:40 +07:00
// Также добавим обработку команды /removeadmin в секцию обработки текстовых сообщений:
// В блоке для обработки текстовых сообщений (после if (message.Text.StartsWith("/admin")))
else if (update.Type == UpdateType.Message && update.Message?.Text != null)
{
var message = update.Message;
Log.Information($"Получено сообщение от {message.Chat.Id}: {message.Text}");
if (message.Text.StartsWith("/admin"))
{
string[] parts = message.Text.Split(' ');
if (parts.Length == 2 && parts[1] == adminPassword)
{
admins.Add(message.Chat.Id);
// Сохраняем администратора в базу данных
await SaveAdminToDatabase(message.Chat.Id, ""); // Добавляем пустую строку для fullName
2025-03-19 22:01:40 +07:00
var authMessage = await botClient.SendMessage(message.Chat.Id, "✅ Вы авторизованы как администратор!");
Log.Information($"Новый администратор: {message.Chat.Id}");
await Task.Delay(2000);
await botClient.DeleteMessage(message.Chat.Id, authMessage.MessageId);
await SendMainMenu(botClient, message.Chat.Id);
}
2025-03-19 22:01:40 +07:00
else
{
var authMessage = await botClient.SendMessage(message.Chat.Id, "❌ Неверный пароль!");
await Task.Delay(2000);
await botClient.DeleteMessage(message.Chat.Id, authMessage.MessageId);
await SendMainMenu(botClient, message.Chat.Id);
}
return;
}
2025-03-19 22:48:53 +07:00
}
2025-03-19 22:01:40 +07:00
2025-03-19 22:48:53 +07:00
else if (data == "admin_panel")
{
if (admins.Contains(chatId))
{
2025-03-19 22:48:53 +07:00
await SendAdminPanel(botClient, chatId);
}
2025-03-19 22:48:53 +07:00
else
{
2025-03-19 22:48:53 +07:00
var authMessage = await botClient.SendMessage(chatId, "⛔ Вы не являетесь администратором!");
Log.Information($"Неавторизованный доступ к админ-панели от {chatId}");
await Task.Delay(2000);
await botClient.DeleteMessage(chatId, authMessage.MessageId);
await SendMainMenu(botClient, chatId);
}
2025-03-19 22:48:53 +07:00
}
else if (data == "view_reports")
{
if (admins.Contains(chatId))
{
await ViewReports(botClient, chatId);
}
2025-03-19 22:48:53 +07:00
else
{
2025-03-19 22:48:53 +07:00
var authMessage = await botClient.SendMessage(chatId, "⛔ Вы не являетесь администратором!");
Log.Information($"Неавторизованный доступ к заявкам от {chatId}");
await Task.Delay(2000);
await botClient.DeleteMessage(chatId, authMessage.MessageId);
await SendMainMenu(botClient, chatId);
}
}
2025-03-19 22:48:53 +07:00
else if (data == "view_archived_reports")
{
2025-03-19 22:48:53 +07:00
if (admins.Contains(chatId))
{
2025-03-19 22:48:53 +07:00
await ViewArchivedReports(botClient, chatId);
}
else
{
2025-03-19 22:48:53 +07:00
var authMessage = await botClient.SendMessage(chatId, "⛔ Вы не являетесь администратором!");
Log.Information($"Неавторизованный доступ к архиву заявок от {chatId}");
await Task.Delay(2000);
2025-03-19 22:48:53 +07:00
await botClient.DeleteMessage(chatId, authMessage.MessageId);
await SendMainMenu(botClient, chatId);
}
}
else if (data == "delete_all_reports")
{
if (superAdmins.Contains(chatId))
{
var confirmKeyboard = new InlineKeyboardMarkup(new[]
{
new[]
{
InlineKeyboardButton.WithCallbackData("✅ Подтвердить", "confirm_delete_all_reports"),
InlineKeyboardButton.WithCallbackData("❌ Отмена", "admin_panel")
}
});
await botClient.SendMessage(
chatId: chatId,
text: "Вы уверены, что хотите удалить все заявки? Это действие необратимо.",
replyMarkup: confirmKeyboard
);
}
else
{
await botClient.SendMessage(chatId, "⛔ У вас нет прав для удаления всех заявок!");
await Task.Delay(2000);
await SendMainMenu(botClient, chatId);
}
}
else if (data == "confirm_delete_all_reports")
{
if (admins.Contains(chatId))
{
await DeleteAllReports(botClient, chatId);
}
else
{
await botClient.SendMessage(chatId, "⛔ У вас нет прав для удаления всех заявок!");
await Task.Delay(2000);
await SendMainMenu(botClient, chatId);
}
}
2025-03-19 22:48:53 +07:00
else if (data != null && data.StartsWith("report_"))
{
2025-03-19 22:48:53 +07:00
long reportId = long.Parse(data.Substring(7));
if (callbackQuery?.Message?.MessageId != null)
{
2025-03-19 22:48:53 +07:00
int messageId = callbackQuery.Message.MessageId;
await ShowReportDetails(botClient, chatId, reportId, messageId);
}
2025-03-19 22:48:53 +07:00
}
else if (data != null && data.StartsWith("status_"))
{
string[] parts = data.Split('_');
long reportId = long.Parse(parts[1]);
string newStatus = parts[2];
if (callbackQuery?.Message?.MessageId != null)
{
2025-03-19 22:48:53 +07:00
int messageId = callbackQuery.Message.MessageId;
await UpdateReportStatus(reportId, newStatus, chatId);
await ShowReportDetails(botClient, chatId, reportId, messageId);
}
}
2025-03-19 22:48:53 +07:00
else if (data != null && data.StartsWith("delete_"))
{
long reportId = long.Parse(data.Substring(7));
await DeleteReport(botClient, chatId, reportId);
}
else if (data == "back_to_list")
{
await ViewReports(botClient, chatId);
}
else if (data == "back_to_admin_panel")
{
await SendAdminPanel(botClient, chatId);
}
else if (data == "main_menu")
{
await SendMainMenu(botClient, chatId);
}
Добавлены настройки пользователя и управление уведомлениями В код добавлены новые методы для работы с настройками пользователя, включая создание таблицы `UserSettings`, отображение настроек и изменение состояния уведомлений. Метод `CreateUserSettingsTableIfNotExists` создает таблицу, если она не существует, и обрабатывает возможные ошибки при создании. Метод `ShowUserSettings` загружает текущие настройки пользователя из базы данных и отправляет сообщение с возможностью изменения состояния уведомлений. В обработке обновлений добавлена логика для обработки нажатий на кнопки, связанных с настройками пользователя и переключением уведомлений. Метод `NotifyUserAboutStatusChange` теперь проверяет, включены ли уведомления для пользователя, перед отправкой сообщения о смене статуса заявки. Метод `ToggleNotifications` изменяет состояние уведомлений для пользователя и обновляет соответствующую запись в базе данных, а также отображает обновленные настройки. В меню добавлена кнопка для перехода к настройкам пользователя.
2025-03-20 11:02:41 +07:00
else if (data == "user_settings")
{
await ShowUserSettings(botClient, chatId);
}
else if (data != null && data.StartsWith("notifications_toggle_"))
{
2025-03-20 11:17:47 +07:00
string action = data.Substring("notifications_toggle_".Length); // "on" или "off"
Добавлены настройки пользователя и управление уведомлениями В код добавлены новые методы для работы с настройками пользователя, включая создание таблицы `UserSettings`, отображение настроек и изменение состояния уведомлений. Метод `CreateUserSettingsTableIfNotExists` создает таблицу, если она не существует, и обрабатывает возможные ошибки при создании. Метод `ShowUserSettings` загружает текущие настройки пользователя из базы данных и отправляет сообщение с возможностью изменения состояния уведомлений. В обработке обновлений добавлена логика для обработки нажатий на кнопки, связанных с настройками пользователя и переключением уведомлений. Метод `NotifyUserAboutStatusChange` теперь проверяет, включены ли уведомления для пользователя, перед отправкой сообщения о смене статуса заявки. Метод `ToggleNotifications` изменяет состояние уведомлений для пользователя и обновляет соответствующую запись в базе данных, а также отображает обновленные настройки. В меню добавлена кнопка для перехода к настройкам пользователя.
2025-03-20 11:02:41 +07:00
await ToggleNotifications(botClient, chatId, action);
}
2025-03-20 11:17:47 +07:00
2025-03-19 22:48:53 +07:00
else if (data != null && data.StartsWith("priority_"))
{
string priority = data.Substring(9);
userReports[chatId].Priority = priority;
userReportSteps[chatId] = 2;
await botClient.SendMessage(chatId, "Пожалуйста, укажите кабинет.");
}
else if (data == "confirm_report")
{
await ConfirmReport(botClient, chatId);
}
else if (data == "cancel_report")
{
await CancelReport(botClient, chatId);
}
2025-03-19 22:48:53 +07:00
}
}
2025-03-19 22:01:40 +07:00
2025-03-19 22:48:53 +07:00
// Обработка текстовых сообщений
if (update.Type == UpdateType.Message && update.Message?.Text != null)
{
var message = update.Message;
// Обработка текстовых сообщений
if (update.Type == UpdateType.Message && update.Message?.Text != null)
2025-03-19 22:48:53 +07:00
{
2025-03-20 10:21:33 +07:00
var receivedMessage = update.Message;
Log.Information($"Получено сообщение от {receivedMessage.Chat.Id}: {receivedMessage.Text}");
if (receivedMessage.Text.StartsWith("/superadm"))
{
string[] parts = receivedMessage.Text.Split(new[] { ' ' }, 3); // Разделяем на 3 части: команду, пароль и остаток как ФИО
if (parts.Length >= 3 && parts[1] == superAdminPassword)
{
string fullName = parts[2]; // Вся оставшаяся строка - это ФИО
admins.Add(receivedMessage.Chat.Id);
superAdmins.Add(receivedMessage.Chat.Id);
adminFullNames[receivedMessage.Chat.Id] = fullName;
// Сохраняем суперпользователя в базу данных
await SaveSuperAdminToDatabase(receivedMessage.Chat.Id, fullName);
var authMessage = await botClient.SendMessage(receivedMessage.Chat.Id, $"✅ Вы авторизованы как суперпользователь, {fullName}!");
Log.Information($"Новый суперпользователь: {receivedMessage.Chat.Id}, ФИО: {fullName}");
await Task.Delay(2000);
await botClient.DeleteMessage(receivedMessage.Chat.Id, authMessage.MessageId);
await SendMainMenu(botClient, receivedMessage.Chat.Id);
}
else
{
var authMessage = await botClient.SendMessage(receivedMessage.Chat.Id, "❌ Неверный формат команды или пароль! Используйте: /superadm пароль Фамилия Имя Отчество");
await Task.Delay(2000);
await botClient.DeleteMessage(receivedMessage.Chat.Id, authMessage.MessageId);
await SendMainMenu(botClient, receivedMessage.Chat.Id);
}
return;
}
// Обработка обычной команды администратора
else if (receivedMessage.Text.StartsWith("/admin"))
2025-03-19 22:48:53 +07:00
{
2025-03-20 10:21:33 +07:00
string[] parts = receivedMessage.Text.Split(new[] { ' ' }, 3); // Разделяем на 3 части: команду, пароль и остаток как ФИО
if (parts.Length >= 3 && parts[1] == adminPassword)
{
string fullName = parts[2]; // Вся оставшаяся строка - это ФИО
2025-03-20 10:21:33 +07:00
admins.Add(receivedMessage.Chat.Id);
adminFullNames[receivedMessage.Chat.Id] = fullName;
// Сохраняем администратора в базу данных, убедившись что он не суперпользователь
2025-03-20 10:21:33 +07:00
await SaveAdminToDatabase(receivedMessage.Chat.Id, fullName);
2025-03-20 10:21:33 +07:00
var authMessage = await botClient.SendMessage(receivedMessage.Chat.Id, $"✅ Вы авторизованы как администратор, {fullName}!");
Log.Information($"Новый администратор: {receivedMessage.Chat.Id}, ФИО: {fullName}");
await Task.Delay(2000);
2025-03-20 10:21:33 +07:00
await botClient.DeleteMessage(receivedMessage.Chat.Id, authMessage.MessageId);
await SendMainMenu(botClient, receivedMessage.Chat.Id);
}
else
{
2025-03-20 10:21:33 +07:00
var authMessage = await botClient.SendMessage(receivedMessage.Chat.Id, "❌ Неверный формат команды или пароль! Используйте: /admin пароль Фамилия Имя Отчество");
await Task.Delay(2000);
2025-03-20 10:21:33 +07:00
await botClient.DeleteMessage(receivedMessage.Chat.Id, authMessage.MessageId);
await SendMainMenu(botClient, receivedMessage.Chat.Id);
}
return;
2025-03-19 22:48:53 +07:00
}
// В блоке для обработки текстовых сообщений
else if (message.Text == "/admins")
2025-03-19 22:48:53 +07:00
{
if (admins.Contains(message.Chat.Id))
{
await ShowAdminsList(botClient, message.Chat.Id);
}
else
{
var authMessage = await botClient.SendMessage(
chatId: message.Chat.Id,
text: "⛔ У вас нет прав для просмотра списка администраторов!"
);
await Task.Delay(2000);
await botClient.DeleteMessage(message.Chat.Id, authMessage.MessageId);
await SendMainMenu(botClient, message.Chat.Id);
}
}
if (message.Text == "/start")
2025-03-19 22:01:40 +07:00
{
await SendMainMenu(botClient, message.Chat.Id);
Log.Information($"Ответ на команду /start с кнопками отправлен.");
2025-03-19 16:38:09 +07:00
}
else if (usersWaitingForReport.TryGetValue(message.Chat.Id, out bool isWaiting) && isWaiting)
{
2025-03-20 10:21:33 +07:00
if (userReportSteps.TryGetValue(message.Chat.Id, out int step))
{
2025-03-20 10:21:33 +07:00
switch (step)
{
case 2:
userReports[message.Chat.Id].Room = message.Text;
userReportSteps[message.Chat.Id] = 3;
await botClient.SendMessage(message.Chat.Id, "Пожалуйста, опишите проблему.");
break;
case 3:
userReports[message.Chat.Id].Description = message.Text;
userReportSteps[message.Chat.Id] = 4;
await botClient.SendMessage(message.Chat.Id, "Пожалуйста, укажите ваше ФИО.");
break;
case 4:
userReports[message.Chat.Id].ReporterName = message.Text;
userReportSteps[message.Chat.Id] = 5;
var confirmKeyboard = new InlineKeyboardMarkup(new[]
2025-03-20 10:21:33 +07:00
{
new[]
{
InlineKeyboardButton.WithCallbackData("✅ Подтвердить", "confirm_report"),
InlineKeyboardButton.WithCallbackData("❌ Отменить", "cancel_report")
}
});
2025-03-20 10:21:33 +07:00
await botClient.SendMessage(
message.Chat.Id,
"Пожалуйста, подтвердите отправку заявки:",
replyMarkup: confirmKeyboard
2025-03-20 10:21:33 +07:00
);
break;
}
2025-03-19 22:01:40 +07:00
}
}
2025-03-19 22:48:53 +07:00
}
else
{
await botClient.SendMessage(message.Chat.Id, " Используйте команду /start для начала работы с ботом.");
2025-03-19 22:01:40 +07:00
}
2025-03-12 22:41:14 +07:00
}
}
2025-03-12 22:41:14 +07:00
catch (Exception ex)
{
2025-03-12 22:41:14 +07:00
Log.Error($"Ошибка при обработке обновлений: {ex.Message}");
Log.Error($"StackTrace: {ex.StackTrace}");
}
}
private static async Task ConfirmReport(ITelegramBotClient botClient, long chatId)
{
if (userReports.TryGetValue(chatId, out var report))
{
await SaveReportToDatabase(chatId, report);
var mainMenuKeyboard = new InlineKeyboardMarkup(new[]
{
new[]
{
InlineKeyboardButton.WithCallbackData("Главное меню", "main_menu")
}
});
await botClient.SendMessage(
chatId: chatId,
text: "✅ Спасибо за заявку! Мы обработаем её в ближайшее время.",
replyMarkup: mainMenuKeyboard
);
usersWaitingForReport[chatId] = false;
userReportSteps.Remove(chatId);
userReports.Remove(chatId);
Log.Information($"Заявка пользователя {chatId} сохранена в базе данных.");
}
}
private static async Task CancelReport(ITelegramBotClient botClient, long chatId)
{
usersWaitingForReport[chatId] = false;
userReportSteps.Remove(chatId);
userReports.Remove(chatId);
await botClient.SendMessage(
chatId: chatId,
text: "❌ Заявка отменена.",
replyMarkup: new InlineKeyboardMarkup(new[]
{
new[]
{
InlineKeyboardButton.WithCallbackData("Главное меню", "main_menu")
}
})
);
Log.Information($"Заявка пользователя {chatId} отменена.");
}
private static async Task DeleteAllReports(ITelegramBotClient botClient, long chatId)
{
try
{
using (var connection = new SqliteConnection("Data Source=bot.db"))
{
await connection.OpenAsync();
var command = connection.CreateCommand();
command.CommandText = "DELETE FROM Reports";
await command.ExecuteNonQueryAsync();
var deletionMessage = await botClient.SendMessage(chatId, "Все заявки успешно удалены.");
Log.Information($"Все заявки удалены пользователем {chatId}.");
// Ждем 2 секунды
await Task.Delay(2000);
// Удаляем сообщение об удалении
await botClient.DeleteMessage(chatId, deletionMessage.MessageId);
// Возвращаемся к панели администратора
await SendAdminPanel(botClient, chatId);
}
}
catch (Exception ex)
{
Log.Error($"Ошибка при удалении всех заявок: {ex.Message}");
await botClient.SendMessage(chatId, "Ошибка при удалении всех заявок.");
}
}
private static async Task DeleteReport(ITelegramBotClient botClient, long chatId, long reportId)
{
try
{
using (var connection = new SqliteConnection("Data Source=bot.db"))
{
await connection.OpenAsync();
var command = connection.CreateCommand();
command.CommandText = "SELECT ChatId FROM Reports WHERE Id = @id";
command.Parameters.AddWithValue("@id", reportId);
var ownerChatId = (long?)await command.ExecuteScalarAsync();
if (ownerChatId == null)
{
await botClient.SendMessage(chatId, $"Заявка #{reportId} не найдена.");
return;
}
if (ownerChatId != chatId && !admins.Contains(chatId))
{
await botClient.SendMessage(chatId, "⛔ Вы не можете удалить эту заявку, так как она не принадлежит вам.");
return;
}
command.CommandText = "DELETE FROM Reports WHERE Id = @id";
await command.ExecuteNonQueryAsync();
var deletionMessage = await botClient.SendMessage(chatId, $"Заявка #{reportId} успешно удалена.");
Log.Information($"Заявка #{reportId} удалена пользователем {chatId}.");
// Ждем 2 секунды
await Task.Delay(2000);
// Удаляем сообщение об удалении
await botClient.DeleteMessage(chatId, deletionMessage.MessageId);
// Отображаем список заявок пользователя
await ViewUserReports(botClient, chatId);
}
}
catch (Exception ex)
{
Log.Error($"Ошибка при удалении заявки #{reportId}: {ex.Message}");
await botClient.SendMessage(chatId, $"Ошибка при удалении заявки #{reportId}.");
}
}
private static async Task NotifyUserAboutStatusChange(long chatId, long reportId, string newStatus)
{
try
{
Добавлены настройки пользователя и управление уведомлениями В код добавлены новые методы для работы с настройками пользователя, включая создание таблицы `UserSettings`, отображение настроек и изменение состояния уведомлений. Метод `CreateUserSettingsTableIfNotExists` создает таблицу, если она не существует, и обрабатывает возможные ошибки при создании. Метод `ShowUserSettings` загружает текущие настройки пользователя из базы данных и отправляет сообщение с возможностью изменения состояния уведомлений. В обработке обновлений добавлена логика для обработки нажатий на кнопки, связанных с настройками пользователя и переключением уведомлений. Метод `NotifyUserAboutStatusChange` теперь проверяет, включены ли уведомления для пользователя, перед отправкой сообщения о смене статуса заявки. Метод `ToggleNotifications` изменяет состояние уведомлений для пользователя и обновляет соответствующую запись в базе данных, а также отображает обновленные настройки. В меню добавлена кнопка для перехода к настройкам пользователя.
2025-03-20 11:02:41 +07:00
// Проверяем настройки пользователя
bool notificationsEnabled = true; // По умолчанию уведомления включены
using (var connection = new SqliteConnection("Data Source=bot.db"))
{
await connection.OpenAsync();
var command = connection.CreateCommand();
command.CommandText = "SELECT NotificationsEnabled FROM UserSettings WHERE UserId = @userId";
command.Parameters.AddWithValue("@userId", chatId);
var result = await command.ExecuteScalarAsync();
if (result != null && result != DBNull.Value)
{
notificationsEnabled = Convert.ToInt32(result) == 1;
}
}
// Если уведомления отключены, не отправляем сообщение
if (!notificationsEnabled)
{
Log.Information($"Уведомление о смене статуса заявки #{reportId} не отправлено пользователю {chatId} (уведомления отключены)");
return;
}
string statusEmoji = GetStatusEmoji(newStatus);
await _botClient.SendMessage(
chatId: chatId,
text: $"{statusEmoji} <b>Статус вашей заявки #{reportId} был изменен на: {newStatus}</b>",
parseMode: ParseMode.Html
);
Log.Information($"Уведомление о смене статуса заявки #{reportId} отправлено пользователю {chatId}");
}
catch (Exception ex)
{
Log.Error($"Ошибка при отправке уведомления пользователю о смене статуса: {ex.Message}");
}
}
Добавлены настройки пользователя и управление уведомлениями В код добавлены новые методы для работы с настройками пользователя, включая создание таблицы `UserSettings`, отображение настроек и изменение состояния уведомлений. Метод `CreateUserSettingsTableIfNotExists` создает таблицу, если она не существует, и обрабатывает возможные ошибки при создании. Метод `ShowUserSettings` загружает текущие настройки пользователя из базы данных и отправляет сообщение с возможностью изменения состояния уведомлений. В обработке обновлений добавлена логика для обработки нажатий на кнопки, связанных с настройками пользователя и переключением уведомлений. Метод `NotifyUserAboutStatusChange` теперь проверяет, включены ли уведомления для пользователя, перед отправкой сообщения о смене статуса заявки. Метод `ToggleNotifications` изменяет состояние уведомлений для пользователя и обновляет соответствующую запись в базе данных, а также отображает обновленные настройки. В меню добавлена кнопка для перехода к настройкам пользователя.
2025-03-20 11:02:41 +07:00
private static async Task ToggleNotifications(ITelegramBotClient botClient, long chatId, string action)
{
try
{
2025-03-20 11:12:10 +07:00
// Проверка текущего состояния перед изменением
bool currentState = true;
using (var connection = new SqliteConnection("Data Source=bot.db"))
{
await connection.OpenAsync();
var checkCommand = connection.CreateCommand();
checkCommand.CommandText = "SELECT NotificationsEnabled FROM UserSettings WHERE UserId = @userId";
checkCommand.Parameters.AddWithValue("@userId", chatId);
var result = await checkCommand.ExecuteScalarAsync();
if (result != null && result != DBNull.Value)
{
currentState = Convert.ToInt32(result) == 1;
}
}
Log.Information($"[Отладка] Переключение уведомлений для пользователя {chatId}: текущее состояние={currentState}, action={action}");
// Если action = "toggle_on", то нужно ВКЛЮЧИТЬ уведомления (установить в БД 1)
// Если action = "toggle_off", то нужно ВЫКЛЮЧИТЬ уведомления (установить в БД 0)
2025-03-20 11:20:49 +07:00
bool newValue = action == "on";
Добавлены настройки пользователя и управление уведомлениями В код добавлены новые методы для работы с настройками пользователя, включая создание таблицы `UserSettings`, отображение настроек и изменение состояния уведомлений. Метод `CreateUserSettingsTableIfNotExists` создает таблицу, если она не существует, и обрабатывает возможные ошибки при создании. Метод `ShowUserSettings` загружает текущие настройки пользователя из базы данных и отправляет сообщение с возможностью изменения состояния уведомлений. В обработке обновлений добавлена логика для обработки нажатий на кнопки, связанных с настройками пользователя и переключением уведомлений. Метод `NotifyUserAboutStatusChange` теперь проверяет, включены ли уведомления для пользователя, перед отправкой сообщения о смене статуса заявки. Метод `ToggleNotifications` изменяет состояние уведомлений для пользователя и обновляет соответствующую запись в базе данных, а также отображает обновленные настройки. В меню добавлена кнопка для перехода к настройкам пользователя.
2025-03-20 11:02:41 +07:00
int dbValue = newValue ? 1 : 0;
2025-03-20 11:12:10 +07:00
Log.Information($"[Отладка] Переключение уведомлений для пользователя {chatId}: action={action}, новое значение={newValue}, значение в БД={dbValue}");
Добавлены настройки пользователя и управление уведомлениями В код добавлены новые методы для работы с настройками пользователя, включая создание таблицы `UserSettings`, отображение настроек и изменение состояния уведомлений. Метод `CreateUserSettingsTableIfNotExists` создает таблицу, если она не существует, и обрабатывает возможные ошибки при создании. Метод `ShowUserSettings` загружает текущие настройки пользователя из базы данных и отправляет сообщение с возможностью изменения состояния уведомлений. В обработке обновлений добавлена логика для обработки нажатий на кнопки, связанных с настройками пользователя и переключением уведомлений. Метод `NotifyUserAboutStatusChange` теперь проверяет, включены ли уведомления для пользователя, перед отправкой сообщения о смене статуса заявки. Метод `ToggleNotifications` изменяет состояние уведомлений для пользователя и обновляет соответствующую запись в базе данных, а также отображает обновленные настройки. В меню добавлена кнопка для перехода к настройкам пользователя.
2025-03-20 11:02:41 +07:00
using (var connection = new SqliteConnection("Data Source=bot.db"))
{
await connection.OpenAsync();
var command = connection.CreateCommand();
command.CommandText = @"
2025-03-20 11:15:05 +07:00
INSERT INTO UserSettings (UserId, NotificationsEnabled)
VALUES (@userId, @value)
ON CONFLICT(UserId)
DO UPDATE SET NotificationsEnabled = @value";
Добавлены настройки пользователя и управление уведомлениями В код добавлены новые методы для работы с настройками пользователя, включая создание таблицы `UserSettings`, отображение настроек и изменение состояния уведомлений. Метод `CreateUserSettingsTableIfNotExists` создает таблицу, если она не существует, и обрабатывает возможные ошибки при создании. Метод `ShowUserSettings` загружает текущие настройки пользователя из базы данных и отправляет сообщение с возможностью изменения состояния уведомлений. В обработке обновлений добавлена логика для обработки нажатий на кнопки, связанных с настройками пользователя и переключением уведомлений. Метод `NotifyUserAboutStatusChange` теперь проверяет, включены ли уведомления для пользователя, перед отправкой сообщения о смене статуса заявки. Метод `ToggleNotifications` изменяет состояние уведомлений для пользователя и обновляет соответствующую запись в базе данных, а также отображает обновленные настройки. В меню добавлена кнопка для перехода к настройкам пользователя.
2025-03-20 11:02:41 +07:00
command.Parameters.AddWithValue("@userId", chatId);
command.Parameters.AddWithValue("@value", dbValue);
2025-03-20 11:12:10 +07:00
int rowsAffected = await command.ExecuteNonQueryAsync();
Log.Information($"[Отладка] Запрос выполнен, затронуто {rowsAffected} строк");
}
// Проверка после изменения
using (var connection = new SqliteConnection("Data Source=bot.db"))
{
await connection.OpenAsync();
var checkCommand = connection.CreateCommand();
checkCommand.CommandText = "SELECT NotificationsEnabled FROM UserSettings WHERE UserId = @userId";
checkCommand.Parameters.AddWithValue("@userId", chatId);
var result = await checkCommand.ExecuteScalarAsync();
bool updatedState = false;
if (result != null && result != DBNull.Value)
{
updatedState = Convert.ToInt32(result) == 1;
}
Log.Information($"[Отладка] После обновления: значение в БД для пользователя {chatId} = {result}, обновленное состояние={updatedState}");
Добавлены настройки пользователя и управление уведомлениями В код добавлены новые методы для работы с настройками пользователя, включая создание таблицы `UserSettings`, отображение настроек и изменение состояния уведомлений. Метод `CreateUserSettingsTableIfNotExists` создает таблицу, если она не существует, и обрабатывает возможные ошибки при создании. Метод `ShowUserSettings` загружает текущие настройки пользователя из базы данных и отправляет сообщение с возможностью изменения состояния уведомлений. В обработке обновлений добавлена логика для обработки нажатий на кнопки, связанных с настройками пользователя и переключением уведомлений. Метод `NotifyUserAboutStatusChange` теперь проверяет, включены ли уведомления для пользователя, перед отправкой сообщения о смене статуса заявки. Метод `ToggleNotifications` изменяет состояние уведомлений для пользователя и обновляет соответствующую запись в базе данных, а также отображает обновленные настройки. В меню добавлена кнопка для перехода к настройкам пользователя.
2025-03-20 11:02:41 +07:00
}
// Показываем обновленные настройки
await ShowUserSettings(botClient, chatId);
string statusText = newValue ? "включены" : "отключены";
Log.Information($"Пользователь {chatId}: уведомления {statusText}");
Добавлены настройки пользователя и управление уведомлениями В код добавлены новые методы для работы с настройками пользователя, включая создание таблицы `UserSettings`, отображение настроек и изменение состояния уведомлений. Метод `CreateUserSettingsTableIfNotExists` создает таблицу, если она не существует, и обрабатывает возможные ошибки при создании. Метод `ShowUserSettings` загружает текущие настройки пользователя из базы данных и отправляет сообщение с возможностью изменения состояния уведомлений. В обработке обновлений добавлена логика для обработки нажатий на кнопки, связанных с настройками пользователя и переключением уведомлений. Метод `NotifyUserAboutStatusChange` теперь проверяет, включены ли уведомления для пользователя, перед отправкой сообщения о смене статуса заявки. Метод `ToggleNotifications` изменяет состояние уведомлений для пользователя и обновляет соответствующую запись в базе данных, а также отображает обновленные настройки. В меню добавлена кнопка для перехода к настройкам пользователя.
2025-03-20 11:02:41 +07:00
}
catch (Exception ex)
{
Log.Error($"Ошибка при изменении настроек уведомлений: {ex.Message}");
2025-03-20 11:12:10 +07:00
Log.Error($"StackTrace: {ex.StackTrace}");
Добавлены настройки пользователя и управление уведомлениями В код добавлены новые методы для работы с настройками пользователя, включая создание таблицы `UserSettings`, отображение настроек и изменение состояния уведомлений. Метод `CreateUserSettingsTableIfNotExists` создает таблицу, если она не существует, и обрабатывает возможные ошибки при создании. Метод `ShowUserSettings` загружает текущие настройки пользователя из базы данных и отправляет сообщение с возможностью изменения состояния уведомлений. В обработке обновлений добавлена логика для обработки нажатий на кнопки, связанных с настройками пользователя и переключением уведомлений. Метод `NotifyUserAboutStatusChange` теперь проверяет, включены ли уведомления для пользователя, перед отправкой сообщения о смене статуса заявки. Метод `ToggleNotifications` изменяет состояние уведомлений для пользователя и обновляет соответствующую запись в базе данных, а также отображает обновленные настройки. В меню добавлена кнопка для перехода к настройкам пользователя.
2025-03-20 11:02:41 +07:00
await botClient.SendMessage(chatId, "Произошла ошибка при обновлении настроек.");
}
}
private static async Task SendMainMenu(ITelegramBotClient botClient, long chatId)
{
var menuButtons = new List<InlineKeyboardButton[]>
{
new[]
{
InlineKeyboardButton.WithCallbackData("📝 Подать заявку", "report"),
InlineKeyboardButton.WithCallbackData("⚙️ Настройки", "user_settings")
Добавлены настройки пользователя и управление уведомлениями В код добавлены новые методы для работы с настройками пользователя, включая создание таблицы `UserSettings`, отображение настроек и изменение состояния уведомлений. Метод `CreateUserSettingsTableIfNotExists` создает таблицу, если она не существует, и обрабатывает возможные ошибки при создании. Метод `ShowUserSettings` загружает текущие настройки пользователя из базы данных и отправляет сообщение с возможностью изменения состояния уведомлений. В обработке обновлений добавлена логика для обработки нажатий на кнопки, связанных с настройками пользователя и переключением уведомлений. Метод `NotifyUserAboutStatusChange` теперь проверяет, включены ли уведомления для пользователя, перед отправкой сообщения о смене статуса заявки. Метод `ToggleNotifications` изменяет состояние уведомлений для пользователя и обновляет соответствующую запись в базе данных, а также отображает обновленные настройки. В меню добавлена кнопка для перехода к настройкам пользователя.
2025-03-20 11:02:41 +07:00
},
new[]
{
InlineKeyboardButton.WithCallbackData("📋 Мои заявки", "user_reports")
}
};
// Добавляем кнопку панели администратора только если пользователь является админом или суперпользователем
if (admins.Contains(chatId))
Добавлены настройки пользователя и управление уведомлениями В код добавлены новые методы для работы с настройками пользователя, включая создание таблицы `UserSettings`, отображение настроек и изменение состояния уведомлений. Метод `CreateUserSettingsTableIfNotExists` создает таблицу, если она не существует, и обрабатывает возможные ошибки при создании. Метод `ShowUserSettings` загружает текущие настройки пользователя из базы данных и отправляет сообщение с возможностью изменения состояния уведомлений. В обработке обновлений добавлена логика для обработки нажатий на кнопки, связанных с настройками пользователя и переключением уведомлений. Метод `NotifyUserAboutStatusChange` теперь проверяет, включены ли уведомления для пользователя, перед отправкой сообщения о смене статуса заявки. Метод `ToggleNotifications` изменяет состояние уведомлений для пользователя и обновляет соответствующую запись в базе данных, а также отображает обновленные настройки. В меню добавлена кнопка для перехода к настройкам пользователя.
2025-03-20 11:02:41 +07:00
{
menuButtons.Add(new[]
{
InlineKeyboardButton.WithCallbackData("🔐 Панель администратора", "admin_panel")
});
}
var keyboard = new InlineKeyboardMarkup(menuButtons);
await botClient.SendMessage(
chatId: chatId,
text: "Главное меню:",
replyMarkup: keyboard
);
}
private static async Task SendAdminPanel(ITelegramBotClient botClient, long chatId)
{
var buttonsRows = new List<InlineKeyboardButton[]>
{
new[]
{
InlineKeyboardButton.WithCallbackData("📋 Менеджер заявок", "view_reports"),
InlineKeyboardButton.WithCallbackData("🗃️ Архив заявок", "view_archived_reports")
},
new[]
{
InlineKeyboardButton.WithCallbackData("⚙️ Личный кабинет", "admin_settings")
}
};
// Добавлять кнопку "Удалить все заявки" только для суперадминов
if (superAdmins.Contains(chatId))
{
buttonsRows.Add(new[]
{
InlineKeyboardButton.WithCallbackData("❌ Удалить все заявки", "delete_all_reports")
});
}
// Кнопка возврата в главное меню
buttonsRows.Add(new[]
{
InlineKeyboardButton.WithCallbackData("🏠 Главное меню", "main_menu")
});
var keyboard = new InlineKeyboardMarkup(buttonsRows);
await botClient.SendMessage(
chatId: chatId,
text: "🔐 <b>Панель администраторов:</b>",
parseMode: ParseMode.Html,
replyMarkup: keyboard
);
}
private static async Task ViewReports(ITelegramBotClient botClient, long chatId)
{
string connectionString = "Data Source=bot.db";
try
{
using (var connection = new SqliteConnection(connectionString))
{
await connection.OpenAsync();
var command = connection.CreateCommand();
command.CommandText = "SELECT Id, Description, Status, Priority FROM Reports WHERE Status != 'закрыта'";
var buttons = new List<InlineKeyboardButton[]>();
using (var reader = await command.ExecuteReaderAsync())
{
while (await reader.ReadAsync())
{
long id = reader.GetInt64(0);
string description = reader.GetString(1).Substring(0, Math.Min(20, reader.GetString(1).Length));
string status = reader.GetString(2);
string priority = reader.GetString(3);
string statusEmoji = GetStatusEmoji(status);
2025-03-19 23:21:03 +07:00
string priorityMarker = priority.ToLower() == "высокий" ? "⚠️ " : "";
buttons.Add(new[]
{
InlineKeyboardButton.WithCallbackData(
2025-03-19 23:21:03 +07:00
$"{priorityMarker}#{id} - {statusEmoji} {status} - {description}...",
$"report_{id}")
});
}
}
// Добавляем кнопки навигации
buttons.Add(new[]
{
InlineKeyboardButton.WithCallbackData("🔙 Назад", "back_to_admin_panel"),
InlineKeyboardButton.WithCallbackData("🏠 Главное меню", "main_menu")
});
await botClient.SendMessage(
2025-03-19 23:21:03 +07:00
chatId: chatId,
text: "Список заявок:",
replyMarkup: new InlineKeyboardMarkup(buttons)
);
}
}
catch (Exception ex)
{
Log.Error($"Ошибка: {ex.Message}");
await botClient.SendMessage(chatId, "Ошибка при получении заявок");
}
}
2025-03-19 23:21:03 +07:00
private static async Task ViewArchivedReports(ITelegramBotClient botClient, long chatId)
{
string connectionString = "Data Source=bot.db";
try
{
using (var connection = new SqliteConnection(connectionString))
{
await connection.OpenAsync();
var command = connection.CreateCommand();
command.CommandText = "SELECT Id, Description, Status, Priority FROM Reports WHERE Status = 'закрыта'";
var buttons = new List<InlineKeyboardButton[]>();
using (var reader = await command.ExecuteReaderAsync())
{
while (await reader.ReadAsync())
{
long id = reader.GetInt64(0);
string description = reader.GetString(1).Substring(0, Math.Min(20, reader.GetString(1).Length));
string status = reader.GetString(2);
string priority = reader.GetString(3);
string statusEmoji = GetStatusEmoji(status);
2025-03-19 23:21:03 +07:00
string priorityMarker = priority.ToLower() == "высокий" ? "⚠️ " : "";
buttons.Add(new[]
{
InlineKeyboardButton.WithCallbackData(
2025-03-19 23:21:03 +07:00
$"{priorityMarker}#{id} - {statusEmoji} {status} - {description}...",
$"report_{id}")
});
}
}
// Добавляем кнопки навигации
buttons.Add(new[]
{
InlineKeyboardButton.WithCallbackData("🔙 Назад", "back_to_admin_panel"),
InlineKeyboardButton.WithCallbackData("🏠 Главное меню", "main_menu")
});
await botClient.SendMessage(
2025-03-19 23:21:03 +07:00
chatId: chatId,
text: "Архив заявок:",
replyMarkup: new InlineKeyboardMarkup(buttons)
);
}
}
catch (Exception ex)
{
Log.Error($"Ошибка: {ex.Message}");
await botClient.SendMessage(chatId, "Ошибка при получении архива заявок");
2025-03-19 23:21:03 +07:00
}
}
2025-03-19 23:09:50 +07:00
2025-03-19 23:11:40 +07:00
2025-03-19 23:21:03 +07:00
private static async Task ShowReportDetails(ITelegramBotClient botClient, long chatId, long reportId, int messageId)
{
try
{
using (var connection = new SqliteConnection("Data Source=bot.db"))
{
await connection.OpenAsync();
var command = connection.CreateCommand();
command.CommandText = "SELECT Priority, Room, Description, ReporterName, Status, DateCreated, AdminId, ChatId FROM Reports WHERE Id = @id";
command.Parameters.AddWithValue("@id", reportId);
using (var reader = await command.ExecuteReaderAsync())
{
if (await reader.ReadAsync())
{
string priority = reader.GetString(0);
string room = reader.GetString(1);
string description = reader.GetString(2);
string reporterName = reader.GetString(3);
string status = reader.GetString(4);
string dateCreated = reader.GetDateTime(5).ToString("yyyy-MM-dd HH:mm:ss");
long ownerChatId = reader.GetInt64(7);
// Проверяем существование столбца AdminId
long adminId = 0;
try
{
if (!reader.IsDBNull(6))
adminId = reader.GetInt64(6);
}
catch
{
Log.Warning($"Столбец AdminId для заявки {reportId} не найден или содержит NULL");
}
string adminFullName = adminId > 0 && adminFullNames.ContainsKey(adminId)
2025-03-20 10:09:22 +07:00
? adminFullNames[adminId]
: "Не назначен";
string priorityEmoji = GetPriorityEmoji(priority);
string statusEmoji = GetStatusEmoji(status);
InlineKeyboardMarkup keyboard;
// Разные клавиатуры для админов и обычных пользователей
if (admins.Contains(chatId))
2025-03-20 10:09:22 +07:00
{
// Клавиатура для администраторов с возможностью изменения статуса
keyboard = new InlineKeyboardMarkup(new[]
{
new[]
{
InlineKeyboardButton.WithCallbackData("🟡 Ожидает", $"status_{reportId}_ожидает"),
InlineKeyboardButton.WithCallbackData("🔵 В работе", $"status_{reportId}_в работе")
},
new[]
{
InlineKeyboardButton.WithCallbackData("🟢 Закрыта", $"status_{reportId}_закрыта")
},
new[]
{
InlineKeyboardButton.WithCallbackData("❌ Удалить заявку", $"delete_{reportId}")
},
new[]
{
InlineKeyboardButton.WithCallbackData("Назад", "back_to_list"),
InlineKeyboardButton.WithCallbackData("Главное меню", "main_menu")
}
});
}
else
2025-03-20 10:09:22 +07:00
{
// Клавиатура для обычных пользователей - только удаление своих заявок
keyboard = new InlineKeyboardMarkup(new[]
{
new[]
{
InlineKeyboardButton.WithCallbackData("❌ Удалить заявку", $"delete_{reportId}")
},
new[]
{
InlineKeyboardButton.WithCallbackData("🔙 Назад к списку", "user_reports"),
InlineKeyboardButton.WithCallbackData("🏠 Главное меню", "main_menu")
}
});
2025-03-20 10:09:22 +07:00
}
string newText = $"Заявка #{reportId}\n\n" +
$"Приоритет: {priorityEmoji} {priority}\n" +
$"Кабинет: {room}\n" +
$"Описание: {description}\n" +
$"ФИО: {reporterName}\n" +
$"Статус: {statusEmoji} {status}\n" +
$"Дата создания: {dateCreated}\n" +
$"Администратор: {adminFullName}";
await botClient.SendMessage(
chatId: chatId,
text: newText,
replyMarkup: keyboard
2025-03-20 10:09:22 +07:00
);
}
else
{
// Если заявка не найдена
await botClient.SendMessage(
chatId: chatId,
text: $"⚠️ Заявка #{reportId} не найдена!"
);
Log.Warning($"Заявка #{reportId} не найдена при попытке просмотра деталей.");
await Task.Delay(2000);
// Возвращаем к нужному списку в зависимости от роли пользователя
if (admins.Contains(chatId))
{
await ViewReports(botClient, chatId);
}
else
{
await ViewUserReports(botClient, chatId);
}
}
}
}
}
catch (Exception ex)
{
2025-03-20 10:09:22 +07:00
Log.Error($"Ошибка при отображении деталей заявки #{reportId}: {ex.Message}");
await botClient.SendMessage(
chatId: chatId,
text: $"Произошла ошибка при загрузке заявки #{reportId}."
);
}
}
2025-03-20 10:09:22 +07:00
// Метод для удаления администратора из базы данных
private static async Task RemoveAdminFromDatabase(long chatId)
{
try
{
using (var connection = new SqliteConnection("Data Source=bot.db"))
{
await connection.OpenAsync();
var command = connection.CreateCommand();
command.CommandText = "DELETE FROM Admins WHERE ChatId = @chatId";
command.Parameters.AddWithValue("@chatId", chatId);
int rowsAffected = await command.ExecuteNonQueryAsync();
if (rowsAffected > 0)
{
admins.Remove(chatId);
Log.Information($"Администратор {chatId} удален из базы данных");
}
else
{
Log.Information($"Администратор {chatId} не найден в базе данных");
}
}
}
catch (Exception ex)
{
Log.Error($"Ошибка при удалении администратора из базы данных: {ex.Message}");
}
}
// Добавим метод для отображения раздела настроек администраторов
private static async Task ShowAdminSettings(ITelegramBotClient botClient, long chatId)
{
try
{
// Проверяем, что запрашивающий пользователь - администратор
if (!admins.Contains(chatId))
{
await botClient.SendMessage(
chatId: chatId,
text: "⛔ У вас нет прав для доступа к настройкам администраторов."
);
await Task.Delay(2000);
await SendMainMenu(botClient, chatId);
return;
}
bool isSuperAdmin = superAdmins.Contains(chatId);
var buttons = new List<InlineKeyboardButton[]>();
2025-03-19 22:51:37 +07:00
// Разные опции в зависимости от типа пользователя
if (isSuperAdmin)
{
buttons.Add(new[] {
InlineKeyboardButton.WithCallbackData("👥 Управление администраторами", "view_admins")
});
}
// Настройки уведомлений для всех типов администраторов
bool notifyOnPendingReports = true;
2025-03-19 22:51:37 +07:00
using (var connection = new SqliteConnection("Data Source=bot.db"))
{
2025-03-19 22:51:37 +07:00
await connection.OpenAsync();
var command = connection.CreateCommand();
command.CommandText = "SELECT NotifyOnPendingReports FROM Admins WHERE ChatId = @chatId";
command.Parameters.AddWithValue("@chatId", chatId);
2025-03-19 22:51:37 +07:00
var result = await command.ExecuteScalarAsync();
if (result != null && result != DBNull.Value)
2025-03-19 22:51:37 +07:00
{
notifyOnPendingReports = Convert.ToInt32(result) == 1;
2025-03-19 22:51:37 +07:00
}
}
string notificationStatus = notifyOnPendingReports ? "✅ Включены" : "❌ Отключены";
string toggleAction = notifyOnPendingReports ? "disable_notifications" : "enable_notifications";
2025-03-19 22:51:37 +07:00
buttons.Add(new[] {
InlineKeyboardButton.WithCallbackData($"Уведомления о просрочке: {notificationStatus}", $"{toggleAction}_{chatId}")
});
2025-03-19 22:51:37 +07:00
// Кнопка выхода из режима администратора или суперпользователя (текст зависит от роли)
buttons.Add(new[] {
InlineKeyboardButton.WithCallbackData(
isSuperAdmin ? "🚪 Выйти из режима суперпользователя" : "🚪 Выйти из режима администратора",
"leave_admin")
});
2025-03-19 22:51:37 +07:00
buttons.Add(new[] {
InlineKeyboardButton.WithCallbackData("🔙 Назад к панели администратора", "admin_panel"),
InlineKeyboardButton.WithCallbackData("🏠 Главное меню", "main_menu")
});
2025-03-19 22:51:37 +07:00
var keyboard = new InlineKeyboardMarkup(buttons);
string roleName = isSuperAdmin ? "суперпользователя" : "администратора";
await botClient.SendMessage(
chatId: chatId,
text: $"⚙️ <b>Настройки {roleName}</b>\n\n" +
$"Ваша роль: {(isSuperAdmin ? "👑 Суперпользователь" : "👤 Администратор")}\n" +
$"Уведомления о просрочках: {notificationStatus}\n\n" +
$"Выберите действие:",
parseMode: ParseMode.Html,
replyMarkup: keyboard
);
}
catch (Exception ex)
{
Log.Error($"Ошибка при отображении настроек администратора: {ex.Message}");
}
}
private static async Task ToggleAdminNotifications(long adminId, bool enable)
{
try
{
using (var connection = new SqliteConnection("Data Source=bot.db"))
{
await connection.OpenAsync();
var command = connection.CreateCommand();
command.CommandText = "UPDATE Admins SET NotifyOnPendingReports = @notify WHERE ChatId = @chatId";
command.Parameters.AddWithValue("@notify", enable ? 1 : 0);
command.Parameters.AddWithValue("@chatId", adminId);
await command.ExecuteNonQueryAsync();
Log.Information($"Уведомления для администратора {adminId} {(enable ? "включены" : "отключены")}");
}
}
catch (Exception ex)
{
Log.Error($"Ошибка при переключении уведомлений для администратора {adminId}: {ex.Message}");
}
}
private static async Task NotifyAdminsAboutWorkAssignment(long reportId, long changerId)
{
try
{
// Получаем данные о заявке
string description = "";
string priority = "";
string room = "";
string changerFullName = adminFullNames[changerId];
using (var connection = new SqliteConnection("Data Source=bot.db"))
{
await connection.OpenAsync();
var command = connection.CreateCommand();
command.CommandText = "SELECT Description, Priority, Room FROM Reports WHERE Id = @id";
command.Parameters.AddWithValue("@id", reportId);
using (var reader = await command.ExecuteReaderAsync())
{
if (await reader.ReadAsync())
{
description = reader.GetString(0);
priority = reader.GetString(1);
room = reader.GetString(2);
}
}
}
foreach (var adminId in admins)
{
// Не уведомляем админа, который сам взял заявку в работу
if (adminId == changerId) continue;
string priorityEmoji = GetPriorityEmoji(priority);
var keyboard = new InlineKeyboardMarkup(new[]
{
new[]
{
InlineKeyboardButton.WithCallbackData("📝 Посмотреть детали", $"report_{reportId}")
}
});
await _botClient.SendMessage(
chatId: adminId,
text: $"{priorityEmoji} <b>Заявка #{reportId} взята в работу администратором {changerFullName}</b>\n\n" +
$"<b>Приоритет:</b> {priority}\n" +
$"<b>Кабинет:</b> {room}\n" +
$"<b>Фрагмент описания:</b> {description.Substring(0, Math.Min(50, description.Length))}...",
parseMode: ParseMode.Html,
replyMarkup: keyboard
);
Log.Information($"Уведомление о взятии в работу заявки #{reportId} отправлено администратору {adminId}");
}
}
catch (Exception ex)
{
Log.Error($"Ошибка при отправке уведомлений о взятии в работу: {ex.Message}");
}
}
private static async Task UpdateReportStatus(long reportId, string newStatus, long changerId)
{
try
{
if (!admins.Contains(changerId))
{
Log.Warning($"Попытка изменения статуса пользователем без прав администратора: {changerId}");
return; // Прерываем выполнение, если пользователь не администратор
}
string oldStatus = "";
long userChatId = 0;
// Сначала получаем текущий статус и chatId пользователя
using (var connection = new SqliteConnection("Data Source=bot.db"))
{
await connection.OpenAsync();
var getStatusCommand = connection.CreateCommand();
getStatusCommand.CommandText = "SELECT Status, ChatId FROM Reports WHERE Id = @id";
getStatusCommand.Parameters.AddWithValue("@id", reportId);
using (var reader = await getStatusCommand.ExecuteReaderAsync())
{
if (await reader.ReadAsync())
{
oldStatus = reader.GetString(0);
userChatId = reader.GetInt64(1);
}
}
}
// Если статус не изменился, прерываем выполнение
if (oldStatus == newStatus) return;
// Обновляем статус и сохраняем ID администратора
using (var connection = new SqliteConnection("Data Source=bot.db"))
{
await connection.OpenAsync();
var command = connection.CreateCommand();
command.CommandText = "UPDATE Reports SET Status = @status, AdminId = @adminId WHERE Id = @id";
command.Parameters.AddWithValue("@status", newStatus);
command.Parameters.AddWithValue("@adminId", changerId);
command.Parameters.AddWithValue("@id", reportId);
await command.ExecuteNonQueryAsync();
// Уведомляем администраторов об изменении статуса
await NotifyAdminsAboutStatusChange(reportId, newStatus, oldStatus, changerId);
// Уведомляем пользователя об изменении статуса
await NotifyUserAboutStatusChange(userChatId, reportId, newStatus);
// Уведомляем администраторов, если заявка взята в работу
if (newStatus == "в работе")
{
await NotifyAdminsAboutWorkAssignment(reportId, changerId);
}
// Перезапускаем мониторинг, если статус изменился обратно на "ожидает"
if (newStatus == "ожидает")
{
var cts = new CancellationTokenSource();
_ = Task.Run(() => MonitorReportStatus(reportId, cts.Token));
}
}
}
catch (Exception ex)
{
Log.Error($"Ошибка при обновлении статуса заявки: {ex.Message}");
}
}
private static async Task SaveReportToDatabase(long chatId, Report report)
2025-03-17 14:53:01 +07:00
{
string connectionString = "Data Source=bot.db"; // Используем SQLite
try
{
using (var connection = new SqliteConnection(connectionString))
{
await connection.OpenAsync();
var insertCommand = connection.CreateCommand();
insertCommand.CommandText =
@"
INSERT INTO Reports (ChatId, Priority, Room, Description, ReporterName, Status)
VALUES (@ChatId, @Priority, @Room, @Description, @ReporterName, 'ожидает');
SELECT last_insert_rowid();
";
2025-03-17 14:53:01 +07:00
insertCommand.Parameters.AddWithValue("@ChatId", chatId);
insertCommand.Parameters.AddWithValue("@Priority", report.Priority);
insertCommand.Parameters.AddWithValue("@Room", report.Room);
insertCommand.Parameters.AddWithValue("@Description", report.Description);
insertCommand.Parameters.AddWithValue("@ReporterName", report.ReporterName);
2025-03-17 14:53:01 +07:00
long reportId = Convert.ToInt64(await insertCommand.ExecuteScalarAsync());
Log.Information($"Заявка от пользователя {chatId} успешно сохранена с ID {reportId}.");
// Уведомляем администраторов о новой заявке
await NotifyAdminsAboutNewReport(reportId, report);
// Запускаем мониторинг статуса заявки
var cts = new CancellationTokenSource();
_ = Task.Run(() => MonitorReportStatus(reportId, cts.Token));
2025-03-17 14:53:01 +07:00
}
}
catch (Exception ex)
{
Log.Error($"Ошибка при сохранении заявки в базу данных: {ex.Message}");
}
}
// Обновляем метод CreateDatabaseIfNotExists
2025-03-17 15:07:41 +07:00
private static async Task CreateDatabaseIfNotExists()
{
string connectionString = "Data Source=bot.db"; // Путь к вашей базе данных
try
{
using (var connection = new SqliteConnection(connectionString))
{
await connection.OpenAsync();
2025-03-19 19:29:40 +07:00
// Проверяем, существует ли таблица Reports
var checkTableCommand = connection.CreateCommand();
checkTableCommand.CommandText = "PRAGMA table_info(Reports);";
var tableInfo = await checkTableCommand.ExecuteReaderAsync();
var requiredColumns = new HashSet<string> { "Id", "ChatId", "Priority", "Room", "Description", "ReporterName", "DateCreated", "Status", "AdminId" };
2025-03-19 19:31:45 +07:00
var existingColumns = new HashSet<string>();
2025-03-19 19:29:40 +07:00
while (await tableInfo.ReadAsync())
{
2025-03-19 19:32:58 +07:00
existingColumns.Add(tableInfo["name"]?.ToString() ?? string.Empty);
2025-03-19 19:29:40 +07:00
}
2025-03-19 19:31:45 +07:00
foreach (var column in requiredColumns)
2025-03-19 19:29:40 +07:00
{
2025-03-19 19:31:45 +07:00
if (!existingColumns.Contains(column))
{
var alterTableCommand = connection.CreateCommand();
switch (column)
{
case "Priority":
alterTableCommand.CommandText = "ALTER TABLE Reports ADD COLUMN Priority TEXT NOT NULL DEFAULT 'низкий';";
break;
case "Room":
2025-03-19 19:32:58 +07:00
alterTableCommand.CommandText = "ALTER TABLE Reports ADD COLUMN Room TEXT NOT NULL DEFAULT '';";
2025-03-19 19:31:45 +07:00
break;
case "Description":
2025-03-19 19:32:58 +07:00
alterTableCommand.CommandText = "ALTER TABLE Reports ADD COLUMN Description TEXT NOT NULL DEFAULT '';";
2025-03-19 19:31:45 +07:00
break;
case "ReporterName":
2025-03-19 19:32:58 +07:00
alterTableCommand.CommandText = "ALTER TABLE Reports ADD COLUMN ReporterName TEXT NOT NULL DEFAULT '';";
2025-03-19 19:31:45 +07:00
break;
case "DateCreated":
alterTableCommand.CommandText = "ALTER TABLE Reports ADD COLUMN DateCreated DATETIME DEFAULT CURRENT_TIMESTAMP;";
break;
case "Status":
alterTableCommand.CommandText = "ALTER TABLE Reports ADD COLUMN Status TEXT DEFAULT 'ожидает';";
break;
case "AdminId":
alterTableCommand.CommandText = "ALTER TABLE Reports ADD COLUMN AdminId INTEGER DEFAULT 0;";
break;
2025-03-19 19:31:45 +07:00
}
await alterTableCommand.ExecuteNonQueryAsync();
Log.Information($"Столбец {column} добавлен в таблицу Reports.");
}
2025-03-19 19:29:40 +07:00
}
// Создаем таблицу Reports, если её не существует
2025-03-17 15:07:41 +07:00
var createTableCommand = connection.CreateCommand();
createTableCommand.CommandText =
@"
CREATE TABLE IF NOT EXISTS Reports (
Id INTEGER PRIMARY KEY AUTOINCREMENT,
ChatId INTEGER NOT NULL,
Priority TEXT NOT NULL,
Room TEXT NOT NULL,
Description TEXT NOT NULL,
ReporterName TEXT NOT NULL,
DateCreated DATETIME DEFAULT CURRENT_TIMESTAMP,
Status TEXT DEFAULT 'ожидает',
AdminId INTEGER DEFAULT 0
);
";
2025-03-17 15:07:41 +07:00
await createTableCommand.ExecuteNonQueryAsync();
Log.Information("Таблица Reports успешно создана (если её не было).");
// Создаем таблицу администраторов
await CreateAdminsTableIfNotExists();
2025-03-17 15:07:41 +07:00
}
}
catch (Exception ex)
{
Log.Error($"Ошибка при создании таблиц в базе данных: {ex.Message}");
2025-03-17 15:07:41 +07:00
}
}
private static Dictionary<long, int> userReportSteps = new Dictionary<long, int>();
private static Dictionary<long, Report> userReports = new Dictionary<long, Report>();
private class Report
{
public string Priority { get; set; } = string.Empty;
public string Room { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty;
public string ReporterName { get; set; } = string.Empty;
}
2025-03-19 20:05:10 +07:00
private static Task HandleErrorAsync(ITelegramBotClient botClient, Exception exception, CancellationToken cancellationToken)
{
2025-03-12 22:41:14 +07:00
Log.Error($"Ошибка в процессе работы с ботом: {exception.Message}");
2025-03-12 22:35:28 +07:00
Log.Error($"StackTrace: {exception.StackTrace}");
return Task.CompletedTask;
}
// Добавим метод для создания таблицы администраторов
private static async Task CreateAdminsTableIfNotExists()
{
try
{
using (var connection = new SqliteConnection("Data Source=bot.db"))
{
await connection.OpenAsync();
var command = connection.CreateCommand();
command.CommandText = @"
CREATE TABLE IF NOT EXISTS Admins (
Id INTEGER PRIMARY KEY AUTOINCREMENT,
ChatId INTEGER NOT NULL UNIQUE,
FullName TEXT NOT NULL,
NotifyOnPendingReports INTEGER NOT NULL DEFAULT 1,
IsSuperAdmin INTEGER NOT NULL DEFAULT 0
);";
await command.ExecuteNonQueryAsync();
Log.Information("Таблица Admins успешно создана (если её не было).");
2025-03-20 09:56:06 +07:00
// Проверяем наличие столбца NotifyOnPendingReports
2025-03-20 09:56:06 +07:00
command.CommandText = "PRAGMA table_info(Admins);";
var tableInfo = await command.ExecuteReaderAsync();
bool notifyColumnExists = false;
bool superAdminColumnExists = false;
2025-03-20 09:56:06 +07:00
while (await tableInfo.ReadAsync())
{
if (tableInfo["name"].ToString() == "NotifyOnPendingReports")
2025-03-20 09:56:06 +07:00
{
notifyColumnExists = true;
}
if (tableInfo["name"].ToString() == "IsSuperAdmin")
{
superAdminColumnExists = true;
2025-03-20 09:56:06 +07:00
}
}
await tableInfo.CloseAsync(); // Закрываем DataReader перед изменением CommandText
if (!notifyColumnExists)
2025-03-20 09:56:06 +07:00
{
command.CommandText = "ALTER TABLE Admins ADD COLUMN NotifyOnPendingReports INTEGER NOT NULL DEFAULT 1;";
2025-03-20 09:56:06 +07:00
await command.ExecuteNonQueryAsync();
Log.Information("Столбец NotifyOnPendingReports добавлен в таблицу Admins.");
2025-03-20 09:56:06 +07:00
}
// Добавляем столбец IsSuperAdmin, если его нет
if (!superAdminColumnExists)
{
command.CommandText = "ALTER TABLE Admins ADD COLUMN IsSuperAdmin INTEGER NOT NULL DEFAULT 0;";
await command.ExecuteNonQueryAsync();
Log.Information("Столбец IsSuperAdmin добавлен в таблицу Admins.");
}
}
}
catch (Exception ex)
{
Log.Error($"Ошибка при создании таблицы Admins: {ex.Message}");
}
}
2025-03-20 09:56:06 +07:00
// Метод для сохранения администратора в базу данных
private static async Task SaveAdminToDatabase(long chatId, string fullName)
{
try
{
using (var connection = new SqliteConnection("Data Source=bot.db"))
{
await connection.OpenAsync();
// Проверяем, существует ли уже такой админ
var checkCommand = connection.CreateCommand();
checkCommand.CommandText = "SELECT COUNT(*) FROM Admins WHERE ChatId = @chatId";
checkCommand.Parameters.AddWithValue("@chatId", chatId);
int count = Convert.ToInt32(await checkCommand.ExecuteScalarAsync());
if (count == 0)
{
// Добавляем нового админа (явно указываем IsSuperAdmin = 0)
var insertCommand = connection.CreateCommand();
insertCommand.CommandText = "INSERT INTO Admins (ChatId, FullName, IsSuperAdmin) VALUES (@chatId, @fullName, 0)";
insertCommand.Parameters.AddWithValue("@chatId", chatId);
insertCommand.Parameters.AddWithValue("@fullName", fullName);
await insertCommand.ExecuteNonQueryAsync();
Log.Information($"Администратор {chatId} добавлен в базу данных");
}
else
{
// Обновляем данные, если пользователь уже существует
var updateCommand = connection.CreateCommand();
updateCommand.CommandText = "UPDATE Admins SET FullName = @fullName WHERE ChatId = @chatId";
updateCommand.Parameters.AddWithValue("@chatId", chatId);
updateCommand.Parameters.AddWithValue("@fullName", fullName);
await updateCommand.ExecuteNonQueryAsync();
Log.Information($"Данные администратора {chatId} обновлены");
}
}
}
catch (Exception ex)
{
Log.Error($"Ошибка при сохранении администратора в базу данных: {ex.Message}");
}
}
// Метод для загрузки администраторов из базы данных
private static async Task LoadAdminsFromDatabase()
{
try
{
using (var connection = new SqliteConnection("Data Source=bot.db"))
{
await connection.OpenAsync();
var command = connection.CreateCommand();
command.CommandText = "SELECT ChatId, FullName, IsSuperAdmin FROM Admins";
using (var reader = await command.ExecuteReaderAsync())
{
while (await reader.ReadAsync())
{
long adminId = reader.GetInt64(0);
string fullName = reader.GetString(1);
bool isSuperAdmin = reader.GetInt32(2) == 1;
admins.Add(adminId);
adminFullNames[adminId] = fullName;
// Добавляем в список суперпользователей, если это суперадмин
if (isSuperAdmin)
{
superAdmins.Add(adminId);
}
Log.Information($"Загружен {(isSuperAdmin ? "суперпользователь" : "администратор")} с ID: {adminId}, ФИО: {fullName}");
}
}
}
Log.Information($"Загружено {admins.Count} администраторов из базы данных, из них {superAdmins.Count} суперпользователей");
}
catch (Exception ex)
{
Log.Error($"Ошибка при загрузке администраторов из базы данных: {ex.Message}");
}
}
private static async Task SaveSuperAdminToDatabase(long chatId, string fullName)
{
try
{
using (var connection = new SqliteConnection("Data Source=bot.db"))
{
await connection.OpenAsync();
// Проверяем, существует ли уже такой админ
var checkCommand = connection.CreateCommand();
checkCommand.CommandText = "SELECT COUNT(*) FROM Admins WHERE ChatId = @chatId";
checkCommand.Parameters.AddWithValue("@chatId", chatId);
int count = Convert.ToInt32(await checkCommand.ExecuteScalarAsync());
if (count == 0)
{
// Добавляем нового суперадмина
var insertCommand = connection.CreateCommand();
insertCommand.CommandText = "INSERT INTO Admins (ChatId, FullName, IsSuperAdmin) VALUES (@chatId, @fullName, 1)";
insertCommand.Parameters.AddWithValue("@chatId", chatId);
insertCommand.Parameters.AddWithValue("@fullName", fullName);
await insertCommand.ExecuteNonQueryAsync();
Log.Information($"Суперпользователь {chatId} добавлен в базу данных");
}
else
{
// Обновляем существующего пользователя до суперадмина
var updateCommand = connection.CreateCommand();
updateCommand.CommandText = "UPDATE Admins SET IsSuperAdmin = 1, FullName = @fullName WHERE ChatId = @chatId";
updateCommand.Parameters.AddWithValue("@chatId", chatId);
updateCommand.Parameters.AddWithValue("@fullName", fullName);
await updateCommand.ExecuteNonQueryAsync();
Log.Information($"Пользователь {chatId} повышен до суперпользователя");
}
}
}
catch (Exception ex)
{
Log.Error($"Ошибка при сохранении суперпользователя в базу данных: {ex.Message}");
}
}
private static async Task RemoveSelfFromAdmins(long chatId)
{
try
{
using (var connection = new SqliteConnection("Data Source=bot.db"))
{
await connection.OpenAsync();
var command = connection.CreateCommand();
command.CommandText = "DELETE FROM Admins WHERE ChatId = @chatId";
command.Parameters.AddWithValue("@chatId", chatId);
int rowsAffected = await command.ExecuteNonQueryAsync();
if (rowsAffected > 0)
{
admins.Remove(chatId);
superAdmins.Remove(chatId);
if (adminFullNames.ContainsKey(chatId))
{
adminFullNames.Remove(chatId);
}
Log.Information($"Пользователь {chatId} удалил себя из администраторов");
}
else
{
Log.Information($"Администратор {chatId} не найден в базе данных");
}
}
}
catch (Exception ex)
{
Log.Error($"Ошибка при удалении себя из администраторов: {ex.Message}");
}
}
private static async Task ShowAdminsList(ITelegramBotClient botClient, long chatId)
{
try
{
// Проверяем, что запрашивающий пользователь - администратор
if (!admins.Contains(chatId))
{
await botClient.SendMessage(
chatId: chatId,
text: "⛔ У вас нет прав для просмотра списка администраторов."
);
return;
}
// Получаем список всех администраторов из базы данных
var adminsList = new List<(long chatId, string username, bool isSuperAdmin)>();
using (var connection = new SqliteConnection("Data Source=bot.db"))
{
await connection.OpenAsync();
var command = connection.CreateCommand();
command.CommandText = "SELECT ChatId, FullName, IsSuperAdmin FROM Admins";
using (var reader = await command.ExecuteReaderAsync())
{
while (await reader.ReadAsync())
{
long adminId = reader.GetInt64(0);
string fullName = reader.GetString(1);
bool isSuperAdmin = reader.GetInt32(2) == 1;
adminsList.Add((adminId, fullName, isSuperAdmin));
}
}
}
// Формируем сообщение
if (adminsList.Count == 0)
{
await botClient.SendMessage(
chatId: chatId,
text: "⚠️ В системе нет зарегистрированных администраторов."
);
return;
}
var buttons = new List<InlineKeyboardButton[]>();
var messageText = new System.Text.StringBuilder();
messageText.AppendLine("📋 <b>Список администраторов:</b>\n");
bool isSuperUser = superAdmins.Contains(chatId);
for (int i = 0; i < adminsList.Count; i++)
{
var (adminId, username, adminIsSuperAdmin) = adminsList[i];
string role = adminIsSuperAdmin ? "👑 Суперпользователь" : "👤 Администратор";
messageText.AppendLine($"{i + 1}. {username} (ID: {adminId}) - {role}");
// Кнопка удаления доступна только суперпользователям и только для других администраторов
if (isSuperUser && adminId != chatId)
{
buttons.Add(new[] {
InlineKeyboardButton.WithCallbackData($"❌ Удалить {username}", $"removeadmin_{adminId}")
});
}
}
// Кнопка "Назад" всегда доступна
buttons.Add(new[] {
InlineKeyboardButton.WithCallbackData("🔙 Назад", "admin_settings")
});
var keyboard = new InlineKeyboardMarkup(buttons);
await botClient.SendMessage(
chatId: chatId,
text: messageText.ToString(),
parseMode: ParseMode.Html,
replyMarkup: keyboard
);
}
catch (Exception ex)
{
Log.Error($"Ошибка при отображении списка администраторов: {ex.Message}");
await botClient.SendMessage(
chatId: chatId,
text: "❌ Произошла ошибка при отображении списка администраторов."
);
}
}
// Метод для уведомления администраторов о новой заявке
private static async Task NotifyAdminsAboutNewReport(long reportId, Report report)
{
try
{
foreach (var adminId in admins)
{
var statusEmoji = GetPriorityEmoji(report.Priority);
var keyboard = new InlineKeyboardMarkup(new[]
{
new[]
{
InlineKeyboardButton.WithCallbackData("📝 Посмотреть детали", $"report_{reportId}"),
InlineKeyboardButton.WithCallbackData("📋 Все заявки", "view_reports")
}
});
await _botClient.SendMessage(
chatId: adminId,
text: $"{statusEmoji} <b>Новая заявка #{reportId}</b>\n\n" +
$"<b>Приоритет:</b> {report.Priority}\n" +
$"<b>Кабинет:</b> {report.Room}\n" +
$"<b>Описание:</b> {report.Description}\n" +
$"<b>От:</b> {report.ReporterName}",
parseMode: ParseMode.Html,
replyMarkup: keyboard
);
Log.Information($"Уведомление о новой заявке #{reportId} отправлено администратору {adminId}");
}
}
catch (Exception ex)
{
Log.Error($"Ошибка при отправке уведомлений администраторам о новой заявке: {ex.Message}");
}
}
// Метод для уведомления администраторов об изменении статуса заявки
private static async Task NotifyAdminsAboutStatusChange(long reportId, string newStatus, string oldStatus, long changerId)
{
try
{
// Получаем данные о заявке
string description = "";
string priority = "";
string room = "";
using (var connection = new SqliteConnection("Data Source=bot.db"))
{
await connection.OpenAsync();
var command = connection.CreateCommand();
command.CommandText = "SELECT Description, Priority, Room FROM Reports WHERE Id = @id";
command.Parameters.AddWithValue("@id", reportId);
using (var reader = await command.ExecuteReaderAsync())
{
if (await reader.ReadAsync())
{
description = reader.GetString(0);
priority = reader.GetString(1);
room = reader.GetString(2);
}
}
}
foreach (var adminId in admins)
{
// Не уведомляем админа, который сам изменил статус
if (adminId == changerId) continue;
string statusEmoji = GetStatusEmoji(newStatus);
var keyboard = new InlineKeyboardMarkup(new[]
{
new[]
{
InlineKeyboardButton.WithCallbackData("📝 Посмотреть детали", $"report_{reportId}")
}
});
await _botClient.SendMessage(
chatId: adminId,
text: $"{statusEmoji} <b>Обновление статуса заявки #{reportId}</b>\n\n" +
$"<b>Приоритет:</b> {priority}\n" +
$"<b>Кабинет:</b> {room}\n" +
$"<b>Статус изменен:</b> {oldStatus} ➡️ {newStatus}\n\n" +
$"<b>Фрагмент описания:</b> {description.Substring(0, Math.Min(50, description.Length))}...",
parseMode: ParseMode.Html,
replyMarkup: keyboard
);
Log.Information($"Уведомление об изменении статуса заявки #{reportId} отправлено администратору {adminId}");
}
}
catch (Exception ex)
{
Log.Error($"Ошибка при отправке уведомлений об изменении статуса: {ex.Message}");
}
}
// Вспомогательный метод для получения emoji в зависимости от приоритета
private static string GetPriorityEmoji(string priority)
{
return priority.ToLower() switch
{
"high" or "высокий" => "🔴",
"medium" or "средний" => "🟠",
"low" or "низкий" => "🟢",
_ => ""
};
}
// Вспомогательный метод для получения emoji в зависимости от статуса
private static string GetStatusEmoji(string status)
{
return status.ToLower() switch
{
"ожидает" => "🟡",
"в работе" => "🔵",
"закрыта" => "🟢",
_ => ""
};
}
}