diff --git a/data-sources/ip2locationio.php b/data-sources/ip2locationio.php new file mode 100644 index 00000000..be0eeacc --- /dev/null +++ b/data-sources/ip2locationio.php @@ -0,0 +1,223 @@ +params = $params; + $this->params['language'] = reset($locales); + if (empty($this->params['language'])) { + $this->params['language'] = 'en'; + } + + $default_options = [ + 'timeout' => 1, + ]; + $this->options = $options + $default_options; + } + + protected function locales($locale, $value) + { + $locales = ['en' => $value]; + if ($locale != 'en') { + $locales[$locale] = $value; + } + + return $locales; + } + + public function city($ip) + { + $data = $this->api_call($ip); + + if (!$data) { + return _geoip_detect2_get_new_empty_record(); + } + + $r = []; + + $r['extra']['original'] = $data; + + if (isset($data['error']['error_message'])) { + throw new \RuntimeException($data['error']['error_message']); + // Example error: + /* @see https://www.ip2location.io/ip2location-documentation + { + "error":{ + "error_code":10000, + "error_message":"Invalid API key or insufficient credit." + } + } + */ + } + + $locale = $this->params['language']; + + if (!empty($data['country_name'])) { + $r['country']['names'] = $this->locales($locale, $data['country_name']); + } + if (!empty($data['country_code'])) { + $r['country']['iso_code'] = strtoupper($data['country_code']); + } + if (!empty($data['region_name'])) { + $r['subdivisions'][0] = [ + 'iso_code' => '', + 'names' => $this->locales($locale, $data['region_name']), + ]; + } + if (!empty($data['city_name'])) { + $r['city']['names'] = $this->locales($locale, $data['city_name']); + } + if (!empty($data['latitude'])) { + $r['location']['latitude'] = $data['latitude']; + } + if (!empty($data['longitude'])) { + $r['location']['longitude'] = $data['longitude']; + } + if (isset($data['asn'])) { + $r['traits']['autonomous_system_number'] = $data['asn']; + } + if (isset($data['as'])) { + $r['traits']['isp'] = $data['as']; + } + if (!empty($data['is_proxy'])) { + $r['traits']['is_anonymous_vpn'] = $data['is_proxy']; + } + + $r['traits']['ip_address'] = $ip; + + $record = new \GeoIp2\Model\City($r, ['en']); + + return $record; + } + + public function country($ip) + { + return $this->city($ip); // too much info shouldn't hurt ... + } + + public function close() + { + } + + private function build_url($ip) + { + $url = 'https://' . self::URL . $ip; + + $params = [ + 'key' => $this->params['key'], + ]; + + return $url . '?' . \http_build_query($params); + } + + private function api_call($ip) + { + try { + // Setting timeout limit to speed up sites + $context = stream_context_create( + [ + 'http' => [ + 'timeout' => $this->options['timeout'], + ], + ] + ); + // Using @file... to supress errors + // Example output: {"country_name":"UNITED STATES","country_code":"US","city":"Aurora, TX","ip":"12.215.42.19"} + + $body = @file_get_contents($this->build_url($ip), false, $context); + $data = json_decode($body, true); + + return $data; + } catch (\Exception $e) { + // If the API isn't available, we have to do this + throw $e; + + return null; + } + } +} + +class Ip2LocationIoSource extends AbstractDataSource +{ + protected $params = []; + + public function __construct() + { + $this->params['key'] = get_option('geoip-detect-ip2locationio_key', ''); + } + + public function getId() + { + return 'ip2locationio'; + } + + public function getLabel() + { + return __('IP2Location.io Geolocation API Service', 'geoip-detect'); + } + + public function getDescriptionHTML() + { + return __('Free 30,000 queries per month. Register API key as IP2Location.io.', 'geoip-detect'); + } + + public function getStatusInformationHTML() + { + $html = ''; + + if (!$this->isWorking()) { + $html .= '