Skip to content

Commit

Permalink
feat: Add ipinfo driver
Browse files Browse the repository at this point in the history
  • Loading branch information
pulkitjalan committed Oct 10, 2024
1 parent 095121c commit 3973bf7
Show file tree
Hide file tree
Showing 3 changed files with 179 additions and 0 deletions.
69 changes: 69 additions & 0 deletions src/Drivers/IPInfoDriver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php

namespace PulkitJalan\IPGeolocation\Drivers;

use Illuminate\Support\Arr;
use GuzzleHttp\Client as GuzzleClient;
use PulkitJalan\IPGeolocation\Exceptions\InvalidCredentialsException;

class IPInfoDriver extends AbstractIPGeolocationDriver implements IPGeolocationInterface
{
/**
* @param array $config
* @param GuzzleClient|null $guzzle
* @throws InvalidCredentialsException
*/
public function __construct(array $config, GuzzleClient $guzzle = null)
{
parent::__construct($config, $guzzle);

if (! Arr::get($this->config, 'token')) {
throw new InvalidCredentialsException('The IPInfo access token is required.');
}
}

/**
* Get array of data using IPInfo.
*
* @param string $ip
* @return array
*/
public function get($ip)
{
$data = $this->getRaw($ip);

if (empty($data)) {
return $this->getDefault();
}

return [
'city' => Arr::get($data, 'city'),
'country' => Arr::get($data, 'country'),
'countryCode' => Arr::get($data, 'country'),
'latitude' => (float) explode(',', Arr::get($data, 'loc', '0,0'))[0],
'longitude' => (float) explode(',', Arr::get($data, 'loc', '0,0'))[1],
'region' => Arr::get($data, 'region'),
'regionCode' => Arr::get($data, 'region'),
'timezone' => Arr::get($data, 'timezone'),
'postalCode' => Arr::get($data, 'postal'),
];
}

/**
* Get the raw IPGeolocation info using IPInfo.
*
* @param string $ip
* @return array
*/
public function getRaw($ip)
{
$url = "https://ipinfo.io/{$ip}?token=" . Arr::get($this->config, 'token');

try {
$response = $this->guzzle->get($url);
return json_decode($response->getBody(), true);
} catch (\Exception $e) {
return [];
}
}
}
11 changes: 11 additions & 0 deletions src/IPGeolocationManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Illuminate\Support\Str;
use GuzzleHttp\Client as GuzzleClient;
use PulkitJalan\IPGeolocation\Drivers\IPApiDriver;
use PulkitJalan\IPGeolocation\Drivers\IPInfoDriver;
use PulkitJalan\IPGeolocation\Drivers\IPStackDriver;
use PulkitJalan\IPGeolocation\Drivers\MaxmindApiDriver;
use PulkitJalan\IPGeolocation\Drivers\MaxmindDatabaseDriver;
Expand Down Expand Up @@ -90,4 +91,14 @@ protected function createIpStackDriver(array $data): IPStackDriver
{
return new IPStackDriver($data, $this->guzzle);
}

/**
* Get the IPInfo driver.
*
* @return IPInfoDriver
*/
protected function createIpInfoDriver(array $data): IPInfoDriver
{
return new IPInfoDriver($data, $this->guzzle);
}
}
99 changes: 99 additions & 0 deletions tests/Drivers/IPInfoDriverTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<?php

use GuzzleHttp\Client;
use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Psr7\Response;
use PulkitJalan\IPGeolocation\Drivers\IPInfoDriver;
use PulkitJalan\IPGeolocation\Exceptions\InvalidCredentialsException;

beforeEach(function () {
$this->validConfig = ['token' => 'test_token'];
$this->invalidConfig = [];
});

it('throws exception with invalid config', function () {
expect(fn () => new IPInfoDriver($this->invalidConfig))
->toThrow(InvalidCredentialsException::class);
});

it('returns correct data for valid IP', function () {
$mockResponse = [
'ip' => '8.8.8.8',
'city' => 'Mountain View',
'region' => 'California',
'country' => 'US',
'loc' => '37.4056,-122.0775',
'postal' => '94043',
'timezone' => 'America/Los_Angeles',
];

$mock = new MockHandler([
new Response(200, [], json_encode($mockResponse)),
]);

$handlerStack = HandlerStack::create($mock);
$client = new Client(['handler' => $handlerStack]);

$driver = new IPInfoDriver($this->validConfig, $client);
$result = $driver->get('8.8.8.8');

expect($result)->toMatchArray([
'city' => 'Mountain View',
'country' => 'US',
'countryCode' => 'US',
'latitude' => 37.4056,
'longitude' => -122.0775,
'region' => 'California',
'regionCode' => 'California',
'timezone' => 'America/Los_Angeles',
'postalCode' => '94043',
]);
});

it('returns default data for invalid response', function () {
$mock = new MockHandler([
new Response(400, []),
]);

$handlerStack = HandlerStack::create($mock);
$client = new Client(['handler' => $handlerStack]);

$driver = new IPInfoDriver($this->validConfig, $client);

expect($driver->get('invalid_ip'))->toEqual([
'city' => null,
'country' => null,
'countryCode' => null,
'latitude' => null,
'longitude' => null,
'region' => null,
'regionCode' => null,
'timezone' => null,
'postalCode' => null,
]);
});

it('returns raw data for valid IP', function () {
$mockResponse = [
'ip' => '8.8.8.8',
'city' => 'Mountain View',
'region' => 'California',
'country' => 'US',
'loc' => '37.4056,-122.0775',
'postal' => '94043',
'timezone' => 'America/Los_Angeles',
];

$mock = new MockHandler([
new Response(200, [], json_encode($mockResponse)),
]);

$handlerStack = HandlerStack::create($mock);
$client = new Client(['handler' => $handlerStack]);

$driver = new IPInfoDriver($this->validConfig, $client);
$result = $driver->getRaw('8.8.8.8');

expect($result)->toBe($mockResponse);
});

0 comments on commit 3973bf7

Please sign in to comment.