Files
swyxweb/frontend/src/calls.ts
T

61 lines
2.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { CallEvent } from './swyx/protocol'
/** Ein gespeicherter eingehender Anruf aus GET /api/calls. */
export interface StoredCall {
id: string
receivedAt: string
line: number | null
peer: string | null
peerNumber: string | null
peerName: string | null
}
export async function fetchIncomingCalls(signal?: AbortSignal): Promise<StoredCall[]> {
const response = await fetch('/api/calls', { signal, cache: 'no-store' })
if (!response.ok) {
throw new Error(`Anrufhistorie nicht abrufbar (HTTP ${response.status}).`)
}
return (await response.json()) as StoredCall[]
}
/** Ältere Snapshots enthalten die Rufnummer teilweise nur in der Anzeigeform. */
export function callerNumber(call: StoredCall): string | null {
const number = call.peerNumber?.trim()
if (number) return number
const peer = call.peer?.trim() ?? ''
const candidate = peer.match(/\(([^()]+)\)$/)?.[1] ?? peer
return /^[+\d][\d\s()/.-]*$/.test(candidate) ? candidate : null
}
export function matchesCall(call: StoredCall, query: string): boolean {
const wanted = query.trim().toLocaleLowerCase('de')
if (!wanted) return true
const text = [callerNumber(call), call.peerName, call.peer].filter(Boolean).join(' ')
if (text.toLocaleLowerCase('de').includes(wanted)) return true
// Rufnummern auch ohne die Leerzeichen/Klammern ihrer Anzeigeform finden.
const digits = wanted.replace(/\D/g, '')
return /^[+\d\s()/.-]+$/.test(wanted) && digits.length > 0 &&
(callerNumber(call)?.replace(/\D/g, '').includes(digits) ?? false)
}
/**
* Meldet Anruf-Ereignisse an das Backend, das sie in der MongoDB ablegt.
*
* Die Ereignisse entstehen nur hier im Browser (aus dem Vergleich zweier
* SwyxTray-Snapshots); das Backend sieht die WebSocket-Verbindung nicht.
* Fire-and-forget: Ist das Backend nicht erreichbar, läuft die Anzeige
* unverändert weiter – die Speicherung ist Beiwerk, nicht Voraussetzung.
*/
export function reportCallEvents(events: CallEvent[]): void {
if (events.length === 0) return
void fetch('/api/calls', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(events),
// Auch beim Schließen des Tabs noch absetzen, z. B. das "ended" beim Auflegen.
keepalive: true,
}).catch((e: unknown) => {
console.warn('Anrufdaten nicht an das Backend gemeldet:', e)
})
}