Skip to content

Commit

Permalink
Add intent support
Browse files Browse the repository at this point in the history
  • Loading branch information
swarley committed Jun 29, 2020
1 parent 0a32817 commit 639df58
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 6 deletions.
22 changes: 22 additions & 0 deletions lib/discordrb.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,28 @@ module Discordrb
# The unix timestamp Discord IDs are based on
DISCORD_EPOCH = 1_420_070_400_000

# Used to declare what events you wish to recieve from Discord.
# @see https://discordapp.com/developers/docs/topics/gateway#gateway-intents
INTENTS = {
servers: 1 << 0,
server_members: 1 << 1,
server_bans: 1 << 2,
server_emojis: 1 << 3,
server_integrations: 1 << 4,
server_webhooks: 1 << 5,
server_invites: 1 << 6,
server_voice_states: 1 << 7,
server_presences: 1 << 8,
server_messages: 1 << 9,
server_message_reactions: 1 << 10,
server_message_typing: 1 << 11,
direct_messages: 1 << 12,
direct_message_reactions: 1 << 13,
direct_message_typing: 1 << 14
}.freeze

ALL_INTENTS = INTENTS.values.reduce(&:|)

# Compares two objects based on IDs - either the objects' IDs are equal, or one object is equal to the other's ID.
def self.id_compare(one_id, other)
other.respond_to?(:resolve_id) ? (one_id.resolve_id == other.resolve_id) : (one_id == other)
Expand Down
28 changes: 25 additions & 3 deletions lib/discordrb/bot.rb
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,13 @@ class Bot
# to Discord's gateway. `:none` will request that no payloads are received compressed (not recommended for
# production bots). `:large` will request that large payloads are received compressed. `:stream` will request
# that all data be received in a continuous compressed stream.
# @param intents [:all, Array<Symbol>] Intents that this bot requires. See {Discordrb::INTENTS}
def initialize(
log_mode: :normal,
token: nil, client_id: nil,
type: nil, name: '', fancy_log: false, suppress_ready: false, parse_self: false,
shard_id: nil, num_shards: nil, redact_token: true, ignore_bots: false,
compress_mode: :large
compress_mode: :large, intents: :all
)
LOGGER.mode = log_mode
LOGGER.token = token if redact_token
Expand All @@ -127,8 +128,10 @@ def initialize(

raise 'Token string is empty or nil' if token.nil? || token.empty?

@intents = intents == :all ? INTENTS.values.reduce(&:|) : calculate_intents(intents)

@token = process_token(@type, token)
@gateway = Gateway.new(self, @token, @shard_key, @compress_mode)
@gateway = Gateway.new(self, @token, @shard_key, @compress_mode, @intents)

init_cache

Expand Down Expand Up @@ -1013,7 +1016,7 @@ def process_token(type, token)

def handle_dispatch(type, data)
# Check whether there are still unavailable servers and there have been more than 10 seconds since READY
if @unavailable_servers&.positive? && (Time.now - @unavailable_timeout_time) > 10
if @unavailable_servers&.positive? && (Time.now - @unavailable_timeout_time) > 10 && !(@intents & INTENTS[:servers]).zero?
# The server streaming timed out!
LOGGER.debug("Server streaming timed out with #{@unavailable_servers} servers remaining")
LOGGER.debug('Calling ready now because server loading is taking a long time. Servers may be unavailable due to an outage, or your bot is on very large servers.')
Expand Down Expand Up @@ -1397,5 +1400,24 @@ def handle_awaits(event)
raise_event(await_event)
end
end

def calculate_intents(intents)
intents.reduce(0) do |sum, intent|
case intent
when Symbol
if INTENTS[intent]
sum | INTENTS[intent]
else
LOGGER.warn("Unknown intent: #{intent}")
sum
end
when Integer
sum | intent
else
LOGGER.warn("Invalid intent: #{intent}")
sum
end
end
end
end
end
4 changes: 3 additions & 1 deletion lib/discordrb/commands/command_bot.rb
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,9 @@ def initialize(attributes = {})
num_shards: attributes[:num_shards],
redact_token: attributes.key?(:redact_token) ? attributes[:redact_token] : true,
ignore_bots: attributes[:ignore_bots],
compress_mode: attributes[:compress_mode])
compress_mode: attributes[:compress_mode],
intents: attributes[:intents] || :all
)

@prefix = attributes[:prefix]
@attributes = {
Expand Down
7 changes: 5 additions & 2 deletions lib/discordrb/gateway.rb
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ class Gateway
# @return [true, false] whether or not this gateway should check for heartbeat ACKs.
attr_accessor :check_heartbeat_acks

def initialize(bot, token, shard_key = nil, compress_mode = :stream)
def initialize(bot, token, shard_key = nil, compress_mode = :stream, intents = ALL_INTENTS)
@token = token
@bot = bot

Expand All @@ -155,6 +155,7 @@ def initialize(bot, token, shard_key = nil, compress_mode = :stream)
@check_heartbeat_acks = true

@compress_mode = compress_mode
@intents = intents
end

# Connect to the gateway server in a separate thread
Expand Down Expand Up @@ -308,7 +309,8 @@ def send_identify(token, properties, compress, large_threshold, shard_key = nil)
token: token,
properties: properties,
compress: compress,
large_threshold: large_threshold
large_threshold: large_threshold,
intents: @intents
}

# Don't include the shard key at all if it is nil as Discord checks for its mere existence
Expand Down Expand Up @@ -714,6 +716,7 @@ def handle_dispatch(packet)

@session = Session.new(data['session_id'])
@session.sequence = 0
@bot.__send__(:notify_ready) if (@intents & INTENTS[:servers]).zero?
when :RESUMED
# The RESUMED event is received after a successful op 6 (resume). It does nothing except tell the bot the
# connection is initiated (like READY would). Starting with v5, it doesn't set a new heartbeat interval anymore
Expand Down

0 comments on commit 639df58

Please sign in to comment.