apps/web/src/lib/hotelBooking.ts

1import type { DirectoryPage } from './pageDirectory'
2
3type Turn = { role: 'user' | 'assistant'; text: string }
4
5/** Simple booking requests have a published answer; policy questions still use retrieval. */
6export function asksForHotelBooking(message: string, history: Turn[]): boolean {
7	const text = message.trim().replace(/’/g, "'")
8	if (
9		/^where (?:should|can) (?:I|we) stay(?: (?:for|during|at) (?:the event|UNLEASH|UNLEASH in (?:Paris|Miami)))?[?.!\s]*$/i.test(
10			text,
11		)
12	)
13		return true
14	if (
15		/^(?:are there|do you (?:have|recommend)|any|can you recommend)(?: any| some)? (?:hotels?|accommodation)[?.!\s]*$/i.test(
16			text,
17		)
18	)
19		return true
20	if (
21		/^where (?:can|should|do) (?:i|we) (?:book|find)(?: a| our| my| the)? (?:discounted |recommended )?(?:hotels?|accommodation)(?: for (?:Paris|Miami|the event))?[?.!\s]*$/i.test(
22			text,
23		)
24	)
25		return true
26	const last = history.findLast((turn) => turn.role === 'assistant')?.text || ''
27	return (
28		/^(?:what(?:'s| is)|where(?:'s| is)) the (?:hotel )?booking link[?.!\s]*$/i.test(
29			text,
30		) && /\bhotels?\b|\baccommodation\b/i.test(last)
31	)
32}
33
34export function hotelBookingReply(
35	pages: DirectoryPage[],
36	event: 'paris' | 'miami',
37): string | null {
38	const eventSlug = `/events/unleash-${event}`
39	const travel = pages.find(
40		(page) => page.url === `${eventSlug}/plan-your-visit`,
41	)
42	const booking = travel?.links.find((link) =>
43		/\bhotel\b|\baccommodation\b/i.test(link.label),
44	)
45	if (!booking || !/^https?:\/\/[^\s<>]+$/i.test(booking.url)) return null
46	return `You can book accommodation for UNLEASH in ${event === 'paris' ? 'Paris' : 'Miami'} here: [Book your hotel](<${booking.url}>).`
47}
48