diff --git a/src/Discord.Net.Core/Entities/Users/IUser.cs b/src/Discord.Net.Core/Entities/Users/IUser.cs index e6008aab6..9596a8338 100644 --- a/src/Discord.Net.Core/Entities/Users/IUser.cs +++ b/src/Discord.Net.Core/Entities/Users/IUser.cs @@ -87,7 +87,7 @@ namespace Discord UserProperties? PublicFlags { get; } /// - /// Gets the direct message channel of this user, or create one if it does not already exist. + /// Creates the direct message channel of this user. /// /// /// This method is used to obtain or create a channel used to send a direct message. @@ -102,7 +102,7 @@ namespace Discord /// /// The following example attempts to send a direct message to the target user and logs the incident should /// it fail. - /// /// /// The options to be used when sending the request. @@ -110,6 +110,6 @@ namespace Discord /// A task that represents the asynchronous operation for getting or creating a DM channel. The task result /// contains the DM channel associated with this user. /// - Task GetOrCreateDMChannelAsync(RequestOptions options = null); + Task CreateDMChannelAsync(RequestOptions options = null); } } diff --git a/src/Discord.Net.Core/Extensions/UserExtensions.cs b/src/Discord.Net.Core/Extensions/UserExtensions.cs index 90f26828a..3e46308e6 100644 --- a/src/Discord.Net.Core/Extensions/UserExtensions.cs +++ b/src/Discord.Net.Core/Extensions/UserExtensions.cs @@ -42,7 +42,7 @@ namespace Discord RequestOptions options = null, AllowedMentions allowedMentions = null) { - return await (await user.GetOrCreateDMChannelAsync().ConfigureAwait(false)).SendMessageAsync(text, isTTS, embed, options, allowedMentions).ConfigureAwait(false); + return await (await user.CreateDMChannelAsync().ConfigureAwait(false)).SendMessageAsync(text, isTTS, embed, options, allowedMentions).ConfigureAwait(false); } /// @@ -94,7 +94,7 @@ namespace Discord RequestOptions options = null ) { - return await (await user.GetOrCreateDMChannelAsync().ConfigureAwait(false)).SendFileAsync(stream, filename, text, isTTS, embed, options).ConfigureAwait(false); + return await (await user.CreateDMChannelAsync().ConfigureAwait(false)).SendFileAsync(stream, filename, text, isTTS, embed, options).ConfigureAwait(false); } /// @@ -149,7 +149,7 @@ namespace Discord Embed embed = null, RequestOptions options = null) { - return await (await user.GetOrCreateDMChannelAsync().ConfigureAwait(false)).SendFileAsync(filePath, text, isTTS, embed, options).ConfigureAwait(false); + return await (await user.CreateDMChannelAsync().ConfigureAwait(false)).SendFileAsync(filePath, text, isTTS, embed, options).ConfigureAwait(false); } /// diff --git a/src/Discord.Net.Examples/Core/Entities/Users/IUser.Examples.cs b/src/Discord.Net.Examples/Core/Entities/Users/IUser.Examples.cs index 79a90b46d..83daedaa0 100644 --- a/src/Discord.Net.Examples/Core/Entities/Users/IUser.Examples.cs +++ b/src/Discord.Net.Examples/Core/Entities/Users/IUser.Examples.cs @@ -18,11 +18,11 @@ namespace Discord.Net.Examples.Core.Entities.Users #endregion - #region GetOrCreateDMChannelAsync + #region CreateDMChannelAsync public async Task MessageUserAsync(IUser user) { - var channel = await user.GetOrCreateDMChannelAsync(); + var channel = await user.CreateDMChannelAsync(); try { await channel.SendMessageAsync("Awesome stuff!"); diff --git a/src/Discord.Net.Rest/Entities/Users/RestUser.cs b/src/Discord.Net.Rest/Entities/Users/RestUser.cs index 131a4ec73..7bc1447fe 100644 --- a/src/Discord.Net.Rest/Entities/Users/RestUser.cs +++ b/src/Discord.Net.Rest/Entities/Users/RestUser.cs @@ -79,13 +79,13 @@ namespace Discord.Rest } /// - /// Returns a direct message channel to this user, or create one if it does not already exist. + /// Creates a direct message channel to this user. /// /// The options to be used when sending the request. /// /// A task that represents the asynchronous get operation. The task result contains a rest DM channel where the user is the recipient. /// - public Task GetOrCreateDMChannelAsync(RequestOptions options = null) + public Task CreateDMChannelAsync(RequestOptions options = null) => UserHelper.CreateDMChannelAsync(this, Discord, options); /// @@ -107,7 +107,7 @@ namespace Discord.Rest //IUser /// - async Task IUser.GetOrCreateDMChannelAsync(RequestOptions options) - => await GetOrCreateDMChannelAsync(options).ConfigureAwait(false); + async Task IUser.CreateDMChannelAsync(RequestOptions options) + => await CreateDMChannelAsync(options).ConfigureAwait(false); } } diff --git a/src/Discord.Net.WebSocket/DiscordSocketClient.cs b/src/Discord.Net.WebSocket/DiscordSocketClient.cs index c6e38c1a9..7a1aaa6d6 100644 --- a/src/Discord.Net.WebSocket/DiscordSocketClient.cs +++ b/src/Discord.Net.WebSocket/DiscordSocketClient.cs @@ -305,7 +305,7 @@ namespace Discord.WebSocket /// /// Clears cached DM channels from the client. /// - public void PurgeDMChannelCache() => State.PurgeDMChannels(); + public void PurgeDMChannelCache() => RemoveDMChannels(); /// public override SocketUser GetUser(ulong id) @@ -317,14 +317,11 @@ namespace Discord.WebSocket /// Clears cached users from the client. /// public void PurgeUserCache() => State.PurgeUsers(); - internal SocketGlobalUser GetOrCreateUser(ClientState state, Discord.API.User model) + internal SocketGlobalUser GetOrCreateUser(ClientState state, Discord.API.User model, bool cache) { - return state.GetOrAddUser(model.Id, x => - { - var user = SocketGlobalUser.Create(this, state, model); - user.GlobalUser.AddRef(); - return user; - }); + if (cache) + return state.GetOrAddUser(model.Id, x => SocketGlobalUser.Create(this, state, model)); + return state.GetUser(model.Id) ?? SocketGlobalUser.Create(this, state, model); } internal SocketGlobalUser GetOrCreateSelfUser(ClientState state, Discord.API.User model) { @@ -1245,6 +1242,19 @@ namespace Discord.WebSocket return; } + if (channel == null) + { + if (!data.GuildId.IsSpecified) // assume it is a DM + { + channel = CreateDMChannel(data.ChannelId, data.Author.Value, State); + } + else + { + await UnknownChannelAsync(type, data.ChannelId).ConfigureAwait(false); + return; + } + } + SocketUser author; if (guild != null) { @@ -1254,7 +1264,7 @@ namespace Discord.WebSocket author = guild.GetUser(data.Author.Value.Id); } else - author = (channel as SocketChannel)?.GetUser(data.Author.Value.Id); + author = (channel as SocketChannel).GetUser(data.Author.Value.Id); if (author == null) { @@ -1270,22 +1280,9 @@ namespace Discord.WebSocket } else if (channel is SocketGroupChannel groupChannel) author = groupChannel.GetOrAddUser(data.Author.Value); - else - author = State.GetOrAddUser(data.Author.Value.Id, x => SocketGlobalUser.Create(this, State, data.Author.Value)); - } - - if (channel == null) - { - if (!data.GuildId.IsSpecified) // assume it is a DM - { - var dm = SocketDMChannel.Create(this, State, data.ChannelId, data.Author.Value); - channel = dm; - State.AddChannel(dm); - dm.Recipient.GlobalUser.DMChannel = dm; - } else { - await UnknownChannelAsync(type, data.ChannelId).ConfigureAwait(false); + await UnknownChannelUserAsync(type, data.Author.Value.Id, channel.Id).ConfigureAwait(false); return; } } @@ -1944,24 +1941,29 @@ namespace Discord.WebSocket { var channel = SocketChannel.CreatePrivate(this, state, model); state.AddChannel(channel as SocketChannel); - if (channel is SocketDMChannel dm) - dm.Recipient.GlobalUser.DMChannel = dm; - return channel; } + internal SocketDMChannel CreateDMChannel(ulong channelId, API.User model, ClientState state) + { + return SocketDMChannel.Create(this, state, channelId, model); + } internal ISocketPrivateChannel RemovePrivateChannel(ulong id) { var channel = State.RemoveChannel(id) as ISocketPrivateChannel; if (channel != null) { - if (channel is SocketDMChannel dmChannel) - dmChannel.Recipient.GlobalUser.DMChannel = null; - foreach (var recipient in channel.Recipients) recipient.GlobalUser.RemoveRef(this); } return channel; } + internal void RemoveDMChannels() + { + var channels = State.DMChannels; + State.PurgeDMChannels(); + foreach (var channel in channels) + channel.Recipient.GlobalUser.RemoveRef(this); + } private async Task GuildAvailableAsync(SocketGuild guild) { diff --git a/src/Discord.Net.WebSocket/Entities/Channels/SocketDMChannel.cs b/src/Discord.Net.WebSocket/Entities/Channels/SocketDMChannel.cs index 7f07d10d0..a42db3b5f 100644 --- a/src/Discord.Net.WebSocket/Entities/Channels/SocketDMChannel.cs +++ b/src/Discord.Net.WebSocket/Entities/Channels/SocketDMChannel.cs @@ -16,15 +16,13 @@ namespace Discord.WebSocket [DebuggerDisplay(@"{DebuggerDisplay,nq}")] public class SocketDMChannel : SocketChannel, IDMChannel, ISocketPrivateChannel, ISocketMessageChannel { - private readonly MessageCache _messages; - /// /// Gets the recipient of the channel. /// public SocketUser Recipient { get; } /// - public IReadOnlyCollection CachedMessages => _messages?.Messages ?? ImmutableArray.Create(); + public IReadOnlyCollection CachedMessages => ImmutableArray.Create(); /// /// Gets a collection that is the current logged-in user and the recipient. @@ -35,13 +33,10 @@ namespace Discord.WebSocket : base(discord, id) { Recipient = recipient; - recipient.GlobalUser.AddRef(); - if (Discord.MessageCacheSize > 0) - _messages = new MessageCache(Discord); } internal static SocketDMChannel Create(DiscordSocketClient discord, ClientState state, Model model) { - var entity = new SocketDMChannel(discord, model.Id, discord.GetOrCreateUser(state, model.Recipients.Value[0])); + var entity = new SocketDMChannel(discord, model.Id, discord.GetOrCreateUser(state, model.Recipients.Value[0], false)); entity.Update(state, model); return entity; } @@ -51,7 +46,7 @@ namespace Discord.WebSocket } internal static SocketDMChannel Create(DiscordSocketClient discord, ClientState state, ulong channelId, API.User recipient) { - var entity = new SocketDMChannel(discord, channelId, discord.GetOrCreateUser(state, recipient)); + var entity = new SocketDMChannel(discord, channelId, discord.GetOrCreateUser(state, recipient, false)); entity.Update(state, recipient); return entity; } @@ -67,7 +62,7 @@ namespace Discord.WebSocket //Messages /// public SocketMessage GetCachedMessage(ulong id) - => _messages?.Get(id); + => null; /// /// Gets the message associated with the given . /// @@ -78,10 +73,7 @@ namespace Discord.WebSocket /// public async Task GetMessageAsync(ulong id, RequestOptions options = null) { - IMessage msg = _messages?.Get(id); - if (msg == null) - msg = await ChannelHelper.GetMessageAsync(this, Discord, id, options).ConfigureAwait(false); - return msg; + return await ChannelHelper.GetMessageAsync(this, Discord, id, options).ConfigureAwait(false); } /// @@ -97,7 +89,7 @@ namespace Discord.WebSocket /// Paged collection of messages. /// public IAsyncEnumerable> GetMessagesAsync(int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null) - => SocketChannelHelper.GetMessagesAsync(this, Discord, _messages, null, Direction.Before, limit, CacheMode.AllowDownload, options); + => ChannelHelper.GetMessagesAsync(this, Discord, null, Direction.Before, limit, options); /// /// Gets a collection of messages in this channel. /// @@ -113,7 +105,7 @@ namespace Discord.WebSocket /// Paged collection of messages. /// public IAsyncEnumerable> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null) - => SocketChannelHelper.GetMessagesAsync(this, Discord, _messages, fromMessageId, dir, limit, CacheMode.AllowDownload, options); + => ChannelHelper.GetMessagesAsync(this, Discord, fromMessageId, dir, limit, options); /// /// Gets a collection of messages in this channel. /// @@ -129,16 +121,16 @@ namespace Discord.WebSocket /// Paged collection of messages. /// public IAsyncEnumerable> GetMessagesAsync(IMessage fromMessage, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null) - => SocketChannelHelper.GetMessagesAsync(this, Discord, _messages, fromMessage.Id, dir, limit, CacheMode.AllowDownload, options); + => ChannelHelper.GetMessagesAsync(this, Discord, fromMessage.Id, dir, limit, options); /// public IReadOnlyCollection GetCachedMessages(int limit = DiscordConfig.MaxMessagesPerBatch) - => SocketChannelHelper.GetCachedMessages(this, Discord, _messages, null, Direction.Before, limit); + => ImmutableArray.Create(); /// public IReadOnlyCollection GetCachedMessages(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch) - => SocketChannelHelper.GetCachedMessages(this, Discord, _messages, fromMessageId, dir, limit); + => ImmutableArray.Create(); /// public IReadOnlyCollection GetCachedMessages(IMessage fromMessage, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch) - => SocketChannelHelper.GetCachedMessages(this, Discord, _messages, fromMessage.Id, dir, limit); + => ImmutableArray.Create(); /// public Task> GetPinnedMessagesAsync(RequestOptions options = null) => ChannelHelper.GetPinnedMessagesAsync(this, Discord, options); @@ -174,9 +166,12 @@ namespace Discord.WebSocket => ChannelHelper.EnterTypingState(this, Discord, options); internal void AddMessage(SocketMessage msg) - => _messages?.Add(msg); + { + } internal SocketMessage RemoveMessage(ulong id) - => _messages?.Remove(id); + { + return null; + } //Users /// @@ -232,13 +227,13 @@ namespace Discord.WebSocket } /// IAsyncEnumerable> IMessageChannel.GetMessagesAsync(int limit, CacheMode mode, RequestOptions options) - => SocketChannelHelper.GetMessagesAsync(this, Discord, _messages, null, Direction.Before, limit, mode, options); + => mode == CacheMode.CacheOnly ? null : GetMessagesAsync(limit, options); /// IAsyncEnumerable> IMessageChannel.GetMessagesAsync(ulong fromMessageId, Direction dir, int limit, CacheMode mode, RequestOptions options) - => SocketChannelHelper.GetMessagesAsync(this, Discord, _messages, fromMessageId, dir, limit, mode, options); + => mode == CacheMode.CacheOnly ? null : GetMessagesAsync(fromMessageId, dir, limit, options); /// IAsyncEnumerable> IMessageChannel.GetMessagesAsync(IMessage fromMessage, Direction dir, int limit, CacheMode mode, RequestOptions options) - => SocketChannelHelper.GetMessagesAsync(this, Discord, _messages, fromMessage.Id, dir, limit, mode, options); + => mode == CacheMode.CacheOnly ? null : GetMessagesAsync(fromMessage.Id, dir, limit, options); /// async Task> IMessageChannel.GetPinnedMessagesAsync(RequestOptions options) => await GetPinnedMessagesAsync(options).ConfigureAwait(false); diff --git a/src/Discord.Net.WebSocket/Entities/Users/SocketGlobalUser.cs b/src/Discord.Net.WebSocket/Entities/Users/SocketGlobalUser.cs index 48de7552a..15c5182fc 100644 --- a/src/Discord.Net.WebSocket/Entities/Users/SocketGlobalUser.cs +++ b/src/Discord.Net.WebSocket/Entities/Users/SocketGlobalUser.cs @@ -12,7 +12,6 @@ namespace Discord.WebSocket public override string Username { get; internal set; } public override ushort DiscriminatorValue { get; internal set; } public override string AvatarId { get; internal set; } - public SocketDMChannel DMChannel { get; internal set; } internal override SocketPresence Presence { get; set; } public override bool IsWebhook => false; @@ -52,7 +51,6 @@ namespace Discord.WebSocket internal void Update(ClientState state, PresenceModel model) { Presence = SocketPresence.Create(model); - DMChannel = state.DMChannels.FirstOrDefault(x => x.Recipient.Id == Id); } private string DebuggerDisplay => $"{Username}#{Discriminator} ({Id}{(IsBot ? ", Bot" : "")}, Global)"; diff --git a/src/Discord.Net.WebSocket/Entities/Users/SocketGroupUser.cs b/src/Discord.Net.WebSocket/Entities/Users/SocketGroupUser.cs index 676c0a86c..9f66bed12 100644 --- a/src/Discord.Net.WebSocket/Entities/Users/SocketGroupUser.cs +++ b/src/Discord.Net.WebSocket/Entities/Users/SocketGroupUser.cs @@ -38,7 +38,7 @@ namespace Discord.WebSocket } internal static SocketGroupUser Create(SocketGroupChannel channel, ClientState state, Model model) { - var entity = new SocketGroupUser(channel, channel.Discord.GetOrCreateUser(state, model)); + var entity = new SocketGroupUser(channel, channel.Discord.GetOrCreateUser(state, model, true)); entity.Update(state, model); return entity; } diff --git a/src/Discord.Net.WebSocket/Entities/Users/SocketGuildUser.cs b/src/Discord.Net.WebSocket/Entities/Users/SocketGuildUser.cs index 9263fe642..6362d4891 100644 --- a/src/Discord.Net.WebSocket/Entities/Users/SocketGuildUser.cs +++ b/src/Discord.Net.WebSocket/Entities/Users/SocketGuildUser.cs @@ -116,20 +116,20 @@ namespace Discord.WebSocket } internal static SocketGuildUser Create(SocketGuild guild, ClientState state, UserModel model) { - var entity = new SocketGuildUser(guild, guild.Discord.GetOrCreateUser(state, model)); + var entity = new SocketGuildUser(guild, guild.Discord.GetOrCreateUser(state, model, true)); entity.Update(state, model); entity.UpdateRoles(new ulong[0]); return entity; } internal static SocketGuildUser Create(SocketGuild guild, ClientState state, MemberModel model) { - var entity = new SocketGuildUser(guild, guild.Discord.GetOrCreateUser(state, model.User)); + var entity = new SocketGuildUser(guild, guild.Discord.GetOrCreateUser(state, model.User, true)); entity.Update(state, model); return entity; } internal static SocketGuildUser Create(SocketGuild guild, ClientState state, PresenceModel model) { - var entity = new SocketGuildUser(guild, guild.Discord.GetOrCreateUser(state, model.User)); + var entity = new SocketGuildUser(guild, guild.Discord.GetOrCreateUser(state, model.User, true)); entity.Update(state, model, false); return entity; } diff --git a/src/Discord.Net.WebSocket/Entities/Users/SocketUser.cs b/src/Discord.Net.WebSocket/Entities/Users/SocketUser.cs index 979314be3..025daf29a 100644 --- a/src/Discord.Net.WebSocket/Entities/Users/SocketUser.cs +++ b/src/Discord.Net.WebSocket/Entities/Users/SocketUser.cs @@ -92,8 +92,8 @@ namespace Discord.WebSocket } /// - public async Task GetOrCreateDMChannelAsync(RequestOptions options = null) - => GlobalUser.DMChannel ?? await UserHelper.CreateDMChannelAsync(this, Discord, options).ConfigureAwait(false) as IDMChannel; + public async Task CreateDMChannelAsync(RequestOptions options = null) + => await UserHelper.CreateDMChannelAsync(this, Discord, options).ConfigureAwait(false); /// public string GetAvatarUrl(ImageFormat format = ImageFormat.Auto, ushort size = 128)