diff --git a/src/Discord.Net.Core/GatewayIntents.cs b/src/Discord.Net.Core/GatewayIntents.cs new file mode 100644 index 000000000..b6f7d15d8 --- /dev/null +++ b/src/Discord.Net.Core/GatewayIntents.cs @@ -0,0 +1,39 @@ +using System; + +namespace Discord +{ + [Flags] + public enum GatewayIntents + { + /// GUILD_CREATE, GUILD_UPDATE, GUILD_DELETE, GUILD_ROLE_CREATE, GUILD_ROLE_UPDATE, GUILD_ROLE_DELETE, CHANNEL_CREATE, CHANNEL_UPDATE, CHANNEL_DELETE, CHANNEL_PINS_UPDATE + GUILDS = 1 << 0, + /// GUILD_MEMBER_ADD, GUILD_MEMBER_UPDATE, GUILD_MEMBER_REMOVE + GUILD_MEMBERS = 1 << 1, + /// GUILD_BAN_ADD, GUILD_BAN_REMOVE + GUILD_BANS = 1 << 2, + /// GUILD_EMOJIS_UPDATE + GUILD_EMOJIS = 1 << 3, + /// GUILD_INTEGRATIONS_UPDATE + GUILD_INTEGRATIONS = 1 << 4, + /// WEBHOOKS_UPDATE + GUILD_WEBHOOKS = 1 << 5, + /// INVITE_CREATE, INVITE_DELETE + GUILD_INVITES = 1 << 6, + /// VOICE_STATE_UPDATE + GUILD_VOICE_STATES = 1 << 7, + /// PRESENCE_UPDATE + GUILD_PRESENCES = 1 << 8, + /// MESSAGE_CREATE, MESSAGE_UPDATE, MESSAGE_DELETE, MESSAGE_DELETE_BULK + GUILD_MESSAGES = 1 << 9, + /// MESSAGE_REACTION_ADD, MESSAGE_REACTION_REMOVE, MESSAGE_REACTION_REMOVE_ALL, MESSAGE_REACTION_REMOVE_EMOJI + GUILD_MESSAGE_REACTIONS = 1 << 10, + /// TYPING_START + GUILD_MESSAGE_TYPING = 1 << 11, + /// CHANNEL_CREATE, MESSAGE_CREATE, MESSAGE_UPDATE, MESSAGE_DELETE, CHANNEL_PINS_UPDATE + DIRECT_MESSAGES = 1 << 12, + /// MESSAGE_REACTION_ADD, MESSAGE_REACTION_REMOVE, MESSAGE_REACTION_REMOVE_ALL, MESSAGE_REACTION_REMOVE_EMOJI + DIRECT_MESSAGE_REACTIONS = 1 << 13, + /// TYPING_START + DIRECT_MESSAGE_TYPING = 1 << 14, + } +} diff --git a/src/Discord.Net.WebSocket/API/Gateway/IdentifyParams.cs b/src/Discord.Net.WebSocket/API/Gateway/IdentifyParams.cs index 1e0bf71c2..e3e24491d 100644 --- a/src/Discord.Net.WebSocket/API/Gateway/IdentifyParams.cs +++ b/src/Discord.Net.WebSocket/API/Gateway/IdentifyParams.cs @@ -1,4 +1,4 @@ -#pragma warning disable CS1591 +#pragma warning disable CS1591 using Newtonsoft.Json; using System.Collections.Generic; @@ -17,5 +17,7 @@ namespace Discord.API.Gateway public Optional ShardingParams { get; set; } [JsonProperty("guild_subscriptions")] public Optional GuildSubscriptions { get; set; } + [JsonProperty("intents")] + public Optional Intents { get; set; } } } diff --git a/src/Discord.Net.WebSocket/DiscordSocketApiClient.cs b/src/Discord.Net.WebSocket/DiscordSocketApiClient.cs index ef97615e2..9702a1031 100644 --- a/src/Discord.Net.WebSocket/DiscordSocketApiClient.cs +++ b/src/Discord.Net.WebSocket/DiscordSocketApiClient.cs @@ -209,7 +209,7 @@ namespace Discord.API await _sentGatewayMessageEvent.InvokeAsync(opCode).ConfigureAwait(false); } - public async Task SendIdentifyAsync(int largeThreshold = 100, int shardID = 0, int totalShards = 1, bool guildSubscriptions = true, RequestOptions options = null) + public async Task SendIdentifyAsync(int largeThreshold = 100, int shardID = 0, int totalShards = 1, bool guildSubscriptions = true, GatewayIntents? gatewayIntents = null, RequestOptions options = null) { options = RequestOptions.CreateOrClone(options); var props = new Dictionary @@ -220,12 +220,16 @@ namespace Discord.API { Token = AuthToken, Properties = props, - LargeThreshold = largeThreshold, - GuildSubscriptions = guildSubscriptions + LargeThreshold = largeThreshold }; if (totalShards > 1) msg.ShardingParams = new int[] { shardID, totalShards }; + if (gatewayIntents.HasValue) + msg.Intents = Convert.ToInt32(gatewayIntents); + else + msg.GuildSubscriptions = guildSubscriptions; + await SendGatewayAsync(GatewayOpCode.Identify, msg, options: options).ConfigureAwait(false); } public async Task SendResumeAsync(string sessionId, int lastSeq, RequestOptions options = null) diff --git a/src/Discord.Net.WebSocket/DiscordSocketClient.cs b/src/Discord.Net.WebSocket/DiscordSocketClient.cs index b56498061..6e7152192 100644 --- a/src/Discord.Net.WebSocket/DiscordSocketClient.cs +++ b/src/Discord.Net.WebSocket/DiscordSocketClient.cs @@ -44,6 +44,7 @@ namespace Discord.WebSocket private RestApplication _applicationInfo; private bool _isDisposed; private bool _guildSubscriptions; + private GatewayIntents? _gatewayIntents; /// /// Provides access to a REST-only client with a shared state from this client. @@ -137,6 +138,7 @@ namespace Discord.WebSocket Rest = new DiscordSocketRestClient(config, ApiClient); _heartbeatTimes = new ConcurrentQueue(); _guildSubscriptions = config.GuildSubscriptions; + _gatewayIntents = config.GatewayIntents; _stateLock = new SemaphoreSlim(1, 1); _gatewayLogger = LogManager.CreateLogger(ShardId == 0 && TotalShards == 1 ? "Gateway" : $"Shard #{ShardId}"); @@ -242,7 +244,7 @@ namespace Discord.WebSocket else { await _gatewayLogger.DebugAsync("Identifying").ConfigureAwait(false); - await ApiClient.SendIdentifyAsync(shardID: ShardId, totalShards: TotalShards, guildSubscriptions: _guildSubscriptions).ConfigureAwait(false); + await ApiClient.SendIdentifyAsync(shardID: ShardId, totalShards: TotalShards, guildSubscriptions: _guildSubscriptions, gatewayIntents: _gatewayIntents).ConfigureAwait(false); } //Wait for READY @@ -517,7 +519,7 @@ namespace Discord.WebSocket _sessionId = null; _lastSeq = 0; - await ApiClient.SendIdentifyAsync(shardID: ShardId, totalShards: TotalShards).ConfigureAwait(false); + await ApiClient.SendIdentifyAsync(shardID: ShardId, totalShards: TotalShards, guildSubscriptions: _guildSubscriptions, gatewayIntents: _gatewayIntents).ConfigureAwait(false); } break; case GatewayOpCode.Reconnect: diff --git a/src/Discord.Net.WebSocket/DiscordSocketConfig.cs b/src/Discord.Net.WebSocket/DiscordSocketConfig.cs index 98ab0ef9b..a8632b8b1 100644 --- a/src/Discord.Net.WebSocket/DiscordSocketConfig.cs +++ b/src/Discord.Net.WebSocket/DiscordSocketConfig.cs @@ -124,6 +124,16 @@ namespace Discord.WebSocket /// public bool GuildSubscriptions { get; set; } = true; + /// + /// Gets or sets gateway intents to limit what events are sent from Discord. Allows for more granular control than the 'GuildSubscriptions' property. + /// + /// + /// For more information, please see + /// GatewayIntents + /// on the official Discord API documentation. + /// + public GatewayIntents? GatewayIntents { get; set; } + /// /// Initializes a default configuration. ///