onyxcord 2.1.0 → 3.2.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.
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
@@ -1,10 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Voice networking — uses OnyxCord::WebSocket (async-websocket based)
3
+ # Voice networking — uses OnyxCord::Internal::WebSocket (async-websocket based)
4
4
  require 'socket'
5
- require 'onyxcord/json'
6
-
7
- require 'onyxcord/websocket'
5
+ require_relative '../internal/json'
6
+ require_relative '../internal/websocket'
8
7
  require 'onyxcord/voice/opcodes'
9
8
 
10
9
  begin
@@ -32,357 +31,6 @@ module OnyxCord::Voice
32
31
  # Encryption modes supported by Discord
33
32
  ENCRYPTION_MODES = %w[aead_xchacha20_poly1305_rtpsize].freeze
34
33
 
35
- # Represents a UDP connection to a voice server. This connection is used to send the actual audio data.
36
- class VoiceUDP
37
- # @return [true, false] whether or not UDP communications are encrypted.
38
- # @deprecated Discord no longer supports unencrypted voice communication.
39
- attr_accessor :encrypted
40
- alias_method :encrypted?, :encrypted
41
-
42
- # Sets the secret key used for encryption
43
- attr_writer :secret_key
44
-
45
- # The UDP encryption mode
46
- attr_reader :mode
47
-
48
- # @!visibility private
49
- attr_writer :mode
50
-
51
- # Creates a new UDP connection. Only creates a socket as the discovery reply may come before the data is
52
- # initialized.
53
- def initialize
54
- @socket = UDPSocket.new
55
- @encrypted = true
56
- end
57
-
58
- # Initializes the UDP socket with data obtained from opcode 2.
59
- # @param ip [String] The IP address to connect to.
60
- # @param port [Integer] The port to connect to.
61
- # @param ssrc [Integer] The Super Secret Relay Code (SSRC). Discord uses this to identify different voice users
62
- # on the same endpoint.
63
- def connect(ip, port, ssrc)
64
- @ip = ip
65
- @port = port
66
- @ssrc = ssrc
67
- end
68
-
69
- # Waits for a UDP discovery reply, and returns the sent data.
70
- # @return [Array(String, Integer)] the IP and port received from the discovery reply.
71
- def receive_discovery_reply
72
- # Wait for a UDP message
73
- message = @socket.recv(74)
74
- ip = message[8..-3].delete("\0")
75
- port = message[-2..].unpack1('n')
76
- [ip, port]
77
- end
78
-
79
- # Makes an audio packet from a buffer and sends it to Discord.
80
- # @param buf [String] The audio data to send, must be exactly one Opus frame
81
- # @param sequence [Integer] The packet sequence number, incremented by one for subsequent packets
82
- # @param time [Integer] When this packet should be played back, in no particular unit (essentially just the
83
- # sequence number multiplied by 960)
84
- def send_audio(buf, sequence, time)
85
- # Header of the audio packet
86
- header = generate_header(sequence, time)
87
-
88
- nonce = generate_nonce
89
- buf = encrypt_audio(buf, header, nonce)
90
- data = header + buf + nonce.byteslice(0, 4)
91
-
92
- send_packet(data)
93
- end
94
-
95
- # Sends the UDP discovery packet with the internally stored SSRC. Discord will send a reply afterwards which can
96
- # be received using {#receive_discovery_reply}
97
- def send_discovery
98
- # Create empty packet
99
- discovery_packet = ''
100
-
101
- # Add Type request (0x1 = request, 0x2 = response)
102
- discovery_packet += [0x1].pack('n')
103
-
104
- # Add Length (excluding Type and itself = 70)
105
- discovery_packet += [70].pack('n')
106
-
107
- # Add SSRC
108
- discovery_packet += [@ssrc].pack('N')
109
-
110
- # Add 66 zeroes so the packet is 74 bytes long
111
- discovery_packet += "\0" * 66
112
-
113
- send_packet(discovery_packet)
114
- end
115
-
116
- def close
117
- @socket.close unless @socket.closed?
118
- end
119
-
120
- private
121
-
122
- # Encrypts audio data using libsodium
123
- # @param buf [String] The encoded audio data to be encrypted
124
- # @param header [String] The RTP header of the packet, used as associated data
125
- # @param nonce [String] The nonce to be used to encrypt the data
126
- # @return [String] the audio data, encrypted
127
- def encrypt_audio(buf, header, nonce)
128
- raise 'No secret key found, despite encryption being enabled!' unless @secret_key
129
-
130
- case @mode
131
- when 'aead_xchacha20_poly1305_rtpsize'
132
- OnyxCord::Voice::XChaCha20AEAD.encrypt(buf, header, nonce, @secret_key)
133
- else
134
- raise "`#{@mode}' is not a supported encryption mode"
135
- end
136
- end
137
-
138
- def send_packet(packet)
139
- @socket.send(packet, 0, @ip, @port)
140
- end
141
-
142
- # @return [String]
143
- def generate_nonce
144
- case @mode
145
- when 'aead_xchacha20_poly1305_rtpsize'
146
- case @incremental_nonce
147
- when nil, 0xff_ff_ff_ff
148
- @incremental_nonce = 0
149
- else
150
- @incremental_nonce += 1
151
- end
152
- [@incremental_nonce].pack('N').ljust(24, "\0")
153
- else
154
- raise "`#{@mode}' is not a supported encryption mode"
155
- end
156
- end
157
-
158
- # @return [String]
159
- def generate_header(sequence, time)
160
- [0x80, 0x78, sequence, time, @ssrc].pack('CCnNN')
161
- end
162
- end
163
-
164
- # Represents a websocket client connection to the voice server. The websocket connection (sometimes called vWS) is
165
- # used to manage general data about the connection, such as sending the speaking packet, which determines the green
166
- # circle around users on Discord, and obtaining UDP connection info.
167
- class VoiceWS
168
- # The version of the voice gateway that's supposed to be used.
169
- VOICE_GATEWAY_VERSION = 8
170
-
171
- # @return [VoiceUDP] the UDP voice connection over which the actual audio data is sent.
172
- attr_reader :udp
173
-
174
- # Makes a new voice websocket client, but doesn't connect it (see {#connect} for that)
175
- # @param channel [Channel] The voice channel to connect to
176
- # @param bot [Bot] The regular bot to which this vWS is bound
177
- # @param token [String] The authentication token which is also used for REST requests
178
- # @param session [String] The voice session ID Discord sends over the regular websocket
179
- # @param endpoint [String] The endpoint URL to connect to
180
- def initialize(channel, bot, token, session, endpoint)
181
- raise 'libsodium is unavailable - unable to create voice bot! Please read https://github.com/kruldevb/OnyxCord/wiki/Installing-libsodium' unless LIBSODIUM_AVAILABLE
182
-
183
- @channel = channel
184
- @bot = bot
185
- @token = token
186
- @session = session
187
-
188
- @endpoint = endpoint
189
-
190
- @udp = VoiceUDP.new
191
- end
192
-
193
- # Send a connection init packet (op 0)
194
- # @param server_id [Integer] The ID of the server to connect to
195
- # @param bot_user_id [Integer] The ID of the bot that is connecting
196
- # @param session_id [String] The voice session ID
197
- # @param token [String] The Discord authentication token
198
- def send_init(server_id, bot_user_id, session_id, token)
199
- send_opcode(
200
- Opcodes::IDENTIFY,
201
- {
202
- server_id: server_id,
203
- user_id: bot_user_id,
204
- session_id: session_id,
205
- token: token
206
- }
207
- )
208
- end
209
-
210
- # Sends the UDP connection packet (op 1)
211
- # @param ip [String] The IP to bind UDP to
212
- # @param port [Integer] The port to bind UDP to
213
- # @param mode [Object] Which mode to use for the voice connection
214
- def send_udp_connection(ip, port, mode)
215
- send_opcode(
216
- Opcodes::SELECT_PROTOCOL,
217
- {
218
- protocol: 'udp',
219
- data: {
220
- address: ip,
221
- port: port,
222
- mode: mode
223
- }
224
- }
225
- )
226
- end
227
-
228
- # Send a heartbeat (op 3), has to be done every @heartbeat_interval seconds or the connection will terminate
229
- def send_heartbeat
230
- millis = Time.now.strftime('%s%L').to_i
231
- @bot.debug("Sending voice heartbeat at #{millis}")
232
-
233
- send_opcode(
234
- Opcodes::HEARTBEAT,
235
- {
236
- t: millis,
237
- seq_ack: @seq
238
- }
239
- )
240
- end
241
-
242
- # Send a speaking packet (op 5). This determines the green circle around the avatar in the voice channel
243
- # @param value [true, false, Integer] Whether or not the bot should be speaking, can also be a bitmask denoting audio type.
244
- def send_speaking(value)
245
- @bot.debug("Speaking: #{value}")
246
- send_opcode(
247
- Opcodes::SPEAKING,
248
- {
249
- speaking: value,
250
- delay: 0
251
- }
252
- )
253
- end
254
-
255
- def send_opcode(opcode, data)
256
- @bot.debug("Sending voice opcode #{opcode} with data: #{data}")
257
- @client.send({
258
- op: opcode,
259
- d: data
260
- }.to_json)
261
- end
262
-
263
- # Event handlers; public for websocket-simple to work correctly
264
- # @!visibility private
265
- def websocket_open
266
- # Give the current thread a name ('Voice Web Socket Internal')
267
- Thread.current[:onyxcord_name] = 'vws-i'
268
-
269
- # Send the init packet
270
- send_init(@channel.server.id, @bot.profile.id, @session, @token)
271
- end
272
-
273
- # @!visibility private
274
- def websocket_message(msg)
275
- @bot.debug("Received VWS message! #{msg}")
276
- packet = JSON.parse(msg)
277
-
278
- @seq = packet['seq'] if packet['seq']
279
-
280
- case packet['op']
281
- when OnyxCord::Voice::Opcodes::READY
282
- # Opcode 2 contains data to initialize the UDP connection
283
- @ws_data = packet['d']
284
-
285
- @ssrc = @ws_data['ssrc']
286
- @port = @ws_data['port']
287
-
288
- @udp_mode = (ENCRYPTION_MODES & @ws_data['modes']).first
289
-
290
- @udp.connect(@ws_data['ip'], @port, @ssrc)
291
- @udp.send_discovery
292
- when OnyxCord::Voice::Opcodes::SESSION_DESCRIPTION
293
- # Opcode 4 sends the secret key used for encryption
294
- @ws_data = packet['d']
295
-
296
- # Reset the sequence when starting a new session
297
- @seq = 0
298
-
299
- @ready = true
300
- @udp.secret_key = @ws_data['secret_key'].pack('C*')
301
- @udp.mode = @ws_data['mode']
302
- when OnyxCord::Voice::Opcodes::HELLO
303
- # Opcode 8 contains the heartbeat interval.
304
- @heartbeat_interval = packet['d']['heartbeat_interval']
305
- send_heartbeat
306
- end
307
- end
308
-
309
- # Communication goes like this:
310
- # me discord
311
- # | |
312
- # websocket connect -> |
313
- # | |
314
- # | <- websocket opcode 2
315
- # | |
316
- # UDP discovery -> |
317
- # | |
318
- # | <- UDP reply packet
319
- # | |
320
- # websocket opcode 1 -> |
321
- # | |
322
- # ...
323
- def connect
324
- # Connect websocket
325
- @thread = Thread.new do
326
- Thread.current[:onyxcord_name] = 'vws'
327
- init_ws
328
- end
329
-
330
- @bot.debug('Started websocket initialization, now waiting for UDP discovery reply')
331
-
332
- # Now wait for opcode 2 and the resulting UDP reply packet
333
- ip, port = @udp.receive_discovery_reply
334
- @bot.debug("UDP discovery reply received! #{ip} #{port}")
335
-
336
- # Send UDP init packet with received UDP data
337
- send_udp_connection(ip, port, @udp_mode)
338
-
339
- @bot.debug('Waiting for op 4 now')
340
-
341
- # Wait for op 4, then finish
342
- sleep 0.05 until @ready
343
- end
344
-
345
- # Disconnects the websocket and kills the thread
346
- def destroy(join_timeout = 1)
347
- @heartbeat_running = false
348
- @client&.close
349
- @udp.close
350
- @thread&.join(join_timeout)
351
- @thread&.kill if @thread&.alive?
352
- end
353
-
354
- private
355
-
356
- def heartbeat_loop
357
- @heartbeat_running = true
358
- while @heartbeat_running
359
- if @heartbeat_interval
360
- sleep @heartbeat_interval / 1000.0
361
- send_heartbeat
362
- else
363
- # If no interval has been set yet, sleep a second and check again
364
- sleep 1
365
- end
366
- end
367
- end
368
-
369
- def init_ws
370
- host = "wss://#{@endpoint}/?v=#{VOICE_GATEWAY_VERSION}"
371
- @bot.debug("Connecting VWS to host: #{host}")
372
-
373
- # Connect the WS
374
- @client = OnyxCord::WebSocket.new(
375
- host,
376
- method(:websocket_open),
377
- method(:websocket_message),
378
- proc { |e| OnyxCord::LOGGER.error "VWS error: #{e}" },
379
- proc { |e| OnyxCord::LOGGER.warn "VWS close: #{e}" }
380
- )
381
-
382
- @bot.debug('VWS connected')
383
-
384
- # Block any further execution
385
- heartbeat_loop
386
- end
387
- end
34
+ require 'onyxcord/voice/network/udp'
35
+ require 'onyxcord/voice/network/websocket'
388
36
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'onyxcord/webhooks/embeds'
4
- require 'onyxcord/message_components'
4
+ require 'onyxcord/utils/message_components'
5
5
 
6
6
  module OnyxCord::Webhooks
7
7
  # A class that acts as a builder for a webhook message object.
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'onyxcord/http'
4
- require 'onyxcord/json'
3
+ require 'onyxcord/internal/http'
4
+ require 'onyxcord/internal/json'
5
5
 
6
6
  require 'onyxcord/webhooks/builder'
7
7
 
@@ -38,7 +38,7 @@ module OnyxCord::Webhooks
38
38
  # embed.image = OnyxCord::Webhooks::EmbedImage.new(url: 'https://i.imgur.com/PcMltU7.jpg')
39
39
  # end
40
40
  # end
41
- # @return [OnyxCord::HTTP::Response] the response returned by Discord.
41
+ # @return [::OnyxCord::Internal::HTTP::Response] the response returned by Discord.
42
42
  def execute(builder = nil, wait = false, components = nil, thread_id: nil, flags: nil, has_components: false, components_v2: false)
43
43
  raise TypeError, 'builder needs to be nil or like a OnyxCord::Webhooks::Builder!' unless
44
44
  (builder.respond_to?(:file) && builder.respond_to?(:to_multipart_hash)) || builder.respond_to?(:to_json_hash) || builder.nil?
@@ -61,9 +61,9 @@ module OnyxCord::Webhooks
61
61
  # @param name [String, nil] The default name.
62
62
  # @param avatar [String, #read, nil] The new avatar, in base64-encoded JPG format.
63
63
  # @param channel_id [String, Integer, nil] The channel to move the webhook to.
64
- # @return [OnyxCord::HTTP::Response] the response returned by Discord.
64
+ # @return [::OnyxCord::Internal::HTTP::Response] the response returned by Discord.
65
65
  def modify(name: nil, avatar: nil, channel_id: nil)
66
- OnyxCord::HTTP.patch(
66
+ ::OnyxCord::Internal::HTTP.patch(
67
67
  @url,
68
68
  { name: name, avatar: avatarise(avatar), channel_id: channel_id }.compact.to_json,
69
69
  'content-type' => 'application/json'
@@ -72,10 +72,10 @@ module OnyxCord::Webhooks
72
72
 
73
73
  # Delete this webhook.
74
74
  # @param reason [String, nil] The reason this webhook was deleted.
75
- # @return [OnyxCord::HTTP::Response] the response returned by Discord.
75
+ # @return [::OnyxCord::Internal::HTTP::Response] the response returned by Discord.
76
76
  # @note This is permanent and cannot be undone.
77
77
  def delete(reason: nil)
78
- OnyxCord::HTTP.delete(@url, 'X-Audit-Log-Reason' => reason)
78
+ ::OnyxCord::Internal::HTTP.delete(@url, 'X-Audit-Log-Reason' => reason)
79
79
  end
80
80
 
81
81
  # Edit a message from this webhook.
@@ -85,7 +85,7 @@ module OnyxCord::Webhooks
85
85
  # @param embeds [Array<Embed, Hash>]
86
86
  # @param allowed_mentions [Hash]
87
87
  # @param thread_id [String, Integer, nil] The id of the thread in which the message resides
88
- # @return [OnyxCord::HTTP::Response] the response returned by Discord.
88
+ # @return [::OnyxCord::Internal::HTTP::Response] the response returned by Discord.
89
89
  # @example Edit message content
90
90
  # client.edit_message(message_id, content: 'goodbye world!')
91
91
  # @example Edit a message via builder
@@ -106,7 +106,7 @@ module OnyxCord::Webhooks
106
106
  builder_flags = data[:flags] if data.is_a?(Hash)
107
107
  flags = View.apply_v2_flag(flags || builder_flags, components, force: has_components || components_v2)
108
108
  data = data.merge({ content: content, embeds: embeds, allowed_mentions: allowed_mentions, components: components, flags: flags }.compact)
109
- OnyxCord::HTTP.patch(
109
+ ::OnyxCord::Internal::HTTP.patch(
110
110
  "#{@url}/messages/#{message_id}#{(query.empty? ? '' : "?#{query}")}",
111
111
  data.compact.to_json,
112
112
  'content-type' => 'application/json'
@@ -115,9 +115,9 @@ module OnyxCord::Webhooks
115
115
 
116
116
  # Delete a message created by this webhook.
117
117
  # @param message_id [String, Integer] The ID of the message to delete.
118
- # @return [OnyxCord::HTTP::Response] the response returned by Discord.
118
+ # @return [::OnyxCord::Internal::HTTP::Response] the response returned by Discord.
119
119
  def delete_message(message_id)
120
- OnyxCord::HTTP.delete("#{@url}/messages/#{message_id}")
120
+ ::OnyxCord::Internal::HTTP.delete("#{@url}/messages/#{message_id}")
121
121
  end
122
122
 
123
123
  private
@@ -139,7 +139,7 @@ module OnyxCord::Webhooks
139
139
  flags = View.apply_v2_flag(flags || builder_flags, components, force: has_components)
140
140
  data = data.merge({ components: components })
141
141
  data[:flags] = flags unless flags.nil?
142
- OnyxCord::HTTP.post(
142
+ ::OnyxCord::Internal::HTTP.post(
143
143
  encode_url(wait, thread_id, with_components: components.any?),
144
144
  data.to_json,
145
145
  'content-type' => 'application/json'
@@ -153,7 +153,7 @@ module OnyxCord::Webhooks
153
153
  flags = View.apply_v2_flag(flags || builder_flags, components, force: has_components)
154
154
  data[:components] = components if components.any?
155
155
  data[:flags] = flags unless flags.nil?
156
- OnyxCord::HTTP.post(
156
+ ::OnyxCord::Internal::HTTP.post(
157
157
  encode_url(wait, thread_id, with_components: components.any?),
158
158
  data.compact
159
159
  )
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ class OnyxCord::Webhooks::Modal
4
+ class GroupBuilder
5
+ # @!visibility private
6
+ def initialize(type, custom_id, id, options = [], required = nil, min_values = nil, max_values = nil)
7
+ @id = id
8
+ @type = type
9
+ @custom_id = custom_id
10
+ @options = options
11
+ @required = required
12
+ @min_values = min_values
13
+ @max_values = max_values
14
+ end
15
+
16
+ # Add a checkbox component to the group.
17
+ # @param value [String] The value that the checkbox represents.
18
+ # @param label [String] The primary text of the checkbox.
19
+ # @param description [String, nil] The description of the checkbox.
20
+ # @param default [true, false, nil] Whether or not the checkbox should be checked by default.
21
+ def checkbox(value:, label:, description: nil, default: nil)
22
+ raise "Cannot add a checkbox to a #{@type}" unless @type == :checkbox_group
23
+
24
+ @options << { value: value, label: label, description: description, default: default }.compact
25
+ end
26
+
27
+ # Add a radio button component to the group.
28
+ # @param value [String] The value that the radio button represents.
29
+ # @param label [String] The primary text of the radio button.
30
+ # @param description [String, nil] The description of the radio button.
31
+ # @param default [true, false, nil] Whether or not the radio button should be selected by default.
32
+ def radio_button(value:, label:, description: nil, default: nil)
33
+ raise "Cannot add a radio button to a #{@type}" unless @type == :radio_group
34
+
35
+ @options << { value: value, label: label, description: description, default: default }.compact
36
+ end
37
+
38
+ alias_method :button, :radio_button
39
+
40
+ # @!visibility private
41
+ def to_h
42
+ {
43
+ id: @id,
44
+ type: COMPONENT_TYPES[@type],
45
+ custom_id: @custom_id,
46
+ options: @options.map(&:to_h),
47
+ required: @required,
48
+ min_values: @min_values,
49
+ max_values: @max_values
50
+ }.compact
51
+ end
52
+ end
53
+
54
+ # This builder is used when adding a label component to a modal.
55
+ end