* Add support for audit log reasons * Made changes per discussiontags/1.0
@@ -66,10 +66,10 @@ namespace Discord | |||||
Task<IReadOnlyCollection<IBan>> GetBansAsync(RequestOptions options = null); | Task<IReadOnlyCollection<IBan>> GetBansAsync(RequestOptions options = null); | ||||
/// <summary> Bans the provided user from this guild and optionally prunes their recent messages. </summary> | /// <summary> Bans the provided user from this guild and optionally prunes their recent messages. </summary> | ||||
/// <param name="pruneDays">The number of days to remove messages from this user for - must be between [0, 7]</param> | /// <param name="pruneDays">The number of days to remove messages from this user for - must be between [0, 7]</param> | ||||
Task AddBanAsync(IUser user, int pruneDays = 0, RequestOptions options = null); | |||||
Task AddBanAsync(IUser user, int pruneDays = 0, string reason = null, RequestOptions options = null); | |||||
/// <summary> Bans the provided user id from this guild and optionally prunes their recent messages. </summary> | /// <summary> Bans the provided user id from this guild and optionally prunes their recent messages. </summary> | ||||
/// <param name="pruneDays">The number of days to remove messages from this user for - must be between [0, 7]</param> | /// <param name="pruneDays">The number of days to remove messages from this user for - must be between [0, 7]</param> | ||||
Task AddBanAsync(ulong userId, int pruneDays = 0, RequestOptions options = null); | |||||
Task AddBanAsync(ulong userId, int pruneDays = 0, string reason = null, RequestOptions options = null); | |||||
/// <summary> Unbans the provided user if it is currently banned. </summary> | /// <summary> Unbans the provided user if it is currently banned. </summary> | ||||
Task RemoveBanAsync(IUser user, RequestOptions options = null); | Task RemoveBanAsync(IUser user, RequestOptions options = null); | ||||
/// <summary> Unbans the provided user id if it is currently banned. </summary> | /// <summary> Unbans the provided user id if it is currently banned. </summary> | ||||
@@ -25,7 +25,7 @@ namespace Discord | |||||
ChannelPermissions GetPermissions(IGuildChannel channel); | ChannelPermissions GetPermissions(IGuildChannel channel); | ||||
/// <summary> Kicks this user from this guild. </summary> | /// <summary> Kicks this user from this guild. </summary> | ||||
Task KickAsync(RequestOptions options = null); | |||||
Task KickAsync(string reason = null, RequestOptions options = null); | |||||
/// <summary> Modifies this user's properties in this guild. </summary> | /// <summary> Modifies this user's properties in this guild. </summary> | ||||
Task ModifyAsync(Action<GuildUserProperties> func, RequestOptions options = null); | Task ModifyAsync(Action<GuildUserProperties> func, RequestOptions options = null); | ||||
@@ -9,8 +9,8 @@ namespace Discord.Net.Rest | |||||
void SetHeader(string key, string value); | void SetHeader(string key, string value); | ||||
void SetCancelToken(CancellationToken cancelToken); | void SetCancelToken(CancellationToken cancelToken); | ||||
Task<RestResponse> SendAsync(string method, string endpoint, CancellationToken cancelToken, bool headerOnly = false); | |||||
Task<RestResponse> SendAsync(string method, string endpoint, string json, CancellationToken cancelToken, bool headerOnly = false); | |||||
Task<RestResponse> SendAsync(string method, string endpoint, IReadOnlyDictionary<string, object> multipartParams, CancellationToken cancelToken, bool headerOnly = false); | |||||
Task<RestResponse> SendAsync(string method, string endpoint, CancellationToken cancelToken, bool headerOnly = false, string reason = null); | |||||
Task<RestResponse> SendAsync(string method, string endpoint, string json, CancellationToken cancelToken, bool headerOnly = false, string reason = null); | |||||
Task<RestResponse> SendAsync(string method, string endpoint, IReadOnlyDictionary<string, object> multipartParams, CancellationToken cancelToken, bool headerOnly = false, string reason = null); | |||||
} | } | ||||
} | } |
@@ -14,6 +14,10 @@ namespace Discord | |||||
public CancellationToken CancelToken { get; set; } = CancellationToken.None; | public CancellationToken CancelToken { get; set; } = CancellationToken.None; | ||||
public RetryMode? RetryMode { get; set; } | public RetryMode? RetryMode { get; set; } | ||||
public bool HeaderOnly { get; internal set; } | public bool HeaderOnly { get; internal set; } | ||||
/// <summary> | |||||
/// The reason for this action in the guild's audit log | |||||
/// </summary> | |||||
public string AuditLogReason { get; set; } | |||||
internal bool IgnoreState { get; set; } | internal bool IgnoreState { get; set; } | ||||
internal string BucketId { get; set; } | internal string BucketId { get; set; } | ||||
@@ -4,5 +4,6 @@ namespace Discord.API.Rest | |||||
internal class CreateGuildBanParams | internal class CreateGuildBanParams | ||||
{ | { | ||||
public Optional<int> DeleteMessageDays { get; set; } | public Optional<int> DeleteMessageDays { get; set; } | ||||
public string Reason { get; set; } | |||||
} | } | ||||
} | } |
@@ -803,7 +803,8 @@ namespace Discord.API | |||||
options = RequestOptions.CreateOrClone(options); | options = RequestOptions.CreateOrClone(options); | ||||
var ids = new BucketIds(guildId: guildId); | var ids = new BucketIds(guildId: guildId); | ||||
await SendAsync("PUT", () => $"guilds/{guildId}/bans/{userId}?delete-message-days={args.DeleteMessageDays}", ids, options: options).ConfigureAwait(false); | |||||
string reason = string.IsNullOrWhiteSpace(args.Reason) ? "" : $"&reason={args.Reason}"; | |||||
await SendAsync("PUT", () => $"guilds/{guildId}/bans/{userId}?delete-message-days={args.DeleteMessageDays}{reason}", ids, options: options).ConfigureAwait(false); | |||||
} | } | ||||
public async Task RemoveGuildBanAsync(ulong guildId, ulong userId, RequestOptions options = null) | public async Task RemoveGuildBanAsync(ulong guildId, ulong userId, RequestOptions options = null) | ||||
{ | { | ||||
@@ -980,14 +981,15 @@ namespace Discord.API | |||||
Expression<Func<string>> endpoint = () => $"guilds/{guildId}/members?limit={limit}&after={afterUserId}"; | Expression<Func<string>> endpoint = () => $"guilds/{guildId}/members?limit={limit}&after={afterUserId}"; | ||||
return await SendAsync<IReadOnlyCollection<GuildMember>>("GET", endpoint, ids, options: options).ConfigureAwait(false); | return await SendAsync<IReadOnlyCollection<GuildMember>>("GET", endpoint, ids, options: options).ConfigureAwait(false); | ||||
} | } | ||||
public async Task RemoveGuildMemberAsync(ulong guildId, ulong userId, RequestOptions options = null) | |||||
public async Task RemoveGuildMemberAsync(ulong guildId, ulong userId, string reason, RequestOptions options = null) | |||||
{ | { | ||||
Preconditions.NotEqual(guildId, 0, nameof(guildId)); | Preconditions.NotEqual(guildId, 0, nameof(guildId)); | ||||
Preconditions.NotEqual(userId, 0, nameof(userId)); | Preconditions.NotEqual(userId, 0, nameof(userId)); | ||||
options = RequestOptions.CreateOrClone(options); | options = RequestOptions.CreateOrClone(options); | ||||
var ids = new BucketIds(guildId: guildId); | var ids = new BucketIds(guildId: guildId); | ||||
await SendAsync("DELETE", () => $"guilds/{guildId}/members/{userId}", ids, options: options).ConfigureAwait(false); | |||||
reason = string.IsNullOrWhiteSpace(reason) ? "" : $"?reason={reason}"; | |||||
await SendAsync("DELETE", () => $"guilds/{guildId}/members/{userId}{reason}", ids, options: options).ConfigureAwait(false); | |||||
} | } | ||||
public async Task ModifyGuildMemberAsync(ulong guildId, ulong userId, Rest.ModifyGuildMemberParams args, RequestOptions options = null) | public async Task ModifyGuildMemberAsync(ulong guildId, ulong userId, Rest.ModifyGuildMemberParams args, RequestOptions options = null) | ||||
{ | { | ||||
@@ -107,9 +107,9 @@ namespace Discord.Rest | |||||
} | } | ||||
public static async Task AddBanAsync(IGuild guild, BaseDiscordClient client, | public static async Task AddBanAsync(IGuild guild, BaseDiscordClient client, | ||||
ulong userId, int pruneDays, RequestOptions options) | |||||
ulong userId, int pruneDays, string reason, RequestOptions options) | |||||
{ | { | ||||
var args = new CreateGuildBanParams { DeleteMessageDays = pruneDays }; | |||||
var args = new CreateGuildBanParams { DeleteMessageDays = pruneDays, Reason = reason }; | |||||
await client.ApiClient.CreateGuildBanAsync(guild.Id, userId, args, options).ConfigureAwait(false); | await client.ApiClient.CreateGuildBanAsync(guild.Id, userId, args, options).ConfigureAwait(false); | ||||
} | } | ||||
public static async Task RemoveBanAsync(IGuild guild, BaseDiscordClient client, | public static async Task RemoveBanAsync(IGuild guild, BaseDiscordClient client, | ||||
@@ -137,10 +137,10 @@ namespace Discord.Rest | |||||
public Task<IReadOnlyCollection<RestBan>> GetBansAsync(RequestOptions options = null) | public Task<IReadOnlyCollection<RestBan>> GetBansAsync(RequestOptions options = null) | ||||
=> GuildHelper.GetBansAsync(this, Discord, options); | => GuildHelper.GetBansAsync(this, Discord, options); | ||||
public Task AddBanAsync(IUser user, int pruneDays = 0, RequestOptions options = null) | |||||
=> GuildHelper.AddBanAsync(this, Discord, user.Id, pruneDays, options); | |||||
public Task AddBanAsync(ulong userId, int pruneDays = 0, RequestOptions options = null) | |||||
=> GuildHelper.AddBanAsync(this, Discord, userId, pruneDays, options); | |||||
public Task AddBanAsync(IUser user, int pruneDays = 0, string reason = null, RequestOptions options = null) | |||||
=> GuildHelper.AddBanAsync(this, Discord, user.Id, pruneDays, reason, options); | |||||
public Task AddBanAsync(ulong userId, int pruneDays = 0, string reason = null, RequestOptions options = null) | |||||
=> GuildHelper.AddBanAsync(this, Discord, userId, pruneDays, reason, options); | |||||
public Task RemoveBanAsync(IUser user, RequestOptions options = null) | public Task RemoveBanAsync(IUser user, RequestOptions options = null) | ||||
=> GuildHelper.RemoveBanAsync(this, Discord, user.Id, options); | => GuildHelper.RemoveBanAsync(this, Discord, user.Id, options); | ||||
@@ -85,8 +85,8 @@ namespace Discord.Rest | |||||
else if (args.RoleIds.IsSpecified) | else if (args.RoleIds.IsSpecified) | ||||
UpdateRoles(args.RoleIds.Value.ToArray()); | UpdateRoles(args.RoleIds.Value.ToArray()); | ||||
} | } | ||||
public Task KickAsync(RequestOptions options = null) | |||||
=> UserHelper.KickAsync(this, Discord, options); | |||||
public Task KickAsync(string reason = null, RequestOptions options = null) | |||||
=> UserHelper.KickAsync(this, Discord, reason, options); | |||||
/// <inheritdoc /> | /// <inheritdoc /> | ||||
public Task AddRoleAsync(IRole role, RequestOptions options = null) | public Task AddRoleAsync(IRole role, RequestOptions options = null) | ||||
=> AddRolesAsync(new[] { role }, options); | => AddRolesAsync(new[] { role }, options); | ||||
@@ -45,7 +45,7 @@ namespace Discord.Rest | |||||
GuildPermissions IGuildUser.GuildPermissions => GuildPermissions.Webhook; | GuildPermissions IGuildUser.GuildPermissions => GuildPermissions.Webhook; | ||||
ChannelPermissions IGuildUser.GetPermissions(IGuildChannel channel) => Permissions.ToChannelPerms(channel, GuildPermissions.Webhook.RawValue); | ChannelPermissions IGuildUser.GetPermissions(IGuildChannel channel) => Permissions.ToChannelPerms(channel, GuildPermissions.Webhook.RawValue); | ||||
Task IGuildUser.KickAsync(RequestOptions options) | |||||
Task IGuildUser.KickAsync(string reason, RequestOptions options) | |||||
{ | { | ||||
throw new NotSupportedException("Webhook users cannot be kicked."); | throw new NotSupportedException("Webhook users cannot be kicked."); | ||||
} | } | ||||
@@ -53,9 +53,9 @@ namespace Discord.Rest | |||||
} | } | ||||
public static async Task KickAsync(IGuildUser user, BaseDiscordClient client, | public static async Task KickAsync(IGuildUser user, BaseDiscordClient client, | ||||
RequestOptions options) | |||||
string reason, RequestOptions options) | |||||
{ | { | ||||
await client.ApiClient.RemoveGuildMemberAsync(user.GuildId, user.Id, options).ConfigureAwait(false); | |||||
await client.ApiClient.RemoveGuildMemberAsync(user.GuildId, user.Id, reason, options).ConfigureAwait(false); | |||||
} | } | ||||
public static async Task<RestDMChannel> CreateDMChannelAsync(IUser user, BaseDiscordClient client, | public static async Task<RestDMChannel> CreateDMChannelAsync(IUser user, BaseDiscordClient client, | ||||
@@ -62,26 +62,31 @@ namespace Discord.Net.Rest | |||||
_cancelToken = cancelToken; | _cancelToken = cancelToken; | ||||
} | } | ||||
public async Task<RestResponse> SendAsync(string method, string endpoint, CancellationToken cancelToken, bool headerOnly) | |||||
public async Task<RestResponse> SendAsync(string method, string endpoint, CancellationToken cancelToken, bool headerOnly, string reason = null) | |||||
{ | { | ||||
string uri = Path.Combine(_baseUrl, endpoint); | string uri = Path.Combine(_baseUrl, endpoint); | ||||
using (var restRequest = new HttpRequestMessage(GetMethod(method), uri)) | using (var restRequest = new HttpRequestMessage(GetMethod(method), uri)) | ||||
{ | |||||
if (reason != null) restRequest.Headers.Add("X-Audit-Log-Reason", Uri.EscapeDataString(reason)); | |||||
return await SendInternalAsync(restRequest, cancelToken, headerOnly).ConfigureAwait(false); | return await SendInternalAsync(restRequest, cancelToken, headerOnly).ConfigureAwait(false); | ||||
} | |||||
} | } | ||||
public async Task<RestResponse> SendAsync(string method, string endpoint, string json, CancellationToken cancelToken, bool headerOnly) | |||||
public async Task<RestResponse> SendAsync(string method, string endpoint, string json, CancellationToken cancelToken, bool headerOnly, string reason = null) | |||||
{ | { | ||||
string uri = Path.Combine(_baseUrl, endpoint); | string uri = Path.Combine(_baseUrl, endpoint); | ||||
using (var restRequest = new HttpRequestMessage(GetMethod(method), uri)) | using (var restRequest = new HttpRequestMessage(GetMethod(method), uri)) | ||||
{ | { | ||||
if (reason != null) restRequest.Headers.Add("X-Audit-Log-Reason", Uri.EscapeDataString(reason)); | |||||
restRequest.Content = new StringContent(json, Encoding.UTF8, "application/json"); | restRequest.Content = new StringContent(json, Encoding.UTF8, "application/json"); | ||||
return await SendInternalAsync(restRequest, cancelToken, headerOnly).ConfigureAwait(false); | return await SendInternalAsync(restRequest, cancelToken, headerOnly).ConfigureAwait(false); | ||||
} | } | ||||
} | } | ||||
public async Task<RestResponse> SendAsync(string method, string endpoint, IReadOnlyDictionary<string, object> multipartParams, CancellationToken cancelToken, bool headerOnly) | |||||
public async Task<RestResponse> SendAsync(string method, string endpoint, IReadOnlyDictionary<string, object> multipartParams, CancellationToken cancelToken, bool headerOnly, string reason = null) | |||||
{ | { | ||||
string uri = Path.Combine(_baseUrl, endpoint); | string uri = Path.Combine(_baseUrl, endpoint); | ||||
using (var restRequest = new HttpRequestMessage(GetMethod(method), uri)) | using (var restRequest = new HttpRequestMessage(GetMethod(method), uri)) | ||||
{ | { | ||||
if (reason != null) restRequest.Headers.Add("X-Audit-Log-Reason", Uri.EscapeDataString(reason)); | |||||
var content = new MultipartFormDataContent("Upload----" + DateTime.Now.ToString(CultureInfo.InvariantCulture)); | var content = new MultipartFormDataContent("Upload----" + DateTime.Now.ToString(CultureInfo.InvariantCulture)); | ||||
if (multipartParams != null) | if (multipartParams != null) | ||||
{ | { | ||||
@@ -15,7 +15,7 @@ namespace Discord.Net.Queue | |||||
public override async Task<RestResponse> SendAsync() | public override async Task<RestResponse> SendAsync() | ||||
{ | { | ||||
return await Client.SendAsync(Method, Endpoint, Json, Options.CancelToken, Options.HeaderOnly).ConfigureAwait(false); | |||||
return await Client.SendAsync(Method, Endpoint, Json, Options.CancelToken, Options.HeaderOnly, Options.AuditLogReason).ConfigureAwait(false); | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -16,7 +16,7 @@ namespace Discord.Net.Queue | |||||
public override async Task<RestResponse> SendAsync() | public override async Task<RestResponse> SendAsync() | ||||
{ | { | ||||
return await Client.SendAsync(Method, Endpoint, MultipartParams, Options.CancelToken, Options.HeaderOnly).ConfigureAwait(false); | |||||
return await Client.SendAsync(Method, Endpoint, MultipartParams, Options.CancelToken, Options.HeaderOnly, Options.AuditLogReason).ConfigureAwait(false); | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -28,7 +28,7 @@ namespace Discord.Net.Queue | |||||
public virtual async Task<RestResponse> SendAsync() | public virtual async Task<RestResponse> SendAsync() | ||||
{ | { | ||||
return await Client.SendAsync(Method, Endpoint, Options.CancelToken, Options.HeaderOnly).ConfigureAwait(false); | |||||
return await Client.SendAsync(Method, Endpoint, Options.CancelToken, Options.HeaderOnly, Options.AuditLogReason).ConfigureAwait(false); | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -281,10 +281,10 @@ namespace Discord.WebSocket | |||||
public Task<IReadOnlyCollection<RestBan>> GetBansAsync(RequestOptions options = null) | public Task<IReadOnlyCollection<RestBan>> GetBansAsync(RequestOptions options = null) | ||||
=> GuildHelper.GetBansAsync(this, Discord, options); | => GuildHelper.GetBansAsync(this, Discord, options); | ||||
public Task AddBanAsync(IUser user, int pruneDays = 0, RequestOptions options = null) | |||||
=> GuildHelper.AddBanAsync(this, Discord, user.Id, pruneDays, options); | |||||
public Task AddBanAsync(ulong userId, int pruneDays = 0, RequestOptions options = null) | |||||
=> GuildHelper.AddBanAsync(this, Discord, userId, pruneDays, options); | |||||
public Task AddBanAsync(IUser user, int pruneDays = 0, string reason = null, RequestOptions options = null) | |||||
=> GuildHelper.AddBanAsync(this, Discord, user.Id, pruneDays, reason, options); | |||||
public Task AddBanAsync(ulong userId, int pruneDays = 0, string reason = null, RequestOptions options = null) | |||||
=> GuildHelper.AddBanAsync(this, Discord, userId, pruneDays, reason, options); | |||||
public Task RemoveBanAsync(IUser user, RequestOptions options = null) | public Task RemoveBanAsync(IUser user, RequestOptions options = null) | ||||
=> GuildHelper.RemoveBanAsync(this, Discord, user.Id, options); | => GuildHelper.RemoveBanAsync(this, Discord, user.Id, options); | ||||
@@ -122,8 +122,8 @@ namespace Discord.WebSocket | |||||
public Task ModifyAsync(Action<GuildUserProperties> func, RequestOptions options = null) | public Task ModifyAsync(Action<GuildUserProperties> func, RequestOptions options = null) | ||||
=> UserHelper.ModifyAsync(this, Discord, func, options); | => UserHelper.ModifyAsync(this, Discord, func, options); | ||||
public Task KickAsync(RequestOptions options = null) | |||||
=> UserHelper.KickAsync(this, Discord, options); | |||||
public Task KickAsync(string reason = null, RequestOptions options = null) | |||||
=> UserHelper.KickAsync(this, Discord, reason, options); | |||||
/// <inheritdoc /> | /// <inheritdoc /> | ||||
public Task AddRoleAsync(IRole role, RequestOptions options = null) | public Task AddRoleAsync(IRole role, RequestOptions options = null) | ||||
=> AddRolesAsync(new[] { role }, options); | => AddRolesAsync(new[] { role }, options); | ||||
@@ -47,7 +47,7 @@ namespace Discord.WebSocket | |||||
GuildPermissions IGuildUser.GuildPermissions => GuildPermissions.Webhook; | GuildPermissions IGuildUser.GuildPermissions => GuildPermissions.Webhook; | ||||
ChannelPermissions IGuildUser.GetPermissions(IGuildChannel channel) => Permissions.ToChannelPerms(channel, GuildPermissions.Webhook.RawValue); | ChannelPermissions IGuildUser.GetPermissions(IGuildChannel channel) => Permissions.ToChannelPerms(channel, GuildPermissions.Webhook.RawValue); | ||||
Task IGuildUser.KickAsync(RequestOptions options) | |||||
Task IGuildUser.KickAsync(string reason, RequestOptions options) | |||||
{ | { | ||||
throw new NotSupportedException("Webhook users cannot be kicked."); | throw new NotSupportedException("Webhook users cannot be kicked."); | ||||
} | } | ||||
@@ -66,7 +66,7 @@ namespace Discord.Net | |||||
_cancelToken = CancellationTokenSource.CreateLinkedTokenSource(_parentToken, _cancelTokenSource.Token).Token; | _cancelToken = CancellationTokenSource.CreateLinkedTokenSource(_parentToken, _cancelTokenSource.Token).Token; | ||||
} | } | ||||
public async Task<RestResponse> SendAsync(string method, string endpoint, CancellationToken cancelToken, bool headerOnly) | |||||
public async Task<RestResponse> SendAsync(string method, string endpoint, CancellationToken cancelToken, bool headerOnly, string reason = null) | |||||
{ | { | ||||
if (method != "GET") | if (method != "GET") | ||||
throw new InvalidOperationException("This RestClient only supports GET requests."); | throw new InvalidOperationException("This RestClient only supports GET requests."); | ||||
@@ -75,11 +75,11 @@ namespace Discord.Net | |||||
var bytes = await _blobCache.DownloadUrl(uri, _headers); | var bytes = await _blobCache.DownloadUrl(uri, _headers); | ||||
return new RestResponse(HttpStatusCode.OK, _headers, new MemoryStream(bytes)); | return new RestResponse(HttpStatusCode.OK, _headers, new MemoryStream(bytes)); | ||||
} | } | ||||
public Task<RestResponse> SendAsync(string method, string endpoint, string json, CancellationToken cancelToken, bool headerOnly) | |||||
public Task<RestResponse> SendAsync(string method, string endpoint, string json, CancellationToken cancelToken, bool headerOnly, string reason = null) | |||||
{ | { | ||||
throw new InvalidOperationException("This RestClient does not support payloads."); | throw new InvalidOperationException("This RestClient does not support payloads."); | ||||
} | } | ||||
public Task<RestResponse> SendAsync(string method, string endpoint, IReadOnlyDictionary<string, object> multipartParams, CancellationToken cancelToken, bool headerOnly) | |||||
public Task<RestResponse> SendAsync(string method, string endpoint, IReadOnlyDictionary<string, object> multipartParams, CancellationToken cancelToken, bool headerOnly, string reason = null) | |||||
{ | { | ||||
throw new InvalidOperationException("This RestClient does not support multipart requests."); | throw new InvalidOperationException("This RestClient does not support multipart requests."); | ||||
} | } | ||||