onyxcord 2.1.0 → 3.2.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 (270) hide show
  1. checksums.yaml +4 -4
  2. data/lib/onyxcord/application_commands/command.rb +4 -97
  3. data/lib/onyxcord/application_commands/context.rb +4 -94
  4. data/lib/onyxcord/application_commands/option.rb +4 -75
  5. data/lib/onyxcord/application_commands/registry.rb +4 -45
  6. data/lib/onyxcord/application_commands.rb +8 -5
  7. data/lib/onyxcord/bot.rb +24 -1759
  8. data/lib/onyxcord/{cache.rb → cache/manager.rb} +16 -14
  9. data/lib/onyxcord/cache/stores/gateway.rb +272 -0
  10. data/lib/onyxcord/commands/bot/channels.rb +48 -0
  11. data/lib/onyxcord/commands/bot/execution.rb +174 -0
  12. data/lib/onyxcord/commands/bot/message_dispatch.rb +58 -0
  13. data/lib/onyxcord/commands/bot/permissions.rb +72 -0
  14. data/lib/onyxcord/commands/bot.rb +209 -0
  15. data/lib/onyxcord/commands/container.rb +21 -2
  16. data/lib/onyxcord/commands/parser.rb +30 -1
  17. data/lib/onyxcord/container.rb +16 -960
  18. data/lib/onyxcord/core/bot/application_commands.rb +210 -0
  19. data/lib/onyxcord/core/bot/awaits.rb +112 -0
  20. data/lib/onyxcord/core/bot/invites.rb +42 -0
  21. data/lib/onyxcord/core/bot/messaging.rb +161 -0
  22. data/lib/onyxcord/core/bot/oauth.rb +27 -0
  23. data/lib/onyxcord/core/bot/presence.rb +103 -0
  24. data/lib/onyxcord/core/bot/runtime.rb +183 -0
  25. data/lib/onyxcord/core/bot/voice.rb +69 -0
  26. data/lib/onyxcord/{logger.rb → core/logger.rb} +5 -0
  27. data/lib/onyxcord/core/version.rb +5 -0
  28. data/lib/onyxcord/events/await/base.rb +48 -0
  29. data/lib/onyxcord/events/await.rb +1 -46
  30. data/lib/onyxcord/events/ban/base.rb +54 -0
  31. data/lib/onyxcord/events/ban/remove.rb +11 -0
  32. data/lib/onyxcord/events/bans.rb +2 -58
  33. data/lib/onyxcord/events/channels/base.rb +91 -0
  34. data/lib/onyxcord/events/channels/delete.rb +73 -0
  35. data/lib/onyxcord/events/channels/pins.rb +44 -0
  36. data/lib/onyxcord/events/channels/recipients.rb +77 -0
  37. data/lib/onyxcord/events/channels.rb +4 -239
  38. data/lib/onyxcord/events/guilds/audit_logs.rb +79 -0
  39. data/lib/onyxcord/events/guilds/base.rb +97 -0
  40. data/lib/onyxcord/events/guilds/emoji.rb +147 -0
  41. data/lib/onyxcord/events/guilds.rb +3 -267
  42. data/lib/onyxcord/events/handlers/channels.rb +133 -0
  43. data/lib/onyxcord/events/handlers/core.rb +146 -0
  44. data/lib/onyxcord/events/handlers/guilds.rb +375 -0
  45. data/lib/onyxcord/events/handlers/interactions.rb +238 -0
  46. data/lib/onyxcord/events/handlers/lifetime.rb +71 -0
  47. data/lib/onyxcord/events/handlers/messages.rb +218 -0
  48. data/lib/onyxcord/events/handlers/presence.rb +56 -0
  49. data/lib/onyxcord/events/handlers/raw.rb +39 -0
  50. data/lib/onyxcord/events/handlers/reactions.rb +98 -0
  51. data/lib/onyxcord/events/handlers/scheduled_events.rb +243 -0
  52. data/lib/onyxcord/events/handlers/voice.rb +46 -0
  53. data/lib/onyxcord/events/integration/base.rb +45 -0
  54. data/lib/onyxcord/events/integration/create.rb +11 -0
  55. data/lib/onyxcord/events/integration/delete.rb +48 -0
  56. data/lib/onyxcord/events/integration/update.rb +11 -0
  57. data/lib/onyxcord/events/integrations.rb +4 -98
  58. data/lib/onyxcord/events/interactions/application_commands.rb +185 -0
  59. data/lib/onyxcord/events/interactions/autocomplete.rb +62 -0
  60. data/lib/onyxcord/events/interactions/base.rb +175 -0
  61. data/lib/onyxcord/events/interactions/components.rb +221 -0
  62. data/lib/onyxcord/events/interactions/permissions.rb +53 -0
  63. data/lib/onyxcord/events/interactions.rb +5 -622
  64. data/lib/onyxcord/events/invite/create.rb +79 -0
  65. data/lib/onyxcord/events/invite/delete.rb +55 -0
  66. data/lib/onyxcord/events/invites.rb +2 -125
  67. data/lib/onyxcord/events/lifetime/base.rb +31 -0
  68. data/lib/onyxcord/events/lifetime.rb +1 -29
  69. data/lib/onyxcord/events/member/add.rb +12 -0
  70. data/lib/onyxcord/events/member/base.rb +67 -0
  71. data/lib/onyxcord/events/member/delete.rb +21 -0
  72. data/lib/onyxcord/events/member/update.rb +25 -0
  73. data/lib/onyxcord/events/members.rb +4 -108
  74. data/lib/onyxcord/events/message/base.rb +295 -0
  75. data/lib/onyxcord/events/message/ids.rb +71 -0
  76. data/lib/onyxcord/events/message/mentions.rb +55 -0
  77. data/lib/onyxcord/events/message/updates.rb +27 -0
  78. data/lib/onyxcord/events/message.rb +4 -397
  79. data/lib/onyxcord/events/poll/add.rb +11 -0
  80. data/lib/onyxcord/events/poll/base.rb +106 -0
  81. data/lib/onyxcord/events/poll/remove.rb +11 -0
  82. data/lib/onyxcord/events/polls.rb +3 -116
  83. data/lib/onyxcord/events/presence/playing.rb +77 -0
  84. data/lib/onyxcord/events/presence/status.rb +60 -0
  85. data/lib/onyxcord/events/presence.rb +2 -129
  86. data/lib/onyxcord/events/raw/base.rb +74 -0
  87. data/lib/onyxcord/events/raw.rb +1 -72
  88. data/lib/onyxcord/events/reactions/base.rb +143 -0
  89. data/lib/onyxcord/events/reactions/clear.rb +99 -0
  90. data/lib/onyxcord/events/reactions.rb +2 -216
  91. data/lib/onyxcord/events/role/create.rb +46 -0
  92. data/lib/onyxcord/events/role/delete.rb +40 -0
  93. data/lib/onyxcord/events/role/update.rb +11 -0
  94. data/lib/onyxcord/events/roles.rb +3 -85
  95. data/lib/onyxcord/events/scheduled_events/events.rb +112 -0
  96. data/lib/onyxcord/events/scheduled_events/users.rb +91 -0
  97. data/lib/onyxcord/events/scheduled_events.rb +2 -169
  98. data/lib/onyxcord/events/thread/base.rb +49 -0
  99. data/lib/onyxcord/events/thread/members.rb +44 -0
  100. data/lib/onyxcord/events/thread/update.rb +18 -0
  101. data/lib/onyxcord/events/threads.rb +3 -98
  102. data/lib/onyxcord/events/typing/base.rb +73 -0
  103. data/lib/onyxcord/events/typing.rb +1 -71
  104. data/lib/onyxcord/events/voice/server_update.rb +48 -0
  105. data/lib/onyxcord/events/voice/state_update.rb +137 -0
  106. data/lib/onyxcord/events/voice_server_update.rb +2 -46
  107. data/lib/onyxcord/events/voice_state_update.rb +2 -135
  108. data/lib/onyxcord/events/webhook/update.rb +65 -0
  109. data/lib/onyxcord/events/webhooks.rb +1 -63
  110. data/lib/onyxcord/gateway/client.rb +460 -0
  111. data/lib/onyxcord/interactions/command.rb +120 -0
  112. data/lib/onyxcord/interactions/context.rb +109 -0
  113. data/lib/onyxcord/interactions/internal/application_command.rb +203 -0
  114. data/lib/onyxcord/interactions/internal/message.rb +152 -0
  115. data/lib/onyxcord/interactions/internal/metadata.rb +109 -0
  116. data/lib/onyxcord/interactions/internal/option_builder.rb +230 -0
  117. data/lib/onyxcord/interactions/internal/permission_builder.rb +90 -0
  118. data/lib/onyxcord/interactions/option.rb +88 -0
  119. data/lib/onyxcord/interactions/registry.rb +50 -0
  120. data/lib/onyxcord/interactions.rb +16 -0
  121. data/lib/onyxcord/internal/async_runtime.rb +32 -0
  122. data/lib/onyxcord/internal/event_bus.rb +591 -0
  123. data/lib/onyxcord/internal/event_executor.rb +155 -0
  124. data/lib/onyxcord/internal/gateway/opcodes.rb +22 -0
  125. data/lib/onyxcord/internal/gateway/session.rb +45 -0
  126. data/lib/onyxcord/internal/http.rb +189 -0
  127. data/lib/onyxcord/internal/json.rb +51 -0
  128. data/lib/onyxcord/{message_payload.rb → internal/message_payload.rb} +3 -3
  129. data/lib/onyxcord/internal/rate_limiter/async_rest.rb +151 -0
  130. data/lib/onyxcord/internal/rate_limiter/gateway.rb +44 -0
  131. data/lib/onyxcord/internal/rate_limiter/rest.rb +144 -0
  132. data/lib/onyxcord/internal/websocket.rb +79 -0
  133. data/lib/onyxcord/light/data.rb +1 -1
  134. data/lib/onyxcord/light/integrations.rb +1 -1
  135. data/lib/onyxcord/light/light_bot.rb +7 -7
  136. data/lib/onyxcord/{data → models}/activity.rb +2 -2
  137. data/lib/onyxcord/{data → models}/application.rb +3 -3
  138. data/lib/onyxcord/{data → models}/avatar_decoration.rb +1 -1
  139. data/lib/onyxcord/{data → models}/channel.rb +23 -23
  140. data/lib/onyxcord/{data → models}/collectibles.rb +1 -1
  141. data/lib/onyxcord/{data → models}/emoji.rb +1 -1
  142. data/lib/onyxcord/models/interaction.rb +450 -0
  143. data/lib/onyxcord/{data → models}/invite.rb +1 -1
  144. data/lib/onyxcord/{data → models}/member.rb +11 -11
  145. data/lib/onyxcord/{data → models}/message.rb +18 -14
  146. data/lib/onyxcord/{data → models}/poll.rb +2 -2
  147. data/lib/onyxcord/{data → models}/primary_server.rb +1 -1
  148. data/lib/onyxcord/{data → models}/profile.rb +4 -4
  149. data/lib/onyxcord/{data → models}/role.rb +6 -12
  150. data/lib/onyxcord/{data → models}/scheduled_event.rb +5 -5
  151. data/lib/onyxcord/{data → models}/server.rb +41 -41
  152. data/lib/onyxcord/{data → models}/server_preview.rb +2 -2
  153. data/lib/onyxcord/{data → models}/team.rb +1 -1
  154. data/lib/onyxcord/{data → models}/user.rb +5 -5
  155. data/lib/onyxcord/{data → models}/webhook.rb +10 -10
  156. data/lib/onyxcord/models.rb +57 -0
  157. data/lib/onyxcord/{api.rb → rest/client.rb} +23 -22
  158. data/lib/onyxcord/{api → rest/routes}/application.rb +79 -57
  159. data/lib/onyxcord/rest/routes/channel/base.rb +73 -0
  160. data/lib/onyxcord/rest/routes/channel/groups.rb +78 -0
  161. data/lib/onyxcord/rest/routes/channel/messages.rb +130 -0
  162. data/lib/onyxcord/rest/routes/channel/permissions.rb +73 -0
  163. data/lib/onyxcord/rest/routes/channel/pins.rb +45 -0
  164. data/lib/onyxcord/rest/routes/channel/polls.rb +32 -0
  165. data/lib/onyxcord/rest/routes/channel/reactions.rb +86 -0
  166. data/lib/onyxcord/rest/routes/channel/threads.rb +176 -0
  167. data/lib/onyxcord/rest/routes/channel/webhooks.rb +47 -0
  168. data/lib/onyxcord/rest/routes/channel.rb +12 -0
  169. data/lib/onyxcord/{api/interaction.rb → rest/routes/interaction/base.rb} +7 -25
  170. data/lib/onyxcord/rest/routes/interaction/response.rb +24 -0
  171. data/lib/onyxcord/rest/routes/interaction.rb +4 -0
  172. data/lib/onyxcord/{api → rest/routes}/invite.rb +7 -7
  173. data/lib/onyxcord/rest/routes/server/admin.rb +174 -0
  174. data/lib/onyxcord/rest/routes/server/assets.rb +25 -0
  175. data/lib/onyxcord/rest/routes/server/bans.rb +67 -0
  176. data/lib/onyxcord/rest/routes/server/base.rb +77 -0
  177. data/lib/onyxcord/rest/routes/server/channels.rb +58 -0
  178. data/lib/onyxcord/rest/routes/server/emoji.rb +48 -0
  179. data/lib/onyxcord/rest/routes/server/members.rb +109 -0
  180. data/lib/onyxcord/rest/routes/server/messages.rb +19 -0
  181. data/lib/onyxcord/rest/routes/server/roles.rb +156 -0
  182. data/lib/onyxcord/rest/routes/server/scheduled_events.rb +86 -0
  183. data/lib/onyxcord/rest/routes/server.rb +12 -0
  184. data/lib/onyxcord/{api → rest/routes}/user.rb +23 -23
  185. data/lib/onyxcord/{api → rest/routes}/webhook.rb +22 -22
  186. data/lib/onyxcord/{allowed_mentions.rb → utils/allowed_mentions.rb} +1 -1
  187. data/lib/onyxcord/utils/timestamp.rb +69 -0
  188. data/lib/onyxcord/voice/{voice_bot.rb → client.rb} +4 -4
  189. data/lib/onyxcord/voice/encoder.rb +1 -1
  190. data/lib/onyxcord/voice/network/udp.rb +135 -0
  191. data/lib/onyxcord/voice/network/websocket.rb +225 -0
  192. data/lib/onyxcord/voice/network.rb +5 -357
  193. data/lib/onyxcord/webhooks/builder.rb +1 -1
  194. data/lib/onyxcord/webhooks/client.rb +13 -13
  195. data/lib/onyxcord/webhooks/modal/group_builder.rb +55 -0
  196. data/lib/onyxcord/webhooks/modal/label_builder.rb +183 -0
  197. data/lib/onyxcord/webhooks/modal.rb +2 -239
  198. data/lib/onyxcord/webhooks/version.rb +3 -3
  199. data/lib/onyxcord/webhooks/view/container_builder.rb +80 -0
  200. data/lib/onyxcord/webhooks/view/file_builder.rb +24 -0
  201. data/lib/onyxcord/webhooks/view/media_gallery_builder.rb +50 -0
  202. data/lib/onyxcord/webhooks/view/row_builder.rb +120 -0
  203. data/lib/onyxcord/webhooks/view/section_builder.rb +61 -0
  204. data/lib/onyxcord/webhooks/view/select_menu_builder.rb +77 -0
  205. data/lib/onyxcord/webhooks/view/separator_builder.rb +22 -0
  206. data/lib/onyxcord/webhooks/view/text_display_builder.rb +20 -0
  207. data/lib/onyxcord/webhooks/view.rb +9 -425
  208. data/lib/onyxcord.rb +106 -42
  209. metadata +207 -92
  210. data/.github/CONTRIBUTING.md +0 -13
  211. data/.github/ISSUE_TEMPLATE/bug_report.md +0 -38
  212. data/.github/ISSUE_TEMPLATE/feature_request.md +0 -24
  213. data/.github/pull_request_template.md +0 -37
  214. data/.github/workflows/ci.yml +0 -78
  215. data/.github/workflows/codeql.yml +0 -65
  216. data/.github/workflows/deploy.yml +0 -54
  217. data/.github/workflows/release.yml +0 -51
  218. data/.gitignore +0 -17
  219. data/.markdownlint.json +0 -4
  220. data/.overcommit.yml +0 -7
  221. data/.rspec +0 -2
  222. data/.rubocop.yml +0 -129
  223. data/.yardopts +0 -1
  224. data/CHANGELOG.md +0 -257
  225. data/Gemfile +0 -6
  226. data/LICENSE.txt +0 -21
  227. data/README.md +0 -448
  228. data/Rakefile +0 -13
  229. data/lib/onyxcord/api/channel.rb +0 -703
  230. data/lib/onyxcord/api/server.rb +0 -775
  231. data/lib/onyxcord/async/runtime.rb +0 -30
  232. data/lib/onyxcord/commands/command_bot.rb +0 -505
  233. data/lib/onyxcord/data/interaction.rb +0 -1151
  234. data/lib/onyxcord/data.rb +0 -57
  235. data/lib/onyxcord/event_executor.rb +0 -153
  236. data/lib/onyxcord/gateway.rb +0 -505
  237. data/lib/onyxcord/http.rb +0 -186
  238. data/lib/onyxcord/json.rb +0 -49
  239. data/lib/onyxcord/rate_limiter/async_rest.rb +0 -150
  240. data/lib/onyxcord/rate_limiter/gateway.rb +0 -42
  241. data/lib/onyxcord/rate_limiter/rest.rb +0 -142
  242. data/lib/onyxcord/version.rb +0 -7
  243. data/lib/onyxcord/websocket.rb +0 -77
  244. data/onyxcord.gemspec +0 -63
  245. /data/lib/onyxcord/{configuration.rb → core/configuration.rb} +0 -0
  246. /data/lib/onyxcord/{errors.rb → core/errors.rb} +0 -0
  247. /data/lib/onyxcord/{upload.rb → internal/upload.rb} +0 -0
  248. /data/lib/onyxcord/{data → models}/attachment.rb +0 -0
  249. /data/lib/onyxcord/{data → models}/audit_logs.rb +0 -0
  250. /data/lib/onyxcord/{data → models}/call.rb +0 -0
  251. /data/lib/onyxcord/{data → models}/channel_tag.rb +0 -0
  252. /data/lib/onyxcord/{data → models}/component.rb +0 -0
  253. /data/lib/onyxcord/{data → models}/embed.rb +0 -0
  254. /data/lib/onyxcord/{data → models}/install_params.rb +0 -0
  255. /data/lib/onyxcord/{data → models}/integration.rb +0 -0
  256. /data/lib/onyxcord/{data → models}/message_activity.rb +0 -0
  257. /data/lib/onyxcord/{data → models}/overwrite.rb +0 -0
  258. /data/lib/onyxcord/{data → models}/reaction.rb +0 -0
  259. /data/lib/onyxcord/{data → models}/recipient.rb +0 -0
  260. /data/lib/onyxcord/{data → models}/role_connection_data.rb +0 -0
  261. /data/lib/onyxcord/{data → models}/role_subscription.rb +0 -0
  262. /data/lib/onyxcord/{data → models}/snapshot.rb +0 -0
  263. /data/lib/onyxcord/{data → models}/timestamp.rb +0 -0
  264. /data/lib/onyxcord/{data → models}/voice_region.rb +0 -0
  265. /data/lib/onyxcord/{data → models}/voice_state.rb +0 -0
  266. /data/lib/onyxcord/{colour_rgb.rb → utils/colour_rgb.rb} +0 -0
  267. /data/lib/onyxcord/{id_object.rb → utils/id_object.rb} +0 -0
  268. /data/lib/onyxcord/{message_components.rb → utils/message_components.rb} +0 -0
  269. /data/lib/onyxcord/{paginator.rb → utils/paginator.rb} +0 -0
  270. /data/lib/onyxcord/{permissions.rb → utils/permissions.rb} +0 -0
@@ -0,0 +1,203 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OnyxCord
4
+ # An ApplicationCommand for slash commands.
5
+ class ApplicationCommand
6
+ # Command types. `chat_input` is a command that appears in the text input field. `user` and `message` types appear as context menus
7
+ # for the respective resource.
8
+ TYPES = {
9
+ chat_input: 1,
10
+ user: 2,
11
+ message: 3,
12
+ primary_entry_point: 4
13
+ }.freeze
14
+
15
+ # @return [Integer]
16
+ attr_reader :application_id
17
+
18
+ # @return [Integer, nil]
19
+ attr_reader :server_id
20
+
21
+ # @return [String]
22
+ attr_reader :name
23
+
24
+ # @return [String]
25
+ attr_reader :description
26
+
27
+ # @return [true, false]
28
+ attr_reader :default_permission
29
+
30
+ # @return [Hash]
31
+ attr_reader :options
32
+
33
+ # @return [Integer]
34
+ attr_reader :id
35
+
36
+ # @return [true, false]
37
+ attr_reader :nsfw
38
+
39
+ # @return [Array<Integer>]
40
+ attr_reader :contexts
41
+
42
+ # @return [Array<Integer>]
43
+ attr_reader :integration_types
44
+
45
+ # @!visibility private
46
+ def initialize(data, bot, server_id = nil)
47
+ @bot = bot
48
+ @id = data['id'].to_i
49
+ @application_id = data['application_id'].to_i
50
+ @server_id = server_id&.to_i
51
+
52
+ @name = data['name']
53
+ @description = data['description']
54
+ @default_permission = data['default_permission']
55
+ @options = data['options']
56
+ @nsfw = data['nsfw'] || false
57
+ @contexts = data['contexts'] || []
58
+ @integration_types = data['integration_types'] || []
59
+ end
60
+
61
+ # @param subcommand [String, nil] The subcommand to mention.
62
+ # @param subcommand_group [String, nil] The subcommand group to mention.
63
+ # @return [String] the layout to mention it in a message
64
+ def mention(subcommand_group: nil, subcommand: nil)
65
+ if subcommand_group && subcommand
66
+ "</#{name} #{subcommand_group} #{subcommand}:#{id}>"
67
+ elsif subcommand_group
68
+ "</#{name} #{subcommand_group}:#{id}>"
69
+ elsif subcommand
70
+ "</#{name} #{subcommand}:#{id}>"
71
+ else
72
+ "</#{name}:#{id}>"
73
+ end
74
+ end
75
+
76
+ alias_method :to_s, :mention
77
+
78
+ # @param name [String] The name to use for this command.
79
+ # @param description [String] The description of this command.
80
+ # @param default_permission [true, false] Whether this command is available with default permissions.
81
+ # @param nsfw [true, false] Whether this command should be marked as age-restricted.
82
+ # @yieldparam (see Bot#edit_application_command)
83
+ # @return (see Bot#edit_application_command)
84
+ def edit(name: nil, description: nil, default_permission: nil, nsfw: nil, &block)
85
+ @bot.edit_application_command(@id, server_id: @server_id, name: name, description: description, default_permission: default_permission, nsfw: nsfw, &block)
86
+ end
87
+
88
+ # Delete this application command.
89
+ # @return (see Bot#delete_application_command)
90
+ def delete
91
+ @bot.delete_application_command(@id, server_id: @server_id)
92
+ end
93
+
94
+ # Get the permission configuration for this application command in a specific server.
95
+ # @param server_id [Integer, String, nil] The ID of the server to fetch command permissions for.
96
+ # @return [Array<Permission>] the permissions for this application command in the given server.
97
+ def permissions(server_id: nil)
98
+ raise ArgumentError, 'A server ID must be provided for global application commands' if @server_id.nil? && server_id.nil?
99
+
100
+ response = JSON.parse(REST::Application.get_application_command_permissions(@bot.token, @bot.profile.id, @server_id || server_id&.resolve_id, @id))
101
+ response['permissions'].map { |permission| Permission.new(permission, response, @bot) }
102
+ rescue OnyxCord::Errors::UnknownError
103
+ # If there aren't any explicit overwrites configured for the command, the response is a 400.
104
+ []
105
+ end
106
+
107
+ # An application command permission for a channel, member, or a role.
108
+ class Permission
109
+ # Map of permission types.
110
+ TYPES = {
111
+ role: 1,
112
+ member: 2,
113
+ channel: 3
114
+ }.freeze
115
+
116
+ # @return [Integer] the type of this permission.
117
+ # @see TYPES
118
+ attr_reader :type
119
+
120
+ # @return [Integer] the ID of the entity this permission is for.
121
+ attr_reader :target_id
122
+
123
+ # @return [Integer] the ID of the server this permission is for.
124
+ attr_reader :server_id
125
+
126
+ # @!visibility private
127
+ def initialize(data, command, bot)
128
+ @bot = bot
129
+ @type = data['type']
130
+ @target_id = data['id'].to_i
131
+ @overwrite = data['permission']
132
+ @command_id = command['id'].to_i
133
+ @server_id = command['guild_id'].to_i
134
+ @application_id = command['application_id'].to_i
135
+ end
136
+
137
+ # Whether this permission has been allowed, e.g has a green check in the UI.
138
+ # @return [true, false]
139
+ def allowed?
140
+ @overwrite == true
141
+ end
142
+
143
+ # Whether this permission has been denied, e.g has a red X-mark in the UI.
144
+ # @return [true, false]
145
+ def denied?
146
+ @overwrite == false
147
+ end
148
+
149
+ # Whether this permission is applied to the everyone role in the server.
150
+ # @return [true, false]
151
+ def everyone?
152
+ @target_id == @server_id
153
+ end
154
+
155
+ # Get the ID of the application command this permission is for.
156
+ # @return [Integer, nil] This will be `nil` if the permission is the
157
+ # default permission.
158
+ def command_id
159
+ @command_id unless default?
160
+ end
161
+
162
+ # Whether this permission is the default for all commands that don't
163
+ # contain explicit permission oerwrites.
164
+ # @return [true, false]
165
+ def default?
166
+ @command_id == @application_id
167
+ end
168
+
169
+ # Whether this permission is applied to every channel in the server.
170
+ # @return [true, false]
171
+ def all_channels?
172
+ @target_id == (@server_id - 1)
173
+ end
174
+
175
+ # Get the user, role, or channel(s) that this permission targets.
176
+ # @return [Array<Channel>, Role, Member]
177
+ def target
178
+ case @type
179
+ when TYPES[:role]
180
+ @bot.server(@server_id).role(@target_id)
181
+ when TYPES[:member]
182
+ @bot.server(@server_id).member(@target_id)
183
+ when TYPES[:channel]
184
+ all_channels? ? @bot.server(@server_id).channels : [@bot.channel(@target_id)]
185
+ end
186
+ end
187
+
188
+ alias_method :targets, :target
189
+
190
+ # @!method role?
191
+ # @return [true, false] whether this permission is for a role.
192
+ # @!method member?
193
+ # @return [true, false] whether this permission is for a member.
194
+ # @!method channel?
195
+ # @return [true, false] whether this permission is for a channel.
196
+ TYPES.each do |name, value|
197
+ define_method("#{name}?") do
198
+ @type == value
199
+ end
200
+ end
201
+ end
202
+ end
203
+ end
@@ -0,0 +1,152 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'onyxcord/utils/id_object'
4
+
5
+ module OnyxCord
6
+ module Interactions
7
+ # A message partial for interactions.
8
+ class Message
9
+ include IDObject
10
+
11
+ # @return [Interaction] The interaction that created this message.
12
+ attr_reader :interaction
13
+
14
+ # @return [String, nil] The content of the message.
15
+ attr_reader :content
16
+
17
+ # @return [true, false] Whether this message is pinned in the channel it belongs to.
18
+ attr_reader :pinned
19
+
20
+ # @return [true, false]
21
+ attr_reader :tts
22
+
23
+ # @return [Time]
24
+ attr_reader :timestamp
25
+
26
+ # @return [Time, nil]
27
+ attr_reader :edited_timestamp
28
+
29
+ # @return [true, false]
30
+ attr_reader :edited
31
+
32
+ # @return [Integer]
33
+ attr_reader :id
34
+
35
+ # @return [User] The user of the application.
36
+ attr_reader :author
37
+
38
+ # @return [Attachment]
39
+ attr_reader :attachments
40
+
41
+ # @return [Array<Embed>]
42
+ attr_reader :embeds
43
+
44
+ # @return [Array<User>]
45
+ attr_reader :mentions
46
+
47
+ # @return [Integer]
48
+ attr_reader :flags
49
+
50
+ # @return [Integer]
51
+ attr_reader :channel_id
52
+
53
+ # @return [Hash, nil]
54
+ attr_reader :message_reference
55
+
56
+ # @return [Array<Component>]
57
+ attr_reader :components
58
+
59
+ # @!visibility private
60
+ def initialize(data, bot, interaction)
61
+ @data = data
62
+ @bot = bot
63
+ @interaction = interaction
64
+ @content = data['content']
65
+ @channel_id = data['channel_id'].to_i
66
+ @pinned = data['pinned']
67
+ @tts = data['tts']
68
+
69
+ @message_reference = data['message_reference']
70
+
71
+ @server_id = @interaction.server_id
72
+
73
+ @timestamp = Time.parse(data['timestamp']) if data['timestamp']
74
+ @edited_timestamp = data['edited_timestamp'].nil? ? nil : Time.parse(data['edited_timestamp'])
75
+ @edited = !@edited_timestamp.nil?
76
+
77
+ @id = data['id'].to_i
78
+
79
+ @author = bot.ensure_user(data['author'] || data['member']['user'])
80
+
81
+ @attachments = []
82
+ @attachments = data['attachments'].map { |e| Attachment.new(e, self, @bot) } if data['attachments']
83
+
84
+ @embeds = []
85
+ @embeds = data['embeds'].map { |e| Embed.new(e, self) } if data['embeds']
86
+
87
+ @mentions = []
88
+
89
+ data['mentions']&.each do |element|
90
+ @mentions << bot.ensure_user(element)
91
+ end
92
+
93
+ @mention_roles = data['mention_roles']
94
+ @mention_everyone = data['mention_everyone']
95
+ @flags = data['flags']
96
+ @pinned = data['pinned']
97
+ @components = data['components']&.filter_map { |component| Components.from_data(component, @bot) } || []
98
+ end
99
+
100
+ # @return [Member, nil] This will return nil if the bot does not have access to the
101
+ # server the interaction originated in.
102
+ def member
103
+ server&.member(@user.id)
104
+ end
105
+
106
+ # @return [Server, nil] This will return nil if the bot does not have access to the
107
+ # server the interaction originated in.
108
+ def server
109
+ @bot.server(@server_id)
110
+ end
111
+
112
+ # @return [Channel] The channel the interaction originates from.
113
+ # @raise [Errors::NoPermission] When the bot is not in the server associated with this interaction.
114
+ def channel
115
+ @bot.channel(@channel_id)
116
+ end
117
+
118
+ # Respond to this message.
119
+ # @param (see Interaction#send_message)
120
+ # @yieldparam (see Interaction#send_message)
121
+ def respond(content: nil, embeds: nil, allowed_mentions: nil, flags: 0, ephemeral: true, components: nil, attachments: nil, &block)
122
+ @interaction.send_message(content: content, embeds: embeds, allowed_mentions: allowed_mentions, flags: flags, ephemeral: ephemeral, components: components, attachments: attachments, &block)
123
+ end
124
+
125
+ # Delete this message.
126
+ def delete
127
+ @interaction.delete_message(@id)
128
+ end
129
+
130
+ # Edit this message's data.
131
+ # @param content (see Interaction#send_message)
132
+ # @param embeds (see Interaction#send_message)
133
+ # @param allowed_mentions (see Interaction#send_message)
134
+ # @yieldparam (see Interaction#send_message)
135
+ def edit(content: nil, embeds: nil, allowed_mentions: nil, components: nil, attachments: nil, &block)
136
+ @interaction.edit_message(@id, content: content, embeds: embeds, allowed_mentions: allowed_mentions, components: components, attachments: attachments, &block)
137
+ end
138
+
139
+ # @return [OnyxCord::Message]
140
+ def to_message
141
+ OnyxCord::Message.new(@data, @bot)
142
+ end
143
+
144
+ alias_method :message, :to_message
145
+
146
+ # @!visibility private
147
+ def inspect
148
+ "<Interaction::Message content=#{@content.inspect} embeds=#{@embeds.inspect} channel_id=#{@channel_id} server_id=#{@server_id} author=#{@author.inspect}>"
149
+ end
150
+ end
151
+ end
152
+ end
@@ -0,0 +1,109 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'onyxcord/utils/id_object'
4
+
5
+ module OnyxCord
6
+ module Interactions
7
+ # Supplemental metadata about an interaction.
8
+ class Metadata
9
+ include IDObject
10
+
11
+ # @return [Integer] the type of the interaction.
12
+ attr_reader :type
13
+
14
+ # @return [User] the user that initiated the interaction.
15
+ attr_reader :user
16
+
17
+ # @return [User, nil] the user that the command was ran on.
18
+ attr_reader :target_user
19
+
20
+ # @return [Integer, nil] the ID of the message the command was ran on.
21
+ attr_reader :target_message_id
22
+
23
+ # @return [Metadata, nil] the metadata for the interaction that opened the modal.
24
+ attr_reader :triggering_metadata
25
+
26
+ # @return [Integer, nil] the ID of the message that contained the interactive message component.
27
+ attr_reader :interacted_message_id
28
+
29
+ # @return [Integer, nil] the ID the original response message; only present on follow-up messages.
30
+ attr_reader :original_response_message_id
31
+
32
+ # @!visibility private
33
+ def initialize(data, message, bot)
34
+ @bot = bot
35
+ @message = message
36
+ @id = data['id'].to_i
37
+ @type = data['type']
38
+ @user = bot.ensure_user(data['user']) if data['user']
39
+ @target_user = bot.ensure_user(data['target_user']) if data['target_user']
40
+ @target_message_id = data['target_message_id']&.to_i
41
+ @triggering_metadata = Metadata.new(data['triggering_interaction_metadata'], @message, @bot) if data['triggering_interaction_metadata']
42
+ @interacted_message_id = data['interacted_message_id']&.to_i
43
+ @original_response_message_id = data['original_response_message_id']&.to_i
44
+ @integration_owners = data['authorizing_integration_owners']&.to_h { |key, value| [key.to_i, value.to_i] }
45
+ end
46
+
47
+ # Check if the interaction was triggered by a user by installed the application.
48
+ # @return [true, false] whether or not the application was installed by the user
49
+ # who initiated this interaction.
50
+ def user_integration?
51
+ @integration_owners[1] == @user.id
52
+ end
53
+
54
+ # Check if the interaction was triggered by a server by installed the application.
55
+ # @return [true, false] whether or not the application was installed by the server
56
+ # where this interaction originates from.
57
+ def server_integration?
58
+ @integration_owners[0] == @message.server.id
59
+ end
60
+
61
+ # Attempt to fetch the target message of the interaction.
62
+ # @return [Message, nil] the target message of the interaction, or `nil` if it couldn't be found.
63
+ def target_message
64
+ return unless @target_message_id
65
+
66
+ @target_message ||= @message.channel.message(@target_message_id)
67
+ end
68
+
69
+ # Attempt to fetch the message that contained the interatctive component.
70
+ # @return [Message, nil] the interacted message with the component, or `nil` if it couldn't be found.
71
+ def interacted_message
72
+ return unless @interacted_message_id
73
+
74
+ @interacted_message ||= @message.channel.message(@interacted_message_id)
75
+ end
76
+
77
+ # Attempt to fetch the original response message of the interaction.
78
+ # @return [Message, nil] the original response message of the interaction, or `nil` if it couldn't be found.
79
+ def original_response_message
80
+ return unless @original_response_message_id
81
+
82
+ @original_response_message ||= @message.channel.message(@original_response_message_id)
83
+ end
84
+
85
+ # @!method command?
86
+ # @return [true, false] whether or not the interaction metadata is for an application command.
87
+ # @!method component?
88
+ # @return [true, false] whether or not the interaction metadata is for a message component.
89
+ # @!method modal_submit?
90
+ # @return [true, false] whether or not the interaction metadata is for a modal submission.
91
+ def command?
92
+ @type == 1
93
+ end
94
+
95
+ def component?
96
+ @type == 3
97
+ end
98
+
99
+ def modal_submit?
100
+ @type == 5
101
+ end
102
+
103
+ # @!visibility private
104
+ def inspect
105
+ "<Interactions::Metadata id=#{@id} type=#{@type} user=#{@user.inspect} target_user=#{@target_user.inspect}>"
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,230 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OnyxCord
4
+ module Interactions
5
+ # A builder for defining slash commands options.
6
+ class OptionBuilder
7
+ # @!visibility private
8
+ TYPES = {
9
+ subcommand: 1,
10
+ subcommand_group: 2,
11
+ string: 3,
12
+ integer: 4,
13
+ boolean: 5,
14
+ user: 6,
15
+ channel: 7,
16
+ role: 8,
17
+ mentionable: 9,
18
+ number: 10,
19
+ attachment: 11
20
+ }.freeze
21
+
22
+ # Channel types that can be provided to #channel
23
+ CHANNEL_TYPES = {
24
+ text: 0,
25
+ dm: 1,
26
+ voice: 2,
27
+ group_dm: 3,
28
+ category: 4,
29
+ news: 5,
30
+ store: 6,
31
+ news_thread: 10,
32
+ public_thread: 11,
33
+ private_thread: 12,
34
+ stage: 13
35
+ }.freeze
36
+
37
+ # @return [Array<Hash>]
38
+ attr_reader :options
39
+
40
+ # @!visibility private
41
+ def initialize
42
+ @options = []
43
+ end
44
+
45
+ # @param name [String, Symbol] The name of the subcommand.
46
+ # @param description [String] A description of the subcommand.
47
+ # @yieldparam [OptionBuilder]
48
+ # @return (see #option)
49
+ # @example
50
+ # bot.register_application_command(:test, 'Test command') do |cmd|
51
+ # cmd.subcommand(:echo) do |sub|
52
+ # sub.string('message', 'What to echo back', required: true)
53
+ # end
54
+ # end
55
+ def subcommand(name, description)
56
+ builder = OptionBuilder.new
57
+ yield builder if block_given?
58
+
59
+ option(TYPES[:subcommand], name, description, options: builder.to_a)
60
+ end
61
+
62
+ # @param name [String, Symbol] The name of the subcommand group.
63
+ # @param description [String] A description of the subcommand group.
64
+ # @yieldparam [OptionBuilder]
65
+ # @return (see #option)
66
+ # @example
67
+ # bot.register_application_command(:test, 'Test command') do |cmd|
68
+ # cmd.subcommand_group(:fun) do |group|
69
+ # group.subcommand(:8ball) do |sub|
70
+ # sub.string(:question, 'What do you ask the mighty 8ball?')
71
+ # end
72
+ # end
73
+ # end
74
+ def subcommand_group(name, description)
75
+ builder = OptionBuilder.new
76
+ yield builder
77
+
78
+ option(TYPES[:subcommand_group], name, description, options: builder.to_a)
79
+ end
80
+
81
+ # @param name [String, Symbol] The name of the argument.
82
+ # @param description [String] A description of the argument.
83
+ # @param required [true, false] Whether this option must be provided.
84
+ # @param min_length [Integer] A minimum length for option value.
85
+ # @param max_length [Integer] A maximum length for option value.
86
+ # @param choices [Hash, nil] Available choices, mapped as `Name => Value`.
87
+ # @param autocomplete [true, false] Whether this option can dynamically show choices.
88
+ # @return (see #option)
89
+ def string(name, description, required: nil, min_length: nil, max_length: nil, choices: nil, autocomplete: nil,
90
+ name_localizations: nil, description_localizations: nil, choice_localizations: nil)
91
+ option(TYPES[:string], name, description,
92
+ required: required, min_length: min_length, max_length: max_length, choices: choices, autocomplete: autocomplete,
93
+ name_localizations: name_localizations, description_localizations: description_localizations,
94
+ choice_localizations: choice_localizations)
95
+ end
96
+
97
+ # @param name [String, Symbol] The name of the argument.
98
+ # @param description [String] A description of the argument.
99
+ # @param required [true, false] Whether this option must be provided.
100
+ # @param min_value [Integer] A minimum value for option.
101
+ # @param max_value [Integer] A maximum value for option.
102
+ # @param choices [Hash, nil] Available choices, mapped as `Name => Value`.
103
+ # @param autocomplete [true, false] Whether this option can dynamically show choices.
104
+ # @return (see #option)
105
+ def integer(name, description, required: nil, min_value: nil, max_value: nil, choices: nil, autocomplete: nil,
106
+ name_localizations: nil, description_localizations: nil, choice_localizations: nil)
107
+ option(TYPES[:integer], name, description,
108
+ required: required, min_value: min_value, max_value: max_value, choices: choices, autocomplete: autocomplete,
109
+ name_localizations: name_localizations, description_localizations: description_localizations,
110
+ choice_localizations: choice_localizations)
111
+ end
112
+
113
+ # @param name [String, Symbol] The name of the argument.
114
+ # @param description [String] A description of the argument.
115
+ # @param required [true, false] Whether this option must be provided.
116
+ # @return (see #option)
117
+ def boolean(name, description, required: nil, name_localizations: nil, description_localizations: nil)
118
+ option(TYPES[:boolean], name, description, required: required,
119
+ name_localizations: name_localizations, description_localizations: description_localizations)
120
+ end
121
+
122
+ # @param name [String, Symbol] The name of the argument.
123
+ # @param description [String] A description of the argument.
124
+ # @param required [true, false] Whether this option must be provided.
125
+ # @return (see #option)
126
+ def user(name, description, required: nil, name_localizations: nil, description_localizations: nil)
127
+ option(TYPES[:user], name, description, required: required,
128
+ name_localizations: name_localizations, description_localizations: description_localizations)
129
+ end
130
+
131
+ # @param name [String, Symbol] The name of the argument.
132
+ # @param description [String] A description of the argument.
133
+ # @param required [true, false] Whether this option must be provided.
134
+ # @param types [Array<Symbol, Integer>] See {CHANNEL_TYPES}
135
+ # @return (see #option)
136
+ def channel(name, description, required: nil, types: nil, name_localizations: nil, description_localizations: nil)
137
+ types = types&.collect { |type| type.is_a?(Numeric) ? type : CHANNEL_TYPES[type] }
138
+ option(TYPES[:channel], name, description, required: required, channel_types: types,
139
+ name_localizations: name_localizations, description_localizations: description_localizations)
140
+ end
141
+
142
+ # @param name [String, Symbol] The name of the argument.
143
+ # @param description [String] A description of the argument.
144
+ # @param required [true, false] Whether this option must be provided.
145
+ # @return (see #option)
146
+ def role(name, description, required: nil, name_localizations: nil, description_localizations: nil)
147
+ option(TYPES[:role], name, description, required: required,
148
+ name_localizations: name_localizations, description_localizations: description_localizations)
149
+ end
150
+
151
+ # @param name [String, Symbol] The name of the argument.
152
+ # @param description [String] A description of the argument.
153
+ # @param required [true, false] Whether this option must be provided.
154
+ # @return (see #option)
155
+ def mentionable(name, description, required: nil, name_localizations: nil, description_localizations: nil)
156
+ option(TYPES[:mentionable], name, description, required: required,
157
+ name_localizations: name_localizations, description_localizations: description_localizations)
158
+ end
159
+
160
+ # @param name [String, Symbol] The name of the argument.
161
+ # @param description [String] A description of the argument.
162
+ # @param required [true, false] Whether this option must be provided.
163
+ # @param min_value [Float] A minimum value for option.
164
+ # @param max_value [Float] A maximum value for option.
165
+ # @param autocomplete [true, false] Whether this option can dynamically show choices.
166
+ # @return (see #option)
167
+ def number(name, description, required: nil, min_value: nil, max_value: nil, choices: nil, autocomplete: nil,
168
+ name_localizations: nil, description_localizations: nil, choice_localizations: nil)
169
+ option(TYPES[:number], name, description,
170
+ required: required, min_value: min_value, max_value: max_value, choices: choices, autocomplete: autocomplete,
171
+ name_localizations: name_localizations, description_localizations: description_localizations,
172
+ choice_localizations: choice_localizations)
173
+ end
174
+
175
+ # @param name [String, Symbol] The name of the argument.
176
+ # @param description [String] A description of the argument.
177
+ # @param required [true, false] Whether this option must be provided.
178
+ # @return (see #option)
179
+ def attachment(name, description, required: nil, name_localizations: nil, description_localizations: nil)
180
+ option(TYPES[:attachment], name, description, required: required,
181
+ name_localizations: name_localizations, description_localizations: description_localizations)
182
+ end
183
+
184
+ # @!visibility private
185
+ # @param type [Integer] The argument type.
186
+ # @param name [String, Symbol] The name of the argument.
187
+ # @param description [String] A description of the argument.
188
+ # @param required [true, false] Whether this option must be provided.
189
+ # @param min_value [Integer, Float] A minimum value for integer and number options.
190
+ # @param max_value [Integer, Float] A maximum value for integer and number options.
191
+ # @param min_length [Integer] A minimum length for string option value.
192
+ # @param max_length [Integer] A maximum length for string option value.
193
+ # @param channel_types [Array<Integer>] Channel types that can be provides for channel options.
194
+ # @param autocomplete [true, false] Whether this option can dynamically show options.
195
+ # @return Hash
196
+ def option(type, name, description, required: nil, choices: nil, options: nil, min_value: nil, max_value: nil,
197
+ min_length: nil, max_length: nil, channel_types: nil, autocomplete: nil,
198
+ name_localizations: nil, description_localizations: nil, choice_localizations: nil)
199
+ opt = { type: type, name: name, description: description }
200
+ choices = build_choices(choices, choice_localizations) if choices
201
+
202
+ opt.merge!({ required: required, choices: choices, options: options, min_value: min_value,
203
+ max_value: max_value, min_length: min_length, max_length: max_length,
204
+ channel_types: channel_types, autocomplete: autocomplete,
205
+ name_localizations: name_localizations, description_localizations: description_localizations }.compact)
206
+
207
+ @options << opt
208
+ opt
209
+ end
210
+
211
+ # @return [Array<Hash>]
212
+ def to_a
213
+ @options
214
+ end
215
+
216
+ private
217
+
218
+ def build_choices(choices, choice_localizations)
219
+ choices.map do |option_name, value|
220
+ choice = { name: option_name, value: value }
221
+ if choice_localizations&.key?(option_name.to_sym) || choice_localizations&.key?(option_name.to_s)
222
+ locs = choice_localizations[option_name.to_sym] || choice_localizations[option_name.to_s]
223
+ choice[:name_localizations] = locs if locs.is_a?(Hash)
224
+ end
225
+ choice
226
+ end
227
+ end
228
+ end
229
+ end
230
+ end