onyxcord 2.0.6 → 2.0.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c794e2e7f5ad51dea52e27c049fb7d08fb7b54c84b452243fe549cd54f46dd5d
4
- data.tar.gz: 2f7e1a9df9cf56085e31dd7bc13e843f8c5bee2e9083817305e6936117c92dd4
3
+ metadata.gz: '080907ed18fd9ca727ddeb4d6ee21935995b3027c53a864442b9ffb315a9fe1e'
4
+ data.tar.gz: 4ad0ff3358ae5bde79a83f8e019a007661a1225d1bc752b06c2c1b992a1eb0a4
5
5
  SHA512:
6
- metadata.gz: dce8555d60a8bf6662bfc357c64918e75ff803ab30c43c93dab390756ee52e0057f20914367ec4cce89e5a6906c0745f99b89f42953bb9b91648caa3fe296378
7
- data.tar.gz: 7b25cd2d344182abbdce7fb5f74f8cffb7dea3ad478d6a03e9018ea138635fac13e9203184f656f677c39b85b26f1a8287f24ac6a855b5b9ae64ec12165e8c72
6
+ metadata.gz: c9098f8a981433ab24e3567bbdbb057d12ac0cf6d80358e2c99dfce84a04e7d68ed3fd59b5b71479580c6997cd17aaac52250b33179754565df0e95493cfc9b4
7
+ data.tar.gz: 137922d8f76e11add880ec027167ce04bbfa3d18b8547a8ed5b726184a7448b4629e0875f49455193185ade34c119d87a49bbbff59070d56eb3cc21c80c39a6f
data/CHANGELOG.md CHANGED
@@ -1,5 +1,47 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.0.13 - 2026-06-28
4
+
5
+ ### Correcoes de gateway
6
+
7
+ - Evita chamadas REST em `Bot#update_voice_state` ao processar `VOICE_STATE_UPDATE`.
8
+ - Torna `GUILD_UPDATE` tolerante a guild ainda nao cacheada.
9
+
10
+ ## 2.0.12 - 2026-06-28
11
+
12
+ ### Correcoes de gateway
13
+
14
+ - Evita chamadas REST durante a criação de eventos do Gateway para `VOICE_STATE_UPDATE` e `CHANNEL_CREATE`.
15
+ - Trata `Async::Cancel` durante dispatch do Gateway como cancelamento esperado, sem registrar erro fatal.
16
+
17
+ ## 2.0.11 - 2026-06-28
18
+
19
+ ### Correcoes de estabilidade
20
+
21
+ - Isola a sessao HTTP persistente por thread para evitar que tarefas em segundo plano disputem a mesma conexao REST das interacoes.
22
+
23
+ ## 2.0.10 - 2026-06-28
24
+
25
+ ### Correcoes de voz
26
+
27
+ - Mantem `channel_id` no cache de `VoiceState` mesmo quando o objeto do canal ainda nao foi resolvido.
28
+ - Expoe `channel_id` e `old_channel_id` em `VoiceStateUpdateEvent`, corrigindo entradas em call que pareciam `nil -> nil`.
29
+ - Permite que raw dispatch handlers filtrem pacotes com chaves string ou symbol.
30
+
31
+ ## 2.0.9 - 2026-06-28
32
+
33
+ ### Correcoes de estabilidade
34
+
35
+ - Tolera um heartbeat sem ACK antes de reconectar, evitando queda por ACK atrasado isolado.
36
+
37
+ ## 2.0.8 - 2026-06-28
38
+
39
+ ### Correcoes de gateway
40
+
41
+ - Forca WebSocket do Gateway e do cliente generico em HTTP/1.1 para evitar `Async::WebSocket::ConnectionError: Failed to negotiate connection!` ao conectar no Discord.
42
+ - Desativa extensoes WebSocket no handshake para evitar close `Error while decoding payload` no Gateway do Discord.
43
+ - Remove o empacotamento separado `onyxcord-webhooks`; webhooks continuam incluidos diretamente na gem `onyxcord`.
44
+
3
45
  ## 2.0.6 - 2026-06-28
4
46
 
5
47
  ### Correcoes de empacotamento
@@ -64,7 +106,7 @@ bot.sync_application_commands!(server_id: ENV.fetch('DISCORD_SERVER_ID'))
64
106
  - **Gateway via Async-WebSocket**: Substituída a implementação de raw TCP sockets + `websocket-client-simple` por `async-websocket`, proporcionando um event loop de gateway extremamente rápido e escalável.
65
107
  - **Parse JSON via Oj**: A gem `oj` foi integrada em modo de compatibilidade (`mode: :compat`), acelerando transparentemente todas as serializações e deserializações de pacotes do Discord na lib inteira.
66
108
  - **Cache Inteligente LRU**: Os caches em memória (usuários, canais, servidores, membros) agora utilizam `LruRedux::ThreadSafeCache`. Os tamanhos padrão foram aumentados (`users: 50_000`, `channels: 10_000`, `servers: 1_000`, `members: 100_000`) e podem ser customizados via `OnyxCord.configure { |c| c.cache_sizes.users = 100_000 }`.
67
- - **Fusão do Webhooks**: A funcionalidade da gem separada `onyxcord-webhooks` foi integrada diretamente no núcleo da gem `onyxcord`. A gem `onyxcord-webhooks` agora atua apenas como um shim de transição deprecado.
109
+ - **Fusão do Webhooks**: A funcionalidade da gem separada `onyxcord-webhooks` foi integrada diretamente no núcleo da gem `onyxcord`; nao ha mais pacote separado para publicar.
68
110
  - **Alvo Ruby ≥ 3.4**: Atualizada a versão mínima requerida do Ruby para aproveitar as otimizações modernas do interpretador e fibras.
69
111
 
70
112
  ## 1.1.8 - 2026-06-28
@@ -81,7 +123,6 @@ bot.sync_application_commands!(server_id: ENV.fetch('DISCORD_SERVER_ID'))
81
123
  - `ruby -c lib/onyxcord/data/component.rb`: sucesso.
82
124
  - `ruby -c spec/components_v2_spec.rb`: sucesso.
83
125
  - `gem build onyxcord.gemspec`: sucesso.
84
- - `gem build onyxcord-webhooks.gemspec`: sucesso.
85
126
 
86
127
  ## 1.1.7 - 2026-06-28
87
128
 
@@ -93,7 +134,6 @@ bot.sync_application_commands!(server_id: ENV.fetch('DISCORD_SERVER_ID'))
93
134
  ### Validacao
94
135
 
95
136
  - `ruby -c onyxcord.gemspec`: sucesso.
96
- - `ruby -c onyxcord-webhooks.gemspec`: sucesso.
97
137
 
98
138
  ## 1.1.6 - 2026-06-28
99
139
 
@@ -160,4 +200,3 @@ bot.sync_application_commands!(server_id: ENV.fetch('DISCORD_SERVER_ID'))
160
200
  - `bundle exec rspec`: 456 exemplos, 0 falhas, 3 pendentes.
161
201
  - RuboCop nos arquivos alterados: sem offenses.
162
202
  - `gem build onyxcord.gemspec`: sucesso.
163
- - `gem build onyxcord-webhooks.gemspec`: sucesso.
data/Rakefile CHANGED
@@ -6,12 +6,8 @@ namespace :main do
6
6
  Bundler::GemHelper.install_tasks(name: 'onyxcord')
7
7
  end
8
8
 
9
- namespace :webhooks do
10
- Bundler::GemHelper.install_tasks(name: 'onyxcord-webhooks')
11
- end
12
-
13
- task build: %i[main:build webhooks:build]
14
- task release: %i[main:release webhooks:release]
9
+ task build: :'main:build'
10
+ task release: :'main:release'
15
11
 
16
12
  # Make "build" the default task
17
13
  task default: :build
data/lib/onyxcord/bot.rb CHANGED
@@ -1119,12 +1119,12 @@ module OnyxCord
1119
1119
  @session_id = data['session_id']
1120
1120
 
1121
1121
  server_id = data['guild_id'].to_i
1122
- server = server(server_id)
1122
+ server = @servers&.[](server_id)
1123
1123
  return unless server
1124
1124
 
1125
1125
  user_id = data['user_id'].to_i
1126
1126
  old_voice_state = server.voice_states[user_id]
1127
- old_channel_id = old_voice_state.voice_channel&.id if old_voice_state
1127
+ old_channel_id = old_voice_state&.channel_id || old_voice_state&.voice_channel&.id
1128
1128
 
1129
1129
  server.update_voice_state(data)
1130
1130
 
@@ -1132,7 +1132,8 @@ module OnyxCord
1132
1132
  if user_id == @profile.id && existing_voice
1133
1133
  new_channel_id = data['channel_id']
1134
1134
  if new_channel_id
1135
- new_channel = channel(new_channel_id)
1135
+ channel_id = new_channel_id.to_i
1136
+ new_channel = @channels&.[](channel_id) || server.channels.find { |channel| channel.id == channel_id }
1136
1137
  existing_voice.channel = new_channel
1137
1138
  else
1138
1139
  voice_destroy(server_id)
@@ -1248,7 +1249,15 @@ module OnyxCord
1248
1249
 
1249
1250
  # Internal handler for GUILD_UPDATE
1250
1251
  def update_guild(data)
1251
- @servers[data['id'].to_i].update_data(data)
1252
+ server_id = data['id'].to_i
1253
+ server = @servers&.[](server_id)
1254
+
1255
+ if server
1256
+ server.update_data(data)
1257
+ else
1258
+ LOGGER.warn("GUILD_UPDATE received for uncached server #{server_id}; caching from payload")
1259
+ ensure_server(data, true)
1260
+ end
1252
1261
  end
1253
1262
 
1254
1263
  # Internal handler for GUILD_DELETE
@@ -1868,6 +1877,11 @@ module OnyxCord
1868
1877
  raise_event(event)
1869
1878
  end
1870
1879
  rescue Exception => e
1880
+ if defined?(Async::Cancel) && e.is_a?(Async::Cancel)
1881
+ LOGGER.debug('Gateway message handling was cancelled.')
1882
+ return
1883
+ end
1884
+
1871
1885
  LOGGER.error('Gateway message error!')
1872
1886
  log_exception(e)
1873
1887
  end
@@ -697,13 +697,15 @@ module OnyxCord
697
697
  end
698
698
 
699
699
  # Update the existing voice state (or the one we just created)
700
- channel = @channels_by_id[data['channel_id'].to_i]
700
+ channel_id = data['channel_id'].to_i
701
+ channel = @channels_by_id[channel_id]
701
702
  @voice_states[user_id].update(
702
703
  channel,
703
704
  data['mute'],
704
705
  data['deaf'],
705
706
  data['self_mute'],
706
- data['self_deaf']
707
+ data['self_deaf'],
708
+ channel_id
707
709
  )
708
710
  else
709
711
  # The user is not in a voice channel anymore, so delete its voice state
@@ -22,6 +22,9 @@ module OnyxCord
22
22
  # @return [Channel] the voice channel this voice state's member is in.
23
23
  attr_reader :voice_channel
24
24
 
25
+ # @return [Integer, nil] the ID of the voice channel this member is in.
26
+ attr_reader :channel_id
27
+
25
28
  # @!visibility private
26
29
  def initialize(user_id)
27
30
  @user_id = user_id
@@ -30,8 +33,9 @@ module OnyxCord
30
33
  # Update this voice state with new data from Discord
31
34
  # @note For internal use only.
32
35
  # @!visibility private
33
- def update(channel, mute, deaf, self_mute, self_deaf)
36
+ def update(channel, mute, deaf, self_mute, self_deaf, channel_id = nil)
34
37
  @voice_channel = channel
38
+ @channel_id = channel_id&.to_i || channel&.id
35
39
  @mute = mute
36
40
  @deaf = deaf
37
41
  @self_mute = self_mute
@@ -32,7 +32,23 @@ module OnyxCord::Events
32
32
  # @!visibility private
33
33
  def initialize(data, bot)
34
34
  @bot = bot
35
- @channel = data.is_a?(OnyxCord::Channel) ? data : bot.channel(data['id'].to_i)
35
+ @channel = if data.is_a?(OnyxCord::Channel)
36
+ data
37
+ else
38
+ cached_channel(bot, data['id']) || OnyxCord::Channel.new(data, bot, cached_server(bot, data['guild_id']))
39
+ end
40
+ end
41
+
42
+ def cached_channel(bot, channel_id)
43
+ channels = bot.instance_variable_get(:@channels)
44
+ channels&.[](channel_id.to_i)
45
+ end
46
+
47
+ def cached_server(bot, server_id)
48
+ return nil unless server_id
49
+
50
+ servers = bot.instance_variable_get(:@servers)
51
+ servers&.[](server_id.to_i)
36
52
  end
37
53
  end
38
54
 
@@ -57,7 +57,7 @@ module OnyxCord::Events
57
57
  def matches?(packet)
58
58
  return true unless @filter
59
59
 
60
- type = packet['t']
60
+ type = packet['t'] || packet[:t]
61
61
  return false unless type
62
62
 
63
63
  if @filter.is_a?(Regexp)
@@ -6,11 +6,17 @@ require 'onyxcord/data'
6
6
  module OnyxCord::Events
7
7
  # Event raised when a user's voice state updates
8
8
  class VoiceStateUpdateEvent < Event
9
- attr_reader :user, :token, :suppress, :session_id, :self_mute, :self_deaf, :mute, :deaf, :server, :channel
9
+ attr_reader :user, :user_id, :token, :suppress, :session_id, :self_mute, :self_deaf, :mute, :deaf, :server, :channel
10
10
 
11
11
  # @return [Channel, nil] the old channel this user was on, or nil if the user is newly joining voice.
12
12
  attr_reader :old_channel
13
13
 
14
+ # @return [Integer, nil] the current voice channel ID, or nil if the user left voice.
15
+ attr_reader :channel_id
16
+
17
+ # @return [Integer, nil] the previous voice channel ID, or nil if the user joined voice.
18
+ attr_reader :old_channel_id
19
+
14
20
  # @!visibility private
15
21
  def initialize(data, old_channel_id, bot)
16
22
  @bot = bot
@@ -22,12 +28,35 @@ module OnyxCord::Events
22
28
  @self_deaf = data['self_deaf']
23
29
  @mute = data['mute']
24
30
  @deaf = data['deaf']
25
- @server = bot.server(data['guild_id'].to_i)
31
+ @user_id = data['user_id']&.to_i
32
+ @channel_id = data['channel_id']&.to_i
33
+ @old_channel_id = old_channel_id&.to_i
34
+ @server = cached_server(bot, data['guild_id'])
26
35
  return unless @server
27
36
 
28
- @channel = bot.channel(data['channel_id'].to_i) if data['channel_id']
29
- @old_channel = bot.channel(old_channel_id) if old_channel_id
30
- @user = bot.user(data['user_id'].to_i)
37
+ @channel = cached_channel(bot, @channel_id, @server)
38
+ @old_channel = cached_channel(bot, @old_channel_id, @server)
39
+ @user = cached_user(bot, data)
40
+ end
41
+
42
+ def cached_server(bot, server_id)
43
+ servers = bot.instance_variable_get(:@servers)
44
+ servers&.[](server_id.to_i)
45
+ end
46
+
47
+ def cached_channel(bot, channel_id, server)
48
+ return nil unless channel_id
49
+
50
+ channels = bot.instance_variable_get(:@channels)
51
+ channels&.[](channel_id.to_i) || server.channels.find { |channel| channel.id == channel_id.to_i }
52
+ end
53
+
54
+ def cached_user(bot, data)
55
+ user_data = data.dig('member', 'user') || data['user']
56
+ return bot.ensure_user(user_data) if user_data
57
+
58
+ users = bot.instance_variable_get(:@users)
59
+ users&.[](data['user_id'].to_i)
31
60
  end
32
61
  end
33
62
 
@@ -39,6 +68,8 @@ module OnyxCord::Events
39
68
 
40
69
  [
41
70
  matches_all(@attributes[:from], event.user) do |a, e|
71
+ next unless e
72
+
42
73
  a == case a
43
74
  when String
44
75
  e.name
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'async'
4
4
  require 'async/http/endpoint'
5
+ require 'async/http/protocol/http11'
5
6
  require 'async/websocket/client'
6
7
  require 'onyxcord/async/runtime'
7
8
  require 'onyxcord/rate_limiter/gateway'
@@ -83,6 +84,7 @@ module OnyxCord
83
84
  @connection = nil
84
85
  @closed = true
85
86
  @pipe_broken = false
87
+ @missed_heartbeat_acks = 0
86
88
  end
87
89
 
88
90
  # Connect to the gateway server inside an Async reactor.
@@ -141,10 +143,17 @@ module OnyxCord
141
143
  def heartbeat
142
144
  if check_heartbeat_acks
143
145
  unless @last_heartbeat_acked
144
- LOGGER.warn('Last heartbeat was not acked — zombie connection! Reconnecting')
145
- @pipe_broken = true
146
- reconnect
147
- return
146
+ @missed_heartbeat_acks += 1
147
+ if @missed_heartbeat_acks >= 2
148
+ LOGGER.warn('Last heartbeats were not acked — zombie connection! Reconnecting')
149
+ @pipe_broken = true
150
+ reconnect
151
+ return
152
+ end
153
+
154
+ LOGGER.warn('Last heartbeat was not acked — waiting one more interval before reconnecting')
155
+ else
156
+ @missed_heartbeat_acks = 0
148
157
  end
149
158
  @last_heartbeat_acked = false
150
159
  end
@@ -218,6 +227,7 @@ module OnyxCord
218
227
 
219
228
  def setup_heartbeats(interval)
220
229
  @last_heartbeat_acked = true
230
+ @missed_heartbeat_acks = 0
221
231
  return if @heartbeat_task
222
232
 
223
233
  @heartbeat_interval = interval
@@ -293,9 +303,9 @@ module OnyxCord
293
303
  @pipe_broken = false
294
304
  @closed = false
295
305
 
296
- endpoint = Async::HTTP::Endpoint.parse(url)
306
+ endpoint = websocket_endpoint(url)
297
307
 
298
- Async::WebSocket::Client.connect(endpoint) do |connection|
308
+ Async::WebSocket::Client.connect(endpoint, extensions: nil) do |connection|
299
309
  @connection = connection
300
310
  LOGGER.debug('WebSocket connected')
301
311
 
@@ -313,6 +323,14 @@ module OnyxCord
313
323
  @connection = nil
314
324
  end
315
325
 
326
+ def websocket_endpoint(url)
327
+ Async::HTTP::Endpoint.parse(
328
+ url,
329
+ protocol: Async::HTTP::Protocol::HTTP11,
330
+ alpn_protocols: ['http/1.1']
331
+ )
332
+ end
333
+
316
334
  def handle_open; end
317
335
 
318
336
  def handle_error(e)
@@ -423,7 +441,10 @@ module OnyxCord
423
441
  # Op 11
424
442
  def handle_heartbeat_ack(packet)
425
443
  LOGGER.debug("Heartbeat ACK: #{packet.inspect}")
426
- @last_heartbeat_acked = true if @check_heartbeat_acks
444
+ if @check_heartbeat_acks
445
+ @last_heartbeat_acked = true
446
+ @missed_heartbeat_acks = 0
447
+ end
427
448
  end
428
449
 
429
450
  def handle_internal_close(e)
@@ -453,7 +474,7 @@ module OnyxCord
453
474
 
454
475
  @send_limiter.wait
455
476
 
456
- @connection.write(Protocol::WebSocket::TextMessage.generate(data))
477
+ @connection.write(data)
457
478
  @connection.flush
458
479
  rescue StandardError => e
459
480
  @pipe_broken = true
data/lib/onyxcord/http.rb CHANGED
@@ -45,15 +45,15 @@ module OnyxCord
45
45
 
46
46
  module_function
47
47
 
48
- # The shared HTTPX session with persistent connections.
48
+ # The shared HTTPX session with persistent connections for the current thread.
49
49
  def session
50
- @session ||= HTTPX.plugin(:persistent)
51
- .plugin(:follow_redirects)
50
+ Thread.current[:onyxcord_http_session] ||= HTTPX.plugin(:persistent)
51
+ .plugin(:follow_redirects)
52
52
  end
53
53
 
54
54
  # Reset the HTTP session (useful for tests).
55
55
  def reset!
56
- @session = nil
56
+ Thread.current[:onyxcord_http_session] = nil
57
57
  end
58
58
 
59
59
  # Perform a raw HTTP request and return a {Response}.
@@ -3,5 +3,5 @@
3
3
  # OnyxCord and all its functionality, in this case only the version.
4
4
  module OnyxCord
5
5
  # The current version of onyxcord.
6
- VERSION = '2.0.6'
6
+ VERSION = '2.0.13'
7
7
  end
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Webhook support for onyxcord
3
+ # Webhook support bundled in onyxcord.
4
4
  module OnyxCord
5
5
  module Webhooks
6
- # The current version of onyxcord-webhooks.
7
- VERSION = '2.0.6'
6
+ # Kept for compatibility with code that checks the webhooks module version.
7
+ VERSION = '2.0.13'
8
8
  end
9
9
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'onyxcord/async/runtime'
4
4
  require 'async/http/endpoint'
5
+ require 'async/http/protocol/http11'
5
6
  require 'async/websocket/client'
6
7
 
7
8
  module OnyxCord
@@ -43,10 +44,10 @@ module OnyxCord
43
44
  private
44
45
 
45
46
  def connect
46
- endpoint = Async::HTTP::Endpoint.parse(@host)
47
+ endpoint = websocket_endpoint(@host)
47
48
 
48
49
  @task = OnyxCord::AsyncRuntime.async do
49
- Async::WebSocket::Client.connect(endpoint) do |connection|
50
+ Async::WebSocket::Client.connect(endpoint, extensions: nil) do |connection|
50
51
  @connection = connection
51
52
  @connected = true
52
53
  @open_handler&.call
@@ -64,5 +65,13 @@ module OnyxCord
64
65
  rescue StandardError => e
65
66
  @error_handler&.call(e)
66
67
  end
68
+
69
+ def websocket_endpoint(url)
70
+ Async::HTTP::Endpoint.parse(
71
+ url,
72
+ protocol: Async::HTTP::Protocol::HTTP11,
73
+ alpn_protocols: ['http/1.1']
74
+ )
75
+ end
67
76
  end
68
77
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: onyxcord
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.6
4
+ version: 2.0.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gustavo Silva
@@ -506,7 +506,6 @@ files:
506
506
  - lib/onyxcord/webhooks/version.rb
507
507
  - lib/onyxcord/webhooks/view.rb
508
508
  - lib/onyxcord/websocket.rb
509
- - onyxcord-webhooks.gemspec
510
509
  - onyxcord.gemspec
511
510
  homepage: https://github.com/kruldevb/OnyxCord
512
511
  licenses:
@@ -1,39 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'lib/onyxcord/webhooks/version'
4
-
5
- Gem::Specification.new do |spec|
6
- spec.name = 'onyxcord-webhooks'
7
- spec.version = OnyxCord::Webhooks::VERSION
8
- spec.authors = ['Gustavo Silva']
9
- spec.email = ['gustavosilva8kt@gmail.com']
10
-
11
- spec.summary = '[DEPRECATED] Webhook client for onyxcord — now bundled into the onyxcord gem'
12
- spec.description = "This gem is deprecated. Webhooks are now included in the onyxcord gem. Install 'onyxcord' instead."
13
- spec.homepage = 'https://github.com/kruldevb/OnyxCord'
14
- spec.license = 'MIT'
15
-
16
- spec.files = ['lib/onyxcord/webhooks.rb', 'lib/onyxcord/webhooks/version.rb']
17
- spec.bindir = 'exe'
18
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
- spec.require_paths = ['lib']
20
-
21
- # This gem now simply depends on the main onyxcord gem
22
- spec.add_dependency 'onyxcord', "~> #{OnyxCord::Webhooks::VERSION}"
23
-
24
- spec.required_ruby_version = '>= 3.4'
25
- spec.metadata = {
26
- 'bug_tracker_uri' => 'https://github.com/kruldevb/OnyxCord/issues',
27
- 'documentation_uri' => 'https://github.com/kruldevb/OnyxCord#readme',
28
- 'source_code_uri' => 'https://github.com/kruldevb/OnyxCord',
29
- 'rubygems_mfa_required' => 'true'
30
- }
31
-
32
- spec.post_install_message = <<~MSG
33
- ⚠️ onyxcord-webhooks is DEPRECATED.
34
- Webhooks are now bundled into the 'onyxcord' gem.
35
- Please update your Gemfile:
36
- gem 'onyxcord', '~> 2.0'
37
- and remove 'onyxcord-webhooks'.
38
- MSG
39
- end