From c2231192268fc31fddb9318e067975bd404d65e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20H=C3=B6glund?= Date: Wed, 6 May 2020 12:07:58 +0200 Subject: [PATCH] Added github integration added new releases command in public module --- PickupBot.Commands/Modules/PublicModule.cs | 38 +++++++- PickupBot.Commands/PickupBot.Commands.csproj | 3 +- PickupBot.GitHub/GitHubService.cs | 47 ++++++++++ PickupBot.GitHub/Models/GitHubRelease.cs | 33 +++++++ PickupBot.GitHub/PickupBot.GitHub.csproj | 11 +++ PickupBot.sln | 8 +- PickupBot/PickupBot.csproj | 5 +- PickupBot/Program.cs | 96 ++++++++++---------- 8 files changed, 189 insertions(+), 52 deletions(-) create mode 100644 PickupBot.GitHub/GitHubService.cs create mode 100644 PickupBot.GitHub/Models/GitHubRelease.cs create mode 100644 PickupBot.GitHub/PickupBot.GitHub.csproj diff --git a/PickupBot.Commands/Modules/PublicModule.cs b/PickupBot.Commands/Modules/PublicModule.cs index 2c2a745..809f74a 100644 --- a/PickupBot.Commands/Modules/PublicModule.cs +++ b/PickupBot.Commands/Modules/PublicModule.cs @@ -3,11 +3,14 @@ using System.Reflection; using System.Text; using System.Threading.Tasks; +using Discord; using Discord.Addons.CommandsExtension; using Discord.Commands; using PickupBot.Commands.Extensions; using PickupBot.Data.Models; using PickupBot.Data.Repositories; +using PickupBot.GitHub; +using PickupBot.GitHub.Models; namespace PickupBot.Commands.Modules { @@ -17,13 +20,16 @@ public class PublicModule : ModuleBase { private readonly CommandService _commandService; private readonly ISubscriberActivitiesRepository _activitiesRepository; - + private readonly GitHubService _githubService; + public PublicModule( CommandService commandService, - ISubscriberActivitiesRepository activitiesRepository) + ISubscriberActivitiesRepository activitiesRepository, + GitHubService gitHubService) { _commandService = commandService; _activitiesRepository = activitiesRepository; + _githubService = gitHubService; } [Command("ping")] @@ -114,5 +120,33 @@ public async Task Top10() await ReplyAsync(sb.ToString()); } + + [Command("releases")] + [Summary("Retrieves the 3 latest releases from github")] + public async Task Releases() + { + using (Context.Channel.EnterTypingState()) + { + var releases = await _githubService.GetReleases(); + + var gitHubReleases = releases as GitHubRelease[] ?? releases.ToArray(); + + foreach (var release in gitHubReleases.Take(3)) + { + var embed = new EmbedBuilder + { + Author = new EmbedAuthorBuilder() + .WithIconUrl(release.Author?.AvatarUrl) + .WithName(release.Author?.Name), + Title = release.Name, + Description = release.Body, + Url = release.Url + + }.Build(); + + await ReplyAsync(embed:embed); + } + } + } } } diff --git a/PickupBot.Commands/PickupBot.Commands.csproj b/PickupBot.Commands/PickupBot.Commands.csproj index 2fb1b0e..6d03fab 100644 --- a/PickupBot.Commands/PickupBot.Commands.csproj +++ b/PickupBot.Commands/PickupBot.Commands.csproj @@ -1,4 +1,4 @@ - + netcoreapp3.1 @@ -13,6 +13,7 @@ + diff --git a/PickupBot.GitHub/GitHubService.cs b/PickupBot.GitHub/GitHubService.cs new file mode 100644 index 0000000..b302faf --- /dev/null +++ b/PickupBot.GitHub/GitHubService.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text.Json; +using System.Threading.Tasks; +using PickupBot.GitHub.Models; + +namespace PickupBot.GitHub +{ + public class GitHubService + { + private readonly HttpClient _client; + + public GitHubService(HttpClient client) + { + client.BaseAddress = new Uri("https://api.github.com/"); + + client.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json"); + client.DefaultRequestHeaders.Add("User-Agent", "Discord-Pickup-Bot"); + + _client = client; + } + + public async Task GetCommits(int count = 10) + { + var response = await _client.GetAsync("/repos/Floydan/discord-pickup-bot/commits"); + + if (response.IsSuccessStatusCode) + { + return await response.Content.ReadAsStringAsync(); + } + + return $"StatusCode: {response.StatusCode}"; + } + + public async Task> GetReleases(int count = 3) + { + var response = await _client.GetAsync("/repos/Floydan/discord-pickup-bot/releases"); + + if (!response.IsSuccessStatusCode) return null; + + await using var stream = await response.Content.ReadAsStreamAsync(); + return await JsonSerializer.DeserializeAsync>(stream); + + } + } +} diff --git a/PickupBot.GitHub/Models/GitHubRelease.cs b/PickupBot.GitHub/Models/GitHubRelease.cs new file mode 100644 index 0000000..4ec9ace --- /dev/null +++ b/PickupBot.GitHub/Models/GitHubRelease.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Text.Json.Serialization; + +namespace PickupBot.GitHub.Models +{ + public class GitHubRelease + { + [JsonPropertyName("author")] + public GitHubAuthor Author { get; set; } + + [JsonPropertyName("name")] + public string Name { get; set; } + + [JsonPropertyName("body")] + public string Body { get; set; } + + [JsonPropertyName("published_at")] + public DateTime PublishedDate { get; set; } + + [JsonPropertyName("html_url")] + public string Url { get; set; } + } + + public class GitHubAuthor + { + [JsonPropertyName("login")] + public string Name { get; set; } + [JsonPropertyName("avatar_url")] + public string AvatarUrl { get; set; } + } +} diff --git a/PickupBot.GitHub/PickupBot.GitHub.csproj b/PickupBot.GitHub/PickupBot.GitHub.csproj new file mode 100644 index 0000000..6ecaab5 --- /dev/null +++ b/PickupBot.GitHub/PickupBot.GitHub.csproj @@ -0,0 +1,11 @@ + + + + netcoreapp3.1 + + + + + + + diff --git a/PickupBot.sln b/PickupBot.sln index d592dbb..a2a4c47 100644 --- a/PickupBot.sln +++ b/PickupBot.sln @@ -15,7 +15,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PickupBot.Data", "PickupBot.Data\PickupBot.Data.csproj", "{8CC4FB91-0E70-43E4-8879-D37FF529E43A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PickupBot.Translation", "PickupBot.Translation\PickupBot.Translation.csproj", "{1FE7EA78-D812-4895-9621-ECB2188F8A2E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PickupBot.Translation", "PickupBot.Translation\PickupBot.Translation.csproj", "{1FE7EA78-D812-4895-9621-ECB2188F8A2E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PickupBot.GitHub", "PickupBot.GitHub\PickupBot.GitHub.csproj", "{1A49EC39-5147-48A3-AB5B-F1FFDEE253CE}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -39,6 +41,10 @@ Global {1FE7EA78-D812-4895-9621-ECB2188F8A2E}.Debug|Any CPU.Build.0 = Debug|Any CPU {1FE7EA78-D812-4895-9621-ECB2188F8A2E}.Release|Any CPU.ActiveCfg = Release|Any CPU {1FE7EA78-D812-4895-9621-ECB2188F8A2E}.Release|Any CPU.Build.0 = Release|Any CPU + {1A49EC39-5147-48A3-AB5B-F1FFDEE253CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1A49EC39-5147-48A3-AB5B-F1FFDEE253CE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1A49EC39-5147-48A3-AB5B-F1FFDEE253CE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1A49EC39-5147-48A3-AB5B-F1FFDEE253CE}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/PickupBot/PickupBot.csproj b/PickupBot/PickupBot.csproj index 384210f..ae1f810 100644 --- a/PickupBot/PickupBot.csproj +++ b/PickupBot/PickupBot.csproj @@ -3,17 +3,20 @@ Exe netcoreapp3.1 a7bb364b-0d73-420c-a3b9-18270f20e20f - 1.5.1 + 1.6.0 + + + diff --git a/PickupBot/Program.cs b/PickupBot/Program.cs index af88d71..aabd93b 100644 --- a/PickupBot/Program.cs +++ b/PickupBot/Program.cs @@ -6,28 +6,67 @@ using Discord.Commands; using Discord.WebSocket; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; using PickupBot.Commands; using PickupBot.Data.Models; using PickupBot.Data.Repositories; +using PickupBot.GitHub; using PickupBot.Translation.Services; namespace PickupBot { public class Program { - public static void Main(string[] args) => new Program().MainAsync().GetAwaiter().GetResult(); - - private async Task MainAsync() + private static IHost _host; + private static async Task Main(string[] args) { - await using var services = ConfigureServices(); + var storageConnectionString = Environment.GetEnvironmentVariable("StorageConnectionString"); - ServiceLocator.SetLocatorProvider(services); - var client = services.GetRequiredService(); + var builder = new HostBuilder() + .ConfigureServices((hostContext, services) => + { + var discordSocketConfig = new DiscordSocketConfig { MessageCacheSize = 100, LogLevel = LogSeverity.Info }; + + services + .AddHttpClient() + .AddSingleton(provider => new DiscordSocketClient(discordSocketConfig)) + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddScoped>(provider => + new AzureTableStorage( + new AzureTableSettings(storageConnectionString, nameof(PickupQueue)) + ) + ) + .AddScoped>(provider => + new AzureTableStorage( + new AzureTableSettings(storageConnectionString, nameof(FlaggedSubscriber)) + ) + ) + .AddScoped>(provider => + new AzureTableStorage( + new AzureTableSettings(storageConnectionString, nameof(SubscriberActivities)) + ) + ) + .AddScoped() + .AddScoped() + .AddScoped(); + + + services.AddHttpClient(); + + }).UseConsoleLifetime(); + + _host = builder.Build(); + + var client = _host.Services.GetRequiredService(); client.Log += LogAsync; client.JoinedGuild += OnJoinedGuild; client.MessageUpdated += OnMessageUpdated; - services.GetRequiredService().Log += LogAsync; + _host.Services.GetRequiredService().Log += LogAsync; // Tokens should be considered secret data and never hard-coded. // We can read from the environment variable to avoid hardcoding. @@ -35,15 +74,14 @@ private async Task MainAsync() await client.StartAsync(); // Here we initialize the logic required to register our commands. - await services.GetRequiredService().InitializeAsync(); + await _host.Services.GetRequiredService().InitializeAsync(); //await client.SetGameAsync("Pickup bot", null, ActivityType.Playing); var prefix = Environment.GetEnvironmentVariable("CommandPrefix") ?? "!"; await client.SetActivityAsync( new Game($"Pickup bot | {prefix}help", ActivityType.Playing, - ActivityProperties.Play, - $"Current players on ra3.se: 3")); + ActivityProperties.Play)); await Task.Delay(-1); } @@ -76,10 +114,7 @@ await guild.CreateTextChannelAsync("pickup", private static async Task OnMessageUpdated(Cacheable before, SocketMessage after, ISocketMessageChannel channel) { - //var message = await before.GetOrDownloadAsync(); - //await LogAsync(new LogMessage(LogSeverity.Info, "OnMessageUpdated", $"{message} -> {after}")); - - var commandHandler = ServiceLocator.Current.GetInstance(); + var commandHandler = _host.Services.GetService(); if (commandHandler != null) await commandHandler.MessageReceivedAsync(after); } @@ -89,38 +124,5 @@ private static Task LogAsync(LogMessage msg) Console.WriteLine(msg.ToString()); return Task.CompletedTask; } - - private static ServiceProvider ConfigureServices() - { - var storageConnectionString = Environment.GetEnvironmentVariable("StorageConnectionString"); - - var discordSocketConfig = new DiscordSocketConfig { MessageCacheSize = 100, LogLevel = LogSeverity.Info }; - - return new ServiceCollection() - .AddSingleton(provider => new DiscordSocketClient(discordSocketConfig)) - .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddScoped>(provider => - new AzureTableStorage( - new AzureTableSettings(storageConnectionString, nameof(PickupQueue)) - ) - ) - .AddScoped>(provider => - new AzureTableStorage( - new AzureTableSettings(storageConnectionString, nameof(FlaggedSubscriber)) - ) - ) - .AddScoped>(provider => - new AzureTableStorage( - new AzureTableSettings(storageConnectionString, nameof(SubscriberActivities)) - ) - ) - .AddScoped() - .AddScoped() - .AddScoped() - .BuildServiceProvider(); - } } }