Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Discord.Net" Version="2.3.1" />
<PackageReference Include="MediatR" Version="9.0.0" />
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="9.0.0" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.10.13" />
Expand All @@ -25,7 +26,7 @@
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
<PackageReference Include="Serilog.Sinks.Debug" Version="2.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="4.1.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.1.3" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.1.4" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System.Threading;
using System.Threading.Tasks;
using ArmaForces.Boderator.BotService.Discord;
using ArmaForces.Boderator.BotService.Features.Test;
using Discord;
using MediatR;
using Microsoft.AspNetCore.Mvc;

Expand All @@ -10,17 +12,29 @@ namespace ArmaForces.Boderator.BotService.Controllers
public class DebugController : Controller
{
private readonly IMediator _mediator;
private readonly IDiscordService _discordService;

public DebugController(IMediator mediator)
public DebugController(IMediator mediator, IDiscordService discordService)
{
_mediator = mediator;
_discordService = discordService;
}

[HttpGet]
[HttpGet("Test")]
public async Task<ActionResult> Test(CancellationToken cToken)
{
string response = await _mediator.Send(new TestCommand(), cToken);
return Ok(response);
}

[HttpGet("GetDiscordStatus")]
public ActionResult GetDiscordStatus() => Ok(_discordService.GetDiscordClientStatus());

[HttpPut("SetBotStatus/{status}")]
public async Task<ActionResult> SetBotStatus(string status, ActivityType type = ActivityType.Playing)
{
await _discordService.SetBotStatus(status, type);
return Ok();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace ArmaForces.Boderator.BotService.DTOs
{
public class DiscordServiceStatus
{
public string ConnectionState { get; init; }
public string LoginState { get; init; }
public string ClientState { get; init; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using Microsoft.Extensions.DependencyInjection;

namespace ArmaForces.Boderator.BotService.Discord.DependencyInjection
{
internal class DiscordServiceBuilder : IDiscordServiceBuilder
{
private IServiceCollection Services { get; }

public DiscordServiceBuilder(IServiceCollection services) => Services = services;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace ArmaForces.Boderator.BotService.Discord.DependencyInjection
{
internal interface IDiscordServiceBuilder
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using ArmaForces.Boderator.BotService.DTOs;
using Discord;
using Discord.WebSocket;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace ArmaForces.Boderator.BotService.Discord
{
public sealed class DiscordService : IDiscordService, IHostedService
{
private readonly ILogger<DiscordService> _log;
private readonly DiscordSocketClient _discordClient;
private string _token;

public DiscordService(ILogger<DiscordService> logger, string token)
{
_log = logger;
_discordClient = new DiscordSocketClient();
_discordClient.Log += message => Task.Run(() => _log.Log(MapSeverity(message.Severity), "[Discord.NET Log] " + message.Message));
_discordClient.Connected += () => Task.Run(() => _log.LogInformation("Discord connected"));
_token = token;
}

public async Task StartAsync(CancellationToken cancellationToken)
{
_log.LogInformation("Discord Service started");
await _discordClient.LoginAsync(TokenType.Bot, _token, true);
await _discordClient.StartAsync();
}

public Task StopAsync(CancellationToken cancellationToken) => Task.Run(() =>
{
_discordClient.Dispose();
_log.LogInformation("Discord Service stopped");
}, cancellationToken);

public DiscordServiceStatus GetDiscordClientStatus()
{
_log.LogInformation($"Current Discord Bot status: Login: {_discordClient.LoginState} | " +
$"Connection: {_discordClient.ConnectionState} | " +
$"Status: {_discordClient.Status}");
return new DiscordServiceStatus
{
ConnectionState = _discordClient.ConnectionState.ToString(),
LoginState = _discordClient.LoginState.ToString(),
ClientState = _discordClient.Status.ToString()
};
}

public async Task SetBotStatus(string newStatus, ActivityType statusType) =>
await _discordClient.SetGameAsync(newStatus, type: statusType);

private static LogLevel MapSeverity(LogSeverity severity) =>
severity switch
{
LogSeverity.Verbose => LogLevel.Trace,
LogSeverity.Debug => LogLevel.Debug,
LogSeverity.Info => LogLevel.Information,
LogSeverity.Warning => LogLevel.Warning,
LogSeverity.Error => LogLevel.Error,
LogSeverity.Critical => LogLevel.Critical
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using ArmaForces.Boderator.BotService.Discord.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

namespace ArmaForces.Boderator.BotService.Discord
{
internal static class DiscordServiceCollectionExtentions
{
public static IDiscordServiceBuilder AddDiscordService(this IServiceCollection serviceDescriptors, string token)
{
serviceDescriptors.AddSingleton<IDiscordService, DiscordService>(sP => new DiscordService(sP.GetService<ILogger<DiscordService>>(), token));
serviceDescriptors.AddHostedService(sP => sP.GetRequiredService<IDiscordService>() as DiscordService);
return new DiscordServiceBuilder(serviceDescriptors);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System.Threading.Tasks;
using ArmaForces.Boderator.BotService.DTOs;
using Discord;

namespace ArmaForces.Boderator.BotService.Discord
{
public interface IDiscordService
{
DiscordServiceStatus GetDiscordClientStatus();
Task SetBotStatus(string newStatus, ActivityType statusType);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System;
using System.Collections;

namespace ArmaForces.Boderator.BotService.Helpers
{
public static class Configuration
{
public static string DiscordToken => GetParameter("DISCORD_TOKEN");

private static IDictionary Parameters { get; }

static Configuration()
{
Parameters = Environment.GetEnvironmentVariables();
}

public static string GetParameter(string key) => (string)Parameters[key];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
using Microsoft.Extensions.Hosting;
using Serilog;

namespace ArmaForces.Boderator.WebService
namespace ArmaForces.Boderator.BotService
{
public class Program
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using ArmaForces.Boderator.BotService.Discord;
using MediatR;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
Expand All @@ -6,7 +7,7 @@
using Microsoft.Extensions.Hosting;
using Microsoft.OpenApi.Models;

namespace ArmaForces.Boderator.WebService
namespace ArmaForces.Boderator.BotService
{
public class Startup
{
Expand All @@ -26,6 +27,7 @@ public void ConfigureServices(IServiceCollection services)
{
c.SwaggerDoc("v3", new OpenApiInfo { Title = "ArmaForces.Boderator.WebService", Version = "v3" });
});
services.AddDiscordService(Helpers.Configuration.DiscordToken);
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
Expand All @@ -46,7 +48,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)

app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapControllerRoute("default", "api/{controller}/{action}");
});
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"Serilog": {
"WriteTo": [
{
"Name": "Console",
"Args": {
"theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console",
"outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} {Level:u3}] [{ThreadId}] {Message:lj}{NewLine}{Exception}"
}
},
{
"Name": "Debug",
"outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} {Level:u3}] [{ThreadId}] {Message:lj}{NewLine}{Exception}"
},
{
"Name": "File",
"Args": {
"path": "Logs/log.txt",
"rollingInterval": "Day",
"retainedFileCountLimit": 7,
"outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} {Level:u3}] [{ThreadId}] {Message:lj}{NewLine}{Exception}"
}
}
],
"Enrich": [ "WithThreadId" ]
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"Serilog": {
"WriteTo": [
{
"Name": "Console",
"Args": {
"theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console",
"outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} {Level:u3}] [{ThreadId}] {Message:lj} {Properties}{NewLine}{Exception}"
}
},
{
"Name": "File",
"Args": {
"path": "log.txt",
"rollingInterval": "Day",
"retainedFileCountLimit": 7,
"outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} {Level:u3}] [{ThreadId}] {Message:lj} {Properties}{NewLine}{Exception}"
}
}
],
"Enrich": [ "WithThreadId" ]
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using System;
using ArmaForces.Boderator.WebService;
using ArmaForces.Boderator.BotService;
using MediatR;
using Microsoft.Extensions.DependencyInjection;

Expand Down