Skip to content

Instantly share code, notes, and snippets.

@railscard
Created January 14, 2021 19:37
Show Gist options
  • Save railscard/02ff4dee700f5dc182f2a789a4aa8315 to your computer and use it in GitHub Desktop.
Save railscard/02ff4dee700f5dc182f2a789a4aa8315 to your computer and use it in GitHub Desktop.
require 'open3'
require 'net/http'
require 'json'
class String
def green; "\e[32m#{self}\e[0m" end
def brown; "\e[33m#{self}\e[0m" end
def blue; "\e[34m#{self}\e[0m" end
def gray; "\e[37m#{self}\e[0m" end
def magenta; "\e[35m#{self}\e[0m" end
def cyan; "\e[36m#{self}\e[0m" end
end
MATCH_EXPRESSION = /(\d+)\s([\*\s]+\*?)?\s?([^\s]+)\s\(([^\s]+)\)\s+(\d+\.\d+)\sms\s+(\d+\.\d+)\sms/
class IPStackClient
QUERY_URL = "http://api.ipstack.com/%{ip}?access_key=#{ENV['IPSTACK_ACCESS_KEY']}"
def self.query(ip)
uri = URI(QUERY_URL % {ip: ip})
response = Net::HTTP.get(uri)
JSON.parse(response)
end
end
module Traceroute
Hop = Struct.new(:number, :drops, :address, :host, :ttl, :rtt) do
def drops_count
drops.to_s.count('*')
end
def location
IPStackClient.query(host).slice("city", "country_name").values.reject { |v| v == "" || v.nil? }.join(", ")
rescue StandardError
"N/A"
end
def to_a
[number, drops, address, host, ttl, rtt]
end
def to_s
[
number.ljust(10),
address.blue.ljust(70),
host.ljust(16),
('%.3f' % ttl.to_f).magenta.ljust(20),
('%.2f' % rtt.to_f).cyan.ljust(20),
"@ #{location.green}"
].join(" ")
end
end
class Command
attr_reader :hops
def initialize(destination)
@destination = destination
@hops = []
end
def run
cmd = "traceroute -I #{@destination}"
Open3.popen2e(cmd) do |stdin, stdout_stderr, wait_thr|
stdout_stderr.each do |l|
match = l.match(MATCH_EXPRESSION)
puts match.nil? ? l.strip : Hop.new(*match.captures).to_s
end
stdin.close
end
end
end
end
raise ArgumentError.new("Please provide host as a first argument.") unless ARGV[0]
command = Traceroute::Command.new(ARGV[0])
command.run
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment