grammerb 1.5.4-x64-mingw-ucrt → 1.5.5-x64-mingw-ucrt

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: 2fc30db9c3bd6bbb440d9dcdfea3405507f34696129a6e39bcbcdb328c34c8c0
4
- data.tar.gz: bd51e4a16901fec11e33d004856cfd50f9ef99941ce1264df5c829a913458a2f
3
+ metadata.gz: 4739abef8b70b5263bc0ba6bef807a09e42f0143691d158779cfe2754b2920c7
4
+ data.tar.gz: 0b6bab00e3740546f54a3a2e2b0e9ff14261dbf4cddac9878e9a596fe6aab53d
5
5
  SHA512:
6
- metadata.gz: ce3baad3cf1b2c3e52db29574ff77f1053d3b04c879e39e56d6896a20d8a8b6bd62684b3749d9db71cdf2672b74b7e5b8e22c857e9beb27d2fdd339fe94f2711
7
- data.tar.gz: 33d36b3142302b2dc39e50d635bc196ec84340ed3a6a22efeda13dc78231b546815f62b25113f32b62aeb64f70dd91e4282564e6899507f7984bc6888c4d6914
6
+ metadata.gz: 2e264ec47539096d2401f64b7374ae3f831224cba3c4fc5cf9d162de29244798a0447101361b023aa740eddc75a5852a224345a09e67596271c13f0c8f211531
7
+ data.tar.gz: b3d224d8436c2c02319399c7e824cbabb166eb1eb7c0130de46668b902be931d1d0311d6e3361b65c6eb145b7ca5bc40b0e4ed709021f67cfed50707a7ff5e71
Binary file
Binary file
Binary file
@@ -47,6 +47,8 @@ module Grammerb
47
47
  @logger = logger || default_logger
48
48
  @entity_cache = {}
49
49
  @entity_cache_mu = Mutex.new
50
+ @entity_cache_ttl = 300 # 5 minutes
51
+ @entity_cache_max = 1000
50
52
  end
51
53
 
52
54
  # --- Connection ---
@@ -249,13 +251,13 @@ module Grammerb
249
251
 
250
252
  def get_entity(entity)
251
253
  key = peer_id(entity)
252
- cached = @entity_cache_mu.synchronize { @entity_cache[key] }
254
+ cached = entity_cache_get(key)
253
255
  return cached if cached
254
256
 
255
257
  h = safe_native { @native.get_entity(key) }
256
258
  return nil unless h
257
259
  peer = Types::Peer.new(h)
258
- @entity_cache_mu.synchronize { @entity_cache[key] = peer }
260
+ entity_cache_set(key, peer)
259
261
  peer
260
262
  end
261
263
 
@@ -267,13 +269,13 @@ module Grammerb
267
269
  def resolve_username(username)
268
270
  normalized = username.to_s.delete_prefix("@")
269
271
  key = "@#{normalized}"
270
- cached = @entity_cache_mu.synchronize { @entity_cache[key] }
272
+ cached = entity_cache_get(key)
271
273
  return cached if cached
272
274
 
273
275
  h = safe_native { @native.resolve_username(normalized) }
274
276
  return nil unless h
275
277
  peer = Types::Peer.new(h)
276
- @entity_cache_mu.synchronize { @entity_cache[key] = peer }
278
+ entity_cache_set(key, peer)
277
279
  peer
278
280
  end
279
281
 
@@ -417,33 +419,33 @@ module Grammerb
417
419
 
418
420
  # --- Files ---
419
421
 
420
- def send_file(chat, path, caption: nil, parse_mode: nil, reply_to: nil, silent: false, schedule: nil, buttons: nil, reply_markup: nil)
422
+ def send_file(chat, path, caption: nil, parse_mode: nil, reply_to: nil, silent: false, schedule: nil, topic_id: nil, buttons: nil, reply_markup: nil)
421
423
  markup = reply_markup || (buttons ? build_buttons(buttons) : nil)
422
- h = safe_native { @native.send_file(peer_id(chat), path.to_s, (caption || "").to_s, parse_mode, reply_to, silent, schedule&.to_i, markup) }
424
+ h = safe_native { @native.send_file(peer_id(chat), path.to_s, (caption || "").to_s, parse_mode, reply_to, silent, schedule&.to_i, topic_id, markup) }
423
425
  wrap_message(h)
424
426
  end
425
427
 
426
- def send_photo(chat, path, caption: nil, parse_mode: nil, reply_to: nil, silent: false, schedule: nil, buttons: nil, reply_markup: nil)
428
+ def send_photo(chat, path, caption: nil, parse_mode: nil, reply_to: nil, silent: false, schedule: nil, topic_id: nil, buttons: nil, reply_markup: nil)
427
429
  markup = reply_markup || (buttons ? build_buttons(buttons) : nil)
428
- h = safe_native { @native.send_photo(peer_id(chat), path.to_s, (caption || "").to_s, parse_mode, reply_to, silent, schedule&.to_i, markup) }
430
+ h = safe_native { @native.send_photo(peer_id(chat), path.to_s, (caption || "").to_s, parse_mode, reply_to, silent, schedule&.to_i, topic_id, markup) }
429
431
  wrap_message(h)
430
432
  end
431
433
 
432
- def send_audio(chat, path, caption: nil, parse_mode: nil, duration: 0, title: nil, performer: nil, reply_to: nil, silent: false, schedule: nil, buttons: nil, reply_markup: nil)
434
+ def send_audio(chat, path, caption: nil, parse_mode: nil, duration: 0, title: nil, performer: nil, reply_to: nil, silent: false, schedule: nil, topic_id: nil, buttons: nil, reply_markup: nil)
433
435
  markup = reply_markup || (buttons ? build_buttons(buttons) : nil)
434
- h = safe_native { @native.send_audio(peer_id(chat), path.to_s, (caption || "").to_s, parse_mode, duration, title, performer, reply_to, silent, schedule&.to_i, markup) }
436
+ h = safe_native { @native.send_audio(peer_id(chat), path.to_s, (caption || "").to_s, parse_mode, duration, title, performer, reply_to, silent, schedule&.to_i, topic_id, markup) }
435
437
  wrap_message(h)
436
438
  end
437
439
 
438
- def send_video(chat, path, caption: nil, parse_mode: nil, duration: 0, width: 0, height: 0, supports_streaming: true, round_message: false, reply_to: nil, silent: false, schedule: nil, buttons: nil, reply_markup: nil)
440
+ def send_video(chat, path, caption: nil, parse_mode: nil, duration: 0, width: 0, height: 0, supports_streaming: true, round_message: false, reply_to: nil, silent: false, schedule: nil, topic_id: nil, buttons: nil, reply_markup: nil)
439
441
  markup = reply_markup || (buttons ? build_buttons(buttons) : nil)
440
- h = safe_native { @native.send_video(peer_id(chat), path.to_s, (caption || "").to_s, parse_mode, duration, width, height, supports_streaming, round_message, reply_to, silent, schedule&.to_i, markup) }
442
+ h = safe_native { @native.send_video(peer_id(chat), path.to_s, (caption || "").to_s, parse_mode, duration, width, height, supports_streaming, round_message, reply_to, silent, schedule&.to_i, topic_id, markup) }
441
443
  wrap_message(h)
442
444
  end
443
445
 
444
- def send_voice(chat, path, caption: nil, parse_mode: nil, duration: 0, waveform: nil, reply_to: nil, silent: false, schedule: nil, buttons: nil, reply_markup: nil)
446
+ def send_voice(chat, path, caption: nil, parse_mode: nil, duration: 0, waveform: nil, reply_to: nil, silent: false, schedule: nil, topic_id: nil, buttons: nil, reply_markup: nil)
445
447
  markup = reply_markup || (buttons ? build_buttons(buttons) : nil)
446
- h = safe_native { @native.send_voice(peer_id(chat), path.to_s, (caption || "").to_s, parse_mode, duration, waveform, reply_to, silent, schedule&.to_i, markup) }
448
+ h = safe_native { @native.send_voice(peer_id(chat), path.to_s, (caption || "").to_s, parse_mode, duration, waveform, reply_to, silent, schedule&.to_i, topic_id, markup) }
447
449
  wrap_message(h)
448
450
  end
449
451
 
@@ -455,15 +457,19 @@ module Grammerb
455
457
  safe_native { @native.send_album(peer_id(chat), items, reply_to, silent, markup) }.map { |h| h ? wrap_message(h) : nil }
456
458
  end
457
459
 
458
- def download_media(chat, message_id, path, &progress)
460
+ def download_media(chat, message_id, path, timeout: 300, &progress)
459
461
  if progress
460
462
  safe_native { @native.start_download_media(peer_id(chat), message_id, path.to_s) }
463
+ deadline = Process.clock_gettime(Process::CLOCK_MONOTONIC) + timeout
461
464
  loop do
462
- p = @native.poll_download_progress
465
+ p = safe_native { @native.poll_download_progress }
463
466
  if p
464
467
  progress.call(p[:downloaded], p[:total])
465
468
  break if p[:done]
466
469
  else
470
+ if Process.clock_gettime(Process::CLOCK_MONOTONIC) > deadline
471
+ raise Errors::TimeoutError, "Download timed out after #{timeout} seconds"
472
+ end
467
473
  sleep 0.05
468
474
  end
469
475
  end
@@ -474,39 +480,39 @@ module Grammerb
474
480
 
475
481
  # --- Special Media ---
476
482
 
477
- def send_location(chat, lat, long, accuracy_radius: nil, reply_to: nil, silent: false, schedule: nil, buttons: nil, reply_markup: nil)
483
+ def send_location(chat, lat, long, accuracy_radius: nil, reply_to: nil, silent: false, schedule: nil, topic_id: nil, buttons: nil, reply_markup: nil)
478
484
  markup = reply_markup || (buttons ? build_buttons(buttons) : nil)
479
- h = safe_native { @native.send_location(peer_id(chat), lat.to_f, long.to_f, accuracy_radius, reply_to, silent, schedule&.to_i, markup) }
485
+ h = safe_native { @native.send_location(peer_id(chat), lat.to_f, long.to_f, accuracy_radius, reply_to, silent, schedule&.to_i, topic_id, markup) }
480
486
  wrap_message(h)
481
487
  end
482
488
 
483
- def send_venue(chat, lat, long, title:, address:, provider: "", venue_id: "", venue_type: "", reply_to: nil, silent: false, schedule: nil, buttons: nil, reply_markup: nil)
489
+ def send_venue(chat, lat, long, title:, address:, provider: "", venue_id: "", venue_type: "", reply_to: nil, silent: false, schedule: nil, topic_id: nil, buttons: nil, reply_markup: nil)
484
490
  markup = reply_markup || (buttons ? build_buttons(buttons) : nil)
485
- h = safe_native { @native.send_venue(peer_id(chat), lat.to_f, long.to_f, title.to_s, address.to_s, provider.to_s, venue_id.to_s, venue_type.to_s, reply_to, silent, schedule&.to_i, markup) }
491
+ h = safe_native { @native.send_venue(peer_id(chat), lat.to_f, long.to_f, title.to_s, address.to_s, provider.to_s, venue_id.to_s, venue_type.to_s, reply_to, silent, schedule&.to_i, topic_id, markup) }
486
492
  wrap_message(h)
487
493
  end
488
494
 
489
- def send_contact(chat, phone_number:, first_name:, last_name: "", vcard: "", reply_to: nil, silent: false, schedule: nil, buttons: nil, reply_markup: nil)
495
+ def send_contact(chat, phone_number:, first_name:, last_name: "", vcard: "", reply_to: nil, silent: false, schedule: nil, topic_id: nil, buttons: nil, reply_markup: nil)
490
496
  markup = reply_markup || (buttons ? build_buttons(buttons) : nil)
491
- h = safe_native { @native.send_contact(peer_id(chat), phone_number.to_s, first_name.to_s, last_name.to_s, vcard.to_s, reply_to, silent, schedule&.to_i, markup) }
497
+ h = safe_native { @native.send_contact(peer_id(chat), phone_number.to_s, first_name.to_s, last_name.to_s, vcard.to_s, reply_to, silent, schedule&.to_i, topic_id, markup) }
492
498
  wrap_message(h)
493
499
  end
494
500
 
495
- def send_dice(chat, emoticon: "\u{1F3B2}", reply_to: nil, silent: false, schedule: nil, buttons: nil, reply_markup: nil)
501
+ def send_dice(chat, emoticon: "\u{1F3B2}", reply_to: nil, silent: false, schedule: nil, topic_id: nil, buttons: nil, reply_markup: nil)
496
502
  markup = reply_markup || (buttons ? build_buttons(buttons) : nil)
497
- h = safe_native { @native.send_dice(peer_id(chat), emoticon.to_s, reply_to, silent, schedule&.to_i, markup) }
503
+ h = safe_native { @native.send_dice(peer_id(chat), emoticon.to_s, reply_to, silent, schedule&.to_i, topic_id, markup) }
498
504
  wrap_message(h)
499
505
  end
500
506
 
501
- def send_sticker(chat, path, reply_to: nil, silent: false, schedule: nil, buttons: nil, reply_markup: nil)
507
+ def send_sticker(chat, path, reply_to: nil, silent: false, schedule: nil, topic_id: nil, buttons: nil, reply_markup: nil)
502
508
  markup = reply_markup || (buttons ? build_buttons(buttons) : nil)
503
- h = safe_native { @native.send_sticker(peer_id(chat), path.to_s, reply_to, silent, schedule&.to_i, markup) }
509
+ h = safe_native { @native.send_sticker(peer_id(chat), path.to_s, reply_to, silent, schedule&.to_i, topic_id, markup) }
504
510
  wrap_message(h)
505
511
  end
506
512
 
507
- def send_animation(chat, path, caption: nil, parse_mode: nil, duration: 0, width: 0, height: 0, reply_to: nil, silent: false, schedule: nil, buttons: nil, reply_markup: nil)
513
+ def send_animation(chat, path, caption: nil, parse_mode: nil, duration: 0, width: 0, height: 0, reply_to: nil, silent: false, schedule: nil, topic_id: nil, buttons: nil, reply_markup: nil)
508
514
  markup = reply_markup || (buttons ? build_buttons(buttons) : nil)
509
- h = safe_native { @native.send_animation(peer_id(chat), path.to_s, (caption || "").to_s, parse_mode, duration, width, height, reply_to, silent, schedule&.to_i, markup) }
515
+ h = safe_native { @native.send_animation(peer_id(chat), path.to_s, (caption || "").to_s, parse_mode, duration, width, height, reply_to, silent, schedule&.to_i, topic_id, markup) }
510
516
  wrap_message(h)
511
517
  end
512
518
 
@@ -718,6 +724,30 @@ module Grammerb
718
724
 
719
725
  private
720
726
 
727
+ def entity_cache_get(key)
728
+ @entity_cache_mu.synchronize do
729
+ entry = @entity_cache[key]
730
+ return nil unless entry
731
+ value, ts = entry
732
+ if (Process.clock_gettime(Process::CLOCK_MONOTONIC) - ts) > @entity_cache_ttl
733
+ @entity_cache.delete(key)
734
+ return nil
735
+ end
736
+ value
737
+ end
738
+ end
739
+
740
+ def entity_cache_set(key, value)
741
+ @entity_cache_mu.synchronize do
742
+ # Evict oldest entries when cache is full
743
+ if @entity_cache.size >= @entity_cache_max
744
+ oldest_key = @entity_cache.min_by { |_, (_, ts)| ts }&.first
745
+ @entity_cache.delete(oldest_key) if oldest_key
746
+ end
747
+ @entity_cache[key] = [value, Process.clock_gettime(Process::CLOCK_MONOTONIC)]
748
+ end
749
+ end
750
+
721
751
  # Wrap native calls: catch RuntimeError from Rust and re-raise as Grammerb::Errors.
722
752
  def safe_native
723
753
  yield
@@ -5,6 +5,7 @@ module Grammerb
5
5
  class ConnectionError < Error; end
6
6
  class AuthError < Error; end
7
7
  class NotConnectedError < Error; end
8
+ class TimeoutError < Error; end
8
9
 
9
10
  # Telegram-specific errors
10
11
  class RPCError < Error
@@ -1,4 +1,4 @@
1
1
  # lib/grammerb/version.rb
2
2
  module Grammerb
3
- VERSION = "1.5.4"
3
+ VERSION = "1.5.5"
4
4
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grammerb
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.4
4
+ version: 1.5.5
5
5
  platform: x64-mingw-ucrt
6
6
  authors:
7
7
  - Developer