new-bitlink-created.ts•11 kB
import { createTrigger, TriggerStrategy, Property } from '@activepieces/pieces-framework';
import { HttpMethod } from '@activepieces/pieces-common';
import { bitlyAuth } from '../common/auth';
import { bitlyApiCall } from '../common/client';
import { groupGuid } from '../common/props';
const LAST_BITLINK_IDS_KEY = 'bitly-last-bitlink-ids';
export const newBitlinkCreatedTrigger = createTrigger({
auth: bitlyAuth,
name: 'new_bitlink_created',
displayName: 'New Bitlink Created',
description: 'Fires when a new Bitlink is created.',
type: TriggerStrategy.POLLING,
props: {
pollingInterval: Property.StaticDropdown({
displayName: 'Polling Interval',
description: 'How frequently to check for new Bitlinks.',
required: false,
defaultValue: '5',
options: {
disabled: false,
options: [
{ label: 'Every 1 minute', value: '1' },
{ label: 'Every 5 minutes', value: '5' },
{ label: 'Every 15 minutes', value: '15' },
{ label: 'Every 30 minutes', value: '30' },
{ label: 'Every hour', value: '60' },
],
},
}),
group_guid: groupGuid,
titleFilter: Property.ShortText({
displayName: 'Title Filter (Optional)',
description: 'Only trigger for Bitlinks containing this text in their title.',
required: false,
}),
tagFilter: Property.ShortText({
displayName: 'Tag Filter (Optional)',
description: 'Only trigger for Bitlinks containing this tag.',
required: false,
}),
includeArchived: Property.Checkbox({
displayName: 'Include Archived Bitlinks',
description: 'Include archived Bitlinks in monitoring.',
required: false,
defaultValue: false,
}),
},
async onEnable(context) {
const { group_guid } = context.propsValue;
const { accessToken } = context.auth;
try {
const response = await bitlyApiCall<{ links: BitlyLink[] }>({
auth: { accessToken },
method: HttpMethod.GET,
resourceUri: `/groups/${group_guid}/bitlinks`,
query: {
size: 50,
archived: context.propsValue.includeArchived ? 'both' : 'off',
},
});
const linkIds = response.links.map((link) => link.id);
await context.store.put<string[]>(LAST_BITLINK_IDS_KEY, linkIds);
console.log(`Bitly New Bitlink trigger initialized with ${linkIds.length} existing links`);
} catch (error: any) {
if (error.response?.status === 401) {
throw new Error(
'Authentication failed: Please check your access token. Make sure your token has permission to access Bitlinks.'
);
}
if (error.response?.status === 403) {
throw new Error(
'Access denied: You do not have permission to list Bitlinks. Please check your Bitly account permissions.'
);
}
throw new Error(
`Failed to initialize Bitlink monitoring: ${error.message || 'Unknown error occurred'}. Please check your Bitly connection.`
);
}
},
async onDisable() {
console.log('Bitly New Bitlink trigger disabled and cleaned up');
},
async run(context) {
const { group_guid, titleFilter, tagFilter, includeArchived } = context.propsValue;
const { accessToken } = context.auth;
try {
const previousLinkIds = await context.store.get<string[]>(LAST_BITLINK_IDS_KEY) || [];
const response = await bitlyApiCall<{ links: BitlyLink[] }>({
auth: { accessToken },
method: HttpMethod.GET,
resourceUri: `/groups/${group_guid}/bitlinks`,
query: {
size: 50,
archived: includeArchived ? 'both' : 'off',
},
});
const allLinks = response.links || [];
const currentLinkIds = allLinks.map((l) => l.id);
await context.store.put<string[]>(LAST_BITLINK_IDS_KEY, currentLinkIds);
let newLinks = allLinks.filter((link) => !previousLinkIds.includes(link.id));
if (titleFilter && titleFilter.trim()) {
const filterText = titleFilter.trim().toLowerCase();
newLinks = newLinks.filter((link) =>
link.title && link.title.toLowerCase().includes(filterText)
);
}
if (tagFilter && tagFilter.trim()) {
const filterTag = tagFilter.trim().toLowerCase();
newLinks = newLinks.filter((link) =>
link.tags && Array.isArray(link.tags) &&
link.tags.some(tag => tag.toLowerCase().includes(filterTag))
);
}
const processedLinks = newLinks.map((link) => ({
id: link.id,
link: link.link,
longUrl: link.long_url,
title: link.title,
tags: link.tags || [],
isArchived: link.archived,
createdAt: link.created_at,
modifiedAt: link.modified_at,
customBitlinks: link.custom_bitlinks || [],
references: {
group: link.references?.group,
},
rawLinkData: link,
triggerInfo: {
detectedAt: new Date().toISOString(),
source: 'bitly',
type: 'new_bitlink',
},
}));
return processedLinks;
} catch (error: any) {
if (error.response?.status === 401) {
throw new Error(
'Authentication failed: Your access token may have expired. Please check your Bitly authentication.'
);
}
if (error.response?.status === 429) {
throw new Error(
'Rate limit exceeded: Bitly API rate limit reached. Consider increasing your polling interval.'
);
}
if (error.response?.status === 403) {
throw new Error(
'Access denied: You do not have permission to list Bitlinks. Please check your account permissions.'
);
}
throw new Error(
`Failed to check for new Bitlinks: ${error.message || 'Unknown error occurred'}. The trigger will retry on the next polling interval.`
);
}
},
async test(context) {
const { group_guid, includeArchived } = context.propsValue;
const { accessToken } = context.auth;
try {
const response = await bitlyApiCall<{ links: BitlyLink[] }>({
auth: { accessToken },
method: HttpMethod.GET,
resourceUri: `/groups/${group_guid}/bitlinks`,
query: {
size: 1,
archived: includeArchived ? 'both' : 'off',
},
});
const links = response.links || [];
if (links.length > 0) {
const testLink = links[0];
return [
{
id: testLink.id,
link: testLink.link,
longUrl: testLink.long_url,
title: testLink.title,
tags: testLink.tags || [],
isArchived: testLink.archived,
createdAt: testLink.created_at,
modifiedAt: testLink.modified_at,
customBitlinks: testLink.custom_bitlinks || [],
references: {
group: testLink.references?.group,
},
rawLinkData: testLink,
triggerInfo: {
detectedAt: new Date().toISOString(),
source: 'bitly',
type: 'new_bitlink',
},
},
];
} else {
return [
{
id: 'bit.ly/test123',
link: 'https://bit.ly/test123',
longUrl: 'https://example.com/very-long-url',
title: 'Sample Bitlink',
tags: ['sample', 'test'],
isArchived: false,
createdAt: '2025-01-15T10:00:00+0000',
modifiedAt: '2025-01-15T10:00:00+0000',
customBitlinks: [],
references: {
group: 'Ba1bc23dE4F',
},
rawLinkData: {
id: 'bit.ly/test123',
link: 'https://bit.ly/test123',
long_url: 'https://example.com/very-long-url',
title: 'Sample Bitlink',
tags: ['sample', 'test'],
archived: false,
created_at: '2025-01-15T10:00:00+0000',
modified_at: '2025-01-15T10:00:00+0000',
custom_bitlinks: [],
references: {
group: 'Ba1bc23dE4F',
},
},
triggerInfo: {
detectedAt: new Date().toISOString(),
source: 'bitly',
type: 'new_bitlink',
},
},
];
}
} catch (error: any) {
return [
{
id: 'bit.ly/test123',
link: 'https://bit.ly/test123',
longUrl: 'https://example.com/test-url',
title: 'Test Bitlink',
tags: ['test'],
isArchived: false,
createdAt: '2025-01-15T10:00:00+0000',
modifiedAt: '2025-01-15T10:00:00+0000',
customBitlinks: [],
references: {
group: 'Ba1bc23dE4F',
},
rawLinkData: {
id: 'bit.ly/test123',
link: 'https://bit.ly/test123',
long_url: 'https://example.com/test-url',
title: 'Test Bitlink',
tags: ['test'],
archived: false,
created_at: '2025-01-15T10:00:00+0000',
modified_at: '2025-01-15T10:00:00+0000',
custom_bitlinks: [],
references: {
group: 'Ba1bc23dE4F',
},
},
triggerInfo: {
detectedAt: new Date().toISOString(),
source: 'bitly',
type: 'new_bitlink',
},
},
];
}
},
sampleData: {
id: 'bit.ly/3XYZ123',
link: 'https://bit.ly/3XYZ123',
longUrl: 'https://example.com/marketing-campaign-landing-page',
title: 'Marketing Campaign Landing Page',
tags: ['marketing', 'campaign', '2025'],
isArchived: false,
createdAt: '2025-01-15T09:30:00+0000',
modifiedAt: '2025-01-15T09:30:00+0000',
customBitlinks: [],
references: {
group: 'Ba1bc23dE4F',
},
rawLinkData: {
id: 'bit.ly/3XYZ123',
link: 'https://bit.ly/3XYZ123',
long_url: 'https://example.com/marketing-campaign-landing-page',
title: 'Marketing Campaign Landing Page',
tags: ['marketing', 'campaign', '2025'],
archived: false,
created_at: '2025-01-15T09:30:00+0000',
modified_at: '2025-01-15T09:30:00+0000',
custom_bitlinks: [],
references: {
group: 'Ba1bc23dE4F',
},
},
triggerInfo: {
detectedAt: '2025-01-15T09:30:00.000Z',
source: 'bitly',
type: 'new_bitlink',
},
},
});
/**
* Interface for Bitly link data structure
*/
interface BitlyLink {
id: string;
link: string;
long_url: string;
title: string;
tags: string[];
archived: boolean;
created_at: string;
modified_at: string;
custom_bitlinks: string[];
references: {
group: string;
};
[key: string]: any;
}