From 8751c0dee393bf274b9d3b7127a502603f01a749 Mon Sep 17 00:00:00 2001 From: ryan Date: Sat, 20 Jun 2026 19:46:33 +0800 Subject: [PATCH] =?UTF-8?q?fix(openflare):=20mmdb=20=E5=9B=BD=E5=AE=B6?= =?UTF-8?q?=E5=90=8D=E8=8A=82=E7=82=B9=E5=9C=A8=E4=B8=96=E7=95=8C=E5=9C=B0?= =?UTF-8?q?=E5=9B=BE=E4=BD=BF=E7=94=A8=E6=AD=A3=E7=A1=AE=E8=B4=A8=E5=BF=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 从 world-geo 生成国家质心表,Server 在仅有 ISO/国家名时补全 geo 坐标 - 全球态势板在缺少经纬度时按 geo_name 解析质心,避免 fallback 到美国 --- docs/changelog/index.md | 2 + .../dashboard/data/country-centroids.json | 682 ++++++++++++++++++ .../components/dashboard/world-stage-map.tsx | 29 + internal/apps/openflare/geoip/node.go | 20 + pkg/geoip/country_centroid.go | 232 ++++++ pkg/geoip/country_centroid_test.go | 13 + 6 files changed, 978 insertions(+) create mode 100644 frontend/app/(main)/components/dashboard/data/country-centroids.json create mode 100644 pkg/geoip/country_centroid.go create mode 100644 pkg/geoip/country_centroid_test.go diff --git a/docs/changelog/index.md b/docs/changelog/index.md index 30658c9d..8790772b 100644 --- a/docs/changelog/index.md +++ b/docs/changelog/index.md @@ -18,6 +18,8 @@ sidebar: false ### 修复 +- 修复全球态势板在仅有 `geo_name`(如 mmdb 的 Germany)而无经纬度时误用美国 fallback 坐标的问题;按国家名/ISO 匹配地图质心。 + - 修复 Agent 心跳上报公网 IP 后节点地理位置未自动更新:进程启动时按 `GeoIPProvider` 初始化 `pkg/geoip`,`mmdb` 模式从内置 GeoLite2 种子到 `data/`,并在 Relay 心跳同步地理位置。 - 修复 Agent 启动时 Pages 部署包下载失败:Pages 部署包统一下载走 upload 文件存储框架,部署记录持久化 `upload_id`,legacy `artifact_path` 仅用于一次性回填 upload。 diff --git a/frontend/app/(main)/components/dashboard/data/country-centroids.json b/frontend/app/(main)/components/dashboard/data/country-centroids.json new file mode 100644 index 00000000..099ca978 --- /dev/null +++ b/frontend/app/(main)/components/dashboard/data/country-centroids.json @@ -0,0 +1,682 @@ +{ + "Afghanistan": [ + 65.99254367483304, + 33.83349410470984 + ], + "Angola": [ + 17.563198329790602, + -12.334557680834592 + ], + "Albania": [ + 20.035803636476235, + 41.179283471608585 + ], + "United Arab Emirates": [ + 54.30345828396012, + 23.905698042805522 + ], + "Argentina": [ + -65.15670576062132, + -35.178771590782524 + ], + "Armenia": [ + 44.929379894609674, + 40.29884592895426 + ], + "France": [ + 165.43817082439585, + -21.285375782391018 + ], + "Australia": [ + 134.361180723562, + -25.574955774991995 + ], + "Austria": [ + 14.10165807418182, + 47.57042831528493 + ], + "Azerbaijan": [ + 47.636777782137415, + 40.3311508093757 + ], + "Burundi": [ + 29.873065896828848, + -3.3802825292327188 + ], + "Belgium": [ + 4.628129604331132, + 50.646494813466056 + ], + "Benin": [ + 2.323507643298733, + 9.63048313950481 + ], + "Burkina Faso": [ + -1.7757430610210276, + 12.260370131848955 + ], + "Bangladesh": [ + 90.21009840315206, + 23.88793565572049 + ], + "Bulgaria": [ + 25.225364036830744, + 42.77785706066581 + ], + "The Bahamas": [ + -78.02733865351972, + 24.719920319716515 + ], + "Bosnia and Herzegovina": [ + 17.762461846176542, + 44.16398853722456 + ], + "Belarus": [ + 28.04895281233843, + 53.53432933090482 + ], + "Belize": [ + -88.72096138346826, + 17.17073148225863 + ], + "Bolivia": [ + -64.69104972918655, + -16.70141507507877 + ], + "Brazil": [ + -53.113858151998855, + -10.827995867833263 + ], + "Brunei": [ + 114.54229268997476, + 4.451218476864121 + ], + "Bhutan": [ + 90.40562361681495, + 27.40133623508629 + ], + "Botswana": [ + 23.791788508036337, + -22.185333985163894 + ], + "Central African Republic": [ + 20.490781591297914, + 6.563625165826992 + ], + "Canada": [ + -102.31777616484295, + 57.94457487676815 + ], + "Switzerland": [ + 8.205812860319684, + 46.805544047201984 + ], + "Chile": [ + -71.34891661948937, + -35.98028631773855 + ], + "China": [ + 103.79804331240364, + 36.61094167680319 + ], + "Ivory Coast": [ + -5.569771898429842, + 7.626172775954684 + ], + "Cameroon": [ + 12.739868035578002, + 5.692692453534944 + ], + "Democratic Republic of the Congo": [ + 23.64811688254194, + -2.8775533309965056 + ], + "Republic of the Congo": [ + 15.21207418503586, + -0.8564004333096924 + ], + "Colombia": [ + -73.07794094917405, + 3.9235618261252663 + ], + "Costa Rica": [ + -84.21742467558424, + 9.986463158070535 + ], + "Cuba": [ + -78.8954025482625, + 21.62136808001903 + ], + "Northern Cyprus": [ + 33.39079188058263, + 35.225753269439686 + ], + "Cyprus": [ + 33.02409208254226, + 34.91304424540028 + ], + "Czech Republic": [ + 15.330767057694615, + 49.70160772219921 + ], + "Germany": [ + 10.380496796525602, + 51.083853487429664 + ], + "Djibouti": [ + 42.56788631653962, + 11.745988995518626 + ], + "Denmark": [ + -41.29088868109839, + 74.72535220460091 + ], + "Dominican Republic": [ + -70.48595892120278, + 18.896879062003393 + ], + "Algeria": [ + 2.6175172555729325, + 28.158202786113698 + ], + "Ecuador": [ + -78.38384779532852, + -1.4454571869341688 + ], + "Egypt": [ + 29.86739912685152, + 26.49286512797635 + ], + "Eritrea": [ + 38.835037148217566, + 15.359809600209143 + ], + "Spain": [ + -3.5708365129134876, + 40.391564705240064 + ], + "Estonia": [ + 25.811350172874032, + 58.69303019372469 + ], + "Ethiopia": [ + 39.60372599651433, + 8.621595995236198 + ], + "Finland": [ + 26.28958351526606, + 64.52279699210293 + ], + "Fiji": [ + 177.98415179869738, + -17.827004078184217 + ], + "United Kingdom": [ + -36.367082569942795, + -54.468348288665524 + ], + "Gabon": [ + 11.774048593462979, + -0.5859798536474902 + ], + "Georgia": [ + 43.48650319000057, + 42.175027555818694 + ], + "Ghana": [ + -1.2150159067556041, + 7.94078880601944 + ], + "Guinea": [ + -10.943568403941383, + 10.44078010915303 + ], + "Gambia": [ + -16.21304964555284, + 13.37062695465985 + ], + "Guinea Bissau": [ + -14.929646023453557, + 12.05088889829685 + ], + "Equatorial Guinea": [ + 10.481670786028316, + 1.5660796013647418 + ], + "Greece": [ + 22.53435219348475, + 39.517734832602365 + ], + "Guatemala": [ + -90.35344030476544, + 15.679044168855697 + ], + "Guyana": [ + -58.978019347627985, + 4.800329726037504 + ], + "Honduras": [ + -86.65651796671759, + 14.821029518594349 + ], + "Croatia": [ + 16.458685366615978, + 45.18567759026696 + ], + "Haiti": [ + -72.67866559866681, + 18.916195586860297 + ], + "Hungary": [ + 19.410867145831855, + 47.168542742918525 + ], + "Indonesia": [ + 101.52237404492608, + -0.44681277438152994 + ], + "India": [ + 79.58636900833257, + 22.901586798523514 + ], + "Ireland": [ + -8.117695195030898, + 53.2341315203433 + ], + "Iran": [ + 54.266246557433305, + 32.57616445788996 + ], + "Iraq": [ + 43.74006501790808, + 33.0341456153028 + ], + "Iceland": [ + -18.509670948264166, + 65.03034972428229 + ], + "Israel": [ + 35.241573878810335, + 31.94758544099519 + ], + "Italy": [ + 12.16233842748749, + 43.51281131035235 + ], + "Jamaica": [ + -77.32850498837172, + 18.172957893241634 + ], + "Jordan": [ + 36.76131486689134, + 31.237145277490367 + ], + "Japan": [ + 137.97352453982398, + 36.589925009528365 + ], + "Kashmir": [ + 77.08733723957188, + 35.415738932286466 + ], + "Kazakhstan": [ + 67.27815427190085, + 48.155989088140196 + ], + "Kenya": [ + 37.795078751163835, + 0.5967194222965451 + ], + "Kyrgyzstan": [ + 74.58224715420873, + 41.48363475100716 + ], + "Cambodia": [ + 104.90702345739547, + 12.717932969523966 + ], + "South Korea": [ + 127.87280447602005, + 36.475157799464604 + ], + "Kosovo": [ + 20.851519165302378, + 42.51783231278167 + ], + "Kuwait": [ + 47.566177395781736, + 29.316145203902064 + ], + "Laos": [ + 103.75263811609112, + 18.494354885305256 + ], + "Lebanon": [ + 35.88502277707876, + 33.91528991779158 + ], + "Liberia": [ + -9.325867879201954, + 6.453996218817175 + ], + "Libya": [ + 18.008785486000946, + 27.031457363755713 + ], + "Sri Lanka": [ + 80.70055059693914, + 7.649883097905021 + ], + "Lesotho": [ + 28.24303757633595, + -29.57351232727891 + ], + "Lithuania": [ + 23.872793668340726, + 55.3142460584835 + ], + "Luxembourg": [ + 6.070340274408408, + 49.76746140228473 + ], + "Latvia": [ + 24.89496154477673, + 56.853143698564296 + ], + "Morocco": [ + -8.459192831832421, + 29.83932361976915 + ], + "Moldova": [ + 28.446472517363826, + 47.2017924696845 + ], + "Madagascar": [ + 46.70172536870331, + -19.374776628372288 + ], + "Mexico": [ + -102.51849775988345, + 23.943713432682014 + ], + "Macedonia": [ + 21.704642152886493, + 41.60373573782414 + ], + "Mali": [ + -3.5321833143642736, + 17.347810147640345 + ], + "Myanmar": [ + 96.49588816533908, + 21.22201469728619 + ], + "Montenegro": [ + 19.233365413523355, + 42.78395456212118 + ], + "Mongolia": [ + 103.06423533091326, + 46.82560864032323 + ], + "Mozambique": [ + 35.53173663088568, + -17.27297477254694 + ], + "Mauritania": [ + -10.34307896458181, + 20.259793585678146 + ], + "Malawi": [ + 34.288911351438394, + -13.200363393826267 + ], + "Malaysia": [ + 114.69201508943004, + 3.57724156754415 + ], + "Namibia": [ + 17.208945346875193, + -22.132302890947404 + ], + "Niger": [ + 9.384787308614277, + 17.41758190683491 + ], + "Nigeria": [ + 8.074235448092892, + 9.58958974174772 + ], + "Nicaragua": [ + -85.03229930746807, + 12.835548864379284 + ], + "Netherlands": [ + 5.646194278986089, + 52.27734132368374 + ], + "Norway": [ + 13.994247649210363, + 64.32249798565987 + ], + "Nepal": [ + 83.9234099472594, + 28.243335814044734 + ], + "New Zealand": [ + 170.54047059084724, + -43.955381757717255 + ], + "Oman": [ + 56.08271927344639, + 20.573738446088598 + ], + "Pakistan": [ + 69.32988114530586, + 29.951585862562073 + ], + "Panama": [ + -80.05970573973497, + 8.521692369504816 + ], + "Peru": [ + -74.38850244798846, + -9.156316252308201 + ], + "Philippines": [ + 121.45754828266669, + 15.948824272939182 + ], + "Papua New Guinea": [ + 144.22896759838426, + -6.607045399379529 + ], + "Poland": [ + 19.379892383012464, + 52.11963086628078 + ], + "United States of America": [ + -99.14669730710926, + 39.52689381707972 + ], + "North Korea": [ + 127.21551783512186, + 40.144856985239926 + ], + "Portugal": [ + -7.977838817691485, + 39.6854900148663 + ], + "Paraguay": [ + -58.39900641582761, + -23.223895588708068 + ], + "Qatar": [ + 51.170816022848, + 25.32876608728452 + ], + "Romania": [ + 24.971632366248883, + 45.84560772065747 + ], + "Russia": [ + 99.05228241954488, + 61.677043847105494 + ], + "Rwanda": [ + 29.91765145538139, + -1.9953628964377972 + ], + "Western Sahara": [ + -12.218085234851758, + 24.221135708939354 + ], + "Saudi Arabia": [ + 44.5342871199886, + 24.122854227726673 + ], + "Sudan": [ + 29.946243665370346, + 15.99205876641883 + ], + "South Sudan": [ + 30.253827921202955, + 7.307277152400154 + ], + "Senegal": [ + -14.472411019597182, + 14.338613732351318 + ], + "Solomon Islands": [ + 160.156396875585, + -9.628589831637283 + ], + "Sierra Leone": [ + -11.82013204896783, + 8.575093438325089 + ], + "El Salvador": [ + -88.86593554283397, + 13.734573052971413 + ], + "Somaliland": [ + 46.25513292885051, + 9.729995248781385 + ], + "Somalia": [ + 45.706539856671256, + 4.747960517798881 + ], + "Republic of Serbia": [ + 20.766249889622852, + 44.19998417744864 + ], + "Suriname": [ + -55.91029765824739, + 4.126766010517478 + ], + "Slovakia": [ + 19.47296461136286, + 48.71540683451534 + ], + "Slovenia": [ + 14.771193461021065, + 46.10807043333343 + ], + "Sweden": [ + 16.752551082675275, + 62.8354879894394 + ], + "Swaziland": [ + 31.47664514492297, + -26.563545981108437 + ], + "Syria": [ + 38.50449031631095, + 35.01769370592341 + ], + "Chad": [ + 18.645815630757973, + 15.32729896930035 + ], + "Togo": [ + 0.949513544830056, + 8.576560980195756 + ], + "Thailand": [ + 101.01060253224972, + 15.132319216387051 + ], + "Tajikistan": [ + 70.98712700685866, + 38.55204366339685 + ], + "Turkmenistan": [ + 59.39292286662992, + 39.1098173228857 + ], + "East Timor": [ + 125.78222644041995, + -8.858373836074785 + ], + "Trinidad and Tobago": [ + -61.270458833911896, + 10.339930045317969 + ], + "Tunisia": [ + 9.546832905099203, + 34.12673069029241 + ], + "Turkey": [ + 35.424986274948736, + 38.998407240706534 + ], + "United Republic of Tanzania": [ + 34.79490109621088, + -6.276146393386636 + ], + "Uganda": [ + 32.36575488492427, + 1.2757695499320103 + ], + "Ukraine": [ + 31.381193375918794, + 49.01345298489402 + ], + "Uruguay": [ + -56.01665573850212, + -32.80651677440885 + ], + "Uzbekistan": [ + 63.148826727968626, + 41.7502616897204 + ], + "Venezuela": [ + -66.1882174671549, + 7.118299933056809 + ], + "Vietnam": [ + 106.29939096235873, + 16.63088189612042 + ], + "Vanuatu": [ + 166.84228659210697, + -15.266627310669035 + ], + "Yemen": [ + 47.546351590294876, + 15.935825615412996 + ], + "South Africa": [ + 25.160630055943862, + -29.008774283210798 + ], + "Zambia": [ + 27.775321721593084, + -13.460954386993254 + ], + "Zimbabwe": [ + 29.850564118889274, + -19.00677451616593 + ] +} diff --git a/frontend/app/(main)/components/dashboard/world-stage-map.tsx b/frontend/app/(main)/components/dashboard/world-stage-map.tsx index 9fd75510..a8db93ad 100644 --- a/frontend/app/(main)/components/dashboard/world-stage-map.tsx +++ b/frontend/app/(main)/components/dashboard/world-stage-map.tsx @@ -14,6 +14,7 @@ import {EmptyState} from '@/components/layout/empty'; import type {DashboardNodeHealth, DistributionItem} from '@/lib/services/openflare'; import {getNodeStatusLabel, getOpenrestyStatusLabel,} from '../../nodes/components/node-utils'; +import countryCentroids from './data/country-centroids.json'; import worldGeoJson from './data/world-geo.json'; echarts.use([ @@ -128,6 +129,26 @@ function getNodeTone(node: DashboardNodeHealth): Tone { return 'healthy'; } +const countryCentroidMap = countryCentroids as Record; + +function resolveCountryCentroid(geoName: string) { + const trimmed = geoName.trim(); + if (!trimmed) { + return null; + } + const direct = countryCentroidMap[trimmed]; + if (direct) { + return direct; + } + const lower = trimmed.toLowerCase(); + for (const [name, coordinates] of Object.entries(countryCentroidMap)) { + if (name.toLowerCase() === lower) { + return coordinates; + } + } + return null; +} + function getNodeCoordinates(node: DashboardNodeHealth, index: number) { if ( typeof node.geo_latitude === 'number' && @@ -139,6 +160,14 @@ function getNodeCoordinates(node: DashboardNodeHealth, index: number) { }; } + const countryCentroid = resolveCountryCentroid(node.geo_name || ''); + if (countryCentroid) { + return { + coordinates: countryCentroid, + derivedFromGeo: true, + }; + } + return { coordinates: [ ...fallbackCoordinates[index % fallbackCoordinates.length], diff --git a/internal/apps/openflare/geoip/node.go b/internal/apps/openflare/geoip/node.go index b0607d08..7f31cfbd 100644 --- a/internal/apps/openflare/geoip/node.go +++ b/internal/apps/openflare/geoip/node.go @@ -9,6 +9,7 @@ import ( "strings" "github.com/Rain-kl/Wavelet/internal/model" + pkggeoip "github.com/Rain-kl/Wavelet/pkg/geoip" "github.com/Rain-kl/Wavelet/pkg/logger" ) @@ -40,7 +41,26 @@ func ApplyNodeGeoFromIP(ctx context.Context, node *model.OpenFlareNode, rawIP st if info.Latitude != nil && info.Longitude != nil { node.GeoLatitude = cloneCoordinate(info.Latitude) node.GeoLongitude = cloneCoordinate(info.Longitude) + return } + applyCountryCentroid(node, info.ISOCode, info.Name) +} + +func applyCountryCentroid(node *model.OpenFlareNode, isoCode, name string) { + if lat, lon, ok := pkggeoip.CountryCentroidByISO(isoCode); ok { + node.GeoLatitude = cloneFloat(lat) + node.GeoLongitude = cloneFloat(lon) + return + } + if lat, lon, ok := pkggeoip.CountryCentroidByName(name); ok { + node.GeoLatitude = cloneFloat(lat) + node.GeoLongitude = cloneFloat(lon) + } +} + +func cloneFloat(value float64) *float64 { + cloned := value + return &cloned } func cloneCoordinate(value *float64) *float64 { diff --git a/pkg/geoip/country_centroid.go b/pkg/geoip/country_centroid.go new file mode 100644 index 00000000..6c397069 --- /dev/null +++ b/pkg/geoip/country_centroid.go @@ -0,0 +1,232 @@ +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}, + "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}, + "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}, + "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}, +} + +func CountryCentroidByName(name string) (lat float64, lon float64, ok bool) { + name = strings.TrimSpace(name) + if name == "" { + return 0, 0, false + } + if v, ok := countryCentroidsByName[name]; ok { + return v.lat, v.lon, true + } + return 0, 0, false +} + +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", +} diff --git a/pkg/geoip/country_centroid_test.go b/pkg/geoip/country_centroid_test.go new file mode 100644 index 00000000..6f3484f9 --- /dev/null +++ b/pkg/geoip/country_centroid_test.go @@ -0,0 +1,13 @@ +package geoip + +import "testing" + +func TestCountryCentroidGermany(t *testing.T) { + lat, lon, ok := CountryCentroidByISO("DE") + if !ok { + t.Fatal("expected DE centroid") + } + if lat < 47 || lat > 55 || lon < 5 || lon > 15 { + t.Fatalf("unexpected Germany centroid: %f,%f", lat, lon) + } +}