From 8b0973a23163aef5d328f0fbb51f8c5021f0bdb5 Mon Sep 17 00:00:00 2001 From: Misha133 Date: Sun, 30 Jun 2024 21:31:13 +0300 Subject: [PATCH] ill just hope it works --- .../Entities/Guilds/IGuild.cs | 3 + .../Entities/Guilds/JoinSourceType.cs | 29 ++++ .../Guilds/MemberSearchPropertiesV2.cs | 114 ++++++++++++- .../Entities/Guilds/MemberSearchV2SortType.cs | 27 +++ .../API/Rest/SearchGuildMembersParamsV2.cs | 71 +++++++- .../Entities/Guilds/GuildHelper.cs | 159 +++++++++++++++++- .../Entities/Guilds/RestGuild.cs | 1 + .../Entities/Guilds/SocketGuild.cs | 1 + 8 files changed, 397 insertions(+), 8 deletions(-) create mode 100644 src/Discord.Net.Core/Entities/Guilds/MemberSearchV2SortType.cs diff --git a/src/Discord.Net.Core/Entities/Guilds/IGuild.cs b/src/Discord.Net.Core/Entities/Guilds/IGuild.cs index b7c6ae27c3..afa169c3e3 100644 --- a/src/Discord.Net.Core/Entities/Guilds/IGuild.cs +++ b/src/Discord.Net.Core/Entities/Guilds/IGuild.cs @@ -1105,6 +1105,9 @@ public interface IGuild : IDeletable, ISnowflakeEntity /// Task> SearchUsersAsync(string query, int limit = DiscordConfig.MaxUsersPerBatch, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); + /// + /// Gets a collection of users in this guild that match the provided search criteria. + /// Task SearchUsersAsyncV2(int limit = DiscordConfig.MaxUsersPerBatch, MemberSearchPropertiesV2 args = null, RequestOptions options = null); /// diff --git a/src/Discord.Net.Core/Entities/Guilds/JoinSourceType.cs b/src/Discord.Net.Core/Entities/Guilds/JoinSourceType.cs index d94c2cd591..d9dabbf808 100644 --- a/src/Discord.Net.Core/Entities/Guilds/JoinSourceType.cs +++ b/src/Discord.Net.Core/Entities/Guilds/JoinSourceType.cs @@ -1,18 +1,47 @@ namespace Discord; +/// +/// Represents the source of a user joining a guild. +/// public enum JoinSourceType { + /// + /// Unknown source. + /// Unknown = 0, + /// + /// The user was invited by a bot. + /// BotInvite = 1, + /// + /// The user was invited by an integration. + /// Integration = 2, + /// + /// The user joined via server discovery. + /// ServerDiscovery = 3, + /// + /// The user joined via the student hub. + /// StudentHub = 4, + /// + /// The user joined via an invite code. + /// InviteCode = 5, + /// + /// The user joined via a vanity URL. + /// VanityUrl = 6, + + /// + /// The user was manually verified + /// + ManualVerification = 7 } diff --git a/src/Discord.Net.Core/Entities/Guilds/MemberSearchPropertiesV2.cs b/src/Discord.Net.Core/Entities/Guilds/MemberSearchPropertiesV2.cs index 67a7b90446..064bcea066 100644 --- a/src/Discord.Net.Core/Entities/Guilds/MemberSearchPropertiesV2.cs +++ b/src/Discord.Net.Core/Entities/Guilds/MemberSearchPropertiesV2.cs @@ -1,19 +1,129 @@ +using System; +using System.Collections.Generic; +using System.Linq; + namespace Discord; +/// +/// Represents the properties for searching members in a guild. +/// public class MemberSearchPropertiesV2 { + /// + /// Gets or sets the after property for the search. + /// public MemberSearchPropertiesV2After After { get; set; } + + /// + /// Gets or sets the sort type for the search. + /// + public MemberSearchV2SortType Sort { get; set; } + + /// + /// + /// + public MemberSearchV2QueryParams? AndQuery { get; set; } + + /// + /// + /// + public MemberSearchV2QueryParams? OrQuery { get; set; } } + +/// +/// Represents the after property for searching members in a guild. +/// public struct MemberSearchPropertiesV2After { + /// + /// Gets or sets the user ID to search after. + /// public ulong UserId { get; set; } - public ulong GuildJoinedAt { get; set; } + /// + /// Gets or sets the guild joined at timestamp to search after. + /// + public long GuildJoinedAt { get; set; } - public MemberSearchPropertiesV2After(ulong userId, ulong guildJoinedAt) + public MemberSearchPropertiesV2After(ulong userId, long guildJoinedAt) { UserId = userId; GuildJoinedAt = guildJoinedAt; } + + public MemberSearchPropertiesV2After(ulong userId, DateTimeOffset guildJoinedAt) + { + UserId = userId; + GuildJoinedAt = guildJoinedAt.ToUnixTimeMilliseconds(); + } +} + +public struct MemberSearchV2QueryParams +{ + public MemberSearchV2SafetySignalsProperties? SafetySignals { get; set; } + + public MemberSearchV2QueryProperties? RoleIds { get; set; } + + public MemberSearchV2RangeProperties? UserId { get; set; } + + public MemberSearchV2RangeProperties? GuildJoinedAt { get; set; } + + public MemberSearchV2QueryProperties? SourceInviteCode { get; set; } + + public MemberSearchV2QueryProperties? JoinSourceType { get; set; } +} + +public struct MemberSearchV2SafetySignalsProperties +{ + public MemberSearchV2SafetySignalProperties? UnusualDmActivityUntil { get; set; } + + public MemberSearchV2SafetySignalProperties? CommunicationDisabledUntil { get; set; } + + public bool? UnusualAccountActivity { get; set; } + + public bool? AutomodQuarantinedUsername { get; set; } +} + +public readonly struct MemberSearchV2QueryProperties +{ + public Dictionary AndQuery { get; } + + public Dictionary OrQuery { get; } + + public MemberSearchV2QueryProperties(Dictionary andQuery, Dictionary orQuery) + { + AndQuery = andQuery; + OrQuery = orQuery; + } + + public MemberSearchV2QueryProperties(Dictionary andQuery, Dictionary orQuery) + { + AndQuery = andQuery.Select(x => new KeyValuePair(x.Key, x.Value)).ToDictionary(); + OrQuery = orQuery.Select(x => new KeyValuePair(x.Key, x.Value)).ToDictionary(); + } + + public MemberSearchV2QueryProperties(Dictionary andQuery, Dictionary orQuery) + { + AndQuery = andQuery.Select(x => new KeyValuePair(x.Key, x.Value)).ToDictionary(); + OrQuery = orQuery.Select(x => new KeyValuePair(x.Key, x.Value)).ToDictionary(); + } +} + +public struct MemberSearchV2SafetySignalProperties +{ + public MemberSearchV2RangeProperties Range { get; set; } +} + +public struct MemberSearchV2RangeProperties +{ + /// + /// Gets or sets the less than property for the search. + /// + public long? LessThanOrEqual { get; set; } + + /// + /// Gets or sets the greater than property for the search. + /// + public long? GreaterThanOrEqual { get; set; } } diff --git a/src/Discord.Net.Core/Entities/Guilds/MemberSearchV2SortType.cs b/src/Discord.Net.Core/Entities/Guilds/MemberSearchV2SortType.cs new file mode 100644 index 0000000000..39fce29bed --- /dev/null +++ b/src/Discord.Net.Core/Entities/Guilds/MemberSearchV2SortType.cs @@ -0,0 +1,27 @@ +namespace Discord; + +/// +/// Represents the sort type for searching members in a guild. +/// +public enum MemberSearchV2SortType +{ + /// + /// Sort by member since newest first. + /// + MemberSinceNewestFirst = 1, + + /// + /// Sort by member since oldest first. + /// + MemberSinceOldestFirst = 2, + + /// + /// Sort by joined discord since newest first. + /// + JoinedDiscordNewestFirst = 3, + + /// + /// Sort by joined discord since oldest first. + /// + JoinedDiscordOldestFirst = 4, +} diff --git a/src/Discord.Net.Rest/API/Rest/SearchGuildMembersParamsV2.cs b/src/Discord.Net.Rest/API/Rest/SearchGuildMembersParamsV2.cs index 5d32f644c6..709e854233 100644 --- a/src/Discord.Net.Rest/API/Rest/SearchGuildMembersParamsV2.cs +++ b/src/Discord.Net.Rest/API/Rest/SearchGuildMembersParamsV2.cs @@ -9,20 +9,83 @@ internal class SearchGuildMembersParamsV2 public Optional Limit { get; set; } [JsonProperty("and_query")] - public Dictionary AndQuery { get; set; } + public Optional AndQuery { get; set; } [JsonProperty("or_query")] - public Dictionary OrQuery { get; set; } + public Optional OrQuery { get; set; } [JsonProperty("after")] - public SearchParamsAfter After { get; set; } + public Optional After { get; set; } + + [JsonProperty("sort")] + public Optional Sort { get; set; } } internal class SearchParamsAfter { [JsonProperty("guild_joined_at")] - public ulong GuildJoinedAt { get; set; } + public long GuildJoinedAt { get; set; } [JsonProperty("user_id")] public ulong UserId { get; set; } } + +internal class SearchQueryParams +{ + [JsonProperty("safety_signals")] + public Optional SafetySignals { get; set; } + + [JsonProperty("role_ids")] + public Optional RoleIds { get; set; } + + [JsonProperty("user_id")] + public Optional UserId { get; set; } + + [JsonProperty("guild_joined_at")] + public Optional GuildJoinedAt { get; set; } + + [JsonProperty("source_invite_code")] + public Optional SourceInviteCode { get; set; } + + [JsonProperty("join_source_type")] + public Optional JoinSourceType { get; set; } +} + +internal class SearchQueryProperties +{ + [JsonProperty("and_query")] + public Optional> AndQuery { get; set; } + + [JsonProperty("or_query")] + public Optional> OrQuery { get; set; } +} + +internal class SafetySignalsProperties +{ + [JsonProperty("unusual_dm_activity_until")] + public Optional UnusualDMActivityUntil { get; set; } + + [JsonProperty("communication_disabled_until")] + public Optional CommunicationDisabledUntil { get; set; } + + [JsonProperty("unusual_account_activity")] + public Optional UnusualAccountActivity { get; set; } + + [JsonProperty("automod_quarantined_username")] + public Optional AutomodQuarantinedUsername { get; set; } +} + +internal class SafetySignalProperties +{ + [JsonProperty("range")] + public SearchRangeProperties Until { get; set; } +} + +internal class SearchRangeProperties +{ + [JsonProperty("gte")] + public Optional GreaterThanOrEqual { get; set; } + + [JsonProperty("lte")] + public Optional LessThanOrEqual { get; set; } +} diff --git a/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs b/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs index 49d783b1b9..563bf32afc 100644 --- a/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs +++ b/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs @@ -772,11 +772,166 @@ public static async Task SearchUsersAsyncV2(IGuild guild, Ba Limit = limit, After = args is null ? null - : new () + : new SearchParamsAfter { UserId = args.After.UserId, GuildJoinedAt = args.After.GuildJoinedAt - } + }, + Sort = args?.Sort ?? Optional.Unspecified, + OrQuery = args is null + ? Optional.Unspecified + : args.OrQuery is null + ? Optional.Unspecified + : new SearchQueryParams + { + GuildJoinedAt = args.OrQuery.Value.GuildJoinedAt is null + ? Optional.Unspecified + : new SearchRangeProperties + { + GreaterThanOrEqual = args.OrQuery.Value.GuildJoinedAt.Value.GreaterThanOrEqual is null + ? Optional.Unspecified + : args.OrQuery.Value.GuildJoinedAt.Value.GreaterThanOrEqual.Value, + LessThanOrEqual = args.OrQuery.Value.GuildJoinedAt.Value.LessThanOrEqual is null + ? Optional.Unspecified + : args.OrQuery.Value.GuildJoinedAt.Value.LessThanOrEqual.Value, + }, + JoinSourceType = args.OrQuery.Value.JoinSourceType is null + ? Optional.Unspecified + : new SearchQueryProperties + { + AndQuery = args.OrQuery.Value.JoinSourceType.Value.AndQuery ?? Optional>.Unspecified, + OrQuery = args.OrQuery.Value.JoinSourceType.Value.OrQuery ?? Optional>.Unspecified + }, + RoleIds = args.OrQuery.Value.RoleIds is null + ? Optional.Unspecified + : new SearchQueryProperties + { + AndQuery = args.OrQuery.Value.RoleIds.Value.AndQuery ?? Optional>.Unspecified, + OrQuery = args.OrQuery.Value.RoleIds.Value.OrQuery ?? Optional>.Unspecified + }, + SourceInviteCode = args.OrQuery.Value.SourceInviteCode is null + ? Optional.Unspecified + : new SearchQueryProperties + { + AndQuery = args.OrQuery.Value.SourceInviteCode.Value.AndQuery ?? Optional>.Unspecified, + OrQuery = args.OrQuery.Value.SourceInviteCode.Value.OrQuery ?? Optional>.Unspecified + }, + SafetySignals = args.OrQuery.Value.SafetySignals is null + ? Optional.Unspecified + : new SafetySignalsProperties + { + AutomodQuarantinedUsername = args.OrQuery.Value.SafetySignals.Value.AutomodQuarantinedUsername is null + ? Optional.Unspecified + : args.OrQuery.Value.SafetySignals.Value.AutomodQuarantinedUsername.Value, + UnusualAccountActivity = args.OrQuery.Value.SafetySignals.Value.UnusualAccountActivity is null + ? Optional.Unspecified + : args.OrQuery.Value.SafetySignals.Value.UnusualAccountActivity.Value, + CommunicationDisabledUntil = args.OrQuery.Value.SafetySignals.Value.CommunicationDisabledUntil is null + ? Optional.Unspecified + : new SafetySignalProperties + { + Until = new SearchRangeProperties + { + GreaterThanOrEqual = args.OrQuery.Value.SafetySignals.Value.CommunicationDisabledUntil.Value.Range.GreaterThanOrEqual ?? Optional.Unspecified, + LessThanOrEqual = args.OrQuery.Value.SafetySignals.Value.CommunicationDisabledUntil.Value.Range.LessThanOrEqual ?? Optional.Unspecified, + } + }, + UnusualDMActivityUntil = args.OrQuery.Value.SafetySignals.Value.UnusualDmActivityUntil is null + ? Optional.Unspecified + : new SafetySignalProperties + { + Until = new SearchRangeProperties + { + GreaterThanOrEqual = args.OrQuery.Value.SafetySignals.Value.UnusualDmActivityUntil.Value.Range.GreaterThanOrEqual ?? Optional.Unspecified, + LessThanOrEqual = args.OrQuery.Value.SafetySignals.Value.UnusualDmActivityUntil.Value.Range.LessThanOrEqual ?? Optional.Unspecified, + } + }, + }, + UserId = args.OrQuery.Value.UserId is null + ? Optional.Unspecified + : new SearchRangeProperties + { + LessThanOrEqual = args.OrQuery.Value.UserId.Value.LessThanOrEqual ?? Optional.Unspecified, + GreaterThanOrEqual = args.OrQuery.Value.UserId.Value.GreaterThanOrEqual ?? Optional.Unspecified, + }, + }, + AndQuery = args is null + ? Optional.Unspecified + : args.AndQuery is null + ? Optional.Unspecified + : new SearchQueryParams + { + GuildJoinedAt = args.AndQuery.Value.GuildJoinedAt is null + ? Optional.Unspecified + : new SearchRangeProperties + { + GreaterThanOrEqual = args.AndQuery.Value.GuildJoinedAt.Value.GreaterThanOrEqual is null + ? Optional.Unspecified + : args.AndQuery.Value.GuildJoinedAt.Value.GreaterThanOrEqual.Value, + LessThanOrEqual = args.AndQuery.Value.GuildJoinedAt.Value.LessThanOrEqual is null + ? Optional.Unspecified + : args.AndQuery.Value.GuildJoinedAt.Value.LessThanOrEqual.Value, + }, + JoinSourceType = args.AndQuery.Value.JoinSourceType is null + ? Optional.Unspecified + : new SearchQueryProperties + { + AndQuery = args.AndQuery.Value.JoinSourceType.Value.AndQuery ?? Optional>.Unspecified, + OrQuery = args.AndQuery.Value.JoinSourceType.Value.OrQuery ?? Optional>.Unspecified + }, + RoleIds = args.AndQuery.Value.RoleIds is null + ? Optional.Unspecified + : new SearchQueryProperties + { + AndQuery = args.AndQuery.Value.RoleIds.Value.AndQuery ?? Optional>.Unspecified, + OrQuery = args.AndQuery.Value.RoleIds.Value.OrQuery ?? Optional>.Unspecified + }, + SourceInviteCode = args.AndQuery.Value.SourceInviteCode is null + ? Optional.Unspecified + : new SearchQueryProperties + { + AndQuery = args.AndQuery.Value.SourceInviteCode.Value.AndQuery ?? Optional>.Unspecified, + OrQuery = args.AndQuery.Value.SourceInviteCode.Value.OrQuery ?? Optional>.Unspecified + }, + SafetySignals = args.AndQuery.Value.SafetySignals is null + ? Optional.Unspecified + : new SafetySignalsProperties + { + AutomodQuarantinedUsername = args.AndQuery.Value.SafetySignals.Value.AutomodQuarantinedUsername is null + ? Optional.Unspecified + : args.AndQuery.Value.SafetySignals.Value.AutomodQuarantinedUsername.Value, + UnusualAccountActivity = args.AndQuery.Value.SafetySignals.Value.UnusualAccountActivity is null + ? Optional.Unspecified + : args.AndQuery.Value.SafetySignals.Value.UnusualAccountActivity.Value, + CommunicationDisabledUntil = args.AndQuery.Value.SafetySignals.Value.CommunicationDisabledUntil is null + ? Optional.Unspecified + : new SafetySignalProperties + { + Until = new SearchRangeProperties + { + GreaterThanOrEqual = args.AndQuery.Value.SafetySignals.Value.CommunicationDisabledUntil.Value.Range.GreaterThanOrEqual ?? Optional.Unspecified, + LessThanOrEqual = args.AndQuery.Value.SafetySignals.Value.CommunicationDisabledUntil.Value.Range.LessThanOrEqual ?? Optional.Unspecified, + } + }, + UnusualDMActivityUntil = args.AndQuery.Value.SafetySignals.Value.UnusualDmActivityUntil is null + ? Optional.Unspecified + : new SafetySignalProperties + { + Until = new SearchRangeProperties + { + GreaterThanOrEqual = args.AndQuery.Value.SafetySignals.Value.UnusualDmActivityUntil.Value.Range.GreaterThanOrEqual ?? Optional.Unspecified, + LessThanOrEqual = args.AndQuery.Value.SafetySignals.Value.UnusualDmActivityUntil.Value.Range.LessThanOrEqual ?? Optional.Unspecified, + } + }, + }, + UserId = args.AndQuery.Value.UserId is null + ? Optional.Unspecified + : new SearchRangeProperties + { + LessThanOrEqual = args.AndQuery.Value.UserId.Value.LessThanOrEqual ?? Optional.Unspecified, + GreaterThanOrEqual = args.AndQuery.Value.UserId.Value.GreaterThanOrEqual ?? Optional.Unspecified, + }, + }, }; var model = await client.ApiClient.SearchGuildMembersAsyncV2(guild.Id, apiArgs, options); diff --git a/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs b/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs index 92fabd0e3f..f0ca509331 100644 --- a/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs +++ b/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs @@ -984,6 +984,7 @@ public Task PruneUsersAsync(int days = 30, bool simulate = false, RequestOp public Task> SearchUsersAsync(string query, int limit = DiscordConfig.MaxUsersPerBatch, RequestOptions options = null) => GuildHelper.SearchUsersAsync(this, Discord, query, limit, options); + /// public Task SearchUsersAsyncV2(int limit = DiscordConfig.MaxUsersPerBatch, MemberSearchPropertiesV2 args = null, RequestOptions options = null) => GuildHelper.SearchUsersAsyncV2(this, Discord, limit, args, options); #endregion diff --git a/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs b/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs index ac3ae0c39a..bb6c3748f2 100644 --- a/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs +++ b/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs @@ -1337,6 +1337,7 @@ internal void CompleteDownloadUsers() public Task> SearchUsersAsync(string query, int limit = DiscordConfig.MaxUsersPerBatch, RequestOptions options = null) => GuildHelper.SearchUsersAsync(this, Discord, query, limit, options); + /// public Task SearchUsersAsyncV2(int limit = DiscordConfig.MaxUsersPerBatch, MemberSearchPropertiesV2 args = null, RequestOptions options = null) => GuildHelper.SearchUsersAsyncV2(this, Discord, limit, args, options); #endregion