diff --git a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/plugins/ft8.js b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/plugins/ft8.js index 1697774..68eabde 100644 --- a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/plugins/ft8.js +++ b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/plugins/ft8.js @@ -168,17 +168,35 @@ function extractAllGrids(message) { } function extractLikelyCallsign(message) { - const parts = String(message || "").toUpperCase().split(/[^A-Z0-9/]+/); - for (const token of parts) { - if (!token) continue; - if (token.length < 3 || token.length > 12) continue; - if (token === "CQ" || token === "DE" || token === "QRZ" || token === "DX") continue; - if (isMaidenheadGridToken(token)) continue; - if (/^[A-Z0-9/]{1,5}\d[A-Z0-9/]{1,6}$/.test(token)) return token; + const tokens = String(message || "") + .toUpperCase() + .split(/[^A-Z0-9/]+/) + .filter(Boolean); + if (tokens.length === 0) return null; + const head = tokens[0]; + if (head === "CQ" || head === "DE" || head === "QRZ") { + if (isLikelyCallsignToken(tokens[1])) return tokens[1]; + for (let i = 1; i < tokens.length; i += 1) { + if (isLikelyCallsignToken(tokens[i])) return tokens[i]; + } + return null; + } + // Directed messages are usually " ...". + if (isLikelyCallsignToken(tokens[0]) && isLikelyCallsignToken(tokens[1])) return tokens[1]; + for (const token of tokens) { + if (isLikelyCallsignToken(token)) return token; } return null; } +function isLikelyCallsignToken(token) { + if (!token) return false; + if (token.length < 3 || token.length > 12) return false; + if (token === "CQ" || token === "DE" || token === "QRZ" || token === "DX") return false; + if (isMaidenheadGridToken(token)) return false; + return /^[A-Z0-9/]{1,5}\d[A-Z0-9/]{1,6}$/.test(token); +} + function isFtxFarewellToken(token) { const normalized = String(token || "").trim().toUpperCase(); return normalized === "RR73" || normalized === "73" || normalized === "RR"; diff --git a/src/trx-server/src/pskreporter.rs b/src/trx-server/src/pskreporter.rs index b5c88a3..1188672 100644 --- a/src/trx-server/src/pskreporter.rs +++ b/src/trx-server/src/pskreporter.rs @@ -205,6 +205,12 @@ fn parse_sender_callsign_ft8(message: &str) -> Option { } } } + // Directed FT8/FT4-style messages are usually " ...". + if let (Some(first), Some(second)) = (tokens.first(), tokens.get(1)) { + if is_callsign(first) && is_callsign(second) { + return Some(second.clone()); + } + } tokens.into_iter().find(|t| is_callsign(t)) } @@ -441,6 +447,14 @@ mod tests { parse_sender_callsign_ft8("CQ SP2SJG JO93"), Some("SP2SJG".to_string()) ); + assert_eq!( + parse_sender_callsign_ft8("K1ABC SP2SJG JO93"), + Some("SP2SJG".to_string()) + ); + assert_eq!( + parse_sender_callsign_ft8("K1ABC SP2SJG -07"), + Some("SP2SJG".to_string()) + ); assert_eq!(parse_locator("CQ SP2SJG JO93"), Some("JO93".to_string())); assert_eq!(parse_locator("CQ SP2SJG RR73"), None); assert_eq!(parse_locator("SP2SJG RR 73"), None);