Updates to GeoIP lookup stuff.
This commit is contained in:
parent
f168aceb03
commit
a311de6acf
5 changed files with 97 additions and 39 deletions
|
@ -7,7 +7,6 @@ use Index\Data\ConnectionFailedException;
|
||||||
use Index\Data\DbTools;
|
use Index\Data\DbTools;
|
||||||
use Misuzu\Config\CfgType;
|
use Misuzu\Config\CfgType;
|
||||||
use Misuzu\Config\DbConfig;
|
use Misuzu\Config\DbConfig;
|
||||||
use Misuzu\Net\GeoIP;
|
|
||||||
use Misuzu\Net\IPAddress;
|
use Misuzu\Net\IPAddress;
|
||||||
use Misuzu\Users\User;
|
use Misuzu\Users\User;
|
||||||
use Misuzu\Users\UserNotFoundException;
|
use Misuzu\Users\UserNotFoundException;
|
||||||
|
@ -139,7 +138,7 @@ if(!is_readable(MSZ_STORAGE) || !is_writable(MSZ_STORAGE)) {
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
GeoIP::init($cfg->getValue('geoip.database', CfgType::T_STR, '/var/lib/GeoIP/GeoLite2-Country.mmdb'));
|
IPAddress::init($ctx);
|
||||||
|
|
||||||
if(!MSZ_DEBUG) {
|
if(!MSZ_DEBUG) {
|
||||||
$twigCacheDirSfx = GitInfo::hash(true);
|
$twigCacheDirSfx = GitInfo::hash(true);
|
||||||
|
|
77
src/GeoIP/GeoIPHelper.php
Normal file
77
src/GeoIP/GeoIPHelper.php
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
<?php
|
||||||
|
namespace Misuzu\GeoIP;
|
||||||
|
|
||||||
|
use InvalidArgumentException;
|
||||||
|
use RuntimeException;
|
||||||
|
use Index\Net\IPAddress;
|
||||||
|
use GeoIp2\Database\Reader;
|
||||||
|
use GeoIp2\Exception\AddressNotFoundException;
|
||||||
|
use GeoIp2\Model\Asn;
|
||||||
|
use GeoIp2\Model\City;
|
||||||
|
use GeoIp2\Model\Country;
|
||||||
|
use Misuzu\Config\IConfig;
|
||||||
|
use Misuzu\Config\CfgType;
|
||||||
|
|
||||||
|
class GeoIPHelper {
|
||||||
|
public const ASN = 'asn';
|
||||||
|
public const CITY = 'city';
|
||||||
|
public const COUNTRY = 'country';
|
||||||
|
|
||||||
|
private IConfig $config;
|
||||||
|
|
||||||
|
private array $readers = [];
|
||||||
|
|
||||||
|
public function __construct(IConfig $config) {
|
||||||
|
$this->config = $config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hasDbPath(string $type): bool {
|
||||||
|
return array_key_exists($type, $this->readers)
|
||||||
|
|| $this->config->hasValue('db.' . $type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDbPath(string $type): string {
|
||||||
|
$type = 'db.' . $type;
|
||||||
|
if(!$this->config->hasValue($type))
|
||||||
|
throw new RuntimeException('Not database path has been configured for $type.');
|
||||||
|
return $this->config->getValue($type, CfgType::T_STR);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getReader(string $type): Reader {
|
||||||
|
if(!array_key_exists($type, $this->readers))
|
||||||
|
return $this->readers[$type] = new Reader($this->getDbPath($type));
|
||||||
|
return $this->readers[$type];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getASN(IPAddress|string $ipAddress): Asn {
|
||||||
|
if($ipAddress instanceof IPAddress)
|
||||||
|
$ipAddress = $ipAddress->getCleanAddress();
|
||||||
|
|
||||||
|
if($this->hasDbPath(self::ASN))
|
||||||
|
return $this->getReader(self::ASN)->asn($ipAddress);
|
||||||
|
|
||||||
|
throw new RuntimeException('There was no database available that could satisfy this request.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCityOrCountry(IPAddress|string $ipAddress): City|Country {
|
||||||
|
if($ipAddress instanceof IPAddress)
|
||||||
|
$ipAddress = $ipAddress->getCleanAddress();
|
||||||
|
|
||||||
|
if($this->hasDbPath(self::CITY))
|
||||||
|
return $this->getReader(self::CITY)->city($ipAddress);
|
||||||
|
if($this->hasDbPath(self::COUNTRY))
|
||||||
|
return $this->getReader(self::COUNTRY)->country($ipAddress);
|
||||||
|
|
||||||
|
throw new RuntimeException('There was no database available that could satisfy this request.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getIsoCountryCode(IPAddress|string $ipAddress, string $fallback = 'XX'): string {
|
||||||
|
try {
|
||||||
|
return $this->getCityOrCountry($ipAddress)->country->isoCode ?? $fallback;
|
||||||
|
} catch(AddressNotFoundException $ex) {
|
||||||
|
return $fallback;
|
||||||
|
} catch(RuntimeException $ex) {
|
||||||
|
return $fallback;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ namespace Misuzu;
|
||||||
|
|
||||||
use Misuzu\Template;
|
use Misuzu\Template;
|
||||||
use Misuzu\Config\IConfig;
|
use Misuzu\Config\IConfig;
|
||||||
|
use Misuzu\GeoIP\GeoIPHelper;
|
||||||
use Misuzu\SharpChat\SharpChatRoutes;
|
use Misuzu\SharpChat\SharpChatRoutes;
|
||||||
use Misuzu\Users\Users;
|
use Misuzu\Users\Users;
|
||||||
use Misuzu\Twitter\TwitterClient;
|
use Misuzu\Twitter\TwitterClient;
|
||||||
|
@ -20,6 +21,7 @@ class MszContext {
|
||||||
private IConfig $config;
|
private IConfig $config;
|
||||||
private Users $users;
|
private Users $users;
|
||||||
private HttpFx $router;
|
private HttpFx $router;
|
||||||
|
private ?GeoIPHelper $geoIP = null;
|
||||||
|
|
||||||
public function __construct(IDbConnection $dbConn, IConfig $config) {
|
public function __construct(IDbConnection $dbConn, IConfig $config) {
|
||||||
$this->dbConn = $dbConn;
|
$this->dbConn = $dbConn;
|
||||||
|
@ -44,6 +46,12 @@ class MszContext {
|
||||||
return $this->users;
|
return $this->users;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
public function getGeoIP(): GeoIPHelper {
|
||||||
|
if($this->geoIP === null)
|
||||||
|
return $this->geoIP = new GeoIPHelper($this->config->scopeTo('geoip'));
|
||||||
|
return $this->geoIP;
|
||||||
|
}
|
||||||
|
|
||||||
public function createTwitterClient(): TwitterClient {
|
public function createTwitterClient(): TwitterClient {
|
||||||
return TwitterClient::create($this->config->scopeTo('twitter'));
|
return TwitterClient::create($this->config->scopeTo('twitter'));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
<?php
|
|
||||||
namespace Misuzu\Net;
|
|
||||||
|
|
||||||
use GeoIp2\Database\Reader as GeoIPDBReader;
|
|
||||||
|
|
||||||
final class GeoIP {
|
|
||||||
private static $geoip = null;
|
|
||||||
private static $geoipDbPath = null;
|
|
||||||
|
|
||||||
public static function init(string $dbPath): void {
|
|
||||||
self::$geoipDbPath = $dbPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getReader(): GeoIPDBReader {
|
|
||||||
if(self::$geoip === null)
|
|
||||||
self::$geoip = new GeoIPDBReader(self::$geoipDbPath);
|
|
||||||
return self::$geoip;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function isAvailable(): bool {
|
|
||||||
return !empty(self::$geoipDbPath)
|
|
||||||
&& is_file(self::$geoipDbPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function resolveCountry(string $ipAddress) {
|
|
||||||
return self::getReader()->country($ipAddress);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,17 +1,19 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Misuzu\Net;
|
namespace Misuzu\Net;
|
||||||
|
|
||||||
use GeoIp2\Exception\AddressNotFoundException;
|
use Misuzu\MszContext;
|
||||||
|
|
||||||
|
// remains for now for backwards compatibility with existing ::create methods
|
||||||
|
// plan is for those ::create methods to Fucking Die so that's fine for now
|
||||||
|
|
||||||
final class IPAddress {
|
final class IPAddress {
|
||||||
public static function country(string $address, string $fallback = 'XX'): string {
|
private static MszContext $context;
|
||||||
if(!GeoIP::isAvailable())
|
|
||||||
return $fallback;
|
|
||||||
|
|
||||||
try {
|
public static function init(MszContext $ctx): void {
|
||||||
return GeoIP::resolveCountry($address)->country->isoCode ?? $fallback;
|
self::$context = $ctx;
|
||||||
} catch(AddressNotFoundException $e) {
|
}
|
||||||
return $fallback;
|
|
||||||
}
|
public static function country(string $address, string $fallback = 'XX'): string {
|
||||||
|
return self::$context->getGeoIP()->getIsoCountryCode($address, $fallback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue