[CompositeRoles] Add listener and options

This commit is contained in:
2023-03-25 09:25:20 +01:00
parent ced9d15083
commit 14f90a2d18
6 changed files with 116 additions and 2 deletions

View File

@@ -0,0 +1,60 @@
using Cocotte.Options;
using Discord;
using Discord.WebSocket;
using Microsoft.Extensions.Options;
namespace Cocotte.Modules.Activities;
public class CompositeRolesListener
{
private readonly ILogger<CompositeRolesListener> _logger;
private readonly IDictionary<ulong, GuildCompositeRoles[]> _compositeRoles;
public CompositeRolesListener(ILogger<CompositeRolesListener> logger,
IOptions<CompositeRolesOptions> compositeRolesOptions)
{
_logger = logger;
// Initialize dictionary: transform string guildIds to ulong
_compositeRoles = compositeRolesOptions.Value.CompositeRoles.ToDictionary(kp => ulong.Parse(kp.Key), kp => kp.Value);
}
public async Task UserUpdated(Cacheable<SocketGuildUser, ulong> cacheable, SocketGuildUser guildUser)
{
// Fetch composite roles for this guild
if (!_compositeRoles.TryGetValue(guildUser.Guild.Id, out var guildCompositeRoles))
{
return;
}
_logger.LogTrace("Guild {Guild} has at least one composite role, checking for user {User}", guildUser.Guild.Name, guildUser.DisplayName);
// Check roles for each composite roles
var roles = guildUser.Roles;
foreach (var compositeRole in guildCompositeRoles)
{
// If the user has the target role, check if we need to remove it
if (roles.FirstOrDefault(r => r.Id == compositeRole.TargetRoleId) is { } presentTargetRole)
{
// Check that the user no associated role
if (!roles.Any(r => compositeRole.CompositeRolesIds.Contains(r.Id)))
{
await guildUser.RemoveRoleAsync(presentTargetRole);
_logger.LogInformation("CompositeRoles removed role {Role} from {User}", presentTargetRole.Name, guildUser.DisplayName);
}
}
// It the user doesn't have the target role, check if we need to add it
else
{
// Check that the user has at least one of the desired roles
if (roles.Any(r => compositeRole.CompositeRolesIds.Contains(r.Id)))
{
var missingTargetRole = guildUser.Guild.GetRole(compositeRole.TargetRoleId);
await guildUser.AddRoleAsync(missingTargetRole);
_logger.LogInformation("CompositeRoles added role {Role} from {User}", missingTargetRole.Name, guildUser.DisplayName);
}
}
}
}
}

View File

@@ -1,5 +1,4 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;
namespace Cocotte.Modules.Activities.Models;

View File

@@ -0,0 +1,14 @@
namespace Cocotte.Options;
public class CompositeRolesOptions
{
public const string SectionName = "CompositeRolesOptions";
public required IReadOnlyDictionary<string, GuildCompositeRoles[]> CompositeRoles { get; init; }
}
public class GuildCompositeRoles
{
public required ulong TargetRoleId { get; init; }
public required ulong[] CompositeRolesIds { get; init; }
}

View File

@@ -21,12 +21,14 @@ IHost host = Host.CreateDefaultBuilder(args)
{
configuration.AddJsonFile("discord.json", false, false);
configuration.AddJsonFile("activity.json", false, false);
configuration.AddJsonFile("compositeRoles.json", false, false);
})
.ConfigureServices((context, services) =>
{
// Options
services.Configure<DiscordOptions>(context.Configuration.GetSection(DiscordOptions.SectionName));
services.Configure<ActivityOptions>(context.Configuration.GetSection(ActivityOptions.SectionName));
services.Configure<CompositeRolesOptions>(context.Configuration.GetSection(CompositeRolesOptions.SectionName));
// Database
services.AddDbContext<CocotteDbContext>(options =>
@@ -53,6 +55,9 @@ IHost host = Host.CreateDefaultBuilder(args)
services.AddTransient<InterstellarFormatter>();
services.AddTransient<ActivityHelper>();
// Composite roles
services.AddSingleton<CompositeRolesListener>();
// Raids
services.AddTransient<RaidFormatter>();
services.AddSingleton<RaidRegisterManager>();

View File

@@ -65,9 +65,19 @@ public class CocotteService : BackgroundService
await _client.LoginAsync(TokenType.Bot, _options.Token);
await _client.StartAsync();
// Register events
RegisterEvents();
await Task.Delay(Timeout.Infinite, stoppingToken);
}
private void RegisterEvents()
{
var composteRolesListener = _serviceProvider.GetRequiredService<CompositeRolesListener>();
_client.GuildMemberUpdated += composteRolesListener.UserUpdated;
}
private bool ValidateOptions()
{
// Validate group options

View File

@@ -0,0 +1,26 @@
{
"CompositeRolesOptions": {
"CompositeRoles": {
"someGuildId (ulong)": [
{
"TargetRoleId": 1,
"CompositeRolesIds": [
0,
1,
2
]
}
],
"anotherGuildId (ulong)": [
{
"TargetRoleId": 45,
"CompositeRolesIds": [
98,
1,
2
]
}
]
}
}
}