diff --git a/components/listen_notes/.gitignore b/components/listen_notes/.gitignore deleted file mode 100644 index ec761ccab7595..0000000000000 --- a/components/listen_notes/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -*.js -*.mjs -dist \ No newline at end of file diff --git a/components/listen_notes/actions/full-search/full-search.mjs b/components/listen_notes/actions/full-search/full-search.mjs new file mode 100644 index 0000000000000..da79072994096 --- /dev/null +++ b/components/listen_notes/actions/full-search/full-search.mjs @@ -0,0 +1,56 @@ +import app from "../../listen_notes.app.mjs"; + +export default { + key: "listen_notes-full-search", + name: "Full Search", + description: "Full-text search on episodes, podcasts, or curated lists of podcasts. [See the documentation](https://www.listennotes.com/api/docs/#get-api-v2-search)", + version: "0.0.1", + type: "action", + props: { + app, + q: { + propDefinition: [ + app, + "q", + ], + }, + sortByDate: { + propDefinition: [ + app, + "sortByDate", + ], + }, + type: { + propDefinition: [ + app, + "type", + ], + }, + language: { + propDefinition: [ + app, + "language", + ], + }, + offset: { + propDefinition: [ + app, + "offset", + ], + }, + }, + + async run({ $ }) { + const response = await this.app.fullSearch({ + $, + params: { + q: this.q, + sort_by_date: this.sortByDate, + type: this.type, + language: this.language, + }, + }); + $.export("$summary", `Successfully retrieved ${response.results.length} results`); + return response; + }, +}; diff --git a/components/listen_notes/actions/get-episode-details/get-episode-details.mjs b/components/listen_notes/actions/get-episode-details/get-episode-details.mjs new file mode 100644 index 0000000000000..bdcd2ebfea74d --- /dev/null +++ b/components/listen_notes/actions/get-episode-details/get-episode-details.mjs @@ -0,0 +1,60 @@ +import app from "../../listen_notes.app.mjs"; + +export default { + key: "listen_notes-get-episode-details", + name: "Get Episode Details", + description: "Get the details of the selected episode. [See the documentation](https://www.listennotes.com/api/docs/#get-api-v2-episodes-id)", + version: "0.0.1", + type: "action", + props: { + app, + q: { + propDefinition: [ + app, + "q", + ], + optional: true, + }, + language: { + propDefinition: [ + app, + "language", + ], + }, + offset: { + propDefinition: [ + app, + "offset", + ], + }, + id: { + propDefinition: [ + app, + "id", + (c) => ({ + q: c.q, + language: c.language, + offset: c.offset, + }), + ], + }, + showTranscript: { + propDefinition: [ + app, + "showTranscript", + ], + }, + }, + + async run({ $ }) { + const response = await this.app.getEpisodeDetails({ + $, + id: this.id, + params: { + show_transcript: this.showTranscript, + }, + }); + $.export("$summary", `Successfully retrieved details for the episode '${response.title}'`); + return response; + }, +}; diff --git a/components/listen_notes/actions/get-podcast-details/get-podcast-details.mjs b/components/listen_notes/actions/get-podcast-details/get-podcast-details.mjs new file mode 100644 index 0000000000000..75b3209c2102a --- /dev/null +++ b/components/listen_notes/actions/get-podcast-details/get-podcast-details.mjs @@ -0,0 +1,68 @@ +import app from "../../listen_notes.app.mjs"; + +export default { + key: "listen_notes-get-podcast-details", + name: "Get Podcast Details", + description: "Get the details of the selected podcast. [See the documentation](https://www.listennotes.com/api/docs/#get-api-v2-podcasts-id)", + version: "0.0.1", + type: "action", + props: { + app, + q: { + propDefinition: [ + app, + "q", + ], + optional: true, + }, + language: { + propDefinition: [ + app, + "language", + ], + }, + offset: { + propDefinition: [ + app, + "offset", + ], + }, + id: { + propDefinition: [ + app, + "id", + (c) => ({ + q: c.q, + type: "podcast", + language: c.language, + offset: c.offset, + }), + ], + }, + nextEpisodePubDate: { + propDefinition: [ + app, + "nextEpisodePubDate", + ], + }, + sort: { + propDefinition: [ + app, + "sort", + ], + }, + }, + + async run({ $ }) { + const response = await this.app.getPodcastDetails({ + $, + id: this.id, + params: { + next_episode_pub_date: this.nextEpisodePubDate, + sort: this.sort, + }, + }); + $.export("$summary", `Successfully retrieved details for the podcast '${response.title}'`); + return response; + }, +}; diff --git a/components/listen_notes/app/listen_notes.app.ts b/components/listen_notes/app/listen_notes.app.ts deleted file mode 100644 index 75cbf47d7cdbd..0000000000000 --- a/components/listen_notes/app/listen_notes.app.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { defineApp } from "@pipedream/types"; - -export default defineApp({ - type: "app", - app: "listen_notes", - propDefinitions: {}, - methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); - }, - }, -}); diff --git a/components/listen_notes/common/constants.mjs b/components/listen_notes/common/constants.mjs new file mode 100644 index 0000000000000..f253ee5a5475e --- /dev/null +++ b/components/listen_notes/common/constants.mjs @@ -0,0 +1,37 @@ +export default { + SEARCH_SORTING_OPTIONS: [ + { + value: "0", + label: "Sort by Relevance", + }, + { + value: "1", + label: "Sort by Date", + }, + ], + EPISODES_SORTING_OPTIONS: [ + { + value: "recent_first", + label: "Recent First", + }, + { + value: "oldest_first", + label: "Oldest First", + }, + ], + TRANSCRIPT_OPTIONS: [ + { + value: "0", + label: "Don't include transcript", + }, + { + value: "1", + label: "Include transcript", + }, + ], + TYPE_OPTIONS: [ + "episode", + "podcast", + "curated", + ], +}; diff --git a/components/listen_notes/listen_notes.app.mjs b/components/listen_notes/listen_notes.app.mjs new file mode 100644 index 0000000000000..3471f52bd0e2f --- /dev/null +++ b/components/listen_notes/listen_notes.app.mjs @@ -0,0 +1,164 @@ +import { axios } from "@pipedream/platform"; +import constants from "./common/constants.mjs"; +import { ConfigurationError } from "@pipedream/platform"; + +export default { + type: "app", + app: "listen_notes", + propDefinitions: { + id: { + type: "string", + label: "Podcast or Episode ID", + description: "The ID of the podcast or episode", + async options({ + q, type, language, offset, + }) { + const response = await this.listPodcasts({ + q, + type, + language, + offset, + }); + const ids = response.results; + return ids.map(({ + title_original, id, + }) => ({ + value: id, + label: title_original, + })); + }, + }, + q: { + type: "string", + label: "Query", + description: "Search term, e.g., person, place, topic... You can use double quotes to do verbatim match", + }, + offset: { + type: "string", + label: "Offset", + description: "The offset parameter is used to paginate through search results", + optional: true, + }, + sortByDate: { + type: "string", + label: "Sort By Date", + description: "Sort by date. If 0, then sort by relevance. If 1, then sort by date", + options: constants.SEARCH_SORTING_OPTIONS, + optional: true, + }, + type: { + type: "string", + label: "Type", + description: "What type of contents do you want to search for?", + options: constants.TYPE_OPTIONS, + optional: true, + }, + showTranscript: { + type: "string", + label: "Show Transcript", + description: "To include the transcript of this episode or not?", + options: constants.TRANSCRIPT_OPTIONS, + optional: true, + }, + nextEpisodePubDate: { + type: "string", + label: "Next Episode Pub Date", + description: "For episodes pagination. It's the value of `next_episode_pub_date` from the response of last request. It is an Epoch Unix timestamp in milliseconds, i.e.: `1479154463000`", + optional: true, + }, + sort: { + type: "string", + label: "Sort", + description: "What type of contents do you want to search for?", + options: constants.EPISODES_SORTING_OPTIONS, + optional: true, + }, + language: { + type: "string", + label: "Language", + description: "Limit search results to a specific language. If not specified, it'll be any language", + async options() { + const response = await this.getLanguages(); + const languages = response.languages; + return languages.map((language) => ({ + value: language, + label: language, + })); + }, + optional: true, + }, + }, + methods: { + _baseUrl() { + return "https://listen-api.listennotes.com/api/v2"; + }, + async _makeRequest(opts = {}) { + const { + $ = this, + path, + headers, + ...otherOpts + } = opts; + return axios($, { + ...otherOpts, + url: this._baseUrl() + path, + headers: { + ...headers, + "X-ListenAPI-Key": `${this.$auth.api_key}`, + }, + }); + }, + async fullSearch(args = {}) { + return this._makeRequest({ + path: "/search", + ...args, + }); + }, + async getPodcastDetails({ + id, + ...args + }) { + return this._makeRequest({ + path: `/podcasts/${id}`, + ...args, + }); + }, + async getEpisodeDetails({ + id, + ...args + }) { + return this._makeRequest({ + path: `/episodes/${id}`, + ...args, + }); + }, + async getLanguages(args = {}) { + return this._makeRequest({ + path: "/languages", + ...args, + }); + }, + async listPodcasts({ + q, + language, + type, + offset, + ...args + }) { + if (!q) { + throw new ConfigurationError("You need to inform a query to list the IDs. Alternatively you can directly inform an ID unsing the custom expression function."); + } + + return this._makeRequest({ + path: "/search", + params: { + q: q, + type: type, + language: language, + offset: offset, + }, + ...args, + }); + }, + }, +}; diff --git a/components/listen_notes/package.json b/components/listen_notes/package.json index 98cda4dae11ac..cf135b7b6549b 100644 --- a/components/listen_notes/package.json +++ b/components/listen_notes/package.json @@ -1,13 +1,12 @@ { "name": "@pipedream/listen_notes", - "version": "0.0.2", + "version": "0.1.0", "description": "Pipedream Listen Notes Components", - "main": "dist/app/listen_notes.app.mjs", + "main": "listen_notes.app.mjs", "keywords": [ "pipedream", "listen_notes" ], - "files": ["dist"], "homepage": "https://pipedream.com/apps/listen_notes", "author": "Pipedream (https://pipedream.com/)", "publishConfig": {