Compare commits

...

95 Commits

Author SHA1 Message Date
Matt Walsh
4e7429bfba 5.21.10 2025-05-31 13:30:30 -05:00
Matt Walsh
c5ffe1542a TEMPORARY don't allow radar on safari on ios 2025-05-31 13:30:21 -05:00
Matt Walsh
5364855c58 5.21.9 2025-05-31 13:20:45 -05:00
Matt Walsh
18efd810bd permalink coloring, readme additions close #88 2025-05-31 13:20:35 -05:00
Matt Walsh
68a6bae3a7 5.21.8 2025-05-30 09:06:45 -05:00
Matt Walsh
5f0f0d9000 Correct smoke forecast text on extended forecast #91 2025-05-30 09:06:40 -05:00
Matt Walsh
9d9cf4b0f3 5.21.7 2025-05-30 07:58:59 -05:00
Matt Walsh
9e500143c0 load radar workers later in the startup process 2025-05-30 07:57:28 -05:00
Matt Walsh
71da682660 5.21.6 2025-05-29 23:08:11 -05:00
Matt Walsh
1b9a1dcb22 don't clobber browser alt-left/right shortcuts 2025-05-29 23:08:04 -05:00
Matt Walsh
095761ee81 5.21.5 2025-05-29 21:04:51 -05:00
Matt Walsh
21e528aaa3 fix for kiosk mode scrollbars #86 2025-05-29 21:03:48 -05:00
Matt Walsh
a92c632937 5.21.4 2025-05-29 20:24:08 -05:00
Matt Walsh
6073fd1733 better missing data handling for current conditions #87 2025-05-29 20:23:55 -05:00
Matt Walsh
5da8185633 Merge pull request #89 from kevinastone/patch-2
Gracefully shutdown on both SIGINT + SIGTERM
2025-05-29 20:02:43 -05:00
Kevin Stone
cf5c818ee3 Gracefully shutdown on both SIGINT + SIGTERM
Most service managers (systemd, docker, etc) use SIGTERM as the shutdown signal by default rather than SIGINT (which is used for interactive CTRL-C).
2025-05-29 17:37:40 -07:00
Matt Walsh
97cec114f6 Merge branch 'main' of github.com:netbymatt/ws4kp 2025-05-29 17:03:55 -05:00
Matt Walsh
7efd2e8db7 add scanlines 2025-05-29 17:03:50 -05:00
Matt Walsh
8c28f41d54 Merge pull request #85 from dylan-park/readme-patch-1
update local run instructions in README
2025-05-29 14:45:07 -05:00
Dylan Park
e9d603fbfc update local run instructions in README 2025-05-29 14:24:05 -05:00
Matt Walsh
32aa43c5b1 update user-agent header, now allowed in some browsers 2025-05-29 14:18:49 -05:00
Matt Walsh
dbc56f014a 5.21.3 2025-05-29 13:34:22 -05:00
Matt Walsh
3161a03797 fix for stale forecast data on regional forecasts #84 2025-05-29 13:32:47 -05:00
Matt Walsh
205fa77f51 5.21.2 2025-05-29 08:36:21 -05:00
Matt Walsh
28bb8f2e2a scale nav buttons on narrow screens 2025-05-29 08:36:13 -05:00
Matt Walsh
cf9a99a6ca update dependencies 2025-05-29 08:31:03 -05:00
Matt Walsh
a83afa71cd code cleanup 2025-05-29 08:30:01 -05:00
Matt Walsh
74f1abd6f8 switch to zoom scaling 2025-05-27 16:33:03 -05:00
Matt Walsh
1bd45bdeeb 5.21.1 2025-05-25 19:39:40 -05:00
Matt Walsh
232061b4d8 revert to ttf font to fix layout problems close #82 2025-05-25 19:39:25 -05:00
Matt Walsh
10d10ffbfb Merge branch 'radar-rendering' 2025-05-25 19:18:32 -05:00
Matt Walsh
25ac2059a6 remove debug timing 2025-05-25 19:11:52 -05:00
Matt Walsh
25626a98c9 5.21.0 2025-05-25 15:18:32 -05:00
Matt Walsh
002e037bbd optimized radar image merging 2025-05-25 15:17:56 -05:00
Matt Walsh
8d20f7672c radar processed in web worker 2025-05-24 16:36:41 -05:00
Matt Walsh
5567fe37a6 add instrumentation 2025-05-24 09:22:23 -05:00
Matt Walsh
2dcc33f210 change to offscreen canvas 2025-05-23 23:13:50 -05:00
Matt Walsh
8f86f80eb5 5.20.5 2025-05-23 22:15:02 -05:00
Matt Walsh
1609ab3d38 radar host overrides 2025-05-23 22:14:48 -05:00
Matt Walsh
0be23ee988 radar speed improvements 2025-05-23 21:18:54 -05:00
Matt Walsh
a3ea2c3708 5.20.4 2025-05-23 16:08:19 -05:00
Matt Walsh
09fb698350 locally limit the number of alerts/hazards 2025-05-23 16:08:11 -05:00
Matt Walsh
6f6efe801c 5.20.3 2025-05-23 15:47:27 -05:00
Matt Walsh
bc77a1891c remove limit for alert endpoint due to recent api change 2025-05-23 15:43:58 -05:00
Matt Walsh
4666878250 5.20.2 2025-05-21 13:55:39 -05:00
Matt Walsh
5813dd9a92 title overflow cleanup 2025-05-21 13:55:27 -05:00
Matt Walsh
8cb8873760 add hooks for geoip lookup 2025-05-21 13:49:49 -05:00
Matt Walsh
323c175936 css cleanup 2025-05-20 22:19:46 -05:00
Matt Walsh
85e2553cb2 5.20.1 2025-05-20 22:10:26 -05:00
Matt Walsh
101d0ac9ea page delivery tweaks 2025-05-20 22:10:13 -05:00
Matt Walsh
834d68f9e3 expose invalidate gulp taks 2025-05-20 18:26:50 -05:00
Matt Walsh
0ee7fdc9f8 Update README.md with ws3kp link 2025-05-20 18:02:25 -05:00
Matt Walsh
d75121e894 5.20.0 2025-05-20 16:29:16 -05:00
Matt Walsh
4cdced3659 prep for additional bottom line displays 2025-05-20 16:28:56 -05:00
Matt Walsh
1a5548d135 5.19.3 2025-05-16 14:42:19 -05:00
Matt Walsh
11c826a2af fix local forecast paging 2025-05-16 14:42:11 -05:00
Matt Walsh
7a129c1cd3 autocomplete cleanup 2025-05-16 11:17:35 -05:00
Matt Walsh
867657a965 5.19.2 2025-05-16 09:39:54 -05:00
Matt Walsh
e89dc52541 fix spc changing locations close #80 2025-05-16 09:39:48 -05:00
Matt Walsh
317883fc04 Add version number to bottom of page 2025-05-16 09:21:04 -05:00
Matt Walsh
a4a601a387 5.19.1 2025-05-15 22:48:44 -05:00
Matt Walsh
375812c024 better spc labeling 2025-05-15 22:48:37 -05:00
Matt Walsh
6af8b58f14 5.19.0 2025-05-15 22:29:10 -05:00
Matt Walsh
6287db7483 Merge branch 'spc-outlook' 2025-05-15 22:28:22 -05:00
Matt Walsh
46a8fa470c 5.18.1 2025-05-15 22:25:26 -05:00
Matt Walsh
8489b7e2be fix autocomplete click-away 2025-05-15 22:25:18 -05:00
Matt Walsh
7a196ac64a skip spc outlook if not in the next 3 days 2025-05-15 22:07:18 -05:00
Matt Walsh
5946ee495a initial data and graph 2025-05-15 16:04:57 -05:00
Matt Walsh
93ac03acd4 optimize gulp image uploads 2025-05-15 09:02:49 -05:00
Matt Walsh
23a0dd6870 5.18.0 2025-05-14 16:16:36 -05:00
Matt Walsh
384693688c change to structured weather icon paths 2025-05-14 16:16:20 -05:00
Matt Walsh
e2877aad77 refactor icon finding scripts 2025-05-14 15:03:35 -05:00
Matt Walsh
7fae649357 nav, header and map image cleanup 2025-05-14 14:50:02 -05:00
Matt Walsh
468e057c51 clean up gulp dependencies 2025-05-14 14:10:05 -05:00
Matt Walsh
4c65f5bc4d eslint cleanup 2025-05-14 13:55:46 -05:00
Matt Walsh
99308155d6 update test to mjs 2025-05-14 09:42:31 -05:00
Matt Walsh
cde7ceda6e update gulp html minifier 2025-05-14 09:02:08 -05:00
Matt Walsh
72938671ac spelling cleanup 2025-05-14 08:42:37 -05:00
Matt Walsh
9e1ea31262 Merge remote-tracking branch 'origin/env-variables' #79 2025-05-14 08:13:54 -05:00
Matt Walsh
e952d860dc add environment variables for default configuration 2025-05-13 23:04:46 -05:00
Matt Walsh
262ea15468 5.17.0 2025-05-13 21:13:37 -05:00
Matt Walsh
5d2e5a6d9c update versions 2025-05-13 14:59:54 -05:00
Matt Walsh
992258d3ce css/sass cleanup 2025-05-13 13:59:12 -05:00
Matt Walsh
b031934022 autocomplete working 2025-05-13 13:57:50 -05:00
Matt Walsh
4cc2312ffd Merge branch 'main' into remove-jquery 2025-05-12 13:35:01 -05:00
Matt Walsh
ce99fc16e7 5.16.6 2025-05-12 10:48:12 -05:00
Matt Walsh
97f96d4091 fix missing states in station list 2025-05-12 10:47:43 -05:00
Matt Walsh
13f08b62cc 5.16.5 2025-05-02 23:22:39 -05:00
Matt Walsh
eacd82b4f4 fix hourly graph not updating close #77 2025-05-02 23:22:24 -05:00
Matt Walsh
91f669e828 add streaming to readme 2025-05-02 10:52:32 -05:00
Matt Walsh
cdbe3d968f city spelling corrections 2025-04-29 16:38:54 -05:00
Matt Walsh
0a388cdb83 clean up settings constructor 2025-04-08 10:40:36 -05:00
Matt Walsh
8678d9f053 5.16.4 2025-04-07 22:13:33 -05:00
Matt Walsh
a592668d0d hourly color coded feels like temperatures close #69 2025-04-07 22:13:20 -05:00
Matt Walsh
c7eb56f60c non-jquery autocomplete, needs more keyboard integration 2024-10-21 23:03:34 -05:00
468 changed files with 31128 additions and 54068 deletions

View File

@@ -2,8 +2,7 @@
"env": {
"browser": true,
"es6": true,
"node": true,
"jquery": true
"node": true
},
"extends": [
"airbnb-base"
@@ -12,10 +11,12 @@
"TravelCities": "readonly",
"RegionalCities": "readonly",
"StationInfo": "readonly",
"SunCalc": "readonly"
"SunCalc": "readonly",
"NoSleep": "readonly",
"OVERRIDES": "readonly"
},
"parserOptions": {
"ecmaVersion": 2023,
"ecmaVersion": "latest",
"sourceType": "module"
},
"plugins": [],

5
.gitignore vendored
View File

@@ -11,4 +11,7 @@ server/music/*
#dist folder
dist/*
!dist/readme.txt
!dist/readme.txt
#environment variables
.env

7
.vscode/launch.json vendored
View File

@@ -15,6 +15,9 @@
"**/*.min.js",
"**/vendor/**"
],
"runtimeArgs": [
"--autoplay-policy=no-user-gesture-required"
]
},
{
"name": "Data:stations",
@@ -66,13 +69,13 @@
},
{
"name": "Test",
"program": "${workspaceFolder}/tests/index.js",
"program": "${workspaceFolder}/tests/index.mjs",
"request": "launch",
"skipFiles": [
"<node_internals>/**"
],
"type": "node",
"outputCapture": "std"
"console": "integratedTerminal"
},
],
"compounds": [

View File

@@ -1,7 +1,4 @@
{
"cSpell.enableFiletypes": [
"javascript"
],
"liveSassCompile.settings.formats": [
{
"format": "compressed",
@@ -23,7 +20,4 @@
"eslint.validate": [
"javascript"
],
"cSpell.words": [
"Tucsan"
]
}

View File

@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2020-2024 Matt Walsh
Copyright (c) 2020-2025 Matt Walsh
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -18,7 +18,7 @@ This project is based on the work of [Mike Battaglia](https://github.com/vbguyny
## Does WeatherStar 4000+ work outside of the USA?
This project is tightly coupled to [NOAA's Weather API](https://www.weather.gov/documentation/services-web-api), which is exclsuive to the United States. Using NOAA's Weather API is a crucial requirement to provide an authentic WeatherStar 4000+ experience.
This project is tightly coupled to [NOAA's Weather API](https://www.weather.gov/documentation/services-web-api), which is exclusive to the United States. Using NOAA's Weather API is a crucial requirement to provide an authentic WeatherStar 4000+ experience.
If you would like to display weather information for international locations (outside of the USA), please checkout a fork of this project created by [@mwood77](https://github.com/mwood77):
- [`ws4kp-international`](https://github.com/mwood77/ws4kp-international)
@@ -31,7 +31,7 @@ To run via Node locally:
git clone https://github.com/netbymatt/ws4kp.git
cd ws4kp
npm i
node index.js
node index.mjs
```
To run via Docker:
@@ -87,16 +87,28 @@ I've made several changes to this Weather Star 4000 simulation compared to the o
## Sharing a permalink (bookmarking)
Selected displays, the forecast city and widescreen setting are sticky from one session to the next. However if you would like to share your exact configuration or bookmark it click the "Copy Permalink" (or get "Get Parmalink") near the bottom of the page. A URL will be copied to your clipboard with all of you selected displays and location (or copy it from the page if your browser doesn't support clipboard transfers directly). You can then share this link or add it to your bookmarks.
Your permalink will be very long. Here is an example for the Orlando Internation Airport:
```
https://weatherstar.netbymatt.com/?hazards-checkbox=false&current-weather-checkbox=true&latest-observations-checkbox=true&hourly-checkbox=false&hourly-graph-checkbox=true&travel-checkbox=false&regional-forecast-checkbox=true&local-forecast-checkbox=true&extended-forecast-checkbox=true&almanac-checkbox=false&spc-outlook-checkbox=true&radar-checkbox=true&settings-wide-checkbox=false&settings-kiosk-checkbox=false&settings-scanLines-checkbox=false&settings-speed-select=1.00&settings-units-select=us&latLonQuery=Orlando+International+Airport%2C+Orlando%2C+FL%2C+USA&latLon=%7B%22lat%22%3A28.431%2C%22lon%22%3A-81.3076%7D
```
You can also build your own permalink. Any omitted settings will be filled with defaults. Here are a few examples:
```
https://weatherstar.netbymatt.com/?latLonQuery=Orlando+International+Airport
https://weatherstar.netbymatt.com/?kiosk=true
https://weatherstar.netbymatt.com/?settings-units-select=metric
```
## Kiosk mode
Kiosk mode can be activated by a checkbox on the page. Note that there is no way out of kiosk mode (except refresh or closing the browser), and the play/pause and other controls will not be available. This is deliberate as a browser's kiosk mode it intended not to be exited or significantly modified.
It's also possible to enter kiosk mode using a permalink. First generate a [Permalink](#sharing-a-permalink-bookmarking), then to the end of it add `&kiosk=true`. Opening this link will load all of the selected displays included in the Permalink, enter kiosk mode immediately upon loading and start playing the forecast.
## Wish list
## Default query string paramaters (environment variables)
When serving this via the built-in Express server, it's possible to define environment variables that direct the user to a default set of paramaters (like the [Permalink](#sharing-a-permalink-bookmarking) above). If a user requests the root page at `http://localhost:8080/` the query string provided by environment variables will be appended to the url thus providing a default configuration.
As time allows I will be working on the following enhancements.
Environment variables can be added to the command line as usual, or via a .env file which is parsed with [dotenv](https://github.com/motdotla/dotenv). Both methods have the same effect.
* Better error reporting when api.weather.gov is down (happens more often than you would think)
Environment variables that are to be added to the default query string are prefixed with `WSQS_` and then use the same key/value pairs generated by the [Permalink](#sharing-a-permalink-bookmarking) above, with the `- (dash)` character replaced by an `_ (underscore)`. For example, if you wanted to turn the travel forecast on, you would find `travel-checkbox=true` in the permalink, it's matching environment variable becomes `WSQS_travel_checkbox=true`.
## Serving static files
The app can be served as a static set of files on any web server. Run the provided gulp task to create a set of static distribution files:
@@ -108,7 +120,7 @@ The resulting files will be in the /dist folder in the root of the project. Thes
## Music
The WeatherStar had wonderful background music from the smooth jazz and new age genres by artists of the time. Lists of the music that played are available by searching online, but it's all copyrighted music and would be difficult to provide as part of this repository.
I've used AI tools to create WeatherStar-inspired music tracks that are unencumbered by copyright and are included in this repo. Too keep the size down, I've only included 4 tracks. Additional tracks will be posted in a companion repository [ws4kp-music](https://github.com/netbymatt/ws4kp-music).
I've used AI tools to create WeatherStar-inspired music tracks that are unencumbered by copyright and are included in this repo. Too keep the size down, I've only included 4 tracks. Additional tracks are in a companion repository [ws4kp-music](https://github.com/netbymatt/ws4kp-music).
### Customizing the music
Placing .mp3 files in the `/server/music` folder will override the default music included in the repo. Subdirectories will not be scanned. When weatherstar loads in the browser it will load a list if available files and randomize the order when it starts playing. On each loop through the available tracks the order will again be shuffled. If you're using the static files method to host your WeatherStar music is located in `/music`.
@@ -129,6 +141,7 @@ Thanks to the WeatherStar community for providing these discussions to further e
* [Stream as FFMPEG](https://github.com/netbymatt/ws4kp/issues/37#issuecomment-2008491948)
* [Weather like it's 1999](https://blog.scottlabs.io/2024/02/weather-like-its-1999/) Raspberry pi, streaming, music and CRT all combined into a complete solution.
* [ws4channels](https://github.com/rice9797/ws4channels) A Dockerized Node.js application to stream WeatherStar 4000 data into Channels DVR using Puppeteer and FFmpeg.
## Customization
A hook is provided as `/server/scripts/custom.js` to allow customizations to your own fork of this project, without accidentally pushing your customizations back upstream to the git repository. An sample file is provided at `/server/scripts/custom.sample.js` and should be renamed to `custom.js` activate it.
@@ -139,6 +152,14 @@ Please do not report issues with api.weather.gov being down. It's a new service
Note: not all units are converted to metric, if selected. Some text-based products such as warnings are simple text strings provided from the national weather service and thus have baked-in units such as "gusts up to 60 mph." These values will not be converted.
## Related Projects
Not retro enough? Try the [Weatherstar 3000+](https://github.com/netbymatt/ws3kp)
## Use
Linking directly to the live web site at https://weatherstar.netbymatt.com is encouraged. As is using the live site for digital signage, home dashboards, streaming and public display. Please note the disclaimer below.
## Disclaimer
This web site should NOT be used in life threatening weather situations, or be relied on to inform the public of such situations. The Internet is an unreliable network subject to server and network outages and by nature is not suitable for such mission critical use. If you require such access to NWS data, please consider one of their subscription services. The authors of this web site shall not be held liable in the event of injury, death or property damage that occur as a result of disregarding this warning.

View File

@@ -1150,7 +1150,7 @@
}
},
{
"city": "Tucsan",
"city": "Tucson",
"lat": 32.2216,
"lon": -110.9698,
"point": {

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -575,7 +575,7 @@
"lon": -77.9447
},
{
"city": "Tucsan",
"city": "Tucson",
"lat": 32.2216,
"lon": -110.9698
}

View File

@@ -9,61 +9,59 @@ import chunk from './chunk.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'];
// immediately invoked function so we can access async/await
const start = async () => {
// chunk the list of states
const chunkStates = chunk(states, 5);
// chunk the list of states
const chunkStates = chunk(states, 1);
// store output
const output = {};
// store output
const output = {};
// process all chunks
for (let i = 0; i < chunkStates.length; i += 1) {
const stateChunk = chunkStates[i];
// loop through states
// process all chunks
for (let i = 0; i < chunkStates.length; i += 1) {
const stateChunk = chunkStates[i];
// loop through states
stateChunk.forEach(async (state) => {
try {
let stations;
let next = `https://api.weather.gov/stations?state=${state}`;
do {
// get list and parse the JSON
// eslint-disable-next-line no-await-in-loop
const stationsRaw = await https(next);
stations = JSON.parse(stationsRaw);
// filter stations for 4 letter identifiers
const stationsFiltered4 = stations.features.filter((station) => station.properties.stationIdentifier.match(/^[A-Z]{4}$/));
// filter against starting letter
const stationsFiltered = stationsFiltered4.filter((station) => !skipStations.includes(station.properties.stationIdentifier.slice(0, 1)));
// add each resulting station to the output
stationsFiltered.forEach((station) => {
const id = station.properties.stationIdentifier;
if (output[id]) {
console.log(`Duplicate station: ${state}-${id}`);
return;
}
output[id] = {
id,
city: station.properties.name,
state,
lat: station.geometry.coordinates[1],
lon: station.geometry.coordinates[0],
};
});
next = stations?.pagination?.next;
// write the output
writeFileSync('./datagenerators/output/stations.json', JSON.stringify(output, null, 2));
}
while (next && stations.features.length > 0);
console.log(`Complete: ${state}`);
return true;
} catch (e) {
console.error(`Unable to get state: ${state}`);
return false;
// eslint-disable-next-line no-await-in-loop
await Promise.allSettled(stateChunk.map(async (state) => {
try {
let stations;
let next = `https://api.weather.gov/stations?state=${state}`;
let round = 0;
do {
console.log(`Getting: ${state}-${round}`);
// get list and parse the JSON
// eslint-disable-next-line no-await-in-loop
const stationsRaw = await https(next);
stations = JSON.parse(stationsRaw);
// filter stations for 4 letter identifiers
const stationsFiltered4 = stations.features.filter((station) => station.properties.stationIdentifier.match(/^[A-Z]{4}$/));
// filter against starting letter
const stationsFiltered = stationsFiltered4.filter((station) => !skipStations.includes(station.properties.stationIdentifier.slice(0, 1)));
// add each resulting station to the output
stationsFiltered.forEach((station) => {
const id = station.properties.stationIdentifier;
if (output[id]) {
console.log(`Duplicate station: ${state}-${id}`);
return;
}
output[id] = {
id,
city: station.properties.name,
state,
lat: station.geometry.coordinates[1],
lon: station.geometry.coordinates[0],
};
});
next = stations?.pagination?.next;
round += 1;
// write the output
writeFileSync('./datagenerators/output/stations.json', JSON.stringify(output, null, 2));
}
});
}
};
// immediately invoked function allows access to async
await start();
while (next && stations.features.length > 0);
console.log(`Complete: ${state}`);
return true;
} catch (e) {
console.error(`Unable to get state: ${state}`);
return false;
}
}));
}

View File

@@ -1,4 +1,5 @@
/* eslint-disable import/no-extraneous-dependencies */
import 'dotenv/config';
import {
src, dest, series, parallel,
} from 'gulp';
@@ -6,16 +7,17 @@ import concat from 'gulp-concat';
import terser from 'gulp-terser';
import ejs from 'gulp-ejs';
import rename from 'gulp-rename';
import htmlmin from 'gulp-htmlmin';
import htmlmin from 'gulp-html-minifier-terser';
import { deleteAsync } from 'del';
import s3Upload from 'gulp-s3-upload';
import s3Upload from 'gulp-s3-uploader';
import webpack from 'webpack-stream';
import TerserPlugin from 'terser-webpack-plugin';
import { readFile } from 'fs/promises';
import file from 'gulp-file';
import { CloudFrontClient, CreateInvalidationCommand } from '@aws-sdk/client-cloudfront';
import OVERRIDES from '../src/overrides.mjs';
// get cloudfront
import { CloudFrontClient, CreateInvalidationCommand } from '@aws-sdk/client-cloudfront';
import reader from '../src/playlist-reader.mjs';
const clean = () => deleteAsync(['./dist/**/*', '!./dist/readme.txt']);
@@ -32,8 +34,6 @@ const jsSourcesData = [
const webpackOptions = {
mode: 'production',
// mode: 'development',
// devtool: 'source-map',
output: {
filename: 'ws.min.js',
},
@@ -62,8 +62,6 @@ const compressJsData = () => src(jsSourcesData)
.pipe(dest(RESOURCES_PATH));
const jsVendorSources = [
'server/scripts/vendor/auto/jquery.js',
'server/scripts/vendor/jquery.autocomplete.min.js',
'server/scripts/vendor/auto/nosleep.js',
'server/scripts/vendor/auto/swiped-events.js',
'server/scripts/vendor/auto/suncalc.js',
@@ -79,6 +77,7 @@ const mjsSources = [
'server/scripts/modules/hazards.mjs',
'server/scripts/modules/currentweather.mjs',
'server/scripts/modules/almanac.mjs',
'server/scripts/modules/spc-outlook.mjs',
'server/scripts/modules/icons.mjs',
'server/scripts/modules/extendedforecast.mjs',
'server/scripts/modules/hourly.mjs',
@@ -115,6 +114,7 @@ const compressHtml = async () => {
.pipe(ejs({
production: version,
version,
OVERRIDES,
}))
.pipe(rename({ extname: '.html' }))
.pipe(htmlmin({ collapseWhitespace: true }))
@@ -140,7 +140,7 @@ const uploadSources = [
];
const upload = () => src(uploadSources, { base: './dist', encoding: false })
.pipe(s3({
Bucket: 'weatherstar',
Bucket: process.env.BUCKET,
StorageClass: 'STANDARD',
maps: {
CacheControl: (keyname) => {
@@ -154,17 +154,21 @@ const upload = () => src(uploadSources, { base: './dist', encoding: false })
const imageSources = [
'server/fonts/**',
'server/images/**',
'!server/images/gimp/**',
];
const uploadImages = () => src(imageSources, { base: './server', encoding: false })
.pipe(
s3({
Bucket: 'weatherstar',
Bucket: process.env.BUCKET,
StorageClass: 'STANDARD',
maps: {
CacheControl: () => 'max-age=31536000',
},
}),
);
const invalidate = () => cloudfront.send(new CreateInvalidationCommand({
DistributionId: 'E9171A4KV8KCW',
DistributionId: process.env.DISTRIBUTION_ID,
InvalidationBatch: {
CallerReference: (new Date()).toLocaleString(),
Paths: {
@@ -190,4 +194,5 @@ export default publishFrontend;
export {
buildDist,
invalidate,
};

View File

@@ -9,7 +9,6 @@ const vendorFiles = [
'./node_modules/luxon/build/es6/luxon.js',
'./node_modules/luxon/build/es6/luxon.js.map',
'./node_modules/nosleep.js/dist/NoSleep.js',
'./node_modules/jquery/dist/jquery.js',
'./node_modules/suncalc/suncalc.js',
'./node_modules/swiped-events/src/swiped-events.js',
];

View File

@@ -1,8 +1,9 @@
import updateVendor from './gulp/update-vendor.mjs';
import publishFrontend, { buildDist } from './gulp/publish-frontend.mjs'
import publishFrontend, { buildDist, invalidate } from './gulp/publish-frontend.mjs';
export {
updateVendor,
publishFrontend,
buildDist,
invalidate,
};

View File

@@ -1,9 +1,11 @@
import 'dotenv/config';
import express from 'express';
import fs from 'fs';
import corsPassThru from './cors/index.mjs';
import radarPassThru from './cors/radar.mjs';
import outlookPassThru from './cors/outlook.mjs';
import playlist from './src/playlist.mjs';
import OVERRIDES from './src/overrides.mjs';
const app = express();
const port = process.env.WS4KP_PORT ?? 8080;
@@ -20,23 +22,74 @@ app.get('/playlist.json', playlist);
// version
const { version } = JSON.parse(fs.readFileSync('package.json'));
// read and parse environment variables to append to the query string
// use the permalink (share) button on the web app to generate a starting point for your configuration
// then take each key/value in the querystring and append WSQS_ to the beginning, and then replace any
// hyphens with underscores in the key name
// environment variables are read from the command line and .env file via the dotenv package
const qsVars = {};
Object.entries(process.env).forEach(([key, value]) => {
// test for key matching pattern described above
if (key.match(/^WSQS_[A-Za-z0-9_]+$/)) {
// convert the key to a querystring formatted key
const formattedKey = key.replace(/^WSQS_/, '').replaceAll('_', '-');
qsVars[formattedKey] = value;
}
});
// single flag to determine if environment variables are present
const hasQsVars = Object.entries(qsVars).length > 0;
// turn the environment query string into search params
const defaultSearchParams = (new URLSearchParams(qsVars)).toString();
const index = (req, res) => {
// test for no query string in request and if environment query string values were provided
if (hasQsVars && Object.keys(req.query).length === 0) {
// redirect the user to the query-string appended url
const url = new URL(`${req.protocol}://${req.host}${req.url}`);
url.search = defaultSearchParams;
res.redirect(307, url.toString());
return;
}
// return the standard page
res.render('index', {
production: false,
version,
OVERRIDES,
});
};
const geoip = (req, res) => {
res.set({
'x-geoip-city': 'Orlando',
'x-geoip-country': 'US',
'x-geoip-country-name': 'United States',
'x-geoip-country-region': 'FL',
'x-geoip-country-region-name': 'Florida',
'x-geoip-latitude': '28.52135',
'x-geoip-longitude': '-81.41079',
'x-geoip-postal-code': '32789',
'x-geoip-time-zone': 'America/New_York',
'content-type': 'application/json',
});
res.json({});
};
// debugging
if (process.env?.DIST === '1') {
// distribution
app.use('/images', express.static('./server/images'));
app.use('/fonts', express.static('./server/fonts'));
app.use('/scripts', express.static('./server/scripts'));
app.use('/geoip', geoip);
app.use('/', express.static('./dist'));
} else {
// debugging
app.get('/index.html', index);
app.use('/geoip', geoip);
app.get('/', index);
app.get('*name', express.static('./server'));
}
@@ -46,8 +99,11 @@ const server = app.listen(port, () => {
});
// graceful shutdown
process.on('SIGINT', () => {
const gracefulShutdown = () => {
server.close(() => {
console.log('Server closed');
});
});
};
process.on('SIGINT', gracefulShutdown);
process.on('SIGTERM', gracefulShutdown);

2250
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "ws4kp",
"version": "5.16.3",
"version": "5.21.10",
"description": "Welcome to the WeatherStar 4000+ project page!",
"main": "index.mjs",
"type": "module",
@@ -32,22 +32,21 @@
"gulp-concat": "^2.6.1",
"gulp-ejs": "^5.1.0",
"gulp-file": "^0.4.0",
"gulp-htmlmin": "^5.0.1",
"gulp-rename": "^2.0.0",
"gulp-s3-upload": "^1.7.3",
"gulp-s3-uploader": "^1.0.6",
"gulp-sass": "^6.0.0",
"gulp-terser": "^2.0.0",
"jquery": "^3.6.0",
"jquery-touchswipe": "^1.6.19",
"luxon": "^3.0.0",
"nosleep.js": "^0.12.0",
"sass": "^1.54.0",
"suncalc": "^1.8.0",
"swiped-events": "^1.1.4",
"terser-webpack-plugin": "^5.3.6",
"webpack-stream": "^7.0.0"
"webpack-stream": "^7.0.0",
"gulp-html-minifier-terser": "^7.1.0"
},
"dependencies": {
"dotenv": "^16.5.0",
"ejs": "^3.1.5",
"express": "^5.1.0"
}

View File

@@ -1,30 +0,0 @@
--Star 3000--
Star3000.ttf - Standard text style for most screens (and Travel Cities title header)
Star3000 Small.ttf - Time/Date and some page headers
Star3000 Large.ttf - Travel Cities Forecast (Forecast portion only)
Star3000 Extra Large.ttf - Only used on some advertiser text
Star3000 Extended.ttf - Only used on some advertiser text
"Heavy" style is an emboldened version of the standard font (used on some STARs)
Star3000 Outline.ttf - A contrast border (stroke) that surrounds the Star3000.ttf base font. When used, must be as a text layer undeneath the base font (and is usually black in color).
Star3000 Small Outline.ttf - A contrast border (stroke) that surrounds the Star3000 Small.ttf base font. When used, must be as a text layer undeneath the base font (and is usually black in color).
Star3000 Large Outline.ttf - A contrast border (stroke) that surrounds the Star3000 Large.ttf base font. When used, must be as a text layer undeneath the base font (and is usually black in color).
***Outlines for other font styles are not currently available.
--Star 4000--
Star4000.ttf - Standard text style for zone forecast, observation tables, regional map cities, almanac, extended forecast day/weather/temperature headers, Current Conditions right half data and most page header titles (also Travel Cities title header before Nov. 1992)
Star4000 Small.ttf - Time/Date, NWS Local Update page header, temperature header for Travel Cities Forecast (after Nov. 1992)
Star4000 Large.ttf - City names and temperature data on Travel Cities Forecast (after Nov. 1992), Extended forecast temperature values (after Feb. 1991), Current Conditions temperature value (after Mar. 1991)
Star4000 Large Compressed - Travel Cities Forecast (before Nov. 1992), regional map temperatures
Star4000 Large Compressed Numbers - Temperature values on regional forecast/observation maps
Star4000 Extended - A proportional width font used for the Current Conditions present weather description and wind data
Star 4 Radar.ttf - Radar airport I.D.
--Star Jr.--
StarJr.ttf - Standard text style for most screens (and Travel Cities title header)
StarJr Small.ttf - Time/Date and some page headers
StarJr Compressed.ttf - Travel Cities Forecast

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,4 +0,0 @@
[Dolphin]
PreviewsShown=true
Timestamp=2020,10,1,21,36,7
Version=4

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 582 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 890 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 110 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 925 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 273 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 717 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 110 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 451 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 925 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 467 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 232 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 729 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 727 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Some files were not shown because too many files have changed in this diff Show More