discorb 0.16.0 → 0.18.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 (199) 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 +2 -4
  8. data/.github/workflows/spec.yml +33 -0
  9. data/.github/workflows/validate.yml +21 -0
  10. data/.gitignore +2 -0
  11. data/.lefthook/commit-msg/validator.rb +5 -0
  12. data/.rspec +2 -0
  13. data/.rspec_parallel +2 -0
  14. data/.rubocop.yml +43 -6
  15. data/Changelog.md +30 -1
  16. data/Gemfile +20 -8
  17. data/Rakefile +226 -98
  18. data/Steepfile +28 -0
  19. data/bin/console +3 -3
  20. data/docs/Examples.md +1 -1
  21. data/docs/application_command.md +156 -47
  22. data/docs/cli/irb.md +2 -2
  23. data/docs/cli/new.md +14 -9
  24. data/docs/cli/run.md +7 -11
  25. data/docs/cli.md +17 -10
  26. data/docs/events.md +247 -213
  27. data/docs/extension.md +1 -2
  28. data/docs/faq.md +0 -1
  29. data/docs/tutorial.md +18 -18
  30. data/docs/voice_events.md +106 -106
  31. data/examples/commands/message.rb +68 -0
  32. data/examples/commands/permission.rb +19 -0
  33. data/examples/commands/slash.rb +48 -0
  34. data/examples/commands/user.rb +54 -0
  35. data/examples/components/authorization_button.rb +4 -3
  36. data/examples/components/select_menu.rb +6 -3
  37. data/examples/extension/main.rb +2 -1
  38. data/examples/extension/message_expander.rb +6 -2
  39. data/examples/sig/commands/message.rbs +5 -0
  40. data/examples/simple/eval.rb +3 -2
  41. data/examples/simple/ping_pong.rb +2 -1
  42. data/examples/simple/rolepanel.rb +17 -6
  43. data/examples/simple/shard.rb +3 -2
  44. data/examples/simple/wait_for_message.rb +4 -1
  45. data/exe/discorb +33 -18
  46. data/lefthook.yml +45 -0
  47. data/lib/discorb/allowed_mentions.rb +2 -1
  48. data/lib/discorb/app_command/command.rb +130 -72
  49. data/lib/discorb/app_command/common.rb +25 -0
  50. data/lib/discorb/app_command/handler.rb +130 -33
  51. data/lib/discorb/app_command.rb +2 -1
  52. data/lib/discorb/application.rb +1 -0
  53. data/lib/discorb/asset.rb +1 -2
  54. data/lib/discorb/attachment.rb +1 -1
  55. data/lib/discorb/audit_logs.rb +19 -10
  56. data/lib/discorb/automod.rb +269 -0
  57. data/lib/discorb/channel/base.rb +108 -0
  58. data/lib/discorb/channel/category.rb +32 -0
  59. data/lib/discorb/channel/container.rb +44 -0
  60. data/lib/discorb/channel/dm.rb +28 -0
  61. data/lib/discorb/channel/guild.rb +246 -0
  62. data/lib/discorb/channel/stage.rb +140 -0
  63. data/lib/discorb/channel/text.rb +336 -0
  64. data/lib/discorb/channel/thread.rb +325 -0
  65. data/lib/discorb/channel/voice.rb +79 -0
  66. data/lib/discorb/channel.rb +2 -1165
  67. data/lib/discorb/client.rb +50 -36
  68. data/lib/discorb/color.rb +37 -60
  69. data/lib/discorb/common.rb +2 -1
  70. data/lib/discorb/components/button.rb +2 -1
  71. data/lib/discorb/components/select_menu.rb +4 -2
  72. data/lib/discorb/components/text_input.rb +12 -2
  73. data/lib/discorb/components.rb +1 -1
  74. data/lib/discorb/dictionary.rb +1 -1
  75. data/lib/discorb/embed.rb +26 -10
  76. data/lib/discorb/emoji.rb +31 -4
  77. data/lib/discorb/emoji_table.rb +4969 -3
  78. data/lib/discorb/event.rb +29 -4
  79. data/lib/discorb/exe/about.rb +2 -1
  80. data/lib/discorb/exe/irb.rb +2 -4
  81. data/lib/discorb/exe/new.rb +89 -26
  82. data/lib/discorb/exe/run.rb +8 -22
  83. data/lib/discorb/exe/setup.rb +25 -12
  84. data/lib/discorb/exe/show.rb +4 -3
  85. data/lib/discorb/extend.rb +1 -0
  86. data/lib/discorb/extension.rb +6 -7
  87. data/lib/discorb/flag.rb +13 -2
  88. data/lib/discorb/gateway.rb +79 -589
  89. data/lib/discorb/gateway_events.rb +638 -0
  90. data/lib/discorb/guild.rb +318 -67
  91. data/lib/discorb/guild_template.rb +11 -5
  92. data/lib/discorb/http.rb +53 -24
  93. data/lib/discorb/integration.rb +4 -1
  94. data/lib/discorb/intents.rb +28 -19
  95. data/lib/discorb/interaction/autocomplete.rb +28 -16
  96. data/lib/discorb/interaction/command.rb +42 -14
  97. data/lib/discorb/interaction/components.rb +5 -2
  98. data/lib/discorb/interaction/modal.rb +0 -1
  99. data/lib/discorb/interaction/response.rb +125 -26
  100. data/lib/discorb/interaction/root.rb +13 -13
  101. data/lib/discorb/interaction.rb +1 -0
  102. data/lib/discorb/invite.rb +5 -2
  103. data/lib/discorb/member.rb +28 -8
  104. data/lib/discorb/message.rb +60 -25
  105. data/lib/discorb/message_meta.rb +3 -3
  106. data/lib/discorb/modules.rb +59 -16
  107. data/lib/discorb/presence.rb +2 -0
  108. data/lib/discorb/rate_limit.rb +7 -2
  109. data/lib/discorb/reaction.rb +2 -2
  110. data/lib/discorb/role.rb +20 -5
  111. data/lib/discorb/shard.rb +1 -1
  112. data/lib/discorb/sticker.rb +9 -8
  113. data/lib/discorb/user.rb +4 -3
  114. data/lib/discorb/utils/colored_puts.rb +1 -0
  115. data/lib/discorb/voice_state.rb +6 -2
  116. data/lib/discorb/webhook.rb +64 -31
  117. data/lib/discorb.rb +7 -5
  118. data/po/yard.pot +20 -20
  119. data/rbs_collection.lock.yaml +88 -0
  120. data/rbs_collection.yaml +21 -0
  121. data/sig/async.rbs +11 -0
  122. data/sig/discorb/activity.rbs +23 -0
  123. data/sig/discorb/allowed_mentions.rbs +44 -0
  124. data/sig/discorb/app_command/base.rbs +282 -0
  125. data/sig/discorb/app_command/handler.rbs +171 -0
  126. data/sig/discorb/application.rbs +142 -0
  127. data/sig/discorb/asset.rbs +32 -0
  128. data/sig/discorb/attachment.rbs +91 -0
  129. data/sig/discorb/audit_log.rbs +231 -0
  130. data/sig/discorb/automod.rbs +128 -0
  131. data/sig/discorb/avatar.rbs +26 -0
  132. data/sig/discorb/channel/base.rbs +179 -0
  133. data/sig/discorb/channel/category.rbs +56 -0
  134. data/sig/discorb/channel/container.rbs +29 -0
  135. data/sig/discorb/channel/dm.rbs +14 -0
  136. data/sig/discorb/channel/news.rbs +20 -0
  137. data/sig/discorb/channel/stage.rbs +77 -0
  138. data/sig/discorb/channel/text.rbs +158 -0
  139. data/sig/discorb/channel/thread.rbs +185 -0
  140. data/sig/discorb/channel/voice.rbs +41 -0
  141. data/sig/discorb/client.rbs +2495 -0
  142. data/sig/discorb/color.rbs +142 -0
  143. data/sig/discorb/component/base.rbs +28 -0
  144. data/sig/discorb/component/button.rbs +65 -0
  145. data/sig/discorb/component/select_menu.rbs +107 -0
  146. data/sig/discorb/component/text_input.rbs +69 -0
  147. data/sig/discorb/connectable.rbs +8 -0
  148. data/sig/discorb/custom_emoji.rbs +90 -0
  149. data/sig/discorb/dictionary.rbs +85 -0
  150. data/sig/discorb/discord_model.rbs +15 -0
  151. data/sig/discorb/embed.rbs +279 -0
  152. data/sig/discorb/emoji.rbs +13 -0
  153. data/sig/discorb/error.rbs +73 -0
  154. data/sig/discorb/event_handler.rbs +27 -0
  155. data/sig/discorb/extension.rbs +1734 -0
  156. data/sig/discorb/flag.rbs +72 -0
  157. data/sig/discorb/gateway.rbs +481 -0
  158. data/sig/discorb/guild.rbs +870 -0
  159. data/sig/discorb/guild_template.rbs +174 -0
  160. data/sig/discorb/http.rbs +147 -0
  161. data/sig/discorb/image.rbs +20 -0
  162. data/sig/discorb/integration.rbs +118 -0
  163. data/sig/discorb/intents.rbs +97 -0
  164. data/sig/discorb/interaction/autocomplete.rbs +9 -0
  165. data/sig/discorb/interaction/base.rbs +66 -0
  166. data/sig/discorb/interaction/command.rbs +66 -0
  167. data/sig/discorb/interaction/message_component.rbs +140 -0
  168. data/sig/discorb/interaction/modal.rbs +50 -0
  169. data/sig/discorb/interaction/responder.rbs +157 -0
  170. data/sig/discorb/invite.rbs +86 -0
  171. data/sig/discorb/member.rbs +187 -0
  172. data/sig/discorb/message.rbs +469 -0
  173. data/sig/discorb/messageable.rbs +153 -0
  174. data/sig/discorb/partial_emoji.rbs +35 -0
  175. data/sig/discorb/permissions.rbs +149 -0
  176. data/sig/discorb/presence.rbs +237 -0
  177. data/sig/discorb/reaction.rbs +33 -0
  178. data/sig/discorb/role.rbs +145 -0
  179. data/sig/discorb/scheduled_event.rbs +148 -0
  180. data/sig/discorb/shard.rbs +62 -0
  181. data/sig/discorb/snowflake.rbs +56 -0
  182. data/sig/discorb/stage_instance.rbs +63 -0
  183. data/sig/discorb/sticker.rbs +116 -0
  184. data/sig/discorb/system_channel_flag.rbs +17 -0
  185. data/sig/discorb/unicode_emoji.rbs +49 -0
  186. data/sig/discorb/user.rbs +93 -0
  187. data/sig/discorb/utils.rbs +8 -0
  188. data/sig/discorb/voice_region.rbs +30 -0
  189. data/sig/discorb/voice_state.rbs +71 -0
  190. data/sig/discorb/webhook.rbs +327 -0
  191. data/sig/discorb/welcome_screen.rbs +78 -0
  192. data/sig/discorb.rbs +6 -7230
  193. data/sig/manifest.yaml +3 -0
  194. data/sig/override.rbs +19 -0
  195. data/template-replace/files/css/common.css +4 -0
  196. metadata +102 -6
  197. data/examples/commands/bookmarker.rb +0 -42
  198. data/examples/commands/hello.rb +0 -10
  199. data/examples/commands/inspect.rb +0 -25
@@ -0,0 +1,246 @@
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 nil 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
+ # @type var payload: Hash[Symbol, untyped]
118
+ payload = {
119
+ position: position,
120
+ }
121
+ payload[:lock_permissions] = lock_permissions
122
+ payload[:parent_id] = parent&.id if parent != Discorb::Unset
123
+ @client.http.request(Route.new("/guilds/#{@guild_id}/channels", "//guilds/:guild_id/channels", :patch),
124
+ payload, audit_log_reason: reason).wait
125
+ end
126
+ end
127
+
128
+ #
129
+ # Set the channel's permission overwrite.
130
+ # @async
131
+ #
132
+ # @param [Discorb::Role, Discorb::Member] target The target of the overwrite.
133
+ # @param [String] reason The reason of setting the overwrite.
134
+ # @param [{Symbol => Boolean}] perms The permission overwrites to replace.
135
+ #
136
+ # @return [Async::Task<void>] The task.
137
+ #
138
+ def set_permissions(target, reason: nil, **perms)
139
+ Async do
140
+ allow_value = @permission_overwrites[target]&.allow_value.to_i
141
+ deny_value = @permission_overwrites[target]&.deny_value.to_i
142
+ perms.each do |perm, value|
143
+ allow_value[Discorb::Permission.bits[perm]] = 1 if value == true
144
+ deny_value[Discorb::Permission.bits[perm]] = 1 if value == false
145
+ end
146
+ payload = {
147
+ allow: allow_value,
148
+ deny: deny_value,
149
+ type: target.is_a?(Member) ? 1 : 0,
150
+ }
151
+ @client.http.request(
152
+ Route.new("/channels/#{@id}/permissions/#{target.id}", "//channels/:channel_id/permissions/:target_id",
153
+ :put), payload, audit_log_reason: reason,
154
+ ).wait
155
+ end
156
+ end
157
+
158
+ alias modify_permissions set_permissions
159
+ alias modify_permisssion set_permissions
160
+ alias edit_permissions set_permissions
161
+ alias edit_permission set_permissions
162
+
163
+ #
164
+ # Delete the channel's permission overwrite.
165
+ # @async
166
+ #
167
+ # @param [Discorb::Role, Discorb::Member] target The target of the overwrite.
168
+ # @param [String] reason The reason of deleting the overwrite.
169
+ #
170
+ # @return [Async::Task<void>] The task.
171
+ #
172
+ def delete_permissions(target, reason: nil)
173
+ Async do
174
+ @client.http.request(
175
+ Route.new("/channels/#{@id}/permissions/#{target.id}", "//channels/:channel_id/permissions/:target_id",
176
+ :delete), {}, audit_log_reason: reason,
177
+ ).wait
178
+ end
179
+ end
180
+
181
+ alias delete_permission delete_permissions
182
+ alias destroy_permissions delete_permissions
183
+ alias destroy_permission delete_permissions
184
+
185
+ #
186
+ # Fetch the channel's invites.
187
+ # @async
188
+ #
189
+ # @return [Async::Task<Array<Discorb::Invite>>] The invites in the channel.
190
+ #
191
+ def fetch_invites
192
+ Async do
193
+ _resp, data = @client.http.request(Route.new("/channels/#{@id}/invites", "//channels/:channel_id/invites",
194
+ :get)).wait
195
+ data.map { |invite| Invite.new(@client, invite, false) }
196
+ end
197
+ end
198
+
199
+ #
200
+ # Create an invite in the channel.
201
+ # @async
202
+ #
203
+ # @param [Integer] max_age The max age of the invite.
204
+ # @param [Integer] max_uses The max uses of the invite.
205
+ # @param [Boolean] temporary Whether the invite is temporary.
206
+ # @param [Boolean] unique Whether the invite is unique.
207
+ # @note if it's `false` it may return existing invite.
208
+ # @param [String] reason The reason of creating the invite.
209
+ #
210
+ # @return [Async::Task<Invite>] The created invite.
211
+ #
212
+ def create_invite(max_age: nil, max_uses: nil, temporary: false, unique: false, reason: nil)
213
+ Async do
214
+ _resp, data = @client.http.request(
215
+ Route.new("/channels/#{@id}/invites", "//channels/:channel_id/invites", :post), {
216
+ max_age: max_age,
217
+ max_uses: max_uses,
218
+ temporary: temporary,
219
+ unique: unique,
220
+ }, audit_log_reason: reason,
221
+ ).wait
222
+ Invite.new(@client, data, false)
223
+ end
224
+ end
225
+
226
+ private
227
+
228
+ def _set_data(data)
229
+ @guild_id = data[:guild_id]
230
+ @position = data[:position]
231
+ @permission_overwrites = if data[:permission_overwrites]
232
+ data[:permission_overwrites].to_h do |ow|
233
+ [
234
+ (ow[:type] == 1 ? guild.roles : guild.members)[ow[:id]],
235
+ PermissionOverwrite.new(ow[:allow].to_i, ow[:deny].to_i),
236
+ ]
237
+ end
238
+ else
239
+ {}
240
+ end
241
+ @parent_id = data[:parent_id]
242
+
243
+ super
244
+ end
245
+ end
246
+ 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.reject(&: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