Browse Source

(binbrk)feature: Support filtering audit log entries on user, action type, and before entry id (#1377)

* Support filtering audit log entries on user, type, and before id

Adds support for filtering audit log entires with GetAuditLogsAsync. Adds the ability to specify a userId and ActionType to filter. Exposes the beforeId filter which was already implemented, yet unused (even when requesting > 100 entries)?

Was thinking that this could expose overloads of GetAuditLogAsync that accepts a IUser and IAuditLogEntry, but dealing with all the combinations of these types may be excessive.

* use only stringbuilder for args instead of string interpolation
tags/2.2.0
Chris Johnston Christopher F 5 years ago
parent
commit
68eb71c175
6 changed files with 46 additions and 14 deletions
  1. +5
    -1
      src/Discord.Net.Core/Entities/Guilds/IGuild.cs
  2. +3
    -1
      src/Discord.Net.Rest/API/Rest/GetAuditLogsParams.cs
  3. +17
    -3
      src/Discord.Net.Rest/DiscordRestApiClient.cs
  4. +5
    -1
      src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs
  5. +8
    -4
      src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs
  6. +8
    -4
      src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs

+ 5
- 1
src/Discord.Net.Core/Entities/Guilds/IGuild.cs View File

@@ -680,12 +680,16 @@ namespace Discord
/// <param name="limit">The number of audit log entries to fetch.</param> /// <param name="limit">The number of audit log entries to fetch.</param>
/// <param name="mode">The <see cref="CacheMode" /> that determines whether the object should be fetched from cache.</param> /// <param name="mode">The <see cref="CacheMode" /> that determines whether the object should be fetched from cache.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <param name="beforeId">The audit log entry ID to get entries before.</param>
/// <param name="actionType">The type of actions to filter.</param>
/// <param name="userId">The user ID to filter entries for.</param>
/// <returns> /// <returns>
/// A task that represents the asynchronous get operation. The task result contains a read-only collection /// A task that represents the asynchronous get operation. The task result contains a read-only collection
/// of the requested audit log entries. /// of the requested audit log entries.
/// </returns> /// </returns>
Task<IReadOnlyCollection<IAuditLogEntry>> GetAuditLogsAsync(int limit = DiscordConfig.MaxAuditLogEntriesPerBatch, Task<IReadOnlyCollection<IAuditLogEntry>> GetAuditLogsAsync(int limit = DiscordConfig.MaxAuditLogEntriesPerBatch,
CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);
CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null, ulong? beforeId = null, ulong? userId = null,
ActionType? actionType = null);


/// <summary> /// <summary>
/// Gets a webhook found within this guild. /// Gets a webhook found within this guild.


+ 3
- 1
src/Discord.Net.Rest/API/Rest/GetAuditLogsParams.cs View File

@@ -1,8 +1,10 @@
namespace Discord.API.Rest
namespace Discord.API.Rest
{ {
class GetAuditLogsParams class GetAuditLogsParams
{ {
public Optional<int> Limit { get; set; } public Optional<int> Limit { get; set; }
public Optional<ulong> BeforeEntryId { get; set; } public Optional<ulong> BeforeEntryId { get; set; }
public Optional<ulong> UserId { get; set; }
public Optional<int> ActionType { get; set; }
} }
} }

+ 17
- 3
src/Discord.Net.Rest/DiscordRestApiClient.cs View File

@@ -1321,11 +1321,25 @@ namespace Discord.API
var ids = new BucketIds(guildId: guildId); var ids = new BucketIds(guildId: guildId);
Expression<Func<string>> endpoint; Expression<Func<string>> endpoint;


var queryArgs = new StringBuilder();
if (args.BeforeEntryId.IsSpecified) if (args.BeforeEntryId.IsSpecified)
endpoint = () => $"guilds/{guildId}/audit-logs?limit={limit}&before={args.BeforeEntryId.Value}";
else
endpoint = () => $"guilds/{guildId}/audit-logs?limit={limit}";
{
queryArgs.Append("&before=")
.Append(args.BeforeEntryId);
}
if (args.UserId.IsSpecified)
{
queryArgs.Append("&user_id=")
.Append(args.UserId.Value);
}
if (args.ActionType.IsSpecified)
{
queryArgs.Append("&action_type=")
.Append(args.ActionType.Value);
}


// still use string interp for the query w/o params, as this is necessary for CreateBucketId
endpoint = () => $"guilds/{guildId}/audit-logs?limit={limit}{queryArgs.ToString()}";
return await SendAsync<AuditLog>("GET", endpoint, ids, options: options).ConfigureAwait(false); return await SendAsync<AuditLog>("GET", endpoint, ids, options: options).ConfigureAwait(false);
} }




+ 5
- 1
src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs View File

@@ -380,7 +380,7 @@ namespace Discord.Rest


// Audit logs // Audit logs
public static IAsyncEnumerable<IReadOnlyCollection<RestAuditLogEntry>> GetAuditLogsAsync(IGuild guild, BaseDiscordClient client, public static IAsyncEnumerable<IReadOnlyCollection<RestAuditLogEntry>> GetAuditLogsAsync(IGuild guild, BaseDiscordClient client,
ulong? from, int? limit, RequestOptions options)
ulong? from, int? limit, RequestOptions options, ulong? userId = null, ActionType? actionType = null)
{ {
return new PagedAsyncEnumerable<RestAuditLogEntry>( return new PagedAsyncEnumerable<RestAuditLogEntry>(
DiscordConfig.MaxAuditLogEntriesPerBatch, DiscordConfig.MaxAuditLogEntriesPerBatch,
@@ -392,6 +392,10 @@ namespace Discord.Rest
}; };
if (info.Position != null) if (info.Position != null)
args.BeforeEntryId = info.Position.Value; args.BeforeEntryId = info.Position.Value;
if (userId.HasValue)
args.UserId = userId.Value;
if (actionType.HasValue)
args.ActionType = (int)actionType.Value;
var model = await client.ApiClient.GetAuditLogsAsync(guild.Id, args, options); var model = await client.ApiClient.GetAuditLogsAsync(guild.Id, args, options);
return model.Entries.Select((x) => RestAuditLogEntry.Create(client, model, x)).ToImmutableArray(); return model.Entries.Select((x) => RestAuditLogEntry.Create(client, model, x)).ToImmutableArray();
}, },


+ 8
- 4
src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs View File

@@ -627,12 +627,15 @@ namespace Discord.Rest
/// </summary> /// </summary>
/// <param name="limit">The number of audit log entries to fetch.</param> /// <param name="limit">The number of audit log entries to fetch.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <param name="beforeId">The audit log entry ID to get entries before.</param>
/// <param name="actionType">The type of actions to filter.</param>
/// <param name="userId">The user ID to filter entries for.</param>
/// <returns> /// <returns>
/// A task that represents the asynchronous get operation. The task result contains a read-only collection /// A task that represents the asynchronous get operation. The task result contains a read-only collection
/// of the requested audit log entries. /// of the requested audit log entries.
/// </returns> /// </returns>
public IAsyncEnumerable<IReadOnlyCollection<RestAuditLogEntry>> GetAuditLogsAsync(int limit, RequestOptions options = null)
=> GuildHelper.GetAuditLogsAsync(this, Discord, null, limit, options);
public IAsyncEnumerable<IReadOnlyCollection<RestAuditLogEntry>> GetAuditLogsAsync(int limit, RequestOptions options = null, ulong? beforeId = null, ulong? userId = null, ActionType? actionType = null)
=> GuildHelper.GetAuditLogsAsync(this, Discord, beforeId, limit, options, userId: userId, actionType: actionType);


//Webhooks //Webhooks
/// <summary> /// <summary>
@@ -866,10 +869,11 @@ namespace Discord.Rest
Task IGuild.DownloadUsersAsync() => Task IGuild.DownloadUsersAsync() =>
throw new NotSupportedException(); throw new NotSupportedException();


async Task<IReadOnlyCollection<IAuditLogEntry>> IGuild.GetAuditLogsAsync(int limit, CacheMode cacheMode, RequestOptions options)
async Task<IReadOnlyCollection<IAuditLogEntry>> IGuild.GetAuditLogsAsync(int limit, CacheMode cacheMode, RequestOptions options,
ulong? beforeId, ulong? userId, ActionType? actionType)
{ {
if (cacheMode == CacheMode.AllowDownload) if (cacheMode == CacheMode.AllowDownload)
return (await GetAuditLogsAsync(limit, options).FlattenAsync().ConfigureAwait(false)).ToImmutableArray();
return (await GetAuditLogsAsync(limit, options, beforeId: beforeId, userId: userId, actionType: actionType).FlattenAsync().ConfigureAwait(false)).ToImmutableArray();
else else
return ImmutableArray.Create<IAuditLogEntry>(); return ImmutableArray.Create<IAuditLogEntry>();
} }


+ 8
- 4
src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs View File

@@ -801,12 +801,15 @@ namespace Discord.WebSocket
/// </summary> /// </summary>
/// <param name="limit">The number of audit log entries to fetch.</param> /// <param name="limit">The number of audit log entries to fetch.</param>
/// <param name="options">The options to be used when sending the request.</param> /// <param name="options">The options to be used when sending the request.</param>
/// <param name="beforeId">The audit log entry ID to filter entries before.</param>
/// <param name="actionType">The type of actions to filter.</param>
/// <param name="userId">The user ID to filter entries for.</param>
/// <returns> /// <returns>
/// A task that represents the asynchronous get operation. The task result contains a read-only collection /// A task that represents the asynchronous get operation. The task result contains a read-only collection
/// of the requested audit log entries. /// of the requested audit log entries.
/// </returns> /// </returns>
public IAsyncEnumerable<IReadOnlyCollection<RestAuditLogEntry>> GetAuditLogsAsync(int limit, RequestOptions options = null)
=> GuildHelper.GetAuditLogsAsync(this, Discord, null, limit, options);
public IAsyncEnumerable<IReadOnlyCollection<RestAuditLogEntry>> GetAuditLogsAsync(int limit, RequestOptions options = null, ulong? beforeId = null, ulong? userId = null, ActionType? actionType = null)
=> GuildHelper.GetAuditLogsAsync(this, Discord, beforeId, limit, options, userId: userId, actionType: actionType);


//Webhooks //Webhooks
/// <summary> /// <summary>
@@ -1160,10 +1163,11 @@ namespace Discord.WebSocket
=> Task.FromResult<IGuildUser>(Owner); => Task.FromResult<IGuildUser>(Owner);


/// <inheritdoc /> /// <inheritdoc />
async Task<IReadOnlyCollection<IAuditLogEntry>> IGuild.GetAuditLogsAsync(int limit, CacheMode cacheMode, RequestOptions options)
async Task<IReadOnlyCollection<IAuditLogEntry>> IGuild.GetAuditLogsAsync(int limit, CacheMode cacheMode, RequestOptions options,
ulong? beforeId, ulong? userId, ActionType? actionType)
{ {
if (cacheMode == CacheMode.AllowDownload) if (cacheMode == CacheMode.AllowDownload)
return (await GetAuditLogsAsync(limit, options).FlattenAsync().ConfigureAwait(false)).ToImmutableArray();
return (await GetAuditLogsAsync(limit, options, beforeId: beforeId, userId: userId, actionType: actionType).FlattenAsync().ConfigureAwait(false)).ToImmutableArray();
else else
return ImmutableArray.Create<IAuditLogEntry>(); return ImmutableArray.Create<IAuditLogEntry>();
} }


Loading…
Cancel
Save