diff --git a/.gitignore b/.gitignore index 1f6b6bd..ffa5987 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules -*-metars.json \ No newline at end of file +*-metars.json +data/ \ No newline at end of file diff --git a/index.js b/index.js index 2c2fbf2..ef0cccb 100644 --- a/index.js +++ b/index.js @@ -3,11 +3,19 @@ import axios from "axios"; import fs from 'fs'; import path from 'path'; +const generatorURL = "https://git.entropic.pro/Aiden/metar-rss"; const API_URL = "https://aviationweather.gov/api/data/"; const METAR_SERVICE = "metar"; -const generatorURL = "https://git.entropic.pro/Aiden/metar-rss"; +const TAF_SERVICE = "taf"; +const SERVICES = [METAR_SERVICE, TAF_SERVICE]; +const SERVICE_FUNC = [newMetar, newTAF]; -let defaultConfig = { +const DATA_DIR = "data"; +if (!fs.existsSync(DATA_DIR)) { + fs.mkdirSync(DATA_DIR); +} + +const defaultConfig = { "outputdir": "/var/www/weather", "icaos": ["KJFK"], "siteurl": "https://example.com", @@ -16,7 +24,7 @@ let defaultConfig = { "loglevel": 4 }; /** Load config file */ -const configFile = "./config.json"; +const configFile = "config.json"; let configData; try { configData = JSON.parse(fs.readFileSync(configFile)); @@ -75,69 +83,114 @@ const checkInterval = Number(configData["check-interval"]) * 1000 * 60; /** Start Service **/ -checkMetar(); //Inital check run -const metarCheckJob = setInterval(checkMetar, checkInterval); //Run the check every interval +checkAPI(); //Inital check run +const metarCheckJob = setInterval(checkAPI, checkInterval); //Run the check every interval /** - * Pulls the current metar and adds it to the feed if it is new + * Pulls the current METAR and TAF and adds it to the feed if it is new */ -function checkMetar() { +function checkAPI() { for (let i = 0; i < icaos.length; i++) { let icao = icaos[i]; - if (loglevel >= 7) console.log("Checking METAR for " + icao); - getMetar(icao).then(res => { - let metarFile = icao+"-metars.json"; - let metars = []; - if (fs.existsSync(metarFile)) - metars = JSON.parse(fs.readFileSync(icao+"-metars.json"))["data"]; - if (res.data != metars[0]) { - if (loglevel >= 6) console.log("New METAR: " + res.data); - metars.unshift(res.data); - if (metars.length > 20) metars.pop(); - fs.writeFileSync(metarFile, JSON.stringify({"data": metars})); + for (let s = 0; s < SERVICES.length; s++) { + let service = SERVICES[s]; + if (loglevel >= 7) console.log("Checking " + service.toUpperCase() + " for " + icao); - let items = []; - for (let i = 0; i < metars.length; i++) { - if (metars[i] != undefined) - items.push(newMetar(metars[i])); + getData(icao, service).then(res => { + let dataFile = path.join(DATA_DIR, icao+"-"+service+".json"); + let data = new Array(); + if (fs.existsSync(dataFile)) + data = JSON.parse(fs.readFileSync(dataFile))[service]; + + //If the recived data is new + if (data === undefined || res.data != data[0]) { + if (loglevel >= 6) console.log("New " + service.toUpperCase() + " for " + icao); + + if (data === undefined) data = [res.data]; + else data.unshift(res.data); + + // Keep a max of 20 entries + if (data.length > 20) data.pop(); + fs.writeFileSync(dataFile, JSON.stringify({[service]: data})); + + let items = []; + for (let j = 0; j < data.length; j++) { + if (data[j] != undefined || data[j] != null) { + items.push(SERVICE_FUNC[s](data[j])); + } + } + + let outputPath = path.join(service, icao); + writeFeed(generateFeed(service, icao, items, outputPath), outputPath); } - - let outputPath = path.join(METAR_SERVICE, icao); - writeFeed(generateFeed(METAR_SERVICE, icao, items, outputPath), outputPath); - } - }); + }); + } } } /** - * Adds a new METAR to the given RSS Feed - * @param {RSS} rss - RSS Feed to add the entry to - * @param {String} metar - metar data to add + * Generates METAR RSS Item + * @param {String} metar - metar text/data to add * @returns {Object} - Object of RSS Item Data */ function newMetar(metar) { let metarSplit = metar.split(" "); + let metarTime = metarSplit[2]; // time/date section of metar + let date = new Date(Date.now()); - let eventDate = new Date(Date.UTC(date.getFullYear(), date.getMonth(), Number(metarSplit[2].substring(0,2)), Number(metarSplit[2].substring(2,4)), Number(metarSplit[2].substring(4,6)))); + let eventDate = new Date(Date.UTC(date.getFullYear(), date.getMonth(), Number(metarTime.substring(0,2)), Number(metarTime.substring(2,4)), Number(metarTime.substring(4,6)))); let item = { title: metarSplit[0] + " " + metarSplit[1] + " " + metarSplit[2], description: metar, - url: API_URL + METAR_SERVICE, + url: API_URL + METAR_SERVICE + "?ids=" + metarSplit[1], guid: metarSplit[1] + metarSplit[2], date: eventDate }; - return item + return item; +} + +/** + * Generates TAF RSS Item + * @param {String} taf - taf text/data to add + * @returns {Object} - Object of RSS Item Data + */ +function newTAF(taf) { + let tafSplit = taf.split(" "); + let tafTime = tafSplit[((tafSplit[1] == "AMD") ? 3 : 2)]; // index of the time/date section is pushed if TAF is amended + + let date = new Date(Date.now()); + let eventDate = new Date(Date.UTC(date.getFullYear(), date.getMonth(),Number(tafTime.substring(0,2)), Number(tafTime.substring(2,4)), Number(tafTime.substring(4,6)))); + + let title; + let id; + if (tafSplit[1] == "AMD") { + title = tafSplit[0] + " " + tafSplit[1] + " " + tafSplit[2] + " " + tafSplit[3]; + id = tafSplit[1] + tafSplit[2] + tafSplit[3]; + } else { + title = tafSplit[0] + " " + tafSplit[1] + " " + tafSplit[2]; + id = tafSplit[1] + tafSplit[2]; + } + + let item = { + title: title, + description: taf, + url: API_URL + TAF_SERVICE + "?ids=" + ((tafSplit[1] == "AMD") ? tafSplit[2] : tafSplit[1]), + guid: id, + date: eventDate + }; + return item; } /** * Pulls METAR data from the API * @param {String} icao ICAO Airport Code + * @param {String} service service to fetch (eg. "metar" or "taf") * @returns Axios generated GET Request Response */ -function getMetar(icao) { - let requestURL = API_URL + METAR_SERVICE + "?ids=" + icao; +function getData(icao, service) { + let requestURL = API_URL + service + "?ids=" + icao; return axios.get(requestURL); } @@ -154,8 +207,8 @@ function generateFeed(service, icao, items, outputPath) { feedURL.pathname = path.join(feedURL.pathname, outputPath, "rss.xml"); let feedOptions = { - title: icao + " " + service, - description: service + " feed for " + icao + " Airport", + title: icao + " " + service.toUpperCase(), + description: service.toUpperCase() + " feed for " + icao + " Airport", feed_url: feedURL, site_url: siteURL, generator: generatorURL diff --git a/package.json b/package.json index 5c376bf..9082766 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "metar-rss", "version": "1.1.0", - "description": "Monitors, generates and updates an RSS Feed File for Airport METARs", + "description": "Monitors, generates and updates an RSS Feed File for Airport METARs and TAFs", "repository": { "type": "git", "url": "https://git.entropic.pro/Aiden/metar-rss"