Added IGroupUser, GroupChannel.Add/Remove Recipient, Add/Remove Recipient events
This commit is contained in:
@@ -551,6 +551,23 @@ namespace Discord.API
|
||||
await SendAsync("DELETE", $"channels/{channelId}/pins/{messageId}", options: options).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
//Channel Recipients
|
||||
public async Task AddGroupRecipientAsync(ulong channelId, ulong userId, RequestOptions options = null)
|
||||
{
|
||||
Preconditions.GreaterThan(channelId, 0, nameof(channelId));
|
||||
Preconditions.GreaterThan(userId, 0, nameof(userId));
|
||||
|
||||
await SendAsync("PUT", $"channels/{channelId}/recipients/{userId}", options: options).ConfigureAwait(false);
|
||||
|
||||
}
|
||||
public async Task RemoveGroupRecipientAsync(ulong channelId, ulong userId, RequestOptions options = null)
|
||||
{
|
||||
Preconditions.NotEqual(channelId, 0, nameof(channelId));
|
||||
Preconditions.NotEqual(userId, 0, nameof(userId));
|
||||
|
||||
await SendAsync("DELETE", $"channels/{channelId}/recipients/{userId}", options: options).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
//Guilds
|
||||
public async Task<Guild> GetGuildAsync(ulong guildId, RequestOptions options = null)
|
||||
{
|
||||
|
||||
12
src/Discord.Net/API/Gateway/RecipientEvent.cs
Normal file
12
src/Discord.Net/API/Gateway/RecipientEvent.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Discord.API.Gateway
|
||||
{
|
||||
public class RecipientEvent
|
||||
{
|
||||
[JsonProperty("user")]
|
||||
public User User { get; set; }
|
||||
[JsonProperty("channel_id")]
|
||||
public ulong ChannelId { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -170,11 +170,9 @@ namespace Discord
|
||||
return new DMChannel(this, new User(model.Recipients.Value[0]), model);
|
||||
else if (model.Type == ChannelType.Group)
|
||||
{
|
||||
var recipients = model.Recipients.Value;
|
||||
var users = new ConcurrentDictionary<ulong, IUser>(1, recipients.Length);
|
||||
for (int i = 0; i < recipients.Length; i++)
|
||||
users[recipients[i].Id] = new User(recipients[i]);
|
||||
return new GroupChannel(this, users, model);
|
||||
var channel = new GroupChannel(this, model);
|
||||
channel.UpdateUsers(model.Recipients.Value, UpdateSource.Creation);
|
||||
return channel;
|
||||
}
|
||||
else
|
||||
throw new InvalidOperationException($"Unexpected channel type: {model.Type}");
|
||||
|
||||
@@ -185,6 +185,18 @@ namespace Discord
|
||||
remove { _userIsTypingEvent.Remove(value); }
|
||||
}
|
||||
private readonly AsyncEvent<Func<IUser, IChannel, Task>> _userIsTypingEvent = new AsyncEvent<Func<IUser, IChannel, Task>>();
|
||||
public event Func<IGroupUser, Task> RecipientAdded
|
||||
{
|
||||
add { _recipientAddedEvent.Add(value); }
|
||||
remove { _recipientAddedEvent.Remove(value); }
|
||||
}
|
||||
private readonly AsyncEvent<Func<IGroupUser, Task>> _recipientAddedEvent = new AsyncEvent<Func<IGroupUser, Task>>();
|
||||
public event Func<IGroupUser, Task> RecipientRemoved
|
||||
{
|
||||
add { _recipientRemovedEvent.Add(value); }
|
||||
remove { _recipientRemovedEvent.Remove(value); }
|
||||
}
|
||||
private readonly AsyncEvent<Func<IGroupUser, Task>> _recipientRemovedEvent = new AsyncEvent<Func<IGroupUser, Task>>();
|
||||
|
||||
//TODO: Add PresenceUpdated? VoiceStateUpdated?, VoiceConnected, VoiceDisconnected;
|
||||
}
|
||||
|
||||
@@ -147,6 +147,7 @@ namespace Discord
|
||||
|
||||
ConnectionState = ConnectionState.Connecting;
|
||||
await _gatewayLogger.InfoAsync("Connecting").ConfigureAwait(false);
|
||||
|
||||
try
|
||||
{
|
||||
_connectTask = new TaskCompletionSource<bool>();
|
||||
@@ -160,7 +161,6 @@ namespace Discord
|
||||
await ApiClient.SendIdentifyAsync().ConfigureAwait(false);
|
||||
|
||||
await _connectTask.Task.ConfigureAwait(false);
|
||||
|
||||
ConnectionState = ConnectionState.Connected;
|
||||
await _gatewayLogger.InfoAsync("Connected").ConfigureAwait(false);
|
||||
}
|
||||
@@ -173,6 +173,7 @@ namespace Discord
|
||||
/// <inheritdoc />
|
||||
public async Task DisconnectAsync()
|
||||
{
|
||||
if (_connectTask?.TrySetCanceled() ?? false) return;
|
||||
await _connectionLock.WaitAsync().ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
@@ -181,6 +182,17 @@ namespace Discord
|
||||
}
|
||||
finally { _connectionLock.Release(); }
|
||||
}
|
||||
private async Task DisconnectAsync(Exception ex)
|
||||
{
|
||||
if (_connectTask?.TrySetException(ex) ?? false) return;
|
||||
await _connectionLock.WaitAsync().ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
_isReconnecting = false;
|
||||
await DisconnectInternalAsync(ex).ConfigureAwait(false);
|
||||
}
|
||||
finally { _connectionLock.Release(); }
|
||||
}
|
||||
private async Task DisconnectInternalAsync(Exception ex)
|
||||
{
|
||||
ulong guildId;
|
||||
@@ -340,17 +352,14 @@ namespace Discord
|
||||
{
|
||||
var recipients = model.Recipients.Value;
|
||||
var user = GetOrAddUser(recipients[0], dataStore);
|
||||
var channel = new CachedDMChannel(this, new CachedPrivateUser(user), model);
|
||||
var channel = new CachedDMChannel(this, new CachedDMUser(user), model);
|
||||
dataStore.AddChannel(channel);
|
||||
return channel;
|
||||
}
|
||||
case ChannelType.Group:
|
||||
{
|
||||
var recipients = model.Recipients.Value;
|
||||
var users = new ConcurrentDictionary<ulong, IUser>(1, recipients.Length);
|
||||
for (int i = 0; i < recipients.Length; i++)
|
||||
users[recipients[i].Id] = new CachedPrivateUser(GetOrAddUser(recipients[i], dataStore));
|
||||
var channel = new CachedGroupChannel(this, users, model);
|
||||
var channel = new CachedGroupChannel(this, model);
|
||||
channel.UpdateUsers(model.Recipients.Value, UpdateSource.Creation);
|
||||
dataStore.AddChannel(channel);
|
||||
return channel;
|
||||
}
|
||||
@@ -521,34 +530,43 @@ namespace Discord
|
||||
//Connection
|
||||
case "READY":
|
||||
{
|
||||
await _gatewayLogger.DebugAsync("Received Dispatch (READY)").ConfigureAwait(false);
|
||||
|
||||
var data = (payload as JToken).ToObject<ReadyEvent>(_serializer);
|
||||
var dataStore = new DataStore( data.Guilds.Length, data.PrivateChannels.Length);
|
||||
|
||||
var currentUser = new CachedSelfUser(this, data.User);
|
||||
int unavailableGuilds = 0;
|
||||
for (int i = 0; i < data.Guilds.Length; i++)
|
||||
try
|
||||
{
|
||||
var model = data.Guilds[i];
|
||||
AddGuild(model, dataStore);
|
||||
if (model.Unavailable == true)
|
||||
unavailableGuilds++;
|
||||
}
|
||||
for (int i = 0; i < data.PrivateChannels.Length; i++)
|
||||
AddPrivateChannel(data.PrivateChannels[i], dataStore);
|
||||
await _gatewayLogger.DebugAsync("Received Dispatch (READY)").ConfigureAwait(false);
|
||||
|
||||
_sessionId = data.SessionId;
|
||||
_currentUser = currentUser;
|
||||
_unavailableGuilds = unavailableGuilds;
|
||||
_lastGuildAvailableTime = Environment.TickCount;
|
||||
DataStore = dataStore;
|
||||
var data = (payload as JToken).ToObject<ReadyEvent>(_serializer);
|
||||
var dataStore = new DataStore(data.Guilds.Length, data.PrivateChannels.Length);
|
||||
|
||||
var currentUser = new CachedSelfUser(this, data.User);
|
||||
int unavailableGuilds = 0;
|
||||
for (int i = 0; i < data.Guilds.Length; i++)
|
||||
{
|
||||
var model = data.Guilds[i];
|
||||
AddGuild(model, dataStore);
|
||||
if (model.Unavailable == true)
|
||||
unavailableGuilds++;
|
||||
}
|
||||
for (int i = 0; i < data.PrivateChannels.Length; i++)
|
||||
AddPrivateChannel(data.PrivateChannels[i], dataStore);
|
||||
|
||||
_sessionId = data.SessionId;
|
||||
_currentUser = currentUser;
|
||||
_unavailableGuilds = unavailableGuilds;
|
||||
_lastGuildAvailableTime = Environment.TickCount;
|
||||
DataStore = dataStore;
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await DisconnectAsync(new Exception("Processing READY failed", ex));
|
||||
return;
|
||||
}
|
||||
|
||||
_guildDownloadTask = WaitForGuildsAsync(_cancelToken.Token, _clientLogger);
|
||||
|
||||
await _readyEvent.InvokeAsync().ConfigureAwait(false);
|
||||
await SyncGuildsAsync().ConfigureAwait(false);
|
||||
|
||||
|
||||
var _ = _connectTask.TrySetResultAsync(true); //Signal the .Connect() call to complete
|
||||
await _gatewayLogger.InfoAsync("Ready").ConfigureAwait(false);
|
||||
}
|
||||
@@ -913,6 +931,51 @@ namespace Discord
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "CHANNEL_RECIPIENT_ADD":
|
||||
{
|
||||
await _gatewayLogger.DebugAsync("Received Dispatch (CHANNEL_RECIPIENT_ADD)").ConfigureAwait(false);
|
||||
|
||||
var data = (payload as JToken).ToObject<RecipientEvent>(_serializer);
|
||||
var channel = DataStore.GetChannel(data.ChannelId) as CachedGroupChannel;
|
||||
if (channel != null)
|
||||
{
|
||||
var user = channel.AddUser(data.User, DataStore);
|
||||
await _recipientAddedEvent.InvokeAsync(user).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
await _gatewayLogger.WarningAsync("CHANNEL_RECIPIENT_ADD referenced an unknown channel.").ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "CHANNEL_RECIPIENT_REMOVE":
|
||||
{
|
||||
await _gatewayLogger.DebugAsync("Received Dispatch (CHANNEL_RECIPIENT_REMOVE)").ConfigureAwait(false);
|
||||
|
||||
var data = (payload as JToken).ToObject<RecipientEvent>(_serializer);
|
||||
var channel = DataStore.GetChannel(data.ChannelId) as CachedGroupChannel;
|
||||
if (channel != null)
|
||||
{
|
||||
var user = channel.RemoveUser(data.User.Id);
|
||||
if (user != null)
|
||||
{
|
||||
user.User.RemoveRef(this);
|
||||
await _recipientRemovedEvent.InvokeAsync(user).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
await _gatewayLogger.WarningAsync("CHANNEL_RECIPIENT_REMOVE referenced an unknown user.").ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
await _gatewayLogger.WarningAsync("CHANNEL_RECIPIENT_ADD referenced an unknown channel.").ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
//Roles
|
||||
case "GUILD_ROLE_CREATE":
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Discord
|
||||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
|
||||
internal class GroupChannel : SnowflakeEntity, IGroupChannel
|
||||
{
|
||||
protected ConcurrentDictionary<ulong, IUser> _users;
|
||||
protected ConcurrentDictionary<ulong, GroupUser> _users;
|
||||
private string _iconId;
|
||||
|
||||
public override DiscordClient Discord { get; }
|
||||
@@ -25,11 +25,10 @@ namespace Discord
|
||||
public virtual IReadOnlyCollection<IMessage> CachedMessages => ImmutableArray.Create<IMessage>();
|
||||
public string IconUrl => API.CDN.GetChannelIconUrl(Id, _iconId);
|
||||
|
||||
public GroupChannel(DiscordClient discord, ConcurrentDictionary<ulong, IUser> recipients, Model model)
|
||||
public GroupChannel(DiscordClient discord, Model model)
|
||||
: base(model.Id)
|
||||
{
|
||||
Discord = discord;
|
||||
_users = recipients;
|
||||
|
||||
Update(model, UpdateSource.Creation);
|
||||
}
|
||||
@@ -46,13 +45,13 @@ namespace Discord
|
||||
UpdateUsers(model.Recipients.Value, source);
|
||||
}
|
||||
|
||||
protected virtual void UpdateUsers(API.User[] models, UpdateSource source)
|
||||
internal virtual void UpdateUsers(API.User[] models, UpdateSource source)
|
||||
{
|
||||
if (!IsAttached)
|
||||
{
|
||||
var users = new ConcurrentDictionary<ulong, IUser>(1, (int)(models.Length * 1.05));
|
||||
var users = new ConcurrentDictionary<ulong, GroupUser>(1, (int)(models.Length * 1.05));
|
||||
for (int i = 0; i < models.Length; i++)
|
||||
users[models[i].Id] = new User(models[i]);
|
||||
users[models[i].Id] = new GroupUser(this, new User(models[i]));
|
||||
_users = users;
|
||||
}
|
||||
}
|
||||
@@ -69,9 +68,13 @@ namespace Discord
|
||||
await Discord.ApiClient.DeleteChannelAsync(Id).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task AddUserAsync(IUser user)
|
||||
{
|
||||
await Discord.ApiClient.AddGroupRecipientAsync(Id, user.Id).ConfigureAwait(false);
|
||||
}
|
||||
public async Task<IUser> GetUserAsync(ulong id)
|
||||
{
|
||||
IUser user;
|
||||
GroupUser user;
|
||||
if (_users.TryGetValue(id, out user))
|
||||
return user;
|
||||
var currentUser = await Discord.GetCurrentUserAsync().ConfigureAwait(false);
|
||||
@@ -82,7 +85,7 @@ namespace Discord
|
||||
public async Task<IReadOnlyCollection<IUser>> GetUsersAsync()
|
||||
{
|
||||
var currentUser = await Discord.GetCurrentUserAsync().ConfigureAwait(false);
|
||||
return _users.Select(x => x.Value).Concat(ImmutableArray.Create(currentUser)).ToReadOnlyCollection(_users);
|
||||
return _users.Select(x => x.Value).Concat<IUser>(ImmutableArray.Create(currentUser)).ToReadOnlyCollection(_users);
|
||||
}
|
||||
|
||||
public async Task<IMessage> SendMessageAsync(string text, bool isTTS)
|
||||
|
||||
@@ -4,6 +4,9 @@ namespace Discord
|
||||
{
|
||||
public interface IGroupChannel : IMessageChannel, IPrivateChannel
|
||||
{
|
||||
/// <summary> Adds a user to this group. </summary>
|
||||
Task AddUserAsync(IUser user);
|
||||
|
||||
/// <summary> Leaves this group. </summary>
|
||||
Task LeaveAsync();
|
||||
}
|
||||
|
||||
47
src/Discord.Net/Entities/Users/GroupUser.cs
Normal file
47
src/Discord.Net/Entities/Users/GroupUser.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using Discord.API.Rest;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
internal class GroupUser : IGroupUser
|
||||
{
|
||||
public GroupChannel Channel { get; private set; }
|
||||
public User User { get; private set; }
|
||||
|
||||
public ulong Id => User.Id;
|
||||
public string AvatarUrl => User.AvatarUrl;
|
||||
public DateTimeOffset CreatedAt => User.CreatedAt;
|
||||
public string Discriminator => User.Discriminator;
|
||||
public ushort DiscriminatorValue => User.DiscriminatorValue;
|
||||
public bool IsAttached => User.IsAttached;
|
||||
public bool IsBot => User.IsBot;
|
||||
public string Mention => User.Mention;
|
||||
public string NicknameMention => User.NicknameMention;
|
||||
public string Username => User.Username;
|
||||
|
||||
public virtual UserStatus Status => UserStatus.Unknown;
|
||||
public virtual Game Game => null;
|
||||
|
||||
public DiscordClient Discord => Channel.Discord;
|
||||
|
||||
public GroupUser(GroupChannel channel, User user)
|
||||
{
|
||||
Channel = channel;
|
||||
User = user;
|
||||
}
|
||||
|
||||
public async Task KickAsync()
|
||||
{
|
||||
await Discord.ApiClient.RemoveGroupRecipientAsync(Channel.Id, Id).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task<IDMChannel> CreateDMChannelAsync()
|
||||
{
|
||||
var args = new CreateDMChannelParams { Recipient = this };
|
||||
var model = await Discord.ApiClient.CreateDMChannelAsync(args).ConfigureAwait(false);
|
||||
|
||||
return new DMChannel(Discord, new User(model.Recipients.Value[0]), model);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,6 @@ using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Model = Discord.API.GuildMember;
|
||||
using PresenceModel = Discord.API.Presence;
|
||||
using VoiceStateModel = Discord.API.VoiceState;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
|
||||
13
src/Discord.Net/Entities/Users/IGroupUser.cs
Normal file
13
src/Discord.Net/Entities/Users/IGroupUser.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
public interface IGroupUser : IUser
|
||||
{
|
||||
/// <summary> Kicks this user from this group. </summary>
|
||||
Task KickAsync();
|
||||
|
||||
/// <summary> Returns a private message channel to this user, creating one if it does not already exist. </summary>
|
||||
Task<IDMChannel> CreateDMChannelAsync();
|
||||
}
|
||||
}
|
||||
@@ -11,11 +11,11 @@ namespace Discord
|
||||
private readonly MessageManager _messages;
|
||||
|
||||
public new DiscordSocketClient Discord => base.Discord as DiscordSocketClient;
|
||||
public new CachedPrivateUser Recipient => base.Recipient as CachedPrivateUser;
|
||||
public new CachedDMUser Recipient => base.Recipient as CachedDMUser;
|
||||
public IReadOnlyCollection<ICachedUser> Members => ImmutableArray.Create<ICachedUser>(Discord.CurrentUser, Recipient);
|
||||
IReadOnlyCollection<CachedPrivateUser> ICachedPrivateChannel.Recipients => ImmutableArray.Create(Recipient);
|
||||
IReadOnlyCollection<CachedDMUser> ICachedPrivateChannel.Recipients => ImmutableArray.Create(Recipient);
|
||||
|
||||
public CachedDMChannel(DiscordSocketClient discord, CachedPrivateUser recipient, Model model)
|
||||
public CachedDMChannel(DiscordSocketClient discord, CachedDMUser recipient, Model model)
|
||||
: base(discord, recipient, model)
|
||||
{
|
||||
if (Discord.MessageCacheSize > 0)
|
||||
|
||||
@@ -5,7 +5,7 @@ using PresenceModel = Discord.API.Presence;
|
||||
namespace Discord
|
||||
{
|
||||
[DebuggerDisplay("{DebuggerDisplay,nq}")]
|
||||
internal class CachedPrivateUser : ICachedUser
|
||||
internal class CachedDMUser : ICachedUser
|
||||
{
|
||||
public CachedGlobalUser User { get; }
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace Discord
|
||||
public string NicknameMention => User.NicknameMention;
|
||||
public string Username => User.Username;
|
||||
|
||||
public CachedPrivateUser(CachedGlobalUser user)
|
||||
public CachedDMUser(CachedGlobalUser user)
|
||||
{
|
||||
User = user;
|
||||
}
|
||||
@@ -36,7 +36,7 @@ namespace Discord
|
||||
User.Update(model, source);
|
||||
}
|
||||
|
||||
public CachedPrivateUser Clone() => MemberwiseClone() as CachedPrivateUser;
|
||||
public CachedDMUser Clone() => MemberwiseClone() as CachedDMUser;
|
||||
ICachedUser ICachedUser.Clone() => Clone();
|
||||
|
||||
public override string ToString() => $"{Username}#{Discriminator}";
|
||||
@@ -6,6 +6,7 @@ using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using MessageModel = Discord.API.Message;
|
||||
using Model = Discord.API.Channel;
|
||||
using UserModel = Discord.API.User;
|
||||
using VoiceStateModel = Discord.API.VoiceState;
|
||||
|
||||
namespace Discord
|
||||
@@ -17,11 +18,11 @@ namespace Discord
|
||||
|
||||
public new DiscordSocketClient Discord => base.Discord as DiscordSocketClient;
|
||||
public IReadOnlyCollection<ICachedUser> Members
|
||||
=> _users.Select(x => x.Value).Concat(ImmutableArray.Create(Discord.CurrentUser)).Cast<ICachedUser>().ToReadOnlyCollection(() => _users.Count + 1);
|
||||
public new IReadOnlyCollection<CachedPrivateUser> Recipients => _users.Cast<CachedPrivateUser>().ToReadOnlyCollection(_users);
|
||||
=> _users.Select(x => x.Value as ICachedUser).Concat(ImmutableArray.Create(Discord.CurrentUser)).ToReadOnlyCollection(() => _users.Count + 1);
|
||||
public new IReadOnlyCollection<CachedDMUser> Recipients => _users.Cast<CachedDMUser>().ToReadOnlyCollection(_users);
|
||||
|
||||
public CachedGroupChannel(DiscordSocketClient discord, ConcurrentDictionary<ulong, IUser> recipients, Model model)
|
||||
: base(discord, recipients, model)
|
||||
public CachedGroupChannel(DiscordSocketClient discord, Model model)
|
||||
: base(discord, model)
|
||||
{
|
||||
if (Discord.MessageCacheSize > 0)
|
||||
_messages = new MessageCache(Discord, this);
|
||||
@@ -36,23 +37,46 @@ namespace Discord
|
||||
base.Update(model, source);
|
||||
}
|
||||
|
||||
protected override void UpdateUsers(API.User[] models, UpdateSource source)
|
||||
internal override void UpdateUsers(UserModel[] models, UpdateSource source)
|
||||
{
|
||||
var users = new ConcurrentDictionary<ulong, IUser>(1, models.Length);
|
||||
var users = new ConcurrentDictionary<ulong, GroupUser>(1, models.Length);
|
||||
for (int i = 0; i < models.Length; i++)
|
||||
users[models[i].Id] = new CachedPrivateUser(Discord.GetOrAddUser(models[i], Discord.DataStore));
|
||||
{
|
||||
var globalUser = Discord.GetOrAddUser(models[i], Discord.DataStore);
|
||||
users[models[i].Id] = new CachedGroupUser(this, globalUser);
|
||||
}
|
||||
_users = users;
|
||||
}
|
||||
|
||||
public CachedGroupUser AddUser(UserModel model, DataStore dataStore)
|
||||
{
|
||||
GroupUser user;
|
||||
if (_users.TryGetValue(model.Id, out user))
|
||||
return user as CachedGroupUser;
|
||||
else
|
||||
{
|
||||
var globalUser = Discord.GetOrAddUser(model, dataStore);
|
||||
var privateUser = new CachedGroupUser(this, globalUser);
|
||||
_users[privateUser.Id] = privateUser;
|
||||
return privateUser;
|
||||
}
|
||||
}
|
||||
public ICachedUser GetUser(ulong id)
|
||||
{
|
||||
IUser user;
|
||||
GroupUser user;
|
||||
if (_users.TryGetValue(id, out user))
|
||||
return user as ICachedUser;
|
||||
return user as CachedGroupUser;
|
||||
if (id == Discord.CurrentUser.Id)
|
||||
return Discord.CurrentUser;
|
||||
return null;
|
||||
}
|
||||
public CachedGroupUser RemoveUser(ulong id)
|
||||
{
|
||||
GroupUser user;
|
||||
if (_users.TryRemove(id, out user))
|
||||
return user as CachedGroupUser;
|
||||
return null;
|
||||
}
|
||||
|
||||
public VoiceState AddOrUpdateVoiceState(VoiceStateModel model, DataStore dataStore, ConcurrentDictionary<ulong, VoiceState> voiceStates = null)
|
||||
{
|
||||
@@ -106,15 +130,7 @@ namespace Discord
|
||||
public CachedDMChannel Clone() => MemberwiseClone() as CachedDMChannel;
|
||||
|
||||
IMessage IMessageChannel.GetCachedMessage(ulong id) => GetMessage(id);
|
||||
ICachedUser ICachedMessageChannel.GetUser(ulong id, bool skipCheck)
|
||||
{
|
||||
IUser user;
|
||||
if (_users.TryGetValue(id, out user))
|
||||
return user as ICachedUser;
|
||||
if (id == Discord.CurrentUser.Id)
|
||||
return Discord.CurrentUser;
|
||||
return null;
|
||||
}
|
||||
ICachedUser ICachedMessageChannel.GetUser(ulong id, bool skipCheck) => GetUser(id);
|
||||
ICachedChannel ICachedChannel.Clone() => Clone();
|
||||
}
|
||||
}
|
||||
|
||||
33
src/Discord.Net/Entities/WebSocket/CachedGroupUser.cs
Normal file
33
src/Discord.Net/Entities/WebSocket/CachedGroupUser.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
[DebuggerDisplay("{DebuggerDisplay,nq}")]
|
||||
internal class CachedGroupUser : GroupUser, ICachedUser
|
||||
{
|
||||
public new DiscordSocketClient Discord => base.Discord as DiscordSocketClient;
|
||||
public new CachedGroupChannel Channel => base.Channel as CachedGroupChannel;
|
||||
public new CachedGlobalUser User => base.User as CachedGlobalUser;
|
||||
public Presence Presence => User.Presence; //{ get; private set; }
|
||||
|
||||
public override Game Game => Presence.Game;
|
||||
public override UserStatus Status => Presence.Status;
|
||||
|
||||
public VoiceState? VoiceState => Channel.GetVoiceState(Id);
|
||||
public bool IsSelfDeafened => VoiceState?.IsSelfDeafened ?? false;
|
||||
public bool IsSelfMuted => VoiceState?.IsSelfMuted ?? false;
|
||||
public bool IsSuppressed => VoiceState?.IsSuppressed ?? false;
|
||||
public CachedVoiceChannel VoiceChannel => VoiceState?.VoiceChannel;
|
||||
|
||||
public CachedGroupUser(CachedGroupChannel channel, CachedGlobalUser user)
|
||||
: base(channel, user)
|
||||
{
|
||||
}
|
||||
|
||||
public CachedGroupUser Clone() => MemberwiseClone() as CachedGroupUser;
|
||||
ICachedUser ICachedUser.Clone() => Clone();
|
||||
|
||||
public override string ToString() => $"{Username}#{Discriminator}";
|
||||
private string DebuggerDisplay => $"{Username}#{Discriminator} ({Id})";
|
||||
}
|
||||
}
|
||||
@@ -208,7 +208,6 @@ namespace Discord
|
||||
var user = Discord.GetOrAddUser(model.User, dataStore);
|
||||
member = new CachedGuildUser(this, user, model);
|
||||
members[user.Id] = member;
|
||||
user.AddRef();
|
||||
DownloadedMemberCount++;
|
||||
}
|
||||
return member;
|
||||
|
||||
@@ -4,6 +4,6 @@ namespace Discord
|
||||
{
|
||||
internal interface ICachedPrivateChannel : ICachedChannel, IPrivateChannel
|
||||
{
|
||||
new IReadOnlyCollection<CachedPrivateUser> Recipients { get; }
|
||||
new IReadOnlyCollection<CachedDMUser> Recipients { get; }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user