diff --git a/Discord.Net.sln b/Discord.Net.sln index 16724d0a9..c1cd9bfcb 100644 --- a/Discord.Net.sln +++ b/Discord.Net.sln @@ -9,6 +9,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution ProjectSection(SolutionItems) = preProject .gitignore = .gitignore LICENSE = LICENSE + README.md = README.md EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Discord.Net.Tests", "Discord.Net.Tests\Discord.Net.Tests.csproj", "{855D6B1D-847B-42DA-BE6A-23683EA89511}" diff --git a/Discord.Net/API/DiscordAPI.cs b/Discord.Net/API/DiscordAPI.cs index dd50bcfe9..e3f356508 100644 --- a/Discord.Net/API/DiscordAPI.cs +++ b/Discord.Net/API/DiscordAPI.cs @@ -43,6 +43,20 @@ namespace Discord.API return Http.Get(Endpoints.ChannelMessages(channelId, 50), options); } + //Members + public static Task Kick(string serverId, string memberId, HttpOptions options) + { + return Http.Delete(Endpoints.ServerMember(serverId, memberId), options); + } + public static Task Ban(string serverId, string memberId, HttpOptions options) + { + return Http.Put(Endpoints.ServerBan(serverId, memberId), options); + } + public static Task Unban(string serverId, string memberId, HttpOptions options) + { + return Http.Delete(Endpoints.ServerBan(serverId, memberId), options); + } + //Invites public static Task CreateInvite(string channelId, int maxAge, int maxUses, bool isTemporary, bool hasXkcdPass, HttpOptions options) { @@ -82,5 +96,25 @@ namespace Discord.API { return Http.Get(Endpoints.VoiceIce, options); } - } + public static Task Mute(string serverId, string memberId, HttpOptions options) + { + var request = new APIRequests.SetMemberMute { Mute = true }; + return Http.Patch(Endpoints.ServerMember(serverId, memberId), options); + } + public static Task Unmute(string serverId, string memberId, HttpOptions options) + { + var request = new APIRequests.SetMemberMute { Mute = false }; + return Http.Patch(Endpoints.ServerMember(serverId, memberId), options); + } + public static Task Deafen(string serverId, string memberId, HttpOptions options) + { + var request = new APIRequests.SetMemberDeaf { Deaf = true }; + return Http.Patch(Endpoints.ServerMember(serverId, memberId), options); + } + public static Task Undeafen(string serverId, string memberId, HttpOptions options) + { + var request = new APIRequests.SetMemberDeaf { Deaf = false }; + return Http.Patch(Endpoints.ServerMember(serverId, memberId), options); + } + } } diff --git a/Discord.Net/API/Endpoints.cs b/Discord.Net/API/Endpoints.cs index e505ceb46..9f1780935 100644 --- a/Discord.Net/API/Endpoints.cs +++ b/Discord.Net/API/Endpoints.cs @@ -18,19 +18,21 @@ // /api/guilds public static readonly string Servers = $"{BaseApi}/guilds"; - public static string Server(string id) { return $"{Servers}/{id}"; } + public static string Server(string id) => $"{Servers}/{id}"; + public static string ServerMember(string serverId, string userId) => $"{Servers}/{serverId}/members/{userId}"; + public static string ServerBan(string serverId, string userId) => $"{Servers}/{serverId}/bans/{userId}"; - // /api/guilds + // /api/invites public static readonly string Invites = $"{BaseApi}/invite"; - public static string Invite(string id) { return $"{Invites}/{id}"; } + public static string Invite(string id) => $"{Invites}/{id}"; // /api/channels public static readonly string Channels = $"{BaseApi}/channels"; - public static string Channel(string id) { return $"{Channels}/{id}"; } - public static string ChannelTyping(string id) { return $"{Channels}/{id}/typing"; } - public static string ChannelMessages(string id) { return $"{Channels}/{id}/messages"; } - public static string ChannelMessages(string id, int limit) { return $"{Channels}/{id}/messages?limit={limit}"; } - public static string ChannelInvites(string id) { return $"{Channels}/{id}/invites"; } + public static string Channel(string id) => $"{Channels}/{id}"; + public static string ChannelTyping(string id) => $"{Channels}/{id}/typing"; + public static string ChannelMessages(string id) => $"{Channels}/{id}/messages"; + public static string ChannelMessages(string id, int limit) => $"{Channels}/{id}/messages?limit={limit}"; + public static string ChannelInvites(string id) => $"{Channels}/{id}/invites"; // /api/voice public static readonly string Voice = $"{BaseApi}/voice"; diff --git a/Discord.Net/API/Models/ApiRequests.cs b/Discord.Net/API/Models/ApiRequests.cs index 96b0be614..8f61f5796 100644 --- a/Discord.Net/API/Models/ApiRequests.cs +++ b/Discord.Net/API/Models/ApiRequests.cs @@ -50,5 +50,16 @@ namespace Discord.API.Models [JsonProperty(PropertyName = "mentions")] public string[] Mentions; } + + public class SetMemberMute + { + [JsonProperty(PropertyName = "mute")] + public bool Mute; + } + public class SetMemberDeaf + { + [JsonProperty(PropertyName = "deaf")] + public bool Deaf; + } } } diff --git a/Discord.Net/DiscordClient.cs b/Discord.Net/DiscordClient.cs index a8c86e343..734b69991 100644 --- a/Discord.Net/DiscordClient.cs +++ b/Discord.Net/DiscordClient.cs @@ -26,18 +26,23 @@ namespace Discord public IEnumerable Users { get { return _users; } } private AsyncCache _users; + public User GetUser(string id) => _users[id]; public IEnumerable Servers { get { return _servers; } } private AsyncCache _servers; + public Server GetServer(string id) => _servers[id]; public IEnumerable Channels { get { return _channels; } } private AsyncCache _channels; + public Channel GetChannel(string id) => _channels[id]; public IEnumerable Messages { get { return _messages; } } private AsyncCache _messages; + public Message GetMessage(string id) => _messages[id]; public IEnumerable Roles { get { return _roles; } } private AsyncCache _roles; + public Role GetRole(string id) => _roles[id]; public bool IsConnected { get { return _isReady; } } @@ -267,14 +272,14 @@ namespace Discord case "GUILD_ROLE_CREATE": { var data = e.Event.ToObject(); - var role = UpdateRole(data); + var role = _roles.Update(data.Role.Id, data.Role); RaiseRoleCreated(role); } break; case "GUILD_ROLE_UPDATE": { var data = e.Event.ToObject(); - var role = UpdateRole(data); + var role = _roles.Update(data.Role.Id, data.Role); RaiseRoleUpdated(role); } break; @@ -412,9 +417,7 @@ namespace Discord return _servers.Update(response.Id, response); } public Task LeaveServer(Server server) - { - return LeaveServer(server.Id); - } + => LeaveServer(server.Id); public async Task LeaveServer(string id) { CheckReady(); @@ -422,6 +425,31 @@ namespace Discord return _servers.Remove(id); } + //Bans + public Task Ban(Server server, User user) + => Ban(server.Id, user.Id); + public Task Ban(Server server, string userId) + => Ban(server.Id, userId); + public Task Ban(string server, User user) + => Ban(server, user.Id); + public Task Ban(string serverId, string userId) + { + CheckReady(); + return DiscordAPI.Ban(serverId, userId, _httpOptions); + } + public Task Unban(Server server, User user) + => Unban(server.Id, user.Id); + public Task Unban(Server server, string userId) + => Unban(server.Id, userId); + public Task Unban(string server, User user) + => Unban(server, user.Id); + public Task Unban(string serverId, string userId) + { + CheckReady(); + return DiscordAPI.Unban(serverId, userId, _httpOptions); + } + + //Invites public Task CreateInvite(Server server, int maxAge, int maxUses, bool isTemporary, bool hasXkcdPass) { @@ -503,34 +531,53 @@ namespace Discord } } - public Server GetServer(string id) - { - return _servers[id]; - } - public Channel GetChannel(string id) + //Voice + public Task Mute(Server server, User user) + => Mute(server.Id, user.Id); + public Task Mute(Server server, string userId) + => Mute(server.Id, userId); + public Task Mute(string server, User user) + => Mute(server, user.Id); + public Task Mute(string serverId, string userId) { - return _channels[id]; - } - public User GetUser(string id) - { - return _users[id]; + CheckReady(); + return DiscordAPI.Mute(serverId, userId, _httpOptions); } - public Models.Message GetMessage(string id) + + public Task Unmute(Server server, User user) + => Unmute(server.Id, user.Id); + public Task Unmute(Server server, string userId) + => Unmute(server.Id, userId); + public Task Unmute(string server, User user) + => Unmute(server, user.Id); + public Task Unmute(string serverId, string userId) { - return _messages[id]; + CheckReady(); + return DiscordAPI.Unmute(serverId, userId, _httpOptions); } - public Role GetRole(string id) + + public Task Deafen(Server server, User user) + => Deafen(server.Id, user.Id); + public Task Deafen(Server server, string userId) + => Deafen(server.Id, userId); + public Task Deafen(string server, User user) + => Deafen(server, user.Id); + public Task Deafen(string serverId, string userId) { - return _roles[id]; + CheckReady(); + return DiscordAPI.Deafen(serverId, userId, _httpOptions); } - - private Role UpdateRole(WebSocketEvents.GuildRoleCreateUpdate role, bool addNew = true) + + public Task Undeafen(Server server, User user) + => Undeafen(server.Id, user.Id); + public Task Undeafen(Server server, string userId) + => Undeafen(server.Id, userId); + public Task Undeafen(string server, User user) + => Undeafen(server, user.Id); + public Task Undeafen(string serverId, string userId) { - return new Role(role.Role.Id, role.GuildId, this) - { - Name = role.Role.Name, - Permissions = role.Role.Permissions - }; + CheckReady(); + return DiscordAPI.Undeafen(serverId, userId, _httpOptions); } private void CheckReady() diff --git a/Discord.Net/Helpers/Http.cs b/Discord.Net/Helpers/Http.cs index 72775b231..fe8e2cb22 100644 --- a/Discord.Net/Helpers/Http.cs +++ b/Discord.Net/Helpers/Http.cs @@ -30,32 +30,63 @@ namespace Discord.Helpers #else private const bool _isDebug = false; #endif + + internal static Task Get(string path, object data, HttpOptions options) + where ResponseT : class + => Send("GET", path, data, options); + internal static Task Get(string path, object data, HttpOptions options) + => Send("GET", path, data, options); + internal static Task Get(string path, HttpOptions options) + where ResponseT : class + => Send("GET", path, null, options); + internal static Task Get(string path, HttpOptions options) + => Send("GET", path, null, options); + + internal static Task Post(string path, object data, HttpOptions options) + where ResponseT : class + => Send("POST", path, data, options); + internal static Task Post(string path, object data, HttpOptions options) + => Send("POST", path, data, options); + internal static Task Post(string path, HttpOptions options) + where ResponseT : class + => Send("POST", path, null, options); + internal static Task Post(string path, HttpOptions options) + => Send("POST", path, null, options); + + internal static Task Put(string path, object data, HttpOptions options) + where ResponseT : class + => Send("PUT", path, data, options); + internal static Task Put(string path, object data, HttpOptions options) + => Send("PUT", path, data, options); + internal static Task Put(string path, HttpOptions options) + where ResponseT : class + => Send("PUT", path, null, options); + internal static Task Put(string path, HttpOptions options) + => Send("PUT", path, null, options); - //GET - internal static async Task Get(string path, object data, HttpOptions options) + internal static Task Patch(string path, object data, HttpOptions options) where ResponseT : class - { - string requestJson = JsonConvert.SerializeObject(data); - string responseJson = await SendRequest("GET", path, requestJson, options, true); - var response = JsonConvert.DeserializeObject(responseJson); -#if DEBUG - CheckResponse(responseJson, response); -#endif - return response; - } - internal static async Task Get(string path, HttpOptions options) + => Send("PATCH", path, data, options); + internal static Task Patch(string path, object data, HttpOptions options) + => Send("PATCH", path, data, options); + internal static Task Patch(string path, HttpOptions options) where ResponseT : class - { - string responseJson = await SendRequest("GET", path, null, options, true); - var response = JsonConvert.DeserializeObject(responseJson); -#if DEBUG - CheckResponse(responseJson, response); -#endif - return response; - } + => Send("PATCH", path, null, options); + internal static Task Patch(string path, HttpOptions options) + => Send("PATCH", path, null, options); - //POST - internal static async Task Post(string path, object data, HttpOptions options) + internal static Task Delete(string path, object data, HttpOptions options) + where ResponseT : class + => Send("DELETE", path, data, options); + internal static Task Delete(string path, object data, HttpOptions options) + => Send("DELETE", path, data, options); + internal static Task Delete(string path, HttpOptions options) + where ResponseT : class + => Send("DELETE", path, null, options); + internal static Task Delete(string path, HttpOptions options) + => Send("DELETE", path, null, options); + + internal static async Task Send(string method, string path, object data, HttpOptions options) where ResponseT : class { string requestJson = JsonConvert.SerializeObject(data); @@ -66,7 +97,7 @@ namespace Discord.Helpers #endif return response; } - internal static async Task Post(string path, object data, HttpOptions options) + internal static async Task Send(string method, string path, object data, HttpOptions options) { string requestJson = JsonConvert.SerializeObject(data); string responseJson = await SendRequest("POST", path, requestJson, options, _isDebug); @@ -75,7 +106,7 @@ namespace Discord.Helpers #endif return responseJson; } - internal static async Task Post(string path, HttpOptions options) + internal static async Task Send(string method, string path, HttpOptions options) where ResponseT : class { string responseJson = await SendRequest("POST", path, null, options, true); @@ -85,7 +116,7 @@ namespace Discord.Helpers #endif return response; } - internal static async Task Post(string path, HttpOptions options) + internal static async Task Send(string method, string path, HttpOptions options) { string responseJson = await SendRequest("POST", path, null, options, _isDebug); #if DEBUG @@ -94,26 +125,6 @@ namespace Discord.Helpers return responseJson; } - //DELETE - internal static async Task Delete(string path, HttpOptions options) - where ResponseT : class - { - string responseJson = await SendRequest("DELETE", path, null, options, true); - var response = JsonConvert.DeserializeObject(responseJson); -#if DEBUG - CheckResponse(responseJson, response); -#endif - return response; - } - internal static async Task Delete(string path, HttpOptions options) - { - string responseJson = await SendRequest("DELETE", path, null, options, _isDebug); -#if DEBUG - CheckEmptyResponse(responseJson); -#endif - return responseJson; - } - private static async Task SendRequest(string method, string path, string data, HttpOptions options, bool hasResponse) { options = options ?? new HttpOptions(); diff --git a/Discord.Net/Properties/AssemblyInfo.cs b/Discord.Net/Properties/AssemblyInfo.cs index a375c505f..9db51651b 100644 --- a/Discord.Net/Properties/AssemblyInfo.cs +++ b/Discord.Net/Properties/AssemblyInfo.cs @@ -1,7 +1,7 @@ using System.Reflection; [assembly: AssemblyTitle("Discord.Net")] -[assembly: AssemblyDescription("A .Net API wrapper for the Discord client")] +[assembly: AssemblyDescription("A .Net API wrapper for the Discord client.")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("RogueException")] [assembly: AssemblyProduct("Discord.Net")] diff --git a/README.md b/README.md index 721684fc8..03b7cdc9f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Discord.Net +# Discord.Net v0.2 A .Net API Wrapper for the Discord client (http://discordapp.com). ## This is an alpha! @@ -6,18 +6,16 @@ The Discord API is still in active development, meaning this library may break a Discord.Net is also in early development so several functions may be unstable or not work at all. # Features -- Login/Logout (account or anonymous) -- Accepting Invites (standard or human readable) -- Deleting Invites +- Login/Logout (with credentials or anonymous) +- Accepting/Creating/Deleting Invites (standard or human readable) - Receiving/Sending Messages - Creating/Destroying Servers - Creating/Destroying Channels +- Kick/Ban/Unban/Mute/Unmute/Deafen/Undeafen Users - Several Discord Events # Upcoming - Modifying User/Channel/Server Settings -- Creating Invites -- Kick/Ban/Unban/Mute/Unmute/Deafen/Undeafen - Sending Private Messages # Example (Echo Client)