diff --git a/components/aws/.upm/store.json b/components/aws/.upm/store.json index 71e420292d53d..07458ed31c819 100644 --- a/components/aws/.upm/store.json +++ b/components/aws/.upm/store.json @@ -1 +1 @@ -{"version":2,"languages":{"nodejs-npm":{"guessedImports":["aws-sdk","axios","shortid"],"guessedImportsHash":"08190b61ee0169fd35ea81dce6f4754d"}}} +{"version":2, "languages":{"nodejs-npm":{"guessedImports":["aws-sdk", "axios", "shortid"], "guessedImportsHash":"08190b61ee0169fd35ea81dce6f4754d"}}} diff --git a/components/aws/package.json b/components/aws/package.json index 24436dba3c0ef..e7a4293572a55 100644 --- a/components/aws/package.json +++ b/components/aws/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/aws", - "version": "1.1.0", + "version": "1.1.1", "description": "Pipedream Aws Components", "main": "aws.app.mjs", "keywords": [ @@ -34,6 +34,7 @@ "@pipedream/platform": "^3.1.0", "adm-zip": "^0.5.10", "dedent": "^1.5.1", + "file-type": "^21.0.0", "mailparser": "^3.6.6", "mailparser-mit": "^1.0.0", "nanoid": "^5.0.4", diff --git a/components/aws/sources/common/include-link.mjs b/components/aws/sources/common/include-link.mjs new file mode 100644 index 0000000000000..61751899e2756 --- /dev/null +++ b/components/aws/sources/common/include-link.mjs @@ -0,0 +1,68 @@ +import { Readable } from "stream"; +import { fileTypeFromBuffer } from "file-type"; + +export default { + props: { + includeLink: { + label: "Include Link", + type: "boolean", + description: "Upload file to your File Stash and emit temporary download link to the file. See [the docs](https://pipedream.com/docs/connect/components/files) to learn more about working with files in Pipedream.", + default: false, + optional: true, + }, + dir: { + type: "dir", + accessMode: "write", + optional: true, + }, + }, + methods: { + async streamToBuffer(stream) { + const chunks = []; + for await (const chunk of stream) { + chunks.push(chunk); + } + return Buffer.concat(chunks); + }, + async stashFile(item) { + const { Body } = await this.getObject({ + Bucket: item.bucket.name, + Key: item.object.key.replace(/\+/g, " "), + }); + const filepath = `${item.bucket.name}/${item.object.key}`; + const buffer = await this.streamToBuffer(Body); + const type = await fileTypeFromBuffer(buffer); + // Upload the attachment to the configured directory (File Stash) so it + // can be accessed later. + const file = await this.dir.open(filepath).fromReadableStream( + Readable.from(buffer), + type?.mime, + buffer.length, + ); + // Return file details and temporary download link: + // { path, get_url, s3Key, type } + return await file.withoutPutUrl().withGetUrl(); + }, + async processEvent(event) { + const { Message: rawMessage } = event.body; + const { + Records: s3Events = [], + Event: eventType, + } = JSON.parse(rawMessage); + + if (eventType === "s3:TestEvent") { + console.log("Received initial test event. Skipping..."); + return; + } + + for (const s3Event of s3Events) { + const meta = this.generateMeta(s3Event); + let { s3: item } = s3Event; + if (this.includeLink) { + item.file = await this.stashFile(item); + } + this.$emit(item, meta); + } + }, + }, +}; diff --git a/components/aws/sources/s3-new-file/s3-new-file.mjs b/components/aws/sources/s3-new-file/s3-new-file.mjs index 8af7e3e768bec..6eac426f42142 100644 --- a/components/aws/sources/s3-new-file/s3-new-file.mjs +++ b/components/aws/sources/s3-new-file/s3-new-file.mjs @@ -1,4 +1,5 @@ import base from "../common/s3.mjs"; +import includeLink from "../common/include-link.mjs"; export default { ...base, @@ -6,10 +7,15 @@ export default { key: "aws-s3-new-file", name: "New S3 File", description: "Emit new event when a file is added to an S3 bucket", - version: "0.1.4", + version: "0.2.0", dedupe: "unique", + props: { + ...base.props, + ...includeLink.props, + }, methods: { ...base.methods, + ...includeLink.methods, getEvents() { return [ "s3:ObjectCreated:*", diff --git a/components/aws/sources/s3-restored-file/s3-restored-file.mjs b/components/aws/sources/s3-restored-file/s3-restored-file.mjs index c620ae5a34cb4..5522954b7741c 100644 --- a/components/aws/sources/s3-restored-file/s3-restored-file.mjs +++ b/components/aws/sources/s3-restored-file/s3-restored-file.mjs @@ -1,14 +1,20 @@ import base from "../common/s3.mjs"; +import includeLink from "../common/include-link.mjs"; export default { ...base, type: "source", key: "aws-s3-restored-file", name: "New Restored S3 File", - description: "Emit new event when an file is restored into a S3 bucket", - version: "0.1.4", + description: "Emit new event when a file is restored into an S3 bucket", + version: "0.2.0", dedupe: "unique", props: { + info: { + type: "alert", + alertType: "info", + content: "Allows receipt of notifications for event initiation and completion when restoring objects from the **S3 Glacier Flexible Retrieval** storage class, **S3 Glacier Deep Archive** storage class, **S3 Intelligent-Tiering Archive Access tier**, and **S3 Intelligent-Tiering Deep Archive Access tier**.", + }, ...base.props, detectRestoreInitiation: { type: "boolean", @@ -16,9 +22,11 @@ export default { description: "When enabled, this event source will also emit events whenever a restore is initiated", default: false, }, + ...includeLink.props, }, methods: { ...base.methods, + ...includeLink.methods, getEvents() { return [ this.detectRestoreInitiation diff --git a/components/box/actions/create-sign-request/create-sign-request.mjs b/components/box/actions/create-sign-request/create-sign-request.mjs index ae14671a3832e..85724d65a4ee3 100644 --- a/components/box/actions/create-sign-request/create-sign-request.mjs +++ b/components/box/actions/create-sign-request/create-sign-request.mjs @@ -6,7 +6,7 @@ export default { name: "Create Box Sign Request", description: "Creates a signature request. This involves preparing a document for signing and sending the signature request to signers. [See the documentation](https://developer.box.com/reference/post-sign-requests/).", key: "box-create-sign-request", - version: "0.0.1", + version: "0.0.2", type: "action", props: { app, diff --git a/components/box/actions/download-file/download-file.mjs b/components/box/actions/download-file/download-file.mjs index fbdbf1a57df0c..e9d2a9fa1d79f 100644 --- a/components/box/actions/download-file/download-file.mjs +++ b/components/box/actions/download-file/download-file.mjs @@ -7,7 +7,7 @@ export default { name: "Download File", description: "Downloads a file from Box to your workflow's `/tmp` directory. [See the documentation](https://developer.box.com/reference/get-files-id-content/)", key: "box-download-file", - version: "0.0.4", + version: "0.0.5", type: "action", props: { app, diff --git a/components/box/actions/get-comments/get-comments.mjs b/components/box/actions/get-comments/get-comments.mjs index fa1264013fae0..2bde6da30b425 100644 --- a/components/box/actions/get-comments/get-comments.mjs +++ b/components/box/actions/get-comments/get-comments.mjs @@ -5,7 +5,7 @@ export default { name: "Get Comments", description: "Fetches comments for a file. [See the documentation](https://developer.box.com/reference/get-files-id-comments/).", key: "box-get-comments", - version: "0.0.1", + version: "0.0.2", type: "action", props: { app, diff --git a/components/box/actions/search-content/search-content.mjs b/components/box/actions/search-content/search-content.mjs index 78ade1dc6d1a4..01ba3c589e4ed 100644 --- a/components/box/actions/search-content/search-content.mjs +++ b/components/box/actions/search-content/search-content.mjs @@ -6,7 +6,7 @@ export default { name: "Search Content", description: "Searches for files, folders, web links, and shared files across the users content or across the entire enterprise. [See the documentation](https://developer.box.com/reference/get-search/).", key: "box-search-content", - version: "0.0.4", + version: "0.0.5", type: "action", props: { app, diff --git a/components/box/actions/upload-file-version/upload-file-version.mjs b/components/box/actions/upload-file-version/upload-file-version.mjs index dce65588e1f0c..308164c90a109 100644 --- a/components/box/actions/upload-file-version/upload-file-version.mjs +++ b/components/box/actions/upload-file-version/upload-file-version.mjs @@ -5,7 +5,7 @@ export default { name: "Upload File Version", description: "Update a file's content. [See the documentation](https://developer.box.com/reference/post-files-id-content/).", key: "box-upload-file-version", - version: "0.1.1", + version: "0.1.2", type: "action", props: { app, diff --git a/components/box/actions/upload-file/upload-file.mjs b/components/box/actions/upload-file/upload-file.mjs index 27b5909d5a09e..1f0bc0dd08650 100644 --- a/components/box/actions/upload-file/upload-file.mjs +++ b/components/box/actions/upload-file/upload-file.mjs @@ -5,7 +5,7 @@ export default { name: "Upload a File", description: "Uploads a small file to Box. [See the documentation](https://developer.box.com/reference/post-files-content/).", key: "box-upload-file", - version: "0.1.1", + version: "0.1.2", type: "action", props: { app, diff --git a/components/box/box.app.mjs b/components/box/box.app.mjs index a7527d7a1d2f0..1addcb58aff4d 100644 --- a/components/box/box.app.mjs +++ b/components/box/box.app.mjs @@ -129,7 +129,9 @@ export default { type: "string", label: "Target", description: "The target item that will be used by webhooks.", - async options({ prevContext }) { + async options({ + prevContext, type, + }) { const { marker, queue, @@ -154,7 +156,7 @@ export default { ...resp.entries.filter((e) => e.type == "folder").map((e) => e.id), ], }, - options: resp.entries.map((e) => ({ + options: resp.entries.filter((e) => !type || e.type == type).map((e) => ({ value: JSON.stringify({ id: e.id, type: e.type, @@ -185,7 +187,7 @@ export default { ...innerResp.entries.filter((e) => e.type == "folder").map((e) => e.id), ], }, - options: innerResp.entries.map((e) => ({ + options: innerResp.entries.filter((e) => !type || e.type == type).map((e) => ({ value: JSON.stringify({ id: e.id, type: e.type, diff --git a/components/box/package.json b/components/box/package.json index 678a26319947a..ba788fa079192 100644 --- a/components/box/package.json +++ b/components/box/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/box", - "version": "0.5.0", + "version": "0.5.1", "description": "Pipedream Box Components", "main": "box.app.mjs", "keywords": [ @@ -11,6 +11,7 @@ "author": "Pipedream (https://pipedream.com/)", "dependencies": { "@pipedream/platform": "^3.1.0", + "file-type": "^21.0.0", "form-data": "^4.0.0", "path": "^0.12.7", "stream": "^0.0.2", diff --git a/components/box/sources/new-event/new-event.mjs b/components/box/sources/new-event/new-event.mjs index 58f449c354429..16599921ca68e 100644 --- a/components/box/sources/new-event/new-event.mjs +++ b/components/box/sources/new-event/new-event.mjs @@ -5,7 +5,7 @@ export default { key: "box-new-event", name: "New Event", description: "Emit new event when an event with subscribed event source triggered on a target. [See the documentation](https://developer.box.com/reference/post-webhooks)", - version: "0.0.4", + version: "0.0.5", type: "source", dedupe: "unique", ...common, diff --git a/components/box/sources/new-file/new-file.mjs b/components/box/sources/new-file/new-file.mjs index 99e6778201c3c..bc52e532aaf25 100644 --- a/components/box/sources/new-file/new-file.mjs +++ b/components/box/sources/new-file/new-file.mjs @@ -1,13 +1,39 @@ import common from "../common/common.mjs"; +import { Readable } from "stream"; +import { fileTypeFromBuffer } from "file-type"; export default { key: "box-new-file", name: "New File Event", - description: "Emit new event when a new file uploaded on a target. [See the documentation](https://developer.box.com/reference/post-webhooks)", - version: "0.0.4", + description: "Emit new event when a new file is uploaded to a target. [See the documentation](https://developer.box.com/reference/post-webhooks)", + version: "0.1.0", type: "source", dedupe: "unique", ...common, + props: { + ...common.props, + webhookTarget: { + propDefinition: [ + common.props.app, + "webhookTarget", + () => ({ + type: "folder", + }), + ], + }, + includeLink: { + label: "Include Link", + type: "boolean", + description: "Upload file to your File Stash and emit temporary download link to the file. See [the docs](https://pipedream.com/docs/connect/components/files) to learn more about working with files in Pipedream.", + default: false, + optional: true, + }, + dir: { + type: "dir", + accessMode: "write", + optional: true, + }, + }, methods: { ...common.methods, getTriggers() { @@ -18,5 +44,29 @@ export default { getSummary(event) { return `New file uploaded event with ID(${event.id})`; }, + async stashFile(event) { + const response = await this.app.downloadFile({ + fileId: event.source.id, + responseType: "arraybuffer", + }); + const buffer = Buffer.from(response); + const filepath = `${event.source.id}/${event.source.name}`; + const type = await fileTypeFromBuffer(buffer); + const file = await this.dir.open(filepath).fromReadableStream( + Readable.from(buffer), + type?.mime, + buffer.length, + ); + return await file.withoutPutUrl().withGetUrl(); + }, + }, + async run(event) { + if (this.includeLink) { + event.body.file = await this.stashFile(event.body); + } + this.$emit( + event.body, + this.getMetadata(event.body), + ); }, }; diff --git a/components/box/sources/new-folder/new-folder.mjs b/components/box/sources/new-folder/new-folder.mjs index f66753c6047b2..7d7a416d85b46 100644 --- a/components/box/sources/new-folder/new-folder.mjs +++ b/components/box/sources/new-folder/new-folder.mjs @@ -4,7 +4,7 @@ export default { key: "box-new-folder", name: "New Folder Event", description: "Emit new event when a new folder created on a target. [See the documentation](https://developer.box.com/reference/post-webhooks)", - version: "0.0.4", + version: "0.0.5", type: "source", dedupe: "unique", ...common, diff --git a/components/buddee/buddee.app.mjs b/components/buddee/buddee.app.mjs index 3004cfd7783b7..630c3f6142b05 100644 --- a/components/buddee/buddee.app.mjs +++ b/components/buddee/buddee.app.mjs @@ -8,4 +8,4 @@ export default { console.log(Object.keys(this.$auth)); }, }, -}; \ No newline at end of file +}; diff --git a/components/egnyte/actions/create-folder/create-folder.mjs b/components/egnyte/actions/create-folder/create-folder.mjs index bce22fdf880bc..6c233d84292dc 100644 --- a/components/egnyte/actions/create-folder/create-folder.mjs +++ b/components/egnyte/actions/create-folder/create-folder.mjs @@ -4,7 +4,7 @@ export default { key: "egnyte-create-folder", name: "Create Folder", description: "Creates a new folder in your Egnyte workspace. [See the documentation](https://developers.egnyte.com/docs/File_System_Management_API_Documentation#Create-a-Folder)", - version: "0.0.1", + version: "0.0.2", type: "action", props: { egnyte, diff --git a/components/egnyte/actions/upload-file/upload-file.mjs b/components/egnyte/actions/upload-file/upload-file.mjs index 60365c3b13fd1..65b26f15e5290 100644 --- a/components/egnyte/actions/upload-file/upload-file.mjs +++ b/components/egnyte/actions/upload-file/upload-file.mjs @@ -6,7 +6,7 @@ export default { key: "egnyte-upload-file", name: "Upload File", description: "Uploads a file to a specified folder in Egnyte. [See the documentation](https://developers.egnyte.com/docs/File_System_Management_API_Documentation#Upload-a-File)", - version: "0.1.1", + version: "0.1.2", type: "action", props: { egnyte, diff --git a/components/egnyte/egnyte.app.mjs b/components/egnyte/egnyte.app.mjs index 220b1f4c16e87..468c8bf47880b 100644 --- a/components/egnyte/egnyte.app.mjs +++ b/components/egnyte/egnyte.app.mjs @@ -55,5 +55,14 @@ export default { ...opts, }); }, + downloadFile({ + folderPath, filename, ...opts + }) { + return this._makeRequest({ + path: `/fs-content/${folderPath}/${filename}`, + responseType: "arraybuffer", + ...opts, + }); + }, }, }; diff --git a/components/egnyte/package.json b/components/egnyte/package.json index 683460347fd79..b27a5d5308371 100644 --- a/components/egnyte/package.json +++ b/components/egnyte/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/egnyte", - "version": "0.2.1", + "version": "0.2.2", "description": "Pipedream Egnyte Components", "main": "egnyte.app.mjs", "keywords": [ diff --git a/components/egnyte/sources/common/base.mjs b/components/egnyte/sources/common/base.mjs index 115064ffd2441..c1a4f0e8e54e3 100644 --- a/components/egnyte/sources/common/base.mjs +++ b/components/egnyte/sources/common/base.mjs @@ -30,6 +30,12 @@ export default { generateMeta() { throw new Error("generateMeta is not implemented"); }, + emitEvents(items) { + items.reverse().forEach((item) => { + const meta = this.generateMeta(item); + this.$emit(item, meta); + }); + }, }, async run() { const lastTs = this._getLastTs(); @@ -67,10 +73,7 @@ export default { } } - newItems.reverse().forEach((item) => { - const meta = this.generateMeta(item); - this.$emit(item, meta); - }); + await this.emitEvents(newItems); }; await processFolder(this.folderPath); diff --git a/components/egnyte/sources/new-file-in-folder/new-file-in-folder.mjs b/components/egnyte/sources/new-file-in-folder/new-file-in-folder.mjs index abb88b87f4f8d..cea9d6919e7bc 100644 --- a/components/egnyte/sources/new-file-in-folder/new-file-in-folder.mjs +++ b/components/egnyte/sources/new-file-in-folder/new-file-in-folder.mjs @@ -1,13 +1,30 @@ import common from "../common/base.mjs"; +import { Readable } from "stream"; +import { fileTypeFromBuffer } from "file-type"; export default { ...common, key: "egnyte-new-file-in-folder", name: "New File in Folder", description: "Emit new event when a file is added within the specified folder in Egnyte. [See the documentation](https://developers.egnyte.com/docs/read/File_System_Management_API_Documentation#List-File-or-Folder)", - version: "0.0.1", + version: "0.1.0", type: "source", dedupe: "unique", + props: { + ...common.props, + includeLink: { + label: "Include Link", + type: "boolean", + description: "Upload attachment to your File Stash and emit temporary download link to the file. See [the docs](https://pipedream.com/docs/connect/components/files) to learn more about working with files in Pipedream.", + default: false, + optional: true, + }, + dir: { + type: "dir", + accessMode: "write", + optional: true, + }, + }, methods: { ...common.methods, getResourceType() { @@ -20,5 +37,29 @@ export default { ts: file.uploaded, }; }, + async stashFile(item) { + const response = await this.egnyte.downloadFile({ + folderPath: this.folderPath, + filename: item.name, + }); + const buffer = Buffer.from(response); + const filepath = `${item.entry_id}/${item.name}`; + const type = await fileTypeFromBuffer(buffer); + const file = await this.dir.open(filepath).fromReadableStream( + Readable.from(buffer), + type?.mime, + buffer.length, + ); + return await file.withoutPutUrl().withGetUrl(); + }, + async emitEvents(items) { + for (const item of items) { + if (this.includeLink) { + item.file = await this.stashFile(item); + } + const meta = this.generateMeta(item); + this.$emit(item, meta); + }; + }, }, }; diff --git a/components/egnyte/sources/new-folder-added/new-folder-added.mjs b/components/egnyte/sources/new-folder-added/new-folder-added.mjs index 74b3f49a03afc..025a02358f6a2 100644 --- a/components/egnyte/sources/new-folder-added/new-folder-added.mjs +++ b/components/egnyte/sources/new-folder-added/new-folder-added.mjs @@ -5,7 +5,7 @@ export default { key: "egnyte-new-folder-added", name: "New Folder", description: "Emit new event when a folder is added within the specified folder in Egnyte. [See the documentation](https://developers.egnyte.com/docs/read/File_System_Management_API_Documentation#List-File-or-Folder).", - version: "0.0.1", + version: "0.0.2", type: "source", dedupe: "unique", methods: { diff --git a/components/gmail/package.json b/components/gmail/package.json index 4d4001aff0649..28f76de70285b 100644 --- a/components/gmail/package.json +++ b/components/gmail/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/gmail", - "version": "1.3.0", + "version": "1.3.1", "description": "Pipedream Gmail Components", "main": "gmail.app.mjs", "keywords": [ @@ -21,6 +21,7 @@ "html-to-text": "^9.0.5", "mime": "^3.0.0", "nodemailer": "^6.7.8", + "stream": "^0.0.3", "uuid": "^10.0.0" } } diff --git a/components/gmail/sources/common/polling-history.mjs b/components/gmail/sources/common/polling-history.mjs index b2c4310f6eccf..42f46834c2d52 100644 --- a/components/gmail/sources/common/polling-history.mjs +++ b/components/gmail/sources/common/polling-history.mjs @@ -187,7 +187,7 @@ export default { console.log(`Message ${id} not found: ${error.message}`); return; } - this.emitEvent(message); + await this.emitEvent(message); }, }, async run() { diff --git a/components/gmail/sources/common/polling-messages.mjs b/components/gmail/sources/common/polling-messages.mjs index e1de223b22607..a8fa0d2ed06b3 100644 --- a/components/gmail/sources/common/polling-messages.mjs +++ b/components/gmail/sources/common/polling-messages.mjs @@ -49,7 +49,7 @@ export default { let maxDate = lastDate; const messages = this.gmail.getAllMessages(messageIds); for await (const message of messages) { - this.emitEvent(message); + await this.emitEvent(message); maxDate = Math.max(maxDate, message.internalDate); } if (maxDate !== lastDate) { @@ -63,7 +63,9 @@ export default { } messages = messages.sort((a, b) => (a.internalDate - b.internalDate)); this.setLastDate(messages[messages.length - 1].internalDate); - messages.forEach((message) => this.emitEvent(message)); + for (const message of messages) { + await this.emitEvent(message); + } }, }, async run() { diff --git a/components/gmail/sources/new-attachment-received/new-attachment-received.mjs b/components/gmail/sources/new-attachment-received/new-attachment-received.mjs index 8f5891425618d..2c67a8f887235 100644 --- a/components/gmail/sources/new-attachment-received/new-attachment-received.mjs +++ b/components/gmail/sources/new-attachment-received/new-attachment-received.mjs @@ -1,13 +1,14 @@ import utils from "../../common/utils.mjs"; import gmail from "../../gmail.app.mjs"; import common from "../common/polling-messages.mjs"; +import { Readable } from "stream"; export default { ...common, key: "gmail-new-attachment-received", name: "New Attachment Received", description: "Emit new event for each attachment in a message received. This source is capped at 100 max new messages per run.", - version: "0.1.0", + version: "0.2.0", type: "source", dedupe: "unique", props: { @@ -34,6 +35,18 @@ export default { description: "Convert the payload response into a single text field. **This reduces the size of the payload and makes it easier for LLMs work with.**", default: false, }, + includeLink: { + label: "Include Link", + type: "boolean", + description: "Upload attachment to your File Stash and emit temporary download link to the file. See [the docs](https://pipedream.com/docs/connect/components/files) to learn more about working with files in Pipedream.", + default: false, + optional: true, + }, + dir: { + type: "dir", + accessMode: "write", + optional: true, + }, }, methods: { ...common.methods, @@ -56,17 +69,51 @@ export default { ts: +message.internalDate, }; }, - emitEvent(message) { + /** + * Downloads a specific attachment from a Gmail message, uploads it to this + * source's File Stash folder, and returns the upload details. + * @param {string} messageId - The ID of the message containing the attachment. + * @param {Object} attachment - The attachment metadata. + * @returns {Promise<{path: string, get_url: string, s3Key: string}>} - The + * uploaded file details. + */ + async stashAttachment(messageId, attachment) { + const attachmentId = attachment.body.attachmentId; + // Download the attachment from Gmail + const messageAttachment = await this.gmail.getAttachment({ + messageId, + attachmentId, + }); + const buffer = Buffer.from(messageAttachment.data, "base64"); + // Construct a file path unique to this attachment to avoid overwriting + // files with the same name. + const filepath = `${messageId}-${attachment.partId}/${attachment.filename}`; + // Upload the attachment to the configured directory (File Stash) so it + // can be accessed later. + const file = await this.dir.open(filepath).fromReadableStream( + Readable.from(buffer), + attachment.mimeType, + attachment.size, + ); + // Return file details and temporary download link: + // { path, get_url, s3Key, type } + return await file.withoutPutUrl().withGetUrl(); + }, + async emitEvent(message) { if (message) { const { parts: attachments = [] } = message.payload; const parsedMessage = utils.validateTextPayload(message, this.withTextPayload); - attachments.filter((attachment) => attachment.body.attachmentId).forEach((attachment) => { - this.$emit({ + for (const attachment of attachments.filter((attachment) => attachment.body.attachmentId)) { + const event = { message: parsedMessage || message, attachment, - }, this.generateMeta(attachment, message)); - }); + }; + if (this.includeLink) { + event.file = await this.stashAttachment(message.id, attachment); + } + this.$emit(event, this.generateMeta(attachment, message)); + } } }, }, diff --git a/components/gmail/sources/new-email-matching-search/new-email-matching-search.mjs b/components/gmail/sources/new-email-matching-search/new-email-matching-search.mjs index 515a022acc7a0..5477ad5692183 100644 --- a/components/gmail/sources/new-email-matching-search/new-email-matching-search.mjs +++ b/components/gmail/sources/new-email-matching-search/new-email-matching-search.mjs @@ -6,7 +6,7 @@ export default { key: "gmail-new-email-matching-search", name: "New Email Matching Search", description: "Emit new event when an email matching the search criteria is received. This source is capped at 100 max new messages per run.", - version: "0.1.0", + version: "0.1.1", type: "source", dedupe: "unique", props: { diff --git a/components/gmail/sources/new-email-received/new-email-received.mjs b/components/gmail/sources/new-email-received/new-email-received.mjs index 998ce93ecf709..bc12a99055b46 100644 --- a/components/gmail/sources/new-email-received/new-email-received.mjs +++ b/components/gmail/sources/new-email-received/new-email-received.mjs @@ -15,7 +15,7 @@ export default { name: "New Email Received", description: "Emit new event when a new email is received.", type: "source", - version: "0.3.0", + version: "0.3.1", dedupe: "unique", props: { gmail, diff --git a/components/gmail/sources/new-labeled-email/new-labeled-email.mjs b/components/gmail/sources/new-labeled-email/new-labeled-email.mjs index 37b6240056f43..3ceea3528fc1f 100644 --- a/components/gmail/sources/new-labeled-email/new-labeled-email.mjs +++ b/components/gmail/sources/new-labeled-email/new-labeled-email.mjs @@ -8,7 +8,7 @@ export default { name: "New Labeled Email", description: "Emit new event when a new email is labeled.", type: "source", - version: "0.1.0", + version: "0.1.1", dedupe: "unique", props: { gmail, diff --git a/components/gmail/sources/new-sent-email/new-sent-email.mjs b/components/gmail/sources/new-sent-email/new-sent-email.mjs index 0ece945e4f955..9bae83bbf784a 100644 --- a/components/gmail/sources/new-sent-email/new-sent-email.mjs +++ b/components/gmail/sources/new-sent-email/new-sent-email.mjs @@ -6,7 +6,7 @@ export default { key: "gmail-new-sent-email", name: "New Sent Email", description: "Emit new event for each new email sent. (Maximum of 100 events emited per execution)", - version: "0.1.0", + version: "0.1.1", type: "source", dedupe: "unique", props: { diff --git a/components/google_drive/actions/add-comment/add-comment.mjs b/components/google_drive/actions/add-comment/add-comment.mjs index 9a92eb31d0699..e566344aa6cae 100644 --- a/components/google_drive/actions/add-comment/add-comment.mjs +++ b/components/google_drive/actions/add-comment/add-comment.mjs @@ -4,7 +4,7 @@ export default { key: "google_drive-add-comment", name: "Add Comment", description: "Add an unanchored comment to a Google Doc (general feedback, no text highlighting). [See the documentation](https://developers.google.com/workspace/drive/api/reference/rest/v3/comments/create)", - version: "0.0.1", + version: "0.0.2", type: "action", props: { googleDrive, diff --git a/components/google_drive/actions/add-file-sharing-preference/add-file-sharing-preference.mjs b/components/google_drive/actions/add-file-sharing-preference/add-file-sharing-preference.mjs index 87b594287cff8..317df7bda597f 100644 --- a/components/google_drive/actions/add-file-sharing-preference/add-file-sharing-preference.mjs +++ b/components/google_drive/actions/add-file-sharing-preference/add-file-sharing-preference.mjs @@ -20,7 +20,7 @@ export default { name: "Share File or Folder", description: "Add a [sharing permission](https://support.google.com/drive/answer/7166529) to the sharing preferences of a file or folder and provide a sharing URL. [See the documentation](https://developers.google.com/drive/api/v3/reference/permissions/create)", - version: "0.2.5", + version: "0.2.6", type: "action", props: { googleDrive, diff --git a/components/google_drive/actions/copy-file/copy-file.mjs b/components/google_drive/actions/copy-file/copy-file.mjs index 09ab114fe5d6e..0481f7e943075 100644 --- a/components/google_drive/actions/copy-file/copy-file.mjs +++ b/components/google_drive/actions/copy-file/copy-file.mjs @@ -4,7 +4,7 @@ export default { key: "google_drive-copy-file", name: "Copy File", description: "Create a copy of the specified file. [See the documentation](https://developers.google.com/drive/api/v3/reference/files/copy) for more information", - version: "0.1.12", + version: "0.1.13", type: "action", props: { googleDrive, diff --git a/components/google_drive/actions/create-file-from-template/create-file-from-template.mjs b/components/google_drive/actions/create-file-from-template/create-file-from-template.mjs index bff14bcbd4c64..e47bd488aca3b 100644 --- a/components/google_drive/actions/create-file-from-template/create-file-from-template.mjs +++ b/components/google_drive/actions/create-file-from-template/create-file-from-template.mjs @@ -8,7 +8,7 @@ export default { key: "google_drive-create-file-from-template", name: "Create New File From Template", description: "Create a new Google Docs file from a template. Optionally include placeholders in the template document that will get replaced from this action. [See documentation](https://www.npmjs.com/package/google-docs-mustaches)", - version: "0.1.12", + version: "0.1.13", type: "action", props: { googleDrive, diff --git a/components/google_drive/actions/create-file-from-text/create-file-from-text.mjs b/components/google_drive/actions/create-file-from-text/create-file-from-text.mjs index b7f4b8cd8c0db..6e1fd77a870fa 100644 --- a/components/google_drive/actions/create-file-from-text/create-file-from-text.mjs +++ b/components/google_drive/actions/create-file-from-text/create-file-from-text.mjs @@ -5,7 +5,7 @@ export default { key: "google_drive-create-file-from-text", name: "Create New File From Text", description: "Create a new file from plain text. [See the documentation](https://developers.google.com/drive/api/v3/reference/files/create) for more information", - version: "0.2.5", + version: "0.2.6", type: "action", props: { googleDrive, diff --git a/components/google_drive/actions/create-folder/create-folder.mjs b/components/google_drive/actions/create-folder/create-folder.mjs index 10aba20d4c1e3..572026f5855c2 100644 --- a/components/google_drive/actions/create-folder/create-folder.mjs +++ b/components/google_drive/actions/create-folder/create-folder.mjs @@ -13,7 +13,7 @@ export default { key: "google_drive-create-folder", name: "Create Folder", description: "Create a new empty folder. [See the documentation](https://developers.google.com/drive/api/v3/reference/files/create) for more information", - version: "0.1.13", + version: "0.1.14", type: "action", props: { googleDrive, diff --git a/components/google_drive/actions/create-shared-drive/create-shared-drive.mjs b/components/google_drive/actions/create-shared-drive/create-shared-drive.mjs index e3d2846b861df..5265b5dc672c6 100644 --- a/components/google_drive/actions/create-shared-drive/create-shared-drive.mjs +++ b/components/google_drive/actions/create-shared-drive/create-shared-drive.mjs @@ -4,7 +4,7 @@ export default { key: "google_drive-create-shared-drive", name: "Create Shared Drive", description: "Create a new shared drive. [See the documentation](https://developers.google.com/drive/api/v3/reference/drives/create) for more information", - version: "0.1.13", + version: "0.1.14", type: "action", props: { googleDrive, diff --git a/components/google_drive/actions/delete-comment/delete-comment.mjs b/components/google_drive/actions/delete-comment/delete-comment.mjs index 6886bc7530f76..f748749b4ca1c 100644 --- a/components/google_drive/actions/delete-comment/delete-comment.mjs +++ b/components/google_drive/actions/delete-comment/delete-comment.mjs @@ -4,7 +4,7 @@ export default { key: "google_drive-delete-comment", name: "Delete Comment", description: "Delete a specific comment (Requires ownership or permissions). [See the documentation](https://developers.google.com/workspace/drive/api/reference/rest/v3/comments/delete)", - version: "0.0.1", + version: "0.0.2", type: "action", props: { googleDrive, diff --git a/components/google_drive/actions/delete-file/delete-file.mjs b/components/google_drive/actions/delete-file/delete-file.mjs index f86232ecc148f..c0d088b8c5a06 100644 --- a/components/google_drive/actions/delete-file/delete-file.mjs +++ b/components/google_drive/actions/delete-file/delete-file.mjs @@ -5,7 +5,7 @@ export default { name: "Delete File", description: "Permanently delete a file or folder without moving it to the trash. [See the documentation](https://developers.google.com/drive/api/v3/reference/files/delete) for more information", - version: "0.1.13", + version: "0.1.14", type: "action", props: { googleDrive, diff --git a/components/google_drive/actions/delete-shared-drive/delete-shared-drive.mjs b/components/google_drive/actions/delete-shared-drive/delete-shared-drive.mjs index 5287621689331..8f3a7f8fee516 100644 --- a/components/google_drive/actions/delete-shared-drive/delete-shared-drive.mjs +++ b/components/google_drive/actions/delete-shared-drive/delete-shared-drive.mjs @@ -4,7 +4,7 @@ export default { key: "google_drive-delete-shared-drive", name: "Delete Shared Drive", description: "Delete a shared drive without any content. [See the documentation](https://developers.google.com/drive/api/v3/reference/drives/delete) for more information", - version: "0.1.12", + version: "0.1.13", type: "action", props: { googleDrive, diff --git a/components/google_drive/actions/download-file/download-file.mjs b/components/google_drive/actions/download-file/download-file.mjs index fbc6f4f5fe5da..27a99891899b6 100644 --- a/components/google_drive/actions/download-file/download-file.mjs +++ b/components/google_drive/actions/download-file/download-file.mjs @@ -18,7 +18,7 @@ export default { key: "google_drive-download-file", name: "Download File", description: "Download a file. [See the documentation](https://developers.google.com/drive/api/v3/manage-downloads) for more information", - version: "0.1.15", + version: "0.1.16", type: "action", props: { googleDrive, diff --git a/components/google_drive/actions/find-file/find-file.mjs b/components/google_drive/actions/find-file/find-file.mjs index 0b5ed2a5af139..062e5dabdc865 100644 --- a/components/google_drive/actions/find-file/find-file.mjs +++ b/components/google_drive/actions/find-file/find-file.mjs @@ -6,7 +6,7 @@ export default { key: "google_drive-find-file", name: "Find File", description: "Search for a specific file by name. [See the documentation](https://developers.google.com/drive/api/v3/search-files) for more information", - version: "0.1.12", + version: "0.1.13", type: "action", props: { googleDrive, diff --git a/components/google_drive/actions/find-folder/find-folder.mjs b/components/google_drive/actions/find-folder/find-folder.mjs index 5179c81b2d6fd..120f6cabd38f4 100644 --- a/components/google_drive/actions/find-folder/find-folder.mjs +++ b/components/google_drive/actions/find-folder/find-folder.mjs @@ -7,7 +7,7 @@ export default { key: "google_drive-find-folder", name: "Find Folder", description: "Search for a specific folder by name. [See the documentation](https://developers.google.com/drive/api/v3/search-files) for more information", - version: "0.1.12", + version: "0.1.13", type: "action", props: { googleDrive, diff --git a/components/google_drive/actions/find-forms/find-forms.mjs b/components/google_drive/actions/find-forms/find-forms.mjs index 3d14e9e3fd62a..6d96930b82af7 100644 --- a/components/google_drive/actions/find-forms/find-forms.mjs +++ b/components/google_drive/actions/find-forms/find-forms.mjs @@ -6,7 +6,7 @@ export default { key: "google_drive-find-forms", name: "Find Forms", description: "List Google Form documents or search for a Form by name. [See the documentation](https://developers.google.com/drive/api/v3/search-files) for more information", - version: "0.0.13", + version: "0.0.14", type: "action", props: { googleDrive, diff --git a/components/google_drive/actions/find-spreadsheets/find-spreadsheets.mjs b/components/google_drive/actions/find-spreadsheets/find-spreadsheets.mjs index 922d99789ebf1..82793f8075235 100644 --- a/components/google_drive/actions/find-spreadsheets/find-spreadsheets.mjs +++ b/components/google_drive/actions/find-spreadsheets/find-spreadsheets.mjs @@ -6,7 +6,7 @@ export default { key: "google_drive-find-spreadsheets", name: "Find Spreadsheets", description: "Search for a specific spreadsheet by name. [See the documentation](https://developers.google.com/drive/api/v3/search-files) for more information", - version: "0.1.12", + version: "0.1.13", type: "action", props: { googleDrive, diff --git a/components/google_drive/actions/get-file-by-id/get-file-by-id.mjs b/components/google_drive/actions/get-file-by-id/get-file-by-id.mjs index c04a2c94c3fae..71d92cb70f743 100644 --- a/components/google_drive/actions/get-file-by-id/get-file-by-id.mjs +++ b/components/google_drive/actions/get-file-by-id/get-file-by-id.mjs @@ -5,7 +5,7 @@ export default { key: "google_drive-get-file-by-id", name: "Get File By ID", description: "Get info on a specific file. [See the documentation](https://developers.google.com/drive/api/reference/rest/v3/files/get) for more information", - version: "0.0.9", + version: "0.0.10", type: "action", props: { googleDrive, diff --git a/components/google_drive/actions/get-folder-id-for-path/get-folder-id-for-path.mjs b/components/google_drive/actions/get-folder-id-for-path/get-folder-id-for-path.mjs index 6dc3c06f89a00..76564070ad1aa 100644 --- a/components/google_drive/actions/get-folder-id-for-path/get-folder-id-for-path.mjs +++ b/components/google_drive/actions/get-folder-id-for-path/get-folder-id-for-path.mjs @@ -12,7 +12,7 @@ export default { key: "google_drive-get-folder-id-for-path", name: "Get Folder ID for a Path", description: "Retrieve a folderId for a path. [See the documentation](https://developers.google.com/drive/api/v3/search-files) for more information", - version: "0.1.14", + version: "0.1.15", type: "action", props: { googleDrive, diff --git a/components/google_drive/actions/get-shared-drive/get-shared-drive.mjs b/components/google_drive/actions/get-shared-drive/get-shared-drive.mjs index 90c5a2f0fe421..2f2a89602e0d4 100644 --- a/components/google_drive/actions/get-shared-drive/get-shared-drive.mjs +++ b/components/google_drive/actions/get-shared-drive/get-shared-drive.mjs @@ -4,7 +4,7 @@ export default { key: "google_drive-get-shared-drive", name: "Get Shared Drive", description: "Get metadata for one or all shared drives. [See the documentation](https://developers.google.com/drive/api/v3/reference/drives/get) for more information", - version: "0.1.12", + version: "0.1.13", type: "action", props: { googleDrive, diff --git a/components/google_drive/actions/list-access-proposals/list-access-proposals.mjs b/components/google_drive/actions/list-access-proposals/list-access-proposals.mjs index 904116c914226..af4f730e852ec 100644 --- a/components/google_drive/actions/list-access-proposals/list-access-proposals.mjs +++ b/components/google_drive/actions/list-access-proposals/list-access-proposals.mjs @@ -4,7 +4,7 @@ export default { key: "google_drive-list-access-proposals", name: "List Access Proposals", description: "List access proposals for a file or folder. [See the documentation](https://developers.google.com/workspace/drive/api/reference/rest/v3/accessproposals/list)", - version: "0.0.5", + version: "0.0.6", type: "action", props: { googleDrive, diff --git a/components/google_drive/actions/list-comments/list-comments.mjs b/components/google_drive/actions/list-comments/list-comments.mjs index 9190fdee7fa06..cef84ddee8f7a 100644 --- a/components/google_drive/actions/list-comments/list-comments.mjs +++ b/components/google_drive/actions/list-comments/list-comments.mjs @@ -4,7 +4,7 @@ export default { key: "google_drive-list-comments", name: "List Comments", description: "List all comments on a file. [See the documentation](https://developers.google.com/workspace/drive/api/reference/rest/v3/comments/list)", - version: "0.0.1", + version: "0.0.2", type: "action", props: { googleDrive, diff --git a/components/google_drive/actions/list-files/list-files.mjs b/components/google_drive/actions/list-files/list-files.mjs index d85753d6f7633..4f66ccaabb554 100644 --- a/components/google_drive/actions/list-files/list-files.mjs +++ b/components/google_drive/actions/list-files/list-files.mjs @@ -5,7 +5,7 @@ export default { key: "google_drive-list-files", name: "List Files", description: "List files from a specific folder. [See the documentation](https://developers.google.com/drive/api/v3/reference/files/list) for more information", - version: "0.1.16", + version: "0.1.17", type: "action", props: { googleDrive, diff --git a/components/google_drive/actions/move-file-to-trash/move-file-to-trash.mjs b/components/google_drive/actions/move-file-to-trash/move-file-to-trash.mjs index dcee3810f1eee..a9112365ac301 100644 --- a/components/google_drive/actions/move-file-to-trash/move-file-to-trash.mjs +++ b/components/google_drive/actions/move-file-to-trash/move-file-to-trash.mjs @@ -5,7 +5,7 @@ export default { key: "google_drive-move-file-to-trash", name: "Move File to Trash", description: "Move a file or folder to trash. [See the documentation](https://developers.google.com/drive/api/v3/reference/files/update) for more information", - version: "0.1.12", + version: "0.1.13", type: "action", props: { googleDrive, diff --git a/components/google_drive/actions/move-file/move-file.mjs b/components/google_drive/actions/move-file/move-file.mjs index f7edbf0715e06..fd9f648dbefac 100644 --- a/components/google_drive/actions/move-file/move-file.mjs +++ b/components/google_drive/actions/move-file/move-file.mjs @@ -4,7 +4,7 @@ export default { key: "google_drive-move-file", name: "Move File", description: "Move a file from one folder to another. [See the documentation](https://developers.google.com/drive/api/v3/reference/files/update) for more information", - version: "0.1.12", + version: "0.1.13", type: "action", props: { googleDrive, diff --git a/components/google_drive/actions/reply-to-comment/reply-to-comment.mjs b/components/google_drive/actions/reply-to-comment/reply-to-comment.mjs index d77e58e9a3252..0495be280de59 100644 --- a/components/google_drive/actions/reply-to-comment/reply-to-comment.mjs +++ b/components/google_drive/actions/reply-to-comment/reply-to-comment.mjs @@ -4,7 +4,7 @@ export default { key: "google_drive-reply-to-comment", name: "Reply to Comment", description: "Add a reply to an existing comment. [See the documentation](https://developers.google.com/workspace/drive/api/reference/rest/v3/replies/create)", - version: "0.0.1", + version: "0.0.2", type: "action", props: { googleDrive, diff --git a/components/google_drive/actions/resolve-access-proposal/resolve-access-proposal.mjs b/components/google_drive/actions/resolve-access-proposal/resolve-access-proposal.mjs index 9b1637864ba56..a12a5cbac394a 100644 --- a/components/google_drive/actions/resolve-access-proposal/resolve-access-proposal.mjs +++ b/components/google_drive/actions/resolve-access-proposal/resolve-access-proposal.mjs @@ -5,7 +5,7 @@ export default { key: "google_drive-resolve-access-proposal", name: "Resolve Access Proposals", description: "Accept or deny a request for access to a file or folder in Google Drive. [See the documentation](https://developers.google.com/workspace/drive/api/reference/rest/v3/accessproposals/resolve)", - version: "0.0.5", + version: "0.0.6", type: "action", props: { googleDrive, diff --git a/components/google_drive/actions/resolve-comment/resolve-comment.mjs b/components/google_drive/actions/resolve-comment/resolve-comment.mjs index f60991909e663..b78ae18c34449 100644 --- a/components/google_drive/actions/resolve-comment/resolve-comment.mjs +++ b/components/google_drive/actions/resolve-comment/resolve-comment.mjs @@ -4,7 +4,7 @@ export default { key: "google_drive-resolve-comment", name: "Resolve Comment", description: "Mark a comment as resolved. [See the documentation](https://developers.google.com/workspace/drive/api/reference/rest/v3/comments/update)", - version: "0.0.1", + version: "0.0.2", type: "action", props: { googleDrive, diff --git a/components/google_drive/actions/search-shared-drives/search-shared-drives.mjs b/components/google_drive/actions/search-shared-drives/search-shared-drives.mjs index 9ca83de502aa9..5d9f421049654 100644 --- a/components/google_drive/actions/search-shared-drives/search-shared-drives.mjs +++ b/components/google_drive/actions/search-shared-drives/search-shared-drives.mjs @@ -4,7 +4,7 @@ export default { key: "google_drive-search-shared-drives", name: "Search for Shared Drives", description: "Search for shared drives with query options. [See the documentation](https://developers.google.com/drive/api/v3/search-shareddrives) for more information", - version: "0.1.13", + version: "0.1.14", type: "action", props: { googleDrive, diff --git a/components/google_drive/actions/update-file/update-file.mjs b/components/google_drive/actions/update-file/update-file.mjs index 9521069573bf2..6673e0b7e3156 100644 --- a/components/google_drive/actions/update-file/update-file.mjs +++ b/components/google_drive/actions/update-file/update-file.mjs @@ -6,7 +6,7 @@ export default { key: "google_drive-update-file", name: "Update File", description: "Update a file's metadata and/or content. [See the documentation](https://developers.google.com/drive/api/v3/reference/files/update) for more information", - version: "2.0.4", + version: "2.0.5", type: "action", props: { googleDrive, diff --git a/components/google_drive/actions/update-shared-drive/update-shared-drive.mjs b/components/google_drive/actions/update-shared-drive/update-shared-drive.mjs index b57b37b266e1c..ba7cd0d145fff 100644 --- a/components/google_drive/actions/update-shared-drive/update-shared-drive.mjs +++ b/components/google_drive/actions/update-shared-drive/update-shared-drive.mjs @@ -4,7 +4,7 @@ export default { key: "google_drive-update-shared-drive", name: "Update Shared Drive", description: "Update an existing shared drive. [See the documentation](https://developers.google.com/drive/api/v3/reference/drives/update) for more information", - version: "0.1.12", + version: "0.1.13", type: "action", props: { googleDrive, diff --git a/components/google_drive/actions/upload-file/upload-file.mjs b/components/google_drive/actions/upload-file/upload-file.mjs index c7080ecd10ab7..0bc64a03b814e 100644 --- a/components/google_drive/actions/upload-file/upload-file.mjs +++ b/components/google_drive/actions/upload-file/upload-file.mjs @@ -13,7 +13,7 @@ export default { key: "google_drive-upload-file", name: "Upload File", description: "Upload a file to Google Drive. [See the documentation](https://developers.google.com/drive/api/v3/manage-uploads) for more information", - version: "2.0.5", + version: "2.0.6", type: "action", props: { googleDrive, diff --git a/components/google_drive/common/utils.mjs b/components/google_drive/common/utils.mjs index d6d9390001ade..8f97a5c2c3ffe 100644 --- a/components/google_drive/common/utils.mjs +++ b/components/google_drive/common/utils.mjs @@ -3,7 +3,9 @@ import { MY_DRIVE_VALUE, LEGACY_MY_DRIVE_VALUE, MAX_FILE_OPTION_PATH_SEGMENTS, + GOOGLE_DRIVE_MIME_TYPE_PREFIX, } from "../common/constants.mjs"; +import { Readable } from "stream"; /** * Returns whether the specified drive ID corresponds to the authenticated @@ -264,6 +266,43 @@ function parseObjectEntries(value = {}) { ); } +async function stashFile(item, googleDrive, dir) { + const fileMetadata = await googleDrive.getFile(item.id, { + fields: "name,mimeType", + }); + let mimeType = fileMetadata.mimeType; + const isWorkspaceDocument = mimeType.includes(GOOGLE_DRIVE_MIME_TYPE_PREFIX); + if (isWorkspaceDocument) { + mimeType = "application/pdf"; + } + const response = isWorkspaceDocument + ? await googleDrive.downloadWorkspaceFile(item.id, { + mimeType, + }) + : await googleDrive.getFile(item.id, { + alt: "media", + }); + // Convert stream to buffer + const chunks = []; + for await (const chunk of response) { + chunks.push(chunk); + } + const buffer = Buffer.concat(chunks); + // Construct a file path unique to this attachment to avoid overwriting + // files with the same name. + const filepath = `${item.id}/${item.name}`; + // Upload the attachment to the configured directory (File Stash) so it + // can be accessed later. + const file = await dir.open(filepath).fromReadableStream( + Readable.from(buffer), + mimeType, + buffer.length, + ); + // Return file details and temporary download link: + // { path, get_url, s3Key, type } + return await file.withoutPutUrl().withGetUrl(); +} + export { MY_DRIVE_VALUE, isMyDrive, @@ -276,4 +315,5 @@ export { streamToBuffer, byteToMB, parseObjectEntries, + stashFile, }; diff --git a/components/google_drive/package.json b/components/google_drive/package.json index b0461679f788b..7a751e83c3876 100644 --- a/components/google_drive/package.json +++ b/components/google_drive/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/google_drive", - "version": "1.0.6", + "version": "1.0.7", "description": "Pipedream Google_drive Components", "main": "google_drive.app.mjs", "keywords": [ diff --git a/components/google_drive/sources/changes-to-specific-files-shared-drive/changes-to-specific-files-shared-drive.mjs b/components/google_drive/sources/changes-to-specific-files-shared-drive/changes-to-specific-files-shared-drive.mjs index 51e23263a238e..deb811da157ef 100644 --- a/components/google_drive/sources/changes-to-specific-files-shared-drive/changes-to-specific-files-shared-drive.mjs +++ b/components/google_drive/sources/changes-to-specific-files-shared-drive/changes-to-specific-files-shared-drive.mjs @@ -16,6 +16,7 @@ import { GOOGLE_DRIVE_NOTIFICATION_UPDATE, } from "../../common/constants.mjs"; import commonDedupeChanges from "../common-dedupe-changes.mjs"; +import { stashFile } from "../../common/utils.mjs"; /** * This source uses the Google Drive API's @@ -27,7 +28,7 @@ export default { key: "google_drive-changes-to-specific-files-shared-drive", name: "Changes to Specific Files (Shared Drive)", description: "Watches for changes to specific files in a shared drive, emitting an event when a change is made to one of those files", - version: "0.2.9", + version: "0.3.0", type: "source", // Dedupe events based on the "x-goog-message-number" header for the target channel: // https://developers.google.com/drive/api/v3/push#making-watch-requests @@ -43,6 +44,18 @@ export default { return this.googleDrive.listFilesOptions(nextPageToken, this.getListFilesOpts()); }, }, + includeLink: { + label: "Include Link", + type: "boolean", + description: "Upload file to your File Stash and emit temporary download link to the file. Google Workspace documents will be converted to PDF. See [the docs](https://pipedream.com/docs/connect/components/files) to learn more about working with files in Pipedream.", + default: false, + optional: true, + }, + dir: { + type: "dir", + accessMode: "write", + optional: true, + }, ...commonDedupeChanges.props, }, hooks: { @@ -59,7 +72,7 @@ export default { const { files } = await this.googleDrive.listFilesInPage(null, args); - this.processChanges(files); + await this.processChanges(files); }, ...common.hooks, }, @@ -109,8 +122,11 @@ export default { }, }; }, - processChange(file, headers) { + async processChange(file, headers) { const changes = this.getChanges(headers); + if (this.includeLink) { + file.file = await stashFile(file, this.googleDrive, this.dir); + } const eventToEmit = { file, ...changes, @@ -118,7 +134,7 @@ export default { const meta = this.generateMeta(file, headers); this.$emit(eventToEmit, meta); }, - processChanges(changedFiles, headers) { + async processChanges(changedFiles, headers) { console.log(`Processing ${changedFiles.length} changed files`); console.log(`Changed files: ${JSON.stringify(changedFiles, null, 2)}!!!`); console.log(`Files: ${this.files}!!!`); @@ -129,7 +145,7 @@ export default { console.log(`Skipping event for irrelevant file ${file.id}`); continue; } - this.processChange(file, headers); + await this.processChange(file, headers); } }, }, diff --git a/components/google_drive/sources/changes-to-specific-files/changes-to-specific-files.mjs b/components/google_drive/sources/changes-to-specific-files/changes-to-specific-files.mjs index f078733ebb816..dc9393736716d 100644 --- a/components/google_drive/sources/changes-to-specific-files/changes-to-specific-files.mjs +++ b/components/google_drive/sources/changes-to-specific-files/changes-to-specific-files.mjs @@ -15,7 +15,7 @@ export default { key: "google_drive-changes-to-specific-files", name: "Changes to Specific Files", description: "Watches for changes to specific files, emitting an event when a change is made to one of those files. To watch for changes to [shared drive](https://support.google.com/a/users/answer/9310351) files, use the **Changes to Specific Files (Shared Drive)** source instead.", - version: "0.2.9", + version: "0.3.0", type: "source", // Dedupe events based on the "x-goog-message-number" header for the target channel: // https://developers.google.com/drive/api/v3/push#making-watch-requests @@ -35,6 +35,18 @@ export default { "updateTypes", ], }, + includeLink: { + label: "Include Link", + type: "boolean", + description: "Upload file to your File Stash and emit temporary download link to the file. Google Workspace documents will be converted to PDF. See [the docs](https://pipedream.com/docs/connect/components/files) to learn more about working with files in Pipedream.", + default: false, + optional: true, + }, + dir: { + type: "dir", + accessMode: "write", + optional: true, + }, }, hooks: { ...changesToSpecificFiles.hooks, @@ -226,7 +238,7 @@ export default { file, ]); if (checkedFile) { - this.processChange(file, headers); + await this.processChange(file, headers); } }, sampleEmit, diff --git a/components/google_drive/sources/new-access-proposal/new-access-proposal.mjs b/components/google_drive/sources/new-access-proposal/new-access-proposal.mjs index 85b77daef3747..c7e7e0e48334e 100644 --- a/components/google_drive/sources/new-access-proposal/new-access-proposal.mjs +++ b/components/google_drive/sources/new-access-proposal/new-access-proposal.mjs @@ -6,7 +6,7 @@ export default { key: "google_drive-new-access-proposal", name: "New Access Proposal", description: "Emit new event when a new access proposal is requested in Google Drive", - version: "0.0.5", + version: "0.0.6", type: "source", dedupe: "unique", props: { diff --git a/components/google_drive/sources/new-files-instant/new-files-instant.mjs b/components/google_drive/sources/new-files-instant/new-files-instant.mjs index d038c3b03b0b6..542f1d210cc9a 100644 --- a/components/google_drive/sources/new-files-instant/new-files-instant.mjs +++ b/components/google_drive/sources/new-files-instant/new-files-instant.mjs @@ -3,6 +3,7 @@ import { GOOGLE_DRIVE_NOTIFICATION_CHANGE, } from "../../common/constants.mjs"; import common from "../common-webhook.mjs"; +import { stashFile } from "../../common/utils.mjs"; import sampleEmit from "./test-event.mjs"; export default { @@ -10,7 +11,7 @@ export default { key: "google_drive-new-files-instant", name: "New Files (Instant)", description: "Emit new event when a new file is added in your linked Google Drive", - version: "0.1.17", + version: "0.2.0", type: "source", dedupe: "unique", props: { @@ -46,6 +47,18 @@ export default { return this.googleDrive.listFilesOptions(nextPageToken, opts); }, }, + includeLink: { + label: "Include Link", + type: "boolean", + description: "Upload file to your File Stash and emit temporary download link to the file. Google Workspace documents will be converted to PDF. See [the docs](https://pipedream.com/docs/connect/components/files) to learn more about working with files in Pipedream.", + default: false, + optional: true, + }, + dir: { + type: "dir", + accessMode: "write", + optional: true, + }, }, hooks: { async deploy() { @@ -62,7 +75,7 @@ export default { const { files } = await this.googleDrive.listFilesInPage(null, args); - this.emitFiles(files); + await this.emitFiles(files); }, ...common.hooks, async activate() { @@ -91,11 +104,14 @@ export default { GOOGLE_DRIVE_NOTIFICATION_CHANGE, ]; }, - emitFiles(files) { + async emitFiles(files) { for (const file of files) { if (!this.shouldProcess(file)) { continue; } + if (this.includeLink) { + file.file = await stashFile(file, this.googleDrive, this.dir); + } this.$emit(file, { summary: `New File: ${file.name}`, id: file.id, @@ -119,7 +135,7 @@ export default { return; } - this.emitFiles(files); + await this.emitFiles(files); this._setLastFileCreatedTime(Date.parse(files[0].createdTime)); }, diff --git a/components/google_drive/sources/new-files-shared-drive/new-files-shared-drive.mjs b/components/google_drive/sources/new-files-shared-drive/new-files-shared-drive.mjs index 10922d600acfd..726892a5590d4 100644 --- a/components/google_drive/sources/new-files-shared-drive/new-files-shared-drive.mjs +++ b/components/google_drive/sources/new-files-shared-drive/new-files-shared-drive.mjs @@ -7,7 +7,7 @@ export default { key: "google_drive-new-files-shared-drive", name: "New Files (Shared Drive)", description: "Emit new event when a new file is added in your shared Google Drive", - version: "0.0.6", + version: "0.1.0", type: "source", dedupe: "unique", props: { @@ -30,6 +30,18 @@ export default { optional: false, }, folders: sourceComponent.props.folders, + includeLink: { + label: "Include Link", + type: "boolean", + description: "Upload file to your File Stash and emit temporary download link to the file. Google Workspace documents will be converted to PDF. See [the docs](https://pipedream.com/docs/connect/components/files) to learn more about working with files in Pipedream.", + default: false, + optional: true, + }, + dir: { + type: "dir", + accessMode: "write", + optional: true, + }, }, hooks: { async deploy() { diff --git a/components/google_drive/sources/new-or-modified-comments/new-or-modified-comments.mjs b/components/google_drive/sources/new-or-modified-comments/new-or-modified-comments.mjs index 54f8508d73917..1a7b44748bf36 100644 --- a/components/google_drive/sources/new-or-modified-comments/new-or-modified-comments.mjs +++ b/components/google_drive/sources/new-or-modified-comments/new-or-modified-comments.mjs @@ -17,7 +17,7 @@ export default { name: "New or Modified Comments (Instant)", description: "Emit new event when a comment is created or modified in the selected file", - version: "1.0.8", + version: "1.0.9", type: "source", // Dedupe events based on the "x-goog-message-number" header for the target channel: // https://developers.google.com/drive/api/v3/push#making-watch-requests diff --git a/components/google_drive/sources/new-or-modified-files/new-or-modified-files.mjs b/components/google_drive/sources/new-or-modified-files/new-or-modified-files.mjs index 0a198c18d4dc5..2db84962a6505 100644 --- a/components/google_drive/sources/new-or-modified-files/new-or-modified-files.mjs +++ b/components/google_drive/sources/new-or-modified-files/new-or-modified-files.mjs @@ -15,6 +15,7 @@ import { } from "../../common/constants.mjs"; import commonDedupeChanges from "../common-dedupe-changes.mjs"; import common from "../common-webhook.mjs"; +import { stashFile } from "../../common/utils.mjs"; import sampleEmit from "./test-event.mjs"; const { googleDrive } = common.props; @@ -24,7 +25,7 @@ export default { key: "google_drive-new-or-modified-files", name: "New or Modified Files (Instant)", description: "Emit new event when a file in the selected Drive is created, modified or trashed.", - version: "0.3.9", + version: "0.4.0", type: "source", // Dedupe events based on the "x-goog-message-number" header for the target channel: // https://developers.google.com/drive/api/v3/push#making-watch-requests @@ -61,6 +62,18 @@ export default { "watchForPropertiesChanges", ], }, + includeLink: { + label: "Include Link", + type: "boolean", + description: "Upload file to your File Stash and emit temporary download link to the file. Google Workspace documents will be converted to PDF. See [the docs](https://pipedream.com/docs/connect/components/files) to learn more about working with files in Pipedream.", + default: false, + optional: true, + }, + dir: { + type: "dir", + accessMode: "write", + optional: true, + }, ...commonDedupeChanges.props, }, hooks: { @@ -152,6 +165,9 @@ export default { file, ...changes, }; + if (this.includeLink) { + eventToEmit.fileURL = await stashFile(file, this.googleDrive, this.dir); + } const meta = this.generateMeta(file, headers); this.$emit(eventToEmit, meta); } diff --git a/components/google_drive/sources/new-or-modified-files/test-event.mjs b/components/google_drive/sources/new-or-modified-files/test-event.mjs index 51ff04cc5a4d2..711fc1c497b4e 100644 --- a/components/google_drive/sources/new-or-modified-files/test-event.mjs +++ b/components/google_drive/sources/new-or-modified-files/test-event.mjs @@ -1 +1 @@ -export default JSON.parse("{\n \"file\": {\n \"kind\": \"drive#file\",\n \"copyRequiresWriterPermission\": false,\n \"writersCanShare\": true,\n \"viewedByMe\": true,\n \"mimeType\": \"application/vnd.google-apps.spreadsheet\",\n \"exportLinks\": {\n \"application/x-vnd.oasis.opendocument.spreadsheet\": \"https://docs.google.com/spreadsheets/export?id=1LmXTIQ0wqKP7T3-l9r127MaTXn3pVbTmw4&exportFormat=ods\",\n \"text/tab-separated-values\": \"https://docs.google.com/spreadsheets/export?id=1LmXTIQ0wqKP7T3-l9r127MaTXnViTOo&exportFormat=tsv\",\n \"application/pdf\": \"https://docs.google.com/spreadsheets/export?id=1LmXTIQ0wqKP7T3-l9r127MaBViTOo&exportFormat=pdf\",\n \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\": \"https://docs.google.com/spreadsheets/export?id=1LmXTIQ0wqKP7T3-l9r127MaTXn3pVbOo&exportFormat=xlsx\",\n \"text/csv\": \"https://docs.google.com/spreadsheets/export?id=1LmXTIQ0wqKP7T3-l9r127MaTXn3pVbBViTOo&exportFormat=csv\",\n \"application/zip\": \"https://docs.google.com/spreadsheets/export?id=1LmXTIQ0wqKP7T3-VbTmw4Pt2BViTOo&exportFormat=zip\",\n \"application/vnd.oasis.opendocument.spreadsheet\": \"https://docs.google.com/spreadsheets/export?id=1LmXTIQ0wqKP7T3-l9r127MaTXn3pVbViTOo&exportFormat=ods\"\n },\n \"parents\": [\n \"0ANs73yKKVA\"\n ],\n \"thumbnailLink\": \"https://docs.google.com/feeds/vt?gd=true&id=1LmXTIQ0wqKP7T3-l9r127MaTXn3pVbTmw4&v=12&s=AMedNnoAAAAAZKWjrEqscucFpYCyRCJqnd0wtBiDtXYh&sz=s220\",\n \"iconLink\": \"https://drive-thirdparty.googleusercontent.com/16/type/application/vnd.google-apps.spreadsheet\",\n \"shared\": false,\n \"lastModifyingUser\": {\n \"displayName\": \"John Doe\",\n \"kind\": \"drive#user\",\n \"me\": true,\n \"permissionId\": \"077423361841532483\",\n \"emailAddress\": \"john@doe.com\",\n \"photoLink\": \"https://lh3.googleusercontent.com/a/default-user=s64\"\n },\n \"owners\": [\n {\n \"displayName\": \"John Doe\",\n \"kind\": \"drive#user\",\n \"me\": true,\n \"permissionId\": \"07742336189483\",\n \"emailAddress\": \"john@doe.com\",\n \"photoLink\": \"https://lh3.googleusercontent.com/a/default-user=s64\"\n }\n ],\n \"webViewLink\": \"https://docs.google.com/spreadsheets/d/1LmXTIQ0wqKP7T3-l9r127MaTXn3pVbTmwTOo/edit?usp=drivesdk\",\n \"size\": \"1024\",\n \"viewersCanCopyContent\": true,\n \"permissions\": [\n {\n \"id\": \"07742336184153259483\",\n \"displayName\": \"John Doe\",\n \"type\": \"user\",\n \"kind\": \"drive#permission\",\n \"photoLink\": \"https://lh3.googleusercontent.com/a/default-user=s64\",\n \"emailAddress\": \"john@doe.com\",\n \"role\": \"owner\",\n \"deleted\": false,\n \"pendingOwner\": false\n }\n ],\n \"hasThumbnail\": true,\n \"spaces\": [\n \"drive\"\n ],\n \"id\": \"1LmXTIQ0wqKP7T3-l9r127Maw4Pt2BViTOo\",\n \"name\": \"Pipedream 2213\",\n \"starred\": false,\n \"trashed\": false,\n \"explicitlyTrashed\": false,\n \"createdTime\": \"2023-02-06T15:13:33.023Z\",\n \"modifiedTime\": \"2023-06-28T12:52:54.570Z\",\n \"modifiedByMeTime\": \"2023-06-28T12:52:54.570Z\",\n \"viewedByMeTime\": \"2023-06-29T06:30:58.441Z\",\n \"quotaBytesUsed\": \"1024\",\n \"version\": \"53\",\n \"ownedByMe\": true,\n \"isAppAuthorized\": false,\n \"capabilities\": {\n \"canChangeViewersCanCopyContent\": true,\n \"canEdit\": true,\n \"canCopy\": true,\n \"canComment\": true,\n \"canAddChildren\": false,\n \"canDelete\": true,\n \"canDownload\": true,\n \"canListChildren\": false,\n \"canRemoveChildren\": false,\n \"canRename\": true,\n \"canTrash\": true,\n \"canReadRevisions\": true,\n \"canChangeCopyRequiresWriterPermission\": true,\n \"canMoveItemIntoTeamDrive\": true,\n \"canUntrash\": true,\n \"canModifyContent\": true,\n \"canMoveItemOutOfDrive\": true,\n \"canAddMyDriveParent\": false,\n \"canRemoveMyDriveParent\": true,\n \"canMoveItemWithinDrive\": true,\n \"canShare\": true,\n \"canMoveChildrenWithinDrive\": false,\n \"canModifyContentRestriction\": true,\n \"canChangeSecurityUpdateEnabled\": false,\n \"canAcceptOwnership\": false,\n \"canReadLabels\": true,\n \"canModifyLabels\": true\n },\n \"thumbnailVersion\": \"12\",\n \"modifiedByMe\": true,\n \"permissionIds\": [\n \"07742336184153259483\"\n ],\n \"linkShareMetadata\": {\n \"securityUpdateEligible\": false,\n \"securityUpdateEnabled\": true\n }\n }\n}") \ No newline at end of file +export default JSON.parse("{\n \"file\": {\n \"kind\": \"drive#file\",\n \"copyRequiresWriterPermission\": false,\n \"writersCanShare\": true,\n \"viewedByMe\": true,\n \"mimeType\": \"application/vnd.google-apps.spreadsheet\",\n \"exportLinks\": {\n \"application/x-vnd.oasis.opendocument.spreadsheet\": \"https://docs.google.com/spreadsheets/export?id=1LmXTIQ0wqKP7T3-l9r127MaTXn3pVbTmw4&exportFormat=ods\",\n \"text/tab-separated-values\": \"https://docs.google.com/spreadsheets/export?id=1LmXTIQ0wqKP7T3-l9r127MaTXnViTOo&exportFormat=tsv\",\n \"application/pdf\": \"https://docs.google.com/spreadsheets/export?id=1LmXTIQ0wqKP7T3-l9r127MaBViTOo&exportFormat=pdf\",\n \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\": \"https://docs.google.com/spreadsheets/export?id=1LmXTIQ0wqKP7T3-l9r127MaTXn3pVbOo&exportFormat=xlsx\",\n \"text/csv\": \"https://docs.google.com/spreadsheets/export?id=1LmXTIQ0wqKP7T3-l9r127MaTXn3pVbBViTOo&exportFormat=csv\",\n \"application/zip\": \"https://docs.google.com/spreadsheets/export?id=1LmXTIQ0wqKP7T3-VbTmw4Pt2BViTOo&exportFormat=zip\",\n \"application/vnd.oasis.opendocument.spreadsheet\": \"https://docs.google.com/spreadsheets/export?id=1LmXTIQ0wqKP7T3-l9r127MaTXn3pVbViTOo&exportFormat=ods\"\n },\n \"parents\": [\n \"0ANs73yKKVA\"\n ],\n \"thumbnailLink\": \"https://docs.google.com/feeds/vt?gd=true&id=1LmXTIQ0wqKP7T3-l9r127MaTXn3pVbTmw4&v=12&s=AMedNnoAAAAAZKWjrEqscucFpYCyRCJqnd0wtBiDtXYh&sz=s220\",\n \"iconLink\": \"https://drive-thirdparty.googleusercontent.com/16/type/application/vnd.google-apps.spreadsheet\",\n \"shared\": false,\n \"lastModifyingUser\": {\n \"displayName\": \"John Doe\",\n \"kind\": \"drive#user\",\n \"me\": true,\n \"permissionId\": \"077423361841532483\",\n \"emailAddress\": \"john@doe.com\",\n \"photoLink\": \"https://lh3.googleusercontent.com/a/default-user=s64\"\n },\n \"owners\": [\n {\n \"displayName\": \"John Doe\",\n \"kind\": \"drive#user\",\n \"me\": true,\n \"permissionId\": \"07742336189483\",\n \"emailAddress\": \"john@doe.com\",\n \"photoLink\": \"https://lh3.googleusercontent.com/a/default-user=s64\"\n }\n ],\n \"webViewLink\": \"https://docs.google.com/spreadsheets/d/1LmXTIQ0wqKP7T3-l9r127MaTXn3pVbTmwTOo/edit?usp=drivesdk\",\n \"size\": \"1024\",\n \"viewersCanCopyContent\": true,\n \"permissions\": [\n {\n \"id\": \"07742336184153259483\",\n \"displayName\": \"John Doe\",\n \"type\": \"user\",\n \"kind\": \"drive#permission\",\n \"photoLink\": \"https://lh3.googleusercontent.com/a/default-user=s64\",\n \"emailAddress\": \"john@doe.com\",\n \"role\": \"owner\",\n \"deleted\": false,\n \"pendingOwner\": false\n }\n ],\n \"hasThumbnail\": true,\n \"spaces\": [\n \"drive\"\n ],\n \"id\": \"1LmXTIQ0wqKP7T3-l9r127Maw4Pt2BViTOo\",\n \"name\": \"Pipedream 2213\",\n \"starred\": false,\n \"trashed\": false,\n \"explicitlyTrashed\": false,\n \"createdTime\": \"2023-02-06T15:13:33.023Z\",\n \"modifiedTime\": \"2023-06-28T12:52:54.570Z\",\n \"modifiedByMeTime\": \"2023-06-28T12:52:54.570Z\",\n \"viewedByMeTime\": \"2023-06-29T06:30:58.441Z\",\n \"quotaBytesUsed\": \"1024\",\n \"version\": \"53\",\n \"ownedByMe\": true,\n \"isAppAuthorized\": false,\n \"capabilities\": {\n \"canChangeViewersCanCopyContent\": true,\n \"canEdit\": true,\n \"canCopy\": true,\n \"canComment\": true,\n \"canAddChildren\": false,\n \"canDelete\": true,\n \"canDownload\": true,\n \"canListChildren\": false,\n \"canRemoveChildren\": false,\n \"canRename\": true,\n \"canTrash\": true,\n \"canReadRevisions\": true,\n \"canChangeCopyRequiresWriterPermission\": true,\n \"canMoveItemIntoTeamDrive\": true,\n \"canUntrash\": true,\n \"canModifyContent\": true,\n \"canMoveItemOutOfDrive\": true,\n \"canAddMyDriveParent\": false,\n \"canRemoveMyDriveParent\": true,\n \"canMoveItemWithinDrive\": true,\n \"canShare\": true,\n \"canMoveChildrenWithinDrive\": false,\n \"canModifyContentRestriction\": true,\n \"canChangeSecurityUpdateEnabled\": false,\n \"canAcceptOwnership\": false,\n \"canReadLabels\": true,\n \"canModifyLabels\": true\n },\n \"thumbnailVersion\": \"12\",\n \"modifiedByMe\": true,\n \"permissionIds\": [\n \"07742336184153259483\"\n ],\n \"linkShareMetadata\": {\n \"securityUpdateEligible\": false,\n \"securityUpdateEnabled\": true\n }\n }\n}"); diff --git a/components/google_drive/sources/new-or-modified-folders/new-or-modified-folders.mjs b/components/google_drive/sources/new-or-modified-folders/new-or-modified-folders.mjs index 2b484e381144a..7d11ba872f060 100644 --- a/components/google_drive/sources/new-or-modified-folders/new-or-modified-folders.mjs +++ b/components/google_drive/sources/new-or-modified-folders/new-or-modified-folders.mjs @@ -20,7 +20,7 @@ export default { key: "google_drive-new-or-modified-folders", name: "New or Modified Folders (Instant)", description: "Emit new event when a folder is created or modified in the selected Drive", - version: "0.2.1", + version: "0.2.2", type: "source", // Dedupe events based on the "x-goog-message-number" header for the target channel: // https://developers.google.com/drive/api/v3/push#making-watch-requests diff --git a/components/google_drive/sources/new-shared-drive/new-shared-drive.mjs b/components/google_drive/sources/new-shared-drive/new-shared-drive.mjs index 0a5585c87c1c8..14506a05ecd72 100644 --- a/components/google_drive/sources/new-shared-drive/new-shared-drive.mjs +++ b/components/google_drive/sources/new-shared-drive/new-shared-drive.mjs @@ -5,7 +5,7 @@ export default { key: "google_drive-new-shared-drive", name: "New Shared Drive", description: "Emits a new event any time a shared drive is created.", - version: "0.1.12", + version: "0.1.13", type: "source", dedupe: "unique", props: { diff --git a/components/google_drive/sources/new-spreadsheet/new-spreadsheet.mjs b/components/google_drive/sources/new-spreadsheet/new-spreadsheet.mjs index a18f50525f472..63781464ce77f 100644 --- a/components/google_drive/sources/new-spreadsheet/new-spreadsheet.mjs +++ b/components/google_drive/sources/new-spreadsheet/new-spreadsheet.mjs @@ -6,7 +6,7 @@ export default { type: "source", name: "New Spreadsheet (Instant)", description: "Emit new event when a new spreadsheet is created in a drive.", - version: "0.1.14", + version: "0.1.15", props: { googleDrive: newFilesInstant.props.googleDrive, db: newFilesInstant.props.db, diff --git a/components/leonardo_ai/leonardo_ai.app.mjs b/components/leonardo_ai/leonardo_ai.app.mjs index 21ed86a6964f8..526c1b8b0d642 100644 --- a/components/leonardo_ai/leonardo_ai.app.mjs +++ b/components/leonardo_ai/leonardo_ai.app.mjs @@ -8,4 +8,4 @@ export default { console.log(Object.keys(this.$auth)); }, }, -}; \ No newline at end of file +}; diff --git a/components/microsoft_onedrive/package.json b/components/microsoft_onedrive/package.json index 1974547c86686..b064de16f6456 100644 --- a/components/microsoft_onedrive/package.json +++ b/components/microsoft_onedrive/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/microsoft_onedrive", - "version": "1.7.2", + "version": "1.7.3", "description": "Pipedream Microsoft OneDrive components", "main": "microsoft_onedrive.app.mjs", "homepage": "https://pipedream.com/apps/microsoft-onedrive", diff --git a/components/microsoft_onedrive/sources/new-file-created/new-file-created.mjs b/components/microsoft_onedrive/sources/new-file-created/new-file-created.mjs index 1be85bd11d248..4832291b64d37 100644 --- a/components/microsoft_onedrive/sources/new-file-created/new-file-created.mjs +++ b/components/microsoft_onedrive/sources/new-file-created/new-file-created.mjs @@ -1,5 +1,7 @@ import onedrive from "../../microsoft_onedrive.app.mjs"; import base from "../common/base.mjs"; +import { Readable } from "stream"; +import httpRequest from "../../common/httpRequest.mjs"; import sampleEmit from "./test-event.mjs"; export default { @@ -8,7 +10,7 @@ export default { key: "microsoft_onedrive-new-file-created", name: "New File Created (Instant)", description: "Emit new event when a new file is created in a OneDrive drive", - version: "0.0.2", + version: "0.1.0", dedupe: "unique", props: { ...base.props, @@ -37,9 +39,22 @@ export default { "fileTypes", ], }, + includeLink: { + label: "Include Link", + type: "boolean", + description: "Upload file to your File Stash and emit temporary download link to the file. See [the docs](https://pipedream.com/docs/connect/components/files) to learn more about working with files in Pipedream.", + default: false, + optional: true, + }, + dir: { + type: "dir", + accessMode: "write", + optional: true, + }, }, methods: { ...base.methods, + httpRequest, getDeltaLinkParams() { const params = {}; if (this.drive) { @@ -62,6 +77,27 @@ export default { } return !this.folder || driveItem?.parentReference?.id === this.folder; }, + async stashFile(driveItem) { + const response = await this.httpRequest({ + url: `items/${driveItem.id}/content`, + responseType: "arraybuffer", + }); + const buffer = Buffer.from(response, "base64"); + const filepath = `${driveItem.id}/${driveItem.name}`; + const file = await this.dir.open(filepath).fromReadableStream( + Readable.from(buffer), + driveItem.file.mimeType, + buffer.length, + ); + return await file.withoutPutUrl().withGetUrl(); + }, + async processEvent(driveItem) { + if (this.includeLink) { + driveItem.fileURL = await this.stashFile(driveItem); + } + const meta = this.generateMeta(driveItem); + this.$emit(driveItem, meta); + }, }, sampleEmit, }; diff --git a/components/microsoft_outlook/package.json b/components/microsoft_outlook/package.json index 4401cd1c10019..513a7d2754097 100644 --- a/components/microsoft_outlook/package.json +++ b/components/microsoft_outlook/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/microsoft_outlook", - "version": "1.6.0", + "version": "1.7.0", "description": "Pipedream Microsoft Outlook Components", "main": "microsoft_outlook.app.mjs", "keywords": [ diff --git a/components/microsoft_outlook/sources/common/common-new-email.mjs b/components/microsoft_outlook/sources/common/common-new-email.mjs index 9d70452001b23..bb3ee8ebd0a7a 100644 --- a/components/microsoft_outlook/sources/common/common-new-email.mjs +++ b/components/microsoft_outlook/sources/common/common-new-email.mjs @@ -25,7 +25,7 @@ export default { return; } for (const item of events) { - this.emitEvent(item); + await this.emitEvent(item); } }, async activate() { diff --git a/components/microsoft_outlook/sources/new-attachment-received/new-attachment-received.mjs b/components/microsoft_outlook/sources/new-attachment-received/new-attachment-received.mjs index 79c32119e6183..e15bc37c27441 100644 --- a/components/microsoft_outlook/sources/new-attachment-received/new-attachment-received.mjs +++ b/components/microsoft_outlook/sources/new-attachment-received/new-attachment-received.mjs @@ -1,13 +1,29 @@ import common from "../common/common-new-email.mjs"; +import { Readable } from "stream"; export default { ...common, key: "microsoft_outlook-new-attachment-received", name: "New Attachment Received (Instant)", description: "Emit new event when a new email containing one or more attachments arrives in a specified Microsoft Outlook folder.", - version: "0.0.5", + version: "0.1.0", type: "source", dedupe: "unique", + props: { + ...common.props, + includeLink: { + label: "Include Link", + type: "boolean", + description: "Upload attachment to your File Stash and emit temporary download link to the file. See [the docs](https://pipedream.com/docs/connect/components/files) to learn more about working with files in Pipedream.", + default: false, + optional: true, + }, + dir: { + type: "dir", + accessMode: "write", + optional: true, + }, + }, methods: { ...common.methods, async getSampleEvents({ pageSize }) { @@ -36,8 +52,48 @@ export default { } return attachments; }, - emitEvent(item) { + async getMessageAttachments(message) { + const { value: attachments } = await this.microsoftOutlook.listAttachments({ + messageId: message.id, + }); + if (!attachments?.length) { + return []; + } + return attachments.map((attachment) => ({ + ...attachment, + messageId: message.id, + messageSubject: message.subject, + messageSender: message.sender, + messageReceivedDateTime: message.receivedDateTime, + parentFolderId: message.parentFolderId, + contentBytes: undefined, + })); + }, + async stashAttachment(item) { + const messageAttachment = await this.microsoftOutlook.getAttachment({ + messageId: item.messageId, + attachmentId: item.id, + responseType: "arraybuffer", + }); + const rawcontent = messageAttachment.toString("base64"); + const buffer = Buffer.from(rawcontent, "base64"); + const filepath = `${item.id}/${item.name}`; + // Upload the attachment to the configured directory (File Stash) so it + // can be accessed later. + const file = await this.dir.open(filepath).fromReadableStream( + Readable.from(buffer), + item.contentType, + buffer.length, + ); + // Return file details and temporary download link: + // { path, get_url, s3Key, type } + return await file.withoutPutUrl().withGetUrl(); + }, + async emitEvent(item) { if (this.isRelevant(item)) { + if (this.includeLink) { + item.file = await this.stashAttachment(item); + } this.$emit(item, this.generateMeta(item)); } }, @@ -67,7 +123,9 @@ export default { }); if (message.hasAttachments) { const attachments = await this.getMessageAttachments(message); - attachments.forEach((item) => this.emitEvent(item)); + for (const item of attachments) { + await this.emitEvent(item); + } } } catch { console.log(`Could not fetch message with ID: ${resourceId}`); diff --git a/components/microsoft_outlook/sources/new-email/new-email.mjs b/components/microsoft_outlook/sources/new-email/new-email.mjs index 957f1fb49d3ef..ba04a634d1781 100644 --- a/components/microsoft_outlook/sources/new-email/new-email.mjs +++ b/components/microsoft_outlook/sources/new-email/new-email.mjs @@ -7,7 +7,7 @@ export default { key: "microsoft_outlook-new-email", name: "New Email Event (Instant)", description: "Emit new event when an email is received in specified folders.", - version: "0.1.1", + version: "0.1.2", type: "source", dedupe: "unique", methods: { diff --git a/components/openai/package.json b/components/openai/package.json index 85d29c0f16812..51b4dba16ccc3 100644 --- a/components/openai/package.json +++ b/components/openai/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/openai", - "version": "1.2.0", + "version": "1.2.1", "description": "Pipedream OpenAI Components", "main": "openai.app.mjs", "keywords": [ @@ -16,6 +16,7 @@ "dependencies": { "@pipedream/platform": "^3.1.0", "bottleneck": "^2.19.5", + "file-type": "^21.0.0", "form-data": "^4.0.0", "got": "^12.6.0", "openai": "^4.77.0" diff --git a/components/openai/sources/new-file-created/new-file-created.mjs b/components/openai/sources/new-file-created/new-file-created.mjs index f503e531f3d6d..3f7a91dd54064 100644 --- a/components/openai/sources/new-file-created/new-file-created.mjs +++ b/components/openai/sources/new-file-created/new-file-created.mjs @@ -1,4 +1,6 @@ import common from "../common/common.mjs"; +import { Readable } from "stream"; +import { fileTypeFromBuffer } from "file-type"; import sampleEmit from "./test-event.mjs"; export default { @@ -6,7 +8,7 @@ export default { key: "openai-new-file-created", name: "New File Created", description: "Emit new event when a new file is created in OpenAI. [See the documentation](https://platform.openai.com/docs/api-reference/files/list)", - version: "0.0.15", + version: "0.1.0", type: "source", dedupe: "unique", props: { @@ -19,6 +21,18 @@ export default { description: "If specified, events will only be emitted for files with the specified purpose.", optional: true, }, + includeLink: { + label: "Include Link", + type: "boolean", + description: "Upload file to your File Stash and emit temporary download link to the file. See [the docs](https://pipedream.com/docs/connect/components/files) to learn more about working with files in Pipedream.", + default: false, + optional: true, + }, + dir: { + type: "dir", + accessMode: "write", + optional: true, + }, }, methods: { ...common.methods, @@ -34,6 +48,44 @@ export default { ts: item.created_at * 1000, }; }, + async stashFile(item) { + const response = await this.openai.retrieveFileContent({ + file_id: item.id, + responseType: "arraybuffer", + }); + const buffer = Buffer.from(response); + const filepath = `${item.id}/${item.filename}`; + const type = await fileTypeFromBuffer(buffer); + const file = await this.dir.open(filepath).fromReadableStream( + Readable.from(buffer), + type?.mime, + buffer.length, + ); + return await file.withoutPutUrl().withGetUrl(); + }, + async getAndProcessItems(maxEvents) { + const lastCreated = this._getLastCreated(); + const { data } = await this.getData(); + if (!data?.length) { + return; + } + this._setLastCreated(data[0].created_at); + const items = data?.filter(({ created_at }) => created_at >= lastCreated).reverse(); + let count = 0; + for (const item of items) { + if (!maxEvents || count < maxEvents) { + if (this.includeLink) { + try { + item.file = await this.stashFile(item); + } catch (error) { + item.file = `Could not upload file ${item.filename } to File Stash`; + } + } + this.$emit(item, this.getMeta(item)); + count++; + } + } + }, }, sampleEmit, }; diff --git a/components/xano_metadata_api/xano_metadata_api.app.mjs b/components/xano_metadata_api/xano_metadata_api.app.mjs index 6c8548b8e0ddb..8c5bfa75f5e9f 100644 --- a/components/xano_metadata_api/xano_metadata_api.app.mjs +++ b/components/xano_metadata_api/xano_metadata_api.app.mjs @@ -8,4 +8,4 @@ export default { console.log(Object.keys(this.$auth)); }, }, -}; \ No newline at end of file +}; diff --git a/components/zoho_desk/package.json b/components/zoho_desk/package.json index dd33cd2e89812..147ab75b48470 100644 --- a/components/zoho_desk/package.json +++ b/components/zoho_desk/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/zoho_desk", - "version": "0.2.0", + "version": "0.2.1", "description": "Pipedream Zoho_desk Components", "main": "zoho_desk.app.mjs", "keywords": [ @@ -12,6 +12,7 @@ "dependencies": { "@pipedream/platform": "^3.1.0", "async-retry": "^1.3.3", + "file-type": "^21.0.0", "form-data": "^4.0.0" }, "publishConfig": { diff --git a/components/zoho_desk/sources/changed-ticket-status/changed-ticket-status.mjs b/components/zoho_desk/sources/changed-ticket-status/changed-ticket-status.mjs index a800e8d0cd780..5baf9b57cf61a 100644 --- a/components/zoho_desk/sources/changed-ticket-status/changed-ticket-status.mjs +++ b/components/zoho_desk/sources/changed-ticket-status/changed-ticket-status.mjs @@ -6,7 +6,7 @@ export default { name: "New Ticket Status Change", description: "Emit new event when a status ticket is changed. [See the docs here](https://desk.zoho.com/DeskAPIDocument#Tickets#Tickets_Listalltickets)", type: "source", - version: "0.0.4", + version: "0.0.5", dedupe: "unique", props: { ...common.props, diff --git a/components/zoho_desk/sources/common/common-polling.mjs b/components/zoho_desk/sources/common/common-polling.mjs index 465601a125adc..f224823601b52 100644 --- a/components/zoho_desk/sources/common/common-polling.mjs +++ b/components/zoho_desk/sources/common/common-polling.mjs @@ -52,9 +52,10 @@ export default { lastResource, ] = resources; - resources - .filter(this.resourceFilter) - .forEach(this.processEvent); + const filteredResources = resources.filter(this.resourceFilter); + for (const resource of filteredResources) { + await this.processEvent(resource); + } if (lastResource) { const { diff --git a/components/zoho_desk/sources/new-account/new-account.mjs b/components/zoho_desk/sources/new-account/new-account.mjs index ff975e65e83a0..99cc3fdf15115 100644 --- a/components/zoho_desk/sources/new-account/new-account.mjs +++ b/components/zoho_desk/sources/new-account/new-account.mjs @@ -6,7 +6,7 @@ export default { name: "New Account", description: "Emit new event when a new account is created. [See the docs here](https://desk.zoho.com/DeskAPIDocument#Accounts#Accounts_Listaccounts)", type: "source", - version: "0.0.4", + version: "0.0.5", dedupe: "unique", props: { ...common.props, diff --git a/components/zoho_desk/sources/new-agent/new-agent.mjs b/components/zoho_desk/sources/new-agent/new-agent.mjs index 576c6bf921def..7e3db438faace 100644 --- a/components/zoho_desk/sources/new-agent/new-agent.mjs +++ b/components/zoho_desk/sources/new-agent/new-agent.mjs @@ -6,7 +6,7 @@ export default { name: "New Agent", description: "Emit new event when a new agent is created. [See the docs here](https://desk.zoho.com/DeskAPIDocument#Agents#Agents_Listagents)", type: "source", - version: "0.0.4", + version: "0.0.5", dedupe: "unique", props: { ...common.props, diff --git a/components/zoho_desk/sources/new-contact/new-contact.mjs b/components/zoho_desk/sources/new-contact/new-contact.mjs index 94c6662b4abf2..eae5482c02314 100644 --- a/components/zoho_desk/sources/new-contact/new-contact.mjs +++ b/components/zoho_desk/sources/new-contact/new-contact.mjs @@ -6,7 +6,7 @@ export default { name: "New Contact", description: "Emit new event when a new contact is created. [See the docs here](https://desk.zoho.com/DeskAPIDocument#Contacts#Contacts_Listcontacts)", type: "source", - version: "0.0.4", + version: "0.0.5", dedupe: "unique", props: { ...common.props, diff --git a/components/zoho_desk/sources/new-ticket-attachment/new-ticket-attachment.mjs b/components/zoho_desk/sources/new-ticket-attachment/new-ticket-attachment.mjs index c9b95d060ce16..c3e8018ba308b 100644 --- a/components/zoho_desk/sources/new-ticket-attachment/new-ticket-attachment.mjs +++ b/components/zoho_desk/sources/new-ticket-attachment/new-ticket-attachment.mjs @@ -1,4 +1,6 @@ import common from "../common/common-polling.mjs"; +import { Readable } from "stream"; +import { fileTypeFromBuffer } from "file-type"; export default { ...common, @@ -6,7 +8,7 @@ export default { name: "New Ticket Attachment", description: "Emit new event when a new ticket attachment is created. [See the docs here](https://desk.zoho.com/DeskAPIDocument#TicketAttachments#TicketAttachments_Listticketattachments)", type: "source", - version: "0.0.4", + version: "0.1.0", dedupe: "unique", props: { ...common.props, @@ -25,6 +27,18 @@ export default { }), ], }, + includeLink: { + label: "Include Link", + type: "boolean", + description: "Upload attachment to your File Stash and emit temporary download link to the file. See [the docs](https://pipedream.com/docs/connect/components/files) to learn more about working with files in Pipedream.", + default: false, + optional: true, + }, + dir: { + type: "dir", + accessMode: "write", + optional: true, + }, }, methods: { ...common.methods, @@ -53,5 +67,27 @@ export default { summary: `Ticket Attachment ID ${resource.id}`, }; }, + async stashFile(resource) { + const response = await this.zohoDesk.makeRequest({ + url: resource.href, + responseType: "arraybuffer", + }); + const buffer = Buffer.from(response); + const filepath = `${resource.id}/${resource.name}`; + const type = await fileTypeFromBuffer(buffer); + const file = await this.dir.open(filepath).fromReadableStream( + Readable.from(buffer), + type?.mime, + buffer.length, + ); + return await file.withoutPutUrl().withGetUrl(); + }, + async processEvent(resource) { + if (this.includeLink) { + resource.file = await this.stashFile(resource); + } + const meta = this.generateMeta(resource); + this.$emit(resource, meta); + }, }, }; diff --git a/components/zoho_desk/sources/new-ticket-comment/new-ticket-comment.mjs b/components/zoho_desk/sources/new-ticket-comment/new-ticket-comment.mjs index 14d31838efe57..855c0bddb17e4 100644 --- a/components/zoho_desk/sources/new-ticket-comment/new-ticket-comment.mjs +++ b/components/zoho_desk/sources/new-ticket-comment/new-ticket-comment.mjs @@ -6,7 +6,7 @@ export default { name: "New Ticket Comment", description: "Emit new event when a new ticket comment is created. [See the docs here](https://desk.zoho.com/DeskAPIDocument#TicketsComments#TicketsComments_Listallticketcomments)", type: "source", - version: "0.0.4", + version: "0.0.5", dedupe: "unique", props: { ...common.props, diff --git a/components/zoho_desk/sources/new-ticket-message/new-ticket-message.mjs b/components/zoho_desk/sources/new-ticket-message/new-ticket-message.mjs index d909ba1e39ada..7dae318dfe53b 100644 --- a/components/zoho_desk/sources/new-ticket-message/new-ticket-message.mjs +++ b/components/zoho_desk/sources/new-ticket-message/new-ticket-message.mjs @@ -6,7 +6,7 @@ export default { name: "New Ticket Message", description: "Emit new event when a message ticket is created. [See the docs here](https://desk.zoho.com/DeskAPIDocument#Threads#Threads_Listallthreads)", type: "source", - version: "0.0.4", + version: "0.0.5", dedupe: "unique", props: { ...common.props, diff --git a/components/zoho_desk/sources/new-ticket/new-ticket.mjs b/components/zoho_desk/sources/new-ticket/new-ticket.mjs index 878001f3b95f1..82ed158708946 100644 --- a/components/zoho_desk/sources/new-ticket/new-ticket.mjs +++ b/components/zoho_desk/sources/new-ticket/new-ticket.mjs @@ -6,7 +6,7 @@ export default { name: "New Ticket", description: "Emit new event when a new ticket is created. [See the docs here](https://desk.zoho.com/DeskAPIDocument#Tickets#Tickets_Listalltickets)", type: "source", - version: "0.0.4", + version: "0.0.5", dedupe: "unique", props: { ...common.props, diff --git a/components/zoho_desk/sources/updated-ticket/updated-ticket.mjs b/components/zoho_desk/sources/updated-ticket/updated-ticket.mjs index cf793594ee531..08265ce22af7d 100644 --- a/components/zoho_desk/sources/updated-ticket/updated-ticket.mjs +++ b/components/zoho_desk/sources/updated-ticket/updated-ticket.mjs @@ -6,7 +6,7 @@ export default { name: "New Updated Ticket", description: "Emit new event when a ticket is updated. [See the docs here](https://desk.zoho.com/DeskAPIDocument#Tickets#Tickets_Listalltickets)", type: "source", - version: "0.0.4", + version: "0.0.5", dedupe: "unique", props: { ...common.props, diff --git a/components/zoho_workdrive/actions/download-file/download-file.mjs b/components/zoho_workdrive/actions/download-file/download-file.mjs index 887c6b9a9b3dc..5c7016b5442ec 100644 --- a/components/zoho_workdrive/actions/download-file/download-file.mjs +++ b/components/zoho_workdrive/actions/download-file/download-file.mjs @@ -7,7 +7,7 @@ export default { key: "zoho_workdrive-download-file", name: "Download File to Tmp Direcory", description: "Download a file to the /tmp directory. [See the documentation](https://workdrive.zoho.com/apidocs/v1/filesfolders/downloadserverfile)", - version: "0.0.4", + version: "0.0.5", type: "action", props: { app, @@ -71,23 +71,12 @@ export default { sync: true, }, }, - methods: { - downloadFile({ - fileId, ...args - }) { - return this.app._makeRequest({ - url: `https://download.${this.app.$auth.base_api_uri}/v1/workdrive/download/${fileId}`, - responseType: "arraybuffer", - ...args, - }); - }, - }, async run({ $ }) { const fileId = this.fileId?.value ?? this.fileId; const fileName = this.fileName ?? this.fileId?.label ?? "file"; const filePath = getFilePath(fileName); - const fileContent = await this.downloadFile({ + const fileContent = await this.app.downloadFile({ fileId, }); diff --git a/components/zoho_workdrive/actions/upload-file/upload-file.mjs b/components/zoho_workdrive/actions/upload-file/upload-file.mjs index 6a1cddfe3d263..afbca6c65c413 100644 --- a/components/zoho_workdrive/actions/upload-file/upload-file.mjs +++ b/components/zoho_workdrive/actions/upload-file/upload-file.mjs @@ -5,7 +5,7 @@ import app from "../../zoho_workdrive.app.mjs"; export default { key: "zoho_workdrive-upload-file", name: "Upload File", - version: "0.0.6", + version: "0.0.7", description: "Upload a new file to your WorkDrive account. [See the documentation](https://workdrive.zoho.com/apidocs/v1/chunkupload/chunkuploadcreatesession)", type: "action", props: { diff --git a/components/zoho_workdrive/package.json b/components/zoho_workdrive/package.json index 4b3ca3106dacc..c6912cb44c3fc 100644 --- a/components/zoho_workdrive/package.json +++ b/components/zoho_workdrive/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/zoho_workdrive", - "version": "0.2.4", + "version": "0.2.5", "description": "Pipedream Zoho WorkDrive Components", "main": "zoho_workdrive.app.mjs", "keywords": [ @@ -15,6 +15,7 @@ "dependencies": { "@pipedream/platform": "^3.1.0", "axios": "^1.5.1", + "file-type": "^21.0.0", "form-data": "^4.0.0" } } diff --git a/components/zoho_workdrive/sources/new-file-in-folder/new-file-in-folder.mjs b/components/zoho_workdrive/sources/new-file-in-folder/new-file-in-folder.mjs index 040f34a92f1e9..c9c530f8eccf4 100644 --- a/components/zoho_workdrive/sources/new-file-in-folder/new-file-in-folder.mjs +++ b/components/zoho_workdrive/sources/new-file-in-folder/new-file-in-folder.mjs @@ -1,11 +1,13 @@ import { DEFAULT_POLLING_SOURCE_TIMER_INTERVAL } from "@pipedream/platform"; import app from "../../zoho_workdrive.app.mjs"; +import { Readable } from "stream"; +import { fileTypeFromBuffer } from "file-type"; import sampleEmit from "./test-event.mjs"; export default { key: "zoho_workdrive-new-file-in-folder", name: "New File In Folder", - version: "0.0.3", + version: "0.1.0", description: "Emit new event when a new file is created in a specific folder.", type: "source", dedupe: "unique", @@ -46,6 +48,18 @@ export default { label: "Folder Id", description: "The unique ID of the folder.", }, + includeLink: { + label: "Include Link", + type: "boolean", + description: "Upload attachment to your File Stash and emit temporary download link to the file. See [the docs](https://pipedream.com/docs/connect/components/files) to learn more about working with files in Pipedream.", + default: false, + optional: true, + }, + dir: { + type: "dir", + accessMode: "write", + optional: true, + }, }, methods: { _getLastDate() { @@ -54,6 +68,22 @@ export default { _setLastDate(lastDate) { this.db.set("lastDate", lastDate); }, + async stashFile(item) { + const fileContent = await this.app.downloadFile({ + fileId: item.id, + }); + const buffer = Buffer.from(fileContent, "base64"); + const filepath = `${item.id}/${item.attributes.name}`; + const type = await fileTypeFromBuffer(buffer); + const file = await this.dir.open(filepath).fromReadableStream( + Readable.from(buffer), + type?.mime, + buffer.length, + ); + // Return file details and temporary download link: + // { path, get_url, s3Key, type } + return await file.withoutPutUrl().withGetUrl(); + }, async startEvent(maxResults = 0) { const { app, @@ -84,6 +114,9 @@ export default { this._setLastDate(maxDate); for (const item of responseArray) { + if (this.includeLink) { + item.file = await this.stashFile(item); + } this.$emit( item, { @@ -97,7 +130,7 @@ export default { }, hooks: { async deploy() { - await this.startEvent(25); + await this.startEvent(10); }, }, async run() { diff --git a/components/zoho_workdrive/sources/new-folder/new-folder.mjs b/components/zoho_workdrive/sources/new-folder/new-folder.mjs index 6fd5fc6b6dddf..66ca921edf7ec 100644 --- a/components/zoho_workdrive/sources/new-folder/new-folder.mjs +++ b/components/zoho_workdrive/sources/new-folder/new-folder.mjs @@ -5,7 +5,7 @@ import sampleEmit from "./test-event.mjs"; export default { key: "zoho_workdrive-new-folder", name: "New Folder", - version: "0.0.3", + version: "0.0.4", description: "Emit new event when a new folder is created in a specific folder.", type: "source", dedupe: "unique", diff --git a/components/zoho_workdrive/zoho_workdrive.app.mjs b/components/zoho_workdrive/zoho_workdrive.app.mjs index fb5cb2dd28152..92fecd795c92b 100644 --- a/components/zoho_workdrive/zoho_workdrive.app.mjs +++ b/components/zoho_workdrive/zoho_workdrive.app.mjs @@ -161,6 +161,15 @@ export default { ...args, }); }, + downloadFile({ + fileId, ...args + }) { + return this._makeRequest({ + url: `https://download.${this.$auth.base_api_uri}/v1/workdrive/download/${fileId}`, + responseType: "arraybuffer", + ...args, + }); + }, async paginateFolders({ folderId, prefix = "", params = {}, }) { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6a798a9636550..927a88947673f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1304,6 +1304,9 @@ importers: dedent: specifier: ^1.5.1 version: 1.5.3(babel-plugin-macros@3.1.0) + file-type: + specifier: ^21.0.0 + version: 21.0.0 mailparser: specifier: ^3.6.6 version: 3.7.1 @@ -1879,6 +1882,9 @@ importers: '@pipedream/platform': specifier: ^3.1.0 version: 3.1.0 + file-type: + specifier: ^21.0.0 + version: 21.0.0 form-data: specifier: ^4.0.0 version: 4.0.1 @@ -5674,6 +5680,9 @@ importers: nodemailer: specifier: ^6.7.8 version: 6.9.16 + stream: + specifier: ^0.0.3 + version: 0.0.3 uuid: specifier: ^10.0.0 version: 10.0.0 @@ -9875,6 +9884,9 @@ importers: bottleneck: specifier: ^2.19.5 version: 2.19.5 + file-type: + specifier: ^21.0.0 + version: 21.0.0 form-data: specifier: ^4.0.0 version: 4.0.1 @@ -16395,6 +16407,9 @@ importers: async-retry: specifier: ^1.3.3 version: 1.3.3 + file-type: + specifier: ^21.0.0 + version: 21.0.0 form-data: specifier: ^4.0.0 version: 4.0.1 @@ -16528,6 +16543,9 @@ importers: axios: specifier: ^1.5.1 version: 1.7.7 + file-type: + specifier: ^21.0.0 + version: 21.0.0 form-data: specifier: ^4.0.0 version: 4.0.1 @@ -18123,6 +18141,9 @@ packages: '@bcoe/v8-coverage@0.2.3': resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + '@borewit/text-codec@0.1.1': + resolution: {integrity: sha512-5L/uBxmjaCIX5h8Z+uu+kA9BQLkc/Wl06UGR5ajNRxu+/XjonB5i8JpgFMrPj3LXTCPA0pv8yxUvbUi+QthGGA==} + '@bufbuild/protobuf@1.10.1': resolution: {integrity: sha512-wJ8ReQbHxsAfXhrf9ixl0aYbZorRuOWpBNzm8pL8ftmSxQx/wnJD5Eg861NwJU/czy2VXFIebCeZnZrI9rktIQ==} @@ -22012,6 +22033,10 @@ packages: '@tediousjs/connection-string@0.5.0': resolution: {integrity: sha512-7qSgZbincDDDFyRweCIEvZULFAw5iz/DeunhvuxpL31nfntX3P4Yd4HkHBRg9H8CdqY1e5WFN1PZIz/REL9MVQ==} + '@tokenizer/inflate@0.2.7': + resolution: {integrity: sha512-MADQgmZT1eKjp06jpI2yozxaU9uVs4GzzgSL+uEq7bVcJ9V1ZXQkeGNql1fsSI0gMy1vhvNTNbUqrx+pZfJVmg==} + engines: {node: '>=18'} + '@tokenizer/token@0.3.0': resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} @@ -25220,6 +25245,9 @@ packages: fetch-ponyfill@7.1.0: resolution: {integrity: sha512-FhbbL55dj/qdVO3YNK7ZEkshvj3eQ7EuIGV2I6ic/2YiocvyWv+7jg2s4AyS0wdRU75s3tA8ZxI/xPigb0v5Aw==} + fflate@0.8.2: + resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} + figures@3.2.0: resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} engines: {node: '>=8'} @@ -25259,6 +25287,10 @@ packages: resolution: {integrity: sha512-ihHtXRzXEziMrQ56VSgU7wkxh55iNchFkosu7Y9/S+tXHdKyrGjVK0ujbqNnsxzea+78MaLhN6PGmfYSAv1ACw==} engines: {node: '>=14.16'} + file-type@21.0.0: + resolution: {integrity: sha512-ek5xNX2YBYlXhiUXui3D/BXa3LdqPmoLJ7rqEx2bKJ7EAUEfmXgW0Das7Dc6Nr9MvqaOnIqiPV0mZk/r/UpNAg==} + engines: {node: '>=20'} + file-type@3.9.0: resolution: {integrity: sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==} engines: {node: '>=0.10.0'} @@ -30633,6 +30665,10 @@ packages: strnum@1.0.5: resolution: {integrity: sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==} + strtok3@10.3.4: + resolution: {integrity: sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg==} + engines: {node: '>=18'} + strtok3@6.3.0: resolution: {integrity: sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==} engines: {node: '>=10'} @@ -30943,6 +30979,10 @@ packages: resolution: {integrity: sha512-Y2fmSnZjQdDb9W4w4r1tswlMHylzWIeOKpx0aZH9BgGtACHhrk3OkT52AzwcuqTRBZtvvnTjDBh8eynMulu8Vg==} engines: {node: '>=14.16'} + token-types@6.1.1: + resolution: {integrity: sha512-kh9LVIWH5CnL63Ipf0jhlBIy0UsrMj/NJDfpsy1SqOXlLKEVyXXYrnFxFT1yOOYVGBSApeVnjPw/sBz5BfEjAQ==} + engines: {node: '>=14.16'} + toml@3.0.0: resolution: {integrity: sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==} @@ -31297,6 +31337,10 @@ packages: resolution: {integrity: sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==} engines: {node: '>= 0.8'} + uint8array-extras@1.5.0: + resolution: {integrity: sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==} + engines: {node: '>=18'} + ulid@3.0.1: resolution: {integrity: sha512-dPJyqPzx8preQhqq24bBG1YNkvigm87K8kVEHCD+ruZg24t6IFEFv00xMWfxcC4djmFtiTLdFuADn4+DOz6R7Q==} hasBin: true @@ -35468,6 +35512,8 @@ snapshots: '@bcoe/v8-coverage@0.2.3': {} + '@borewit/text-codec@0.1.1': {} + '@bufbuild/protobuf@1.10.1': {} '@bufbuild/protobuf@2.5.0': {} @@ -40301,6 +40347,14 @@ snapshots: '@tediousjs/connection-string@0.5.0': {} + '@tokenizer/inflate@0.2.7': + dependencies: + debug: 4.4.1(supports-color@10.0.0) + fflate: 0.8.2 + token-types: 6.1.1 + transitivePeerDependencies: + - supports-color + '@tokenizer/token@0.3.0': {} '@tootallnate/once@1.1.2': {} @@ -44293,6 +44347,8 @@ snapshots: transitivePeerDependencies: - encoding + fflate@0.8.2: {} + figures@3.2.0: dependencies: escape-string-regexp: 1.0.5 @@ -44334,6 +44390,15 @@ snapshots: strtok3: 7.1.1 token-types: 5.0.1 + file-type@21.0.0: + dependencies: + '@tokenizer/inflate': 0.2.7 + strtok3: 10.3.4 + token-types: 6.1.1 + uint8array-extras: 1.5.0 + transitivePeerDependencies: + - supports-color + file-type@3.9.0: {} file-uri-to-path@1.0.0: {} @@ -51605,6 +51670,10 @@ snapshots: strnum@1.0.5: {} + strtok3@10.3.4: + dependencies: + '@tokenizer/token': 0.3.0 + strtok3@6.3.0: dependencies: '@tokenizer/token': 0.3.0 @@ -52064,6 +52133,12 @@ snapshots: '@tokenizer/token': 0.3.0 ieee754: 1.2.1 + token-types@6.1.1: + dependencies: + '@borewit/text-codec': 0.1.1 + '@tokenizer/token': 0.3.0 + ieee754: 1.2.1 + toml@3.0.0: {} tomlify-j0.4@3.0.0: {} @@ -52562,6 +52637,8 @@ snapshots: dependencies: random-bytes: 1.0.0 + uint8array-extras@1.5.0: {} + ulid@3.0.1: {} unbox-primitive@1.0.2: