@agnocon/piece-buttondown 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.MIT-AP +24 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/actions/create-subscriber.d.ts +17 -0
- package/dist/lib/actions/create-subscriber.d.ts.map +1 -0
- package/dist/lib/actions/create-subscriber.js +155 -0
- package/dist/lib/actions/create-subscriber.js.map +1 -0
- package/dist/lib/actions/custom-api-call.d.ts +13 -0
- package/dist/lib/actions/custom-api-call.d.ts.map +1 -0
- package/dist/lib/actions/custom-api-call.js +19 -0
- package/dist/lib/actions/custom-api-call.js.map +1 -0
- package/dist/lib/actions/list-subscribers.d.ts +11 -0
- package/dist/lib/actions/list-subscribers.d.ts.map +1 -0
- package/dist/lib/actions/list-subscribers.js +115 -0
- package/dist/lib/actions/list-subscribers.js.map +1 -0
- package/dist/lib/actions/send-email.d.ts +16 -0
- package/dist/lib/actions/send-email.d.ts.map +1 -0
- package/dist/lib/actions/send-email.js +147 -0
- package/dist/lib/actions/send-email.js.map +1 -0
- package/dist/lib/common/auth.d.ts +2 -0
- package/dist/lib/common/auth.d.ts.map +1 -0
- package/dist/lib/common/auth.js +46 -0
- package/dist/lib/common/auth.js.map +1 -0
- package/dist/lib/common/client.d.ts +20 -0
- package/dist/lib/common/client.d.ts.map +1 -0
- package/dist/lib/common/client.js +41 -0
- package/dist/lib/common/client.js.map +1 -0
- package/dist/lib/common/options.d.ts +22 -0
- package/dist/lib/common/options.d.ts.map +1 -0
- package/dist/lib/common/options.js +58 -0
- package/dist/lib/common/options.js.map +1 -0
- package/dist/lib/common/types.d.ts +81 -0
- package/dist/lib/common/types.d.ts.map +1 -0
- package/dist/lib/common/types.js +3 -0
- package/dist/lib/common/types.js.map +1 -0
- package/dist/lib/common/webhook.d.ts +36 -0
- package/dist/lib/common/webhook.d.ts.map +1 -0
- package/dist/lib/common/webhook.js +80 -0
- package/dist/lib/common/webhook.js.map +1 -0
- package/dist/lib/triggers/email-sent.d.ts +14 -0
- package/dist/lib/triggers/email-sent.d.ts.map +1 -0
- package/dist/lib/triggers/email-sent.js +43 -0
- package/dist/lib/triggers/email-sent.js.map +1 -0
- package/dist/lib/triggers/new-subscriber.d.ts +14 -0
- package/dist/lib/triggers/new-subscriber.d.ts.map +1 -0
- package/dist/lib/triggers/new-subscriber.js +43 -0
- package/dist/lib/triggers/new-subscriber.js.map +1 -0
- package/dist/lib/triggers/subscriber-confirmed.d.ts +14 -0
- package/dist/lib/triggers/subscriber-confirmed.d.ts.map +1 -0
- package/dist/lib/triggers/subscriber-confirmed.js +43 -0
- package/dist/lib/triggers/subscriber-confirmed.js.map +1 -0
- package/package.json +46 -0
- package/src/index.ts +26 -0
- package/src/lib/actions/create-subscriber.ts +171 -0
- package/src/lib/actions/custom-api-call.ts +11 -0
- package/src/lib/actions/list-subscribers.ts +125 -0
- package/src/lib/actions/send-email.ts +162 -0
- package/src/lib/common/auth.ts +58 -0
- package/src/lib/common/client.ts +83 -0
- package/src/lib/common/options.ts +65 -0
- package/src/lib/common/types.ts +141 -0
- package/src/lib/common/webhook.ts +105 -0
- package/src/lib/triggers/email-sent.ts +39 -0
- package/src/lib/triggers/new-subscriber.ts +39 -0
- package/src/lib/triggers/subscriber-confirmed.ts +39 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { HttpMethod, httpClient } from '@agnocon/pieces-common';
|
|
2
|
+
|
|
3
|
+
export const BUTTONDOWN_BASE_URL = 'https://api.buttondown.com/v1';
|
|
4
|
+
|
|
5
|
+
type QueryValue =
|
|
6
|
+
| string
|
|
7
|
+
| number
|
|
8
|
+
| boolean
|
|
9
|
+
| Array<string | number | boolean>
|
|
10
|
+
| undefined;
|
|
11
|
+
|
|
12
|
+
export interface ButtondownRequest {
|
|
13
|
+
auth: string;
|
|
14
|
+
method: HttpMethod;
|
|
15
|
+
path: string;
|
|
16
|
+
query?: Record<string, QueryValue>;
|
|
17
|
+
body?: unknown;
|
|
18
|
+
headers?: Record<string, string | undefined>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface ButtondownPagedResponse<T> {
|
|
22
|
+
results: T[];
|
|
23
|
+
count: number;
|
|
24
|
+
next?: string | null;
|
|
25
|
+
previous?: string | null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const sanitizeHeaders = (headers: Record<string, string | undefined> = {}) =>
|
|
29
|
+
Object.fromEntries(
|
|
30
|
+
Object.entries(headers).filter(([, value]) => value !== undefined)
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
const serializeQueryParams = (
|
|
34
|
+
query?: Record<string, QueryValue>
|
|
35
|
+
): Record<string, string> | undefined => {
|
|
36
|
+
if (!query) {
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const result: Record<string, string> = {};
|
|
41
|
+
|
|
42
|
+
for (const [key, value] of Object.entries(query)) {
|
|
43
|
+
if (value === undefined) {
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (Array.isArray(value)) {
|
|
48
|
+
if (value.length === 0) {
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
result[key] = value.map((item) => String(item)).join(',');
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
result[key] = String(value);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return Object.keys(result).length > 0 ? result : undefined;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export const buttondownRequest = async <TResponse>({
|
|
62
|
+
auth,
|
|
63
|
+
method,
|
|
64
|
+
path,
|
|
65
|
+
query,
|
|
66
|
+
body,
|
|
67
|
+
headers,
|
|
68
|
+
}: ButtondownRequest): Promise<TResponse> => {
|
|
69
|
+
const response = await httpClient.sendRequest<TResponse>({
|
|
70
|
+
method,
|
|
71
|
+
url: `${BUTTONDOWN_BASE_URL}${path}`,
|
|
72
|
+
headers: {
|
|
73
|
+
Authorization: `Token ${auth}`,
|
|
74
|
+
Accept: 'application/json',
|
|
75
|
+
'Content-Type': 'application/json',
|
|
76
|
+
...sanitizeHeaders(headers),
|
|
77
|
+
},
|
|
78
|
+
queryParams: serializeQueryParams(query),
|
|
79
|
+
body,
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
return response.body;
|
|
83
|
+
};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ButtondownSubscriberType,
|
|
3
|
+
ButtondownSubscriberSource,
|
|
4
|
+
ButtondownEmailStatus,
|
|
5
|
+
ButtondownEmailType,
|
|
6
|
+
} from './types';
|
|
7
|
+
|
|
8
|
+
export const subscriberTypeOptions: { label: string; value: ButtondownSubscriberType }[] = [
|
|
9
|
+
{ label: 'Regular', value: 'regular' },
|
|
10
|
+
{ label: 'Premium', value: 'premium' },
|
|
11
|
+
{ label: 'Unactivated', value: 'unactivated' },
|
|
12
|
+
{ label: 'Paused', value: 'paused' },
|
|
13
|
+
{ label: 'Trialed', value: 'trialed' },
|
|
14
|
+
{ label: 'Upcoming', value: 'upcoming' },
|
|
15
|
+
{ label: 'Churning', value: 'churning' },
|
|
16
|
+
{ label: 'Churned', value: 'churned' },
|
|
17
|
+
{ label: 'Unsubscribed', value: 'unsubscribed' },
|
|
18
|
+
{ label: 'Undeliverable', value: 'undeliverable' },
|
|
19
|
+
{ label: 'Blocked', value: 'blocked' },
|
|
20
|
+
{ label: 'Complained', value: 'complained' },
|
|
21
|
+
{ label: 'Gifted', value: 'gifted' },
|
|
22
|
+
{ label: 'Past Due', value: 'past_due' },
|
|
23
|
+
{ label: 'Removed', value: 'removed' },
|
|
24
|
+
{ label: 'Unpaid', value: 'unpaid' },
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
export const subscriberSourceOptions: { label: string; value: ButtondownSubscriberSource }[] = [
|
|
28
|
+
{ label: 'Admin', value: 'admin' },
|
|
29
|
+
{ label: 'API', value: 'api' },
|
|
30
|
+
{ label: 'Carrd', value: 'carrd' },
|
|
31
|
+
{ label: 'Comment', value: 'comment' },
|
|
32
|
+
{ label: 'Embedded form', value: 'embedded_form' },
|
|
33
|
+
{ label: 'Hosted form', value: 'form' },
|
|
34
|
+
{ label: 'Import', value: 'import' },
|
|
35
|
+
{ label: 'Memberful', value: 'memberful' },
|
|
36
|
+
{ label: 'Organic', value: 'organic' },
|
|
37
|
+
{ label: 'Patreon', value: 'patreon' },
|
|
38
|
+
{ label: 'Stripe', value: 'stripe' },
|
|
39
|
+
{ label: 'User portal', value: 'user' },
|
|
40
|
+
{ label: 'Zapier', value: 'zapier' },
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
export const subscriberOrderingOptions = [
|
|
44
|
+
{ label: 'Newest first', value: '-creation_date' },
|
|
45
|
+
{ label: 'Oldest first', value: 'creation_date' },
|
|
46
|
+
{ label: 'Email address (A-Z)', value: 'email_address' },
|
|
47
|
+
{ label: 'Email address (Z-A)', value: '-email_address' },
|
|
48
|
+
{ label: 'Last opened (recent first)', value: '-last_open_date' },
|
|
49
|
+
{ label: 'Last opened (oldest first)', value: 'last_open_date' },
|
|
50
|
+
];
|
|
51
|
+
|
|
52
|
+
export const emailStatusOptions: { label: string; value: ButtondownEmailStatus }[] = [
|
|
53
|
+
{ label: 'Send immediately (about_to_send)', value: 'about_to_send' },
|
|
54
|
+
{ label: 'Draft', value: 'draft' },
|
|
55
|
+
{ label: 'Scheduled', value: 'scheduled' },
|
|
56
|
+
];
|
|
57
|
+
|
|
58
|
+
export const emailTypeOptions: { label: string; value: ButtondownEmailType }[] = [
|
|
59
|
+
{ label: 'Public', value: 'public' },
|
|
60
|
+
{ label: 'Private', value: 'private' },
|
|
61
|
+
{ label: 'Premium', value: 'premium' },
|
|
62
|
+
{ label: 'Free', value: 'free' },
|
|
63
|
+
{ label: 'Churned', value: 'churned' },
|
|
64
|
+
{ label: 'Archival', value: 'archival' },
|
|
65
|
+
];
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
export type ButtondownSubscriberType =
|
|
2
|
+
| 'blocked'
|
|
3
|
+
| 'complained'
|
|
4
|
+
| 'churning'
|
|
5
|
+
| 'churned'
|
|
6
|
+
| 'gifted'
|
|
7
|
+
| 'unactivated'
|
|
8
|
+
| 'unpaid'
|
|
9
|
+
| 'undeliverable'
|
|
10
|
+
| 'premium'
|
|
11
|
+
| 'past_due'
|
|
12
|
+
| 'paused'
|
|
13
|
+
| 'regular'
|
|
14
|
+
| 'removed'
|
|
15
|
+
| 'trialed'
|
|
16
|
+
| 'unsubscribed'
|
|
17
|
+
| 'upcoming';
|
|
18
|
+
|
|
19
|
+
export type ButtondownSubscriberSource =
|
|
20
|
+
| 'admin'
|
|
21
|
+
| 'api'
|
|
22
|
+
| 'carrd'
|
|
23
|
+
| 'comment'
|
|
24
|
+
| 'embedded_form'
|
|
25
|
+
| 'form'
|
|
26
|
+
| 'import'
|
|
27
|
+
| 'memberful'
|
|
28
|
+
| 'organic'
|
|
29
|
+
| 'patreon'
|
|
30
|
+
| 'stripe'
|
|
31
|
+
| 'user'
|
|
32
|
+
| 'zapier';
|
|
33
|
+
|
|
34
|
+
export interface ButtondownSubscriber {
|
|
35
|
+
id: string;
|
|
36
|
+
creation_date: string;
|
|
37
|
+
email_address: string;
|
|
38
|
+
type: ButtondownSubscriberType;
|
|
39
|
+
tags: string[];
|
|
40
|
+
metadata: Record<string, unknown>;
|
|
41
|
+
notes?: string;
|
|
42
|
+
referrer_url?: string;
|
|
43
|
+
utm_campaign?: string;
|
|
44
|
+
utm_medium?: string;
|
|
45
|
+
utm_source?: string;
|
|
46
|
+
ip_address?: string;
|
|
47
|
+
source: ButtondownSubscriberSource;
|
|
48
|
+
last_open_date?: string | null;
|
|
49
|
+
last_click_date?: string | null;
|
|
50
|
+
click_rate?: number | null;
|
|
51
|
+
open_rate?: number | null;
|
|
52
|
+
churn_date?: string | null;
|
|
53
|
+
unsubscription_date?: string | null;
|
|
54
|
+
undeliverability_date?: string | null;
|
|
55
|
+
[key: string]: unknown;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface ButtondownSubscriberInput {
|
|
59
|
+
email_address: string;
|
|
60
|
+
notes?: string;
|
|
61
|
+
metadata?: Record<string, unknown>;
|
|
62
|
+
tags?: string[];
|
|
63
|
+
referrer_url?: string;
|
|
64
|
+
utm_campaign?: string;
|
|
65
|
+
utm_medium?: string;
|
|
66
|
+
utm_source?: string;
|
|
67
|
+
referring_subscriber_id?: string;
|
|
68
|
+
type?: ButtondownSubscriberType;
|
|
69
|
+
ip_address?: string;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export type ButtondownEmailType =
|
|
73
|
+
| 'public'
|
|
74
|
+
| 'private'
|
|
75
|
+
| 'premium'
|
|
76
|
+
| 'free'
|
|
77
|
+
| 'churned'
|
|
78
|
+
| 'archival';
|
|
79
|
+
|
|
80
|
+
export type ButtondownEmailStatus =
|
|
81
|
+
| 'draft'
|
|
82
|
+
| 'managed_by_rss'
|
|
83
|
+
| 'about_to_send'
|
|
84
|
+
| 'scheduled'
|
|
85
|
+
| 'in_flight'
|
|
86
|
+
| 'paused'
|
|
87
|
+
| 'deleted'
|
|
88
|
+
| 'errored'
|
|
89
|
+
| 'sent'
|
|
90
|
+
| 'imported'
|
|
91
|
+
| 'throttled'
|
|
92
|
+
| 'resending'
|
|
93
|
+
| 'transactional'
|
|
94
|
+
| 'suppressed';
|
|
95
|
+
|
|
96
|
+
export interface ButtondownEmail {
|
|
97
|
+
id: string;
|
|
98
|
+
creation_date: string;
|
|
99
|
+
modification_date: string;
|
|
100
|
+
subject: string;
|
|
101
|
+
body: string;
|
|
102
|
+
status: ButtondownEmailStatus;
|
|
103
|
+
email_type: ButtondownEmailType;
|
|
104
|
+
publish_date?: string | null;
|
|
105
|
+
description?: string;
|
|
106
|
+
canonical_url?: string;
|
|
107
|
+
image?: string;
|
|
108
|
+
metadata?: Record<string, unknown>;
|
|
109
|
+
attachments?: string[];
|
|
110
|
+
[key: string]: unknown;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export interface ButtondownEmailInput {
|
|
114
|
+
subject: string;
|
|
115
|
+
body?: string;
|
|
116
|
+
status?: ButtondownEmailStatus;
|
|
117
|
+
email_type?: ButtondownEmailType;
|
|
118
|
+
publish_date?: string;
|
|
119
|
+
description?: string;
|
|
120
|
+
canonical_url?: string;
|
|
121
|
+
image?: string;
|
|
122
|
+
metadata?: Record<string, unknown>;
|
|
123
|
+
slug?: string;
|
|
124
|
+
attachments?: string[];
|
|
125
|
+
should_trigger_pay_per_email_billing?: boolean;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export type ButtondownWebhookEvent =
|
|
129
|
+
| 'subscriber.created'
|
|
130
|
+
| 'subscriber.confirmed'
|
|
131
|
+
| 'email.sent';
|
|
132
|
+
|
|
133
|
+
export interface ButtondownWebhook {
|
|
134
|
+
id: string;
|
|
135
|
+
creation_date: string;
|
|
136
|
+
url: string;
|
|
137
|
+
event_types: ButtondownWebhookEvent[];
|
|
138
|
+
status?: 'enabled' | 'disabled';
|
|
139
|
+
description?: string;
|
|
140
|
+
signing_key?: string;
|
|
141
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { HttpMethod } from '@agnocon/pieces-common';
|
|
2
|
+
import { createTrigger, Property, TriggerStrategy } from '@agnocon/pieces-framework';
|
|
3
|
+
import { buttondownAuth } from './auth';
|
|
4
|
+
import { buttondownRequest } from './client';
|
|
5
|
+
import { ButtondownWebhook, ButtondownWebhookEvent } from './types';
|
|
6
|
+
|
|
7
|
+
export interface ButtondownWebhookPayload {
|
|
8
|
+
event_type?: string;
|
|
9
|
+
data?: Record<string, unknown>;
|
|
10
|
+
[key: string]: unknown;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface CreateButtondownWebhookTriggerParams {
|
|
14
|
+
name: string;
|
|
15
|
+
displayName: string;
|
|
16
|
+
description: string;
|
|
17
|
+
aiMetadata: {
|
|
18
|
+
description: string;
|
|
19
|
+
};
|
|
20
|
+
eventType: ButtondownWebhookEvent;
|
|
21
|
+
sampleData: unknown;
|
|
22
|
+
enrich?: (params: {
|
|
23
|
+
apiKey: string;
|
|
24
|
+
payload: ButtondownWebhookPayload;
|
|
25
|
+
}) => Promise<Record<string, unknown>>;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const createButtondownWebhookTrigger = ({
|
|
29
|
+
name,
|
|
30
|
+
displayName,
|
|
31
|
+
description,
|
|
32
|
+
aiMetadata,
|
|
33
|
+
eventType,
|
|
34
|
+
sampleData,
|
|
35
|
+
enrich,
|
|
36
|
+
}: CreateButtondownWebhookTriggerParams) =>
|
|
37
|
+
createTrigger({
|
|
38
|
+
auth: buttondownAuth,
|
|
39
|
+
name,
|
|
40
|
+
displayName,
|
|
41
|
+
description,
|
|
42
|
+
aiMetadata,
|
|
43
|
+
type: TriggerStrategy.WEBHOOK,
|
|
44
|
+
props: {
|
|
45
|
+
webhookDescription: Property.ShortText({
|
|
46
|
+
displayName: 'Webhook Description',
|
|
47
|
+
description: 'Optional description stored with the webhook in Buttondown.',
|
|
48
|
+
required: false,
|
|
49
|
+
}),
|
|
50
|
+
signingKey: Property.ShortText({
|
|
51
|
+
displayName: 'Webhook Signing Key',
|
|
52
|
+
description: 'Optional HMAC signing key to validate webhook requests.',
|
|
53
|
+
required: false,
|
|
54
|
+
}),
|
|
55
|
+
},
|
|
56
|
+
sampleData,
|
|
57
|
+
async onEnable(context) {
|
|
58
|
+
const webhook = await buttondownRequest<ButtondownWebhook>({
|
|
59
|
+
auth: context.auth.secret_text,
|
|
60
|
+
method: HttpMethod.POST,
|
|
61
|
+
path: '/webhooks',
|
|
62
|
+
body: {
|
|
63
|
+
url: context.webhookUrl,
|
|
64
|
+
event_types: [eventType],
|
|
65
|
+
description: context.propsValue.webhookDescription,
|
|
66
|
+
signing_key: context.propsValue.signingKey,
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
await context.store.put('webhookId', webhook.id);
|
|
71
|
+
},
|
|
72
|
+
async onDisable(context) {
|
|
73
|
+
const webhookId = await context.store.get<string>('webhookId');
|
|
74
|
+
if (!webhookId) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
await buttondownRequest<void>({
|
|
79
|
+
auth: context.auth.secret_text,
|
|
80
|
+
method: HttpMethod.DELETE,
|
|
81
|
+
path: `/webhooks/${webhookId}`,
|
|
82
|
+
});
|
|
83
|
+
},
|
|
84
|
+
async run(context) {
|
|
85
|
+
const payload = context.payload.body as ButtondownWebhookPayload;
|
|
86
|
+
if (payload?.event_type !== eventType) {
|
|
87
|
+
return [];
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
let enriched: Record<string, unknown> | undefined;
|
|
91
|
+
if (enrich) {
|
|
92
|
+
enriched = await enrich({
|
|
93
|
+
apiKey: context.auth.secret_text,
|
|
94
|
+
payload,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return [
|
|
99
|
+
{
|
|
100
|
+
...payload,
|
|
101
|
+
...(enriched ?? {}),
|
|
102
|
+
},
|
|
103
|
+
];
|
|
104
|
+
},
|
|
105
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { HttpMethod } from '@agnocon/pieces-common';
|
|
2
|
+
import { buttondownRequest } from '../common/client';
|
|
3
|
+
import { createButtondownWebhookTrigger } from '../common/webhook';
|
|
4
|
+
import { ButtondownEmail } from '../common/types';
|
|
5
|
+
|
|
6
|
+
export const buttondownEmailSent = createButtondownWebhookTrigger({
|
|
7
|
+
name: 'buttondown_email_sent',
|
|
8
|
+
displayName: 'Email Sent',
|
|
9
|
+
description: 'Triggers when an email is sent from Buttondown.',
|
|
10
|
+
aiMetadata: {
|
|
11
|
+
description:
|
|
12
|
+
'Fires when an email is dispatched to subscribers from Buttondown. Represents a sent newsletter/email; the payload is enriched with the full email details.',
|
|
13
|
+
},
|
|
14
|
+
eventType: 'email.sent',
|
|
15
|
+
sampleData: {
|
|
16
|
+
event_type: 'email.sent',
|
|
17
|
+
data: {
|
|
18
|
+
email: 'eml_123456789',
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
enrich: async ({ apiKey, payload }) => {
|
|
22
|
+
const emailData = payload.data?.['email'];
|
|
23
|
+
let email: ButtondownEmail | undefined;
|
|
24
|
+
|
|
25
|
+
if (typeof emailData === 'string') {
|
|
26
|
+
email = await buttondownRequest<ButtondownEmail>({
|
|
27
|
+
auth: apiKey,
|
|
28
|
+
method: HttpMethod.GET,
|
|
29
|
+
path: `/emails/${encodeURIComponent(emailData)}`,
|
|
30
|
+
});
|
|
31
|
+
} else if (emailData && typeof emailData === 'object') {
|
|
32
|
+
email = emailData as ButtondownEmail;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
email,
|
|
37
|
+
};
|
|
38
|
+
},
|
|
39
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { HttpMethod } from '@agnocon/pieces-common';
|
|
2
|
+
import { buttondownRequest } from '../common/client';
|
|
3
|
+
import { createButtondownWebhookTrigger } from '../common/webhook';
|
|
4
|
+
import { ButtondownSubscriber } from '../common/types';
|
|
5
|
+
|
|
6
|
+
export const buttondownNewSubscriber = createButtondownWebhookTrigger({
|
|
7
|
+
name: 'buttondown_new_subscriber',
|
|
8
|
+
displayName: 'New Subscriber',
|
|
9
|
+
description: 'Triggers when a new subscriber is created.',
|
|
10
|
+
aiMetadata: {
|
|
11
|
+
description:
|
|
12
|
+
'Fires when a subscriber is added to the Buttondown newsletter, regardless of confirmation status. Represents a newly created subscriber record; the payload is enriched with the full subscriber details.',
|
|
13
|
+
},
|
|
14
|
+
eventType: 'subscriber.created',
|
|
15
|
+
sampleData: {
|
|
16
|
+
event_type: 'subscriber.created',
|
|
17
|
+
data: {
|
|
18
|
+
subscriber: 'sub_123456789',
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
enrich: async ({ apiKey, payload }) => {
|
|
22
|
+
const subscriberData = payload.data?.['subscriber'];
|
|
23
|
+
let subscriber: ButtondownSubscriber | undefined;
|
|
24
|
+
|
|
25
|
+
if (typeof subscriberData === 'string') {
|
|
26
|
+
subscriber = await buttondownRequest<ButtondownSubscriber>({
|
|
27
|
+
auth: apiKey,
|
|
28
|
+
method: HttpMethod.GET,
|
|
29
|
+
path: `/subscribers/${encodeURIComponent(subscriberData)}`,
|
|
30
|
+
});
|
|
31
|
+
} else if (subscriberData && typeof subscriberData === 'object') {
|
|
32
|
+
subscriber = subscriberData as ButtondownSubscriber;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
subscriber,
|
|
37
|
+
};
|
|
38
|
+
},
|
|
39
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { HttpMethod } from '@agnocon/pieces-common';
|
|
2
|
+
import { buttondownRequest } from '../common/client';
|
|
3
|
+
import { createButtondownWebhookTrigger } from '../common/webhook';
|
|
4
|
+
import { ButtondownSubscriber } from '../common/types';
|
|
5
|
+
|
|
6
|
+
export const buttondownSubscriberConfirmed = createButtondownWebhookTrigger({
|
|
7
|
+
name: 'buttondown_subscriber_confirmed',
|
|
8
|
+
displayName: 'Subscriber Confirmed',
|
|
9
|
+
description: 'Triggers when a subscriber confirms their email.',
|
|
10
|
+
aiMetadata: {
|
|
11
|
+
description:
|
|
12
|
+
'Fires when a subscriber completes double opt-in and confirms their email address in Buttondown. Represents a subscriber transitioning to confirmed status; the payload is enriched with the full subscriber details.',
|
|
13
|
+
},
|
|
14
|
+
eventType: 'subscriber.confirmed',
|
|
15
|
+
sampleData: {
|
|
16
|
+
event_type: 'subscriber.confirmed',
|
|
17
|
+
data: {
|
|
18
|
+
subscriber: 'sub_123456789',
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
enrich: async ({ apiKey, payload }) => {
|
|
22
|
+
const subscriberData = payload.data?.['subscriber'];
|
|
23
|
+
let subscriber: ButtondownSubscriber | undefined;
|
|
24
|
+
|
|
25
|
+
if (typeof subscriberData === 'string') {
|
|
26
|
+
subscriber = await buttondownRequest<ButtondownSubscriber>({
|
|
27
|
+
auth: apiKey,
|
|
28
|
+
method: HttpMethod.GET,
|
|
29
|
+
path: `/subscribers/${encodeURIComponent(subscriberData)}`,
|
|
30
|
+
});
|
|
31
|
+
} else if (subscriberData && typeof subscriberData === 'object') {
|
|
32
|
+
subscriber = subscriberData as ButtondownSubscriber;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
subscriber,
|
|
37
|
+
};
|
|
38
|
+
},
|
|
39
|
+
});
|