Browse Source

add safeguard for tiv

pull/2269/head
Quin Lynch 3 years ago
parent
commit
1356755d3a
11 changed files with 428 additions and 116 deletions
  1. +5
    -3
      src/Discord.Net.Rest/Entities/Channels/RestStageChannel.cs
  2. +17
    -17
      src/Discord.Net.Rest/Entities/Channels/RestTextChannel.cs
  3. +169
    -17
      src/Discord.Net.Rest/Entities/Channels/RestVoiceChannel.cs
  4. +0
    -1
      src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs
  5. +0
    -1
      src/Discord.Net.Rest/Entities/Interactions/RestInteraction.cs
  6. +1
    -1
      src/Discord.Net.Rest/Entities/Roles/RestRole.cs
  7. +1
    -1
      src/Discord.Net.Rest/Net/ED25519/CryptoBytes.cs
  8. +3
    -8
      src/Discord.Net.Rest/Net/Queue/RequestQueue.cs
  9. +5
    -4
      src/Discord.Net.WebSocket/Entities/Channels/SocketStageChannel.cs
  10. +21
    -21
      src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs
  11. +206
    -42
      src/Discord.Net.WebSocket/Entities/Channels/SocketVoiceChannel.cs

+ 5
- 3
src/Discord.Net.Rest/Entities/Channels/RestStageChannel.cs View File

@@ -12,7 +12,11 @@ namespace Discord.Rest
public class RestStageChannel : RestVoiceChannel, IStageChannel public class RestStageChannel : RestVoiceChannel, IStageChannel
{ {
/// <inheritdoc/> /// <inheritdoc/>
public string Topic { get; private set; }
/// <remarks>
/// This field is always false for stage channels.
/// </remarks>
public override bool IsTextInVoice
=> false;


/// <inheritdoc/> /// <inheritdoc/>
public StagePrivacyLevel? PrivacyLevel { get; private set; } public StagePrivacyLevel? PrivacyLevel { get; private set; }
@@ -37,13 +41,11 @@ namespace Discord.Rest
IsLive = isLive; IsLive = isLive;
if(isLive) if(isLive)
{ {
Topic = model.Topic;
PrivacyLevel = model.PrivacyLevel; PrivacyLevel = model.PrivacyLevel;
IsDiscoverableDisabled = model.DiscoverableDisabled; IsDiscoverableDisabled = model.DiscoverableDisabled;
} }
else else
{ {
Topic = null;
PrivacyLevel = null; PrivacyLevel = null;
IsDiscoverableDisabled = null; IsDiscoverableDisabled = null;
} }


+ 17
- 17
src/Discord.Net.Rest/Entities/Channels/RestTextChannel.cs View File

@@ -86,25 +86,25 @@ namespace Discord.Rest
=> ChannelHelper.GetUsersAsync(this, Guild, Discord, null, null, options); => ChannelHelper.GetUsersAsync(this, Guild, Discord, null, null, options);


/// <inheritdoc /> /// <inheritdoc />
public Task<RestMessage> GetMessageAsync(ulong id, RequestOptions options = null)
public virtual Task<RestMessage> GetMessageAsync(ulong id, RequestOptions options = null)
=> ChannelHelper.GetMessageAsync(this, Discord, id, options); => ChannelHelper.GetMessageAsync(this, Discord, id, options);
/// <inheritdoc /> /// <inheritdoc />
public IAsyncEnumerable<IReadOnlyCollection<RestMessage>> GetMessagesAsync(int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null)
public virtual IAsyncEnumerable<IReadOnlyCollection<RestMessage>> GetMessagesAsync(int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null)
=> ChannelHelper.GetMessagesAsync(this, Discord, null, Direction.Before, limit, options); => ChannelHelper.GetMessagesAsync(this, Discord, null, Direction.Before, limit, options);
/// <inheritdoc /> /// <inheritdoc />
public IAsyncEnumerable<IReadOnlyCollection<RestMessage>> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null)
public virtual IAsyncEnumerable<IReadOnlyCollection<RestMessage>> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null)
=> ChannelHelper.GetMessagesAsync(this, Discord, fromMessageId, dir, limit, options); => ChannelHelper.GetMessagesAsync(this, Discord, fromMessageId, dir, limit, options);
/// <inheritdoc /> /// <inheritdoc />
public IAsyncEnumerable<IReadOnlyCollection<RestMessage>> GetMessagesAsync(IMessage fromMessage, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null)
public virtual IAsyncEnumerable<IReadOnlyCollection<RestMessage>> GetMessagesAsync(IMessage fromMessage, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null)
=> ChannelHelper.GetMessagesAsync(this, Discord, fromMessage.Id, dir, limit, options); => ChannelHelper.GetMessagesAsync(this, Discord, fromMessage.Id, dir, limit, options);
/// <inheritdoc /> /// <inheritdoc />
public Task<IReadOnlyCollection<RestMessage>> GetPinnedMessagesAsync(RequestOptions options = null)
public virtual Task<IReadOnlyCollection<RestMessage>> GetPinnedMessagesAsync(RequestOptions options = null)
=> ChannelHelper.GetPinnedMessagesAsync(this, Discord, options); => ChannelHelper.GetPinnedMessagesAsync(this, Discord, options);


/// <inheritdoc /> /// <inheritdoc />
/// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception> /// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception>
/// <exception cref="ArgumentException">The only valid <see cref="MessageFlags"/> are <see cref="MessageFlags.SuppressEmbeds"/> and <see cref="MessageFlags.None"/>.</exception> /// <exception cref="ArgumentException">The only valid <see cref="MessageFlags"/> are <see cref="MessageFlags.SuppressEmbeds"/> and <see cref="MessageFlags.None"/>.</exception>
public Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null,
public virtual Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null,
RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null,
MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
=> ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, allowedMentions, messageReference, => ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, allowedMentions, messageReference,
@@ -136,7 +136,7 @@ namespace Discord.Rest
/// <exception cref="IOException">An I/O error occurred while opening the file.</exception> /// <exception cref="IOException">An I/O error occurred while opening the file.</exception>
/// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception> /// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception>
/// <exception cref="ArgumentException">The only valid <see cref="MessageFlags"/> are <see cref="MessageFlags.SuppressEmbeds"/> and <see cref="MessageFlags.None"/>.</exception> /// <exception cref="ArgumentException">The only valid <see cref="MessageFlags"/> are <see cref="MessageFlags.SuppressEmbeds"/> and <see cref="MessageFlags.None"/>.</exception>
public Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null,
public virtual Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null,
RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null,
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
Embed[] embeds = null, MessageFlags flags = MessageFlags.None) Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
@@ -146,7 +146,7 @@ namespace Discord.Rest
/// <inheritdoc /> /// <inheritdoc />
/// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception> /// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception>
/// <exception cref="ArgumentException">The only valid <see cref="MessageFlags"/> are <see cref="MessageFlags.SuppressEmbeds"/> and <see cref="MessageFlags.None"/>.</exception> /// <exception cref="ArgumentException">The only valid <see cref="MessageFlags"/> are <see cref="MessageFlags.SuppressEmbeds"/> and <see cref="MessageFlags.None"/>.</exception>
public Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS = false,
public virtual Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS = false,
Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null,
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
Embed[] embeds = null, MessageFlags flags = MessageFlags.None) Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
@@ -156,7 +156,7 @@ namespace Discord.Rest
/// <inheritdoc /> /// <inheritdoc />
/// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception> /// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception>
/// <exception cref="ArgumentException">The only valid <see cref="MessageFlags"/> are <see cref="MessageFlags.SuppressEmbeds"/> and <see cref="MessageFlags.None"/>.</exception> /// <exception cref="ArgumentException">The only valid <see cref="MessageFlags"/> are <see cref="MessageFlags.SuppressEmbeds"/> and <see cref="MessageFlags.None"/>.</exception>
public Task<RestUserMessage> SendFileAsync(FileAttachment attachment, string text, bool isTTS = false,
public virtual Task<RestUserMessage> SendFileAsync(FileAttachment attachment, string text, bool isTTS = false,
Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null,
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
Embed[] embeds = null, MessageFlags flags = MessageFlags.None) Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
@@ -166,35 +166,35 @@ namespace Discord.Rest
/// <inheritdoc /> /// <inheritdoc />
/// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception> /// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception>
/// <exception cref="ArgumentException">The only valid <see cref="MessageFlags"/> are <see cref="MessageFlags.SuppressEmbeds"/> and <see cref="MessageFlags.None"/>.</exception> /// <exception cref="ArgumentException">The only valid <see cref="MessageFlags"/> are <see cref="MessageFlags.SuppressEmbeds"/> and <see cref="MessageFlags.None"/>.</exception>
public Task<RestUserMessage> SendFilesAsync(IEnumerable<FileAttachment> attachments, string text, bool isTTS = false,
public virtual Task<RestUserMessage> SendFilesAsync(IEnumerable<FileAttachment> attachments, string text, bool isTTS = false,
Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null,
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
Embed[] embeds = null, MessageFlags flags = MessageFlags.None) Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
=> ChannelHelper.SendFilesAsync(this, Discord, attachments, text, isTTS, embed, allowedMentions, messageReference, components, stickers, options, embeds, flags); => ChannelHelper.SendFilesAsync(this, Discord, attachments, text, isTTS, embed, allowedMentions, messageReference, components, stickers, options, embeds, flags);


/// <inheritdoc /> /// <inheritdoc />
public Task DeleteMessageAsync(ulong messageId, RequestOptions options = null)
public virtual Task DeleteMessageAsync(ulong messageId, RequestOptions options = null)
=> ChannelHelper.DeleteMessageAsync(this, messageId, Discord, options); => ChannelHelper.DeleteMessageAsync(this, messageId, Discord, options);
/// <inheritdoc /> /// <inheritdoc />
public Task DeleteMessageAsync(IMessage message, RequestOptions options = null)
public virtual Task DeleteMessageAsync(IMessage message, RequestOptions options = null)
=> ChannelHelper.DeleteMessageAsync(this, message.Id, Discord, options); => ChannelHelper.DeleteMessageAsync(this, message.Id, Discord, options);


/// <inheritdoc /> /// <inheritdoc />
public Task DeleteMessagesAsync(IEnumerable<IMessage> messages, RequestOptions options = null)
public virtual Task DeleteMessagesAsync(IEnumerable<IMessage> messages, RequestOptions options = null)
=> ChannelHelper.DeleteMessagesAsync(this, Discord, messages.Select(x => x.Id), options); => ChannelHelper.DeleteMessagesAsync(this, Discord, messages.Select(x => x.Id), options);
/// <inheritdoc /> /// <inheritdoc />
public Task DeleteMessagesAsync(IEnumerable<ulong> messageIds, RequestOptions options = null)
public virtual Task DeleteMessagesAsync(IEnumerable<ulong> messageIds, RequestOptions options = null)
=> ChannelHelper.DeleteMessagesAsync(this, Discord, messageIds, options); => ChannelHelper.DeleteMessagesAsync(this, Discord, messageIds, options);


/// <inheritdoc /> /// <inheritdoc />
public async Task<IUserMessage> ModifyMessageAsync(ulong messageId, Action<MessageProperties> func, RequestOptions options = null)
public virtual async Task<IUserMessage> ModifyMessageAsync(ulong messageId, Action<MessageProperties> func, RequestOptions options = null)
=> await ChannelHelper.ModifyMessageAsync(this, messageId, func, Discord, options).ConfigureAwait(false); => await ChannelHelper.ModifyMessageAsync(this, messageId, func, Discord, options).ConfigureAwait(false);


/// <inheritdoc /> /// <inheritdoc />
public Task TriggerTypingAsync(RequestOptions options = null)
public virtual Task TriggerTypingAsync(RequestOptions options = null)
=> ChannelHelper.TriggerTypingAsync(this, Discord, options); => ChannelHelper.TriggerTypingAsync(this, Discord, options);
/// <inheritdoc /> /// <inheritdoc />
public IDisposable EnterTypingState(RequestOptions options = null)
public virtual IDisposable EnterTypingState(RequestOptions options = null)
=> ChannelHelper.EnterTypingState(this, Discord, options); => ChannelHelper.EnterTypingState(this, Discord, options);


/// <summary> /// <summary>


+ 169
- 17
src/Discord.Net.Rest/Entities/Channels/RestVoiceChannel.cs View File

@@ -16,6 +16,11 @@ namespace Discord.Rest
public class RestVoiceChannel : RestTextChannel, IVoiceChannel, IRestAudioChannel public class RestVoiceChannel : RestTextChannel, IVoiceChannel, IRestAudioChannel
{ {
#region RestVoiceChannel #region RestVoiceChannel
/// <summary>
/// Gets whether or not the guild has Text-In-Voice enabled and the voice channel is a TiV channel.
/// </summary>
public virtual bool IsTextInVoice
=> Guild.Features.HasTextInVoice;
/// <inheritdoc /> /// <inheritdoc />
public int Bitrate { get; private set; } public int Bitrate { get; private set; }
/// <inheritdoc /> /// <inheritdoc />
@@ -66,26 +71,173 @@ namespace Discord.Rest


#endregion #endregion


#region Invites
/// <inheritdoc />
public async Task<IInviteMetadata> CreateInviteAsync(int? maxAge = 86400, int? maxUses = null, bool isTemporary = false, bool isUnique = false, RequestOptions options = null)
=> await ChannelHelper.CreateInviteAsync(this, Discord, maxAge, maxUses, isTemporary, isUnique, options).ConfigureAwait(false);
/// <inheritdoc />
public async Task<IInviteMetadata> CreateInviteToApplicationAsync(ulong applicationId, int? maxAge, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null)
=> await ChannelHelper.CreateInviteToApplicationAsync(this, Discord, maxAge, maxUses, isTemporary, isUnique, applicationId, options).ConfigureAwait(false);
/// <inheritdoc />
public virtual async Task<IInviteMetadata> CreateInviteToApplicationAsync(DefaultApplications application, int? maxAge = 86400, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null)
=> await ChannelHelper.CreateInviteToApplicationAsync(this, Discord, maxAge, maxUses, isTemporary, isUnique, (ulong)application, options);
/// <inheritdoc />
public async Task<IInviteMetadata> CreateInviteToStreamAsync(IUser user, int? maxAge, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null)
=> await ChannelHelper.CreateInviteToStreamAsync(this, Discord, maxAge, maxUses, isTemporary, isUnique, user, options).ConfigureAwait(false);
/// <inheritdoc />
public async Task<IReadOnlyCollection<IInviteMetadata>> GetInvitesAsync(RequestOptions options = null)
=> await ChannelHelper.GetInvitesAsync(this, Discord, options).ConfigureAwait(false);

private string DebuggerDisplay => $"{Name} ({Id}, Voice)"; private string DebuggerDisplay => $"{Name} ({Id}, Voice)";

#region TextOverrides

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override Task<RestMessage> GetMessageAsync(ulong id, RequestOptions options = null)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.GetMessageAsync(id, options);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override Task DeleteMessageAsync(IMessage message, RequestOptions options = null)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.DeleteMessageAsync(message, options);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override Task DeleteMessageAsync(ulong messageId, RequestOptions options = null)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.DeleteMessageAsync(messageId, options);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override Task DeleteMessagesAsync(IEnumerable<IMessage> messages, RequestOptions options = null)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.DeleteMessagesAsync(messages, options);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override Task DeleteMessagesAsync(IEnumerable<ulong> messageIds, RequestOptions options = null)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.DeleteMessagesAsync(messageIds, options);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override IDisposable EnterTypingState(RequestOptions options = null)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.EnterTypingState(options);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override IAsyncEnumerable<IReadOnlyCollection<RestMessage>> GetMessagesAsync(IMessage fromMessage, Direction dir, int limit = 100, RequestOptions options = null)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.GetMessagesAsync(fromMessage, dir, limit, options);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override IAsyncEnumerable<IReadOnlyCollection<RestMessage>> GetMessagesAsync(int limit = 100, RequestOptions options = null)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.GetMessagesAsync(limit, options);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override IAsyncEnumerable<IReadOnlyCollection<RestMessage>> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = 100, RequestOptions options = null)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.GetMessagesAsync(fromMessageId, dir, limit, options);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override Task<IReadOnlyCollection<RestMessage>> GetPinnedMessagesAsync(RequestOptions options = null)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.GetPinnedMessagesAsync(options);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override Task<RestWebhook> GetWebhookAsync(ulong id, RequestOptions options = null)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.GetWebhookAsync(id, options);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override Task<IReadOnlyCollection<RestWebhook>> GetWebhooksAsync(RequestOptions options = null)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.GetWebhooksAsync(options);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override Task<RestWebhook> CreateWebhookAsync(string name, Stream avatar = null, RequestOptions options = null)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.CreateWebhookAsync(name, avatar, options);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override Task<IUserMessage> ModifyMessageAsync(ulong messageId, Action<MessageProperties> func, RequestOptions options = null)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.ModifyMessageAsync(messageId, func, options);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override Task<RestUserMessage> SendFileAsync(FileAttachment attachment, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.SendFileAsync(attachment, text, isTTS, embed, options, allowedMentions, messageReference, components, stickers, embeds, flags);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.SendFileAsync(stream, filename, text, isTTS, embed, options, isSpoiler, allowedMentions, messageReference, components, stickers, embeds, flags);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.SendFileAsync(filePath, text, isTTS, embed, options, isSpoiler, allowedMentions, messageReference, components, stickers, embeds, flags);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override Task<RestUserMessage> SendFilesAsync(IEnumerable<FileAttachment> attachments, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.SendFilesAsync(attachments, text, isTTS, embed, options, allowedMentions, messageReference, components, stickers, embeds, flags);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.SendMessageAsync(text, isTTS, embed, options, allowedMentions, messageReference, components, stickers, embeds, flags);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override Task TriggerTypingAsync(RequestOptions options = null)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.TriggerTypingAsync(options);
}

#endregion #endregion



#region IAudioChannel #region IAudioChannel
/// <inheritdoc /> /// <inheritdoc />
/// <exception cref="NotSupportedException">Connecting to a REST-based channel is not supported.</exception> /// <exception cref="NotSupportedException">Connecting to a REST-based channel is not supported.</exception>


+ 0
- 1
src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs View File

@@ -1161,7 +1161,6 @@ namespace Discord.Rest
/// in order to use this property. /// in order to use this property.
/// </remarks> /// </remarks>
/// </param> /// </param>
/// <param name="speakers">A collection of speakers for the event.</param>
/// <param name="location">The location of the event; links are supported</param> /// <param name="location">The location of the event; links are supported</param>
/// <param name="coverImage">The optional banner image for the event.</param> /// <param name="coverImage">The optional banner image for the event.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>


+ 0
- 1
src/Discord.Net.Rest/Entities/Interactions/RestInteraction.cs View File

@@ -333,7 +333,6 @@ namespace Discord.Rest
=> await FollowupWithFilesAsync(attachments, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options).ConfigureAwait(false); => await FollowupWithFilesAsync(attachments, text, embeds, isTTS, ephemeral, allowedMentions, components, embed, options).ConfigureAwait(false);
/// <inheritdoc/> /// <inheritdoc/>
Task IDiscordInteraction.RespondWithFilesAsync(IEnumerable<FileAttachment> attachments, string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options) => throw new NotSupportedException("REST-Based interactions don't support files."); Task IDiscordInteraction.RespondWithFilesAsync(IEnumerable<FileAttachment> attachments, string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options) => throw new NotSupportedException("REST-Based interactions don't support files.");
/// <inheritdoc/>
#if NETCOREAPP3_0_OR_GREATER != true #if NETCOREAPP3_0_OR_GREATER != true
/// <inheritdoc/> /// <inheritdoc/>
Task IDiscordInteraction.RespondWithFileAsync(Stream fileStream, string fileName, string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options) => throw new NotSupportedException("REST-Based interactions don't support files."); Task IDiscordInteraction.RespondWithFileAsync(Stream fileStream, string fileName, string text, Embed[] embeds, bool isTTS, bool ephemeral, AllowedMentions allowedMentions, MessageComponent components, Embed embed, RequestOptions options) => throw new NotSupportedException("REST-Based interactions don't support files.");


+ 1
- 1
src/Discord.Net.Rest/Entities/Roles/RestRole.cs View File

@@ -25,7 +25,7 @@ namespace Discord.Rest
public string Name { get; private set; } public string Name { get; private set; }
/// <inheritdoc /> /// <inheritdoc />
public string Icon { get; private set; } public string Icon { get; private set; }
/// <inheritdoc>/>
/// <inheritdoc/>
public Emoji Emoji { get; private set; } public Emoji Emoji { get; private set; }
/// <inheritdoc /> /// <inheritdoc />
public GuildPermissions Permissions { get; private set; } public GuildPermissions Permissions { get; private set; }


+ 1
- 1
src/Discord.Net.Rest/Net/ED25519/CryptoBytes.cs View File

@@ -243,7 +243,7 @@ namespace Discord.Net.ED25519
/// <summary> /// <summary>
/// // Decode a base58-encoded string into byte array /// // Decode a base58-encoded string into byte array
/// </summary> /// </summary>
/// <param name="strBase58">Base58 data string</param>
/// <param name="input">Base58 data string</param>
/// <returns>Byte array</returns> /// <returns>Byte array</returns>
public static byte[] Base58Decode(string input) public static byte[] Base58Decode(string input)
{ {


+ 3
- 8
src/Discord.Net.Rest/Net/Queue/RequestQueue.cs View File

@@ -60,14 +60,9 @@ namespace Discord.Net.Queue
_clearToken?.Cancel(); _clearToken?.Cancel();
_clearToken?.Dispose(); _clearToken?.Dispose();
_clearToken = new CancellationTokenSource(); _clearToken = new CancellationTokenSource();
if (_parentToken != null)
{
_requestCancelTokenSource?.Dispose();
_requestCancelTokenSource = CancellationTokenSource.CreateLinkedTokenSource(_clearToken.Token, _parentToken);
_requestCancelToken = _requestCancelTokenSource.Token;
}
else
_requestCancelToken = _clearToken.Token;
_requestCancelTokenSource?.Dispose();
_requestCancelTokenSource = CancellationTokenSource.CreateLinkedTokenSource(_clearToken.Token, _parentToken);
_requestCancelToken = _requestCancelTokenSource.Token;
} }
finally { _tokenLock.Release(); } finally { _tokenLock.Release(); }
} }


+ 5
- 4
src/Discord.Net.WebSocket/Entities/Channels/SocketStageChannel.cs View File

@@ -15,7 +15,11 @@ namespace Discord.WebSocket
public class SocketStageChannel : SocketVoiceChannel, IStageChannel public class SocketStageChannel : SocketVoiceChannel, IStageChannel
{ {
/// <inheritdoc/> /// <inheritdoc/>
public string Topic { get; private set; }
/// <remarks>
/// This field is always false for stage channels.
/// </remarks>
public override bool IsTextInVoice
=> false;


/// <inheritdoc/> /// <inheritdoc/>
public StagePrivacyLevel? PrivacyLevel { get; private set; } public StagePrivacyLevel? PrivacyLevel { get; private set; }
@@ -49,19 +53,16 @@ namespace Discord.WebSocket
entity.Update(state, model); entity.Update(state, model);
return entity; return entity;
} }

internal void Update(StageInstance model, bool isLive = false) internal void Update(StageInstance model, bool isLive = false)
{ {
IsLive = isLive; IsLive = isLive;
if (isLive) if (isLive)
{ {
Topic = model.Topic;
PrivacyLevel = model.PrivacyLevel; PrivacyLevel = model.PrivacyLevel;
IsDiscoverableDisabled = model.DiscoverableDisabled; IsDiscoverableDisabled = model.DiscoverableDisabled;
} }
else else
{ {
Topic = null;
PrivacyLevel = null; PrivacyLevel = null;
IsDiscoverableDisabled = null; IsDiscoverableDisabled = null;
} }


+ 21
- 21
src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs View File

@@ -128,7 +128,7 @@ namespace Discord.WebSocket


#region Messages #region Messages
/// <inheritdoc /> /// <inheritdoc />
public SocketMessage GetCachedMessage(ulong id)
public virtual SocketMessage GetCachedMessage(ulong id)
=> _messages?.Get(id); => _messages?.Get(id);
/// <summary> /// <summary>
/// Gets a message from this message channel. /// Gets a message from this message channel.
@@ -143,7 +143,7 @@ namespace Discord.WebSocket
/// A task that represents an asynchronous get operation for retrieving the message. The task result contains /// A task that represents an asynchronous get operation for retrieving the message. The task result contains
/// the retrieved message; <c>null</c> if no message is found with the specified identifier. /// the retrieved message; <c>null</c> if no message is found with the specified identifier.
/// </returns> /// </returns>
public async Task<IMessage> GetMessageAsync(ulong id, RequestOptions options = null)
public virtual async Task<IMessage> GetMessageAsync(ulong id, RequestOptions options = null)
{ {
IMessage msg = _messages?.Get(id); IMessage msg = _messages?.Get(id);
if (msg == null) if (msg == null)
@@ -163,7 +163,7 @@ namespace Discord.WebSocket
/// <returns> /// <returns>
/// Paged collection of messages. /// Paged collection of messages.
/// </returns> /// </returns>
public IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null)
public virtual IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null)
=> SocketChannelHelper.GetMessagesAsync(this, Discord, _messages, null, Direction.Before, limit, CacheMode.AllowDownload, options); => SocketChannelHelper.GetMessagesAsync(this, Discord, _messages, null, Direction.Before, limit, CacheMode.AllowDownload, options);
/// <summary> /// <summary>
/// Gets a collection of messages in this channel. /// Gets a collection of messages in this channel.
@@ -179,7 +179,7 @@ namespace Discord.WebSocket
/// <returns> /// <returns>
/// Paged collection of messages. /// Paged collection of messages.
/// </returns> /// </returns>
public IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null)
public virtual IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null)
=> SocketChannelHelper.GetMessagesAsync(this, Discord, _messages, fromMessageId, dir, limit, CacheMode.AllowDownload, options); => SocketChannelHelper.GetMessagesAsync(this, Discord, _messages, fromMessageId, dir, limit, CacheMode.AllowDownload, options);
/// <summary> /// <summary>
/// Gets a collection of messages in this channel. /// Gets a collection of messages in this channel.
@@ -195,25 +195,25 @@ namespace Discord.WebSocket
/// <returns> /// <returns>
/// Paged collection of messages. /// Paged collection of messages.
/// </returns> /// </returns>
public IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(IMessage fromMessage, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null)
public virtual IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(IMessage fromMessage, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null)
=> SocketChannelHelper.GetMessagesAsync(this, Discord, _messages, fromMessage.Id, dir, limit, CacheMode.AllowDownload, options); => SocketChannelHelper.GetMessagesAsync(this, Discord, _messages, fromMessage.Id, dir, limit, CacheMode.AllowDownload, options);
/// <inheritdoc /> /// <inheritdoc />
public IReadOnlyCollection<SocketMessage> GetCachedMessages(int limit = DiscordConfig.MaxMessagesPerBatch)
public virtual IReadOnlyCollection<SocketMessage> GetCachedMessages(int limit = DiscordConfig.MaxMessagesPerBatch)
=> SocketChannelHelper.GetCachedMessages(this, Discord, _messages, null, Direction.Before, limit); => SocketChannelHelper.GetCachedMessages(this, Discord, _messages, null, Direction.Before, limit);
/// <inheritdoc /> /// <inheritdoc />
public IReadOnlyCollection<SocketMessage> GetCachedMessages(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch)
public virtual IReadOnlyCollection<SocketMessage> GetCachedMessages(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch)
=> SocketChannelHelper.GetCachedMessages(this, Discord, _messages, fromMessageId, dir, limit); => SocketChannelHelper.GetCachedMessages(this, Discord, _messages, fromMessageId, dir, limit);
/// <inheritdoc /> /// <inheritdoc />
public IReadOnlyCollection<SocketMessage> GetCachedMessages(IMessage fromMessage, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch)
public virtual IReadOnlyCollection<SocketMessage> GetCachedMessages(IMessage fromMessage, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch)
=> SocketChannelHelper.GetCachedMessages(this, Discord, _messages, fromMessage.Id, dir, limit); => SocketChannelHelper.GetCachedMessages(this, Discord, _messages, fromMessage.Id, dir, limit);
/// <inheritdoc /> /// <inheritdoc />
public Task<IReadOnlyCollection<RestMessage>> GetPinnedMessagesAsync(RequestOptions options = null)
public virtual Task<IReadOnlyCollection<RestMessage>> GetPinnedMessagesAsync(RequestOptions options = null)
=> ChannelHelper.GetPinnedMessagesAsync(this, Discord, options); => ChannelHelper.GetPinnedMessagesAsync(this, Discord, options);


/// <inheritdoc /> /// <inheritdoc />
/// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception> /// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception>
/// <exception cref="ArgumentException">The only valid <see cref="MessageFlags"/> are <see cref="MessageFlags.SuppressEmbeds"/> and <see cref="MessageFlags.None"/>.</exception> /// <exception cref="ArgumentException">The only valid <see cref="MessageFlags"/> are <see cref="MessageFlags.SuppressEmbeds"/> and <see cref="MessageFlags.None"/>.</exception>
public Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null,
public virtual Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null,
RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null,
MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None) MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
=> ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, allowedMentions, messageReference, => ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, allowedMentions, messageReference,
@@ -221,7 +221,7 @@ namespace Discord.WebSocket


/// <inheritdoc /> /// <inheritdoc />
/// <exception cref="ArgumentException">The only valid <see cref="MessageFlags"/> are <see cref="MessageFlags.SuppressEmbeds"/> and <see cref="MessageFlags.None"/>.</exception> /// <exception cref="ArgumentException">The only valid <see cref="MessageFlags"/> are <see cref="MessageFlags.SuppressEmbeds"/> and <see cref="MessageFlags.None"/>.</exception>
public Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null,
public virtual Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null,
RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null,
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
Embed[] embeds = null, MessageFlags flags = MessageFlags.None) Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
@@ -230,7 +230,7 @@ namespace Discord.WebSocket
/// <inheritdoc /> /// <inheritdoc />
/// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception> /// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception>
/// <exception cref="ArgumentException">The only valid <see cref="MessageFlags"/> are <see cref="MessageFlags.SuppressEmbeds"/> and <see cref="MessageFlags.None"/>.</exception> /// <exception cref="ArgumentException">The only valid <see cref="MessageFlags"/> are <see cref="MessageFlags.SuppressEmbeds"/> and <see cref="MessageFlags.None"/>.</exception>
public Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS = false,
public virtual Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS = false,
Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null,
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
Embed[] embeds = null, MessageFlags flags = MessageFlags.None) Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
@@ -239,7 +239,7 @@ namespace Discord.WebSocket
/// <inheritdoc /> /// <inheritdoc />
/// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception> /// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception>
/// <exception cref="ArgumentException">The only valid <see cref="MessageFlags"/> are <see cref="MessageFlags.SuppressEmbeds"/> and <see cref="MessageFlags.None"/>.</exception> /// <exception cref="ArgumentException">The only valid <see cref="MessageFlags"/> are <see cref="MessageFlags.SuppressEmbeds"/> and <see cref="MessageFlags.None"/>.</exception>
public Task<RestUserMessage> SendFileAsync(FileAttachment attachment, string text, bool isTTS = false,
public virtual Task<RestUserMessage> SendFileAsync(FileAttachment attachment, string text, bool isTTS = false,
Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null,
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
Embed[] embeds = null, MessageFlags flags = MessageFlags.None) Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
@@ -248,7 +248,7 @@ namespace Discord.WebSocket
/// <inheritdoc /> /// <inheritdoc />
/// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception> /// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception>
/// <exception cref="ArgumentException">The only valid <see cref="MessageFlags"/> are <see cref="MessageFlags.SuppressEmbeds"/> and <see cref="MessageFlags.None"/>.</exception> /// <exception cref="ArgumentException">The only valid <see cref="MessageFlags"/> are <see cref="MessageFlags.SuppressEmbeds"/> and <see cref="MessageFlags.None"/>.</exception>
public Task<RestUserMessage> SendFilesAsync(IEnumerable<FileAttachment> attachments, string text, bool isTTS = false,
public virtual Task<RestUserMessage> SendFilesAsync(IEnumerable<FileAttachment> attachments, string text, bool isTTS = false,
Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null,
MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null,
Embed[] embeds = null, MessageFlags flags = MessageFlags.None) Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
@@ -256,28 +256,28 @@ namespace Discord.WebSocket
messageReference, components, stickers, options, embeds, flags); messageReference, components, stickers, options, embeds, flags);


/// <inheritdoc /> /// <inheritdoc />
public Task DeleteMessagesAsync(IEnumerable<IMessage> messages, RequestOptions options = null)
public virtual Task DeleteMessagesAsync(IEnumerable<IMessage> messages, RequestOptions options = null)
=> ChannelHelper.DeleteMessagesAsync(this, Discord, messages.Select(x => x.Id), options); => ChannelHelper.DeleteMessagesAsync(this, Discord, messages.Select(x => x.Id), options);
/// <inheritdoc /> /// <inheritdoc />
public Task DeleteMessagesAsync(IEnumerable<ulong> messageIds, RequestOptions options = null)
public virtual Task DeleteMessagesAsync(IEnumerable<ulong> messageIds, RequestOptions options = null)
=> ChannelHelper.DeleteMessagesAsync(this, Discord, messageIds, options); => ChannelHelper.DeleteMessagesAsync(this, Discord, messageIds, options);


/// <inheritdoc /> /// <inheritdoc />
public async Task<IUserMessage> ModifyMessageAsync(ulong messageId, Action<MessageProperties> func, RequestOptions options = null)
public virtual async Task<IUserMessage> ModifyMessageAsync(ulong messageId, Action<MessageProperties> func, RequestOptions options = null)
=> await ChannelHelper.ModifyMessageAsync(this, messageId, func, Discord, options).ConfigureAwait(false); => await ChannelHelper.ModifyMessageAsync(this, messageId, func, Discord, options).ConfigureAwait(false);


/// <inheritdoc /> /// <inheritdoc />
public Task DeleteMessageAsync(ulong messageId, RequestOptions options = null)
public virtual Task DeleteMessageAsync(ulong messageId, RequestOptions options = null)
=> ChannelHelper.DeleteMessageAsync(this, messageId, Discord, options); => ChannelHelper.DeleteMessageAsync(this, messageId, Discord, options);
/// <inheritdoc /> /// <inheritdoc />
public Task DeleteMessageAsync(IMessage message, RequestOptions options = null)
public virtual Task DeleteMessageAsync(IMessage message, RequestOptions options = null)
=> ChannelHelper.DeleteMessageAsync(this, message.Id, Discord, options); => ChannelHelper.DeleteMessageAsync(this, message.Id, Discord, options);


/// <inheritdoc /> /// <inheritdoc />
public Task TriggerTypingAsync(RequestOptions options = null)
public virtual Task TriggerTypingAsync(RequestOptions options = null)
=> ChannelHelper.TriggerTypingAsync(this, Discord, options); => ChannelHelper.TriggerTypingAsync(this, Discord, options);
/// <inheritdoc /> /// <inheritdoc />
public IDisposable EnterTypingState(RequestOptions options = null)
public virtual IDisposable EnterTypingState(RequestOptions options = null)
=> ChannelHelper.EnterTypingState(this, Discord, options); => ChannelHelper.EnterTypingState(this, Discord, options);


internal void AddMessage(SocketMessage msg) internal void AddMessage(SocketMessage msg)


+ 206
- 42
src/Discord.Net.WebSocket/Entities/Channels/SocketVoiceChannel.cs View File

@@ -18,30 +18,18 @@ namespace Discord.WebSocket
public class SocketVoiceChannel : SocketTextChannel, IVoiceChannel, ISocketAudioChannel public class SocketVoiceChannel : SocketTextChannel, IVoiceChannel, ISocketAudioChannel
{ {
#region SocketVoiceChannel #region SocketVoiceChannel
/// <inheritdoc />
public int Bitrate { get; private set; }
/// <inheritdoc />
public int? UserLimit { get; private set; }
/// <inheritdoc/>
public string RTCRegion { get; private set; }

/// <inheritdoc />
public ulong? CategoryId { get; private set; }
/// <summary> /// <summary>
/// Gets the parent (category) channel of this channel.
/// Gets whether or not the guild has Text-In-Voice enabled and the voice channel is a TiV channel.
/// </summary> /// </summary>
/// <returns>
/// A category channel representing the parent of this channel; <c>null</c> if none is set.
/// </returns>
public ICategoryChannel Category
=> CategoryId.HasValue ? Guild.GetChannel(CategoryId.Value) as ICategoryChannel : null;
public virtual bool IsTextInVoice
=> Guild.Features.HasTextInVoice;


/// <inheritdoc /> /// <inheritdoc />
public string Mention => MentionUtils.MentionChannel(Id);

public int Bitrate { get; private set; }
/// <inheritdoc />
public int? UserLimit { get; private set; }
/// <inheritdoc /> /// <inheritdoc />
public Task SyncPermissionsAsync(RequestOptions options = null)
=> ChannelHelper.SyncPermissionsAsync(this, Discord, options);
public string RTCRegion { get; private set; }


/// <summary> /// <summary>
/// Gets a collection of users that are currently connected to this voice channel. /// Gets a collection of users that are currently connected to this voice channel.
@@ -100,38 +88,214 @@ namespace Discord.WebSocket
return null; return null;
} }


/// <inheritdoc/>
/// <exception cref="InvalidOperationException">Cannot create threads in voice channels.</exception>
/// <inheritdoc/> <exception cref="InvalidOperationException">Cannot create threads in voice channels.</exception>
public override Task<SocketThreadChannel> CreateThreadAsync(string name, ThreadType type = ThreadType.PublicThread, ThreadArchiveDuration autoArchiveDuration = ThreadArchiveDuration.OneDay, IMessage message = null, bool? invitable = null, int? slowmode = null, RequestOptions options = null) public override Task<SocketThreadChannel> 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("Voice channels cannot contain threads."); => throw new InvalidOperationException("Voice channels cannot contain threads.");
/// <inheritdoc/>
/// <exception cref="InvalidOperationException">Cannot modify text channel properties within a voice channel.</exception>

/// <inheritdoc/> <exception cref="InvalidOperationException">Cannot modify text channel properties for voice channels.</exception>
public override Task ModifyAsync(Action<TextChannelProperties> func, RequestOptions options = null) public override Task ModifyAsync(Action<TextChannelProperties> func, RequestOptions options = null)
=> throw new InvalidOperationException("Cannot modify text channel properties for voice channels."); => throw new InvalidOperationException("Cannot modify text channel properties for voice channels.");
#endregion #endregion


#region Invites
/// <inheritdoc />
public async Task<IInviteMetadata> CreateInviteAsync(int? maxAge = 86400, int? maxUses = null, bool isTemporary = false, bool isUnique = false, RequestOptions options = null)
=> await ChannelHelper.CreateInviteAsync(this, Discord, maxAge, maxUses, isTemporary, isUnique, options).ConfigureAwait(false);
/// <inheritdoc />
public async Task<IInviteMetadata> CreateInviteToApplicationAsync(ulong applicationId, int? maxAge, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null)
=> await ChannelHelper.CreateInviteToApplicationAsync(this, Discord, maxAge, maxUses, isTemporary, isUnique, applicationId, options).ConfigureAwait(false);
/// <inheritdoc />
public virtual async Task<IInviteMetadata> CreateInviteToApplicationAsync(DefaultApplications application, int? maxAge = 86400, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null)
=> await ChannelHelper.CreateInviteToApplicationAsync(this, Discord, maxAge, maxUses, isTemporary, isUnique, (ulong)application, options);
/// <inheritdoc />
public async Task<IInviteMetadata> CreateInviteToStreamAsync(IUser user, int? maxAge, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null)
=> await ChannelHelper.CreateInviteToStreamAsync(this, Discord, maxAge, maxUses, isTemporary, isUnique, user, options).ConfigureAwait(false);
/// <inheritdoc />
public async Task<IReadOnlyCollection<IInviteMetadata>> GetInvitesAsync(RequestOptions options = null)
=> await ChannelHelper.GetInvitesAsync(this, Discord, options).ConfigureAwait(false);
#region TextOverrides

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override Task<IMessage> GetMessageAsync(ulong id, RequestOptions options = null)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.GetMessageAsync(id, options);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override Task DeleteMessageAsync(IMessage message, RequestOptions options = null)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.DeleteMessageAsync(message, options);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override Task DeleteMessageAsync(ulong messageId, RequestOptions options = null)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.DeleteMessageAsync(messageId, options);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override Task DeleteMessagesAsync(IEnumerable<IMessage> messages, RequestOptions options = null)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.DeleteMessagesAsync(messages, options);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override Task DeleteMessagesAsync(IEnumerable<ulong> messageIds, RequestOptions options = null)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.DeleteMessagesAsync(messageIds, options);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override IDisposable EnterTypingState(RequestOptions options = null)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.EnterTypingState(options);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override SocketMessage GetCachedMessage(ulong id)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.GetCachedMessage(id);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override IReadOnlyCollection<SocketMessage> GetCachedMessages(IMessage fromMessage, Direction dir, int limit = 100)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.GetCachedMessages(fromMessage, dir, limit);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override IReadOnlyCollection<SocketMessage> GetCachedMessages(int limit = 100)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.GetCachedMessages(limit);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override IReadOnlyCollection<SocketMessage> GetCachedMessages(ulong fromMessageId, Direction dir, int limit = 100)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.GetCachedMessages(fromMessageId, dir, limit);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(IMessage fromMessage, Direction dir, int limit = 100, RequestOptions options = null)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.GetMessagesAsync(fromMessage, dir, limit, options);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(int limit = 100, RequestOptions options = null)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.GetMessagesAsync(limit, options);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = 100, RequestOptions options = null)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.GetMessagesAsync(fromMessageId, dir, limit, options);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override Task<IReadOnlyCollection<RestMessage>> GetPinnedMessagesAsync(RequestOptions options = null)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.GetPinnedMessagesAsync(options);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override Task<RestWebhook> GetWebhookAsync(ulong id, RequestOptions options = null)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.GetWebhookAsync(id, options);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override Task<IReadOnlyCollection<RestWebhook>> GetWebhooksAsync(RequestOptions options = null)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.GetWebhooksAsync(options);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override Task<RestWebhook> CreateWebhookAsync(string name, Stream avatar = null, RequestOptions options = null)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.CreateWebhookAsync(name, avatar, options);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override Task<IUserMessage> ModifyMessageAsync(ulong messageId, Action<MessageProperties> func, RequestOptions options = null)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.ModifyMessageAsync(messageId, func, options);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override Task<RestUserMessage> SendFileAsync(FileAttachment attachment, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.SendFileAsync(attachment, text, isTTS, embed, options, allowedMentions, messageReference, components, stickers, embeds, flags);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.SendFileAsync(stream, filename, text, isTTS, embed, options, isSpoiler, allowedMentions, messageReference, components, stickers, embeds, flags);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.SendFileAsync(filePath, text, isTTS, embed, options, isSpoiler, allowedMentions, messageReference, components, stickers, embeds, flags);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override Task<RestUserMessage> SendFilesAsync(IEnumerable<FileAttachment> attachments, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.SendFilesAsync(attachments, text, isTTS, embed, options, allowedMentions, messageReference, components, stickers, embeds, flags);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.SendMessageAsync(text, isTTS, embed, options, allowedMentions, messageReference, components, stickers, embeds, flags);
}

/// <inheritdoc/> <exception cref="NotSupportedException">This function is only supported in Text-In-Voice channels.</exception>
public override Task TriggerTypingAsync(RequestOptions options = null)
{
if (!IsTextInVoice)
throw new NotSupportedException("This function is only supported in Text-In-Voice channels");
return base.TriggerTypingAsync(options);
}

#endregion


private string DebuggerDisplay => $"{Name} ({Id}, Voice)"; private string DebuggerDisplay => $"{Name} ({Id}, Voice)";
internal new SocketVoiceChannel Clone() => MemberwiseClone() as SocketVoiceChannel; internal new SocketVoiceChannel Clone() => MemberwiseClone() as SocketVoiceChannel;
#endregion


#region IGuildChannel #region IGuildChannel
/// <inheritdoc /> /// <inheritdoc />


Loading…
Cancel
Save