Class: DiscordRDA::Bot

Inherits:
Object
  • Object
show all
Defined in:
lib/discord_rda/bot.rb

Overview

Main Bot class for DiscordRDA. Entry point for building Discord bots.

Examples:

Basic bot

bot = DiscordRDA::Bot.new(token: ENV['DISCORD_TOKEN'])
bot.on(:message_create) { |e| puts e.content }
bot.run

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(token:, **options) ⇒ Bot

Initialize a new bot

Parameters:

  • token (String)

    Bot token

  • options (Hash)

    Configuration options



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/discord_rda/bot.rb', line 70

def initialize(token:, **options)
  @config = Configuration.new(options.merge(token: token))
  @logger = Logger.new(
    level: @config.log_level,
    format: @config.log_format,
    file_path: @config.log_file_path,
    rotate_age: @config.log_rotate_age,
    rotate_size: @config.log_rotate_size
  )
  @restart_manager = RestartManager.new(logger: @logger)
  @restart_state = @restart_manager.consume_boot_state
  @tracer = Tracer.new(enabled: @config.trace_enabled, logger: @logger)
  @error_tracker = ErrorTracker.new(enabled: @config.error_tracking, logger: @logger)
  @supervisor = ExecutionSupervisor.new(logger: @logger)
  @event_bus = EventBus.new(logger: @logger)
  @cache = build_cache
  @shard_manager = ShardManager.new(@config, @event_bus, @logger, gateway_state: restart_gateway_state)
  @rest = RestClient.new(@config, @logger)

  # Configure entity API clients
  configure_entity_apis(@rest)

  setup_event_handlers
  setup_interaction_handlers

  # Initialize scalable components
  @scalable_rest = nil
  @reshard_manager = ReshardManager.new(self, @shard_manager, @logger)
  @hot_reload_manager = HotReloadManager.new(self, @logger)
  @plugins = PluginRegistry.new(logger: @logger)
  @restart_manager.attach(self)
  @slash_commands = {}
  @running = false
  @commands = {}
  @active_record = nil

  setup_event_handlers
end

Instance Attribute Details

#active_recordActiveRecordSystem? (readonly)

Returns ActiveRecord integration helper.

Returns:



59
60
61
# File 'lib/discord_rda/bot.rb', line 59

def active_record
  @active_record
end

#cacheEntityCache (readonly)

Returns Entity cache.

Returns:



23
24
25
# File 'lib/discord_rda/bot.rb', line 23

def cache
  @cache
end

#configConfiguration (readonly)

Returns Bot configuration.

Returns:



14
15
16
# File 'lib/discord_rda/bot.rb', line 14

def config
  @config
end

#error_trackerErrorTracker (readonly)

Returns Error tracking helper.

Returns:



47
48
49
# File 'lib/discord_rda/bot.rb', line 47

def error_tracker
  @error_tracker
end

#event_busEventBus (readonly)

Returns Event bus.

Returns:



20
21
22
# File 'lib/discord_rda/bot.rb', line 20

def event_bus
  @event_bus
end

#hot_reload_managerHotReloadManager (readonly)

Returns Hot reload manager.

Returns:



38
39
40
# File 'lib/discord_rda/bot.rb', line 38

def hot_reload_manager
  @hot_reload_manager
end

#loggerLogger (readonly)

Returns Logger instance.

Returns:

  • (Logger)

    Logger instance



17
18
19
# File 'lib/discord_rda/bot.rb', line 17

def logger
  @logger
end

#pluginsPluginRegistry (readonly)

Returns Plugin registry.

Returns:



41
42
43
# File 'lib/discord_rda/bot.rb', line 41

def plugins
  @plugins
end

#reshard_managerReshardManager (readonly)

Returns Reshard manager.

Returns:



35
36
37
# File 'lib/discord_rda/bot.rb', line 35

def reshard_manager
  @reshard_manager
end

#restRestClient (readonly)

Returns REST client.

Returns:



29
30
31
# File 'lib/discord_rda/bot.rb', line 29

def rest
  @rest
end

#restart_managerRestartManager (readonly)

Returns Instant restart helper.

Returns:



50
51
52
# File 'lib/discord_rda/bot.rb', line 50

def restart_manager
  @restart_manager
end

#restart_stateHash (readonly)

Returns Boot-time restart state.

Returns:

  • (Hash)

    Boot-time restart state



56
57
58
# File 'lib/discord_rda/bot.rb', line 56

def restart_state
  @restart_state
end

#runningBoolean (readonly)

Returns Whether bot is running.

Returns:

  • (Boolean)

    Whether bot is running



62
63
64
# File 'lib/discord_rda/bot.rb', line 62

def running
  @running
end

#scalable_restScalableRestClient (readonly)

Returns Scalable REST client (if enabled).

Returns:



32
33
34
# File 'lib/discord_rda/bot.rb', line 32

def scalable_rest
  @scalable_rest
end

#shard_managerShardManager (readonly)

Returns Shard manager.

Returns:



26
27
28
# File 'lib/discord_rda/bot.rb', line 26

def shard_manager
  @shard_manager
end

#slash_commandsHash (readonly)

Returns Registered slash commands.

Returns:

  • (Hash)

    Registered slash commands



65
66
67
# File 'lib/discord_rda/bot.rb', line 65

def slash_commands
  @slash_commands
end

#supervisorExecutionSupervisor (readonly)

Returns Fault-tolerant execution supervisor.

Returns:



53
54
55
# File 'lib/discord_rda/bot.rb', line 53

def supervisor
  @supervisor
end

#tracerTracer (readonly)

Returns Trace helper.

Returns:



44
45
46
# File 'lib/discord_rda/bot.rb', line 44

def tracer
  @tracer
end

Instance Method Details

#add_group_dm_recipient(channel_id, user_id, access_token:, nick: nil) ⇒ void

This method returns an undefined value.

Add a recipient to a group DM

Parameters:

  • channel_id (String, Snowflake)

    Group DM channel ID

  • user_id (String, Snowflake)

    User ID

  • access_token (String)

    OAuth2 access token with gdm.join scope

  • nick (String, nil) (defaults to: nil)

    Nickname for the recipient in the group DM



417
418
419
420
# File 'lib/discord_rda/bot.rb', line 417

def add_group_dm_recipient(channel_id, user_id, access_token:, nick: nil)
  payload = { access_token: access_token, nick: nick }.compact
  @rest.put("/channels/#{channel_id}/recipients/#{user_id}", body: payload)
end

#add_guild_member(guild_id, user_id, access_token:, **options) ⇒ Hash

Add a member to a guild through OAuth2

Parameters:

  • guild_id (String, Snowflake)

    Guild ID

  • user_id (String, Snowflake)

    User ID

  • access_token (String)

    User OAuth2 access token

  • options (Hash)

    Optional member settings

Returns:

  • (Hash)

    Discord add-member response



780
781
782
783
784
785
786
787
788
789
# File 'lib/discord_rda/bot.rb', line 780

def add_guild_member(guild_id, user_id, access_token:, **options)
  payload = {
    access_token: access_token,
    nick: options[:nick],
    roles: options[:roles],
    mute: options[:mute],
    deaf: options[:deaf]
  }.compact
  @rest.put("/guilds/#{guild_id}/members/#{user_id}", body: payload)
end

#add_guild_member_role(guild_id, user_id, role_id, reason: nil) ⇒ void

This method returns an undefined value.

Add role to guild member

Parameters:

  • guild_id (String, Snowflake)

    Guild ID

  • user_id (String, Snowflake)

    User ID

  • role_id (String, Snowflake)

    Role ID

  • reason (String) (defaults to: nil)

    Audit log reason



816
817
818
819
# File 'lib/discord_rda/bot.rb', line 816

def add_guild_member_role(guild_id, user_id, role_id, reason: nil)
  headers = reason ? { 'X-Audit-Log-Reason' => CGI.escape(reason) } : {}
  @rest.put("/guilds/#{guild_id}/members/#{user_id}/roles/#{role_id}", headers: headers)
end

#add_reaction(channel_id, message_id, emoji) ⇒ void

This method returns an undefined value.

Add a reaction to a message

Parameters:

  • channel_id (String, Snowflake)

    Channel ID

  • message_id (String, Snowflake)

    Message ID

  • emoji (String, Emoji)

    Emoji (unicode or name:id format)



688
689
690
691
# File 'lib/discord_rda/bot.rb', line 688

def add_reaction(channel_id, message_id, emoji)
  emoji_str = emoji.respond_to?(:id) ? "#{emoji.name}:#{emoji.id}" : emoji.to_s
  @rest.put("/channels/#{channel_id}/messages/#{message_id}/reactions/#{CGI.escape(emoji_str)}/@me")
end

#add_thread_member(thread_id, user_id) ⇒ void

This method returns an undefined value.

Add a user to a thread

Parameters:

  • thread_id (String, Snowflake)

    Thread channel ID

  • user_id (String, Snowflake)

    User ID



567
568
569
# File 'lib/discord_rda/bot.rb', line 567

def add_thread_member(thread_id, user_id)
  @rest.put("/channels/#{thread_id}/thread-members/#{user_id}")
end

#analyticsHash

Get analytics data (if analytics plugin registered)

Returns:

  • (Hash)

    Analytics data



676
677
678
679
# File 'lib/discord_rda/bot.rb', line 676

def analytics
  analytics_plugin = @plugins.get(:Analytics)
  analytics_plugin&.summary || {}
end

#application_infoHash

Get current bot application metadata

Returns:

  • (Hash)

    Application payload



1764
1765
1766
# File 'lib/discord_rda/bot.rb', line 1764

def application_info
  @rest.get('/oauth2/applications/@me')
end

#application_role_connection(application_id) ⇒ Hash?

Get application role connection metadata for the current user

Parameters:

  • application_id (String, Snowflake)

    Application ID

Returns:

  • (Hash, nil)

    Role connection payload



1743
1744
1745
# File 'lib/discord_rda/bot.rb', line 1743

def application_role_connection(application_id)
  User.get_application_role_connection(application_id)
end

#archived_threads(channel_id, scope: :public, before: nil, limit: nil) ⇒ Hash

List archived threads for a channel

Parameters:

  • channel_id (String, Snowflake)

    Parent channel ID

  • scope (Symbol) (defaults to: :public)

    :public, :private, or :joined_private

  • before (Time, String, nil) (defaults to: nil)

    ISO8601 timestamp cursor

  • limit (Integer, nil) (defaults to: nil)

    Max threads to return

Returns:

  • (Hash)

    Archived thread response



616
617
618
619
620
621
622
623
624
625
626
627
628
629
# File 'lib/discord_rda/bot.rb', line 616

def archived_threads(channel_id, scope: :public, before: nil, limit: nil)
  path = case scope
         when :public then "/channels/#{channel_id}/threads/archived/public"
         when :private then "/channels/#{channel_id}/threads/archived/private"
         when :joined_private then "/channels/#{channel_id}/users/@me/threads/archived/private"
         else
           raise ArgumentError, "Unknown archived thread scope: #{scope}"
         end

  params = {}
  params[:before] = before.is_a?(Time) ? before.iso8601 : before if before
  params[:limit] = limit if limit
  @rest.get(path, params: params)
end

#authorization_infoHash

Get current authorization information

Returns:

  • (Hash)

    Authorization payload



1770
1771
1772
# File 'lib/discord_rda/bot.rb', line 1770

def authorization_info
  @rest.get('/oauth2/@me')
end

#auto_moderation_rule(guild_id, rule_id) ⇒ AutoModerationRule?

Get a specific auto moderation rule

Parameters:

Returns:



1505
1506
1507
1508
1509
1510
# File 'lib/discord_rda/bot.rb', line 1505

def auto_moderation_rule(guild_id, rule_id)
  data = @rest.get("/guilds/#{guild_id}/auto-moderation/rules/#{rule_id}")
  AutoModerationRule.new(data)
rescue RestClient::NotFoundError
  nil
end

#auto_moderation_rules(guild_id) ⇒ Array<AutoModerationRule>

List auto moderation rules for a guild

Parameters:

Returns:



1496
1497
1498
1499
# File 'lib/discord_rda/bot.rb', line 1496

def auto_moderation_rules(guild_id)
  data = @rest.get("/guilds/#{guild_id}/auto-moderation/rules")
  data.map { |rule| AutoModerationRule.new(rule) }
end

#begin_guild_prune(guild_id, days:, compute_prune_count: true, include_roles: nil, reason: nil) ⇒ Integer?

Begin a guild prune

Parameters:

  • guild_id (String, Snowflake)

    Guild ID

  • days (Integer)

    Inactive days threshold

  • compute_prune_count (Boolean) (defaults to: true)

    Whether to include the prune count

  • include_roles (Array<String, Snowflake>) (defaults to: nil)

    Optional role IDs

  • reason (String, nil) (defaults to: nil)

    Audit log reason

Returns:

  • (Integer, nil)

    Number of pruned members when requested



1139
1140
1141
1142
1143
1144
# File 'lib/discord_rda/bot.rb', line 1139

def begin_guild_prune(guild_id, days:, compute_prune_count: true, include_roles: nil, reason: nil)
  payload = { days: days, compute_prune_count: compute_prune_count }
  payload[:include_roles] = Array(include_roles).map(&:to_s) if include_roles
  response = @rest.post("/guilds/#{guild_id}/prune", body: payload, headers: audit_log_headers(reason))
  response && response['pruned']
end

#bulk_delete_messages(channel_id, message_ids, reason: nil) ⇒ void

This method returns an undefined value.

Bulk delete messages

Parameters:

  • channel_id (String, Snowflake)

    Channel ID

  • message_ids (Array<String, Snowflake>)

    Message IDs to delete (2-100)

  • reason (String) (defaults to: nil)

    Audit log reason



1689
1690
1691
1692
# File 'lib/discord_rda/bot.rb', line 1689

def bulk_delete_messages(channel_id, message_ids, reason: nil)
  headers = reason ? { 'X-Audit-Log-Reason' => CGI.escape(reason) } : {}
  @rest.post("/channels/#{channel_id}/messages/bulk-delete", body: { messages: message_ids.map(&:to_s) }, headers: headers)
end

#bulk_register_commands(commands) ⇒ Array<ApplicationCommand>

Bulk register global commands (replaces existing)

Parameters:

Returns:



160
161
162
163
164
165
166
167
168
# File 'lib/discord_rda/bot.rb', line 160

def bulk_register_commands(commands)
  return [] unless me

  app_id = me.id.to_s
  payload = commands.map(&:to_h)

  data = @rest.put("/applications/#{app_id}/commands", body: payload)
  data.map { |cmd| ApplicationCommand.new(cmd) }
end

#channel(channel_id) ⇒ Channel?

Get a channel by ID

Parameters:

  • channel_id (String, Snowflake)

    Channel ID

Returns:

  • (Channel, nil)

    Channel or nil



351
352
353
354
355
356
357
358
359
360
361
# File 'lib/discord_rda/bot.rb', line 351

def channel(channel_id)
  cached = @cache.channel(channel_id)
  return cached if cached

  data = @rest.get("/channels/#{channel_id}")
  channel = Channel.new(data)
  @cache.cache_channel(channel)
  channel
rescue RestClient::NotFoundError
  nil
end

#channel_invites(channel_id) ⇒ Array<Hash>

Get invites for a channel

Parameters:

  • channel_id (String, Snowflake)

    Channel ID

Returns:

  • (Array<Hash>)

    Invite payloads



492
493
494
# File 'lib/discord_rda/bot.rb', line 492

def channel_invites(channel_id)
  @rest.get("/channels/#{channel_id}/invites")
end

#channel_message(channel_id, message_id) ⇒ Message?

Get a single message from a channel

Parameters:

  • channel_id (String, Snowflake)

    Channel ID

  • message_id (String, Snowflake)

    Message ID

Returns:

  • (Message, nil)

    Message or nil



404
405
406
407
408
409
# File 'lib/discord_rda/bot.rb', line 404

def channel_message(channel_id, message_id)
  data = @rest.get("/channels/#{channel_id}/messages/#{message_id}")
  Message.new(data)
rescue RestClient::NotFoundError
  nil
end

#channel_messages(channel_id, limit: 50, before: nil, after: nil, around: nil) ⇒ Array<Message>

Get messages from a channel with pagination

Parameters:

  • channel_id (String, Snowflake)

    Channel ID

  • limit (Integer) (defaults to: 50)

    Max messages to fetch (1-100, default 50)

  • before (String, Snowflake) (defaults to: nil)

    Get messages before this ID

  • after (String, Snowflake) (defaults to: nil)

    Get messages after this ID

  • around (String, Snowflake) (defaults to: nil)

    Get messages around this ID

Returns:



390
391
392
393
394
395
396
397
398
# File 'lib/discord_rda/bot.rb', line 390

def channel_messages(channel_id, limit: 50, before: nil, after: nil, around: nil)
  params = { limit: limit }
  params[:before] = before.to_s if before
  params[:after] = after.to_s if after
  params[:around] = around.to_s if around

  data = @rest.get("/channels/#{channel_id}/messages", params: params)
  data.map { |msg| Message.new(msg) }
end

#channel_webhooks(channel_id) ⇒ Array<Webhook>

Get channel webhooks

Parameters:

  • channel_id (String, Snowflake)

    Channel ID

Returns:



963
964
965
# File 'lib/discord_rda/bot.rb', line 963

def channel_webhooks(channel_id)
  @rest.get("/channels/#{channel_id}/webhooks").map { |hook| Webhook.new(hook) }
end

#consume_entitlement(entitlement_id, application_id: nil) ⇒ void

This method returns an undefined value.

Consume an entitlement

Parameters:

  • entitlement_id (String, Snowflake)

    Entitlement ID

  • application_id (String, Snowflake, nil) (defaults to: nil)

    Application ID



1586
1587
1588
1589
# File 'lib/discord_rda/bot.rb', line 1586

def consume_entitlement(entitlement_id, application_id: nil)
  app_id = application_id || application_id_for_rest
  @rest.post("/applications/#{app_id}/entitlements/#{entitlement_id}/consume")
end

#context_menu(type:, name:, **options) {|Interaction| ... } ⇒ ApplicationCommand

Register a context menu command (user or message)

Parameters:

  • type (Symbol)

    :user or :message

  • name (String)

    Command name

  • options (Hash)

    Command options

Yields:

Returns:



146
147
148
149
150
151
152
153
154
155
# File 'lib/discord_rda/bot.rb', line 146

def context_menu(type:, name:, **options, &block)
  cmd_type = type == :user ? 2 : 3
  builder = CommandBuilder.new(name, '', type: cmd_type)
  builder.dm_allowed(options[:dm_permission]) if options.key?(:dm_permission)
  builder.default_permissions(options[:default_member_permissions]) if options[:default_member_permissions]
  builder.nsfw(options[:nsfw]) if options[:nsfw]
  builder.handler(&block) if block

  register_application_command(builder.build, name: name, guild_id: options[:guild_id])
end

#create_auto_moderation_rule(guild_id, reason: nil, **options) ⇒ AutoModerationRule

Create an auto moderation rule

Parameters:

  • guild_id (String, Snowflake)

    Guild ID

  • reason (String, nil) (defaults to: nil)

    Audit log reason

  • options (Hash)

    Rule payload

Returns:



1517
1518
1519
1520
# File 'lib/discord_rda/bot.rb', line 1517

def create_auto_moderation_rule(guild_id, reason: nil, **options)
  data = @rest.post("/guilds/#{guild_id}/auto-moderation/rules", body: options.compact, headers: audit_log_headers(reason))
  AutoModerationRule.new(data)
end

#create_channel_invite(channel_id, reason: nil, **options) {|InviteBuilder| ... } ⇒ Hash

Create a channel invite

Parameters:

  • channel_id (String, Snowflake)

    Channel ID

  • reason (String, nil) (defaults to: nil)

    Audit log reason

Yields:

Returns:

  • (Hash)

    Invite payload



501
502
503
504
505
506
507
508
509
# File 'lib/discord_rda/bot.rb', line 501

def create_channel_invite(channel_id, reason: nil, **options, &block)
  builder = InviteBuilder.new
  options.each do |key, value|
    builder.public_send(key, value) if builder.respond_to?(key)
  end
  block.call(builder) if block

  @rest.post("/channels/#{channel_id}/invites", body: builder.to_h, headers: audit_log_headers(reason))
end

#create_dm(user_id) ⇒ Channel

Create a DM channel with a user

Parameters:

  • user_id (String, Snowflake)

    Target user ID

Returns:



1729
1730
1731
1732
# File 'lib/discord_rda/bot.rb', line 1729

def create_dm(user_id)
  data = @rest.post('/users/@me/channels', body: { recipient_id: user_id.to_s })
  Channel.new(data)
end

#create_guild(name:, **options) ⇒ Guild

Create a guild

Parameters:

  • name (String)

    Guild name

  • options (Hash)

    Optional guild creation payload

Returns:

  • (Guild)

    Created guild



325
326
327
328
329
# File 'lib/discord_rda/bot.rb', line 325

def create_guild(name:, **options)
  payload = { name: name }.merge(options).compact
  data = @rest.post('/guilds', body: payload)
  Guild.new(data)
end

#create_guild_ban(guild_id, user_id, delete_message_days: nil, reason: nil) ⇒ void

This method returns an undefined value.

Create guild ban

Parameters:

  • guild_id (String, Snowflake)

    Guild ID

  • user_id (String, Snowflake)

    User ID

  • delete_message_days (Integer) (defaults to: nil)

    Days of messages to delete (0-7)

  • reason (String) (defaults to: nil)

    Audit log reason



930
931
932
933
934
935
# File 'lib/discord_rda/bot.rb', line 930

def create_guild_ban(guild_id, user_id, delete_message_days: nil, reason: nil)
  payload = {}
  payload[:delete_message_days] = delete_message_days if delete_message_days
  headers = reason ? { 'X-Audit-Log-Reason' => CGI.escape(reason) } : {}
  @rest.put("/guilds/#{guild_id}/bans/#{user_id}", body: payload, headers: headers)
end

#create_guild_channel(guild_id, name:, type: 0, **options) ⇒ Channel

Create guild channel

Parameters:

  • guild_id (String, Snowflake)

    Guild ID

  • name (String)

    Channel name

  • type (Integer) (defaults to: 0)

    Channel type (0=text, 2=voice, 4=category, etc.)

  • options (Hash)

    Optional settings

Returns:



1658
1659
1660
1661
1662
# File 'lib/discord_rda/bot.rb', line 1658

def create_guild_channel(guild_id, name:, type: 0, **options)
  payload = { name: name, type: type }.merge(options.slice(:topic, :bitrate, :user_limit, :parent_id, :nsfw, :permission_overwrites, :rate_limit_per_user))
  data = @rest.post("/guilds/#{guild_id}/channels", body: payload)
  Channel.new(data)
end

#create_guild_from_template(code, name:, icon: nil) ⇒ Guild

Create a guild from a template

Parameters:

  • code (String)

    Template code

  • name (String)

    Guild name

  • icon (String, nil) (defaults to: nil)

    Base64 icon data

Returns:

  • (Guild)

    Created guild



1488
1489
1490
1491
# File 'lib/discord_rda/bot.rb', line 1488

def create_guild_from_template(code, name:, icon: nil)
  data = @rest.post("/guilds/templates/#{code}", body: { name: name, icon: icon }.compact)
  Guild.new(data)
end

#create_guild_role(guild_id, name:, reason: nil, **options) ⇒ Role

Create guild role

Parameters:

  • guild_id (String, Snowflake)

    Guild ID

  • name (String)

    Role name

  • options (Hash)

    Optional settings (permissions, color, hoist, mentionable)

Returns:

  • (Role)

    Created role



857
858
859
860
861
# File 'lib/discord_rda/bot.rb', line 857

def create_guild_role(guild_id, name:, reason: nil, **options)
  payload = { name: name }.merge(options.slice(:permissions, :color, :hoist, :mentionable, :icon, :unicode_emoji))
  data = @rest.post("/guilds/#{guild_id}/roles", body: payload, headers: audit_log_headers(reason))
  Role.new(data.merge('guild_id' => guild_id.to_s))
end

#create_guild_scheduled_event(guild_id, reason: nil, **options) ⇒ GuildScheduledEvent

Create a scheduled event

Parameters:

  • guild_id (String, Snowflake)

    Guild ID

  • reason (String, nil) (defaults to: nil)

    Audit log reason

  • options (Hash)

    Scheduled event payload

Returns:



1310
1311
1312
1313
# File 'lib/discord_rda/bot.rb', line 1310

def create_guild_scheduled_event(guild_id, reason: nil, **options)
  data = @rest.post("/guilds/#{guild_id}/scheduled-events", body: options.compact, headers: audit_log_headers(reason))
  GuildScheduledEvent.new(data)
end

#create_guild_soundboard_sound(guild_id, reason: nil, **options) ⇒ Hash

Create a guild soundboard sound

Parameters:

  • guild_id (String, Snowflake)

    Guild ID

  • reason (String, nil) (defaults to: nil)

    Audit log reason

  • options (Hash)

    Soundboard payload

Returns:

  • (Hash)

    Soundboard sound payload



1619
1620
1621
# File 'lib/discord_rda/bot.rb', line 1619

def create_guild_soundboard_sound(guild_id, reason: nil, **options)
  @rest.post("/guilds/#{guild_id}/soundboard-sounds", body: options.compact, headers: audit_log_headers(reason))
end

#create_guild_template(guild_id, name:, description: nil) ⇒ Hash

Create a guild template

Parameters:

  • guild_id (String, Snowflake)

    Guild ID

  • name (String)

    Template name

  • description (String, nil) (defaults to: nil)

    Template description

Returns:

  • (Hash)

    Template payload



1443
1444
1445
# File 'lib/discord_rda/bot.rb', line 1443

def create_guild_template(guild_id, name:, description: nil)
  @rest.post("/guilds/#{guild_id}/templates", body: { name: name, description: description }.compact)
end

#create_stage_instance(channel_id:, topic:, privacy_level: nil, send_start_notification: nil, guild_scheduled_event_id: nil) ⇒ Hash

Create a stage instance

Parameters:

  • channel_id (String, Snowflake)

    Stage channel ID

  • topic (String)

    Stage topic

  • privacy_level (Integer, nil) (defaults to: nil)

    Privacy level

  • send_start_notification (Boolean, nil) (defaults to: nil)

    Send notification

  • guild_scheduled_event_id (String, Snowflake, nil) (defaults to: nil)

    Associated scheduled event

Returns:

  • (Hash)

    Stage instance payload



1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
# File 'lib/discord_rda/bot.rb', line 1359

def create_stage_instance(channel_id:, topic:, privacy_level: nil, send_start_notification: nil, guild_scheduled_event_id: nil)
  payload = {
    channel_id: channel_id.to_s,
    topic: topic,
    privacy_level: privacy_level,
    send_start_notification: send_start_notification,
    guild_scheduled_event_id: guild_scheduled_event_id&.to_s
  }.compact
  @rest.post('/stage-instances', body: payload)
end

#create_test_entitlement(sku_id:, owner_id:, owner_type:, application_id: nil) ⇒ Hash

Create a test entitlement

Parameters:

  • sku_id (String, Snowflake)

    SKU ID

  • owner_id (String, Snowflake)

    User or guild owner ID

  • owner_type (Integer)

    1 for guild, 2 for user

  • application_id (String, Snowflake, nil) (defaults to: nil)

    Application ID

Returns:

  • (Hash)

    Entitlement payload



1567
1568
1569
1570
1571
# File 'lib/discord_rda/bot.rb', line 1567

def create_test_entitlement(sku_id:, owner_id:, owner_type:, application_id: nil)
  app_id = application_id || application_id_for_rest
  payload = { sku_id: sku_id.to_s, owner_id: owner_id.to_s, owner_type: owner_type }
  @rest.post("/applications/#{app_id}/entitlements", body: payload)
end

#create_webhook(channel_id, name:, avatar: nil, reason: nil) ⇒ Webhook

Create a webhook

Parameters:

  • channel_id (String, Snowflake)

    Channel ID

  • name (String)

    Webhook name

  • avatar (String) (defaults to: nil)

    Base64-encoded avatar image (optional)

Returns:



954
955
956
957
958
# File 'lib/discord_rda/bot.rb', line 954

def create_webhook(channel_id, name:, avatar: nil, reason: nil)
  payload = { name: name }
  payload[:avatar] = avatar if avatar
  Webhook.new(@rest.post("/channels/#{channel_id}/webhooks", body: payload, headers: audit_log_headers(reason)))
end

#crosspost_message(channel_id, message_id) ⇒ Message

Crosspost a message in an announcement channel

Parameters:

  • channel_id (String, Snowflake)

    Channel ID

  • message_id (String, Snowflake)

    Message ID

Returns:

  • (Message)

    Crossposted message



378
379
380
381
# File 'lib/discord_rda/bot.rb', line 378

def crosspost_message(channel_id, message_id)
  data = @rest.post("/channels/#{channel_id}/messages/#{message_id}/crosspost")
  Message.new(data)
end

#current_user_connectionsArray<Hash>

Get OAuth2 connections for the current user

Returns:

  • (Array<Hash>)

    User connections



1736
1737
1738
# File 'lib/discord_rda/bot.rb', line 1736

def current_user_connections
  User.get_connections
end

#current_user_guild_member(guild_id) ⇒ Hash?

Get the current user’s member object in a guild

Parameters:

Returns:

  • (Hash, nil)

    Member payload



1715
1716
1717
# File 'lib/discord_rda/bot.rb', line 1715

def current_user_guild_member(guild_id)
  User.get_current_user_guild_member(guild_id)
end

#current_user_guilds(limit: 200, after: nil, before: nil, with_counts: false) ⇒ Array<Hash>

Get the current user’s guilds

Parameters:

  • limit (Integer) (defaults to: 200)

    Max guilds to return

  • after (String, Snowflake, nil) (defaults to: nil)

    Cursor

  • before (String, Snowflake, nil) (defaults to: nil)

    Cursor

  • with_counts (Boolean) (defaults to: false)

    Include approximate counts

Returns:

  • (Array<Hash>)

    Partial guild payloads



1708
1709
1710
# File 'lib/discord_rda/bot.rb', line 1708

def current_user_guilds(limit: 200, after: nil, before: nil, with_counts: false)
  User.get_current_user_guilds(limit: limit, after: after&.to_s, before: before&.to_s, with_counts: with_counts)
end

#default_soundboard_soundsHash

Get default soundboard sounds

Returns:

  • (Hash)

    Soundboard payload



1593
1594
1595
# File 'lib/discord_rda/bot.rb', line 1593

def default_soundboard_sounds
  @rest.get('/soundboard-default-sounds')
end

#delete_auto_moderation_rule(guild_id, rule_id, reason: nil) ⇒ void

This method returns an undefined value.

Delete an auto moderation rule

Parameters:

  • guild_id (String, Snowflake)

    Guild ID

  • rule_id (String, Snowflake)

    Rule ID

  • reason (String, nil) (defaults to: nil)

    Audit log reason



1538
1539
1540
# File 'lib/discord_rda/bot.rb', line 1538

def delete_auto_moderation_rule(guild_id, rule_id, reason: nil)
  @rest.delete("/guilds/#{guild_id}/auto-moderation/rules/#{rule_id}", headers: audit_log_headers(reason))
end

#delete_channel(channel_id, reason: nil) ⇒ Channel

Delete channel

Parameters:

  • channel_id (String, Snowflake)

    Channel ID

  • reason (String) (defaults to: nil)

    Audit log reason

Returns:



1678
1679
1680
1681
1682
# File 'lib/discord_rda/bot.rb', line 1678

def delete_channel(channel_id, reason: nil)
  headers = reason ? { 'X-Audit-Log-Reason' => CGI.escape(reason) } : {}
  data = @rest.delete("/channels/#{channel_id}", headers: headers)
  Channel.new(data)
end

#delete_channel_permission(channel_id, overwrite_id, reason: nil) ⇒ void

This method returns an undefined value.

Delete a channel permission overwrite

Parameters:

  • channel_id (String, Snowflake)

    Channel ID

  • overwrite_id (String, Snowflake)

    Role or member overwrite ID

  • reason (String, nil) (defaults to: nil)

    Audit log reason



485
486
487
# File 'lib/discord_rda/bot.rb', line 485

def delete_channel_permission(channel_id, overwrite_id, reason: nil)
  @rest.delete("/channels/#{channel_id}/permissions/#{overwrite_id}", headers: audit_log_headers(reason))
end

#delete_global_command(command_id) ⇒ void

This method returns an undefined value.

Delete a global command

Parameters:

  • command_id (String)

    Command ID



173
174
175
# File 'lib/discord_rda/bot.rb', line 173

def delete_global_command(command_id)
  @rest.delete("/applications/#{me.id}/commands/#{command_id}") if me
end

#delete_guild(guild_id) ⇒ void

This method returns an undefined value.

Delete a guild

Parameters:



344
345
346
# File 'lib/discord_rda/bot.rb', line 344

def delete_guild(guild_id)
  @rest.delete("/guilds/#{guild_id}")
end

#delete_guild_command(guild_id, command_id) ⇒ void

This method returns an undefined value.

Delete a guild command

Parameters:

  • guild_id (String)

    Guild ID

  • command_id (String)

    Command ID



181
182
183
# File 'lib/discord_rda/bot.rb', line 181

def delete_guild_command(guild_id, command_id)
  @rest.delete("/applications/#{me.id}/guilds/#{guild_id}/commands/#{command_id}") if me
end

#delete_guild_integration(guild_id, integration_id, reason: nil) ⇒ void

This method returns an undefined value.

Delete a guild integration

Parameters:

  • guild_id (String, Snowflake)

    Guild ID

  • integration_id (String, Snowflake)

    Integration ID

  • reason (String, nil) (defaults to: nil)

    Audit log reason



1172
1173
1174
# File 'lib/discord_rda/bot.rb', line 1172

def delete_guild_integration(guild_id, integration_id, reason: nil)
  @rest.delete("/guilds/#{guild_id}/integrations/#{integration_id}", headers: audit_log_headers(reason))
end

#delete_guild_role(guild_id, role_id, reason: nil) ⇒ void

This method returns an undefined value.

Delete guild role

Parameters:

  • guild_id (String, Snowflake)

    Guild ID

  • role_id (String, Snowflake)

    Role ID

  • reason (String) (defaults to: nil)

    Audit log reason



892
893
894
895
# File 'lib/discord_rda/bot.rb', line 892

def delete_guild_role(guild_id, role_id, reason: nil)
  headers = reason ? { 'X-Audit-Log-Reason' => CGI.escape(reason) } : {}
  @rest.delete("/guilds/#{guild_id}/roles/#{role_id}", headers: headers)
end

#delete_guild_scheduled_event(guild_id, event_id) ⇒ void

This method returns an undefined value.

Delete a scheduled event

Parameters:



1330
1331
1332
# File 'lib/discord_rda/bot.rb', line 1330

def delete_guild_scheduled_event(guild_id, event_id)
  @rest.delete("/guilds/#{guild_id}/scheduled-events/#{event_id}")
end

#delete_guild_soundboard_sound(guild_id, sound_id, reason: nil) ⇒ void

This method returns an undefined value.

Delete a guild soundboard sound

Parameters:

  • guild_id (String, Snowflake)

    Guild ID

  • sound_id (String, Snowflake)

    Sound ID

  • reason (String, nil) (defaults to: nil)

    Audit log reason



1638
1639
1640
# File 'lib/discord_rda/bot.rb', line 1638

def delete_guild_soundboard_sound(guild_id, sound_id, reason: nil)
  @rest.delete("/guilds/#{guild_id}/soundboard-sounds/#{sound_id}", headers: audit_log_headers(reason))
end

#delete_guild_template(guild_id, code) ⇒ Hash

Delete a guild template

Parameters:

  • guild_id (String, Snowflake)

    Guild ID

  • code (String)

    Template code

Returns:

  • (Hash)

    Deleted template payload



1470
1471
1472
# File 'lib/discord_rda/bot.rb', line 1470

def delete_guild_template(guild_id, code)
  @rest.delete("/guilds/#{guild_id}/templates/#{code}")
end

#delete_stage_instance(channel_id, reason: nil) ⇒ void

This method returns an undefined value.

Delete a stage instance

Parameters:

  • channel_id (String, Snowflake)

    Stage channel ID

  • reason (String, nil) (defaults to: nil)

    Audit log reason



1392
1393
1394
# File 'lib/discord_rda/bot.rb', line 1392

def delete_stage_instance(channel_id, reason: nil)
  @rest.delete("/stage-instances/#{channel_id}", headers: audit_log_headers(reason))
end

#delete_test_entitlement(entitlement_id, application_id: nil) ⇒ void

This method returns an undefined value.

Delete a test entitlement

Parameters:

  • entitlement_id (String, Snowflake)

    Entitlement ID

  • application_id (String, Snowflake, nil) (defaults to: nil)

    Application ID



1577
1578
1579
1580
# File 'lib/discord_rda/bot.rb', line 1577

def delete_test_entitlement(entitlement_id, application_id: nil)
  app_id = application_id || application_id_for_rest
  @rest.delete("/applications/#{app_id}/entitlements/#{entitlement_id}")
end

#delete_webhook(webhook_id, token: nil) ⇒ void

This method returns an undefined value.

Delete a webhook

Parameters:

  • webhook_id (String, Snowflake)

    Webhook ID

  • token (String) (defaults to: nil)

    Webhook token (optional, for webhook-owned deletes)



995
996
997
998
# File 'lib/discord_rda/bot.rb', line 995

def delete_webhook(webhook_id, token: nil)
  path = token ? "/webhooks/#{webhook_id}/#{token}" : "/webhooks/#{webhook_id}"
  @rest.delete(path)
end

#delete_webhook_message(webhook_id, token, message_id, thread_id: nil) ⇒ void

This method returns an undefined value.

Delete a webhook message

Parameters:

  • webhook_id (String, Snowflake)

    Webhook ID

  • token (String)

    Webhook token

  • message_id (String, Snowflake)

    Message ID

  • thread_id (String, Snowflake, nil) (defaults to: nil)

    Thread channel ID



1096
1097
1098
1099
1100
# File 'lib/discord_rda/bot.rb', line 1096

def delete_webhook_message(webhook_id, token, message_id, thread_id: nil)
  params = {}
  params[:thread_id] = thread_id.to_s if thread_id
  @rest.delete("/webhooks/#{webhook_id}/#{token}/messages/#{message_id}", params: params)
end

#edit_channel_permissions(channel_id, overwrite_id, allow:, deny:, type:, reason: nil) ⇒ void

This method returns an undefined value.

Edit a channel permission overwrite

Parameters:

  • channel_id (String, Snowflake)

    Channel ID

  • overwrite_id (String, Snowflake)

    Role or member ID

  • allow (Integer, String)

    Allowed permissions bitfield

  • deny (Integer, String)

    Denied permissions bitfield

  • type (Integer)

    0 for role, 1 for member

  • reason (String, nil) (defaults to: nil)

    Audit log reason



471
472
473
474
475
476
477
478
# File 'lib/discord_rda/bot.rb', line 471

def edit_channel_permissions(channel_id, overwrite_id, allow:, deny:, type:, reason: nil)
  payload = {
    allow: allow.to_s,
    deny: deny.to_s,
    type: type
  }
  @rest.put("/channels/#{channel_id}/permissions/#{overwrite_id}", body: payload, headers: audit_log_headers(reason))
end

#edit_webhook_message(webhook_id, token, message_id, thread_id: nil, content: nil, **options) ⇒ Message

Edit a webhook message

Parameters:

  • webhook_id (String, Snowflake)

    Webhook ID

  • token (String)

    Webhook token

  • message_id (String, Snowflake)

    Message ID

  • thread_id (String, Snowflake, nil) (defaults to: nil)

    Thread channel ID

  • content (String, nil) (defaults to: nil)

    New content

  • options (Hash)

    Additional edit payload

Returns:



1082
1083
1084
1085
1086
1087
1088
# File 'lib/discord_rda/bot.rb', line 1082

def edit_webhook_message(webhook_id, token, message_id, thread_id: nil, content: nil, **options)
  params = {}
  params[:thread_id] = thread_id.to_s if thread_id
  payload = { content: content }.merge(options).compact
  data = @rest.patch("/webhooks/#{webhook_id}/#{token}/messages/#{message_id}", body: payload, params: params)
  Message.new(data)
end

#enable_active_record(database_url: nil, **options) ⇒ Object



113
114
115
116
117
# File 'lib/discord_rda/bot.rb', line 113

def enable_active_record(database_url: nil, **options)
  @active_record = ActiveRecordSystem.new(logger: @logger)
  @active_record.connect(database_url: database_url, **options)
  @active_record
end

#enable_auto_reshard(max_guilds_per_shard: 1000) ⇒ void

This method returns an undefined value.

Enable auto-resharding based on guild count

Parameters:

  • max_guilds_per_shard (Integer) (defaults to: 1000)

    Max guilds per shard



661
662
663
664
665
666
# File 'lib/discord_rda/bot.rb', line 661

def enable_auto_reshard(max_guilds_per_shard: 1000)
  @event_bus.on(:guild_create) do |_event|
    guild_count = @shard_manager.total_guilds || 0
    @reshard_manager.auto_reshard_if_needed(guild_count, max_guilds_per_shard: max_guilds_per_shard)
  end
end

#enable_hot_reload(watch_dir: 'lib') ⇒ void

This method returns an undefined value.

Enable hot reload for development

Parameters:

  • watch_dir (String) (defaults to: 'lib')

    Directory to watch



644
645
646
647
648
# File 'lib/discord_rda/bot.rb', line 644

def enable_hot_reload(watch_dir: 'lib')
  @logger.info('Enabling hot reload', watch_dir: watch_dir)
  @hot_reload_manager = HotReloadManager.new(self, @logger, watch_dir: watch_dir)
  @hot_reload_manager.enable
end

#enable_scalable_rest(proxy: nil) ⇒ void

This method returns an undefined value.

Enable scalable REST client (queue-based rate limiting)

Parameters:

  • proxy (Hash) (defaults to: nil)

    Optional proxy configuration



634
635
636
637
638
639
# File 'lib/discord_rda/bot.rb', line 634

def enable_scalable_rest(proxy: nil)
  @logger.info('Enabling scalable REST client')
  @scalable_rest = ScalableRestClient.new(@config, @logger, proxy: proxy)
  @scalable_rest.start
  configure_entity_apis(@scalable_rest)
end

#entitlements(application_id: nil, **options) ⇒ Array<Hash>

Get entitlements for the current application

Parameters:

  • application_id (String, Snowflake, nil) (defaults to: nil)

    Application ID

  • options (Hash)

    Query filters

Returns:

  • (Array<Hash>)

    Entitlement payloads



1554
1555
1556
1557
1558
1559
# File 'lib/discord_rda/bot.rb', line 1554

def entitlements(application_id: nil, **options)
  app_id = application_id || application_id_for_rest
  params = normalize_rest_params(options, :before, :after, :guild_id, :user_id, :limit, :exclude_ended)
  params[:sku_ids] = Array(options[:sku_ids]).map(&:to_s).join(',') if options[:sku_ids]
  @rest.get("/applications/#{app_id}/entitlements", params: params)
end

#execute_github_webhook(webhook_id, token, payload) ⇒ Object

Execute a GitHub-compatible webhook

Parameters:

  • webhook_id (String, Snowflake)

    Webhook ID

  • token (String)

    Webhook token

  • payload (Hash)

    GitHub webhook payload

Returns:

  • (Object)

    API response



1055
1056
1057
# File 'lib/discord_rda/bot.rb', line 1055

def execute_github_webhook(webhook_id, token, payload)
  @rest.post("/webhooks/#{webhook_id}/#{token}/github", body: payload)
end

#execute_slack_webhook(webhook_id, token, payload) ⇒ Object

Execute a Slack-compatible webhook

Parameters:

  • webhook_id (String, Snowflake)

    Webhook ID

  • token (String)

    Webhook token

  • payload (Hash)

    Slack webhook payload

Returns:

  • (Object)

    API response



1046
1047
1048
# File 'lib/discord_rda/bot.rb', line 1046

def execute_slack_webhook(webhook_id, token, payload)
  @rest.post("/webhooks/#{webhook_id}/#{token}/slack", body: payload)
end

#execute_webhook(webhook_id, token, content = nil, **options) ⇒ Message?

Execute webhook

Parameters:

  • webhook_id (String, Snowflake)

    Webhook ID

  • token (String)

    Webhook token

  • content (String) (defaults to: nil)

    Message content

  • options (Hash)

    Options (username, avatar_url, embeds, etc.)

Options Hash (**options):

  • :wait (Boolean)

    Return the created message

  • :thread_id (String, Snowflake)

    Execute in a thread

Returns:



982
983
984
985
986
987
988
989
# File 'lib/discord_rda/bot.rb', line 982

def execute_webhook(webhook_id, token, content = nil, **options)
  params = {}
  params[:wait] = options[:wait] unless options[:wait].nil?
  params[:thread_id] = options[:thread_id].to_s if options[:thread_id]
  payload = { content: content }.merge(options.slice(:username, :avatar_url, :embeds, :components, :allowed_mentions, :tts))
  response = @rest.post("/webhooks/#{webhook_id}/#{token}", body: payload, params: params)
  response.is_a?(Hash) ? Message.new(response) : nil
end

#follow_news_channel(channel_id, webhook_channel_id) ⇒ Hash

Follow an announcement channel into a target channel

Parameters:

  • channel_id (String, Snowflake)

    Source announcement channel ID

  • webhook_channel_id (String, Snowflake)

    Destination channel ID

Returns:

  • (Hash)

    Followed channel response



515
516
517
# File 'lib/discord_rda/bot.rb', line 515

def follow_news_channel(channel_id, webhook_channel_id)
  @rest.post("/channels/#{channel_id}/followers", body: { webhook_channel_id: webhook_channel_id.to_s })
end

#gatewayHash

Get gateway information

Returns:

  • (Hash)

    Gateway payload



1776
1777
1778
# File 'lib/discord_rda/bot.rb', line 1776

def gateway
  @rest.get('/gateway')
end

#gateway_botHash

Get gateway bot information

Returns:

  • (Hash)

    Gateway bot payload



1782
1783
1784
# File 'lib/discord_rda/bot.rb', line 1782

def gateway_bot
  @rest.get('/gateway/bot')
end

#get_reactions(channel_id, message_id, emoji, limit: 25, after: nil) ⇒ Array<User>

Get reactions for a message

Parameters:

  • channel_id (String, Snowflake)

    Channel ID

  • message_id (String, Snowflake)

    Message ID

  • emoji (String, Emoji)

    Emoji filter

  • limit (Integer) (defaults to: 25)

    Max users to return (1-100, default 25)

  • after (String, Snowflake, nil) (defaults to: nil)

    Cursor for pagination

Returns:

  • (Array<User>)

    Users who reacted



711
712
713
714
715
716
717
# File 'lib/discord_rda/bot.rb', line 711

def get_reactions(channel_id, message_id, emoji, limit: 25, after: nil)
  emoji_str = emoji.respond_to?(:id) ? "#{emoji.name}:#{emoji.id}" : emoji.to_s
  params = { limit: limit }
  params[:after] = after.to_s if after
  data = @rest.get("/channels/#{channel_id}/messages/#{message_id}/reactions/#{CGI.escape(emoji_str)}", params: params)
  data.map { |u| User.new(u) }
end

#guild(guild_id) ⇒ Guild?

Get a guild by ID

Parameters:

Returns:

  • (Guild, nil)

    Guild or nil



309
310
311
312
313
314
315
316
317
318
319
# File 'lib/discord_rda/bot.rb', line 309

def guild(guild_id)
  cached = @cache.guild(guild_id)
  return cached if cached

  data = @rest.get("/guilds/#{guild_id}")
  guild = Guild.new(data)
  @cache.cache_guild(guild)
  guild
rescue RestClient::NotFoundError
  nil
end

#guild_audit_log(guild_id, user_id: nil, action_type: nil, before: nil, after: nil, limit: nil) ⇒ AuditLog

Get audit log entries for a guild

Parameters:

  • guild_id (String, Snowflake)

    Guild ID

  • user_id (String, Snowflake, nil) (defaults to: nil)

    Filter by acting user

  • action_type (Integer, nil) (defaults to: nil)

    Filter by action type

  • before (String, Snowflake, nil) (defaults to: nil)

    Pagination cursor

  • after (String, Snowflake, nil) (defaults to: nil)

    Pagination cursor

  • limit (Integer, nil) (defaults to: nil)

    Max entries

Returns:



1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
# File 'lib/discord_rda/bot.rb', line 1273

def guild_audit_log(guild_id, user_id: nil, action_type: nil, before: nil, after: nil, limit: nil)
  params = {
    user_id: user_id&.to_s,
    action_type: action_type,
    before: before&.to_s,
    after: after&.to_s,
    limit: limit
  }.compact
  AuditLog.new(@rest.get("/guilds/#{guild_id}/audit-logs", params: params))
end

#guild_ban(guild_id, user_id) ⇒ Hash?

Get a specific guild ban

Parameters:

Returns:

  • (Hash, nil)

    Ban data or nil



917
918
919
920
921
922
# File 'lib/discord_rda/bot.rb', line 917

def guild_ban(guild_id, user_id)
  data = @rest.get("/guilds/#{guild_id}/bans/#{user_id}")
  { user: User.new(data['user']), reason: data['reason'] }
rescue RestClient::NotFoundError
  nil
end

#guild_bans(guild_id, limit: 100, before: nil, after: nil) ⇒ Array<Hash>

Get guild bans

Parameters:

  • guild_id (String, Snowflake)

    Guild ID

  • limit (Integer) (defaults to: 100)

    Max bans (1-1000, default 100)

  • before (String, Snowflake, nil) (defaults to: nil)

    Cursor for pagination

  • after (String, Snowflake, nil) (defaults to: nil)

    Cursor for pagination

Returns:

  • (Array<Hash>)

    Bans (user + reason data)



905
906
907
908
909
910
911
# File 'lib/discord_rda/bot.rb', line 905

def guild_bans(guild_id, limit: 100, before: nil, after: nil)
  params = { limit: limit }
  params[:before] = before.to_s if before
  params[:after] = after.to_s if after
  data = @rest.get("/guilds/#{guild_id}/bans", params: params)
  data.map { |b| { user: User.new(b['user']), reason: b['reason'] } }
end

#guild_channels(guild_id) ⇒ Array<Channel>

Get guild channels

Parameters:

Returns:



1107
1108
1109
1110
# File 'lib/discord_rda/bot.rb', line 1107

def guild_channels(guild_id)
  data = @rest.get("/guilds/#{guild_id}/channels")
  data.map { |c| Channel.new(c) }
end

#guild_integrations(guild_id) ⇒ Array<Integration>

Get integrations for a guild

Parameters:

Returns:



1163
1164
1165
# File 'lib/discord_rda/bot.rb', line 1163

def guild_integrations(guild_id)
  @rest.get("/guilds/#{guild_id}/integrations").map { |integration| Integration.new(integration.merge('guild_id' => guild_id.to_s)) }
end

#guild_invites(guild_id) ⇒ Array<Hash>

Get active invites for a guild

Parameters:

Returns:

  • (Array<Hash>)

    Invite payloads



1156
1157
1158
# File 'lib/discord_rda/bot.rb', line 1156

def guild_invites(guild_id)
  @rest.get("/guilds/#{guild_id}/invites")
end

#guild_member(guild_id, user_id) ⇒ Member?

Get a guild member

Parameters:

Returns:

  • (Member, nil)

    Member or nil



733
734
735
736
737
738
# File 'lib/discord_rda/bot.rb', line 733

def guild_member(guild_id, user_id)
  data = @rest.get("/guilds/#{guild_id}/members/#{user_id}")
  Member.new(data.merge('guild_id' => guild_id.to_s))
rescue RestClient::NotFoundError
  nil
end

#guild_members(guild_id, limit: 100, after: nil) ⇒ Array<Member>

List guild members with pagination

Parameters:

  • guild_id (String, Snowflake)

    Guild ID

  • limit (Integer) (defaults to: 100)

    Max members (1-1000, default 100)

  • after (String, Snowflake) (defaults to: nil)

    Get members after this user ID

Returns:



745
746
747
748
749
750
# File 'lib/discord_rda/bot.rb', line 745

def guild_members(guild_id, limit: 100, after: nil)
  params = { limit: limit }
  params[:after] = after.to_s if after
  data = @rest.get("/guilds/#{guild_id}/members", params: params)
  data.map { |m| Member.new(m.merge('guild_id' => guild_id.to_s)) }
end

#guild_onboarding(guild_id) ⇒ Hash?

Get guild onboarding

Parameters:

Returns:

  • (Hash, nil)

    Onboarding payload



1251
1252
1253
1254
1255
# File 'lib/discord_rda/bot.rb', line 1251

def guild_onboarding(guild_id)
  @rest.get("/guilds/#{guild_id}/onboarding")
rescue RestClient::NotFoundError
  nil
end

#guild_preview(guild_id) ⇒ Hash?

Get a guild preview

Parameters:

Returns:

  • (Hash, nil)

    Guild preview payload



1115
1116
1117
1118
1119
# File 'lib/discord_rda/bot.rb', line 1115

def guild_preview(guild_id)
  @rest.get("/guilds/#{guild_id}/preview")
rescue RestClient::NotFoundError
  nil
end

#guild_prune_count(guild_id, days:, include_roles: nil) ⇒ Integer?

Get the expected prune count for a guild

Parameters:

  • guild_id (String, Snowflake)

    Guild ID

  • days (Integer)

    Inactive days threshold

  • include_roles (Array<String, Snowflake>) (defaults to: nil)

    Optional role IDs

Returns:

  • (Integer, nil)

    Number of prunable members



1126
1127
1128
1129
1130
# File 'lib/discord_rda/bot.rb', line 1126

def guild_prune_count(guild_id, days:, include_roles: nil)
  params = { days: days }
  params[:include_roles] = Array(include_roles).map(&:to_s).join(',') if include_roles
  @rest.get("/guilds/#{guild_id}/prune", params: params)['pruned']
end

#guild_roles(guild_id) ⇒ Array<Role>

Get guild roles

Parameters:

Returns:

  • (Array<Role>)

    Roles



847
848
849
850
# File 'lib/discord_rda/bot.rb', line 847

def guild_roles(guild_id)
  data = @rest.get("/guilds/#{guild_id}/roles")
  data.map { |r| Role.new(r.merge('guild_id' => guild_id.to_s)) }
end

#guild_scheduled_event(guild_id, event_id, with_user_count: false) ⇒ GuildScheduledEvent?

Get a specific scheduled event

Parameters:

  • guild_id (String, Snowflake)

    Guild ID

  • event_id (String, Snowflake)

    Event ID

  • with_user_count (Boolean) (defaults to: false)

    Include subscriber count

Returns:



1298
1299
1300
1301
1302
1303
# File 'lib/discord_rda/bot.rb', line 1298

def guild_scheduled_event(guild_id, event_id, with_user_count: false)
  data = @rest.get("/guilds/#{guild_id}/scheduled-events/#{event_id}", params: { with_user_count: with_user_count })
  GuildScheduledEvent.new(data)
rescue RestClient::NotFoundError
  nil
end

#guild_scheduled_event_users(guild_id, event_id, limit: nil, with_member: false, before: nil, after: nil) ⇒ Array<Hash>

List users subscribed to a scheduled event

Parameters:

  • guild_id (String, Snowflake)

    Guild ID

  • event_id (String, Snowflake)

    Event ID

  • limit (Integer, nil) (defaults to: nil)

    Max users

  • with_member (Boolean) (defaults to: false)

    Include member objects

  • before (String, Snowflake, nil) (defaults to: nil)

    Pagination cursor

  • after (String, Snowflake, nil) (defaults to: nil)

    Pagination cursor

Returns:

  • (Array<Hash>)

    Subscriber payloads



1342
1343
1344
1345
1346
1347
1348
1349
1350
# File 'lib/discord_rda/bot.rb', line 1342

def guild_scheduled_event_users(guild_id, event_id, limit: nil, with_member: false, before: nil, after: nil)
  params = {
    limit: limit,
    with_member: with_member,
    before: before&.to_s,
    after: after&.to_s
  }.compact
  @rest.get("/guilds/#{guild_id}/scheduled-events/#{event_id}/users", params: params)
end

#guild_scheduled_events(guild_id, with_user_count: false) ⇒ Array<GuildScheduledEvent>

List scheduled events for a guild

Parameters:

  • guild_id (String, Snowflake)

    Guild ID

  • with_user_count (Boolean) (defaults to: false)

    Include subscriber counts

Returns:



1288
1289
1290
1291
# File 'lib/discord_rda/bot.rb', line 1288

def guild_scheduled_events(guild_id, with_user_count: false)
  data = @rest.get("/guilds/#{guild_id}/scheduled-events", params: { with_user_count: with_user_count })
  data.map { |event| GuildScheduledEvent.new(event) }
end

#guild_soundboard_sound(guild_id, sound_id) ⇒ Hash?

Get a single guild soundboard sound

Parameters:

Returns:

  • (Hash, nil)

    Soundboard sound payload



1608
1609
1610
1611
1612
# File 'lib/discord_rda/bot.rb', line 1608

def guild_soundboard_sound(guild_id, sound_id)
  @rest.get("/guilds/#{guild_id}/soundboard-sounds/#{sound_id}")
rescue RestClient::NotFoundError
  nil
end

#guild_soundboard_sounds(guild_id) ⇒ Hash

Get guild soundboard sounds

Parameters:

Returns:

  • (Hash)

    Soundboard payload



1600
1601
1602
# File 'lib/discord_rda/bot.rb', line 1600

def guild_soundboard_sounds(guild_id)
  @rest.get("/guilds/#{guild_id}/soundboard-sounds")
end

#guild_sticker(guild_id, sticker_id) ⇒ Sticker?

Get a guild sticker

Parameters:

Returns:



1408
1409
1410
1411
1412
1413
# File 'lib/discord_rda/bot.rb', line 1408

def guild_sticker(guild_id, sticker_id)
  data = @rest.get("/guilds/#{guild_id}/stickers/#{sticker_id}")
  Sticker.new(data)
rescue RestClient::NotFoundError
  nil
end

#guild_stickers(guild_id) ⇒ Array<Sticker>

List stickers for a guild

Parameters:

Returns:

  • (Array<Sticker>)

    Guild stickers



1399
1400
1401
1402
# File 'lib/discord_rda/bot.rb', line 1399

def guild_stickers(guild_id)
  data = @rest.get("/guilds/#{guild_id}/stickers")
  data.map { |sticker| Sticker.new(sticker) }
end

#guild_template(code) ⇒ Hash?

Fetch a guild template by code

Parameters:

  • code (String)

    Template code

Returns:

  • (Hash, nil)

    Template payload



1477
1478
1479
1480
1481
# File 'lib/discord_rda/bot.rb', line 1477

def guild_template(code)
  @rest.get("/guilds/templates/#{code}")
rescue RestClient::NotFoundError
  nil
end

#guild_templates(guild_id) ⇒ Array<Hash>

Get guild templates

Parameters:

Returns:

  • (Array<Hash>)

    Template payloads



1434
1435
1436
# File 'lib/discord_rda/bot.rb', line 1434

def guild_templates(guild_id)
  @rest.get("/guilds/#{guild_id}/templates")
end

#guild_vanity_url(guild_id) ⇒ Hash?

Get a guild vanity URL

Parameters:

Returns:

  • (Hash, nil)

    Vanity URL payload



1208
1209
1210
1211
1212
# File 'lib/discord_rda/bot.rb', line 1208

def guild_vanity_url(guild_id)
  @rest.get("/guilds/#{guild_id}/vanity-url")
rescue RestClient::NotFoundError
  nil
end

#guild_voice_regions(guild_id) ⇒ Array<Hash>

Get voice regions for a guild

Parameters:

Returns:

  • (Array<Hash>)

    Voice regions



1149
1150
1151
# File 'lib/discord_rda/bot.rb', line 1149

def guild_voice_regions(guild_id)
  @rest.get("/guilds/#{guild_id}/regions")
end

#guild_webhooks(guild_id) ⇒ Array<Webhook>

Get guild webhooks

Parameters:

Returns:



970
971
972
# File 'lib/discord_rda/bot.rb', line 970

def guild_webhooks(guild_id)
  @rest.get("/guilds/#{guild_id}/webhooks").map { |hook| Webhook.new(hook) }
end

#guild_welcome_screen(guild_id) ⇒ Hash?

Get a guild welcome screen

Parameters:

Returns:

  • (Hash, nil)

    Welcome screen payload



1226
1227
1228
1229
1230
# File 'lib/discord_rda/bot.rb', line 1226

def guild_welcome_screen(guild_id)
  @rest.get("/guilds/#{guild_id}/welcome-screen")
rescue RestClient::NotFoundError
  nil
end

#guild_widget(guild_id) ⇒ Hash?

Get guild widget data

Parameters:

Returns:

  • (Hash, nil)

    Widget payload



1199
1200
1201
1202
1203
# File 'lib/discord_rda/bot.rb', line 1199

def guild_widget(guild_id)
  @rest.get("/guilds/#{guild_id}/widget.json")
rescue RestClient::NotFoundError
  nil
end

#guild_widget_image(guild_id, style: nil) ⇒ String

Build a guild widget image URL

Parameters:

  • guild_id (String, Snowflake)

    Guild ID

  • style (String, nil) (defaults to: nil)

    Widget image style

Returns:

  • (String)

    Widget image URL



1218
1219
1220
1221
# File 'lib/discord_rda/bot.rb', line 1218

def guild_widget_image(guild_id, style: nil)
  url = "https://discord.com/api/guilds/#{guild_id}/widget.png"
  style ? "#{url}?style=#{CGI.escape(style)}" : url
end

#guild_widget_settings(guild_id) ⇒ Hash?

Get guild widget settings

Parameters:

Returns:

  • (Hash, nil)

    Widget settings



1179
1180
1181
1182
1183
# File 'lib/discord_rda/bot.rb', line 1179

def guild_widget_settings(guild_id)
  @rest.get("/guilds/#{guild_id}/widget")
rescue RestClient::NotFoundError
  nil
end

#invalid_bucket_statusHash?

Get invalid request bucket status

Returns:

  • (Hash, nil)

    Invalid bucket status



670
671
672
# File 'lib/discord_rda/bot.rb', line 670

def invalid_bucket_status
  @scalable_rest&.invalid_bucket&.status
end

#join_thread(thread_id) ⇒ void

This method returns an undefined value.

Join a thread

Parameters:

  • thread_id (String, Snowflake)

    Thread channel ID



559
560
561
# File 'lib/discord_rda/bot.rb', line 559

def join_thread(thread_id)
  @rest.put("/channels/#{thread_id}/thread-members/@me")
end

#leave_guild(guild_id) ⇒ void

This method returns an undefined value.

Leave a guild as the current user

Parameters:



1722
1723
1724
# File 'lib/discord_rda/bot.rb', line 1722

def leave_guild(guild_id)
  User.leave_guild(guild_id)
end

#leave_thread(thread_id) ⇒ void

This method returns an undefined value.

Leave a thread

Parameters:

  • thread_id (String, Snowflake)

    Thread channel ID



574
575
576
# File 'lib/discord_rda/bot.rb', line 574

def leave_thread(thread_id)
  @rest.delete("/channels/#{thread_id}/thread-members/@me")
end

#meUser

Fetch current user

Returns:

  • (User)

    Bot user



301
302
303
304
# File 'lib/discord_rda/bot.rb', line 301

def me
  data = @rest.get('/users/@me')
  User.new(data)
end

#modify_auto_moderation_rule(guild_id, rule_id, reason: nil, **options) ⇒ AutoModerationRule

Modify an auto moderation rule

Parameters:

  • guild_id (String, Snowflake)

    Guild ID

  • rule_id (String, Snowflake)

    Rule ID

  • reason (String, nil) (defaults to: nil)

    Audit log reason

  • options (Hash)

    Rule payload

Returns:



1528
1529
1530
1531
# File 'lib/discord_rda/bot.rb', line 1528

def modify_auto_moderation_rule(guild_id, rule_id, reason: nil, **options)
  data = @rest.patch("/guilds/#{guild_id}/auto-moderation/rules/#{rule_id}", body: options.compact, headers: audit_log_headers(reason))
  AutoModerationRule.new(data)
end

#modify_channel(channel_id, **options) ⇒ Channel

Modify channel

Parameters:

  • channel_id (String, Snowflake)

    Channel ID

  • options (Hash)

    Settings to modify

Returns:



1668
1669
1670
1671
1672
# File 'lib/discord_rda/bot.rb', line 1668

def modify_channel(channel_id, **options)
  payload = options.slice(:name, :type, :position, :topic, :nsfw, :rate_limit_per_user, :bitrate, :user_limit, :parent_id, :default_auto_archive_duration)
  data = @rest.patch("/channels/#{channel_id}", body: payload)
  Channel.new(data)
end

#modify_current_member(guild_id, nick: nil, reason: nil) ⇒ Member

Modify the current bot member in a guild

Parameters:

  • guild_id (String, Snowflake)

    Guild ID

  • nick (String, nil) (defaults to: nil)

    New nickname

  • reason (String, nil) (defaults to: nil)

    Audit log reason

Returns:



796
797
798
799
# File 'lib/discord_rda/bot.rb', line 796

def modify_current_member(guild_id, nick: nil, reason: nil)
  data = @rest.patch("/guilds/#{guild_id}/members/@me", body: { nick: nick }.compact, headers: audit_log_headers(reason))
  Member.new(data.merge('guild_id' => guild_id.to_s))
end

#modify_current_user(username: nil, avatar: nil) ⇒ User?

Modify the bot user’s profile

Parameters:

  • username (String, nil) (defaults to: nil)

    New username

  • avatar (File, String, nil) (defaults to: nil)

    New avatar

Returns:

  • (User, nil)

    Updated user



1698
1699
1700
# File 'lib/discord_rda/bot.rb', line 1698

def modify_current_user(username: nil, avatar: nil)
  User.modify_current_user(username: username, avatar: avatar)
end

#modify_current_user_nick(guild_id, nick: nil, reason: nil) ⇒ Hash

Modify the current bot nickname in a guild

Parameters:

  • guild_id (String, Snowflake)

    Guild ID

  • nick (String, nil) (defaults to: nil)

    New nickname

  • reason (String, nil) (defaults to: nil)

    Audit log reason

Returns:

  • (Hash)

    Discord nickname response



806
807
808
# File 'lib/discord_rda/bot.rb', line 806

def modify_current_user_nick(guild_id, nick: nil, reason: nil)
  @rest.patch("/guilds/#{guild_id}/members/@me/nick", body: { nick: nick }.compact, headers: audit_log_headers(reason))
end

#modify_guild(guild_id, reason: nil, **options) ⇒ Guild

Modify a guild

Parameters:

  • guild_id (String, Snowflake)

    Guild ID

  • reason (String, nil) (defaults to: nil)

    Audit log reason

  • options (Hash)

    Guild modification payload

Returns:

  • (Guild)

    Updated guild



336
337
338
339
# File 'lib/discord_rda/bot.rb', line 336

def modify_guild(guild_id, reason: nil, **options)
  data = @rest.patch("/guilds/#{guild_id}", body: options.compact, headers: audit_log_headers(reason))
  Guild.new(data)
end

#modify_guild_member(guild_id, user_id, **options) ⇒ Member

Modify a guild member

Parameters:

  • guild_id (String, Snowflake)

    Guild ID

  • user_id (String, Snowflake)

    User ID

  • options (Hash)

    Options to modify (nick, roles, mute, deaf, channel_id)

Returns:



768
769
770
771
772
# File 'lib/discord_rda/bot.rb', line 768

def modify_guild_member(guild_id, user_id, **options)
  payload = options.slice(:nick, :roles, :mute, :deaf, :channel_id, :communication_disabled_until)
  data = @rest.patch("/guilds/#{guild_id}/members/#{user_id}", body: payload)
  Member.new(data.merge('guild_id' => guild_id.to_s))
end

#modify_guild_onboarding(guild_id, **options) ⇒ Hash

Modify guild onboarding

Parameters:

  • guild_id (String, Snowflake)

    Guild ID

  • options (Hash)

    Raw onboarding payload

Returns:

  • (Hash)

    Updated onboarding payload



1261
1262
1263
# File 'lib/discord_rda/bot.rb', line 1261

def modify_guild_onboarding(guild_id, **options)
  @rest.put("/guilds/#{guild_id}/onboarding", body: options)
end

#modify_guild_role(guild_id, role_id, reason: nil, **options) ⇒ Role

Modify guild role

Parameters:

  • guild_id (String, Snowflake)

    Guild ID

  • role_id (String, Snowflake)

    Role ID

  • options (Hash)

    Settings to modify

Returns:

  • (Role)

    Updated role



868
869
870
871
872
# File 'lib/discord_rda/bot.rb', line 868

def modify_guild_role(guild_id, role_id, reason: nil, **options)
  payload = options.slice(:name, :permissions, :color, :hoist, :mentionable, :icon, :unicode_emoji)
  data = @rest.patch("/guilds/#{guild_id}/roles/#{role_id}", body: payload, headers: audit_log_headers(reason))
  Role.new(data.merge('guild_id' => guild_id.to_s))
end

#modify_guild_role_positions(guild_id, positions, reason: nil) ⇒ Array<Role>

Modify guild role positions

Parameters:

  • guild_id (String, Snowflake)

    Guild ID

  • positions (Array<Hash>)

    Array of { id:, position: }

  • reason (String, nil) (defaults to: nil)

    Audit log reason

Returns:

  • (Array<Role>)

    Updated role ordering



879
880
881
882
883
884
885
# File 'lib/discord_rda/bot.rb', line 879

def modify_guild_role_positions(guild_id, positions, reason: nil)
  payload = positions.map do |position|
    { id: (position[:id] || position['id']).to_s, position: position[:position] || position['position'] }
  end
  data = @rest.patch("/guilds/#{guild_id}/roles", body: payload, headers: audit_log_headers(reason))
  data.map { |role| Role.new(role.merge('guild_id' => guild_id.to_s)) }
end

#modify_guild_scheduled_event(guild_id, event_id, reason: nil, **options) ⇒ GuildScheduledEvent

Modify a scheduled event

Parameters:

  • guild_id (String, Snowflake)

    Guild ID

  • event_id (String, Snowflake)

    Event ID

  • reason (String, nil) (defaults to: nil)

    Audit log reason

  • options (Hash)

    Scheduled event payload

Returns:



1321
1322
1323
1324
# File 'lib/discord_rda/bot.rb', line 1321

def modify_guild_scheduled_event(guild_id, event_id, reason: nil, **options)
  data = @rest.patch("/guilds/#{guild_id}/scheduled-events/#{event_id}", body: options.compact, headers: audit_log_headers(reason))
  GuildScheduledEvent.new(data)
end

#modify_guild_soundboard_sound(guild_id, sound_id, reason: nil, **options) ⇒ Hash

Modify a guild soundboard sound

Parameters:

  • guild_id (String, Snowflake)

    Guild ID

  • sound_id (String, Snowflake)

    Sound ID

  • reason (String, nil) (defaults to: nil)

    Audit log reason

  • options (Hash)

    Soundboard payload

Returns:

  • (Hash)

    Soundboard sound payload



1629
1630
1631
# File 'lib/discord_rda/bot.rb', line 1629

def modify_guild_soundboard_sound(guild_id, sound_id, reason: nil, **options)
  @rest.patch("/guilds/#{guild_id}/soundboard-sounds/#{sound_id}", body: options.compact, headers: audit_log_headers(reason))
end

#modify_guild_template(guild_id, code, name: nil, description: nil) ⇒ Hash

Modify a guild template

Parameters:

  • guild_id (String, Snowflake)

    Guild ID

  • code (String)

    Template code

  • name (String, nil) (defaults to: nil)

    New template name

  • description (String, nil) (defaults to: nil)

    New template description

Returns:

  • (Hash)

    Template payload



1461
1462
1463
1464
# File 'lib/discord_rda/bot.rb', line 1461

def modify_guild_template(guild_id, code, name: nil, description: nil)
  payload = { name: name, description: description }.compact
  @rest.patch("/guilds/#{guild_id}/templates/#{code}", body: payload)
end

#modify_guild_welcome_screen(guild_id, enabled: nil, welcome_channels: nil, description: nil, reason: nil) ⇒ Hash

Modify a guild welcome screen

Parameters:

  • guild_id (String, Snowflake)

    Guild ID

  • enabled (Boolean, nil) (defaults to: nil)

    Whether enabled

  • welcome_channels (Array<Hash>, nil) (defaults to: nil)

    Welcome channel configuration

  • description (String, nil) (defaults to: nil)

    Welcome description

  • reason (String, nil) (defaults to: nil)

    Audit log reason

Returns:

  • (Hash)

    Updated welcome screen payload



1239
1240
1241
1242
1243
1244
1245
1246
# File 'lib/discord_rda/bot.rb', line 1239

def modify_guild_welcome_screen(guild_id, enabled: nil, welcome_channels: nil, description: nil, reason: nil)
  payload = {
    enabled: enabled,
    welcome_channels: welcome_channels,
    description: description
  }.compact
  @rest.patch("/guilds/#{guild_id}/welcome-screen", body: payload, headers: audit_log_headers(reason))
end

#modify_guild_widget(guild_id, enabled: nil, channel_id: nil, reason: nil) ⇒ Hash

Modify guild widget settings

Parameters:

  • guild_id (String, Snowflake)

    Guild ID

  • enabled (Boolean, nil) (defaults to: nil)

    Whether widget is enabled

  • channel_id (String, Snowflake, nil) (defaults to: nil)

    Widget channel ID

  • reason (String, nil) (defaults to: nil)

    Audit log reason

Returns:

  • (Hash)

    Updated widget settings



1191
1192
1193
1194
# File 'lib/discord_rda/bot.rb', line 1191

def modify_guild_widget(guild_id, enabled: nil, channel_id: nil, reason: nil)
  payload = { enabled: enabled, channel_id: channel_id&.to_s }.compact
  @rest.patch("/guilds/#{guild_id}/widget", body: payload, headers: audit_log_headers(reason))
end

#modify_stage_instance(channel_id, topic: nil, privacy_level: nil) ⇒ Hash

Modify a stage instance

Parameters:

  • channel_id (String, Snowflake)

    Stage channel ID

  • topic (String, nil) (defaults to: nil)

    Updated topic

  • privacy_level (Integer, nil) (defaults to: nil)

    Updated privacy level

Returns:

  • (Hash)

    Updated stage instance payload



1384
1385
1386
# File 'lib/discord_rda/bot.rb', line 1384

def modify_stage_instance(channel_id, topic: nil, privacy_level: nil)
  @rest.patch("/stage-instances/#{channel_id}", body: { topic: topic, privacy_level: privacy_level }.compact)
end

#modify_webhook(webhook_id, name: nil, avatar: nil, channel_id: nil, reason: nil) ⇒ Webhook

Modify a webhook

Parameters:

  • webhook_id (String, Snowflake)

    Webhook ID

  • name (String, nil) (defaults to: nil)

    New webhook name

  • avatar (String, nil) (defaults to: nil)

    Base64 avatar data

  • channel_id (String, Snowflake, nil) (defaults to: nil)

    New channel ID

Returns:

  • (Webhook)

    Updated webhook payload



1025
1026
1027
1028
# File 'lib/discord_rda/bot.rb', line 1025

def modify_webhook(webhook_id, name: nil, avatar: nil, channel_id: nil, reason: nil)
  payload = { name: name, avatar: avatar, channel_id: channel_id&.to_s }.compact
  Webhook.new(@rest.patch("/webhooks/#{webhook_id}", body: payload, headers: audit_log_headers(reason)))
end

#modify_webhook_with_token(webhook_id, token, name: nil, avatar: nil) ⇒ Webhook

Modify a webhook using its token

Parameters:

  • webhook_id (String, Snowflake)

    Webhook ID

  • token (String)

    Webhook token

  • name (String, nil) (defaults to: nil)

    New webhook name

  • avatar (String, nil) (defaults to: nil)

    Base64 avatar data

Returns:

  • (Webhook)

    Updated webhook payload



1036
1037
1038
1039
# File 'lib/discord_rda/bot.rb', line 1036

def modify_webhook_with_token(webhook_id, token, name: nil, avatar: nil)
  payload = { name: name, avatar: avatar }.compact
  Webhook.new(@rest.patch("/webhooks/#{webhook_id}/#{token}", body: payload))
end

#on(event) { ... } ⇒ Subscription

Register an event handler

Parameters:

  • event (String, Symbol)

    Event type

Yields:

  • Event handler block

Returns:

  • (Subscription)

    Subscription object



189
190
191
# File 'lib/discord_rda/bot.rb', line 189

def on(event, &block)
  @event_bus.on(event, &block)
end

#once(event) { ... } ⇒ Subscription

Register a one-time event handler

Parameters:

  • event (String, Symbol)

    Event type

Yields:

  • Event handler block

Returns:

  • (Subscription)

    Subscription object



197
198
199
# File 'lib/discord_rda/bot.rb', line 197

def once(event, &block)
  @event_bus.once(event, &block)
end

#pin_message(channel_id, message_id, reason: nil) ⇒ void

This method returns an undefined value.

Pin a channel message

Parameters:

  • channel_id (String, Snowflake)

    Channel ID

  • message_id (String, Snowflake)

    Message ID

  • reason (String, nil) (defaults to: nil)

    Audit log reason



450
451
452
# File 'lib/discord_rda/bot.rb', line 450

def pin_message(channel_id, message_id, reason: nil)
  @rest.put("/channels/#{channel_id}/pins/#{message_id}", headers: audit_log_headers(reason))
end

#pinned_messages(channel_id) ⇒ Array<Message>

Get pinned messages for a channel

Parameters:

  • channel_id (String, Snowflake)

    Channel ID

Returns:

  • (Array<Message>)

    Pinned messages



440
441
442
443
# File 'lib/discord_rda/bot.rb', line 440

def pinned_messages(channel_id)
  data = @rest.get("/channels/#{channel_id}/pins")
  data.map { |message| Message.new(message) }
end

#register_command(name, description = '', options = []) { ... } ⇒ void Also known as: command

This method returns an undefined value.

Register a command

Parameters:

  • name (String)

    Command name

  • description (String) (defaults to: '')

    Command description

  • options (Array<Hash>) (defaults to: [])

    Command options

Yields:

  • Command handler



216
217
218
219
220
221
222
# File 'lib/discord_rda/bot.rb', line 216

def register_command(name, description = '', options = [], &block)
  @commands[name.to_s] = {
    description: description,
    options: options,
    handler: block
  }
end

#register_plugin(plugin) ⇒ Boolean Also known as: plugin

Register a plugin

Parameters:

  • plugin (Plugin)

    Plugin to register

Returns:

  • (Boolean)

    True if registered



228
229
230
# File 'lib/discord_rda/bot.rb', line 228

def register_plugin(plugin)
  @plugins.register(plugin, self)
end

#remove_all_reactions(channel_id, message_id) ⇒ void

This method returns an undefined value.

Remove all reactions from a message

Parameters:

  • channel_id (String, Snowflake)

    Channel ID

  • message_id (String, Snowflake)

    Message ID



723
724
725
# File 'lib/discord_rda/bot.rb', line 723

def remove_all_reactions(channel_id, message_id)
  @rest.delete("/channels/#{channel_id}/messages/#{message_id}/reactions")
end

#remove_group_dm_recipient(channel_id, user_id) ⇒ void

This method returns an undefined value.

Remove a recipient from a group DM

Parameters:

  • channel_id (String, Snowflake)

    Group DM channel ID

  • user_id (String, Snowflake)

    User ID



426
427
428
# File 'lib/discord_rda/bot.rb', line 426

def remove_group_dm_recipient(channel_id, user_id)
  @rest.delete("/channels/#{channel_id}/recipients/#{user_id}")
end

#remove_guild_ban(guild_id, user_id, reason: nil) ⇒ void

This method returns an undefined value.

Remove guild ban (unban)

Parameters:

  • guild_id (String, Snowflake)

    Guild ID

  • user_id (String, Snowflake)

    User ID

  • reason (String) (defaults to: nil)

    Audit log reason



942
943
944
945
# File 'lib/discord_rda/bot.rb', line 942

def remove_guild_ban(guild_id, user_id, reason: nil)
  headers = reason ? { 'X-Audit-Log-Reason' => CGI.escape(reason) } : {}
  @rest.delete("/guilds/#{guild_id}/bans/#{user_id}", headers: headers)
end

#remove_guild_member(guild_id, user_id, reason: nil) ⇒ void

This method returns an undefined value.

Remove guild member (kick)

Parameters:

  • guild_id (String, Snowflake)

    Guild ID

  • user_id (String, Snowflake)

    User ID

  • reason (String) (defaults to: nil)

    Audit log reason



837
838
839
840
# File 'lib/discord_rda/bot.rb', line 837

def remove_guild_member(guild_id, user_id, reason: nil)
  headers = reason ? { 'X-Audit-Log-Reason' => CGI.escape(reason) } : {}
  @rest.delete("/guilds/#{guild_id}/members/#{user_id}", headers: headers)
end

#remove_guild_member_role(guild_id, user_id, role_id, reason: nil) ⇒ void

This method returns an undefined value.

Remove role from guild member

Parameters:

  • guild_id (String, Snowflake)

    Guild ID

  • user_id (String, Snowflake)

    User ID

  • role_id (String, Snowflake)

    Role ID

  • reason (String) (defaults to: nil)

    Audit log reason



827
828
829
830
# File 'lib/discord_rda/bot.rb', line 827

def remove_guild_member_role(guild_id, user_id, role_id, reason: nil)
  headers = reason ? { 'X-Audit-Log-Reason' => CGI.escape(reason) } : {}
  @rest.delete("/guilds/#{guild_id}/members/#{user_id}/roles/#{role_id}", headers: headers)
end

#remove_reaction(channel_id, message_id, emoji, user_id: '@me') ⇒ void

This method returns an undefined value.

Remove a reaction from a message

Parameters:

  • channel_id (String, Snowflake)

    Channel ID

  • message_id (String, Snowflake)

    Message ID

  • emoji (String, Emoji)

    Emoji

  • user_id (String, Snowflake) (defaults to: '@me')

    User ID (default: @me)



699
700
701
702
# File 'lib/discord_rda/bot.rb', line 699

def remove_reaction(channel_id, message_id, emoji, user_id: '@me')
  emoji_str = emoji.respond_to?(:id) ? "#{emoji.name}:#{emoji.id}" : emoji.to_s
  @rest.delete("/channels/#{channel_id}/messages/#{message_id}/reactions/#{CGI.escape(emoji_str)}/#{user_id}")
end

#remove_thread_member(thread_id, user_id) ⇒ void

This method returns an undefined value.

Remove a user from a thread

Parameters:

  • thread_id (String, Snowflake)

    Thread channel ID

  • user_id (String, Snowflake)

    User ID



582
583
584
# File 'lib/discord_rda/bot.rb', line 582

def remove_thread_member(thread_id, user_id)
  @rest.delete("/channels/#{thread_id}/thread-members/#{user_id}")
end

#reshard_to(new_shard_count) ⇒ void

This method returns an undefined value.

Trigger zero-downtime resharding

Parameters:

  • new_shard_count (Integer)

    New shard count



653
654
655
656
# File 'lib/discord_rda/bot.rb', line 653

def reshard_to(new_shard_count)
  @logger.info('Triggering resharding', new_count: new_shard_count)
  @reshard_manager.reshard_to(new_shard_count)
end

#restart!(command: nil, env: {}) ⇒ Object



109
110
111
# File 'lib/discord_rda/bot.rb', line 109

def restart!(command: nil, env: {})
  @restart_manager.restart!(command: command, env: env)
end

#run(async: false) ⇒ void

This method returns an undefined value.

Run the bot

Parameters:

  • async (Boolean) (defaults to: false)

    Run asynchronously



243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
# File 'lib/discord_rda/bot.rb', line 243

def run(async: false)
  @running = true
  install_signal_handlers

  @logger.info('Starting DiscordRDA bot', version: VERSION, shards: @config.shards.length)

  # Start REST client
  @rest.start

  # Calculate shard count if auto
  shard_count = if @config.shards == [:auto]
                   @shard_manager.calculate_shard_count(:auto, @rest)
                 else
                   @config.shards.length
                 end

  @shard_manager.instance_variable_set(:@shard_count, shard_count)

  # Start shards
  if async
    Async { start_shards }
  else
    start_shards
  end
end

#search_guild_members(guild_id, query, limit: 25) ⇒ Array<Member>

Search guild members by query

Parameters:

  • guild_id (String, Snowflake)

    Guild ID

  • query (String)

    Search query (username/nickname prefix)

  • limit (Integer) (defaults to: 25)

    Max results (1-100, default 25)

Returns:

  • (Array<Member>)

    Matching members



757
758
759
760
761
# File 'lib/discord_rda/bot.rb', line 757

def search_guild_members(guild_id, query, limit: 25)
  params = { query: query, limit: limit }
  data = @rest.get("/guilds/#{guild_id}/members/search", params: params)
  data.map { |m| Member.new(m.merge('guild_id' => guild_id.to_s)) }
end

#send_message(channel_id, content = nil, **options) ⇒ Message

Send a message to a channel

Parameters:

  • channel_id (String, Snowflake)

    Channel ID

  • content (String) (defaults to: nil)

    Message content

  • options (Hash)

    Message options

Returns:



368
369
370
371
372
# File 'lib/discord_rda/bot.rb', line 368

def send_message(channel_id, content = nil, **options)
  payload = { content: content }.merge(options).compact
  data = @rest.post("/channels/#{channel_id}/messages", body: payload)
  Message.new(data)
end

#send_soundboard_sound(channel_id, sound_id:, source_guild_id: nil) ⇒ void

This method returns an undefined value.

Send a soundboard sound in a voice-connected channel

Parameters:

  • channel_id (String, Snowflake)

    Voice channel ID

  • sound_id (String, Snowflake)

    Sound ID

  • source_guild_id (String, Snowflake, nil) (defaults to: nil)

    Source guild for default/shared sounds



1647
1648
1649
1650
# File 'lib/discord_rda/bot.rb', line 1647

def send_soundboard_sound(channel_id, sound_id:, source_guild_id: nil)
  payload = { sound_id: sound_id.to_s, source_guild_id: source_guild_id&.to_s }.compact
  @rest.post("/channels/#{channel_id}/send-soundboard-sound", body: payload)
end

#skus(application_id: nil) ⇒ Array<Hash>

Get SKUs for the current application

Parameters:

  • application_id (String, Snowflake, nil) (defaults to: nil)

    Application ID

Returns:

  • (Array<Hash>)

    SKU payloads



1545
1546
1547
1548
# File 'lib/discord_rda/bot.rb', line 1545

def skus(application_id: nil)
  app_id = application_id || application_id_for_rest
  @rest.get("/applications/#{app_id}/skus")
end

#slash(name, description, **options) {|CommandBuilder| ... } ⇒ ApplicationCommand

Register a slash command (global or guild-specific)

Parameters:

  • name (String)

    Command name

  • description (String)

    Command description

  • options (Hash)

    Command options

Options Hash (**options):

  • :guild_id (String)

    Guild-specific command (nil for global)

  • :options (Array<Hash>)

    Command options

  • :default_member_permissions (Integer)

    Default required permissions

  • :dm_permission (Boolean)

    Whether works in DMs

Yields:

Returns:



129
130
131
132
133
134
135
136
137
138
# File 'lib/discord_rda/bot.rb', line 129

def slash(name, description, **options, &block)
  builder = CommandBuilder.new(name, description, type: options[:type] || 1)
  builder.dm_allowed(options[:dm_permission]) if options.key?(:dm_permission)
  builder.default_permissions(options[:default_member_permissions]) if options[:default_member_permissions]
  builder.nsfw(options[:nsfw]) if options[:nsfw]

  block.call(builder) if block

  register_application_command(builder.build, name: name, guild_id: options[:guild_id])
end

#stage_instance(channel_id) ⇒ Hash?

Get a stage instance

Parameters:

  • channel_id (String, Snowflake)

    Stage channel ID

Returns:

  • (Hash, nil)

    Stage instance payload



1373
1374
1375
1376
1377
# File 'lib/discord_rda/bot.rb', line 1373

def stage_instance(channel_id)
  @rest.get("/stage-instances/#{channel_id}")
rescue RestClient::NotFoundError
  nil
end

#start_thread(channel_id, name:, type: nil, auto_archive_duration: nil, invitable: nil, rate_limit_per_user: nil) ⇒ Channel

Start a thread without a seed message

Parameters:

  • channel_id (String, Snowflake)

    Parent channel ID

  • name (String)

    Thread name

  • type (Integer, nil) (defaults to: nil)

    Thread type

  • auto_archive_duration (Integer, nil) (defaults to: nil)

    Auto archive duration in minutes

  • invitable (Boolean, nil) (defaults to: nil)

    Whether non-moderators can add users

  • rate_limit_per_user (Integer, nil) (defaults to: nil)

    Thread slowmode

Returns:



544
545
546
547
548
549
550
551
552
553
554
# File 'lib/discord_rda/bot.rb', line 544

def start_thread(channel_id, name:, type: nil, auto_archive_duration: nil, invitable: nil, rate_limit_per_user: nil)
  payload = {
    name: name,
    type: type,
    auto_archive_duration: auto_archive_duration,
    invitable: invitable,
    rate_limit_per_user: rate_limit_per_user
  }.compact
  data = @rest.post("/channels/#{channel_id}/threads", body: payload)
  Channel.new(data)
end

#start_thread_from_message(channel_id, message_id, name:, auto_archive_duration: nil, rate_limit_per_user: nil) ⇒ Channel

Start a thread from an existing message

Parameters:

  • channel_id (String, Snowflake)

    Parent channel ID

  • message_id (String, Snowflake)

    Message ID

  • name (String)

    Thread name

  • auto_archive_duration (Integer, nil) (defaults to: nil)

    Auto archive duration in minutes

  • rate_limit_per_user (Integer, nil) (defaults to: nil)

    Thread slowmode

Returns:



526
527
528
529
530
531
532
533
534
# File 'lib/discord_rda/bot.rb', line 526

def start_thread_from_message(channel_id, message_id, name:, auto_archive_duration: nil, rate_limit_per_user: nil)
  payload = {
    name: name,
    auto_archive_duration: auto_archive_duration,
    rate_limit_per_user: rate_limit_per_user
  }.compact
  data = @rest.post("/channels/#{channel_id}/messages/#{message_id}/threads", body: payload)
  Channel.new(data)
end

#statusHash

Get bot status

Returns:

  • (Hash)

    Status information



290
291
292
293
294
295
296
297
# File 'lib/discord_rda/bot.rb', line 290

def status
  {
    running: @running,
    shards: @shard_manager.status,
    cache: @cache.stats,
    plugins: @plugins.stats
  }
end

#sticker(sticker_id) ⇒ Sticker?

Get a standard sticker

Parameters:

  • sticker_id (String, Snowflake)

    Sticker ID

Returns:



1418
1419
1420
1421
1422
1423
# File 'lib/discord_rda/bot.rb', line 1418

def sticker(sticker_id)
  data = @rest.get("/stickers/#{sticker_id}")
  Sticker.new(data)
rescue RestClient::NotFoundError
  nil
end

#sticker_packsHash

List available premium sticker packs

Returns:

  • (Hash)

    Sticker pack payload



1427
1428
1429
# File 'lib/discord_rda/bot.rb', line 1427

def sticker_packs
  @rest.get('/sticker-packs')
end

#stopvoid

This method returns an undefined value.

Stop the bot



271
272
273
274
275
276
# File 'lib/discord_rda/bot.rb', line 271

def stop
  @logger.info('Stopping bot')
  @running = false
  @shard_manager.stop
  @rest.stop
end

#sync_guild_template(guild_id, code) ⇒ Hash

Sync a guild template

Parameters:

  • guild_id (String, Snowflake)

    Guild ID

  • code (String)

    Template code

Returns:

  • (Hash)

    Template payload



1451
1452
1453
# File 'lib/discord_rda/bot.rb', line 1451

def sync_guild_template(guild_id, code)
  @rest.put("/guilds/#{guild_id}/templates/#{code}")
end

#thread_member(thread_id, user_id, with_member: false) ⇒ Hash?

Get a specific thread member

Parameters:

  • thread_id (String, Snowflake)

    Thread channel ID

  • user_id (String, Snowflake)

    User ID

  • with_member (Boolean) (defaults to: false)

    Include member object when available

Returns:

  • (Hash, nil)

    Thread member payload



591
592
593
594
595
# File 'lib/discord_rda/bot.rb', line 591

def thread_member(thread_id, user_id, with_member: false)
  @rest.get("/channels/#{thread_id}/thread-members/#{user_id}", params: { with_member: with_member })
rescue RestClient::NotFoundError
  nil
end

#thread_members(thread_id, with_member: false, after: nil, limit: nil) ⇒ Array<Hash>

List members in a thread

Parameters:

  • thread_id (String, Snowflake)

    Thread channel ID

  • with_member (Boolean) (defaults to: false)

    Include member objects when available

  • after (String, Snowflake, nil) (defaults to: nil)

    Cursor

  • limit (Integer, nil) (defaults to: nil)

    Max results

Returns:

  • (Array<Hash>)

    Thread member payloads



603
604
605
606
607
608
# File 'lib/discord_rda/bot.rb', line 603

def thread_members(thread_id, with_member: false, after: nil, limit: nil)
  params = { with_member: with_member }
  params[:after] = after.to_s if after
  params[:limit] = limit if limit
  @rest.get("/channels/#{thread_id}/thread-members", params: params)
end

#trigger_typing(channel_id) ⇒ void

This method returns an undefined value.

Trigger typing indicator for a channel

Parameters:

  • channel_id (String, Snowflake)

    Channel ID



433
434
435
# File 'lib/discord_rda/bot.rb', line 433

def trigger_typing(channel_id)
  @rest.post("/channels/#{channel_id}/typing")
end

#unpin_message(channel_id, message_id, reason: nil) ⇒ void

This method returns an undefined value.

Unpin a channel message

Parameters:

  • channel_id (String, Snowflake)

    Channel ID

  • message_id (String, Snowflake)

    Message ID

  • reason (String, nil) (defaults to: nil)

    Audit log reason



459
460
461
# File 'lib/discord_rda/bot.rb', line 459

def unpin_message(channel_id, message_id, reason: nil)
  @rest.delete("/channels/#{channel_id}/pins/#{message_id}", headers: audit_log_headers(reason))
end

#update_application_role_connection(application_id, platform_name: nil, platform_username: nil, metadata: {}) ⇒ Hash?

Update application role connection metadata for the current user

Parameters:

  • application_id (String, Snowflake)

    Application ID

  • platform_name (String, nil) (defaults to: nil)

    Platform name

  • platform_username (String, nil) (defaults to: nil)

    Platform username

  • metadata (Hash) (defaults to: {})

    Metadata payload

Returns:

  • (Hash, nil)

    Updated role connection payload



1753
1754
1755
1756
1757
1758
1759
1760
# File 'lib/discord_rda/bot.rb', line 1753

def update_application_role_connection(application_id, platform_name: nil, platform_username: nil, metadata: {})
  User.update_application_role_connection(
    application_id,
    platform_name: platform_name,
    platform_username: platform_username,
    metadata: 
  )
end

#update_presence(status: 'online', activity: nil) ⇒ void

This method returns an undefined value.

Update bot presence

Parameters:

  • status (String) (defaults to: 'online')

    online, idle, dnd, invisible

  • activity (Hash) (defaults to: nil)

    Activity data



282
283
284
285
286
# File 'lib/discord_rda/bot.rb', line 282

def update_presence(status: 'online', activity: nil)
  @shard_manager.shards.each do |shard|
    shard.update_presence(status: status, activity: activity)
  end
end

#use(middleware) ⇒ void

This method returns an undefined value.

Use middleware

Parameters:



236
237
238
# File 'lib/discord_rda/bot.rb', line 236

def use(middleware)
  @event_bus.use(middleware)
end

#wait_for(event, timeout: nil) { ... } ⇒ Event?

Wait for an event

Parameters:

  • event (String, Symbol)

    Event type

  • timeout (Float) (defaults to: nil)

    Timeout in seconds

Yields:

  • Block to match event

Returns:

  • (Event, nil)

    Event or nil if timeout



206
207
208
# File 'lib/discord_rda/bot.rb', line 206

def wait_for(event, timeout: nil, &block)
  @event_bus.wait_for(event, timeout: timeout, &block)
end

#webhook(webhook_id) ⇒ Webhook?

Get a webhook by ID

Parameters:

  • webhook_id (String, Snowflake)

    Webhook ID

Returns:

  • (Webhook, nil)

    Webhook payload



1003
1004
1005
1006
1007
# File 'lib/discord_rda/bot.rb', line 1003

def webhook(webhook_id)
  Webhook.new(@rest.get("/webhooks/#{webhook_id}"))
rescue RestClient::NotFoundError
  nil
end

#webhook_message(webhook_id, token, message_id, thread_id: nil) ⇒ Message?

Get a webhook message

Parameters:

  • webhook_id (String, Snowflake)

    Webhook ID

  • token (String)

    Webhook token

  • message_id (String, Snowflake)

    Message ID

  • thread_id (String, Snowflake, nil) (defaults to: nil)

    Thread channel ID

Returns:

  • (Message, nil)

    Webhook message



1065
1066
1067
1068
1069
1070
1071
1072
# File 'lib/discord_rda/bot.rb', line 1065

def webhook_message(webhook_id, token, message_id, thread_id: nil)
  params = {}
  params[:thread_id] = thread_id.to_s if thread_id
  data = @rest.get("/webhooks/#{webhook_id}/#{token}/messages/#{message_id}", params: params)
  Message.new(data)
rescue RestClient::NotFoundError
  nil
end

#webhook_with_token(webhook_id, token) ⇒ Webhook?

Get a webhook by ID and token

Parameters:

  • webhook_id (String, Snowflake)

    Webhook ID

  • token (String)

    Webhook token

Returns:

  • (Webhook, nil)

    Webhook payload



1013
1014
1015
1016
1017
# File 'lib/discord_rda/bot.rb', line 1013

def webhook_with_token(webhook_id, token)
  Webhook.new(@rest.get("/webhooks/#{webhook_id}/#{token}"))
rescue RestClient::NotFoundError
  nil
end