425 lines
12 KiB
TypeScript
425 lines
12 KiB
TypeScript
import * as sdk from '@botpress/sdk'
|
|
|
|
const plainTextSchema = sdk.z.object({ type: sdk.z.literal('plain_text'), text: sdk.z.string() }).strict()
|
|
const markdownSchema = sdk.z.object({ type: sdk.z.literal('mrkdwn'), text: sdk.z.string() }).strict()
|
|
const plainOrMarkdown = sdk.z.discriminatedUnion('type', [markdownSchema, plainTextSchema])
|
|
|
|
const imageElement = sdk.z
|
|
.object({
|
|
type: sdk.z.literal('image'),
|
|
image_url: sdk.z.string().describe('The full URL to the image file'),
|
|
alt_text: sdk.z.string().describe('Plain text summary of the image'),
|
|
})
|
|
.strict()
|
|
.describe('Display an image to a user')
|
|
|
|
const imageBlock = sdk.z
|
|
.object({
|
|
type: sdk.z.literal('image'),
|
|
image_url: sdk.z.string().describe('The full URL to the image file'),
|
|
alt_text: sdk.z.string().describe('Plain text summary of the image'),
|
|
title: plainTextSchema.optional(),
|
|
})
|
|
.strict()
|
|
.describe('Display an image to a user')
|
|
|
|
const buttonSchema = sdk.z
|
|
.object({
|
|
type: sdk.z.literal('button'),
|
|
action_id: sdk.z.string().describe('A unique identifier for the button'),
|
|
text: plainTextSchema,
|
|
url: sdk.z.string().optional().describe('An external URL to open when the button is clicked'),
|
|
value: sdk.z.string().optional().describe('The value to send along with the interaction payload'),
|
|
style: sdk.z
|
|
.enum(['primary', 'danger'])
|
|
.optional()
|
|
.describe('Decorates buttons with alternative visual color schemes. Leave empty for default.'),
|
|
})
|
|
.strict()
|
|
.describe('Button Block. Display a button')
|
|
|
|
const staticSelectSchema = sdk.z
|
|
.object({
|
|
type: sdk.z.literal('static_select'),
|
|
placeholder: plainTextSchema,
|
|
action_id: sdk.z.string(),
|
|
options: sdk.z.array(
|
|
sdk.z
|
|
.object({
|
|
text: plainTextSchema,
|
|
value: sdk.z.string(),
|
|
})
|
|
.strict()
|
|
),
|
|
})
|
|
.strict()
|
|
|
|
const contextBlock = sdk.z
|
|
.object({
|
|
type: sdk.z.literal('context'),
|
|
elements: sdk.z.array(sdk.z.discriminatedUnion('type', [imageElement, ...plainOrMarkdown.options])).max(10),
|
|
})
|
|
.strict()
|
|
.describe('Display multiple elements in a group')
|
|
|
|
const dividerBlock = sdk.z.object({ type: sdk.z.literal('divider') }).describe('A simple divider block')
|
|
|
|
const headerBlock = sdk.z
|
|
.object({
|
|
type: sdk.z.literal('header'),
|
|
text: plainTextSchema,
|
|
})
|
|
.strict()
|
|
.describe(
|
|
'A header is a plain-text block that displays in a larger, bold font. Use it to delineate between different groups of content in your app surface'
|
|
)
|
|
|
|
const fileBlock = sdk.z
|
|
.object({
|
|
type: sdk.z.literal('file'),
|
|
external_id: sdk.z.string(),
|
|
source: sdk.z.literal('remote'),
|
|
})
|
|
.strict()
|
|
.describe('A file block')
|
|
|
|
const radioButtonsSchema = sdk.z
|
|
.object({
|
|
type: sdk.z.literal('radio_buttons'),
|
|
options: sdk.z.array(
|
|
sdk.z
|
|
.object({
|
|
text: plainTextSchema,
|
|
value: sdk.z.string(),
|
|
})
|
|
.strict()
|
|
),
|
|
action_id: sdk.z.string(),
|
|
})
|
|
.strict()
|
|
.describe('A radio buttons block')
|
|
|
|
const checkboxesSchema = sdk.z
|
|
.object({
|
|
type: sdk.z.literal('checkboxes'),
|
|
options: sdk.z.array(
|
|
sdk.z.object({
|
|
text: plainTextSchema,
|
|
value: sdk.z.string(),
|
|
})
|
|
),
|
|
action_id: sdk.z.string(),
|
|
})
|
|
.strict()
|
|
.describe('A checkboxes block')
|
|
|
|
const overflowSchema = sdk.z
|
|
.object({
|
|
type: sdk.z.literal('overflow'),
|
|
options: sdk.z
|
|
.array(
|
|
sdk.z
|
|
.object({
|
|
text: plainTextSchema,
|
|
value: sdk.z.string().max(75),
|
|
description: plainTextSchema.optional(),
|
|
url: sdk.z
|
|
.string()
|
|
.optional()
|
|
.describe(
|
|
"A URL to load in the user's browser when the option is clicked. The url attribute is only available in overflow menus."
|
|
),
|
|
})
|
|
.strict()
|
|
)
|
|
.max(5),
|
|
action_id: sdk.z.string(),
|
|
})
|
|
.strict()
|
|
.describe('An overflow block')
|
|
|
|
const actionId = sdk.z
|
|
.string()
|
|
.max(255)
|
|
.describe(
|
|
'An identifier for the input value when the parent modal is submitted. You can use this when you receive a view_submission payload to identify the value of the input element. Should be unique among all other action_ids in the containing block. '
|
|
)
|
|
|
|
const datePickerSchema = sdk.z
|
|
.object({
|
|
type: sdk.z.literal('datepicker'),
|
|
action_id: actionId,
|
|
placeholder: plainTextSchema.optional(),
|
|
initial_date: sdk.z.string().optional(),
|
|
})
|
|
.strict()
|
|
.describe('A date picker block')
|
|
|
|
const dateTimePickerSchema = sdk.z
|
|
.object({
|
|
type: sdk.z.literal('datetimepicker'),
|
|
action_id: actionId,
|
|
initial_date_time: sdk.z
|
|
.number()
|
|
.describe(
|
|
'The initial date and time that is selected when the element is loaded, represented as a UNUIX timestamp in seconds. This should be in the format of 10 digits, for example 1628633820 represents the date and time August 10th, 2021 at 03:17pm PST'
|
|
)
|
|
.optional(),
|
|
// confirm: // TODO:
|
|
focus_on_load: sdk.z.boolean().optional(),
|
|
})
|
|
.strict()
|
|
.describe('A date picker block')
|
|
|
|
const timePickerSchema = sdk.z
|
|
.object({
|
|
type: sdk.z.literal('timepicker'),
|
|
action_id: actionId,
|
|
placeholder: plainTextSchema.optional(),
|
|
initial_time: sdk.z.string().optional(),
|
|
})
|
|
.strict()
|
|
.describe('A time picker block')
|
|
|
|
const optionSchema = sdk.z
|
|
.object({
|
|
text: plainTextSchema,
|
|
value: sdk.z.string(),
|
|
})
|
|
.strict()
|
|
|
|
const optionGroupSchema = sdk.z
|
|
.object({
|
|
label: plainTextSchema,
|
|
options: sdk.z.array(optionSchema),
|
|
})
|
|
.strict()
|
|
|
|
const multiSelectStaticMenuSchema = sdk.z
|
|
.object({
|
|
type: sdk.z.literal('multi_static_select'),
|
|
placeholder: plainTextSchema,
|
|
action_id: sdk.z.string(),
|
|
options: sdk.z.array(optionSchema).optional(),
|
|
option_groups: sdk.z.array(optionGroupSchema).optional(),
|
|
})
|
|
.strict()
|
|
.refine((obj) => !!obj.options || !!obj.option_groups, {
|
|
message: 'At least one of options or option_groups must be provided',
|
|
})
|
|
.describe('A multi-select menu block')
|
|
|
|
const conversationsSelectMenuSchema = sdk.z
|
|
.object({
|
|
type: sdk.z.literal('conversations_select'),
|
|
placeholder: plainTextSchema,
|
|
action_id: sdk.z.string(),
|
|
})
|
|
.strict()
|
|
.describe('A conversations select menu block')
|
|
|
|
const channelsSelectMenuSchema = sdk.z
|
|
.object({
|
|
type: sdk.z.literal('channels_select'),
|
|
placeholder: plainTextSchema,
|
|
action_id: sdk.z.string(),
|
|
})
|
|
.strict()
|
|
.describe('A channels select menu block')
|
|
|
|
const usersSelectMenuSchema = sdk.z
|
|
.object({
|
|
type: sdk.z.literal('users_select'),
|
|
placeholder: plainTextSchema,
|
|
action_id: sdk.z.string(),
|
|
})
|
|
.strict()
|
|
.describe('A users select menu block')
|
|
|
|
const externalSelectMenuSchema = sdk.z
|
|
.object({
|
|
type: sdk.z.literal('external_select'),
|
|
placeholder: plainTextSchema,
|
|
action_id: sdk.z.string(),
|
|
})
|
|
.strict()
|
|
.describe('An external select menu block')
|
|
|
|
const conversationsMultiSelectMenuSchema = sdk.z
|
|
.object({
|
|
type: sdk.z.literal('conversations_multi_select'),
|
|
placeholder: plainTextSchema,
|
|
action_id: sdk.z.string(),
|
|
})
|
|
.strict()
|
|
.describe('A conversations multi-select menu block')
|
|
|
|
const channelsMultiSelectMenuSchema = sdk.z
|
|
.object({
|
|
type: sdk.z.literal('channels_multi_select'),
|
|
placeholder: plainTextSchema,
|
|
action_id: sdk.z.string(),
|
|
})
|
|
.strict()
|
|
.describe('A channels multi-select menu block')
|
|
|
|
const usersMultiSelectMenuSchema = sdk.z
|
|
.object({
|
|
type: sdk.z.literal('users_multi_select'),
|
|
placeholder: plainTextSchema,
|
|
action_id: sdk.z.string(),
|
|
})
|
|
.strict()
|
|
.describe('A users multi-select menu block')
|
|
|
|
const externalMultiSelectMenuSchema = sdk.z
|
|
.object({
|
|
type: sdk.z.literal('external_multi_select'),
|
|
placeholder: plainTextSchema,
|
|
action_id: sdk.z.string(),
|
|
})
|
|
.strict()
|
|
.describe('An external multi-select menu block')
|
|
|
|
const plainTextInput = sdk.z
|
|
.object({
|
|
type: sdk.z.literal('plain_text_input'),
|
|
action_id: sdk.z
|
|
.string()
|
|
.max(255)
|
|
.describe(
|
|
'An identifier for the input value when the parent modal is submitted. You can use this when you receive a view_submission payload to identify the value of the input element. Should be unique among all other action_ids in the containing block.'
|
|
),
|
|
initial_value: sdk.z.string().describe('The initial value in the plain-text input when it is loaded.').optional(),
|
|
multiline: sdk.z
|
|
.boolean()
|
|
.optional()
|
|
.describe('Indicates whether the input will be a single line (false) or a larger textarea (true'),
|
|
min_length: sdk.z.number().min(0).max(3000).optional(),
|
|
max_length: sdk.z.number().min(0).max(3000).optional(),
|
|
focus_on_load: sdk.z.boolean().optional(),
|
|
placeholder: plainTextSchema.optional(),
|
|
// TODO: dispatch_action_config
|
|
})
|
|
.strict()
|
|
|
|
const multiSelectMenus = sdk.z.discriminatedUnion('type', [
|
|
multiSelectStaticMenuSchema.sourceType(),
|
|
externalMultiSelectMenuSchema,
|
|
usersMultiSelectMenuSchema,
|
|
conversationsMultiSelectMenuSchema,
|
|
channelsMultiSelectMenuSchema,
|
|
])
|
|
|
|
const selectMenus = sdk.z.discriminatedUnion('type', [
|
|
staticSelectSchema,
|
|
externalSelectMenuSchema,
|
|
usersSelectMenuSchema,
|
|
conversationsSelectMenuSchema,
|
|
channelsSelectMenuSchema,
|
|
])
|
|
|
|
const inputBlock = sdk.z
|
|
.object({
|
|
type: sdk.z.literal('input'),
|
|
label: plainTextSchema,
|
|
element: sdk.z.discriminatedUnion('type', [
|
|
plainTextInput,
|
|
checkboxesSchema,
|
|
radioButtonsSchema,
|
|
...selectMenus.options,
|
|
...multiSelectMenus.options,
|
|
datePickerSchema,
|
|
]),
|
|
dispatch_action: sdk.z.boolean().optional(),
|
|
block_id: sdk.z.string().max(255).optional(),
|
|
hint: plainTextSchema.optional(),
|
|
optional: sdk.z.boolean().optional(),
|
|
})
|
|
|
|
.strict()
|
|
.describe('An input block')
|
|
|
|
const sectionSchema = sdk.z
|
|
.object({
|
|
type: sdk.z.literal('section'),
|
|
text: plainOrMarkdown.optional(),
|
|
fields: sdk.z.array(plainOrMarkdown).min(1).max(10).optional(),
|
|
accessory: sdk.z
|
|
.discriminatedUnion('type', [
|
|
buttonSchema,
|
|
checkboxesSchema,
|
|
datePickerSchema,
|
|
imageElement,
|
|
overflowSchema,
|
|
radioButtonsSchema,
|
|
...multiSelectMenus.options,
|
|
...selectMenus.options,
|
|
timePickerSchema,
|
|
])
|
|
.optional(),
|
|
})
|
|
.strict()
|
|
.describe('Show a message using markdown')
|
|
|
|
const actionsBlock = sdk.z
|
|
.object({
|
|
type: sdk.z.literal('actions'),
|
|
elements: sdk.z
|
|
.array(
|
|
sdk.z.discriminatedUnion('type', [
|
|
buttonSchema,
|
|
checkboxesSchema,
|
|
datePickerSchema,
|
|
dateTimePickerSchema,
|
|
overflowSchema,
|
|
radioButtonsSchema,
|
|
...selectMenus.options,
|
|
timePickerSchema,
|
|
])
|
|
)
|
|
.max(5),
|
|
})
|
|
.describe('Display multiple elements in a group')
|
|
.strict()
|
|
|
|
const blocks = sdk.z.discriminatedUnion('type', [
|
|
actionsBlock,
|
|
contextBlock,
|
|
dividerBlock,
|
|
fileBlock,
|
|
headerBlock,
|
|
imageBlock,
|
|
inputBlock,
|
|
sectionSchema,
|
|
// video // TODO:
|
|
])
|
|
|
|
const mention = sdk.z.object({
|
|
type: sdk.z.string(),
|
|
start: sdk.z.number(), // position in string
|
|
end: sdk.z.number(),
|
|
user: sdk.z.object({
|
|
id: sdk.z.string(),
|
|
name: sdk.z.string(),
|
|
}),
|
|
})
|
|
|
|
export const textSchema = sdk.z
|
|
.object({
|
|
text: sdk.z
|
|
.string()
|
|
.describe(
|
|
'Field text must be defined but it is ignored if blocks are provided. In this situation, the text must be provided in the blocks array'
|
|
),
|
|
blocks: sdk.z
|
|
.array(blocks)
|
|
.max(50)
|
|
.optional()
|
|
.describe(
|
|
'Multiple blocks can be added to this array. If a block is provided, the text field is ignored and the text must be added as a block'
|
|
),
|
|
mentions: sdk.z.array(mention).optional(),
|
|
})
|
|
.strict()
|