view src/geoip.rs @ 36:0c5f8caf6736

Implement geoip lookups
author Lewin Bormann <lbo@spheniscida.de>
date Sat, 16 Jul 2022 10:45:58 -0700
parents
children fd0237049be0
line wrap: on
line source

use anyhow::{Context, Error};
use log::warn;
use maxminddb::{
    geoip2::{City, Country},
    Reader,
};

use std::collections::BTreeMap;
use std::net::IpAddr;
use std::path::Path;

pub struct GeoIP {
    r: Reader<Vec<u8>>,
}

impl GeoIP {
    pub fn new<P: AsRef<Path>>(path: P) -> Result<GeoIP, Error> {
        Ok(GeoIP {
            r: Reader::open_readfile(path)?,
        })
    }

    pub fn lookup(&self, addr: IpAddr) -> Option<(String, String)> {
        match self.r.lookup::<City>(addr) {
            Ok(c) => Some((
                c.country
                    .map(|c| c.iso_code.unwrap_or(""))
                    .unwrap_or("")
                    .to_string(),
                c.city
                    .map(|c| {
                        c.names
                            .unwrap_or_else(BTreeMap::new)
                            .get("en")
                            .unwrap_or(&"")
                            .to_string()
                    })
                    .unwrap_or(String::new()),
            )),
            Err(e) => {
                warn!("GeoIP lookup failed: {}", e);
                None
            }
        }
    }
}