discorb 0.0.1
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/.gitignore +56 -0
- data/.yardopts +6 -0
- data/Changelog.md +5 -0
- data/Gemfile +23 -0
- data/Gemfile.lock +70 -0
- data/LICENSE.txt +21 -0
- data/README.md +53 -0
- data/Rakefile +46 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/discorb.gemspec +37 -0
- data/docs/Examples.md +26 -0
- data/docs/events.md +480 -0
- data/docs/voice_events.md +283 -0
- data/examples/components/authorization_button.rb +43 -0
- data/examples/components/select_menu.rb +61 -0
- data/examples/extension/main.rb +12 -0
- data/examples/extension/message_expander.rb +41 -0
- data/examples/simple/eval.rb +32 -0
- data/examples/simple/ping_pong.rb +16 -0
- data/examples/simple/rolepanel.rb +65 -0
- data/examples/simple/wait_for_message.rb +30 -0
- data/lib/discorb/application.rb +157 -0
- data/lib/discorb/asset.rb +57 -0
- data/lib/discorb/audit_logs.rb +323 -0
- data/lib/discorb/channel.rb +1101 -0
- data/lib/discorb/client.rb +363 -0
- data/lib/discorb/color.rb +173 -0
- data/lib/discorb/common.rb +123 -0
- data/lib/discorb/components.rb +290 -0
- data/lib/discorb/dictionary.rb +119 -0
- data/lib/discorb/embed.rb +345 -0
- data/lib/discorb/emoji.rb +218 -0
- data/lib/discorb/emoji_table.rb +3799 -0
- data/lib/discorb/error.rb +98 -0
- data/lib/discorb/event.rb +35 -0
- data/lib/discorb/extend.rb +18 -0
- data/lib/discorb/extension.rb +54 -0
- data/lib/discorb/file.rb +69 -0
- data/lib/discorb/flag.rb +109 -0
- data/lib/discorb/gateway.rb +967 -0
- data/lib/discorb/gateway_requests.rb +47 -0
- data/lib/discorb/guild.rb +1244 -0
- data/lib/discorb/guild_template.rb +211 -0
- data/lib/discorb/image.rb +43 -0
- data/lib/discorb/integration.rb +111 -0
- data/lib/discorb/intents.rb +137 -0
- data/lib/discorb/interaction.rb +333 -0
- data/lib/discorb/internet.rb +285 -0
- data/lib/discorb/invite.rb +145 -0
- data/lib/discorb/log.rb +70 -0
- data/lib/discorb/member.rb +232 -0
- data/lib/discorb/message.rb +583 -0
- data/lib/discorb/modules.rb +138 -0
- data/lib/discorb/permission.rb +270 -0
- data/lib/discorb/presence.rb +308 -0
- data/lib/discorb/reaction.rb +48 -0
- data/lib/discorb/role.rb +189 -0
- data/lib/discorb/sticker.rb +157 -0
- data/lib/discorb/user.rb +163 -0
- data/lib/discorb/utils.rb +16 -0
- data/lib/discorb/voice_state.rb +251 -0
- data/lib/discorb/webhook.rb +420 -0
- data/lib/discorb.rb +51 -0
- 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
|