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:
poduck
2025-12-18 22:59:37 -05:00
parent 9848268d34
commit 3aa7199503
16292 changed files with 1284892 additions and 4708 deletions

View File

@@ -0,0 +1,76 @@
import { birdAuth } from '../auth';
import { createAction, Property } from '@activepieces/pieces-framework';
import {
httpClient,
HttpMethod,
} from '@activepieces/pieces-common';
import dayjs from 'dayjs';
export const listMessages = createAction({
auth: birdAuth,
name: 'listMessages',
displayName: 'List Messages',
description: 'Lists an Messages via Bird Channels API',
props: {
status : Property.StaticDropdown({
displayName: 'Status',
description: 'The status of the messages to filter by (select "All" for all statuses)',
required: true,
options: {
options: [
{ label: 'All', value: 'all' },
{ label: 'Pending', value: 'pending' },
{ label: 'Accepted', value: 'accepted' },
{ label: 'Rejected', value: 'rejected' },
{ label: 'Processing', value: 'processing' },
{ label: 'Scheduled', value: 'scheduled' },
{ label: 'Sent', value: 'sent' },
{ label: 'Sending Failed', value: 'sending_failed' },
{ label: 'Delivered', value: 'delivered' },
{ label: 'Delivery Failed', value: 'delivery_failed' },
{ label: 'Deleted', value: 'deleted' },
{ label: 'Skipped', value: 'skipped' },
]},
}),
startAt: Property.DateTime({
displayName: 'Start Date and Time',
description: 'The start date and time (in UTC) to filter messages',
required: true,
defaultValue: dayjs().subtract(1, 'day').format('YYYY-MM-DDTHH:mm:ss[Z]'),
}),
endAt: Property.DateTime({
displayName: 'End Date and Time',
description: 'The end date and time (in UTC) to filter messages, should not exceed 7 days from start date',
required: true,
defaultValue: dayjs().format('YYYY-MM-DDTHH:mm:ss[Z]'),
}),
pageToken: Property.ShortText({
displayName: 'Next Page Token',
description: 'Token for pagination to fetch next set of results after 1000 messages',
required: false,
}),
},
async run(context) {
const { status, startAt, endAt, pageToken } = context.propsValue;
const auth = context.auth.props;
const response = await httpClient.sendRequest<any>({
method: HttpMethod.GET,
url: `https://api.bird.com/workspaces/${auth.workspaceId}/channels/${auth.channelId}/messages`,
queryParams: {
limit: '1000',
...(status === 'all' ? {} : { status: status }),
startAt: startAt,
endAt: endAt,
...(pageToken ? { pageToken: pageToken } : {}),
},
headers: {
'Authorization': `Bearer ${auth.apiKey}`,
'Content-Type': 'application/json',
},
});
return response.body
},
});

View File

@@ -0,0 +1,69 @@
import { birdAuth } from '../auth';
import { createAction, Property } from '@activepieces/pieces-framework';
import {
httpClient,
HttpMethod,
HttpRequest,
} from '@activepieces/pieces-common';
export const sendSMSAction = createAction({
auth: birdAuth,
name: 'send-sms',
displayName: 'Send SMS',
description: 'Sends an SMS message via Bird Channels API.',
props: {
recipient: Property.ShortText({
displayName: 'Recipient',
description: 'The phone number to send the message to (with country code)',
required: true,
}),
message: Property.LongText({
displayName: 'Message',
description: 'The body of the SMS message',
required: true,
}),
reference: Property.ShortText({
displayName: 'Reference',
description: 'Your own identifier for the message (optional)',
required: false,
}),
scheduledFor: Property.DateTime({
displayName: 'Scheduled For (UTC timestamp)',
description: 'Message to be sent at a specific datetime eg. 2025-04-27T15:08:18.613Z. If not set, the message will be sent immediately.',
required: false,
}),
},
async run(context) {
const { recipient, message, reference, scheduledFor } = context.propsValue;
const auth = context.auth.props;
// Format request for Bird Channels API
const request: HttpRequest = {
method: HttpMethod.POST,
url: `https://api.bird.com/workspaces/${auth.workspaceId}/channels/${auth.channelId}/messages`,
headers: {
'Authorization': `Bearer ${auth.apiKey}`,
'Content-Type': 'application/json'
},
body: {
receiver: {
contacts: [
{
identifierValue: recipient
}
]
},
body: {
type: 'text',
text: {
text: message
}
},
...(reference && { reference }),
...(scheduledFor && { scheduledFor }),
},
};
return await httpClient.sendRequest(request);
},
});

View File

@@ -0,0 +1,28 @@
import { PieceAuth } from '@activepieces/pieces-framework';
export interface BirdAuthValue {
apiKey: string;
workspaceId: string;
channelId: string;
}
export const birdAuth = PieceAuth.CustomAuth({
props: {
apiKey: PieceAuth.SecretText({
displayName: 'API Key',
description: 'Bird API Access Key from Settings > Security > Access Keys',
required: true,
}),
workspaceId: PieceAuth.SecretText({
displayName: 'Workspace ID',
description: 'Bird Workspace ID found in your workspace URL',
required: true,
}),
channelId: PieceAuth.SecretText({
displayName: 'Channel ID',
description: 'Your SMS channel ID from Bird dashboard',
required: true,
}),
},
required: true,
});