Updates to GeoIP lookup stuff.

This commit is contained in:
Pachira 2023-01-05 20:03:26 +00:00
parent f168aceb03
commit a311de6acf
5 changed files with 97 additions and 39 deletions

View file

@ -7,7 +7,6 @@ use Index\Data\ConnectionFailedException;
use Index\Data\DbTools;
use Misuzu\Config\CfgType;
use Misuzu\Config\DbConfig;
use Misuzu\Net\GeoIP;
use Misuzu\Net\IPAddress;
use Misuzu\Users\User;
use Misuzu\Users\UserNotFoundException;
@ -139,7 +138,7 @@ if(!is_readable(MSZ_STORAGE) || !is_writable(MSZ_STORAGE)) {
exit;
}
GeoIP::init($cfg->getValue('geoip.database', CfgType::T_STR, '/var/lib/GeoIP/GeoLite2-Country.mmdb'));
IPAddress::init($ctx);
if(!MSZ_DEBUG) {
$twigCacheDirSfx = GitInfo::hash(true);

77
src/GeoIP/GeoIPHelper.php Normal file
View 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;
}
}
}

View file

@ -3,6 +3,7 @@ namespace Misuzu;
use Misuzu\Template;
use Misuzu\Config\IConfig;
use Misuzu\GeoIP\GeoIPHelper;
use Misuzu\SharpChat\SharpChatRoutes;
use Misuzu\Users\Users;
use Misuzu\Twitter\TwitterClient;
@ -20,6 +21,7 @@ class MszContext {
private IConfig $config;
private Users $users;
private HttpFx $router;
private ?GeoIPHelper $geoIP = null;
public function __construct(IDbConnection $dbConn, IConfig $config) {
$this->dbConn = $dbConn;
@ -44,6 +46,12 @@ class MszContext {
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 {
return TwitterClient::create($this->config->scopeTo('twitter'));
}

View file

@ -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);
}
}

View file

@ -1,17 +1,19 @@
<?php
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 {
public static function country(string $address, string $fallback = 'XX'): string {
if(!GeoIP::isAvailable())
return $fallback;
private static MszContext $context;
try {
return GeoIP::resolveCountry($address)->country->isoCode ?? $fallback;
} catch(AddressNotFoundException $e) {
return $fallback;
}
public static function init(MszContext $ctx): void {
self::$context = $ctx;
}
public static function country(string $address, string $fallback = 'XX'): string {
return self::$context->getGeoIP()->getIsoCountryCode($address, $fallback);
}
}