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,26 @@
|
||||
import { propsValidation } from '@activepieces/pieces-common';
|
||||
import { createAction } from '@activepieces/pieces-framework';
|
||||
import { zohoCampaignsAuth, zohoCampaignsCommon } from '../common';
|
||||
|
||||
export const addContactToMailingList = createAction({
|
||||
auth: zohoCampaignsAuth,
|
||||
name: 'addContactToMailingList',
|
||||
displayName: 'Add Contact to Mailing List',
|
||||
description: 'Add contacts to your mailing lists.',
|
||||
props: zohoCampaignsCommon.addContactToMailingListProperties(),
|
||||
async run({ auth, propsValue }) {
|
||||
const location = auth.props?.['location'] as string || 'zoho.com';
|
||||
const accessToken = auth.access_token
|
||||
|
||||
await propsValidation.validateZod(
|
||||
propsValue,
|
||||
zohoCampaignsCommon.addContactToMailingListSchema
|
||||
);
|
||||
return await zohoCampaignsCommon.addContactToMailingList({
|
||||
accessToken,
|
||||
location,
|
||||
listkey: String(propsValue.listkey),
|
||||
emailids: propsValue.emails.join(','),
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,38 @@
|
||||
import { propsValidation } from '@activepieces/pieces-common';
|
||||
import { createAction } from '@activepieces/pieces-framework';
|
||||
import { zohoCampaignsAuth, zohoCampaignsCommon } from '../common';
|
||||
|
||||
export const addTagToContact = createAction({
|
||||
auth: zohoCampaignsAuth,
|
||||
name: 'addTagToContact',
|
||||
displayName: 'Add Tag to Contact',
|
||||
description:
|
||||
"Apply a tag to a contact by email. Creates the tag if it doesn't exist.",
|
||||
props: zohoCampaignsCommon.addTagToContactProperties,
|
||||
async run({ auth, propsValue }) {
|
||||
const location = auth.props?.['location'] as string || 'zoho.com';
|
||||
const accessToken = auth.access_token;
|
||||
await propsValidation.validateZod(
|
||||
propsValue,
|
||||
zohoCampaignsCommon.addTagToContactSchema
|
||||
);
|
||||
const tags = await zohoCampaignsCommon.listTags({ accessToken, location });
|
||||
const tagExists =
|
||||
tags !== undefined &&
|
||||
tags.some((tagMap) =>
|
||||
Object.values(tagMap).some((t) => t.tag_name === propsValue.tagName)
|
||||
);
|
||||
if (!tagExists) {
|
||||
await zohoCampaignsCommon.createTag({
|
||||
accessToken,
|
||||
location,
|
||||
tagName: propsValue.tagName,
|
||||
});
|
||||
}
|
||||
return await zohoCampaignsCommon.addTagToContact({
|
||||
accessToken,
|
||||
location,
|
||||
...propsValue,
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,32 @@
|
||||
import { propsValidation } from '@activepieces/pieces-common';
|
||||
import { createAction } from '@activepieces/pieces-framework';
|
||||
import { zohoCampaignsAuth, zohoCampaignsCommon } from '../common';
|
||||
|
||||
export const addUpdateContact = createAction({
|
||||
auth: zohoCampaignsAuth,
|
||||
name: 'addUpdateContact',
|
||||
displayName: 'Add/Update Contact',
|
||||
description:
|
||||
'Add a new contact or update an existing one. Confirmation email sent based on mailing list settings.',
|
||||
props: zohoCampaignsCommon.addUpdateContactProperties(),
|
||||
async run({ auth, propsValue }) {
|
||||
const location = auth.props?.['location'] as string || 'zoho.com';
|
||||
const accessToken = auth.access_token;
|
||||
await propsValidation.validateZod(
|
||||
propsValue,
|
||||
zohoCampaignsCommon.addUpdateContactSchema
|
||||
);
|
||||
const { additionalFields, ...baseFields } = propsValue.contactinfo;
|
||||
|
||||
return await zohoCampaignsCommon.addUpdateContact({
|
||||
accessToken,
|
||||
location,
|
||||
...propsValue,
|
||||
listkey: String(propsValue.listkey),
|
||||
contactinfo: {
|
||||
...baseFields,
|
||||
...additionalFields,
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,42 @@
|
||||
import { propsValidation } from '@activepieces/pieces-common';
|
||||
import { createAction } from '@activepieces/pieces-framework';
|
||||
import { zohoCampaignsAuth, zohoCampaignsCommon } from '../common';
|
||||
|
||||
export const cloneCampaign = createAction({
|
||||
auth: zohoCampaignsAuth,
|
||||
name: 'cloneCampaign',
|
||||
displayName: 'Clone Campaign',
|
||||
description: 'Clone an existing campaign, optionally renaming.',
|
||||
props: zohoCampaignsCommon.cloneCampaignProperties(),
|
||||
async run({ auth, propsValue }) {
|
||||
const location = auth.props?.['location'] as string || 'zoho.com';
|
||||
const accessToken = auth.access_token;
|
||||
await propsValidation.validateZod(
|
||||
propsValue,
|
||||
zohoCampaignsCommon.cloneCampaignSchema
|
||||
);
|
||||
const {
|
||||
campaignkey,
|
||||
campaignname,
|
||||
subject,
|
||||
from_name,
|
||||
from_add,
|
||||
reply_to,
|
||||
encode_type,
|
||||
} = propsValue;
|
||||
const campaigninfo = {
|
||||
oldcampaignkey: campaignkey,
|
||||
...(campaignname && { campaignname }),
|
||||
...(subject && { subject }),
|
||||
...(from_name && { from_name }),
|
||||
...(from_add && { from_add }),
|
||||
...(reply_to && { reply_to }),
|
||||
...(encode_type && { encode_type }),
|
||||
};
|
||||
return await zohoCampaignsCommon.cloneCampaign({
|
||||
accessToken,
|
||||
location,
|
||||
campaigninfo,
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,31 @@
|
||||
import { propsValidation } from '@activepieces/pieces-common';
|
||||
import { createAction } from '@activepieces/pieces-framework';
|
||||
import { zohoCampaignsAuth, zohoCampaignsCommon } from '../common';
|
||||
export const createCampaign = createAction({
|
||||
auth: zohoCampaignsAuth,
|
||||
name: 'createCampaign',
|
||||
displayName: 'Create Campaign',
|
||||
description:
|
||||
'Create a new campaign with campaign name, subject, topic, sender name/address, and mailing list.',
|
||||
props: zohoCampaignsCommon.createCampaignProperties(),
|
||||
async run({ auth, propsValue }) {
|
||||
const location = auth.props?.['location'] as string || 'zoho.com';
|
||||
const accessToken = auth.access_token ;
|
||||
await propsValidation.validateZod(
|
||||
propsValue,
|
||||
zohoCampaignsCommon.createCampaignSchema
|
||||
);
|
||||
const list_details =
|
||||
propsValue.list_details?.reduce((acc, curr) => {
|
||||
acc[curr] = [];
|
||||
return acc;
|
||||
}, {} as { [key: string]: [] }) || {};
|
||||
|
||||
return await zohoCampaignsCommon.createCampaign({
|
||||
accessToken,
|
||||
location,
|
||||
...propsValue,
|
||||
list_details,
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,49 @@
|
||||
import { propsValidation } from '@activepieces/pieces-common';
|
||||
import { createAction } from '@activepieces/pieces-framework';
|
||||
import { zohoCampaignsAuth, zohoCampaignsCommon } from '../common';
|
||||
|
||||
export const findCampaign = createAction({
|
||||
auth: zohoCampaignsAuth,
|
||||
name: 'findCampaign',
|
||||
displayName: 'Find Campaign',
|
||||
description: 'Locate an existing campaign by campaign name.',
|
||||
props: zohoCampaignsCommon.findCampaignProperties(),
|
||||
async run({ auth, propsValue }) {
|
||||
const location = auth.props?.['location'] as string || 'zoho.com';
|
||||
const accessToken = auth.access_token
|
||||
await propsValidation.validateZod(
|
||||
propsValue,
|
||||
zohoCampaignsCommon.findCampaignSchema
|
||||
);
|
||||
const { campaignName, status, sort, fromindex, range } = propsValue;
|
||||
|
||||
const searchParams: any = {
|
||||
accessToken,
|
||||
};
|
||||
|
||||
if (status) searchParams.status = status;
|
||||
if (sort) searchParams.sort = sort;
|
||||
if (fromindex) searchParams.fromindex = fromindex;
|
||||
if (range) searchParams.range = range;
|
||||
|
||||
const campaigns = await zohoCampaignsCommon.listCampaigns({
|
||||
...searchParams,
|
||||
location
|
||||
});
|
||||
const needle = (campaignName ?? '').trim().toLowerCase();
|
||||
|
||||
// Try to find case-insensitive and partial match
|
||||
const matchingCampaigns = campaigns.filter((campaign) =>
|
||||
(campaign.campaign_name ?? '').toLowerCase().includes(needle)
|
||||
);
|
||||
|
||||
if (matchingCampaigns.length === 0) {
|
||||
const statusText = status ? ` with status "${status}"` : '';
|
||||
throw new Error(
|
||||
`No campaign found with a name containing "${campaignName}"${statusText} in the selected account.`
|
||||
);
|
||||
}
|
||||
|
||||
return matchingCampaigns;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,57 @@
|
||||
import { propsValidation } from '@activepieces/pieces-common';
|
||||
import { createAction } from '@activepieces/pieces-framework';
|
||||
import { zohoCampaignsAuth, zohoCampaignsCommon } from '../common';
|
||||
|
||||
export const findContact = createAction({
|
||||
auth: zohoCampaignsAuth,
|
||||
name: 'findContact',
|
||||
displayName: 'Find Contact',
|
||||
description: 'Look up an existing contact by email address.',
|
||||
props: zohoCampaignsCommon.findContactProperties(),
|
||||
async run({ auth, propsValue }) {
|
||||
const location = auth.props?.['location'] as string || 'zoho.com';
|
||||
const accessToken = auth.access_token;
|
||||
await propsValidation.validateZod(
|
||||
propsValue,
|
||||
zohoCampaignsCommon.findContactSchema
|
||||
);
|
||||
const {
|
||||
listkey,
|
||||
contactEmail: email,
|
||||
status,
|
||||
sort,
|
||||
fromindex,
|
||||
range,
|
||||
} = propsValue;
|
||||
|
||||
const searchParams: any = {
|
||||
accessToken,
|
||||
listkey: listkey as string,
|
||||
};
|
||||
|
||||
if (status) searchParams.status = status;
|
||||
if (sort) searchParams.sort = sort;
|
||||
if (fromindex) searchParams.fromindex = fromindex;
|
||||
if (range) searchParams.range = range;
|
||||
|
||||
const contacts = await zohoCampaignsCommon.listContacts({
|
||||
...searchParams,
|
||||
location,
|
||||
});
|
||||
const needle = (email ?? '').trim().toLowerCase();
|
||||
|
||||
// Try to find case-insensitive and partial match
|
||||
const matchingContacts = contacts.filter((contact) =>
|
||||
(contact.contact_email ?? '').toLowerCase().includes(needle)
|
||||
);
|
||||
|
||||
if (matchingContacts.length === 0) {
|
||||
const statusText = status ? ` with status "${status}"` : '';
|
||||
throw new Error(
|
||||
`No contact found with an email containing "${email}"${statusText} in the selected mailing list.`
|
||||
);
|
||||
}
|
||||
|
||||
return matchingContacts;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,24 @@
|
||||
import { propsValidation } from '@activepieces/pieces-common';
|
||||
import { createAction } from '@activepieces/pieces-framework';
|
||||
import { zohoCampaignsAuth, zohoCampaignsCommon } from '../common';
|
||||
|
||||
export const removeTag = createAction({
|
||||
auth: zohoCampaignsAuth,
|
||||
name: 'removeTag',
|
||||
displayName: 'Remove Tag',
|
||||
description: 'Remove a tag from a contact.',
|
||||
props: zohoCampaignsCommon.removeTagProperties,
|
||||
async run({ auth, propsValue }) {
|
||||
const location = auth.props?.['location'] as string || 'zoho.com';
|
||||
const accessToken = auth.access_token;
|
||||
await propsValidation.validateZod(
|
||||
propsValue,
|
||||
zohoCampaignsCommon.removeTagSchema
|
||||
);
|
||||
return await zohoCampaignsCommon.removeTag({
|
||||
accessToken,
|
||||
location,
|
||||
...propsValue,
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,25 @@
|
||||
import { propsValidation } from '@activepieces/pieces-common';
|
||||
import { createAction } from '@activepieces/pieces-framework';
|
||||
import { zohoCampaignsAuth, zohoCampaignsCommon } from '../common';
|
||||
|
||||
export const sendCampaign = createAction({
|
||||
auth: zohoCampaignsAuth,
|
||||
name: 'sendCampaign',
|
||||
displayName: 'Send Campaign',
|
||||
description: 'Send a campaign that has been created or cloned.',
|
||||
props: zohoCampaignsCommon.sendCampaignProperties(),
|
||||
async run({ auth, propsValue }) {
|
||||
const location = auth.props?.['location'] as string || 'zoho.com';
|
||||
const accessToken = auth.access_token;
|
||||
await propsValidation.validateZod(
|
||||
propsValue,
|
||||
zohoCampaignsCommon.sendCampaignSchema
|
||||
);
|
||||
const { campaignkey } = propsValue;
|
||||
return await zohoCampaignsCommon.sendCampaign({
|
||||
accessToken,
|
||||
location,
|
||||
campaignkey: campaignkey as string,
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,31 @@
|
||||
import { propsValidation } from '@activepieces/pieces-common';
|
||||
import { createAction } from '@activepieces/pieces-framework';
|
||||
import { zohoCampaignsAuth, zohoCampaignsCommon } from '../common';
|
||||
|
||||
export const unsubscribeContact = createAction({
|
||||
auth: zohoCampaignsAuth,
|
||||
name: 'unsubscribeContact',
|
||||
displayName: 'Unsubscribe Contact',
|
||||
description: 'Remove a contact from a mailing list.',
|
||||
props: zohoCampaignsCommon.unsubscribeContactProperties(),
|
||||
async run({ auth, propsValue }) {
|
||||
const location = auth.props?.['location'] as string || 'zoho.com';
|
||||
const accessToken = auth.access_token;
|
||||
await propsValidation.validateZod(
|
||||
propsValue,
|
||||
zohoCampaignsCommon.unsubscribeContactSchema
|
||||
);
|
||||
const { additionalFields, ...baseFields } = propsValue.contactinfo;
|
||||
|
||||
return await zohoCampaignsCommon.unsubscribeContact({
|
||||
accessToken,
|
||||
location,
|
||||
listkey: String(propsValue.listkey),
|
||||
contactinfo: {
|
||||
...baseFields,
|
||||
...additionalFields,
|
||||
},
|
||||
...(propsValue.topic_id && { topic_id: propsValue.topic_id }),
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,393 @@
|
||||
import { httpClient, HttpMethod } from '@activepieces/pieces-common';
|
||||
import { PieceAuth, Property } from '@activepieces/pieces-framework';
|
||||
import { OAuth2GrantType } from '@activepieces/shared';
|
||||
import * as properties from './properties';
|
||||
import * as schemas from './schemas';
|
||||
import {
|
||||
AddContactToMailingListParams,
|
||||
AddTagToContactParams,
|
||||
AddUpdateContactParams,
|
||||
AuthorizationParams,
|
||||
CloneCampaignParams,
|
||||
CreateCampaignParams,
|
||||
CreateCampaignResponse,
|
||||
CreateTagParams,
|
||||
ListCampaignParams,
|
||||
ListCampaignResponse,
|
||||
ListContactsParams,
|
||||
ListContactsResponse,
|
||||
ListMailingListsParams,
|
||||
ListMailingListsResponse,
|
||||
ListTagsResponse,
|
||||
ListTopicsResponse,
|
||||
RemoveTagParams,
|
||||
SendCampaignParams,
|
||||
UnsubscribeContactParams,
|
||||
} from './types';
|
||||
|
||||
export const zohoCampaignsAuth = PieceAuth.OAuth2({
|
||||
props: {
|
||||
location: Property.StaticDropdown({
|
||||
displayName: 'Data Center',
|
||||
description: 'The data center location of your Zoho Campaigns account',
|
||||
required: true,
|
||||
options: {
|
||||
options: [
|
||||
{
|
||||
label: 'zoho.com (United States)',
|
||||
value: 'zoho.com',
|
||||
},
|
||||
{
|
||||
label: 'zoho.eu (Europe)',
|
||||
value: 'zoho.eu',
|
||||
},
|
||||
{
|
||||
label: 'zoho.in (India)',
|
||||
value: 'zoho.in',
|
||||
},
|
||||
{
|
||||
label: 'zoho.com.au (Australia)',
|
||||
value: 'zoho.com.au',
|
||||
},
|
||||
{
|
||||
label: 'zoho.jp (Japan)',
|
||||
value: 'zoho.jp',
|
||||
},
|
||||
{
|
||||
label: 'zoho.com.cn (China)',
|
||||
value: 'zoho.com.cn',
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
},
|
||||
description: 'Connect your Zoho Campaigns account using OAuth2',
|
||||
grantType: OAuth2GrantType.AUTHORIZATION_CODE,
|
||||
required: true,
|
||||
authUrl: 'https://accounts.{location}/oauth/v2/auth',
|
||||
tokenUrl: 'https://accounts.{location}/oauth/v2/token',
|
||||
scope: ['ZohoCampaigns.campaign.ALL', 'ZohoCampaigns.contact.ALL'],
|
||||
});
|
||||
|
||||
export const zohoCampaignsCommon = {
|
||||
baseUrl: (location = 'zoho.com') => {
|
||||
return `https://campaigns.${location}/api/v1.1`;
|
||||
},
|
||||
endpoints: {
|
||||
createCampaign: '/createCampaign',
|
||||
createTag: '/tag/add',
|
||||
cloneCampaign: '/json/clonecampaign',
|
||||
sendCampaign: '/sendcampaign',
|
||||
addUpdateContact: '/json/listsubscribe',
|
||||
addTagToContact: '/tag/associate',
|
||||
removeTag: '/tag/deassociate',
|
||||
unsubscribeContact: '/json/listunsubscribe',
|
||||
addContactToMailingList: '/addlistsubscribersinbulk',
|
||||
listContacts: '/getlistsubscribers',
|
||||
listCampaigns: '/recentcampaigns',
|
||||
listMailingLists: '/getmailinglists',
|
||||
listTopics: '/topics',
|
||||
listTags: '/tag/getalltags',
|
||||
},
|
||||
baseHeaders: (accessToken: string) => {
|
||||
return {
|
||||
Authorization: `Zoho-oauthtoken ${accessToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
};
|
||||
},
|
||||
baseParams: {
|
||||
resfmt: 'JSON',
|
||||
},
|
||||
|
||||
// Properties
|
||||
createCampaignProperties: properties.createCampaign,
|
||||
cloneCampaignProperties: properties.cloneCampaign,
|
||||
sendCampaignProperties: properties.sendCampaign,
|
||||
addUpdateContactProperties: properties.addUpdateContact,
|
||||
addTagToContactProperties: properties.addTagToContact,
|
||||
removeTagProperties: properties.removeTag,
|
||||
unsubscribeContactProperties: properties.unsubscribeContact,
|
||||
addContactToMailingListProperties: properties.addContactToMailingList,
|
||||
findContactProperties: properties.findContact,
|
||||
findCampaignProperties: properties.findCampaign,
|
||||
newContactProperties: properties.newContact,
|
||||
unsubscribeProperties: properties.unsubscribe,
|
||||
|
||||
// Schemas
|
||||
createCampaignSchema: schemas.createCampaign,
|
||||
cloneCampaignSchema: schemas.cloneCampaign,
|
||||
sendCampaignSchema: schemas.sendCampaign,
|
||||
addUpdateContactSchema: schemas.addUpdateContact,
|
||||
addTagToContactSchema: schemas.addTagToContact,
|
||||
removeTagSchema: schemas.removeTag,
|
||||
unsubscribeContactSchema: schemas.unsubscribeContact,
|
||||
addContactToMailingListSchema: schemas.addContactToMailingList,
|
||||
findContactSchema: schemas.findContact,
|
||||
findCampaignSchema: schemas.findCampaign,
|
||||
|
||||
// Methods
|
||||
createCampaign: async ({
|
||||
accessToken,
|
||||
location = 'zoho.com',
|
||||
...campaignParams
|
||||
}: CreateCampaignParams & { location?: string }) => {
|
||||
const {
|
||||
list_details: listDetails,
|
||||
topicId,
|
||||
...restParams
|
||||
} = campaignParams;
|
||||
|
||||
const list_details = JSON.stringify(listDetails);
|
||||
const body = new URLSearchParams({
|
||||
resfmt: 'json',
|
||||
list_details,
|
||||
...restParams,
|
||||
...(topicId && { topicId }),
|
||||
}).toString();
|
||||
const response = await httpClient.sendRequest<CreateCampaignResponse>({
|
||||
method: HttpMethod.POST,
|
||||
url: `${zohoCampaignsCommon.baseUrl(location)}${zohoCampaignsCommon.endpoints.createCampaign}`,
|
||||
headers: {
|
||||
...zohoCampaignsCommon.baseHeaders(accessToken),
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
body,
|
||||
});
|
||||
return response.body;
|
||||
},
|
||||
createTag: async ({ accessToken, location = 'zoho.com', tagName }: CreateTagParams & { location?: string }) => {
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.GET,
|
||||
url: `${zohoCampaignsCommon.baseUrl(location)}${zohoCampaignsCommon.endpoints.createTag}`,
|
||||
headers: zohoCampaignsCommon.baseHeaders(accessToken),
|
||||
queryParams: {
|
||||
...zohoCampaignsCommon.baseParams,
|
||||
tagName,
|
||||
},
|
||||
});
|
||||
return response.body;
|
||||
},
|
||||
cloneCampaign: async ({ accessToken, location = 'zoho.com', campaigninfo }: CloneCampaignParams & { location?: string }) => {
|
||||
const strCampaignInfo = JSON.stringify(campaigninfo);
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.POST,
|
||||
url: `${zohoCampaignsCommon.baseUrl(location)}${zohoCampaignsCommon.endpoints.cloneCampaign}`,
|
||||
headers: zohoCampaignsCommon.baseHeaders(accessToken),
|
||||
queryParams: {
|
||||
...zohoCampaignsCommon.baseParams,
|
||||
campaigninfo: strCampaignInfo,
|
||||
},
|
||||
});
|
||||
return response.body;
|
||||
},
|
||||
sendCampaign: async ({ accessToken, location = 'zoho.com', campaignkey }: SendCampaignParams & { location?: string }) => {
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.POST,
|
||||
url: `${zohoCampaignsCommon.baseUrl(location)}${zohoCampaignsCommon.endpoints.sendCampaign}`,
|
||||
headers: {
|
||||
...zohoCampaignsCommon.baseHeaders(accessToken),
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
queryParams: {
|
||||
...zohoCampaignsCommon.baseParams,
|
||||
campaignkey,
|
||||
},
|
||||
});
|
||||
return response.body;
|
||||
},
|
||||
addUpdateContact: async ({
|
||||
accessToken,
|
||||
location = 'zoho.com',
|
||||
...contactParams
|
||||
}: AddUpdateContactParams & { location?: string }) => {
|
||||
const {
|
||||
listkey,
|
||||
contactinfo: contactInfoObj,
|
||||
source,
|
||||
topic_id,
|
||||
} = contactParams;
|
||||
const body = new URLSearchParams({
|
||||
...zohoCampaignsCommon.baseParams,
|
||||
listkey,
|
||||
...(source && { source }),
|
||||
...(topic_id && { topic_id }),
|
||||
contactinfo: JSON.stringify(contactInfoObj),
|
||||
}).toString();
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.POST,
|
||||
url: `${zohoCampaignsCommon.baseUrl(location)}${zohoCampaignsCommon.endpoints.addUpdateContact}`,
|
||||
headers: {
|
||||
...zohoCampaignsCommon.baseHeaders(accessToken),
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
body,
|
||||
});
|
||||
|
||||
return response.body;
|
||||
},
|
||||
addTagToContact: async ({
|
||||
accessToken,
|
||||
location = 'zoho.com',
|
||||
...tagParams
|
||||
}: AddTagToContactParams & { location?: string }) => {
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.GET,
|
||||
url: `${zohoCampaignsCommon.baseUrl(location)}${zohoCampaignsCommon.endpoints.addTagToContact}`,
|
||||
headers: zohoCampaignsCommon.baseHeaders(accessToken),
|
||||
queryParams: {
|
||||
...zohoCampaignsCommon.baseParams,
|
||||
...tagParams,
|
||||
},
|
||||
});
|
||||
return response.body;
|
||||
},
|
||||
removeTag: async ({ accessToken, location = 'zoho.com', ...tagParams }: RemoveTagParams & { location?: string }) => {
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.GET,
|
||||
url: `${zohoCampaignsCommon.baseUrl(location)}${zohoCampaignsCommon.endpoints.removeTag}`,
|
||||
headers: zohoCampaignsCommon.baseHeaders(accessToken),
|
||||
queryParams: {
|
||||
...zohoCampaignsCommon.baseParams,
|
||||
...tagParams,
|
||||
},
|
||||
});
|
||||
return response.body;
|
||||
},
|
||||
unsubscribeContact: async ({
|
||||
accessToken,
|
||||
location = 'zoho.com',
|
||||
...unsubscribeParams
|
||||
}: UnsubscribeContactParams & { location?: string }) => {
|
||||
const {
|
||||
contactinfo: contactInfoObj,
|
||||
listkey,
|
||||
topic_id,
|
||||
} = unsubscribeParams;
|
||||
const body = new URLSearchParams({
|
||||
...zohoCampaignsCommon.baseParams,
|
||||
listkey,
|
||||
...(topic_id && { topic_id }),
|
||||
contactinfo: JSON.stringify(contactInfoObj),
|
||||
}).toString();
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.POST,
|
||||
url: `${zohoCampaignsCommon.baseUrl(location)}${zohoCampaignsCommon.endpoints.unsubscribeContact}`,
|
||||
headers: {
|
||||
...zohoCampaignsCommon.baseHeaders(accessToken),
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
body,
|
||||
});
|
||||
return response.body;
|
||||
},
|
||||
addContactToMailingList: async ({
|
||||
accessToken,
|
||||
location = 'zoho.com',
|
||||
...mailingListParams
|
||||
}: AddContactToMailingListParams & { location?: string }) => {
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.POST,
|
||||
url: `${zohoCampaignsCommon.baseUrl(location)}${zohoCampaignsCommon.endpoints.addContactToMailingList}`,
|
||||
headers: zohoCampaignsCommon.baseHeaders(accessToken),
|
||||
queryParams: {
|
||||
...zohoCampaignsCommon.baseParams,
|
||||
...mailingListParams,
|
||||
},
|
||||
});
|
||||
return response.body;
|
||||
},
|
||||
listContacts: async ({
|
||||
accessToken,
|
||||
location = 'zoho.com',
|
||||
listkey,
|
||||
...rest
|
||||
}: ListContactsParams & { location?: string }) => {
|
||||
const { fromindex, range, ...otherParams } = rest;
|
||||
const strFromIndex =
|
||||
typeof fromindex === 'number' ? String(fromindex) : undefined;
|
||||
const strRange = typeof range === 'number' ? String(range) : undefined;
|
||||
const queryParams = {
|
||||
...zohoCampaignsCommon.baseParams,
|
||||
listkey,
|
||||
...(fromindex && { fromindex: strFromIndex }),
|
||||
...(range && { range: strRange }),
|
||||
...otherParams,
|
||||
};
|
||||
const response = await httpClient.sendRequest<ListContactsResponse>({
|
||||
method: HttpMethod.GET,
|
||||
url: `${zohoCampaignsCommon.baseUrl(location)}${zohoCampaignsCommon.endpoints.listContacts}`,
|
||||
headers: zohoCampaignsCommon.baseHeaders(accessToken),
|
||||
queryParams,
|
||||
});
|
||||
return response.body.list_of_details || [];
|
||||
},
|
||||
listCampaigns: async ({
|
||||
accessToken,
|
||||
location = 'zoho.com',
|
||||
...filterParams
|
||||
}: ListCampaignParams & { location?: string }) => {
|
||||
const { fromindex, range, ...otherParams } = filterParams;
|
||||
const strFromIndex =
|
||||
typeof fromindex === 'number' ? String(fromindex) : undefined;
|
||||
const strRange = typeof range === 'number' ? String(range) : undefined;
|
||||
const queryParams = {
|
||||
...zohoCampaignsCommon.baseParams,
|
||||
...(fromindex && { fromindex: strFromIndex }),
|
||||
...(range && { range: strRange }),
|
||||
...otherParams,
|
||||
};
|
||||
const response = await httpClient.sendRequest<ListCampaignResponse>({
|
||||
method: HttpMethod.GET,
|
||||
url: `${zohoCampaignsCommon.baseUrl(location)}${zohoCampaignsCommon.endpoints.listCampaigns}`,
|
||||
headers: zohoCampaignsCommon.baseHeaders(accessToken),
|
||||
queryParams,
|
||||
});
|
||||
return response.body.recent_campaigns || [];
|
||||
},
|
||||
listMailingLists: async ({
|
||||
accessToken,
|
||||
location = 'zoho.com',
|
||||
...filterParams
|
||||
}: ListMailingListsParams & { location?: string }) => {
|
||||
const { fromindex, range, ...otherParams } = filterParams;
|
||||
const strFromIndex =
|
||||
typeof fromindex === 'number' ? String(fromindex) : undefined;
|
||||
const strRange = typeof range === 'number' ? String(range) : undefined;
|
||||
const queryParams = {
|
||||
...zohoCampaignsCommon.baseParams,
|
||||
...(fromindex && { fromindex: strFromIndex }),
|
||||
...(range && { range: strRange }),
|
||||
...otherParams,
|
||||
};
|
||||
|
||||
const response = await httpClient.sendRequest<ListMailingListsResponse>({
|
||||
method: HttpMethod.GET,
|
||||
url: `${zohoCampaignsCommon.baseUrl(location)}${zohoCampaignsCommon.endpoints.listMailingLists}`,
|
||||
headers: zohoCampaignsCommon.baseHeaders(accessToken),
|
||||
queryParams,
|
||||
});
|
||||
return response.body.list_of_details || [];
|
||||
},
|
||||
listTopics: async ({ accessToken, location = 'zoho.com' }: AuthorizationParams & { location?: string }) => {
|
||||
const response = await httpClient.sendRequest<ListTopicsResponse>({
|
||||
method: HttpMethod.GET,
|
||||
url: `${zohoCampaignsCommon.baseUrl(location)}${zohoCampaignsCommon.endpoints.listTopics}`,
|
||||
headers: zohoCampaignsCommon.baseHeaders(accessToken),
|
||||
queryParams: {
|
||||
...zohoCampaignsCommon.baseParams,
|
||||
},
|
||||
});
|
||||
return response.body.topicDetails;
|
||||
},
|
||||
listTags: async ({ accessToken, location = 'zoho.com' }: AuthorizationParams & { location?: string }) => {
|
||||
const response = await httpClient.sendRequest<ListTagsResponse>({
|
||||
method: HttpMethod.GET,
|
||||
url: `${zohoCampaignsCommon.baseUrl(location)}${zohoCampaignsCommon.endpoints.listTags}`,
|
||||
headers: zohoCampaignsCommon.baseHeaders(accessToken),
|
||||
queryParams: {
|
||||
...zohoCampaignsCommon.baseParams,
|
||||
},
|
||||
});
|
||||
return response.body.tags;
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,471 @@
|
||||
import { PiecePropValueSchema, Property } from '@activepieces/pieces-framework';
|
||||
import { zohoCampaignsAuth, zohoCampaignsCommon } from '.';
|
||||
import { Tag } from './types';
|
||||
|
||||
// Custom Properties
|
||||
const campaignDropdown = () =>
|
||||
Property.Dropdown({
|
||||
auth: zohoCampaignsAuth,
|
||||
displayName: 'Campaign',
|
||||
description: 'Select the campaign',
|
||||
required: true,
|
||||
refreshers: ['auth'],
|
||||
options: async ({ auth }) => {
|
||||
const authValue = auth as PiecePropValueSchema<typeof zohoCampaignsAuth>;
|
||||
const location = authValue.props?.['location'] || 'zoho.com';
|
||||
if (!auth) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'Connect your Zoho Campaigns account first',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
const campaigns = await zohoCampaignsCommon.listCampaigns({
|
||||
accessToken: authValue.access_token,
|
||||
location,
|
||||
});
|
||||
if (campaigns.length === 0) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'No campaigns found',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
options: campaigns.map((campaign) => ({
|
||||
label: campaign.campaign_name,
|
||||
value: campaign.campaign_key,
|
||||
})),
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
const tagDropdown = ({ required = true }: { required?: boolean }) =>
|
||||
Property.Dropdown({
|
||||
auth: zohoCampaignsAuth,
|
||||
displayName: 'Tag',
|
||||
description: 'Select the tag to associate with the contact',
|
||||
required: required,
|
||||
refreshers: ['auth'],
|
||||
options: async ({
|
||||
auth,
|
||||
}): Promise<{
|
||||
disabled?: boolean;
|
||||
placeholder?: string;
|
||||
options: Array<{ label: string; value: string }>;
|
||||
}> => {
|
||||
const authValue = auth as PiecePropValueSchema<typeof zohoCampaignsAuth>;
|
||||
const location = authValue.props?.['location'] || 'zoho.com';
|
||||
if (!auth) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'Connect your Zoho Campaigns account first',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
const tags = await zohoCampaignsCommon.listTags({
|
||||
accessToken: authValue.access_token,
|
||||
location,
|
||||
});
|
||||
if (!tags || tags.length === 0) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'No tags found',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
|
||||
const tagOptions = tags.flatMap((tagMap: Tag) =>
|
||||
Object.values(tagMap).map((tag: any) => ({
|
||||
label: tag.tag_name,
|
||||
value: tag.tag_name,
|
||||
}))
|
||||
);
|
||||
|
||||
return {
|
||||
options: tagOptions,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
const mailingListDropdown = ({ required = true }) =>
|
||||
Property.Dropdown({
|
||||
auth: zohoCampaignsAuth,
|
||||
displayName: 'Mailing List',
|
||||
description: 'Select the mailing list',
|
||||
required: required,
|
||||
refreshers: ['auth'],
|
||||
options: async ({ auth }) => {
|
||||
const authValue = auth as PiecePropValueSchema<typeof zohoCampaignsAuth>;
|
||||
const location = authValue.props?.['location'] || 'zoho.com';
|
||||
|
||||
if (!auth) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'Connect your Zoho Campaigns account first',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
const mailingLists = await zohoCampaignsCommon.listMailingLists({
|
||||
accessToken: authValue.access_token,
|
||||
location,
|
||||
});
|
||||
if (mailingLists.length === 0) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'No mailing lists found',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
return {
|
||||
options: mailingLists.map((list) => ({
|
||||
label: list.listname,
|
||||
value: list.listkey,
|
||||
})),
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
const mailingListMultiSelectDropdown = ({ required = true }) =>
|
||||
Property.MultiSelectDropdown({
|
||||
auth: zohoCampaignsAuth,
|
||||
displayName: 'Mailing Lists',
|
||||
description: 'Select the mailing lists',
|
||||
required: required,
|
||||
refreshers: ['auth'],
|
||||
options: async ({ auth }) => {
|
||||
const authValue = auth as PiecePropValueSchema<typeof zohoCampaignsAuth>;
|
||||
const location = authValue.props?.['location'] || 'zoho.com';
|
||||
if (!auth) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'Connect your Zoho Campaigns account first',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
const mailingLists = await zohoCampaignsCommon.listMailingLists({
|
||||
accessToken: authValue.access_token,
|
||||
location,
|
||||
});
|
||||
if (mailingLists.length === 0) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'No mailing lists found',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
return {
|
||||
options: mailingLists.map((list) => ({
|
||||
label: list.listname,
|
||||
value: list.listkey,
|
||||
})),
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
const topicDropdown = ({ required = true }) =>
|
||||
Property.Dropdown({
|
||||
auth: zohoCampaignsAuth,
|
||||
displayName: 'Topic',
|
||||
description: 'Select the topic',
|
||||
required: required,
|
||||
refreshers: ['auth'],
|
||||
options: async ({ auth }) => {
|
||||
const authValue = auth as PiecePropValueSchema<typeof zohoCampaignsAuth>;
|
||||
const location = authValue.props?.['location'] || 'zoho.com';
|
||||
if (!auth) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'Connect your Zoho Campaigns account first',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
const topics = await zohoCampaignsCommon.listTopics({
|
||||
accessToken: authValue.access_token,
|
||||
location,
|
||||
});
|
||||
if (topics.length === 0) {
|
||||
return {
|
||||
disabled: true,
|
||||
placeholder: 'No topics found',
|
||||
options: [],
|
||||
};
|
||||
}
|
||||
return {
|
||||
options: topics.map((topic) => ({
|
||||
label: topic.topicName,
|
||||
value: topic.topicId,
|
||||
})),
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
const contactInformation = Property.DynamicProperties({
|
||||
displayName: 'Contact Information',
|
||||
description: 'Information about the contact',
|
||||
required: true,
|
||||
auth: zohoCampaignsAuth,
|
||||
refreshers: ['auth'],
|
||||
props: async () => ({
|
||||
'Contact Email': Property.ShortText({
|
||||
displayName: 'Contact Email',
|
||||
description: 'Email address of the contact',
|
||||
required: true,
|
||||
}),
|
||||
'First Name': Property.ShortText({
|
||||
displayName: 'First Name',
|
||||
description: 'First name of the contact',
|
||||
required: false,
|
||||
}),
|
||||
'Last Name': Property.ShortText({
|
||||
displayName: 'Last Name',
|
||||
description: 'Last name of the contact',
|
||||
required: false,
|
||||
}),
|
||||
Phone: Property.ShortText({
|
||||
displayName: 'Phone',
|
||||
description: 'Phone number of the contact',
|
||||
required: false,
|
||||
}),
|
||||
'Company Name': Property.ShortText({
|
||||
displayName: 'Company Name',
|
||||
description: 'Company name of the contact',
|
||||
required: false,
|
||||
}),
|
||||
additionalFields: Property.Object({
|
||||
displayName: 'Additional Fields',
|
||||
description:
|
||||
'Additional fields for the contact in key-value pairs. For example, {"City": "New York", "State": "NY"}',
|
||||
required: false,
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
// Action Properties
|
||||
export const createCampaign = () => ({
|
||||
campaignname: Property.ShortText({
|
||||
displayName: 'Campaign Name',
|
||||
description: 'A name to your campaign',
|
||||
required: true,
|
||||
}),
|
||||
from_email: Property.ShortText({
|
||||
displayName: 'From Email',
|
||||
description: 'Sender email address for the campaign',
|
||||
required: true,
|
||||
}),
|
||||
subject: Property.ShortText({
|
||||
displayName: 'Subject',
|
||||
description: 'The subject line of the campaign',
|
||||
required: true,
|
||||
}),
|
||||
list_details: mailingListMultiSelectDropdown({ required: true }),
|
||||
content_url: Property.ShortText({
|
||||
displayName: 'Content URL',
|
||||
description: 'Public URL containing the HTML content for your campaign',
|
||||
required: false,
|
||||
}),
|
||||
topicId: topicDropdown({ required: false }),
|
||||
});
|
||||
|
||||
export const cloneCampaign = () => ({
|
||||
campaignkey: campaignDropdown(),
|
||||
campaignname: Property.ShortText({
|
||||
displayName: 'Campaign Name',
|
||||
description: 'New name for the cloned campaign',
|
||||
required: false,
|
||||
}),
|
||||
subject: Property.ShortText({
|
||||
displayName: 'Subject',
|
||||
description: 'New subject line for the cloned campaign',
|
||||
required: false,
|
||||
}),
|
||||
from_name: Property.ShortText({
|
||||
displayName: 'From Name',
|
||||
description: 'Sender name for the cloned campaign',
|
||||
required: false,
|
||||
}),
|
||||
from_add: Property.ShortText({
|
||||
displayName: 'From Email',
|
||||
description: 'Sender email address for the cloned campaign',
|
||||
required: false,
|
||||
}),
|
||||
reply_to: Property.ShortText({
|
||||
displayName: 'Reply-To Email',
|
||||
description: 'Reply-to email address for the cloned campaign',
|
||||
required: false,
|
||||
}),
|
||||
encode_type: Property.ShortText({
|
||||
displayName: 'Encoding Type',
|
||||
description: 'Email encoding type (e.g., UTF-8)',
|
||||
required: false,
|
||||
}),
|
||||
});
|
||||
|
||||
export const sendCampaign = () => ({
|
||||
campaignkey: campaignDropdown(),
|
||||
});
|
||||
|
||||
export const addUpdateContact = () => ({
|
||||
listkey: mailingListDropdown({ required: true }),
|
||||
contactinfo: contactInformation,
|
||||
source: Property.ShortText({
|
||||
displayName: 'Source',
|
||||
description: 'Contact source can be added.',
|
||||
required: false,
|
||||
}),
|
||||
topic_id: topicDropdown({ required: false }),
|
||||
});
|
||||
|
||||
export const addTagToContact: {
|
||||
tagName: any;
|
||||
lead_email: any;
|
||||
} = {
|
||||
tagName: tagDropdown({ required: true }),
|
||||
lead_email: Property.ShortText({
|
||||
displayName: 'Contact Email',
|
||||
description: 'Email address of the contact to tag',
|
||||
required: true,
|
||||
}),
|
||||
};
|
||||
|
||||
export const removeTag: {
|
||||
tagName: any;
|
||||
lead_email: any;
|
||||
} = {
|
||||
tagName: tagDropdown({ required: true }),
|
||||
lead_email: Property.ShortText({
|
||||
displayName: 'Contact Email',
|
||||
description: 'Email address of the contact to remove the tag from',
|
||||
required: true,
|
||||
}),
|
||||
};
|
||||
|
||||
export const unsubscribeContact = () => ({
|
||||
listkey: mailingListDropdown({ required: true }),
|
||||
contactinfo: contactInformation,
|
||||
topic_id: topicDropdown({ required: false }),
|
||||
});
|
||||
|
||||
export const addContactToMailingList = () => ({
|
||||
listkey: mailingListDropdown({ required: true }),
|
||||
emails: Property.Array({
|
||||
displayName: 'Emails',
|
||||
description:
|
||||
'Contacts email addresses to be added to the mailing list (maximum 10 emails)',
|
||||
required: true,
|
||||
}),
|
||||
});
|
||||
|
||||
export const findContact = () => ({
|
||||
listkey: mailingListDropdown({ required: true }),
|
||||
contactEmail: Property.ShortText({
|
||||
displayName: 'Contact Email',
|
||||
description: 'Email of the contact to be found (partial matches supported)',
|
||||
required: true,
|
||||
}),
|
||||
status: Property.StaticDropdown({
|
||||
displayName: 'Contact Status',
|
||||
description: 'Filter contacts by status',
|
||||
required: true,
|
||||
options: {
|
||||
options: [
|
||||
{ label: 'Active', value: 'active' },
|
||||
{ label: 'Recent', value: 'recent' },
|
||||
{ label: 'Most Recent', value: 'most recent' },
|
||||
{ label: 'Unsubscribed', value: 'unsub' },
|
||||
{ label: 'Bounced', value: 'bounce' },
|
||||
],
|
||||
},
|
||||
}),
|
||||
sort: Property.StaticDropdown({
|
||||
displayName: 'Sort Order',
|
||||
description: 'Sort order for results',
|
||||
required: true,
|
||||
options: {
|
||||
options: [
|
||||
{ label: 'Ascending', value: 'asc' },
|
||||
{ label: 'Descending', value: 'desc' },
|
||||
],
|
||||
},
|
||||
}),
|
||||
fromindex: Property.Number({
|
||||
displayName: 'From Index',
|
||||
description: 'Starting index for pagination (optional, default: 1)',
|
||||
required: false,
|
||||
}),
|
||||
range: Property.Number({
|
||||
displayName: 'Range',
|
||||
description: 'Number of contacts to retrieve (optional, default: all)',
|
||||
required: false,
|
||||
}),
|
||||
});
|
||||
|
||||
export const findCampaign = () => ({
|
||||
campaignName: Property.ShortText({
|
||||
displayName: 'Campaign Name',
|
||||
description: 'Name of the campaign to be found (partial matches supported)',
|
||||
required: true,
|
||||
}),
|
||||
status: Property.StaticDropdown({
|
||||
displayName: 'Campaign Status',
|
||||
description: 'Filter campaigns by status (optional)',
|
||||
required: false,
|
||||
options: {
|
||||
options: [
|
||||
{ label: 'All', value: 'all' },
|
||||
{ label: 'All Campaigns', value: 'all campaigns' },
|
||||
{ label: 'Drafts', value: 'drafts' },
|
||||
{ label: 'Scheduled', value: 'scheduled' },
|
||||
{ label: 'In Progress', value: 'inprogress' },
|
||||
{ label: 'Sent', value: 'sent' },
|
||||
{ label: 'Stopped', value: 'stopped' },
|
||||
{ label: 'Canceled', value: 'canceled' },
|
||||
{ label: 'To Be Reviewed', value: 'tobereviewed' },
|
||||
{ label: 'Reviewed', value: 'reviewed' },
|
||||
{ label: 'Paused', value: 'paused' },
|
||||
{ label: 'In Testing', value: 'intesting' },
|
||||
],
|
||||
},
|
||||
}),
|
||||
sort: Property.StaticDropdown({
|
||||
displayName: 'Sort Order',
|
||||
description: 'Sort order for results (optional)',
|
||||
required: false,
|
||||
options: {
|
||||
options: [
|
||||
{ label: 'Ascending', value: 'asc' },
|
||||
{ label: 'Descending', value: 'desc' },
|
||||
],
|
||||
},
|
||||
}),
|
||||
fromindex: Property.Number({
|
||||
displayName: 'From Index',
|
||||
description: 'Starting index for pagination (optional, default: 1)',
|
||||
required: false,
|
||||
}),
|
||||
range: Property.Number({
|
||||
displayName: 'Range',
|
||||
description: 'Number of campaigns to retrieve (optional, default: 5)',
|
||||
required: false,
|
||||
}),
|
||||
});
|
||||
|
||||
export const newContact = () => ({
|
||||
listkey: mailingListDropdown({ required: true }),
|
||||
});
|
||||
|
||||
export const unsubscribe = () => ({
|
||||
listkey: mailingListDropdown({ required: true }),
|
||||
status: Property.StaticDropdown({
|
||||
displayName: 'Unsubscribe Type',
|
||||
description: 'Type of contact removal to monitor (default: unsubscribed)',
|
||||
required: false,
|
||||
options: {
|
||||
options: [
|
||||
{ label: 'Unsubscribed', value: 'unsub' },
|
||||
{ label: 'Bounced', value: 'bounce' },
|
||||
],
|
||||
},
|
||||
}),
|
||||
});
|
||||
@@ -0,0 +1,73 @@
|
||||
import z from 'zod';
|
||||
|
||||
export const createCampaign = {
|
||||
campaignname: z.string(),
|
||||
from_email: z.string().email(),
|
||||
subject: z.string(),
|
||||
content_url: z.string().url().optional(),
|
||||
list_details: z.array(z.string()),
|
||||
topicId: z.string().nullable().optional(),
|
||||
}
|
||||
|
||||
export const cloneCampaign = {
|
||||
campaignkey: z.string(),
|
||||
campaignname: z.string().optional(),
|
||||
subject: z.string().optional(),
|
||||
from_name: z.string().optional(),
|
||||
from_add: z.string().email().optional(),
|
||||
reply_to: z.string().email().optional(),
|
||||
encode_type: z.string().optional(),
|
||||
}
|
||||
|
||||
export const sendCampaign = {
|
||||
campaignkey: z.string(),
|
||||
}
|
||||
|
||||
export const addUpdateContact = {
|
||||
listkey: z.string(),
|
||||
contactinfo: z.object({
|
||||
'Contact Email': z.string().email(),
|
||||
}),
|
||||
source: z.string().optional(),
|
||||
topic_id: z.string().nullable().optional(),
|
||||
}
|
||||
|
||||
export const addTagToContact = {
|
||||
tagName: z.string(),
|
||||
lead_email: z.string().email(),
|
||||
}
|
||||
|
||||
export const removeTag = {
|
||||
tagName: z.string(),
|
||||
lead_email: z.string().email(),
|
||||
}
|
||||
|
||||
export const unsubscribeContact = {
|
||||
listkey: z.string(),
|
||||
contactinfo: z.object({
|
||||
'Contact Email': z.string().email(),
|
||||
}),
|
||||
topic_id: z.string().nullable().optional(),
|
||||
}
|
||||
|
||||
export const addContactToMailingList = {
|
||||
listkey: z.string(),
|
||||
emails: z.array(z.string().email()).min(1).max(10),
|
||||
}
|
||||
|
||||
export const findContact = {
|
||||
listkey: z.string(),
|
||||
contactEmail: z.string().email(),
|
||||
status: z.enum(['active', 'recent', 'most recent', 'unsub', 'bounce']).optional(),
|
||||
sort: z.enum(['asc', 'desc']).optional(),
|
||||
fromindex: z.number().min(1).optional(),
|
||||
range: z.number().min(1).optional(),
|
||||
}
|
||||
|
||||
export const findCampaign = {
|
||||
campaignName: z.string(),
|
||||
status: z.enum(['all', 'all campaigns', 'drafts', 'scheduled', 'inprogress', 'sent', 'stopped', 'canceled', 'tobereviewed', 'reviewed', 'paused', 'intesting']).optional(),
|
||||
sort: z.enum(['asc', 'desc']).optional(),
|
||||
fromindex: z.number().min(1).optional(),
|
||||
range: z.number().min(1).optional(),
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
export interface AuthorizationParams {
|
||||
accessToken: string;
|
||||
}
|
||||
|
||||
export interface BaseCampaignKeyParams {
|
||||
campaignkey: string;
|
||||
}
|
||||
|
||||
export interface CreateCampaignParams extends AuthorizationParams {
|
||||
campaignname: string;
|
||||
from_email: string;
|
||||
subject: string;
|
||||
content_url?: string;
|
||||
list_details: object;
|
||||
topicId?: string;
|
||||
}
|
||||
|
||||
export interface CreateTagParams extends AuthorizationParams {
|
||||
tagName: string;
|
||||
}
|
||||
|
||||
export interface CloneCampaignParams extends AuthorizationParams {
|
||||
campaigninfo: object;
|
||||
}
|
||||
|
||||
export interface SendCampaignParams
|
||||
extends AuthorizationParams,
|
||||
BaseCampaignKeyParams {}
|
||||
|
||||
export interface AddUpdateContactParams extends AuthorizationParams {
|
||||
listkey: string;
|
||||
contactinfo: object;
|
||||
source?: string;
|
||||
topic_id?: string;
|
||||
}
|
||||
|
||||
export interface AddTagToContactParams extends AuthorizationParams {
|
||||
tagName: string;
|
||||
lead_email: string;
|
||||
}
|
||||
|
||||
export interface RemoveTagParams extends AuthorizationParams {
|
||||
tagName: string;
|
||||
lead_email: string;
|
||||
}
|
||||
|
||||
export interface UnsubscribeContactParams extends AuthorizationParams {
|
||||
listkey: string;
|
||||
contactinfo: object;
|
||||
topic_id?: string;
|
||||
}
|
||||
|
||||
export interface AddContactToMailingListParams extends AuthorizationParams {
|
||||
listkey: string;
|
||||
emailids: string;
|
||||
}
|
||||
|
||||
export interface ListContactsParams extends AuthorizationParams {
|
||||
listkey: string;
|
||||
sort?: 'asc' | 'desc';
|
||||
fromindex?: number;
|
||||
range?: number;
|
||||
status?: 'active' | 'recent' | 'most recent' | 'unsub' | 'bounce';
|
||||
}
|
||||
|
||||
export interface ListCampaignParams extends AuthorizationParams {
|
||||
sort?: 'asc' | 'desc';
|
||||
fromindex?: number;
|
||||
range?: number;
|
||||
status?:
|
||||
| 'all'
|
||||
| 'all campaigns'
|
||||
| 'drafts'
|
||||
| 'scheduled'
|
||||
| 'inprogress'
|
||||
| 'sent'
|
||||
| 'stopped'
|
||||
| 'canceled'
|
||||
| 'tobereviewed'
|
||||
| 'reviewed'
|
||||
| 'paused'
|
||||
| 'intesting';
|
||||
}
|
||||
|
||||
export interface ListMailingListsParams extends AuthorizationParams {
|
||||
sort?: 'asc' | 'desc';
|
||||
fromindex?: number;
|
||||
range?: number;
|
||||
}
|
||||
|
||||
|
||||
// API Response types
|
||||
export type Campaign = {
|
||||
campaign_key: string;
|
||||
campaign_name: string;
|
||||
created_date_string: string;
|
||||
campaign_status: string;
|
||||
created_time: string;
|
||||
campaign_preview: string;
|
||||
};
|
||||
|
||||
export type Contact = {
|
||||
firstname: string;
|
||||
added_time: string;
|
||||
phone: string;
|
||||
companyname: string;
|
||||
contact_email: string;
|
||||
lastname: string;
|
||||
zuid: string;
|
||||
};
|
||||
|
||||
export type MailingList = {
|
||||
date: string;
|
||||
deletable: string;
|
||||
segments: object;
|
||||
updated_time_gmt: string;
|
||||
listdesc: string;
|
||||
created_time_gmt: string;
|
||||
list_created_time: string;
|
||||
noofunsubcnt: string;
|
||||
lockstatus: string;
|
||||
listkey: string;
|
||||
listtype: string;
|
||||
sentcnt: string;
|
||||
owner: string;
|
||||
list_campaigns_count: string;
|
||||
created_time: string;
|
||||
noofcontacts: string;
|
||||
editable: string;
|
||||
listname: string;
|
||||
listdgs: string;
|
||||
noofbouncecnt: string;
|
||||
issmart: string;
|
||||
list_created_date: string;
|
||||
listnotifications: string;
|
||||
listunino: string;
|
||||
zuid: string;
|
||||
servicetype: string;
|
||||
sno: string;
|
||||
is_public: string;
|
||||
otherslist: string;
|
||||
zx: string;
|
||||
};
|
||||
|
||||
export type Topic = {
|
||||
topicId: string;
|
||||
topicName: string;
|
||||
primaryList: number;
|
||||
};
|
||||
|
||||
export type Tag = {
|
||||
[key: string]: {
|
||||
tagowner: string;
|
||||
tag_created_time: string;
|
||||
tag_name: string;
|
||||
tag_color: string;
|
||||
tag_desc: string;
|
||||
tagged_contact_count: string;
|
||||
is_crm_tag: string;
|
||||
zuid: string;
|
||||
};
|
||||
};
|
||||
|
||||
export interface ListCampaignResponse {
|
||||
fromindex: string;
|
||||
total_record_count: string;
|
||||
code: string;
|
||||
recent_campaigns: Campaign[];
|
||||
range: string;
|
||||
campaign_count: string;
|
||||
uri: string;
|
||||
version: string;
|
||||
requestdetails: string;
|
||||
status: string;
|
||||
}
|
||||
|
||||
export interface ListContactsResponse {
|
||||
code: string;
|
||||
uri: string;
|
||||
version: string;
|
||||
list_of_details: Contact[];
|
||||
requestdetails: {
|
||||
fromindex: number;
|
||||
range: number;
|
||||
sort: string;
|
||||
status: string;
|
||||
};
|
||||
status: string;
|
||||
}
|
||||
|
||||
export interface ListMailingListsResponse {
|
||||
code: string;
|
||||
uri: string;
|
||||
version: string;
|
||||
list_of_details: MailingList[];
|
||||
requestdetails: {
|
||||
fromindex: number;
|
||||
range: number;
|
||||
total_list_count: number;
|
||||
sort: string;
|
||||
};
|
||||
status: string;
|
||||
}
|
||||
|
||||
export interface ListTopicsResponse {
|
||||
topicDetails: Topic[];
|
||||
message: string;
|
||||
code: string;
|
||||
uri: string;
|
||||
}
|
||||
|
||||
export interface CreateCampaignResponse {
|
||||
message: string;
|
||||
campaignKey: string;
|
||||
code: string;
|
||||
uri: string;
|
||||
}
|
||||
|
||||
export interface ListTagsResponse {
|
||||
uri: string;
|
||||
version: string;
|
||||
requestdetails: string;
|
||||
tags?: Tag[];
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
import {
|
||||
DedupeStrategy,
|
||||
Polling,
|
||||
pollingHelper,
|
||||
} from '@activepieces/pieces-common';
|
||||
import {
|
||||
AppConnectionValueForAuthProperty,
|
||||
createTrigger,
|
||||
TriggerStrategy,
|
||||
} from '@activepieces/pieces-framework';
|
||||
import dayjs from 'dayjs';
|
||||
import { zohoCampaignsAuth, zohoCampaignsCommon } from '../common';
|
||||
|
||||
const polling: Polling<
|
||||
AppConnectionValueForAuthProperty<typeof zohoCampaignsAuth>,
|
||||
Record<string, never>
|
||||
> = {
|
||||
strategy: DedupeStrategy.TIMEBASED,
|
||||
items: async ({ auth }) => {
|
||||
const location = auth.props?.['location'] as string || 'zoho.com';
|
||||
const accessToken = auth.access_token;
|
||||
const items = await zohoCampaignsCommon.listCampaigns({
|
||||
accessToken,
|
||||
location,
|
||||
});
|
||||
return items.map((item) => ({
|
||||
epochMilliSeconds: dayjs(item.created_date_string).valueOf(),
|
||||
data: item,
|
||||
}));
|
||||
},
|
||||
};
|
||||
|
||||
export const newCampaign = createTrigger({
|
||||
auth: zohoCampaignsAuth,
|
||||
name: 'newCampaign',
|
||||
displayName: 'New Campaign',
|
||||
description: 'Fires when a new campaign is created.',
|
||||
props: {},
|
||||
sampleData: {
|
||||
campaign_key: 'f70c4878c4a47169407e63917ad24497',
|
||||
campaign_name: 'Summer Newsletter 2024',
|
||||
created_date_string: '19 Aug 2024, 11:26 AM',
|
||||
campaign_status: 'Draft',
|
||||
created_time: '1724065567000',
|
||||
campaign_preview:
|
||||
'https://campaigns.zoho.com/EmailDisplayAction.do?&campaignId=303000023454038',
|
||||
},
|
||||
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,76 @@
|
||||
import {
|
||||
DedupeStrategy,
|
||||
Polling,
|
||||
pollingHelper,
|
||||
} from '@activepieces/pieces-common';
|
||||
import {
|
||||
AppConnectionValueForAuthProperty,
|
||||
createTrigger,
|
||||
PiecePropValueSchema,
|
||||
StaticPropsValue,
|
||||
TriggerStrategy,
|
||||
} from '@activepieces/pieces-framework';
|
||||
import dayjs from 'dayjs';
|
||||
import { zohoCampaignsAuth, zohoCampaignsCommon } from '../common';
|
||||
|
||||
const polling: Polling<
|
||||
AppConnectionValueForAuthProperty<typeof zohoCampaignsAuth>,
|
||||
StaticPropsValue<any>
|
||||
> = {
|
||||
strategy: DedupeStrategy.TIMEBASED,
|
||||
items: async ({ auth, propsValue }) => {
|
||||
const location = auth.props?.['location'] as string || 'zoho.com';
|
||||
const accessToken = auth.access_token;
|
||||
const { listkey } = propsValue;
|
||||
|
||||
if (!listkey) {
|
||||
throw new Error('Mailing list is required');
|
||||
}
|
||||
|
||||
const items = await zohoCampaignsCommon.listContacts({
|
||||
accessToken,
|
||||
location,
|
||||
listkey,
|
||||
sort:'desc',
|
||||
});
|
||||
|
||||
return items.map((item) => ({
|
||||
epochMilliSeconds: dayjs(item.added_time).valueOf(),
|
||||
data: item,
|
||||
}));
|
||||
},
|
||||
};
|
||||
|
||||
export const newContact = createTrigger({
|
||||
auth: zohoCampaignsAuth,
|
||||
name: 'newContact',
|
||||
displayName: 'New Contact',
|
||||
description: 'Fires when a new contact is added to a selected mailing list.',
|
||||
props: zohoCampaignsCommon.newContactProperties(),
|
||||
sampleData: {
|
||||
contact_email: 'john.doe@example.com',
|
||||
firstname: 'John',
|
||||
lastname: 'Doe',
|
||||
phone: '+1-555-123-4567',
|
||||
companyname: 'Acme Corp',
|
||||
zuid: '12345678',
|
||||
added_time: '1699123456789',
|
||||
},
|
||||
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,78 @@
|
||||
import {
|
||||
DedupeStrategy,
|
||||
Polling,
|
||||
pollingHelper,
|
||||
} from '@activepieces/pieces-common';
|
||||
import {
|
||||
AppConnectionValueForAuthProperty,
|
||||
createTrigger,
|
||||
PiecePropValueSchema,
|
||||
StaticPropsValue,
|
||||
TriggerStrategy,
|
||||
} from '@activepieces/pieces-framework';
|
||||
import dayjs from 'dayjs';
|
||||
import { zohoCampaignsAuth, zohoCampaignsCommon } from '../common';
|
||||
|
||||
// replace auth with piece auth variable
|
||||
const polling: Polling<
|
||||
AppConnectionValueForAuthProperty<typeof zohoCampaignsAuth>,
|
||||
StaticPropsValue<any>
|
||||
> = {
|
||||
strategy: DedupeStrategy.TIMEBASED,
|
||||
items: async ({ auth, propsValue }) => {
|
||||
const { listkey, status = 'unsub' } = propsValue;
|
||||
const location = auth.props?.['location'] as string || 'zoho.com';
|
||||
const accessToken = auth.access_token;
|
||||
|
||||
if (!listkey) {
|
||||
throw new Error('Mailing list is required');
|
||||
}
|
||||
|
||||
const items = await zohoCampaignsCommon.listContacts({
|
||||
accessToken,
|
||||
location,
|
||||
listkey,
|
||||
sort: 'desc',
|
||||
status,
|
||||
});
|
||||
return items.map((item) => ({
|
||||
epochMilliSeconds: dayjs(item.added_time).valueOf(),
|
||||
data: item,
|
||||
}));
|
||||
},
|
||||
};
|
||||
|
||||
export const unsubscribe = createTrigger({
|
||||
auth: zohoCampaignsAuth,
|
||||
name: 'unsubscribe',
|
||||
displayName: 'Unsubscribe',
|
||||
description:
|
||||
'Fires when a contact is removed from a mailing list or unsubscribed.',
|
||||
props: zohoCampaignsCommon.unsubscribeProperties(),
|
||||
sampleData: {
|
||||
contact_email: 'unsubscribed@example.com',
|
||||
firstname: 'John',
|
||||
lastname: 'Doe',
|
||||
phone: '+1-555-123-4567',
|
||||
companyname: 'Acme Corp',
|
||||
zuid: '12345678',
|
||||
added_time: '1699123456789',
|
||||
},
|
||||
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);
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user