module IrcUserPing
IrcUserPing — testable user ping round-trip tracking (IRC PING/PONG and CTCP). Public: ping_message, user_ping_command, register!, record_reply!, record_pong_reply!, take! Depends: Normalize Tests: test/lib/irc_user_ping_test.rb
Constants
- PING_PREFIX
Public Instance Methods
Source
# File lib/irc_user_ping.rb, line 31 def ctcp_ping_message(token:) "PING #{ping_message(token: token)}" end
Source
# File lib/irc_user_ping.rb, line 104 def find_pending_by_pong_nick(params, store: pending_store) pong_nicks(params).each do |nick| key = store_key(nick) entry = store[key] return [key, entry] if entry && !entry[:award] end nil end
Source
# File lib/irc_user_ping.rb, line 130 def parse_token(args) Array(args).each do |part| text = part.to_s.sub(/\A:/, "") match = text.match(/\A#{PING_PREFIX}(\d+)\z/) return match[1].to_i if match end nil end
Source
# File lib/irc_user_ping.rb, line 23 def ping_message(token:) "#{PING_PREFIX}#{token}" end
Source
# File lib/irc_user_ping.rb, line 113 def pong_nicks(params) Array(params).filter_map do |part| text = part.to_s.sub(/\A:/, "").strip next if text.empty? next if text.match?(/\A#{PING_PREFIX}/i) Normalize.nick(text) end end
Source
# File lib/irc_user_ping.rb, line 123 def record_award_reply!(nick:, args:, received_at:, store: pending_store) result = record_reply!(nick: nick, args: args, received_at: received_at, store: store) return nil unless result&.dig(:award) result end
Source
# File lib/irc_user_ping.rb, line 79 def record_lag_reply!(nick:, args:, received_at:, store: pending_store) entry = store[store_key(nick)] return nil unless entry return nil if entry[:award] record_reply!(nick: nick, args: args, received_at: received_at, store: store) end
Source
# File lib/irc_user_ping.rb, line 87 def record_pong_reply!(params:, received_at:, store: pending_store) token = parse_token(params) key, entry = if token store.find { |_store_key, candidate| candidate[:context] == token && !candidate[:award] } else find_pending_by_pong_nick(params, store: store) end return nil unless entry sent_at = entry[:ping_sent_at] || entry[:sent_at] ms = ((received_at - sent_at) * 1000).round context = entry[:context] nick = entry[:nick] store.delete(key) { ms: ms, context: context, nick: nick } end
Source
# File lib/irc_user_ping.rb, line 62 def record_reply!(nick:, args:, received_at:, store: pending_store) key = store_key(nick) entry = store[key] return nil unless entry token = parse_token(args) return nil unless token return nil if entry[:context] != token sent_at = entry[:ping_sent_at] || entry[:sent_at] ms = ((received_at - sent_at) * 1000).round context = entry[:context] award = entry[:award] store.delete(key) { ms: ms, context: context, nick: entry[:nick], award: award } end
Source
# File lib/irc_user_ping.rb, line 35 def register!(nick:, sent_at:, context:, award: nil, store: pending_store) key = store_key(nick) store[key] = { sent_at: sent_at, context: context, nick: Normalize.nick(nick), award: award } end
Source
# File lib/irc_user_ping.rb, line 49 def remove!(nick:, store: pending_store) take!(nick: nick, store: store) end
Source
# File lib/irc_user_ping.rb, line 15 def reset!(store: {}) @pending = store end
Source
# File lib/irc_user_ping.rb, line 53 def stale_awards(max_age_sec:, now: Process.clock_gettime(Process::CLOCK_MONOTONIC), store: pending_store) store.filter_map do |key, entry| next unless entry[:award] next if (now - entry[:sent_at]) < max_age_sec [key, entry] end end
Source
# File lib/irc_user_ping.rb, line 139 def store_key(nick) Normalize.nick(nick).downcase end
Source
# File lib/irc_user_ping.rb, line 45 def take!(nick:, store: pending_store) store.delete(store_key(nick)) end
Source
# File lib/irc_user_ping.rb, line 27 def user_ping_command(nick:, token:) "PING #{nick} :#{ping_message(token: token)}" end