@guayaba/workflow-piece-gmail 0.12.3

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.
@@ -0,0 +1,192 @@
1
+ import {
2
+ createTrigger,
3
+ TriggerStrategy,
4
+ FilesService,
5
+ } from '@guayaba/workflows-framework';
6
+ import { GmailProps } from '../common/props';
7
+ import { gmailAuth, createGoogleClient } from '../auth';
8
+ import { google } from 'googleapis';
9
+ import { parseStream, convertAttachment } from '../common/data';
10
+
11
+ async function enrichGmailMessage({
12
+ gmail,
13
+ messageId,
14
+ files,
15
+ labelInfo,
16
+ }: {
17
+ gmail: any;
18
+ messageId: string;
19
+ files: FilesService;
20
+ labelInfo: {
21
+ labelId: string;
22
+ labelName: string;
23
+ };
24
+ }) {
25
+ const rawMailResponse = await gmail.users.messages.get({
26
+ userId: 'me',
27
+ id: messageId,
28
+ format: 'raw',
29
+ });
30
+
31
+ const threadResponse = await gmail.users.threads.get({
32
+ userId: 'me',
33
+ id: rawMailResponse.data.threadId!,
34
+ });
35
+
36
+ const parsedMailResponse = await parseStream(
37
+ Buffer.from(rawMailResponse.data.raw as string, 'base64').toString('utf-8')
38
+ );
39
+
40
+ return {
41
+ message: {
42
+ ...parsedMailResponse,
43
+ attachments: await convertAttachment(
44
+ parsedMailResponse.attachments,
45
+ files
46
+ ),
47
+ },
48
+ thread: threadResponse.data,
49
+ labelInfo: {
50
+ ...labelInfo,
51
+ addedAt: Date.now(),
52
+ },
53
+ };
54
+ }
55
+
56
+ export const gmailNewLabeledEmailTrigger = createTrigger({
57
+ auth: gmailAuth,
58
+ name: 'new_labeled_email',
59
+ displayName: 'New Labeled Email',
60
+ description: 'Triggers when a label is added to an email',
61
+ props: {
62
+ label: {
63
+ ...GmailProps.label,
64
+ required: true,
65
+ },
66
+ },
67
+ sampleData: {},
68
+ type: TriggerStrategy.POLLING,
69
+ onEnable: async (context) => {
70
+ const authClient = await createGoogleClient(context.auth);
71
+ const gmail = google.gmail({ version: 'v1', auth: authClient });
72
+
73
+ const profile = await gmail.users.getProfile({
74
+ userId: 'me',
75
+ });
76
+
77
+ await context.store.put('lastHistoryId', profile.data.historyId);
78
+ },
79
+ onDisable: async (context) => {
80
+ await context.store.delete('lastHistoryId');
81
+ },
82
+ run: async (context) => {
83
+ const authClient = await createGoogleClient(context.auth);
84
+ const gmail = google.gmail({ version: 'v1', auth: authClient });
85
+
86
+ const lastHistoryId = await context.store.get('lastHistoryId');
87
+
88
+ const historyResponse = await gmail.users.history.list({
89
+ userId: 'me',
90
+ startHistoryId: lastHistoryId as string,
91
+ labelId: context.propsValue.label.id,
92
+ historyTypes: ['labelAdded', 'messageAdded'],
93
+ });
94
+
95
+ const labeledMessages = new Map<string, string>();
96
+ const results = [];
97
+
98
+ if (historyResponse.data.history) {
99
+ for (const history of historyResponse.data.history) {
100
+ if (history.labelsAdded) {
101
+ for (const labelAdded of history.labelsAdded) {
102
+ if (
103
+ labelAdded.labelIds?.includes(context.propsValue.label.id) &&
104
+ labelAdded.message?.id
105
+ ) {
106
+ labeledMessages.set(
107
+ labelAdded.message.id,
108
+ history.id?.toString() || ''
109
+ );
110
+ }
111
+ }
112
+ } else if (history.messagesAdded) {
113
+ for (const messageAdded of history.messagesAdded) {
114
+ if (
115
+ messageAdded.message?.id &&
116
+ messageAdded.message.labelIds?.includes(
117
+ context.propsValue.label.id
118
+ )
119
+ ) {
120
+ labeledMessages.set(
121
+ messageAdded.message.id,
122
+ history.id?.toString() || ''
123
+ );
124
+ }
125
+ }
126
+ }
127
+ }
128
+ }
129
+
130
+ for (const [messageId, historyId] of labeledMessages) {
131
+ const enrichedMessage = await enrichGmailMessage({
132
+ gmail,
133
+ messageId,
134
+ files: context.files,
135
+ labelInfo: {
136
+ labelId: context.propsValue.label.id,
137
+ labelName: context.propsValue.label.name,
138
+ },
139
+ });
140
+
141
+ if (lastHistoryId !== historyId) {
142
+ results.push({
143
+ id: historyId,
144
+ data: enrichedMessage,
145
+ });
146
+ }
147
+ }
148
+
149
+ if (historyResponse.data.historyId) {
150
+ await context.store.put('lastHistoryId', historyResponse.data.historyId);
151
+ }
152
+
153
+ return results;
154
+ },
155
+ test: async (context) => {
156
+ const authClient = await createGoogleClient(context.auth);
157
+ const gmail = google.gmail({ version: 'v1', auth: authClient });
158
+
159
+ const messagesResponse = await gmail.users.messages.list({
160
+ userId: 'me',
161
+ labelIds: [context.propsValue.label.id],
162
+ maxResults: 5,
163
+ });
164
+
165
+ const results = [];
166
+
167
+ if (messagesResponse.data.messages) {
168
+ for (const message of messagesResponse.data.messages) {
169
+ const messageId = message.id;
170
+ if (!messageId) {
171
+ continue;
172
+ }
173
+ const enrichedMessage = await enrichGmailMessage({
174
+ gmail,
175
+ messageId: messageId,
176
+ files: context.files,
177
+ labelInfo: {
178
+ labelId: context.propsValue.label.id,
179
+ labelName: context.propsValue.label.name,
180
+ },
181
+ });
182
+
183
+ results.push({
184
+ id: messageId,
185
+ data: enrichedMessage,
186
+ });
187
+ }
188
+ }
189
+
190
+ return results;
191
+ },
192
+ });
package/tsconfig.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "extends": "../../../../tsconfig.base.json",
3
+ "files": [],
4
+ "include": [],
5
+ "references": [
6
+ {
7
+ "path": "./tsconfig.lib.json"
8
+ }
9
+ ],
10
+ "compilerOptions": {
11
+ "forceConsistentCasingInFileNames": true,
12
+ "strict": true,
13
+ "noImplicitReturns": true,
14
+ "noFallthroughCasesInSwitch": true
15
+ }
16
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "module": "commonjs",
5
+ "rootDir": ".",
6
+ "baseUrl": ".",
7
+ "paths": {},
8
+ "outDir": "./dist",
9
+ "declaration": true,
10
+ "declarationMap": true,
11
+ "types": ["node"]
12
+ },
13
+ "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"],
14
+ "include": ["src/**/*.ts"]
15
+ }