| @@ -9,6 +9,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution | |||||
| ProjectSection(SolutionItems) = preProject | ProjectSection(SolutionItems) = preProject | ||||
| .gitignore = .gitignore | .gitignore = .gitignore | ||||
| LICENSE = LICENSE | LICENSE = LICENSE | ||||
| README.md = README.md | |||||
| EndProjectSection | EndProjectSection | ||||
| EndProject | EndProject | ||||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Discord.Net.Tests", "Discord.Net.Tests\Discord.Net.Tests.csproj", "{855D6B1D-847B-42DA-BE6A-23683EA89511}" | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Discord.Net.Tests", "Discord.Net.Tests\Discord.Net.Tests.csproj", "{855D6B1D-847B-42DA-BE6A-23683EA89511}" | ||||
| @@ -43,6 +43,20 @@ namespace Discord.API | |||||
| return Http.Get<APIResponses.GetMessages[]>(Endpoints.ChannelMessages(channelId, 50), options); | return Http.Get<APIResponses.GetMessages[]>(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 | //Invites | ||||
| public static Task<APIResponses.CreateInvite> CreateInvite(string channelId, int maxAge, int maxUses, bool isTemporary, bool hasXkcdPass, HttpOptions options) | public static Task<APIResponses.CreateInvite> CreateInvite(string channelId, int maxAge, int maxUses, bool isTemporary, bool hasXkcdPass, HttpOptions options) | ||||
| { | { | ||||
| @@ -82,5 +96,25 @@ namespace Discord.API | |||||
| { | { | ||||
| return Http.Get<APIResponses.GetIce>(Endpoints.VoiceIce, options); | return Http.Get<APIResponses.GetIce>(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); | |||||
| } | |||||
| } | |||||
| } | } | ||||
| @@ -18,19 +18,21 @@ | |||||
| // /api/guilds | // /api/guilds | ||||
| public static readonly string Servers = $"{BaseApi}/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 readonly string Invites = $"{BaseApi}/invite"; | ||||
| public static string Invite(string id) { return $"{Invites}/{id}"; } | |||||
| public static string Invite(string id) => $"{Invites}/{id}"; | |||||
| // /api/channels | // /api/channels | ||||
| public static readonly string Channels = $"{BaseApi}/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 | // /api/voice | ||||
| public static readonly string Voice = $"{BaseApi}/voice"; | public static readonly string Voice = $"{BaseApi}/voice"; | ||||
| @@ -50,5 +50,16 @@ namespace Discord.API.Models | |||||
| [JsonProperty(PropertyName = "mentions")] | [JsonProperty(PropertyName = "mentions")] | ||||
| public string[] Mentions; | public string[] Mentions; | ||||
| } | } | ||||
| public class SetMemberMute | |||||
| { | |||||
| [JsonProperty(PropertyName = "mute")] | |||||
| public bool Mute; | |||||
| } | |||||
| public class SetMemberDeaf | |||||
| { | |||||
| [JsonProperty(PropertyName = "deaf")] | |||||
| public bool Deaf; | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -26,18 +26,23 @@ namespace Discord | |||||
| public IEnumerable<User> Users { get { return _users; } } | public IEnumerable<User> Users { get { return _users; } } | ||||
| private AsyncCache<User, API.Models.UserReference> _users; | private AsyncCache<User, API.Models.UserReference> _users; | ||||
| public User GetUser(string id) => _users[id]; | |||||
| public IEnumerable<Server> Servers { get { return _servers; } } | public IEnumerable<Server> Servers { get { return _servers; } } | ||||
| private AsyncCache<Server, API.Models.ServerReference> _servers; | private AsyncCache<Server, API.Models.ServerReference> _servers; | ||||
| public Server GetServer(string id) => _servers[id]; | |||||
| public IEnumerable<Channel> Channels { get { return _channels; } } | public IEnumerable<Channel> Channels { get { return _channels; } } | ||||
| private AsyncCache<Channel, API.Models.ChannelReference> _channels; | private AsyncCache<Channel, API.Models.ChannelReference> _channels; | ||||
| public Channel GetChannel(string id) => _channels[id]; | |||||
| public IEnumerable<Message> Messages { get { return _messages; } } | public IEnumerable<Message> Messages { get { return _messages; } } | ||||
| private AsyncCache<Message, API.Models.MessageReference> _messages; | private AsyncCache<Message, API.Models.MessageReference> _messages; | ||||
| public Message GetMessage(string id) => _messages[id]; | |||||
| public IEnumerable<Role> Roles { get { return _roles; } } | public IEnumerable<Role> Roles { get { return _roles; } } | ||||
| private AsyncCache<Role, API.Models.Role> _roles; | private AsyncCache<Role, API.Models.Role> _roles; | ||||
| public Role GetRole(string id) => _roles[id]; | |||||
| public bool IsConnected { get { return _isReady; } } | public bool IsConnected { get { return _isReady; } } | ||||
| @@ -267,14 +272,14 @@ namespace Discord | |||||
| case "GUILD_ROLE_CREATE": | case "GUILD_ROLE_CREATE": | ||||
| { | { | ||||
| var data = e.Event.ToObject<WebSocketEvents.GuildRoleCreateUpdate>(); | var data = e.Event.ToObject<WebSocketEvents.GuildRoleCreateUpdate>(); | ||||
| var role = UpdateRole(data); | |||||
| var role = _roles.Update(data.Role.Id, data.Role); | |||||
| RaiseRoleCreated(role); | RaiseRoleCreated(role); | ||||
| } | } | ||||
| break; | break; | ||||
| case "GUILD_ROLE_UPDATE": | case "GUILD_ROLE_UPDATE": | ||||
| { | { | ||||
| var data = e.Event.ToObject<WebSocketEvents.GuildRoleCreateUpdate>(); | var data = e.Event.ToObject<WebSocketEvents.GuildRoleCreateUpdate>(); | ||||
| var role = UpdateRole(data); | |||||
| var role = _roles.Update(data.Role.Id, data.Role); | |||||
| RaiseRoleUpdated(role); | RaiseRoleUpdated(role); | ||||
| } | } | ||||
| break; | break; | ||||
| @@ -412,9 +417,7 @@ namespace Discord | |||||
| return _servers.Update(response.Id, response); | return _servers.Update(response.Id, response); | ||||
| } | } | ||||
| public Task<Server> LeaveServer(Server server) | public Task<Server> LeaveServer(Server server) | ||||
| { | |||||
| return LeaveServer(server.Id); | |||||
| } | |||||
| => LeaveServer(server.Id); | |||||
| public async Task<Server> LeaveServer(string id) | public async Task<Server> LeaveServer(string id) | ||||
| { | { | ||||
| CheckReady(); | CheckReady(); | ||||
| @@ -422,6 +425,31 @@ namespace Discord | |||||
| return _servers.Remove(id); | 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 | //Invites | ||||
| public Task<Invite> CreateInvite(Server server, int maxAge, int maxUses, bool isTemporary, bool hasXkcdPass) | public Task<Invite> 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() | private void CheckReady() | ||||
| @@ -30,32 +30,63 @@ namespace Discord.Helpers | |||||
| #else | #else | ||||
| private const bool _isDebug = false; | private const bool _isDebug = false; | ||||
| #endif | #endif | ||||
| internal static Task<ResponseT> Get<ResponseT>(string path, object data, HttpOptions options) | |||||
| where ResponseT : class | |||||
| => Send<ResponseT>("GET", path, data, options); | |||||
| internal static Task<string> Get(string path, object data, HttpOptions options) | |||||
| => Send("GET", path, data, options); | |||||
| internal static Task<ResponseT> Get<ResponseT>(string path, HttpOptions options) | |||||
| where ResponseT : class | |||||
| => Send<ResponseT>("GET", path, null, options); | |||||
| internal static Task<string> Get(string path, HttpOptions options) | |||||
| => Send("GET", path, null, options); | |||||
| internal static Task<ResponseT> Post<ResponseT>(string path, object data, HttpOptions options) | |||||
| where ResponseT : class | |||||
| => Send<ResponseT>("POST", path, data, options); | |||||
| internal static Task<string> Post(string path, object data, HttpOptions options) | |||||
| => Send("POST", path, data, options); | |||||
| internal static Task<ResponseT> Post<ResponseT>(string path, HttpOptions options) | |||||
| where ResponseT : class | |||||
| => Send<ResponseT>("POST", path, null, options); | |||||
| internal static Task<string> Post(string path, HttpOptions options) | |||||
| => Send("POST", path, null, options); | |||||
| internal static Task<ResponseT> Put<ResponseT>(string path, object data, HttpOptions options) | |||||
| where ResponseT : class | |||||
| => Send<ResponseT>("PUT", path, data, options); | |||||
| internal static Task<string> Put(string path, object data, HttpOptions options) | |||||
| => Send("PUT", path, data, options); | |||||
| internal static Task<ResponseT> Put<ResponseT>(string path, HttpOptions options) | |||||
| where ResponseT : class | |||||
| => Send<ResponseT>("PUT", path, null, options); | |||||
| internal static Task<string> Put(string path, HttpOptions options) | |||||
| => Send("PUT", path, null, options); | |||||
| //GET | |||||
| internal static async Task<ResponseT> Get<ResponseT>(string path, object data, HttpOptions options) | |||||
| internal static Task<ResponseT> Patch<ResponseT>(string path, object data, HttpOptions options) | |||||
| where ResponseT : class | where ResponseT : class | ||||
| { | |||||
| string requestJson = JsonConvert.SerializeObject(data); | |||||
| string responseJson = await SendRequest("GET", path, requestJson, options, true); | |||||
| var response = JsonConvert.DeserializeObject<ResponseT>(responseJson); | |||||
| #if DEBUG | |||||
| CheckResponse(responseJson, response); | |||||
| #endif | |||||
| return response; | |||||
| } | |||||
| internal static async Task<ResponseT> Get<ResponseT>(string path, HttpOptions options) | |||||
| => Send<ResponseT>("PATCH", path, data, options); | |||||
| internal static Task<string> Patch(string path, object data, HttpOptions options) | |||||
| => Send("PATCH", path, data, options); | |||||
| internal static Task<ResponseT> Patch<ResponseT>(string path, HttpOptions options) | |||||
| where ResponseT : class | where ResponseT : class | ||||
| { | |||||
| string responseJson = await SendRequest("GET", path, null, options, true); | |||||
| var response = JsonConvert.DeserializeObject<ResponseT>(responseJson); | |||||
| #if DEBUG | |||||
| CheckResponse(responseJson, response); | |||||
| #endif | |||||
| return response; | |||||
| } | |||||
| => Send<ResponseT>("PATCH", path, null, options); | |||||
| internal static Task<string> Patch(string path, HttpOptions options) | |||||
| => Send("PATCH", path, null, options); | |||||
| //POST | |||||
| internal static async Task<ResponseT> Post<ResponseT>(string path, object data, HttpOptions options) | |||||
| internal static Task<ResponseT> Delete<ResponseT>(string path, object data, HttpOptions options) | |||||
| where ResponseT : class | |||||
| => Send<ResponseT>("DELETE", path, data, options); | |||||
| internal static Task<string> Delete(string path, object data, HttpOptions options) | |||||
| => Send("DELETE", path, data, options); | |||||
| internal static Task<ResponseT> Delete<ResponseT>(string path, HttpOptions options) | |||||
| where ResponseT : class | |||||
| => Send<ResponseT>("DELETE", path, null, options); | |||||
| internal static Task<string> Delete(string path, HttpOptions options) | |||||
| => Send("DELETE", path, null, options); | |||||
| internal static async Task<ResponseT> Send<ResponseT>(string method, string path, object data, HttpOptions options) | |||||
| where ResponseT : class | where ResponseT : class | ||||
| { | { | ||||
| string requestJson = JsonConvert.SerializeObject(data); | string requestJson = JsonConvert.SerializeObject(data); | ||||
| @@ -66,7 +97,7 @@ namespace Discord.Helpers | |||||
| #endif | #endif | ||||
| return response; | return response; | ||||
| } | } | ||||
| internal static async Task<string> Post(string path, object data, HttpOptions options) | |||||
| internal static async Task<string> Send(string method, string path, object data, HttpOptions options) | |||||
| { | { | ||||
| string requestJson = JsonConvert.SerializeObject(data); | string requestJson = JsonConvert.SerializeObject(data); | ||||
| string responseJson = await SendRequest("POST", path, requestJson, options, _isDebug); | string responseJson = await SendRequest("POST", path, requestJson, options, _isDebug); | ||||
| @@ -75,7 +106,7 @@ namespace Discord.Helpers | |||||
| #endif | #endif | ||||
| return responseJson; | return responseJson; | ||||
| } | } | ||||
| internal static async Task<ResponseT> Post<ResponseT>(string path, HttpOptions options) | |||||
| internal static async Task<ResponseT> Send<ResponseT>(string method, string path, HttpOptions options) | |||||
| where ResponseT : class | where ResponseT : class | ||||
| { | { | ||||
| string responseJson = await SendRequest("POST", path, null, options, true); | string responseJson = await SendRequest("POST", path, null, options, true); | ||||
| @@ -85,7 +116,7 @@ namespace Discord.Helpers | |||||
| #endif | #endif | ||||
| return response; | return response; | ||||
| } | } | ||||
| internal static async Task<string> Post(string path, HttpOptions options) | |||||
| internal static async Task<string> Send(string method, string path, HttpOptions options) | |||||
| { | { | ||||
| string responseJson = await SendRequest("POST", path, null, options, _isDebug); | string responseJson = await SendRequest("POST", path, null, options, _isDebug); | ||||
| #if DEBUG | #if DEBUG | ||||
| @@ -94,26 +125,6 @@ namespace Discord.Helpers | |||||
| return responseJson; | return responseJson; | ||||
| } | } | ||||
| //DELETE | |||||
| internal static async Task<ResponseT> Delete<ResponseT>(string path, HttpOptions options) | |||||
| where ResponseT : class | |||||
| { | |||||
| string responseJson = await SendRequest("DELETE", path, null, options, true); | |||||
| var response = JsonConvert.DeserializeObject<ResponseT>(responseJson); | |||||
| #if DEBUG | |||||
| CheckResponse(responseJson, response); | |||||
| #endif | |||||
| return response; | |||||
| } | |||||
| internal static async Task<string> 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<string> SendRequest(string method, string path, string data, HttpOptions options, bool hasResponse) | private static async Task<string> SendRequest(string method, string path, string data, HttpOptions options, bool hasResponse) | ||||
| { | { | ||||
| options = options ?? new HttpOptions(); | options = options ?? new HttpOptions(); | ||||
| @@ -1,7 +1,7 @@ | |||||
| using System.Reflection; | using System.Reflection; | ||||
| [assembly: AssemblyTitle("Discord.Net")] | [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: AssemblyConfiguration("")] | ||||
| [assembly: AssemblyCompany("RogueException")] | [assembly: AssemblyCompany("RogueException")] | ||||
| [assembly: AssemblyProduct("Discord.Net")] | [assembly: AssemblyProduct("Discord.Net")] | ||||
| @@ -1,4 +1,4 @@ | |||||
| # Discord.Net | |||||
| # Discord.Net v0.2 | |||||
| A .Net API Wrapper for the Discord client (http://discordapp.com). | A .Net API Wrapper for the Discord client (http://discordapp.com). | ||||
| ## This is an alpha! | ## 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. | Discord.Net is also in early development so several functions may be unstable or not work at all. | ||||
| # Features | # 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 | - Receiving/Sending Messages | ||||
| - Creating/Destroying Servers | - Creating/Destroying Servers | ||||
| - Creating/Destroying Channels | - Creating/Destroying Channels | ||||
| - Kick/Ban/Unban/Mute/Unmute/Deafen/Undeafen Users | |||||
| - Several Discord Events | - Several Discord Events | ||||
| # Upcoming | # Upcoming | ||||
| - Modifying User/Channel/Server Settings | - Modifying User/Channel/Server Settings | ||||
| - Creating Invites | |||||
| - Kick/Ban/Unban/Mute/Unmute/Deafen/Undeafen | |||||
| - Sending Private Messages | - Sending Private Messages | ||||
| # Example (Echo Client) | # Example (Echo Client) | ||||