discorb 0.16.0 → 0.17.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.
Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +1 -0
  3. data/.github/workflows/build_main.yml +2 -2
  4. data/.github/workflows/build_version.yml +1 -1
  5. data/.github/workflows/codeql-analysis.yml +1 -1
  6. data/.github/workflows/lint-push.yml +3 -5
  7. data/.github/workflows/lint.yml +1 -1
  8. data/.github/workflows/spec.yml +30 -0
  9. data/.lefthook/commit-msg/validator.rb +5 -0
  10. data/.rspec +2 -0
  11. data/.rspec_parallel +2 -0
  12. data/.rubocop.yml +43 -6
  13. data/Changelog.md +14 -1
  14. data/Gemfile +14 -8
  15. data/Rakefile +41 -26
  16. data/bin/console +3 -3
  17. data/docs/Examples.md +1 -1
  18. data/docs/application_command.md +138 -46
  19. data/docs/cli/irb.md +2 -2
  20. data/docs/cli/new.md +14 -9
  21. data/docs/cli/run.md +7 -11
  22. data/docs/cli.md +17 -10
  23. data/docs/events.md +209 -211
  24. data/docs/extension.md +1 -2
  25. data/docs/faq.md +0 -1
  26. data/docs/tutorial.md +12 -12
  27. data/docs/voice_events.md +106 -106
  28. data/examples/commands/message.rb +63 -0
  29. data/examples/commands/permission.rb +18 -0
  30. data/examples/commands/slash.rb +44 -0
  31. data/examples/commands/user.rb +51 -0
  32. data/examples/components/authorization_button.rb +2 -2
  33. data/examples/components/select_menu.rb +2 -2
  34. data/examples/extension/main.rb +1 -1
  35. data/examples/extension/message_expander.rb +5 -2
  36. data/examples/simple/eval.rb +2 -2
  37. data/examples/simple/ping_pong.rb +1 -1
  38. data/examples/simple/rolepanel.rb +1 -1
  39. data/examples/simple/shard.rb +1 -1
  40. data/examples/simple/wait_for_message.rb +1 -1
  41. data/exe/discorb +31 -16
  42. data/lefthook.yml +45 -0
  43. data/lib/discorb/allowed_mentions.rb +1 -0
  44. data/lib/discorb/app_command/command.rb +127 -65
  45. data/lib/discorb/app_command/common.rb +25 -0
  46. data/lib/discorb/app_command/handler.rb +115 -33
  47. data/lib/discorb/app_command.rb +2 -1
  48. data/lib/discorb/application.rb +1 -0
  49. data/lib/discorb/asset.rb +1 -2
  50. data/lib/discorb/attachment.rb +1 -1
  51. data/lib/discorb/audit_logs.rb +11 -8
  52. data/lib/discorb/channel/base.rb +108 -0
  53. data/lib/discorb/channel/category.rb +32 -0
  54. data/lib/discorb/channel/container.rb +44 -0
  55. data/lib/discorb/channel/dm.rb +28 -0
  56. data/lib/discorb/channel/guild.rb +245 -0
  57. data/lib/discorb/channel/stage.rb +140 -0
  58. data/lib/discorb/channel/text.rb +345 -0
  59. data/lib/discorb/channel/thread.rb +321 -0
  60. data/lib/discorb/channel/voice.rb +79 -0
  61. data/lib/discorb/channel.rb +2 -1165
  62. data/lib/discorb/client.rb +38 -26
  63. data/lib/discorb/common.rb +2 -1
  64. data/lib/discorb/components/button.rb +2 -1
  65. data/lib/discorb/components/select_menu.rb +4 -2
  66. data/lib/discorb/components/text_input.rb +12 -2
  67. data/lib/discorb/components.rb +1 -1
  68. data/lib/discorb/embed.rb +22 -7
  69. data/lib/discorb/emoji.rb +30 -3
  70. data/lib/discorb/emoji_table.rb +4969 -3
  71. data/lib/discorb/event.rb +29 -4
  72. data/lib/discorb/exe/about.rb +1 -0
  73. data/lib/discorb/exe/irb.rb +2 -4
  74. data/lib/discorb/exe/new.rb +90 -23
  75. data/lib/discorb/exe/run.rb +8 -22
  76. data/lib/discorb/exe/setup.rb +25 -12
  77. data/lib/discorb/exe/show.rb +4 -3
  78. data/lib/discorb/extend.rb +1 -0
  79. data/lib/discorb/extension.rb +6 -3
  80. data/lib/discorb/flag.rb +11 -0
  81. data/lib/discorb/gateway.rb +67 -19
  82. data/lib/discorb/guild.rb +188 -56
  83. data/lib/discorb/guild_template.rb +10 -4
  84. data/lib/discorb/http.rb +16 -9
  85. data/lib/discorb/integration.rb +4 -1
  86. data/lib/discorb/intents.rb +1 -1
  87. data/lib/discorb/interaction/autocomplete.rb +28 -16
  88. data/lib/discorb/interaction/command.rb +36 -12
  89. data/lib/discorb/interaction/components.rb +5 -2
  90. data/lib/discorb/interaction/modal.rb +0 -1
  91. data/lib/discorb/interaction/response.rb +61 -22
  92. data/lib/discorb/interaction/root.rb +13 -13
  93. data/lib/discorb/interaction.rb +1 -0
  94. data/lib/discorb/invite.rb +5 -2
  95. data/lib/discorb/member.rb +25 -5
  96. data/lib/discorb/message.rb +47 -14
  97. data/lib/discorb/message_meta.rb +1 -0
  98. data/lib/discorb/modules.rb +56 -14
  99. data/lib/discorb/presence.rb +2 -2
  100. data/lib/discorb/rate_limit.rb +7 -2
  101. data/lib/discorb/reaction.rb +4 -4
  102. data/lib/discorb/role.rb +19 -4
  103. data/lib/discorb/shard.rb +1 -1
  104. data/lib/discorb/sticker.rb +8 -7
  105. data/lib/discorb/user.rb +2 -1
  106. data/lib/discorb/utils/colored_puts.rb +1 -0
  107. data/lib/discorb/voice_state.rb +10 -6
  108. data/lib/discorb/webhook.rb +36 -24
  109. data/lib/discorb.rb +5 -3
  110. data/po/yard.pot +9 -9
  111. data/sig/discorb.rbs +7232 -7235
  112. metadata +21 -5
  113. data/examples/commands/bookmarker.rb +0 -42
  114. data/examples/commands/hello.rb +0 -10
  115. data/examples/commands/inspect.rb +0 -25
@@ -0,0 +1,245 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Discorb
4
+ #
5
+ # Represents a channel in guild.
6
+ # @abstract
7
+ #
8
+ class GuildChannel < Channel
9
+ # @return [Integer] The position of the channel as integer.
10
+ attr_reader :position
11
+ # @return [Hash{Discorb::Role, Discorb::Member => PermissionOverwrite}] The permission overwrites of the channel.
12
+ attr_reader :permission_overwrites
13
+
14
+ # @!attribute [r] mention
15
+ # @return [String] The mention of the channel.
16
+ #
17
+ # @!attribute [r] parent
18
+ # @macro client_cache
19
+ # @return [Discorb::CategoryChannel] The parent of channel.
20
+ # @return [nil] If the channel is not a child of category.
21
+ #
22
+ # @!attribute [r] guild
23
+ # @return [Discorb::Guild] The guild of channel.
24
+ # @macro client_cache
25
+
26
+ include Comparable
27
+ @channel_type = nil
28
+
29
+ #
30
+ # Compares position of two channels.
31
+ #
32
+ # @param [Discorb::GuildChannel] other The channel to compare.
33
+ #
34
+ # @return [-1, 0, 1] -1 if the channel is at lower than the other, 1 if the channel is at highter than the other.
35
+ #
36
+ def <=>(other)
37
+ return 0 unless other.respond_to?(:position)
38
+
39
+ @position <=> other.position
40
+ end
41
+
42
+ #
43
+ # Checks if the channel is same as another.
44
+ #
45
+ # @param [Discorb::GuildChannel] other The channel to check.
46
+ #
47
+ # @return [Boolean] `true` if the channel is same as another.
48
+ #
49
+ def ==(other)
50
+ return false unless other.respond_to?(:id)
51
+
52
+ @id == other.id
53
+ end
54
+
55
+ #
56
+ # Stringifies the channel.
57
+ #
58
+ # @return [String] The name of the channel with `#`.
59
+ #
60
+ def to_s
61
+ "##{@name}"
62
+ end
63
+
64
+ def mention
65
+ "<##{@id}>"
66
+ end
67
+
68
+ def parent
69
+ return nil unless @parent_id
70
+
71
+ @client.channels[@parent_id]
72
+ end
73
+
74
+ alias category parent
75
+
76
+ def guild
77
+ @client.guilds[@guild_id]
78
+ end
79
+
80
+ def inspect
81
+ "#<#{self.class} \"##{@name}\" id=#{@id}>"
82
+ end
83
+
84
+ #
85
+ # Deletes the channel.
86
+ # @async
87
+ #
88
+ # @param [String] reason The reason of deleting the channel.
89
+ #
90
+ # @return [Async::Task<self>] The deleted channel.
91
+ #
92
+ def delete!(reason: nil)
93
+ Async do
94
+ @client.http.request(Route.new(base_url.wait.to_s, "//webhooks/:webhook_id/:token", :delete), {},
95
+ audit_log_reason: reason).wait
96
+ @deleted = true
97
+ self
98
+ end
99
+ end
100
+
101
+ alias close! delete!
102
+ alias destroy! delete!
103
+
104
+ #
105
+ # Moves the channel to another position.
106
+ # @async
107
+ #
108
+ # @param [Integer] position The position to move the channel.
109
+ # @param [Boolean] lock_permissions Whether to lock the permissions of the channel.
110
+ # @param [Discorb::CategoryChannel] parent The parent of channel.
111
+ # @param [String] reason The reason of moving the channel.
112
+ #
113
+ # @return [Async::Task<self>] The moved channel.
114
+ #
115
+ def move(position, lock_permissions: false, parent: Discorb::Unset, reason: nil)
116
+ Async do
117
+ payload = {
118
+ position: position,
119
+ }
120
+ payload[:lock_permissions] = lock_permissions
121
+ payload[:parent_id] = parent&.id if parent != Discorb::Unset
122
+ @client.http.request(Route.new("/guilds/#{@guild_id}/channels", "//guilds/:guild_id/channels", :patch),
123
+ payload, audit_log_reason: reason).wait
124
+ end
125
+ end
126
+
127
+ #
128
+ # Set the channel's permission overwrite.
129
+ # @async
130
+ #
131
+ # @param [Discorb::Role, Discorb::Member] target The target of the overwrite.
132
+ # @param [String] reason The reason of setting the overwrite.
133
+ # @param [{Symbol => Boolean}] perms The permission overwrites to replace.
134
+ #
135
+ # @return [Async::Task<void>] The task.
136
+ #
137
+ def set_permissions(target, reason: nil, **perms)
138
+ Async do
139
+ allow_value = @permission_overwrites[target]&.allow_value.to_i
140
+ deny_value = @permission_overwrites[target]&.deny_value.to_i
141
+ perms.each do |perm, value|
142
+ allow_value[Discorb::Permission.bits[perm]] = 1 if value == true
143
+ deny_value[Discorb::Permission.bits[perm]] = 1 if value == false
144
+ end
145
+ payload = {
146
+ allow: allow_value,
147
+ deny: deny_value,
148
+ type: target.is_a?(Member) ? 1 : 0,
149
+ }
150
+ @client.http.request(
151
+ Route.new("/channels/#{@id}/permissions/#{target.id}", "//channels/:channel_id/permissions/:target_id",
152
+ :put), payload, audit_log_reason: reason,
153
+ ).wait
154
+ end
155
+ end
156
+
157
+ alias modify_permissions set_permissions
158
+ alias modify_permisssion set_permissions
159
+ alias edit_permissions set_permissions
160
+ alias edit_permission set_permissions
161
+
162
+ #
163
+ # Delete the channel's permission overwrite.
164
+ # @async
165
+ #
166
+ # @param [Discorb::Role, Discorb::Member] target The target of the overwrite.
167
+ # @param [String] reason The reason of deleting the overwrite.
168
+ #
169
+ # @return [Async::Task<void>] The task.
170
+ #
171
+ def delete_permissions(target, reason: nil)
172
+ Async do
173
+ @client.http.request(
174
+ Route.new("/channels/#{@id}/permissions/#{target.id}", "//channels/:channel_id/permissions/:target_id",
175
+ :delete), {}, audit_log_reason: reason,
176
+ ).wait
177
+ end
178
+ end
179
+
180
+ alias delete_permission delete_permissions
181
+ alias destroy_permissions delete_permissions
182
+ alias destroy_permission delete_permissions
183
+
184
+ #
185
+ # Fetch the channel's invites.
186
+ # @async
187
+ #
188
+ # @return [Async::Task<Array<Discorb::Invite>>] The invites in the channel.
189
+ #
190
+ def fetch_invites
191
+ Async do
192
+ _resp, data = @client.http.request(Route.new("/channels/#{@id}/invites", "//channels/:channel_id/invites",
193
+ :get)).wait
194
+ data.map { |invite| Invite.new(@client, invite, false) }
195
+ end
196
+ end
197
+
198
+ #
199
+ # Create an invite in the channel.
200
+ # @async
201
+ #
202
+ # @param [Integer] max_age The max age of the invite.
203
+ # @param [Integer] max_uses The max uses of the invite.
204
+ # @param [Boolean] temporary Whether the invite is temporary.
205
+ # @param [Boolean] unique Whether the invite is unique.
206
+ # @note if it's `false` it may return existing invite.
207
+ # @param [String] reason The reason of creating the invite.
208
+ #
209
+ # @return [Async::Task<Invite>] The created invite.
210
+ #
211
+ def create_invite(max_age: nil, max_uses: nil, temporary: false, unique: false, reason: nil)
212
+ Async do
213
+ _resp, data = @client.http.request(
214
+ Route.new("/channels/#{@id}/invites", "//channels/:channel_id/invites", :post), {
215
+ max_age: max_age,
216
+ max_uses: max_uses,
217
+ temporary: temporary,
218
+ unique: unique,
219
+ }, audit_log_reason: reason,
220
+ ).wait
221
+ Invite.new(@client, data, false)
222
+ end
223
+ end
224
+
225
+ private
226
+
227
+ def _set_data(data)
228
+ @guild_id = data[:guild_id]
229
+ @position = data[:position]
230
+ @permission_overwrites = if data[:permission_overwrites]
231
+ data[:permission_overwrites].to_h do |ow|
232
+ [
233
+ (ow[:type] == 1 ? guild.roles : guild.members)[ow[:id]],
234
+ PermissionOverwrite.new(ow[:allow].to_i, ow[:deny].to_i),
235
+ ]
236
+ end
237
+ else
238
+ {}
239
+ end
240
+ @parent_id = data[:parent_id]
241
+
242
+ super
243
+ end
244
+ end
245
+ end
@@ -0,0 +1,140 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Discorb
4
+ #
5
+ # Represents a stage channel.
6
+ #
7
+ class StageChannel < GuildChannel
8
+ # @return [Integer] The bitrate of the voice channel.
9
+ attr_reader :bitrate
10
+ # @return [Integer] The user limit of the voice channel.
11
+ attr_reader :user_limit
12
+ #
13
+ # @private
14
+ # @return [Discorb::Dictionary{Discorb::Snowflake => StageInstance}]
15
+ # The stage instances associated with the stage channel.
16
+ #
17
+ attr_reader :stage_instances
18
+
19
+ include Connectable
20
+
21
+ # @!attribute [r] stage_instance
22
+ # @return [Discorb::StageInstance] The stage instance of the channel.
23
+
24
+ @channel_type = 13
25
+ #
26
+ # Initialize a new stage channel.
27
+ # @private
28
+ #
29
+ def initialize(...)
30
+ @stage_instances = Dictionary.new
31
+ super(...)
32
+ end
33
+
34
+ def stage_instance
35
+ @stage_instances[0]
36
+ end
37
+
38
+ #
39
+ # Edit the stage channel.
40
+ # @async
41
+ # @macro edit
42
+ #
43
+ # @param [String] name The name of the stage channel.
44
+ # @param [Integer] position The position of the stage channel.
45
+ # @param [Integer] bitrate The bitrate of the stage channel.
46
+ # @param [Symbol] rtc_region The region of the stage channel.
47
+ # @param [String] reason The reason of editing the stage channel.
48
+ #
49
+ # @return [Async::Task<self>] The edited stage channel.
50
+ #
51
+ def edit(
52
+ name: Discorb::Unset,
53
+ position: Discorb::Unset,
54
+ bitrate: Discorb::Unset,
55
+ rtc_region: Discorb::Unset,
56
+ reason: nil
57
+ )
58
+ Async do
59
+ payload = {}
60
+ payload[:name] = name if name != Discorb::Unset
61
+ payload[:position] = position if position != Discorb::Unset
62
+ payload[:bitrate] = bitrate if bitrate != Discorb::Unset
63
+ payload[:rtc_region] = rtc_region if rtc_region != Discorb::Unset
64
+ @client.http.request(Route.new("/channels/#{@id}", "//channels/:channel_id", :patch), payload,
65
+ audit_log_reason: reason).wait
66
+ self
67
+ end
68
+ end
69
+
70
+ alias modify edit
71
+
72
+ #
73
+ # Start a stage instance.
74
+ # @async
75
+ #
76
+ # @param [String] topic The topic of the stage instance.
77
+ # @param [Boolean] public Whether the stage instance is public or not.
78
+ # @param [String] reason The reason of starting the stage instance.
79
+ #
80
+ # @return [Async::Task<Discorb::StageInstance>] The started stage instance.
81
+ #
82
+ def start(topic, public: false, reason: nil)
83
+ Async do
84
+ _resp, data = @client.http.request(
85
+ Route.new("/stage-instances", "//stage-instances", :post),
86
+ {
87
+ channel_id: @id,
88
+ topic: topic,
89
+ public: public ? 2 : 1,
90
+ }, audit_log_reason: reason,
91
+ ).wait
92
+ StageInstance.new(@client, data)
93
+ end
94
+ end
95
+
96
+ #
97
+ # Fetch a current stage instance.
98
+ # @async
99
+ #
100
+ # @return [Async::Task<StageInstance>] The current stage instance.
101
+ # @return [Async::Task<nil>] If there is no current stage instance.
102
+ #
103
+ def fetch_stage_instance
104
+ Async do
105
+ _resp, data = @client.http.request(Route.new("/stage-instances/#{@id}", "//stage-instances/:stage_instance_id",
106
+ :get)).wait
107
+ rescue Discorb::NotFoundError
108
+ nil
109
+ else
110
+ StageInstance.new(@client, data)
111
+ end
112
+ end
113
+
114
+ def voice_states
115
+ guild.voice_states.select { |state| state.channel&.id == @id }
116
+ end
117
+
118
+ def members
119
+ voice_states.map(&:member)
120
+ end
121
+
122
+ def speakers
123
+ voice_states.filter { |state| !state.suppress? }.map(&:member)
124
+ end
125
+
126
+ def audiences
127
+ voice_states.filter(&:suppress?).map(&:member)
128
+ end
129
+
130
+ private
131
+
132
+ def _set_data(data)
133
+ @bitrate = data[:bitrate]
134
+ @user_limit = data[:user_limit]
135
+ @topic = data[:topic]
136
+ @rtc_region = data[:rtc_region]&.to_sym
137
+ super
138
+ end
139
+ end
140
+ end