Docker-ready Next.js + Prisma/Postgres e-invitation app: themed invite pages, RSVP, comments, share links, email + SMS invites with reply-to-RSVP-by-text, co-hosts, photo dropbox, and browser push notifications.
34 lines
1.3 KiB
TypeScript
34 lines
1.3 KiB
TypeScript
import type { RsvpStatus } from '@prisma/client';
|
|
|
|
export type ParsedSmsRsvpReply = { status: RsvpStatus; numGuests: number };
|
|
|
|
const YES_WORDS = new Set(['yes', 'y', 'yep', 'yeah', 'yup', 'ya']);
|
|
const NO_WORDS = new Set(['no', 'n', 'nope', 'nah']);
|
|
const MAYBE_WORDS = new Set(['maybe', 'perhaps', 'unsure', 'tentative', 'possibly']);
|
|
|
|
/**
|
|
* Parses a guest's free-form SMS reply into an RSVP status plus an optional
|
|
* guest count (e.g. "YES 3", "no", "Maybe, 2 people"). Only the first word is
|
|
* used to determine status - guests reply in all kinds of phrasing, but the
|
|
* status word almost always leads. Returns null when no recognized status
|
|
* word is found, so the caller can ask the guest to try again.
|
|
*/
|
|
export function parseSmsRsvpReply(rawBody: string): ParsedSmsRsvpReply | null {
|
|
const body = rawBody.trim();
|
|
if (!body) return null;
|
|
|
|
const firstWord = body.toLowerCase().match(/[a-z']+/)?.[0];
|
|
if (!firstWord) return null;
|
|
|
|
let status: RsvpStatus;
|
|
if (YES_WORDS.has(firstWord)) status = 'YES';
|
|
else if (NO_WORDS.has(firstWord)) status = 'NO';
|
|
else if (MAYBE_WORDS.has(firstWord)) status = 'MAYBE';
|
|
else return null;
|
|
|
|
const countMatch = body.match(/\d+/);
|
|
const numGuests = countMatch ? Math.min(Math.max(parseInt(countMatch[0], 10), 1), 50) : 1;
|
|
|
|
return { status, numGuests };
|
|
}
|