package ru.soune.nocopy.service.geo; import com.maxmind.geoip2.DatabaseReader; import com.maxmind.geoip2.model.CountryResponse; import jakarta.annotation.PostConstruct; import lombok.extern.slf4j.Slf4j; import org.springframework.core.io.ClassPathResource; import org.springframework.stereotype.Service; import java.net.InetAddress; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @Service @Slf4j public class GeoCountryService { private DatabaseReader dbReader; private final Map cache = new ConcurrentHashMap<>(); @PostConstruct public void init() { try { var resource = new ClassPathResource("geo/GeoLite2-Country.mmdb"); this.dbReader = new DatabaseReader.Builder(resource.getInputStream()).build(); log.info("Geo DB loaded"); } catch (Exception e) { log.error("Failed to load Geo DB", e); throw new RuntimeException(e); } } public String getCountry(String url) { if (url == null || url.isBlank()) { return null; } String host = extractHost(url); if (cache.containsKey(host)) { return cache.get(host); } try { InetAddress ip = InetAddress.getByName(host); CountryResponse response = dbReader.country(ip); String country = response.getCountry().getIsoCode(); cache.put(host, country); return country; } catch (Exception e) { log.debug("Cannot determine country for: {}", host); cache.put(host, null); return null; } } private String extractHost(String url) { String cleaned = url.replaceFirst("^https?://", ""); return cleaned.split("[/:]")[0]; } }