discorb 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +56 -0
  3. data/.yardopts +6 -0
  4. data/Changelog.md +5 -0
  5. data/Gemfile +23 -0
  6. data/Gemfile.lock +70 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +53 -0
  9. data/Rakefile +46 -0
  10. data/bin/console +15 -0
  11. data/bin/setup +8 -0
  12. data/discorb.gemspec +37 -0
  13. data/docs/Examples.md +26 -0
  14. data/docs/events.md +480 -0
  15. data/docs/voice_events.md +283 -0
  16. data/examples/components/authorization_button.rb +43 -0
  17. data/examples/components/select_menu.rb +61 -0
  18. data/examples/extension/main.rb +12 -0
  19. data/examples/extension/message_expander.rb +41 -0
  20. data/examples/simple/eval.rb +32 -0
  21. data/examples/simple/ping_pong.rb +16 -0
  22. data/examples/simple/rolepanel.rb +65 -0
  23. data/examples/simple/wait_for_message.rb +30 -0
  24. data/lib/discorb/application.rb +157 -0
  25. data/lib/discorb/asset.rb +57 -0
  26. data/lib/discorb/audit_logs.rb +323 -0
  27. data/lib/discorb/channel.rb +1101 -0
  28. data/lib/discorb/client.rb +363 -0
  29. data/lib/discorb/color.rb +173 -0
  30. data/lib/discorb/common.rb +123 -0
  31. data/lib/discorb/components.rb +290 -0
  32. data/lib/discorb/dictionary.rb +119 -0
  33. data/lib/discorb/embed.rb +345 -0
  34. data/lib/discorb/emoji.rb +218 -0
  35. data/lib/discorb/emoji_table.rb +3799 -0
  36. data/lib/discorb/error.rb +98 -0
  37. data/lib/discorb/event.rb +35 -0
  38. data/lib/discorb/extend.rb +18 -0
  39. data/lib/discorb/extension.rb +54 -0
  40. data/lib/discorb/file.rb +69 -0
  41. data/lib/discorb/flag.rb +109 -0
  42. data/lib/discorb/gateway.rb +967 -0
  43. data/lib/discorb/gateway_requests.rb +47 -0
  44. data/lib/discorb/guild.rb +1244 -0
  45. data/lib/discorb/guild_template.rb +211 -0
  46. data/lib/discorb/image.rb +43 -0
  47. data/lib/discorb/integration.rb +111 -0
  48. data/lib/discorb/intents.rb +137 -0
  49. data/lib/discorb/interaction.rb +333 -0
  50. data/lib/discorb/internet.rb +285 -0
  51. data/lib/discorb/invite.rb +145 -0
  52. data/lib/discorb/log.rb +70 -0
  53. data/lib/discorb/member.rb +232 -0
  54. data/lib/discorb/message.rb +583 -0
  55. data/lib/discorb/modules.rb +138 -0
  56. data/lib/discorb/permission.rb +270 -0
  57. data/lib/discorb/presence.rb +308 -0
  58. data/lib/discorb/reaction.rb +48 -0
  59. data/lib/discorb/role.rb +189 -0
  60. data/lib/discorb/sticker.rb +157 -0
  61. data/lib/discorb/user.rb +163 -0
  62. data/lib/discorb/utils.rb +16 -0
  63. data/lib/discorb/voice_state.rb +251 -0
  64. data/lib/discorb/webhook.rb +420 -0
  65. data/lib/discorb.rb +51 -0
  66. metadata +120 -0
@@ -0,0 +1,123 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Discorb
4
+ API_BASE_URL = "https://discord.com/api/v9"
5
+ VERSION = "0.0.1"
6
+ USER_AGENT = "DiscordBot (https://github.com/discorb-lib/discorb #{VERSION}) Ruby/#{RUBY_VERSION}"
7
+
8
+ #
9
+ # @abstract
10
+ # Represents Discord model.
11
+ #
12
+ class DiscordModel
13
+ def eql?(other)
14
+ self == other
15
+ end
16
+
17
+ def ==(other)
18
+ if respond_to?(:id) && other.respond_to?(:id)
19
+ id == other.id
20
+ else
21
+ super
22
+ end
23
+ end
24
+
25
+ # @!visibility private
26
+ def inspect
27
+ super
28
+ end
29
+
30
+ def hash
31
+ @id.hash
32
+ end
33
+ end
34
+
35
+ #
36
+ # Represents Snowflake of Discord.
37
+ #
38
+ # @see https://discord.com/developers/docs/reference#snowflakes Official Discord API docs
39
+ class Snowflake < DiscordModel
40
+ # @!visibility private
41
+ def initialize(value)
42
+ @value = value.to_i
43
+ end
44
+
45
+ # @!attribute [r] timestamp
46
+ # Timestamp of snowflake.
47
+ #
48
+ # @return [Time] Timestamp of snowflake.
49
+ #
50
+ # @!attribute [r] worker_id
51
+ # Worker ID of snowflake.
52
+ #
53
+ # @return [Integer] Worker ID of snowflake.
54
+ #
55
+ # @!attribute [r] process_id
56
+ # Process ID of snowflake.
57
+ #
58
+ # @return [Integer] Process ID of snowflake.
59
+ # @!attribute [r] increment
60
+ # Increment of snowflake.
61
+ #
62
+ # @return [Integer] Increment of snowflake.
63
+
64
+ #
65
+ # Stringify snowflake.
66
+ #
67
+ # @return [String] Stringified snowflake.
68
+ #
69
+ def to_s
70
+ @value.to_s
71
+ end
72
+
73
+ #
74
+ # Integerize snowflake.
75
+ #
76
+ # @return [Integer] Integerized snowflake.
77
+ #
78
+ def to_i
79
+ @value.to_i
80
+ end
81
+
82
+ #
83
+ # Compares snowflake with other object.
84
+ #
85
+ # @param [#to_s] other Object to compare with.
86
+ #
87
+ # @return [Boolean] True if snowflake is equal to other object.
88
+ #
89
+ def ==(other)
90
+ return false unless other.respond_to?(:to_s)
91
+
92
+ to_s == other.to_s
93
+ end
94
+
95
+ #
96
+ # Alias of {#==}.
97
+ #
98
+ def eql?(other)
99
+ self == other
100
+ end
101
+
102
+ # Return hash of snowflake.
103
+ def hash
104
+ to_s.hash
105
+ end
106
+
107
+ def timestamp
108
+ Time.at(((sf >> 22) + 1_420_070_400_000) / 1000)
109
+ end
110
+
111
+ def worker_id
112
+ (snowflake & 0x3E0000) >> 17
113
+ end
114
+
115
+ def process_id
116
+ (snowflake & 0x1F000) >> 12
117
+ end
118
+
119
+ def increment
120
+ snowflake & 0xFFF
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,290 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Discorb
4
+ #
5
+ # @abstract
6
+ # Represents a Discord component.
7
+ #
8
+ class Component
9
+ class << self
10
+ #
11
+ # Create a new component from hash data.
12
+ #
13
+ # @see https://discord.com/developers/docs/interactions/message-components Official Discord API documentation
14
+ # @param [Hash] data Hash data.
15
+ #
16
+ # @return [Component] A new component.
17
+ #
18
+ def from_hash(data)
19
+ case data[:type]
20
+ when 2
21
+ Button.new(
22
+ data[:label],
23
+ data[:style],
24
+ emoji: data[:emoji],
25
+ custom_id: data[:custom_id],
26
+ url: data[:url],
27
+ disabled: data[:disabled],
28
+ )
29
+ when 3
30
+ SelectMenu.new(
31
+ data[:custom_id],
32
+ data[:options].map { |o| SelectMenu::Option.from_hash(o) },
33
+ placeholder: data[:placeholder],
34
+ min_values: data[:min_values],
35
+ max_values: data[:max_values],
36
+ )
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ #
43
+ # Represents a button component.
44
+ #
45
+ class Button < Component
46
+ # @return [String] The label of the button.
47
+ attr_accessor :label
48
+ # @return [:primary, :secondary, :success, :danger, :link] The style of the button.
49
+ attr_accessor :style
50
+ # @return [Discorb::Emoji] The emoji of the button.
51
+ attr_accessor :emoji
52
+ # @return [String] The custom ID of the button.
53
+ # Won't be used if the style is `:link`.
54
+ attr_accessor :custom_id
55
+ # @return [String] The URL of the button.
56
+ # Only used when the style is `:link`.
57
+ attr_accessor :url
58
+ # @return [Boolean] Whether the button is disabled.
59
+ attr_accessor :disabled
60
+ alias disabled? disabled
61
+
62
+ @styles = {
63
+ primary: 1,
64
+ secondary: 2,
65
+ success: 3,
66
+ danger: 4,
67
+ link: 5,
68
+ }.freeze
69
+
70
+ #
71
+ # Initialize a new button.
72
+ #
73
+ # @param [String] label The label of the button.
74
+ # @param [:primary, :secondary, :success, :danger, :link] style The style of the button.
75
+ # @param [Discorb::Emoji] emoji The emoji of the button.
76
+ # @param [String] custom_id The custom ID of the button.
77
+ # @param [String] url The URL of the button.
78
+ # @param [Boolean] disabled Whether the button is disabled.
79
+ #
80
+ def initialize(label, style = :primary, emoji: nil, custom_id: nil, url: nil, disabled: false)
81
+ @label = label
82
+ @style = style
83
+ @emoji = emoji
84
+ @custom_id = custom_id
85
+ @url = url
86
+ @disabled = disabled
87
+ end
88
+
89
+ #
90
+ # Converts the button to a hash.
91
+ #
92
+ # @see https://discord.com/developers/docs/interactions/message-components#button-object-button-structure Official Discord API docs
93
+ # @return [Hash] A hash representation of the button.
94
+ #
95
+ def to_hash
96
+ if @style == :link
97
+ {
98
+ type: 2,
99
+ label: @label,
100
+ style: self.class.styles[@style],
101
+ url: @url,
102
+ emoji: hash_emoji(@emoji),
103
+ disabled: @disabled,
104
+ }
105
+ else
106
+ {
107
+ type: 2,
108
+ label: @label,
109
+ style: self.class.styles[@style],
110
+ custom_id: @custom_id,
111
+ emoji: hash_emoji(@emoji),
112
+ disabled: @disabled,
113
+ }
114
+ end
115
+ end
116
+
117
+ class << self
118
+ # @!visibility private
119
+ attr_reader :styles
120
+ end
121
+
122
+ private
123
+
124
+ def hash_emoji(emoji)
125
+ case emoji
126
+ when UnicodeEmoji
127
+ {
128
+ id: nil,
129
+ name: emoji.to_s,
130
+ animated: false,
131
+ }
132
+ when CustomEmoji
133
+ {
134
+ id: emoji.id,
135
+ name: emoji.name,
136
+ animated: emoji.animated?,
137
+ }
138
+ end
139
+ end
140
+ end
141
+
142
+ #
143
+ # Represents a select menu component.
144
+ #
145
+ class SelectMenu < Component
146
+ # @return [String] The custom ID of the select menu.
147
+ attr_accessor :custom_id
148
+ # @return [Array<SelectMenu::Option>] The options of the select menu.
149
+ attr_accessor :options
150
+ # @return [Integer] The minimum number of values.
151
+ attr_accessor :min_values
152
+ # @return [Integer] The maximum number of values.
153
+ attr_accessor :max_values
154
+ # @return [Boolean] Whether the select menu is disabled.
155
+ attr_reader :disabled
156
+ alias disabled? disabled
157
+
158
+ #
159
+ # Initialize a new select menu.
160
+ #
161
+ # @param [String, Symbol] custom_id Custom ID of the select menu.
162
+ # @param [Array<Discorb::SelectMenu::Option>] options The options of the select menu.
163
+ # @param [String] placeholder The placeholder of the select menu.
164
+ # @param [Integer] min_values The minimum number of values.
165
+ # @param [Integer] max_values The maximum number of values.
166
+ #
167
+ def initialize(custom_id, options, placeholder: nil, min_values: 1, max_values: 1)
168
+ @custom_id = custom_id
169
+ @options = options
170
+ @placeholder = placeholder
171
+ @min_values = min_values
172
+ @max_values = max_values
173
+ end
174
+
175
+ #
176
+ # Converts the select menu to a hash.
177
+ #
178
+ # @see https://discord.com/developers/docs/interactions/message-components#select-menu-object-select-menu-structure Official Discord API docs
179
+ # @return [Hash] A hash representation of the select menu.
180
+ #
181
+ def to_hash
182
+ {
183
+ type: 3,
184
+ custom_id: @custom_id,
185
+ options: @options.map(&:to_hash),
186
+ placeholder: @placeholder,
187
+ min_values: @min_values,
188
+ max_values: @max_values,
189
+ }
190
+ end
191
+
192
+ #
193
+ # Represents an option of a select menu.
194
+ #
195
+ class Option
196
+ # @return [String] The label of the option.
197
+ attr_accessor :label
198
+ # @return [String] The value of the option.
199
+ attr_accessor :value
200
+ # @return [String] The description of the option.
201
+ attr_accessor :description
202
+ # @return [Discorb::Emoji] The emoji of the option.
203
+ attr_accessor :emoji
204
+ # @return [Boolean] Whether the option is default.
205
+ attr_accessor :default
206
+
207
+ #
208
+ # Initialize a new option.
209
+ #
210
+ # @param [String] label The label of the option.
211
+ # @param [String] value The value of the option.
212
+ # @param [String] description The description of the option.
213
+ # @param [Discorb::Emoji] emoji The emoji of the option.
214
+ # @param [Boolean] default Whether the option is default.
215
+ def initialize(label, value, description: nil, emoji: nil, default: false)
216
+ @label = label
217
+ @value = value
218
+ @description = description
219
+ @emoji = emoji
220
+ @default = default
221
+ end
222
+
223
+ #
224
+ # Converts the option to a hash.
225
+ #
226
+ # @see https://discord.com/developers/docs/interactions/message-components#select-menu-object-select-option-structure Official Discord API docs
227
+ # @return [Hash] Hash representation of the option.
228
+ #
229
+ def to_hash
230
+ {
231
+ label: @label,
232
+ value: @value,
233
+ description: @description,
234
+ emoji: hash_emoji(@emoji),
235
+ default: @default,
236
+ }
237
+ end
238
+
239
+ # @!visibility private
240
+ def hash_emoji(emoji)
241
+ case emoji
242
+ when UnicodeEmoji
243
+ {
244
+ id: nil,
245
+ name: emoji.to_s,
246
+ animated: false,
247
+ }
248
+ when CustomEmoji
249
+ {
250
+ id: emoji.id,
251
+ name: emoji.name,
252
+ animated: emoji.animated?,
253
+ }
254
+ end
255
+ end
256
+
257
+ class << self
258
+ #
259
+ # Creates a new option from a hash.
260
+ #
261
+ # @param [Hash] data A hash representing the option.
262
+ #
263
+ # @return [Discorb::SelectMenu::Option] A new option.
264
+ #
265
+ def from_hash(data)
266
+ new(data[:label], data[:value], description: data[:description], emoji: data[:emoji], default: data[:default])
267
+ end
268
+ end
269
+ end
270
+
271
+ private
272
+
273
+ def hash_emoji(emoji)
274
+ case emoji
275
+ when UnicodeEmoji
276
+ {
277
+ id: nil,
278
+ name: emoji.to_s,
279
+ animated: false,
280
+ }
281
+ when CustomEmoji
282
+ {
283
+ id: emoji.id,
284
+ name: emoji.name,
285
+ animated: emoji.animated?,
286
+ }
287
+ end
288
+ end
289
+ end
290
+ end
@@ -0,0 +1,119 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Discorb
4
+ class Dictionary
5
+ # @return [Integer] The maximum number of items in the dictionary.
6
+ attr_accessor :limit
7
+
8
+ #
9
+ # Initialize a new Dictionary.
10
+ #
11
+ # @param [Hash] hash A hash of items to add to the dictionary.
12
+ # @param [Integer] limit The maximum number of items in the dictionary.
13
+ # @param [false, Proc] sort Whether to sort the items in the dictionary.
14
+ #
15
+ def initialize(hash = {}, limit: nil, sort: false)
16
+ @cache = hash.transform_keys(&:to_s)
17
+ @limit = limit
18
+ @sort = sort
19
+ end
20
+
21
+ #
22
+ # Registers a new item in the dictionary.
23
+ #
24
+ # @param [#to_s] id The ID of the item.
25
+ # @param [Object] body The item to register.
26
+ #
27
+ # @return [self] The dictionary.
28
+ #
29
+ def register(id, body)
30
+ @cache[id.to_s] = body
31
+ @cache = @cache.sort_by(&@sort).to_h if @sort
32
+ @cache.remove(@cache.values[-1]) if !@limit.nil? && @cache.size > @limit
33
+ body
34
+ end
35
+
36
+ #
37
+ # Merges another dictionary into this one.
38
+ #
39
+ # @param [Discorb::Dictionary] other The dictionary to merge.
40
+ #
41
+ def merge(other)
42
+ @cache.merge!(other)
43
+ end
44
+
45
+ #
46
+ # Removes an item from the dictionary.
47
+ #
48
+ # @param [#to_s] id The ID of the item to remove.
49
+ #
50
+ def remove(id)
51
+ @cache.remove(id.to_s)
52
+ end
53
+
54
+ #
55
+ # Get an item from the dictionary.
56
+ #
57
+ # @param [#to_s] id The ID of the item.
58
+ # @return [Object] The item.
59
+ # @return [nil] if the item was not found.
60
+ #
61
+ # @overload get(index)
62
+ # @param [Integer] index The index of the item.
63
+ #
64
+ # @return [Object] The item.
65
+ # @return [nil] if the item is not found.
66
+ #
67
+ def get(id)
68
+ res = @cache[id.to_s]
69
+ if res.nil? && id.is_a?(Integer) && id < @cache.length
70
+ @cache.values[id]
71
+ else
72
+ res
73
+ end
74
+ end
75
+
76
+ #
77
+ # Returns the values of the dictionary.
78
+ #
79
+ # @return [Array] The values of the dictionary.
80
+ #
81
+ def values
82
+ @cache.values
83
+ end
84
+
85
+ #
86
+ # Checks if the dictionary has an ID.
87
+ #
88
+ # @param [#to_s] id The ID to check.
89
+ #
90
+ # @return [Boolean] `true` if the dictionary has the ID, `false` otherwise.
91
+ #
92
+ def has?(id)
93
+ !self[id].nil?
94
+ end
95
+
96
+ def method_missing(name, ...)
97
+ if values.respond_to?(name)
98
+ values.send(name, ...)
99
+ else
100
+ super
101
+ end
102
+ end
103
+
104
+ def respond_to_missing?(name, args, kwargs)
105
+ if values.respond_to?(name)
106
+ true
107
+ else
108
+ super
109
+ end
110
+ end
111
+
112
+ alias [] get
113
+ alias []= register
114
+
115
+ def inspect
116
+ "#<#{self.class} #{values.length} items>"
117
+ end
118
+ end
119
+ end