chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,209 @@
|
||||
import * as sdk from '@botpress/sdk'
|
||||
|
||||
type Channel = 'dm' | 'channel'
|
||||
|
||||
export type Target = {
|
||||
displayName: string
|
||||
tags: { [key: string]: string }
|
||||
channel: Channel
|
||||
}
|
||||
|
||||
export const actions = {
|
||||
addReaction: {
|
||||
title: 'Add Reaction',
|
||||
description: 'Add a reaction to a message',
|
||||
input: {
|
||||
schema: sdk.z.object({
|
||||
name: sdk.z
|
||||
.string()
|
||||
.title('Reaction name')
|
||||
.describe('The name of the reaction to add, ex: thumbsup')
|
||||
.placeholder('thumbsup'),
|
||||
messageId: sdk.z.string().title('Message ID').describe('The ID of the message, ex: {{event.messageId}}'),
|
||||
}),
|
||||
},
|
||||
output: {
|
||||
schema: sdk.z.object({}),
|
||||
},
|
||||
},
|
||||
|
||||
findTarget: {
|
||||
title: 'Find Target',
|
||||
description: 'Find a target in Slack (ex: a channel, a user to send a dm, etc)',
|
||||
input: {
|
||||
schema: sdk.z.object({
|
||||
query: sdk.z
|
||||
.string()
|
||||
.min(2)
|
||||
.title('Search Query')
|
||||
.describe('What to search for, ex name of a channel, a user, etc.'),
|
||||
channel: sdk.z
|
||||
.enum(['dm', 'channel'])
|
||||
.title('Channel Name')
|
||||
.describe('Which channel to look into, ex: dm, channel'),
|
||||
}),
|
||||
},
|
||||
output: {
|
||||
schema: sdk.z.object({
|
||||
targets: sdk.z
|
||||
.array(
|
||||
sdk.z.object({
|
||||
displayName: sdk.z.string().title('Display Name').describe('The display name of the target'),
|
||||
tags: sdk.z.record(sdk.z.string()).title('Tags').describe('The tags of the target'),
|
||||
channel: sdk.z
|
||||
.enum(['dm', 'channel'])
|
||||
.title('Channel type')
|
||||
.describe('The type of channel of the target'),
|
||||
})
|
||||
)
|
||||
.title('Targets')
|
||||
.describe('The matching targets'),
|
||||
}),
|
||||
},
|
||||
},
|
||||
|
||||
retrieveMessage: {
|
||||
title: 'Retrieve Message',
|
||||
description: 'Retrieve a message from Slack',
|
||||
input: {
|
||||
schema: sdk.z.object({
|
||||
ts: sdk.z.string().title('Timestamp').describe('The timestamp of the message to retrieve'),
|
||||
channel: sdk.z.string().title('Channel').describe('The channel of the message to retrieve'),
|
||||
}),
|
||||
},
|
||||
output: {
|
||||
schema: sdk.z.object({
|
||||
type: sdk.z.string().title('Type').describe('The type of the message'),
|
||||
user: sdk.z.string().title('User').describe('The user who sent the message'),
|
||||
ts: sdk.z.string().title('Timestamp').describe('The timestamp of the message'),
|
||||
text: sdk.z.string().title('Text').describe('The text of the message'),
|
||||
}),
|
||||
},
|
||||
},
|
||||
|
||||
getOrCreateChannelConversation: {
|
||||
title: 'Get or Create Channel Conversation',
|
||||
description: 'Get or create a conversation in a channel',
|
||||
input: {
|
||||
schema: sdk.z.object({
|
||||
conversation: sdk.z.object({
|
||||
channelId: sdk.z
|
||||
.string()
|
||||
.optional()
|
||||
.title('Channel ID')
|
||||
.describe('The ID of the channel you want the conversation to be created at'),
|
||||
}),
|
||||
}),
|
||||
},
|
||||
output: {
|
||||
schema: sdk.z.object({
|
||||
conversationId: sdk.z.string().title('Conversation ID').describe('The ID of the new conversation'),
|
||||
}),
|
||||
},
|
||||
},
|
||||
|
||||
syncMembers: {
|
||||
title: 'Sync Members',
|
||||
description:
|
||||
'Sync Slack workspace members to Botpress users. This action keeps track of the last sync timestamp and will only sync updated members since the last sync.',
|
||||
input: {
|
||||
schema: sdk.z.object({}),
|
||||
},
|
||||
output: {
|
||||
schema: sdk.z.object({
|
||||
syncedCount: sdk.z.number().title('Synced Count').describe('The number of members synced'),
|
||||
}),
|
||||
},
|
||||
},
|
||||
|
||||
updateChannelTopic: {
|
||||
title: 'Update Channel Topic',
|
||||
description: 'Update the topic of a channel',
|
||||
input: {
|
||||
schema: sdk.z.object({
|
||||
topic: sdk.z.string().title('New Topic').describe('The new topic of the channel'),
|
||||
channelId: sdk.z.string().title('Channel ID').describe('The channel id of the target channel'),
|
||||
}),
|
||||
},
|
||||
output: {
|
||||
schema: sdk.z.object({}),
|
||||
},
|
||||
},
|
||||
|
||||
getChannelsInfo: {
|
||||
title: 'Get Channels Info',
|
||||
description:
|
||||
'Get information about Slack channels one page at a time. Returns channel details for the current page and a cursor for the next page.',
|
||||
input: {
|
||||
schema: sdk.z.object({
|
||||
includeArchived: sdk.z
|
||||
.boolean()
|
||||
.optional()
|
||||
.title('Include Archived')
|
||||
.describe('Whether to include archived channels in the results'),
|
||||
includePrivate: sdk.z
|
||||
.boolean()
|
||||
.optional()
|
||||
.title('Include Private')
|
||||
.describe('Whether to include private channels in the results'),
|
||||
includeDm: sdk.z
|
||||
.boolean()
|
||||
.optional()
|
||||
.title('Include Direct Messages')
|
||||
.describe('Whether to include direct messages in the results'),
|
||||
cursor: sdk.z
|
||||
.string()
|
||||
.optional()
|
||||
.title('Cursor')
|
||||
.describe('Pagination cursor for fetching the next page of channels. Omit for the first page.'),
|
||||
}),
|
||||
},
|
||||
output: {
|
||||
schema: sdk.z.object({
|
||||
channels: sdk.z
|
||||
.array(
|
||||
sdk.z.object({
|
||||
id: sdk.z.string().title('Channel ID').describe('The Slack ID of the channel'),
|
||||
name: sdk.z.string().title('Name').describe('The name of the channel'),
|
||||
topic: sdk.z.string().title('Topic').describe('The topic of the channel'),
|
||||
purpose: sdk.z.string().title('Purpose').describe('The purpose of the channel'),
|
||||
numMembers: sdk.z.number().title('Number of Members').describe('The number of members in the channel'),
|
||||
isPrivate: sdk.z.boolean().title('Is Private').describe('Whether the channel is private'),
|
||||
isArchived: sdk.z.boolean().title('Is Archived').describe('Whether the channel is archived'),
|
||||
isDm: sdk.z.boolean().title('Is DM').describe('Whether this is a direct message conversation'),
|
||||
userId: sdk.z
|
||||
.string()
|
||||
.title('User ID')
|
||||
.describe('The Slack user ID of the other participant (for 1:1 DMs)'),
|
||||
creator: sdk.z.string().title('Creator').describe('The Slack user ID of the channel creator'),
|
||||
created: sdk.z.number().title('Created').describe('The Unix timestamp of when the channel was created'),
|
||||
})
|
||||
)
|
||||
.title('Channels')
|
||||
.describe('List of channels on this page'),
|
||||
nextCursor: sdk.z
|
||||
.string()
|
||||
.title('Next Cursor')
|
||||
.describe('Cursor for the next page. Empty string if no more pages.'),
|
||||
}),
|
||||
},
|
||||
},
|
||||
|
||||
getUserProfile: {
|
||||
title: 'Get User Profile',
|
||||
description: 'Get information about a user',
|
||||
input: {
|
||||
schema: sdk.z.object({
|
||||
userId: sdk.z.string().title('User ID').describe('The ID of the user to retrieve information about'),
|
||||
}),
|
||||
},
|
||||
output: {
|
||||
schema: sdk.z.object({
|
||||
firstName: sdk.z.string().optional().title('Firstname').describe('The first name of the user'),
|
||||
lastName: sdk.z.string().optional().title('Lastname').describe('The last name of the user'),
|
||||
email: sdk.z.string().optional().title('Email').describe('The email of the user'),
|
||||
displayName: sdk.z.string().optional().title('Display Name').describe('The display name of the user'),
|
||||
}),
|
||||
},
|
||||
},
|
||||
} as const satisfies sdk.IntegrationDefinitionProps['actions']
|
||||
@@ -0,0 +1,86 @@
|
||||
import * as sdk from '@botpress/sdk'
|
||||
import { textSchema } from './text-input-schema'
|
||||
|
||||
const messages = {
|
||||
...sdk.messages.defaults,
|
||||
text: {
|
||||
schema: textSchema,
|
||||
},
|
||||
bloc: sdk.messages.markdownBloc,
|
||||
} as const satisfies sdk.ChannelDefinition['messages']
|
||||
|
||||
const conversationTags = {
|
||||
id: {
|
||||
title: 'ID',
|
||||
description: 'The Slack ID of the conversation',
|
||||
},
|
||||
title: {
|
||||
title: 'Title',
|
||||
description: 'The title of the conversation',
|
||||
},
|
||||
} as const satisfies Record<string, Required<sdk.TagDefinition>>
|
||||
|
||||
const messageTags = {
|
||||
ts: {
|
||||
title: 'Timestamp',
|
||||
description: 'The timestamp of the message',
|
||||
},
|
||||
userId: {
|
||||
title: 'User ID',
|
||||
description: 'The Slack ID of the user who sent the message',
|
||||
},
|
||||
channelId: {
|
||||
title: 'Channel ID',
|
||||
description: 'The Slack ID of the channel where the message was sent',
|
||||
},
|
||||
mentionsBot: {
|
||||
title: 'Mentions Bot?',
|
||||
description: 'Whether the message mentions the Slack App bot',
|
||||
},
|
||||
forkedToThread: {
|
||||
title: 'Forked to Thread?',
|
||||
description: 'Whether the message created a thread',
|
||||
},
|
||||
} as const satisfies Record<string, Required<sdk.TagDefinition>>
|
||||
|
||||
export const channels = {
|
||||
channel: {
|
||||
title: 'Channel',
|
||||
description: 'A general channel',
|
||||
messages,
|
||||
message: { tags: messageTags },
|
||||
conversation: {
|
||||
tags: { ...conversationTags },
|
||||
},
|
||||
},
|
||||
|
||||
dm: {
|
||||
title: 'Direct Message',
|
||||
description: 'A direct message channel',
|
||||
messages,
|
||||
message: { tags: messageTags },
|
||||
conversation: {
|
||||
tags: { ...conversationTags },
|
||||
},
|
||||
},
|
||||
|
||||
thread: {
|
||||
title: 'Thread',
|
||||
description: 'A thread inside a channel',
|
||||
messages,
|
||||
message: { tags: messageTags },
|
||||
conversation: {
|
||||
tags: {
|
||||
...conversationTags,
|
||||
thread: {
|
||||
title: 'Thread ID',
|
||||
description: 'The Slack ID of the thread',
|
||||
},
|
||||
isBotReplyThread: {
|
||||
title: 'Is Bot Reply Thread?',
|
||||
description: 'Whether the thread is a bot reply thread',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
} as const satisfies sdk.IntegrationDefinitionProps['channels']
|
||||
@@ -0,0 +1 @@
|
||||
export * from './channels'
|
||||
@@ -0,0 +1,424 @@
|
||||
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()
|
||||
@@ -0,0 +1,146 @@
|
||||
import * as sdk from '@botpress/sdk'
|
||||
|
||||
export const events = {
|
||||
reactionAdded: {
|
||||
title: 'Reaction Added',
|
||||
description: 'Triggered when a reaction is added to a message',
|
||||
schema: sdk.z.object({
|
||||
reaction: sdk.z.string().title('Reaction').describe('The reaction that was added'),
|
||||
userId: sdk.z.string().optional().title('User ID').describe('The ID of the user who added the reaction'),
|
||||
conversationId: sdk.z.string().optional().title('Conversation ID').describe('The ID of the conversation'),
|
||||
targets: sdk.z
|
||||
.object({
|
||||
dm: sdk.z.record(sdk.z.string()).optional().title('DMs').describe('The DMs targeted by the reaction'),
|
||||
channel: sdk.z
|
||||
.record(sdk.z.string())
|
||||
.optional()
|
||||
.title('Channels')
|
||||
.describe('The channels targeted by the reaction'),
|
||||
thread: sdk.z
|
||||
.record(sdk.z.string())
|
||||
.optional()
|
||||
.title('Threads')
|
||||
.describe('The threads targeted by the reaction'),
|
||||
})
|
||||
.title('Targets')
|
||||
.describe('The targets of the reaction'),
|
||||
}),
|
||||
},
|
||||
|
||||
reactionRemoved: {
|
||||
title: 'Reaction Removed',
|
||||
description: 'Triggered when a reaction is removed from a message',
|
||||
schema: sdk.z.object({
|
||||
reaction: sdk.z.string().title('Reaction').describe('The reaction that was removed'),
|
||||
userId: sdk.z.string().optional().title('User ID').describe('The ID of the user who removed the reaction'),
|
||||
conversationId: sdk.z.string().optional().title('Conversation ID').describe('The ID of the conversation'),
|
||||
targets: sdk.z
|
||||
.object({
|
||||
dm: sdk.z.record(sdk.z.string()).optional(),
|
||||
channel: sdk.z.record(sdk.z.string()).optional(),
|
||||
thread: sdk.z.record(sdk.z.string()).optional(),
|
||||
})
|
||||
.title('Targets')
|
||||
.describe('The targets of the reaction'),
|
||||
}),
|
||||
},
|
||||
|
||||
memberJoinedWorkspace: {
|
||||
title: 'Member Joined Workspace',
|
||||
description: 'Triggered when a member joins the workspace',
|
||||
schema: sdk.z.object({
|
||||
userId: sdk.z.string().title('Botpress ID').describe('The Botpress ID of the user who joined the workspace'),
|
||||
target: sdk.z
|
||||
.object({
|
||||
userId: sdk.z.string().title('Slack ID').describe('The Slack ID of the user who joined the workspace'),
|
||||
userName: sdk.z.string().title('Username').describe('The username of the user who joined the workspace'),
|
||||
userRealName: sdk.z
|
||||
.string()
|
||||
.title('Real name')
|
||||
.describe('The real name of the user who joined the workspace'),
|
||||
userDisplayName: sdk.z
|
||||
.string()
|
||||
.title('Display name')
|
||||
.describe('The display name of the user who joined the workspace'),
|
||||
})
|
||||
.title('Target')
|
||||
.describe('Slack user who joined the workspace'),
|
||||
}),
|
||||
},
|
||||
|
||||
memberJoinedChannel: {
|
||||
title: 'Member Joined Channel',
|
||||
description: 'Triggered when a member joins a channel',
|
||||
schema: sdk.z.object({
|
||||
botpressUserId: sdk.z
|
||||
.string()
|
||||
.title('Botpress user ID')
|
||||
.describe('The Botpress ID of the user who joined the channel'),
|
||||
botpressConversationId: sdk.z
|
||||
.string()
|
||||
.title('Botpress Channel ID')
|
||||
.describe('The Botpress ID of the channel the user joined'),
|
||||
inviterBotpressUserId: sdk.z
|
||||
.string()
|
||||
.optional()
|
||||
.title('Botpress Inviter User ID')
|
||||
.describe('The Botpress ID of the user who invited the new member'),
|
||||
targets: sdk.z
|
||||
.object({
|
||||
slackUserId: sdk.z
|
||||
.string()
|
||||
.title('Slack User ID')
|
||||
.describe('The Slack ID of the user who joined the channel'),
|
||||
slackChannelId: sdk.z
|
||||
.string()
|
||||
.title('Slack Channel ID')
|
||||
.describe('The Slack ID of the channel the user joined'),
|
||||
slackInviterId: sdk.z
|
||||
.string()
|
||||
.optional()
|
||||
.title('Slack Inviter ID')
|
||||
.describe('The Slack ID of the user who invited the new member'),
|
||||
})
|
||||
.title('Targets')
|
||||
.describe('Slack IDs of the user, channel and inviter'),
|
||||
}),
|
||||
},
|
||||
|
||||
memberLeftChannel: {
|
||||
title: 'Member Left Channel',
|
||||
description: 'Triggered when a member leaves a channel',
|
||||
schema: sdk.z.object({
|
||||
botpressUserId: sdk.z
|
||||
.string()
|
||||
.title('Botpress user ID')
|
||||
.describe('The Botpress ID of the user who left the channel'),
|
||||
botpressConversationId: sdk.z
|
||||
.string()
|
||||
.title('Botpress Channel ID')
|
||||
.describe('The Botpress ID of the channel the user left'),
|
||||
targets: sdk.z
|
||||
.object({
|
||||
slackUserId: sdk.z.string().title('Slack User ID').describe('The Slack ID of the user who left the channel'),
|
||||
slackChannelId: sdk.z
|
||||
.string()
|
||||
.title('Slack Channel ID')
|
||||
.describe('The Slack ID of the channel the user left'),
|
||||
})
|
||||
.title('Targets')
|
||||
.describe('Slack IDs of the user and channel'),
|
||||
}),
|
||||
},
|
||||
|
||||
workflowWebhook: {
|
||||
title: 'Workflow Webhook',
|
||||
description: 'Triggered when the workflow webhook is triggered',
|
||||
schema: sdk.z.object({
|
||||
value: sdk.z.any().title('Value').describe('The value of the workflow webhook'),
|
||||
userId: sdk.z
|
||||
.string()
|
||||
.optional()
|
||||
.title('Slack User ID')
|
||||
.describe('The Slack ID of the user who triggered the workflow'),
|
||||
}),
|
||||
},
|
||||
} as const satisfies sdk.IntegrationDefinitionProps['events']
|
||||
@@ -0,0 +1,6 @@
|
||||
export * from './actions'
|
||||
export * from './channels'
|
||||
export * from './events'
|
||||
export * from './secrets'
|
||||
export * from './states'
|
||||
export * from './user-tags'
|
||||
@@ -0,0 +1,15 @@
|
||||
import * as sdk from '@botpress/sdk'
|
||||
|
||||
export const secrets = {
|
||||
CLIENT_ID: {
|
||||
description: 'The client ID of your Slack OAuth app.',
|
||||
},
|
||||
|
||||
CLIENT_SECRET: {
|
||||
description: 'The client secret of your Slack OAuth app.',
|
||||
},
|
||||
|
||||
SIGNING_SECRET: {
|
||||
description: 'The signing secret of your Slack OAuth app used to verify requests signature.',
|
||||
},
|
||||
} as const satisfies sdk.IntegrationDefinitionProps['secrets']
|
||||
@@ -0,0 +1,67 @@
|
||||
import * as sdk from '@botpress/sdk'
|
||||
|
||||
export const states = {
|
||||
sync: {
|
||||
type: 'integration',
|
||||
schema: sdk.z.object({
|
||||
usersLastSyncTs: sdk.z
|
||||
.number()
|
||||
.optional()
|
||||
.title('Users Last Sync Timestamp')
|
||||
.describe('The timestamp of the last sync'),
|
||||
}),
|
||||
},
|
||||
|
||||
/** @deprecated - Remove this once we're confident nobody has long-lived access tokens anymore */
|
||||
credentials: {
|
||||
type: 'integration',
|
||||
schema: sdk.z.object({
|
||||
accessToken: sdk.z.string().secret().title('Long-lived access token').describe('The Bot User OAuth Token'),
|
||||
signingSecret: sdk.z.string().secret().title('Unused signing secret').describe('The Slack Signing Secret'),
|
||||
}),
|
||||
},
|
||||
|
||||
oAuthCredentialsV2: {
|
||||
type: 'integration',
|
||||
schema: sdk.z.object({
|
||||
shortLivedAccessToken: sdk.z
|
||||
.object({
|
||||
currentAccessToken: sdk.z.string().secret().describe('The Bot User OAuth Access Token'),
|
||||
issuedAt: sdk.z.string().datetime().describe('The timestamp of when the access token was issued'),
|
||||
expiresAt: sdk.z.string().datetime().describe('The timestamp of when the access token expires'),
|
||||
})
|
||||
.title('Short-lived access token')
|
||||
.describe('Access token that expires after 12 hours'),
|
||||
rotatingRefreshToken: sdk.z
|
||||
.object({
|
||||
token: sdk.z.string().secret().describe('The Bot User OAuth Refresh Token'),
|
||||
issuedAt: sdk.z.string().datetime().describe('The timestamp of when the refresh token was issued'),
|
||||
})
|
||||
.title('Rotating refresh token')
|
||||
.describe('Refresh token that does not expire but can be used only once to get a new access token'),
|
||||
grantedScopes: sdk.z.array(sdk.z.string()).title('Scopes').describe('The scopes granted to the token'),
|
||||
botUserId: sdk.z.string().title('Slack bot user').describe('The ID of the Slack bot user'),
|
||||
teamId: sdk.z.string().title('Slack workspace').describe('The ID of the Slack team'),
|
||||
// Allows re-registering the integration with a revoked refresh token if it hasn't changed:
|
||||
originalRefreshToken: sdk.z
|
||||
.string()
|
||||
.optional()
|
||||
.title('Original refresh token')
|
||||
.describe('The now-revoked refresh token that was used to set up the integration'),
|
||||
}),
|
||||
},
|
||||
appCredentials: {
|
||||
type: 'integration',
|
||||
schema: sdk.z.object({
|
||||
clientId: sdk.z.string().optional().title('Client ID').describe('OAuth Client ID'),
|
||||
clientSecret: sdk.z.string().secret().optional().title('Client Secret').describe('OAuth Client Secret'),
|
||||
signingSecret: sdk.z.string().secret().optional().title('Signing Secret').describe('The Slack Signing Secret'),
|
||||
appConfigurationRefreshToken: sdk.z
|
||||
.string()
|
||||
.secret()
|
||||
.optional()
|
||||
.title('App Configuration Refresh Token')
|
||||
.describe('Generated from api.slack.com/apps, used for manifest-based setup'),
|
||||
}),
|
||||
},
|
||||
} as const satisfies sdk.IntegrationDefinitionProps['states']
|
||||
@@ -0,0 +1,91 @@
|
||||
import * as sdk from '@botpress/sdk'
|
||||
|
||||
export const user = {
|
||||
tags: {
|
||||
dm_conversation_id: {
|
||||
title: 'DM Conversation ID',
|
||||
description:
|
||||
'The ID of the conversation used to DM the user (created by calling the `startDmConversation` action)',
|
||||
},
|
||||
id: {
|
||||
title: 'ID',
|
||||
description: 'The Slack ID of the user (U0000XXXXXX)',
|
||||
},
|
||||
tz: {
|
||||
title: 'Timezone',
|
||||
description: 'The timezone of the user',
|
||||
},
|
||||
is_bot: {
|
||||
title: 'Is a bot',
|
||||
description: 'Whether the user is a bot',
|
||||
},
|
||||
is_admin: {
|
||||
title: 'Is an admin',
|
||||
description: 'Whether the user is an admin',
|
||||
},
|
||||
title: {
|
||||
title: 'Profile title',
|
||||
description: "The on the user's profile",
|
||||
},
|
||||
phone: {
|
||||
title: 'Phone number',
|
||||
description: 'The phone number of the user',
|
||||
},
|
||||
email: {
|
||||
title: 'Email',
|
||||
description: 'The email address of the user',
|
||||
},
|
||||
real_name: {
|
||||
title: 'Real name',
|
||||
description: 'The real name of the user',
|
||||
},
|
||||
display_name: {
|
||||
title: 'Display name',
|
||||
description: 'The display name of the user',
|
||||
},
|
||||
real_name_normalized: {
|
||||
title: 'Normalized real name',
|
||||
description: 'The normalized real name of the user',
|
||||
},
|
||||
display_name_normalized: {
|
||||
title: 'Normalized display name',
|
||||
description: 'The normalized display name of the user',
|
||||
},
|
||||
avatar_hash: {
|
||||
title: 'Avatar hash code',
|
||||
description: "A hashed representation of the user avatar's avatar",
|
||||
},
|
||||
status_text: {
|
||||
title: 'Status text',
|
||||
description: 'The status text of the user',
|
||||
},
|
||||
status_emoji: {
|
||||
title: 'Status emoji',
|
||||
description: 'The status emoji of the user',
|
||||
},
|
||||
image_24: {
|
||||
title: 'Avatar x24',
|
||||
description: 'The URL of the user avatar (24x24)',
|
||||
},
|
||||
image_48: {
|
||||
title: 'Avatar x48',
|
||||
description: 'The URL of the user avatar (48x48)',
|
||||
},
|
||||
image_192: {
|
||||
title: 'Avatar x192',
|
||||
description: 'The URL of the user avatar (192x192)',
|
||||
},
|
||||
image_512: {
|
||||
title: 'Avatar x512',
|
||||
description: 'The URL of the user avatar (512x512)',
|
||||
},
|
||||
image_1024: {
|
||||
title: 'Avatar x1024',
|
||||
description: 'The URL of the user avatar (1024x1024)',
|
||||
},
|
||||
team: {
|
||||
title: 'Team',
|
||||
description: 'The Slack ID of the team (T0000XXXXXX)',
|
||||
},
|
||||
},
|
||||
} as const satisfies sdk.IntegrationDefinitionProps['user']
|
||||
Reference in New Issue
Block a user