[Feature] Voice channel status support (#2777)
* initial commit * MOCKED CHANNELS AGRHHHHHHHH * fix for sharded * yup
This commit is contained in:
@@ -238,6 +238,11 @@ namespace Discord
|
||||
/// </summary>
|
||||
public const int MaxApplicationTagCount = 5;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the maximum length of a voice channel status.
|
||||
/// </summary>
|
||||
public const int MaxVoiceChannelStatusLength = 500;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the maximum number of entitlements that can be gotten per-batch.
|
||||
/// </summary>
|
||||
|
||||
@@ -249,6 +249,16 @@ namespace Discord
|
||||
/// <summary>
|
||||
/// Guild Onboarding was updated.
|
||||
/// </summary>
|
||||
OnboardingUpdated = 167
|
||||
OnboardingUpdated = 167,
|
||||
|
||||
/// <summary>
|
||||
/// A voice channel status was updated by a user.
|
||||
/// </summary>
|
||||
VoiceChannelStatusUpdated = 192,
|
||||
|
||||
/// <summary>
|
||||
/// A voice channel status was deleted by a user.
|
||||
/// </summary>
|
||||
VoiceChannelStatusDeleted = 193
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,5 +41,15 @@ namespace Discord
|
||||
/// </returns>
|
||||
/// <seealso cref="VoiceChannelProperties"/>
|
||||
Task ModifyAsync(Action<VoiceChannelProperties> func, RequestOptions options = null);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the voice channel status in the current channel.
|
||||
/// </summary>
|
||||
/// <param name="status">The string to set as status.</param>
|
||||
/// <param name="options">The options to be used when sending the request.</param>
|
||||
/// <returns>
|
||||
/// A task that represents the asynchronous modification operation.
|
||||
/// </returns>
|
||||
Task SetStatusAsync(string status, RequestOptions options = null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,5 +182,10 @@ namespace Discord
|
||||
/// Allows sending voice messages.
|
||||
/// </summary>
|
||||
SendVoiceMessages = 1L << 46,
|
||||
|
||||
/// <summary>
|
||||
/// Allows setting voice channel status.
|
||||
/// </summary>
|
||||
SetVoiceChannelStatus = 1L << 48,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace Discord
|
||||
/// <summary>
|
||||
/// Gets a <see cref="ChannelPermissions"/> that grants all permissions for voice channels.
|
||||
/// </summary>
|
||||
public static readonly ChannelPermissions Voice = new(0b10001_001010_001010_110011_111101_111111_111101_010001);
|
||||
public static readonly ChannelPermissions Voice = new(0b1_010001_001010_001010_110011_111101_111111_111101_010001);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a <see cref="ChannelPermissions"/> that grants all permissions for stage channels.
|
||||
@@ -142,6 +142,9 @@ namespace Discord
|
||||
public bool CreateEvents => Permissions.GetValue(RawValue, ChannelPermission.CreateEvents);
|
||||
/// <summary> If <see langword="true"/>, a user can send voice messages in this channel.</summary>
|
||||
public bool SendVoiceMessages => Permissions.GetValue(RawValue, ChannelPermission.SendVoiceMessages);
|
||||
/// <summary> If <see langword="true"/>, a user can set the status of a voice channel.</summary>
|
||||
public bool SetVoiceChannelStatus => Permissions.GetValue(RawValue, GuildPermission.SetVoiceChannelStatus);
|
||||
|
||||
|
||||
/// <summary> Creates a new <see cref="ChannelPermissions"/> with the provided packed value.</summary>
|
||||
public ChannelPermissions(ulong rawValue) { RawValue = rawValue; }
|
||||
@@ -179,7 +182,8 @@ namespace Discord
|
||||
bool? startEmbeddedActivities = null,
|
||||
bool? useSoundboard = null,
|
||||
bool? createEvents = null,
|
||||
bool? sendVoiceMessages = null)
|
||||
bool? sendVoiceMessages = null,
|
||||
bool? setVoiceChannelStatus = null)
|
||||
{
|
||||
ulong value = initialValue;
|
||||
|
||||
@@ -216,6 +220,7 @@ namespace Discord
|
||||
Permissions.SetValue(ref value, useSoundboard, ChannelPermission.UseSoundboard);
|
||||
Permissions.SetValue(ref value, createEvents, ChannelPermission.CreateEvents);
|
||||
Permissions.SetValue(ref value, sendVoiceMessages, ChannelPermission.SendVoiceMessages);
|
||||
Permissions.SetValue(ref value, setVoiceChannelStatus, ChannelPermission.SetVoiceChannelStatus);
|
||||
|
||||
RawValue = value;
|
||||
}
|
||||
@@ -254,12 +259,13 @@ namespace Discord
|
||||
bool startEmbeddedActivities = false,
|
||||
bool useSoundboard = false,
|
||||
bool createEvents = false,
|
||||
bool sendVoiceMessages = false)
|
||||
bool sendVoiceMessages = false,
|
||||
bool setVoiceChannelStatus = false)
|
||||
: this(0, createInstantInvite, manageChannel, addReactions, viewChannel, sendMessages, sendTTSMessages, manageMessages,
|
||||
embedLinks, attachFiles, readMessageHistory, mentionEveryone, useExternalEmojis, connect,
|
||||
speak, muteMembers, deafenMembers, moveMembers, useVoiceActivation, prioritySpeaker, stream, manageRoles, manageWebhooks,
|
||||
useApplicationCommands, requestToSpeak, manageThreads, createPublicThreads, createPrivateThreads, useExternalStickers, sendMessagesInThreads,
|
||||
startEmbeddedActivities, useSoundboard, createEvents, sendVoiceMessages)
|
||||
startEmbeddedActivities, useSoundboard, createEvents, sendVoiceMessages, setVoiceChannelStatus)
|
||||
{ }
|
||||
|
||||
/// <summary> Creates a new <see cref="ChannelPermissions"/> from this one, changing the provided non-null permissions.</summary>
|
||||
@@ -296,7 +302,8 @@ namespace Discord
|
||||
bool? startEmbeddedActivities = null,
|
||||
bool? useSoundboard = null,
|
||||
bool? createEvents = null,
|
||||
bool? sendVoiceMessages = null)
|
||||
bool? sendVoiceMessages = null,
|
||||
bool? setVoiceChannelStatus = null)
|
||||
=> new ChannelPermissions(RawValue,
|
||||
createInstantInvite,
|
||||
manageChannel,
|
||||
@@ -330,7 +337,8 @@ namespace Discord
|
||||
startEmbeddedActivities,
|
||||
useSoundboard,
|
||||
createEvents,
|
||||
sendVoiceMessages);
|
||||
sendVoiceMessages,
|
||||
setVoiceChannelStatus);
|
||||
|
||||
public bool Has(ChannelPermission permission) => Permissions.GetValue(RawValue, permission);
|
||||
|
||||
|
||||
@@ -267,5 +267,10 @@ namespace Discord
|
||||
/// Allows sending voice messages.
|
||||
/// </summary>
|
||||
SendVoiceMessages = 1L << 46,
|
||||
|
||||
/// <summary>
|
||||
/// Allows setting voice channel status.
|
||||
/// </summary>
|
||||
SetVoiceChannelStatus = 1L << 48,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,6 +110,8 @@ namespace Discord
|
||||
public bool ViewMonetizationAnalytics => Permissions.GetValue(RawValue, GuildPermission.ViewMonetizationAnalytics);
|
||||
/// <summary> If <see langword="true"/>, a user can send voice messages in this channel.</summary>
|
||||
public bool SendVoiceMessages => Permissions.GetValue(RawValue, GuildPermission.SendVoiceMessages);
|
||||
/// <summary> If <see langword="true"/>, a user can set the status of a voice channel.</summary>
|
||||
public bool SetVoiceChannelStatus => Permissions.GetValue(RawValue, GuildPermission.SetVoiceChannelStatus);
|
||||
|
||||
/// <summary> Creates a new <see cref="GuildPermissions"/> with the provided packed value. </summary>
|
||||
public GuildPermissions(ulong rawValue) { RawValue = rawValue; }
|
||||
@@ -161,7 +163,8 @@ namespace Discord
|
||||
bool? moderateMembers = null,
|
||||
bool? useSoundboard = null,
|
||||
bool? viewMonetizationAnalytics = null,
|
||||
bool? sendVoiceMessages = null)
|
||||
bool? sendVoiceMessages = null,
|
||||
bool? setVoiceChannelStatus = null)
|
||||
{
|
||||
ulong value = initialValue;
|
||||
|
||||
@@ -209,6 +212,7 @@ namespace Discord
|
||||
Permissions.SetValue(ref value, useSoundboard, GuildPermission.UseSoundboard);
|
||||
Permissions.SetValue(ref value, viewMonetizationAnalytics, GuildPermission.ViewMonetizationAnalytics);
|
||||
Permissions.SetValue(ref value, sendVoiceMessages, GuildPermission.SendVoiceMessages);
|
||||
Permissions.SetValue(ref value, setVoiceChannelStatus, GuildPermission.SetVoiceChannelStatus);
|
||||
|
||||
RawValue = value;
|
||||
}
|
||||
@@ -258,7 +262,8 @@ namespace Discord
|
||||
bool moderateMembers = false,
|
||||
bool useSoundboard = false,
|
||||
bool viewMonetizationAnalytics = false,
|
||||
bool sendVoiceMessages = false)
|
||||
bool sendVoiceMessages = false,
|
||||
bool setVoiceChannelStatus = false)
|
||||
: this(0,
|
||||
createInstantInvite: createInstantInvite,
|
||||
manageRoles: manageRoles,
|
||||
@@ -303,7 +308,8 @@ namespace Discord
|
||||
moderateMembers: moderateMembers,
|
||||
useSoundboard: useSoundboard,
|
||||
viewMonetizationAnalytics: viewMonetizationAnalytics,
|
||||
sendVoiceMessages: sendVoiceMessages)
|
||||
sendVoiceMessages: sendVoiceMessages,
|
||||
setVoiceChannelStatus: setVoiceChannelStatus)
|
||||
{ }
|
||||
|
||||
/// <summary> Creates a new <see cref="GuildPermissions"/> from this one, changing the provided non-null permissions. </summary>
|
||||
@@ -351,13 +357,14 @@ namespace Discord
|
||||
bool? moderateMembers = null,
|
||||
bool? useSoundboard = null,
|
||||
bool? viewMonetizationAnalytics = null,
|
||||
bool? sendVoiceMessages = null)
|
||||
bool? sendVoiceMessages = null,
|
||||
bool? setVoiceChannelStatus = null)
|
||||
=> new GuildPermissions(RawValue, createInstantInvite, kickMembers, banMembers, administrator, manageChannels, manageGuild, addReactions,
|
||||
viewAuditLog, viewGuildInsights, viewChannel, sendMessages, sendTTSMessages, manageMessages, embedLinks, attachFiles,
|
||||
readMessageHistory, mentionEveryone, useExternalEmojis, connect, speak, muteMembers, deafenMembers, moveMembers,
|
||||
useVoiceActivation, prioritySpeaker, stream, changeNickname, manageNicknames, manageRoles, manageWebhooks, manageEmojisAndStickers,
|
||||
useApplicationCommands, requestToSpeak, manageEvents, manageThreads, createPublicThreads, createPrivateThreads, useExternalStickers, sendMessagesInThreads,
|
||||
startEmbeddedActivities, moderateMembers, useSoundboard, viewMonetizationAnalytics, sendVoiceMessages);
|
||||
startEmbeddedActivities, moderateMembers, useSoundboard, viewMonetizationAnalytics, sendVoiceMessages, setVoiceChannelStatus);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a value that indicates if a specific <see cref="GuildPermission"/> is enabled
|
||||
|
||||
@@ -36,4 +36,7 @@ internal class AuditLogOptions
|
||||
|
||||
[JsonProperty("auto_moderation_rule_trigger_type")]
|
||||
public AutoModTriggerType? AutoModRuleTriggerType { get; set; }
|
||||
|
||||
[JsonProperty("status")]
|
||||
public string Status { get; set; }
|
||||
}
|
||||
|
||||
@@ -46,6 +46,9 @@ namespace Discord.API
|
||||
[JsonProperty("video_quality_mode")]
|
||||
public Optional<VideoQualityMode> VideoQualityMode { get; set; }
|
||||
|
||||
[JsonProperty("status")]
|
||||
public Optional<string> Status { get; set; }
|
||||
|
||||
//PrivateChannel
|
||||
[JsonProperty("recipients")]
|
||||
public Optional<User[]> Recipients { get; set; }
|
||||
|
||||
9
src/Discord.Net.Rest/API/Rest/ModifyVoiceStatusParams.cs
Normal file
9
src/Discord.Net.Rest/API/Rest/ModifyVoiceStatusParams.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API.Rest;
|
||||
|
||||
internal class ModifyVoiceStatusParams
|
||||
{
|
||||
[JsonProperty("status")]
|
||||
public string Status { get; set; }
|
||||
}
|
||||
@@ -467,6 +467,17 @@ namespace Discord.API
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task ModifyVoiceChannelStatusAsync(ulong channelId, string status, RequestOptions options = null)
|
||||
{
|
||||
Preconditions.NotEqual(channelId, 0, nameof(channelId));
|
||||
|
||||
var payload = new ModifyVoiceStatusParams { Status = status };
|
||||
var ids = new BucketIds();
|
||||
|
||||
await SendJsonAsync("PUT", () => $"channels/{channelId}/voice-status", payload, ids, options: options);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Threads
|
||||
|
||||
@@ -86,6 +86,9 @@ internal static class AuditLogHelper
|
||||
[ActionType.OnboardingQuestionCreated] = OnboardingPromptCreatedAuditLogData.Create,
|
||||
[ActionType.OnboardingQuestionUpdated] = OnboardingPromptUpdatedAuditLogData.Create,
|
||||
[ActionType.OnboardingUpdated] = OnboardingUpdatedAuditLogData.Create,
|
||||
|
||||
[ActionType.VoiceChannelStatusUpdated] = VoiceChannelStatusUpdateAuditLogData.Create,
|
||||
[ActionType.VoiceChannelStatusDeleted] = VoiceChannelStatusDeletedAuditLogData.Create
|
||||
};
|
||||
|
||||
public static IAuditLogData CreateData(BaseDiscordClient discord, EntryModel entry, Model log = null)
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
using EntryModel = Discord.API.AuditLogEntry;
|
||||
using Model = Discord.API.AuditLog;
|
||||
|
||||
namespace Discord.Rest;
|
||||
|
||||
/// <summary>
|
||||
/// Contains a piece of audit log data related to a voice channel status delete.
|
||||
/// </summary>
|
||||
public class VoiceChannelStatusDeletedAuditLogData : IAuditLogData
|
||||
{
|
||||
private VoiceChannelStatusDeletedAuditLogData(ulong channelId)
|
||||
{
|
||||
ChannelId = channelId;
|
||||
}
|
||||
|
||||
internal static VoiceChannelStatusDeletedAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log = null)
|
||||
{
|
||||
return new (entry.TargetId!.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the id of the channel status was removed in.
|
||||
/// </summary>
|
||||
public ulong ChannelId { get; }
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using EntryModel = Discord.API.AuditLogEntry;
|
||||
using Model = Discord.API.AuditLog;
|
||||
|
||||
namespace Discord.Rest;
|
||||
|
||||
/// <summary>
|
||||
/// Contains a piece of audit log data related to a voice channel status update.
|
||||
/// </summary>
|
||||
public class VoiceChannelStatusUpdateAuditLogData : IAuditLogData
|
||||
{
|
||||
private VoiceChannelStatusUpdateAuditLogData(string status, ulong channelId)
|
||||
{
|
||||
Status = status;
|
||||
ChannelId = channelId;
|
||||
}
|
||||
|
||||
internal static VoiceChannelStatusUpdateAuditLogData Create(BaseDiscordClient discord, EntryModel entry, Model log = null)
|
||||
{
|
||||
return new (entry.Options.Status, entry.TargetId!.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the status that was set in the voice channel.
|
||||
/// </summary>
|
||||
public string Status { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the id of the channel status was updated in.
|
||||
/// </summary>
|
||||
public ulong ChannelId { get; }
|
||||
}
|
||||
@@ -636,5 +636,16 @@ namespace Discord.Rest
|
||||
await client.ApiClient.ModifyGuildChannelAsync(channel.Id, apiArgs, options).ConfigureAwait(false);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Voice
|
||||
|
||||
public static async Task ModifyVoiceChannelStatusAsync(IVoiceChannel channel, string status, BaseDiscordClient client, RequestOptions options)
|
||||
{
|
||||
Preconditions.AtMost(status.Length, DiscordConfig.MaxVoiceChannelStatusLength, $"Voice channel status length must be less than {DiscordConfig.MaxVoiceChannelStatusLength}.");
|
||||
|
||||
await client.ApiClient.ModifyVoiceChannelStatusAsync(channel.Id, status, options).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,5 +150,13 @@ namespace Discord.Rest
|
||||
|
||||
return Discord.ApiClient.ModifyUserVoiceState(Guild.Id, user.Id, args);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <remarks>
|
||||
/// Setting voice channel status is not supported in stage channels.
|
||||
/// </remarks>
|
||||
/// <exception cref="NotSupportedException">Setting voice channel status is not supported in stage channels.</exception>
|
||||
public override Task SetStatusAsync(string status, RequestOptions options = null)
|
||||
=> throw new NotSupportedException("Setting voice channel status is not supported in stage channels.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,6 +69,10 @@ namespace Discord.Rest
|
||||
public override Task<RestThreadChannel> CreateThreadAsync(string name, ThreadType type = ThreadType.PublicThread, ThreadArchiveDuration autoArchiveDuration = ThreadArchiveDuration.OneDay, IMessage message = null, bool? invitable = null, int? slowmode = null, RequestOptions options = null)
|
||||
=> throw new InvalidOperationException("Cannot create a thread within a voice channel");
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual Task SetStatusAsync(string status, RequestOptions options = null)
|
||||
=> ChannelHelper.ModifyVoiceChannelStatusAsync(this, status, Discord, options);
|
||||
|
||||
#endregion
|
||||
|
||||
private string DebuggerDisplay => $"{Name} ({Id}, Voice)";
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API.Gateway;
|
||||
|
||||
internal class VoiceChannelStatusUpdateEvent
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public ulong Id { get; set; }
|
||||
|
||||
[JsonProperty("guild_id")]
|
||||
public ulong GuildId { get; set; }
|
||||
|
||||
[JsonProperty("status")]
|
||||
public string Status { get; set; }
|
||||
}
|
||||
@@ -76,6 +76,22 @@ namespace Discord.WebSocket
|
||||
remove { _channelUpdatedEvent.Remove(value); }
|
||||
}
|
||||
internal readonly AsyncEvent<Func<SocketChannel, SocketChannel, Task>> _channelUpdatedEvent = new AsyncEvent<Func<SocketChannel, SocketChannel, Task>>();
|
||||
|
||||
/// <summary>
|
||||
/// Fired when status of a voice channel is updated.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The previous state of the channel is passed into the first parameter; the updated channel is passed into the second one.
|
||||
/// </remarks>
|
||||
public event Func<Cacheable<SocketVoiceChannel, ulong>, string, string, Task> VoiceChannelStatusUpdated
|
||||
{
|
||||
add { _voiceChannelStatusUpdated.Add(value); }
|
||||
remove { _voiceChannelStatusUpdated.Remove(value); }
|
||||
}
|
||||
|
||||
internal readonly AsyncEvent<Func<Cacheable<SocketVoiceChannel, ulong>, string, string, Task>> _voiceChannelStatusUpdated = new();
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Messages
|
||||
|
||||
@@ -519,6 +519,8 @@ namespace Discord.WebSocket
|
||||
client.WebhooksUpdated += (arg1, arg2) => _webhooksUpdated.InvokeAsync(arg1, arg2);
|
||||
client.AuditLogCreated += (arg1, arg2) => _auditLogCreated.InvokeAsync(arg1, arg2);
|
||||
|
||||
client.VoiceChannelStatusUpdated += (arg1, arg2, arg3) => _voiceChannelStatusUpdated.InvokeAsync(arg1, arg2, arg3);
|
||||
|
||||
client.EntitlementCreated += (arg1) => _entitlementCreated.InvokeAsync(arg1);
|
||||
client.EntitlementUpdated += (arg1, arg2) => _entitlementUpdated.InvokeAsync(arg1, arg2);
|
||||
client.EntitlementDeleted += (arg1) => _entitlementDeleted.InvokeAsync(arg1);
|
||||
|
||||
@@ -2333,6 +2333,24 @@ namespace Discord.WebSocket
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case "VOICE_CHANNEL_STATUS_UPDATE":
|
||||
{
|
||||
await _gatewayLogger.DebugAsync("Received Dispatch (VOICE_CHANNEL_STATUS_UPDATE)").ConfigureAwait(false);
|
||||
|
||||
var data = (payload as JToken).ToObject<VoiceChannelStatusUpdateEvent>(_serializer);
|
||||
var guild = State.GetGuild(data.GuildId);
|
||||
|
||||
var channel = State.GetChannel(data.Id) as SocketVoiceChannel;
|
||||
var channelCacheable = new Cacheable<SocketVoiceChannel, ulong>(channel, data.Id, channel is not null, () => null);
|
||||
|
||||
var before = (string)channel?.Status?.Clone();
|
||||
var after = data.Status;
|
||||
channel?.UpdateVoiceStatus(data.Status);
|
||||
|
||||
await TimedInvokeAsync(_voiceChannelStatusUpdated, nameof(VoiceChannelStatusUpdated), channelCacheable, before, after);
|
||||
}
|
||||
break;
|
||||
#endregion
|
||||
|
||||
#region Invites
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
using EntryModel = Discord.API.AuditLogEntry;
|
||||
using Model = Discord.API.AuditLog;
|
||||
|
||||
namespace Discord.WebSocket;
|
||||
|
||||
/// <summary>
|
||||
/// Contains a piece of audit log data related to a voice channel status delete.
|
||||
/// </summary>
|
||||
public class SocketVoiceChannelStatusDeleteAuditLogData : ISocketAuditLogData
|
||||
{
|
||||
private SocketVoiceChannelStatusDeleteAuditLogData(ulong channelId)
|
||||
{
|
||||
ChannelId = channelId;
|
||||
}
|
||||
|
||||
internal static SocketVoiceChannelStatusDeleteAuditLogData Create(DiscordSocketClient discord, EntryModel entry)
|
||||
{
|
||||
return new (entry.TargetId!.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the id of the channel status was removed in.
|
||||
/// </summary>
|
||||
public ulong ChannelId { get; }
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using EntryModel = Discord.API.AuditLogEntry;
|
||||
using Model = Discord.API.AuditLog;
|
||||
|
||||
namespace Discord.WebSocket;
|
||||
|
||||
/// <summary>
|
||||
/// Contains a piece of audit log data related to a voice channel status update.
|
||||
/// </summary>
|
||||
public class SocketVoiceChannelStatusUpdatedAuditLogData : ISocketAuditLogData
|
||||
{
|
||||
private SocketVoiceChannelStatusUpdatedAuditLogData(string status, ulong channelId)
|
||||
{
|
||||
Status = status;
|
||||
ChannelId = channelId;
|
||||
}
|
||||
|
||||
internal static SocketVoiceChannelStatusUpdatedAuditLogData Create(DiscordSocketClient discord, EntryModel entry)
|
||||
{
|
||||
return new (entry.Options.Status, entry.TargetId!.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the status that was set in the voice channel.
|
||||
/// </summary>
|
||||
public string Status { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the id of the channel status was updated in.
|
||||
/// </summary>
|
||||
public ulong ChannelId { get; }
|
||||
}
|
||||
@@ -8,9 +8,9 @@ namespace Discord.WebSocket;
|
||||
/// <summary>
|
||||
/// Contains a piece of audit log data related to a webhook deletion.
|
||||
/// </summary>
|
||||
public class SocketWebhookDeleteAuditLogData : ISocketAuditLogData
|
||||
public class SocketWebhookDeletedAuditLogData : ISocketAuditLogData
|
||||
{
|
||||
private SocketWebhookDeleteAuditLogData(ulong id, Model model)
|
||||
private SocketWebhookDeletedAuditLogData(ulong id, Model model)
|
||||
{
|
||||
WebhookId = id;
|
||||
ChannelId = model.ChannelId!.Value;
|
||||
@@ -19,13 +19,13 @@ public class SocketWebhookDeleteAuditLogData : ISocketAuditLogData
|
||||
Avatar = model.AvatarHash;
|
||||
}
|
||||
|
||||
internal static SocketWebhookDeleteAuditLogData Create(DiscordSocketClient discord, EntryModel entry)
|
||||
internal static SocketWebhookDeletedAuditLogData Create(DiscordSocketClient discord, EntryModel entry)
|
||||
{
|
||||
var changes = entry.Changes;
|
||||
|
||||
var (data, _) = AuditLogHelper.CreateAuditLogEntityInfo<Model>(changes, discord);
|
||||
|
||||
return new SocketWebhookDeleteAuditLogData(entry.TargetId!.Value,data);
|
||||
return new SocketWebhookDeletedAuditLogData(entry.TargetId!.Value,data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -40,7 +40,7 @@ internal static class SocketAuditLogHelper
|
||||
|
||||
[ActionType.WebhookCreated] = SocketWebhookCreateAuditLogData.Create,
|
||||
[ActionType.WebhookUpdated] = SocketWebhookUpdateAuditLogData.Create,
|
||||
[ActionType.WebhookDeleted] = SocketWebhookDeleteAuditLogData.Create,
|
||||
[ActionType.WebhookDeleted] = SocketWebhookDeletedAuditLogData.Create,
|
||||
|
||||
[ActionType.EmojiCreated] = SocketEmoteCreateAuditLogData.Create,
|
||||
[ActionType.EmojiUpdated] = SocketEmoteUpdateAuditLogData.Create,
|
||||
@@ -84,6 +84,10 @@ internal static class SocketAuditLogHelper
|
||||
[ActionType.OnboardingQuestionCreated] = SocketOnboardingPromptCreatedAuditLogData.Create,
|
||||
[ActionType.OnboardingQuestionUpdated] = SocketOnboardingPromptUpdatedAuditLogData.Create,
|
||||
[ActionType.OnboardingUpdated] = SocketOnboardingUpdatedAuditLogData.Create,
|
||||
|
||||
[ActionType.VoiceChannelStatusUpdated] = SocketVoiceChannelStatusUpdatedAuditLogData.Create,
|
||||
[ActionType.VoiceChannelStatusDeleted] = SocketVoiceChannelStatusDeleteAuditLogData.Create,
|
||||
|
||||
};
|
||||
|
||||
public static ISocketAuditLogData CreateData(DiscordSocketClient discord, EntryModel entry)
|
||||
|
||||
@@ -43,6 +43,12 @@ namespace Discord.WebSocket
|
||||
public IReadOnlyCollection<SocketGuildUser> Speakers
|
||||
=> Users.Where(x => !x.IsSuppressed).ToImmutableArray();
|
||||
|
||||
/// <inheritdoc/>
|
||||
/// <remarks>
|
||||
/// This property is not supported in stage channels and will always return <see cref="string.Empty"/>.
|
||||
/// </remarks>
|
||||
public override string Status => string.Empty;
|
||||
|
||||
internal new SocketStageChannel Clone() => MemberwiseClone() as SocketStageChannel;
|
||||
|
||||
internal SocketStageChannel(DiscordSocketClient discord, ulong id, SocketGuild guild)
|
||||
@@ -156,5 +162,13 @@ namespace Discord.WebSocket
|
||||
|
||||
return Discord.ApiClient.ModifyUserVoiceState(Guild.Id, user.Id, args);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <remarks>
|
||||
/// Setting voice channel status is not supported in stage channels.
|
||||
/// </remarks>
|
||||
/// <exception cref="NotSupportedException">Setting voice channel status is not supported in stage channels.</exception>
|
||||
public override Task SetStatusAsync(string status, RequestOptions options = null)
|
||||
=> throw new NotSupportedException("Setting voice channel status is not supported in stage channels.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,11 @@ namespace Discord.WebSocket
|
||||
/// <inheritdoc/>
|
||||
public VideoQualityMode VideoQualityMode { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the voice channel status set in this channel. <see langword="null" /> if it is not set.
|
||||
/// </summary>
|
||||
public virtual string Status { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of users that are currently connected to this voice channel.
|
||||
/// </summary>
|
||||
@@ -51,12 +56,19 @@ namespace Discord.WebSocket
|
||||
: base(discord, id, guild)
|
||||
{
|
||||
}
|
||||
|
||||
internal new static SocketVoiceChannel Create(SocketGuild guild, ClientState state, Model model)
|
||||
{
|
||||
var entity = new SocketVoiceChannel(guild?.Discord, model.Id, guild);
|
||||
entity.Update(state, model);
|
||||
return entity;
|
||||
}
|
||||
|
||||
internal void UpdateVoiceStatus(string status)
|
||||
{
|
||||
Status = status;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
internal override void Update(ClientState state, Model model)
|
||||
{
|
||||
@@ -65,8 +77,13 @@ namespace Discord.WebSocket
|
||||
UserLimit = model.UserLimit.GetValueOrDefault() != 0 ? model.UserLimit.Value : (int?)null;
|
||||
VideoQualityMode = model.VideoQualityMode.GetValueOrDefault(VideoQualityMode.Auto);
|
||||
RTCRegion = model.RTCRegion.GetValueOrDefault(null);
|
||||
Status = model.Status.GetValueOrDefault(null);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual Task SetStatusAsync(string status, RequestOptions options = null)
|
||||
=> ChannelHelper.ModifyVoiceChannelStatusAsync(this, status, Discord, options);
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task ModifyAsync(Action<VoiceChannelProperties> func, RequestOptions options = null)
|
||||
=> ChannelHelper.ModifyAsync(this, Discord, func, options);
|
||||
|
||||
@@ -93,6 +93,7 @@ namespace Discord
|
||||
AssertFlag(() => new ChannelPermissions(useSoundboard: true), ChannelPermission.UseSoundboard);
|
||||
AssertFlag(() => new ChannelPermissions(createEvents: true), ChannelPermission.CreateEvents);
|
||||
AssertFlag(() => new ChannelPermissions(sendVoiceMessages: true), ChannelPermission.SendVoiceMessages);
|
||||
AssertFlag(() => new ChannelPermissions(setVoiceChannelStatus: true), ChannelPermission.SetVoiceChannelStatus);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -158,6 +159,7 @@ namespace Discord
|
||||
AssertUtil(ChannelPermission.PrioritySpeaker, x => x.PrioritySpeaker, (p, enable) => p.Modify(prioritySpeaker: enable));
|
||||
AssertUtil(ChannelPermission.Stream, x => x.Stream, (p, enable) => p.Modify(stream: enable));
|
||||
AssertUtil(ChannelPermission.SendVoiceMessages, x => x.SendVoiceMessages, (p, enable) => p.Modify(sendVoiceMessages: enable));
|
||||
AssertUtil(ChannelPermission.SetVoiceChannelStatus, x => x.SetVoiceChannelStatus, (p, enable) => p.Modify(setVoiceChannelStatus: enable));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -103,6 +103,7 @@ namespace Discord
|
||||
AssertFlag(() => new GuildPermissions(viewMonetizationAnalytics: true), GuildPermission.ViewMonetizationAnalytics);
|
||||
AssertFlag(() => new GuildPermissions(useSoundboard: true), GuildPermission.UseSoundboard);
|
||||
AssertFlag(() => new GuildPermissions(sendVoiceMessages: true), GuildPermission.SendVoiceMessages);
|
||||
AssertFlag(() => new GuildPermissions(setVoiceChannelStatus: true), GuildPermission.SetVoiceChannelStatus);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -184,6 +185,7 @@ namespace Discord
|
||||
AssertUtil(GuildPermission.ViewMonetizationAnalytics, x => x.ViewMonetizationAnalytics, (p, enable) => p.Modify(viewMonetizationAnalytics: enable));
|
||||
AssertUtil(GuildPermission.UseSoundboard, x => x.UseSoundboard, (p, enable) => p.Modify(useSoundboard: enable));
|
||||
AssertUtil(GuildPermission.SendVoiceMessages, x => x.SendVoiceMessages, (p, enable) => p.Modify(sendVoiceMessages: enable));
|
||||
AssertUtil(GuildPermission.SetVoiceChannelStatus, x => x.SetVoiceChannelStatus, (p, enable) => p.Modify(setVoiceChannelStatus: enable));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,6 +75,8 @@ namespace Discord
|
||||
public Task<IGuildUser> GetUserAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null) => throw new NotImplementedException();
|
||||
public IAsyncEnumerable<IReadOnlyCollection<IGuildUser>> GetUsersAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null) => throw new NotImplementedException();
|
||||
public Task ModifyAsync(Action<VoiceChannelProperties> func, RequestOptions options = null) => throw new NotImplementedException();
|
||||
public Task SetStatusAsync(string status, RequestOptions options = null) => throw new NotImplementedException();
|
||||
|
||||
public Task ModifyAsync(Action<GuildChannelProperties> func, RequestOptions options = null) => throw new NotImplementedException();
|
||||
public Task ModifyAsync(Action<AudioChannelProperties> func, RequestOptions options = null) => throw new NotImplementedException();
|
||||
public Task<IUserMessage> ModifyMessageAsync(ulong messageId, Action<MessageProperties> func, RequestOptions options = null) => throw new NotImplementedException();
|
||||
|
||||
Reference in New Issue
Block a user