2
0
Files
bot/packages/schemas/features/whatsapp.ts

224 lines
5.0 KiB
TypeScript
Raw Normal View History

import { z } from '../zod'
import { credentialsBaseSchema } from './blocks/shared'
import {
ComparisonOperators,
LogicalOperator,
} from './blocks/logic/condition/constants'
const mediaSchema = z.object({ link: z.string() })
const headerSchema = z
.object({
type: z.literal('image'),
image: mediaSchema,
})
.or(
z.object({
type: z.literal('video'),
video: mediaSchema,
})
)
.or(
z.object({
type: z.literal('text'),
text: z.string(),
})
)
const bodySchema = z.object({
text: z.string(),
})
const actionSchema = z.object({
buttons: z.array(
z.object({
type: z.literal('reply'),
reply: z.object({ id: z.string(), title: z.string() }),
})
),
})
const templateSchema = z.object({
name: z.string(),
language: z.object({
code: z.string(),
}),
})
const interactiveSchema = z.object({
type: z.literal('button'),
header: headerSchema.optional(),
body: bodySchema.optional(),
action: actionSchema,
})
// https://developers.facebook.com/docs/whatsapp/cloud-api/reference/messages#message-object
const sendingMessageSchema = z.discriminatedUnion('type', [
z.object({
type: z.literal('text'),
text: z.object({
body: z.string(),
preview_url: z.boolean().optional(),
}),
}),
z.object({
type: z.literal('image'),
image: mediaSchema,
}),
z.object({
type: z.literal('audio'),
audio: mediaSchema,
}),
z.object({
type: z.literal('video'),
video: mediaSchema,
}),
z.object({
type: z.literal('interactive'),
interactive: interactiveSchema,
}),
z.object({
type: z.literal('template'),
template: templateSchema,
}),
])
export const incomingMessageSchema = z.discriminatedUnion('type', [
z.object({
from: z.string(),
type: z.literal('text'),
text: z.object({
body: z.string(),
}),
timestamp: z.string(),
}),
z.object({
from: z.string(),
type: z.literal('button'),
button: z.object({
text: z.string(),
payload: z.string(),
}),
timestamp: z.string(),
}),
z.object({
from: z.string(),
type: z.literal('interactive'),
interactive: z.object({
button_reply: z.object({
id: z.string(),
title: z.string(),
}),
}),
timestamp: z.string(),
}),
z.object({
from: z.string(),
type: z.literal('image'),
image: z.object({ id: z.string() }),
timestamp: z.string(),
}),
z.object({
from: z.string(),
type: z.literal('video'),
video: z.object({ id: z.string() }),
timestamp: z.string(),
}),
z.object({
from: z.string(),
type: z.literal('audio'),
audio: z.object({ id: z.string() }),
timestamp: z.string(),
}),
z.object({
from: z.string(),
type: z.literal('document'),
document: z.object({ id: z.string() }),
timestamp: z.string(),
}),
z.object({
from: z.string(),
type: z.literal('location'),
location: z.object({
latitude: z.number(),
longitude: z.number(),
}),
timestamp: z.string(),
}),
])
export const whatsAppWebhookRequestBodySchema = z.object({
entry: z.array(
z.object({
changes: z.array(
z.object({
value: z.object({
metadata: z.object({
phone_number_id: z.string(),
}),
contacts: z
.array(
z.object({
profile: z.object({
name: z.string(),
}),
})
)
.optional(),
messages: z.array(incomingMessageSchema).optional(),
}),
})
),
})
),
})
:zap: Introduce a new high-performing standalone chat API (#1200) Closes #1154 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Added authentication functionality for user sessions in chat API. - Introduced chat-related API endpoints for starting, previewing, and continuing chat sessions, and streaming messages. - Implemented WhatsApp API webhook handling for receiving and processing messages. - Added environment variable `NEXT_PUBLIC_CHAT_API_URL` for chat API URL configuration. - **Bug Fixes** - Adjusted file upload logic to correctly determine the API host. - Fixed message streaming URL in chat integration with OpenAI. - **Documentation** - Updated guides for creating blocks, local installation, self-hosting, and deployment to use `bun` instead of `pnpm`. - **Refactor** - Refactored chat API functionalities to use modular architecture. - Simplified client log saving and session update functionalities by using external functions. - Transitioned package management and workflow commands to use `bun`. - **Chores** - Switched to `bun` for package management in Dockerfiles and GitHub workflows. - Added new Dockerfile for chat API service setup with Bun framework. - Updated `.prettierignore` and documentation with new commands. - **Style** - No visible changes to end-users. - **Tests** - No visible changes to end-users. - **Revert** - No reverts in this release. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
2024-03-21 10:23:23 +01:00
export type WhatsAppWebhookRequestBody = z.infer<
typeof whatsAppWebhookRequestBodySchema
>
export const whatsAppCredentialsSchema = z
.object({
type: z.literal('whatsApp'),
data: z.object({
systemUserAccessToken: z.string(),
phoneNumberId: z.string(),
}),
})
.merge(credentialsBaseSchema)
const whatsAppComparisonSchema = z.object({
id: z.string(),
comparisonOperator: z.nativeEnum(ComparisonOperators).optional(),
value: z.string().optional(),
})
export type WhatsAppComparison = z.infer<typeof whatsAppComparisonSchema>
const startConditionSchema = z.object({
logicalOperator: z.nativeEnum(LogicalOperator),
comparisons: z.array(
z.object({
id: z.string(),
comparisonOperator: z.nativeEnum(ComparisonOperators).optional(),
value: z.string().optional(),
})
),
})
export const whatsAppSettingsSchema = z.object({
isEnabled: z.boolean().optional(),
startCondition: startConditionSchema.optional(),
sessionExpiryTimeout: z
.number()
.max(48)
.min(0.01)
.optional()
.describe('Expiration delay in hours after latest interaction'),
})
export const defaultSessionExpiryTimeout = 4
export type WhatsAppIncomingMessage = z.infer<typeof incomingMessageSchema>
export type WhatsAppSendingMessage = z.infer<typeof sendingMessageSchema>
export type WhatsAppCredentials = z.infer<typeof whatsAppCredentialsSchema>