From adf36d62f21748fd18ec139338d00c29888f1b49 Mon Sep 17 00:00:00 2001 From: RogueException Date: Sun, 25 Oct 2015 23:57:31 -0300 Subject: [PATCH 01/24] Update invite's references if they dont point to something in cache --- src/Discord.Net/Helpers/Reference.cs | 2 +- src/Discord.Net/Models/Invite.cs | 34 +++++++++++++++++++++++++--- src/Discord.Net/Models/Server.cs | 12 +++++++--- 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/src/Discord.Net/Helpers/Reference.cs b/src/Discord.Net/Helpers/Reference.cs index e02932e9b..4b2aecaa6 100644 --- a/src/Discord.Net/Helpers/Reference.cs +++ b/src/Discord.Net/Helpers/Reference.cs @@ -63,6 +63,6 @@ namespace Discord _getItem = getItem; _onCache = onCache; _onUncache = onUncache; - } + } } } diff --git a/src/Discord.Net/Models/Invite.cs b/src/Discord.Net/Models/Invite.cs index f08f1c6cc..a8f6caf73 100644 --- a/src/Discord.Net/Models/Invite.cs +++ b/src/Discord.Net/Models/Invite.cs @@ -26,24 +26,45 @@ namespace Discord [JsonIgnore] public User Inviter => _inviter.Value; private readonly Reference _inviter; + private User _generatedInviter; /// Returns the server this invite is to. [JsonIgnore] public Server Server => _server.Value; private readonly Reference _server; + private Server _generatedServer; /// Returns the channel this invite is to. [JsonIgnore] public Channel Channel => _channel.Value; private readonly Reference _channel; + private Channel _generatedChannel; internal Invite(DiscordClient client, string code, string xkcdPass, string serverId, string inviterId, string channelId) : base(client, code) { XkcdCode = xkcdPass; - _server = new Reference(serverId, x => _client.Servers[x] ?? new Server(client, x)); - _inviter = new Reference(serverId, x => _client.Users[x, _server.Id] ?? new User(client, x, _server.Id)); - _channel = new Reference(serverId, x => _client.Channels[x] ?? new Channel(client, x, _server.Id, null)); + _server = new Reference(serverId, x => + { + var server = _client.Servers[x]; + if (server == null) + server = _generatedServer = new Server(client, x); + return server; + }); + _inviter = new Reference(serverId, x => + { + var inviter = _client.Users[x, _server.Id]; + if (inviter == null) + inviter = _generatedInviter = new User(client, x, _server.Id); + return inviter; + }); + _channel = new Reference(serverId, x => + { + var channel = _client.Channels[x]; + if (channel == null) + channel = _generatedChannel = new Channel(client, x, _server.Id, null); + return channel; + }); } internal override void LoadReferences() { @@ -58,6 +79,13 @@ namespace Discord internal void Update(InviteInfo model) { + if (model.Guild != null && _generatedServer != null) + _generatedServer.Update(model.Guild); + if (model.Inviter != null && _generatedInviter != null) + _generatedInviter.Update(model.Inviter); + if (model.Channel != null && _generatedChannel != null) + _generatedChannel.Update(model.Channel); + if (model.IsRevoked != null) IsRevoked = model.IsRevoked.Value; if (model.IsTemporary != null) diff --git a/src/Discord.Net/Models/Server.cs b/src/Discord.Net/Models/Server.cs index d6689d1a4..f614be04e 100644 --- a/src/Discord.Net/Models/Server.cs +++ b/src/Discord.Net/Models/Server.cs @@ -123,15 +123,21 @@ namespace Discord _afkChannel.Unload(); } - internal void Update(GuildInfo model) + internal void Update(GuildReference model) { + if (model.Name != null) + Name = model.Name; + } + + internal void Update(GuildInfo model) + { + Update(model as GuildReference); + if (model.AFKTimeout != null) AFKTimeout = model.AFKTimeout.Value; if (model.AFKChannelId != null) if (model.JoinedAt != null) JoinedAt = model.JoinedAt.Value; - if (model.Name != null) - Name = model.Name; if (model.OwnerId != null && _ownerId != model.OwnerId) { _ownerId = model.OwnerId; From f377249d54d845aa52e91f4ccbb804364a3419bd Mon Sep 17 00:00:00 2001 From: RogueException Date: Mon, 26 Oct 2015 00:00:46 -0300 Subject: [PATCH 02/24] User.AvatarUrl returns null if AvatarId is null --- src/Discord.Net/Models/User.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Discord.Net/Models/User.cs b/src/Discord.Net/Models/User.cs index 4fba8ae5b..3726f6616 100644 --- a/src/Discord.Net/Models/User.cs +++ b/src/Discord.Net/Models/User.cs @@ -24,7 +24,7 @@ namespace Discord /// Returns the unique identifier for this user's current avatar. public string AvatarId { get; private set; } /// Returns the URL to this user's current avatar. - public string AvatarUrl => API.Endpoints.UserAvatar(Id, AvatarId); + public string AvatarUrl => AvatarId != null ? API.Endpoints.UserAvatar(Id, AvatarId) : null; /// Returns the datetime that this user joined this server. public DateTime JoinedAt { get; private set; } From 334b049d248d42edd85e0e2f24c8dd1d355b05d7 Mon Sep 17 00:00:00 2001 From: RogueException Date: Mon, 26 Oct 2015 00:06:21 -0300 Subject: [PATCH 03/24] Properly update invite state --- src/Discord.Net/DiscordClient.Invites.cs | 3 ++- src/Discord.Net/Models/Invite.cs | 19 ++++++++++++++++--- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/Discord.Net/DiscordClient.Invites.cs b/src/Discord.Net/DiscordClient.Invites.cs index 10d1ee016..027257d9b 100644 --- a/src/Discord.Net/DiscordClient.Invites.cs +++ b/src/Discord.Net/DiscordClient.Invites.cs @@ -26,7 +26,8 @@ namespace Discord var response = await _api.GetInvite(inviteIdOrXkcd).ConfigureAwait(false); var invite = new Invite(this, response.Code, response.XkcdPass, response.Guild.Id, response.Inviter?.Id, response.Channel?.Id); invite.Cache(); //Builds references - return invite; + invite.Update(response); + return invite; } /// Creates a new invite to the default channel of the provided server. diff --git a/src/Discord.Net/Models/Invite.cs b/src/Discord.Net/Models/Invite.cs index a8f6caf73..97ad94a04 100644 --- a/src/Discord.Net/Models/Invite.cs +++ b/src/Discord.Net/Models/Invite.cs @@ -48,21 +48,30 @@ namespace Discord { var server = _client.Servers[x]; if (server == null) + { server = _generatedServer = new Server(client, x); + server.Cache(); + } return server; }); _inviter = new Reference(serverId, x => { var inviter = _client.Users[x, _server.Id]; if (inviter == null) + { inviter = _generatedInviter = new User(client, x, _server.Id); + inviter.Cache(); + } return inviter; }); _channel = new Reference(serverId, x => { var channel = _client.Channels[x]; if (channel == null) + { channel = _generatedChannel = new Channel(client, x, _server.Id, null); + channel.Cache(); + } return channel; }); } @@ -75,9 +84,9 @@ namespace Discord internal override void UnloadReferences() { } public override string ToString() => XkcdCode ?? Id; - - internal void Update(InviteInfo model) + + internal void Update(InviteReference model) { if (model.Guild != null && _generatedServer != null) _generatedServer.Update(model.Guild); @@ -85,6 +94,10 @@ namespace Discord _generatedInviter.Update(model.Inviter); if (model.Channel != null && _generatedChannel != null) _generatedChannel.Update(model.Channel); + } + internal void Update(InviteInfo model) + { + Update(model as InviteReference); if (model.IsRevoked != null) IsRevoked = model.IsRevoked.Value; @@ -96,6 +109,6 @@ namespace Discord MaxUses = model.MaxUses.Value; if (model.Uses != null) Uses = model.Uses.Value; - } + } } } From bd74e4b7128e0bbce171fc80b7ba8f2f312bf83f Mon Sep 17 00:00:00 2001 From: RogueException Date: Mon, 26 Oct 2015 01:39:28 -0300 Subject: [PATCH 04/24] Added PruneUsers, renamed a few APIClient functions. --- src/Discord.Net/API/Endpoints.cs | 1 + src/Discord.Net/API/Members.cs | 6 ++++++ src/Discord.Net/DiscordAPIClient.cs | 20 ++++++++++++++++---- src/Discord.Net/DiscordClient.Bans.cs | 4 ++-- src/Discord.Net/DiscordClient.Users.cs | 9 +++++++++ 5 files changed, 34 insertions(+), 6 deletions(-) diff --git a/src/Discord.Net/API/Endpoints.cs b/src/Discord.Net/API/Endpoints.cs index 67c256a88..f283d9bae 100644 --- a/src/Discord.Net/API/Endpoints.cs +++ b/src/Discord.Net/API/Endpoints.cs @@ -28,6 +28,7 @@ public static string ServerBan(string serverId, string userId) => $"guilds/{serverId}/bans/{userId}"; public static string ServerRoles(string serverId) => $"guilds/{serverId}/roles"; public static string ServerRole(string serverId, string roleId) => $"guilds/{serverId}/roles/{roleId}"; + public static string ServerPrune(string serverId, int days) => $"guilds/{serverId}/prune?days={days}"; public const string Invites = "invite"; public static string Invite(string inviteId) => $"invite/{inviteId}"; diff --git a/src/Discord.Net/API/Members.cs b/src/Discord.Net/API/Members.cs index 2a48b653d..9e69390c6 100644 --- a/src/Discord.Net/API/Members.cs +++ b/src/Discord.Net/API/Members.cs @@ -82,6 +82,12 @@ namespace Discord.API public IEnumerable Roles; } + public class PruneUsersResponse + { + [JsonProperty("pruned")] + public int? Pruned; + } + //Events internal sealed class MemberAddEvent : MemberInfo { } internal sealed class MemberUpdateEvent : MemberInfo { } diff --git a/src/Discord.Net/DiscordAPIClient.cs b/src/Discord.Net/DiscordAPIClient.cs index 8b3590a27..92f23f008 100644 --- a/src/Discord.Net/DiscordAPIClient.cs +++ b/src/Discord.Net/DiscordAPIClient.cs @@ -136,7 +136,7 @@ namespace Discord return _rest.Delete(Endpoints.Invite(inviteId)); } - //Members + //Users public Task EditUser(string serverId, string userId, bool? mute = null, bool? deaf = null, IEnumerable roles = null) { if (serverId == null) throw new ArgumentNullException(nameof(serverId)); @@ -145,27 +145,39 @@ namespace Discord var request = new EditMemberRequest { Mute = mute, Deaf = deaf, Roles = roles }; return _rest.Patch(Endpoints.ServerMember(serverId, userId), request); } - public Task Kick(string serverId, string userId) + public Task KickUser(string serverId, string userId) { if (serverId == null) throw new ArgumentNullException(nameof(serverId)); if (userId == null) throw new ArgumentNullException(nameof(userId)); return _rest.Delete(Endpoints.ServerMember(serverId, userId)); } - public Task Ban(string serverId, string userId) + public Task BanUser(string serverId, string userId) { if (serverId == null) throw new ArgumentNullException(nameof(serverId)); if (userId == null) throw new ArgumentNullException(nameof(userId)); return _rest.Put(Endpoints.ServerBan(serverId, userId)); } - public Task Unban(string serverId, string userId) + public Task UnbanUser(string serverId, string userId) { if (serverId == null) throw new ArgumentNullException(nameof(serverId)); if (userId == null) throw new ArgumentNullException(nameof(userId)); return _rest.Delete(Endpoints.ServerBan(serverId, userId)); } + public async Task PruneUsers(string serverId, int days, bool simulate) + { + if (serverId == null) throw new ArgumentNullException(nameof(serverId)); + if (days <= 0) throw new ArgumentOutOfRangeException(nameof(days)); + + PruneUsersResponse response; + if (simulate) + response = await _rest.Get(Endpoints.ServerPrune(serverId, days)); + else + response = await _rest.Post(Endpoints.ServerPrune(serverId, days)); + return response.Pruned ?? 0; + } //Messages public Task SendMessage(string channelId, string message, IEnumerable mentionedUserIds = null, string nonce = null, bool isTTS = false) diff --git a/src/Discord.Net/DiscordClient.Bans.cs b/src/Discord.Net/DiscordClient.Bans.cs index e910d4bf6..6272f9d0b 100644 --- a/src/Discord.Net/DiscordClient.Bans.cs +++ b/src/Discord.Net/DiscordClient.Bans.cs @@ -38,7 +38,7 @@ namespace Discord if (user.Server == null) throw new ArgumentException("Unable to ban a user in a private chat."); CheckReady(); - return _api.Ban(user.Server.Id, user.Id); + return _api.BanUser(user.Server.Id, user.Id); } /// Unbans a user from the provided server. @@ -48,7 +48,7 @@ namespace Discord if (userId == null) throw new ArgumentNullException(nameof(userId)); CheckReady(); - try { await _api.Unban(server.Id, userId).ConfigureAwait(false); } + try { await _api.UnbanUser(server.Id, userId).ConfigureAwait(false); } catch (HttpException ex) when (ex.StatusCode == HttpStatusCode.NotFound) { } } } diff --git a/src/Discord.Net/DiscordClient.Users.cs b/src/Discord.Net/DiscordClient.Users.cs index dba8f06a4..b236c2220 100644 --- a/src/Discord.Net/DiscordClient.Users.cs +++ b/src/Discord.Net/DiscordClient.Users.cs @@ -173,6 +173,15 @@ namespace Discord return _api.EditUser(user.Server?.Id, user.Id, mute: mute, deaf: deaf, roles: roles.Select(x => x.Id)); } + public Task PruneUsers(string serverId, int days, bool simulate = false) + { + if (serverId == null) throw new ArgumentNullException(nameof(serverId)); + if (days <= 0) throw new ArgumentOutOfRangeException(nameof(days)); + CheckReady(); + + return _api.PruneUsers(serverId, days, simulate); + } + public Task EditProfile(string currentPassword = "", string username = null, string email = null, string password = null, ImageType avatarType = ImageType.Png, byte[] avatar = null) From 40b1617b85e8321f08f3e7a380d605114e74472d Mon Sep 17 00:00:00 2001 From: RogueException Date: Mon, 26 Oct 2015 01:40:27 -0300 Subject: [PATCH 05/24] Minor cleanup --- src/Discord.Net/DiscordClient.Users.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Discord.Net/DiscordClient.Users.cs b/src/Discord.Net/DiscordClient.Users.cs index b236c2220..76ff5538b 100644 --- a/src/Discord.Net/DiscordClient.Users.cs +++ b/src/Discord.Net/DiscordClient.Users.cs @@ -1,5 +1,4 @@ -using Discord.API; -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -182,7 +181,7 @@ namespace Discord return _api.PruneUsers(serverId, days, simulate); } - public Task EditProfile(string currentPassword = "", + public Task EditProfile(string currentPassword = "", string username = null, string email = null, string password = null, ImageType avatarType = ImageType.Png, byte[] avatar = null) { From 110511606b1eea944cfa174e0a05ba63a94421fa Mon Sep 17 00:00:00 2001 From: RogueException Date: Mon, 26 Oct 2015 01:47:16 -0300 Subject: [PATCH 06/24] Minor logging change --- src/Discord.Net/DiscordClient.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Discord.Net/DiscordClient.cs b/src/Discord.Net/DiscordClient.cs index c162c237f..64bdcd8b7 100644 --- a/src/Discord.Net/DiscordClient.cs +++ b/src/Discord.Net/DiscordClient.cs @@ -90,7 +90,7 @@ namespace Discord ChannelUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client, $"Channel Updated: {e.Server?.Name ?? "[Private]"}/{e.Channel?.Name}"); MessageReceived += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client, - $"Message Created: {e.Server?.Name ?? "[Private]"}/{e.Channel?.Name}/{e.Message?.Id}"); + $"Message Received: {e.Server?.Name ?? "[Private]"}/{e.Channel?.Name}/{e.Message?.Id}"); MessageDeleted += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client, $"Message Deleted: {e.Server?.Name ?? "[Private]"}/{e.Channel?.Name}/{e.Message?.Id}"); MessageUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client, From adf45ad6a472735f39cef035ab33d14ddecbfc5f Mon Sep 17 00:00:00 2001 From: RogueException Date: Mon, 26 Oct 2015 01:54:30 -0300 Subject: [PATCH 07/24] More cleanup --- src/Discord.Net/DiscordClient.Messages.cs | 2 +- src/Discord.Net/DiscordClient.Users.cs | 2 +- src/Discord.Net/DiscordClient.cs | 14 +++++++------- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Discord.Net/DiscordClient.Messages.cs b/src/Discord.Net/DiscordClient.Messages.cs index 670164f4f..6768e07e2 100644 --- a/src/Discord.Net/DiscordClient.Messages.cs +++ b/src/Discord.Net/DiscordClient.Messages.cs @@ -46,7 +46,7 @@ namespace Discord public const int MaxMessageSize = 2000; public event EventHandler MessageReceived; - private void RaiseMessageCreated(Message msg) + private void RaiseMessageReceived(Message msg) { if (MessageReceived != null) RaiseEvent(nameof(MessageReceived), () => MessageReceived(this, new MessageEventArgs(msg))); diff --git a/src/Discord.Net/DiscordClient.Users.cs b/src/Discord.Net/DiscordClient.Users.cs index 76ff5538b..1af545d8b 100644 --- a/src/Discord.Net/DiscordClient.Users.cs +++ b/src/Discord.Net/DiscordClient.Users.cs @@ -84,7 +84,7 @@ namespace Discord RaiseEvent(nameof(UserRemoved), () => UserRemoved(this, new UserEventArgs(user))); } public event EventHandler UserUpdated; - private void RaiseMemberUpdated(User user) + private void RaiseUserUpdated(User user) { if (UserUpdated != null) RaiseEvent(nameof(UserUpdated), () => UserUpdated(this, new UserEventArgs(user))); diff --git a/src/Discord.Net/DiscordClient.cs b/src/Discord.Net/DiscordClient.cs index 64bdcd8b7..39a280766 100644 --- a/src/Discord.Net/DiscordClient.cs +++ b/src/Discord.Net/DiscordClient.cs @@ -119,13 +119,13 @@ namespace Discord if (_config.LogLevel >= LogMessageSeverity.Verbose) { UserIsTypingUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Client, - $"Updated User (Is Typing): {e.Server?.Name ?? "[Private]"}/{e.Channel?.Name}/{e.User?.Name}"); + $"User Updated (Is Typing): {e.Server?.Name ?? "[Private]"}/{e.Channel?.Name}/{e.User?.Name}"); MessageReadRemotely += (s, e) => RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Client, $"Read Message (Remotely): {e.Server?.Name ?? "[Private]"}/{e.Channel?.Name}/{e.Message?.Id}"); MessageSent += (s, e) => RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Client, $"Sent Message: {e.Server?.Name ?? "[Private]"}/{e.Channel?.Name}/{e.Message?.Id}"); UserPresenceUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Verbose, LogMessageSource.Client, - $"Updated Member (Presence): {e.Server?.Name ?? "[Private]"}/{e.User?.Name}"); + $"User Updated (Presence): {e.Server?.Name ?? "[Private]"}/{e.User?.Name}"); _api.RestClient.OnRequest += (s, e) => { @@ -140,9 +140,9 @@ namespace Discord _channels.ItemCreated += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Created Channel {e.Item.Server?.Id ?? "[Private]"}/{e.Item.Id}"); _channels.ItemDestroyed += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Destroyed Channel {e.Item.Server?.Id ?? "[Private]"}/{e.Item.Id}"); _channels.Cleared += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Cleared Channels"); - _users.ItemCreated += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Created Member {e.Item.Server?.Id ?? "[Private]"}/{e.Item.Id}"); - _users.ItemDestroyed += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Destroyed Member {e.Item.Server?.Id ?? "[Private]"}/{e.Item.Id}"); - _users.Cleared += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Cleared Members"); + _users.ItemCreated += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Created User {e.Item.Server?.Id ?? "[Private]"}/{e.Item.Id}"); + _users.ItemDestroyed += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Destroyed User {e.Item.Server?.Id ?? "[Private]"}/{e.Item.Id}"); + _users.Cleared += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Cleared Users"); _messages.ItemCreated += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Created Message {e.Item.Server?.Id ?? "[Private]"}/{e.Item.Channel.Id}/{e.Item.Id}"); _messages.ItemDestroyed += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Destroyed Message {e.Item.Server?.Id ?? "[Private]"}/{e.Item.Channel.Id}/{e.Item.Id}"); _messages.ItemRemapped += (s, e) => RaiseOnLog(LogMessageSeverity.Debug, LogMessageSource.Cache, $"Remapped Message {e.Item.Server?.Id ?? "[Private]"}/{e.Item.Channel.Id}/[{e.OldId} -> {e.NewId}]"); @@ -406,7 +406,7 @@ namespace Discord if (user != null) { user.Update(data); - RaiseMemberUpdated(user); + RaiseUserUpdated(user); } } break; @@ -499,7 +499,7 @@ namespace Discord } } - RaiseMessageCreated(msg); + RaiseMessageReceived(msg); if (Config.AckMessages && !isAuthor) await _api.AckMessage(data.Id, data.ChannelId).ConfigureAwait(false); From 1ce82912f3f5e5a52f89015897d6099208874cbe Mon Sep 17 00:00:00 2001 From: RogueException Date: Mon, 26 Oct 2015 02:05:07 -0300 Subject: [PATCH 08/24] Made PruneUsers more consistent with the other API calls --- src/Discord.Net/DiscordAPIClient.cs | 10 ++++------ src/Discord.Net/DiscordClient.Users.cs | 5 +++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/Discord.Net/DiscordAPIClient.cs b/src/Discord.Net/DiscordAPIClient.cs index 92f23f008..c252667a5 100644 --- a/src/Discord.Net/DiscordAPIClient.cs +++ b/src/Discord.Net/DiscordAPIClient.cs @@ -166,17 +166,15 @@ namespace Discord return _rest.Delete(Endpoints.ServerBan(serverId, userId)); } - public async Task PruneUsers(string serverId, int days, bool simulate) + public Task PruneUsers(string serverId, int days, bool simulate) { if (serverId == null) throw new ArgumentNullException(nameof(serverId)); if (days <= 0) throw new ArgumentOutOfRangeException(nameof(days)); - - PruneUsersResponse response; + if (simulate) - response = await _rest.Get(Endpoints.ServerPrune(serverId, days)); + return _rest.Get(Endpoints.ServerPrune(serverId, days)); else - response = await _rest.Post(Endpoints.ServerPrune(serverId, days)); - return response.Pruned ?? 0; + return _rest.Post(Endpoints.ServerPrune(serverId, days)); } //Messages diff --git a/src/Discord.Net/DiscordClient.Users.cs b/src/Discord.Net/DiscordClient.Users.cs index 1af545d8b..2782909c3 100644 --- a/src/Discord.Net/DiscordClient.Users.cs +++ b/src/Discord.Net/DiscordClient.Users.cs @@ -172,13 +172,14 @@ namespace Discord return _api.EditUser(user.Server?.Id, user.Id, mute: mute, deaf: deaf, roles: roles.Select(x => x.Id)); } - public Task PruneUsers(string serverId, int days, bool simulate = false) + public async Task PruneUsers(string serverId, int days, bool simulate = false) { if (serverId == null) throw new ArgumentNullException(nameof(serverId)); if (days <= 0) throw new ArgumentOutOfRangeException(nameof(days)); CheckReady(); - return _api.PruneUsers(serverId, days, simulate); + var response = await _api.PruneUsers(serverId, days, simulate); + return response.Pruned ?? 0; } public Task EditProfile(string currentPassword = "", From cc04f7eb555f6c6aad41ec0203adf8e495066bba Mon Sep 17 00:00:00 2001 From: Brandon Smith Date: Mon, 26 Oct 2015 09:17:35 -0300 Subject: [PATCH 09/24] Added Modules project --- Discord.Net.sln | 18 ++++++ .../Discord.Net.Modules.csproj | 56 +++++++++++++++++++ .../Properties/AssemblyInfo.cs | 18 ++++++ .../Discord.Net.Modules.xproj | 21 +++++++ src/Discord.Net.Modules/project.json | 22 ++++++++ 5 files changed, 135 insertions(+) create mode 100644 src/Discord.Net.Modules.Net45/Discord.Net.Modules.csproj create mode 100644 src/Discord.Net.Modules.Net45/Properties/AssemblyInfo.cs create mode 100644 src/Discord.Net.Modules/Discord.Net.Modules.xproj create mode 100644 src/Discord.Net.Modules/project.json diff --git a/Discord.Net.sln b/Discord.Net.sln index bac38366c..1c32308ff 100644 --- a/Discord.Net.sln +++ b/Discord.Net.sln @@ -26,6 +26,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Discord.Net", "src\Discord. EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Discord.Net.Commands", "src\Discord.Net.Commands.Net45\Discord.Net.Commands.csproj", "{1B5603B4-6F8F-4289-B945-7BAAE523D740}" EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Discord.Net.Modules", "src\Discord.Net.Modules\Discord.Net.Modules.xproj", "{01584E8A-78DA-486F-9EF9-A894E435841B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Discord.Net.Modules", "src\Discord.Net.Modules.Net45\Discord.Net.Modules.csproj", "{3091164F-66AE-4543-A63D-167C1116241D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -63,6 +67,18 @@ Global {1B5603B4-6F8F-4289-B945-7BAAE523D740}.FullDebug|Any CPU.Build.0 = Debug|Any CPU {1B5603B4-6F8F-4289-B945-7BAAE523D740}.Release|Any CPU.ActiveCfg = Release|Any CPU {1B5603B4-6F8F-4289-B945-7BAAE523D740}.Release|Any CPU.Build.0 = Release|Any CPU + {01584E8A-78DA-486F-9EF9-A894E435841B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {01584E8A-78DA-486F-9EF9-A894E435841B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {01584E8A-78DA-486F-9EF9-A894E435841B}.FullDebug|Any CPU.ActiveCfg = Debug|Any CPU + {01584E8A-78DA-486F-9EF9-A894E435841B}.FullDebug|Any CPU.Build.0 = Debug|Any CPU + {01584E8A-78DA-486F-9EF9-A894E435841B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {01584E8A-78DA-486F-9EF9-A894E435841B}.Release|Any CPU.Build.0 = Release|Any CPU + {3091164F-66AE-4543-A63D-167C1116241D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3091164F-66AE-4543-A63D-167C1116241D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3091164F-66AE-4543-A63D-167C1116241D}.FullDebug|Any CPU.ActiveCfg = Debug|Any CPU + {3091164F-66AE-4543-A63D-167C1116241D}.FullDebug|Any CPU.Build.0 = Debug|Any CPU + {3091164F-66AE-4543-A63D-167C1116241D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3091164F-66AE-4543-A63D-167C1116241D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -75,5 +91,7 @@ Global {855D6B1D-847B-42DA-BE6A-23683EA89511} = {6317A2E6-8E36-4C3E-949B-3F10EC888AB9} {8D71A857-879A-4A10-859E-5FF824ED6688} = {DF03D4E8-38F6-4FE1-BC52-E38124BE8AFD} {1B5603B4-6F8F-4289-B945-7BAAE523D740} = {DF03D4E8-38F6-4FE1-BC52-E38124BE8AFD} + {01584E8A-78DA-486F-9EF9-A894E435841B} = {EA68EBE2-51C8-4440-9EF7-D633C90A5D35} + {3091164F-66AE-4543-A63D-167C1116241D} = {DF03D4E8-38F6-4FE1-BC52-E38124BE8AFD} EndGlobalSection EndGlobal diff --git a/src/Discord.Net.Modules.Net45/Discord.Net.Modules.csproj b/src/Discord.Net.Modules.Net45/Discord.Net.Modules.csproj new file mode 100644 index 000000000..4bc5bf376 --- /dev/null +++ b/src/Discord.Net.Modules.Net45/Discord.Net.Modules.csproj @@ -0,0 +1,56 @@ + + + + + Debug + AnyCPU + {3091164F-66AE-4543-A63D-167C1116241D} + Library + Properties + Discord + Discord.Net.Commands + 512 + v4.5 + False + + + true + full + false + bin\Debug\ + TRACE;DEBUG;NET45 + prompt + 4 + 6 + + + pdbonly + true + bin\Release\ + TRACE;NET45 + prompt + 4 + true + 6 + + + + + + + + + + {8d71a857-879a-4a10-859e-5ff824ed6688} + Discord.Net + + + + + \ No newline at end of file diff --git a/src/Discord.Net.Modules.Net45/Properties/AssemblyInfo.cs b/src/Discord.Net.Modules.Net45/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..3eea0d999 --- /dev/null +++ b/src/Discord.Net.Modules.Net45/Properties/AssemblyInfo.cs @@ -0,0 +1,18 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("Discord.Net.Modules")] +[assembly: AssemblyDescription("A Discord.Net extension adding basic plugin support.")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("RogueException")] +[assembly: AssemblyProduct("Discord.Net.Modules")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] +[assembly: Guid("76ea00e6-ea24-41e1-acb2-639c0313fa80")] + +[assembly: AssemblyVersion("0.8.0.0")] +[assembly: AssemblyFileVersion("0.8.0.0")] + diff --git a/src/Discord.Net.Modules/Discord.Net.Modules.xproj b/src/Discord.Net.Modules/Discord.Net.Modules.xproj new file mode 100644 index 000000000..f6db54ed1 --- /dev/null +++ b/src/Discord.Net.Modules/Discord.Net.Modules.xproj @@ -0,0 +1,21 @@ + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + 01584e8a-78da-486f-9ef9-a894e435841b + Discord + ..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\artifacts\bin\$(MSBuildProjectName)\ + + + 2.0 + + + True + + + \ No newline at end of file diff --git a/src/Discord.Net.Modules/project.json b/src/Discord.Net.Modules/project.json new file mode 100644 index 000000000..857314fb8 --- /dev/null +++ b/src/Discord.Net.Modules/project.json @@ -0,0 +1,22 @@ +{ + "version": "0.8.0-beta1", + "description": "A Discord.Net extension adding basic plugin support.", + "authors": [ "RogueException" ], + "tags": [ "discord", "discordapp" ], + "projectUrl": "https://github.com/RogueException/Discord.Net", + "licenseUrl": "http://opensource.org/licenses/MIT", + "repository": { + "type": "git", + "url": "git://github.com/RogueException/Discord.Net" + }, + "compilationOptions": { + "warningsAsErrors": true + }, + "dependencies": { + "Discord.Net": "0.8.0-beta1" + }, + "frameworks": { + "net45": { }, + "dnx451": { } + } +} From a4d6a0e2bcea7000ea14be6d556da8b47eec7f88 Mon Sep 17 00:00:00 2001 From: Brandon Smith Date: Mon, 26 Oct 2015 09:22:59 -0300 Subject: [PATCH 10/24] 0.8.1-beta1 --- src/Discord.Net.Commands.Net45/Properties/AssemblyInfo.cs | 4 ++-- src/Discord.Net.Commands/project.json | 4 ++-- src/Discord.Net.Modules.Net45/Properties/AssemblyInfo.cs | 4 ++-- src/Discord.Net.Modules/project.json | 4 ++-- src/Discord.Net.Net45/Properties/AssemblyInfo.cs | 4 ++-- src/Discord.Net/project.json | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Discord.Net.Commands.Net45/Properties/AssemblyInfo.cs b/src/Discord.Net.Commands.Net45/Properties/AssemblyInfo.cs index e242053d8..c9652a642 100644 --- a/src/Discord.Net.Commands.Net45/Properties/AssemblyInfo.cs +++ b/src/Discord.Net.Commands.Net45/Properties/AssemblyInfo.cs @@ -13,6 +13,6 @@ using System.Runtime.InteropServices; [assembly: ComVisible(false)] [assembly: Guid("76ea00e6-ea24-41e1-acb2-639c0313fa80")] -[assembly: AssemblyVersion("0.8.0.0")] -[assembly: AssemblyFileVersion("0.8.0.0")] +[assembly: AssemblyVersion("0.8.1.0")] +[assembly: AssemblyFileVersion("0.8.1.0")] diff --git a/src/Discord.Net.Commands/project.json b/src/Discord.Net.Commands/project.json index aac273d4e..259f9606a 100644 --- a/src/Discord.Net.Commands/project.json +++ b/src/Discord.Net.Commands/project.json @@ -1,5 +1,5 @@ { - "version": "0.8.0-beta1", + "version": "0.8.1-beta1", "description": "A Discord.Net extension adding basic command support.", "authors": [ "RogueException" ], "tags": [ "discord", "discordapp" ], @@ -13,7 +13,7 @@ "warningsAsErrors": true }, "dependencies": { - "Discord.Net": "0.8.0-beta1" + "Discord.Net": "0.8.1-beta1" }, "frameworks": { "net45": { }, diff --git a/src/Discord.Net.Modules.Net45/Properties/AssemblyInfo.cs b/src/Discord.Net.Modules.Net45/Properties/AssemblyInfo.cs index 3eea0d999..f61c1c991 100644 --- a/src/Discord.Net.Modules.Net45/Properties/AssemblyInfo.cs +++ b/src/Discord.Net.Modules.Net45/Properties/AssemblyInfo.cs @@ -13,6 +13,6 @@ using System.Runtime.InteropServices; [assembly: ComVisible(false)] [assembly: Guid("76ea00e6-ea24-41e1-acb2-639c0313fa80")] -[assembly: AssemblyVersion("0.8.0.0")] -[assembly: AssemblyFileVersion("0.8.0.0")] +[assembly: AssemblyVersion("0.8.1.0")] +[assembly: AssemblyFileVersion("0.8.1.0")] diff --git a/src/Discord.Net.Modules/project.json b/src/Discord.Net.Modules/project.json index 857314fb8..9f71ee00c 100644 --- a/src/Discord.Net.Modules/project.json +++ b/src/Discord.Net.Modules/project.json @@ -1,5 +1,5 @@ { - "version": "0.8.0-beta1", + "version": "0.8.1-beta1", "description": "A Discord.Net extension adding basic plugin support.", "authors": [ "RogueException" ], "tags": [ "discord", "discordapp" ], @@ -13,7 +13,7 @@ "warningsAsErrors": true }, "dependencies": { - "Discord.Net": "0.8.0-beta1" + "Discord.Net": "0.8.1-beta1" }, "frameworks": { "net45": { }, diff --git a/src/Discord.Net.Net45/Properties/AssemblyInfo.cs b/src/Discord.Net.Net45/Properties/AssemblyInfo.cs index 857ea2201..2825ff2a9 100644 --- a/src/Discord.Net.Net45/Properties/AssemblyInfo.cs +++ b/src/Discord.Net.Net45/Properties/AssemblyInfo.cs @@ -13,5 +13,5 @@ using System.Runtime.InteropServices; [assembly: ComVisible(false)] [assembly: Guid("76ea00e6-ea24-41e1-acb2-639c0313fa80")] -[assembly: AssemblyVersion("0.8.0")] -[assembly: AssemblyFileVersion("0.8.0")] +[assembly: AssemblyVersion("0.8.1.0")] +[assembly: AssemblyFileVersion("0.8.1.0")] diff --git a/src/Discord.Net/project.json b/src/Discord.Net/project.json index 8a2b2e1b2..3d0b55689 100644 --- a/src/Discord.Net/project.json +++ b/src/Discord.Net/project.json @@ -1,5 +1,5 @@ { - "version": "0.8.0-beta1", + "version": "0.8.1-beta1", "description": "An unofficial .Net API wrapper for the Discord client.", "authors": [ "RogueException" From 2ba268e892af3506c029600627820b87da6cf19d Mon Sep 17 00:00:00 2001 From: RogueException Date: Mon, 26 Oct 2015 14:04:13 -0300 Subject: [PATCH 11/24] Actually use GetMessages(beforeMessageId) --- src/Discord.Net/API/Endpoints.cs | 1 + src/Discord.Net/DiscordAPIClient.cs | 7 +++++-- src/Discord.Net/DiscordClient.Messages.cs | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Discord.Net/API/Endpoints.cs b/src/Discord.Net/API/Endpoints.cs index f283d9bae..7e77db7c6 100644 --- a/src/Discord.Net/API/Endpoints.cs +++ b/src/Discord.Net/API/Endpoints.cs @@ -16,6 +16,7 @@ public static string ChannelTyping(string channelId) => $"channels/{channelId}/typing"; public static string ChannelMessages(string channelId) => $"channels/{channelId}/messages"; public static string ChannelMessages(string channelId, int limit) => $"channels/{channelId}/messages?limit={limit}"; + public static string ChannelMessages(string channelId, int limit, string beforeId) => $"channels/{channelId}/messages?limit={limit}&before={beforeId}"; public static string ChannelMessage(string channelId, string msgId) => $"channels/{channelId}/messages/{msgId}"; public static string ChannelMessageAck(string channelId, string msgId) => $"channels/{channelId}/messages/{msgId}/ack"; public static string ChannelInvites(string channelId) => $"channels/{channelId}/invites"; diff --git a/src/Discord.Net/DiscordAPIClient.cs b/src/Discord.Net/DiscordAPIClient.cs index c252667a5..b81792ebb 100644 --- a/src/Discord.Net/DiscordAPIClient.cs +++ b/src/Discord.Net/DiscordAPIClient.cs @@ -92,11 +92,14 @@ namespace Discord var request = new ReorderChannelsRequest(channels); return _rest.Patch(Endpoints.ServerChannels(serverId), request); } - public Task GetMessages(string channelId, int count) + public Task GetMessages(string channelId, int count, string beforeMessageId = null) { if (channelId == null) throw new ArgumentNullException(nameof(channelId)); - return _rest.Get(Endpoints.ChannelMessages(channelId, count)); + if (beforeMessageId != null) + return _rest.Get(Endpoints.ChannelMessages(channelId, count, beforeMessageId)); + else + return _rest.Get(Endpoints.ChannelMessages(channelId, count)); } //Incidents diff --git a/src/Discord.Net/DiscordClient.Messages.cs b/src/Discord.Net/DiscordClient.Messages.cs index 6768e07e2..ebf9e748a 100644 --- a/src/Discord.Net/DiscordClient.Messages.cs +++ b/src/Discord.Net/DiscordClient.Messages.cs @@ -210,7 +210,7 @@ namespace Discord { try { - var msgs = await _api.GetMessages(channel.Id, count).ConfigureAwait(false); + var msgs = await _api.GetMessages(channel.Id, count, beforeMessageId).ConfigureAwait(false); return msgs.Select(x => { Message msg = null; From 3f62cb9e77200957c81b51d9025d7cab9993f44e Mon Sep 17 00:00:00 2001 From: RogueException Date: Mon, 26 Oct 2015 14:33:44 -0300 Subject: [PATCH 12/24] Added kick/ban/unban to DiscordClient --- src/Discord.Net/DiscordClient.Users.cs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/Discord.Net/DiscordClient.Users.cs b/src/Discord.Net/DiscordClient.Users.cs index 2782909c3..41a3f0e5d 100644 --- a/src/Discord.Net/DiscordClient.Users.cs +++ b/src/Discord.Net/DiscordClient.Users.cs @@ -172,6 +172,26 @@ namespace Discord return _api.EditUser(user.Server?.Id, user.Id, mute: mute, deaf: deaf, roles: roles.Select(x => x.Id)); } + public Task KickUser(User user) + { + if (user == null) throw new ArgumentNullException(nameof(user)); + + return _api.KickUser(user.Server?.Id, user.Id); + } + public Task BanUser(User user) + { + if (user == null) throw new ArgumentNullException(nameof(user)); + + return _api.BanUser(user.Server?.Id, user.Id); + } + public Task UnbanUser(Server server, string userId) + { + if (server == null) throw new ArgumentNullException(nameof(server)); + if (userId == null) throw new ArgumentNullException(nameof(userId)); + + return _api.UnbanUser(server.Id, userId); + } + public async Task PruneUsers(string serverId, int days, bool simulate = false) { if (serverId == null) throw new ArgumentNullException(nameof(serverId)); From dc10f95d419acf6964a95bbd81b1eac584593ed0 Mon Sep 17 00:00:00 2001 From: RogueException Date: Mon, 26 Oct 2015 17:11:37 -0300 Subject: [PATCH 13/24] Show user names in log, not their ids. --- src/Discord.Net/DiscordClient.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Discord.Net/DiscordClient.cs b/src/Discord.Net/DiscordClient.cs index 39a280766..ca562a01e 100644 --- a/src/Discord.Net/DiscordClient.cs +++ b/src/Discord.Net/DiscordClient.cs @@ -106,13 +106,13 @@ namespace Discord UserUnbanned += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client, $"Unbanned User: {e.Server?.Name ?? "[Private]"}/{e.UserId}"); UserAdded += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client, - $"User Joined: {e.Server?.Name ?? "[Private]"}/{e.User.Id}"); + $"User Joined: {e.Server?.Name ?? "[Private]"}/{e.User.Name}"); UserRemoved += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client, - $"User Left: {e.Server?.Name ?? "[Private]"}/{e.User.Id}"); + $"User Left: {e.Server?.Name ?? "[Private]"}/{e.User.Name}"); UserUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client, - $"User Updated: {e.Server?.Name ?? "[Private]"}/{e.User.Id}"); + $"User Updated: {e.Server?.Name ?? "[Private]"}/{e.User.Name}"); UserVoiceStateUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client, - $"User Updated (Voice State): {e.Server?.Name ?? "[Private]"}/{e.User.Id}"); + $"User Updated (Voice State): {e.Server?.Name ?? "[Private]"}/{e.User.Name}"); ProfileUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client, "Profile Updated"); } From 4d07686f71a59b35ad23a6430f7a61101b432740 Mon Sep 17 00:00:00 2001 From: RogueException Date: Tue, 27 Oct 2015 02:29:08 -0300 Subject: [PATCH 14/24] Switched User.VoiceChannel to use new reference system --- src/Discord.Net/Models/User.cs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/Discord.Net/Models/User.cs b/src/Discord.Net/Models/User.cs index 3726f6616..1c28c5531 100644 --- a/src/Discord.Net/Models/User.cs +++ b/src/Discord.Net/Models/User.cs @@ -61,7 +61,8 @@ namespace Discord private readonly Reference _server; [JsonIgnore] - public Channel VoiceChannel { get; private set; } + public Channel VoiceChannel => _voiceChannel.Value; + private Reference _voiceChannel; [JsonIgnore] public IEnumerable Roles => _roles.Select(x => x.Value); @@ -130,6 +131,8 @@ namespace Discord if (Id == _client.CurrentUserId) x.CurrentUser = null; }); + _voiceChannel = new Reference(x => _client.Channels[x]); + Status = UserStatus.Offline; _channels = new ConcurrentDictionary(); if (serverId != null) @@ -210,16 +213,16 @@ namespace Discord SessionId = model.SessionId; if (model.Token != null) Token = model.Token; - - if (model.ChannelId != null) - VoiceChannel = _client.Channels[model.ChannelId]; + if (model.IsSelfDeafened != null) IsSelfDeafened = model.IsSelfDeafened.Value; if (model.IsSelfMuted != null) IsSelfMuted = model.IsSelfMuted.Value; if (model.IsServerSuppressed != null) IsServerSuppressed = model.IsServerSuppressed.Value; - } + + _voiceChannel.Id = model.ChannelId; //Can be null + } private void UpdateRoles(IEnumerable roles) { if (_server.Id != null) From bf5d9ec5278dea10d1bd272d81a1271ac3321d1c Mon Sep 17 00:00:00 2001 From: RogueException Date: Tue, 27 Oct 2015 02:50:24 -0300 Subject: [PATCH 15/24] Removed Server.Invites, added DiscordClient.GetInvites(server) --- src/Discord.Net/API/Endpoints.cs | 15 ++++++++------- src/Discord.Net/API/Invites.cs | 2 ++ src/Discord.Net/DiscordAPIClient.cs | 6 ++++++ src/Discord.Net/DiscordClient.Invites.cs | 19 +++++++++++++++++-- src/Discord.Net/Models/Server.cs | 14 -------------- 5 files changed, 33 insertions(+), 23 deletions(-) diff --git a/src/Discord.Net/API/Endpoints.cs b/src/Discord.Net/API/Endpoints.cs index 7e77db7c6..2ff2711bc 100644 --- a/src/Discord.Net/API/Endpoints.cs +++ b/src/Discord.Net/API/Endpoints.cs @@ -13,33 +13,34 @@ public const string Channels = "channels"; public static string Channel(string channelId) => $"channels/{channelId}"; - public static string ChannelTyping(string channelId) => $"channels/{channelId}/typing"; + public static string ChannelInvites(string channelId) => $"channels/{channelId}/invites"; public static string ChannelMessages(string channelId) => $"channels/{channelId}/messages"; public static string ChannelMessages(string channelId, int limit) => $"channels/{channelId}/messages?limit={limit}"; public static string ChannelMessages(string channelId, int limit, string beforeId) => $"channels/{channelId}/messages?limit={limit}&before={beforeId}"; public static string ChannelMessage(string channelId, string msgId) => $"channels/{channelId}/messages/{msgId}"; public static string ChannelMessageAck(string channelId, string msgId) => $"channels/{channelId}/messages/{msgId}/ack"; - public static string ChannelInvites(string channelId) => $"channels/{channelId}/invites"; public static string ChannelPermission(string channelId, string userOrRoleId) => $"channels/{channelId}/permissions/{userOrRoleId}"; + public static string ChannelTyping(string channelId) => $"channels/{channelId}/typing"; public const string Servers = "guilds"; public static string Server(string serverId) => $"guilds/{serverId}"; + public static string ServerBan(string serverId, string userId) => $"guilds/{serverId}/bans/{userId}"; public static string ServerChannels(string serverId) => $"guilds/{serverId}/channels"; + public static string ServerInvites(string serverId) => $"guilds/{serverId}/invites"; public static string ServerMember(string serverId, string userId) => $"guilds/{serverId}/members/{userId}"; - public static string ServerBan(string serverId, string userId) => $"guilds/{serverId}/bans/{userId}"; + public static string ServerPrune(string serverId, int days) => $"guilds/{serverId}/prune?days={days}"; public static string ServerRoles(string serverId) => $"guilds/{serverId}/roles"; public static string ServerRole(string serverId, string roleId) => $"guilds/{serverId}/roles/{roleId}"; - public static string ServerPrune(string serverId, int days) => $"guilds/{serverId}/prune?days={days}"; public const string Invites = "invite"; public static string Invite(string inviteId) => $"invite/{inviteId}"; public static string InviteUrl(string inviteId) => $"https://discord.gg/{inviteId}"; public const string Users = "users"; - public static string UserMe => $"users/@me"; - public static string UserChannels(string userId) => $"users/{userId}/channels"; public static string UserAvatar(string userId, string avatarId) => $"users/{userId}/avatars/{avatarId}.jpg"; - + public static string UserChannels(string userId) => $"users/{userId}/channels"; + public static string UserMe => $"users/@me"; + public const string Voice = "voice"; public const string VoiceRegions = "voice/regions"; //public const string VoiceIce = "voice/ice"; diff --git a/src/Discord.Net/API/Invites.cs b/src/Discord.Net/API/Invites.cs index 62d2049b3..d2344dae2 100644 --- a/src/Discord.Net/API/Invites.cs +++ b/src/Discord.Net/API/Invites.cs @@ -4,6 +4,7 @@ using Newtonsoft.Json; using System; +using System.Collections.Generic; namespace Discord.API { @@ -53,6 +54,7 @@ namespace Discord.API //Get public class GetInviteResponse : InviteReference { } + public class GetInvitesResponse : List { } //Accept public class AcceptInviteResponse : InviteReference { } diff --git a/src/Discord.Net/DiscordAPIClient.cs b/src/Discord.Net/DiscordAPIClient.cs index b81792ebb..f547d81f7 100644 --- a/src/Discord.Net/DiscordAPIClient.cs +++ b/src/Discord.Net/DiscordAPIClient.cs @@ -126,6 +126,12 @@ namespace Discord return _rest.Get(Endpoints.Invite(inviteIdOrXkcd)); } + public Task GetInvites(string serverId) + { + if (serverId == null) throw new ArgumentNullException(nameof(serverId)); + + return _rest.Get(Endpoints.ServerInvites(serverId)); + } public Task AcceptInvite(string inviteId) { if (inviteId == null) throw new ArgumentNullException(nameof(inviteId)); diff --git a/src/Discord.Net/DiscordClient.Invites.cs b/src/Discord.Net/DiscordClient.Invites.cs index 027257d9b..0d3b8804e 100644 --- a/src/Discord.Net/DiscordClient.Invites.cs +++ b/src/Discord.Net/DiscordClient.Invites.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Net; using System.Threading.Tasks; @@ -10,8 +11,6 @@ namespace Discord /// Supported formats: inviteCode, xkcdCode, https://discord.gg/inviteCode, https://discord.gg/xkcdCode public async Task GetInvite(string inviteIdOrXkcd) { - //This doesn't work well if it's an invite to a different server! - if (inviteIdOrXkcd == null) throw new ArgumentNullException(nameof(inviteIdOrXkcd)); CheckReady(); @@ -30,6 +29,22 @@ namespace Discord return invite; } + /// Gets all active (non-expired) invites to a provided server. + public async Task GetInvites(Server server) + { + if (server == null) throw new ArgumentNullException(nameof(server)); + CheckReady(); + + var response = await _api.GetInvites(server.Id).ConfigureAwait(false); + return response.Select(x => + { + var invite = new Invite(this, x.Code, x.XkcdPass, x.Guild.Id, x.Inviter?.Id, x.Channel?.Id); + invite.Cache(); //Builds references + invite.Update(x); + return invite; + }).ToArray(); + } + /// Creates a new invite to the default channel of the provided server. /// Time (in seconds) until the invite expires. Set to 0 to never expire. /// If true, a user accepting this invite will be kicked from the server after closing their client. diff --git a/src/Discord.Net/Models/Server.cs b/src/Discord.Net/Models/Server.cs index f614be04e..602f01db0 100644 --- a/src/Discord.Net/Models/Server.cs +++ b/src/Discord.Net/Models/Server.cs @@ -55,11 +55,6 @@ namespace Discord public IEnumerable VoiceChannels => _channels.Select(x => x.Value).Where(x => x.Type == ChannelType.Voice); private ConcurrentDictionary _channels; - /// Returns a collection of all invites to this server. - [JsonIgnore] - public IEnumerable Invites => _invites.Values; - private ConcurrentDictionary _invites; - /// Returns a collection of all users within this server with their server-specific data. [JsonIgnore] public IEnumerable Members => _members.Select(x => x.Value); @@ -85,7 +80,6 @@ namespace Discord //Local Cache _bans = new ConcurrentDictionary(); - _invites = new ConcurrentDictionary(); } internal override void LoadReferences() { @@ -113,11 +107,6 @@ namespace Discord roles.Clear(); //Local Cache - var invites = _invites; - foreach (var invite in invites) - invite.Value.Uncache(); - invites.Clear(); - _bans.Clear(); _afkChannel.Unload(); @@ -218,9 +207,6 @@ namespace Discord _channels.TryRemove(channel.Id, out channel); } - internal void AddInvite(Invite invite) => _invites.TryAdd(invite.Id, invite); - internal void RemoveInvite(Invite invite) => _invites.TryRemove(invite.Id, out invite); - internal void AddMember(User user) { if (_members.TryAdd(user.Id, user)) From ad81e76c5e3c72f283733a23cdc740bbf8a8e3cc Mon Sep 17 00:00:00 2001 From: RogueException Date: Tue, 27 Oct 2015 10:49:38 -0300 Subject: [PATCH 16/24] Added message length check. --- src/Discord.Net/DiscordClient.Messages.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Discord.Net/DiscordClient.Messages.cs b/src/Discord.Net/DiscordClient.Messages.cs index ebf9e748a..28b3c068c 100644 --- a/src/Discord.Net/DiscordClient.Messages.cs +++ b/src/Discord.Net/DiscordClient.Messages.cs @@ -93,6 +93,7 @@ namespace Discord { if (channel == null) throw new ArgumentNullException(nameof(channel)); if (text == null) throw new ArgumentNullException(nameof(text)); + if (text.Length > MaxMessageSize) throw new ArgumentOutOfRangeException(nameof(text), $"Message must be {MaxMessageSize} characters or less."); CheckReady(); return SendMessage(channel, text, false); @@ -102,6 +103,7 @@ namespace Discord { if (channel == null) throw new ArgumentNullException(nameof(channel)); if (text == null) throw new ArgumentNullException(nameof(text)); + if (text.Length > MaxMessageSize) throw new ArgumentOutOfRangeException(nameof(text), $"Message must be {MaxMessageSize} characters or less."); CheckReady(); return SendMessage(channel, text, false); @@ -111,7 +113,8 @@ namespace Discord { if (user == null) throw new ArgumentNullException(nameof(user)); if (text == null) throw new ArgumentNullException(nameof(text)); - CheckReady(); + if (text.Length > MaxMessageSize) throw new ArgumentOutOfRangeException(nameof(text), $"Message must be {MaxMessageSize} characters or less."); + CheckReady(); var channel = await CreatePMChannel(user).ConfigureAwait(false); return await SendMessage(channel, text).ConfigureAwait(false); @@ -164,6 +167,8 @@ namespace Discord public Task EditMessage(Message message, string text) { if (message == null) throw new ArgumentNullException(nameof(message)); + if (text == null) throw new ArgumentNullException(nameof(text)); + if (text.Length > MaxMessageSize) throw new ArgumentOutOfRangeException(nameof(text), $"Message must be {MaxMessageSize} characters or less."); CheckReady(); if (text != null && text.Length > MaxMessageSize) From bde4176dc2692dcfe4fd6fe1984e5c515e3a6230 Mon Sep 17 00:00:00 2001 From: Brandon Smith Date: Tue, 27 Oct 2015 14:21:03 -0300 Subject: [PATCH 17/24] Added support for GUILD_MEMBERS_CHUNK --- src/Discord.Net/API/Members.cs | 7 ++++++- src/Discord.Net/DiscordClient.cs | 11 +++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/Discord.Net/API/Members.cs b/src/Discord.Net/API/Members.cs index 9e69390c6..1f702719e 100644 --- a/src/Discord.Net/API/Members.cs +++ b/src/Discord.Net/API/Members.cs @@ -92,5 +92,10 @@ namespace Discord.API internal sealed class MemberAddEvent : MemberInfo { } internal sealed class MemberUpdateEvent : MemberInfo { } internal sealed class MemberRemoveEvent : MemberInfo { } - internal sealed class MemberVoiceStateUpdateEvent : VoiceMemberInfo { } + internal sealed class MemberVoiceStateUpdateEvent : VoiceMemberInfo { } + internal sealed class MembersChunkEvent + { + [JsonProperty("members")] + public MemberInfo[] Members; + } } diff --git a/src/Discord.Net/DiscordClient.cs b/src/Discord.Net/DiscordClient.cs index 39a280766..bef7a8986 100644 --- a/src/Discord.Net/DiscordClient.cs +++ b/src/Discord.Net/DiscordClient.cs @@ -418,6 +418,17 @@ namespace Discord RaiseUserRemoved(user); } break; + case "GUILD_MEMBERS_CHUNK": + { + var data = e.Payload.ToObject(_serializer); + foreach (var memberData in data.Members) + { + var user = _users.GetOrAdd(memberData.User.Id, memberData.GuildId); + user.Update(memberData); + //RaiseUserAdded(user); + } + } + break; //Roles case "GUILD_ROLE_CREATE": From d710b5d0fcc2a4fe9c13e3f1d9743cb55e570936 Mon Sep 17 00:00:00 2001 From: Brandon Smith Date: Tue, 27 Oct 2015 14:27:32 -0300 Subject: [PATCH 18/24] Added opcode 8 --- src/Discord.Net/API/Messages.cs | 15 +++++++++++++++ src/Discord.Net/DiscordClient.Users.cs | 8 ++++++++ src/Discord.Net/Net/WebSockets/DataWebSocket.cs | 6 ++++++ 3 files changed, 29 insertions(+) diff --git a/src/Discord.Net/API/Messages.cs b/src/Discord.Net/API/Messages.cs index 8fc031dd1..a5edb27ec 100644 --- a/src/Discord.Net/API/Messages.cs +++ b/src/Discord.Net/API/Messages.cs @@ -125,6 +125,21 @@ namespace Discord.API //Get public sealed class GetMessagesResponse : List { } + //Commands + internal sealed class GetUsersCommand : WebSocketMessage + { + public GetUsersCommand() : base(8) { } + public class Data + { + [JsonProperty("guild_id")] + public string ServerId; + [JsonProperty("query")] + public string Query; + [JsonProperty("limit")] + public int Limit; + } + } + //Events internal sealed class MessageCreateEvent : MessageInfo { } internal sealed class MessageUpdateEvent : MessageInfo { } diff --git a/src/Discord.Net/DiscordClient.Users.cs b/src/Discord.Net/DiscordClient.Users.cs index 2782909c3..fe75b6358 100644 --- a/src/Discord.Net/DiscordClient.Users.cs +++ b/src/Discord.Net/DiscordClient.Users.cs @@ -182,6 +182,14 @@ namespace Discord return response.Pruned ?? 0; } + /// When Config.UseLargeThreshold is enabled, running this command will request the Discord server to provide you with all offline users for a particular server. + public void RequestOfflineUsers(string serverId) + { + if (serverId == null) throw new ArgumentNullException(nameof(serverId)); + + _dataSocket.SendGetUsers(serverId); + } + public Task EditProfile(string currentPassword = "", string username = null, string email = null, string password = null, ImageType avatarType = ImageType.Png, byte[] avatar = null) diff --git a/src/Discord.Net/Net/WebSockets/DataWebSocket.cs b/src/Discord.Net/Net/WebSockets/DataWebSocket.cs index 49d368748..3db1c1a93 100644 --- a/src/Discord.Net/Net/WebSockets/DataWebSocket.cs +++ b/src/Discord.Net/Net/WebSockets/DataWebSocket.cs @@ -141,5 +141,11 @@ namespace Discord.Net.WebSockets leaveVoice.Payload.ServerId = serverId; QueueMessage(leaveVoice); } + public void SendGetUsers(string serverId, string query = "", int limit = 0) + { + var getOfflineUsers = new GetUsersCommand(); + getOfflineUsers.Payload.ServerId = serverId; + QueueMessage(getOfflineUsers); + } } } From dd7e570b6042f08f22b4c91fef44cfa8497b0d21 Mon Sep 17 00:00:00 2001 From: Brandon Smith Date: Tue, 27 Oct 2015 14:55:47 -0300 Subject: [PATCH 19/24] Bumped LargeThreshold up to 100 when enabled, to match client behavor --- src/Discord.Net/Net/WebSockets/DataWebSocket.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Discord.Net/Net/WebSockets/DataWebSocket.cs b/src/Discord.Net/Net/WebSockets/DataWebSocket.cs index 3db1c1a93..7e59565d7 100644 --- a/src/Discord.Net/Net/WebSockets/DataWebSocket.cs +++ b/src/Discord.Net/Net/WebSockets/DataWebSocket.cs @@ -27,7 +27,7 @@ namespace Discord.Net.WebSockets msg.Payload.Token = token; msg.Payload.Properties["$device"] = "Discord.Net"; if (_client.Config.UseLargeThreshold) - msg.Payload.LargeThreshold = 50; + msg.Payload.LargeThreshold = 100; msg.Payload.Compress = true; QueueMessage(msg); } From de1472160c9919b9c192a2f07535be48d238eeb1 Mon Sep 17 00:00:00 2001 From: Brandon Smith Date: Tue, 27 Oct 2015 20:47:34 -0300 Subject: [PATCH 20/24] Dont send the everyone role in EditUser --- src/Discord.Net/DiscordClient.Users.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Discord.Net/DiscordClient.Users.cs b/src/Discord.Net/DiscordClient.Users.cs index dad44fc63..21e257b0a 100644 --- a/src/Discord.Net/DiscordClient.Users.cs +++ b/src/Discord.Net/DiscordClient.Users.cs @@ -169,7 +169,10 @@ namespace Discord if (user == null) throw new ArgumentNullException(nameof(user)); CheckReady(); - return _api.EditUser(user.Server?.Id, user.Id, mute: mute, deaf: deaf, roles: roles.Select(x => x.Id)); + var everyoneId = user.Server.Id; + return _api.EditUser(user.Server?.Id, user.Id, + mute: mute, deaf: deaf, + roles: roles.Select(x => x.Id).Where(x => x != everyoneId)); } public Task KickUser(User user) From 3c0cef43617fc28003e79dacd5cf66d9ae4e3e49 Mon Sep 17 00:00:00 2001 From: Brandon Smith Date: Tue, 27 Oct 2015 20:51:48 -0300 Subject: [PATCH 21/24] Dont nullref if EditUser is called in a private channel. --- src/Discord.Net/DiscordClient.Users.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Discord.Net/DiscordClient.Users.cs b/src/Discord.Net/DiscordClient.Users.cs index 21e257b0a..e63fd04c1 100644 --- a/src/Discord.Net/DiscordClient.Users.cs +++ b/src/Discord.Net/DiscordClient.Users.cs @@ -169,10 +169,10 @@ namespace Discord if (user == null) throw new ArgumentNullException(nameof(user)); CheckReady(); - var everyoneId = user.Server.Id; - return _api.EditUser(user.Server?.Id, user.Id, + var serverId = user.Server?.Id; + return _api.EditUser(serverId, user.Id, mute: mute, deaf: deaf, - roles: roles.Select(x => x.Id).Where(x => x != everyoneId)); + roles: roles.Select(x => x.Id).Where(x => x != serverId)); } public Task KickUser(User user) From 3e5a6b2b32a15f95e72dece232ebb8e3d341c3b1 Mon Sep 17 00:00:00 2001 From: Brandon Smith Date: Tue, 27 Oct 2015 14:55:47 -0300 Subject: [PATCH 22/24] Bumped LargeThreshold up to 100 when enabled, to match client behavor --- src/Discord.Net/Net/WebSockets/DataWebSocket.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Discord.Net/Net/WebSockets/DataWebSocket.cs b/src/Discord.Net/Net/WebSockets/DataWebSocket.cs index 3db1c1a93..7e59565d7 100644 --- a/src/Discord.Net/Net/WebSockets/DataWebSocket.cs +++ b/src/Discord.Net/Net/WebSockets/DataWebSocket.cs @@ -27,7 +27,7 @@ namespace Discord.Net.WebSockets msg.Payload.Token = token; msg.Payload.Properties["$device"] = "Discord.Net"; if (_client.Config.UseLargeThreshold) - msg.Payload.LargeThreshold = 50; + msg.Payload.LargeThreshold = 100; msg.Payload.Compress = true; QueueMessage(msg); } From e162abc9ef81026641aacae65fdcb89be66f946d Mon Sep 17 00:00:00 2001 From: Brandon Smith Date: Tue, 27 Oct 2015 20:47:34 -0300 Subject: [PATCH 23/24] Dont send the everyone role in EditUser --- src/Discord.Net/DiscordClient.Users.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Discord.Net/DiscordClient.Users.cs b/src/Discord.Net/DiscordClient.Users.cs index dad44fc63..21e257b0a 100644 --- a/src/Discord.Net/DiscordClient.Users.cs +++ b/src/Discord.Net/DiscordClient.Users.cs @@ -169,7 +169,10 @@ namespace Discord if (user == null) throw new ArgumentNullException(nameof(user)); CheckReady(); - return _api.EditUser(user.Server?.Id, user.Id, mute: mute, deaf: deaf, roles: roles.Select(x => x.Id)); + var everyoneId = user.Server.Id; + return _api.EditUser(user.Server?.Id, user.Id, + mute: mute, deaf: deaf, + roles: roles.Select(x => x.Id).Where(x => x != everyoneId)); } public Task KickUser(User user) From 229f2ee7fbbcad3aa27374217685e32f7a2469a2 Mon Sep 17 00:00:00 2001 From: Brandon Smith Date: Tue, 27 Oct 2015 20:51:48 -0300 Subject: [PATCH 24/24] Dont nullref if EditUser is called in a private channel. --- src/Discord.Net/DiscordClient.Users.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Discord.Net/DiscordClient.Users.cs b/src/Discord.Net/DiscordClient.Users.cs index 21e257b0a..e63fd04c1 100644 --- a/src/Discord.Net/DiscordClient.Users.cs +++ b/src/Discord.Net/DiscordClient.Users.cs @@ -169,10 +169,10 @@ namespace Discord if (user == null) throw new ArgumentNullException(nameof(user)); CheckReady(); - var everyoneId = user.Server.Id; - return _api.EditUser(user.Server?.Id, user.Id, + var serverId = user.Server?.Id; + return _api.EditUser(serverId, user.Id, mute: mute, deaf: deaf, - roles: roles.Select(x => x.Id).Where(x => x != everyoneId)); + roles: roles.Select(x => x.Id).Where(x => x != serverId)); } public Task KickUser(User user)