Spaces:
Running
Running
File size: 3,730 Bytes
0dd2082 | 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 | const BaseProvider = require('./BaseProvider');
const logger = require('../utils/logger');
class OSMProvider extends BaseProvider {
constructor() {
super('osm_nominatim', { priority: 2, timeout: 5000 });
this.baseUrl = 'https://nominatim.openstreetmap.org/search';
}
async search(intent, pagination) {
const { category = 'place', location, neighborhood } = intent;
const area = [neighborhood, location].filter(Boolean).join(', ');
// If neither neighborhood nor location were parsed by AI, use the raw query as fallback
const searchTerm = category === 'all'
? `places ${area ? 'in ' + area : ''}`.trim()
: `${category} ${area ? 'in ' + area : ''}`.trim();
logger.info(`OSMProvider requested Nominatim query: "${searchTerm}"`);
const params = new URLSearchParams({
q: searchTerm,
format: 'json',
limit: 15,
addressdetails: 1,
extratags: 1
});
const url = `${this.baseUrl}?${params.toString()}`;
const response = await fetch(url, {
method: 'GET',
headers: {
'User-Agent': 'RedThreadBot/1.0 (https://github.com/ayush/redthread)'
}
});
if (!response.ok) {
throw new Error(`Nominatim API Error: ${response.status}`);
}
const data = await response.json();
const results = data.map(el => {
const extratags = el.extratags || {};
// Extract genuine real-world features from OSM metadata (no fakeism)
const realFeatures = [];
if (extratags.internet_access === 'wlan' || extratags.wifi === 'yes') realFeatures.push('WiFi');
if (extratags.wheelchair === 'yes') realFeatures.push('Wheelchair Accessible');
if (extratags.outdoor_seating === 'yes') realFeatures.push('Outdoor Seating');
if (extratags.air_conditioning === 'yes') realFeatures.push('AC');
if (extratags.takeaway === 'yes') realFeatures.push('Takeaway');
if (extratags.delivery === 'yes') realFeatures.push('Delivery');
if (extratags.diet_vegan === 'yes' || extratags.vegan === 'yes') realFeatures.push('Vegan Options');
if (extratags.parking === 'yes') realFeatures.push('Parking');
return {
id: `osm-${el.place_id}`,
name: el.name || `Unnamed ${el.type || category}`,
category: el.type || category,
address: el.display_name,
rating: extratags.rating || 'N/A', // OSM rarely has ratings, fallback to honest N/A
priceRange: extratags.price || extratags.charge || 'N/A', // Honest fallback instead of RNG
features: realFeatures,
coordinates: { lat: el.lat, lon: el.lon },
source: this.name
};
});
return {
results,
meta: {
total: results.length,
source: this.name,
providerTime: new Date().toISOString()
}
};
}
async healthCheck() {
try {
const start = Date.now();
const res = await fetch(`${this.baseUrl}?q=Bhubaneswar&format=json&limit=1`, {
headers: { 'User-Agent': 'RedThreadBot/1.0' }
});
if (res.ok) {
return { status: 'up', latency: Date.now() - start };
}
return { status: 'down', error: `HTTP ${res.status}` };
} catch (err) {
return { status: 'down', error: err.message };
}
}
}
module.exports = OSMProvider;
|