From 51b2fbeaa04041df09d168ab1d877fd8d6b441f8 Mon Sep 17 00:00:00 2001 From: quin lynch Date: Sat, 31 Jul 2021 16:14:41 -0300 Subject: [PATCH] Threads pre release testing --- src/Discord.Net.Core/Discord.Net.Core.xml | 47 ++++++++++++++++++- src/Discord.Net.Rest/DiscordRestApiClient.cs | 4 +- .../Discord.Net.WebSocket.xml | 38 +++++++++++++++ .../DiscordSocketClient.cs | 18 +++++-- .../Entities/Channels/SocketTextChannel.cs | 9 +++- .../Entities/Channels/SocketThreadChannel.cs | 5 +- .../Entities/Guilds/SocketGuild.cs | 32 +++++++++---- 7 files changed, 134 insertions(+), 19 deletions(-) diff --git a/src/Discord.Net.Core/Discord.Net.Core.xml b/src/Discord.Net.Core/Discord.Net.Core.xml index b351ad49d..1ab7ab78d 100644 --- a/src/Discord.Net.Core/Discord.Net.Core.xml +++ b/src/Discord.Net.Core/Discord.Net.Core.xml @@ -1003,6 +1003,51 @@ A message was unpinned from this guild. + + + A integration was created + + + + + A integration was updated + + + + + An integration was deleted + + + + + A stage instance was created. + + + + + A stage instance was updated. + + + + + A stage instance was deleted. + + + + + A sticker was created. + + + + + A sticker was updated. + + + + + A sticker was deleted. + + Represents data applied to an . @@ -6105,7 +6150,7 @@ The built embed object. Total embed length exceeds . - Any Url must be well formatted include its protocols (i.e http:// or https://). + Any Url must include its protocols (i.e http:// or https://). diff --git a/src/Discord.Net.Rest/DiscordRestApiClient.cs b/src/Discord.Net.Rest/DiscordRestApiClient.cs index 51e98c1a3..d34a6a4b9 100644 --- a/src/Discord.Net.Rest/DiscordRestApiClient.cs +++ b/src/Discord.Net.Rest/DiscordRestApiClient.cs @@ -463,7 +463,9 @@ namespace Discord.API options = RequestOptions.CreateOrClone(options); - await SendAsync("PUT", $"channels/{channelId}/thread-members/{userId}", options: options).ConfigureAwait(false); + var bucket = new BucketIds(channelId: channelId); + + await SendAsync("PUT", () => $"channels/{channelId}/thread-members/{userId}", bucket, options: options).ConfigureAwait(false); } public async Task LeaveThreadAsync(ulong channelId, RequestOptions options = null) diff --git a/src/Discord.Net.WebSocket/Discord.Net.WebSocket.xml b/src/Discord.Net.WebSocket/Discord.Net.WebSocket.xml index 8c6f031fa..b17f73024 100644 --- a/src/Discord.Net.WebSocket/Discord.Net.WebSocket.xml +++ b/src/Discord.Net.WebSocket/Discord.Net.WebSocket.xml @@ -2187,6 +2187,38 @@ + + + Creates a thread within this . + + + When is the thread type will be based off of the + channel its created in. When called on a , it creates a . + When called on a , it creates a . The id of the created + thread will be the same as the id of the message, and as such a message can only have a + single thread created from it. + + The name of the thread. + + The type of the thread. + + Note: This parameter is not used if the parameter is not specified. + + + + The duration on which this thread archives after. + + Note: Options and + are only available for guilds that are boosted. You can check in the to see if the + guild has the THREE_DAY_THREAD_ARCHIVE and SEVEN_DAY_THREAD_ARCHIVE. + + + The message which to start the thread from. + The options to be used when sending the request. + + A task that represents the asynchronous create operation. The task result contains a + + @@ -2352,6 +2384,9 @@ + + + @@ -2390,6 +2425,9 @@ Represents a thread channel inside of a guild. + + + Gets the owner of the current thread. diff --git a/src/Discord.Net.WebSocket/DiscordSocketClient.cs b/src/Discord.Net.WebSocket/DiscordSocketClient.cs index 0c55eeab6..12802247d 100644 --- a/src/Discord.Net.WebSocket/DiscordSocketClient.cs +++ b/src/Discord.Net.WebSocket/DiscordSocketClient.cs @@ -1992,12 +1992,15 @@ namespace Discord.WebSocket if ((threadChannel = guild.ThreadChannels.FirstOrDefault(x => x.Id == data.Id)) != null) { threadChannel.Update(this.State, data); - threadChannel.AddOrUpdateThreadMember(data.ThreadMember.Value, guild.CurrentUser); + + if(data.ThreadMember.IsSpecified) + threadChannel.AddOrUpdateThreadMember(data.ThreadMember.Value, guild.CurrentUser); } else { threadChannel = (SocketThreadChannel)guild.AddChannel(this.State, data); - threadChannel.AddOrUpdateThreadMember(data.ThreadMember.Value, guild.CurrentUser); + if (data.ThreadMember.IsSpecified) + threadChannel.AddOrUpdateThreadMember(data.ThreadMember.Value, guild.CurrentUser); await TimedInvokeAsync(_threadCreated, nameof(ThreadCreated), threadChannel).ConfigureAwait(false); } } @@ -2092,12 +2095,19 @@ namespace Discord.WebSocket var data = (payload as JToken).ToObject(_serializer); - //var guild = State.GetGuild(data.) + var thread = (SocketThreadChannel)State.GetChannel(data.Id.Value); + + if (thread == null) + { + await UnknownChannelAsync(type, data.Id.Value); + return; + } + thread.AddOrUpdateThreadMember(data, thread.Guild.CurrentUser); } break; - case "THREAD_MEMBERS_UPDATE": // based on intents + case "THREAD_MEMBERS_UPDATE": { await _gatewayLogger.DebugAsync("Received Dispatch (THREAD_MEMBERS_UPDATE)").ConfigureAwait(false); diff --git a/src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs b/src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs index ca9164a46..a0d14fdab 100644 --- a/src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs +++ b/src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs @@ -72,7 +72,7 @@ namespace Discord.WebSocket { base.Update(state, model); CategoryId = model.CategoryId; - Topic = model.Topic.Value; + Topic = model.Topic.GetValueOrDefault(); SlowModeInterval = model.SlowMode.GetValueOrDefault(); // some guilds haven't been patched to include this yet? _nsfw = model.Nsfw.GetValueOrDefault(); } @@ -115,7 +115,12 @@ namespace Discord.WebSocket ThreadArchiveDuration autoArchiveDuration = ThreadArchiveDuration.OneDay, IMessage message = null, RequestOptions options = null) { var model = await ThreadHelper.CreateThreadAsync(Discord, this, name, type, autoArchiveDuration, message, options); - return SocketThreadChannel.Create(this.Guild, Discord.State, model); + + var thread = (SocketThreadChannel)Guild.AddOrUpdateChannel(Discord.State, model); + + await thread.DownloadUsersAsync(); + + return thread; } //Messages diff --git a/src/Discord.Net.WebSocket/Entities/Channels/SocketThreadChannel.cs b/src/Discord.Net.WebSocket/Entities/Channels/SocketThreadChannel.cs index 141d7535c..8065a8b2b 100644 --- a/src/Discord.Net.WebSocket/Entities/Channels/SocketThreadChannel.cs +++ b/src/Discord.Net.WebSocket/Entities/Channels/SocketThreadChannel.cs @@ -146,7 +146,6 @@ namespace Discord.WebSocket return member; } - //Users /// public new SocketThreadUser GetUser(ulong id) { @@ -310,7 +309,7 @@ namespace Discord.WebSocket /// This method is not supported in threads. /// public override Task ModifyAsync(Action func, RequestOptions options = null) - => throw new NotImplementedException(); + => ThreadHelper.ModifyAsync(this, Discord, func, options); /// /// @@ -339,5 +338,7 @@ namespace Discord.WebSocket /// public override Task SyncPermissionsAsync(RequestOptions options = null) => throw new NotImplementedException(); + + string IChannel.Name => this.Name; } } diff --git a/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs b/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs index 58e2c152f..f720db018 100644 --- a/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs +++ b/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs @@ -32,7 +32,7 @@ namespace Discord.WebSocket private readonly SemaphoreSlim _audioLock; private TaskCompletionSource _syncPromise, _downloaderPromise; private TaskCompletionSource _audioConnectPromise; - private ConcurrentHashSet _channels; + private ConcurrentDictionary _channels; private ConcurrentDictionary _members; private ConcurrentDictionary _roles; private ConcurrentDictionary _voiceStates; @@ -307,7 +307,7 @@ namespace Discord.WebSocket { var channels = _channels; var state = Discord.State; - return channels.Select(x => state.GetChannel(x) as SocketGuildChannel).Where(x => x != null).ToReadOnlyCollection(channels); + return channels.Select(x => x.Value).Where(x => x != null).ToReadOnlyCollection(channels); } } /// @@ -363,7 +363,7 @@ namespace Discord.WebSocket if (!IsAvailable) { if (_channels == null) - _channels = new ConcurrentHashSet(); + _channels = new ConcurrentDictionary(); if (_members == null) _members = new ConcurrentDictionary(); if (_roles == null) @@ -379,20 +379,20 @@ namespace Discord.WebSocket Update(state, model as Model); - var channels = new ConcurrentHashSet(ConcurrentHashSet.DefaultConcurrencyLevel, (int)(model.Channels.Length * 1.05)); + var channels = new ConcurrentDictionary(ConcurrentHashSet.DefaultConcurrencyLevel, (int)(model.Channels.Length * 1.05)); { for (int i = 0; i < model.Channels.Length; i++) { var channel = SocketGuildChannel.Create(this, state, model.Channels[i]); state.AddChannel(channel); - channels.TryAdd(channel.Id); + channels.TryAdd(channel.Id, channel); } for(int i = 0; i < model.Threads.Length; i++) { var threadChannel = SocketThreadChannel.Create(this, state, model.Threads[i]); state.AddChannel(threadChannel); - channels.TryAdd(threadChannel.Id); + channels.TryAdd(threadChannel.Id, threadChannel); } } @@ -703,20 +703,34 @@ namespace Discord.WebSocket internal SocketGuildChannel AddChannel(ClientState state, ChannelModel model) { var channel = SocketGuildChannel.Create(this, state, model); - _channels.TryAdd(model.Id); + _channels.TryAdd(model.Id, channel); state.AddChannel(channel); return channel; } + + internal SocketGuildChannel AddOrUpdateChannel(ClientState state, ChannelModel model) + { + if (_channels.TryGetValue(model.Id, out SocketGuildChannel channel)) + channel.Update(Discord.State, model); + else + { + channel = SocketGuildChannel.Create(this, Discord.State, model); + _channels[channel.Id] = channel; + state.AddChannel(channel); + } + return channel; + } + internal SocketGuildChannel RemoveChannel(ClientState state, ulong id) { - if (_channels.TryRemove(id)) + if (_channels.TryRemove(id, out var _)) return state.RemoveChannel(id) as SocketGuildChannel; return null; } internal void PurgeChannelCache(ClientState state) { foreach (var channelId in _channels) - state.RemoveChannel(channelId); + state.RemoveChannel(channelId.Key); _channels.Clear(); }