Added voice states to group channels
This commit is contained in:
@@ -167,12 +167,12 @@ namespace Discord
|
|||||||
remove { _userPresenceUpdatedEvent.Remove(value); }
|
remove { _userPresenceUpdatedEvent.Remove(value); }
|
||||||
}
|
}
|
||||||
private readonly AsyncEvent<Func<IGuildUser, IPresence, IPresence, Task>> _userPresenceUpdatedEvent = new AsyncEvent<Func<IGuildUser, IPresence, IPresence, Task>>();
|
private readonly AsyncEvent<Func<IGuildUser, IPresence, IPresence, Task>> _userPresenceUpdatedEvent = new AsyncEvent<Func<IGuildUser, IPresence, IPresence, Task>>();
|
||||||
public event Func<IGuildUser, IVoiceState, IVoiceState, Task> UserVoiceStateUpdated
|
public event Func<IUser, IVoiceState, IVoiceState, Task> UserVoiceStateUpdated
|
||||||
{
|
{
|
||||||
add { _userVoiceStateUpdatedEvent.Add(value); }
|
add { _userVoiceStateUpdatedEvent.Add(value); }
|
||||||
remove { _userVoiceStateUpdatedEvent.Remove(value); }
|
remove { _userVoiceStateUpdatedEvent.Remove(value); }
|
||||||
}
|
}
|
||||||
private readonly AsyncEvent<Func<IGuildUser, IVoiceState, IVoiceState, Task>> _userVoiceStateUpdatedEvent = new AsyncEvent<Func<IGuildUser, IVoiceState, IVoiceState, Task>>();
|
private readonly AsyncEvent<Func<IUser, IVoiceState, IVoiceState, Task>> _userVoiceStateUpdatedEvent = new AsyncEvent<Func<IUser, IVoiceState, IVoiceState, Task>>();
|
||||||
public event Func<ISelfUser, ISelfUser, Task> CurrentUserUpdated
|
public event Func<ISelfUser, ISelfUser, Task> CurrentUserUpdated
|
||||||
{
|
{
|
||||||
add { _selfUpdatedEvent.Add(value); }
|
add { _selfUpdatedEvent.Add(value); }
|
||||||
|
|||||||
@@ -1280,39 +1280,66 @@ namespace Discord
|
|||||||
var data = (payload as JToken).ToObject<API.VoiceState>(_serializer);
|
var data = (payload as JToken).ToObject<API.VoiceState>(_serializer);
|
||||||
if (data.GuildId.HasValue)
|
if (data.GuildId.HasValue)
|
||||||
{
|
{
|
||||||
var guild = DataStore.GetGuild(data.GuildId.Value);
|
ICachedUser user;
|
||||||
if (guild != null)
|
VoiceState before, after;
|
||||||
|
if (data.GuildId != null)
|
||||||
{
|
{
|
||||||
if (!guild.IsSynced)
|
var guild = DataStore.GetGuild(data.GuildId.Value);
|
||||||
|
if (guild != null)
|
||||||
{
|
{
|
||||||
await _gatewayLogger.DebugAsync("Ignored VOICE_STATE_UPDATE, guild is not synced yet.").ConfigureAwait(false);
|
if (!guild.IsSynced)
|
||||||
return;
|
{
|
||||||
}
|
await _gatewayLogger.DebugAsync("Ignored VOICE_STATE_UPDATE, guild is not synced yet.").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
VoiceState before, after;
|
if (data.ChannelId != null)
|
||||||
if (data.ChannelId != null)
|
{
|
||||||
{
|
before = guild.GetVoiceState(data.UserId)?.Clone() ?? new VoiceState(null, null, false, false, false);
|
||||||
before = guild.GetVoiceState(data.UserId)?.Clone() ?? new VoiceState(null, null, false, false, false);
|
after = guild.AddOrUpdateVoiceState(data, DataStore);
|
||||||
after = guild.AddOrUpdateVoiceState(data, DataStore);
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
before = guild.RemoveVoiceState(data.UserId) ?? new VoiceState(null, null, false, false, false);
|
||||||
|
after = new VoiceState(null, data);
|
||||||
|
}
|
||||||
|
user = guild.GetUser(data.UserId);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
before = guild.RemoveVoiceState(data.UserId) ?? new VoiceState(null, null, false, false, false);
|
await _gatewayLogger.WarningAsync("VOICE_STATE_UPDATE referenced an unknown guild.").ConfigureAwait(false);
|
||||||
after = new VoiceState(null, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
var user = guild.GetUser(data.UserId);
|
|
||||||
if (user != null)
|
|
||||||
await _userVoiceStateUpdatedEvent.InvokeAsync(user, before, after).ConfigureAwait(false);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
await _gatewayLogger.WarningAsync("VOICE_STATE_UPDATE referenced an unknown user.").ConfigureAwait(false);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await _gatewayLogger.WarningAsync("VOICE_STATE_UPDATE referenced an unknown guild.").ConfigureAwait(false);
|
var groupChannel = DataStore.GetChannel(data.ChannelId.Value) as CachedGroupChannel;
|
||||||
|
if (groupChannel != null)
|
||||||
|
{
|
||||||
|
if (data.ChannelId != null)
|
||||||
|
{
|
||||||
|
before = groupChannel.GetVoiceState(data.UserId)?.Clone() ?? new VoiceState(null, null, false, false, false);
|
||||||
|
after = groupChannel.AddOrUpdateVoiceState(data, DataStore);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
before = groupChannel.RemoveVoiceState(data.UserId) ?? new VoiceState(null, null, false, false, false);
|
||||||
|
after = new VoiceState(null, data);
|
||||||
|
}
|
||||||
|
user = groupChannel.GetUser(data.UserId);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await _gatewayLogger.WarningAsync("VOICE_STATE_UPDATE referenced an unknown channel.").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user != null)
|
||||||
|
await _userVoiceStateUpdatedEvent.InvokeAsync(user, before, after).ConfigureAwait(false);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await _gatewayLogger.WarningAsync("VOICE_STATE_UPDATE referenced an unknown user.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,10 +30,10 @@ namespace Discord
|
|||||||
{
|
{
|
||||||
Discord = discord;
|
Discord = discord;
|
||||||
_users = recipients;
|
_users = recipients;
|
||||||
|
|
||||||
Update(model, UpdateSource.Creation);
|
Update(model, UpdateSource.Creation);
|
||||||
}
|
}
|
||||||
public void Update(Model model, UpdateSource source)
|
public virtual void Update(Model model, UpdateSource source)
|
||||||
{
|
{
|
||||||
if (source == UpdateSource.Rest && IsAttached) return;
|
if (source == UpdateSource.Rest && IsAttached) return;
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ namespace Discord
|
|||||||
Name = model.Name.Value;
|
Name = model.Name.Value;
|
||||||
if (model.Icon.IsSpecified)
|
if (model.Icon.IsSpecified)
|
||||||
_iconId = model.Icon.Value;
|
_iconId = model.Icon.Value;
|
||||||
|
|
||||||
if (source != UpdateSource.Creation && model.Recipients.IsSpecified)
|
if (source != UpdateSource.Creation && model.Recipients.IsSpecified)
|
||||||
UpdateUsers(model.Recipients.Value, source);
|
UpdateUsers(model.Recipients.Value, source);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,16 +6,18 @@ using System.Linq;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MessageModel = Discord.API.Message;
|
using MessageModel = Discord.API.Message;
|
||||||
using Model = Discord.API.Channel;
|
using Model = Discord.API.Channel;
|
||||||
|
using VoiceStateModel = Discord.API.VoiceState;
|
||||||
|
|
||||||
namespace Discord
|
namespace Discord
|
||||||
{
|
{
|
||||||
internal class CachedGroupChannel : GroupChannel, IGroupChannel, ICachedChannel, ICachedMessageChannel, ICachedPrivateChannel
|
internal class CachedGroupChannel : GroupChannel, IGroupChannel, ICachedChannel, ICachedMessageChannel, ICachedPrivateChannel
|
||||||
{
|
{
|
||||||
private readonly MessageManager _messages;
|
private readonly MessageManager _messages;
|
||||||
|
private ConcurrentDictionary<ulong, VoiceState> _voiceStates;
|
||||||
|
|
||||||
public new DiscordSocketClient Discord => base.Discord as DiscordSocketClient;
|
public new DiscordSocketClient Discord => base.Discord as DiscordSocketClient;
|
||||||
public IReadOnlyCollection<ICachedUser> Members
|
public IReadOnlyCollection<ICachedUser> Members
|
||||||
=> _users.Select(x => x.Value).Concat(ImmutableArray.Create(Discord.CurrentUser)).Cast<ICachedUser>().ToReadOnlyCollection(_users, 1);
|
=> _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);
|
public new IReadOnlyCollection<CachedPrivateUser> Recipients => _users.Cast<CachedPrivateUser>().ToReadOnlyCollection(_users);
|
||||||
|
|
||||||
public CachedGroupChannel(DiscordSocketClient discord, ConcurrentDictionary<ulong, IUser> recipients, Model model)
|
public CachedGroupChannel(DiscordSocketClient discord, ConcurrentDictionary<ulong, IUser> recipients, Model model)
|
||||||
@@ -25,6 +27,13 @@ namespace Discord
|
|||||||
_messages = new MessageCache(Discord, this);
|
_messages = new MessageCache(Discord, this);
|
||||||
else
|
else
|
||||||
_messages = new MessageManager(Discord, this);
|
_messages = new MessageManager(Discord, this);
|
||||||
|
_voiceStates = new ConcurrentDictionary<ulong, VoiceState>(1, 5);
|
||||||
|
}
|
||||||
|
public override void Update(Model model, UpdateSource source)
|
||||||
|
{
|
||||||
|
if (source == UpdateSource.Rest && IsAttached) return;
|
||||||
|
|
||||||
|
base.Update(model, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void UpdateUsers(API.User[] models, UpdateSource source)
|
protected override void UpdateUsers(API.User[] models, UpdateSource source)
|
||||||
@@ -35,6 +44,38 @@ namespace Discord
|
|||||||
_users = users;
|
_users = users;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ICachedUser GetUser(ulong id)
|
||||||
|
{
|
||||||
|
IUser user;
|
||||||
|
if (_users.TryGetValue(id, out user))
|
||||||
|
return user as ICachedUser;
|
||||||
|
if (id == Discord.CurrentUser.Id)
|
||||||
|
return Discord.CurrentUser;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VoiceState AddOrUpdateVoiceState(VoiceStateModel model, DataStore dataStore, ConcurrentDictionary<ulong, VoiceState> voiceStates = null)
|
||||||
|
{
|
||||||
|
var voiceChannel = dataStore.GetChannel(model.ChannelId.Value) as CachedVoiceChannel;
|
||||||
|
var voiceState = new VoiceState(voiceChannel, model);
|
||||||
|
(voiceStates ?? _voiceStates)[model.UserId] = voiceState;
|
||||||
|
return voiceState;
|
||||||
|
}
|
||||||
|
public VoiceState? GetVoiceState(ulong id)
|
||||||
|
{
|
||||||
|
VoiceState voiceState;
|
||||||
|
if (_voiceStates.TryGetValue(id, out voiceState))
|
||||||
|
return voiceState;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
public VoiceState? RemoveVoiceState(ulong id)
|
||||||
|
{
|
||||||
|
VoiceState voiceState;
|
||||||
|
if (_voiceStates.TryRemove(id, out voiceState))
|
||||||
|
return voiceState;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public override async Task<IMessage> GetMessageAsync(ulong id)
|
public override async Task<IMessage> GetMessageAsync(ulong id)
|
||||||
{
|
{
|
||||||
return await _messages.DownloadAsync(id).ConfigureAwait(false);
|
return await _messages.DownloadAsync(id).ConfigureAwait(false);
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ namespace Discord.Extensions
|
|||||||
{
|
{
|
||||||
public static IReadOnlyCollection<TValue> ToReadOnlyCollection<TKey, TValue>(this IReadOnlyDictionary<TKey, TValue> source)
|
public static IReadOnlyCollection<TValue> ToReadOnlyCollection<TKey, TValue>(this IReadOnlyDictionary<TKey, TValue> source)
|
||||||
=> new ConcurrentDictionaryWrapper<TValue>(source.Select(x => x.Value), () => source.Count);
|
=> new ConcurrentDictionaryWrapper<TValue>(source.Select(x => x.Value), () => source.Count);
|
||||||
public static IReadOnlyCollection<TValue> ToReadOnlyCollection<TValue, TSource>(this IEnumerable<TValue> query, IReadOnlyCollection<TSource> source, int countOffset = 0)
|
public static IReadOnlyCollection<TValue> ToReadOnlyCollection<TValue, TSource>(this IEnumerable<TValue> query, IReadOnlyCollection<TSource> source)
|
||||||
=> new ConcurrentDictionaryWrapper<TValue>(query, () => source.Count + countOffset);
|
=> new ConcurrentDictionaryWrapper<TValue>(query, () => source.Count);
|
||||||
public static IReadOnlyCollection<TValue> ToReadOnlyCollection<TValue>(this IEnumerable<TValue> query, Func<int> countFunc)
|
public static IReadOnlyCollection<TValue> ToReadOnlyCollection<TValue>(this IEnumerable<TValue> query, Func<int> countFunc)
|
||||||
=> new ConcurrentDictionaryWrapper<TValue>(query, countFunc);
|
=> new ConcurrentDictionaryWrapper<TValue>(query, countFunc);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user