chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 13:34:48 +08:00
commit 77bb5bf71f
3762 changed files with 353249 additions and 0 deletions
+209
View File
@@ -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()
+146
View File
@@ -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']
+6
View File
@@ -0,0 +1,6 @@
export * from './actions'
export * from './channels'
export * from './events'
export * from './secrets'
export * from './states'
export * from './user-tags'
+15
View File
@@ -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']
+67
View File
@@ -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']