rubycord 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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,135 @@
1
+ module Rubycord
2
+ # A channel referenced by an invite. It has less data than regular channels, so it's a separate class
3
+ class InviteChannel
4
+ include IDObject
5
+
6
+ # @return [String] this channel's name.
7
+ attr_reader :name
8
+
9
+ # @return [Integer] this channel's type (0: text, 1: private, 2: voice, 3: group).
10
+ attr_reader :type
11
+
12
+ # @!visibility private
13
+ def initialize(data, bot)
14
+ @bot = bot
15
+
16
+ @id = data["id"].to_i
17
+ @name = data["name"]
18
+ @type = data["type"]
19
+ end
20
+ end
21
+
22
+ # A server referenced to by an invite
23
+ class InviteServer
24
+ include IDObject
25
+
26
+ # @return [String] this server's name.
27
+ attr_reader :name
28
+
29
+ # @return [String, nil] the hash of the server's invite splash screen (for partnered servers) or nil if none is
30
+ # present
31
+ attr_reader :splash_hash
32
+
33
+ # @!visibility private
34
+ def initialize(data, bot)
35
+ @bot = bot
36
+
37
+ @id = data["id"].to_i
38
+ @name = data["name"]
39
+ @splash_hash = data["splash_hash"]
40
+ end
41
+ end
42
+
43
+ # A Discord invite to a channel
44
+ class Invite
45
+ # @return [InviteChannel, Channel] the channel this invite references.
46
+ attr_reader :channel
47
+
48
+ # @return [InviteServer, Server] the server this invite references.
49
+ attr_reader :server
50
+
51
+ # @return [Integer] the amount of uses left on this invite.
52
+ attr_reader :uses
53
+ alias_method :max_uses, :uses
54
+
55
+ # @return [User, nil] the user that made this invite. May also be nil if the user can't be determined.
56
+ attr_reader :inviter
57
+ alias_method :user, :inviter
58
+
59
+ # @return [true, false] whether or not this invite grants temporary membership. If someone joins a server with this invite, they will be removed from the server when they go offline unless they've received a role.
60
+ attr_reader :temporary
61
+ alias_method :temporary?, :temporary
62
+
63
+ # @return [true, false] whether this invite is still valid.
64
+ attr_reader :revoked
65
+ alias_method :revoked?, :revoked
66
+
67
+ # @return [String] this invite's code
68
+ attr_reader :code
69
+
70
+ # @return [Integer, nil] the amount of members in the server. Will be nil if it has not been resolved.
71
+ attr_reader :member_count
72
+ alias_method :user_count, :member_count
73
+
74
+ # @return [Integer, nil] the amount of online members in the server. Will be nil if it has not been resolved.
75
+ attr_reader :online_member_count
76
+ alias_method :online_user_count, :online_member_count
77
+
78
+ # @return [Integer, nil] the invites max age before it expires, or nil if it's unknown. If the max age is 0, the invite will never expire unless it's deleted.
79
+ attr_reader :max_age
80
+
81
+ # @return [Time, nil] when this invite was created, or nil if it's unknown
82
+ attr_reader :created_at
83
+
84
+ # @!visibility private
85
+ def initialize(data, bot)
86
+ @bot = bot
87
+
88
+ @channel = if data["channel_id"]
89
+ bot.channel(data["channel_id"])
90
+ else
91
+ InviteChannel.new(data["channel"], bot)
92
+ end
93
+
94
+ @server = if data["guild_id"]
95
+ bot.server(data["guild_id"])
96
+ else
97
+ InviteServer.new(data["guild"], bot)
98
+ end
99
+
100
+ @uses = data["uses"]
101
+ @inviter = data["inviter"] ? bot.ensure_user(data["inviter"]) : nil
102
+ @temporary = data["temporary"]
103
+ @revoked = data["revoked"]
104
+ @online_member_count = data["approximate_presence_count"]
105
+ @member_count = data["approximate_member_count"]
106
+ @max_age = data["max_age"]
107
+ @created_at = data["created_at"]
108
+
109
+ @code = data["code"]
110
+ end
111
+
112
+ # Code based comparison
113
+ def ==(other)
114
+ other.respond_to?(:code) ? (@code == other.code) : (@code == other)
115
+ end
116
+
117
+ # Deletes this invite
118
+ # @param reason [String] The reason the invite is being deleted.
119
+ def delete(reason = nil)
120
+ API::Invite.delete(@bot.token, @code, reason)
121
+ end
122
+
123
+ alias_method :revoke, :delete
124
+
125
+ # The inspect method is overwritten to give more useful output
126
+ def inspect
127
+ "<Invite code=#{@code} channel=#{@channel} uses=#{@uses} temporary=#{@temporary} revoked=#{@revoked} created_at=#{@created_at} max_age=#{@max_age}>"
128
+ end
129
+
130
+ # Creates an invite URL.
131
+ def url
132
+ "https://discord.gg/#{@code}"
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,370 @@
1
+ module Rubycord
2
+ # Mixin for the attributes members and private members should have
3
+ module MemberAttributes
4
+ # @return [Time] when this member joined the server.
5
+ attr_reader :joined_at
6
+
7
+ # @return [Time, nil] when this member boosted this server, `nil` if they haven't.
8
+ attr_reader :boosting_since
9
+
10
+ # @return [String, nil] the nickname this member has, or `nil` if it has none.
11
+ attr_reader :nick
12
+ alias_method :nickname, :nick
13
+
14
+ # @return [Array<Role>] the roles this member has.
15
+ attr_reader :roles
16
+
17
+ # @return [Server] the server this member is on.
18
+ attr_reader :server
19
+
20
+ # @return [Time] When the user's timeout will expire.
21
+ attr_reader :communication_disabled_until
22
+ alias_method :timeout, :communication_disabled_until
23
+ end
24
+
25
+ # A member is a user on a server. It differs from regular users in that it has roles, voice statuses and things like
26
+ # that.
27
+ class Member < DelegateClass(User)
28
+ # @return [true, false] whether this member is muted server-wide.
29
+ def mute
30
+ voice_state_attribute(:mute)
31
+ end
32
+
33
+ # @return [true, false] whether this member is deafened server-wide.
34
+ def deaf
35
+ voice_state_attribute(:deaf)
36
+ end
37
+
38
+ # @return [true, false] whether this member has muted themselves.
39
+ def self_mute
40
+ voice_state_attribute(:self_mute)
41
+ end
42
+
43
+ # @return [true, false] whether this member has deafened themselves.
44
+ def self_deaf
45
+ voice_state_attribute(:self_deaf)
46
+ end
47
+
48
+ # @return [Channel] the voice channel this member is in.
49
+ def voice_channel
50
+ voice_state_attribute(:voice_channel)
51
+ end
52
+
53
+ alias_method :muted?, :mute
54
+ alias_method :deafened?, :deaf
55
+ alias_method :self_muted?, :self_mute
56
+ alias_method :self_deafened?, :self_deaf
57
+
58
+ include MemberAttributes
59
+
60
+ # @!visibility private
61
+ def initialize(data, server, bot)
62
+ @bot = bot
63
+
64
+ @user = bot.ensure_user(data["user"])
65
+ super(@user) # Initialize the delegate class
66
+
67
+ @server = server
68
+ @server_id = server&.id || data["guild_id"].to_i
69
+
70
+ @role_ids = data["roles"]&.map(&:to_i) || []
71
+
72
+ @nick = data["nick"]
73
+ @joined_at = data["joined_at"] ? Time.parse(data["joined_at"]) : nil
74
+ @boosting_since = data["premium_since"] ? Time.parse(data["premium_since"]) : nil
75
+ timeout_until = data["communication_disabled_until"]
76
+ @communication_disabled_until = timeout_until ? Time.parse(timeout_until) : nil
77
+ @permissions = Permissions.new(data["permissions"]) if data["permissions"]
78
+ end
79
+
80
+ # @return [Server] the server this member is on.
81
+ # @raise [Rubycord::Errors::NoPermission] This can happen when receiving interactions for servers in which the bot is not
82
+ # authorized with the `bot` scope.
83
+ def server
84
+ return @server if @server
85
+
86
+ @server = @bot.server(@server_id)
87
+ raise Rubycord::Errors::NoPermission, "The bot does not have access to this server" unless @server
88
+
89
+ @server
90
+ end
91
+
92
+ # @return [Array<Role>] the roles this member has.
93
+ # @raise [Rubycord::Errors::NoPermission] This can happen when receiving interactions for servers in which the bot is not
94
+ # authorized with the `bot` scope.
95
+ def roles
96
+ return @roles if @roles
97
+
98
+ update_roles(@role_ids)
99
+ @roles
100
+ end
101
+
102
+ # @return [true, false] if this user is a Nitro Booster of this server.
103
+ def boosting?
104
+ !@boosting_since.nil?
105
+ end
106
+
107
+ # @return [true, false] whether this member is the server owner.
108
+ def owner?
109
+ server.owner == self
110
+ end
111
+
112
+ # @param role [Role, String, Integer] the role to check or its ID.
113
+ # @return [true, false] whether this member has the specified role.
114
+ def role?(role)
115
+ role = role.resolve_id
116
+ roles.any?(role)
117
+ end
118
+
119
+ # @see Member#set_roles
120
+ def roles=(role)
121
+ set_roles(role)
122
+ end
123
+
124
+ # Check if the current user has communication disabled.
125
+ # @return [true, false]
126
+ def communication_disabled?
127
+ !@communication_disabled_until.nil? && @communication_disabled_until > Time.now
128
+ end
129
+
130
+ alias_method :timeout?, :communication_disabled?
131
+
132
+ # Set a user's timeout duration, or remove it by setting the timeout to `nil`.
133
+ # @param timeout_until [Time, nil] When the timeout will end.
134
+ def communication_disabled_until=(timeout_until)
135
+ raise ArgumentError, "A time out cannot exceed 28 days" if timeout_until && timeout_until > (Time.now + 2_419_200)
136
+
137
+ API::Server.update_member(@bot.token, @server_id, @user.id, communication_disabled_until: timeout_until.iso8601)
138
+ end
139
+
140
+ alias_method :timeout=, :communication_disabled_until=
141
+
142
+ # Bulk sets a member's roles.
143
+ # @param role [Role, Array<Role>] The role(s) to set.
144
+ # @param reason [String] The reason the user's roles are being changed.
145
+ def set_roles(role, reason = nil)
146
+ role_ids = role_id_array(role)
147
+ API::Server.update_member(@bot.token, @server_id, @user.id, roles: role_ids, reason: reason)
148
+ end
149
+
150
+ # Adds and removes roles from a member.
151
+ # @param add [Role, Array<Role>] The role(s) to add.
152
+ # @param remove [Role, Array<Role>] The role(s) to remove.
153
+ # @param reason [String] The reason the user's roles are being changed.
154
+ # @example Remove the 'Member' role from a user, and add the 'Muted' role to them.
155
+ # to_add = server.roles.find {|role| role.name == 'Muted'}
156
+ # to_remove = server.roles.find {|role| role.name == 'Member'}
157
+ # member.modify_roles(to_add, to_remove)
158
+ def modify_roles(add, remove, reason = nil)
159
+ add_role_ids = role_id_array(add)
160
+ remove_role_ids = role_id_array(remove)
161
+ old_role_ids = resolve_role_ids
162
+ new_role_ids = (old_role_ids - remove_role_ids + add_role_ids).uniq
163
+
164
+ API::Server.update_member(@bot.token, @server_id, @user.id, roles: new_role_ids, reason: reason)
165
+ end
166
+
167
+ # Adds one or more roles to this member.
168
+ # @param role [Role, Array<Role, String, Integer>, String, Integer] The role(s), or their ID(s), to add.
169
+ # @param reason [String] The reason the user's roles are being changed.
170
+ def add_role(role, reason = nil)
171
+ role_ids = role_id_array(role)
172
+
173
+ if role_ids.count == 1
174
+ API::Server.add_member_role(@bot.token, @server_id, @user.id, role_ids[0], reason)
175
+ else
176
+ old_role_ids = resolve_role_ids
177
+ new_role_ids = (old_role_ids + role_ids).uniq
178
+ API::Server.update_member(@bot.token, @server_id, @user.id, roles: new_role_ids, reason: reason)
179
+ end
180
+ end
181
+
182
+ # Removes one or more roles from this member.
183
+ # @param role [Role, Array<Role>] The role(s) to remove.
184
+ # @param reason [String] The reason the user's roles are being changed.
185
+ def remove_role(role, reason = nil)
186
+ role_ids = role_id_array(role)
187
+
188
+ if role_ids.count == 1
189
+ API::Server.remove_member_role(@bot.token, @server_id, @user.id, role_ids[0], reason)
190
+ else
191
+ old_role_ids = resolve_role_ids
192
+ new_role_ids = old_role_ids.reject { |i| role_ids.include?(i) }
193
+ API::Server.update_member(@bot.token, @server_id, @user.id, roles: new_role_ids, reason: reason)
194
+ end
195
+ end
196
+
197
+ # @return [Role] the highest role this member has.
198
+ def highest_role
199
+ roles.max_by(&:position)
200
+ end
201
+
202
+ # @return [Role, nil] the role this member is being hoisted with.
203
+ def hoist_role
204
+ hoisted_roles = roles.select(&:hoist)
205
+ return nil if hoisted_roles.empty?
206
+
207
+ hoisted_roles.max_by(&:position)
208
+ end
209
+
210
+ # @return [Role, nil] the role this member is basing their colour on.
211
+ def colour_role
212
+ coloured_roles = roles.select { |v| v.colour.combined.nonzero? }
213
+ return nil if coloured_roles.empty?
214
+
215
+ coloured_roles.max_by(&:position)
216
+ end
217
+ alias_method :color_role, :colour_role
218
+
219
+ # @return [ColourRGB, nil] the colour this member has.
220
+ def colour
221
+ return nil unless colour_role
222
+
223
+ colour_role.color
224
+ end
225
+ alias_method :color, :colour
226
+
227
+ # Server deafens this member.
228
+ def server_deafen
229
+ API::Server.update_member(@bot.token, @server_id, @user.id, deaf: true)
230
+ end
231
+
232
+ # Server undeafens this member.
233
+ def server_undeafen
234
+ API::Server.update_member(@bot.token, @server_id, @user.id, deaf: false)
235
+ end
236
+
237
+ # Server mutes this member.
238
+ def server_mute
239
+ API::Server.update_member(@bot.token, @server_id, @user.id, mute: true)
240
+ end
241
+
242
+ # Server unmutes this member.
243
+ def server_unmute
244
+ API::Server.update_member(@bot.token, @server_id, @user.id, mute: false)
245
+ end
246
+
247
+ # Bans this member from the server.
248
+ # @param message_days [Integer] How many days worth of messages sent by the member should be deleted.
249
+ # @param reason [String] The reason this member is being banned.
250
+ def ban(message_days = 0, reason: nil)
251
+ server.ban(@user, message_days, reason: reason)
252
+ end
253
+
254
+ # Unbans this member from the server.
255
+ # @param reason [String] The reason this member is being unbanned.
256
+ def unban(reason = nil)
257
+ server.unban(@user, reason)
258
+ end
259
+
260
+ # Kicks this member from the server.
261
+ # @param reason [String] The reason this member is being kicked.
262
+ def kick(reason = nil)
263
+ server.kick(@user, reason)
264
+ end
265
+
266
+ # @see Member#set_nick
267
+ def nick=(nick)
268
+ set_nick(nick)
269
+ end
270
+
271
+ alias_method :nickname=, :nick=
272
+
273
+ # Sets or resets this member's nickname. Requires the Change Nickname permission for the bot itself and Manage
274
+ # Nicknames for other users.
275
+ # @param nick [String, nil] The string to set the nickname to, or nil if it should be reset.
276
+ # @param reason [String] The reason the user's nickname is being changed.
277
+ def set_nick(nick, reason = nil)
278
+ # Discord uses the empty string to signify 'no nickname' so we convert nil into that
279
+ nick ||= ""
280
+
281
+ if @user.current_bot?
282
+ API::User.change_own_nickname(@bot.token, @server_id, nick, reason)
283
+ else
284
+ API::Server.update_member(@bot.token, @server_id, @user.id, nick: nick, reason: nil)
285
+ end
286
+ end
287
+
288
+ alias_method :set_nickname, :set_nick
289
+
290
+ # @return [String] the name the user displays as (nickname if they have one, global_name if they have one, username otherwise)
291
+ def display_name
292
+ nickname || global_name || username
293
+ end
294
+
295
+ # Update this member's roles
296
+ # @note For internal use only.
297
+ # @!visibility private
298
+ def update_roles(role_ids)
299
+ @roles = [server.role(@server_id)]
300
+ role_ids.each do |id|
301
+ # It is possible for members to have roles that do not exist
302
+ # on the server any longer.
303
+ role = server.role(id)
304
+ @roles << role if role
305
+ end
306
+ end
307
+
308
+ # Update this member's nick
309
+ # @note For internal use only.
310
+ # @!visibility private
311
+ def update_nick(nick)
312
+ @nick = nick
313
+ end
314
+
315
+ # Update this member's boosting timestamp
316
+ # @note For internal user only.
317
+ # @!visibility private
318
+ def update_boosting_since(time)
319
+ @boosting_since = time
320
+ end
321
+
322
+ # @!visibility private
323
+ def update_communication_disabled_until(time)
324
+ time = time ? Time.parse(time) : nil
325
+ @communication_disabled_until = time
326
+ end
327
+
328
+ # Update this member
329
+ # @note For internal use only.
330
+ # @!visibility private
331
+ def update_data(data)
332
+ update_roles(data["roles"]) if data["roles"]
333
+ update_nick(data["nick"]) if data.key?("nick")
334
+ @mute = data["mute"] if data.key?("mute")
335
+ @deaf = data["deaf"] if data.key?("deaf")
336
+
337
+ @joined_at = Time.parse(data["joined_at"]) if data["joined_at"]
338
+ timeout_until = data["communication_disabled_until"]
339
+ @communication_disabled_until = timeout_until ? Time.parse(timeout_until) : nil
340
+ end
341
+
342
+ include PermissionCalculator
343
+
344
+ # Overwriting inspect for debug purposes
345
+ def inspect
346
+ "<Member user=#{@user.inspect} server=#{@server&.inspect || @server_id} joined_at=#{@joined_at} roles=#{@roles&.inspect || @role_ids} voice_channel=#{@voice_channel.inspect} mute=#{@mute} deaf=#{@deaf} self_mute=#{@self_mute} self_deaf=#{@self_deaf}>"
347
+ end
348
+
349
+ private
350
+
351
+ # Utility method to get a list of role IDs from one role or an array of roles
352
+ def role_id_array(role)
353
+ if role.is_a? Array
354
+ role.map(&:resolve_id)
355
+ else
356
+ [role.resolve_id]
357
+ end
358
+ end
359
+
360
+ # Utility method to get data out of this member's voice state
361
+ def voice_state_attribute(name)
362
+ voice_state = server.voice_states[@user.id]
363
+ voice_state&.send name
364
+ end
365
+
366
+ def resolve_role_ids
367
+ @roles ? @roles.collect(&:id) : @role_ids
368
+ end
369
+ end
370
+ end