// Copyright 2026 Arctel.net // SPDX-License-Identifier: Apache-2.0 package geoip import "strings" type countryCentroid struct { lat float64 lon float64 } var countryCentroidsByName = map[string]countryCentroid{ "Afghanistan": {lat: 33.833494, lon: 65.992544}, "Albania": {lat: 41.179283, lon: 20.035804}, "Algeria": {lat: 28.158203, lon: 2.617517}, "Angola": {lat: -12.334558, lon: 17.563198}, "Argentina": {lat: -35.178772, lon: -65.156706}, "Armenia": {lat: 40.298846, lon: 44.929380}, "Australia": {lat: -25.574956, lon: 134.361181}, "Austria": {lat: 47.570428, lon: 14.101658}, "Azerbaijan": {lat: 40.331151, lon: 47.636778}, "Bangladesh": {lat: 23.887936, lon: 90.210098}, "Belarus": {lat: 53.534329, lon: 28.048953}, "Belgium": {lat: 50.646495, lon: 4.628130}, "Belize": {lat: 17.170731, lon: -88.720961}, "Benin": {lat: 9.630483, lon: 2.323508}, "Bhutan": {lat: 27.401336, lon: 90.405624}, "Bolivia": {lat: -16.701415, lon: -64.691050}, "Bosnia and Herzegovina": {lat: 44.163989, lon: 17.762462}, "Botswana": {lat: -22.185334, lon: 23.791789}, "Brazil": {lat: -10.827996, lon: -53.113858}, "Brunei": {lat: 4.451218, lon: 114.542293}, "Bulgaria": {lat: 42.777857, lon: 25.225364}, "Burkina Faso": {lat: 12.260370, lon: -1.775743}, "Burundi": {lat: -3.380283, lon: 29.873066}, "Cambodia": {lat: 12.717933, lon: 104.907023}, "Cameroon": {lat: 5.692692, lon: 12.739868}, "Canada": {lat: 57.944575, lon: -102.317776}, "Central African Republic": {lat: 6.563625, lon: 20.490782}, "Chad": {lat: 15.327299, lon: 18.645816}, "Chile": {lat: -35.980286, lon: -71.348917}, "China": {lat: 36.610942, lon: 103.798043}, "Colombia": {lat: 3.923562, lon: -73.077941}, "Costa Rica": {lat: 9.986463, lon: -84.217425}, "Croatia": {lat: 45.185678, lon: 16.458685}, "Cuba": {lat: 21.621368, lon: -78.895403}, "Cyprus": {lat: 34.913044, lon: 33.024092}, "Czech Republic": {lat: 49.701608, lon: 15.330767}, "Democratic Republic of the Congo": {lat: -2.877553, lon: 23.648117}, "Denmark": {lat: 74.725352, lon: -41.290889}, "Djibouti": {lat: 11.745989, lon: 42.567886}, "Dominican Republic": {lat: 18.896879, lon: -70.485959}, "East Timor": {lat: -8.858374, lon: 125.782226}, "Ecuador": {lat: -1.445457, lon: -78.383848}, "Egypt": {lat: 26.492865, lon: 29.867399}, "El Salvador": {lat: 13.734573, lon: -88.865936}, "Equatorial Guinea": {lat: 1.566080, lon: 10.481671}, "Eritrea": {lat: 15.359810, lon: 38.835037}, "Estonia": {lat: 58.693030, lon: 25.811350}, "Ethiopia": {lat: 8.621596, lon: 39.603726}, "Fiji": {lat: -17.827004, lon: 177.984152}, "Finland": {lat: 64.522797, lon: 26.289584}, "France": {lat: -21.285376, lon: 165.438171}, "Gabon": {lat: -0.585980, lon: 11.774049}, "Gambia": {lat: 13.370627, lon: -16.213050}, "Georgia": {lat: 42.175028, lon: 43.486503}, "Germany": {lat: 51.083853, lon: 10.380497}, "Ghana": {lat: 7.940789, lon: -1.215016}, "Greece": {lat: 39.517735, lon: 22.534352}, "Guatemala": {lat: 15.679044, lon: -90.353440}, "Guinea": {lat: 10.440780, lon: -10.943568}, "Guinea Bissau": {lat: 12.050889, lon: -14.929646}, "Guyana": {lat: 4.800330, lon: -58.978019}, "Haiti": {lat: 18.916196, lon: -72.678666}, "Honduras": {lat: 14.821030, lon: -86.656518}, "Hong Kong": {lat: 22.278300, lon: 114.174700}, "Hungary": {lat: 47.168543, lon: 19.410867}, "Iceland": {lat: 65.030350, lon: -18.509671}, "India": {lat: 22.901587, lon: 79.586369}, "Indonesia": {lat: -0.446813, lon: 101.522374}, "Iran": {lat: 32.576164, lon: 54.266247}, "Iraq": {lat: 33.034146, lon: 43.740065}, "Ireland": {lat: 53.234132, lon: -8.117695}, "Israel": {lat: 31.947585, lon: 35.241574}, "Italy": {lat: 43.512811, lon: 12.162338}, "Ivory Coast": {lat: 7.626173, lon: -5.569772}, "Jamaica": {lat: 18.172958, lon: -77.328505}, "Japan": {lat: 36.589925, lon: 137.973525}, "Jordan": {lat: 31.237145, lon: 36.761315}, "Kashmir": {lat: 35.415739, lon: 77.087337}, "Kazakhstan": {lat: 48.155989, lon: 67.278154}, "Kenya": {lat: 0.596719, lon: 37.795079}, "Kosovo": {lat: 42.517832, lon: 20.851519}, "Kuwait": {lat: 29.316145, lon: 47.566177}, "Kyrgyzstan": {lat: 41.483635, lon: 74.582247}, "Laos": {lat: 18.494355, lon: 103.752638}, "Latvia": {lat: 56.853144, lon: 24.894962}, "Lebanon": {lat: 33.915290, lon: 35.885023}, "Lesotho": {lat: -29.573512, lon: 28.243038}, "Liberia": {lat: 6.453996, lon: -9.325868}, "Libya": {lat: 27.031457, lon: 18.008785}, "Lithuania": {lat: 55.314246, lon: 23.872794}, "Luxembourg": {lat: 49.767461, lon: 6.070340}, "Macedonia": {lat: 41.603736, lon: 21.704642}, "Madagascar": {lat: -19.374777, lon: 46.701725}, "Malawi": {lat: -13.200363, lon: 34.288911}, "Malaysia": {lat: 3.577242, lon: 114.692015}, "Mali": {lat: 17.347810, lon: -3.532183}, "Mauritania": {lat: 20.259794, lon: -10.343079}, "Mexico": {lat: 23.943713, lon: -102.518498}, "Moldova": {lat: 47.201792, lon: 28.446473}, "Mongolia": {lat: 46.825609, lon: 103.064235}, "Montenegro": {lat: 42.783955, lon: 19.233365}, "Morocco": {lat: 29.839324, lon: -8.459193}, "Mozambique": {lat: -17.272975, lon: 35.531737}, "Myanmar": {lat: 21.222015, lon: 96.495888}, "Namibia": {lat: -22.132303, lon: 17.208945}, "Nepal": {lat: 28.243336, lon: 83.923410}, "Netherlands": {lat: 52.277341, lon: 5.646194}, "New Zealand": {lat: -43.955382, lon: 170.540471}, "Nicaragua": {lat: 12.835549, lon: -85.032299}, "Niger": {lat: 17.417582, lon: 9.384787}, "Nigeria": {lat: 9.589590, lon: 8.074235}, "North Korea": {lat: 40.144857, lon: 127.215518}, "Northern Cyprus": {lat: 35.225753, lon: 33.390792}, "Norway": {lat: 64.322498, lon: 13.994248}, "Oman": {lat: 20.573738, lon: 56.082719}, "Pakistan": {lat: 29.951586, lon: 69.329881}, "Panama": {lat: 8.521692, lon: -80.059706}, "Papua New Guinea": {lat: -6.607045, lon: 144.228968}, "Paraguay": {lat: -23.223896, lon: -58.399006}, "Peru": {lat: -9.156316, lon: -74.388502}, "Philippines": {lat: 15.948824, lon: 121.457548}, "Poland": {lat: 52.119631, lon: 19.379892}, "Portugal": {lat: 39.685490, lon: -7.977839}, "Qatar": {lat: 25.328766, lon: 51.170816}, "Republic of Serbia": {lat: 44.199984, lon: 20.766250}, "Republic of the Congo": {lat: -0.856400, lon: 15.212074}, "Romania": {lat: 45.845608, lon: 24.971632}, "Russia": {lat: 61.677044, lon: 99.052282}, "Rwanda": {lat: -1.995363, lon: 29.917651}, "Saudi Arabia": {lat: 24.122854, lon: 44.534287}, "Senegal": {lat: 14.338614, lon: -14.472411}, "Sierra Leone": {lat: 8.575093, lon: -11.820132}, "Singapore": {lat: 1.352100, lon: 103.819800}, "Slovakia": {lat: 48.715407, lon: 19.472965}, "Slovenia": {lat: 46.108070, lon: 14.771193}, "Solomon Islands": {lat: -9.628590, lon: 160.156397}, "Somalia": {lat: 4.747961, lon: 45.706540}, "Somaliland": {lat: 9.729995, lon: 46.255133}, "South Africa": {lat: -29.008774, lon: 25.160630}, "South Korea": {lat: 36.475158, lon: 127.872804}, "South Sudan": {lat: 7.307277, lon: 30.253828}, "Spain": {lat: 40.391565, lon: -3.570837}, "Sri Lanka": {lat: 7.649883, lon: 80.700551}, "Sudan": {lat: 15.992059, lon: 29.946244}, "Suriname": {lat: 4.126766, lon: -55.910298}, "Swaziland": {lat: -26.563546, lon: 31.476645}, "Sweden": {lat: 62.835488, lon: 16.752551}, "Switzerland": {lat: 46.805544, lon: 8.205813}, "Syria": {lat: 35.017694, lon: 38.504490}, "Taiwan": {lat: 23.697800, lon: 120.960500}, "Tajikistan": {lat: 38.552044, lon: 70.987127}, "Thailand": {lat: 15.132319, lon: 101.010603}, "The Bahamas": {lat: 24.719920, lon: -78.027339}, "Togo": {lat: 8.576561, lon: 0.949514}, "Trinidad and Tobago": {lat: 10.339930, lon: -61.270459}, "Tunisia": {lat: 34.126731, lon: 9.546833}, "Turkey": {lat: 38.998407, lon: 35.424986}, "Turkmenistan": {lat: 39.109817, lon: 59.392923}, "Uganda": {lat: 1.275770, lon: 32.365755}, "Ukraine": {lat: 49.013453, lon: 31.381193}, "United Arab Emirates": {lat: 23.905698, lon: 54.303458}, "United Kingdom": {lat: -54.468348, lon: -36.367083}, "United Republic of Tanzania": {lat: -6.276146, lon: 34.794901}, "United States of America": {lat: 39.526894, lon: -99.146697}, "Uruguay": {lat: -32.806517, lon: -56.016656}, "Uzbekistan": {lat: 41.750262, lon: 63.148827}, "Vanuatu": {lat: -15.266627, lon: 166.842287}, "Venezuela": {lat: 7.118300, lon: -66.188217}, "Vietnam": {lat: 16.630882, lon: 106.299391}, "Western Sahara": {lat: 24.221136, lon: -12.218085}, "Yemen": {lat: 15.935826, lon: 47.546352}, "Zambia": {lat: -13.460954, lon: 27.775322}, "Zimbabwe": {lat: -19.006775, lon: 29.850564}, } // CountryCentroidByName returns latitude and longitude for a country name, if found. // Accepts composite labels such as "Hong Kong, Hong Kong, HK" from GeoIP providers. func CountryCentroidByName(name string) (lat float64, lon float64, ok bool) { name = strings.TrimSpace(name) if name == "" { return 0, 0, false } if v, found := countryCentroidsByName[name]; found { return v.lat, v.lon, true } // Try comma-separated parts (city / region / country / ISO). for part := range strings.SplitSeq(name, ",") { part = strings.TrimSpace(part) if part == "" { continue } if v, found := countryCentroidsByName[part]; found { return v.lat, v.lon, true } if lat, lon, ok = CountryCentroidByISO(part); ok { return lat, lon, true } } return 0, 0, false } // CountryCentroidByISO returns latitude and longitude for an ISO country code, if found. func CountryCentroidByISO(iso string) (lat float64, lon float64, ok bool) { name, ok := isoToCountryName[strings.ToUpper(strings.TrimSpace(iso))] if !ok { return 0, 0, false } return CountryCentroidByName(name) } var isoToCountryName = map[string]string{ "AT": "Austria", "AU": "Australia", "BR": "Brazil", "CA": "Canada", "CH": "Switzerland", "CN": "China", "DE": "Germany", "ES": "Spain", "FI": "Finland", "FR": "France", "GB": "United Kingdom", "HK": "Hong Kong", "ID": "Indonesia", "IE": "Ireland", "IN": "India", "IT": "Italy", "JP": "Japan", "KR": "South Korea", "MY": "Malaysia", "NL": "Netherlands", "NO": "Norway", "PL": "Poland", "RU": "Russia", "SE": "Sweden", "SG": "Singapore", "TH": "Thailand", "TW": "Taiwan", "US": "United States of America", "VN": "Vietnam", }