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:
co-authored by
Claude Opus 4.5
parent
9848268d34
commit
3aa7199503
+71
@@ -0,0 +1,71 @@
|
||||
import { createAction, Property } from "@activepieces/pieces-framework";
|
||||
import { AuthenticationType, httpClient, HttpMethod } from "@activepieces/pieces-common";
|
||||
import { emailOctopusAuth } from "../common/auth";
|
||||
import { emailOctopusProps } from "../common/props";
|
||||
|
||||
export const addOrUpdateContact = createAction({
|
||||
auth: emailOctopusAuth,
|
||||
name: 'add_or_update_contact',
|
||||
displayName: 'Add / Update Contact',
|
||||
description: 'Adds a new contact to a list or updates an existing contact if one exists.',
|
||||
props: {
|
||||
list_id: emailOctopusProps.listId(),
|
||||
email_address: Property.ShortText({
|
||||
displayName: 'Email Address',
|
||||
description: "The contact's email address.",
|
||||
required: true,
|
||||
}),
|
||||
fields: emailOctopusProps.fields(),
|
||||
tags: Property.Array({
|
||||
displayName: 'Tags',
|
||||
description: 'Tags to associate with the contact. Existing tags will not be removed.',
|
||||
required: false,
|
||||
}),
|
||||
status: Property.StaticDropdown({
|
||||
displayName: 'Status',
|
||||
description: 'The status of the contact.',
|
||||
required: false,
|
||||
options: {
|
||||
options: [
|
||||
{ label: 'Subscribed', value: 'subscribed' },
|
||||
{ label: 'Unsubscribed', value: 'unsubscribed' },
|
||||
{ label: 'Pending', value: 'pending' },
|
||||
],
|
||||
},
|
||||
}),
|
||||
},
|
||||
|
||||
async run(context) {
|
||||
const { list_id, email_address, fields, tags, status } = context.propsValue;
|
||||
|
||||
const body: Record<string, unknown> = {
|
||||
email_address: email_address,
|
||||
};
|
||||
|
||||
if (fields) {
|
||||
body['fields'] = Object.fromEntries(
|
||||
Object.entries(fields).filter(([, value]) => value !== null && value !== undefined && value !== '')
|
||||
);
|
||||
}
|
||||
if (status) {
|
||||
body['status'] = status;
|
||||
}
|
||||
if (tags && (tags as string[]).length > 0) {
|
||||
body['tags'] = Object.fromEntries(
|
||||
(tags as string[]).map(tag => [tag, true])
|
||||
);
|
||||
}
|
||||
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.PUT,
|
||||
url: `https://api.emailoctopus.com/lists/${list_id}/contacts`,
|
||||
body: body,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: context.auth.secret_text,
|
||||
},
|
||||
});
|
||||
|
||||
return response.body;
|
||||
},
|
||||
});
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
import { createAction, Property } from "@activepieces/pieces-framework";
|
||||
import { HttpMethod } from "@activepieces/pieces-common";
|
||||
import { createHash } from "crypto";
|
||||
import { emailOctopusAuth } from "../common/auth";
|
||||
import { EmailOctopusClient } from "../common/client";
|
||||
import { emailOctopusProps } from "../common/props";
|
||||
|
||||
export const addTagToContact = createAction({
|
||||
auth: emailOctopusAuth,
|
||||
name: 'add_tag_to_contact',
|
||||
displayName: 'Add Tag to Contact',
|
||||
description: 'Add one or more tags to a contact in a specified list.',
|
||||
props: {
|
||||
list_id: emailOctopusProps.listId(),
|
||||
email_address: Property.ShortText({
|
||||
displayName: 'Email Address',
|
||||
description: "The contact's email address.",
|
||||
required: true,
|
||||
}),
|
||||
tags: Property.Array({
|
||||
displayName: 'Tags',
|
||||
description: 'The tags to add to the contact.',
|
||||
required: true,
|
||||
}),
|
||||
},
|
||||
|
||||
async run(context) {
|
||||
const { list_id, email_address, tags } = context.propsValue;
|
||||
const client = new EmailOctopusClient(context.auth.secret_text);
|
||||
|
||||
|
||||
const contactId = createHash('md5')
|
||||
.update(email_address.toLowerCase())
|
||||
.digest('hex');
|
||||
|
||||
|
||||
const tagsObject = Object.fromEntries(
|
||||
(tags as string[]).map(tag => [tag, true])
|
||||
);
|
||||
|
||||
const body = {
|
||||
tags: tagsObject,
|
||||
};
|
||||
|
||||
|
||||
return await client.makeRequest(
|
||||
HttpMethod.PUT,
|
||||
`/lists/${list_id}/contacts/${contactId}`,
|
||||
body
|
||||
);
|
||||
},
|
||||
});
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
import { createAction, Property } from "@activepieces/pieces-framework";
|
||||
import { HttpMethod } from "@activepieces/pieces-common";
|
||||
import { emailOctopusAuth } from "../common/auth";
|
||||
import { EmailOctopusClient } from "../common/client";
|
||||
|
||||
export const createList = createAction({
|
||||
auth: emailOctopusAuth,
|
||||
name: 'create_list',
|
||||
displayName: 'Create List',
|
||||
description: 'Creates a new mailing list.',
|
||||
props: {
|
||||
name: Property.ShortText({
|
||||
displayName: 'List Name',
|
||||
description: 'The name for the new list.',
|
||||
required: true,
|
||||
}),
|
||||
},
|
||||
|
||||
async run(context) {
|
||||
const { name } = context.propsValue;
|
||||
const client = new EmailOctopusClient(context.auth.secret_text);
|
||||
|
||||
const body = {
|
||||
name,
|
||||
};
|
||||
|
||||
|
||||
return await client.makeRequest(
|
||||
HttpMethod.POST,
|
||||
`/lists`,
|
||||
body
|
||||
);
|
||||
},
|
||||
});
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
import { createAction, Property } from "@activepieces/pieces-framework";
|
||||
// 👇 1. Remove `isAxiosError` and import `HttpError` instead
|
||||
import { HttpError, HttpMethod } from "@activepieces/pieces-common";
|
||||
import { createHash } from "crypto";
|
||||
import { emailOctopusAuth } from "../common/auth";
|
||||
import { EmailOctopusClient } from "../common/client";
|
||||
import { emailOctopusProps } from "../common/props";
|
||||
|
||||
export const findContact = createAction({
|
||||
auth: emailOctopusAuth,
|
||||
name: 'find_contact',
|
||||
displayName: 'Find Contact',
|
||||
description: 'Finds a contact by email address within a given list.',
|
||||
props: {
|
||||
list_id: emailOctopusProps.listId(),
|
||||
email_address: Property.ShortText({
|
||||
displayName: 'Email Address',
|
||||
description: 'The email address of the contact to find.',
|
||||
required: true,
|
||||
}),
|
||||
},
|
||||
|
||||
async run(context) {
|
||||
const { list_id, email_address } = context.propsValue;
|
||||
const client = new EmailOctopusClient(context.auth.secret_text);
|
||||
|
||||
const contactId = createHash('md5')
|
||||
.update(email_address.toLowerCase())
|
||||
.digest('hex');
|
||||
|
||||
try {
|
||||
const response = await client.makeRequest(
|
||||
HttpMethod.GET,
|
||||
`/lists/${list_id}/contacts/${contactId}`
|
||||
);
|
||||
|
||||
return {
|
||||
found:true,
|
||||
result:response
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
if (error instanceof HttpError && error.response.status === 404) {
|
||||
return {
|
||||
found:false,
|
||||
result:{}
|
||||
};
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
});
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
import { createAction, Property } from "@activepieces/pieces-framework";
|
||||
import { HttpMethod } from "@activepieces/pieces-common";
|
||||
import { createHash } from "crypto";
|
||||
import { emailOctopusAuth } from "../common/auth";
|
||||
import { EmailOctopusClient } from "../common/client";
|
||||
import { emailOctopusProps } from "../common/props";
|
||||
|
||||
export const removeTagFromContact = createAction({
|
||||
auth: emailOctopusAuth,
|
||||
name: 'remove_tag_from_contact',
|
||||
displayName: 'Remove Tag from Contact',
|
||||
description: 'Remove one or more tags from a contact in a specified list.',
|
||||
props: {
|
||||
list_id: emailOctopusProps.listId(),
|
||||
email_address: Property.ShortText({
|
||||
displayName: 'Email Address',
|
||||
description: "The email address of the contact to modify.",
|
||||
required: true,
|
||||
}),
|
||||
tags: Property.Array({
|
||||
displayName: 'Tags',
|
||||
description: 'The tags to remove from the contact.',
|
||||
required: true,
|
||||
}),
|
||||
},
|
||||
|
||||
async run(context) {
|
||||
const { list_id, email_address, tags } = context.propsValue;
|
||||
const client = new EmailOctopusClient(context.auth.secret_text);
|
||||
|
||||
|
||||
const contactId = createHash('md5')
|
||||
.update(email_address.toLowerCase())
|
||||
.digest('hex');
|
||||
|
||||
|
||||
const tagsObject = Object.fromEntries(
|
||||
(tags as string[]).map(tag => [tag, false])
|
||||
);
|
||||
|
||||
const body = {
|
||||
tags: tagsObject,
|
||||
};
|
||||
|
||||
|
||||
return await client.makeRequest(
|
||||
HttpMethod.PUT,
|
||||
`/lists/${list_id}/contacts/${contactId}`,
|
||||
body
|
||||
);
|
||||
},
|
||||
});
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
import { createAction, Property } from "@activepieces/pieces-framework";
|
||||
import { HttpMethod } from "@activepieces/pieces-common";
|
||||
import { createHash } from "crypto";
|
||||
import { emailOctopusAuth } from "../common/auth";
|
||||
import { EmailOctopusClient } from "../common/client";
|
||||
import { emailOctopusProps } from "../common/props";
|
||||
|
||||
export const unsubscribeContact = createAction({
|
||||
auth: emailOctopusAuth,
|
||||
name: 'unsubscribe_contact',
|
||||
displayName: 'Unsubscribe Contact',
|
||||
description: 'Sets a contact\'s status to "Unsubscribed" in a specific list.',
|
||||
props: {
|
||||
list_id: emailOctopusProps.listId(),
|
||||
email_address: Property.ShortText({
|
||||
displayName: 'Email Address',
|
||||
description: "The email address of the contact to unsubscribe.",
|
||||
required: true,
|
||||
}),
|
||||
},
|
||||
|
||||
async run(context) {
|
||||
const { list_id, email_address } = context.propsValue;
|
||||
const client = new EmailOctopusClient(context.auth.secret_text);
|
||||
|
||||
|
||||
const contactId = createHash('md5')
|
||||
.update(email_address.toLowerCase())
|
||||
.digest('hex');
|
||||
|
||||
const body = {
|
||||
status: 'unsubscribed',
|
||||
};
|
||||
|
||||
|
||||
return await client.makeRequest(
|
||||
HttpMethod.PUT,
|
||||
`/lists/${list_id}/contacts/${contactId}`,
|
||||
body
|
||||
);
|
||||
},
|
||||
});
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
import { createAction, Property } from "@activepieces/pieces-framework";
|
||||
import { HttpMethod } from "@activepieces/pieces-common";
|
||||
import { createHash } from "crypto";
|
||||
import { emailOctopusAuth } from "../common/auth";
|
||||
import { EmailOctopusClient } from "../common/client";
|
||||
import { emailOctopusProps } from "../common/props";
|
||||
|
||||
export const updateContactEmail = createAction({
|
||||
auth: emailOctopusAuth,
|
||||
name: 'update_contact_email',
|
||||
displayName: "Update Contact's Email Address",
|
||||
description: "Change the email address of a contact in a list.",
|
||||
props: {
|
||||
list_id: emailOctopusProps.listId(),
|
||||
current_email_address: Property.ShortText({
|
||||
displayName: 'Current Email Address',
|
||||
description: "The contact's current email address used to find them.",
|
||||
required: true,
|
||||
}),
|
||||
new_email_address: Property.ShortText({
|
||||
displayName: 'New Email Address',
|
||||
description: "The new email address for the contact.",
|
||||
required: true,
|
||||
}),
|
||||
},
|
||||
|
||||
async run(context) {
|
||||
const { list_id, current_email_address, new_email_address } = context.propsValue;
|
||||
const client = new EmailOctopusClient(context.auth.secret_text);
|
||||
|
||||
|
||||
const contactId = createHash('md5')
|
||||
.update(current_email_address.toLowerCase())
|
||||
.digest('hex');
|
||||
|
||||
const body = {
|
||||
email_address: new_email_address,
|
||||
};
|
||||
|
||||
|
||||
return await client.makeRequest(
|
||||
HttpMethod.PUT,
|
||||
`/lists/${list_id}/contacts/${contactId}`,
|
||||
body
|
||||
);
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,37 @@
|
||||
import { PieceAuth } from '@activepieces/pieces-framework';
|
||||
import { httpClient, HttpMethod, AuthenticationType } from '@activepieces/pieces-common';
|
||||
|
||||
// The base URL for the EmailOctopus API
|
||||
const emailOctopusApiUrl = 'https://api.emailoctopus.com';
|
||||
|
||||
export const emailOctopusAuth = PieceAuth.SecretText({
|
||||
displayName: 'API Key',
|
||||
description: `
|
||||
To get your API key:
|
||||
1. Log in to your EmailOctopus account.
|
||||
2. Go to your **account settings**.
|
||||
3. Generate a new API key.
|
||||
**Note:** If you have a 'legacy' key, you must generate a new one for API v2.
|
||||
`,
|
||||
required: true,
|
||||
validate: async ({ auth }) => {
|
||||
try {
|
||||
await httpClient.sendRequest({
|
||||
method: HttpMethod.GET,
|
||||
url: `${emailOctopusApiUrl}/lists`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: auth,
|
||||
},
|
||||
});
|
||||
return {
|
||||
valid: true,
|
||||
};
|
||||
} catch (e) {
|
||||
return {
|
||||
valid: false,
|
||||
error: 'Invalid API key.',
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,70 @@
|
||||
import { httpClient, HttpMethod, HttpRequest } from "@activepieces/pieces-common";
|
||||
|
||||
export const emailOctopusApiUrl = 'https://api.emailoctopus.com';
|
||||
|
||||
|
||||
export interface EmailOctopusListDetails extends EmailOctopusList {
|
||||
fields: {
|
||||
tag: string;
|
||||
type: 'text' | 'number' | 'date'|'choice_single'|'choice_multiple'
|
||||
label: string;
|
||||
choices:string[]
|
||||
}[];
|
||||
}
|
||||
|
||||
export class EmailOctopusClient {
|
||||
constructor(private apiKey: string) {}
|
||||
|
||||
async makeRequest<T>(method: HttpMethod, url: string, body?: object): Promise<T> {
|
||||
const request: HttpRequest<object> = {
|
||||
method,
|
||||
url: `${emailOctopusApiUrl}${url}`,
|
||||
body: body,
|
||||
headers: {
|
||||
"Accept": "application/json",
|
||||
"Content-Type": "application/json",
|
||||
"Authorization":`Bearer ${this.apiKey}`
|
||||
},
|
||||
};
|
||||
|
||||
const { body: responseBody } = await httpClient.sendRequest<T>(request);
|
||||
return responseBody;
|
||||
}
|
||||
|
||||
async getLists(): Promise<EmailOctopusList[]> {
|
||||
const response = await this.makeRequest<{ data: EmailOctopusList[] }>(
|
||||
HttpMethod.GET,
|
||||
'/lists'
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
|
||||
async getList(listId: string): Promise<EmailOctopusListDetails> {
|
||||
return await this.makeRequest<EmailOctopusListDetails>(
|
||||
HttpMethod.GET,
|
||||
`/lists/${listId}`
|
||||
);
|
||||
}
|
||||
|
||||
async getCampaigns(): Promise<EmailOctopusCampaign[]> {
|
||||
const response = await this.makeRequest<{ data: EmailOctopusCampaign[] }>(
|
||||
HttpMethod.GET,
|
||||
'/campaigns'
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
}
|
||||
|
||||
export interface EmailOctopusList {
|
||||
id: string;
|
||||
name: string;
|
||||
created_at: string;
|
||||
}
|
||||
|
||||
export interface EmailOctopusCampaign {
|
||||
id: string;
|
||||
name: string;
|
||||
status: string;
|
||||
created_at: string;
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
import {
|
||||
Property,
|
||||
DynamicPropsValue,
|
||||
DropdownState,
|
||||
InputPropertyMap,
|
||||
PropertyContext,
|
||||
} from '@activepieces/pieces-framework';
|
||||
import { EmailOctopusClient } from './client';
|
||||
import { emailOctopusAuth } from './auth';
|
||||
|
||||
type AuthAndProps = {
|
||||
auth: string | undefined;
|
||||
propsValue: Record<string, unknown>;
|
||||
};
|
||||
|
||||
export const emailOctopusProps = {
|
||||
listId: (required = true) =>
|
||||
Property.Dropdown({
|
||||
auth: emailOctopusAuth,
|
||||
displayName: 'List',
|
||||
description: 'The mailing list to use.',
|
||||
required: required,
|
||||
refreshers: [],
|
||||
options: async (context) => {
|
||||
const { auth } = context;
|
||||
if (!auth) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'Connect your account first',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
const client = new EmailOctopusClient(auth.secret_text);
|
||||
const lists = await client.getLists();
|
||||
return {
|
||||
disabled: false,
|
||||
options: lists.map((list) => ({
|
||||
label: list.name,
|
||||
value: list.id,
|
||||
})),
|
||||
};
|
||||
},
|
||||
}),
|
||||
|
||||
campaignId: (required = false) =>
|
||||
Property.Dropdown({
|
||||
auth: emailOctopusAuth,
|
||||
displayName: 'Campaign',
|
||||
description:
|
||||
'Select a campaign to filter events. Leave blank to trigger for all campaigns.',
|
||||
required: required,
|
||||
refreshers: [],
|
||||
options: async (context) => {
|
||||
const { auth } = context;
|
||||
if (!auth) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'Connect your account first',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
const client = new EmailOctopusClient(auth.secret_text);
|
||||
const campaigns = await client.getCampaigns();
|
||||
return {
|
||||
disabled: false,
|
||||
options: campaigns.map((campaign) => ({
|
||||
label: campaign.name,
|
||||
value: campaign.id,
|
||||
})),
|
||||
};
|
||||
},
|
||||
}),
|
||||
|
||||
fields: () =>
|
||||
Property.DynamicProperties({
|
||||
auth: emailOctopusAuth,
|
||||
displayName: 'Fields',
|
||||
description: "The contact's custom fields.",
|
||||
required: true,
|
||||
refreshers: ['list_id'],
|
||||
props: async ({ auth, list_id }): Promise<InputPropertyMap> => {
|
||||
if (!auth || !list_id) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const client = new EmailOctopusClient(auth.secret_text);
|
||||
const listDetails = await client.getList(list_id as unknown as string);
|
||||
|
||||
const fields: DynamicPropsValue = {};
|
||||
for (const field of listDetails.fields) {
|
||||
if (field.tag === 'EmailAddress') continue;
|
||||
switch (field.type) {
|
||||
case 'number':
|
||||
fields[field.tag] = Property.Number({
|
||||
displayName: field.label,
|
||||
required: false,
|
||||
});
|
||||
break;
|
||||
case 'date':
|
||||
fields[field.tag] = Property.ShortText({
|
||||
displayName: field.label,
|
||||
description: 'Date in YYYY-MM-DD format.',
|
||||
required: false,
|
||||
});
|
||||
break;
|
||||
case 'text':
|
||||
fields[field.tag] = Property.ShortText({
|
||||
displayName: field.label,
|
||||
required: false,
|
||||
});
|
||||
break;
|
||||
case 'choice_single':
|
||||
fields[field.tag] = Property.StaticDropdown({
|
||||
displayName: field.label,
|
||||
required: false,
|
||||
options: {
|
||||
disabled: false,
|
||||
options: field.choices
|
||||
? field.choices.map((opt) => ({ label: opt, value: opt }))
|
||||
: [],
|
||||
},
|
||||
});
|
||||
break;
|
||||
case 'choice_multiple':
|
||||
fields[field.tag] = Property.StaticMultiSelectDropdown({
|
||||
displayName: field.label,
|
||||
required: false,
|
||||
options: {
|
||||
disabled: false,
|
||||
options: field.choices
|
||||
? field.choices.map((opt) => ({ label: opt, value: opt }))
|
||||
: [],
|
||||
},
|
||||
});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return fields;
|
||||
},
|
||||
}),
|
||||
};
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
import { Property, createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
|
||||
import { emailOctopusAuth } from '../common/auth';
|
||||
import { emailOctopusProps } from '../common/props';
|
||||
import { MarkdownVariant } from '@activepieces/shared';
|
||||
|
||||
interface EmailOctopusEvent {
|
||||
type: string;
|
||||
id: string;
|
||||
contact_email_address: string;
|
||||
contact_fields?: Record<string, string>;
|
||||
contact_tags?: string[];
|
||||
contact_status?: string;
|
||||
list_id?: string;
|
||||
occurred_at?: string;
|
||||
}
|
||||
|
||||
export const contactUnsubscribes = createTrigger({
|
||||
auth: emailOctopusAuth,
|
||||
name: 'contactUnsubscribes',
|
||||
displayName: 'Contact Unsubscribes',
|
||||
description: 'Triggers when a contact unsubscribes from a list.',
|
||||
props: {
|
||||
list_id: emailOctopusProps.listId(true),
|
||||
liveMarkdown: Property.MarkDown({
|
||||
value: `
|
||||
**Live URL:**
|
||||
\`\`\`text
|
||||
{{webhookUrl}}
|
||||
\`\`\``,
|
||||
variant: MarkdownVariant.BORDERLESS,
|
||||
}),
|
||||
instructions: Property.MarkDown({
|
||||
value: `
|
||||
**Manual Setup Required**
|
||||
|
||||
1. Go to your EmailOctopus Dashboard.
|
||||
2. Navigate to **API & Integrations → Webhooks**.
|
||||
3. Click **Add webhook**.
|
||||
4. Paste the Above URL:
|
||||
5. Select the **Email unsubscribed** event.
|
||||
6. (Optional) Restrict to the specific list chosen above.
|
||||
7. Save the webhook.
|
||||
`,
|
||||
}),
|
||||
},
|
||||
sampleData: {
|
||||
id: '42636763-73f9-463e-af8b-3f720bb3d889',
|
||||
type: 'contact.unsubscribed',
|
||||
list_id: 'fa482fa2-5ac4-11ed-9f7a-67da1c836cf8',
|
||||
contact_id: 'e3ab8c80-5f65-11ed-835e-030e4bb63150',
|
||||
occurred_at: '2022-11-18T15:20:23+00:00',
|
||||
contact_fields: {
|
||||
LastName: 'Example',
|
||||
FirstName: 'Claire',
|
||||
},
|
||||
contact_status: 'unsubscribed',
|
||||
contact_email_address: 'claire@example.com',
|
||||
contact_tags: ['vip'],
|
||||
},
|
||||
type: TriggerStrategy.WEBHOOK,
|
||||
async onEnable() {
|
||||
return;
|
||||
},
|
||||
async onDisable() {
|
||||
return;
|
||||
},
|
||||
async run(context) {
|
||||
const events = context.payload.body;
|
||||
const listIdFilter = context.propsValue.list_id;
|
||||
|
||||
if (Array.isArray(events)) {
|
||||
return events.filter(
|
||||
(event: EmailOctopusEvent) =>
|
||||
event.type === 'contact.unsubscribed' &&
|
||||
(!listIdFilter || event.list_id === listIdFilter)
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
(events as EmailOctopusEvent)?.type === 'contact.unsubscribed' &&
|
||||
(!listIdFilter || (events as EmailOctopusEvent).list_id === listIdFilter)
|
||||
) {
|
||||
return [events];
|
||||
}
|
||||
|
||||
return [];
|
||||
},
|
||||
});
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
import { Property, createTrigger, TriggerStrategy } from '@activepieces/pieces-framework';
|
||||
import { emailOctopusProps } from '../common/props';
|
||||
import { emailOctopusAuth } from '../common/auth';
|
||||
import { MarkdownVariant } from '@activepieces/shared';
|
||||
|
||||
interface EmailOctopusEvent {
|
||||
type: string;
|
||||
id: string;
|
||||
contact_email_address: string;
|
||||
campaign_id?: string;
|
||||
list_id?: string;
|
||||
contact_id?: string;
|
||||
occurred_at?: string;
|
||||
}
|
||||
|
||||
export const emailClicked = createTrigger({
|
||||
auth: emailOctopusAuth,
|
||||
name: 'emailClicked',
|
||||
displayName: 'Email Clicked',
|
||||
description: 'Triggers when a link inside a specific campaign email is clicked.',
|
||||
props: {
|
||||
campaign_id: emailOctopusProps.campaignId(),
|
||||
liveMarkdown: Property.MarkDown({
|
||||
value: `
|
||||
**Live URL:**
|
||||
\`\`\`text
|
||||
{{webhookUrl}}
|
||||
\`\`\``,
|
||||
variant: MarkdownVariant.BORDERLESS,
|
||||
}),
|
||||
instructions: Property.MarkDown({
|
||||
value: `
|
||||
**Manual Setup Required**
|
||||
|
||||
1. Go to your EmailOctopus Dashboard.
|
||||
2. Navigate to **API & Integrations** → **Webhooks**.
|
||||
3. Click **Add webhook**.
|
||||
4. Paste the Above URL into the **URL** field:
|
||||
5. Select the **Email clicked** event.
|
||||
6. (Optional) Choose the campaign you want to filter on in this trigger.
|
||||
7. Save the webhook.
|
||||
`,
|
||||
}),
|
||||
},
|
||||
sampleData: {
|
||||
id: '42636763-73f9-463e-af8b-3f720bb3d889',
|
||||
type: 'contact.clicked',
|
||||
list_id: 'fa482fa2-5ac4-11ed-9f7a-67da1c836cf8',
|
||||
contact_id: 'e3ab8c80-5f65-11ed-835e-030e4bb63150',
|
||||
occurred_at: '2022-11-18T15:20:23+00:00',
|
||||
contact_email_address: 'user@example.com',
|
||||
campaign_id: '12345678-1234-1234-1234-123456789abc',
|
||||
},
|
||||
type: TriggerStrategy.WEBHOOK,
|
||||
async onEnable() {
|
||||
return;
|
||||
},
|
||||
async onDisable() {
|
||||
return;
|
||||
},
|
||||
async run(context) {
|
||||
const events = context.payload.body;
|
||||
const campaignIdFilter = context.propsValue.campaign_id;
|
||||
|
||||
if (Array.isArray(events)) {
|
||||
return events.filter(
|
||||
(event: EmailOctopusEvent) =>
|
||||
event.type === 'contact.clicked' &&
|
||||
(!campaignIdFilter || event.campaign_id === campaignIdFilter)
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
(events as EmailOctopusEvent)?.type === 'contact.clicked' &&
|
||||
(!campaignIdFilter || (events as EmailOctopusEvent).campaign_id === campaignIdFilter)
|
||||
) {
|
||||
return [events];
|
||||
}
|
||||
|
||||
return [];
|
||||
},
|
||||
});
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
import { Property, TriggerStrategy, createTrigger } from "@activepieces/pieces-framework";
|
||||
import { emailOctopusAuth } from "../common/auth";
|
||||
import { emailOctopusProps } from "../common/props";
|
||||
import { MarkdownVariant } from "@activepieces/shared";
|
||||
|
||||
export const emailBounced = createTrigger({
|
||||
auth: emailOctopusAuth,
|
||||
name: 'email_bounced',
|
||||
displayName: 'Email Bounced',
|
||||
description: 'Triggers when an email to a recipient bounces from a specific campaign.',
|
||||
props: {
|
||||
campaign_id: emailOctopusProps.campaignId(),
|
||||
liveMarkdown: Property.MarkDown({
|
||||
value: `
|
||||
**Live URL:**
|
||||
\`\`\`text
|
||||
{{webhookUrl}}
|
||||
\`\`\``,
|
||||
variant: MarkdownVariant.BORDERLESS,
|
||||
}),
|
||||
instructions: Property.MarkDown({
|
||||
value: `
|
||||
**Manual Setup Required**
|
||||
|
||||
1. Go to your EmailOctopus Dashboard.
|
||||
2. Navigate to **API & Integrations**, then select the **Webhooks** tab.
|
||||
3. Click **Add webhook**.
|
||||
4. Paste the Above URL below into the **URL** field:
|
||||
5. Select the **Email bounced** event.
|
||||
6. Click **Add webhook**.
|
||||
`,
|
||||
}),
|
||||
},
|
||||
type: TriggerStrategy.WEBHOOK,
|
||||
sampleData: {
|
||||
"id": "42636763-73f9-463e-af8b-3f720bb3d889",
|
||||
"type": "contact.bounced",
|
||||
"list_id": "fa482fa2-5ac4-11ed-9f7a-67da1c836cf8",
|
||||
"contact_id": "e3ab8c80-5f65-11ed-835e-030e4bb63150",
|
||||
"occurred_at": "2022-11-18T15:20:23+00:00",
|
||||
"contact_email_address": "user@example.com",
|
||||
"contact_status": "BOUNCED",
|
||||
"campaign_id": "12345678-1234-1234-1234-123456789abc"
|
||||
},
|
||||
|
||||
async onEnable(context) { return },
|
||||
async onDisable(context) { return },
|
||||
|
||||
async run(context) {
|
||||
const payloadBody = context.payload.body as { type: string; campaign_id: string };
|
||||
const campaignIdFilter = context.propsValue.campaign_id;
|
||||
|
||||
if (payloadBody.type !== 'contact.bounced') {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (campaignIdFilter && payloadBody.campaign_id !== campaignIdFilter) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [payloadBody];
|
||||
},
|
||||
});
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
import {
|
||||
Property,
|
||||
TriggerStrategy,
|
||||
createTrigger,
|
||||
} from '@activepieces/pieces-framework';
|
||||
import { emailOctopusAuth } from '../common/auth';
|
||||
import { emailOctopusProps } from '../common/props';
|
||||
import { MarkdownVariant } from '@activepieces/shared';
|
||||
|
||||
export const emailOpened = createTrigger({
|
||||
auth: emailOctopusAuth,
|
||||
name: 'email_opened',
|
||||
displayName: 'Email Opened',
|
||||
description:
|
||||
'Triggers when a recipient opens an email from a specified campaign.',
|
||||
props: {
|
||||
campaign_id: emailOctopusProps.campaignId(),
|
||||
liveMarkdown: Property.MarkDown({
|
||||
value: `
|
||||
**Live URL:**
|
||||
\`\`\`text
|
||||
{{webhookUrl}}
|
||||
\`\`\``,
|
||||
variant: MarkdownVariant.BORDERLESS,
|
||||
}),
|
||||
instructions: Property.MarkDown({
|
||||
variant: MarkdownVariant.INFO,
|
||||
|
||||
value: `
|
||||
**Manual Setup Required**
|
||||
|
||||
1. Go to your EmailOctopus Dashboard.
|
||||
2. Navigate to **API & Integrations**, then select the **Webhooks** tab.
|
||||
3. Click **Add webhook**.
|
||||
4. Paste the Above URL into the **URL** field:
|
||||
5. Select the **Email opened** event.
|
||||
6. Click **Add webhook**.
|
||||
`,
|
||||
}),
|
||||
},
|
||||
type: TriggerStrategy.WEBHOOK,
|
||||
sampleData: {
|
||||
id: '42636763-73f9-463e-af8b-3f720bb3d889',
|
||||
type: 'contact.opened',
|
||||
list_id: 'fa482fa2-5ac4-11ed-9f7a-67da1c836cf8',
|
||||
contact_id: 'e3ab8c80-5f65-11ed-835e-030e4bb63150',
|
||||
occurred_at: '2022-11-18T15:20:23+00:00',
|
||||
contact_email_address: 'user@example.com',
|
||||
campaign_id: '12345678-1234-1234-1234-123456789abc',
|
||||
},
|
||||
|
||||
async onEnable(context) {
|
||||
return;
|
||||
},
|
||||
async onDisable(context) {
|
||||
return;
|
||||
},
|
||||
|
||||
async run(context) {
|
||||
const payloadBody = context.payload.body as {
|
||||
type: string;
|
||||
campaign_id: string;
|
||||
};
|
||||
const campaignIdFilter = context.propsValue.campaign_id;
|
||||
|
||||
if (payloadBody.type !== 'contact.opened') {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (campaignIdFilter && payloadBody.campaign_id !== campaignIdFilter) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [payloadBody];
|
||||
},
|
||||
});
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
import {
|
||||
Property,
|
||||
createTrigger,
|
||||
TriggerStrategy,
|
||||
} from '@activepieces/pieces-framework';
|
||||
import { emailOctopusAuth } from '../common/auth';
|
||||
import { emailOctopusProps } from '../common/props';
|
||||
import { MarkdownVariant } from '@activepieces/shared';
|
||||
|
||||
interface EmailOctopusEvent {
|
||||
type: string;
|
||||
id: string;
|
||||
contact_email_address: string;
|
||||
contact_fields?: Record<string, string>;
|
||||
contact_tags?: string[];
|
||||
contact_status?: string;
|
||||
list_id?: string;
|
||||
occurred_at?: string;
|
||||
}
|
||||
|
||||
export const newContact = createTrigger({
|
||||
auth: emailOctopusAuth,
|
||||
name: 'newContact',
|
||||
displayName: 'New Contact',
|
||||
description: 'Triggers when a new contact is added to a particular list.',
|
||||
props: {
|
||||
list_id: emailOctopusProps.listId(true),
|
||||
liveMarkdown: Property.MarkDown({
|
||||
value: `
|
||||
**Live URL:**
|
||||
\`\`\`text
|
||||
{{webhookUrl}}
|
||||
\`\`\``,
|
||||
variant: MarkdownVariant.BORDERLESS,
|
||||
}),
|
||||
instructions: Property.MarkDown({
|
||||
variant: MarkdownVariant.INFO,
|
||||
value: `
|
||||
**Manual Setup Required**
|
||||
|
||||
1. Go to your EmailOctopus Dashboard.
|
||||
2. Navigate to **API & Integrations → Webhooks**.
|
||||
3. Click **Add webhook**.
|
||||
4. Paste the Above URL.
|
||||
5. Select the **Contact created** event.
|
||||
6. (Optional) Restrict to the specific list chosen above.
|
||||
7. Save the webhook.
|
||||
`,
|
||||
}),
|
||||
},
|
||||
sampleData: {
|
||||
id: '42636763-73f9-463e-af8b-3f720bb3d889',
|
||||
type: 'contact.created',
|
||||
list_id: 'fa482fa2-5ac4-11ed-9f7a-67da1c836cf8',
|
||||
contact_id: 'e3ab8c80-5f65-11ed-835e-030e4bb63150',
|
||||
occurred_at: '2022-11-18T15:20:23+00:00',
|
||||
contact_fields: {
|
||||
LastName: 'Example',
|
||||
FirstName: 'Claire',
|
||||
},
|
||||
contact_status: 'subscribed',
|
||||
contact_email_address: 'claire@example.com',
|
||||
contact_tags: ['vip'],
|
||||
},
|
||||
type: TriggerStrategy.WEBHOOK,
|
||||
async onEnable() {
|
||||
return;
|
||||
},
|
||||
async onDisable() {
|
||||
return;
|
||||
},
|
||||
async run(context) {
|
||||
const events = context.payload.body;
|
||||
const listIdFilter = context.propsValue.list_id;
|
||||
|
||||
if (Array.isArray(events)) {
|
||||
return events.filter(
|
||||
(event: EmailOctopusEvent) =>
|
||||
event.type === 'contact.created' &&
|
||||
(!listIdFilter || event.list_id === listIdFilter)
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
(events as EmailOctopusEvent)?.type === 'contact.created' &&
|
||||
(!listIdFilter || (events as EmailOctopusEvent).list_id === listIdFilter)
|
||||
) {
|
||||
return [events];
|
||||
}
|
||||
|
||||
return [];
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user