Добавлена поддержка администраторов и логирования

Внесены изменения в класс `Program`:
- Инициализация логгера с выводом в консоль и файл.
- Загрузка списка администраторов из базы данных при запуске бота.
- Метод для сохранения администратора в базе данных при авторизации.
- Обновлен метод `UpdateReportStatus` для уведомления администраторов об изменении статуса заявки.
- Добавлены методы для создания и загрузки таблицы администраторов.
- Изменено форматирование сообщений с использованием emoji для статусов и приоритетов.
- Обновлены SQL-запросы для работы с новыми полями и логикой в базе данных.
This commit is contained in:
Mef 2025-03-19 20:19:46 +07:00
parent 8092d54ff8
commit fa790e52d7

View File

@ -64,6 +64,10 @@ class Program
// Создание базы данных и таблицы, если они не существуют // Создание базы данных и таблицы, если они не существуют
await CreateDatabaseIfNotExists(); await CreateDatabaseIfNotExists();
// Загрузка списка администраторов из базы данных
await LoadAdminsFromDatabase();
Log.Information($"Загружено {admins.Count} администраторов из базы данных");
var cts = new CancellationTokenSource(); var cts = new CancellationTokenSource();
Log.Information("Начало получения обновлений..."); Log.Information("Начало получения обновлений...");
@ -200,7 +204,7 @@ class Program
if (callbackQuery?.Message?.MessageId != null) if (callbackQuery?.Message?.MessageId != null)
{ {
int messageId = callbackQuery.Message.MessageId; int messageId = callbackQuery.Message.MessageId;
await UpdateReportStatus(reportId, newStatus); await UpdateReportStatus(reportId, newStatus, chatId);
await ShowReportDetails(botClient, chatId, reportId, messageId); await ShowReportDetails(botClient, chatId, reportId, messageId);
} }
} }
@ -237,13 +241,15 @@ class Program
var message = update.Message; var message = update.Message;
Log.Information($"Получено сообщение от {message.Chat.Id}: {message.Text}"); Log.Information($"Получено сообщение от {message.Chat.Id}: {message.Text}");
// Обработка команды /admin для авторизации
if (message.Text.StartsWith("/admin")) if (message.Text.StartsWith("/admin"))
{ {
string[] parts = message.Text.Split(' '); string[] parts = message.Text.Split(' ');
if (parts.Length == 2 && parts[1] == adminPassword) if (parts.Length == 2 && parts[1] == adminPassword)
{ {
admins.Add(message.Chat.Id); admins.Add(message.Chat.Id);
// Сохраняем администратора в базу данных
await SaveAdminToDatabase(message.Chat.Id);
var authMessage = await botClient.SendMessage(message.Chat.Id, "✅ Вы авторизованы как администратор!"); var authMessage = await botClient.SendMessage(message.Chat.Id, "✅ Вы авторизованы как администратор!");
Log.Information($"Новый администратор: {message.Chat.Id}"); Log.Information($"Новый администратор: {message.Chat.Id}");
await Task.Delay(2000); await Task.Delay(2000);
@ -534,6 +540,9 @@ class Program
string status = reader.GetString(4); string status = reader.GetString(4);
string dateCreated = reader.GetDateTime(5).ToString("yyyy-MM-dd HH:mm:ss"); 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[] var statusButtons = new InlineKeyboardMarkup(new[]
{ {
new[] new[]
@ -557,11 +566,11 @@ class Program
}); });
string newText = $"Заявка #{reportId}\n\n" + string newText = $"Заявка #{reportId}\n\n" +
$"Приоритет: {priority}\n" + $"Приоритет: {priorityEmoji} {priority}\n" +
$"Кабинет: {room}\n" + $"Кабинет: {room}\n" +
$"Описание: {description}\n" + $"Описание: {description}\n" +
$"ФИО: {reporterName}\n" + $"ФИО: {reporterName}\n" +
$"Статус: {status}\n" + $"Статус: {statusEmoji} {status}\n" +
$"Дата создания: {dateCreated}"; $"Дата создания: {dateCreated}";
await botClient.SendMessage( await botClient.SendMessage(
@ -585,10 +594,26 @@ class Program
private static async Task UpdateReportStatus(long reportId, string newStatus) private static async Task UpdateReportStatus(long reportId, string newStatus, long changerId)
{ {
try 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 = (string)await getStatusCommand.ExecuteScalarAsync();
}
// Если статус не изменился, прерываем выполнение
if (oldStatus == newStatus) return;
// Обновляем статус
using (var connection = new SqliteConnection("Data Source=bot.db")) using (var connection = new SqliteConnection("Data Source=bot.db"))
{ {
await connection.OpenAsync(); await connection.OpenAsync();
@ -597,11 +622,14 @@ class Program
command.Parameters.AddWithValue("@status", newStatus); command.Parameters.AddWithValue("@status", newStatus);
command.Parameters.AddWithValue("@id", reportId); command.Parameters.AddWithValue("@id", reportId);
await command.ExecuteNonQueryAsync(); await command.ExecuteNonQueryAsync();
// Уведомляем администраторов об изменении статуса
await NotifyAdminsAboutStatusChange(reportId, newStatus, oldStatus, changerId);
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
Log.Error($"Ошибка: {ex.Message}"); Log.Error($"Ошибка при обновлении статуса заявки: {ex.Message}");
} }
} }
@ -620,6 +648,7 @@ class Program
@" @"
INSERT INTO Reports (ChatId, Priority, Room, Description, ReporterName, Status) INSERT INTO Reports (ChatId, Priority, Room, Description, ReporterName, Status)
VALUES (@ChatId, @Priority, @Room, @Description, @ReporterName, 'ожидает'); VALUES (@ChatId, @Priority, @Room, @Description, @ReporterName, 'ожидает');
SELECT last_insert_rowid();
"; ";
insertCommand.Parameters.AddWithValue("@ChatId", chatId); insertCommand.Parameters.AddWithValue("@ChatId", chatId);
insertCommand.Parameters.AddWithValue("@Priority", report.Priority); insertCommand.Parameters.AddWithValue("@Priority", report.Priority);
@ -627,8 +656,11 @@ class Program
insertCommand.Parameters.AddWithValue("@Description", report.Description); insertCommand.Parameters.AddWithValue("@Description", report.Description);
insertCommand.Parameters.AddWithValue("@ReporterName", report.ReporterName); insertCommand.Parameters.AddWithValue("@ReporterName", report.ReporterName);
await insertCommand.ExecuteNonQueryAsync(); long reportId = Convert.ToInt64(await insertCommand.ExecuteScalarAsync());
Log.Information($"Заявка от пользователя {chatId} успешно сохранена."); Log.Information($"Заявка от пользователя {chatId} успешно сохранена с ID {reportId}.");
// Уведомляем администраторов о новой заявке
await NotifyAdminsAboutNewReport(reportId, report);
} }
} }
catch (Exception ex) catch (Exception ex)
@ -639,6 +671,7 @@ class Program
// Обновляем метод CreateDatabaseIfNotExists
private static async Task CreateDatabaseIfNotExists() private static async Task CreateDatabaseIfNotExists()
{ {
string connectionString = "Data Source=bot.db"; // Путь к вашей базе данных string connectionString = "Data Source=bot.db"; // Путь к вашей базе данных
@ -693,7 +726,7 @@ class Program
} }
} }
// Создаем таблицу, если её не существует // Создаем таблицу Reports, если её не существует
var createTableCommand = connection.CreateCommand(); var createTableCommand = connection.CreateCommand();
createTableCommand.CommandText = createTableCommand.CommandText =
@" @"
@ -709,13 +742,15 @@ class Program
); );
"; ";
await createTableCommand.ExecuteNonQueryAsync(); await createTableCommand.ExecuteNonQueryAsync();
Log.Information("Таблица Reports успешно создана (если её не было)."); Log.Information("Таблица Reports успешно создана (если её не было).");
// Создаем таблицу администраторов
await CreateAdminsTableIfNotExists();
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
Log.Error($"Ошибка при создании таблицы в базе данных: {ex.Message}"); Log.Error($"Ошибка при создании таблиц в базе данных: {ex.Message}");
} }
} }
@ -725,6 +760,7 @@ class Program
private static Dictionary<long, int> userReportSteps = new Dictionary<long, int>(); private static Dictionary<long, int> userReportSteps = new Dictionary<long, int>();
private static Dictionary<long, Report> userReports = new Dictionary<long, Report>(); private static Dictionary<long, Report> userReports = new Dictionary<long, Report>();
@ -744,4 +780,210 @@ class Program
Log.Error($"StackTrace: {exception.StackTrace}"); Log.Error($"StackTrace: {exception.StackTrace}");
return Task.CompletedTask; 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
{
"ожидает" => "🟡",
"в работе" => "🔵",
"закрыта" => "🟢",
_ => ""
};
}
} }