Skip to content

Commit c771a92

Browse files
committed
Change myip CLI interface, will fetch ip info only from one site once.
1 parent 62efe88 commit c771a92

File tree

2 files changed

+55
-51
lines changed

2 files changed

+55
-51
lines changed

src/cli.cr

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,19 @@
11
require "option_parser"
22
require "./myip"
33

4+
ARGV << "--help" if ARGV.empty?
5+
6+
ip111 = false
7+
ip138 = false
8+
ipsb = false
9+
410
OptionParser.parse do |parser|
511
parser.banner = <<-USAGE
6-
Usage: myip <option>
12+
Usage:
13+
myip ip111 => get ip from http://www.ip111.cn
14+
myip ip138 => get ip info from https://www.ip138.com
15+
myip ipsb => get ip info from https://api.ip.sb/geoip
16+
717
USAGE
818

919
parser.on("-h", "--help", "Show this help message and exit") do
@@ -27,12 +37,22 @@ USAGE
2737
STDERR.puts parser
2838
exit 1
2939
end
40+
41+
parser.unknown_args do |args|
42+
if args.includes? "ip111"
43+
ip111 = true
44+
elsif args.includes? "ip138"
45+
ip138 = true
46+
elsif args.includes? "ipsb"
47+
ipsb = true
48+
end
49+
end
3050
end
3151

3252
myip = Myip.new
33-
# myip.ip_from_ip138
34-
myip.ip_from_ib_sb
35-
myip.ip_from_ip111
53+
myip.ip_from_ip138 if ip138
54+
myip.ip_from_ip_sb if ipsb
55+
myip.ip_from_ip111 if ip111
3656
myip.process
3757

3858
at_exit do

src/myip.cr

Lines changed: 31 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -6,30 +6,23 @@ require "http/headers"
66
require "colorize"
77
require "term-spinner"
88

9-
alias IPInfo = String
10-
alias IP = String
11-
129
class String
1310
def as_title
1411
self.colorize(:yellow).on_blue.bold
1512
end
1613
end
1714

1815
class Myip
19-
def new_spinner(msg : String, interval = 0.5.seconds)
20-
Term::Spinner.new(":spinner " + msg, format: :dots, interval: interval)
21-
end
22-
23-
getter chan = Channel(Tuple(IPInfo, IP?)).new
16+
getter chan = Channel(Tuple(String, String?)).new
2417
property chan_send_count : Int32 = 0
2518
property detail_chan_send_count : Int32 = 0
2619

27-
def ip_from_ib_sb
20+
def ip_from_ip_sb
2821
self.chan_send_count = chan_send_count() + 1
2922

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

3427
spinner.run do
3528
response = HTTP::Client.get(url)
@@ -50,50 +43,45 @@ class Myip
5043
end
5144

5245
def ip_from_ip111
46+
spinner = Term::Spinner::Multi.new(":spinner", format: :dots, interval: 0.2.seconds)
47+
5348
# 注意: ip111.cn 仅支持 http, 不支持 https:
5449
ip111_url = "http://www.ip111.cn"
55-
spinner = new_spinner("Connecting to #{ip111_url.as_title}")
50+
sp1 = spinner.register ":spinner Connecting to #{ip111_url.as_title} ..."
5651

5752
doc = uninitialized Lexbor::Parser
5853

59-
spinner.run do
54+
sp1.run do
6055
doc, _code = from_url(ip111_url)
6156

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

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

67-
spinner.success
62+
sp1.success
6863
end
6964

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

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

77-
urls << [url, title]
78-
end
79-
80-
spinner = new_spinner("Connecting to #{ip111_url.as_title}#{urls.map(&.[0]).join(" ").as_title} ...")
81-
82-
# 这里只能用 each, 没有 map, 因为 doc.nodes("iframe") 是一个 Iterator::SelectIterator 对象
83-
urls.each do |(url, title)|
84-
self.chan_send_count = chan_send_count() + 1
73+
sp = spinner.register("Connecting to #{url.as_title} ...")
8574

8675
spawn do
87-
spinner.run do
76+
sp.run do
8877
doc, _code = from_url(url, headers: headers)
89-
title =
90-
ipinfo = doc.body!.tag_text.strip
78+
ipinfo = doc.body!.tag_text.strip
9179

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

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

96-
spinner.success
84+
sp.success
9785
rescue ex : ArgumentError | Socket::Error
9886
chan.send({ex.message.not_nil!, nil})
9987
end
@@ -102,42 +90,42 @@ class Myip
10290
end
10391

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

10796
spawn do
10897
url = "https://www.ip138.com"
109-
spinner = new_spinner("Connecting to :status ...")
98+
sp = spinner.register("Connecting to #{url.as_title} ...")
11099

111-
spinner.update(status: url.as_title.to_s)
112100
ip138_url = ""
113101

114-
spinner.run do
102+
sp.run do
115103
doc, _code = from_url(url, follow: true)
116-
ip138_url = doc.css("iframe").first.attribute_by("src")
104+
ip138_url = doc.css("iframe").first.attribute_by("src").not_nil!
117105

118-
spinner.success
106+
sp.success
119107
end
120108

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

123-
spinner.update(status: ip138_url.as_title.to_s)
111+
sp1 = spinner.register("Connecting to #{ip138_url.as_title} ...")
124112

125113
code = 0
126114
doc = uninitialized Lexbor::Parser
127115

128-
spinner.run do
116+
sp1.run do
129117
doc, code = from_url("https:#{ip138_url}", headers: headers)
130118

131-
spinner.success
119+
sp1.success
132120
end
133121

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

138-
spinner.update(status: url.as_title.to_s)
126+
sp2 = spinner.register("Connecting to #{url.as_title} ...")
139127

140-
spinner.run do
128+
sp2.run do
141129
doc, _code = from_url(url, headers: headers)
142130

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

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

149-
spinner.success
137+
sp2.success
150138
end
151139
else
152140
chan.send({doc.css("body p").first.tag_text.strip, nil})
@@ -157,27 +145,23 @@ class Myip
157145
end
158146

159147
def process
148+
spinner = Term::Spinner::Multi.new(":spinner", format: :dots, interval: 0.2.seconds)
160149
detail_chan = Channel(String).new
161-
details_ip_urls = [] of String
162-
spinner = new_spinner("Connecting to :status: ...")
163150

164151
chan_send_count.times do
165152
select
166153
when value = chan.receive
167154
ipinfo, ip = value
168155

169-
STDERR.puts ipinfo
156+
STDERR.puts "\n#{ipinfo}"
170157

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

174163
spawn do
175-
details_ip_url = "https://www.ipshudi.com/#{ip}.htm"
176-
details_ip_urls << details_ip_url.as_title.to_s
177-
178-
spinner.update(status: "#{details_ip_urls.join(" ")}")
179-
180-
spinner.run do
164+
sp.run do
181165
doc, _code = from_url(details_ip_url)
182166

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

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

191-
spinner.success
175+
sp.success
192176
end
193177
end
194178
end

0 commit comments

Comments
 (0)