From 222fbfcefc8b9fa714b93d211015a2bc8483369d Mon Sep 17 00:00:00 2001 From: "github-classroom[bot]" <66690702+github-classroom[bot]@users.noreply.github.com> Date: Sat, 12 Apr 2025 09:54:46 +0000 Subject: [PATCH] Initial commit --- .gitignore | 5 + .idea/.idea.SimpleTGBot/.idea/.gitignore | 13 ++ .idea/.idea.SimpleTGBot/.idea/encodings.xml | 4 + .idea/.idea.SimpleTGBot/.idea/indexLayout.xml | 8 ++ .idea/.idea.SimpleTGBot/.idea/vcs.xml | 6 + SimpleTGBot.sln | 16 +++ SimpleTGBot/Program.cs | 11 ++ SimpleTGBot/SimpleTGBot.csproj | 14 +++ SimpleTGBot/TelegramBot.cs | 118 ++++++++++++++++++ 9 files changed, 195 insertions(+) create mode 100644 .gitignore create mode 100644 .idea/.idea.SimpleTGBot/.idea/.gitignore create mode 100644 .idea/.idea.SimpleTGBot/.idea/encodings.xml create mode 100644 .idea/.idea.SimpleTGBot/.idea/indexLayout.xml create mode 100644 .idea/.idea.SimpleTGBot/.idea/vcs.xml create mode 100644 SimpleTGBot.sln create mode 100644 SimpleTGBot/Program.cs create mode 100644 SimpleTGBot/SimpleTGBot.csproj create mode 100644 SimpleTGBot/TelegramBot.cs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..add57be --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +bin/ +obj/ +/packages/ +riderModule.iml +/_ReSharper.Caches/ \ No newline at end of file diff --git a/.idea/.idea.SimpleTGBot/.idea/.gitignore b/.idea/.idea.SimpleTGBot/.idea/.gitignore new file mode 100644 index 0000000..8839526 --- /dev/null +++ b/.idea/.idea.SimpleTGBot/.idea/.gitignore @@ -0,0 +1,13 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Rider ignored files +/contentModel.xml +/projectSettingsUpdater.xml +/modules.xml +/.idea.SimpleTGBot.iml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/.idea.SimpleTGBot/.idea/encodings.xml b/.idea/.idea.SimpleTGBot/.idea/encodings.xml new file mode 100644 index 0000000..df87cf9 --- /dev/null +++ b/.idea/.idea.SimpleTGBot/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/.idea.SimpleTGBot/.idea/indexLayout.xml b/.idea/.idea.SimpleTGBot/.idea/indexLayout.xml new file mode 100644 index 0000000..7b08163 --- /dev/null +++ b/.idea/.idea.SimpleTGBot/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.SimpleTGBot/.idea/vcs.xml b/.idea/.idea.SimpleTGBot/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/.idea.SimpleTGBot/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/SimpleTGBot.sln b/SimpleTGBot.sln new file mode 100644 index 0000000..3d633ed --- /dev/null +++ b/SimpleTGBot.sln @@ -0,0 +1,16 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleTGBot", "SimpleTGBot\SimpleTGBot.csproj", "{BFA186C8-2B12-4779-8691-9914B54DD319}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {BFA186C8-2B12-4779-8691-9914B54DD319}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BFA186C8-2B12-4779-8691-9914B54DD319}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BFA186C8-2B12-4779-8691-9914B54DD319}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BFA186C8-2B12-4779-8691-9914B54DD319}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/SimpleTGBot/Program.cs b/SimpleTGBot/Program.cs new file mode 100644 index 0000000..d7cf41c --- /dev/null +++ b/SimpleTGBot/Program.cs @@ -0,0 +1,11 @@ +namespace SimpleTGBot; + +public static class Program +{ + // Метод main немного видоизменился для асинхронной работы + public static async Task Main(string[] args) + { + TelegramBot telegramBot = new TelegramBot(); + await telegramBot.Run(); + } +} \ No newline at end of file diff --git a/SimpleTGBot/SimpleTGBot.csproj b/SimpleTGBot/SimpleTGBot.csproj new file mode 100644 index 0000000..f48b654 --- /dev/null +++ b/SimpleTGBot/SimpleTGBot.csproj @@ -0,0 +1,14 @@ + + + + Exe + net7.0 + enable + enable + + + + + + + diff --git a/SimpleTGBot/TelegramBot.cs b/SimpleTGBot/TelegramBot.cs new file mode 100644 index 0000000..fc5c525 --- /dev/null +++ b/SimpleTGBot/TelegramBot.cs @@ -0,0 +1,118 @@ +using System.Reflection.Metadata.Ecma335; + +namespace SimpleTGBot; +using Telegram.Bot; +using Telegram.Bot.Exceptions; +using Telegram.Bot.Polling; +using Telegram.Bot.Types; +using Telegram.Bot.Types.Enums; + +public class TelegramBot +{ + // Токен TG-бота. Можно получить у @BotFather + private const string BotToken = "ВАШ_ТОКЕН_ИДЕНТИФИКАЦИИ_БОТА"; + + /// + /// Инициализирует и обеспечивает работу бота до нажатия клавиши Esc + /// + public async Task Run() + { + // Если вам нужно хранить какие-то данные во время работы бота (массив информации, логи бота, + // историю сообщений для каждого пользователя), то это всё надо инициализировать в этом методе. + // TODO: Инициализация необходимых полей + + // Инициализируем наш клиент, передавая ему токен. + var botClient = new TelegramBotClient(BotToken); + + // Служебные вещи для организации правильной работы с потоками + using CancellationTokenSource cts = new CancellationTokenSource(); + + // Разрешённые события, которые будет получать и обрабатывать наш бот. + // Будем получать только сообщения. При желании можно поработать с другими событиями. + ReceiverOptions receiverOptions = new ReceiverOptions() + { + AllowedUpdates = new [] { UpdateType.Message } + }; + + // Привязываем все обработчики и начинаем принимать сообщения для бота + botClient.StartReceiving( + updateHandler: OnMessageReceived, + pollingErrorHandler: OnErrorOccured, + receiverOptions: receiverOptions, + cancellationToken: cts.Token + ); + + // Проверяем что токен верный и получаем информацию о боте + var me = await botClient.GetMeAsync(cancellationToken: cts.Token); + Console.WriteLine($"Бот @{me.Username} запущен.\nДля остановки нажмите клавишу Esc..."); + + // Ждём, пока будет нажата клавиша Esc, тогда завершаем работу бота + while (Console.ReadKey().Key != ConsoleKey.Escape){} + + // Отправляем запрос для остановки работы клиента. + cts.Cancel(); + } + + /// + /// Обработчик события получения сообщения. + /// + /// Клиент, который получил сообщение + /// Событие, произошедшее в чате. Новое сообщение, голос в опросе, исключение из чата и т. д. + /// Служебный токен для работы с многопоточностью + async Task OnMessageReceived(ITelegramBotClient botClient, Update update, CancellationToken cancellationToken) + { + // Работаем только с сообщениями. Остальные события игнорируем + var message = update.Message; + if (message is null) + { + return; + } + // Будем обрабатывать только текстовые сообщения. + // При желании можно обрабатывать стикеры, фото, голосовые и т. д. + // + // Обратите внимание на использованную конструкцию. Она эквивалентна проверке на null, приведённой выше. + // Подробнее об этом синтаксисе: https://medium.com/@mattkenefick/snippets-in-c-more-ways-to-check-for-null-4eb735594c09 + if (message.Text is not { } messageText) + { + return; + } + + // Получаем ID чата, в которое пришло сообщение. Полезно, чтобы отличать пользователей друг от друга. + var chatId = message.Chat.Id; + + // Печатаем на консоль факт получения сообщения + Console.WriteLine($"Получено сообщение в чате {chatId}: '{messageText}'"); + + // TODO: Обработка пришедших сообщений + + // Отправляем обратно то же сообщение, что и получили + Message sentMessage = await botClient.SendTextMessageAsync( + chatId: chatId, + text: "Ты написал:\n" + messageText, + cancellationToken: cancellationToken); + } + + /// + /// Обработчик исключений, возникших при работе бота + /// + /// Клиент, для которого возникло исключение + /// Возникшее исключение + /// Служебный токен для работы с многопоточностью + /// + Task OnErrorOccured(ITelegramBotClient botClient, Exception exception, CancellationToken cancellationToken) + { + // В зависимости от типа исключения печатаем различные сообщения об ошибке + var errorMessage = exception switch + { + ApiRequestException apiRequestException + => $"Telegram API Error:\n[{apiRequestException.ErrorCode}]\n{apiRequestException.Message}", + + _ => exception.ToString() + }; + + Console.WriteLine(errorMessage); + + // Завершаем работу + return Task.CompletedTask; + } +} \ No newline at end of file