telegram-bot/Program.cs

442 lines
18 KiB
C#
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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(); // Добавили await для получения объекта User
Log.Information($"Бот {me.FirstName} запущен! ID: {me.Id}");
}
catch (Exception ex)
{
Log.Error($"Ошибка при подключении к Telegram API: {ex.Message}");
throw;
}
// Создание базы данных и таблицы, если они не существуют
await CreateDatabaseIfNotExists();
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 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;
// Your existing code here
}
int callbackMessageId = callbackQuery.Message.MessageId;
await botClient.AnswerCallbackQuery(callbackQuery.Id); // Убираем "часики" у кнопки
if (data == "report")
{
usersWaitingForReport[chatId] = true;
await botClient.SendMessage(chatId, "Пожалуйста, отправьте описание проблемы.");
Log.Information($"Пользователь {chatId} начал создание заявки");
}
else if (data == "view_reports")
{
if (admins.Contains(chatId))
{
await ViewReports(botClient, chatId);
}
else
{
await botClient.SendMessage(chatId, "⛔ Вы не являетесь администратором!");
Log.Information($"Неавторизованный доступ к заявкам от {chatId}");
}
}
else if (data.StartsWith("report_"))
{
long reportId = long.Parse(data.Substring(7));
await ShowReportDetails(botClient, chatId, reportId, callbackMessageId);
}
else if (data.StartsWith("status_"))
{
string[] parts = data.Split('_');
long reportId = long.Parse(parts[1]);
string newStatus = parts[2];
await UpdateReportStatus(reportId, newStatus);
await ShowReportDetails(botClient, chatId, reportId, callbackMessageId);
}
else if (data == "back_to_list")
{
await ViewReports(botClient, chatId);
}
else if (data == "main_menu")
{
await SendMainMenu(botClient, chatId);
}
}
}
// Обработка текстовых сообщений
if (update.Type != UpdateType.Message || update.Message?.Text == null)
return;
var message = update.Message;
Log.Information($"Получено сообщение от {message.Chat.Id}: {message.Text}");
// Обработка команды /admin для авторизации
if (message.Text.StartsWith("/admin"))
{
string[] parts = message.Text.Split(' ');
if (parts.Length == 2 && parts[1] == adminPassword)
{
admins.Add(message.Chat.Id);
await botClient.SendMessage(message.Chat.Id, "✅ Вы авторизованы как администратор!");
Log.Information($"Новый администратор: {message.Chat.Id}");
}
else
{
await botClient.SendMessage(message.Chat.Id, "❌ Неверный пароль!");
}
return;
}
if (message.Text == "/start")
{
var keyboard = new InlineKeyboardMarkup(new[]
{
new[]
{
InlineKeyboardButton.WithCallbackData("Подать заявку", "report"),
InlineKeyboardButton.WithCallbackData("Просмотр заявок", "view_reports")
}
});
await botClient.SendMessage(
chatId: message.Chat.Id,
text: "Привет! Я бот для сбора заявок на ремонт оборудования.",
replyMarkup: keyboard
);
Log.Information($"Ответ на команду /start с кнопками отправлен.");
}
else if (usersWaitingForReport.TryGetValue(message.Chat.Id, out bool isWaiting) && isWaiting)
{
string problemDescription = message.Text;
await SaveReportToDatabase(message.Chat.Id, problemDescription);
// Создаем клавиатуру с кнопкой возврата
var keyboard = new InlineKeyboardMarkup(new[]
{
new[]
{
InlineKeyboardButton.WithCallbackData("Главное меню", "main_menu")
}
});
await botClient.SendMessage(
chatId: message.Chat.Id,
text: "✅ Спасибо за заявку! Мы обработаем её в ближайшее время.",
replyMarkup: keyboard);
usersWaitingForReport[message.Chat.Id] = false;
Log.Information($"Заявка пользователя {message.Chat.Id} сохранена в базе данных.");
}
else
{
await botClient.SendMessage(chatId: message.Chat.Id, text: " Используйте кнопки для навигации.");
}
}
catch (Exception ex)
{
Log.Error($"Ошибка при обработке обновлений: {ex.Message}");
Log.Error($"StackTrace: {ex.StackTrace}");
}
}
private static async Task SendMainMenu(ITelegramBotClient botClient, long chatId)
{
var keyboard = new InlineKeyboardMarkup(new[]
{
new[]
{
InlineKeyboardButton.WithCallbackData("Подать заявку", "report"),
InlineKeyboardButton.WithCallbackData("Просмотр заявок", "view_reports")
}
});
await botClient.SendMessage(
chatId: chatId,
text: "Главное меню:",
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";
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 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 Description, Status FROM Reports WHERE Id = @id";
command.Parameters.AddWithValue("@id", reportId);
using (var reader = await command.ExecuteReaderAsync())
{
if (await reader.ReadAsync())
{
string description = reader.GetString(0);
string status = reader.GetString(1);
var statusButtons = new InlineKeyboardMarkup(new[]
{
new[]
{
InlineKeyboardButton.WithCallbackData("🟡 Ожидает", $"status_{reportId}_ожидает"),
InlineKeyboardButton.WithCallbackData("🔵 В работе", $"status_{reportId}_в работе")
},
new[]
{
InlineKeyboardButton.WithCallbackData("🟢 Закрыта", $"status_{reportId}_закрыта")
},
new[]
{
InlineKeyboardButton.WithCallbackData("Назад", "back_to_list"),
InlineKeyboardButton.WithCallbackData("Главное меню", "main_menu")
}
});
string newText = $"Заявка #{reportId}\n\nОписание: {description}\nСтатус: {status}";
await botClient.EditMessageText(
chatId: chatId,
messageId: messageId,
text: newText,
replyMarkup: statusButtons
);
}
}
}
}
catch (Exception ex)
{
Log.Error($"Ошибка: {ex.Message}");
}
}
private static async Task UpdateReportStatus(long reportId, string newStatus)
{
try
{
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();
}
}
catch (Exception ex)
{
Log.Error($"Ошибка: {ex.Message}");
}
}
private static async Task SaveReportToDatabase(long chatId, string description)
{
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, Description)
VALUES (@ChatId, @Description);
";
insertCommand.Parameters.AddWithValue("@ChatId", chatId);
insertCommand.Parameters.AddWithValue("@Description", description);
await insertCommand.ExecuteNonQueryAsync();
Log.Information($"Заявка от пользователя {chatId} успешно сохранена.");
}
}
catch (Exception ex)
{
Log.Error($"Ошибка при сохранении заявки в базу данных: {ex.Message}");
}
}
private static async Task CreateDatabaseIfNotExists()
{
string connectionString = "Data Source=bot.db"; // Путь к вашей базе данных
try
{
using (var connection = new SqliteConnection(connectionString))
{
await connection.OpenAsync();
var createTableCommand = connection.CreateCommand();
createTableCommand.CommandText =
@"
CREATE TABLE IF NOT EXISTS Reports (
Id INTEGER PRIMARY KEY AUTOINCREMENT,
ChatId INTEGER NOT NULL,
Description TEXT NOT NULL,
DateCreated DATETIME DEFAULT CURRENT_TIMESTAMP,
Status TEXT DEFAULT 'В процессе'
);
";
await createTableCommand.ExecuteNonQueryAsync();
Log.Information("Таблица Reports успешно создана (если её не было).");
}
}
catch (Exception ex)
{
Log.Error($"Ошибка при создании таблицы в базе данных: {ex.Message}");
}
}
private static Task HandleErrorAsync(ITelegramBotClient botClient, Exception exception, CancellationToken cancellationToken)
{
Log.Error($"Ошибка в процессе работы с ботом: {exception.Message}");
Log.Error($"StackTrace: {exception.StackTrace}");
return Task.CompletedTask;
}
}