diff --git a/.gitignore b/.gitignore index 97e5868..8819f51 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ **/obj appsettings.Development.json .user -**/*.user \ No newline at end of file +**/*.user +.fake \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..a658066 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,27 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": ".NET Core Launch (console)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + "program": "${workspaceFolder}/CosmosProposalBot/bin/Debug/net6.0/CosmosProposalBot.dll", + "args": [], + "cwd": "${workspaceFolder}/CosmosProposalBot", + "console": "integratedTerminal", + "stopAtEntry": false, + "env": { + "DOTNET_ENVIRONMENT": "Development" + } + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach" + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..18cdc14 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "files.exclude": { + ".vs/**": true, + "**/bin": true, + "**/obj": true + }, + } \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..92f95b9 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,41 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/CosmosProposalBot/CosmosProposalBot.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "publish", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "${workspaceFolder}/CosmosProposalBot/CosmosProposalBot.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "watch", + "command": "dotnet", + "type": "process", + "args": [ + "watch", + "run", + "--project", + "${workspaceFolder}/CosmosProposalBot/CosmosProposalBot.csproj" + ], + "problemMatcher": "$msCompile" + } + ] +} \ No newline at end of file diff --git a/CosmosProposalBot/Modules/SubscribeModule.cs b/CosmosProposalBot/Modules/SubscribeModule.cs index 346b25b..cf2e492 100644 --- a/CosmosProposalBot/Modules/SubscribeModule.cs +++ b/CosmosProposalBot/Modules/SubscribeModule.cs @@ -30,75 +30,19 @@ public SubscribeModule( ILogger logger, [SlashCommand("supported-chains", "Lists all chains that the bot currently supports")] public async Task SupportedChains() - { - try - { - await DeferAsync(); - - await using var scope = _serviceProvider.CreateAsyncScope(); - var dbContext = scope.ServiceProvider.GetRequiredService(); - var guildSpecificChains = dbContext.Chains - .Where( c => c.CustomForGuildId == Context.Guild.Id ) - .Select( c => $"`{c.Name}`" ) - .ToList(); - - var standardChains = _options.Value.SupportedChains - .Select( c => $"`{c}`" ); - - var eb = new EmbedBuilder() - .WithTitle( "Supported Chains" ) - .WithFields( - new EmbedFieldBuilder() - .WithName("Standard") - .WithValue(string.Join(", ", standardChains)), - new EmbedFieldBuilder() - .WithName("Custom") - .WithValue(string.Join(", ", guildSpecificChains))); - - await FollowupAsync($"", embed: eb.Build()); - } - catch( Exception e ) - { - Console.WriteLine( e ); - throw; - } - } + => await _serviceProvider.CreateScope().ServiceProvider + .GetRequiredService() + .SupportedChains( Context ); [SlashCommand( "private", "Subscribes to DMs about proposals for a given chain" )] public async Task SubscribePrivate( string chainName ) - { - try - { - await DeferAsync( ephemeral: true ); - - await using var scope = _serviceProvider.CreateAsyncScope(); - var subscriptionHelper = scope.ServiceProvider.GetRequiredService(); - - await subscriptionHelper.SubscribeDm( Context, chainName ); - } - catch( Exception e ) - { - Console.WriteLine( e ); - throw; - } - } + => await _serviceProvider.CreateScope().ServiceProvider + .GetRequiredService() + .SubscribePrivate( Context, chainName ); [SlashCommand( "channel", "Subscribes to channel notifications about proposals for a given chain" )] public async Task SubscribeChannel( string chainName ) - { - try - { - await DeferAsync(); - - await using var scope = _serviceProvider.CreateAsyncScope(); - var subscriptionHelper = scope.ServiceProvider.GetRequiredService(); - - await subscriptionHelper.SubscribeChannel( Context, chainName ); - } - catch( Exception e ) - { - Console.WriteLine( e ); - throw; - } - } + => await _serviceProvider.CreateScope().ServiceProvider + .GetRequiredService() + .SubscribeChannel( Context, chainName ); } diff --git a/CosmosProposalBot/Util/SubscribeModuleActions.cs b/CosmosProposalBot/Util/SubscribeModuleActions.cs new file mode 100644 index 0000000..a348407 --- /dev/null +++ b/CosmosProposalBot/Util/SubscribeModuleActions.cs @@ -0,0 +1,106 @@ +using System.Text; +using CosmosProposalBot.Configuration; +using CosmosProposalBot.Data; +using CosmosProposalBot.Data.Model; +using CosmosProposalBot.Util; +using Discord; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +namespace CosmosProposalBot.Modules; + +public interface ISubscribeModuleActions +{ + Task SupportedChains(IInteractionContext context); + Task SubscribePrivate( IInteractionContext context, string chainName ); + Task SubscribeChannel( IInteractionContext context, string chainName ); +} + +public class SubscribeModuleActions : ISubscribeModuleActions +{ + private readonly ILogger _logger; + private readonly IOptions _options; + private readonly IServiceProvider _serviceProvider; + + public SubscribeModuleActions( ILogger logger, + IOptions options, + IServiceProvider serviceProvider) + { + _logger = logger; + _options = options; + _serviceProvider = serviceProvider; + } + + public async Task SupportedChains(IInteractionContext context) + { + try + { + await context.Interaction.DeferAsync(); + + await using var scope = _serviceProvider.CreateAsyncScope(); + var dbContext = scope.ServiceProvider.GetRequiredService(); + var guildSpecificChains = dbContext.Chains + .Where( c => c.CustomForGuildId == context.Guild.Id ) + .Select( c => $"`{c.Name}`" ) + .ToList(); + + var standardChains = _options.Value.SupportedChains + .Select( c => $"`{c}`" ); + + var eb = new EmbedBuilder() + .WithTitle( "Supported Chains" ) + .WithFields( + new EmbedFieldBuilder() + .WithName("Standard") + .WithValue(string.Join(", ", standardChains)), + new EmbedFieldBuilder() + .WithName("Custom") + .WithValue(string.Join(", ", guildSpecificChains))); + + await context.Interaction.FollowupAsync($"", embed: eb.Build()); + } + catch( Exception e ) + { + Console.WriteLine( e ); + throw; + } + } + + public async Task SubscribePrivate( IInteractionContext context, string chainName ) + { + try + { + await context.Interaction.DeferAsync( ephemeral: true ); + + await using var scope = _serviceProvider.CreateAsyncScope(); + var subscriptionHelper = scope.ServiceProvider.GetRequiredService(); + + await subscriptionHelper.SubscribeDm( context, chainName ); + } + catch( Exception e ) + { + Console.WriteLine( e ); + throw; + } + } + + public async Task SubscribeChannel( IInteractionContext context, string chainName ) + { + try + { + await context.Interaction.DeferAsync(); + + await using var scope = _serviceProvider.CreateAsyncScope(); + var subscriptionHelper = scope.ServiceProvider.GetRequiredService(); + + await subscriptionHelper.SubscribeChannel( context, chainName ); + } + catch( Exception e ) + { + Console.WriteLine( e ); + throw; + } + } +} diff --git a/Tests/Util/SubscribeModuleActionsTest b/Tests/Util/SubscribeModuleActionsTest new file mode 100644 index 0000000..0148c14 --- /dev/null +++ b/Tests/Util/SubscribeModuleActionsTest @@ -0,0 +1,32 @@ +using System.Threading.Tasks; +using AutoFixture; +using CosmosProposalBot.Modules; +using Discord; +using Moq; +using Xunit; + +namespace Tests.Util; + +public class SubscribeModuleActionsTest +{ + private readonly IFixture _fixture = FixtureFactory.CreateFixture(); + private SubscribeModuleActions _configModuleActions; + private Mock _interactionMock; + private Mock _interactionContextMock; + + public SubscribeModuleActionsTest() + { + _interactionMock = _fixture.Freeze>(); + _interactionContextMock = _fixture.Freeze>(); + _interactionContextMock.Setup( m => m.Interaction ) + .Returns( _interactionMock.Object ); + + _configModuleActions = _fixture.Create(); + } + + [Fact] + public async Task SupportedChains_Something() + { + System.Console.WriteLine("Hello World"); + } +} \ No newline at end of file