* Support Gateway Intents Allows supplying gateway intents through DiscordSocketConfig which will be passed through the IDENTIFY payload, in order to choose what gateway events you want to receive. * Fixing enum casing * Feedback * Updating comment for GuildSubscriptions * Comment updatepull/1570/head
@@ -0,0 +1,41 @@ | |||||
using System; | |||||
namespace Discord | |||||
{ | |||||
[Flags] | |||||
public enum GatewayIntents | |||||
{ | |||||
/// <summary> This intent includes no events </summary> | |||||
None = 0, | |||||
/// <summary> This intent includes GUILD_CREATE, GUILD_UPDATE, GUILD_DELETE, GUILD_ROLE_CREATE, GUILD_ROLE_UPDATE, GUILD_ROLE_DELETE, CHANNEL_CREATE, CHANNEL_UPDATE, CHANNEL_DELETE, CHANNEL_PINS_UPDATE </summary> | |||||
Guilds = 1 << 0, | |||||
/// <summary> This intent includes GUILD_MEMBER_ADD, GUILD_MEMBER_UPDATE, GUILD_MEMBER_REMOVE </summary> | |||||
GuildMembers = 1 << 1, | |||||
/// <summary> This intent includes GUILD_BAN_ADD, GUILD_BAN_REMOVE </summary> | |||||
GuildBans = 1 << 2, | |||||
/// <summary> This intent includes GUILD_EMOJIS_UPDATE </summary> | |||||
GuildEmojis = 1 << 3, | |||||
/// <summary> This intent includes GUILD_INTEGRATIONS_UPDATE </summary> | |||||
GuildIntegrations = 1 << 4, | |||||
/// <summary> This intent includes WEBHOOKS_UPDATE </summary> | |||||
GuildWebhooks = 1 << 5, | |||||
/// <summary> This intent includes INVITE_CREATE, INVITE_DELETE </summary> | |||||
GuildInvites = 1 << 6, | |||||
/// <summary> This intent includes VOICE_STATE_UPDATE </summary> | |||||
GuildVoiceStates = 1 << 7, | |||||
/// <summary> This intent includes PRESENCE_UPDATE </summary> | |||||
GuildPresences = 1 << 8, | |||||
/// <summary> This intent includes MESSAGE_CREATE, MESSAGE_UPDATE, MESSAGE_DELETE, MESSAGE_DELETE_BULK </summary> | |||||
GuildMessages = 1 << 9, | |||||
/// <summary> This intent includes MESSAGE_REACTION_ADD, MESSAGE_REACTION_REMOVE, MESSAGE_REACTION_REMOVE_ALL, MESSAGE_REACTION_REMOVE_EMOJI </summary> | |||||
GuildMessageReactions = 1 << 10, | |||||
/// <summary> This intent includes TYPING_START </summary> | |||||
GuildMessageTyping = 1 << 11, | |||||
/// <summary> This intent includes CHANNEL_CREATE, MESSAGE_CREATE, MESSAGE_UPDATE, MESSAGE_DELETE, CHANNEL_PINS_UPDATE </summary> | |||||
DirectMessages = 1 << 12, | |||||
/// <summary> This intent includes MESSAGE_REACTION_ADD, MESSAGE_REACTION_REMOVE, MESSAGE_REACTION_REMOVE_ALL, MESSAGE_REACTION_REMOVE_EMOJI </summary> | |||||
DirectMessageReactions = 1 << 13, | |||||
/// <summary> This intent includes TYPING_START </summary> | |||||
DirectMessageTyping = 1 << 14, | |||||
} | |||||
} |
@@ -1,4 +1,4 @@ | |||||
#pragma warning disable CS1591 | |||||
#pragma warning disable CS1591 | |||||
using Newtonsoft.Json; | using Newtonsoft.Json; | ||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
@@ -17,5 +17,7 @@ namespace Discord.API.Gateway | |||||
public Optional<int[]> ShardingParams { get; set; } | public Optional<int[]> ShardingParams { get; set; } | ||||
[JsonProperty("guild_subscriptions")] | [JsonProperty("guild_subscriptions")] | ||||
public Optional<bool> GuildSubscriptions { get; set; } | public Optional<bool> GuildSubscriptions { get; set; } | ||||
[JsonProperty("intents")] | |||||
public Optional<int> Intents { get; set; } | |||||
} | } | ||||
} | } |
@@ -209,7 +209,7 @@ namespace Discord.API | |||||
await _sentGatewayMessageEvent.InvokeAsync(opCode).ConfigureAwait(false); | 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); | options = RequestOptions.CreateOrClone(options); | ||||
var props = new Dictionary<string, string> | var props = new Dictionary<string, string> | ||||
@@ -220,12 +220,16 @@ namespace Discord.API | |||||
{ | { | ||||
Token = AuthToken, | Token = AuthToken, | ||||
Properties = props, | Properties = props, | ||||
LargeThreshold = largeThreshold, | |||||
GuildSubscriptions = guildSubscriptions | |||||
LargeThreshold = largeThreshold | |||||
}; | }; | ||||
if (totalShards > 1) | if (totalShards > 1) | ||||
msg.ShardingParams = new int[] { shardID, totalShards }; | msg.ShardingParams = new int[] { shardID, totalShards }; | ||||
if (gatewayIntents.HasValue) | |||||
msg.Intents = (int)gatewayIntents.Value; | |||||
else | |||||
msg.GuildSubscriptions = guildSubscriptions; | |||||
await SendGatewayAsync(GatewayOpCode.Identify, msg, options: options).ConfigureAwait(false); | await SendGatewayAsync(GatewayOpCode.Identify, msg, options: options).ConfigureAwait(false); | ||||
} | } | ||||
public async Task SendResumeAsync(string sessionId, int lastSeq, RequestOptions options = null) | public async Task SendResumeAsync(string sessionId, int lastSeq, RequestOptions options = null) | ||||
@@ -44,6 +44,7 @@ namespace Discord.WebSocket | |||||
private RestApplication _applicationInfo; | private RestApplication _applicationInfo; | ||||
private bool _isDisposed; | private bool _isDisposed; | ||||
private bool _guildSubscriptions; | private bool _guildSubscriptions; | ||||
private GatewayIntents? _gatewayIntents; | |||||
/// <summary> | /// <summary> | ||||
/// Provides access to a REST-only client with a shared state from this client. | /// 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); | Rest = new DiscordSocketRestClient(config, ApiClient); | ||||
_heartbeatTimes = new ConcurrentQueue<long>(); | _heartbeatTimes = new ConcurrentQueue<long>(); | ||||
_guildSubscriptions = config.GuildSubscriptions; | _guildSubscriptions = config.GuildSubscriptions; | ||||
_gatewayIntents = config.GatewayIntents; | |||||
_stateLock = new SemaphoreSlim(1, 1); | _stateLock = new SemaphoreSlim(1, 1); | ||||
_gatewayLogger = LogManager.CreateLogger(ShardId == 0 && TotalShards == 1 ? "Gateway" : $"Shard #{ShardId}"); | _gatewayLogger = LogManager.CreateLogger(ShardId == 0 && TotalShards == 1 ? "Gateway" : $"Shard #{ShardId}"); | ||||
@@ -242,7 +244,7 @@ namespace Discord.WebSocket | |||||
else | else | ||||
{ | { | ||||
await _gatewayLogger.DebugAsync("Identifying").ConfigureAwait(false); | 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 | //Wait for READY | ||||
@@ -517,7 +519,7 @@ namespace Discord.WebSocket | |||||
_sessionId = null; | _sessionId = null; | ||||
_lastSeq = 0; | _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; | break; | ||||
case GatewayOpCode.Reconnect: | case GatewayOpCode.Reconnect: | ||||
@@ -121,10 +121,21 @@ namespace Discord.WebSocket | |||||
/// <summary> | /// <summary> | ||||
/// Gets or sets enabling dispatching of guild subscription events e.g. presence and typing events. | /// Gets or sets enabling dispatching of guild subscription events e.g. presence and typing events. | ||||
/// This is not used if <see cref="GatewayIntents"/> are provided. | |||||
/// </summary> | /// </summary> | ||||
public bool GuildSubscriptions { get; set; } = true; | public bool GuildSubscriptions { get; set; } = true; | ||||
/// <summary> | /// <summary> | ||||
/// Gets or sets gateway intents to limit what events are sent from Discord. Allows for more granular control than the <see cref="GuildSubscriptions"/> property. | |||||
/// </summary> | |||||
/// <remarks> | |||||
/// For more information, please see | |||||
/// <see href="https://discord.com/developers/docs/topics/gateway#gateway-intents">GatewayIntents</see> | |||||
/// on the official Discord API documentation. | |||||
/// </remarks> | |||||
public GatewayIntents? GatewayIntents { get; set; } | |||||
/// <summary> | |||||
/// Initializes a default configuration. | /// Initializes a default configuration. | ||||
/// </summary> | /// </summary> | ||||
public DiscordSocketConfig() | public DiscordSocketConfig() | ||||