forked from MyZubster-Ecosystem/myzubster
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgeocoding.js
More file actions
113 lines (106 loc) 路 2.69 KB
/
Copy pathgeocoding.js
File metadata and controls
113 lines (106 loc) 路 2.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
const https = require('https');
const GEOCODING_TIMEOUT = 5000;
const NOMINATIM_BASE = 'https://nominatim.openstreetmap.org';
function requestJson(url) {
return new Promise((resolve) => {
const req = https.get(
url,
{
headers: {
'Accept-Language': 'it',
'User-Agent': 'MyZubster/1.0 (test@myzubster.com)',
},
},
(res) => {
let body = '';
res.setEncoding('utf8');
res.on('data', (chunk) => {
body += chunk;
});
res.on('end', () => {
if (res.statusCode < 200 || res.statusCode >= 300) {
resolve(null);
return;
}
try {
resolve(JSON.parse(body));
} catch (_) {
resolve(null);
}
});
}
);
req.setTimeout(GEOCODING_TIMEOUT, () => {
req.destroy();
resolve(null);
});
req.on('error', () => {
resolve(null);
});
});
}
async function geocodeAddress(address) {
if (!address || address.trim() === '') return null;
const url =
NOMINATIM_BASE +
'/search?q=' +
encodeURIComponent(address) +
'&format=json&limit=1&addressdetails=1';
const results = await requestJson(url);
if (!Array.isArray(results) || results.length === 0) return null;
const first = results[0];
const lat = parseFloat(first.lat);
const lng = parseFloat(first.lon);
if (
!Number.isFinite(lat) ||
!Number.isFinite(lng) ||
lat < -90 ||
lat > 90 ||
lng < -180 ||
lng > 180
) {
return null;
}
return {
lat,
lng,
displayName: first.display_name || '',
osmId: first.osm_id || null,
osmType: first.osm_type || null,
neighborhood:
(first.address && (first.address.suburb || first.address.neighbourhood)) || '',
city:
(first.address &&
(first.address.city ||
first.address.town ||
first.address.village ||
first.address.municipality)) ||
'',
};
}
async function reverseGeocode(lat, lng) {
if (lat === undefined || lng === undefined) return null;
const url =
NOMINATIM_BASE +
'/reverse?lat=' +
lat +
'&lon=' +
lng +
'&format=json&addressdetails=1';
const data = await requestJson(url);
if (!data || data.error) return null;
return {
displayName: data.display_name || '',
address: data.display_name || '',
neighborhood:
(data.address && (data.address.suburb || data.address.neighbourhood)) || '',
city:
(data.address &&
(data.address.city ||
data.address.town ||
data.address.village ||
data.address.municipality)) ||
'',
};
}
module.exports = { geocodeAddress, reverseGeocode };