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.
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.