From 6055fcede4480ade4eae198d6bd7af2628cb94cd Mon Sep 17 00:00:00 2001 From: kislovdm Date: Mon, 12 Feb 2024 20:15:59 +0300 Subject: [PATCH] Init --- .dockerignore | 24 +++ .github/workflows/docker.yml | 49 +++++ .gitignore | 192 ++++++++++++++++++ Dockerfile | 15 ++ src/Sibur.BuggyBot.sln | 25 +++ src/Sibur.BuggyBot/App/App.cs | 41 ++++ src/Sibur.BuggyBot/App/IApp.cs | 6 + src/Sibur.BuggyBot/Di/Di.cs | 43 ++++ src/Sibur.BuggyBot/Messaging/ITelegram.cs | 26 +++ src/Sibur.BuggyBot/Messaging/Telegram.cs | 58 ++++++ src/Sibur.BuggyBot/NLog.config | 18 ++ src/Sibur.BuggyBot/Program.cs | 14 ++ .../Settings/TelegramSettings.cs | 6 + src/Sibur.BuggyBot/Sibur.BuggyBot.csproj | 30 +++ src/Sibur.BuggyBot/appsettings.json | 6 + 15 files changed, 553 insertions(+) create mode 100644 .dockerignore create mode 100644 .github/workflows/docker.yml create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 src/Sibur.BuggyBot.sln create mode 100644 src/Sibur.BuggyBot/App/App.cs create mode 100644 src/Sibur.BuggyBot/App/IApp.cs create mode 100644 src/Sibur.BuggyBot/Di/Di.cs create mode 100644 src/Sibur.BuggyBot/Messaging/ITelegram.cs create mode 100644 src/Sibur.BuggyBot/Messaging/Telegram.cs create mode 100644 src/Sibur.BuggyBot/NLog.config create mode 100644 src/Sibur.BuggyBot/Program.cs create mode 100644 src/Sibur.BuggyBot/Settings/TelegramSettings.cs create mode 100644 src/Sibur.BuggyBot/Sibur.BuggyBot.csproj create mode 100644 src/Sibur.BuggyBot/appsettings.json diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..b09d81b --- /dev/null +++ b/.dockerignore @@ -0,0 +1,24 @@ +**/.classpath +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +README.md diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 0000000..1fd0b36 --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,49 @@ +name: Create and publish a Docker image + +# Configures this workflow to run every time a change is pushed to the branch called `release`. +on: + push: + branches: [ "master" ] + tags: + - '*' + +# Defines two custom environment variables for the workflow. These are used for the Container registry domain, and a name for the Docker image that this workflow builds. +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +# There is a single job in this workflow. It's configured to run on the latest available version of Ubuntu. +jobs: + build-and-push-image: + runs-on: ubuntu-latest + # Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job. + permissions: + contents: read + packages: write + # + steps: + - name: Checkout repository + uses: actions/checkout@v3 + # Uses the `docker/login-action` action to log in to the Container registry registry using the account and password that will publish the packages. Once published, the packages are scoped to the account defined here. + - name: Log in to the Container registry + uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + # This step uses [docker/metadata-action](https://github.com/docker/metadata-action#about) to extract tags and labels that will be applied to the specified image. The `id` "meta" allows the output of this step to be referenced in a subsequent step. The `images` value provides the base name for the tags and labels. + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + # This step uses the `docker/build-push-action` action to build the image, based on your repository's `Dockerfile`. If the build succeeds, it pushes the image to GitHub Packages. + # It uses the `context` parameter to define the build's context as the set of files located in the specified path. For more information, see "[Usage](https://github.com/docker/build-push-action#usage)" in the README of the `docker/build-push-action` repository. + # It uses the `tags` and `labels` parameters to tag and label the image with the output from the "meta" step. + - name: Build and push Docker image + uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4 + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d5526ab --- /dev/null +++ b/.gitignore @@ -0,0 +1,192 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +#rider +.idea/ + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Xamarin Studio / monodevelop user-specific +*.userprefs +*.dll.mdb +*.exe.mdb + +# Build results +[Dd]ebug/ +[Rr]elease/ +x64/ +build/ +[Bb]in/ +[Oo]bj/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +*_i.c +*_p.c +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.log +*.scc + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# Other Visual Studio data +.vs/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +*.ncrunch* +.*crunch*.local.xml + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.Publish.xml + +# Enable nuget.exe in the .nuget folder (though normally executables are not tracked) +!.nuget/NuGet.exe + +# Windows Azure Build Output +csx +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# VSCode +.vscode/ + +# Others +sql/ +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.[Pp]ublish.xml +*.pfx +*.publishsettings + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +App_Data/*.mdf +App_Data/*.ldf + + +#LightSwitch generated files +GeneratedArtifacts/ +_Pvt_Extensions/ +ModelManifest.xml + +# ========================= +# Windows detritus +# ========================= + +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Mac desktop service store files +.DS_Store + +# =================================================== +# Exclude F# project specific directories and files +# =================================================== + +# NuGet Packages Directory +packages/ + +# Test results produced by build +TestResults.xml + +# Nuget outputs +nuget/*.nupkg +release.cmd +release.sh +localpackages/ +*.orig +docsrc/content/license.md +docsrc/content/release-notes.md +.fake +docsrc/tools/FSharp.Formatting.svclog +artifacts +/artifacts +/artifacts + +.ionide +AssemblyInfo.cs diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..a36c325 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,15 @@ +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build + +# copy csproj and restore as distinct layers +COPY ./src /solution/ +WORKDIR /solution/ +RUN dotnet restore + +FROM build AS publish +RUN dotnet publish -c release --property PublishDir=/app --no-restore /p:TreatWarningsAsErrors=true /warnaserror -warnaserror + +# final stage/image +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS final +WORKDIR /app +COPY --from=publish /app ./ +ENTRYPOINT ["dotnet", "Approve.Checker.dll"] diff --git a/src/Sibur.BuggyBot.sln b/src/Sibur.BuggyBot.sln new file mode 100644 index 0000000..9ce629c --- /dev/null +++ b/src/Sibur.BuggyBot.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.8.34330.188 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sibur.BuggyBot", "Sibur.BuggyBot\Sibur.BuggyBot.csproj", "{818B0609-5FDB-41F0-9050-372CB57AD751}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {818B0609-5FDB-41F0-9050-372CB57AD751}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {818B0609-5FDB-41F0-9050-372CB57AD751}.Debug|Any CPU.Build.0 = Debug|Any CPU + {818B0609-5FDB-41F0-9050-372CB57AD751}.Release|Any CPU.ActiveCfg = Release|Any CPU + {818B0609-5FDB-41F0-9050-372CB57AD751}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {8D20BDBE-4209-43B8-812E-9300EAC636BD} + EndGlobalSection +EndGlobal diff --git a/src/Sibur.BuggyBot/App/App.cs b/src/Sibur.BuggyBot/App/App.cs new file mode 100644 index 0000000..e435e74 --- /dev/null +++ b/src/Sibur.BuggyBot/App/App.cs @@ -0,0 +1,41 @@ +using Sibur.BuggyBot.Messaging; +using System; +using Telegram.Bot.Types; + +namespace Sibur.BuggyBot.App; + +public class App : IApp +{ + private readonly ITelegram _telegram; + private readonly Random _random; + private readonly string[] _assignee = new[] { "yaprostosplu", "RobinsonBastard" }; + + public App(ITelegram telegram) + { + _telegram = telegram; + _telegram.Start().GetAwaiter().GetResult(); + _telegram.MessageHook = OnMessage; + _random = new Random(); + } + + private async Task OnMessage(Message message) + { + if (message.Text?.StartsWith($"@{_telegram.NickName}") == true) + { + var assignee = _assignee[_random.Next(0, _assignee.Length)]; + var msg = $"@{assignee}, прошу взять в работу."; + + await _telegram.SendMessageAsync(message.Chat.Id, msg, replyToMessageId: message.MessageId); + } + + Console.WriteLine($"[{message.From?.Id}] {message.Text}"); + } + + public async Task RunAsync() + { + while (true) + { + await Task.Delay(TimeSpan.FromSeconds(1)); + } + } +} \ No newline at end of file diff --git a/src/Sibur.BuggyBot/App/IApp.cs b/src/Sibur.BuggyBot/App/IApp.cs new file mode 100644 index 0000000..52686ce --- /dev/null +++ b/src/Sibur.BuggyBot/App/IApp.cs @@ -0,0 +1,6 @@ +namespace Sibur.BuggyBot.App; + +public interface IApp +{ + Task RunAsync(); +} \ No newline at end of file diff --git a/src/Sibur.BuggyBot/Di/Di.cs b/src/Sibur.BuggyBot/Di/Di.cs new file mode 100644 index 0000000..a943330 --- /dev/null +++ b/src/Sibur.BuggyBot/Di/Di.cs @@ -0,0 +1,43 @@ +using Autofac; +using Microsoft.Extensions.Configuration; +using Newtonsoft.Json; +using NLog; +using Sibur.BuggyBot.App; +using Sibur.BuggyBot.Messaging; +using Sibur.BuggyBot.Settings; +using Telegram.Bot; + +namespace Sibur.BuggyBot.Di; + +public class DI +{ + public IContainer Build() + { + var container = new ContainerBuilder(); + + var config = new ConfigurationBuilder() + .AddJsonFile("appsettings.json") + .AddEnvironmentVariables() + .Build(); + container.Register(c => config).As().SingleInstance(); + container.RegisterType().As().SingleInstance(); + + container.RegisterType().As(); + container.Register(c => + { + var settings = c.Resolve().GetSection("Telegram").Get()!; ; + Console.WriteLine(JsonConvert.SerializeObject(settings)); + return settings; + }) + .As().SingleInstance(); + + container.Register(c => LogManager.GetLogger("main")).As(); + container.Register(c => + { + var client = new TelegramBotClient(c.Resolve().Token); + return client; + }).AsSelf().SingleInstance(); + + return container.Build(); + } +} \ No newline at end of file diff --git a/src/Sibur.BuggyBot/Messaging/ITelegram.cs b/src/Sibur.BuggyBot/Messaging/ITelegram.cs new file mode 100644 index 0000000..e4e2f55 --- /dev/null +++ b/src/Sibur.BuggyBot/Messaging/ITelegram.cs @@ -0,0 +1,26 @@ +using Telegram.Bot; +using Telegram.Bot.Types; +using Telegram.Bot.Types.Enums; +using Telegram.Bot.Types.ReplyMarkups; + +namespace Sibur.BuggyBot.Messaging; + +public interface ITelegram +{ + Task Start(); + public Func? MessageHook { get; set; } + public string? NickName { get; set; } + Task SendMessageAsync( + ChatId chatId, + string text, + int? messageThreadId = default, + ParseMode? parseMode = default, + IEnumerable? entities = default, + bool? disableWebPagePreview = default, + bool? disableNotification = default, + bool? protectContent = default, + int? replyToMessageId = default, + bool? allowSendingWithoutReply = default, + IReplyMarkup? replyMarkup = default, + CancellationToken cancellationToken = default); +} \ No newline at end of file diff --git a/src/Sibur.BuggyBot/Messaging/Telegram.cs b/src/Sibur.BuggyBot/Messaging/Telegram.cs new file mode 100644 index 0000000..6703d67 --- /dev/null +++ b/src/Sibur.BuggyBot/Messaging/Telegram.cs @@ -0,0 +1,58 @@ +using NLog; +using Telegram.Bot; +using Telegram.Bot.Polling; +using Telegram.Bot.Types; +using Telegram.Bot.Types.Enums; +using Telegram.Bot.Types.ReplyMarkups; + +namespace Sibur.BuggyBot.Messaging +{ + public sealed class Telegram: ITelegram + { + private readonly TelegramBotClient _telegram; + private readonly ILogger _logger; + public Func? MessageHook { get; set; } = null; + public string? NickName { get; set; } = null; + + public Telegram(TelegramBotClient telegram, ILogger logger) + { + _telegram = telegram; + _logger = logger; + } + + public async Task Start() + { + var cts = new CancellationTokenSource(); + _telegram.StartReceiving(updateHandler: HandleUpdateAsync, + pollingErrorHandler: PollingErrorHandler, + receiverOptions: new ReceiverOptions(), + cancellationToken: cts.Token); + + NickName = (await _telegram.GetMeAsync(cancellationToken: cts.Token)).Username; + } + + + private void PollingErrorHandler(ITelegramBotClient arg1, Exception arg2, CancellationToken arg3) + { + + } + + private void HandleUpdateAsync(ITelegramBotClient arg1, Update update, CancellationToken arg3) + { + if (update.Message != null) + { + _logger.Info($"{update.Message.Chat.Id}: {update.Message.Text}"); + MessageHook?.Invoke(update.Message); + } + } + + public Task SendMessageAsync(ChatId chatId, string text, int? messageThreadId = default, ParseMode? parseMode = default, + IEnumerable? entities = default, bool? disableWebPagePreview = default, bool? disableNotification = default, + bool? protectContent = default, int? replyToMessageId = default, bool? allowSendingWithoutReply = default, + IReplyMarkup? replyMarkup = default, CancellationToken cancellationToken = default) + { + return _telegram.SendTextMessageAsync(chatId, text, messageThreadId, parseMode, entities, disableWebPagePreview, + disableNotification, protectContent, replyToMessageId, allowSendingWithoutReply, replyMarkup, cancellationToken); + } + } +} diff --git a/src/Sibur.BuggyBot/NLog.config b/src/Sibur.BuggyBot/NLog.config new file mode 100644 index 0000000..99cb37d --- /dev/null +++ b/src/Sibur.BuggyBot/NLog.config @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Sibur.BuggyBot/Program.cs b/src/Sibur.BuggyBot/Program.cs new file mode 100644 index 0000000..2dbe1fa --- /dev/null +++ b/src/Sibur.BuggyBot/Program.cs @@ -0,0 +1,14 @@ +using Autofac; +using Sibur.BuggyBot.App; +using Sibur.BuggyBot.Di; + +class Program +{ + static async Task Main(string[] args) + { + var container = new DI().Build(); + + var app = container.Resolve(); + await app.RunAsync(); + } +} \ No newline at end of file diff --git a/src/Sibur.BuggyBot/Settings/TelegramSettings.cs b/src/Sibur.BuggyBot/Settings/TelegramSettings.cs new file mode 100644 index 0000000..34c8727 --- /dev/null +++ b/src/Sibur.BuggyBot/Settings/TelegramSettings.cs @@ -0,0 +1,6 @@ +namespace Sibur.BuggyBot.Settings; + +public sealed class TelegramSettings +{ + public string Token { get; init; } = ""; +} \ No newline at end of file diff --git a/src/Sibur.BuggyBot/Sibur.BuggyBot.csproj b/src/Sibur.BuggyBot/Sibur.BuggyBot.csproj new file mode 100644 index 0000000..c62b875 --- /dev/null +++ b/src/Sibur.BuggyBot/Sibur.BuggyBot.csproj @@ -0,0 +1,30 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + + + + + + + + + + Always + + + Always + + + + diff --git a/src/Sibur.BuggyBot/appsettings.json b/src/Sibur.BuggyBot/appsettings.json new file mode 100644 index 0000000..b3973ca --- /dev/null +++ b/src/Sibur.BuggyBot/appsettings.json @@ -0,0 +1,6 @@ +{ + "urls": "http://*:80", + "Telegram": { + "Token": "" + } +}