diff --git a/src/myip.cr b/src/myip.cr index decc78d..d60110f 100644 --- a/src/myip.cr +++ b/src/myip.cr @@ -2,6 +2,7 @@ require "lexbor" require "./myip/*" require "http/client" require "json" +require "http/headers" class Myip getter chan = Channel(Tuple(String, String)).new @@ -12,25 +13,38 @@ class Myip response = HTTP::Client.get(url) result = JSON.parse(response.body) io = IO::Memory.new - PrettyPrint.format(result, io, 79) + PrettyPrint.format(result, io, width: 79) io.rewind - chan.send({"ip.sb/geoip:您访问外网地址信息:\n", io.gets_to_end}) + chan.send({"----- Result from: #{url}:您访问外网地址信息:-----\n", io.gets_to_end}) rescue ex : ArgumentError | Socket::Error - chan.send({"ip.sb/geoip:", ex.message.not_nil!}) + chan.send({"----- Error from: #{url}:-----\n", ex.message.not_nil!}) end end def get_ip_from_ip138 spawn do - url = "http://www.ip138.com" - doc = from_url(url, follow: true) + url = "https://www.ip138.com" + doc, code = from_url(url, follow: true) ip138_url = doc.css("iframe").first.attribute_by("src") - url = "http:#{ip138_url}" - doc = from_url(url) + headers = HTTP::Headers{"Origin" => "https://ip.skk.moe"} - chan.send({"ip138.com:", doc.css("body p").first.tag_text.strip}) + doc, code = from_url("https:#{ip138_url}", headers: headers) + + 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}" + doc, code = from_url(url, headers: headers) + + output = String.build do |io| + doc.css("div.table-box>table>tbody tr").each { |x| io << x.tag_text } + end + + chan.send({"----- Result from: #{url}:-----\n", output.squeeze('\n')}) + else + chan.send({"----- Result from: #{url}:-----\n", doc.css("body p").first.tag_text.strip}) + end rescue ex : ArgumentError | Socket::Error - chan.send({"ip138.com:", ex.message.not_nil!}) + chan.send({"----- Error from: #{url}:-----\n", ex.message.not_nil!}) end end @@ -38,8 +52,8 @@ class Myip 2.times do select when value = chan.receive - title, ip = value - STDERR.puts "#{title}#{ip}" + title, ipinfo = value + STDERR.puts "#{title}#{ipinfo}" when timeout 5.seconds STDERR.puts "Timeout, check your network connection!" exit @@ -47,16 +61,19 @@ class Myip end end - private def from_url(url : String, follow : Bool = false) : Lexbor::Parser - response = HTTP::Client.get url + private def from_url(url : String, *, follow : Bool = false, headers = HTTP::Headers.new) : Tuple(Lexbor::Parser, Int32) + response = HTTP::Client.get url, headers: headers if response.status_code == 200 - Lexbor::Parser.new(response.body) + {Lexbor::Parser.new(response.body), 200} elsif follow && response.status_code == 301 - from_url response.headers["Location"], follow: true + from_url response.headers["Location"], follow: true, headers: headers + elsif response.status_code == 502 + {Lexbor::Parser.new(response.body), 502} else raise ArgumentError.new "Host #{url} returned #{response.status_code}" end - rescue Socket::Error + rescue e : Socket::Error + e.inspect_with_backtrace(STDERR) raise Socket::Error.new "Visit #{url} failed, please check your internet connection." end end