From 1967f41461ecdae8dd8761ce0aae68321f9027f1 Mon Sep 17 00:00:00 2001 From: 107 <107@DESKTOP-UP8U7M2> Date: Fri, 21 Mar 2025 09:56:56 +0700 Subject: [PATCH] =?UTF-8?q?=D1=82=D0=B8=D0=BF=D0=B0=20=D0=BD=D0=BE=D0=B2?= =?UTF-8?q?=D1=8B=D1=8F=20=D1=81=D0=B8=D1=81=D1=82=D0=B5=D0=BC=D0=B0=20?= =?UTF-8?q?=D0=B0=D0=B4=D0=BC=D0=B8=D0=BD=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Program.cs | 501 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 353 insertions(+), 148 deletions(-) diff --git a/Program.cs b/Program.cs index b6275e9..1f6a4aa 100644 --- a/Program.cs +++ b/Program.cs @@ -19,6 +19,9 @@ class Program private static HashSet admins = new HashSet(); // Хранение списка администраторов private static string adminPassword = "admin123"; // Простой пароль для администратора private static Dictionary adminFullNames = new Dictionary(); + private static HashSet superAdmins = new HashSet(); // Хранение списка суперпользователей + private static string superAdminPassword = "superadmin123"; // Пароль для суперпользователя + static async Task Main() { @@ -450,13 +453,76 @@ class Program else if (data != null && data.StartsWith("user_report_")) { long reportId = long.Parse(data.Substring("user_report_".Length)); - await ShowReportDetails(botClient, chatId, reportId, callbackQuery.Message.MessageId); + 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") + { + await RemoveSelfFromAdmins(chatId); + + var message = await botClient.SendMessage( + chatId: chatId, + text: "✅ Вы вышли из режима администратора." + ); + + 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); + } + } // Также добавим обработку команды /removeadmin в секцию обработки текстовых сообщений: // В блоке для обработки текстовых сообщений (после if (message.Text.StartsWith("/admin"))) @@ -649,7 +715,37 @@ class Program var receivedMessage = update.Message; Log.Information($"Получено сообщение от {receivedMessage.Chat.Id}: {receivedMessage.Text}"); - if (receivedMessage.Text.StartsWith("/admin")) + 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")) { string[] parts = receivedMessage.Text.Split(new[] { ' ' }, 3); // Разделяем на 3 части: команду, пароль и остаток как ФИО if (parts.Length >= 3 && parts[1] == adminPassword) @@ -657,7 +753,8 @@ class Program string fullName = parts[2]; // Вся оставшаяся строка - это ФИО admins.Add(receivedMessage.Chat.Id); adminFullNames[receivedMessage.Chat.Id] = fullName; - // Сохраняем администратора в базу данных + + // Сохраняем администратора в базу данных, убедившись что он не суперпользователь await SaveAdminToDatabase(receivedMessage.Chat.Id, fullName); var authMessage = await botClient.SendMessage(receivedMessage.Chat.Id, $"✅ Вы авторизованы как администратор, {fullName}!"); @@ -1308,101 +1405,6 @@ class Program } } - // Метод для отображения списка администраторов - 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)>(); - - using (var connection = new SqliteConnection("Data Source=bot.db")) - { - await connection.OpenAsync(); - var command = connection.CreateCommand(); - command.CommandText = "SELECT ChatId FROM Admins"; - - using (var reader = await command.ExecuteReaderAsync()) - { - while (await reader.ReadAsync()) - { - long adminId = reader.GetInt64(0); - string username = "Неизвестно"; - - // Пытаемся получить имя пользователя - try - { - var user = await botClient.GetChat(adminId); - username = user.Username ?? user.FirstName ?? "Неизвестно"; - } - catch - { - // Если возникает ошибка при получении информации о пользователе, - // просто используем "Неизвестно" - } - - adminsList.Add((adminId, username)); - } - } - } - - // Формируем сообщение - if (adminsList.Count == 0) - { - await botClient.SendMessage( - chatId: chatId, - text: "⚠️ В системе нет зарегистрированных администраторов." - ); - return; - } - - var buttons = new List(); - var messageText = new System.Text.StringBuilder(); - messageText.AppendLine("📋 Список администраторов:\n"); - - for (int i = 0; i < adminsList.Count; i++) - { - var (adminId, username) = adminsList[i]; - messageText.AppendLine($"{i + 1}. {username} (ID: {adminId})"); - - 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 ShowAdminSettings(ITelegramBotClient botClient, long chatId) @@ -1421,54 +1423,44 @@ class Program return; } - // Получаем список всех администраторов из базы данных - var adminsList = new List<(long chatId, string username, bool notifyOnPendingReports)>(); + bool isSuperAdmin = superAdmins.Contains(chatId); + var buttons = new List(); + // Разные опции в зависимости от типа пользователя + if (isSuperAdmin) + { + buttons.Add(new[] { + InlineKeyboardButton.WithCallbackData("👥 Управление администраторами", "view_admins") + }); + } + + // Настройки уведомлений для всех типов администраторов + bool notifyOnPendingReports = true; using (var connection = new SqliteConnection("Data Source=bot.db")) { await connection.OpenAsync(); var command = connection.CreateCommand(); - command.CommandText = "SELECT ChatId, FullName, NotifyOnPendingReports FROM Admins"; + command.CommandText = "SELECT NotifyOnPendingReports FROM Admins WHERE ChatId = @chatId"; + command.Parameters.AddWithValue("@chatId", chatId); - using (var reader = await command.ExecuteReaderAsync()) + var result = await command.ExecuteScalarAsync(); + if (result != null && result != DBNull.Value) { - while (await reader.ReadAsync()) - { - long adminId = reader.GetInt64(0); - string username = reader.GetString(1); - bool notifyOnPendingReports = reader.GetInt32(2) == 1; - - adminsList.Add((adminId, username, notifyOnPendingReports)); - } + notifyOnPendingReports = Convert.ToInt32(result) == 1; } } - // Формируем сообщение - if (adminsList.Count == 0) - { - await botClient.SendMessage( - chatId: chatId, - text: "⚠️ В системе нет зарегистрированных администраторов." - ); - return; - } + string notificationStatus = notifyOnPendingReports ? "✅ Включены" : "❌ Отключены"; + string toggleAction = notifyOnPendingReports ? "disable_notifications" : "enable_notifications"; - var buttons = new List(); - var messageText = new System.Text.StringBuilder(); - messageText.AppendLine("📋 Список администраторов:\n"); + buttons.Add(new[] { + InlineKeyboardButton.WithCallbackData($"Уведомления о просрочке: {notificationStatus}", $"{toggleAction}_{chatId}") + }); - foreach (var (adminId, username, notifyOnPendingReports) in adminsList) - { - string notificationStatus = notifyOnPendingReports ? "✅ Включены" : "❌ Отключены"; - string toggleAction = notifyOnPendingReports ? "disable_notifications" : "enable_notifications"; - - messageText.AppendLine($"{username} (ID: {adminId}) - Уведомления: {notificationStatus}"); - - buttons.Add(new[] { - InlineKeyboardButton.WithCallbackData($"❌ Удалить {username}", $"removeadmin_{adminId}"), - InlineKeyboardButton.WithCallbackData($"Уведомления: {notificationStatus}", $"{toggleAction}_{adminId}") - }); - } + // Кнопка выхода из режима администратора + buttons.Add(new[] { + InlineKeyboardButton.WithCallbackData("🚪 Выйти из режима администратора", "leave_admin") + }); buttons.Add(new[] { InlineKeyboardButton.WithCallbackData("🔙 Назад к панели администратора", "admin_panel"), @@ -1477,21 +1469,27 @@ class Program var keyboard = new InlineKeyboardMarkup(buttons); + string roleName = isSuperAdmin ? "суперпользователя" : "администратора"; + await botClient.SendMessage( chatId: chatId, - text: messageText.ToString(), + text: $"⚙️ Настройки {roleName}\n\n" + + $"Ваша роль: {(isSuperAdmin ? "👑 Суперпользователь" : "👤 Администратор")}\n" + + $"Уведомления о просрочках: {notificationStatus}\n\n" + + $"Выберите действие:", parseMode: ParseMode.Html, replyMarkup: keyboard ); } catch (Exception ex) { - Log.Error($"Ошибка при отображении настроек администраторов: {ex.Message}"); + Log.Error($"Ошибка при отображении настроек администратора: {ex.Message}"); } } + private static async Task ToggleAdminNotifications(long adminId, bool enable) { try @@ -1811,12 +1809,13 @@ class Program 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 - );"; + 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 успешно создана (если её не было)."); @@ -1824,13 +1823,17 @@ class Program command.CommandText = "PRAGMA table_info(Admins);"; var tableInfo = await command.ExecuteReaderAsync(); bool notifyColumnExists = false; + bool superAdminColumnExists = false; while (await tableInfo.ReadAsync()) { if (tableInfo["name"].ToString() == "NotifyOnPendingReports") { notifyColumnExists = true; - break; + } + if (tableInfo["name"].ToString() == "IsSuperAdmin") + { + superAdminColumnExists = true; } } @@ -1842,6 +1845,14 @@ class Program await command.ExecuteNonQueryAsync(); Log.Information("Столбец NotifyOnPendingReports добавлен в таблицу Admins."); } + + // Добавляем столбец 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) @@ -1854,6 +1865,7 @@ class Program + // Метод для сохранения администратора в базу данных private static async Task SaveAdminToDatabase(long chatId, string fullName) { @@ -1871,14 +1883,24 @@ class Program if (count == 0) { - // Добавляем нового админа + // Добавляем нового админа (явно указываем IsSuperAdmin = 0) var insertCommand = connection.CreateCommand(); - insertCommand.CommandText = "INSERT INTO Admins (ChatId, FullName) VALUES (@chatId, @fullName)"; + 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) @@ -1887,6 +1909,7 @@ class Program } } + // Метод для загрузки администраторов из базы данных private static async Task LoadAdminsFromDatabase() { @@ -1896,7 +1919,7 @@ class Program { await connection.OpenAsync(); var command = connection.CreateCommand(); - command.CommandText = "SELECT ChatId, FullName FROM Admins"; + command.CommandText = "SELECT ChatId, FullName, IsSuperAdmin FROM Admins"; using (var reader = await command.ExecuteReaderAsync()) { @@ -1904,13 +1927,22 @@ class Program { long adminId = reader.GetInt64(0); string fullName = reader.GetString(1); + bool isSuperAdmin = reader.GetInt32(2) == 1; + admins.Add(adminId); adminFullNames[adminId] = fullName; - Log.Information($"Загружен администратор с ID: {adminId}, ФИО: {fullName}"); + + // Добавляем в список суперпользователей, если это суперадмин + if (isSuperAdmin) + { + superAdmins.Add(adminId); + } + + Log.Information($"Загружен {(isSuperAdmin ? "суперпользователь" : "администратор")} с ID: {adminId}, ФИО: {fullName}"); } } } - Log.Information($"Загружено {admins.Count} администраторов из базы данных"); + Log.Information($"Загружено {admins.Count} администраторов из базы данных, из них {superAdmins.Count} суперпользователей"); } catch (Exception ex) { @@ -1918,6 +1950,179 @@ class Program } } + 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(); + var messageText = new System.Text.StringBuilder(); + messageText.AppendLine("📋 Список администраторов:\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("🚪 Выйти из режима администратора", "leave_admin") + }); + + 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) {