1 // Copyright (c) 2017 Matthew Brennan Jones <matthew.brennan.jones@gmail.com> 2 // Boost Software License - Version 1.0 3 // Get http://ipinfo.io info with the D programming language 4 // https://github.com/workhorsy/d-ipinfo 5 6 /++ 7 Get http://ipinfo.io with the D programming language. 8 9 Home page: 10 $(LINK https://github.com/workhorsy/d-ipinfo) 11 12 Version: 1.1.0 13 14 License: 15 Boost Software License - Version 1.0 16 17 Examples: 18 ---- 19 import std.stdio : stdout, stderr; 20 import ipinfo : getIpinfo, IpinfoData; 21 22 getIpinfo(delegate(IpinfoData data, Exception err) { 23 if (err) { 24 stderr.writefln("%s", err); 25 } else { 26 stdout.writefln("ip: %s", data.ip); 27 stdout.writefln("latitude: %s", data.latitude); 28 stdout.writefln("longitude: %s", data.longitude); 29 stdout.writefln("org: %s", data.org); 30 stdout.writefln("city: %s", data.city); 31 stdout.writefln("region: %s", data.region); 32 stdout.writefln("country: %s", data.country); 33 stdout.writefln("postal: %s", data.postal); 34 } 35 }); 36 37 /* 38 ip: 203.205.28.14 39 latitude: 37.385999999999996 40 longitude: -122.0838 41 org: AS15169 Google Inc. 42 city: Mountain View 43 region: California 44 country: US 45 postal: 94043 46 */ 47 ---- 48 +/ 49 50 module ipinfo; 51 52 /++ 53 Data gathered in IpinfoData: 54 ---- 55 struct IpinfoData { 56 string ip; 57 string latitude; 58 string longitude; 59 string org; 60 string city; 61 string region; 62 string country; 63 string postal; 64 } 65 ---- 66 +/ 67 68 struct IpinfoData { 69 string ip; 70 string latitude; 71 string longitude; 72 string org; 73 string city; 74 string region; 75 string country; 76 string postal; 77 } 78 79 void delegate(string url, void delegate(int status, string response) cb) httpGet; 80 private void delegate(string url, void delegate(int status, string response) cb) httpGetDefault; 81 82 static this() { 83 httpGetDefault = delegate(string url, void delegate(int status, string response) cb) { 84 import std.net.curl : HTTP, CurlException, get; 85 86 auto http = HTTP(); 87 string content = ""; 88 89 try { 90 content = cast(string) get(url, http); 91 } catch (CurlException ex) { 92 } 93 94 ushort status = http.statusLine().code; 95 cb(status, content); 96 }; 97 98 httpGet = httpGetDefault; 99 } 100 101 /++ 102 Returns the ipinfo info using a callback. 103 104 Params: 105 cb = The callback to fire when the ipinfo has been downloaded. The callback 106 sends the IpinfoData data and an Exception if there was any problem. 107 +/ 108 void getIpinfo(void delegate(IpinfoData data, Exception err) cb) { 109 import std.json : JSONValue, parseJSON; 110 import std..string : chomp, format; 111 import std.array : split; 112 113 IpinfoData data; 114 immutable string URL = "https://ipinfo.io/json"; 115 116 // Get ipinfo for this ip address 117 httpGet(URL, delegate(int status, string response) { 118 if (status != 200) { 119 auto err = new Exception("Request for \"%s\" failed with status code: %s".format(URL, status)); 120 cb(data, err); 121 return; 122 } 123 124 try { 125 JSONValue j = parseJSON(response); 126 127 string[] loc = split(j["loc"].str(), ","); 128 129 data.ip = j["ip"].str(); 130 data.latitude = chomp(loc[0]); 131 data.longitude = chomp(loc[1]); 132 data.org = j["org"].str(); 133 data.city = j["city"].str(); 134 data.region = j["region"].str(); 135 data.country = j["country"].str(); 136 data.postal = j["postal"].str(); 137 } catch (Throwable) { 138 auto err = new Exception("Failed to parse \"%s\" JSON response".format(URL)); 139 cb(data, err); 140 return; 141 } 142 143 cb(data, null); 144 }); 145 }