Browse Source

Merge branch 'release/3.x' of https://github.com/Discord-Net-Labs/Discord.Net-Labs into merger-labs

pull/1923/head
quin lynch 3 years ago
parent
commit
7a276fb7d8
14 changed files with 131 additions and 80 deletions
  1. +2
    -2
      src/Discord.Net.Core/Discord.Net.Core.xml
  2. +1
    -13
      src/Discord.Net.Core/Entities/Interactions/Message Components/ComponentBuilder.cs
  3. +2
    -2
      src/Discord.Net.Core/Extensions/MessageExtensions.cs
  4. +8
    -4
      src/Discord.Net.Core/Utils/Preconditions.cs
  5. +21
    -11
      src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs
  6. +12
    -5
      src/Discord.Net.Rest/Entities/Channels/RestDMChannel.cs
  7. +12
    -5
      src/Discord.Net.Rest/Entities/Channels/RestGroupChannel.cs
  8. +4
    -1
      src/Discord.Net.Rest/Entities/Guilds/RestBan.cs
  9. +6
    -4
      src/Discord.Net.Rest/Entities/Interactions/InteractionHelper.cs
  10. +4
    -3
      src/Discord.Net.Rest/Entities/Messages/MessageHelper.cs
  11. +4
    -1
      src/Discord.Net.Rest/Entities/Users/RestGroupUser.cs
  12. +40
    -21
      src/Discord.Net.WebSocket/DiscordSocketClient.cs
  13. +1
    -1
      src/Discord.Net.WebSocket/Entities/Interaction/Message Components/SocketMessageComponent.cs
  14. +14
    -7
      src/Discord.Net.WebSocket/Extensions/EntityExtensions.cs

+ 2
- 2
src/Discord.Net.Core/Discord.Net.Core.xml View File

@@ -5653,7 +5653,7 @@
Gets or sets this menu options description.
</summary>
<exception cref="T:System.ArgumentException" accessor="set"><see cref="P:Discord.SelectMenuOptionBuilder.Description"/> length exceeds <see cref="F:Discord.SelectMenuOptionBuilder.MaxDescriptionLength"/>.</exception>
<exception cref="T:System.ArgumentException" accessor="set"><see cref="P:Discord.SelectMenuOptionBuilder.Label"/> length subceeds 1.</exception>
<exception cref="T:System.ArgumentException" accessor="set"><see cref="P:Discord.SelectMenuOptionBuilder.Description"/> length subceeds 1.</exception>
</member>
<member name="P:Discord.SelectMenuOptionBuilder.Emote">
<summary>
@@ -10979,7 +10979,7 @@
<seealso cref="M:Discord.IMessage.RemoveReactionAsync(Discord.IEmote,Discord.IUser,Discord.RequestOptions)"/>
<seealso cref="T:Discord.IEmote"/>
</member>
<member name="M:Discord.MessageExtensions.ReplyAsync(Discord.IUserMessage,System.String,System.Boolean,Discord.Embed,Discord.AllowedMentions,Discord.RequestOptions)">
<member name="M:Discord.MessageExtensions.ReplyAsync(Discord.IUserMessage,System.String,System.Boolean,Discord.Embed,Discord.AllowedMentions,Discord.RequestOptions,Discord.MessageComponent,Discord.ISticker[])">
<summary>
Sends an inline reply that references a message.
</summary>


+ 1
- 13
src/Discord.Net.Core/Entities/Interactions/Message Components/ComponentBuilder.cs View File

@@ -367,8 +367,6 @@ namespace Discord
if (value.Length < 1)
throw new ArgumentException("Button label must be 1 character or more!", paramName: nameof(Label));
}
else
throw new ArgumentException("Button label must not be null or empty!", paramName: nameof(Label));

_label = value;
}
@@ -391,8 +389,6 @@ namespace Discord
if (value.Length < 1)
throw new ArgumentException("Custom Id must be 1 character or more!", paramName: nameof(CustomId));
}
else
throw new ArgumentException("Custom Id must not be null or empty!", paramName: nameof(CustomId));
_customId = value;
}
}
@@ -644,8 +640,6 @@ namespace Discord
if (value.Length < 1)
throw new ArgumentException("Custom Id must be 1 character or more!", paramName: nameof(CustomId));
}
else
throw new ArgumentException("Custom Id must not be null or empty!", paramName: nameof(CustomId));
_customId = value;
}
}
@@ -667,8 +661,6 @@ namespace Discord
if (value.Length < 1)
throw new ArgumentException("The placeholder must be 1 character or more!", paramName: nameof(Placeholder));
}
else
throw new ArgumentException("The placeholder must not be null or empty!", paramName: nameof(Placeholder));

_placeholder = value;
}
@@ -938,8 +930,6 @@ namespace Discord
if (value.Length < 1)
throw new ArgumentException("Select option label must be 1 character or more!", paramName: nameof(Label));
}
else
throw new ArgumentException("Select option label must not be null or empty!", paramName: nameof(Label));

_label = value;
}
@@ -973,7 +963,7 @@ namespace Discord
/// Gets or sets this menu options description.
/// </summary>
/// <exception cref="ArgumentException" accessor="set"><see cref="Description"/> length exceeds <see cref="MaxDescriptionLength"/>.</exception>
/// <exception cref="ArgumentException" accessor="set"><see cref="Label"/> length subceeds 1.</exception>
/// <exception cref="ArgumentException" accessor="set"><see cref="Description"/> length subceeds 1.</exception>
public string Description
{
get => _description;
@@ -986,8 +976,6 @@ namespace Discord
if (value.Length < 1)
throw new ArgumentException("The description must be 1 character or more!", paramName: nameof(Label));
}
else
throw new ArgumentException("The description must not be null or empty!", paramName: nameof(Label));

_description = value;
}


+ 2
- 2
src/Discord.Net.Core/Extensions/MessageExtensions.cs View File

@@ -87,9 +87,9 @@ namespace Discord
/// A task that represents an asynchronous send operation for delivering the message. The task result
/// contains the sent message.
/// </returns>
public static async Task<IUserMessage> ReplyAsync(this IUserMessage msg, string text = null, bool isTTS = false, Embed embed = null, AllowedMentions allowedMentions = null, RequestOptions options = null)
public static async Task<IUserMessage> ReplyAsync(this IUserMessage msg, string text = null, bool isTTS = false, Embed embed = null, AllowedMentions allowedMentions = null, RequestOptions options = null, MessageComponent components = null, ISticker[] stickers = null)
{
return await msg.Channel.SendMessageAsync(text, isTTS, embed, options, allowedMentions, new MessageReference(messageId: msg.Id)).ConfigureAwait(false);
return await msg.Channel.SendMessageAsync(text, isTTS, embed, options, allowedMentions, new MessageReference(messageId: msg.Id), components, stickers).ConfigureAwait(false);
}
}
}

+ 8
- 4
src/Discord.Net.Core/Utils/Preconditions.cs View File

@@ -4,7 +4,7 @@ namespace Discord
{
internal static class Preconditions
{
//Objects
#region Objects
/// <exception cref="ArgumentNullException"><paramref name="obj"/> must not be <see langword="null"/>.</exception>
public static void NotNull<T>(T obj, string name, string msg = null) where T : class { if (obj == null) throw CreateNotNullException(name, msg); }
/// <exception cref="ArgumentNullException"><paramref name="obj"/> must not be <see langword="null"/>.</exception>
@@ -15,8 +15,9 @@ namespace Discord
if (msg == null) return new ArgumentNullException(paramName: name);
else return new ArgumentNullException(paramName: name, message: msg);
}
#endregion

//Strings
#region Strings
/// <exception cref="ArgumentException"><paramref name="obj"/> cannot be blank.</exception>
public static void NotEmpty(string obj, string name, string msg = null) { if (obj.Length == 0) throw CreateNotEmptyException(name, msg); }
/// <exception cref="ArgumentException"><paramref name="obj"/> cannot be blank.</exception>
@@ -58,8 +59,9 @@ namespace Discord

private static ArgumentException CreateNotEmptyException(string name, string msg)
=> new ArgumentException(message: msg ?? "Argument cannot be blank.", paramName: name);
#endregion

//Numerics
#region Numerics
/// <exception cref="ArgumentException">Value may not be equal to <paramref name="value"/>.</exception>
public static void NotEqual(sbyte obj, sbyte value, string name, string msg = null) { if (obj == value) throw CreateNotEqualException(name, msg, value); }
/// <exception cref="ArgumentException">Value may not be equal to <paramref name="value"/>.</exception>
@@ -271,8 +273,9 @@ namespace Discord

private static ArgumentException CreateLessThanException<T>(string name, string msg, T value)
=> new ArgumentException(message: msg ?? $"Value must be less than {value}.", paramName: name);
#endregion

// Bulk Delete
#region Bulk Delete
/// <exception cref="ArgumentOutOfRangeException">Messages are younger than 2 weeks.</exception>
public static void YoungerThanTwoWeeks(ulong[] collection, string name)
{
@@ -293,5 +296,6 @@ namespace Discord
throw new ArgumentException(message: "The everyone role cannot be assigned to a user.", paramName: name);
}
}
#endregion
}
}

+ 21
- 11
src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs View File

@@ -12,7 +12,7 @@ namespace Discord.Rest
{
internal static class ChannelHelper
{
//General
#region General
public static async Task DeleteAsync(IChannel channel, BaseDiscordClient client,
RequestOptions options)
{
@@ -107,8 +107,9 @@ namespace Discord.Rest

return await client.ApiClient.ModifyStageInstanceAsync(channel.Id, apiArgs, options);
}
#endregion

//Invites
#region Invites
public static async Task<IReadOnlyCollection<RestInviteMetadata>> GetInvitesAsync(IGuildChannel channel, BaseDiscordClient client,
RequestOptions options)
{
@@ -183,8 +184,9 @@ namespace Discord.Rest
var model = await client.ApiClient.CreateChannelInviteAsync(channel.Id, args, options).ConfigureAwait(false);
return RestInviteMetadata.Create(client, null, channel, model);
}
#endregion

//Messages
#region Messages
public static async Task<RestMessage> GetMessageAsync(IMessageChannel channel, BaseDiscordClient client,
ulong id, RequestOptions options)
{
@@ -285,12 +287,12 @@ namespace Discord.Rest
}
}

if(stickers != null)
if (stickers != null)
{
Preconditions.AtMost(stickers.Length, 3, nameof(stickers), "A max of 3 stickers are allowed.");
}

var args = new CreateMessageParams(text) { IsTTS = isTTS, Embed = embed?.ToModel(), AllowedMentions = allowedMentions?.ToModel(), MessageReference = messageReference?.ToModel(), Components = component?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional<API.ActionRowComponent[]>.Unspecified, Stickers = stickers?.Any() ?? false ? stickers.Select(x => x.Id).ToArray() : Optional<ulong[]>.Unspecified};
var args = new CreateMessageParams(text) { IsTTS = isTTS, Embed = embed?.ToModel(), AllowedMentions = allowedMentions?.ToModel(), MessageReference = messageReference?.ToModel(), Components = component?.Components.Select(x => new API.ActionRowComponent(x)).ToArray() ?? Optional<API.ActionRowComponent[]>.Unspecified, Stickers = stickers?.Any() ?? false ? stickers.Select(x => x.Id).ToArray() : Optional<ulong[]>.Unspecified };
var model = await client.ApiClient.CreateMessageAsync(channel.Id, args, options).ConfigureAwait(false);
return RestUserMessage.Create(client, channel, client.CurrentUser, model);
}
@@ -397,8 +399,9 @@ namespace Discord.Rest
await client.ApiClient.DeleteMessagesAsync(channel.Id, args, options).ConfigureAwait(false);
}
}
#endregion

//Permission Overwrites
#region Permission Overwrites
public static async Task AddPermissionOverwriteAsync(IGuildChannel channel, BaseDiscordClient client,
IUser user, OverwritePermissions perms, RequestOptions options)
{
@@ -421,8 +424,9 @@ namespace Discord.Rest
{
await client.ApiClient.DeleteChannelPermissionAsync(channel.Id, role.Id, options).ConfigureAwait(false);
}
#endregion

//Users
#region Users
/// <exception cref="InvalidOperationException">Resolving permissions requires the parent guild to be downloaded.</exception>
public static async Task<RestGuildUser> GetUserAsync(IGuildChannel channel, IGuild guild, BaseDiscordClient client,
ulong id, RequestOptions options)
@@ -467,8 +471,9 @@ namespace Discord.Rest
count: limit
);
}
#endregion

//Typing
#region Typing
public static async Task TriggerTypingAsync(IMessageChannel channel, BaseDiscordClient client,
RequestOptions options = null)
{
@@ -477,8 +482,9 @@ namespace Discord.Rest
public static IDisposable EnterTypingState(IMessageChannel channel, BaseDiscordClient client,
RequestOptions options)
=> new TypingNotifier(channel, options);
#endregion

//Webhooks
#region Webhooks
public static async Task<RestWebhook> CreateWebhookAsync(ITextChannel channel, BaseDiscordClient client, string name, Stream avatar, RequestOptions options)
{
var args = new CreateWebhookParams { Name = name };
@@ -501,7 +507,9 @@ namespace Discord.Rest
return models.Select(x => RestWebhook.Create(client, channel, x))
.ToImmutableArray();
}
// Categories
#endregion

#region Categories
public static async Task<ICategoryChannel> GetCategoryAsync(INestedChannel channel, BaseDiscordClient client, RequestOptions options)
{
// if no category id specified, return null
@@ -515,7 +523,8 @@ namespace Discord.Rest
public static async Task SyncPermissionsAsync(INestedChannel channel, BaseDiscordClient client, RequestOptions options)
{
var category = await GetCategoryAsync(channel, client, options).ConfigureAwait(false);
if (category == null) throw new InvalidOperationException("This channel does not have a parent channel.");
if (category == null)
throw new InvalidOperationException("This channel does not have a parent channel.");

var apiArgs = new ModifyGuildChannelParams
{
@@ -530,5 +539,6 @@ namespace Discord.Rest
};
await client.ApiClient.ModifyGuildChannelAsync(channel.Id, apiArgs, options).ConfigureAwait(false);
}
#endregion
}
}

+ 12
- 5
src/Discord.Net.Rest/Entities/Channels/RestDMChannel.cs View File

@@ -15,6 +15,7 @@ namespace Discord.Rest
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public class RestDMChannel : RestChannel, IDMChannel, IRestPrivateChannel, IRestMessageChannel
{
#region RestDMChannel
/// <summary>
/// Gets the current logged-in user.
/// </summary>
@@ -154,20 +155,24 @@ namespace Discord.Rest
/// </returns>
public override string ToString() => $"@{Recipient}";
private string DebuggerDisplay => $"@{Recipient} ({Id}, DM)";
#endregion

//IDMChannel
#region IDMChannel
/// <inheritdoc />
IUser IDMChannel.Recipient => Recipient;
#endregion

//IRestPrivateChannel
#region IRestPrivateChannel
/// <inheritdoc />
IReadOnlyCollection<RestUser> IRestPrivateChannel.Recipients => ImmutableArray.Create(Recipient);
#endregion

//IPrivateChannel
#region IPrivateChannel
/// <inheritdoc />
IReadOnlyCollection<IUser> IPrivateChannel.Recipients => ImmutableArray.Create<IUser>(Recipient);
#endregion

//IMessageChannel
#region IMessageChannel
/// <inheritdoc />
async Task<IMessage> IMessageChannel.GetMessageAsync(ulong id, CacheMode mode, RequestOptions options)
{
@@ -212,8 +217,9 @@ namespace Discord.Rest
/// <inheritdoc />
async Task<IUserMessage> IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageReference messageReference, MessageComponent component, ISticker[] stickers)
=> await SendMessageAsync(text, isTTS, embed, options, allowedMentions, messageReference, component, stickers).ConfigureAwait(false);
#endregion

//IChannel
#region IChannel
/// <inheritdoc />
string IChannel.Name => $"@{Recipient}";

@@ -223,5 +229,6 @@ namespace Discord.Rest
/// <inheritdoc />
IAsyncEnumerable<IReadOnlyCollection<IUser>> IChannel.GetUsersAsync(CacheMode mode, RequestOptions options)
=> ImmutableArray.Create<IReadOnlyCollection<IUser>>(Users).ToAsyncEnumerable();
#endregion
}
}

+ 12
- 5
src/Discord.Net.Rest/Entities/Channels/RestGroupChannel.cs View File

@@ -16,6 +16,7 @@ namespace Discord.Rest
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public class RestGroupChannel : RestChannel, IGroupChannel, IRestPrivateChannel, IRestMessageChannel, IRestAudioChannel
{
#region RestGroupChannel
private string _iconId;
private ImmutableDictionary<ulong, RestGroupUser> _users;

@@ -143,14 +144,17 @@ namespace Discord.Rest

public override string ToString() => Name;
private string DebuggerDisplay => $"{Name} ({Id}, Group)";
#endregion

//ISocketPrivateChannel
#region ISocketPrivateChannel
IReadOnlyCollection<RestUser> IRestPrivateChannel.Recipients => Recipients;
#endregion

//IPrivateChannel
#region IPrivateChannel
IReadOnlyCollection<IUser> IPrivateChannel.Recipients => Recipients;
#endregion

//IMessageChannel
#region IMessageChannel
async Task<IMessage> IMessageChannel.GetMessageAsync(ulong id, CacheMode mode, RequestOptions options)
{
if (mode == CacheMode.AllowDownload)
@@ -190,17 +194,20 @@ namespace Discord.Rest

async Task<IUserMessage> IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageReference messageReference, MessageComponent component, ISticker[] stickers)
=> await SendMessageAsync(text, isTTS, embed, options, allowedMentions, messageReference, component, stickers).ConfigureAwait(false);
#endregion

//IAudioChannel
#region IAudioChannel
/// <inheritdoc />
/// <exception cref="NotSupportedException">Connecting to a group channel is not supported.</exception>
Task<IAudioClient> IAudioChannel.ConnectAsync(bool selfDeaf, bool selfMute, bool external) { throw new NotSupportedException(); }
Task IAudioChannel.DisconnectAsync() { throw new NotSupportedException(); }
#endregion

//IChannel
#region IChannel
Task<IUser> IChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options)
=> Task.FromResult<IUser>(GetUser(id));
IAsyncEnumerable<IReadOnlyCollection<IUser>> IChannel.GetUsersAsync(CacheMode mode, RequestOptions options)
=> ImmutableArray.Create<IReadOnlyCollection<IUser>>(Users).ToAsyncEnumerable();
#endregion
}
}

+ 4
- 1
src/Discord.Net.Rest/Entities/Guilds/RestBan.cs View File

@@ -9,6 +9,7 @@ namespace Discord.Rest
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public class RestBan : IBan
{
#region RestBan
/// <summary>
/// Gets the banned user.
/// </summary>
@@ -37,9 +38,11 @@ namespace Discord.Rest
/// </returns>
public override string ToString() => User.ToString();
private string DebuggerDisplay => $"{User}: {Reason}";
#endregion

//IBan
#region IBan
/// <inheritdoc />
IUser IBan.User => User;
#endregion
}
}

+ 6
- 4
src/Discord.Net.Rest/Entities/Interactions/InteractionHelper.cs View File

@@ -340,9 +340,10 @@ namespace Discord.Rest
var embeds = args.Embeds;

bool hasText = args.Content.IsSpecified ? !string.IsNullOrEmpty(args.Content.Value) : !string.IsNullOrEmpty(message.Content);
bool hasEmbeds = (embed.IsSpecified && embed.Value != null) || (embeds.IsSpecified && embeds.Value?.Length > 0) || message.Embeds.Any();
bool hasEmbeds = embed.IsSpecified && embed.Value != null || embeds.IsSpecified && embeds.Value?.Length > 0 || message.Embeds.Any();
bool hasComponents = args.Components.IsSpecified && args.Components.Value != null;

if (!hasText && !hasEmbeds)
if (!hasComponents && !hasText && !hasEmbeds)
Preconditions.NotNullOrEmpty(args.Content.IsSpecified ? args.Content.Value : string.Empty, nameof(args.Content));

var apiEmbeds = embed.IsSpecified || embeds.IsSpecified ? new List<API.Embed>() : null;
@@ -383,9 +384,10 @@ namespace Discord.Rest
var embeds = args.Embeds;

bool hasText = !string.IsNullOrEmpty(args.Content.GetValueOrDefault());
bool hasEmbeds = (embed.IsSpecified && embed.Value != null) || (embeds.IsSpecified && embeds.Value?.Length > 0);
bool hasEmbeds = embed.IsSpecified && embed.Value != null || embeds.IsSpecified && embeds.Value?.Length > 0;
bool hasComponents = args.Components.IsSpecified && args.Components.Value != null;

if (!hasText && !hasEmbeds)
if (!hasComponents && !hasText && !hasEmbeds)
Preconditions.NotNullOrEmpty(args.Content.IsSpecified ? args.Content.Value : string.Empty, nameof(args.Content));

var apiEmbeds = embed.IsSpecified || embeds.IsSpecified ? new List<API.Embed>() : null;


+ 4
- 3
src/Discord.Net.Rest/Entities/Messages/MessageHelper.cs View File

@@ -38,7 +38,7 @@ namespace Discord.Rest
var embeds = args.Embeds;

bool hasText = args.Content.IsSpecified ? !string.IsNullOrEmpty(args.Content.Value) : !string.IsNullOrEmpty(msg.Content);
bool hasEmbeds = (embed.IsSpecified && embed.Value != null) || (embeds.IsSpecified && embeds.Value?.Length > 0) || msg.Embeds.Any();
bool hasEmbeds = embed.IsSpecified && embed.Value != null || embeds.IsSpecified && embeds.Value?.Length > 0 || msg.Embeds.Any();

if (!hasText && !hasEmbeds)
Preconditions.NotNullOrEmpty(args.Content.IsSpecified ? args.Content.Value : string.Empty, nameof(args.Content));
@@ -101,9 +101,10 @@ namespace Discord.Rest
var embeds = args.Embeds;

bool hasText = args.Content.IsSpecified && string.IsNullOrEmpty(args.Content.Value);
bool hasEmbeds = (embed.IsSpecified && embed.Value != null) || (embeds.IsSpecified && embeds.Value?.Length > 0);
bool hasEmbeds = embed.IsSpecified && embed.Value != null || embeds.IsSpecified && embeds.Value?.Length > 0;
bool hasComponents = args.Components.IsSpecified && args.Components.Value != null;

if (!hasText && !hasEmbeds)
if (!hasComponents && !hasText && !hasEmbeds)
Preconditions.NotNullOrEmpty(args.Content.IsSpecified ? args.Content.Value : string.Empty, nameof(args.Content));

if (args.AllowedMentions.IsSpecified)


+ 4
- 1
src/Discord.Net.Rest/Entities/Users/RestGroupUser.cs View File

@@ -10,6 +10,7 @@ namespace Discord.Rest
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public class RestGroupUser : RestUser, IGroupUser
{
#region RestGroupUser
internal RestGroupUser(BaseDiscordClient discord, ulong id)
: base(discord, id)
{
@@ -20,8 +21,9 @@ namespace Discord.Rest
entity.Update(model);
return entity;
}
#endregion

//IVoiceState
#region IVoiceState
/// <inheritdoc />
bool IVoiceState.IsDeafened => false;
/// <inheritdoc />
@@ -40,5 +42,6 @@ namespace Discord.Rest
bool IVoiceState.IsStreaming => false;
/// <inheritdoc />
DateTimeOffset? IVoiceState.RequestToSpeakTimestamp => null;
#endregion
}
}

+ 40
- 21
src/Discord.Net.WebSocket/DiscordSocketClient.cs View File

@@ -24,6 +24,7 @@ namespace Discord.WebSocket
/// </summary>
public partial class DiscordSocketClient : BaseSocketClient, IDiscordClient
{
#region DiscordSocketClient
private readonly ConcurrentQueue<ulong> _largeGuilds;
internal readonly JsonSerializer _serializer;
private readonly DiscordShardedClient _shardedClient;
@@ -62,6 +63,7 @@ namespace Discord.WebSocket
/// <inheritdoc />
public override IActivity Activity { get => _activity.GetValueOrDefault(); protected set => _activity = Optional.Create(value); }
private Optional<IActivity> _activity;
#endregion

//From DiscordSocketConfig
internal int TotalShards { get; private set; }
@@ -436,7 +438,7 @@ namespace Discord.WebSocket

var entity = State.GetOrAddCommand(model.Id, (id) => SocketApplicationCommand.Create(this, model));

// update it incase it was cached
//Update it incase it was cached
entity.Update(model);

return entity;
@@ -448,7 +450,7 @@ namespace Discord.WebSocket

var entities = models.Select(x => SocketApplicationCommand.Create(this, x));

// purge our previous commands
//Purge our previous commands
State.PurgeCommands(x => x.IsGlobalCommand);

foreach(var entity in entities)
@@ -513,7 +515,7 @@ namespace Discord.WebSocket
{
var guild = State.GetGuild(model.GuildId.Value);

// since the sticker can be from another guild, check if we are in the guild or its in the cache
//Since the sticker can be from another guild, check if we are in the guild or its in the cache
if (guild != null)
sticker = guild.AddOrUpdateSticker(model);
else
@@ -678,7 +680,7 @@ namespace Discord.WebSocket
return null;

GameModel game = null;
// Discord only accepts rich presence over RPC, don't even bother building a payload
//Discord only accepts rich presence over RPC, don't even bother building a payload

if (activity.GetValueOrDefault() != null)
{
@@ -700,6 +702,7 @@ namespace Discord.WebSocket
game);
}

#region ProcessMessageAsync
private async Task ProcessMessageAsync(GatewayOpCode opCode, int? seq, string type, object payload)
{
if (seq != null)
@@ -772,7 +775,7 @@ namespace Discord.WebSocket
case GatewayOpCode.Dispatch:
switch (type)
{
//Connection
#region Connection
case "READY":
{
try
@@ -849,8 +852,9 @@ namespace Discord.WebSocket
await _gatewayLogger.InfoAsync("Resumed previous session").ConfigureAwait(false);
}
break;
#endregion

//Guilds
#region Guilds
case "GUILD_CREATE":
{
var data = (payload as JToken).ToObject<ExtendedGuild>(_serializer);
@@ -1000,8 +1004,9 @@ namespace Discord.WebSocket
}
}
break;
#endregion

//Channels
#region Channels
case "CHANNEL_CREATE":
{
await _gatewayLogger.DebugAsync("Received Dispatch (CHANNEL_CREATE)").ConfigureAwait(false);
@@ -1103,8 +1108,9 @@ namespace Discord.WebSocket
}
}
break;
#endregion

//Members
#region Members
case "GUILD_MEMBER_ADD":
{
await _gatewayLogger.DebugAsync("Received Dispatch (GUILD_MEMBER_ADD)").ConfigureAwait(false);
@@ -1275,8 +1281,9 @@ namespace Discord.WebSocket
}
}
break;
#endregion

//Roles
#region Roles
case "GUILD_ROLE_CREATE":
{
await _gatewayLogger.DebugAsync("Received Dispatch (GUILD_ROLE_CREATE)").ConfigureAwait(false);
@@ -1368,8 +1375,9 @@ namespace Discord.WebSocket
}
}
break;
#endregion

//Bans
#region Bans
case "GUILD_BAN_ADD":
{
await _gatewayLogger.DebugAsync("Received Dispatch (GUILD_BAN_ADD)").ConfigureAwait(false);
@@ -1422,8 +1430,9 @@ namespace Discord.WebSocket
}
}
break;
#endregion

//Messages
#region Messages
case "MESSAGE_CREATE":
{
await _gatewayLogger.DebugAsync("Received Dispatch (MESSAGE_CREATE)").ConfigureAwait(false);
@@ -1754,8 +1763,9 @@ namespace Discord.WebSocket
await TimedInvokeAsync(_messagesBulkDeletedEvent, nameof(MessagesBulkDeleted), cacheableList, cacheableChannel).ConfigureAwait(false);
}
break;
#endregion

//Statuses
#region Statuses
case "PRESENCE_UPDATE":
{
await _gatewayLogger.DebugAsync("Received Dispatch (PRESENCE_UPDATE)").ConfigureAwait(false);
@@ -1843,8 +1853,9 @@ namespace Discord.WebSocket
await TimedInvokeAsync(_userIsTypingEvent, nameof(UserIsTyping), cacheableUser, cacheableChannel).ConfigureAwait(false);
}
break;
#endregion

//Users
#region Users
case "USER_UPDATE":
{
await _gatewayLogger.DebugAsync("Received Dispatch (USER_UPDATE)").ConfigureAwait(false);
@@ -1863,8 +1874,9 @@ namespace Discord.WebSocket
}
}
break;
#endregion

//Voice
#region Voice
case "VOICE_STATE_UPDATE":
{
await _gatewayLogger.DebugAsync("Received Dispatch (VOICE_STATE_UPDATE)").ConfigureAwait(false);
@@ -1901,7 +1913,7 @@ namespace Discord.WebSocket
after = SocketVoiceState.Create(null, data);
}

// per g250k, this should always be sent, but apparently not always
//Per g250k, this should always be sent, but apparently not always
user = guild.GetUser(data.UserId)
?? (data.Member.IsSpecified ? guild.AddOrUpdateUser(data.Member.Value) : null);
if (user == null)
@@ -1993,8 +2005,9 @@ namespace Discord.WebSocket

}
break;
#endregion

//Invites
#region Invites
case "INVITE_CREATE":
{
await _gatewayLogger.DebugAsync("Received Dispatch (INVITE_CREATE)").ConfigureAwait(false);
@@ -2051,8 +2064,9 @@ namespace Discord.WebSocket
}
}
break;
#endregion

// Interactions
#region Interactions
case "INTERACTION_CREATE":
{
await _gatewayLogger.DebugAsync("Received Dispatch (INTERACTION_CREATE)").ConfigureAwait(false);
@@ -2189,8 +2203,9 @@ namespace Discord.WebSocket
await TimedInvokeAsync(_applicationCommandDeleted, nameof(ApplicationCommandDeleted), applicationCommand).ConfigureAwait(false);
}
break;
#endregion

// Threads
#region Threads
case "THREAD_CREATE":
{
await _gatewayLogger.DebugAsync("Received Dispatch (THREAD_CREATE)").ConfigureAwait(false);
@@ -2251,7 +2266,7 @@ namespace Discord.WebSocket
}
else
{
// Thread is updated but was not cached, likely meaning the thread was unarchived.
//Thread is updated but was not cached, likely meaning the thread was unarchived.
threadChannel = (SocketThreadChannel)guild.AddChannel(State, data);
if (data.ThreadMember.IsSpecified)
threadChannel.AddOrUpdateThreadMember(data.ThreadMember.Value, guild.CurrentUser);
@@ -2507,8 +2522,9 @@ namespace Discord.WebSocket
}
}
break;
#endregion

//Ignored (User only)
#region Ignored (User only)
case "CHANNEL_PINS_ACK":
await _gatewayLogger.DebugAsync("Ignored Dispatch (CHANNEL_PINS_ACK)").ConfigureAwait(false);
break;
@@ -2530,11 +2546,13 @@ namespace Discord.WebSocket
case "WEBHOOKS_UPDATE":
await _gatewayLogger.DebugAsync("Ignored Dispatch (WEBHOOKS_UPDATE)").ConfigureAwait(false);
break;
#endregion

//Others
#region Others
default:
await _gatewayLogger.WarningAsync($"Unknown Dispatch ({type})").ConfigureAwait(false);
break;
#endregion
}
break;
default:
@@ -2548,6 +2566,7 @@ namespace Discord.WebSocket
Console.WriteLine(ex);
}
}
#endregion

private async Task RunHeartbeatAsync(int intervalMillis, CancellationToken cancelToken)
{


+ 1
- 1
src/Discord.Net.WebSocket/Entities/Interaction/Message Components/SocketMessageComponent.cs View File

@@ -150,7 +150,7 @@ namespace Discord.WebSocket
var embeds = args.Embeds;

bool hasText = args.Content.IsSpecified ? !string.IsNullOrEmpty(args.Content.Value) : !string.IsNullOrEmpty(Message.Content);
bool hasEmbeds = (embed.IsSpecified && embed.Value != null) || (embeds.IsSpecified && embeds.Value?.Length > 0) || Message.Embeds.Any();
bool hasEmbeds = embed.IsSpecified && embed.Value != null || embeds.IsSpecified && embeds.Value?.Length > 0 || Message.Embeds.Any();

if (!hasText && !hasEmbeds)
Preconditions.NotNullOrEmpty(args.Content.IsSpecified ? args.Content.Value : string.Empty, nameof(args.Content));


+ 14
- 7
src/Discord.Net.WebSocket/Extensions/EntityExtensions.cs View File

@@ -9,7 +9,7 @@ namespace Discord.WebSocket
{
public static IActivity ToEntity(this API.Game model)
{
// Custom Status Game
#region Custom Status Game
if (model.Id.IsSpecified && model.Id.Value == "custom")
{
return new CustomStatusGame()
@@ -21,13 +21,14 @@ namespace Discord.WebSocket
CreatedAt = DateTimeOffset.FromUnixTimeMilliseconds(model.CreatedAt.Value),
};
}
#endregion

// Spotify Game
#region Spotify Game
if (model.SyncId.IsSpecified)
{
var assets = model.Assets.GetValueOrDefault()?.ToEntity();
string albumText = assets?[1]?.Text;
string albumArtId = assets?[1]?.ImageId?.Replace("spotify:","");
string albumArtId = assets?[1]?.ImageId?.Replace("spotify:", "");
var timestamps = model.Timestamps.IsSpecified ? model.Timestamps.Value.ToEntity() : null;
return new SpotifyGame
{
@@ -37,7 +38,7 @@ namespace Discord.WebSocket
TrackUrl = CDN.GetSpotifyDirectUrl(model.SyncId.Value),
AlbumTitle = albumText,
TrackTitle = model.Details.GetValueOrDefault(),
Artists = model.State.GetValueOrDefault()?.Split(';').Select(x=>x?.Trim()).ToImmutableArray(),
Artists = model.State.GetValueOrDefault()?.Split(';').Select(x => x?.Trim()).ToImmutableArray(),
StartedAt = timestamps?.Start,
EndsAt = timestamps?.End,
Duration = timestamps?.End - timestamps?.Start,
@@ -46,8 +47,9 @@ namespace Discord.WebSocket
Flags = model.Flags.GetValueOrDefault(),
};
}
#endregion

// Rich Game
#region Rich Game
if (model.ApplicationId.IsSpecified)
{
ulong appId = model.ApplicationId.Value;
@@ -66,7 +68,9 @@ namespace Discord.WebSocket
Flags = model.Flags.GetValueOrDefault()
};
}
// Stream Game
#endregion

#region Stream Game
if (model.StreamUrl.IsSpecified)
{
return new StreamingGame(
@@ -77,10 +81,13 @@ namespace Discord.WebSocket
Details = model.Details.GetValueOrDefault()
};
}
// Normal Game
#endregion

#region Normal Game
return new Game(model.Name, model.Type.GetValueOrDefault() ?? ActivityType.Playing,
model.Flags.IsSpecified ? model.Flags.Value : ActivityProperties.None,
model.Details.GetValueOrDefault());
#endregion
}

// (Small, Large)


Loading…
Cancel
Save