package ru.soune.nocopy.service.geo; import com.maxmind.geoip2.DatabaseReader; import com.maxmind.geoip2.exception.GeoIp2Exception; import com.maxmind.geoip2.model.CityResponse; import com.maxmind.geoip2.model.CountryResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.stereotype.Service; import java.io.IOException; import java.net.InetAddress; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @Service @Slf4j public class GeoCountryService { private final DatabaseReader countryDbReader; private final DatabaseReader cityDbReader; public GeoCountryService() throws IOException { Resource resource = new ClassPathResource("geo/GeoLite2-Country.mmdb"); this.countryDbReader = new DatabaseReader.Builder(resource.getInputStream()).build(); Resource cityResource = new ClassPathResource("geo/GeoLite2-City.mmdb"); this.cityDbReader = new DatabaseReader.Builder(cityResource.getInputStream()).build(); } public String getCountryName(String input) { try { CountryResponse response = extractCountry(input); return response.getCountry().getName(); } catch (Exception e) { log.error("Failed for input: {}", input, e); return "UNKNOWN"; } } public Map getUniqueGeoCount(List ipList) { Set uniqueCountries = new HashSet<>(); Set uniqueCountryCodes = new HashSet<>(); Set uniqueCities = new HashSet<>(); if (ipList != null) { for (String ip : ipList) { try { String country = getCountryByIp(ip); if (!"UNKNOWN".equals(country)) { uniqueCountries.add(country); } String countryCode = getCountryCodeByIp(ip); if (!"UNKNOWN".equals(countryCode)) { uniqueCountryCodes.add(countryCode); } String city = getCityByIp(ip); if (!"UNKNOWN".equals(city)) { uniqueCities.add(city); } } catch (Exception e) { log.error("Error processing IP: {}", ip, e); } } } return Map.of( "uniqueCountries", uniqueCountries.size(), "uniqueCountryCodes", uniqueCountryCodes.size(), "uniqueCities", uniqueCities.size() ); } public String getCountryCode(String input) { try { CountryResponse response = extractCountry(input); return response.getCountry().getIsoCode(); } catch (Exception e) { log.error("Failed for input: {}", input, e); return "UNKNOWN"; } } public String getCityByIp(String ip) { try { InetAddress ipAddress = InetAddress.getByName(ip); CityResponse response = cityDbReader.city(ipAddress); return response.getCity().getName(); } catch (Exception e) { log.error("Failed to get city for IP: {}", ip, e); return "UNKNOWN"; } } public String getCountryByIp(String ip) { try { InetAddress ipAddress = InetAddress.getByName(ip); CountryResponse response = countryDbReader.country(ipAddress); return response.getCountry().getName(); } catch (Exception e) { log.error("Failed to get country for IP: {}", ip, e); return "UNKNOWN"; } } public String getCountryCodeByIp(String ip) { try { InetAddress ipAddress = InetAddress.getByName(ip); CountryResponse response = countryDbReader.country(ipAddress); return response.getCountry().getIsoCode(); } catch (Exception e) { log.error("Failed to get country code for IP: {}", ip, e); return "UNKNOWN"; } } private CountryResponse extractCountry(String input) throws IOException, GeoIp2Exception { String domain = extractDomain(input); InetAddress ip = InetAddress.getByName(domain); return countryDbReader.country(ip); } private String extractDomain(String input) { if (input == null || input.isEmpty()) { throw new IllegalArgumentException("Input is empty"); } String cleaned = input.replaceAll("^https?://", ""); cleaned = cleaned.split("/")[0]; cleaned = cleaned.split(":")[0]; return cleaned; } }