@pipedream/pcloud 0.3.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.
package/LICENSE ADDED
@@ -0,0 +1,7 @@
1
+ Copyright 2020 Pipedream, Inc.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,43 @@
1
+ import pcloud from "../../pcloud.app.mjs";
2
+
3
+ export default {
4
+ props: {
5
+ pcloud,
6
+ },
7
+ methods: {
8
+ validateLocationId() {
9
+ const VALID_LOCATIONS = [
10
+ "0",
11
+ "1",
12
+ ];
13
+ const locationId = this.pcloud.$auth.locationid;
14
+
15
+ if (!VALID_LOCATIONS.includes(locationId)) {
16
+ return "Unable to retrieve your account's Location ID - try reconnecting your pCloud account to Pipedream";
17
+ }
18
+
19
+ return true;
20
+ },
21
+ async validateInputs() {
22
+ return true;
23
+ },
24
+ },
25
+ async run({ $ }) {
26
+ const validations = [
27
+ this.validateLocationId(),
28
+ await this.validateInputs(),
29
+ ];
30
+
31
+ const errors = validations.filter((result) => result !== true);
32
+ if (errors.length) {
33
+ throw new Error(errors.join("; "));
34
+ }
35
+
36
+ const requestMethod = this.requestMethod;
37
+ const response = await this.pcloud._withRetries(() => requestMethod());
38
+
39
+ $.export("$summary", this.getSummary());
40
+
41
+ return response;
42
+ },
43
+ };
@@ -0,0 +1,76 @@
1
+ import pcloud from "../../pcloud.app.mjs";
2
+ import common from "../common/base.mjs";
3
+
4
+ export default {
5
+ ...common,
6
+ key: "pcloud-copy-file",
7
+ name: "Copy File",
8
+ description:
9
+ "Copy a file to the specified destination. [See the docs here](https://docs.pcloud.com/methods/file/copyfile.html)",
10
+ version: "0.0.1",
11
+ type: "action",
12
+ props: {
13
+ ...common.props,
14
+ fileId: {
15
+ propDefinition: [
16
+ pcloud,
17
+ "fileId",
18
+ ],
19
+ description: `Select a **File** to copy.
20
+ \\
21
+ Alternatively, you can provide a custom *File ID*.`,
22
+ },
23
+ toFolderId: {
24
+ propDefinition: [
25
+ pcloud,
26
+ "folderId",
27
+ ],
28
+ label: "Destination Folder ID",
29
+ description: `Select a **Destination Folder** to receive the copied file.
30
+ \\
31
+ Alternatively, you can provide a custom *Folder ID*.`,
32
+ },
33
+ name: {
34
+ propDefinition: [
35
+ pcloud,
36
+ "name",
37
+ ],
38
+ label: "New File Name",
39
+ description: "Name of the destination file.",
40
+ },
41
+ overwrite: {
42
+ propDefinition: [
43
+ pcloud,
44
+ "overwrite",
45
+ ],
46
+ },
47
+ modifiedTime: {
48
+ propDefinition: [
49
+ pcloud,
50
+ "modifiedTime",
51
+ ],
52
+ },
53
+ createdTime: {
54
+ propDefinition: [
55
+ pcloud,
56
+ "createdTime",
57
+ ],
58
+ },
59
+ },
60
+ methods: {
61
+ ...common.methods,
62
+ getSummary() {
63
+ return `Copied file "${this.name}" successfully`;
64
+ },
65
+ async requestMethod() {
66
+ return this.pcloud.copyFile(
67
+ this.fileId,
68
+ this.toFolderId,
69
+ this.name,
70
+ !this.overwrite,
71
+ this.modifiedTime,
72
+ this.createdTime,
73
+ );
74
+ },
75
+ },
76
+ };
@@ -0,0 +1,61 @@
1
+ import pcloud from "../../pcloud.app.mjs";
2
+ import common from "../common/base.mjs";
3
+
4
+ export default {
5
+ ...common,
6
+ key: "pcloud-copy-folder",
7
+ name: "Copy Folder",
8
+ description: "Copy a folder to the specified folder. [See the docs here](https://docs.pcloud.com/methods/folder/copyfolder.html)",
9
+ version: "0.0.1",
10
+ type: "action",
11
+ props: {
12
+ ...common.props,
13
+ folderId: {
14
+ propDefinition: [
15
+ pcloud,
16
+ "folderId",
17
+ ],
18
+ description: `Select a **Folder** to copy.
19
+ \\
20
+ Alternatively, you can provide a custom *Folder ID*.`,
21
+ },
22
+ toFolderId: {
23
+ propDefinition: [
24
+ pcloud,
25
+ "folderId",
26
+ ],
27
+ label: "Destination Folder ID",
28
+ description: `Select a **Destination Folder** where the folder will be copied to.
29
+ \\
30
+ Alternatively, you can provide a custom *Folder ID*.`,
31
+ },
32
+ overwrite: {
33
+ propDefinition: [
34
+ pcloud,
35
+ "overwrite",
36
+ ],
37
+ },
38
+ copyContentOnly: {
39
+ type: "boolean",
40
+ label: "Copy Content Only?",
41
+ description:
42
+ "If true, only the contents of source folder will be copied, otherwise the folder itself is copied.",
43
+ default: false,
44
+ optional: true,
45
+ },
46
+ },
47
+ methods: {
48
+ ...common.methods,
49
+ getSummary() {
50
+ return "Copied folder successfully";
51
+ },
52
+ async requestMethod() {
53
+ return this.pcloud.copyFolder(
54
+ this.folderId,
55
+ this.toFolderId,
56
+ !this.overwrite,
57
+ this.copyContentOnly,
58
+ );
59
+ },
60
+ },
61
+ };
@@ -0,0 +1,40 @@
1
+ import pcloud from "../../pcloud.app.mjs";
2
+ import common from "../common/base.mjs";
3
+
4
+ export default {
5
+ ...common,
6
+ key: "pcloud-create-folder",
7
+ name: "Create Folder",
8
+ description:
9
+ "Create a folder in the specified folder. [See the docs here](https://docs.pcloud.com/methods/folder/createfolder.html)",
10
+ version: "0.0.1",
11
+ type: "action",
12
+ props: {
13
+ ...common.props,
14
+ folderId: {
15
+ propDefinition: [
16
+ pcloud,
17
+ "folderId",
18
+ ],
19
+ description: `Select a **Folder** to create the new folder within.
20
+ \\
21
+ Alternatively, you can provide a custom *Folder ID*.`,
22
+ label: "Parent Folder ID",
23
+ },
24
+ name: {
25
+ propDefinition: [
26
+ pcloud,
27
+ "name",
28
+ ],
29
+ },
30
+ },
31
+ methods: {
32
+ ...common.methods,
33
+ getSummary() {
34
+ return `Created folder "${this.name}" successfully`;
35
+ },
36
+ async requestMethod() {
37
+ return this.pcloud.createFolder(this.name, this.folderId);
38
+ },
39
+ },
40
+ };
@@ -0,0 +1,37 @@
1
+ import pcloud from "../../pcloud.app.mjs";
2
+ import common from "../common/base.mjs";
3
+
4
+ export default {
5
+ ...common,
6
+ key: "pcloud-download-files",
7
+ name: "Download File(s)",
8
+ description: "Download one or more files to a folder. [See the docs here](https://docs.pcloud.com/methods/file/downloadfile.html)",
9
+ version: "0.0.1",
10
+ type: "action",
11
+ props: {
12
+ ...common.props,
13
+ urls: {
14
+ type: "string[]",
15
+ label: "URLs",
16
+ description: "URL(s) of the files to download.",
17
+ },
18
+ folderId: {
19
+ propDefinition: [
20
+ pcloud,
21
+ "folderId",
22
+ ],
23
+ description: `Select a **Folder** to receive the downloaded files.
24
+ \\
25
+ Alternatively, you can provide a custom *Folder ID*.`,
26
+ },
27
+ },
28
+ methods: {
29
+ ...common.methods,
30
+ getSummary() {
31
+ return `Downloaded ${this.urls.length} files successfully`;
32
+ },
33
+ async requestMethod() {
34
+ return this.pcloud.downloadFiles(this.urls, this.folderId);
35
+ },
36
+ },
37
+ };
@@ -0,0 +1,64 @@
1
+ import pcloud from "../../pcloud.app.mjs";
2
+ import common from "../common/base.mjs";
3
+
4
+ export default {
5
+ ...common,
6
+ key: "pcloud-list-contents",
7
+ name: "List Contents",
8
+ description: "Get the contents of the specified folder. [See the docs here](https://docs.pcloud.com/methods/folder/listfolder.html)",
9
+ version: "0.0.1",
10
+ type: "action",
11
+ props: {
12
+ ...common.props,
13
+ folderId: {
14
+ propDefinition: [
15
+ pcloud,
16
+ "folderId",
17
+ ],
18
+ description: `Select a **Folder** to get the contents of.
19
+ \\
20
+ Alternatively, you can provide a custom *Folder ID*.`,
21
+ },
22
+ recursive: {
23
+ type: "boolean",
24
+ label: "Recursive?",
25
+ description:
26
+ "If true, returns contents of the folder **and all subfolders,** recursively.",
27
+ default: false,
28
+ },
29
+ showDeleted: {
30
+ propDefinition: [
31
+ pcloud,
32
+ "showDeleted",
33
+ ],
34
+ },
35
+ noFiles: {
36
+ type: "boolean",
37
+ label: "Folders Only?",
38
+ description:
39
+ "If true, only the **folder** (sub)structure will be returned.",
40
+ default: false,
41
+ },
42
+ noShares: {
43
+ type: "boolean",
44
+ label: "Exclude Shares?",
45
+ description: "If true, excludes shared files and folders.",
46
+ default: true,
47
+ },
48
+ },
49
+ methods: {
50
+ ...common.methods,
51
+ getSummary() {
52
+ return "Listed folder contents successfully";
53
+ },
54
+ async requestMethod() {
55
+ return this.pcloud.listContents(
56
+ this.folderId,
57
+ this.recursive,
58
+ this.showDeleted,
59
+ this.noFiles,
60
+ this.noShares,
61
+ );
62
+ },
63
+ },
64
+ };
@@ -0,0 +1,80 @@
1
+ import pcloud from "../../pcloud.app.mjs";
2
+ import common from "../common/base.mjs";
3
+ import { promises as fsPromises } from "fs";
4
+
5
+ export default {
6
+ ...common,
7
+ key: "pcloud-upload-file",
8
+ name: "Upload File",
9
+ description:
10
+ "Upload a file to the specified folder. [See the docs here](https://docs.pcloud.com/methods/file/uploadfile.html)",
11
+ version: "0.0.1",
12
+ type: "action",
13
+ props: {
14
+ ...common.props,
15
+ folderId: {
16
+ propDefinition: [
17
+ pcloud,
18
+ "folderId",
19
+ ],
20
+ description: `Select a **Folder** to receive the uploaded file.
21
+ \\
22
+ Alternatively, you can provide a custom *Folder ID*.`,
23
+ },
24
+ name: {
25
+ propDefinition: [
26
+ pcloud,
27
+ "name",
28
+ ],
29
+ description: `Name of the file to upload. This must be a file in the workflow's \`/tmp\` directory.
30
+ \\
31
+ [See the docs on how to work with files in your workflow.](https://pipedream.com/docs/code/nodejs/working-with-files/)`,
32
+ },
33
+ renameIfExists: {
34
+ type: "boolean",
35
+ label: "Rename if Exists",
36
+ description:
37
+ "If true, the uploaded file will be renamed, if another file with the requested name already exists in the specified folder.",
38
+ default: true,
39
+ },
40
+ modifiedTime: {
41
+ propDefinition: [
42
+ pcloud,
43
+ "modifiedTime",
44
+ ],
45
+ },
46
+ createdTime: {
47
+ propDefinition: [
48
+ pcloud,
49
+ "createdTime",
50
+ ],
51
+ },
52
+ },
53
+ methods: {
54
+ ...common.methods,
55
+ async validateInputs() {
56
+ const files = await fsPromises.readdir("/tmp");
57
+ const fileName = this.name;
58
+
59
+ if (!files.includes(fileName)) {
60
+ return `File "${this.name}" not found in the /tmp directory`;
61
+ }
62
+
63
+ return true;
64
+ },
65
+ getSummary() {
66
+ return `Uploaded file "${this.name}" successfully`;
67
+ },
68
+ async requestMethod() {
69
+ return this.pcloud.uploadFile(
70
+ this.folderId,
71
+ this.name,
72
+ this.noPartial,
73
+ this.progressHash,
74
+ this.renameIfExists,
75
+ this.modifiedTime,
76
+ this.createdTime,
77
+ );
78
+ },
79
+ },
80
+ };
package/package.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "@pipedream/pcloud",
3
+ "version": "0.3.3",
4
+ "description": "Pipedream pCloud Components",
5
+ "main": "pcloud.app.mjs",
6
+ "keywords": [
7
+ "pipedream",
8
+ "pcloud"
9
+ ],
10
+ "homepage": "https://pipedream.com/apps/pcloud",
11
+ "author": "Pipedream <support@pipedream.com> (https://pipedream.com/)",
12
+ "license": "MIT",
13
+ "dependencies": {
14
+ "async-retry": "^1.3.1",
15
+ "lodash": "^4.17.20",
16
+ "pcloud-sdk-js": "^2.0.0"
17
+ },
18
+ "publishConfig": {
19
+ "access": "public"
20
+ }
21
+ }
package/pcloud.app.mjs ADDED
@@ -0,0 +1,361 @@
1
+ import get from "lodash/get.js";
2
+ import retry from "async-retry";
3
+ import pcloudSdk from "pcloud-sdk-js";
4
+
5
+ export default {
6
+ type: "app",
7
+ app: "pcloud",
8
+ propDefinitions: {
9
+ fileId: {
10
+ type: "integer",
11
+ label: "File ID",
12
+ async options() {
13
+ return this.getFileOptions();
14
+ },
15
+ },
16
+ folderId: {
17
+ type: "integer",
18
+ label: "Folder ID",
19
+ async options() {
20
+ return this.getFolderOptions();
21
+ },
22
+ default: 0,
23
+ },
24
+ name: {
25
+ type: "string",
26
+ label: "Name",
27
+ description: "Name of the folder to be created.",
28
+ },
29
+ overwrite: {
30
+ type: "boolean",
31
+ label: "Overwrite?",
32
+ description: `If true, and an entry with the same name already exists, it will be overwritten.
33
+ \\
34
+ Otherwise, an error \`2004\` will be returned instead.`,
35
+ default: false,
36
+ optional: true,
37
+ },
38
+ showDeleted: {
39
+ type: "boolean",
40
+ label: "Show Deleted?",
41
+ description:
42
+ "If true, deleted files and folders that can be undeleted will be displayed.",
43
+ default: false,
44
+ optional: true,
45
+ },
46
+ modifiedTime: {
47
+ type: "integer",
48
+ label: "Modified Time",
49
+ description: "Must be Unix time (seconds).",
50
+ optional: true,
51
+ },
52
+ createdTime: {
53
+ type: "integer",
54
+ label: "Created Time",
55
+ description: `Must be Unix time (seconds).
56
+ \\
57
+ Requires \`Modified Time\` to be set.`,
58
+ optional: true,
59
+ },
60
+ },
61
+ methods: {
62
+ async api() {
63
+ global.locationid = Number(this.$auth.locationid);
64
+ // eslint-disable-next-line no-unused-vars
65
+ /*
66
+ const locations = {
67
+ 1: "api.pcloud.com",
68
+ 2: "eapi.pcloud.com",
69
+ };
70
+ */
71
+ return pcloudSdk.createClient(
72
+ this.$auth.oauth_access_token,
73
+ "oauth",
74
+ );
75
+ },
76
+ _isRetriableStatusCode(statusCode) {
77
+ return [
78
+ 408,
79
+ 429,
80
+ 500,
81
+ ].includes(statusCode);
82
+ },
83
+ async _withRetries(apiCall) {
84
+ const retryOpts = {
85
+ retries: 3,
86
+ factor: 2,
87
+ };
88
+ return retry(async (bail) => {
89
+ try {
90
+ return await apiCall();
91
+ } catch (err) {
92
+ const statusCode = [
93
+ get(err, [
94
+ "response",
95
+ "status",
96
+ ]),
97
+ ];
98
+ if (!this._isRetriableStatusCode(statusCode)) {
99
+ if (err.result) {
100
+ bail(`
101
+ Error processing pCloud request (result: ${err.result}):
102
+ ${JSON.stringify(err.error)}
103
+ `);
104
+ } else {
105
+ bail(`
106
+ Unexpected error (status code: ${statusCode}):
107
+ ${JSON.stringify(err.message)}
108
+ `);
109
+ console.warn(`Temporary error: ${err.error}`);
110
+ }
111
+ }
112
+ throw err;
113
+ }
114
+ }, retryOpts);
115
+ },
116
+ /**
117
+ * Takes one file and copies it as another file in the user's filesystem.
118
+ * pCloud API domain URL depends on the location of pCLoud data center associated to the
119
+ * account.
120
+ * @params {integer} fileId - ID of the file to copy.
121
+ * @params {integer} toFolderId - ID of the destination folder.
122
+ * @params {string} toName - Name of the destination file.
123
+ * @params {boolean} noOver - If `true` and a file with the specified name already exists,
124
+ * no overwriting will be performed.
125
+ * @params {string} modifiedTime - Must be a UNIX timestamp.
126
+ * seconds.
127
+ * @params {string} createdTime - If specified, file created time is set. It's required to
128
+ * provide `modifiedTime` to set `createdTime`. Must be in unix time seconds.
129
+ * @returns {metadata: array, result: integer } An array with the [metadata](https://docs.pcloud.com/structures/metadata.html) of the newly copied file. A `result` integer that indicates the results of the API operation, 0 means success, a non-zero result means an error occurred, when the result is non-zero an `error` message is included.
130
+ */
131
+ async copyFile(
132
+ fileId,
133
+ toFolderId,
134
+ toName,
135
+ noOver,
136
+ modifiedTime,
137
+ createdTime,
138
+ ) {
139
+ const params = {
140
+ fileid: fileId,
141
+ tofolderid: toFolderId,
142
+ };
143
+
144
+ if (toName) {
145
+ params.toname = toName;
146
+ }
147
+ if (noOver) {
148
+ params.noover = 1;
149
+ }
150
+ if (modifiedTime) {
151
+ params.mtime = modifiedTime;
152
+ }
153
+ if (createdTime) {
154
+ params.ctime = createdTime;
155
+ }
156
+ return (
157
+ await this.api()
158
+ ).api("copyfile", {
159
+ params,
160
+ });
161
+ },
162
+ /**
163
+ * Copies a folder to the specified folder.
164
+ * @params {integer} folderId - ID of the folder to copy.
165
+ * @params {integer} toFolderId - ID of the destination folder.
166
+ * @params {boolean} noOver - If `true` and files with the same name already exist it will
167
+ * return a `2004` error code. Othrwise files will be overwritten.
168
+ * @params {boolean} copyContentOnly - If set, only the content of source folder will be copied
169
+ * otherwise the folder itself is copied.
170
+ * @returns {metadata: array, result: integer } An array with the [metadata](https://docs.pcloud.com/structures/metadata.html) of the newly copied folder. A `result` integer that indicates the results of the API operation, 0 means success, a non-zero result means an error occurred, when the result is non-zero an `error` message is included.
171
+ */
172
+ async copyFolder(folderId, toFolderId, noOver, copyContentOnly) {
173
+ const params = {};
174
+ params.folderid = folderId;
175
+ params.tofolderid = toFolderId;
176
+ if (noOver) {
177
+ params.noover = 1;
178
+ }
179
+ if (copyContentOnly) {
180
+ params.copycontentonly = 1;
181
+ }
182
+ return (
183
+ await this.api()
184
+ ).api("copyfolder", {
185
+ params,
186
+ });
187
+ },
188
+ /**
189
+ * Creates a folder in the specified folder.
190
+ * @params {string} name - Name of the folder to be created.
191
+ * @params {integer} folderId - ID of the parent folder where the new folder will be created.
192
+ * @returns {metadata: array, result: integer } An array with the [metadata](https://docs.pcloud.com/structures/metadata.html) of the newly created folder. A `result` integer that indicates the results of the API operation, 0 means success, a non-zero result means an error occurred, when the result is non-zero an `error` message is included.
193
+ */
194
+ async createFolder(name, folderId) {
195
+ return (await this.api()).createfolder(name, folderId);
196
+ },
197
+ /**
198
+ * Downloads one or more files from links supplied in the url parameter.
199
+ * @params {array} urls - URL(s) of the files to download.
200
+ * @params {integer} folderId - ID of the folder, in which to download the files.
201
+ * @returns {metadata: array, result: integer } An array with the [metadata]
202
+ * (https://docs.pcloud.com/structures/metadata.html) of each of the downloaded files. A
203
+ * `result` integer that indicates the results of the API operation, 0 means success, a
204
+ * non-zero result means an error occurred, when the result is non-zero an `error` message is
205
+ * included.
206
+ */
207
+ async downloadFiles(urls, folderId) {
208
+ return (await this.api()).remoteupload(urls.join(" "), folderId);
209
+ },
210
+ /**
211
+ * Gets the dynamically populated options for file related props.
212
+ * @returns {array} An array to use as dynamically populated options in file ID related
213
+ * props.
214
+ */
215
+ async getFileOptions() {
216
+ const folderItems = await this._withRetries(() =>
217
+ this.listContents(
218
+ 0, //0 - ID for the root folder
219
+ true,
220
+ null,
221
+ false,
222
+ ));
223
+ let options = [];
224
+ let name = "";
225
+ let populateOptions = function (name, folderItem) {
226
+ if (folderItem.name === "/" || name === "/") {
227
+ name = `${name}${folderItem.name}`;
228
+ } else {
229
+ name = `${name}/${folderItem.name}`;
230
+ }
231
+ if (!folderItem.isfolder) {
232
+ options.push({
233
+ label: name,
234
+ value: folderItem.fileid,
235
+ });
236
+ }
237
+ if (folderItem.isfolder && folderItem.contents.length) {
238
+ folderItem.contents.forEach((content) => {
239
+ populateOptions(name, content);
240
+ });
241
+ } else {
242
+ return;
243
+ }
244
+ };
245
+ populateOptions(name, folderItems);
246
+ return options;
247
+ },
248
+ /**
249
+ * Gets the dynamically populated options for folder related props.
250
+ * @returns {array} An array to use as dynamically populated options in folder ID related
251
+ * props.
252
+ */
253
+ async getFolderOptions() {
254
+ const folders = await this._withRetries(() =>
255
+ this.listContents(
256
+ 0, //0 - ID for the root folder
257
+ true,
258
+ null,
259
+ true,
260
+ ));
261
+ const options = [];
262
+ let name = "";
263
+ let populateOptions = function (name, folder) {
264
+ if (folder.name === "/" || name === "/") {
265
+ name = `${name}${folder.name}`;
266
+ } else {
267
+ name = `${name}/${folder.name}`;
268
+ }
269
+ options.push({
270
+ label: name,
271
+ value: folder.folderid,
272
+ });
273
+ if (folder.contents.length) {
274
+ folder.contents.forEach((content) => {
275
+ populateOptions(name, content);
276
+ });
277
+ } else {
278
+ return;
279
+ }
280
+ };
281
+ populateOptions(name, folders);
282
+ return options;
283
+ },
284
+ /**
285
+ * Lists the metadata of the specified folder's contents.
286
+ * pCloud API domain URL depends on the location of pCLoud data center associated to the
287
+ * account.
288
+ * @params {integer} folderId - ID of the folder to list contents. If not specified, the root
289
+ * folder will be used.
290
+ * @params {boolean} recursive - If is set full directory tree will be returned, which means
291
+ * that all directories will have contents filed.
292
+ * @params {boolean} showDeleted - If is set, deleted files and folders that can be undeleted
293
+ * will be displayed.
294
+ * @params {boolean} noFiles - If is set, only the folder (sub)structure will be returned.
295
+ * @params {boolean} noShares - If is set, only user's own folders and files will be displayed.
296
+ * @returns {metadata: array, result: integer } An array with the [metadata](https://docs.pcloud.com/structures/metadata.html) of each of the retrieved files and folders, if `recursive` is set, an additional `contents` element will be presented for the contents of inner folders. A `result` integer that indicates the results of the API operation, 0 means success, a non-zero result means an error occurred, when the result is non-zero an `error` message is included.
297
+ */
298
+ async listContents(folderId, recursive, showDeleted, noFiles, noShares) {
299
+ const optionalParams = {};
300
+ if (recursive) {
301
+ optionalParams.recursive = 1; //Need to use an integer for `recursive`, `showDeleted`, `noFiles`,
302
+ //and `noShares` if `true`
303
+ }
304
+ if (showDeleted) {
305
+ optionalParams.showdeleted = 1;
306
+ }
307
+ if (noFiles) {
308
+ optionalParams.nofiles = 1;
309
+ }
310
+ if (noShares) {
311
+ optionalParams.noshares = 1;
312
+ }
313
+ return (await this.api()).listfolder(folderId, optionalParams);
314
+ },
315
+ /**
316
+ * Uploads a file to the user's filesystem.
317
+ * @params {integer} folderid - ID of the folder where the file will be uploaded.
318
+ * @params {string} name - Name of the file to upload.
319
+ * @params {boolean} renameIfExists - When `true`, the uploaded file will
320
+ * be renamed, if file with
321
+ * the requested name exists in the folder.
322
+ * @params {integer} modifiedTime - If set, file modified time is set. Must be a unix timestamp.
323
+ * @params {integer} createdTime - If set, file created time is set. Must be a unix timestamp.
324
+ * It's required to provide `modifiedTime` to set `createdTime`.
325
+ * @returns {checksums: array, fileids: array, metadata: array, result: integer} A `checksums` array, each element with the file checksums calculated with `md5` and `sha1` algorithms, the `id` of the created file under the one element `fileids` array, and an array with the [metadata](https://docs.pcloud.com/structures/metadata.html) of the newly uploaded file. A `result` integer that indicates the results of the API operation, 0 means success, a non-zero result means an error occurred, when the result is non-zero an `error` message is included.
326
+ */
327
+ async uploadFile(
328
+ folderid,
329
+ name,
330
+ renameIfExists,
331
+ modifiedTime,
332
+ createdTime,
333
+ ) {
334
+ const params = {
335
+ folderid,
336
+ };
337
+ const files = [
338
+ {
339
+ name,
340
+ file: `/tmp/${name}`,
341
+ },
342
+ ];
343
+ if (renameIfExists) {
344
+ params.renameifexists = 1;
345
+ }
346
+ if (modifiedTime) {
347
+ params.mtime = modifiedTime;
348
+ }
349
+ if (createdTime) {
350
+ params.ctime = createdTime;
351
+ }
352
+ return (
353
+ await this.api()
354
+ ).api("uploadfile", {
355
+ method: "post",
356
+ params,
357
+ files,
358
+ });
359
+ },
360
+ },
361
+ };
@@ -0,0 +1,120 @@
1
+ import pcloud from "../../pcloud.app.mjs";
2
+ import get from "lodash/get.js";
3
+
4
+ export default {
5
+ key: "pcloud-watch-folder",
6
+ name: "Watch Folder",
7
+ description:
8
+ "Emit new event when a file is created or modified in the specified folder.",
9
+ version: "0.0.1",
10
+ type: "source",
11
+ dedupe: "last",
12
+ props: {
13
+ pcloud,
14
+ db: "$.service.db",
15
+ timer: {
16
+ label: "Polling schedule",
17
+ description: "Pipedream polls pCloud for events on this schedule.",
18
+ type: "$.interface.timer",
19
+ default: {
20
+ intervalSeconds: 60 * 15, // by default, run every 15 minutes.
21
+ },
22
+ },
23
+ folderId: {
24
+ propDefinition: [
25
+ pcloud,
26
+ "folderId",
27
+ ],
28
+ description: `Select a **Folder** to watch for changes.
29
+ \\
30
+ Alternatively, you can provide a custom *Folder ID*.`,
31
+ },
32
+ event: {
33
+ type: "string",
34
+ label: "Folder Event",
35
+ options: [
36
+ "Created",
37
+ "Modified",
38
+ ],
39
+ description:
40
+ "Specify when to emit an event related to a given folder. Note that pCloud preserves files' `created` and `modified` timestamps on upload. If manually uploading via pCloud's `uploadfile` API, these timestamps can be set by specifying the `mtime` and `ctime` parameters, respectively.",
41
+ default: "Created",
42
+ },
43
+ showDeleted: {
44
+ propDefinition: [
45
+ pcloud,
46
+ "showDeleted",
47
+ ],
48
+ },
49
+ },
50
+ hooks: {
51
+ async deploy() {
52
+ const files = [];
53
+ const pCloudContentsData = await this.getContents();
54
+ const hasContents = get(pCloudContentsData, [
55
+ "contents",
56
+ ]);
57
+ if (hasContents) {
58
+ for (const folderItem of pCloudContentsData.contents) {
59
+ if (!folderItem.isfolder) {
60
+ files.push(folderItem);
61
+ if (files.length == 10) {
62
+ break;
63
+ }
64
+ }
65
+ }
66
+ } else {
67
+ console.log("No data available, skipping iteration");
68
+ }
69
+ files.forEach(this.emitpCloudEvent);
70
+ this.db.set("lastPolledTime", +Date.now());
71
+ },
72
+ },
73
+ methods: {
74
+ async getContents() {
75
+ return this.pcloud._withRetries(() =>
76
+ this.pcloud.listContents(
77
+ this.folderId,
78
+ false,
79
+ this.showDeleted,
80
+ false,
81
+ false,
82
+ ));
83
+ },
84
+ emitpCloudEvent(pCloudEvent) {
85
+ const metadata = this.getEventData(pCloudEvent);
86
+ this.$emit(pCloudEvent, metadata);
87
+ },
88
+ getEventData(pcloudEvent) {
89
+ const eventDate = pcloudEvent[this.event.toLowerCase()];
90
+ const ts = +new Date(eventDate);
91
+ return {
92
+ id: ts,
93
+ summary: `${this.event} file "${pcloudEvent.name}"`,
94
+ ts,
95
+ };
96
+ },
97
+ },
98
+ async run() {
99
+ const lastPolledTime = this.db.get("lastPolledTime");
100
+ const files = [];
101
+ const pCloudContentsData = await this.getContents();
102
+ const hasContents = get(pCloudContentsData, [
103
+ "contents",
104
+ ]);
105
+ if (hasContents) {
106
+ for (const folderItem of pCloudContentsData.contents) {
107
+ if (!folderItem.isfolder) {
108
+ let fileTime = +new Date(folderItem[this.event.toLowerCase()]);
109
+ if (fileTime > lastPolledTime) {
110
+ files.push(folderItem);
111
+ }
112
+ }
113
+ }
114
+ } else {
115
+ console.log("No data available, skipping iteration");
116
+ }
117
+ files.forEach(this.emitpCloudEvent);
118
+ this.db.set("lastPolledTime", +Date.now());
119
+ },
120
+ };