chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
import sdk, { z } from '@botpress/sdk'
|
||||
import { Task, Project, Section, SharedLabel } from './entities'
|
||||
|
||||
export const actions = {
|
||||
changeTaskPriority: {
|
||||
title: 'Change Task Priority',
|
||||
description: 'Change the priority of a task',
|
||||
input: {
|
||||
schema: z.object({
|
||||
taskId: Task.schema.shape.id,
|
||||
priority: Task.schema.shape.priority,
|
||||
}),
|
||||
},
|
||||
output: {
|
||||
schema: z.object({}),
|
||||
},
|
||||
},
|
||||
getTaskId: {
|
||||
title: 'Get Task ID',
|
||||
description: 'Get the ID of the first task matching the given name',
|
||||
input: {
|
||||
schema: z.object({
|
||||
name: z.string().title('Name').describe('The name of the task to search for'),
|
||||
// NOTE: this actually refers to the `content` property of the Task
|
||||
// entity: the `name` property does not exist
|
||||
}),
|
||||
},
|
||||
output: {
|
||||
schema: z.object({
|
||||
taskId: Task.schema.shape.id.nullable(),
|
||||
}),
|
||||
},
|
||||
},
|
||||
getProjectId: {
|
||||
title: 'Get Project ID',
|
||||
description: 'Get the ID of the project',
|
||||
input: {
|
||||
schema: z.object({
|
||||
name: Project.schema.shape.name,
|
||||
}),
|
||||
},
|
||||
output: {
|
||||
schema: z.object({
|
||||
projectId: Project.schema.shape.id.nullable(),
|
||||
}),
|
||||
},
|
||||
},
|
||||
getAllProjects: {
|
||||
title: 'Get All Projects',
|
||||
description: 'Get all projects',
|
||||
input: {
|
||||
schema: z.object({}),
|
||||
},
|
||||
output: {
|
||||
schema: z.object({
|
||||
projects: z.array(Project.schema).title('Projects').describe('All projects that are available to the user'),
|
||||
}),
|
||||
},
|
||||
},
|
||||
getAllSections: {
|
||||
title: 'Get All Sections',
|
||||
description: 'Get all sections in a project',
|
||||
input: {
|
||||
schema: z.object({
|
||||
projectId: Project.schema.shape.id
|
||||
.optional()
|
||||
.title('Project ID (optional)')
|
||||
.describe('The ID of the project. If omitted, the sections of all projects will be returned.'),
|
||||
}),
|
||||
},
|
||||
output: {
|
||||
schema: z.object({
|
||||
sections: z
|
||||
.array(Section.schema)
|
||||
.title('Sections')
|
||||
.describe('All sections in the project, or all sections in all projects if projectId is omitted'),
|
||||
}),
|
||||
},
|
||||
},
|
||||
getAllTasks: {
|
||||
title: 'Get All Tasks',
|
||||
description: 'Find tasks using optional filters',
|
||||
input: {
|
||||
schema: z.object({
|
||||
projectId: Project.schema.shape.id
|
||||
.optional()
|
||||
.title('Filter by Project ID (optional)')
|
||||
.describe('The ID of the project. If omitted, tasks from all projects will be included in the results.'),
|
||||
sectionId: Section.schema.shape.id
|
||||
.optional()
|
||||
.title('Filter by Section ID (optional)')
|
||||
.describe('The ID of the section. If omitted, tasks from all sections will be included in the results.'),
|
||||
labelName: SharedLabel.schema.shape.name
|
||||
.optional()
|
||||
.title('Filter by Label Name (optional)')
|
||||
.describe('The name of the label. If omitted, tasks with any label will be included in the results.'),
|
||||
}),
|
||||
},
|
||||
output: {
|
||||
schema: z.object({
|
||||
tasks: z.array(Task.schema).title('Tasks').describe('All matching tasks'),
|
||||
}),
|
||||
},
|
||||
},
|
||||
createNewTask: {
|
||||
title: 'Create New Task',
|
||||
description: 'Create a new task',
|
||||
input: {
|
||||
schema: z.object({
|
||||
content: Task.schema.shape.content,
|
||||
description: Task.schema.shape.description.optional(),
|
||||
projectId: Project.schema.shape.id
|
||||
.optional()
|
||||
.title('Project ID (optional)')
|
||||
.describe("The ID of the project. If omitted, the task will be added to the user's Inbox."),
|
||||
sectionId: Section.schema.shape.id
|
||||
.optional()
|
||||
.title('Section ID (optional)')
|
||||
.describe('The ID of section to put task into.'),
|
||||
labelNames: z
|
||||
.array(SharedLabel.schema.shape.name)
|
||||
.optional()
|
||||
.title('Label Names (optional)')
|
||||
.describe('The names of the labels to add to the task. If omitted, no label will be added.'),
|
||||
parentTaskId: Task.schema.shape.id
|
||||
.optional()
|
||||
.title('Parent Task ID (optional)')
|
||||
.describe('The ID of the parent task. If omitted, the task will have no parent task.'),
|
||||
priority: Task.schema.shape.priority
|
||||
.optional()
|
||||
.title('Priority (optional)')
|
||||
.describe('The priority level of the task, from 1 (normal) to 4 (urgent).'),
|
||||
dueDate: Task.schema.shape.dueDate
|
||||
.optional()
|
||||
.title('Due Date')
|
||||
.describe(
|
||||
'The due date of the task. Must be in RFC3339 format in UTC. If omitted, the task will have no due date.'
|
||||
),
|
||||
}),
|
||||
},
|
||||
output: {
|
||||
schema: z.object({
|
||||
taskId: Task.schema.shape.id,
|
||||
}),
|
||||
},
|
||||
},
|
||||
} as const satisfies sdk.IntegrationDefinitionProps['actions']
|
||||
@@ -0,0 +1,27 @@
|
||||
import * as sdk from '@botpress/sdk'
|
||||
|
||||
export const channels = {
|
||||
comments: {
|
||||
title: 'Task comments',
|
||||
description: 'Comment thread on a task',
|
||||
messages: {
|
||||
text: sdk.messages.defaults.text,
|
||||
},
|
||||
conversation: {
|
||||
tags: {
|
||||
id: {
|
||||
title: 'Task ID',
|
||||
description: 'The ID of the task',
|
||||
},
|
||||
},
|
||||
},
|
||||
message: {
|
||||
tags: {
|
||||
id: {
|
||||
title: 'Comment ID',
|
||||
description: 'The ID of the comment',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
} as const satisfies sdk.IntegrationDefinitionProps['channels']
|
||||
@@ -0,0 +1,23 @@
|
||||
import sdk, { z } from '@botpress/sdk'
|
||||
|
||||
export const configuration = {
|
||||
schema: z.object({}),
|
||||
identifier: {
|
||||
linkTemplateScript: 'linkTemplate.vrl',
|
||||
required: true,
|
||||
},
|
||||
} as const satisfies sdk.IntegrationDefinitionProps['configuration']
|
||||
|
||||
export const configurations = {
|
||||
apiToken: {
|
||||
title: 'Manual configuration',
|
||||
description: 'Configure manually by supplying an API token',
|
||||
schema: z.object({
|
||||
apiToken: z.string().title('API Token').describe('The API token to authenticate with the Todoist API'),
|
||||
}),
|
||||
},
|
||||
} satisfies sdk.IntegrationDefinitionProps['configurations']
|
||||
|
||||
export const identifier = {
|
||||
extractScript: 'extract.vrl',
|
||||
} as const satisfies sdk.IntegrationDefinitionProps['identifier']
|
||||
@@ -0,0 +1,26 @@
|
||||
// documentation for Color: https://developer.todoist.com/guides/#colors
|
||||
|
||||
export namespace Color {
|
||||
export const names = [
|
||||
'berry_red',
|
||||
'red',
|
||||
'orange',
|
||||
'yellow',
|
||||
'olive_green',
|
||||
'lime_green',
|
||||
'green',
|
||||
'mint_green',
|
||||
'teal',
|
||||
'sky_blue',
|
||||
'light_blue',
|
||||
'blue',
|
||||
'grape',
|
||||
'violet',
|
||||
'lavender',
|
||||
'magenta',
|
||||
'salmon',
|
||||
'charcoal',
|
||||
'gunmetal',
|
||||
'taupe',
|
||||
] as const
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import { z } from '@botpress/sdk'
|
||||
|
||||
// documentation for Comment: https://developer.todoist.com/rest/v2/#comments
|
||||
|
||||
export namespace Comment {
|
||||
const _fields = {
|
||||
id: z.string().title('ID').describe('The ID of the comment'),
|
||||
taskId: z
|
||||
.string()
|
||||
.title('Task ID')
|
||||
.optional()
|
||||
.describe('The ID of the task this comment belongs to. Omitted if the comment belongs to a project.'),
|
||||
projectId: z
|
||||
.string()
|
||||
.title('Project ID')
|
||||
.optional()
|
||||
.describe('The ID of the project this comment belongs to. Omitted if the comment belongs to a task.'),
|
||||
postedAt: z.string().title('Posted At').describe('Date and time when comment was added, RFC3339 format in UTC.'),
|
||||
content: z
|
||||
.string()
|
||||
.title('Content')
|
||||
.describe('The text of the comment. This value may contain markdown-formatted text and hyperlinks.'),
|
||||
} as const
|
||||
|
||||
export const schema = z.object(_fields)
|
||||
export type InferredType = z.infer<typeof schema>
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
import sdk from '@botpress/sdk'
|
||||
|
||||
import { Color } from './color'
|
||||
import { Comment } from './comment'
|
||||
import { PersonalLabel } from './personal-label'
|
||||
import { Project } from './project'
|
||||
import { Section } from './section'
|
||||
import { SharedLabel } from './shared-label'
|
||||
import { Task } from './task'
|
||||
|
||||
export { Comment, PersonalLabel, Project, Section, SharedLabel, Task, Color }
|
||||
|
||||
export const entities = {
|
||||
task: {
|
||||
title: 'Task',
|
||||
description: 'A task in Todoist',
|
||||
schema: Task.schema,
|
||||
},
|
||||
project: {
|
||||
title: 'Project',
|
||||
description: 'A project in Todoist',
|
||||
schema: Project.schema,
|
||||
},
|
||||
section: {
|
||||
title: 'Section',
|
||||
description: 'A section in a Todoist project',
|
||||
schema: Section.schema,
|
||||
},
|
||||
comment: {
|
||||
title: 'Comment',
|
||||
description: 'A comment on a Todoist task',
|
||||
schema: Comment.schema,
|
||||
},
|
||||
personalLabel: {
|
||||
title: 'Personal Label',
|
||||
description: 'A personal label in Todoist',
|
||||
schema: PersonalLabel.schema,
|
||||
},
|
||||
sharedLabel: {
|
||||
title: 'Shared Label',
|
||||
description: 'A shared label in Todoist',
|
||||
schema: SharedLabel.schema,
|
||||
},
|
||||
} as const satisfies sdk.IntegrationDefinitionProps['entities']
|
||||
@@ -0,0 +1,21 @@
|
||||
import { z } from '@botpress/sdk'
|
||||
import { Color } from './color'
|
||||
|
||||
// documentation for Label: https://developer.todoist.com/rest/v2/#labels
|
||||
|
||||
export namespace PersonalLabel {
|
||||
const _fields = {
|
||||
id: z.string().title('ID').describe('The ID of the label.'),
|
||||
name: z.string().title('Name').describe('The name of the label.'),
|
||||
color: z.enum(Color.names).title('Color Name').describe('The color of the label.'),
|
||||
orderWithinList: z
|
||||
.number()
|
||||
.title('Order Within List')
|
||||
.nonnegative()
|
||||
.describe("Numerical index indicating label's order within the user's label list."),
|
||||
isFavorite: z.boolean().title('Is Favorite?').describe('Whether the label is marked as favorite or not.'),
|
||||
} as const
|
||||
|
||||
export const schema = z.object(_fields)
|
||||
export type InferredType = z.infer<typeof schema>
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import { z } from '@botpress/sdk'
|
||||
import { Color } from './color'
|
||||
|
||||
// documentation for Project: https://developer.todoist.com/rest/v2/#projects
|
||||
|
||||
export namespace Project {
|
||||
const _fields = {
|
||||
id: z.string().title('ID').describe('The ID of the project.'),
|
||||
name: z.string().title('Name').describe('The name of the project.'),
|
||||
color: z.enum(Color.names).title('Color Name').describe('The color of the project.'),
|
||||
parentProjectId: z
|
||||
.string()
|
||||
.title('Parent Project ID')
|
||||
.optional()
|
||||
.describe('The ID of the parent project. Omitted if the project has no parent project.'),
|
||||
positionWithinParent: z
|
||||
.number()
|
||||
.title('Position Within Parent')
|
||||
.describe(
|
||||
"Numerical index indicating project's order within its parent project (read-only). Will be 0 for inbox projects."
|
||||
),
|
||||
numberOfComments: z
|
||||
.number()
|
||||
.title('Number of Comments')
|
||||
.nonnegative()
|
||||
.describe('The number of comments on the project.'),
|
||||
isShared: z.boolean().title('Is Shared?').describe('Whether the project is shared or not.'),
|
||||
isFavorite: z.boolean().title('Is Favorite?').describe('Whether the project is marked as favorite or not.'),
|
||||
isInboxProject: z.boolean().title('Is Inbox Project?').describe("Whether the project is the user's inbox."),
|
||||
isTeamInbox: z.boolean().title('Is Team Inbox?').describe('Whether the project is a team inbox.'),
|
||||
webUrl: z.string().title('Web URL').describe('The URL of the project in the Todoist web app.'),
|
||||
} as const
|
||||
|
||||
export const schema = z.object(_fields)
|
||||
export type InferredType = z.infer<typeof schema>
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import { z } from '@botpress/sdk'
|
||||
|
||||
// documentation for Section: https://developer.todoist.com/rest/v2/#sections
|
||||
|
||||
export namespace Section {
|
||||
const _fields = {
|
||||
id: z.string().title('ID').describe('The ID of the section.'),
|
||||
name: z.string().title('Name').describe('The name of the section.'),
|
||||
projectId: z.string().title('Project ID').optional().describe('The ID of the project this section belongs to.'),
|
||||
positionWithinParent: z
|
||||
.number()
|
||||
.title('Position Within Parent')
|
||||
.describe("Numerical index indicating section's order within its parent project."),
|
||||
} as const
|
||||
|
||||
export const schema = z.object(_fields)
|
||||
export type InferredType = z.infer<typeof schema>
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { z } from '@botpress/sdk'
|
||||
|
||||
// documentation for Label: https://developer.todoist.com/rest/v2/#labels
|
||||
|
||||
/**
|
||||
* Shared labels are ephemeral in nature. They only exist as long as at least
|
||||
* one task is associated with them. Once all tasks are removed from a shared
|
||||
* label, the label ceases to exist.
|
||||
*
|
||||
* A user can convert a shared label to a personal label at any time. The label
|
||||
* will then become customizable and will remain in the account even if not
|
||||
* assigned to any active tasks.
|
||||
*
|
||||
* Likewise, a personal label can be converted to a shared label by the user if
|
||||
* they no longer require them to be stored against their account, but they
|
||||
* still appear on shared tasks.
|
||||
*/
|
||||
export namespace SharedLabel {
|
||||
const _fields = {
|
||||
name: z.string().title('Name').describe('The name of the label.'),
|
||||
} as const
|
||||
|
||||
export const schema = z.object(_fields)
|
||||
export type InferredType = z.infer<typeof schema>
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
import { z } from '@botpress/sdk'
|
||||
|
||||
/**
|
||||
* Note: `item` is an old term used by Todoist to refer to tasks in their old
|
||||
* Sync API. While the REST API uses the term `task` and sends us Task entities,
|
||||
* we still receive Item entities in webhook events. Todoist is currently in the
|
||||
* process of phasing out the Item entity in favor of the Task entity, but for
|
||||
* now we must manually do some mapping between the two, since we only want to
|
||||
* expose the Task entity to the user.
|
||||
*/
|
||||
|
||||
// documentation for Task: https://developer.todoist.com/rest/v2/#tasks
|
||||
// documentation for Item: https://developer.todoist.com/sync/v9/#items
|
||||
|
||||
export namespace Task {
|
||||
const _fields = {
|
||||
id: z.string().title('ID').describe('The ID of the task'),
|
||||
projectId: z.string().title('Project ID').describe('The ID of the project this task belongs to (read-only).'),
|
||||
sectionId: z
|
||||
.string()
|
||||
.title('Section ID')
|
||||
.optional()
|
||||
.describe('The ID of the section this task belongs to (read-only). Omitted if the task is not in a section.'),
|
||||
content: z
|
||||
.string()
|
||||
.title('Content')
|
||||
.describe('The text of the task. This value may contain markdown-formatted text and hyperlinks.'),
|
||||
description: z
|
||||
.string()
|
||||
.title('Description')
|
||||
.describe('A description for the task. This value may contain markdown-formatted text and hyperlinks.'),
|
||||
isCompleted: z.boolean().title('Is Completed?').describe('Whether the task is completed or not.'),
|
||||
labels: z
|
||||
.array(z.string().title('Label Name').describe('The name of a label associated with the task.'))
|
||||
.title('Labels')
|
||||
.describe(
|
||||
'The labels associated with the task. This is a list of names that may represent either personal or shared labels.'
|
||||
),
|
||||
parentTaskId: z
|
||||
.string()
|
||||
.title('Parent Task ID')
|
||||
.optional()
|
||||
.describe('The ID of the parent task (read-only). Omitted if the task has no parent task.'),
|
||||
positionWithinParent: z
|
||||
.number()
|
||||
.title('Position Within Parent')
|
||||
.describe(
|
||||
"Numerical index indicating task's order within its parent (task, or project for top-level tasks) (read-only)."
|
||||
),
|
||||
priority: z
|
||||
.number()
|
||||
.title('Priority')
|
||||
.min(1)
|
||||
.max(4)
|
||||
.describe('Task priority from 1 (urgent) to 4 (lowest, default value).'),
|
||||
dueDate: z
|
||||
.string()
|
||||
.title('Due Date')
|
||||
.optional()
|
||||
.describe('The due date of the task. Omitted if the task has no due date.'),
|
||||
isRecurringDueDate: z
|
||||
.boolean()
|
||||
.title('Is Recurring Due Date?')
|
||||
.describe('Whether the due date is recurring or not.'),
|
||||
webUrl: z
|
||||
.string()
|
||||
.title('Web URL')
|
||||
.describe('URL to access this task in the Todoist web or mobile applications (read-only).'),
|
||||
numberOfComments: z
|
||||
.number()
|
||||
.title('Number of Comments')
|
||||
.nonnegative()
|
||||
.describe('The number of comments associated with the task (read-only).'),
|
||||
createdAt: z.string().title('Created At').describe('The date when the task was created (read-only).'),
|
||||
createdBy: z.string().title('Created By ID').describe('The ID of the user who created the task (read-only).'),
|
||||
assignee: z
|
||||
.string()
|
||||
.title('Assignee ID')
|
||||
.optional()
|
||||
.describe('The ID of the user to whom the task is assigned. Omitted if the task is not assigned.'),
|
||||
assigner: z
|
||||
.string()
|
||||
.title('Assigner ID')
|
||||
.optional()
|
||||
.describe('The ID of the user who assigned the task (read-only). Omitted if the task is not assigned.'),
|
||||
duration: z
|
||||
.object({
|
||||
amount: z.number().title('Amount').positive().describe('The amount of time.'),
|
||||
unit: z.enum(['minute', 'day']).title('Unit').describe('The unit of time.'),
|
||||
})
|
||||
.title('Duration')
|
||||
.optional()
|
||||
.describe('The duration of the task. Omitted if the task has no duration.'),
|
||||
} as const
|
||||
|
||||
export const schema = z.object(_fields)
|
||||
export type InferredType = z.infer<typeof schema>
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import sdk, { z } from '@botpress/sdk'
|
||||
import { Task } from './entities'
|
||||
|
||||
export const events = {
|
||||
taskAdded: {
|
||||
title: 'Task Added',
|
||||
description: 'A task has been added',
|
||||
schema: z.object({
|
||||
id: Task.schema.shape.id,
|
||||
content: Task.schema.shape.content,
|
||||
description: Task.schema.shape.description,
|
||||
priority: Task.schema.shape.priority,
|
||||
}),
|
||||
},
|
||||
taskPriorityChanged: {
|
||||
title: 'Task Priority Changed',
|
||||
description:
|
||||
'The priority of a task has been changed. The old priority is only available if the bot user is at the origin of the change',
|
||||
schema: z.object({
|
||||
id: Task.schema.shape.id,
|
||||
newPriority: Task.schema.shape.priority.title('New Priority'),
|
||||
oldPriority: Task.schema.shape.priority.optional().title('Old Priority'),
|
||||
}),
|
||||
},
|
||||
taskCompleted: {
|
||||
title: 'Task Completed',
|
||||
description: 'A task has been completed',
|
||||
schema: z.object({
|
||||
user_id: z.string().title('User ID').describe('The ID of the user who completed the task'),
|
||||
id: Task.schema.shape.id,
|
||||
content: Task.schema.shape.content,
|
||||
description: Task.schema.shape.description,
|
||||
priority: Task.schema.shape.priority,
|
||||
}),
|
||||
},
|
||||
} as const satisfies sdk.IntegrationDefinitionProps['events']
|
||||
@@ -0,0 +1,8 @@
|
||||
export * from './actions'
|
||||
export * from './channels'
|
||||
export * from './configuration'
|
||||
export * from './entities'
|
||||
export * from './events'
|
||||
export * from './secrets'
|
||||
export * from './states'
|
||||
export * from './user-tags'
|
||||
@@ -0,0 +1,16 @@
|
||||
import sdk from '@botpress/sdk'
|
||||
|
||||
export const secrets = {
|
||||
CLIENT_ID: {
|
||||
optional: false,
|
||||
description: 'Client ID in the App Management page of your Todoist app',
|
||||
},
|
||||
CLIENT_SECRET: {
|
||||
optional: false,
|
||||
description: 'Client Secret in the App Management page of your Todoist app',
|
||||
},
|
||||
WEBHOOK_SHARED_SECRET: {
|
||||
optional: false,
|
||||
description: 'Webhook shared secret',
|
||||
},
|
||||
} as const satisfies sdk.IntegrationDefinitionProps['secrets']
|
||||
@@ -0,0 +1,21 @@
|
||||
import sdk, { z } from '@botpress/sdk'
|
||||
|
||||
export const states = {
|
||||
credentials: {
|
||||
type: 'integration',
|
||||
schema: z.object({
|
||||
accessToken: z
|
||||
.string()
|
||||
.title('Access Token')
|
||||
.describe('The access token used to communicate with the Todoist API'),
|
||||
}),
|
||||
},
|
||||
|
||||
// TODO: This state is unused. Delete it in the next major version.
|
||||
configuration: {
|
||||
type: 'integration',
|
||||
schema: z.object({
|
||||
botUserId: z.string().optional().title('Bot User ID').describe('The ID of the bot user in Todoist'),
|
||||
}),
|
||||
},
|
||||
} as const satisfies sdk.IntegrationDefinitionProps['states']
|
||||
@@ -0,0 +1,10 @@
|
||||
import sdk from '@botpress/sdk'
|
||||
|
||||
export const user = {
|
||||
tags: {
|
||||
id: {
|
||||
title: 'Todoist User ID',
|
||||
description: 'The unique ID of the user on Todoist',
|
||||
},
|
||||
},
|
||||
} as const satisfies sdk.IntegrationDefinitionProps['user']
|
||||
Reference in New Issue
Block a user