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,184 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { httpClient, HttpMethod } from '@activepieces/pieces-common';
|
||||
import { autocallsAuth, baseApiUrl } from '../..';
|
||||
|
||||
export const addLead = createAction({
|
||||
auth:autocallsAuth,
|
||||
name: 'addLead',
|
||||
displayName: 'Add lead to a campaign',
|
||||
description: "Add lead to an outbound campaign, to be called by an assistant from our platform.",
|
||||
props: {
|
||||
campaign: Property.Dropdown({
|
||||
auth: autocallsAuth,
|
||||
displayName: 'Campaign',
|
||||
description: 'Select a campaign',
|
||||
required: true,
|
||||
refreshers: ['auth'],
|
||||
refreshOnSearch: false,
|
||||
options: async ({ auth }) => {
|
||||
if (!auth) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'Please authenticate first',
|
||||
options: []
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await httpClient.sendRequest({
|
||||
method: HttpMethod.GET,
|
||||
url: baseApiUrl + 'api/user/campaigns',
|
||||
headers: {
|
||||
Authorization: "Bearer " + auth,
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
},
|
||||
});
|
||||
|
||||
if (res.status !== 200) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'Error fetching campaigns',
|
||||
options: [],
|
||||
};
|
||||
} else if (!res.body || res.body.length === 0) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'No campaigns found. Create one first.',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
options: res.body.map((campaign: any) => ({
|
||||
value: campaign.id,
|
||||
label: campaign.name,
|
||||
})),
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'Failed to fetch campaigns',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
}
|
||||
}),
|
||||
phone_number: Property.ShortText({
|
||||
displayName: 'Customer phone number',
|
||||
description: 'Enter the phone number of the customer',
|
||||
required: true,
|
||||
}),
|
||||
variables: Property.Object({
|
||||
displayName: 'Variables',
|
||||
description: 'Variables to pass to the assistant',
|
||||
required: true,
|
||||
defaultValue: {
|
||||
customer_name: 'John',
|
||||
}
|
||||
}),
|
||||
allow_dupplicate: Property.Checkbox({
|
||||
displayName: 'Allow duplicates',
|
||||
description: 'Allow the same phone number to be added to the campaign more than once',
|
||||
required: true,
|
||||
defaultValue: false
|
||||
}),
|
||||
num_secondary_contacts: Property.Number({
|
||||
displayName: 'Number of Secondary Contacts',
|
||||
description: 'How many secondary contacts do you want to add?',
|
||||
required: false,
|
||||
defaultValue: 0,
|
||||
}),
|
||||
secondary_contacts: Property.DynamicProperties({
|
||||
auth: autocallsAuth,
|
||||
displayName: 'Secondary Contacts',
|
||||
description: 'Add secondary contacts for this lead. Each contact can have its own phone number and variables.',
|
||||
required: false,
|
||||
refreshers: ['num_secondary_contacts'],
|
||||
props: async ({ num_secondary_contacts }) => {
|
||||
const contacts: any = {};
|
||||
const numContacts = Number(num_secondary_contacts) || 0;
|
||||
|
||||
// Generate fields based on the number specified
|
||||
for (let i = 1; i <= numContacts && i <= 10; i++) {
|
||||
contacts[`contact_${i}_phone`] = Property.ShortText({
|
||||
displayName: `Contact ${i} - Phone Number`,
|
||||
description: `Phone number for secondary contact ${i}`,
|
||||
required: true,
|
||||
});
|
||||
|
||||
contacts[`contact_${i}_variables`] = Property.Object({
|
||||
displayName: `Contact ${i} - Variables`,
|
||||
description: `Variables for secondary contact ${i} as key-value pairs`,
|
||||
required: false,
|
||||
defaultValue: {
|
||||
customer_name: 'John',
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return contacts;
|
||||
},
|
||||
})
|
||||
},
|
||||
async run(context) {
|
||||
if (!context.auth) {
|
||||
throw new Error('Authentication is required');
|
||||
}
|
||||
|
||||
try {
|
||||
const body: any = {
|
||||
campaign_id: context.propsValue['campaign'],
|
||||
phone_number: context.propsValue['phone_number'],
|
||||
variables: context.propsValue['variables'],
|
||||
allow_dupplicate: context.propsValue['allow_dupplicate'],
|
||||
};
|
||||
|
||||
// Add secondary contacts if provided
|
||||
if (context.propsValue['secondary_contacts']) {
|
||||
const secondaryContactsData = context.propsValue['secondary_contacts'] as Record<string, any>;
|
||||
const numContacts = Number(context.propsValue['num_secondary_contacts']) || 0;
|
||||
const secondaryContacts: any[] = [];
|
||||
|
||||
// Process the specified number of contacts
|
||||
for (let i = 1; i <= numContacts && i <= 10; i++) {
|
||||
const phoneNumber = secondaryContactsData[`contact_${i}_phone`];
|
||||
const variables = secondaryContactsData[`contact_${i}_variables`];
|
||||
|
||||
// Only add contact if phone number is provided
|
||||
if (phoneNumber && phoneNumber.trim() !== '') {
|
||||
secondaryContacts.push({
|
||||
phone_number: phoneNumber,
|
||||
variables: variables || {
|
||||
customer_name: '',
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (secondaryContacts.length > 0) {
|
||||
body.secondary_contacts = secondaryContacts;
|
||||
}
|
||||
}
|
||||
|
||||
const res = await httpClient.sendRequest<string[]>({
|
||||
method: HttpMethod.POST,
|
||||
url: baseApiUrl + 'api/user/lead',
|
||||
body: body,
|
||||
headers: {
|
||||
Authorization: "Bearer " + context.auth.secret_text,
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
},
|
||||
});
|
||||
|
||||
if (res.status !== 200) {
|
||||
throw new Error(`Failed to add lead: ${res.status}`);
|
||||
}
|
||||
|
||||
return res.body;
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to add lead: ${error}`);
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,79 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { httpClient, HttpMethod } from '@activepieces/pieces-common';
|
||||
import { autocallsAuth, baseApiUrl } from '../..';
|
||||
|
||||
export const campaignControl = createAction({
|
||||
auth:autocallsAuth,
|
||||
name: 'campaignControl',
|
||||
displayName: 'Start/Stop Campaign',
|
||||
description: "Start or stop an outbound campaign from our platform.",
|
||||
props: {
|
||||
campaign: Property.Dropdown({
|
||||
auth: autocallsAuth,
|
||||
displayName: 'Campaign',
|
||||
description: 'Select a campaign',
|
||||
required: true,
|
||||
refreshers: ['auth'],
|
||||
refreshOnSearch: false,
|
||||
options: async ({ auth }) => {
|
||||
const res = await httpClient.sendRequest({
|
||||
method: HttpMethod.GET,
|
||||
url: baseApiUrl + 'api/user/campaigns',
|
||||
headers: {
|
||||
Authorization: "Bearer " + auth?.secret_text,
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
},
|
||||
});
|
||||
|
||||
if (res.status !== 200) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'Error fetching campaigns',
|
||||
options: [],
|
||||
};
|
||||
} else if (res.body.length === 0) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'No campaigns found. Create one first.',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
options: res.body.map((campaign: any) => ({
|
||||
value: campaign.id,
|
||||
label: campaign.name,
|
||||
})),
|
||||
};
|
||||
}
|
||||
}),
|
||||
action: Property.StaticDropdown({
|
||||
displayName: 'Action',
|
||||
description: 'Select action to perform on the campaign',
|
||||
required: true,
|
||||
options: {
|
||||
options: [
|
||||
{ label: 'Start Campaign', value: 'start' },
|
||||
{ label: 'Stop Campaign', value: 'stop' }
|
||||
]
|
||||
}
|
||||
})
|
||||
},
|
||||
async run(context) {
|
||||
const res = await httpClient.sendRequest<string[]>({
|
||||
method: HttpMethod.POST,
|
||||
url: baseApiUrl + 'api/user/campaigns/update-status',
|
||||
body: {
|
||||
campaign_id: context.propsValue['campaign'],
|
||||
action: context.propsValue['action'],
|
||||
},
|
||||
headers: {
|
||||
Authorization: "Bearer " + context.auth.secret_text,
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
},
|
||||
});
|
||||
return res.body;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,66 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { httpClient, HttpMethod } from '@activepieces/pieces-common';
|
||||
import { autocallsAuth, baseApiUrl } from '../..';
|
||||
|
||||
export const deleteLead = createAction({
|
||||
auth:autocallsAuth,
|
||||
name: 'deleteLead',
|
||||
displayName: 'Delete Lead',
|
||||
description: "Delete a lead from a campaign.",
|
||||
props: {
|
||||
lead: Property.Dropdown({
|
||||
auth: autocallsAuth,
|
||||
displayName: 'Lead',
|
||||
description: 'Select a lead to delete',
|
||||
required: true,
|
||||
refreshers: ['auth'],
|
||||
refreshOnSearch: false,
|
||||
options: async ({ auth }) => {
|
||||
const res = await httpClient.sendRequest({
|
||||
method: HttpMethod.GET,
|
||||
url: baseApiUrl + 'api/user/leads',
|
||||
headers: {
|
||||
Authorization: "Bearer " + auth,
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
},
|
||||
});
|
||||
|
||||
if (res.status !== 200) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'Error fetching leads',
|
||||
options: [],
|
||||
};
|
||||
} else if (res.body.length === 0) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'No leads found.',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
options: res.body.map((lead: any) => ({
|
||||
value: lead.id,
|
||||
label: `${lead.phone_number} - ${lead.campaign.name}`,
|
||||
})),
|
||||
};
|
||||
}
|
||||
})
|
||||
},
|
||||
async run(context) {
|
||||
const leadId = context.propsValue['lead'];
|
||||
|
||||
const res = await httpClient.sendRequest<string[]>({
|
||||
method: HttpMethod.DELETE,
|
||||
url: baseApiUrl + 'api/user/leads/' + leadId,
|
||||
headers: {
|
||||
Authorization: "Bearer " + context.auth.secret_text,
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
},
|
||||
});
|
||||
return res.body;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,79 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { httpClient, HttpMethod } from '@activepieces/pieces-common';
|
||||
import { autocallsAuth, baseApiUrl } from '../..';
|
||||
|
||||
export const makePhoneCall = createAction({
|
||||
auth:autocallsAuth,
|
||||
name: 'makePhoneCall',
|
||||
displayName: 'Make Phone Call',
|
||||
description: "Call a customer by it's phone number using an assistant from our platform.",
|
||||
props: {
|
||||
assistant: Property.Dropdown({
|
||||
auth: autocallsAuth,
|
||||
displayName: 'Assistant',
|
||||
description: 'Select an assistant',
|
||||
required: true,
|
||||
refreshers: ['auth'],
|
||||
refreshOnSearch: false,
|
||||
options: async ({ auth }) => {
|
||||
const res = await httpClient.sendRequest({
|
||||
method: HttpMethod.GET,
|
||||
url: baseApiUrl + 'api/user/assistants/outbound',
|
||||
headers: {
|
||||
Authorization: "Bearer " + auth?.secret_text,
|
||||
},
|
||||
});
|
||||
|
||||
if (res.status !== 200) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'Error fetching assistants',
|
||||
options: [],
|
||||
};
|
||||
} else if (res.body.length === 0) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'No outbound assistants found. Create one first.',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
options: res.body.map((assistant: any) => ({
|
||||
value: assistant.id,
|
||||
label: assistant.name,
|
||||
})),
|
||||
};
|
||||
}
|
||||
}),
|
||||
phone_number: Property.ShortText({
|
||||
displayName: 'Customer phone number',
|
||||
description: 'Enter the phone number of the customer',
|
||||
required: true,
|
||||
}),
|
||||
|
||||
variables: Property.Object({
|
||||
displayName: 'Variables',
|
||||
description: 'Variables to pass to the assistant',
|
||||
required: true,
|
||||
defaultValue: {
|
||||
customer_name: 'John',
|
||||
}
|
||||
})
|
||||
},
|
||||
async run(context) {
|
||||
const res = await httpClient.sendRequest<string[]>({
|
||||
method: HttpMethod.POST,
|
||||
url: baseApiUrl + 'api/user/make_call',
|
||||
body: {
|
||||
assistant_id: context.propsValue['assistant'],
|
||||
phone_number: context.propsValue['phone_number'],
|
||||
variables: context.propsValue['variables'],
|
||||
},
|
||||
headers: {
|
||||
Authorization: "Bearer " + context.auth.secret_text,
|
||||
},
|
||||
});
|
||||
return res.body;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,80 @@
|
||||
import { createAction, Property} from '@activepieces/pieces-framework';
|
||||
import { httpClient, HttpMethod } from '@activepieces/pieces-common';
|
||||
import { autocallsAuth, baseApiUrl } from '../..';
|
||||
|
||||
export const sendSms = createAction({
|
||||
auth:autocallsAuth,
|
||||
name: 'sendSms',
|
||||
displayName: 'Send SMS to Customer',
|
||||
description: "Send an SMS to a customer using a phone number from our platform.",
|
||||
props: {
|
||||
from: Property.Dropdown({
|
||||
auth: autocallsAuth,
|
||||
displayName: 'From phone number',
|
||||
description: 'Select an SMS capable phone number to send the SMS from',
|
||||
required: true,
|
||||
refreshers: ['auth'],
|
||||
refreshOnSearch: false,
|
||||
options: async ({ auth }) => {
|
||||
const res = await httpClient.sendRequest({
|
||||
method: HttpMethod.GET,
|
||||
url: baseApiUrl + 'api/user/phone-numbers',
|
||||
headers: {
|
||||
Authorization: "Bearer " + auth?.secret_text,
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
},
|
||||
});
|
||||
|
||||
if (res.status !== 200) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'Error fetching phone numbers',
|
||||
options: [],
|
||||
};
|
||||
} else if (res.body.length === 0) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'No phone numbers found. Purchase an SMS capable phone number first.',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
options: res.body.map((phoneNumber: any) => ({
|
||||
value: phoneNumber.id,
|
||||
label: phoneNumber.phone_number,
|
||||
})),
|
||||
};
|
||||
}
|
||||
}),
|
||||
to: Property.ShortText({
|
||||
displayName: 'Customer phone number',
|
||||
description: 'Enter the phone number of the customer',
|
||||
required: true,
|
||||
}),
|
||||
|
||||
body: Property.ShortText({
|
||||
displayName: 'Text message',
|
||||
description: 'Enter the text message to send to the customer (max 300 characters)',
|
||||
required: true,
|
||||
}),
|
||||
},
|
||||
async run(context) {
|
||||
const res = await httpClient.sendRequest<string[]>({
|
||||
method: HttpMethod.POST,
|
||||
url: baseApiUrl + 'api/user/sms',
|
||||
body: {
|
||||
from: context.propsValue['from'],
|
||||
to: context.propsValue['to'],
|
||||
body: context.propsValue['body'],
|
||||
},
|
||||
headers: {
|
||||
Authorization: "Bearer " + context.auth.secret_text,
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
},
|
||||
});
|
||||
return res.body;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,109 @@
|
||||
import { createTrigger, TriggerStrategy, Property, AppConnectionValueForAuthProperty } from '@activepieces/pieces-framework';
|
||||
import { DedupeStrategy, Polling, pollingHelper, httpClient, HttpMethod } from '@activepieces/pieces-common';
|
||||
import { autocallsAuth, baseApiUrl } from '../..';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
const polling: Polling<AppConnectionValueForAuthProperty<typeof autocallsAuth>, { start?: string; end?: string }> = {
|
||||
strategy: DedupeStrategy.TIMEBASED,
|
||||
items: async ({ auth, propsValue }) => {
|
||||
const res = await httpClient.sendRequest({
|
||||
method: HttpMethod.GET,
|
||||
url: baseApiUrl + 'api/user/assistants',
|
||||
headers: {
|
||||
Authorization: 'Bearer ' + auth.secret_text,
|
||||
},
|
||||
});
|
||||
|
||||
if (res.status !== 200) {
|
||||
throw new Error(`Failed to fetch assistants. Status: ${res.status}`);
|
||||
}
|
||||
|
||||
const assistants =
|
||||
(res.body as Array<{
|
||||
id: number;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}>) || [];
|
||||
|
||||
const filteredAssistants = assistants.filter((assistant) => {
|
||||
const assistantDate = assistant.created_at
|
||||
? dayjs(assistant.created_at)
|
||||
: dayjs(assistant.updated_at);
|
||||
|
||||
// Check start date filter
|
||||
if (propsValue['start']) {
|
||||
const startDate = dayjs(propsValue['start']);
|
||||
if (assistantDate.isBefore(startDate)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check end date filter
|
||||
if (propsValue['end']) {
|
||||
const endDate = dayjs(propsValue['end']);
|
||||
if (assistantDate.isAfter(endDate)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
return filteredAssistants.map((assistant) => {
|
||||
const assistantDate = assistant.created_at
|
||||
? dayjs(assistant.created_at)
|
||||
: dayjs(assistant.updated_at);
|
||||
return {
|
||||
epochMilliSeconds: assistantDate.valueOf(),
|
||||
data: assistant,
|
||||
};
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export const getAssistants = createTrigger({
|
||||
auth:autocallsAuth,
|
||||
name: 'getAssistants',
|
||||
displayName: 'Updated Assistant',
|
||||
description: 'Triggers when assistants are fetched or updated in your Autocalls account.',
|
||||
props: {
|
||||
start: Property.DateTime({
|
||||
displayName: 'Start Date',
|
||||
description: 'Filter assistants created after this date. Example: 2024-01-15T10:30:00Z',
|
||||
required: false,
|
||||
}),
|
||||
end: Property.DateTime({
|
||||
displayName: 'End Date',
|
||||
description: 'Filter assistants created before this date. Example: 2024-12-31T23:59:59Z',
|
||||
required: false,
|
||||
}),
|
||||
},
|
||||
sampleData: {
|
||||
id: "assistant_123",
|
||||
name: "Customer Support Assistant",
|
||||
description: "Handles customer inquiries and support requests",
|
||||
status: "active",
|
||||
created_at: "2024-01-15T10:30:00Z",
|
||||
updated_at: "2024-01-15T14:20:00Z",
|
||||
settings: {
|
||||
voice: "en-US-female",
|
||||
language: "en-US",
|
||||
max_duration: 300
|
||||
}
|
||||
},
|
||||
type: TriggerStrategy.POLLING,
|
||||
async test(context) {
|
||||
return await pollingHelper.test(polling, context);
|
||||
},
|
||||
async onEnable(context) {
|
||||
const { store, auth, propsValue } = context;
|
||||
await pollingHelper.onEnable(polling, { store, auth, propsValue });
|
||||
},
|
||||
async onDisable(context) {
|
||||
const { store, auth, propsValue } = context;
|
||||
await pollingHelper.onDisable(polling, { store, auth, propsValue });
|
||||
},
|
||||
async run(context) {
|
||||
return await pollingHelper.poll(polling, context);
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,89 @@
|
||||
import { createTrigger, Property, TriggerStrategy } from '@activepieces/pieces-framework';
|
||||
import { httpClient, HttpMethod } from '@activepieces/pieces-common';
|
||||
import { autocallsAuth, baseApiUrl } from '../..';
|
||||
|
||||
export const inboundCall = createTrigger({
|
||||
auth:autocallsAuth,
|
||||
name: 'inboundCall',
|
||||
displayName: 'Inbound Call',
|
||||
description: 'Triggers for variables before connecting an inbound call.',
|
||||
props: {
|
||||
assistant: Property.Dropdown({
|
||||
auth: autocallsAuth,
|
||||
displayName: 'Assistant',
|
||||
description: 'Select an assistant',
|
||||
required: true,
|
||||
refreshers: ['auth'],
|
||||
refreshOnSearch: false,
|
||||
options: async ({ auth }) => {
|
||||
const res = await httpClient.sendRequest({
|
||||
method: HttpMethod.GET,
|
||||
url: baseApiUrl + 'api/user/assistants',
|
||||
headers: {
|
||||
Authorization: "Bearer " + auth?.secret_text,
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
},
|
||||
});
|
||||
|
||||
if (res.status !== 200) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'Error fetching assistants',
|
||||
options: [],
|
||||
};
|
||||
} else if (res.body.length === 0) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'No assistants found. Create one first.',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
options: res.body.map((assistant: any) => ({
|
||||
value: assistant.id,
|
||||
label: assistant.name,
|
||||
})),
|
||||
};
|
||||
}
|
||||
}),
|
||||
},
|
||||
sampleData: {
|
||||
customer_phone: '+16380991171',
|
||||
assistant_phone: '+16380991171',
|
||||
},
|
||||
type: TriggerStrategy.WEBHOOK,
|
||||
async onEnable(context) {
|
||||
await httpClient.sendRequest({
|
||||
method: HttpMethod.POST,
|
||||
url: baseApiUrl + 'api/user/assistants/enable-inbound-webhook',
|
||||
body: {
|
||||
assistant_id: context.propsValue['assistant'],
|
||||
webhook_url: context.webhookUrl,
|
||||
},
|
||||
headers: {
|
||||
Authorization: "Bearer " + context.auth.secret_text,
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
},
|
||||
});
|
||||
},
|
||||
async onDisable(context) {
|
||||
await httpClient.sendRequest({
|
||||
method: HttpMethod.POST,
|
||||
url: baseApiUrl + 'api/user/assistants/disable-inbound-webhook',
|
||||
body: {
|
||||
assistant_id: context.propsValue['assistant'],
|
||||
},
|
||||
headers: {
|
||||
Authorization: "Bearer " + context.auth.secret_text,
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
},
|
||||
});
|
||||
},
|
||||
async run(context) {
|
||||
return [context.payload.body]
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,114 @@
|
||||
import { createTrigger, Property, TriggerStrategy } from '@activepieces/pieces-framework';
|
||||
import { httpClient, HttpMethod } from '@activepieces/pieces-common';
|
||||
import { autocallsAuth, baseApiUrl } from '../..';
|
||||
|
||||
export const phoneCallEnded = createTrigger({
|
||||
auth:autocallsAuth,
|
||||
name: 'phoneCallEnded',
|
||||
displayName: 'Phone Call Ended',
|
||||
description: 'Triggers when a phone call ends, with extracted variables.',
|
||||
props: {
|
||||
assistant: Property.Dropdown({
|
||||
auth: autocallsAuth,
|
||||
displayName: 'Assistant',
|
||||
description: 'Select an assistant',
|
||||
required: true,
|
||||
refreshers: ['auth'],
|
||||
refreshOnSearch: false,
|
||||
options: async ({ auth }) => {
|
||||
const res = await httpClient.sendRequest({
|
||||
method: HttpMethod.GET,
|
||||
url: baseApiUrl + 'api/user/assistants',
|
||||
headers: {
|
||||
Authorization: "Bearer " + auth?.secret_text,
|
||||
},
|
||||
});
|
||||
|
||||
if (res.status !== 200) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'Error fetching assistants',
|
||||
options: [],
|
||||
};
|
||||
} else if (res.body.length === 0) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'No assistants found. Create one first.',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
options: res.body.map((assistant: {id:number,name:string}) => ({
|
||||
value: assistant.id,
|
||||
label: assistant.name,
|
||||
})),
|
||||
};
|
||||
}
|
||||
}),
|
||||
},
|
||||
sampleData: {
|
||||
customer_phone: '+16380991171',
|
||||
assistant_phone: '+16380991171',
|
||||
duration: 120,
|
||||
status: 'completed',
|
||||
extracted_variables: {
|
||||
status: false,
|
||||
summary: 'Call ended without clear objective being met.'
|
||||
},
|
||||
input_variables: {
|
||||
customer_name: 'John'
|
||||
},
|
||||
transcript: [
|
||||
{
|
||||
sender: 'bot',
|
||||
timestamp: 1722347063.574402,
|
||||
text: 'Hi! How are you, John?'
|
||||
},
|
||||
{
|
||||
sender: 'human',
|
||||
timestamp: 1722347068.886166,
|
||||
text: 'Im fine. How about you?'
|
||||
},
|
||||
{
|
||||
sender: 'bot',
|
||||
timestamp: 1722347069.76683,
|
||||
text: 'Im doing well, thank you for asking.'
|
||||
},
|
||||
{
|
||||
sender: 'bot',
|
||||
timestamp: 1722347071.577889,
|
||||
text: 'How can I assist you today?'
|
||||
},
|
||||
]
|
||||
},
|
||||
type: TriggerStrategy.WEBHOOK,
|
||||
async onEnable(context) {
|
||||
await httpClient.sendRequest({
|
||||
method: HttpMethod.POST,
|
||||
url: baseApiUrl + 'api/user/assistants/enable-webhook',
|
||||
body: {
|
||||
assistant_id: context.propsValue['assistant'],
|
||||
webhook_url: context.webhookUrl,
|
||||
},
|
||||
headers: {
|
||||
Authorization: "Bearer " + context.auth.secret_text,
|
||||
},
|
||||
});
|
||||
},
|
||||
async onDisable(context) {
|
||||
await httpClient.sendRequest({
|
||||
method: HttpMethod.POST,
|
||||
url: baseApiUrl + 'api/user/assistants/disable-webhook',
|
||||
body: {
|
||||
assistant_id: context.propsValue['assistant'],
|
||||
},
|
||||
headers: {
|
||||
Authorization: "Bearer " + context.auth.secret_text,
|
||||
},
|
||||
});
|
||||
},
|
||||
async run(context) {
|
||||
return [context.payload.body]
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user