101 lines
4.0 KiB
C#
101 lines
4.0 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)
|
|
{
|
|
yappers ??= new HashSet<ulong>();
|
|
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 null || yapperRoleId is null)
|
|
{
|
|
_logger.LogError($"Found incorrect state, alert channel or yapper role does not exist.");
|
|
return;
|
|
}
|
|
|
|
if (!CheckIfTimeoutExpired(voice_state.GuildId)) return;
|
|
|
|
// Notify that new yapper has arrived
|
|
await SendYapperNotification(yapperRoleId.GetValueOrDefault(), alertChannelId.GetValueOrDefault());
|
|
}
|
|
|
|
yappers.Add(voice_state.UserId);
|
|
_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;
|
|
if (yappers.Count == 0) SetGuildTimeout(voice_state.GuildId);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
private void SetGuildTimeout(ulong guild_id)
|
|
{
|
|
#if DEBUG
|
|
var expiration = DateTimeOffset.UtcNow.AddMinutes(1);
|
|
#else
|
|
var expiration = DateTimeOffset.UtcNow.AddHours(2);
|
|
#endif
|
|
|
|
_yapperNotificationTimeoutCache.Set(guild_id, expiration, expiration);
|
|
}
|
|
|
|
private bool CheckIfTimeoutExpired(ulong guild_id)
|
|
{
|
|
var timeOutCached =
|
|
_yapperNotificationTimeoutCache.TryGetValue(guild_id, out DateTimeOffset timeout);
|
|
if (timeOutCached == false) return true;
|
|
if (timeout < DateTimeOffset.UtcNow) return true;
|
|
return false;
|
|
}
|
|
|
|
private async Task SendYapperNotification(ulong yapperRoleId, ulong alertChannelId)
|
|
{
|
|
await _restClient.SendMessageAsync(
|
|
alertChannelId,
|
|
new MessageProperties()
|
|
{
|
|
AllowedMentions = new AllowedMentionsProperties() {AllowedRoles = [yapperRoleId]},
|
|
Content = $"<@&{yapperRoleId}> " + PhraseProvider.GetYapperPhrase()
|
|
});
|
|
}
|
|
} |