Add Activepieces integration for workflow automation
- Add Activepieces fork with SmoothSchedule custom piece - Create integrations app with Activepieces service layer - Add embed token endpoint for iframe integration - Create Automations page with embedded workflow builder - Add sidebar visibility fix for embed mode - Add list inactive customers endpoint to Public API - Include SmoothSchedule triggers: event created/updated/cancelled - Include SmoothSchedule actions: create/update/cancel events, list resources/services/customers 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"extends": [
|
||||
"../../../../.eslintrc.base.json"
|
||||
],
|
||||
"ignorePatterns": [
|
||||
"!**/*"
|
||||
],
|
||||
"overrides": [
|
||||
{
|
||||
"files": [
|
||||
"*.ts",
|
||||
"*.tsx",
|
||||
"*.js",
|
||||
"*.jsx"
|
||||
],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": [
|
||||
"*.ts",
|
||||
"*.tsx"
|
||||
],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": [
|
||||
"*.js",
|
||||
"*.jsx"
|
||||
],
|
||||
"rules": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
# pieces-chatling
|
||||
|
||||
This library was generated with [Nx](https://nx.dev).
|
||||
|
||||
## Building
|
||||
|
||||
Run `nx build pieces-chatling` to build the library.
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "@activepieces/piece-chatling",
|
||||
"version": "0.0.1",
|
||||
"type": "commonjs",
|
||||
"main": "./src/index.js",
|
||||
"types": "./src/index.d.ts",
|
||||
"dependencies": {
|
||||
"tslib": "^2.3.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
{
|
||||
"name": "pieces-chatling",
|
||||
"$schema": "../../../../node_modules/nx/schemas/project-schema.json",
|
||||
"sourceRoot": "packages/pieces/community/chatling/src",
|
||||
"projectType": "library",
|
||||
"release": {
|
||||
"version": {
|
||||
"manifestRootsToUpdate": [
|
||||
"dist/{projectRoot}"
|
||||
],
|
||||
"currentVersionResolver": "git-tag",
|
||||
"fallbackCurrentVersionResolver": "disk"
|
||||
}
|
||||
},
|
||||
"tags": [],
|
||||
"targets": {
|
||||
"build": {
|
||||
"executor": "@nx/js:tsc",
|
||||
"outputs": [
|
||||
"{options.outputPath}"
|
||||
],
|
||||
"options": {
|
||||
"outputPath": "dist/packages/pieces/community/chatling",
|
||||
"tsConfig": "packages/pieces/community/chatling/tsconfig.lib.json",
|
||||
"packageJson": "packages/pieces/community/chatling/package.json",
|
||||
"main": "packages/pieces/community/chatling/src/index.ts",
|
||||
"assets": [
|
||||
"packages/pieces/community/chatling/*.md",
|
||||
{
|
||||
"input": "packages/pieces/community/chatling/src/i18n",
|
||||
"output": "./src/i18n",
|
||||
"glob": "**/!(i18n.json)"
|
||||
}
|
||||
],
|
||||
"buildableProjectDepsInPackageJsonType": "dependencies",
|
||||
"updateBuildableProjectDepsInPackageJson": true
|
||||
},
|
||||
"dependsOn": [
|
||||
"prebuild",
|
||||
"^build"
|
||||
]
|
||||
},
|
||||
"nx-release-publish": {
|
||||
"options": {
|
||||
"packageRoot": "dist/{projectRoot}"
|
||||
}
|
||||
},
|
||||
"prebuild": {
|
||||
"dependsOn": [
|
||||
"^build"
|
||||
],
|
||||
"executor": "nx:run-commands",
|
||||
"options": {
|
||||
"cwd": "packages/pieces/community/chatling",
|
||||
"command": "bun install --no-save --silent"
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"executor": "@nx/eslint:lint",
|
||||
"outputs": [
|
||||
"{options.outputFile}"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
import {
|
||||
createCustomApiCallAction,
|
||||
HttpMethod,
|
||||
} from '@activepieces/pieces-common';
|
||||
import { createPiece, PieceAuth } from '@activepieces/pieces-framework';
|
||||
import { PieceCategory } from '@activepieces/shared';
|
||||
import { makeRequest } from './lib/common';
|
||||
import { sendMessage } from './lib/actions/send-message';
|
||||
import { createChatbot } from './lib/actions/create-chatbot';
|
||||
import { newConversation } from './lib/triggers/new-conversation';
|
||||
import { newContact } from './lib/triggers/new-contact';
|
||||
|
||||
const markdownDescription = `
|
||||
To obtain your API key:
|
||||
|
||||
1. Go to your [Chatling account](https://app.chatling.ai)
|
||||
2. Open **Project Settings**
|
||||
3. Click the **API Keys** tab
|
||||
4. Press **New API key** and generate a new key
|
||||
5. Copy the key (it's only shown once)
|
||||
`;
|
||||
|
||||
export const chatlingAuth = PieceAuth.SecretText({
|
||||
displayName: 'API Key',
|
||||
description: markdownDescription,
|
||||
required: true,
|
||||
validate: async ({ auth }) => {
|
||||
try {
|
||||
await makeRequest(auth, HttpMethod.GET, '/project/settings');
|
||||
return { valid: true };
|
||||
} catch (e) {
|
||||
return {
|
||||
valid: false,
|
||||
error: 'Invalid API key',
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
export const chatling = createPiece({
|
||||
displayName: 'Chatling',
|
||||
description: 'Build AI chatbots trained on your data.',
|
||||
auth: chatlingAuth,
|
||||
minimumSupportedRelease: '0.36.1',
|
||||
logoUrl: 'https://cdn.activepieces.com/pieces/chatling.png',
|
||||
categories: [PieceCategory.ARTIFICIAL_INTELLIGENCE],
|
||||
authors: ['onyedikachi-david'],
|
||||
actions: [
|
||||
sendMessage,
|
||||
createChatbot,
|
||||
createCustomApiCallAction({
|
||||
auth: chatlingAuth,
|
||||
baseUrl: () => 'https://api.chatling.ai/v2',
|
||||
authMapping: async (auth) => ({
|
||||
Authorization: `Bearer ${(auth as { secret_text: string }).secret_text}`,
|
||||
}),
|
||||
}),
|
||||
],
|
||||
triggers: [newConversation, newContact],
|
||||
});
|
||||
@@ -0,0 +1,38 @@
|
||||
import { HttpMethod } from '@activepieces/pieces-common';
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { chatlingAuth } from '../../index';
|
||||
import { makeRequest } from '../common';
|
||||
import { templateIdDropdown } from '../common/props';
|
||||
|
||||
export const createChatbot = createAction({
|
||||
auth: chatlingAuth,
|
||||
name: 'create_chatbot',
|
||||
displayName: 'Create Chatbot',
|
||||
description: 'Create a new chatbot using a template or from scratch.',
|
||||
props: {
|
||||
name: Property.ShortText({
|
||||
displayName: 'Name',
|
||||
description: 'The name of the chatbot',
|
||||
required: true,
|
||||
}),
|
||||
template_id: templateIdDropdown,
|
||||
},
|
||||
|
||||
async run(context) {
|
||||
const { name, template_id } = context.propsValue;
|
||||
const apiKey = context.auth.secret_text;
|
||||
|
||||
const body: Record<string, unknown> = { name };
|
||||
|
||||
if (template_id) body['template_id'] = template_id;
|
||||
|
||||
const response = await makeRequest(
|
||||
apiKey,
|
||||
HttpMethod.POST,
|
||||
'/chatbots',
|
||||
body
|
||||
);
|
||||
|
||||
return response;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,80 @@
|
||||
import { HttpMethod } from '@activepieces/pieces-common';
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { chatlingAuth } from '../../index';
|
||||
import { makeRequest } from '../common';
|
||||
import {
|
||||
chatbotIdDropdown,
|
||||
aiModelIdDropdown,
|
||||
languageIdDropdown,
|
||||
contactIdDropdown,
|
||||
conversationIdDropdown,
|
||||
} from '../common/props';
|
||||
|
||||
export const sendMessage = createAction({
|
||||
auth: chatlingAuth,
|
||||
name: 'send_message',
|
||||
displayName: 'Send Message',
|
||||
description: 'Send a message to the chatbot and receive an AI response.',
|
||||
props: {
|
||||
chatbotId: chatbotIdDropdown,
|
||||
message: Property.LongText({
|
||||
displayName: 'Message',
|
||||
description: 'The message to send to the AI',
|
||||
required: true,
|
||||
}),
|
||||
ai_model_id: aiModelIdDropdown,
|
||||
conversation_id: conversationIdDropdown,
|
||||
contact_id: contactIdDropdown,
|
||||
language_id: languageIdDropdown,
|
||||
temperature: Property.Number({
|
||||
displayName: 'Temperature',
|
||||
description:
|
||||
'Controls randomness (0 = focused, 1 = creative). Default is 0.',
|
||||
required: false,
|
||||
defaultValue: 0,
|
||||
}),
|
||||
instructions: Property.Array({
|
||||
displayName: 'Instructions',
|
||||
description: 'Additional instructions to tailor the AI response',
|
||||
required: false,
|
||||
}),
|
||||
},
|
||||
|
||||
async run(context) {
|
||||
const {
|
||||
chatbotId,
|
||||
message,
|
||||
ai_model_id,
|
||||
conversation_id,
|
||||
contact_id,
|
||||
language_id,
|
||||
temperature,
|
||||
instructions,
|
||||
} = context.propsValue;
|
||||
|
||||
const apiKey = context.auth.secret_text;
|
||||
|
||||
const body: Record<string, unknown> = {
|
||||
message,
|
||||
ai_model_id,
|
||||
};
|
||||
|
||||
if (conversation_id) body['conversation_id'] = conversation_id;
|
||||
if (contact_id) body['contact_id'] = contact_id;
|
||||
if (language_id) body['language_id'] = language_id;
|
||||
if (temperature !== undefined && temperature !== null)
|
||||
body['temperature'] = temperature;
|
||||
if (instructions && instructions.length > 0)
|
||||
body['instructions'] = instructions;
|
||||
|
||||
const response = await makeRequest(
|
||||
apiKey,
|
||||
HttpMethod.POST,
|
||||
`/chatbots/${chatbotId}/ai/kb/chat`,
|
||||
body
|
||||
);
|
||||
|
||||
return response;
|
||||
},
|
||||
});
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
import { HttpMethod, httpClient } from '@activepieces/pieces-common';
|
||||
|
||||
export const chatlingCommon = {
|
||||
baseUrl: 'https://api.chatling.ai/v2',
|
||||
};
|
||||
|
||||
export async function makeRequest<T = unknown>(
|
||||
apiKey: string,
|
||||
method: HttpMethod,
|
||||
path: string,
|
||||
body?: unknown
|
||||
): Promise<T> {
|
||||
const response = await httpClient.sendRequest<T>({
|
||||
method,
|
||||
url: `${chatlingCommon.baseUrl}${path}`,
|
||||
headers: {
|
||||
Authorization: `Bearer ${apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body,
|
||||
});
|
||||
|
||||
return response.body;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,274 @@
|
||||
import { HttpMethod } from '@activepieces/pieces-common';
|
||||
import { DropdownOption, Property } from '@activepieces/pieces-framework';
|
||||
import { makeRequest } from './index';
|
||||
import { chatlingAuth } from '../../index';
|
||||
|
||||
export const chatbotIdDropdown = Property.Dropdown({
|
||||
auth: chatlingAuth,
|
||||
displayName: 'Chatbot',
|
||||
description: 'Select a chatbot',
|
||||
required: true,
|
||||
refreshers: [],
|
||||
options: async ({ auth }) => {
|
||||
if (!auth) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'Please connect your account first.',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
|
||||
const response = await makeRequest<{
|
||||
data: {
|
||||
chatbots: { id: string; name: string }[];
|
||||
};
|
||||
}>(auth.secret_text, HttpMethod.GET, '/chatbots');
|
||||
|
||||
const options: DropdownOption<string>[] = response.data.chatbots.map(
|
||||
(chatbot) => ({
|
||||
label: chatbot.name,
|
||||
value: chatbot.id,
|
||||
})
|
||||
);
|
||||
|
||||
return {
|
||||
disabled: false,
|
||||
options,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export const aiModelIdDropdown = Property.Dropdown({
|
||||
auth: chatlingAuth,
|
||||
displayName: 'AI Model',
|
||||
description: 'Select the AI model to use',
|
||||
required: true,
|
||||
refreshers: ['chatbotId'],
|
||||
options: async ({ auth, chatbotId }) => {
|
||||
if (!auth) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'Please connect your account first.',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
|
||||
if (!chatbotId) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'Please select a chatbot first.',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
|
||||
const response = await makeRequest<{
|
||||
data: {
|
||||
models: { id: number; name: string }[];
|
||||
};
|
||||
}>(
|
||||
auth.secret_text,
|
||||
HttpMethod.GET,
|
||||
`/chatbots/${chatbotId}/ai/kb/models`
|
||||
);
|
||||
|
||||
const options: DropdownOption<number>[] = response.data.models.map(
|
||||
(model) => ({
|
||||
label: model.name,
|
||||
value: model.id,
|
||||
})
|
||||
);
|
||||
|
||||
return {
|
||||
disabled: false,
|
||||
options,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export const languageIdDropdown = Property.Dropdown({
|
||||
auth: chatlingAuth,
|
||||
displayName: 'Language',
|
||||
description: 'Select the language for the AI response',
|
||||
required: false,
|
||||
refreshers: ['chatbotId'],
|
||||
options: async ({ auth, chatbotId }) => {
|
||||
if (!auth) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'Please connect your account first.',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
|
||||
if (!chatbotId) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'Please select a chatbot first.',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
|
||||
const response = await makeRequest<{
|
||||
data: {
|
||||
languages: { id: number; name: string }[];
|
||||
};
|
||||
}>(
|
||||
auth.secret_text,
|
||||
HttpMethod.GET,
|
||||
`/chatbots/${chatbotId}/ai/kb/languages`
|
||||
);
|
||||
|
||||
const options: DropdownOption<number>[] = response.data.languages.map(
|
||||
(language) => ({
|
||||
label: language.name,
|
||||
value: language.id,
|
||||
})
|
||||
);
|
||||
|
||||
return {
|
||||
disabled: false,
|
||||
options,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export const contactIdDropdown = Property.Dropdown({
|
||||
auth: chatlingAuth,
|
||||
displayName: 'Contact',
|
||||
description: 'Associate the conversation with a contact',
|
||||
required: false,
|
||||
refreshers: ['chatbotId'],
|
||||
options: async ({ auth, chatbotId }) => {
|
||||
if (!auth) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'Please connect your account first.',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
|
||||
if (!chatbotId) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'Please select a chatbot first.',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
|
||||
const response = await makeRequest<{
|
||||
data: {
|
||||
contacts: { id: string; name: string; email: string }[];
|
||||
};
|
||||
}>(
|
||||
auth.secret_text,
|
||||
HttpMethod.GET,
|
||||
`/chatbots/${chatbotId}/contacts`
|
||||
);
|
||||
|
||||
const options: DropdownOption<string>[] = response.data.contacts.map(
|
||||
(contact) => ({
|
||||
label: contact.name || contact.email || contact.id,
|
||||
value: contact.id,
|
||||
})
|
||||
);
|
||||
|
||||
return {
|
||||
disabled: false,
|
||||
options,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export const templateIdDropdown = Property.Dropdown({
|
||||
auth: chatlingAuth,
|
||||
displayName: 'Template',
|
||||
description: 'Use a template to create the chatbot',
|
||||
required: false,
|
||||
refreshers: [],
|
||||
options: async ({ auth }) => {
|
||||
if (!auth) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'Please connect your account first.',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
|
||||
const response = await makeRequest<{
|
||||
data: {
|
||||
templates: { id: number; name: string; description: string }[];
|
||||
};
|
||||
}>(auth.secret_text, HttpMethod.GET, '/chatbot-templates');
|
||||
|
||||
const options: DropdownOption<number>[] = response.data.templates.map(
|
||||
(template) => ({
|
||||
label: template.name,
|
||||
value: template.id,
|
||||
})
|
||||
);
|
||||
|
||||
return {
|
||||
disabled: false,
|
||||
options,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export const conversationIdDropdown = Property.Dropdown({
|
||||
auth: chatlingAuth,
|
||||
displayName: 'Conversation',
|
||||
description: 'Continue an existing conversation',
|
||||
required: false,
|
||||
refreshers: ['chatbotId'],
|
||||
options: async ({ auth, chatbotId }) => {
|
||||
if (!auth) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'Please connect your account first.',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
|
||||
if (!chatbotId) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'Please select a chatbot first.',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
|
||||
const response = await makeRequest<{
|
||||
data: {
|
||||
conversations: {
|
||||
id: string;
|
||||
created_at: string;
|
||||
messages: { text: string; role: string }[];
|
||||
}[];
|
||||
};
|
||||
}>(
|
||||
auth.secret_text,
|
||||
HttpMethod.GET,
|
||||
`/chatbots/${chatbotId}/conversations`
|
||||
);
|
||||
|
||||
const options: DropdownOption<string>[] = response.data.conversations.map(
|
||||
(conv) => {
|
||||
const firstUserMsg = conv.messages?.find((m) => m.role === 'user');
|
||||
const preview = firstUserMsg?.text
|
||||
? firstUserMsg.text.substring(0, 50) +
|
||||
(firstUserMsg.text.length > 50 ? '...' : '')
|
||||
: conv.created_at;
|
||||
return {
|
||||
label: preview,
|
||||
value: conv.id,
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
return {
|
||||
disabled: false,
|
||||
options,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
import {
|
||||
createTrigger,
|
||||
TriggerStrategy,
|
||||
AppConnectionValueForAuthProperty,
|
||||
} from '@activepieces/pieces-framework';
|
||||
import {
|
||||
DedupeStrategy,
|
||||
HttpMethod,
|
||||
Polling,
|
||||
pollingHelper,
|
||||
} from '@activepieces/pieces-common';
|
||||
import { chatlingAuth } from '../../index';
|
||||
import { chatbotIdDropdown } from '../common/props';
|
||||
import { makeRequest } from '../common';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
type ContactItem = {
|
||||
id: string;
|
||||
name: string;
|
||||
email: string;
|
||||
phone: string;
|
||||
job_title: string;
|
||||
website: string;
|
||||
company: string;
|
||||
created_at: string;
|
||||
};
|
||||
|
||||
const polling: Polling<
|
||||
AppConnectionValueForAuthProperty<typeof chatlingAuth>,
|
||||
{ chatbotId: string }
|
||||
> = {
|
||||
strategy: DedupeStrategy.TIMEBASED,
|
||||
items: async ({ auth, propsValue, lastFetchEpochMS }) => {
|
||||
const response = await makeRequest<{
|
||||
data: {
|
||||
contacts: ContactItem[];
|
||||
};
|
||||
}>(
|
||||
auth.secret_text,
|
||||
HttpMethod.GET,
|
||||
`/chatbots/${propsValue.chatbotId}/contacts?sort=date_desc`
|
||||
);
|
||||
|
||||
const contacts = response.data.contacts;
|
||||
|
||||
const items = contacts
|
||||
.filter((contact) => {
|
||||
if (lastFetchEpochMS === 0) return true;
|
||||
return dayjs(contact.created_at).valueOf() > lastFetchEpochMS;
|
||||
})
|
||||
.map((contact) => ({
|
||||
epochMilliSeconds: dayjs(contact.created_at).valueOf(),
|
||||
data: contact,
|
||||
}));
|
||||
|
||||
return items;
|
||||
},
|
||||
};
|
||||
|
||||
export const newContact = createTrigger({
|
||||
auth: chatlingAuth,
|
||||
name: 'new_contact',
|
||||
displayName: 'New Contact/Lead',
|
||||
description: 'Triggers when a new contact or lead is collected by the chatbot.',
|
||||
props: {
|
||||
chatbotId: chatbotIdDropdown,
|
||||
},
|
||||
type: TriggerStrategy.POLLING,
|
||||
async onEnable(context) {
|
||||
await pollingHelper.onEnable(polling, {
|
||||
auth: context.auth,
|
||||
store: context.store,
|
||||
propsValue: context.propsValue,
|
||||
});
|
||||
},
|
||||
async onDisable(context) {
|
||||
await pollingHelper.onDisable(polling, {
|
||||
auth: context.auth,
|
||||
store: context.store,
|
||||
propsValue: context.propsValue,
|
||||
});
|
||||
},
|
||||
async test(context) {
|
||||
return await pollingHelper.test(polling, context);
|
||||
},
|
||||
async run(context) {
|
||||
return await pollingHelper.poll(polling, context);
|
||||
},
|
||||
sampleData: {
|
||||
id: 'contact_abc123',
|
||||
name: 'John Doe',
|
||||
email: 'john@example.com',
|
||||
phone: '+1234567890',
|
||||
job_title: 'Product Manager',
|
||||
website: 'https://example.com',
|
||||
company: 'Acme Inc',
|
||||
created_at: '2024-01-15T10:30:00.000Z',
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,102 @@
|
||||
import {
|
||||
createTrigger,
|
||||
TriggerStrategy,
|
||||
AppConnectionValueForAuthProperty,
|
||||
} from '@activepieces/pieces-framework';
|
||||
import {
|
||||
DedupeStrategy,
|
||||
HttpMethod,
|
||||
Polling,
|
||||
pollingHelper,
|
||||
} from '@activepieces/pieces-common';
|
||||
import { chatlingAuth } from '../../index';
|
||||
import { chatbotIdDropdown } from '../common/props';
|
||||
import { makeRequest } from '../common';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
type ConversationItem = {
|
||||
id: string;
|
||||
contact_id: string;
|
||||
archived: boolean;
|
||||
important: boolean;
|
||||
created_at: string;
|
||||
messages: { id: string; text: string; role: string }[];
|
||||
};
|
||||
|
||||
const polling: Polling<
|
||||
AppConnectionValueForAuthProperty<typeof chatlingAuth>,
|
||||
{ chatbotId: string }
|
||||
> = {
|
||||
strategy: DedupeStrategy.TIMEBASED,
|
||||
items: async ({ auth, propsValue, lastFetchEpochMS }) => {
|
||||
const response = await makeRequest<{
|
||||
data: {
|
||||
conversations: ConversationItem[];
|
||||
};
|
||||
}>(
|
||||
auth.secret_text,
|
||||
HttpMethod.GET,
|
||||
`/chatbots/${propsValue.chatbotId}/conversations?sort=date_desc`
|
||||
);
|
||||
|
||||
const conversations = response.data.conversations;
|
||||
|
||||
// Filter by lastFetchEpochMS if not first run
|
||||
const items = conversations
|
||||
.filter((conv) => {
|
||||
if (lastFetchEpochMS === 0) return true;
|
||||
return dayjs(conv.created_at).valueOf() > lastFetchEpochMS;
|
||||
})
|
||||
.map((conv) => ({
|
||||
epochMilliSeconds: dayjs(conv.created_at).valueOf(),
|
||||
data: conv,
|
||||
}));
|
||||
|
||||
return items;
|
||||
},
|
||||
};
|
||||
|
||||
export const newConversation = createTrigger({
|
||||
auth: chatlingAuth,
|
||||
name: 'new_conversation',
|
||||
displayName: 'New Conversation',
|
||||
description: 'Triggers when a new conversation is started by a customer.',
|
||||
props: {
|
||||
chatbotId: chatbotIdDropdown,
|
||||
},
|
||||
type: TriggerStrategy.POLLING,
|
||||
async onEnable(context) {
|
||||
await pollingHelper.onEnable(polling, {
|
||||
auth: context.auth,
|
||||
store: context.store,
|
||||
propsValue: context.propsValue,
|
||||
});
|
||||
},
|
||||
async onDisable(context) {
|
||||
await pollingHelper.onDisable(polling, {
|
||||
auth: context.auth,
|
||||
store: context.store,
|
||||
propsValue: context.propsValue,
|
||||
});
|
||||
},
|
||||
async test(context) {
|
||||
return await pollingHelper.test(polling, context);
|
||||
},
|
||||
async run(context) {
|
||||
return await pollingHelper.poll(polling, context);
|
||||
},
|
||||
sampleData: {
|
||||
id: 'conv_abc123',
|
||||
contact_id: 'contact_xyz',
|
||||
archived: false,
|
||||
important: false,
|
||||
created_at: '2024-01-15T10:30:00.000Z',
|
||||
messages: [
|
||||
{
|
||||
id: 'msg_1',
|
||||
text: 'Hello, I need help with your product.',
|
||||
role: 'user',
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"extends": "../../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"importHelpers": true,
|
||||
"noImplicitOverride": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noPropertyAccessFromIndexSignature": true
|
||||
},
|
||||
"files": [],
|
||||
"include": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.lib.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../../../dist/out-tsc",
|
||||
"declaration": true,
|
||||
"types": ["node"]
|
||||
},
|
||||
"include": ["src/**/*.ts"]
|
||||
}
|
||||
Reference in New Issue
Block a user