SquadBot/StateMangers/VoiceStateManager.cs

75 lines
3.5 KiB
C#

using Microsoft.Extensions.Caching.Memory;
using NetCord;
using NetCord.Gateway;
using NetCord.Hosting.Gateway;
using NetCord.Rest;
using SquadBot.Providers;
namespace SquadBot.StateMangers;
public class VoiceStateManager
{
// Key: GuildId Value: List of UserId for users in voice channel
// TODO: We probably want to persist this somewhere else (Redis/Valkey)
private Dictionary<ulong, ISet<ulong>> _guildVoiceStates;
private IMemoryCache _yapperNotificationTimeoutCache;
private RestClient _restClient;
private ILogger<VoiceStateManager> _logger;
public VoiceStateManager(ILogger<VoiceStateManager> logger, RestClient restClient, IMemoryCache yapperNotificationTimeoutCache)
{
_guildVoiceStates = new Dictionary<ulong, ISet<ulong>>();
_yapperNotificationTimeoutCache = yapperNotificationTimeoutCache;
_restClient = restClient ?? throw new System.ArgumentNullException(nameof(restClient));
_logger = logger ?? throw new System.ArgumentNullException(nameof(logger));
}
public async Task HandleVoiceStateChange(VoiceState voice_state)
{
if (voice_state.ChannelId is not null)
{
// Joining channel
_logger.LogInformation($"New yapper detected: {voice_state.User.Username}");
if (!_guildVoiceStates.TryGetValue(voice_state.GuildId, out var yappers) || yappers.Count < 0)
{
var channels = await _restClient.GetGuildChannelsAsync(voice_state.GuildId);
var alertChannelId = channels.FirstOrDefault(channel => channel.Name == "bot-tinkering")?.Id;
var guildRoles = await _restClient.GetGuildRolesAsync(voice_state.GuildId,
new RestRequestProperties() { AuditLogReason = "Role lookup" });
var yapperRoleId = guildRoles.FirstOrDefault(role => role.Name.ToLower() == "yapper")?.Id;
if (alertChannelId is not null && yapperRoleId is not null && (!_yapperNotificationTimeoutCache.TryGetValue(voice_state.GuildId, out DateTimeOffset timeout) || DateTimeOffset.UtcNow.CompareTo(timeout) > 0))
{
// Notify that new yapper has arrived
await _restClient.SendMessageAsync(
alertChannelId.GetValueOrDefault(),
new MessageProperties()
{
AllowedMentions = new AllowedMentionsProperties() {AllowedRoles = [yapperRoleId.GetValueOrDefault()]},
Content = $"<@&{yapperRoleId.GetValueOrDefault()}> " + PhraseProvider.GetYapperPhrase()
});
}
yappers = new HashSet<ulong>() { voice_state.UserId };
}
else
{
yappers = yappers.Append(voice_state.UserId).ToHashSet();
}
_guildVoiceStates[voice_state.GuildId] = yappers;
}
else
{
// Leaving channel
_logger.LogInformation($"Yapper leaving: {voice_state.User.Username}");
if (_guildVoiceStates.TryGetValue(voice_state.GuildId, out var yappers))
{
yappers.Remove(voice_state.UserId);
_guildVoiceStates[voice_state.GuildId] = yappers;
var expiration = DateTimeOffset.UtcNow.AddHours(2);
_yapperNotificationTimeoutCache.Set(voice_state.GuildId, expiration, expiration);
}
}
return;
}
}