@pipedream/google_drive 4.0.0 → 5.0.0
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/actions/add-comment/add-comment.mjs +1 -1
- package/actions/add-file-sharing-preference/add-file-sharing-preference.mjs +1 -1
- package/actions/copy-file/copy-file.mjs +1 -1
- package/actions/create-file-from-template/create-file-from-template.mjs +1 -1
- package/actions/create-file-from-text/create-file-from-text.mjs +1 -1
- package/actions/create-folder/create-folder.mjs +1 -1
- package/actions/create-shared-drive/create-shared-drive.mjs +1 -1
- package/actions/create-text-file/create-text-file.mjs +1 -1
- package/actions/delete-comment/delete-comment.mjs +1 -1
- package/actions/delete-file/delete-file.mjs +1 -1
- package/actions/delete-reply/delete-reply.mjs +1 -1
- package/actions/delete-shared-drive/delete-shared-drive.mjs +1 -1
- package/actions/download-file/download-file.mjs +26 -7
- package/actions/find-file/find-file.mjs +1 -1
- package/actions/find-folder/find-folder.mjs +1 -1
- package/actions/find-forms/find-forms.mjs +1 -1
- package/actions/find-spreadsheets/find-spreadsheets.mjs +1 -1
- package/actions/get-comment/get-comment.mjs +1 -1
- package/actions/get-current-user/get-current-user.mjs +1 -1
- package/actions/get-file/get-file.mjs +1 -1
- package/actions/get-file-by-id/get-file-by-id.mjs +1 -1
- package/actions/get-folder-id-for-path/get-folder-id-for-path.mjs +1 -1
- package/actions/get-reply/get-reply.mjs +1 -1
- package/actions/get-shared-drive/get-shared-drive.mjs +1 -1
- package/actions/get-user-details/get-user-details.mjs +1 -1
- package/actions/is-folder-ancestor/is-folder-ancestor.mjs +1 -1
- package/actions/list-access-proposals/list-access-proposals.mjs +1 -1
- package/actions/list-comments/list-comments.mjs +1 -1
- package/actions/list-files/list-files.mjs +1 -1
- package/actions/list-mime-type-options/list-mime-type-options.mjs +1 -1
- package/actions/list-permissions/list-permissions.mjs +1 -1
- package/actions/list-replies/list-replies.mjs +1 -1
- package/actions/list-shared-drives/list-shared-drives.mjs +1 -1
- package/actions/list-theme-id-options/list-theme-id-options.mjs +1 -1
- package/actions/move-file/move-file.mjs +1 -1
- package/actions/move-file-to-trash/move-file-to-trash.mjs +1 -1
- package/actions/remove-file-sharing-permission/remove-file-sharing-permission.mjs +1 -1
- package/actions/remove-sharing/remove-sharing.mjs +1 -1
- package/actions/reply-to-comment/reply-to-comment.mjs +1 -1
- package/actions/resolve-access-proposal/resolve-access-proposal.mjs +1 -1
- package/actions/resolve-comment/resolve-comment.mjs +1 -1
- package/actions/search-files/search-files.mjs +1 -1
- package/actions/search-shared-drives/search-shared-drives.mjs +1 -1
- package/actions/share-file/share-file.mjs +1 -1
- package/actions/trash-file/trash-file.mjs +1 -1
- package/actions/update-comment/update-comment.mjs +1 -1
- package/actions/update-file/update-file.mjs +1 -1
- package/actions/update-reply/update-reply.mjs +1 -1
- package/actions/update-shared-drive/update-shared-drive.mjs +1 -1
- package/actions/upload-file/upload-file.mjs +1 -1
- package/common/constants.mjs +22 -12
- package/common/utils.mjs +32 -0
- package/google_drive.app.mjs +90 -11
- package/package.json +1 -1
- package/sources/changes-to-files-in-drive/changes-to-files-in-drive.mjs +9 -6
- package/sources/changes-to-specific-files/changes-to-specific-files.mjs +1 -1
- package/sources/changes-to-specific-files-shared-drive/changes-to-specific-files-shared-drive.mjs +9 -6
- package/sources/common-dedupe-changes.mjs +22 -11
- package/sources/common-webhook.mjs +104 -40
- package/sources/new-access-proposal/new-access-proposal.mjs +1 -1
- package/sources/new-files-instant/new-files-instant.mjs +4 -1
- package/sources/new-files-instant-polling/new-files-instant-polling.mjs +38 -47
- package/sources/new-files-shared-drive/new-files-shared-drive.mjs +2 -16
- package/sources/new-or-modified-comments/new-or-modified-comments.mjs +10 -7
- package/sources/new-or-modified-comments-polling/new-or-modified-comments-polling.mjs +1 -1
- package/sources/new-or-modified-files/new-or-modified-files.mjs +20 -1
- package/sources/new-or-modified-files-polling/new-or-modified-files-polling.mjs +37 -36
- package/sources/new-or-modified-folders/new-or-modified-folders.mjs +52 -50
- package/sources/new-or-modified-folders-polling/new-or-modified-folders-polling.mjs +55 -63
- package/sources/new-shared-drive/new-shared-drive.mjs +1 -1
- package/sources/new-spreadsheet/new-spreadsheet.mjs +1 -1
- package/sources/new-spreadsheet-polling/new-spreadsheet-polling.mjs +38 -47
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import { DEFAULT_POLLING_SOURCE_TIMER_INTERVAL } from "@pipedream/platform";
|
|
2
2
|
import googleDrive from "../../google_drive.app.mjs";
|
|
3
3
|
import { getListFilesOpts } from "../../common/utils.mjs";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
CHANGE_FILTER_FILE_FIELDS,
|
|
6
|
+
GOOGLE_DRIVE_FOLDER_MIME_TYPE,
|
|
7
|
+
} from "../../common/constants.mjs";
|
|
5
8
|
import sampleEmit from "./test-event.mjs";
|
|
6
9
|
|
|
7
10
|
export default {
|
|
8
11
|
key: "google_drive-new-files-instant-polling",
|
|
9
12
|
name: "New Files (Polling)",
|
|
10
13
|
description: "Emit new event when a new file is added in your linked Google Drive",
|
|
11
|
-
version: "0.0
|
|
14
|
+
version: "0.1.0",
|
|
12
15
|
type: "source",
|
|
13
16
|
dedupe: "unique",
|
|
14
17
|
props: {
|
|
@@ -51,6 +54,12 @@ export default {
|
|
|
51
54
|
"changesPageSize",
|
|
52
55
|
],
|
|
53
56
|
},
|
|
57
|
+
maxEmitsPerRun: {
|
|
58
|
+
propDefinition: [
|
|
59
|
+
googleDrive,
|
|
60
|
+
"maxEmitsPerRun",
|
|
61
|
+
],
|
|
62
|
+
},
|
|
54
63
|
},
|
|
55
64
|
hooks: {
|
|
56
65
|
async deploy() {
|
|
@@ -143,54 +152,36 @@ export default {
|
|
|
143
152
|
const currentRunTimestamp = Date.now();
|
|
144
153
|
const lastRunTimestamp = this._getLastRunTimestamp();
|
|
145
154
|
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
155
|
+
const caughtUp = await this.googleDrive.processChangesPages({
|
|
156
|
+
pageToken: this._getPageToken(),
|
|
157
|
+
driveId: this.getDriveId(),
|
|
158
|
+
pageSize: this.changesPageSize,
|
|
159
|
+
fileFields: CHANGE_FILTER_FILE_FIELDS,
|
|
160
|
+
maxEmits: this.maxEmitsPerRun,
|
|
161
|
+
changeFilter: ({ file }) => Date.parse(file.createdTime) > lastRunTimestamp
|
|
162
|
+
&& this.shouldProcess(file),
|
|
163
|
+
processPage: async (changedFiles) => {
|
|
164
|
+
console.log(changedFiles.length
|
|
165
|
+
? `Processing ${changedFiles.length} new files`
|
|
166
|
+
: "No new files since last run");
|
|
167
|
+
|
|
168
|
+
let emitted = 0;
|
|
169
|
+
for (const file of changedFiles) {
|
|
170
|
+
const fullFile = await this.googleDrive.getFile(file.id, {
|
|
171
|
+
fields: "*",
|
|
172
|
+
});
|
|
173
|
+
await this.emitFile(fullFile);
|
|
174
|
+
emitted++;
|
|
166
175
|
}
|
|
176
|
+
return emitted;
|
|
177
|
+
},
|
|
178
|
+
savePageToken: (nextPageToken) => this._setPageToken(nextPageToken),
|
|
179
|
+
});
|
|
167
180
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
// Check if it's a new file (created after last run)
|
|
174
|
-
const fileCreatedTime = Date.parse(fullFile.createdTime);
|
|
175
|
-
if (fileCreatedTime <= lastRunTimestamp) {
|
|
176
|
-
console.log(`Skipping existing file ${fullFile.name || fullFile.id}`);
|
|
177
|
-
continue;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
if (!this.shouldProcess(fullFile)) {
|
|
181
|
-
console.log(`Skipping file ${fullFile.name || fullFile.id}`);
|
|
182
|
-
continue;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
await this.emitFile(fullFile);
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
// Save the next page token after successfully processing
|
|
189
|
-
this._setPageToken(nextPageToken);
|
|
181
|
+
// Hold until caught up so backlog files aren't skipped
|
|
182
|
+
if (caughtUp) {
|
|
183
|
+
this._setLastRunTimestamp(currentRunTimestamp);
|
|
190
184
|
}
|
|
191
|
-
|
|
192
|
-
// Update the last run timestamp after processing all changes
|
|
193
|
-
this._setLastRunTimestamp(currentRunTimestamp);
|
|
194
185
|
},
|
|
195
186
|
sampleEmit,
|
|
196
187
|
};
|
|
@@ -7,7 +7,7 @@ export default {
|
|
|
7
7
|
key: "google_drive-new-files-shared-drive",
|
|
8
8
|
name: "New Files (Shared Drive)",
|
|
9
9
|
description: "Emit new event when a new file is added in your shared Google Drive",
|
|
10
|
-
version: "0.1.
|
|
10
|
+
version: "0.1.18",
|
|
11
11
|
type: "source",
|
|
12
12
|
dedupe: "unique",
|
|
13
13
|
props: {
|
|
@@ -69,21 +69,7 @@ export default {
|
|
|
69
69
|
},
|
|
70
70
|
methods: sourceComponent.methods,
|
|
71
71
|
async run() {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
const driveId = this.getDriveId();
|
|
75
|
-
const changedFilesStream =
|
|
76
|
-
this.googleDrive.listChanges(pageToken, driveId, this.changesPageSize);
|
|
77
|
-
for await (const changedFilesPage of changedFilesStream) {
|
|
78
|
-
const { nextPageToken } = changedFilesPage;
|
|
79
|
-
|
|
80
|
-
// Process all the changed files retrieved from the current page
|
|
81
|
-
await this.processChanges();
|
|
82
|
-
|
|
83
|
-
// After successfully processing the changed files, we store the page
|
|
84
|
-
// token of the next page
|
|
85
|
-
this._setPageToken(nextPageToken);
|
|
86
|
-
}
|
|
72
|
+
await this.processChanges();
|
|
87
73
|
},
|
|
88
74
|
sampleEmit,
|
|
89
75
|
};
|
|
@@ -18,10 +18,8 @@ export default {
|
|
|
18
18
|
name: "New or Modified Comments (Instant)",
|
|
19
19
|
description:
|
|
20
20
|
"Emit new event when a comment is created or modified in the selected file",
|
|
21
|
-
version: "1.0
|
|
21
|
+
version: "1.1.0",
|
|
22
22
|
type: "source",
|
|
23
|
-
// Dedupe events based on the "x-goog-message-number" header for the target channel:
|
|
24
|
-
// https://developers.google.com/drive/api/v3/push#making-watch-requests
|
|
25
23
|
dedupe: "unique",
|
|
26
24
|
props: {
|
|
27
25
|
...common.props,
|
|
@@ -72,17 +70,19 @@ export default {
|
|
|
72
70
|
GOOGLE_DRIVE_NOTIFICATION_CHANGE,
|
|
73
71
|
];
|
|
74
72
|
},
|
|
75
|
-
|
|
73
|
+
isRelevantChange({ file }) {
|
|
74
|
+
return file.id === this.fileId;
|
|
75
|
+
},
|
|
76
|
+
generateMeta(data) {
|
|
76
77
|
const {
|
|
77
78
|
id: commentId,
|
|
78
79
|
content: summary,
|
|
79
80
|
modifiedTime: tsString,
|
|
80
81
|
} = data;
|
|
81
82
|
const ts = Date.parse(tsString);
|
|
82
|
-
const eventId = headers && headers["x-goog-message-number"];
|
|
83
83
|
|
|
84
84
|
return {
|
|
85
|
-
id: md5(`${commentId}-${
|
|
85
|
+
id: md5(`${commentId}-${ts}`),
|
|
86
86
|
summary,
|
|
87
87
|
ts,
|
|
88
88
|
};
|
|
@@ -109,6 +109,7 @@ export default {
|
|
|
109
109
|
changedFiles = changedFiles.filter(({ id }) => id === this.fileId);
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
+
let emitted = 0;
|
|
112
113
|
for (const file of changedFiles) {
|
|
113
114
|
const lastCommentTimeForFile = this._getLastCommentTimeForFile(file.id);
|
|
114
115
|
let maxModifiedTime = lastCommentTimeForFile;
|
|
@@ -127,13 +128,15 @@ export default {
|
|
|
127
128
|
comment,
|
|
128
129
|
...changes,
|
|
129
130
|
};
|
|
130
|
-
const meta = this.generateMeta(comment
|
|
131
|
+
const meta = this.generateMeta(comment);
|
|
131
132
|
this.$emit(eventToEmit, meta);
|
|
133
|
+
emitted++;
|
|
132
134
|
|
|
133
135
|
maxModifiedTime = Math.max(maxModifiedTime, commentTime);
|
|
134
136
|
this._updateLastCommentTimeForFile(file.id, maxModifiedTime);
|
|
135
137
|
}
|
|
136
138
|
}
|
|
139
|
+
return emitted;
|
|
137
140
|
},
|
|
138
141
|
},
|
|
139
142
|
};
|
|
@@ -7,7 +7,7 @@ export default {
|
|
|
7
7
|
key: "google_drive-new-or-modified-comments-polling",
|
|
8
8
|
name: "New or Modified Comments (Polling)",
|
|
9
9
|
description: "Emit new event when a comment is created or modified in the selected file",
|
|
10
|
-
version: "0.0.
|
|
10
|
+
version: "0.0.16",
|
|
11
11
|
type: "source",
|
|
12
12
|
dedupe: "unique",
|
|
13
13
|
props: {
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
GOOGLE_DRIVE_NOTIFICATION_ADD,
|
|
15
15
|
GOOGLE_DRIVE_NOTIFICATION_CHANGE,
|
|
16
16
|
GOOGLE_DRIVE_NOTIFICATION_UPDATE,
|
|
17
|
+
MASS_CHANGE_MAX_AGE_MILLISECONDS,
|
|
17
18
|
PDF_EXPORTABLE_MIME_TYPES,
|
|
18
19
|
} from "../../common/constants.mjs";
|
|
19
20
|
import commonDedupeChanges from "../common-dedupe-changes.mjs";
|
|
@@ -28,7 +29,7 @@ export default {
|
|
|
28
29
|
key: "google_drive-new-or-modified-files",
|
|
29
30
|
name: "New or Modified Files (Instant)",
|
|
30
31
|
description: "Emit new event when a file in the selected Drive is created, modified or trashed.",
|
|
31
|
-
version: "
|
|
32
|
+
version: "2.0.0",
|
|
32
33
|
type: "source",
|
|
33
34
|
dedupe: "unique",
|
|
34
35
|
props: {
|
|
@@ -92,6 +93,7 @@ export default {
|
|
|
92
93
|
const { files } = await this.googleDrive.listFilesInPage(null, args);
|
|
93
94
|
|
|
94
95
|
await this.processChanges(files);
|
|
96
|
+
this.flushFileIntervals();
|
|
95
97
|
},
|
|
96
98
|
...common.hooks,
|
|
97
99
|
},
|
|
@@ -116,6 +118,22 @@ export default {
|
|
|
116
118
|
getChangesFileFields() {
|
|
117
119
|
return CHANGED_FILE_FIELDS;
|
|
118
120
|
},
|
|
121
|
+
// Skip bulk moves/sharing of old files; createdTime keeps uploads with an old modifiedTime
|
|
122
|
+
isRelevantChange({
|
|
123
|
+
time, file,
|
|
124
|
+
}) {
|
|
125
|
+
if (!this.shouldProcess(file)) {
|
|
126
|
+
return false;
|
|
127
|
+
}
|
|
128
|
+
if (this.watchForPropertiesChanges || file.trashed || !time) {
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
const changedAt = Date.parse(time);
|
|
132
|
+
return [
|
|
133
|
+
file.modifiedTime,
|
|
134
|
+
file.createdTime,
|
|
135
|
+
].some((t) => !t || changedAt - Date.parse(t) <= MASS_CHANGE_MAX_AGE_MILLISECONDS);
|
|
136
|
+
},
|
|
119
137
|
generateMeta({
|
|
120
138
|
id, name, modifiedTime, trashed,
|
|
121
139
|
}) {
|
|
@@ -187,6 +205,7 @@ export default {
|
|
|
187
205
|
} finally {
|
|
188
206
|
this.recordFileEmits(emittedFileIds);
|
|
189
207
|
}
|
|
208
|
+
return emittedFileIds.length;
|
|
190
209
|
},
|
|
191
210
|
},
|
|
192
211
|
sampleEmit,
|
|
@@ -2,14 +2,17 @@ import { DEFAULT_POLLING_SOURCE_TIMER_INTERVAL } from "@pipedream/platform";
|
|
|
2
2
|
import googleDrive from "../../google_drive.app.mjs";
|
|
3
3
|
import { getListFilesOpts } from "../../common/utils.mjs";
|
|
4
4
|
import sampleEmit from "./test-event.mjs";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
CHANGE_FILTER_FILE_FIELDS,
|
|
7
|
+
GOOGLE_DRIVE_FOLDER_MIME_TYPE,
|
|
8
|
+
} from "../../common/constants.mjs";
|
|
6
9
|
import md5 from "md5";
|
|
7
10
|
|
|
8
11
|
export default {
|
|
9
12
|
key: "google_drive-new-or-modified-files-polling",
|
|
10
13
|
name: "New or Modified Files (Polling)",
|
|
11
14
|
description: "Emit new event when a file in the selected Drive is created, modified or trashed. [See the documentation](https://developers.google.com/drive/api/v3/reference/changes/list)",
|
|
12
|
-
version: "0.0
|
|
15
|
+
version: "0.1.0",
|
|
13
16
|
type: "source",
|
|
14
17
|
dedupe: "unique",
|
|
15
18
|
props: {
|
|
@@ -72,6 +75,12 @@ export default {
|
|
|
72
75
|
"changesPageSize",
|
|
73
76
|
],
|
|
74
77
|
},
|
|
78
|
+
maxEmitsPerRun: {
|
|
79
|
+
propDefinition: [
|
|
80
|
+
googleDrive,
|
|
81
|
+
"maxEmitsPerRun",
|
|
82
|
+
],
|
|
83
|
+
},
|
|
75
84
|
},
|
|
76
85
|
hooks: {
|
|
77
86
|
async deploy() {
|
|
@@ -177,46 +186,38 @@ export default {
|
|
|
177
186
|
},
|
|
178
187
|
},
|
|
179
188
|
async run() {
|
|
180
|
-
// Store the current run timestamp at the start
|
|
181
189
|
const currentRunTimestamp = Date.now();
|
|
182
190
|
const lastRunTimestamp = this._getLastRunTimestamp();
|
|
183
191
|
|
|
184
|
-
const
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
changedFiles
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
fields: "*",
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
if (!this.shouldProcess(fullFile, lastRunTimestamp)) {
|
|
207
|
-
console.log(`Skipping file ${fullFile.name || fullFile.id}`);
|
|
208
|
-
continue;
|
|
192
|
+
const caughtUp = await this.googleDrive.processChangesPages({
|
|
193
|
+
pageToken: this._getPageToken(),
|
|
194
|
+
driveId: this.getDriveId(),
|
|
195
|
+
pageSize: this.changesPageSize,
|
|
196
|
+
fileFields: CHANGE_FILTER_FILE_FIELDS,
|
|
197
|
+
maxEmits: this.maxEmitsPerRun,
|
|
198
|
+
changeFilter: ({ file }) => this.shouldProcess(file, lastRunTimestamp),
|
|
199
|
+
processPage: async (changedFiles) => {
|
|
200
|
+
console.log(changedFiles.length
|
|
201
|
+
? `Processing ${changedFiles.length} changed files`
|
|
202
|
+
: "No changed files since last run");
|
|
203
|
+
|
|
204
|
+
let emitted = 0;
|
|
205
|
+
for (const file of changedFiles) {
|
|
206
|
+
const fullFile = await this.googleDrive.getFile(file.id, {
|
|
207
|
+
fields: "*",
|
|
208
|
+
});
|
|
209
|
+
await this.emitFile(fullFile);
|
|
210
|
+
emitted++;
|
|
209
211
|
}
|
|
212
|
+
return emitted;
|
|
213
|
+
},
|
|
214
|
+
savePageToken: (nextPageToken) => this._setPageToken(nextPageToken),
|
|
215
|
+
});
|
|
210
216
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
// Save the next page token after successfully processing
|
|
215
|
-
this._setPageToken(nextPageToken);
|
|
217
|
+
// Hold until caught up so backlog files aren't skipped
|
|
218
|
+
if (caughtUp) {
|
|
219
|
+
this._setLastRunTimestamp(currentRunTimestamp);
|
|
216
220
|
}
|
|
217
|
-
|
|
218
|
-
// Update the last run timestamp after processing all changes
|
|
219
|
-
this._setLastRunTimestamp(currentRunTimestamp);
|
|
220
221
|
},
|
|
221
222
|
sampleEmit,
|
|
222
223
|
};
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
// 2) A timer that runs on regular intervals, renewing the notification channel as needed
|
|
10
10
|
|
|
11
11
|
import {
|
|
12
|
+
CHANGE_FILTER_FILE_FIELDS,
|
|
13
|
+
GOOGLE_DRIVE_FOLDER_MIME_TYPE,
|
|
12
14
|
GOOGLE_DRIVE_NOTIFICATION_ADD,
|
|
13
15
|
GOOGLE_DRIVE_NOTIFICATION_CHANGE,
|
|
14
16
|
GOOGLE_DRIVE_NOTIFICATION_UPDATE,
|
|
@@ -21,7 +23,7 @@ export default {
|
|
|
21
23
|
key: "google_drive-new-or-modified-folders",
|
|
22
24
|
name: "New or Modified Folders (Instant)",
|
|
23
25
|
description: "Emit new event when a folder is created or modified in the selected Drive",
|
|
24
|
-
version: "0.
|
|
26
|
+
version: "1.0.0",
|
|
25
27
|
type: "source",
|
|
26
28
|
// Dedupe events based on the "x-goog-message-number" header for the target channel:
|
|
27
29
|
// https://developers.google.com/drive/api/v3/push#making-watch-requests
|
|
@@ -55,12 +57,21 @@ export default {
|
|
|
55
57
|
|
|
56
58
|
const args = this.getListFilesOpts({
|
|
57
59
|
q: `mimeType = "application/vnd.google-apps.folder" and modifiedTime > "${timeString}" and trashed = false`,
|
|
58
|
-
fields:
|
|
60
|
+
fields: `files(${CHANGE_FILTER_FILE_FIELDS})`,
|
|
59
61
|
});
|
|
60
62
|
|
|
61
63
|
const { files } = await this.googleDrive.listFilesInPage(null, args);
|
|
62
64
|
|
|
63
|
-
await this.
|
|
65
|
+
const changeFilter = await this.getChangeFilter();
|
|
66
|
+
const folders = [];
|
|
67
|
+
for (const file of files) {
|
|
68
|
+
if (folders.length < 5 && await changeFilter({
|
|
69
|
+
file,
|
|
70
|
+
})) {
|
|
71
|
+
folders.push(file);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
await this.processChanges(folders);
|
|
64
75
|
},
|
|
65
76
|
...common.hooks,
|
|
66
77
|
},
|
|
@@ -79,20 +90,24 @@ export default {
|
|
|
79
90
|
GOOGLE_DRIVE_NOTIFICATION_UPDATE,
|
|
80
91
|
];
|
|
81
92
|
},
|
|
82
|
-
|
|
93
|
+
getChangesFileFields() {
|
|
94
|
+
return CHANGE_FILTER_FILE_FIELDS;
|
|
95
|
+
},
|
|
96
|
+
async getAllParents(folderId, parentsCache = new Map()) {
|
|
83
97
|
const allParents = [];
|
|
84
98
|
let currentId = folderId;
|
|
85
99
|
|
|
86
100
|
while (currentId) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
101
|
+
if (!parentsCache.has(currentId)) {
|
|
102
|
+
const { parents } = await this.googleDrive.getFile(currentId, {
|
|
103
|
+
fields: "parents",
|
|
104
|
+
});
|
|
105
|
+
parentsCache.set(currentId, parents?.[0]);
|
|
106
|
+
}
|
|
107
|
+
currentId = parentsCache.get(currentId);
|
|
108
|
+
if (currentId) {
|
|
109
|
+
allParents.push(currentId);
|
|
94
110
|
}
|
|
95
|
-
currentId = parents?.[0];
|
|
96
111
|
}
|
|
97
112
|
|
|
98
113
|
return allParents;
|
|
@@ -108,16 +123,13 @@ export default {
|
|
|
108
123
|
ts,
|
|
109
124
|
};
|
|
110
125
|
},
|
|
111
|
-
|
|
126
|
+
getChanges(headers) {
|
|
112
127
|
if (!headers) {
|
|
113
128
|
return {
|
|
114
129
|
change: { },
|
|
115
130
|
};
|
|
116
131
|
}
|
|
117
|
-
const resourceUri = headers["x-goog-resource-uri"];
|
|
118
|
-
const metadata = await this.googleDrive.getFileMetadata(`${resourceUri}&fields=*`);
|
|
119
132
|
return {
|
|
120
|
-
...metadata,
|
|
121
133
|
change: {
|
|
122
134
|
state: headers["x-goog-resource-state"],
|
|
123
135
|
resourceURI: headers["x-goog-resource-uri"],
|
|
@@ -125,45 +137,34 @@ export default {
|
|
|
125
137
|
},
|
|
126
138
|
};
|
|
127
139
|
},
|
|
128
|
-
async
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
(file) => file.mimeType === "application/vnd.google-apps.folder",
|
|
133
|
-
);
|
|
134
|
-
|
|
135
|
-
const filteredFiles = [];
|
|
136
|
-
for (const file of files) {
|
|
140
|
+
async getChangeFilter() {
|
|
141
|
+
let targetId = this.folderId;
|
|
142
|
+
const parentsCache = new Map();
|
|
143
|
+
return async ({ file }) => {
|
|
137
144
|
// The changelog is updated each time a folder is opened. Check the
|
|
138
145
|
// folder's `modifiedTime` to see if the folder has been modified.
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
: this.drive);
|
|
143
|
-
|
|
144
|
-
const allParents = [];
|
|
145
|
-
if (this.includeSubfolders) {
|
|
146
|
-
allParents.push(...(await this.getAllParents(file.id)));
|
|
147
|
-
} else if (fileInfo.parents) {
|
|
148
|
-
allParents.push(fileInfo.parents[0]);
|
|
146
|
+
if (file.mimeType !== GOOGLE_DRIVE_FOLDER_MIME_TYPE
|
|
147
|
+
|| this._getLastModifiedTimeForFile(file.id) == Date.parse(file.modifiedTime)) {
|
|
148
|
+
return false;
|
|
149
149
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
150
|
+
if (!targetId) {
|
|
151
|
+
({ id: targetId } = await this.googleDrive.getFile(this.isMyDrive()
|
|
152
|
+
? "root"
|
|
153
|
+
: this.drive, {
|
|
154
|
+
fields: "id",
|
|
155
|
+
}));
|
|
153
156
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
157
|
+
const allParents = this.includeSubfolders
|
|
158
|
+
? await this.getAllParents(file.id, parentsCache)
|
|
159
|
+
: (file.parents ?? []).slice(0, 1);
|
|
160
|
+
return allParents.includes(targetId);
|
|
161
|
+
};
|
|
162
|
+
},
|
|
163
|
+
async processChanges(changedFiles, headers) {
|
|
164
|
+
const changes = this.getChanges(headers);
|
|
165
|
+
for (const { id } of changedFiles) {
|
|
166
|
+
const file = await this.googleDrive.getFile(id);
|
|
163
167
|
const modifiedTime = Date.parse(file.modifiedTime);
|
|
164
|
-
if (lastModifiedTimeForFile == modifiedTime) continue;
|
|
165
|
-
|
|
166
|
-
const changes = await this.getChanges(headers);
|
|
167
168
|
|
|
168
169
|
const eventToEmit = {
|
|
169
170
|
file,
|
|
@@ -175,6 +176,7 @@ export default {
|
|
|
175
176
|
|
|
176
177
|
this._setModifiedTimeForFile(file.id, modifiedTime);
|
|
177
178
|
}
|
|
179
|
+
return changedFiles.length;
|
|
178
180
|
},
|
|
179
181
|
},
|
|
180
182
|
};
|