rubycord 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. checksums.yaml +7 -0
  2. data/lib/rubycord/allowed_mentions.rb +34 -0
  3. data/lib/rubycord/api/application.rb +200 -0
  4. data/lib/rubycord/api/channel.rb +597 -0
  5. data/lib/rubycord/api/interaction.rb +52 -0
  6. data/lib/rubycord/api/invite.rb +42 -0
  7. data/lib/rubycord/api/server.rb +557 -0
  8. data/lib/rubycord/api/user.rb +153 -0
  9. data/lib/rubycord/api/webhook.rb +138 -0
  10. data/lib/rubycord/api.rb +356 -0
  11. data/lib/rubycord/await.rb +49 -0
  12. data/lib/rubycord/bot.rb +1757 -0
  13. data/lib/rubycord/cache.rb +259 -0
  14. data/lib/rubycord/colour_rgb.rb +41 -0
  15. data/lib/rubycord/commands/command_bot.rb +519 -0
  16. data/lib/rubycord/commands/container.rb +110 -0
  17. data/lib/rubycord/commands/events.rb +9 -0
  18. data/lib/rubycord/commands/parser.rb +325 -0
  19. data/lib/rubycord/commands/rate_limiter.rb +142 -0
  20. data/lib/rubycord/container.rb +753 -0
  21. data/lib/rubycord/data/activity.rb +269 -0
  22. data/lib/rubycord/data/application.rb +48 -0
  23. data/lib/rubycord/data/attachment.rb +109 -0
  24. data/lib/rubycord/data/audit_logs.rb +343 -0
  25. data/lib/rubycord/data/channel.rb +996 -0
  26. data/lib/rubycord/data/component.rb +227 -0
  27. data/lib/rubycord/data/embed.rb +249 -0
  28. data/lib/rubycord/data/emoji.rb +80 -0
  29. data/lib/rubycord/data/integration.rb +120 -0
  30. data/lib/rubycord/data/interaction.rb +798 -0
  31. data/lib/rubycord/data/invite.rb +135 -0
  32. data/lib/rubycord/data/member.rb +370 -0
  33. data/lib/rubycord/data/message.rb +412 -0
  34. data/lib/rubycord/data/overwrite.rb +106 -0
  35. data/lib/rubycord/data/profile.rb +89 -0
  36. data/lib/rubycord/data/reaction.rb +31 -0
  37. data/lib/rubycord/data/recipient.rb +32 -0
  38. data/lib/rubycord/data/role.rb +246 -0
  39. data/lib/rubycord/data/server.rb +1002 -0
  40. data/lib/rubycord/data/user.rb +261 -0
  41. data/lib/rubycord/data/voice_region.rb +43 -0
  42. data/lib/rubycord/data/voice_state.rb +39 -0
  43. data/lib/rubycord/data/webhook.rb +232 -0
  44. data/lib/rubycord/data.rb +40 -0
  45. data/lib/rubycord/errors.rb +737 -0
  46. data/lib/rubycord/events/await.rb +46 -0
  47. data/lib/rubycord/events/bans.rb +58 -0
  48. data/lib/rubycord/events/channels.rb +186 -0
  49. data/lib/rubycord/events/generic.rb +126 -0
  50. data/lib/rubycord/events/guilds.rb +191 -0
  51. data/lib/rubycord/events/interactions.rb +480 -0
  52. data/lib/rubycord/events/invites.rb +123 -0
  53. data/lib/rubycord/events/lifetime.rb +29 -0
  54. data/lib/rubycord/events/members.rb +91 -0
  55. data/lib/rubycord/events/message.rb +337 -0
  56. data/lib/rubycord/events/presence.rb +127 -0
  57. data/lib/rubycord/events/raw.rb +45 -0
  58. data/lib/rubycord/events/reactions.rb +156 -0
  59. data/lib/rubycord/events/roles.rb +86 -0
  60. data/lib/rubycord/events/threads.rb +94 -0
  61. data/lib/rubycord/events/typing.rb +70 -0
  62. data/lib/rubycord/events/voice_server_update.rb +45 -0
  63. data/lib/rubycord/events/voice_state_update.rb +103 -0
  64. data/lib/rubycord/events/webhooks.rb +62 -0
  65. data/lib/rubycord/gateway.rb +867 -0
  66. data/lib/rubycord/id_object.rb +37 -0
  67. data/lib/rubycord/light/data.rb +60 -0
  68. data/lib/rubycord/light/integrations.rb +71 -0
  69. data/lib/rubycord/light/light_bot.rb +56 -0
  70. data/lib/rubycord/light.rb +6 -0
  71. data/lib/rubycord/logger.rb +118 -0
  72. data/lib/rubycord/paginator.rb +55 -0
  73. data/lib/rubycord/permissions.rb +251 -0
  74. data/lib/rubycord/version.rb +5 -0
  75. data/lib/rubycord/voice/encoder.rb +113 -0
  76. data/lib/rubycord/voice/network.rb +366 -0
  77. data/lib/rubycord/voice/sodium.rb +96 -0
  78. data/lib/rubycord/voice/voice_bot.rb +408 -0
  79. data/lib/rubycord/webhooks/builder.rb +100 -0
  80. data/lib/rubycord/webhooks/client.rb +132 -0
  81. data/lib/rubycord/webhooks/embeds.rb +248 -0
  82. data/lib/rubycord/webhooks/modal.rb +78 -0
  83. data/lib/rubycord/webhooks/version.rb +7 -0
  84. data/lib/rubycord/webhooks/view.rb +192 -0
  85. data/lib/rubycord/webhooks.rb +12 -0
  86. data/lib/rubycord/websocket.rb +70 -0
  87. data/lib/rubycord.rb +140 -0
  88. metadata +231 -0
@@ -0,0 +1,261 @@
1
+ module Rubycord
2
+ # Mixin for the attributes users should have
3
+ module UserAttributes
4
+ # Types of user's account flags mapped to their API value.
5
+ FLAGS = {
6
+ staff: 1 << 0,
7
+ partner: 1 << 1,
8
+ hypesquad: 1 << 2,
9
+ bug_hunter_level_1: 1 << 3,
10
+ hypesquad_online_house_1: 1 << 6,
11
+ hypesquad_online_house_2: 1 << 7,
12
+ hypesquad_online_house_3: 1 << 8,
13
+ premium_early_supporter: 1 << 9,
14
+ team_pseudo_user: 1 << 10,
15
+ bug_hunter_level_2: 1 << 14,
16
+ verified_bot: 1 << 16,
17
+ verified_developer: 1 << 17,
18
+ certified_moderator: 1 << 18,
19
+ bot_http_interactions: 1 << 19,
20
+ active_developer: 1 << 22
21
+ }.freeze
22
+
23
+ # @return [String] this user's username
24
+ attr_reader :username
25
+ alias_method :name, :username
26
+
27
+ # @return [String, nil] this user's global name
28
+ attr_reader :global_name
29
+
30
+ # @return [String] this user's discriminator which is used internally to identify users with identical usernames.
31
+ attr_reader :discriminator
32
+ alias_method :discrim, :discriminator
33
+ alias_method :tag, :discriminator
34
+ alias_method :discord_tag, :discriminator
35
+
36
+ # @return [true, false] whether this user is a Discord bot account
37
+ attr_reader :bot_account
38
+ alias_method :bot_account?, :bot_account
39
+
40
+ # @return [true, false] whether this is fake user for a webhook message
41
+ attr_reader :webhook_account
42
+ alias_method :webhook_account?, :webhook_account
43
+ alias_method :webhook?, :webhook_account
44
+
45
+ # @return [String] the ID of this user's current avatar, can be used to generate an avatar URL.
46
+ # @see #avatar_url
47
+ attr_accessor :avatar_id
48
+
49
+ # Utility function to get Discord's display name of a user not in server
50
+ # @return [String] the name the user displays as (global_name if they have one, username otherwise)
51
+ def display_name
52
+ global_name || username
53
+ end
54
+
55
+ # Utility function to mention users in messages
56
+ # @return [String] the mention code in the form of <@id>
57
+ def mention
58
+ "<@#{@id}>"
59
+ end
60
+
61
+ # Utility function to get Discord's distinct representation of a user, i.e. username + discriminator
62
+ # @return [String] distinct representation of user
63
+ # TODO: Maybe change this method again after discriminator removal ?
64
+ def distinct
65
+ if @discriminator && @discriminator != "0"
66
+ "#{@username}##{@discriminator}"
67
+ else
68
+ @username.to_s
69
+ end
70
+ end
71
+
72
+ # Utility function to get a user's avatar URL.
73
+ # @param format [String, nil] If `nil`, the URL will default to `webp` for static avatars, and will detect if the user has a `gif` avatar. You can otherwise specify one of `webp`, `jpg`, `png`, or `gif` to override this. Will always be PNG for default avatars.
74
+ # @return [String] the URL to the avatar image.
75
+ # TODO: Maybe change this method again after discriminator removal ?
76
+ def avatar_url(format = nil)
77
+ unless @avatar_id
78
+ return API::User.default_avatar(@discriminator, legacy: true) if @discriminator && @discriminator != "0"
79
+
80
+ return API::User.default_avatar(@id)
81
+ end
82
+
83
+ API::User.avatar_url(@id, @avatar_id, format)
84
+ end
85
+
86
+ # @return [Integer] the public flags on a user's account
87
+ attr_reader :public_flags
88
+
89
+ FLAGS.each do |name, value|
90
+ define_method(:"#{name}?") do
91
+ (@public_flags & value).positive?
92
+ end
93
+ end
94
+ end
95
+
96
+ # User on Discord, including internal data like discriminators
97
+ class User
98
+ include IDObject
99
+ include UserAttributes
100
+
101
+ # @return [Symbol] the current online status of the user (`:online`, `:offline` or `:idle`)
102
+ attr_reader :status
103
+
104
+ # @return [ActivitySet] the activities of the user
105
+ attr_reader :activities
106
+
107
+ # @return [Hash<Symbol, Symbol>] the current online status (`:online`, `:idle` or `:dnd`) of the user
108
+ # on various device types (`:desktop`, `:mobile`, or `:web`). The value will be `nil` if the user is offline or invisible.
109
+ attr_reader :client_status
110
+
111
+ # @!visibility private
112
+ def initialize(data, bot)
113
+ @bot = bot
114
+
115
+ @username = data["username"]
116
+ @global_name = data["global_name"]
117
+ @id = data["id"].to_i
118
+ @discriminator = data["discriminator"]
119
+ @avatar_id = data["avatar"]
120
+ @roles = {}
121
+ @activities = Rubycord::ActivitySet.new
122
+ @public_flags = data["public_flags"] || 0
123
+
124
+ @bot_account = false
125
+ @bot_account = true if data["bot"]
126
+
127
+ @webhook_account = false
128
+ @webhook_account = true if data["_webhook"]
129
+
130
+ @status = :offline
131
+ @client_status = process_client_status(data["client_status"])
132
+ end
133
+
134
+ # Get a user's PM channel or send them a PM
135
+ # @overload pm
136
+ # Creates a private message channel for this user or returns an existing one if it already exists
137
+ # @return [Channel] the PM channel to this user.
138
+ # @overload pm(content)
139
+ # Sends a private to this user.
140
+ # @param content [String] The content to send.
141
+ # @return [Message] the message sent to this user.
142
+ def pm(content = nil)
143
+ if content
144
+ # Recursively call pm to get the channel, then send a message to it
145
+ channel = pm
146
+ channel.send_message(content)
147
+ else
148
+ # If no message was specified, return the PM channel
149
+ @bot.pm_channel(@id)
150
+ end
151
+ end
152
+
153
+ alias_method :dm, :pm
154
+
155
+ # Send the user a file.
156
+ # @param file [File] The file to send to the user
157
+ # @param caption [String] The caption of the file being sent
158
+ # @param filename [String] Overrides the filename of the uploaded file
159
+ # @param spoiler [true, false] Whether or not this file should appear as a spoiler.
160
+ # @return [Message] the message sent to this user.
161
+ # @example Send a file from disk
162
+ # user.send_file(File.open('rubytaco.png', 'r'))
163
+ def send_file(file, caption = nil, filename: nil, spoiler: nil)
164
+ pm.send_file(file, caption: caption, filename: filename, spoiler: spoiler)
165
+ end
166
+
167
+ # Set the user's username
168
+ # @note for internal use only
169
+ # @!visibility private
170
+ def update_username(username)
171
+ @username = username
172
+ end
173
+
174
+ # Set the user's global_name
175
+ # @note For internal use only.
176
+ # @!visibility private
177
+ def update_global_name(global_name)
178
+ @global_name = global_name
179
+ end
180
+
181
+ # Set the user's presence data
182
+ # @note for internal use only
183
+ # @!visibility private
184
+ def update_presence(data)
185
+ @status = data["status"].to_sym
186
+ @client_status = process_client_status(data["client_status"])
187
+
188
+ @activities = Rubycord::ActivitySet.new(data["activities"].map { |act| Activity.new(act, @bot) })
189
+ end
190
+
191
+ # Add an await for a message from this user. Specifically, this adds a global await for a MessageEvent with this
192
+ # user's ID as a :from attribute.
193
+ # @see Bot#add_await
194
+ def await(key, attributes = {}, &)
195
+ @bot.add_await(key, Rubycord::Events::MessageEvent, {from: @id}.merge(attributes), &)
196
+ end
197
+
198
+ # Add a blocking await for a message from this user. Specifically, this adds a global await for a MessageEvent with this
199
+ # user's ID as a :from attribute.
200
+ # @see Bot#add_await!
201
+ def await!(attributes = {}, &)
202
+ @bot.add_await!(Rubycord::Events::MessageEvent, {from: @id}.merge(attributes), &)
203
+ end
204
+
205
+ # Gets the member this user is on a server
206
+ # @param server [Server] The server to get the member for
207
+ # @return [Member] this user as a member on a particular server
208
+ def on(server)
209
+ id = server.resolve_id
210
+ @bot.server(id).member(@id)
211
+ end
212
+
213
+ # Is the user the bot?
214
+ # @return [true, false] whether this user is the bot
215
+ def current_bot?
216
+ @bot.profile.id == @id
217
+ end
218
+
219
+ # @!visibility private
220
+ def process_client_status(client_status)
221
+ (client_status || {}).to_h { |k, v| [k.to_sym, v.to_sym] }
222
+ end
223
+
224
+ # @!method offline?
225
+ # @return [true, false] whether this user is offline.
226
+ # @!method idle?
227
+ # @return [true, false] whether this user is idle.
228
+ # @!method online?
229
+ # @return [true, false] whether this user is online.
230
+ # @!method dnd?
231
+ # @return [true, false] whether this user is set to do not disturb.
232
+ %i[offline idle online dnd].each do |e|
233
+ define_method(:"#{e}?") do
234
+ @status.to_sym == e
235
+ end
236
+ end
237
+
238
+ # @return [String, nil] the game the user is currently playing, or `nil` if nothing is being played.
239
+ # @deprecated Please use {ActivitySet#games} for information about the user's game activity
240
+ def game
241
+ @activities.games.first&.name
242
+ end
243
+
244
+ # @return [Integer] returns 1 for twitch streams, or 0 for no stream.
245
+ # @deprecated Please use {ActivitySet#streaming} for information about the user's stream activity
246
+ def stream_type
247
+ @activities.streaming ? 1 : 0
248
+ end
249
+
250
+ # @return [String, nil] the URL to the stream, if the user is currently streaming something
251
+ # @deprecated Please use {ActivitySet#streaming} for information about the user's stream activity
252
+ def stream_url
253
+ @activities.streaming.first&.url
254
+ end
255
+
256
+ # The inspect method is overwritten to give more useful output
257
+ def inspect
258
+ "<User username=#{@username} id=#{@id} discriminator=#{@discriminator}>"
259
+ end
260
+ end
261
+ end
@@ -0,0 +1,43 @@
1
+ module Rubycord
2
+ # Voice regions are the locations of servers that handle voice communication in Discord
3
+ class VoiceRegion
4
+ # @return [String] unique ID for the region
5
+ attr_reader :id
6
+ alias_method :to_s, :id
7
+
8
+ # @return [String] name of the region
9
+ attr_reader :name
10
+
11
+ # @return [String] an example hostname for the region
12
+ attr_reader :sample_hostname
13
+
14
+ # @return [Integer] an example port for the region
15
+ attr_reader :sample_port
16
+
17
+ # @return [true, false] if this is a VIP-only server
18
+ attr_reader :vip
19
+
20
+ # @return [true, false] if this voice server is the closest to the client
21
+ attr_reader :optimal
22
+
23
+ # @return [true, false] whether this is a deprecated voice region (avoid switching to these)
24
+ attr_reader :deprecated
25
+
26
+ # @return [true, false] whether this is a custom voice region (used for events/etc)
27
+ attr_reader :custom
28
+
29
+ def initialize(data)
30
+ @id = data["id"]
31
+
32
+ @name = data["name"]
33
+
34
+ @sample_hostname = data["sample_hostname"]
35
+ @sample_port = data["sample_port"]
36
+
37
+ @vip = data["vip"]
38
+ @optimal = data["optimal"]
39
+ @deprecated = data["deprecated"]
40
+ @custom = data["custom"]
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,39 @@
1
+ module Rubycord
2
+ # A voice state represents the state of a member's connection to a voice channel. It includes data like the voice
3
+ # channel the member is connected to and mute/deaf flags.
4
+ class VoiceState
5
+ # @return [Integer] the ID of the user whose voice state is represented by this object.
6
+ attr_reader :user_id
7
+
8
+ # @return [true, false] whether this voice state's member is muted server-wide.
9
+ attr_reader :mute
10
+
11
+ # @return [true, false] whether this voice state's member is deafened server-wide.
12
+ attr_reader :deaf
13
+
14
+ # @return [true, false] whether this voice state's member has muted themselves.
15
+ attr_reader :self_mute
16
+
17
+ # @return [true, false] whether this voice state's member has deafened themselves.
18
+ attr_reader :self_deaf
19
+
20
+ # @return [Channel] the voice channel this voice state's member is in.
21
+ attr_reader :voice_channel
22
+
23
+ # @!visibility private
24
+ def initialize(user_id)
25
+ @user_id = user_id
26
+ end
27
+
28
+ # Update this voice state with new data from Discord
29
+ # @note For internal use only.
30
+ # @!visibility private
31
+ def update(channel, mute, deaf, self_mute, self_deaf)
32
+ @voice_channel = channel
33
+ @mute = mute
34
+ @deaf = deaf
35
+ @self_mute = self_mute
36
+ @self_deaf = self_deaf
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,232 @@
1
+ require "rubycord/webhooks/builder"
2
+ require "rubycord/webhooks/view"
3
+
4
+ module Rubycord
5
+ # A webhook on a server channel
6
+ class Webhook
7
+ include IDObject
8
+
9
+ # @return [String] the webhook name.
10
+ attr_reader :name
11
+
12
+ # @return [Channel] the channel that the webhook is currently connected to.
13
+ attr_reader :channel
14
+
15
+ # @return [Server] the server that the webhook is currently connected to.
16
+ attr_reader :server
17
+
18
+ # @return [String, nil] the webhook's token, if this is an Incoming Webhook.
19
+ attr_reader :token
20
+
21
+ # @return [String] the webhook's avatar id.
22
+ attr_reader :avatar
23
+
24
+ # @return [Integer] the webhook's type (1: Incoming, 2: Channel Follower)
25
+ attr_reader :type
26
+
27
+ # Gets the user object of the creator of the webhook. May be limited to username, discriminator,
28
+ # ID and avatar if the bot cannot reach the owner
29
+ # @return [Member, User, nil] the user object of the owner or nil if the webhook was requested using the token.
30
+ attr_reader :owner
31
+
32
+ def initialize(data, bot)
33
+ @bot = bot
34
+
35
+ @name = data["name"]
36
+ @id = data["id"].to_i
37
+ @channel = bot.channel(data["channel_id"])
38
+ @server = @channel.server
39
+ @token = data["token"]
40
+ @avatar = data["avatar"]
41
+ @type = data["type"]
42
+
43
+ # Will not exist if the data was requested through a webhook token
44
+ return unless data["user"]
45
+
46
+ @owner = @server.member(data["user"]["id"].to_i)
47
+ return if @owner
48
+
49
+ Rubycord::LOGGER.debug("Member with ID #{data["user"]["id"]} not cached (possibly left the server).")
50
+ @owner = @bot.ensure_user(data["user"])
51
+ end
52
+
53
+ # Sets the webhook's avatar.
54
+ # @param avatar [String, #read] The new avatar, in base64-encoded JPG format.
55
+ def avatar=(avatar)
56
+ update_webhook(avatar: avatarise(avatar))
57
+ end
58
+
59
+ # Deletes the webhook's avatar.
60
+ def delete_avatar
61
+ update_webhook(avatar: nil)
62
+ end
63
+
64
+ # Sets the webhook's channel
65
+ # @param channel [Channel, String, Integer] The channel the webhook should use.
66
+ def channel=(channel)
67
+ update_webhook(channel_id: channel.resolve_id)
68
+ end
69
+
70
+ # Sets the webhook's name.
71
+ # @param name [String] The webhook's new name.
72
+ def name=(name)
73
+ update_webhook(name: name)
74
+ end
75
+
76
+ # Updates the webhook if you need to edit more than 1 attribute.
77
+ # @param data [Hash] the data to update.
78
+ # @option data [String, #read, nil] :avatar The new avatar, in base64-encoded JPG format, or nil to delete the avatar.
79
+ # @option data [Channel, String, Integer] :channel The channel the webhook should use.
80
+ # @option data [String] :name The webhook's new name.
81
+ # @option data [String] :reason The reason for the webhook changes.
82
+ def update(data)
83
+ # Only pass a value for avatar if the key is defined as sending nil will delete the
84
+ data[:avatar] = avatarise(data[:avatar]) if data.key?(:avatar)
85
+ data[:channel_id] = data[:channel]&.resolve_id
86
+ data.delete(:channel)
87
+ update_webhook(data)
88
+ end
89
+
90
+ # Deletes the webhook.
91
+ # @param reason [String] The reason the webhook is being deleted.
92
+ def delete(reason = nil)
93
+ if token?
94
+ API::Webhook.token_delete_webhook(@token, @id, reason)
95
+ else
96
+ API::Webhook.delete_webhook(@bot.token, @id, reason)
97
+ end
98
+ end
99
+
100
+ # Execute a webhook.
101
+ # @param content [String] The content of the message. May be 2000 characters long at most.
102
+ # @param username [String] The username the webhook will display as. If this is not set, the default username set in the webhook's settings.
103
+ # @param avatar_url [String] The URL of an image file to be used as an avatar. If this is not set, the default avatar from the webhook's
104
+ # @param tts [true, false] Whether this message should use TTS or not. By default, it doesn't.
105
+ # @param file [File] File to be sent together with the message. Mutually exclusive with embeds; a webhook message can contain
106
+ # either a file to be sent or embeds.
107
+ # @param embeds [Array<Webhooks::Embed, Hash>] Embeds to attach to this message.
108
+ # @param allowed_mentions [AllowedMentions, Hash] Mentions that are allowed to ping in the `content`.
109
+ # @param wait [true, false] Whether Discord should wait for the message to be successfully received by clients, or
110
+ # whether it should return immediately after sending the message. If `true` a {Message} object will be returned.
111
+ # @yield [builder] Gives the builder to the block to add additional steps, or to do the entire building process.
112
+ # @yieldparam builder [Builder] The builder given as a parameter which is used as the initial step to start from.
113
+ # @example Execute the webhook with kwargs
114
+ # client.execute(
115
+ # content: 'Testing',
116
+ # username: 'rubycord',
117
+ # embeds: [
118
+ # { timestamp: Time.now.iso8601, title: 'testing', image: { url: 'https://i.imgur.com/PcMltU7.jpg' } }
119
+ # ])
120
+ # @example Execute the webhook with an already existing builder
121
+ # builder = Rubycord::Webhooks::Builder.new # ...
122
+ # client.execute(builder)
123
+ # @example Execute the webhook by building a new message
124
+ # client.execute do |builder|
125
+ # builder.content = 'Testing'
126
+ # builder.username = 'rubycord'
127
+ # builder.add_embed do |embed|
128
+ # embed.timestamp = Time.now
129
+ # embed.title = 'Testing'
130
+ # embed.image = Rubycord::Webhooks::EmbedImage.new(url: 'https://i.imgur.com/PcMltU7.jpg')
131
+ # end
132
+ # end
133
+ # @return [Message, nil] If `wait` is `true`, a {Message} will be returned. Otherwise this method will return `nil`.
134
+ # @note This is only available to webhooks with publically exposed tokens. This excludes channel follow webhooks and webhooks retrieved
135
+ # via the audit log.
136
+ def execute(content: nil, username: nil, avatar_url: nil, tts: nil, file: nil, embeds: nil, allowed_mentions: nil, wait: true, builder: nil, components: nil)
137
+ raise Rubycord::Errors::UnauthorizedWebhook unless @token
138
+
139
+ params = {content: content, username: username, avatar_url: avatar_url, tts: tts, file: file, embeds: embeds, allowed_mentions: allowed_mentions}
140
+
141
+ builder ||= Webhooks::Builder.new
142
+ view = Webhooks::View.new
143
+
144
+ yield(builder, view) if block_given?
145
+
146
+ data = builder.to_json_hash.merge(params.compact)
147
+ components ||= view
148
+
149
+ resp = API::Webhook.token_execute_webhook(@token, @id, wait, data[:content], data[:username], data[:avatar_url], data[:tts], data[:file], data[:embeds], data[:allowed_mentions], nil, components.to_a)
150
+
151
+ Message.new(JSON.parse(resp), @bot) if wait
152
+ end
153
+
154
+ # Delete a message created by this webhook.
155
+ # @param message [Message, String, Integer] The ID of the message to delete.
156
+ def delete_message(message)
157
+ raise Rubycord::Errors::UnauthorizedWebhook unless @token
158
+
159
+ API::Webhook.token_delete_message(@token, @id, message.resolve_id)
160
+ end
161
+
162
+ # Edit a message created by this webhook.
163
+ # @param message [Message, String, Integer] The ID of the message to edit.
164
+ # @param content [String] The content of the message. May be 2000 characters long at most.
165
+ # @param embeds [Array<Webhooks::Embed, Hash>] Embeds to be attached to the message.
166
+ # @param allowed_mentions [AllowedMentions, Hash] Mentions that are allowed to ping in the `content`.
167
+ # @param builder [Builder, nil] The builder to start out with, or nil if one should be created anew.
168
+ # @yield [builder] Gives the builder to the block to add additional steps, or to do the entire building process.
169
+ # @yieldparam builder [Webhooks::Builder] The builder given as a parameter which is used as the initial step to start from.
170
+ # @return [Message] The updated message.
171
+ # @param components [View, Array<Hash>] Interaction components to associate with this message.
172
+ # @note When editing `allowed_mentions`, it will update visually in the client but not alert the user with a notification.
173
+ def edit_message(message, content: nil, embeds: nil, allowed_mentions: nil, builder: nil, components: nil)
174
+ raise Rubycord::Errors::UnauthorizedWebhook unless @token
175
+
176
+ params = {content: content, embeds: embeds, allowed_mentions: allowed_mentions}.compact
177
+
178
+ builder ||= Webhooks::Builder.new
179
+ view ||= Webhooks::View.new
180
+
181
+ yield(builder, view) if block_given?
182
+
183
+ data = builder.to_json_hash.merge(params.compact)
184
+ components ||= view
185
+
186
+ resp = API::Webhook.token_edit_message(@token, @id, message.resolve_id, data[:content], data[:embeds], data[:allowed_mentions], components.to_a)
187
+ Message.new(JSON.parse(resp), @bot)
188
+ end
189
+
190
+ # Utility function to get a webhook's avatar URL.
191
+ # @return [String] the URL to the avatar image
192
+ def avatar_url
193
+ return API::User.default_avatar(@id) unless @avatar
194
+
195
+ API::User.avatar_url(@id, @avatar)
196
+ end
197
+
198
+ # The `inspect` method is overwritten to give more useful output.
199
+ def inspect
200
+ "<Webhook name=#{@name} id=#{@id}>"
201
+ end
202
+
203
+ # Utility function to know if the webhook was requested through a webhook token, rather than auth.
204
+ # @return [true, false] whether the webhook was requested by token or not.
205
+ def token?
206
+ @owner.nil?
207
+ end
208
+
209
+ private
210
+
211
+ def avatarise(avatar)
212
+ if avatar.respond_to? :read
213
+ "data:image/jpg;base64,#{Base64.strict_encode64(avatar.read)}"
214
+ else
215
+ avatar
216
+ end
217
+ end
218
+
219
+ def update_internal(data)
220
+ @name = data["name"]
221
+ @avatar_id = data["avatar"]
222
+ @channel = @bot.channel(data["channel_id"])
223
+ end
224
+
225
+ def update_webhook(new_data)
226
+ reason = new_data.delete(:reason)
227
+ data = JSON.parse(token? ? API::Webhook.token_update_webhook(@token, @id, new_data, reason) : API::Webhook.update_webhook(@bot.token, @id, new_data, reason))
228
+ # Only update cache if API call worked
229
+ update_internal(data) if data["name"]
230
+ end
231
+ end
232
+ end
@@ -0,0 +1,40 @@
1
+ require "rubycord/allowed_mentions"
2
+ require "rubycord/permissions"
3
+ require "rubycord/id_object"
4
+ require "rubycord/colour_rgb"
5
+ require "rubycord/errors"
6
+ require "rubycord/api"
7
+ require "rubycord/api/channel"
8
+ require "rubycord/api/server"
9
+ require "rubycord/api/invite"
10
+ require "rubycord/api/user"
11
+ require "rubycord/api/webhook"
12
+ require "rubycord/webhooks/embeds"
13
+ require "rubycord/webhooks/view"
14
+ require "rubycord/paginator"
15
+ require "time"
16
+ require "base64"
17
+
18
+ require "rubycord/data/activity"
19
+ require "rubycord/data/application"
20
+ require "rubycord/data/user"
21
+ require "rubycord/data/voice_state"
22
+ require "rubycord/data/voice_region"
23
+ require "rubycord/data/member"
24
+ require "rubycord/data/recipient"
25
+ require "rubycord/data/profile"
26
+ require "rubycord/data/role"
27
+ require "rubycord/data/invite"
28
+ require "rubycord/data/overwrite"
29
+ require "rubycord/data/channel"
30
+ require "rubycord/data/embed"
31
+ require "rubycord/data/attachment"
32
+ require "rubycord/data/message"
33
+ require "rubycord/data/reaction"
34
+ require "rubycord/data/emoji"
35
+ require "rubycord/data/integration"
36
+ require "rubycord/data/server"
37
+ require "rubycord/data/webhook"
38
+ require "rubycord/data/audit_logs"
39
+ require "rubycord/data/interaction"
40
+ require "rubycord/data/component"