const geolib = require("geolib"); // Use OSM API to get coordinates https://nominatim.openstreetmap.org/search?q=search+query&format=json&limit=1 const getCoordinates = async (location) => { return new Promise((resolve, reject) => { // Make location url friendly location = encodeURIComponent(location); const url = `https://nominatim.openstreetmap.org/search?q=${location}&format=json&limit=1`; // use custom useragent (discord-iem-bot, chris@chrischro.me) const options = { headers: { 'User-Agent': 'Discord-IEM-Bot/1.0 (chris@chrischro.me)', }, }; // Make request fetch(url, options) .then(response => response.json()) .then(data => { if (data.length > 0) { resolve({ lat: data[0].lat, lon: data[0].lon, }); } else { reject('Location not found'); } }) .catch(err => { reject(err); }); }) }; const getForecast = async (lat, lon) => { return new Promise((resolve, reject) => { const url = `https://api.weather.gov/points/${lat},${lon}`; // use same custom ua const options = { headers: { 'User-Agent': 'Discord-IEM-Bot/1.0 (chris@chrischro.me)', }, }; // Make request fetch(url, options) .then(response => response.json()) .then(data => { if (data.properties?.forecast) { fetch(data.properties.forecast) .then(response => response.json()) .then(data2 => { data2.properties.relativeLocation = data.properties.relativeLocation; resolve(data2); }) .catch(err => { reject(err); }); } else { reject('Forecast not found'); } }) .catch(err => { reject(err); }); }) }; const getWeatherBySearch = async (search) => { return new Promise((resolve, reject) => { getCoordinates(search) .then(coords => { getForecast(coords.lat, coords.lon) .then(data => { resolve(data); }) .catch(err => { reject(err); }); }) .catch(err => { reject(err); }); }) }; const generateDiscordEmbeds = (forecastData, numOfDays) => { // Take the first 7 periods and make them into embeds const embeds = []; if (!numOfDays) numOfDays = 1; for (let i = 0; i < numOfDays; i++) { const period = forecastData.properties.periods[i]; if (period.icon?.startsWith("/")) { period.icon = `https://api.weather.gov${period.icon}` } const embed = { title: `${period.name} in ${forecastData.properties.relativeLocation.properties.city} ${forecastData.properties.relativeLocation.properties.state}`, description: `Valid - \n${period.detailedForecast}`, timestamp: new Date(period.startTime), thumbnail: { url: period.icon, }, fields: [ { name: 'Temperature', value: `${period.temperature}°F`, inline: true }, { name: 'Wind', value: `${period.windDirection}@${period.windSpeed}`, inline: true }, { name: 'Precipitation', value: period.probabilityOfPrecipitation?.value ? period.probabilityOfPrecipitation?.value + '%' : '0%', inline: true }, { name: 'Humidity', value: period.relativeHumidity?.value ? period.relativeHumidity.value + '%' : "0%", } ], footer: { text: `Data provided by the National Weather Service · Elevation ${forecastData.properties.elevation.value}m` } }; embeds.push(embed); } return embeds; } module.exports = { getCoordinates, getForecast, getWeatherBySearch, generateDiscordEmbeds };