Skip to content

Commit 68eb71c

Browse files
Chris-Johnstonfoxbot
authored andcommitted
(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
1 parent c54867f commit 68eb71c

File tree

6 files changed

+46
-14
lines changed

6 files changed

+46
-14
lines changed

src/Discord.Net.Core/Entities/Guilds/IGuild.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -680,12 +680,16 @@ public interface IGuild : IDeletable, ISnowflakeEntity
680680
/// <param name="limit">The number of audit log entries to fetch.</param>
681681
/// <param name="mode">The <see cref="CacheMode" /> that determines whether the object should be fetched from cache.</param>
682682
/// <param name="options">The options to be used when sending the request.</param>
683+
/// <param name="beforeId">The audit log entry ID to get entries before.</param>
684+
/// <param name="actionType">The type of actions to filter.</param>
685+
/// <param name="userId">The user ID to filter entries for.</param>
683686
/// <returns>
684687
/// A task that represents the asynchronous get operation. The task result contains a read-only collection
685688
/// of the requested audit log entries.
686689
/// </returns>
687690
Task<IReadOnlyCollection<IAuditLogEntry>> GetAuditLogsAsync(int limit = DiscordConfig.MaxAuditLogEntriesPerBatch,
688-
CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);
691+
CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null, ulong? beforeId = null, ulong? userId = null,
692+
ActionType? actionType = null);
689693

690694
/// <summary>
691695
/// Gets a webhook found within this guild.
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
namespace Discord.API.Rest
1+
namespace Discord.API.Rest
22
{
33
class GetAuditLogsParams
44
{
55
public Optional<int> Limit { get; set; }
66
public Optional<ulong> BeforeEntryId { get; set; }
7+
public Optional<ulong> UserId { get; set; }
8+
public Optional<int> ActionType { get; set; }
79
}
810
}

src/Discord.Net.Rest/DiscordRestApiClient.cs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1321,11 +1321,25 @@ public async Task<AuditLog> GetAuditLogsAsync(ulong guildId, GetAuditLogsParams
13211321
var ids = new BucketIds(guildId: guildId);
13221322
Expression<Func<string>> endpoint;
13231323

1324+
var queryArgs = new StringBuilder();
13241325
if (args.BeforeEntryId.IsSpecified)
1325-
endpoint = () => $"guilds/{guildId}/audit-logs?limit={limit}&before={args.BeforeEntryId.Value}";
1326-
else
1327-
endpoint = () => $"guilds/{guildId}/audit-logs?limit={limit}";
1326+
{
1327+
queryArgs.Append("&before=")
1328+
.Append(args.BeforeEntryId);
1329+
}
1330+
if (args.UserId.IsSpecified)
1331+
{
1332+
queryArgs.Append("&user_id=")
1333+
.Append(args.UserId.Value);
1334+
}
1335+
if (args.ActionType.IsSpecified)
1336+
{
1337+
queryArgs.Append("&action_type=")
1338+
.Append(args.ActionType.Value);
1339+
}
13281340

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

src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ public static async Task<int> PruneUsersAsync(IGuild guild, BaseDiscordClient cl
380380

381381
// Audit logs
382382
public static IAsyncEnumerable<IReadOnlyCollection<RestAuditLogEntry>> GetAuditLogsAsync(IGuild guild, BaseDiscordClient client,
383-
ulong? from, int? limit, RequestOptions options)
383+
ulong? from, int? limit, RequestOptions options, ulong? userId = null, ActionType? actionType = null)
384384
{
385385
return new PagedAsyncEnumerable<RestAuditLogEntry>(
386386
DiscordConfig.MaxAuditLogEntriesPerBatch,
@@ -392,6 +392,10 @@ public static IAsyncEnumerable<IReadOnlyCollection<RestAuditLogEntry>> GetAuditL
392392
};
393393
if (info.Position != null)
394394
args.BeforeEntryId = info.Position.Value;
395+
if (userId.HasValue)
396+
args.UserId = userId.Value;
397+
if (actionType.HasValue)
398+
args.ActionType = (int)actionType.Value;
395399
var model = await client.ApiClient.GetAuditLogsAsync(guild.Id, args, options);
396400
return model.Entries.Select((x) => RestAuditLogEntry.Create(client, model, x)).ToImmutableArray();
397401
},

src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -627,12 +627,15 @@ public Task<int> PruneUsersAsync(int days = 30, bool simulate = false, RequestOp
627627
/// </summary>
628628
/// <param name="limit">The number of audit log entries to fetch.</param>
629629
/// <param name="options">The options to be used when sending the request.</param>
630+
/// <param name="beforeId">The audit log entry ID to get entries before.</param>
631+
/// <param name="actionType">The type of actions to filter.</param>
632+
/// <param name="userId">The user ID to filter entries for.</param>
630633
/// <returns>
631634
/// A task that represents the asynchronous get operation. The task result contains a read-only collection
632635
/// of the requested audit log entries.
633636
/// </returns>
634-
public IAsyncEnumerable<IReadOnlyCollection<RestAuditLogEntry>> GetAuditLogsAsync(int limit, RequestOptions options = null)
635-
=> GuildHelper.GetAuditLogsAsync(this, Discord, null, limit, options);
637+
public IAsyncEnumerable<IReadOnlyCollection<RestAuditLogEntry>> GetAuditLogsAsync(int limit, RequestOptions options = null, ulong? beforeId = null, ulong? userId = null, ActionType? actionType = null)
638+
=> GuildHelper.GetAuditLogsAsync(this, Discord, beforeId, limit, options, userId: userId, actionType: actionType);
636639

637640
//Webhooks
638641
/// <summary>
@@ -866,10 +869,11 @@ async Task<IReadOnlyCollection<IGuildUser>> IGuild.GetUsersAsync(CacheMode mode,
866869
Task IGuild.DownloadUsersAsync() =>
867870
throw new NotSupportedException();
868871

869-
async Task<IReadOnlyCollection<IAuditLogEntry>> IGuild.GetAuditLogsAsync(int limit, CacheMode cacheMode, RequestOptions options)
872+
async Task<IReadOnlyCollection<IAuditLogEntry>> IGuild.GetAuditLogsAsync(int limit, CacheMode cacheMode, RequestOptions options,
873+
ulong? beforeId, ulong? userId, ActionType? actionType)
870874
{
871875
if (cacheMode == CacheMode.AllowDownload)
872-
return (await GetAuditLogsAsync(limit, options).FlattenAsync().ConfigureAwait(false)).ToImmutableArray();
876+
return (await GetAuditLogsAsync(limit, options, beforeId: beforeId, userId: userId, actionType: actionType).FlattenAsync().ConfigureAwait(false)).ToImmutableArray();
873877
else
874878
return ImmutableArray.Create<IAuditLogEntry>();
875879
}

src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -801,12 +801,15 @@ internal void CompleteDownloadUsers()
801801
/// </summary>
802802
/// <param name="limit">The number of audit log entries to fetch.</param>
803803
/// <param name="options">The options to be used when sending the request.</param>
804+
/// <param name="beforeId">The audit log entry ID to filter entries before.</param>
805+
/// <param name="actionType">The type of actions to filter.</param>
806+
/// <param name="userId">The user ID to filter entries for.</param>
804807
/// <returns>
805808
/// A task that represents the asynchronous get operation. The task result contains a read-only collection
806809
/// of the requested audit log entries.
807810
/// </returns>
808-
public IAsyncEnumerable<IReadOnlyCollection<RestAuditLogEntry>> GetAuditLogsAsync(int limit, RequestOptions options = null)
809-
=> GuildHelper.GetAuditLogsAsync(this, Discord, null, limit, options);
811+
public IAsyncEnumerable<IReadOnlyCollection<RestAuditLogEntry>> GetAuditLogsAsync(int limit, RequestOptions options = null, ulong? beforeId = null, ulong? userId = null, ActionType? actionType = null)
812+
=> GuildHelper.GetAuditLogsAsync(this, Discord, beforeId, limit, options, userId: userId, actionType: actionType);
810813

811814
//Webhooks
812815
/// <summary>
@@ -1160,10 +1163,11 @@ Task<IGuildUser> IGuild.GetOwnerAsync(CacheMode mode, RequestOptions options)
11601163
=> Task.FromResult<IGuildUser>(Owner);
11611164

11621165
/// <inheritdoc />
1163-
async Task<IReadOnlyCollection<IAuditLogEntry>> IGuild.GetAuditLogsAsync(int limit, CacheMode cacheMode, RequestOptions options)
1166+
async Task<IReadOnlyCollection<IAuditLogEntry>> IGuild.GetAuditLogsAsync(int limit, CacheMode cacheMode, RequestOptions options,
1167+
ulong? beforeId, ulong? userId, ActionType? actionType)
11641168
{
11651169
if (cacheMode == CacheMode.AllowDownload)
1166-
return (await GetAuditLogsAsync(limit, options).FlattenAsync().ConfigureAwait(false)).ToImmutableArray();
1170+
return (await GetAuditLogsAsync(limit, options, beforeId: beforeId, userId: userId, actionType: actionType).FlattenAsync().ConfigureAwait(false)).ToImmutableArray();
11671171
else
11681172
return ImmutableArray.Create<IAuditLogEntry>();
11691173
}

0 commit comments

Comments
 (0)