Class: Discordrb::Bot
- Inherits:
-
Object
- Object
- Discordrb::Bot
- Includes:
- Cache, EventContainer
- Defined in:
- lib/discordrb/bot.rb
Overview
Represents a Discord bot, including servers, users, etc.
Direct Known Subclasses
Instance Attribute Summary collapse
-
#awaits ⇒ Hash<Symbol => Await>
readonly
The list of registered Awaits.
-
#event_threads ⇒ Array<Thread>
readonly
The list of currently running threads used to parse and call events.
-
#gateway ⇒ Gateway
readonly
The gateway connection is an internal detail that is useless to most people.
-
#name ⇒ Object
The bot's name which discordrb sends to Discord when making any request, so Discord can identify bots with the same codebase.
-
#shard_key ⇒ Array(Integer, Integer)
readonly
The current shard key.
-
#should_parse_self ⇒ Object
Whether or not the bot should parse its own messages.
-
#voices ⇒ Hash<Integer => VoiceBot>
readonly
The voice connections this bot currently has, by the server ID to which they are connected.
Instance Method Summary collapse
-
#add_await(key, type, attributes = {}) {|event| ... } ⇒ Await
Add an await the bot should listen to.
-
#bot_application ⇒ Application?
(also: #bot_app)
The bot's OAuth application.
-
#connected? ⇒ true, false
Whether or not the bot is currently connected to Discord.
-
#create_oauth_application(name, redirect_uris) ⇒ Array(String, String)
Creates a new application to do OAuth authorization with.
-
#create_server(name, region = :london) ⇒ Server
Creates a server on Discord with a specified name and a region.
- #debug(message) ⇒ Object
-
#debug=(new_debug) ⇒ Object
Sets debug mode.
-
#delete_invite(code) ⇒ Object
Revokes an invite to a server.
-
#dispatch(type, data) ⇒ Object
Dispatches an event to this bot.
-
#dnd ⇒ Object
Sets the bot's status to DnD (red icon).
- #emoji(id = nil) ⇒ Object (also: #emojis, #all_emoji)
-
#find_emoji(name) ⇒ GlobalEmoji?
Finds an emoji by its name.
-
#game=(name) ⇒ String
Sets the currently playing game to the specified game.
-
#idle ⇒ Object
(also: #away)
Sets status to idle.
-
#ignore_user(user) ⇒ Object
Add a user to the list of ignored users.
-
#ignored?(user) ⇒ true, false
Checks whether a user is being ignored.
-
#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) ⇒ Bot
constructor
Makes a new bot with the given authentication data.
-
#invisible ⇒ Object
Sets the bot's status to invisible (appears offline).
-
#invite_url(server: nil, permission_bits: nil) ⇒ String
Creates an OAuth invite URL that can be used to invite this bot to a particular server.
-
#join(invite) ⇒ Object
Makes the bot join an invite to a server.
- #log_exception(e) ⇒ Object
-
#mode=(new_mode) ⇒ Object
Sets the logging mode.
-
#online ⇒ Object
(also: #on)
Sets status to online.
-
#parse_mention(mention, server = nil) ⇒ User, ...
Gets the user, role or emoji from a mention of the user, role or emoji.
-
#profile ⇒ Profile
(also: #bot_user)
The bot's user profile.
- #prune_empty_groups ⇒ Object
-
#raise_heartbeat_event ⇒ Object
Raises a heartbeat event.
-
#raw_token ⇒ Object
The raw token, without any prefix.
-
#run(async = false) ⇒ Object
Runs the bot, which logs into Discord and connects the WebSocket.
-
#send_file(channel_id, file, caption: nil, tts: false) ⇒ Object
Sends a file to a channel.
-
#send_message(channel_id, content, tts = false, embed = nil) ⇒ Message
Sends a text message to a channel given its ID and the message's content.
-
#send_temporary_message(channel_id, content, timeout, tts = false, embed = nil) ⇒ Object
Sends a text message to a channel given its ID and the message's content, then deletes it after the specified timeout in seconds.
-
#servers ⇒ Hash<Integer => Server>
The list of servers the bot is currently in.
-
#stop(no_sync = false) ⇒ Object
Stops the bot gracefully, disconnecting the websocket without immediately killing the thread.
-
#stream(name, url) ⇒ String
Sets the currently online stream to the specified name and Twitch URL.
-
#suppress_ready_debug ⇒ Object
Prevents the READY packet from being printed regardless of debug mode.
-
#sync ⇒ Object
Blocks execution until the websocket stops, which should only happen manually triggered or due to an error.
-
#token ⇒ String
The Discord API token received when logging in.
-
#unignore_user(user) ⇒ Object
Remove a user from the ignore list.
-
#update_oauth_application(name, redirect_uris, description = '', icon = nil) ⇒ Object
Changes information about your OAuth application.
-
#update_status(status, game, url, since = 0, afk = false) ⇒ Object
Updates presence status.
-
#users ⇒ Hash<Integer => User>
The list of users the bot shares a server with.
-
#voice(thing) ⇒ VoiceBot?
Gets the voice bot for a particular server or channel.
-
#voice_connect(chan, encrypted = true) ⇒ Voice::VoiceBot
Connects to a voice channel, initializes network connections and returns the Voice::VoiceBot over which audio data can then be sent.
-
#voice_destroy(server_id, destroy_vws = true) ⇒ Object
Disconnects the client from a specific voice connection given the server ID.
Methods included from Cache
#channel, #ensure_channel, #ensure_server, #ensure_user, #find_channel, #find_user, #init_cache, #invite, #member, #pm_channel, #request_chunks, #resolve_invite_code, #server, #user
Methods included from EventContainer
#add_handler, #await, #channel_create, #channel_delete, #channel_recipient_add, #channel_recipient_remove, #channel_update, class_from_string, #clear!, #disconnected, event_class, handler_class, #heartbeat, #include_events, #member_join, #member_leave, #member_update, #mention, #message, #message_delete, #message_edit, #playing, #pm, #presence, #raw, #reaction_add, #reaction_remove, #reaction_remove_all, #ready, #remove_handler, #server_create, #server_delete, #server_emoji, #server_emoji_create, #server_emoji_delete, #server_emoji_update, #server_update, #typing, #unknown, #user_ban, #user_unban, #voice_state_update
Methods included from Events
Constructor Details
#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) ⇒ Bot
Makes a new bot with the given authentication data. It will be ready to be added event handlers to and can eventually be run with #run.
As support for logging in using username and password has been removed in version 3.0.0, only a token login is
possible. Be sure to specify the type
parameter as :user
if you're logging in as a user.
Simply creating a bot won't be enough to start sending messages etc. with, only a limited set of methods can be used after logging in. If you want to do something when the bot has connected successfully, either do it in the EventContainer#ready event, or use the #run method with the :async parameter and do the processing after that.
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/discordrb/bot.rb', line 97 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 ) LOGGER.mode = if log_mode.is_a? TrueClass # Specifically check for `true` because people might not have updated yet :debug else log_mode end LOGGER.token = token if redact_token @should_parse_self = parse_self @client_id = client_id @type = type || :bot @name = name @shard_key = num_shards ? [shard_id, num_shards] : nil LOGGER.fancy = fancy_log @prevent_ready = suppress_ready @token = process_token(@type, token) @gateway = Gateway.new(self, @token, @shard_key) init_cache @voices = {} @should_connect_to_voice = {} @ignored_ids = Set.new @ignore_bots = ignore_bots @event_threads = [] @current_thread = 0 @status = :online end |
Instance Attribute Details
#awaits ⇒ Hash<Symbol => Await> (readonly)
Returns the list of registered Awaits.
56 57 58 |
# File 'lib/discordrb/bot.rb', line 56 def awaits @awaits end |
#event_threads ⇒ Array<Thread> (readonly)
The list of currently running threads used to parse and call events.
The threads will have a local variable :discordrb_name
in the format of et-1234
, where
"et" stands for "event thread" and the number is a continually incrementing number representing
how many events were executed before.
43 44 45 |
# File 'lib/discordrb/bot.rb', line 43 def event_threads @event_threads end |
#gateway ⇒ Gateway (readonly)
The gateway connection is an internal detail that is useless to most people. It is however essential while debugging or developing discordrb itself, or while writing very custom bots.
61 62 63 |
# File 'lib/discordrb/bot.rb', line 61 def gateway @gateway end |
#name ⇒ Object
The bot's name which discordrb sends to Discord when making any request, so Discord can identify bots with the same codebase. Not required but I recommend setting it anyway.
50 51 52 |
# File 'lib/discordrb/bot.rb', line 50 def name @name end |
#shard_key ⇒ Array(Integer, Integer) (readonly)
Returns the current shard key.
53 54 55 |
# File 'lib/discordrb/bot.rb', line 53 def shard_key @shard_key end |
#should_parse_self ⇒ Object
Whether or not the bot should parse its own messages. Off by default.
46 47 48 |
# File 'lib/discordrb/bot.rb', line 46 def should_parse_self @should_parse_self end |
#voices ⇒ Hash<Integer => VoiceBot> (readonly)
Returns the voice connections this bot currently has, by the server ID to which they are connected.
277 278 279 |
# File 'lib/discordrb/bot.rb', line 277 def voices @voices end |
Instance Method Details
#add_await(key, type, attributes = {}) {|event| ... } ⇒ Await
Add an await the bot should listen to. For information on awaits, see Await.
546 547 548 549 550 551 |
# File 'lib/discordrb/bot.rb', line 546 def add_await(key, type, attributes = {}, &block) raise "You can't await an AwaitEvent!" if type == Discordrb::Events::AwaitEvent await = Await.new(self, key, type, attributes, block) @awaits ||= {} @awaits[key] = await end |
#bot_application ⇒ Application? Also known as: bot_app
The bot's OAuth application.
201 202 203 204 205 206 |
# File 'lib/discordrb/bot.rb', line 201 def bot_application gateway_check return nil unless @type == :bot response = API.oauth_application(token) Application.new(JSON.parse(response), self) end |
#connected? ⇒ true, false
Returns whether or not the bot is currently connected to Discord.
252 253 254 |
# File 'lib/discordrb/bot.rb', line 252 def connected? @gateway.open? end |
#create_oauth_application(name, redirect_uris) ⇒ Array(String, String)
Creates a new application to do OAuth authorization with. This allows you to use OAuth to authorize users using Discord. For information how to use this, see the docs: https://discordapp.com/developers/docs/topics/oauth2
420 421 422 423 |
# File 'lib/discordrb/bot.rb', line 420 def create_oauth_application(name, redirect_uris) response = JSON.parse(API.create_oauth_application(@token, name, redirect_uris)) [response['id'], response['secret']] end |
#create_server(name, region = :london) ⇒ Server
Discord's API doesn't directly return the server when creating it, so this method waits until the data has been received via the websocket. This may make the execution take a while.
Creates a server on Discord with a specified name and a region.
406 407 408 409 410 411 412 413 |
# File 'lib/discordrb/bot.rb', line 406 def create_server(name, region = :london) response = API::Server.create(token, name, region) id = JSON.parse(response)['id'].to_i sleep 0.1 until @servers[id] server = @servers[id] debug "Successfully created server #{server.id} with name #{server.name}" server end |
#debug(message) ⇒ Object
575 576 577 |
# File 'lib/discordrb/bot.rb', line 575 def debug() LOGGER.debug() end |
#debug=(new_debug) ⇒ Object
Sets debug mode. If debug mode is on, many things will be outputted to STDOUT.
524 525 526 |
# File 'lib/discordrb/bot.rb', line 524 def debug=(new_debug) LOGGER.debug = new_debug end |
#delete_invite(code) ⇒ Object
Revokes an invite to a server. Will fail unless you have the Manage Server permission. It is recommended that you use Invite#delete instead.
341 342 343 344 |
# File 'lib/discordrb/bot.rb', line 341 def delete_invite(code) invite = resolve_invite_code(code) API::Invite.delete(token, invite) end |
#dispatch(type, data) ⇒ Object
Dispatches an event to this bot. Called by the gateway connection handler used internally.
585 586 587 |
# File 'lib/discordrb/bot.rb', line 585 def dispatch(type, data) handle_dispatch(type, data) end |
#dnd ⇒ Object
Sets the bot's status to DnD (red icon).
512 513 514 515 |
# File 'lib/discordrb/bot.rb', line 512 def dnd gateway_check update_status(:dnd, @game, nil) end |
#emoji(id) ⇒ Object #emoji ⇒ Array<GlobalEmoji> Also known as: emojis, all_emoji
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
# File 'lib/discordrb/bot.rb', line 162 def emoji(id = nil) gateway_check if id emoji @emoji.find { |sth| sth.id == id } else emoji = {} @servers.each do |_, server| server.emoji.values.each do |element| emoji[element.name] = GlobalEmoji.new(element, self) end end @emoji = emoji.values end end |
#find_emoji(name) ⇒ GlobalEmoji?
Finds an emoji by its name.
184 185 186 187 |
# File 'lib/discordrb/bot.rb', line 184 def find_emoji(name) LOGGER.out("Resolving emoji #{name}") emoji.find { |element| element.name == name } end |
#game=(name) ⇒ String
Sets the currently playing game to the specified game.
479 480 481 482 483 |
# File 'lib/discordrb/bot.rb', line 479 def game=(name) gateway_check update_status(@status, name, nil) name end |
#idle ⇒ Object Also known as: away
Sets status to idle.
504 505 506 507 |
# File 'lib/discordrb/bot.rb', line 504 def idle gateway_check update_status(:idle, @game, nil) end |
#ignore_user(user) ⇒ Object
Ignoring a user only prevents any message events (including mentions, commands etc.) from them! Typing and presence and any other events will still be received.
Add a user to the list of ignored users. Those users will be ignored in message events at event processing level.
557 558 559 |
# File 'lib/discordrb/bot.rb', line 557 def ignore_user(user) @ignored_ids << user.resolve_id end |
#ignored?(user) ⇒ true, false
Checks whether a user is being ignored.
570 571 572 |
# File 'lib/discordrb/bot.rb', line 570 def ignored?(user) @ignored_ids.include?(user.resolve_id) end |
#invisible ⇒ Object
Sets the bot's status to invisible (appears offline).
518 519 520 521 |
# File 'lib/discordrb/bot.rb', line 518 def invisible gateway_check update_status(:invisible, @game, nil) end |
#invite_url(server: nil, permission_bits: nil) ⇒ String
Creates an OAuth invite URL that can be used to invite this bot to a particular server. Requires the application ID to have been set during initialization.
268 269 270 271 272 273 274 |
# File 'lib/discordrb/bot.rb', line 268 def invite_url(server: nil, permission_bits: nil) raise 'No application ID has been set during initialization! Add one as the `client_id` named parameter while creating your bot.' unless @client_id server_id_str = server ? "&guild_id=#{server.id}" : '' = ? "&permissions=#{}" : '' "https://discordapp.com/oauth2/authorize?&client_id=#{@client_id}#{server_id_str}#{}&scope=bot" end |
#join(invite) ⇒ Object
Makes the bot join an invite to a server.
258 259 260 261 |
# File 'lib/discordrb/bot.rb', line 258 def join(invite) resolved = invite(invite).code API::Invite.accept(token, resolved) end |
#log_exception(e) ⇒ Object
580 581 582 |
# File 'lib/discordrb/bot.rb', line 580 def log_exception(e) LOGGER.log_exception(e) end |
#mode=(new_mode) ⇒ Object
Sets the logging mode
530 531 532 |
# File 'lib/discordrb/bot.rb', line 530 def mode=(new_mode) LOGGER.mode = new_mode end |
#online ⇒ Object Also known as: on
Sets status to online.
496 497 498 499 |
# File 'lib/discordrb/bot.rb', line 496 def online gateway_check update_status(:online, @game, @streamurl) end |
#parse_mention(mention, server = nil) ⇒ User, ...
Gets the user, role or emoji from a mention of the user, role or emoji.
439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 |
# File 'lib/discordrb/bot.rb', line 439 def parse_mention(mention, server = nil) # Mention format: <@id> if /<@!?(?<id>\d+)>?/ =~ mention user(id.to_i) elsif /<@&(?<id>\d+)>?/ =~ mention return server.role(id.to_i) if server @servers.values.each do |element| role = element.role(id.to_i) return role unless role.nil? end # Return nil if no role is found nil elsif /<:(\w+):(?<id>\d+)>?/ =~ mention emoji.find { |element| element.id.to_i == id.to_i } end end |
#profile ⇒ Profile Also known as: bot_user
The bot's user profile. This special user object can be used to edit user data like the current username (see Profile#username=).
192 193 194 195 |
# File 'lib/discordrb/bot.rb', line 192 def profile gateway_check @profile end |
#prune_empty_groups ⇒ Object
594 595 596 597 598 |
# File 'lib/discordrb/bot.rb', line 594 def prune_empty_groups @channels.each_value do |channel| channel.leave_group if channel.group? && channel.recipients.empty? end end |
#raise_heartbeat_event ⇒ Object
Raises a heartbeat event. Called by the gateway connection handler used internally.
590 591 592 |
# File 'lib/discordrb/bot.rb', line 590 def raise_heartbeat_event raise_event(HeartbeatEvent.new(self)) end |
#raw_token ⇒ Object
Returns the raw token, without any prefix.
220 221 222 |
# File 'lib/discordrb/bot.rb', line 220 def raw_token @token.split(' ').last end |
#run(async = false) ⇒ Object
Runs the bot, which logs into Discord and connects the WebSocket. This prevents all further execution unless it is executed with async
= :async
.
230 231 232 233 234 235 236 |
# File 'lib/discordrb/bot.rb', line 230 def run(async = false) @gateway.run_async return if async debug('Oh wait! Not exiting yet as run was run synchronously.') @gateway.sync end |
#send_file(channel_id, file, caption: nil, tts: false) ⇒ Object
This executes in a blocking way, so if you're sending long files, be wary of delays.
Sends a file to a channel. If it is an image, it will automatically be embedded.
385 386 387 388 |
# File 'lib/discordrb/bot.rb', line 385 def send_file(channel_id, file, caption: nil, tts: false) response = API::Channel.upload_file(token, channel_id, file, caption: , tts: tts) Message.new(JSON.parse(response), self) end |
#send_message(channel_id, content, tts = false, embed = nil) ⇒ Message
Sends a text message to a channel given its ID and the message's content.
352 353 354 355 356 357 358 |
# File 'lib/discordrb/bot.rb', line 352 def (channel_id, content, tts = false, = nil) channel_id = channel_id.resolve_id debug("Sending message to #{channel_id} with content '#{content}'") response = API::Channel.(token, channel_id, content, [], tts, ? .to_hash : nil) Message.new(JSON.parse(response), self) end |
#send_temporary_message(channel_id, content, timeout, tts = false, embed = nil) ⇒ Object
Sends a text message to a channel given its ID and the message's content, then deletes it after the specified timeout in seconds.
367 368 369 370 371 372 373 374 375 376 377 |
# File 'lib/discordrb/bot.rb', line 367 def (channel_id, content, timeout, tts = false, = nil) Thread.new do = (channel_id, content, tts, ) sleep(timeout) .delete end nil end |
#servers ⇒ Hash<Integer => Server>
The list of servers the bot is currently in.
150 151 152 153 |
# File 'lib/discordrb/bot.rb', line 150 def servers gateway_check @servers end |
#stop(no_sync = false) ⇒ Object
Stops the bot gracefully, disconnecting the websocket without immediately killing the thread. This means that Discord is immediately aware of the closed connection and makes the bot appear offline instantly.
247 248 249 |
# File 'lib/discordrb/bot.rb', line 247 def stop(no_sync = false) @gateway.stop(no_sync) end |
#stream(name, url) ⇒ String
Sets the currently online stream to the specified name and Twitch URL.
489 490 491 492 493 |
# File 'lib/discordrb/bot.rb', line 489 def stream(name, url) gateway_check update_status(@status, name, url) name end |
#suppress_ready_debug ⇒ Object
Prevents the READY packet from being printed regardless of debug mode.
535 536 537 |
# File 'lib/discordrb/bot.rb', line 535 def suppress_ready_debug @prevent_ready = true end |
#sync ⇒ Object
Blocks execution until the websocket stops, which should only happen manually triggered or due to an error. This is necessary to have a continuously running bot.
240 241 242 |
# File 'lib/discordrb/bot.rb', line 240 def sync @gateway.sync end |
#token ⇒ String
The Discord API token received when logging in. Useful to explicitly call API methods.
213 214 215 216 |
# File 'lib/discordrb/bot.rb', line 213 def token API.bot_name = @name @token end |
#unignore_user(user) ⇒ Object
Remove a user from the ignore list.
563 564 565 |
# File 'lib/discordrb/bot.rb', line 563 def unignore_user(user) @ignored_ids.delete(user.resolve_id) end |
#update_oauth_application(name, redirect_uris, description = '', icon = nil) ⇒ Object
Changes information about your OAuth application
431 432 433 |
# File 'lib/discordrb/bot.rb', line 431 def update_oauth_application(name, redirect_uris, description = '', icon = nil) API.update_oauth_application(@token, name, redirect_uris, description, icon) end |
#update_status(status, game, url, since = 0, afk = false) ⇒ Object
Updates presence status.
464 465 466 467 468 469 470 471 472 473 474 |
# File 'lib/discordrb/bot.rb', line 464 def update_status(status, game, url, since = 0, afk = false) gateway_check @game = game @status = status @streamurl = url type = url ? 1 : 0 game_obj = game || url ? { name: game, url: url, type: type } : nil @gateway.send_status_update(status, since, game_obj, afk) end |
#users ⇒ Hash<Integer => User>
The list of users the bot shares a server with.
143 144 145 146 |
# File 'lib/discordrb/bot.rb', line 143 def users gateway_check @users end |
#voice(thing) ⇒ VoiceBot?
Gets the voice bot for a particular server or channel. You can connect to a new channel using the #voice_connect method.
283 284 285 286 287 288 289 290 291 292 293 294 |
# File 'lib/discordrb/bot.rb', line 283 def voice(thing) id = thing.resolve_id return @voices[id] if @voices[id] channel = channel(id) return nil unless channel server_id = channel.server.id return @voices[server_id] if @voices[server_id] nil end |
#voice_connect(chan, encrypted = true) ⇒ Voice::VoiceBot
Connects to a voice channel, initializes network connections and returns the Voice::VoiceBot over which audio data can then be sent. After connecting, the bot can also be accessed using #voice. If the bot is already connected to voice, the existing connection will be terminated - you don't have to call Voice::VoiceBot#destroy before calling this method.
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 |
# File 'lib/discordrb/bot.rb', line 304 def voice_connect(chan, encrypted = true) chan = channel(chan.resolve_id) server_id = chan.server.id @should_encrypt_voice = encrypted if @voices[chan.id] debug('Voice bot exists already! Destroying it') @voices[chan.id].destroy @voices.delete(chan.id) end debug("Got voice channel: #{chan}") @should_connect_to_voice[server_id] = chan @gateway.send_voice_state_update(server_id.to_s, chan.id.to_s, false, false) debug('Voice channel init packet sent! Now waiting.') sleep(0.05) until @voices[server_id] debug('Voice connect succeeded!') @voices[server_id] end |
#voice_destroy(server_id, destroy_vws = true) ⇒ Object
Disconnects the client from a specific voice connection given the server ID. Usually it's more convenient to use Voice::VoiceBot#destroy rather than this.
332 333 334 335 336 |
# File 'lib/discordrb/bot.rb', line 332 def voice_destroy(server_id, destroy_vws = true) @gateway.send_voice_state_update(server_id.to_s, nil, false, false) @voices[server_id].destroy if @voices[server_id] && destroy_vws @voices.delete(server_id) end |