fix(udp): ignore N0CALL, and stop returning a grid as a callsign

N0CALL is what WSJT-X transmits under when its owner never set a callsign. It
has a letter, a digit and an ordinary shape, so nothing rejected it: it was
spotted, coloured, counted as a new WPX prefix, and now that CQ grids are read
it would have put a grid into the worked index under a callsign nobody holds.

The obvious fix - adding it to looksLikeCall's reject list - was wrong, and the
test caught it before it shipped. That function answers "could this token be a
callsign at all", and the CQ grammar uses it to decide whether the word after CQ
is a modifier (DX, NA, a zone) or the call itself. Teaching it that N0CALL is
not a callsign made "CQ N0CALL JN36" skip a slot and return JN36. Shape and
policy are different questions and now live in different functions.

Chasing that turned up the real defect behind it: ANY unrecognised word after CQ
made the parser skip a slot, and a four-character grid passes every shape test a
callsign does. "CQ FOO JN36" returned JN36 as the sender - logged, spotted and
coloured as a station. A grid in the callsign slot is now refused outright.
This commit is contained in:
2026-08-10 21:51:49 +02:00
parent 6969560efb
commit 55879809f2
5 changed files with 72 additions and 29 deletions
+12 -12
View File
@@ -37,19 +37,19 @@ func TestParseN1MMContactInfo(t *testing.T) {
t.Fatal("expected a loggable contact, got ok=false")
}
want := map[string]string{
"<call:5>VE9AA": "callsign",
"<call:5>VE9AA": "callsign",
"<qso_date:8>20240315": "date",
"<time_on:6>142530": "time",
"<band:3>20m": "band",
"<mode:2>CW": "mode",
"<freq:9>14.025000": "freq",
"<rst_sent:3>599": "rst sent",
"<rst_rcvd:3>599": "rst rcvd",
"<gridsquare:4>FN65": "grid",
"<name:4>Mike": "name",
"<stx:1>1": "stx serial",
"<srx:2>42": "srx serial",
"<eor>": "terminator",
"<time_on:6>142530": "time",
"<band:3>20m": "band",
"<mode:2>CW": "mode",
"<freq:9>14.025000": "freq",
"<rst_sent:3>599": "rst sent",
"<rst_rcvd:3>599": "rst rcvd",
"<gridsquare:4>FN65": "grid",
"<name:4>Mike": "name",
"<stx:1>1": "stx serial",
"<srx:2>42": "srx serial",
"<eor>": "terminator",
}
for sub, label := range want {
if !strings.Contains(adif, sub) {