require "nokogiri" require "json" require "date" require "socket" config = { "sam.address" => "127.0.0.1", "sam.port" => 7656, "identiguy" => "identiguy.i2p" } def samcmd fircmd, seccmd, args = {} cmd = "#{fircmd} #{seccmd}" args.each_pair { |arg, value| cmd << " #{arg}=\"#{value.to_s}\"" } return cmd end def parsesamcmd ans ans.chomp! ans += " " f = ans.index " " s = ans.index " ", f + 1 w = ans[f+1...s] args = Hash.new loop do g1 = ans.index "=", s+1 break if g1 == nil g2 = ans.index " ", g1+1 args[ans[s+1..g1-1]] = ans[g1+1..g2-1] s = g2 end return [ans[0...f], w, args] end begin csock = TCPSocket.new config["sam.address"], config["sam.port"] ssock = TCPSocket.new config["sam.address"], config["sam.port"] rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH $stderr.puts "Error cann't open a connection to port #{config["sam.port"]}" end puts "Connect to SAM..." csock.puts samcmd "HELLO", "VERSION" res = parsesamcmd csock.gets if res[2]["RESULT"] != "OK" $stderr.puts "Error [4] #{res.inspect}" exit elsif res[2]["VERSION"].to_f < 3.3 $stderr.puts "Error [5] #{res.inspect} - SAM version must be 3.3 or higher" exit end ssock.puts samcmd "HELLO", "VERSION" ssock.gets puts "Create session..." csock.puts samcmd "SESSION", "CREATE", { "STYLE" => "STREAM", "ID" => "identiguy-client", "DESTINATION" => "TRANSIENT", "SIGNATURE_TYPE" => "ECDSA_SHA512_P521", "i2cp.leaseSetEncType" => "4,0", "i2cp.destination.sigType" => "EdDSA_SHA512_Ed25519", "inbound.length" => "0", "outbound.length" => "0", "inbound.nickname" => "identiguy-client" } res = parsesamcmd csock.gets if res[2]["RESULT"] != "OK" $stderr.puts "Error [1] #{res.inspect}" exit end puts "Naming lookup..." csock.puts samcmd "NAMING", "LOOKUP", { "NAME" => config["identiguy"] } res = parsesamcmd csock.gets if res[2]["RESULT"] != "OK" $stderr.puts "Error [2] #{res.inspect}" exit end dest = res[2]["VALUE"] puts "Connect to #{config["identiguy"]}..." ssock.puts samcmd "STREAM", "CONNECT", { "ID" => "identiguy-client", "DESTINATION" => dest } res = parsesamcmd(ssock.gets) if res[2]["RESULT"] != "OK" $stderr.puts "Error [3] #{res.inspect}" exit end http_request = <<~ENDOFREQUEST GET / HTTP/1.1 Host: #{config["identiguy"]} User-Agent: Ruby Script Accept: text/html Connection: close ENDOFREQUEST puts "Send request" ssock.puts http_request puts "Receive response..." resp = ssock.read ssock.close # evaling resp doc = Nokogiri::HTML resp puts "Parse response..." eepsites = Array.new tables = doc.xpath("//table//tr//td") full = tables.length / 3 i = 0 while i < tables.length name = tables[i].content if name.include? ".b32.i2p" i += 2 next end eepsites << name i += 3 end eepsites.uniq! puts "Write into file..." File.write "dat_#{DateTime.now.strftime("%Y-%m-%d_%H-%M-%S")}.json", JSON.dump([eepsites.length, eepsites]) csock.puts "QUIT" csock.close