diff --git a/components/spotlightr/actions/create-video/create-video.mjs b/components/spotlightr/actions/create-video/create-video.mjs new file mode 100644 index 0000000000000..a1a0dc5aad8de --- /dev/null +++ b/components/spotlightr/actions/create-video/create-video.mjs @@ -0,0 +1,138 @@ +import { ConfigurationError } from "@pipedream/platform"; +import FormData from "form-data"; +import fs from "fs"; +import { checkTmp } from "../../common/utils.mjs"; +import spotlightr from "../../spotlightr.app.mjs"; + +export default { + key: "spotlightr-create-video", + name: "Create Video", + version: "0.0.1", + description: "Create a video in an application. [See the documentation](https://app.spotlightr.com/docs/api/#create-video)", + type: "action", + props: { + spotlightr, + url: { + type: "string", + label: "URL", + description: "The video URL. `You must provide at least the URL or File.`", + optional: true, + }, + name: { + type: "string", + label: "Name", + description: "The name of the video.", + }, + customS3: { + type: "string", + label: "Custom S3", + description: "**0** or **ID** of custom integration.", + default: "0", + }, + hls: { + type: "integer", + label: "HLS", + description: "The media streaming protocol.", + options: [ + { + label: "To leave as unsecured.", + value: 0, + }, + { + label: "To encode.", + value: 1, + }, + ], + optional: true, + }, + videoGroup: { + propDefinition: [ + spotlightr, + "videoGroup", + ], + optional: true, + }, + create: { + type: "integer", + label: "Create", + description: "The type of the creation.", + options: [ + { + label: "To debug.", + value: 0, + }, + { + label: "To confirm.", + value: 1, + }, + ], + optional: true, + }, + playerSettings: { + type: "object", + label: "Player Settings", + description: "Video ID for coping playerSettings (decoded base64)", + optional: true, + }, + file: { + type: "string", + label: "File", + description: "Full path to the file in `/tmp/` directory. E.g. `/tmp/video.mp4`. `You must provide at least the URL or File.`", + optional: true, + }, + }, + async run({ $ }) { + const { + spotlightr, + url, + file, + ...data + } = this; + + if (!file && !url) { + throw new ConfigurationError("You must provide at least the URL or File."); + } + + let preparedData = {}; + if (file) { + const formData = new FormData(); + + const path = checkTmp(file); + if (!fs.existsSync(path)) { + throw new ConfigurationError("File does not exist!"); + } + + formData.append("file", fs.createReadStream(path)); + for (const [ + key, + value, + ] of Object.entries(data)) { + formData.append(key, value); + } + + preparedData = { + formDataRequest: true, + headers: formData.getHeaders(), + data: formData, + }; + + } else { + preparedData = { + data: { + URL: url, + ...data, + }, + }; + } + + const response = await spotlightr.createVideo({ + $, + ...preparedData, + }); + + $.export("$summary", `A new video with ${response.data + ? `URL: ${response.data}` + : `Id: ${response}`} was successfully created!`); + return response.data || response; + }, +}; diff --git a/components/spotlightr/actions/delete-videos/delete-videos.mjs b/components/spotlightr/actions/delete-videos/delete-videos.mjs new file mode 100644 index 0000000000000..00406ca58fa98 --- /dev/null +++ b/components/spotlightr/actions/delete-videos/delete-videos.mjs @@ -0,0 +1,35 @@ +import spotlightr from "../../spotlightr.app.mjs"; + +export default { + key: "spotlightr-delete-videos", + name: "Delete Videos", + version: "0.0.1", + description: "Delete videos from your account. [See the documentation](https://app.spotlightr.com/docs/api/#deleteVideo)", + type: "action", + props: { + spotlightr, + videoId: { + propDefinition: [ + spotlightr, + "videoId", + ], + type: "string[]", + }, + }, + async run({ $ }) { + const { + spotlightr, + videoId, + } = this; + + const response = await spotlightr.deleteVideo({ + $, + params: { + IDs: videoId, + }, + }); + + $.export("$summary", `The videos with Ids: ${videoId.toString()} were successfully deleted!`); + return response; + }, +}; diff --git a/components/spotlightr/common/utils.mjs b/components/spotlightr/common/utils.mjs new file mode 100644 index 0000000000000..dc2ed5a5be34d --- /dev/null +++ b/components/spotlightr/common/utils.mjs @@ -0,0 +1,6 @@ +export const checkTmp = (filename) => { + if (filename.indexOf("/tmp") === -1) { + return `/tmp/${filename}`; + } + return filename; +}; diff --git a/components/spotlightr/package.json b/components/spotlightr/package.json index 5cfd974938446..d61745dce68b8 100644 --- a/components/spotlightr/package.json +++ b/components/spotlightr/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/spotlightr", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream Spotlightr Components", "main": "spotlightr.app.mjs", "keywords": [ @@ -11,5 +11,10 @@ "author": "Pipedream (https://pipedream.com/)", "publishConfig": { "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^1.5.1", + "form-data": "^4.0.0", + "fs": "^0.0.1-security" } -} \ No newline at end of file +} diff --git a/components/spotlightr/sources/video-viewed/test-event.mjs b/components/spotlightr/sources/video-viewed/test-event.mjs new file mode 100644 index 0000000000000..23d5f7993327f --- /dev/null +++ b/components/spotlightr/sources/video-viewed/test-event.mjs @@ -0,0 +1,28 @@ +export default { + "id": 123123123, + "videoID": 123123123, + "date": "2023-10-24 17:37:20", + "cookie": "n7mqa33xk123123mtpmn", + "userID": 123123123, + "email": "", + "IP": "", + "phone": "", + "data": "", + "watchedSegments": "", + "percentWatched": 0, + "country": "", + "country_name": "", + "region_name": "", + "city": "", + "zip": "", + "latitude": "0.00000000", + "longitude": "0.00000000", + "currency_code": "", + "currency_name": "", + "device": "", + "browser": "", + "viewerID": 123123123, + "contactData": "", + "referer": "oembed5.cdn.spotlightr.com", + "customViewerID": "" +} \ No newline at end of file diff --git a/components/spotlightr/sources/video-viewed/video-viewed.mjs b/components/spotlightr/sources/video-viewed/video-viewed.mjs new file mode 100644 index 0000000000000..2af9cfdc6e0af --- /dev/null +++ b/components/spotlightr/sources/video-viewed/video-viewed.mjs @@ -0,0 +1,76 @@ +import { DEFAULT_POLLING_SOURCE_TIMER_INTERVAL } from "@pipedream/platform"; +import spotlightr from "../../spotlightr.app.mjs"; +import sampleEmit from "./test-event.mjs"; + +export default { + key: "spotlightr-video-viewed", + name: "New Video View", + version: "0.0.1", + description: "Emit new event when a specific video is viewed by a user.", + type: "source", + dedupe: "unique", + props: { + spotlightr, + db: "$.service.db", + timer: { + label: "Polling interval", + description: "Pipedream will poll the Spotlightr on this schedule", + type: "$.interface.timer", + default: { + intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, + }, + }, + videoId: { + propDefinition: [ + spotlightr, + "videoId", + ], + }, + }, + methods: { + _getLastDate() { + return this.db.get("lastDate") || 0; + }, + _setLastDate(lastDate) { + this.db.set("lastDate", lastDate); + }, + async startEvent(maxResults = 0) { + const { + spotlightr, + videoId, + } = this; + + const lastDate = this._getLastDate(); + const items = spotlightr.paginate({ + fn: spotlightr.getViews, + maxResults, + params: { + videoID: videoId, + }, + }); + + let responseArray = []; + + for await (const item of items) { + if (new Date(item.date) <= new Date(lastDate)) break; + responseArray.push(item); + } + if (responseArray.length) this._setLastDate(responseArray[0].created_time); + + for (const item of responseArray.reverse()) { + this.$emit( + item, + { + id: item.id, + summary: `New view with id: "${item.id}" was created!`, + ts: Date.parse(item.date), + }, + ); + } + }, + }, + async run() { + await this.startEvent(); + }, + sampleEmit, +}; diff --git a/components/spotlightr/spotlightr.app.mjs b/components/spotlightr/spotlightr.app.mjs index 6ec8e2a7c460d..86e0b3e4dd7b9 100644 --- a/components/spotlightr/spotlightr.app.mjs +++ b/components/spotlightr/spotlightr.app.mjs @@ -1,11 +1,126 @@ +import axiosPipedream from "@pipedream/platform"; +import axios from "axios"; + export default { type: "app", app: "spotlightr", - propDefinitions: {}, + propDefinitions: { + videoGroup: { + type: "string", + label: "Video Group", + description: "The ID of the project.", + async options() { + const { data } = await this.listGroups(); + + return data.map(({ + id: value, name: label, + }) => ({ + label, + value, + })); + }, + }, + videoId: { + type: "string", + label: "Video Id", + description: "The ID of the video.", + async options() { + const { videos: { data } } = await this.listVideos(); + + return data.map(({ + id: value, name: label, + }) => ({ + label, + value, + })); + }, + }, + }, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + _apiUrl() { + return "https://api.spotlightr.com/api"; + }, + _getApiKey() { + return this.$auth.api_key; + }, + _getParams(params = {}) { + return { + ...params, + "vooKey": this._getApiKey(), + }; + }, + _makeRequest({ + $ = this, params, path, formDataRequest = false, ...opts + }) { + const config = { + url: `${this._apiUrl()}/${path}`, + params: this._getParams(params), + ...opts, + }; + + if (formDataRequest) return axios(config); + return axiosPipedream.axios($, config); + }, + createVideo(args = {}) { + return this._makeRequest({ + method: "POST", + path: "createVideo", + ...args, + }); + }, + deleteVideo(args = {}) { + return this._makeRequest({ + method: "POST", + path: "deleteVideo", + ...args, + }); + }, + getViews(args = {}) { + return this._makeRequest({ + path: "views/getViews", + ...args, + }); + }, + listGroups(args = {}) { + return this._makeRequest({ + path: "groups", + ...args, + }); + }, + listVideos(args = {}) { + return this._makeRequest({ + path: "videos", + ...args, + }); + }, + async *paginate({ + fn, params = {}, maxResults = null, + }) { + let hasMore = false; + let count = 0; + let page = 0; + + do { + params.page = ++page; + const { + data, + current_page: currentPage, + last_page: lastPage, + } = await fn({ + params, + }); + + for (const d of data) { + yield d; + + if (maxResults && ++count === maxResults) { + return count; + } + } + + hasMore = currentPage != lastPage; + + } while (hasMore); }, }, }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7d55ec08128db..84d8ad1fd45fc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5559,7 +5559,14 @@ importers: '@pipedream/platform': 1.5.1 components/spotlightr: - specifiers: {} + specifiers: + '@pipedream/platform': ^1.5.1 + form-data: ^4.0.0 + fs: ^0.0.1-security + dependencies: + '@pipedream/platform': 1.5.1 + form-data: 4.0.0 + fs: 0.0.1-security components/spreadsheet_com: specifiers: