5 votes

Comment déterminer si un utilisateur a rejoint, changé ou quitté un canal vocal ?

J'utilise Discord.Net et j'observe plusieurs canaux vocaux. Si ces canaux vocaux ont un état muet, défini par le robot (et non par les permissions), les utilisateurs de ce canal vocal devraient également être en sourdine.

Le simple fait de retirer la permission de parler d'un canal vocal n'affectera pas les gens instantanément, comme vous pouvez le voir ici.

https://support.discord.com/hc/en-us/community/posts/360052856033-Directly-affect-people-in-channels-on-permission-changes

S'ils le laissent, ils devraient être démutés.

Celui-ci contient donc toutes les informations requises

public sealed class ObservedVoiceChannel
{
    public ulong VoiceChannelId { get; set; }
    public bool IsMuted { get; set; }
    // ... other information go here ...
}

et j'ai un service qui contient tous les canaux vocaux observés.

public sealed class ObservedVoiceChannelsCache : Dictionary<ulong, ObservedVoiceChannel>
{
}

Puisqu'il n'y a qu'un UserVoiceStateUpdated J'ai trouvé le code suivant.

Après quelques tests, je pense que ce code fonctionne bien pour moi. Bien que je sache que les instructions if peuvent être améliorées en termes de lisibilité avec des opérateurs "ou", je le ferai après avoir résolu le dernier problème.

Lorsque vous quittez un canal vocal muet observé, consultez le commentaire

// l'utilisateur a quitté le canal vocal muet observé

l'utilisateur ne sera pas démuté par le robot. Parfois, lorsque l'utilisateur rejoint et quitte le robot assez rapidement, le gestionnaire lève une exception.

Le serveur a répondu par une erreur 400 : BadRequest.

at Discord.Net.Queue.RequestBucket.SendAsync(RestRequest request)
at Discord.Net.Queue.RequestQueue.SendAsync(RestRequest request) at Discord.API.DiscordRestApiClient.SendInternalAsync(String method, String endpoint, RestRequest request) at Discord.API.DiscordRestApiClient.SendJsonAsync(String method, String endpoint, Object payload, BucketId bucketId, ClientBucketType clientBucket, RequestOptions options) at Discord.API.DiscordRestApiClient.ModifyGuildMemberAsync(UInt64 guildId, UInt64 userId, ModifyGuildMemberParams args, RequestOptions options) at Discord.Rest.UserHelper.ModifyAsync(IGuildUser user, BaseDiscordClient client, Action`1 func, RequestOptions options) at ...OnUserVoiceStateUpdated(SocketUser socketUser, SocketVoiceState oldSocketVoiceState, SocketVoiceState newSocketVoiceState) in /.../UserVoiceStateUpdatedEventHandler.cs:ligne 52

Voici le code que j'utilise actuellement

public sealed class UserVoiceStateUpdatedEventHandler
{
    private readonly ObservedVoiceChannelsCache _observedVoiceChannelsCache;

    public UserVoiceStateUpdatedEventHandler(ObservedVoiceChannelsCache observedVoiceChannelsCache)
    {
        _observedVoiceChannelsCache = observedVoiceChannelsCache;
    }

    public async Task OnUserVoiceStateUpdated(
        SocketUser socketUser, 
        SocketVoiceState oldSocketVoiceState,
        SocketVoiceState newSocketVoiceState)
    {
        if (socketUser is SocketGuildUser socketGuildUser)
        {
            bool userIsMuted = socketGuildUser.VoiceState?.IsMuted == true;
            bool userIsNotOffline = socketGuildUser.Status != UserStatus.Offline;

            // user left observed muted voice channel
            if (oldSocketVoiceState.VoiceChannel != null && 
                newSocketVoiceState.VoiceChannel == null &&
                _observedVoiceChannelsCache.TryGetValue(oldSocketVoiceState.VoiceChannel.Id, out ObservedVoiceChannel observedLeftVoiceChannel) &&
                observedLeftVoiceChannel.IsMuted &&
                userIsMuted &&
                userIsNotOffline
                )
            {
                await SetUserMuteState(socketGuildUser, false);
            }
            // user joined observed muted voice channel
            else if (oldSocketVoiceState.VoiceChannel == null && 
                     newSocketVoiceState.VoiceChannel != null &&
                     _observedVoiceChannelsCache.TryGetValue(newSocketVoiceState.VoiceChannel.Id, out ObservedVoiceChannel observedJoinedVoiceChannel) &&
                     observedJoinedVoiceChannel.IsMuted &&
                     !userIsMuted &&
                     userIsNotOffline)
            {
                await SetUserMuteState(socketGuildUser, true);
            }
            // user changed voice channels
            else if (oldSocketVoiceState.VoiceChannel != null && 
                     newSocketVoiceState.VoiceChannel != null &&
                     userIsNotOffline)
            {
                bool oldVoiceChannelObserved = _observedVoiceChannelsCache.TryGetValue(
                    oldSocketVoiceState.VoiceChannel.Id, out ObservedVoiceChannel oldObservedVoiceChannel);

                bool newVoiceChannelObserved = _observedVoiceChannelsCache.TryGetValue(
                    newSocketVoiceState.VoiceChannel.Id, out ObservedVoiceChannel newObservedVoiceChannel);

                // user moved from observed muted voice channel to unobserved voice channel
                if (oldVoiceChannelObserved && 
                    !newVoiceChannelObserved &&
                    oldObservedVoiceChannel.IsMuted &&
                    userIsMuted)
                {
                    await SetUserMuteState(socketGuildUser, false);
                }
                // user moved from unobserved voice channel to observed muted voice channel
                else if (!oldVoiceChannelObserved && 
                         newVoiceChannelObserved &&
                         newObservedVoiceChannel.IsMuted &&
                         !userIsMuted)
                {
                    await SetUserMuteState(socketGuildUser, true);
                }
                // both voice channels are observed
                else if (oldVoiceChannelObserved && newVoiceChannelObserved)
                {
                    // user moved from muted to unmuted voice channel
                    if (oldObservedVoiceChannel.IsMuted && 
                        !newObservedVoiceChannel.IsMuted &&
                        userIsMuted)
                    {
                        await SetUserMuteState(socketGuildUser, false);
                    }
                    // user moved from unmuted to muted voice channel
                    else if (!oldObservedVoiceChannel.IsMuted && 
                             newObservedVoiceChannel.IsMuted && 
                             !userIsMuted)
                    {
                        await SetUserMuteState(socketGuildUser, true);
                    }
                    // user moved from muted to muted voice channel
                    else if (oldObservedVoiceChannel.IsMuted && 
                             newObservedVoiceChannel.IsMuted && 
                             !userIsMuted)
                    {
                        await SetUserMuteState(socketGuildUser, true);
                    }
                }
            }
        }
    }

    private Task SetUserMuteState(SocketGuildUser socketGuildUser, bool muteUser)
        => socketGuildUser.ModifyAsync(guildUserProperties => guildUserProperties.Mute = muteUser);
}

et je voudrais savoir comment débloquer les utilisateurs qui ont laissé le canal vocal observé en sourdine.

J'ai découvert que cette ligne ici

bool userIsMuted = socketGuildUser.VoiceState?.IsMuted == true;

retourne false après avoir quitté le canal vocal car l'état vocal est nul. Il semble donc qu'il n'y ait aucun moyen de vérifier si l'utilisateur sera mis en sourdine lorsqu'il rejoindra le canal.

0voto

StageCodes Points 23

La façon dont vous déterminez si quelqu'un rejoint, déplace ou quitte les canaux vocaux est en regardant les données suivantes SocketVoiceState oldSocketVoiceState y SocketVoiceState newSocketVoiceState paramètres VoiceChannel respectivement. ( oldSocketVoiceState.VoiceChannel -> newSocketVoiceState.VoiceChannel pour les exemples ci-dessous) :

  • Entrer dans un nouveau canal vocal en n'étant pas connecté (null -> canal A)
  • Déplacement entre les canaux vocaux (canal A -> canal B)
  • Déconnexion d'un canal vocal (canal B -> null)

Pour couper le son d'une personne qui rejoint un canal vocal et le rétablir une fois qu'elle se déconnecte, vous devez écrire ce qui suit :

public async Task LogUserVoiceStateUpdatedAsync(SocketUser user, SocketVoiceState curVoiceState,
    SocketVoiceState nextVoiceState)
{
    if (user is not SocketGuildUser guildUser)
    {
        // They aren't a guild user, so we can't do anything to them.
        return;
    }

    // Note, you should make a method for the two switches below as in 
    // reality you're only changing one true/false flag depending on 
    // the voice states.

    // The user is leaving the voice channel.
    if (curVoiceState.VoiceChannel != null && nextVoiceState.VoiceChannel == null)
    {
        // Unmute the user.
        try
        {
            // Surround in try-catch in the event we lack permissions.
            await guildUser.ModifyAsync(x => x.Mute = false);
        }
        catch (Exception e)
        {
            // Will ALWAYS throw 400 bad request. I don't exactly know why, 
            // but it has to do with the modification being done after the user leaves the voice channel.

            // The warning can be safely be ignored.
            // _logger.LogWarning(e, $"Failed to unmute user in guild {guildUser.Guild.Id}.");
        }
    }
    else if (curVoiceState.VoiceChannel == null && nextVoiceState.VoiceChannel != null)
    {
        // Mute the user.
        try
        {
            // Surround in try-catch in the event we lack permissions.
            await guildUser.ModifyAsync(x => x.Mute = true);
        }
        catch (Exception e)
        {
            _logger.LogWarning(e, $"Failed to mute user in guild {guildUser.Guild.Id}.");
        }
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X