Updated to use the v2 API. Added Embeds, Channel Permissions and Voice State parsing. Moved Presence from User to Member.
This commit is contained in:
@@ -97,6 +97,9 @@
|
||||
<Compile Include="..\Discord.Net\Message.cs">
|
||||
<Link>Message.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Discord.Net\PackedPermissions.cs">
|
||||
<Link>PackedPermissions.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Discord.Net\Regions.cs">
|
||||
<Link>Regions.cs</Link>
|
||||
</Compile>
|
||||
|
||||
@@ -51,13 +51,52 @@ namespace Discord.API.Models
|
||||
[JsonProperty(PropertyName = "verified")]
|
||||
public bool IsVerified;
|
||||
}
|
||||
internal class PresenceUserInfo : UserReference
|
||||
internal class MemberInfo
|
||||
{
|
||||
[JsonProperty(PropertyName = "user_id")]
|
||||
public string UserId;
|
||||
[JsonProperty(PropertyName = "user")]
|
||||
public UserReference User;
|
||||
[JsonProperty(PropertyName = "guild_id")]
|
||||
public string ServerId;
|
||||
}
|
||||
internal class PresenceMemberInfo : MemberInfo
|
||||
{
|
||||
[JsonProperty(PropertyName = "game_id")]
|
||||
public string GameId;
|
||||
[JsonProperty(PropertyName = "status")]
|
||||
public string Status;
|
||||
}
|
||||
internal class VoiceMemberInfo : MemberInfo
|
||||
{
|
||||
[JsonProperty(PropertyName = "channel_id")]
|
||||
public string ChannelId;
|
||||
[JsonProperty(PropertyName = "suppress")]
|
||||
public bool IsSuppressed;
|
||||
[JsonProperty(PropertyName = "session_id")]
|
||||
public string SessionId;
|
||||
[JsonProperty(PropertyName = "self_mute")]
|
||||
public bool IsSelfMuted;
|
||||
[JsonProperty(PropertyName = "self_deaf")]
|
||||
public bool IsSelfDeafened;
|
||||
[JsonProperty(PropertyName = "mute")]
|
||||
public bool IsMuted;
|
||||
[JsonProperty(PropertyName = "deaf")]
|
||||
public bool IsDeafened;
|
||||
[JsonProperty(PropertyName = "token")]
|
||||
public string Token;
|
||||
}
|
||||
internal class RoleMemberInfo : MemberInfo
|
||||
{
|
||||
[JsonProperty(PropertyName = "mute")]
|
||||
public bool IsMuted;
|
||||
[JsonProperty(PropertyName = "deaf")]
|
||||
public bool IsDeafened;
|
||||
[JsonProperty(PropertyName = "joined_at")]
|
||||
public DateTime? JoinedAt;
|
||||
[JsonProperty(PropertyName = "roles")]
|
||||
public string[] Roles;
|
||||
}
|
||||
|
||||
//Channels
|
||||
internal class ChannelReference
|
||||
@@ -73,12 +112,26 @@ namespace Discord.API.Models
|
||||
}
|
||||
internal class ChannelInfo : ChannelReference
|
||||
{
|
||||
public sealed class PermissionOverwrite
|
||||
{
|
||||
[JsonProperty(PropertyName = "type")]
|
||||
public string Type;
|
||||
[JsonProperty(PropertyName = "id")]
|
||||
public string Id;
|
||||
[JsonProperty(PropertyName = "deny")]
|
||||
public uint Deny;
|
||||
[JsonProperty(PropertyName = "allow")]
|
||||
public uint Allow;
|
||||
}
|
||||
|
||||
[JsonProperty(PropertyName = "last_message_id")]
|
||||
public string LastMessageId;
|
||||
[JsonProperty(PropertyName = "is_private")]
|
||||
public bool IsPrivate;
|
||||
[JsonProperty(PropertyName = "position")]
|
||||
public int Position;
|
||||
[JsonProperty(PropertyName = "permission_overwrites")]
|
||||
public object[] PermissionOverwrites;
|
||||
public PermissionOverwrite[] PermissionOverwrites;
|
||||
[JsonProperty(PropertyName = "recipient")]
|
||||
public UserReference Recipient;
|
||||
}
|
||||
@@ -114,28 +167,14 @@ namespace Discord.API.Models
|
||||
}
|
||||
internal class ExtendedServerInfo : ServerInfo
|
||||
{
|
||||
public class Membership
|
||||
{
|
||||
[JsonProperty(PropertyName = "roles")]
|
||||
public string[] Roles;
|
||||
[JsonProperty(PropertyName = "mute")]
|
||||
public bool IsMuted;
|
||||
[JsonProperty(PropertyName = "deaf")]
|
||||
public bool IsDeaf;
|
||||
[JsonProperty(PropertyName = "joined_at")]
|
||||
public DateTime JoinedAt;
|
||||
[JsonProperty(PropertyName = "user")]
|
||||
public UserReference User;
|
||||
}
|
||||
|
||||
[JsonProperty(PropertyName = "channels")]
|
||||
public ChannelInfo[] Channels;
|
||||
[JsonProperty(PropertyName = "members")]
|
||||
public Membership[] Members;
|
||||
[JsonProperty(PropertyName = "presence")]
|
||||
public object[] Presence;
|
||||
public RoleMemberInfo[] Members;
|
||||
[JsonProperty(PropertyName = "presences")]
|
||||
public PresenceMemberInfo[] Presences;
|
||||
[JsonProperty(PropertyName = "voice_states")]
|
||||
public object[] VoiceStates;
|
||||
public VoiceMemberInfo[] VoiceStates;
|
||||
}
|
||||
|
||||
//Messages
|
||||
@@ -150,7 +189,7 @@ namespace Discord.API.Models
|
||||
}
|
||||
internal class Message : MessageReference
|
||||
{
|
||||
public class Attachment
|
||||
public sealed class Attachment
|
||||
{
|
||||
[JsonProperty(PropertyName = "id")]
|
||||
public string Id;
|
||||
@@ -167,6 +206,40 @@ namespace Discord.API.Models
|
||||
[JsonProperty(PropertyName = "height")]
|
||||
public int Height;
|
||||
}
|
||||
public sealed class Embed
|
||||
{
|
||||
public sealed class ProviderInfo
|
||||
{
|
||||
[JsonProperty(PropertyName = "url")]
|
||||
public string Url;
|
||||
[JsonProperty(PropertyName = "name")]
|
||||
public string Name;
|
||||
}
|
||||
public sealed class ThumbnailInfo
|
||||
{
|
||||
[JsonProperty(PropertyName = "url")]
|
||||
public string Url;
|
||||
[JsonProperty(PropertyName = "proxy_url")]
|
||||
public string ProxyUrl;
|
||||
[JsonProperty(PropertyName = "width")]
|
||||
public int Width;
|
||||
[JsonProperty(PropertyName = "height")]
|
||||
public int Height;
|
||||
}
|
||||
|
||||
[JsonProperty(PropertyName = "url")]
|
||||
public string Url;
|
||||
[JsonProperty(PropertyName = "type")]
|
||||
public string Type;
|
||||
[JsonProperty(PropertyName = "title")]
|
||||
public string Title;
|
||||
[JsonProperty(PropertyName = "description")]
|
||||
public string Description;
|
||||
[JsonProperty(PropertyName = "provider")]
|
||||
public ProviderInfo Provider;
|
||||
[JsonProperty(PropertyName = "thumbnail")]
|
||||
public ThumbnailInfo Thumbnail;
|
||||
}
|
||||
|
||||
[JsonProperty(PropertyName = "tts")]
|
||||
public bool IsTextToSpeech;
|
||||
@@ -179,7 +252,7 @@ namespace Discord.API.Models
|
||||
[JsonProperty(PropertyName = "mentions")]
|
||||
public UserReference[] Mentions;
|
||||
[JsonProperty(PropertyName = "embeds")]
|
||||
public object[] Embeds; //TODO: Parse this
|
||||
public Embed[] Embeds; //TODO: Parse this
|
||||
[JsonProperty(PropertyName = "attachments")]
|
||||
public Attachment[] Attachments;
|
||||
[JsonProperty(PropertyName = "content")]
|
||||
|
||||
@@ -22,6 +22,8 @@ namespace Discord.API.Models
|
||||
{
|
||||
[JsonProperty(PropertyName = "token")]
|
||||
public string Token;
|
||||
[JsonProperty(PropertyName = "v")]
|
||||
public int Version = 2;
|
||||
[JsonProperty(PropertyName = "properties")]
|
||||
public Dictionary<string, string> Properties = new Dictionary<string, string>();
|
||||
}
|
||||
|
||||
@@ -11,12 +11,24 @@ namespace Discord.API.Models
|
||||
{
|
||||
public sealed class Ready
|
||||
{
|
||||
public sealed class ReadStateInfo
|
||||
{
|
||||
[JsonProperty(PropertyName = "id")]
|
||||
public string ChannelId;
|
||||
[JsonProperty(PropertyName = "mention_count")]
|
||||
public int MentionCount;
|
||||
[JsonProperty(PropertyName = "last_message_id")]
|
||||
public string LastMessageId;
|
||||
}
|
||||
|
||||
[JsonProperty(PropertyName = "v")]
|
||||
public int Version;
|
||||
[JsonProperty(PropertyName = "user")]
|
||||
public SelfUserInfo User;
|
||||
[JsonProperty(PropertyName = "session_id")]
|
||||
public string SessionId;
|
||||
[JsonProperty(PropertyName = "read_state")]
|
||||
public object[] ReadState;
|
||||
public ReadStateInfo[] ReadState;
|
||||
[JsonProperty(PropertyName = "guilds")]
|
||||
public ExtendedServerInfo[] Guilds;
|
||||
[JsonProperty(PropertyName = "private_channels")]
|
||||
@@ -36,32 +48,15 @@ namespace Discord.API.Models
|
||||
public sealed class ChannelUpdate : ChannelInfo { }
|
||||
|
||||
//Memberships
|
||||
public abstract class GuildMemberEvent
|
||||
{
|
||||
[JsonProperty(PropertyName = "user")]
|
||||
public UserReference User;
|
||||
[JsonProperty(PropertyName = "guild_id")]
|
||||
public string GuildId;
|
||||
}
|
||||
public sealed class GuildMemberAdd : GuildMemberEvent
|
||||
{
|
||||
[JsonProperty(PropertyName = "joined_at")]
|
||||
public DateTime JoinedAt;
|
||||
[JsonProperty(PropertyName = "roles")]
|
||||
public string[] Roles;
|
||||
}
|
||||
public sealed class GuildMemberUpdate : GuildMemberEvent
|
||||
{
|
||||
[JsonProperty(PropertyName = "roles")]
|
||||
public string[] Roles;
|
||||
}
|
||||
public sealed class GuildMemberRemove : GuildMemberEvent { }
|
||||
public sealed class GuildMemberAdd : RoleMemberInfo { }
|
||||
public sealed class GuildMemberUpdate : RoleMemberInfo { }
|
||||
public sealed class GuildMemberRemove : MemberInfo { }
|
||||
|
||||
//Roles
|
||||
public abstract class GuildRoleEvent
|
||||
{
|
||||
[JsonProperty(PropertyName = "guild_id")]
|
||||
public string GuildId;
|
||||
public string ServerId;
|
||||
}
|
||||
public sealed class GuildRoleCreateUpdate : GuildRoleEvent
|
||||
{
|
||||
@@ -78,7 +73,7 @@ namespace Discord.API.Models
|
||||
public abstract class GuildBanEvent
|
||||
{
|
||||
[JsonProperty(PropertyName = "guild_id")]
|
||||
public string GuildId;
|
||||
public string ServerId;
|
||||
}
|
||||
public sealed class GuildBanAddRemove : GuildBanEvent
|
||||
{
|
||||
@@ -93,28 +88,8 @@ namespace Discord.API.Models
|
||||
|
||||
//User
|
||||
public sealed class UserUpdate : SelfUserInfo { }
|
||||
public sealed class PresenceUpdate : PresenceUserInfo { }
|
||||
public sealed class VoiceStateUpdate
|
||||
{
|
||||
[JsonProperty(PropertyName = "user_id")]
|
||||
public string UserId;
|
||||
[JsonProperty(PropertyName = "guild_id")]
|
||||
public string GuildId;
|
||||
[JsonProperty(PropertyName = "channel_id")]
|
||||
public string ChannelId;
|
||||
[JsonProperty(PropertyName = "suppress")]
|
||||
public bool IsSuppressed;
|
||||
[JsonProperty(PropertyName = "session_id")]
|
||||
public string SessionId;
|
||||
[JsonProperty(PropertyName = "self_mute")]
|
||||
public bool IsSelfMuted;
|
||||
[JsonProperty(PropertyName = "self_deaf")]
|
||||
public bool IsSelfDeafened;
|
||||
[JsonProperty(PropertyName = "mute")]
|
||||
public bool IsMuted;
|
||||
[JsonProperty(PropertyName = "deaf")]
|
||||
public bool IsDeafened;
|
||||
}
|
||||
public sealed class PresenceUpdate : PresenceMemberInfo { }
|
||||
public sealed class VoiceStateUpdate : VoiceMemberInfo { }
|
||||
|
||||
//Chat
|
||||
public sealed class MessageCreate : Message { }
|
||||
|
||||
@@ -4,8 +4,16 @@ using System.Linq;
|
||||
|
||||
namespace Discord
|
||||
{
|
||||
public sealed class Channel
|
||||
public sealed class Channel
|
||||
{
|
||||
public sealed class PermissionOverwrite
|
||||
{
|
||||
public string Type { get; internal set; }
|
||||
public string Id { get; internal set; }
|
||||
public PackedPermissions Deny { get; internal set; }
|
||||
public PackedPermissions Allow { get; internal set; }
|
||||
}
|
||||
|
||||
private readonly DiscordClient _client;
|
||||
|
||||
/// <summary> Returns the unique identifier for this channel. </summary>
|
||||
@@ -15,8 +23,10 @@ namespace Discord
|
||||
/// <summary> Returns the name of this channel. </summary>
|
||||
public string Name { get { return !IsPrivate ? $"#{_name}" : $"@{Recipient.Name}"; } internal set { _name = value; } }
|
||||
|
||||
/// <summary> Returns the position of this channel in the channel list for this server. </summary>
|
||||
public int Position { get; internal set; }
|
||||
/// <summary> Returns false is this is a public chat and true if this is a private chat with another user (see Recipient). </summary>
|
||||
public bool IsPrivate { get; }
|
||||
public bool IsPrivate { get; }
|
||||
/// <summary> Returns the type of this channel (see ChannelTypes). </summary>
|
||||
public string Type { get; internal set; }
|
||||
|
||||
@@ -37,9 +47,8 @@ namespace Discord
|
||||
[JsonIgnore]
|
||||
public IEnumerable<Message> Messages => _client.Messages.Where(x => x.ChannelId == Id);
|
||||
|
||||
//TODO: Not Implemented
|
||||
/// <summary> Not implemented, stored for reference. </summary>
|
||||
public object[] PermissionOverwrites { get; internal set; }
|
||||
/// <summary> Returns a collection of all custom permissions used for this channel. </summary>
|
||||
public PermissionOverwrite[] PermissionOverwrites { get; internal set; }
|
||||
|
||||
internal Channel(string id, string serverId, DiscordClient client)
|
||||
{
|
||||
|
||||
@@ -187,19 +187,19 @@ namespace Discord
|
||||
}
|
||||
|
||||
public event EventHandler<MemberEventArgs> MemberAdded;
|
||||
private void RaiseMemberAdded(Membership membership, Server server)
|
||||
private void RaiseMemberAdded(Membership membership)
|
||||
{
|
||||
if (MemberAdded != null)
|
||||
MemberAdded(this, new MemberEventArgs(membership));
|
||||
}
|
||||
public event EventHandler<MemberEventArgs> MemberRemoved;
|
||||
private void RaiseMemberRemoved(Membership membership, Server server)
|
||||
private void RaiseMemberRemoved(Membership membership)
|
||||
{
|
||||
if (MemberRemoved != null)
|
||||
MemberRemoved(this, new MemberEventArgs(membership));
|
||||
}
|
||||
public event EventHandler<MemberEventArgs> MemberUpdated;
|
||||
private void RaiseMemberUpdated(Membership membership, Server server)
|
||||
private void RaiseMemberUpdated(Membership membership)
|
||||
{
|
||||
if (MemberUpdated != null)
|
||||
MemberUpdated(this, new MemberEventArgs(membership));
|
||||
@@ -217,11 +217,11 @@ namespace Discord
|
||||
}
|
||||
}
|
||||
|
||||
public event EventHandler<UserEventArgs> PresenceUpdated;
|
||||
private void RaisePresenceUpdated(User user)
|
||||
public event EventHandler<MemberEventArgs> PresenceUpdated;
|
||||
private void RaisePresenceUpdated(Membership member)
|
||||
{
|
||||
if (PresenceUpdated != null)
|
||||
PresenceUpdated(this, new UserEventArgs(user));
|
||||
PresenceUpdated(this, new MemberEventArgs(member));
|
||||
}
|
||||
public event EventHandler<MemberEventArgs> VoiceStateUpdated;
|
||||
private void RaiseVoiceStateUpdated(Membership member)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Discord.API;
|
||||
using Discord.API.Models;
|
||||
using Discord.Helpers;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
@@ -19,10 +20,13 @@ namespace Discord
|
||||
private ManualResetEventSlim _isStopping;
|
||||
private readonly Regex _userRegex, _channelRegex;
|
||||
private readonly MatchEvaluator _userRegexEvaluator, _channelRegexEvaluator;
|
||||
private readonly JsonSerializer _serializer;
|
||||
|
||||
/// <summary> Returns the User object for the current logged in user. </summary>
|
||||
public User User { get; private set; }
|
||||
/// <summary> Returns the id of the current logged in user. </summary>
|
||||
public string UserId { get; private set; }
|
||||
public string SessionId { get; private set; }
|
||||
|
||||
/// <summary> Returns a collection of all users the client can see across all servers. </summary>
|
||||
/// <remarks> This collection does not guarantee any ordering. </remarks>
|
||||
@@ -64,6 +68,12 @@ namespace Discord
|
||||
{
|
||||
_isStopping = new ManualResetEventSlim(false);
|
||||
|
||||
_serializer = new JsonSerializer();
|
||||
#if TEST_RESPONSES
|
||||
_serializer.CheckAdditionalContent = true;
|
||||
_serializer.MissingMemberHandling = MissingMemberHandling.Error;
|
||||
#endif
|
||||
|
||||
_userRegex = new Regex(@"<@\d+?>", RegexOptions.Compiled);
|
||||
_channelRegex = new Regex(@"<#\d+?>", RegexOptions.Compiled);
|
||||
_userRegexEvaluator = new MatchEvaluator(e =>
|
||||
@@ -90,11 +100,7 @@ namespace Discord
|
||||
(server, model) =>
|
||||
{
|
||||
server.Name = model.Name;
|
||||
if (!server.Channels.Any()) //A default channel always exists with the same id as the server.
|
||||
{
|
||||
var defaultChannel = new ChannelReference() { Id = server.DefaultChannelId, GuildId = server.Id };
|
||||
_channels.Update(defaultChannel.Id, defaultChannel.GuildId, defaultChannel);
|
||||
}
|
||||
_channels.Update(server.DefaultChannelId, server.Id, null);
|
||||
if (model is ExtendedServerInfo)
|
||||
{
|
||||
var extendedModel = model as ExtendedServerInfo;
|
||||
@@ -102,9 +108,7 @@ namespace Discord
|
||||
server.AFKTimeout = extendedModel.AFKTimeout;
|
||||
server.JoinedAt = extendedModel.JoinedAt ?? DateTime.MinValue;
|
||||
server.OwnerId = extendedModel.OwnerId;
|
||||
server.Presence = extendedModel.Presence;
|
||||
server.Region = extendedModel.Region;
|
||||
server.VoiceStates = extendedModel.VoiceStates;
|
||||
|
||||
foreach (var role in extendedModel.Roles)
|
||||
_roles.Update(role.Id, model.Id, role);
|
||||
@@ -113,11 +117,13 @@ namespace Discord
|
||||
foreach (var membership in extendedModel.Members)
|
||||
{
|
||||
_users.Update(membership.User.Id, membership.User);
|
||||
var newMember = new Membership(server.Id, membership.User.Id, membership.JoinedAt, this);
|
||||
newMember.Update(membership);
|
||||
server.AddMember(newMember);
|
||||
server.UpdateMember(membership);
|
||||
}
|
||||
}
|
||||
foreach (var membership in extendedModel.VoiceStates)
|
||||
server.UpdateMember(membership);
|
||||
foreach (var membership in extendedModel.Presences)
|
||||
server.UpdateMember(membership);
|
||||
}
|
||||
},
|
||||
server => { }
|
||||
);
|
||||
@@ -131,13 +137,27 @@ namespace Discord
|
||||
if (model is ChannelInfo)
|
||||
{
|
||||
var extendedModel = model as ChannelInfo;
|
||||
channel.PermissionOverwrites = extendedModel.PermissionOverwrites;
|
||||
channel.Position = extendedModel.Position;
|
||||
|
||||
if (extendedModel.IsPrivate)
|
||||
{
|
||||
var user = _users.Update(extendedModel.Recipient.Id, extendedModel.Recipient);
|
||||
channel.RecipientId = user.Id;
|
||||
channel.RecipientId = user.Id;
|
||||
user.PrivateChannelId = channel.Id;
|
||||
}
|
||||
|
||||
if (extendedModel.PermissionOverwrites != null)
|
||||
{
|
||||
channel.PermissionOverwrites = extendedModel.PermissionOverwrites.Select(x => new Channel.PermissionOverwrite
|
||||
{
|
||||
Type = x.Type,
|
||||
Id = x.Id,
|
||||
Deny = new PackedPermissions(x.Deny),
|
||||
Allow = new PackedPermissions(x.Allow)
|
||||
}).ToArray();
|
||||
}
|
||||
else
|
||||
channel.PermissionOverwrites = null;
|
||||
}
|
||||
},
|
||||
channel =>
|
||||
@@ -170,8 +190,41 @@ namespace Discord
|
||||
}).ToArray();
|
||||
}
|
||||
else
|
||||
extendedModel.Attachments = null;
|
||||
message.Embeds = extendedModel.Embeds;
|
||||
message.Attachments = new Message.Attachment[0];
|
||||
if (extendedModel.Embeds != null)
|
||||
{
|
||||
message.Embeds = extendedModel.Embeds.Select(x =>
|
||||
{
|
||||
var embed = new Message.Embed
|
||||
{
|
||||
Url = x.Url,
|
||||
Type = x.Type,
|
||||
Description = x.Description,
|
||||
Title = x.Title
|
||||
};
|
||||
if (x.Provider != null)
|
||||
{
|
||||
embed.Provider = new Message.EmbedProvider
|
||||
{
|
||||
Url = x.Provider.Url,
|
||||
Name = x.Provider.Name
|
||||
};
|
||||
}
|
||||
if (x.Thumbnail != null)
|
||||
{
|
||||
embed.Thumbnail = new Message.File
|
||||
{
|
||||
Url = x.Thumbnail.Url,
|
||||
ProxyUrl = x.Thumbnail.ProxyUrl,
|
||||
Width = x.Thumbnail.Width,
|
||||
Height = x.Thumbnail.Height
|
||||
};
|
||||
}
|
||||
return embed;
|
||||
}).ToArray();
|
||||
}
|
||||
else
|
||||
message.Embeds = new Message.Embed[0];
|
||||
message.IsMentioningEveryone = extendedModel.IsMentioningEveryone;
|
||||
message.IsTTS = extendedModel.IsTextToSpeech;
|
||||
message.MentionIds = extendedModel.Mentions?.Select(x => x.Id)?.ToArray() ?? new string[0];
|
||||
@@ -206,12 +259,6 @@ namespace Discord
|
||||
var extendedModel = model as SelfUserInfo;
|
||||
user.Email = extendedModel.Email;
|
||||
user.IsVerified = extendedModel.IsVerified;
|
||||
}
|
||||
if (model is PresenceUserInfo)
|
||||
{
|
||||
var extendedModel = model as PresenceUserInfo;
|
||||
user.GameId = extendedModel.GameId;
|
||||
user.Status = extendedModel.Status;
|
||||
}
|
||||
},
|
||||
user => { }
|
||||
@@ -246,101 +293,104 @@ namespace Discord
|
||||
//Global
|
||||
case "READY": //Resync
|
||||
{
|
||||
var data = e.Event.ToObject<WebSocketEvents.Ready>();
|
||||
var data = e.Event.ToObject<WebSocketEvents.Ready>(_serializer);
|
||||
|
||||
_servers.Clear();
|
||||
_channels.Clear();
|
||||
_users.Clear();
|
||||
|
||||
UserId = data.User.Id;
|
||||
SessionId = data.SessionId;
|
||||
User = _users.Update(data.User.Id, data.User);
|
||||
foreach (var server in data.Guilds)
|
||||
_servers.Update(server.Id, server);
|
||||
foreach (var channel in data.PrivateChannels)
|
||||
_channels.Update(channel.Id, null, channel);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
//Servers
|
||||
case "GUILD_CREATE":
|
||||
{
|
||||
var data = e.Event.ToObject<WebSocketEvents.GuildCreate>();
|
||||
var data = e.Event.ToObject<WebSocketEvents.GuildCreate>(_serializer);
|
||||
var server = _servers.Update(data.Id, data);
|
||||
RaiseServerCreated(server);
|
||||
try { RaiseServerCreated(server); } catch { }
|
||||
}
|
||||
break;
|
||||
case "GUILD_UPDATE":
|
||||
{
|
||||
var data = e.Event.ToObject<WebSocketEvents.GuildUpdate>();
|
||||
var data = e.Event.ToObject<WebSocketEvents.GuildUpdate>(_serializer);
|
||||
var server = _servers.Update(data.Id, data);
|
||||
RaiseServerUpdated(server);
|
||||
try { RaiseServerUpdated(server); } catch { }
|
||||
}
|
||||
break;
|
||||
case "GUILD_DELETE":
|
||||
{
|
||||
var data = e.Event.ToObject<WebSocketEvents.GuildDelete>();
|
||||
var data = e.Event.ToObject<WebSocketEvents.GuildDelete>(_serializer);
|
||||
var server = _servers.Remove(data.Id);
|
||||
if (server != null)
|
||||
RaiseServerDestroyed(server);
|
||||
try { RaiseServerDestroyed(server); } catch { }
|
||||
}
|
||||
break;
|
||||
|
||||
//Channels
|
||||
case "CHANNEL_CREATE":
|
||||
{
|
||||
var data = e.Event.ToObject<WebSocketEvents.ChannelCreate>();
|
||||
var data = e.Event.ToObject<WebSocketEvents.ChannelCreate>(_serializer);
|
||||
var channel = _channels.Update(data.Id, data.GuildId, data);
|
||||
RaiseChannelCreated(channel);
|
||||
try { RaiseChannelCreated(channel); } catch { }
|
||||
}
|
||||
break;
|
||||
case "CHANNEL_UPDATE":
|
||||
{
|
||||
var data = e.Event.ToObject<WebSocketEvents.ChannelUpdate>();
|
||||
var data = e.Event.ToObject<WebSocketEvents.ChannelUpdate>(_serializer);
|
||||
var channel = _channels.Update(data.Id, data.GuildId, data);
|
||||
RaiseChannelUpdated(channel);
|
||||
try { RaiseChannelUpdated(channel); } catch { }
|
||||
}
|
||||
break;
|
||||
case "CHANNEL_DELETE":
|
||||
{
|
||||
var data = e.Event.ToObject<WebSocketEvents.ChannelDelete>();
|
||||
var data = e.Event.ToObject<WebSocketEvents.ChannelDelete>(_serializer);
|
||||
var channel = _channels.Remove(data.Id);
|
||||
if (channel != null)
|
||||
RaiseChannelDestroyed(channel);
|
||||
try { RaiseChannelDestroyed(channel); } catch { }
|
||||
}
|
||||
break;
|
||||
|
||||
//Members
|
||||
case "GUILD_MEMBER_ADD":
|
||||
{
|
||||
var data = e.Event.ToObject<WebSocketEvents.GuildMemberAdd>();
|
||||
var data = e.Event.ToObject<WebSocketEvents.GuildMemberAdd>(_serializer);
|
||||
var user = _users.Update(data.User.Id, data.User);
|
||||
var server = _servers[data.GuildId];
|
||||
var membership = new Membership(server.Id, data.User.Id, data.JoinedAt, this) { RoleIds = data.Roles };
|
||||
server.AddMember(membership);
|
||||
RaiseMemberAdded(membership, server);
|
||||
var server = _servers[data.ServerId];
|
||||
if (server != null)
|
||||
{
|
||||
var member = server.UpdateMember(data);
|
||||
try { RaiseMemberAdded(member); } catch { }
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "GUILD_MEMBER_UPDATE":
|
||||
{
|
||||
var data = e.Event.ToObject<WebSocketEvents.GuildMemberUpdate>();
|
||||
var data = e.Event.ToObject<WebSocketEvents.GuildMemberUpdate>(_serializer);
|
||||
var user = _users.Update(data.User.Id, data.User);
|
||||
var server = _servers[data.GuildId];
|
||||
var membership = server.GetMember(data.User.Id);
|
||||
if (membership != null)
|
||||
membership.RoleIds = data.Roles;
|
||||
RaiseMemberUpdated(membership, server);
|
||||
var server = _servers[data.ServerId];
|
||||
if (server != null)
|
||||
{
|
||||
var member = server.UpdateMember(data);
|
||||
try { RaiseMemberUpdated(member); } catch { }
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "GUILD_MEMBER_REMOVE":
|
||||
{
|
||||
var data = e.Event.ToObject<WebSocketEvents.GuildMemberRemove>();
|
||||
var user = _users.Update(data.User.Id, data.User);
|
||||
var server = _servers[data.GuildId];
|
||||
var data = e.Event.ToObject<WebSocketEvents.GuildMemberRemove>(_serializer);
|
||||
var server = _servers[data.ServerId];
|
||||
if (server != null)
|
||||
{
|
||||
var membership = server.RemoveMember(user.Id);
|
||||
if (membership != null)
|
||||
RaiseMemberRemoved(membership, server);
|
||||
var member = server.RemoveMember(data.UserId);
|
||||
if (member != null)
|
||||
try { RaiseMemberRemoved(member); } catch { }
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -348,121 +398,138 @@ namespace Discord
|
||||
//Roles
|
||||
case "GUILD_ROLE_CREATE":
|
||||
{
|
||||
var data = e.Event.ToObject<WebSocketEvents.GuildRoleCreateUpdate>();
|
||||
var role = _roles.Update(data.Role.Id, data.GuildId, data.Role);
|
||||
RaiseRoleCreated(role);
|
||||
var data = e.Event.ToObject<WebSocketEvents.GuildRoleCreateUpdate>(_serializer);
|
||||
var role = _roles.Update(data.Role.Id, data.ServerId, data.Role);
|
||||
try { RaiseRoleCreated(role); } catch { }
|
||||
}
|
||||
break;
|
||||
case "GUILD_ROLE_UPDATE":
|
||||
{
|
||||
var data = e.Event.ToObject<WebSocketEvents.GuildRoleCreateUpdate>();
|
||||
var role = _roles.Update(data.Role.Id, data.GuildId, data.Role);
|
||||
RaiseRoleUpdated(role);
|
||||
var data = e.Event.ToObject<WebSocketEvents.GuildRoleCreateUpdate>(_serializer);
|
||||
var role = _roles.Update(data.Role.Id, data.ServerId, data.Role);
|
||||
try { RaiseRoleUpdated(role); } catch { }
|
||||
}
|
||||
break;
|
||||
case "GUILD_ROLE_DELETE":
|
||||
{
|
||||
var data = e.Event.ToObject<WebSocketEvents.GuildRoleDelete>();
|
||||
var data = e.Event.ToObject<WebSocketEvents.GuildRoleDelete>(_serializer);
|
||||
var role = _roles.Remove(data.RoleId);
|
||||
if (role != null)
|
||||
RaiseRoleDeleted(role);
|
||||
try { RaiseRoleDeleted(role); } catch { }
|
||||
}
|
||||
break;
|
||||
|
||||
//Bans
|
||||
case "GUILD_BAN_ADD":
|
||||
{
|
||||
var data = e.Event.ToObject<WebSocketEvents.GuildBanAddRemove>();
|
||||
var data = e.Event.ToObject<WebSocketEvents.GuildBanAddRemove>(_serializer);
|
||||
var user = _users.Update(data.User.Id, data.User);
|
||||
var server = _servers[data.GuildId];
|
||||
RaiseBanAdded(user, server);
|
||||
var server = _servers[data.ServerId];
|
||||
try { RaiseBanAdded(user, server); } catch { }
|
||||
}
|
||||
break;
|
||||
case "GUILD_BAN_REMOVE":
|
||||
{
|
||||
var data = e.Event.ToObject<WebSocketEvents.GuildBanAddRemove>();
|
||||
var data = e.Event.ToObject<WebSocketEvents.GuildBanAddRemove>(_serializer);
|
||||
var user = _users.Update(data.User.Id, data.User);
|
||||
var server = _servers[data.GuildId];
|
||||
var server = _servers[data.ServerId];
|
||||
if (server != null && server.RemoveBan(user.Id))
|
||||
RaiseBanRemoved(user, server);
|
||||
{
|
||||
try { RaiseBanRemoved(user, server); } catch { }
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
//Messages
|
||||
case "MESSAGE_CREATE":
|
||||
{
|
||||
var data = e.Event.ToObject<WebSocketEvents.MessageCreate>();
|
||||
var data = e.Event.ToObject<WebSocketEvents.MessageCreate>(_serializer);
|
||||
var msg = _messages.Update(data.Id, data.ChannelId, data);
|
||||
msg.User.UpdateActivity(data.Timestamp);
|
||||
RaiseMessageCreated(msg);
|
||||
try { RaiseMessageCreated(msg); } catch { }
|
||||
}
|
||||
break;
|
||||
case "MESSAGE_UPDATE":
|
||||
{
|
||||
var data = e.Event.ToObject<WebSocketEvents.MessageUpdate>();
|
||||
var data = e.Event.ToObject<WebSocketEvents.MessageUpdate>(_serializer);
|
||||
var msg = _messages.Update(data.Id, data.ChannelId, data);
|
||||
RaiseMessageUpdated(msg);
|
||||
try { RaiseMessageUpdated(msg); } catch { }
|
||||
}
|
||||
break;
|
||||
case "MESSAGE_DELETE":
|
||||
{
|
||||
var data = e.Event.ToObject<WebSocketEvents.MessageDelete>();
|
||||
var data = e.Event.ToObject<WebSocketEvents.MessageDelete>(_serializer);
|
||||
var msg = GetMessage(data.MessageId);
|
||||
if (msg != null)
|
||||
{
|
||||
_messages.Remove(msg.Id);
|
||||
try { RaiseMessageDeleted(msg); } catch { }
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "MESSAGE_ACK":
|
||||
{
|
||||
var data = e.Event.ToObject<WebSocketEvents.MessageAck>();
|
||||
var data = e.Event.ToObject<WebSocketEvents.MessageAck>(_serializer);
|
||||
var msg = GetMessage(data.MessageId);
|
||||
RaiseMessageAcknowledged(msg);
|
||||
if (msg != null)
|
||||
try { RaiseMessageAcknowledged(msg); } catch { }
|
||||
}
|
||||
break;
|
||||
|
||||
//Statuses
|
||||
case "PRESENCE_UPDATE":
|
||||
{
|
||||
var data = e.Event.ToObject<WebSocketEvents.PresenceUpdate>();
|
||||
var user = _users.Update(data.Id, data);
|
||||
RaisePresenceUpdated(user);
|
||||
var data = e.Event.ToObject<WebSocketEvents.PresenceUpdate>(_serializer);
|
||||
var user = _users.Update(data.User.Id, data.User);
|
||||
var server = _servers[data.ServerId];
|
||||
if (server != null)
|
||||
{
|
||||
var member = server.UpdateMember(data);
|
||||
try { RaisePresenceUpdated(member); } catch { }
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "VOICE_STATE_UPDATE":
|
||||
{
|
||||
var data = e.Event.ToObject<WebSocketEvents.VoiceStateUpdate>();
|
||||
var member = GetMember(data.GuildId, data.UserId);
|
||||
if (member != null)
|
||||
var data = e.Event.ToObject<WebSocketEvents.VoiceStateUpdate>(_serializer);
|
||||
var server = _servers[data.ServerId];
|
||||
if (server != null)
|
||||
{
|
||||
member.Update(data);
|
||||
RaiseVoiceStateUpdated(member);
|
||||
var member = server.UpdateMember(data);
|
||||
if (member != null)
|
||||
try { RaiseVoiceStateUpdated(member); } catch { }
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "TYPING_START":
|
||||
{
|
||||
var data = e.Event.ToObject<WebSocketEvents.TypingStart>();
|
||||
var data = e.Event.ToObject<WebSocketEvents.TypingStart>(_serializer);
|
||||
var channel = _channels[data.ChannelId];
|
||||
var user = _users[data.UserId];
|
||||
RaiseUserTyping(user, channel);
|
||||
if (user != null)
|
||||
{
|
||||
user.UpdateActivity(DateTime.UtcNow);
|
||||
if (channel != null)
|
||||
try { RaiseUserTyping(user, channel); } catch { }
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
//Voice
|
||||
case "VOICE_SERVER_UPDATE":
|
||||
{
|
||||
var data = e.Event.ToObject<WebSocketEvents.VoiceServerUpdate>();
|
||||
var data = e.Event.ToObject<WebSocketEvents.VoiceServerUpdate>(_serializer);
|
||||
var server = _servers[data.ServerId];
|
||||
RaiseVoiceServerUpdated(server, data.Endpoint);
|
||||
try { RaiseVoiceServerUpdated(server, data.Endpoint); } catch { }
|
||||
}
|
||||
break;
|
||||
|
||||
//Settings
|
||||
case "USER_UPDATE":
|
||||
{
|
||||
var data = e.Event.ToObject<WebSocketEvents.UserUpdate>();
|
||||
var data = e.Event.ToObject<WebSocketEvents.UserUpdate>(_serializer);
|
||||
var user = _users.Update(data.Id, data);
|
||||
RaiseUserUpdated(user);
|
||||
try { RaiseUserUpdated(user); } catch { }
|
||||
}
|
||||
break;
|
||||
case "USER_SETTINGS_UPDATE":
|
||||
|
||||
@@ -98,7 +98,8 @@ namespace Discord
|
||||
{
|
||||
throw new InvalidOperationException("Bad Token");
|
||||
}
|
||||
_connectWaitOnLogin2.Wait(cancelToken); //Waiting on READY handler
|
||||
try { _connectWaitOnLogin2.Wait(cancelToken); } //Waiting on READY handler
|
||||
catch (OperationCanceledException) { return; }
|
||||
|
||||
_isConnected = true;
|
||||
RaiseConnected();
|
||||
@@ -150,11 +151,7 @@ namespace Discord
|
||||
QueueMessage(new WebSocketCommands.KeepAlive());
|
||||
_connectWaitOnLogin.Set(); //Pre-Event
|
||||
}
|
||||
try
|
||||
{
|
||||
RaiseGotEvent(msg.Type, msg.Payload as JToken);
|
||||
}
|
||||
catch { } //Don't allow user exceptions to affect our state
|
||||
RaiseGotEvent(msg.Type, msg.Payload as JToken);
|
||||
if (msg.Type == "READY")
|
||||
_connectWaitOnLogin2.Set(); //Post-Event
|
||||
break;
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace Discord.Helpers
|
||||
private readonly Action<TValue, TModel> _onUpdate;
|
||||
private readonly Action<TValue> _onRemove;
|
||||
|
||||
public AsyncCache(Func<string, string, TValue> onCreate, Action<TValue, TModel> onUpdate, Action<TValue> onRemove)
|
||||
public AsyncCache(Func<string, string, TValue> onCreate, Action<TValue, TModel> onUpdate, Action<TValue> onRemove = null)
|
||||
{
|
||||
_dictionary = new ConcurrentDictionary<string, TValue>();
|
||||
_onCreate = onCreate;
|
||||
@@ -49,7 +49,8 @@ namespace Discord.Helpers
|
||||
isNew = !_dictionary.TryGetValue(key, out value);
|
||||
if (isNew)
|
||||
value = _onCreate(key, parentKey);
|
||||
_onUpdate(value, model);
|
||||
if (model != null)
|
||||
_onUpdate(value, model);
|
||||
if (isNew)
|
||||
{
|
||||
//If this fails, repeat as an update instead of an add
|
||||
@@ -68,7 +69,11 @@ namespace Discord.Helpers
|
||||
{
|
||||
TValue value = null;
|
||||
if (_dictionary.TryRemove(key, out value))
|
||||
{
|
||||
if (_onRemove != null)
|
||||
_onRemove(value);
|
||||
return value;
|
||||
}
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ using System.Globalization;
|
||||
|
||||
#if TEST_RESPONSES
|
||||
using System.Diagnostics;
|
||||
using JsonErrorEventArgs = Newtonsoft.Json.Serialization.ErrorEventArgs;
|
||||
#endif
|
||||
|
||||
namespace Discord.Helpers
|
||||
|
||||
@@ -18,6 +18,11 @@ namespace Discord
|
||||
public bool IsSuppressed { get; internal set; }
|
||||
|
||||
public string SessionId { get; internal set; }
|
||||
public string Token { get; internal set; }
|
||||
/// <summary> Returns the id for the game this user is currently playing. </summary>
|
||||
public string GameId { get; internal set; }
|
||||
/// <summary> Returns the current status for this user. </summary>
|
||||
public string Status { get; internal set; }
|
||||
|
||||
public string ServerId { get; }
|
||||
public Server Server => _client.GetServer(ServerId);
|
||||
@@ -31,29 +36,11 @@ namespace Discord
|
||||
public string[] RoleIds { get; internal set; }
|
||||
public IEnumerable<Role> Roles => RoleIds.Select(x => _client.GetRole(x));
|
||||
|
||||
public Membership(string serverId, string userId, DateTime joinedAt, DiscordClient client)
|
||||
public Membership(string serverId, string userId, DiscordClient client)
|
||||
{
|
||||
ServerId = serverId;
|
||||
UserId = userId;
|
||||
JoinedAt = joinedAt;
|
||||
_client = client;
|
||||
}
|
||||
|
||||
internal void Update(ExtendedServerInfo.Membership data)
|
||||
{
|
||||
IsDeafened = data.IsDeaf;
|
||||
IsMuted = data.IsMuted;
|
||||
RoleIds = data.Roles;
|
||||
}
|
||||
internal void Update(WebSocketEvents.VoiceStateUpdate data)
|
||||
{
|
||||
VoiceChannelId = data.ChannelId;
|
||||
IsDeafened = data.IsDeafened;
|
||||
IsMuted = data.IsMuted;
|
||||
IsSelfDeafened = data.IsSelfDeafened;
|
||||
IsSelfMuted = data.IsSelfMuted;
|
||||
IsSuppressed = data.IsSuppressed;
|
||||
SessionId = data.SessionId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,10 +7,39 @@ namespace Discord
|
||||
{
|
||||
public sealed class Message
|
||||
{
|
||||
public class Attachment
|
||||
public sealed class Attachment : File
|
||||
{
|
||||
/// <summary> Unique identifier for this file. </summary>
|
||||
public string Id { get; internal set; }
|
||||
/// <summary> Size, in bytes, of this file file. </summary>
|
||||
public int Size { get; internal set; }
|
||||
/// <summary> Filename of this file. </summary>
|
||||
public string Filename { get; internal set; }
|
||||
}
|
||||
public sealed class Embed
|
||||
{
|
||||
/// <summary> URL of this embed. </summary>
|
||||
public string Url { get; internal set; }
|
||||
/// <summary> Type of this embed. </summary>
|
||||
public string Type { get; internal set; }
|
||||
/// <summary> Title for this embed. </summary>
|
||||
public string Title { get; internal set; }
|
||||
/// <summary> Summary of this embed. </summary>
|
||||
public string Description { get; internal set; }
|
||||
/// <summary> Returns information about the providing website of this embed. </summary>
|
||||
public EmbedProvider Provider { get; internal set; }
|
||||
/// <summary> Returns the thumbnail of this embed. </summary>
|
||||
public File Thumbnail { get; internal set; }
|
||||
}
|
||||
public sealed class EmbedProvider
|
||||
{
|
||||
/// <summary> URL of this embed provider. </summary>
|
||||
public string Url { get; internal set; }
|
||||
/// <summary> Name of this embed provider. </summary>
|
||||
public string Name { get; internal set; }
|
||||
}
|
||||
public class File
|
||||
{
|
||||
/// <summary> Download url for this file. </summary>
|
||||
public string Url { get; internal set; }
|
||||
/// <summary> Preview url for this file. </summary>
|
||||
@@ -19,10 +48,6 @@ namespace Discord
|
||||
public int? Width { get; internal set; }
|
||||
/// <summary> Height of this file, if it is an image. </summary>
|
||||
public int? Height { get; internal set; }
|
||||
/// <summary> Size, in bytes, of this file file. </summary>
|
||||
public int Size { get; internal set; }
|
||||
/// <summary> Filename of this file. </summary>
|
||||
public string Filename { get; internal set; }
|
||||
}
|
||||
|
||||
private readonly DiscordClient _client;
|
||||
@@ -49,6 +74,9 @@ namespace Discord
|
||||
public DateTime? EditedTimestamp { get; internal set; }
|
||||
/// <summary> Returns the attachments included in this message. </summary>
|
||||
public Attachment[] Attachments { get; internal set; }
|
||||
//TODO: Not Implemented
|
||||
/// <summary> Returns a collection of all embeded content in this message. </summary>
|
||||
public Embed[] Embeds { get; internal set; }
|
||||
|
||||
/// <summary> Returns a collection of all user ids mentioned in this message. </summary>
|
||||
public string[] MentionIds { get; internal set; }
|
||||
@@ -68,10 +96,6 @@ namespace Discord
|
||||
[JsonIgnore]
|
||||
public User User => _client.GetUser(UserId);
|
||||
|
||||
//TODO: Not Implemented
|
||||
/// <summary> Not implemented, stored for reference. </summary>
|
||||
public object[] Embeds { get; internal set; }
|
||||
|
||||
internal Message(string id, string channelId, DiscordClient client)
|
||||
{
|
||||
Id = id;
|
||||
|
||||
67
src/Discord.Net/PackedPermissions.cs
Normal file
67
src/Discord.Net/PackedPermissions.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
namespace Discord
|
||||
{
|
||||
public sealed class PackedPermissions
|
||||
{
|
||||
private uint _rawValue;
|
||||
internal uint RawValue { get { return _rawValue; } set { _rawValue = value; } }
|
||||
|
||||
internal PackedPermissions() { }
|
||||
internal PackedPermissions(uint rawValue) { _rawValue = rawValue; }
|
||||
|
||||
/// <summary> If True, a user may create invites. </summary>
|
||||
public bool General_CreateInstantInvite => ((_rawValue >> 0) & 0x1) == 1;
|
||||
/// <summary> If True, a user may ban users from the server. </summary>
|
||||
public bool General_BanMembers => ((_rawValue >> 1) & 0x1) == 1;
|
||||
/// <summary> If True, a user may kick users from the server. </summary>
|
||||
public bool General_KickMembers => ((_rawValue >> 2) & 0x1) == 1;
|
||||
/// <summary> If True, a user adjust roles. </summary>
|
||||
/// <remarks> Having this permission effectively gives all the others as a user may add them to themselves. </remarks>
|
||||
public bool General_ManageRoles => ((_rawValue >> 3) & 0x1) == 1;
|
||||
/// <summary> If True, a user may create, delete and modify channels. </summary>
|
||||
public bool General_ManageChannels => ((_rawValue >> 4) & 0x1) == 1;
|
||||
/// <summary> If True, a user may adjust server properties. </summary>
|
||||
public bool General_ManageServer => ((_rawValue >> 5) & 0x1) == 1;
|
||||
|
||||
//4 Unused
|
||||
|
||||
/// <summary> If True, a user may join channels. </summary>
|
||||
/// <remarks> Note that without this permission, a channel is not sent by the server. </remarks>
|
||||
public bool Text_ReadMessages => ((_rawValue >> 10) & 0x1) == 1;
|
||||
/// <summary> If True, a user may send messages. </summary>
|
||||
public bool Text_SendMessages => ((_rawValue >> 11) & 0x1) == 1;
|
||||
/// <summary> If True, a user may send text-to-speech messages. </summary>
|
||||
public bool Text_SendTTSMessages => ((_rawValue >> 12) & 0x1) == 1;
|
||||
/// <summary> If True, a user may delete messages. </summary>
|
||||
public bool Text_ManageMessages => ((_rawValue >> 13) & 0x1) == 1;
|
||||
/// <summary> If True, Discord will auto-embed links sent by this user. </summary>
|
||||
public bool Text_EmbedLinks => ((_rawValue >> 14) & 0x1) == 1;
|
||||
/// <summary> If True, a user may send files. </summary>
|
||||
public bool Text_AttachFiles => ((_rawValue >> 15) & 0x1) == 1;
|
||||
/// <summary> If True, a user may read previous messages. </summary>
|
||||
public bool Text_ReadMessageHistory => ((_rawValue >> 16) & 0x1) == 1;
|
||||
/// <summary> If True, a user may mention @everyone. </summary>
|
||||
public bool Text_MentionEveryone => ((_rawValue >> 17) & 0x1) == 1;
|
||||
|
||||
//2 Unused
|
||||
|
||||
/// <summary> If True, a user may connect to a voice channel. </summary>
|
||||
public bool Voice_Connect => ((_rawValue >> 20) & 0x1) == 1;
|
||||
/// <summary> If True, a user may speak in a voice channel. </summary>
|
||||
public bool Voice_Speak => ((_rawValue >> 21) & 0x1) == 1;
|
||||
/// <summary> If True, a user may mute users. </summary>
|
||||
public bool Voice_MuteMembers => ((_rawValue >> 22) & 0x1) == 1;
|
||||
/// <summary> If True, a user may deafen users. </summary>
|
||||
public bool Voice_DeafenMembers => ((_rawValue >> 23) & 0x1) == 1;
|
||||
/// <summary> If True, a user may move other users between voice channels. </summary>
|
||||
public bool Voice_MoveMembers => ((_rawValue >> 24) & 0x1) == 1;
|
||||
/// <summary> If True, a user may use voice activation rather than push-to-talk. </summary>
|
||||
public bool Voice_UseVoiceActivation => ((_rawValue >> 25) & 0x1) == 1;
|
||||
|
||||
//6 Unused
|
||||
|
||||
public static implicit operator uint (PackedPermissions perms)
|
||||
{
|
||||
return perms._rawValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,70 +4,6 @@ namespace Discord
|
||||
{
|
||||
public sealed class Role
|
||||
{
|
||||
public sealed class PackedPermissions
|
||||
{
|
||||
private uint _rawValue;
|
||||
internal uint RawValue { get { return _rawValue; } set { _rawValue = value; } }
|
||||
|
||||
internal PackedPermissions() { }
|
||||
|
||||
/// <summary> If True, a user may create invites. </summary>
|
||||
public bool General_CreateInstantInvite => ((_rawValue >> 0) & 0x1) == 1;
|
||||
/// <summary> If True, a user may ban users from the server. </summary>
|
||||
public bool General_BanMembers => ((_rawValue >> 1) & 0x1) == 1;
|
||||
/// <summary> If True, a user may kick users from the server. </summary>
|
||||
public bool General_KickMembers => ((_rawValue >> 2) & 0x1) == 1;
|
||||
/// <summary> If True, a user adjust roles. </summary>
|
||||
/// <remarks> Having this permission effectively gives all the others as a user may add them to themselves. </remarks>
|
||||
public bool General_ManageRoles => ((_rawValue >> 3) & 0x1) == 1;
|
||||
/// <summary> If True, a user may create, delete and modify channels. </summary>
|
||||
public bool General_ManageChannels => ((_rawValue >> 4) & 0x1) == 1;
|
||||
/// <summary> If True, a user may adjust server properties. </summary>
|
||||
public bool General_ManageServer => ((_rawValue >> 5) & 0x1) == 1;
|
||||
|
||||
//4 Unused
|
||||
|
||||
/// <summary> If True, a user may join channels. </summary>
|
||||
/// <remarks> Note that without this permission, a channel is not sent by the server. </remarks>
|
||||
public bool Text_ReadMessages => ((_rawValue >> 10) & 0x1) == 1;
|
||||
/// <summary> If True, a user may send messages. </summary>
|
||||
public bool Text_SendMessages => ((_rawValue >> 11) & 0x1) == 1;
|
||||
/// <summary> If True, a user may send text-to-speech messages. </summary>
|
||||
public bool Text_SendTTSMessages => ((_rawValue >> 12) & 0x1) == 1;
|
||||
/// <summary> If True, a user may delete messages. </summary>
|
||||
public bool Text_ManageMessages => ((_rawValue >> 13) & 0x1) == 1;
|
||||
/// <summary> If True, Discord will auto-embed links sent by this user. </summary>
|
||||
public bool Text_EmbedLinks => ((_rawValue >> 14) & 0x1) == 1;
|
||||
/// <summary> If True, a user may send files. </summary>
|
||||
public bool Text_AttachFiles => ((_rawValue >> 15) & 0x1) == 1;
|
||||
/// <summary> If True, a user may read previous messages. </summary>
|
||||
public bool Text_ReadMessageHistory => ((_rawValue >> 16) & 0x1) == 1;
|
||||
/// <summary> If True, a user may mention @everyone. </summary>
|
||||
public bool Text_MentionEveryone => ((_rawValue >> 17) & 0x1) == 1;
|
||||
|
||||
//2 Unused
|
||||
|
||||
/// <summary> If True, a user may connect to a voice channel. </summary>
|
||||
public bool Voice_Connect => ((_rawValue >> 20) & 0x1) == 1;
|
||||
/// <summary> If True, a user may speak in a voice channel. </summary>
|
||||
public bool Voice_Speak => ((_rawValue >> 21) & 0x1) == 1;
|
||||
/// <summary> If True, a user may mute users. </summary>
|
||||
public bool Voice_MuteMembers => ((_rawValue >> 22) & 0x1) == 1;
|
||||
/// <summary> If True, a user may deafen users. </summary>
|
||||
public bool Voice_DeafenMembers => ((_rawValue >> 23) & 0x1) == 1;
|
||||
/// <summary> If True, a user may move other users between voice channels. </summary>
|
||||
public bool Voice_MoveMembers => ((_rawValue >> 24) & 0x1) == 1;
|
||||
/// <summary> If True, a user may use voice activation rather than push-to-talk. </summary>
|
||||
public bool Voice_UseVoiceActivation => ((_rawValue >> 25) & 0x1) == 1;
|
||||
|
||||
//6 Unused
|
||||
|
||||
public static implicit operator uint(PackedPermissions perms)
|
||||
{
|
||||
return perms._rawValue;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly DiscordClient _client;
|
||||
|
||||
/// <summary> Returns the unique identifier for this role. </summary>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using Discord.Helpers;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -38,9 +39,9 @@ namespace Discord
|
||||
/// <summary> Returns the default channel for this server. </summary>
|
||||
public Channel DefaultChannel =>_client.GetChannel(DefaultChannelId);
|
||||
|
||||
internal ConcurrentDictionary<string, Membership> _members;
|
||||
internal AsyncCache<Membership, API.Models.MemberInfo> _members;
|
||||
/// <summary> Returns a collection of all channels within this server. </summary>
|
||||
public IEnumerable<Membership> Members => _members.Values;
|
||||
public IEnumerable<Membership> Members => _members;
|
||||
|
||||
internal ConcurrentDictionary<string, bool> _bans;
|
||||
/// <summary> Returns a collection of all users banned on this server. </summary>
|
||||
@@ -54,38 +55,59 @@ namespace Discord
|
||||
/// <summary> Returns a collection of all roles within this server. </summary>
|
||||
public IEnumerable<Role> Roles => _client.Roles.Where(x => x.ServerId == Id);
|
||||
|
||||
//TODO: Not Implemented
|
||||
/// <summary> Not implemented, stored for reference. </summary>
|
||||
public object Presence { get; internal set; }
|
||||
//TODO: Not Implemented
|
||||
/// <summary> Not implemented, stored for reference. </summary>
|
||||
public object[] VoiceStates { get; internal set; }
|
||||
|
||||
internal Server(string id, DiscordClient client)
|
||||
{
|
||||
Id = id;
|
||||
_client = client;
|
||||
_members = new ConcurrentDictionary<string, Membership>();
|
||||
_bans = new ConcurrentDictionary<string, bool>();
|
||||
_members = new AsyncCache<Membership, API.Models.MemberInfo>(
|
||||
(key, parentKey) => new Membership(parentKey, key, _client),
|
||||
(member, model) =>
|
||||
{
|
||||
if (model is API.Models.PresenceMemberInfo)
|
||||
{
|
||||
var extendedModel = model as API.Models.PresenceMemberInfo;
|
||||
member.Status = extendedModel.Status;
|
||||
member.GameId = extendedModel.GameId;
|
||||
}
|
||||
if (model is API.Models.VoiceMemberInfo)
|
||||
{
|
||||
var extendedModel = model as API.Models.VoiceMemberInfo;
|
||||
member.VoiceChannelId = extendedModel.ChannelId;
|
||||
member.IsDeafened = extendedModel.IsDeafened;
|
||||
member.IsMuted = extendedModel.IsMuted;
|
||||
member.IsSelfDeafened = extendedModel.IsSelfDeafened;
|
||||
member.IsSelfMuted = extendedModel.IsSelfMuted;
|
||||
member.IsSuppressed = extendedModel.IsSuppressed;
|
||||
member.SessionId = extendedModel.SessionId;
|
||||
member.Token = extendedModel.Token;
|
||||
}
|
||||
if (model is API.Models.RoleMemberInfo)
|
||||
{
|
||||
var extendedModel = model as API.Models.RoleMemberInfo;
|
||||
member.IsDeafened = extendedModel.IsDeafened;
|
||||
member.IsMuted = extendedModel.IsMuted;
|
||||
member.RoleIds = extendedModel.Roles;
|
||||
if (extendedModel.JoinedAt.HasValue)
|
||||
member.JoinedAt = extendedModel.JoinedAt.Value;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
internal void AddMember(Membership membership)
|
||||
internal Membership UpdateMember(API.Models.MemberInfo membership)
|
||||
{
|
||||
_members[membership.UserId] = membership;
|
||||
return _members.Update(membership.User?.Id ?? membership.UserId, Id, membership);
|
||||
}
|
||||
internal Membership RemoveMember(string userId)
|
||||
{
|
||||
Membership result = null;
|
||||
_members.TryRemove(userId, out result);
|
||||
return result;
|
||||
return _members.Remove(userId);
|
||||
}
|
||||
public Membership GetMembership(User user)
|
||||
=> GetMember(user.Id);
|
||||
public Membership GetMember(string userId)
|
||||
{
|
||||
Membership result = null;
|
||||
_members.TryGetValue(userId, out result);
|
||||
return result;
|
||||
return _members[userId];
|
||||
}
|
||||
|
||||
internal void AddBan(string banId)
|
||||
|
||||
@@ -27,10 +27,6 @@ namespace Discord
|
||||
/// <summary> Returns if the email for this user has been verified. </summary>
|
||||
/// <remarks> This field is only ever populated for the current logged in user. </remarks>
|
||||
public bool IsVerified { get; internal set; }
|
||||
/// <summary> Returns the id for the game this user is currently playing. </summary>
|
||||
public string GameId { get; internal set; }
|
||||
/// <summary> Returns the current status for this user. </summary>
|
||||
public string Status { get; internal set; }
|
||||
|
||||
/// <summary> Returns the string "<@Id>" to be used as a shortcut when including mentions in text. </summary>
|
||||
public string Mention { get { return $"<@{Id}>"; } }
|
||||
|
||||
Reference in New Issue
Block a user