Удалены блоки кода, связанные с добавлением администратора, просмотром списка администраторов, доступом к админ-панели и обработкой отчетов. Изменен порядок проверки команды "/admins" для улучшения логики обработки текстовых сообщений.
1159 lines
50 KiB
C#
1159 lines
50 KiB
C#
using System;
|
||
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;
|
||
using Telegram.Bot.Types.ReplyMarkups;
|
||
|
||
class Program
|
||
{
|
||
private static string _botToken = string.Empty;
|
||
private static TelegramBotClient _botClient = null!;
|
||
private static Dictionary<long, bool> usersWaitingForReport = new Dictionary<long, bool>(); // Отслеживаем состояние пользователей
|
||
private static HashSet<long> admins = new HashSet<long>(); // Хранение списка администраторов
|
||
private static string adminPassword = "admin123"; // Простой пароль для администратора
|
||
|
||
static async Task Main()
|
||
{
|
||
// Загружаем конфигурацию из appsettings.json
|
||
try
|
||
{
|
||
Log.Information("Загрузка конфигурации из appsettings.json...");
|
||
var config = new ConfigurationBuilder()
|
||
.SetBasePath(AppContext.BaseDirectory) // <-- Используем правильный путь
|
||
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
|
||
.Build();
|
||
|
||
_botToken = config["BotToken"] ?? throw new Exception("BotToken не найден в конфигурации!");
|
||
Log.Information("Конфигурация успешно загружена");
|
||
}
|
||
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-бота...");
|
||
|
||
try
|
||
{
|
||
|
||
_botClient = new TelegramBotClient(_botToken);
|
||
var me = await _botClient.GetMe();
|
||
Log.Information($"Бот {me.FirstName} запущен! ID: {me.Id}");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log.Error($"Ошибка при подключении к Telegram API: {ex.Message}");
|
||
|
||
throw;
|
||
}
|
||
|
||
// Создание базы данных и таблицы, если они не существуют
|
||
await CreateDatabaseIfNotExists();
|
||
|
||
// Загрузка списка администраторов из базы данных
|
||
await LoadAdminsFromDatabase();
|
||
Log.Information($"Загружено {admins.Count} администраторов из базы данных");
|
||
|
||
var cts = new CancellationTokenSource();
|
||
Log.Information("Начало получения обновлений...");
|
||
|
||
try
|
||
{
|
||
// Применение StartReceiving для работы с задачами
|
||
_botClient.StartReceiving(HandleUpdateAsync, HandleErrorAsync, cancellationToken: cts.Token);
|
||
Log.Information("Получение обновлений успешно началось.");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log.Error($"Ошибка при запуске получения обновлений: {ex.Message}");
|
||
throw;
|
||
}
|
||
|
||
// Создание TaskCompletionSource для удержания процесса бота
|
||
var tcs = new TaskCompletionSource();
|
||
await tcs.Task; // Это заставит бота работать до тех пор, пока не будет отменен
|
||
|
||
// Ожидаем отмены через token
|
||
cts.Token.WaitHandle.WaitOne();
|
||
}
|
||
|
||
private static async Task DeletePreviousMessage(ITelegramBotClient botClient, long chatId, int messageId)
|
||
{
|
||
try
|
||
{
|
||
await botClient.DeleteMessage(chatId, messageId);
|
||
Log.Information($"Сообщение {messageId} в чате {chatId} удалено.");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log.Error($"Ошибка при удалении сообщения {messageId} в чате {chatId}: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
|
||
private static async Task HandleUpdateAsync(ITelegramBotClient botClient, Update update, CancellationToken cancellationToken)
|
||
{
|
||
try
|
||
{
|
||
// Обработка нажатий на кнопки
|
||
if (update.Type == UpdateType.CallbackQuery)
|
||
{
|
||
var callbackQuery = update.CallbackQuery;
|
||
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); // Удаляем предыдущее сообщение
|
||
}
|
||
|
||
if (callbackQuery?.Id != null)
|
||
{
|
||
await botClient.AnswerCallbackQuery(callbackQuery.Id); // Убираем "часики" у кнопки
|
||
}
|
||
|
||
if (data == "report")
|
||
{
|
||
usersWaitingForReport[chatId] = true;
|
||
userReportSteps[chatId] = 1;
|
||
userReports[chatId] = new Report();
|
||
var priorityKeyboard = new InlineKeyboardMarkup(new[]
|
||
{
|
||
new[]
|
||
{
|
||
InlineKeyboardButton.WithCallbackData("Низкий", "priority_low"),
|
||
InlineKeyboardButton.WithCallbackData("Средний", "priority_medium"),
|
||
InlineKeyboardButton.WithCallbackData("Высокий", "priority_high")
|
||
}
|
||
});
|
||
await botClient.SendMessage(chatId, "Пожалуйста, выберите приоритет:", replyMarkup: priorityKeyboard);
|
||
Log.Information($"Пользователь {chatId} начал создание заявки");
|
||
}
|
||
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);
|
||
}
|
||
}
|
||
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);
|
||
}
|
||
}
|
||
else if (data != null && data.StartsWith("removeadmin_"))
|
||
{
|
||
long adminIdToRemove = long.Parse(data.Substring(11));
|
||
|
||
// Проверяем, что пользователь является администратором
|
||
if (admins.Contains(chatId))
|
||
{
|
||
// Проверяем, не пытается ли пользователь удалить себя
|
||
if (adminIdToRemove == chatId)
|
||
{
|
||
await botClient.SendMessage(
|
||
chatId: chatId,
|
||
text: "⚠️ Вы не можете удалить себя из администраторов!"
|
||
);
|
||
}
|
||
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);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// Обработка текстовых сообщений
|
||
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);
|
||
|
||
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);
|
||
}
|
||
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;
|
||
}
|
||
|
||
// В блоке для обработки текстовых сообщений
|
||
if (message.Text == "/admins")
|
||
{
|
||
if (admins.Contains(message.Chat.Id))
|
||
{
|
||
await ShowAdminsList(botClient, message.Chat.Id);
|
||
}
|
||
else
|
||
{
|
||
await botClient.SendMessage(
|
||
chatId: message.Chat.Id,
|
||
text: "⛔ У вас нет прав для просмотра списка администраторов!"
|
||
);
|
||
}
|
||
}
|
||
|
||
if (message.Text == "/start")
|
||
{
|
||
var keyboard = new InlineKeyboardMarkup(new[]
|
||
{
|
||
new[]
|
||
{
|
||
InlineKeyboardButton.WithCallbackData("Подать заявку", "report"),
|
||
InlineKeyboardButton.WithCallbackData("Панель администратора", "admin_panel")
|
||
}
|
||
});
|
||
|
||
await botClient.SendMessage(
|
||
chatId: message.Chat.Id,
|
||
text: "Привет! Я бот для сбора заявок на ремонт оборудования.",
|
||
replyMarkup: keyboard
|
||
);
|
||
Log.Information($"Ответ на команду /start с кнопками отправлен.");
|
||
}
|
||
else if (usersWaitingForReport.TryGetValue(message.Chat.Id, out bool isWaiting) && isWaiting)
|
||
{
|
||
if (userReportSteps.TryGetValue(message.Chat.Id, out int step))
|
||
{
|
||
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;
|
||
await SaveReportToDatabase(message.Chat.Id, userReports[message.Chat.Id]);
|
||
var mainMenuKeyboard = new InlineKeyboardMarkup(new[]
|
||
{
|
||
new[]
|
||
{
|
||
InlineKeyboardButton.WithCallbackData("Главное меню", "main_menu")
|
||
}
|
||
});
|
||
await botClient.SendMessage(
|
||
message.Chat.Id,
|
||
"✅ Спасибо за заявку! Мы обработаем её в ближайшее время.",
|
||
replyMarkup: mainMenuKeyboard
|
||
);
|
||
usersWaitingForReport[message.Chat.Id] = false;
|
||
userReportSteps.Remove(message.Chat.Id);
|
||
userReports.Remove(message.Chat.Id);
|
||
Log.Information($"Заявка пользователя {message.Chat.Id} сохранена в базе данных.");
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
await botClient.SendMessage(message.Chat.Id, "ℹ️ Используйте команду /start для начала работы с ботом.");
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log.Error($"Ошибка при обработке обновлений: {ex.Message}");
|
||
Log.Error($"StackTrace: {ex.StackTrace}");
|
||
}
|
||
}
|
||
|
||
|
||
|
||
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 = "DELETE FROM Reports WHERE Id = @id";
|
||
command.Parameters.AddWithValue("@id", reportId);
|
||
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 ViewReports(botClient, chatId);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log.Error($"Ошибка при удалении заявки #{reportId}: {ex.Message}");
|
||
await botClient.SendMessage(chatId, $"Ошибка при удалении заявки #{reportId}.");
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
private static async Task SendMainMenu(ITelegramBotClient botClient, long chatId)
|
||
{
|
||
var keyboard = new InlineKeyboardMarkup(new[]
|
||
{
|
||
new[]
|
||
{
|
||
InlineKeyboardButton.WithCallbackData("Подать заявку", "report"),
|
||
InlineKeyboardButton.WithCallbackData("Панель администратора", "admin_panel")
|
||
}
|
||
});
|
||
|
||
await botClient.SendMessage(
|
||
chatId: chatId,
|
||
text: "Главное меню:",
|
||
replyMarkup: keyboard
|
||
);
|
||
}
|
||
|
||
private static async Task SendAdminPanel(ITelegramBotClient botClient, long chatId)
|
||
{
|
||
var keyboard = new InlineKeyboardMarkup(new[]
|
||
{
|
||
new[]
|
||
{
|
||
InlineKeyboardButton.WithCallbackData("📋 Менеджер заявок", "view_reports"),
|
||
InlineKeyboardButton.WithCallbackData("🗃️ Архив заявок", "view_archived_reports")
|
||
},
|
||
new[]
|
||
{
|
||
InlineKeyboardButton.WithCallbackData("⚙️ Управление администраторами", "admin_settings")
|
||
},
|
||
new[]
|
||
{
|
||
InlineKeyboardButton.WithCallbackData("🏠 Главное меню", "main_menu")
|
||
}
|
||
});
|
||
|
||
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 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);
|
||
|
||
buttons.Add(new[]
|
||
{
|
||
InlineKeyboardButton.WithCallbackData(
|
||
$"#{id} - {status} - {description}...",
|
||
$"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, "Ошибка при получении заявок");
|
||
}
|
||
}
|
||
|
||
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 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);
|
||
|
||
buttons.Add(new[]
|
||
{
|
||
InlineKeyboardButton.WithCallbackData(
|
||
$"#{id} - {status} - {description}...",
|
||
$"report_{id}")
|
||
});
|
||
}
|
||
}
|
||
|
||
// Добавляем кнопки навигации
|
||
buttons.Add(new[]
|
||
{
|
||
InlineKeyboardButton.WithCallbackData("Назад", "back_to_admin_panel"),
|
||
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, "Ошибка при получении архива заявок");
|
||
}
|
||
}
|
||
|
||
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 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");
|
||
|
||
string priorityEmoji = GetPriorityEmoji(priority);
|
||
string statusEmoji = GetStatusEmoji(status);
|
||
|
||
var statusButtons = 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")
|
||
}
|
||
});
|
||
|
||
string newText = $"Заявка #{reportId}\n\n" +
|
||
$"Приоритет: {priorityEmoji} {priority}\n" +
|
||
$"Кабинет: {room}\n" +
|
||
$"Описание: {description}\n" +
|
||
$"ФИО: {reporterName}\n" +
|
||
$"Статус: {statusEmoji} {status}\n" +
|
||
$"Дата создания: {dateCreated}";
|
||
|
||
await botClient.SendMessage(
|
||
chatId: chatId,
|
||
text: newText,
|
||
replyMarkup: statusButtons
|
||
);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log.Error($"Ошибка: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
|
||
// Метод для удаления администратора из базы данных
|
||
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 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<InlineKeyboardButton[]>();
|
||
var messageText = new System.Text.StringBuilder();
|
||
messageText.AppendLine("📋 <b>Список администраторов:</b>\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)
|
||
{
|
||
try
|
||
{
|
||
// Проверяем, что запрашивающий пользователь - администратор
|
||
if (!admins.Contains(chatId))
|
||
{
|
||
await botClient.SendMessage(
|
||
chatId: chatId,
|
||
text: "⛔ У вас нет прав для доступа к настройкам администраторов."
|
||
);
|
||
await Task.Delay(2000);
|
||
await SendMainMenu(botClient, chatId);
|
||
return;
|
||
}
|
||
|
||
var keyboard = new InlineKeyboardMarkup(new[]
|
||
{
|
||
new[] {
|
||
InlineKeyboardButton.WithCallbackData("👥 Список администраторов", "view_admins")
|
||
},
|
||
new[] {
|
||
InlineKeyboardButton.WithCallbackData("🔙 Назад к панели администратора", "admin_panel"),
|
||
InlineKeyboardButton.WithCallbackData("🏠 Главное меню", "main_menu")
|
||
}
|
||
});
|
||
|
||
await botClient.SendMessage(
|
||
chatId: chatId,
|
||
text: "⚙️ <b>Управление администраторами</b>",
|
||
parseMode: ParseMode.Html,
|
||
replyMarkup: keyboard
|
||
);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log.Error($"Ошибка при отображении настроек администраторов: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
private static async Task UpdateReportStatus(long reportId, string newStatus, long changerId)
|
||
{
|
||
try
|
||
{
|
||
string oldStatus = "";
|
||
|
||
// Сначала получаем текущий статус
|
||
using (var connection = new SqliteConnection("Data Source=bot.db"))
|
||
{
|
||
await connection.OpenAsync();
|
||
var getStatusCommand = connection.CreateCommand();
|
||
getStatusCommand.CommandText = "SELECT Status FROM Reports WHERE Id = @id";
|
||
getStatusCommand.Parameters.AddWithValue("@id", reportId);
|
||
oldStatus = (await getStatusCommand.ExecuteScalarAsync())?.ToString() ?? string.Empty;
|
||
}
|
||
|
||
// Если статус не изменился, прерываем выполнение
|
||
if (oldStatus == newStatus) return;
|
||
|
||
// Обновляем статус
|
||
using (var connection = new SqliteConnection("Data Source=bot.db"))
|
||
{
|
||
await connection.OpenAsync();
|
||
var command = connection.CreateCommand();
|
||
command.CommandText = "UPDATE Reports SET Status = @status WHERE Id = @id";
|
||
command.Parameters.AddWithValue("@status", newStatus);
|
||
command.Parameters.AddWithValue("@id", reportId);
|
||
await command.ExecuteNonQueryAsync();
|
||
|
||
// Уведомляем администраторов об изменении статуса
|
||
await NotifyAdminsAboutStatusChange(reportId, newStatus, oldStatus, changerId);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log.Error($"Ошибка при обновлении статуса заявки: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
private static async Task SaveReportToDatabase(long chatId, Report report)
|
||
{
|
||
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();
|
||
";
|
||
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);
|
||
|
||
long reportId = Convert.ToInt64(await insertCommand.ExecuteScalarAsync());
|
||
Log.Information($"Заявка от пользователя {chatId} успешно сохранена с ID {reportId}.");
|
||
|
||
// Уведомляем администраторов о новой заявке
|
||
await NotifyAdminsAboutNewReport(reportId, report);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log.Error($"Ошибка при сохранении заявки в базу данных: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
|
||
|
||
// Обновляем метод CreateDatabaseIfNotExists
|
||
private static async Task CreateDatabaseIfNotExists()
|
||
{
|
||
string connectionString = "Data Source=bot.db"; // Путь к вашей базе данных
|
||
|
||
try
|
||
{
|
||
using (var connection = new SqliteConnection(connectionString))
|
||
{
|
||
await connection.OpenAsync();
|
||
|
||
// Проверяем, существует ли таблица 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" };
|
||
var existingColumns = new HashSet<string>();
|
||
|
||
while (await tableInfo.ReadAsync())
|
||
{
|
||
existingColumns.Add(tableInfo["name"]?.ToString() ?? string.Empty);
|
||
}
|
||
|
||
foreach (var column in requiredColumns)
|
||
{
|
||
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":
|
||
alterTableCommand.CommandText = "ALTER TABLE Reports ADD COLUMN Room TEXT NOT NULL DEFAULT '';";
|
||
break;
|
||
case "Description":
|
||
alterTableCommand.CommandText = "ALTER TABLE Reports ADD COLUMN Description TEXT NOT NULL DEFAULT '';";
|
||
break;
|
||
case "ReporterName":
|
||
alterTableCommand.CommandText = "ALTER TABLE Reports ADD COLUMN ReporterName TEXT NOT NULL DEFAULT '';";
|
||
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;
|
||
}
|
||
await alterTableCommand.ExecuteNonQueryAsync();
|
||
Log.Information($"Столбец {column} добавлен в таблицу Reports.");
|
||
}
|
||
}
|
||
|
||
// Создаем таблицу Reports, если её не существует
|
||
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 'ожидает'
|
||
);
|
||
";
|
||
await createTableCommand.ExecuteNonQueryAsync();
|
||
Log.Information("Таблица Reports успешно создана (если её не было).");
|
||
|
||
// Создаем таблицу администраторов
|
||
await CreateAdminsTableIfNotExists();
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log.Error($"Ошибка при создании таблиц в базе данных: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
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;
|
||
}
|
||
|
||
|
||
|
||
private static Task HandleErrorAsync(ITelegramBotClient botClient, Exception exception, CancellationToken cancellationToken)
|
||
{
|
||
Log.Error($"Ошибка в процессе работы с ботом: {exception.Message}");
|
||
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
|
||
);";
|
||
await command.ExecuteNonQueryAsync();
|
||
Log.Information("Таблица Admins успешно создана (если её не было).");
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log.Error($"Ошибка при создании таблицы Admins: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
// Метод для сохранения администратора в базу данных
|
||
private static async Task SaveAdminToDatabase(long chatId)
|
||
{
|
||
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) VALUES (@chatId)";
|
||
insertCommand.Parameters.AddWithValue("@chatId", chatId);
|
||
await insertCommand.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 FROM Admins";
|
||
|
||
using (var reader = await command.ExecuteReaderAsync())
|
||
{
|
||
while (await reader.ReadAsync())
|
||
{
|
||
long adminId = reader.GetInt64(0);
|
||
admins.Add(adminId);
|
||
Log.Information($"Загружен администратор с ID: {adminId}");
|
||
}
|
||
}
|
||
}
|
||
Log.Information($"Загружено {admins.Count} администраторов из базы данных");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log.Error($"Ошибка при загрузке администраторов из базы данных: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
// Метод для уведомления администраторов о новой заявке
|
||
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
|
||
{
|
||
"ожидает" => "🟡",
|
||
"в работе" => "🔵",
|
||
"закрыта" => "🟢",
|
||
_ => "ℹ️"
|
||
};
|
||
}
|
||
|
||
} |