Skip to content

Commit

Permalink
Change myip CLI interface, will fetch ip info only from one site once.
Browse files Browse the repository at this point in the history
  • Loading branch information
zw963 committed Aug 24, 2024
1 parent 62efe88 commit c771a92
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 51 deletions.
28 changes: 24 additions & 4 deletions src/cli.cr
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
require "option_parser"
require "./myip"

ARGV << "--help" if ARGV.empty?

ip111 = false
ip138 = false
ipsb = false

OptionParser.parse do |parser|
parser.banner = <<-USAGE
Usage: myip <option>
Usage:
myip ip111 => get ip from http://www.ip111.cn
myip ip138 => get ip info from https://www.ip138.com
myip ipsb => get ip info from https://api.ip.sb/geoip
USAGE

parser.on("-h", "--help", "Show this help message and exit") do
Expand All @@ -27,12 +37,22 @@ USAGE
STDERR.puts parser
exit 1
end

parser.unknown_args do |args|
if args.includes? "ip111"
ip111 = true
elsif args.includes? "ip138"
ip138 = true
elsif args.includes? "ipsb"
ipsb = true
end
end
end

myip = Myip.new
# myip.ip_from_ip138
myip.ip_from_ib_sb
myip.ip_from_ip111
myip.ip_from_ip138 if ip138
myip.ip_from_ip_sb if ipsb
myip.ip_from_ip111 if ip111
myip.process

at_exit do
Expand Down
78 changes: 31 additions & 47 deletions src/myip.cr
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,23 @@ require "http/headers"
require "colorize"
require "term-spinner"

alias IPInfo = String
alias IP = String

class String
def as_title
self.colorize(:yellow).on_blue.bold
end
end

class Myip
def new_spinner(msg : String, interval = 0.5.seconds)
Term::Spinner.new(":spinner " + msg, format: :dots, interval: interval)
end

getter chan = Channel(Tuple(IPInfo, IP?)).new
getter chan = Channel(Tuple(String, String?)).new
property chan_send_count : Int32 = 0
property detail_chan_send_count : Int32 = 0

def ip_from_ib_sb
def ip_from_ip_sb
self.chan_send_count = chan_send_count() + 1

spawn do
url = "https://api.ip.sb/geoip"
spinner = new_spinner("Connecting to #{url.as_title} ...")
spinner = Term::Spinner.new(":spinner Connecting to #{url.as_title} ...", format: :dots, interval: 0.2.seconds)

spinner.run do
response = HTTP::Client.get(url)
Expand All @@ -50,50 +43,45 @@ class Myip
end

def ip_from_ip111
spinner = Term::Spinner::Multi.new(":spinner", format: :dots, interval: 0.2.seconds)

# 注意: ip111.cn 仅支持 http, 不支持 https:
ip111_url = "http://www.ip111.cn"
spinner = new_spinner("Connecting to #{ip111_url.as_title}")
sp1 = spinner.register ":spinner Connecting to #{ip111_url.as_title} ..."

doc = uninitialized Lexbor::Parser

spinner.run do
sp1.run do
doc, _code = from_url(ip111_url)

title = doc.css(".card-header").first.tag_text.strip
ipinfo = doc.css(".card-body p").first.tag_text.strip

STDERR.puts "#{title}#{ipinfo}"

spinner.success
sp1.success
end

headers = HTTP::Headers{"Referer" => "http://www.ip111.cn/"}

urls = [] of Array(String)
# 这里只能用 each, 没有 map, 因为 doc.nodes("iframe") 是一个 Iterator::SelectIterator 对象
doc.nodes("iframe").each do |node|
self.chan_send_count = chan_send_count() + 1
url = node.attribute_by("src").not_nil!
title = node.parent!.parent!.parent!.css(".card-header").first.tag_text.strip

urls << [url, title]
end

spinner = new_spinner("Connecting to #{ip111_url.as_title}#{urls.map(&.[0]).join(" ").as_title} ...")

# 这里只能用 each, 没有 map, 因为 doc.nodes("iframe") 是一个 Iterator::SelectIterator 对象
urls.each do |(url, title)|
self.chan_send_count = chan_send_count() + 1
sp = spinner.register("Connecting to #{url.as_title} ...")

spawn do
spinner.run do
sp.run do
doc, _code = from_url(url, headers: headers)
title =
ipinfo = doc.body!.tag_text.strip
ipinfo = doc.body!.tag_text.strip

ip = ipinfo[/[a-z0-9:.]+/]

chan.send({"#{title}#{ipinfo}", ip})

spinner.success
sp.success
rescue ex : ArgumentError | Socket::Error
chan.send({ex.message.not_nil!, nil})
end
Expand All @@ -102,42 +90,42 @@ class Myip
end

def ip_from_ip138
spinner = Term::Spinner::Multi.new(":spinner", format: :dots, interval: 0.2.seconds)
self.chan_send_count = chan_send_count + 1

spawn do
url = "https://www.ip138.com"
spinner = new_spinner("Connecting to :status ...")
sp = spinner.register("Connecting to #{url.as_title} ...")

spinner.update(status: url.as_title.to_s)
ip138_url = ""

spinner.run do
sp.run do
doc, _code = from_url(url, follow: true)
ip138_url = doc.css("iframe").first.attribute_by("src")
ip138_url = doc.css("iframe").first.attribute_by("src").not_nil!

spinner.success
sp.success
end

headers = HTTP::Headers{"Origin" => "https://ip.skk.moe"}

spinner.update(status: ip138_url.as_title.to_s)
sp1 = spinner.register("Connecting to #{ip138_url.as_title} ...")

code = 0
doc = uninitialized Lexbor::Parser

spinner.run do
sp1.run do
doc, code = from_url("https:#{ip138_url}", headers: headers)

spinner.success
sp1.success
end

if code == 502
myip = doc.css("body p span.F").first.tag_text[/IP:\s*([0-9.]+)/, 1]
url = "https://www.ip138.com/iplookup.php?ip=#{myip}"

spinner.update(status: url.as_title.to_s)
sp2 = spinner.register("Connecting to #{url.as_title} ...")

spinner.run do
sp2.run do
doc, _code = from_url(url, headers: headers)

output = String.build do |io|
Expand All @@ -146,7 +134,7 @@ class Myip

chan.send({output.squeeze('\n'), nil})

spinner.success
sp2.success
end
else
chan.send({doc.css("body p").first.tag_text.strip, nil})
Expand All @@ -157,27 +145,23 @@ class Myip
end

def process
spinner = Term::Spinner::Multi.new(":spinner", format: :dots, interval: 0.2.seconds)
detail_chan = Channel(String).new
details_ip_urls = [] of String
spinner = new_spinner("Connecting to :status: ...")

chan_send_count.times do
select
when value = chan.receive
ipinfo, ip = value

STDERR.puts ipinfo
STDERR.puts "\n#{ipinfo}"

if !ip.nil?
self.detail_chan_send_count = detail_chan_send_count() + 1
details_ip_url = "https://www.ipshudi.com/#{ip}.htm"
sp = spinner.register("Connecting to #{details_ip_url.as_title} ...")

spawn do
details_ip_url = "https://www.ipshudi.com/#{ip}.htm"
details_ip_urls << details_ip_url.as_title.to_s

spinner.update(status: "#{details_ip_urls.join(" ")}")

spinner.run do
sp.run do
doc, _code = from_url(details_ip_url)

output = String.build do |io|
Expand All @@ -188,7 +172,7 @@ class Myip

detail_chan.send(output.squeeze('\n'))

spinner.success
sp.success
end
end
end
Expand Down

0 comments on commit c771a92

Please sign in to comment.