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.
- checksums.yaml +7 -0
- data/lib/rubycord/allowed_mentions.rb +34 -0
- data/lib/rubycord/api/application.rb +200 -0
- data/lib/rubycord/api/channel.rb +597 -0
- data/lib/rubycord/api/interaction.rb +52 -0
- data/lib/rubycord/api/invite.rb +42 -0
- data/lib/rubycord/api/server.rb +557 -0
- data/lib/rubycord/api/user.rb +153 -0
- data/lib/rubycord/api/webhook.rb +138 -0
- data/lib/rubycord/api.rb +356 -0
- data/lib/rubycord/await.rb +49 -0
- data/lib/rubycord/bot.rb +1757 -0
- data/lib/rubycord/cache.rb +259 -0
- data/lib/rubycord/colour_rgb.rb +41 -0
- data/lib/rubycord/commands/command_bot.rb +519 -0
- data/lib/rubycord/commands/container.rb +110 -0
- data/lib/rubycord/commands/events.rb +9 -0
- data/lib/rubycord/commands/parser.rb +325 -0
- data/lib/rubycord/commands/rate_limiter.rb +142 -0
- data/lib/rubycord/container.rb +753 -0
- data/lib/rubycord/data/activity.rb +269 -0
- data/lib/rubycord/data/application.rb +48 -0
- data/lib/rubycord/data/attachment.rb +109 -0
- data/lib/rubycord/data/audit_logs.rb +343 -0
- data/lib/rubycord/data/channel.rb +996 -0
- data/lib/rubycord/data/component.rb +227 -0
- data/lib/rubycord/data/embed.rb +249 -0
- data/lib/rubycord/data/emoji.rb +80 -0
- data/lib/rubycord/data/integration.rb +120 -0
- data/lib/rubycord/data/interaction.rb +798 -0
- data/lib/rubycord/data/invite.rb +135 -0
- data/lib/rubycord/data/member.rb +370 -0
- data/lib/rubycord/data/message.rb +412 -0
- data/lib/rubycord/data/overwrite.rb +106 -0
- data/lib/rubycord/data/profile.rb +89 -0
- data/lib/rubycord/data/reaction.rb +31 -0
- data/lib/rubycord/data/recipient.rb +32 -0
- data/lib/rubycord/data/role.rb +246 -0
- data/lib/rubycord/data/server.rb +1002 -0
- data/lib/rubycord/data/user.rb +261 -0
- data/lib/rubycord/data/voice_region.rb +43 -0
- data/lib/rubycord/data/voice_state.rb +39 -0
- data/lib/rubycord/data/webhook.rb +232 -0
- data/lib/rubycord/data.rb +40 -0
- data/lib/rubycord/errors.rb +737 -0
- data/lib/rubycord/events/await.rb +46 -0
- data/lib/rubycord/events/bans.rb +58 -0
- data/lib/rubycord/events/channels.rb +186 -0
- data/lib/rubycord/events/generic.rb +126 -0
- data/lib/rubycord/events/guilds.rb +191 -0
- data/lib/rubycord/events/interactions.rb +480 -0
- data/lib/rubycord/events/invites.rb +123 -0
- data/lib/rubycord/events/lifetime.rb +29 -0
- data/lib/rubycord/events/members.rb +91 -0
- data/lib/rubycord/events/message.rb +337 -0
- data/lib/rubycord/events/presence.rb +127 -0
- data/lib/rubycord/events/raw.rb +45 -0
- data/lib/rubycord/events/reactions.rb +156 -0
- data/lib/rubycord/events/roles.rb +86 -0
- data/lib/rubycord/events/threads.rb +94 -0
- data/lib/rubycord/events/typing.rb +70 -0
- data/lib/rubycord/events/voice_server_update.rb +45 -0
- data/lib/rubycord/events/voice_state_update.rb +103 -0
- data/lib/rubycord/events/webhooks.rb +62 -0
- data/lib/rubycord/gateway.rb +867 -0
- data/lib/rubycord/id_object.rb +37 -0
- data/lib/rubycord/light/data.rb +60 -0
- data/lib/rubycord/light/integrations.rb +71 -0
- data/lib/rubycord/light/light_bot.rb +56 -0
- data/lib/rubycord/light.rb +6 -0
- data/lib/rubycord/logger.rb +118 -0
- data/lib/rubycord/paginator.rb +55 -0
- data/lib/rubycord/permissions.rb +251 -0
- data/lib/rubycord/version.rb +5 -0
- data/lib/rubycord/voice/encoder.rb +113 -0
- data/lib/rubycord/voice/network.rb +366 -0
- data/lib/rubycord/voice/sodium.rb +96 -0
- data/lib/rubycord/voice/voice_bot.rb +408 -0
- data/lib/rubycord/webhooks/builder.rb +100 -0
- data/lib/rubycord/webhooks/client.rb +132 -0
- data/lib/rubycord/webhooks/embeds.rb +248 -0
- data/lib/rubycord/webhooks/modal.rb +78 -0
- data/lib/rubycord/webhooks/version.rb +7 -0
- data/lib/rubycord/webhooks/view.rb +192 -0
- data/lib/rubycord/webhooks.rb +12 -0
- data/lib/rubycord/websocket.rb +70 -0
- data/lib/rubycord.rb +140 -0
- 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"
|