feat: Add Node.js script for WSPR data fetching

Co-authored-by: aider (gemini/gemini-2.5-pro) <aider@aider.chat>
This commit is contained in:
2026-04-01 12:22:51 -06:00
parent 517cf400b3
commit c7dcba0228
3 changed files with 28 additions and 140 deletions

View File

@@ -0,0 +1,24 @@
import { QuerierWsprLive } from './js/QuerierWsprLive.js';
// This function reuses your existing code to perform the same search
// as the wspr.live URL you provided.
async function fetchWsprData() {
const querier = new QuerierWsprLive();
// Parameters from your query URL:
const band = '20m';
const min = 0;
const callsign = 'VE6AZX';
const timeStart = '2026-01-06 07:00:00';
const timeEnd = ''; // An empty string means no end time
console.log("Fetching WSPR data...");
const results = await querier.SearchRegularType1(band, min, callsign, timeStart, timeEnd);
console.log(`Found ${results.length} records.`);
console.log(results);
return results;
}
fetchWsprData();

View File

@@ -6,9 +6,7 @@ See the /faq/tos page for details.
(If this generated header is stamped on a file which is a 3rd party file or under a different license or copyright, then ignore this copyright statement and use that file's terms.) (If this generated header is stamped on a file which is a 3rd party file or under a different license or copyright, then ignore this copyright statement and use that file's terms.)
*/ */
import * as utl from '/js/Utl.js'; import * as utl from './Utl.js';
import { Timeline } from '/js/Timeline.js';
// fold this functionality back into the original Event.js later // fold this functionality back into the original Event.js later
@@ -53,7 +51,7 @@ extends Event
this.AddHandler(this); this.AddHandler(this);
// timeline // timeline
this.t = t ?? new Timeline(); this.t = null;
// //
@@ -121,137 +119,3 @@ extends Event
// A class that does the work of helping components interact with the URL
// and the variables captured within the URL.
//
// Also manages browser history and gives the typical user experience of
// how history works, without page reloads.
class UrlStateProxy
extends Base
{
constructor()
{
super();
this.urlPrior = "";
window.addEventListener("popstate", (event) => {
this.DoUrlSet();
});
}
OnPageLoad()
{
this.DoUrlSet();
this.DoUrlGet();
}
DoUrlSet()
{
// capture current url and its search params, and parse
const url = new URL(window.location);
const params = new URLSearchParams(url.search);
// console.log(`window.location: ${window.location}`)
// console.log(`urlIn.origin: ${url.origin}`)
// console.log(`urlIn.pathname: ${url.pathname}`)
// console.log(`urlIn.search: ${url.search}`)
// console.log(`paramsIn : ${params.toString()}`);
// synchronously send to interested listeners
this.Emit({
type: "ON_URL_SET",
Get: (param, defaultValue) => {
return utl.GetSearchParam(param, defaultValue);
},
});
}
DoUrlGet()
{
// synchronously send to interested listeners
let paramsOut = new URLSearchParams(``);
let evt = {
type: "ON_URL_GET",
Set: (param, value) => {
paramsOut.set(param, value);
},
allowBlank: false,
};
this.Emit(evt);
const urlIn = new URL(window.location);
let paramsIn = new URLSearchParams(urlIn.search);
// filter out blank parameters unless requested not to
if (evt.allowBlank == false)
{
for (let [key, value] of Array.from(paramsOut.entries()))
{
if (value === "")
{
paramsOut.delete(key);
}
}
}
const urlOut = new URL(`${urlIn.origin}${urlIn.pathname}?${paramsOut.toString()}`);
// console.log("")
// console.log("")
// console.log(`old : ${urlIn.href}`);
// console.log(`params : ${paramsOut.toString()}`);
// console.log(`new : ${urlOut.href}`);
let paramsInSorted = new URLSearchParams(paramsIn.toString());
paramsInSorted.sort();
let pIn = paramsInSorted.toString();
let paramsOutSorted = new URLSearchParams(paramsOut.toString());
paramsOutSorted.sort();
let pOut = paramsOutSorted.toString();
let didNewHistoryEntry = false;
if (pIn != pOut)
{
// console.log("params are different, updating url and history")
// console.log(pIn)
// console.log(pOut)
history.pushState({}, "", urlOut.href);
didNewHistoryEntry = true;
}
return didNewHistoryEntry;
}
OnEvent(evt)
{
switch (evt.type) {
case "REQ_URL_GET": this.OnReqUrlGet(); break;
}
}
OnReqUrlGet()
{
// the purpose of this is to blow away the forward history when (say)
// a user clicks search, which triggers a URL re-evaluation.
let didNewHistoryEntry = this.DoUrlGet();
if (didNewHistoryEntry == false)
{
// force new history, request came in to re-evaluate, clearly
// a change has occurred.
history.pushState({}, "", window.location);
}
}
}
// global single instance
let urlStateProxy = new UrlStateProxy();

View File

@@ -6,10 +6,10 @@ See the /faq/tos page for details.
(If this generated header is stamped on a file which is a 3rd party file or under a different license or copyright, then ignore this copyright statement and use that file's terms.) (If this generated header is stamped on a file which is a 3rd party file or under a different license or copyright, then ignore this copyright statement and use that file's terms.)
*/ */
import * as utl from '/js/Utl.js'; import * as utl from './Utl.js';
import { Base } from './Base.js'; import { Base } from './Base.js';
import { WSPR } from '/js/WSPR.js'; import { WSPR } from './WSPR.js';
const QUERY_URL_BASE = 'https://db1.wspr.live/'; const QUERY_URL_BASE = 'https://db1.wspr.live/';