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,259 @@
1
+ require "rubycord/api"
2
+ require "rubycord/api/server"
3
+ require "rubycord/api/invite"
4
+ require "rubycord/api/user"
5
+ require "rubycord/data"
6
+
7
+ module Rubycord
8
+ # This mixin module does caching stuff for the library. It conveniently separates the logic behind
9
+ # the caching (like, storing the user hashes or making API calls to retrieve things) from the Bot that
10
+ # actually uses it.
11
+ module Cache
12
+ # Initializes this cache
13
+ def init_cache
14
+ @users = {}
15
+
16
+ @voice_regions = {}
17
+
18
+ @servers = {}
19
+
20
+ @channels = {}
21
+ @pm_channels = {}
22
+ @thread_members = {}
23
+ end
24
+
25
+ # Returns or caches the available voice regions
26
+ def voice_regions
27
+ return @voice_regions unless @voice_regions.empty?
28
+
29
+ regions = JSON.parse API.voice_regions(token)
30
+ regions.each do |data|
31
+ @voice_regions[data["id"]] = VoiceRegion.new(data)
32
+ end
33
+
34
+ @voice_regions
35
+ end
36
+
37
+ # Gets a channel given its ID. This queries the internal channel cache, and if the channel doesn't
38
+ # exist in there, it will get the data from Discord.
39
+ # @param id [Integer] The channel ID for which to search for.
40
+ # @param server [Server] The server for which to search the channel for. If this isn't specified, it will be
41
+ # inferred using the API
42
+ # @return [Channel, nil] The channel identified by the ID.
43
+ # @raise Rubycord::Errors::NoPermission
44
+ def channel(id, server = nil)
45
+ id = id.resolve_id
46
+
47
+ debug("Obtaining data for channel with id #{id}")
48
+ return @channels[id] if @channels[id]
49
+
50
+ begin
51
+ response = API::Channel.resolve(token, id)
52
+ rescue Rubycord::Errors::UnknownChannel
53
+ return nil
54
+ end
55
+ channel = Channel.new(JSON.parse(response), self, server)
56
+ @channels[id] = channel
57
+ end
58
+
59
+ alias_method :group_channel, :channel
60
+
61
+ # Gets a user by its ID.
62
+ # @note This can only resolve users known by the bot (i.e. that share a server with the bot).
63
+ # @param id [Integer] The user ID that should be resolved.
64
+ # @return [User, nil] The user identified by the ID, or `nil` if it couldn't be found.
65
+ def user(id)
66
+ id = id.resolve_id
67
+ return @users[id] if @users[id]
68
+
69
+ LOGGER.out("Resolving user #{id}")
70
+ begin
71
+ response = API::User.resolve(token, id)
72
+ rescue Rubycord::Errors::UnknownUser
73
+ return nil
74
+ end
75
+ user = User.new(JSON.parse(response), self)
76
+ @users[id] = user
77
+ end
78
+
79
+ # Gets a server by its ID.
80
+ # @note This can only resolve servers the bot is currently in.
81
+ # @param id [Integer] The server ID that should be resolved.
82
+ # @return [Server, nil] The server identified by the ID, or `nil` if it couldn't be found.
83
+ def server(id)
84
+ id = id.resolve_id
85
+ return @servers[id] if @servers[id]
86
+
87
+ LOGGER.out("Resolving server #{id}")
88
+ begin
89
+ response = API::Server.resolve(token, id)
90
+ rescue Rubycord::Errors::NoPermission
91
+ return nil
92
+ end
93
+ server = Server.new(JSON.parse(response), self)
94
+ @servers[id] = server
95
+ end
96
+
97
+ # Gets a member by both IDs, or `Server` and user ID.
98
+ # @param server_or_id [Server, Integer] The `Server` or server ID for which a member should be resolved
99
+ # @param user_id [Integer] The ID of the user that should be resolved
100
+ # @return [Member, nil] The member identified by the IDs, or `nil` if none could be found
101
+ def member(server_or_id, user_id)
102
+ server_id = server_or_id.resolve_id
103
+ user_id = user_id.resolve_id
104
+ server = server_or_id.is_a?(Server) ? server_or_id : self.server(server_id)
105
+
106
+ return server.member(user_id) if server.member_cached?(user_id)
107
+
108
+ LOGGER.out("Resolving member #{server_id} on server #{user_id}")
109
+ begin
110
+ response = API::Server.resolve_member(token, server_id, user_id)
111
+ rescue Rubycord::Errors::UnknownUser, Rubycord::Errors::UnknownMember
112
+ return nil
113
+ end
114
+ member = Member.new(JSON.parse(response), server, self)
115
+ server.cache_member(member)
116
+ end
117
+
118
+ # Creates a PM channel for the given user ID, or if one exists already, returns that one.
119
+ # It is recommended that you use {User#pm} instead, as this is mainly for internal use. However,
120
+ # usage of this method may be unavoidable if only the user ID is known.
121
+ # @param id [Integer] The user ID to generate a private channel for.
122
+ # @return [Channel] A private channel for that user.
123
+ def pm_channel(id)
124
+ id = id.resolve_id
125
+ return @pm_channels[id] if @pm_channels[id]
126
+
127
+ debug("Creating pm channel with user id #{id}")
128
+ response = API::User.create_pm(token, id)
129
+ channel = Channel.new(JSON.parse(response), self)
130
+ @pm_channels[id] = channel
131
+ end
132
+
133
+ alias_method :private_channel, :pm_channel
134
+
135
+ # Ensures a given user object is cached and if not, cache it from the given data hash.
136
+ # @param data [Hash] A data hash representing a user.
137
+ # @return [User] the user represented by the data hash.
138
+ def ensure_user(data)
139
+ if @users.include?(data["id"].to_i)
140
+ @users[data["id"].to_i]
141
+ else
142
+ @users[data["id"].to_i] = User.new(data, self)
143
+ end
144
+ end
145
+
146
+ # Ensures a given server object is cached and if not, cache it from the given data hash.
147
+ # @param data [Hash] A data hash representing a server.
148
+ # @param force_cache [true, false] Whether the object in cache should be updated with the given
149
+ # data if it already exists.
150
+ # @return [Server] the server represented by the data hash.
151
+ def ensure_server(data, force_cache = false)
152
+ if @servers.include?(data["id"].to_i)
153
+ server = @servers[data["id"].to_i]
154
+ server.update_data(data) if force_cache
155
+ server
156
+ else
157
+ @servers[data["id"].to_i] = Server.new(data, self)
158
+ end
159
+ end
160
+
161
+ # Ensures a given channel object is cached and if not, cache it from the given data hash.
162
+ # @param data [Hash] A data hash representing a channel.
163
+ # @param server [Server, nil] The server the channel is on, if known.
164
+ # @return [Channel] the channel represented by the data hash.
165
+ def ensure_channel(data, server = nil)
166
+ if @channels.include?(data["id"].to_i)
167
+ @channels[data["id"].to_i]
168
+ else
169
+ @channels[data["id"].to_i] = Channel.new(data, self, server)
170
+ end
171
+ end
172
+
173
+ # Ensures a given thread member object is cached.
174
+ # @param data [Hash] Thread member data.
175
+ def ensure_thread_member(data)
176
+ thread_id = data["id"].to_i
177
+ user_id = data["user_id"].to_i
178
+
179
+ @thread_members[thread_id] ||= {}
180
+ @thread_members[thread_id][user_id] = data.slice("join_timestamp", "flags")
181
+ end
182
+
183
+ # Requests member chunks for a given server ID.
184
+ # @param id [Integer] The server ID to request chunks for.
185
+ def request_chunks(id)
186
+ @gateway.send_request_members(id, "", 0)
187
+ end
188
+
189
+ # Gets the code for an invite.
190
+ # @param invite [String, Invite] The invite to get the code for. Possible formats are:
191
+ #
192
+ # * An {Invite} object
193
+ # * The code for an invite
194
+ # * A fully qualified invite URL (e.g. `https://discord.com/invite/0A37aN7fasF7n83q`)
195
+ # * A short invite URL with protocol (e.g. `https://discord.gg/0A37aN7fasF7n83q`)
196
+ # * A short invite URL without protocol (e.g. `discord.gg/0A37aN7fasF7n83q`)
197
+ # @return [String] Only the code for the invite.
198
+ def resolve_invite_code(invite)
199
+ invite = invite.code if invite.is_a? Rubycord::Invite
200
+ invite = invite[invite.rindex("/") + 1..] if invite.start_with?("http", "discord.gg")
201
+ invite
202
+ end
203
+
204
+ # Gets information about an invite.
205
+ # @param invite [String, Invite] The invite to join. For possible formats see {#resolve_invite_code}.
206
+ # @return [Invite] The invite with information about the given invite URL.
207
+ def invite(invite)
208
+ code = resolve_invite_code(invite)
209
+ Invite.new(JSON.parse(API::Invite.resolve(token, code)), self)
210
+ end
211
+
212
+ # Finds a channel given its name and optionally the name of the server it is in.
213
+ # @param channel_name [String] The channel to search for.
214
+ # @param server_name [String] The server to search for, or `nil` if only the channel should be searched for.
215
+ # @param type [Integer, nil] The type of channel to search for (0: text, 1: private, 2: voice, 3: group), or `nil` if any type of
216
+ # channel should be searched for
217
+ # @return [Array<Channel>] The array of channels that were found. May be empty if none were found.
218
+ def find_channel(channel_name, server_name = nil, type: nil)
219
+ results = []
220
+
221
+ if /<#(?<id>\d+)>?/ =~ channel_name
222
+ # Check for channel mentions separately
223
+ return [channel(id)]
224
+ end
225
+
226
+ @servers.each_value do |server|
227
+ server.channels.each do |channel|
228
+ results << channel if channel.name == channel_name && (server_name || server.name) == server.name && (!type || (channel.type == type))
229
+ end
230
+ end
231
+
232
+ results
233
+ end
234
+
235
+ # Finds a user given its username or username & discriminator.
236
+ # @overload find_user(username)
237
+ # Find all cached users with a certain username.
238
+ # @param username [String] The username to look for.
239
+ # @return [Array<User>] The array of users that were found. May be empty if none were found.
240
+ # @overload find_user(username, discrim)
241
+ # Find a cached user with a certain username and discriminator.
242
+ # Find a user by name and discriminator
243
+ # @param username [String] The username to look for.
244
+ # @param discrim [String] The user's discriminator
245
+ # @return [User, nil] The user that was found, or `nil` if none was found
246
+ # @note This method only searches through users that have been cached. Users that have not yet been cached
247
+ # by the bot but still share a connection with the user (mutual server) will not be found.
248
+ # @example Find users by name
249
+ # bot.find_user('z64') #=> Array<User>
250
+ # @example Find a user by name and discriminator
251
+ # bot.find_user('z64', '2639') #=> User
252
+ def find_user(username, discrim = nil)
253
+ users = @users.values.find_all { |e| e.username == username }
254
+ return users.find { |u| u.discrim == discrim } if discrim
255
+
256
+ users
257
+ end
258
+ end
259
+ end
@@ -0,0 +1,41 @@
1
+ module Rubycord
2
+ # A colour (red, green and blue values). Used for role colours. If you prefer the American spelling, the alias
3
+ # {ColorRGB} is also available.
4
+ class ColourRGB
5
+ # @return [Integer] the red part of this colour (0-255).
6
+ attr_reader :red
7
+
8
+ # @return [Integer] the green part of this colour (0-255).
9
+ attr_reader :green
10
+
11
+ # @return [Integer] the blue part of this colour (0-255).
12
+ attr_reader :blue
13
+
14
+ # @return [Integer] the colour's RGB values combined into one integer.
15
+ attr_reader :combined
16
+ alias_method :to_i, :combined
17
+
18
+ # Make a new colour from the combined value.
19
+ # @param combined [String, Integer] The colour's RGB values combined into one integer or a hexadecimal string
20
+ # @example Initialize a with a base 10 integer
21
+ # ColourRGB.new(7506394) #=> ColourRGB
22
+ # ColourRGB.new(0x7289da) #=> ColourRGB
23
+ # @example Initialize a with a hexadecimal string
24
+ # ColourRGB.new('7289da') #=> ColourRGB
25
+ def initialize(combined)
26
+ @combined = combined.is_a?(String) ? combined.to_i(16) : combined
27
+ @red = (@combined >> 16) & 0xFF
28
+ @green = (@combined >> 8) & 0xFF
29
+ @blue = @combined & 0xFF
30
+ end
31
+
32
+ # @return [String] the colour as a hexadecimal.
33
+ def hex
34
+ @combined.to_s(16)
35
+ end
36
+ alias_method :hexadecimal, :hex
37
+ end
38
+
39
+ # Alias for the class {ColourRGB}
40
+ ColorRGB = ColourRGB
41
+ end