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