diff --git a/components/serphouse/actions/google-jobs-search/google-jobs-search.mjs b/components/serphouse/actions/google-jobs-search/google-jobs-search.mjs new file mode 100644 index 0000000000000..6b6f1863e500d --- /dev/null +++ b/components/serphouse/actions/google-jobs-search/google-jobs-search.mjs @@ -0,0 +1,80 @@ +import serphouse from "../../serphouse.app.mjs"; + +export default { + key: "serphouse-google-jobs-search", + name: "Google Jobs Search", + description: "Performs a Google Jobs search using the Serphouse API. [See the documentation](https://docs.serphouse.com/google-apis/google-jobs-api)", + version: "0.0.1", + type: "action", + annotations: { + destructiveHint: false, + openWorldHint: true, + readOnlyHint: true, + }, + props: { + serphouse, + query: { + propDefinition: [ + serphouse, + "query", + ], + }, + domain: { + propDefinition: [ + serphouse, + "domain", + () => ({ + type: "google", + }), + ], + }, + language: { + propDefinition: [ + serphouse, + "language", + ({ domain }) => ({ + domain, + }), + ], + }, + locationAlert: { + propDefinition: [ + serphouse, + "locationAlert", + ], + }, + locationId: { + propDefinition: [ + serphouse, + "locationId", + ({ domain }) => ({ + domain, + }), + ], + }, + dateRange: { + propDefinition: [ + serphouse, + "dateRange", + ], + }, + }, + async run({ $ }) { + const response = await this.serphouse.googleJobsSearch({ + $, + data: { + data: { + q: this.query, + domain: this.domain, + lang: this.language, + loc_id: this.locationId, + date_range: this.dateRange, + }, + }, + }); + if (response.status === "success") { + $.export("$summary", `Successfully performed Google Jobs search for "${this.query}".`); + } + return response; + }, +}; diff --git a/components/serphouse/actions/perform-search/perform-search.mjs b/components/serphouse/actions/perform-search/perform-search.mjs new file mode 100644 index 0000000000000..3537d627b264b --- /dev/null +++ b/components/serphouse/actions/perform-search/perform-search.mjs @@ -0,0 +1,136 @@ +import serphouse from "../../serphouse.app.mjs"; +import { ConfigurationError } from "@pipedream/platform"; + +export default { + key: "serphouse-perform-search", + name: "Perform Search", + description: "Performs a search using the Serphouse API. [See the documentation](https://docs.serphouse.com/serp-api/live-using-http-get-method)", + version: "0.0.1", + type: "action", + annotations: { + destructiveHint: false, + openWorldHint: true, + readOnlyHint: true, + }, + props: { + serphouse, + query: { + propDefinition: [ + serphouse, + "query", + ], + }, + domain: { + propDefinition: [ + serphouse, + "domain", + ], + }, + language: { + propDefinition: [ + serphouse, + "language", + ({ domain }) => ({ + domain, + }), + ], + }, + device: { + type: "string", + label: "Device", + description: "The device to use for the search", + options: [ + "desktop", + "tablet", + "mobile", + ], + }, + serpType: { + type: "string", + label: "SERP Type", + description: "The type of SERP to use for the search", + options: [ + "web", + "news", + "image", + ], + }, + locationAlert: { + propDefinition: [ + serphouse, + "locationAlert", + ], + }, + locationId: { + propDefinition: [ + serphouse, + "locationId", + ({ domain }) => ({ + domain, + }), + ], + optional: true, + }, + verbatim: { + type: "boolean", + label: "Verbatim", + description: "If true, the search will be performed verbatim", + optional: true, + }, + gfilter: { + type: "boolean", + label: "GFilter", + description: "Parameter defines if the filters for 'Similar Results' and 'Omitted Results' are on or off. It can be set to `true` (default) to enable these filters, or `false` to disable these filters.", + optional: true, + default: true, + }, + page: { + type: "integer", + label: "Page", + description: "Give specific page to get the result of that page number. By default it will get you first page", + optional: true, + }, + numResults: { + type: "integer", + label: "Number of Results", + description: "Define number of result you want to get per page. By default you will get top 100 results.", + optional: true, + }, + dateRange: { + propDefinition: [ + serphouse, + "dateRange", + ], + }, + }, + async run({ $ }) { + const type = this.serphouse.getDomainType(this.domain); + if (!this.locationId && (type === "google" || type === "bing")) { + throw new ConfigurationError("Location is required for Google and Bing searches"); + } + const response = await this.serphouse.performSearch({ + $, + params: { + q: this.query, + domain: this.domain, + lang: this.language, + device: this.device, + serp_type: this.serpType, + loc_id: this.locationId, + verbatim: this.verbatim + ? "1" + : "0", + gfilter: this.gfilter + ? "1" + : "0", + page: this.page, + num_result: this.numResults, + date_range: this.dateRange, + }, + }); + if (response.status === "success") { + $.export("$summary", `Successfully performed search for "${this.query}".`); + } + return response; + }, +}; diff --git a/components/serphouse/package.json b/components/serphouse/package.json index f493623ac967c..0d3136b4022eb 100644 --- a/components/serphouse/package.json +++ b/components/serphouse/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/serphouse", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream SERPhouse Components", "main": "serphouse.app.mjs", "keywords": [ @@ -11,5 +11,8 @@ "author": "Pipedream (https://pipedream.com/)", "publishConfig": { "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^3.1.0" } } diff --git a/components/serphouse/serphouse.app.mjs b/components/serphouse/serphouse.app.mjs index 6db701d8211f1..7441b30eb7a6d 100644 --- a/components/serphouse/serphouse.app.mjs +++ b/components/serphouse/serphouse.app.mjs @@ -1,11 +1,170 @@ +import { + axios, ConfigurationError, +} from "@pipedream/platform"; + export default { type: "app", app: "serphouse", - propDefinitions: {}, + propDefinitions: { + domain: { + type: "string", + label: "Domain", + description: "The domain to search", + async options({ type }) { + const { results } = await this.listDomains(); + if (type) { + return results.filter((domain) => domain.includes(type)); + } + return results; + }, + }, + language: { + type: "string", + label: "Language", + description: "The language to use for the search", + async options({ domain }) { + if (!domain) { + return []; + } + const type = this.getDomainType(domain); + const { results } = await this.listLanguages({ + type, + }); + return Object.entries(results).map(([ + key, + value, + ]) => ({ + label: value, + value: key, + })); + }, + }, + locationAlert: { + type: "alert", + alertType: "info", + content: "Please enter a search query in Locations to list location options.", + }, + locationId: { + type: "string", + label: "Location", + description: "Search for a location or enter a location ID. Required for Google and Bing searches.", + useQuery: true, + async options({ + domain, query, + }) { + if (!domain || !query) { + return []; + } + const type = this.getDomainType(domain); + const { results } = await this.listLocations({ + params: { + q: query, + type, + }, + }); + return results.map(({ + id: value, + name: label, + }) => ({ + value, + label, + })); + }, + }, + query: { + type: "string", + label: "Query", + description: "Search phrase that you want to search", + }, + dateRange: { + type: "string", + label: "Date Range", + description: "Parameter defines the date range for the search", + optional: true, + options: [ + { + label: "Past hour", + value: "h", + }, + { + label: "Past 24 hours", + value: "d", + }, + { + label: "Past week", + value: "w", + }, + { + label: "Past month", + value: "m", + }, + { + label: "Past year", + value: "y", + }, + ], + }, + }, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + _baseUrl() { + return "https://api.serphouse.com"; + }, + _makeRequest({ + $ = this, path, ...opts + }) { + return axios($, { + url: `${this._baseUrl()}${path}`, + headers: { + Authorization: `Bearer ${this.$auth.api_key}`, + }, + ...opts, + }); + }, + getDomainType(domain) { + const type = domain.includes("google") + ? "google" + : domain.includes("bing") + ? "bing" + : domain.includes("yahoo") + ? "yahoo" + : "other"; + if (type === "other") { + throw new ConfigurationError("Invalid domain"); + } + return type; + }, + performSearch(opts = {}) { + return this._makeRequest({ + path: "/serp/live", + ...opts, + }); + }, + googleJobsSearch(opts = {}) { + return this._makeRequest({ + path: "/google-jobs-api", + method: "post", + ...opts, + }); + }, + listDomains(opts = {}) { + return this._makeRequest({ + path: "/domain/list", + ...opts, + }); + }, + listLanguages({ + type, ...opts + }) { + return this._makeRequest({ + path: `/language/list/${type}`, + ...opts, + }); + }, + listLocations(opts = {}) { + return this._makeRequest({ + path: "/location/search", + ...opts, + }); }, }, -}; \ No newline at end of file +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b39136a8e242c..b56cd98d4b7de 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -3414,8 +3414,7 @@ importers: components/cronly: {} - components/cronlytic: - specifiers: {} + components/cronlytic: {} components/crossmint: {} @@ -3732,8 +3731,7 @@ importers: components/deel: {} - components/deep_tagger: - specifiers: {} + components/deep_tagger: {} components/deepgram: dependencies: @@ -8192,8 +8190,7 @@ importers: specifier: ^1.0.3 version: 1.0.3 - components/linkupapi: - specifiers: {} + components/linkupapi: {} components/linode: dependencies: @@ -13001,7 +12998,11 @@ importers: components/serpdog: {} - components/serphouse: {} + components/serphouse: + dependencies: + '@pipedream/platform': + specifier: ^3.1.0 + version: 3.1.0 components/serply: dependencies: