Compare commits

..

9 Commits

Author SHA1 Message Date
Matt Walsh
9150d42802 5.27.2 2025-07-15 22:13:04 -05:00
Matt Walsh
54257e4667 add new naming issue template 2025-07-15 22:07:52 -05:00
Matt Walsh
7d50ce28bd Allow for station data overrides #125 2025-07-15 22:00:33 -05:00
Matt Walsh
2db7f30de7 5.27.1 2025-07-11 22:36:57 -05:00
Matt Walsh
5c7a6ab1a4 fix for rss feed encoding types close #124 2025-07-11 22:36:47 -05:00
Matt Walsh
4b63328b74 update dependencies 2025-07-06 10:54:20 -05:00
Matt Walsh
ae1d004f60 Merge pull request #123 from rmitchellscott/fix-static-envs
fix: url encode envs in static-env-handler. Fixes #122.
2025-07-06 10:36:51 -05:00
Mitchell Scott
7dd4c1dd24 fix: url encode envs in static-env-handler. Fixes #122. 2025-07-04 04:41:56 -06:00
Matt Walsh
1120247c99 include custom rss feed in build #57 2025-06-30 23:32:30 -05:00
12 changed files with 16564 additions and 16518 deletions

13
.github/ISSUE_TEMPLATE/naming _issue.md vendored Normal file
View File

@@ -0,0 +1,13 @@
---
name: Naming issue
about: A city, airport or other location is not named correctly
title: 'Name Issue: '
labels: naming
assignees: ''
---
This form is not for reporting a location that you can not find from the search box.
Use this form to help us rename airports, points of interest and other data provided from the API (rarely updated) to a better name. For example the airport in Broomfield colorado was renamed from "Jeffco" in the API to "Rocky Mountain Metro" it's new name.
You can also make a pull request on the `[station-overrides.mjs](https://github.com/netbymatt/ws4kp/blob/main/datagenerators/stations-states.mjs)` file which includes instructions on how to make the change directly. This is the preferred method.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,19 @@
// station overrides are used to change the data for a station that is provided by the api
// the most common use is to adjust the city (station name) for formatting or to update an outdated name
// a complete station object looks like this:
// {
// "id": "KMCO", // 4-letter station identifier and key for lookups
// "city": "Orlando International Airport", // name displayed for this station
// "state": "FL", // state
// "lat": 28.41826, // latitude of station
// "lon": -81.32413 // longitude of station
// }
// any or all of the data for a station can be overwritten, follow the existing override patterns below
const overrides = {
KBJC: {
city: 'Rocky Mountain Metro',
},
};
export default overrides;

View File

@@ -5,6 +5,7 @@ import { writeFileSync } from 'fs';
import https from './https.mjs';
import states from './stations-states.mjs';
import chunk from './chunk.mjs';
import overrides from './stations-overrides.mjs';
// skip stations starting with these letters
const skipStations = ['U', 'C', 'H', 'W', 'Y', 'T', 'S', 'M', 'O', 'L', 'A', 'F', 'B', 'N', 'V', 'R', 'D', 'E', 'I', 'G', 'J'];
@@ -43,12 +44,16 @@ for (let i = 0; i < chunkStates.length; i += 1) {
console.log(`Duplicate station: ${state}-${id}`);
return;
}
// get any overrides if available
const override = overrides[id] ?? {};
output[id] = {
id,
city: station.properties.name,
state,
lat: station.geometry.coordinates[1],
lon: station.geometry.coordinates[0],
// finally add the overrides
...override,
};
});
next = stations?.pagination?.next;
@@ -59,7 +64,7 @@ for (let i = 0; i < chunkStates.length; i += 1) {
while (next && stations.features.length > 0);
console.log(`Complete: ${state}`);
return true;
} catch (e) {
} catch {
console.error(`Unable to get state: ${state}`);
return false;
}

View File

@@ -89,6 +89,7 @@ const mjsSources = [
'server/scripts/modules/travelforecast.mjs',
'server/scripts/modules/progress.mjs',
'server/scripts/modules/media.mjs',
'server/scripts/modules/custom-rss-feed.mjs',
'server/scripts/index.mjs',
];

715
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "ws4kp",
"version": "5.27.0",
"version": "5.27.2",
"description": "Welcome to the WeatherStar 4000+ project page!",
"main": "index.mjs",
"type": "module",
@@ -49,7 +49,7 @@
"webpack-stream": "^7.0.0"
},
"dependencies": {
"dotenv": "^16.5.0",
"dotenv": "^17.0.1",
"ejs": "^3.1.5",
"express": "^5.1.0"
}

View File

@@ -13350,6 +13350,13 @@ const StationInfo = {
lat: 38.7578,
lon: -104.3013,
},
KAEJ: {
id: 'KAEJ',
city: 'Central Colorado Regional Airport',
state: 'CO',
lat: 38.81416,
lon: -106.12069,
},
KAFF: {
id: 'KAFF',
city: 'Air Force Academy',
@@ -13357,13 +13364,6 @@ const StationInfo = {
lat: 38.96667,
lon: -104.81667,
},
KAIB: {
id: 'KAIB',
city: 'Nucla Hopkins Field Airport',
state: 'CO',
lat: 38.23875,
lon: -108.563277,
},
KAJZ: {
id: 'KAJZ',
city: 'Delta/Blake Field Airport',
@@ -13415,7 +13415,7 @@ const StationInfo = {
},
KBJC: {
id: 'KBJC',
city: 'Broomfield / Jeffco',
city: 'Rocky Mountain Metro',
state: 'CO',
lat: 39.90085,
lon: -105.10417,

View File

@@ -114,11 +114,14 @@ class CurrentWeather extends WeatherDisplay {
const wind = (typeof this.data.WindSpeed === 'number') ? this.data.WindDirection.padEnd(3, '') + this.data.WindSpeed.toString().padStart(3, ' ') : this.data.WindSpeed;
// get location (city name) from StationInfo if available (allows for overrides)
const location = (StationInfo[this.data.station.properties.stationIdentifier]?.city ?? locationCleanup(this.data.station.properties.name)).substr(0, 20);
const fill = {
temp: this.data.Temperature + String.fromCharCode(176),
condition,
wind,
location: locationCleanup(this.data.station.properties.name).substr(0, 20),
location,
humidity: `${this.data.Humidity}%`,
dewpoint: this.data.DewPoint + String.fromCharCode(176),
ceiling: (this.data.Ceiling === 0 ? 'Unlimited' : this.data.Ceiling + this.data.CeilingUnit),

View File

@@ -133,7 +133,10 @@ const baseScreens = [
// hazards
hazards,
// station name
(data) => `Conditions at ${locationCleanup(data.station.properties.name).substr(0, 20)}`,
(data) => {
const location = (StationInfo[data.station.properties.stationIdentifier]?.city ?? locationCleanup(data.station.properties.name)).substr(0, 20);
return `Conditions at ${location}`;
},
// temperature
(data) => {

View File

@@ -64,9 +64,11 @@ const getFeed = async (url) => {
// this returns a data url
// a few sanity checks
if (rssResponse.status.content_type.indexOf('xml') < 0) return;
if (rssResponse.contents.indexOf('base64') > 100) return;
// determine return type
const isBase64 = rssResponse.status.content_type.substring(0, 8) !== 'text/xml';
// base 64 decode everything after the comma
const rss = atob(rssResponse.contents.split('base64,')[1]);
const rss = isBase64 ? atob(rssResponse.contents.split('base64,')[1]) : rssResponse.contents;
// parse the rss
const doc = parser.parseFromString(rss, 'text/xml');

35
static-env-handler.sh Normal file → Executable file
View File

@@ -4,22 +4,27 @@ set -eu
ROOT="/usr/share/nginx/html"
QS=""
# URL encode a string
url_encode() {
local string="$1"
printf '%s' "$string" | sed 's/ /%20/g; s/"/%22/g; s/</%3C/g; s/>/%3E/g; s/&/%26/g; s/#/%23/g; s/+/%2B/g'
}
# build query string from WSQS_ env vars
for var in $(env); do
case "$var" in
WSQS_*=*)
key="${var%%=*}"
val="${var#*=}"
key="${key#WSQS_}"
key="${key//_/-}"
if [ -n "$QS" ]; then
QS="$QS&${key}=${val}"
else
QS="${key}=${val}"
fi
;;
esac
done
while IFS='=' read -r key val; do
# Remove WSQS_ prefix and convert underscores to hyphens
key="${key#WSQS_}"
key="${key//_/-}"
# URL encode the value
encoded_val=$(url_encode "$val")
if [ -n "$QS" ]; then
QS="$QS&${key}=${encoded_val}"
else
QS="${key}=${encoded_val}"
fi
done << EOF
$(env | grep '^WSQS_')
EOF
if [ -n "$QS" ]; then