Browse Source

More regions (#177)

* Preconditions

* ChannelHelper

* RestDMChannel

* RestGroupChannel

* RestBan

* RestGroupUser

* EntityExtensions

* DiscordSocketClient

* DiscordSocketClient
pull/1923/head
Simon Hjorthøj GitHub 3 years ago
parent
commit
77b8e78de4
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 115 additions and 55 deletions
  1. +8
    -4
      src/Discord.Net.Core/Utils/Preconditions.cs
  2. +21
    -11
      src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs
  3. +12
    -5
      src/Discord.Net.Rest/Entities/Channels/RestDMChannel.cs
  4. +12
    -5
      src/Discord.Net.Rest/Entities/Channels/RestGroupChannel.cs
  5. +4
    -1
      src/Discord.Net.Rest/Entities/Guilds/RestBan.cs
  6. +4
    -1
      src/Discord.Net.Rest/Entities/Users/RestGroupUser.cs
  7. +40
    -21
      src/Discord.Net.WebSocket/DiscordSocketClient.cs
  8. +14
    -7
      src/Discord.Net.WebSocket/Extensions/EntityExtensions.cs

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

@@ -4,7 +4,7 @@ namespace Discord
{ {
internal static class Preconditions internal static class Preconditions
{ {
//Objects
#region Objects
/// <exception cref="ArgumentNullException"><paramref name="obj"/> must not be <see langword="null"/>.</exception> /// <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); } 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> /// <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); if (msg == null) return new ArgumentNullException(paramName: name);
else return new ArgumentNullException(paramName: name, message: msg); else return new ArgumentNullException(paramName: name, message: msg);
} }
#endregion


//Strings
#region Strings
/// <exception cref="ArgumentException"><paramref name="obj"/> cannot be blank.</exception> /// <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); } 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> /// <exception cref="ArgumentException"><paramref name="obj"/> cannot be blank.</exception>
@@ -58,8 +59,9 @@ namespace Discord


private static ArgumentException CreateNotEmptyException(string name, string msg) private static ArgumentException CreateNotEmptyException(string name, string msg)
=> new ArgumentException(message: msg ?? "Argument cannot be blank.", paramName: name); => 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> /// <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); } 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> /// <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) private static ArgumentException CreateLessThanException<T>(string name, string msg, T value)
=> new ArgumentException(message: msg ?? $"Value must be less than {value}.", paramName: name); => 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> /// <exception cref="ArgumentOutOfRangeException">Messages are younger than 2 weeks.</exception>
public static void YoungerThanTwoWeeks(ulong[] collection, string name) 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); 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 internal static class ChannelHelper
{ {
//General
#region General
public static async Task DeleteAsync(IChannel channel, BaseDiscordClient client, public static async Task DeleteAsync(IChannel channel, BaseDiscordClient client,
RequestOptions options) RequestOptions options)
{ {
@@ -107,8 +107,9 @@ namespace Discord.Rest


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


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


//Messages
#region Messages
public static async Task<RestMessage> GetMessageAsync(IMessageChannel channel, BaseDiscordClient client, public static async Task<RestMessage> GetMessageAsync(IMessageChannel channel, BaseDiscordClient client,
ulong id, RequestOptions options) 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."); 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); var model = await client.ApiClient.CreateMessageAsync(channel.Id, args, options).ConfigureAwait(false);
return RestUserMessage.Create(client, channel, client.CurrentUser, model); 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); 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, public static async Task AddPermissionOverwriteAsync(IGuildChannel channel, BaseDiscordClient client,
IUser user, OverwritePermissions perms, RequestOptions options) IUser user, OverwritePermissions perms, RequestOptions options)
{ {
@@ -421,8 +424,9 @@ namespace Discord.Rest
{ {
await client.ApiClient.DeleteChannelPermissionAsync(channel.Id, role.Id, options).ConfigureAwait(false); 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> /// <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, public static async Task<RestGuildUser> GetUserAsync(IGuildChannel channel, IGuild guild, BaseDiscordClient client,
ulong id, RequestOptions options) ulong id, RequestOptions options)
@@ -467,8 +471,9 @@ namespace Discord.Rest
count: limit count: limit
); );
} }
#endregion


//Typing
#region Typing
public static async Task TriggerTypingAsync(IMessageChannel channel, BaseDiscordClient client, public static async Task TriggerTypingAsync(IMessageChannel channel, BaseDiscordClient client,
RequestOptions options = null) RequestOptions options = null)
{ {
@@ -477,8 +482,9 @@ namespace Discord.Rest
public static IDisposable EnterTypingState(IMessageChannel channel, BaseDiscordClient client, public static IDisposable EnterTypingState(IMessageChannel channel, BaseDiscordClient client,
RequestOptions options) RequestOptions options)
=> new TypingNotifier(channel, 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) public static async Task<RestWebhook> CreateWebhookAsync(ITextChannel channel, BaseDiscordClient client, string name, Stream avatar, RequestOptions options)
{ {
var args = new CreateWebhookParams { Name = name }; var args = new CreateWebhookParams { Name = name };
@@ -501,7 +507,9 @@ namespace Discord.Rest
return models.Select(x => RestWebhook.Create(client, channel, x)) return models.Select(x => RestWebhook.Create(client, channel, x))
.ToImmutableArray(); .ToImmutableArray();
} }
// Categories
#endregion

#region Categories
public static async Task<ICategoryChannel> GetCategoryAsync(INestedChannel channel, BaseDiscordClient client, RequestOptions options) public static async Task<ICategoryChannel> GetCategoryAsync(INestedChannel channel, BaseDiscordClient client, RequestOptions options)
{ {
// if no category id specified, return null // 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) public static async Task SyncPermissionsAsync(INestedChannel channel, BaseDiscordClient client, RequestOptions options)
{ {
var category = await GetCategoryAsync(channel, client, options).ConfigureAwait(false); 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 var apiArgs = new ModifyGuildChannelParams
{ {
@@ -530,5 +539,6 @@ namespace Discord.Rest
}; };
await client.ApiClient.ModifyGuildChannelAsync(channel.Id, apiArgs, options).ConfigureAwait(false); 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}")] [DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public class RestDMChannel : RestChannel, IDMChannel, IRestPrivateChannel, IRestMessageChannel public class RestDMChannel : RestChannel, IDMChannel, IRestPrivateChannel, IRestMessageChannel
{ {
#region RestDMChannel
/// <summary> /// <summary>
/// Gets the current logged-in user. /// Gets the current logged-in user.
/// </summary> /// </summary>
@@ -154,20 +155,24 @@ namespace Discord.Rest
/// </returns> /// </returns>
public override string ToString() => $"@{Recipient}"; public override string ToString() => $"@{Recipient}";
private string DebuggerDisplay => $"@{Recipient} ({Id}, DM)"; private string DebuggerDisplay => $"@{Recipient} ({Id}, DM)";
#endregion


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


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


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


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


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


@@ -223,5 +229,6 @@ namespace Discord.Rest
/// <inheritdoc /> /// <inheritdoc />
IAsyncEnumerable<IReadOnlyCollection<IUser>> IChannel.GetUsersAsync(CacheMode mode, RequestOptions options) IAsyncEnumerable<IReadOnlyCollection<IUser>> IChannel.GetUsersAsync(CacheMode mode, RequestOptions options)
=> ImmutableArray.Create<IReadOnlyCollection<IUser>>(Users).ToAsyncEnumerable(); => 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}")] [DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public class RestGroupChannel : RestChannel, IGroupChannel, IRestPrivateChannel, IRestMessageChannel, IRestAudioChannel public class RestGroupChannel : RestChannel, IGroupChannel, IRestPrivateChannel, IRestMessageChannel, IRestAudioChannel
{ {
#region RestGroupChannel
private string _iconId; private string _iconId;
private ImmutableDictionary<ulong, RestGroupUser> _users; private ImmutableDictionary<ulong, RestGroupUser> _users;


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


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


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


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


//IMessageChannel
#region IMessageChannel
async Task<IMessage> IMessageChannel.GetMessageAsync(ulong id, CacheMode mode, RequestOptions options) async Task<IMessage> IMessageChannel.GetMessageAsync(ulong id, CacheMode mode, RequestOptions options)
{ {
if (mode == CacheMode.AllowDownload) 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) 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); => await SendMessageAsync(text, isTTS, embed, options, allowedMentions, messageReference, component, stickers).ConfigureAwait(false);
#endregion


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


//IChannel
#region IChannel
Task<IUser> IChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) Task<IUser> IChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options)
=> Task.FromResult<IUser>(GetUser(id)); => Task.FromResult<IUser>(GetUser(id));
IAsyncEnumerable<IReadOnlyCollection<IUser>> IChannel.GetUsersAsync(CacheMode mode, RequestOptions options) IAsyncEnumerable<IReadOnlyCollection<IUser>> IChannel.GetUsersAsync(CacheMode mode, RequestOptions options)
=> ImmutableArray.Create<IReadOnlyCollection<IUser>>(Users).ToAsyncEnumerable(); => 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}")] [DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public class RestBan : IBan public class RestBan : IBan
{ {
#region RestBan
/// <summary> /// <summary>
/// Gets the banned user. /// Gets the banned user.
/// </summary> /// </summary>
@@ -37,9 +38,11 @@ namespace Discord.Rest
/// </returns> /// </returns>
public override string ToString() => User.ToString(); public override string ToString() => User.ToString();
private string DebuggerDisplay => $"{User}: {Reason}"; private string DebuggerDisplay => $"{User}: {Reason}";
#endregion


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

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

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


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

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

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


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


var entity = State.GetOrAddCommand(model.Id, (id) => SocketApplicationCommand.Create(this, model)); 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); entity.Update(model);


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


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


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


foreach(var entity in entities) foreach(var entity in entities)
@@ -513,7 +515,7 @@ namespace Discord.WebSocket
{ {
var guild = State.GetGuild(model.GuildId.Value); 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) if (guild != null)
sticker = guild.AddOrUpdateSticker(model); sticker = guild.AddOrUpdateSticker(model);
else else
@@ -678,7 +680,7 @@ namespace Discord.WebSocket
return null; return null;


GameModel game = 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) if (activity.GetValueOrDefault() != null)
{ {
@@ -700,6 +702,7 @@ namespace Discord.WebSocket
game); game);
} }


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


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


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


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


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


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


//Messages
#region Messages
case "MESSAGE_CREATE": case "MESSAGE_CREATE":
{ {
await _gatewayLogger.DebugAsync("Received Dispatch (MESSAGE_CREATE)").ConfigureAwait(false); 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); await TimedInvokeAsync(_messagesBulkDeletedEvent, nameof(MessagesBulkDeleted), cacheableList, cacheableChannel).ConfigureAwait(false);
} }
break; break;
#endregion


//Statuses
#region Statuses
case "PRESENCE_UPDATE": case "PRESENCE_UPDATE":
{ {
await _gatewayLogger.DebugAsync("Received Dispatch (PRESENCE_UPDATE)").ConfigureAwait(false); 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); await TimedInvokeAsync(_userIsTypingEvent, nameof(UserIsTyping), cacheableUser, cacheableChannel).ConfigureAwait(false);
} }
break; break;
#endregion


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


//Voice
#region Voice
case "VOICE_STATE_UPDATE": case "VOICE_STATE_UPDATE":
{ {
await _gatewayLogger.DebugAsync("Received Dispatch (VOICE_STATE_UPDATE)").ConfigureAwait(false); await _gatewayLogger.DebugAsync("Received Dispatch (VOICE_STATE_UPDATE)").ConfigureAwait(false);
@@ -1901,7 +1913,7 @@ namespace Discord.WebSocket
after = SocketVoiceState.Create(null, data); 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) user = guild.GetUser(data.UserId)
?? (data.Member.IsSpecified ? guild.AddOrUpdateUser(data.Member.Value) : null); ?? (data.Member.IsSpecified ? guild.AddOrUpdateUser(data.Member.Value) : null);
if (user == null) if (user == null)
@@ -1993,8 +2005,9 @@ namespace Discord.WebSocket


} }
break; break;
#endregion


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


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


// Threads
#region Threads
case "THREAD_CREATE": case "THREAD_CREATE":
{ {
await _gatewayLogger.DebugAsync("Received Dispatch (THREAD_CREATE)").ConfigureAwait(false); await _gatewayLogger.DebugAsync("Received Dispatch (THREAD_CREATE)").ConfigureAwait(false);
@@ -2251,7 +2266,7 @@ namespace Discord.WebSocket
} }
else 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); threadChannel = (SocketThreadChannel)guild.AddChannel(State, data);
if (data.ThreadMember.IsSpecified) if (data.ThreadMember.IsSpecified)
threadChannel.AddOrUpdateThreadMember(data.ThreadMember.Value, guild.CurrentUser); threadChannel.AddOrUpdateThreadMember(data.ThreadMember.Value, guild.CurrentUser);
@@ -2507,8 +2522,9 @@ namespace Discord.WebSocket
} }
} }
break; break;
#endregion


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


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


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


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


// Spotify Game
#region Spotify Game
if (model.SyncId.IsSpecified) if (model.SyncId.IsSpecified)
{ {
var assets = model.Assets.GetValueOrDefault()?.ToEntity(); var assets = model.Assets.GetValueOrDefault()?.ToEntity();
string albumText = assets?[1]?.Text; 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; var timestamps = model.Timestamps.IsSpecified ? model.Timestamps.Value.ToEntity() : null;
return new SpotifyGame return new SpotifyGame
{ {
@@ -37,7 +38,7 @@ namespace Discord.WebSocket
TrackUrl = CDN.GetSpotifyDirectUrl(model.SyncId.Value), TrackUrl = CDN.GetSpotifyDirectUrl(model.SyncId.Value),
AlbumTitle = albumText, AlbumTitle = albumText,
TrackTitle = model.Details.GetValueOrDefault(), 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, StartedAt = timestamps?.Start,
EndsAt = timestamps?.End, EndsAt = timestamps?.End,
Duration = timestamps?.End - timestamps?.Start, Duration = timestamps?.End - timestamps?.Start,
@@ -46,8 +47,9 @@ namespace Discord.WebSocket
Flags = model.Flags.GetValueOrDefault(), Flags = model.Flags.GetValueOrDefault(),
}; };
} }
#endregion


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

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

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


// (Small, Large) // (Small, Large)


Loading…
Cancel
Save