我正在使用 Discord.Net 并观察多个语音频道。如果这些语音通道处于静音状态,由机器人设置(不是通过权限),则该语音通道中的用户也应该被静音。
简单地从语音频道中删除发言权限不会立即影响人们,如您所见
如果他们离开,他们应该被取消静音。
所以这个包含所有必需的信息
public sealed class ObservedVoiceChannel
{
public ulong VoiceChannelId { get; set; }
public bool IsMuted { get; set; }
// ... other information go here ...
}
我有一个服务保存所有观察到的语音频道
public sealed class ObservedVoiceChannelsCache : Dictionary<ulong, ObservedVoiceChannel>
{
}
因为只有一个 UserVoiceStateUpdated
事件,所以我想出了以下代码。
经过一些测试,我认为这段代码对我来说很好用。虽然我知道 if 语句可以通过“或”运算符提高可读性,但我会在解决最后一个问题后进行改进。
离开观察到的静音语音频道时,请参阅评论
<块引用>// 用户离开观察到的静音语音通道
用户不会被机器人取消静音。有时,当加入和离开足够快时,处理程序会抛出异常
<块引用>服务器响应错误 400:BadRequest
<块引用>在 Discord.Net.Queue.RequestBucket.SendAsync(RestRequest 请求)
在 Discord.Net.Queue.RequestQueue.SendAsync(RestRequest request) 在
Discord.API.DiscordRestApiClient.SendInternalAsync(字符串方法,
字符串端点,RestRequest 请求)在
Discord.API.DiscordRestApiClient.SendJsonAsync(字符串方法,字符串
端点、对象负载、BucketId bucketId、ClientBucketType
clientBucket、RequestOptions 选项)在
Discord.API.DiscordRestApiClient.ModifyGuildMemberAsync(UInt64
guildId, UInt64 userId, ModifyGuildMemberParams args, RequestOptions
选项)在 Discord.Rest.UserHelper.ModifyAsync(IGuildUser 用户,
BaseDiscordClient 客户端,Action`1 func,RequestOptions 选项)在
...OnUserVoiceStateUpdated(SocketUser socketUser, SocketVoiceState
oldSocketVoiceState, SocketVoiceState newSocketVoiceState) 中
//.../UserVoiceStateUpdatedEventHandler.cs:line 52
这是我目前使用的代码
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);
}
我想知道如何将离开观察到的静音语音频道的用户取消静音。
我发现这里有这条线
bool userIsMuted = socketGuildUser.VoiceState?.IsMuted == true;
离开语音通道后返回false,因为语音状态为空。所以似乎没有办法检查用户再次加入时是否会被静音。
答案 0 :(得分:0)
确定某人是加入、移动还是离开语音频道的方法是分别查看 SocketVoiceState oldSocketVoiceState
和 SocketVoiceState newSocketVoiceState
参数的 VoiceChannel 属性。 (oldSocketVoiceState.VoiceChannel
-> newSocketVoiceState.VoiceChannel
对于以下示例):
要将加入语音频道的人静音,然后在他们断开连接后取消静音,您可以编写以下内容:
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}.");
}
}
}