* Remove DM cache and fix references * Move line back to where it waspull/1852/head
@@ -87,7 +87,7 @@ namespace Discord | |||
UserProperties? PublicFlags { get; } | |||
/// <summary> | |||
/// 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. | |||
/// </summary> | |||
/// <remarks> | |||
/// This method is used to obtain or create a channel used to send a direct message. | |||
@@ -102,7 +102,7 @@ namespace Discord | |||
/// <example> | |||
/// <para>The following example attempts to send a direct message to the target user and logs the incident should | |||
/// it fail.</para> | |||
/// <code region="GetOrCreateDMChannelAsync" language="cs" | |||
/// <code region="CreateDMChannelAsync" language="cs" | |||
/// source="../../../Discord.Net.Examples/Core/Entities/Users/IUser.Examples.cs"/> | |||
/// </example> | |||
/// <param name="options">The options to be used when sending the request.</param> | |||
@@ -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. | |||
/// </returns> | |||
Task<IDMChannel> GetOrCreateDMChannelAsync(RequestOptions options = null); | |||
Task<IDMChannel> CreateDMChannelAsync(RequestOptions options = null); | |||
} | |||
} |
@@ -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); | |||
} | |||
/// <summary> | |||
@@ -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); | |||
} | |||
/// <summary> | |||
@@ -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); | |||
} | |||
/// <summary> | |||
@@ -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!"); | |||
@@ -79,13 +79,13 @@ namespace Discord.Rest | |||
} | |||
/// <summary> | |||
/// 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. | |||
/// </summary> | |||
/// <param name="options">The options to be used when sending the request.</param> | |||
/// <returns> | |||
/// A task that represents the asynchronous get operation. The task result contains a rest DM channel where the user is the recipient. | |||
/// </returns> | |||
public Task<RestDMChannel> GetOrCreateDMChannelAsync(RequestOptions options = null) | |||
public Task<RestDMChannel> CreateDMChannelAsync(RequestOptions options = null) | |||
=> UserHelper.CreateDMChannelAsync(this, Discord, options); | |||
/// <inheritdoc /> | |||
@@ -107,7 +107,7 @@ namespace Discord.Rest | |||
//IUser | |||
/// <inheritdoc /> | |||
async Task<IDMChannel> IUser.GetOrCreateDMChannelAsync(RequestOptions options) | |||
=> await GetOrCreateDMChannelAsync(options).ConfigureAwait(false); | |||
async Task<IDMChannel> IUser.CreateDMChannelAsync(RequestOptions options) | |||
=> await CreateDMChannelAsync(options).ConfigureAwait(false); | |||
} | |||
} |
@@ -305,7 +305,7 @@ namespace Discord.WebSocket | |||
/// <summary> | |||
/// Clears cached DM channels from the client. | |||
/// </summary> | |||
public void PurgeDMChannelCache() => State.PurgeDMChannels(); | |||
public void PurgeDMChannelCache() => RemoveDMChannels(); | |||
/// <inheritdoc /> | |||
public override SocketUser GetUser(ulong id) | |||
@@ -317,14 +317,11 @@ namespace Discord.WebSocket | |||
/// Clears cached users from the client. | |||
/// </summary> | |||
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) | |||
{ | |||
@@ -1271,21 +1281,8 @@ 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) | |||
{ | |||
@@ -16,15 +16,13 @@ namespace Discord.WebSocket | |||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")] | |||
public class SocketDMChannel : SocketChannel, IDMChannel, ISocketPrivateChannel, ISocketMessageChannel | |||
{ | |||
private readonly MessageCache _messages; | |||
/// <summary> | |||
/// Gets the recipient of the channel. | |||
/// </summary> | |||
public SocketUser Recipient { get; } | |||
/// <inheritdoc /> | |||
public IReadOnlyCollection<SocketMessage> CachedMessages => _messages?.Messages ?? ImmutableArray.Create<SocketMessage>(); | |||
public IReadOnlyCollection<SocketMessage> CachedMessages => ImmutableArray.Create<SocketMessage>(); | |||
/// <summary> | |||
/// 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 | |||
/// <inheritdoc /> | |||
public SocketMessage GetCachedMessage(ulong id) | |||
=> _messages?.Get(id); | |||
=> null; | |||
/// <summary> | |||
/// Gets the message associated with the given <paramref name="id"/>. | |||
/// </summary> | |||
@@ -78,10 +73,7 @@ namespace Discord.WebSocket | |||
/// </returns> | |||
public async Task<IMessage> 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); | |||
} | |||
/// <summary> | |||
@@ -97,7 +89,7 @@ namespace Discord.WebSocket | |||
/// Paged collection of messages. | |||
/// </returns> | |||
public IAsyncEnumerable<IReadOnlyCollection<IMessage>> 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); | |||
/// <summary> | |||
/// Gets a collection of messages in this channel. | |||
/// </summary> | |||
@@ -113,7 +105,7 @@ namespace Discord.WebSocket | |||
/// Paged collection of messages. | |||
/// </returns> | |||
public IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null) | |||
=> SocketChannelHelper.GetMessagesAsync(this, Discord, _messages, fromMessageId, dir, limit, CacheMode.AllowDownload, options); | |||
=> ChannelHelper.GetMessagesAsync(this, Discord, fromMessageId, dir, limit, options); | |||
/// <summary> | |||
/// Gets a collection of messages in this channel. | |||
/// </summary> | |||
@@ -129,16 +121,16 @@ namespace Discord.WebSocket | |||
/// Paged collection of messages. | |||
/// </returns> | |||
public IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(IMessage fromMessage, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null) | |||
=> SocketChannelHelper.GetMessagesAsync(this, Discord, _messages, fromMessage.Id, dir, limit, CacheMode.AllowDownload, options); | |||
=> ChannelHelper.GetMessagesAsync(this, Discord, fromMessage.Id, dir, limit, options); | |||
/// <inheritdoc /> | |||
public IReadOnlyCollection<SocketMessage> GetCachedMessages(int limit = DiscordConfig.MaxMessagesPerBatch) | |||
=> SocketChannelHelper.GetCachedMessages(this, Discord, _messages, null, Direction.Before, limit); | |||
=> ImmutableArray.Create<SocketMessage>(); | |||
/// <inheritdoc /> | |||
public IReadOnlyCollection<SocketMessage> GetCachedMessages(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch) | |||
=> SocketChannelHelper.GetCachedMessages(this, Discord, _messages, fromMessageId, dir, limit); | |||
=> ImmutableArray.Create<SocketMessage>(); | |||
/// <inheritdoc /> | |||
public IReadOnlyCollection<SocketMessage> GetCachedMessages(IMessage fromMessage, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch) | |||
=> SocketChannelHelper.GetCachedMessages(this, Discord, _messages, fromMessage.Id, dir, limit); | |||
=> ImmutableArray.Create<SocketMessage>(); | |||
/// <inheritdoc /> | |||
public Task<IReadOnlyCollection<RestMessage>> 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 | |||
/// <summary> | |||
@@ -232,13 +227,13 @@ namespace Discord.WebSocket | |||
} | |||
/// <inheritdoc /> | |||
IAsyncEnumerable<IReadOnlyCollection<IMessage>> 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); | |||
/// <inheritdoc /> | |||
IAsyncEnumerable<IReadOnlyCollection<IMessage>> 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); | |||
/// <inheritdoc /> | |||
IAsyncEnumerable<IReadOnlyCollection<IMessage>> 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); | |||
/// <inheritdoc /> | |||
async Task<IReadOnlyCollection<IMessage>> IMessageChannel.GetPinnedMessagesAsync(RequestOptions options) | |||
=> await GetPinnedMessagesAsync(options).ConfigureAwait(false); | |||
@@ -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)"; | |||
@@ -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; | |||
} | |||
@@ -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; | |||
} | |||
@@ -92,8 +92,8 @@ namespace Discord.WebSocket | |||
} | |||
/// <inheritdoc /> | |||
public async Task<IDMChannel> GetOrCreateDMChannelAsync(RequestOptions options = null) | |||
=> GlobalUser.DMChannel ?? await UserHelper.CreateDMChannelAsync(this, Discord, options).ConfigureAwait(false) as IDMChannel; | |||
public async Task<IDMChannel> CreateDMChannelAsync(RequestOptions options = null) | |||
=> await UserHelper.CreateDMChannelAsync(this, Discord, options).ConfigureAwait(false); | |||
/// <inheritdoc /> | |||
public string GetAvatarUrl(ImageFormat format = ImageFormat.Auto, ushort size = 128) | |||