diff --git a/Controllers/ExampleController.cs b/Controllers/ExampleController.cs index b209d80..c43c26a 100644 --- a/Controllers/ExampleController.cs +++ b/Controllers/ExampleController.cs @@ -1,6 +1,6 @@ using Microsoft.AspNetCore.Mvc; -namespace TG_Bot_Template.Controllers +namespace $safeprojectname$.Controllers { /// /// Example controller diff --git a/Dockerfile b/Dockerfile index c3e03cc..dc3f5e7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,17 +8,16 @@ EXPOSE 80 FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build ARG BUILD_CONFIGURATION=Release WORKDIR /src -COPY ["TG-Bot-Template.csproj", "."] -RUN dotnet restore "./TG-Bot-Template.csproj" COPY . . +RUN dotnet restore WORKDIR "/src/." -RUN dotnet build "./TG-Bot-Template.csproj" -c $BUILD_CONFIGURATION -o /app/build +RUN dotnet build -c $BUILD_CONFIGURATION -o /app/build FROM build AS publish ARG BUILD_CONFIGURATION=Release -RUN dotnet publish "./TG-Bot-Template.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false +RUN dotnet publish -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false FROM base AS final WORKDIR /app COPY --from=publish /app/publish . -ENTRYPOINT ["dotnet", "TG-Bot-Template.dll"] \ No newline at end of file +ENTRYPOINT ["dotnet", "$safeprojectname$"] \ No newline at end of file diff --git a/MyTemplate.vstemplate b/MyTemplate.vstemplate new file mode 100644 index 0000000..c0cead8 --- /dev/null +++ b/MyTemplate.vstemplate @@ -0,0 +1,35 @@ + + + Telegram.Bit + Template of new ASP .NET 8 Telegram bot project + CSharp + + + 1000 + true + Telegram.Bot + true + Enabled + true + true + __TemplateIcon.ico + + + + + launchSettings.json + + + + ExampleController.cs + + appsettings.json + appsettings.Development.json + Dockerfile + .dockerignore + Program.cs + Startup.cs + TelegramBotService.cs + + + \ No newline at end of file diff --git a/Program.cs b/Program.cs index b593410..565e2aa 100644 --- a/Program.cs +++ b/Program.cs @@ -1,25 +1,23 @@ - -using Microsoft.AspNetCore; - -namespace TG_Bot_Template +namespace $safeprojectname$ { public class Program +{ + public static void Main() { - public static void Main() + CreateHostBuilder() + .Build() + .Run(); + } + private static IHostBuilder CreateHostBuilder() + { + return Host.CreateDefaultBuilder() + .ConfigureWebHostDefaults(webHost => { - CreateHostBuilder() - .Build() - .Run(); - } - private static IHostBuilder CreateHostBuilder() - { - return Host.CreateDefaultBuilder() - .ConfigureWebHostDefaults(webHost => { - webHost.UseStartup(); - webHost.UseStaticWebAssets(); - webHost.UseKestrel(kestrelOptions => { kestrelOptions.ListenAnyIP(80); }); - }); + webHost.UseStartup(); + webHost.UseStaticWebAssets(); + webHost.UseKestrel(kestrelOptions => { kestrelOptions.ListenAnyIP(80); }); + }); - } } } +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..91b1f09 --- /dev/null +++ b/README.md @@ -0,0 +1,45 @@ +# Template for Telegram BOT project +## About it +This is a template for VS 2023 Community/Enterprice for creating project with Telegram Bot service and base settings. + + + +## Used stack: +- .NET 8 Sdk Web +- ASP +- Swagger UI with commas setup +- Telegram.Bots (For .NET) + +# Use as template +For start used this project as a template, u should to download it. +After that, open it with Visual Studio, press "Project" -> "Export Template". +In window u need to select "Project export"(For exporting exactly Project) and press "Next". +In next window u can edit template name, description and icon. +After pressing "Finish" button, you can create project with this template. + +### OR + +Another way to use this project as a template: ZIP to folder with VS. +Download this project and compress it to .zip file with any name. After that, go to this destination: +```bash +C:\Users\{{YOUR_USERNAME}}\AppData\Roaming\Microsoft\VisualStudio\{{VS_VERSION}}\ +``` +Create folder with this name: `ProjectTemplatesCache` and pull zipped project to created folder. +After reloading VS you can create new project with this template. + +# Use as base for project +Its very simple to use, just download it and in file `appsettings.json` change in +"tg-token" (`"tg-token": "TOKEN"`) variable from TOKEN to your Bot`s token from [@BotFather](https://t.me/BotFather). + +After that, change press RMB on project and select "Sync Namespaces". If you need to use Dockerfile, change from "$safeprojectname$" to your project name in last stroke + +# appsettings.json + +Your appsettings.json file must be looked like this: +```json +{ + "tg-token": "123456:AaBbCcDd" +} +``` +or any with this variable + diff --git a/Startup.cs b/Startup.cs index e4c7174..fb9af1e 100644 --- a/Startup.cs +++ b/Startup.cs @@ -1,7 +1,7 @@ using Microsoft.AspNetCore.Hosting.Server; using System; -namespace TG_Bot_Template +namespace $safeprojectname$ { /// /// Startup class for ASP.NET with setting and configuration diff --git a/TelegramBotService.cs b/TelegramBotService.cs index 63648a2..0eb9f9c 100644 --- a/TelegramBotService.cs +++ b/TelegramBotService.cs @@ -1,141 +1,139 @@ -using System; -using Telegram.Bot.Types; -using Telegram.Bot; +using Telegram.Bot; using Telegram.Bot.Polling; +using Telegram.Bot.Types; using Telegram.Bot.Types.Enums; -using System.Runtime.CompilerServices; using Telegram.Bot.Types.InlineQueryResults; -namespace TG_Bot_Template +namespace $safeprojectname$ { public class TelegramBotService(IConfiguration conf, ILogger logger) : TelegramBotClient(conf.GetValue("tg-token")), IHostedService +{ + private static Dictionary _userStates = new Dictionary(); + + // For add any property, u should to add it in StartAsync func, like this: + // _PROPERTY_NAME = PROPERTY_NAME_FROM_CLASS + + private static ILogger _logger { get; set; } + + + private static async Task MainHandler(ITelegramBotClient botClient, Update update, CancellationToken cancellationToken) { - private static Dictionary _userStates = new Dictionary(); - - // For add any property, u should to add it in StartAsync func, like this: - // _PROPERTY_NAME = PROPERTY_NAME_FROM_CLASS - - private static ILogger _logger { get; set; } - - - private static async Task MainHandler(ITelegramBotClient botClient, Update update, CancellationToken cancellationToken) - { - _logger.Log( - LogLevel.Information, - $"Received an update: {update.Type}, Caller ID: {update.Message?.From?.Id ?? update.CallbackQuery?.From.Id ?? update.InlineQuery?.From.Id}" - ); - var handler = update switch - { - - { Message: { } message } => HandleUpdateAsync(botClient, message), - //{ EditedMessage: { } message } => BotOnMessageReceived(message, cancellationToken), - { CallbackQuery: { } callbackQuery } => QueryUpdateHandler(botClient, callbackQuery), - { InlineQuery: { } inlineQuery } => InlineUpdateHandler(botClient, inlineQuery), - //{ ChosenInlineResult: { } chosenInlineResult } => BotOnChosenInlineResultReceived(chosenInlineResult, cancellationToken), - _ => Task.CompletedTask - }; - - await handler; - - - } - private static async Task HandleUpdateAsync(ITelegramBotClient botClient, Message message) - { - try - { - string messageText = message.Text ?? message.Caption; - switch (messageText) - { - case "/start": - await botClient.SendTextMessageAsync(message.From.Id, "Start"); - break; - - default: - break; - } - } - catch (Exception ex) - { - _logger.LogError($"{ex.Message}"); - _logger.LogError($"Stack: {ex.StackTrace}"); - } - } - - private static async Task QueryUpdateHandler(ITelegramBotClient botClient, CallbackQuery callbackQuery) - { - try - { - string queryData = callbackQuery.Data; - switch (queryData) - { - case "test": - await botClient.AnswerCallbackQueryAsync(callbackQuery.Id, "Tested"); - break; - - default: - break; - } - } - catch (Exception ex) - { - _logger.LogError($"{ex.Message}"); - _logger.LogError($"Stack: {ex.StackTrace}"); - } - } - - private static async Task InlineUpdateHandler(ITelegramBotClient botClient, InlineQuery inlineQuery) - { - try - { - string inlineData = inlineQuery.Query; - switch (inlineData) - { - case "test": - await botClient.AnswerInlineQueryAsync(inlineQuery.Id, new InlineQueryResult[] { }); - break; - - default: - break; - } - } - catch (Exception ex) - { - _logger.LogError($"{ex.Message}"); - _logger.LogError($"Stack: {ex.StackTrace}"); - } - } - - - public async Task StartAsync(CancellationToken cancellationToken) - { - logger.Log(LogLevel.Information, $"Starting build {this.GetType().Name}"); - // StartReceiving does not block the caller thread. Receiving is done on the ThreadPool. - ReceiverOptions receiverOptions = new() - { - AllowedUpdates = [UpdateType.Message, UpdateType.CallbackQuery, UpdateType.InlineQuery] // receive all update types except ChatMember related updates - }; - - _logger = logger; - - this.StartReceiving( - updateHandler: MainHandler, - pollingErrorHandler: (k, ex, ctx) => { - Console.WriteLine(ex.Message); - - return Task.CompletedTask; - }, - receiverOptions: receiverOptions, - cancellationToken: cancellationToken + _logger.Log( + LogLevel.Information, + $"Received an update: {update.Type}, Caller ID: {update.Message?.From?.Id ?? update.CallbackQuery?.From.Id ?? update.InlineQuery?.From.Id}" ); - var me = await this.GetMeAsync(cancellationToken: cancellationToken); - logger.Log(LogLevel.Information, $"Start listening bot @{me.Username}"); - } - - public async Task StopAsync(CancellationToken cancellationToken) + var handler = update switch { - logger.Log(LogLevel.Information, $"Stopping service"); - await this.LogOutAsync(cancellationToken); - } + + { Message: { } message } => HandleUpdateAsync(botClient, message), + //{ EditedMessage: { } message } => BotOnMessageReceived(message, cancellationToken), + { CallbackQuery: { } callbackQuery } => QueryUpdateHandler(botClient, callbackQuery), + { InlineQuery: { } inlineQuery } => InlineUpdateHandler(botClient, inlineQuery), + //{ ChosenInlineResult: { } chosenInlineResult } => BotOnChosenInlineResultReceived(chosenInlineResult, cancellationToken), + _ => Task.CompletedTask + }; + + await handler; + } + private static async Task HandleUpdateAsync(ITelegramBotClient botClient, Message message) + { + try + { + string messageText = message.Text ?? message.Caption; + switch (messageText) + { + case "/start": + await botClient.SendTextMessageAsync(message.From.Id, "Start"); + break; + + default: + break; + } + } + catch (Exception ex) + { + _logger.LogError($"{ex.Message}"); + _logger.LogError($"Stack: {ex.StackTrace}"); + } + } + + private static async Task QueryUpdateHandler(ITelegramBotClient botClient, CallbackQuery callbackQuery) + { + try + { + string queryData = callbackQuery.Data; + switch (queryData) + { + case "test": + await botClient.AnswerCallbackQueryAsync(callbackQuery.Id, "Tested"); + break; + + default: + break; + } + } + catch (Exception ex) + { + _logger.LogError($"{ex.Message}"); + _logger.LogError($"Stack: {ex.StackTrace}"); + } + } + + private static async Task InlineUpdateHandler(ITelegramBotClient botClient, InlineQuery inlineQuery) + { + try + { + string inlineData = inlineQuery.Query; + switch (inlineData) + { + case "test": + await botClient.AnswerInlineQueryAsync(inlineQuery.Id, new InlineQueryResult[] { }); + break; + + default: + break; + } + } + catch (Exception ex) + { + _logger.LogError($"{ex.Message}"); + _logger.LogError($"Stack: {ex.StackTrace}"); + } + } + + + public async Task StartAsync(CancellationToken cancellationToken) + { + logger.Log(LogLevel.Information, $"Starting build {this.GetType().Name}"); + // StartReceiving does not block the caller thread. Receiving is done on the ThreadPool. + ReceiverOptions receiverOptions = new() + { + AllowedUpdates = [UpdateType.Message, UpdateType.CallbackQuery, UpdateType.InlineQuery] // receive all update types except ChatMember related updates + }; + + _logger = logger; + + this.StartReceiving( + updateHandler: MainHandler, + pollingErrorHandler: (k, ex, ctx) => + { + logger.LogError(ex.StackTrace); + + return Task.CompletedTask; + }, + receiverOptions: receiverOptions, + cancellationToken: cancellationToken + ); + var me = await this.GetMeAsync(cancellationToken: cancellationToken); + logger.Log(LogLevel.Information, $"Start listening bot @{me.Username}"); + } + + public async Task StopAsync(CancellationToken cancellationToken) + { + logger.Log(LogLevel.Information, $"Stopping service"); + } + +} } diff --git a/__TemplateIcon.ico b/__TemplateIcon.ico new file mode 100644 index 0000000..aae70d3 Binary files /dev/null and b/__TemplateIcon.ico differ