From bf46620b5214a79233ac7455e1c8f6ecdb3421d1 Mon Sep 17 00:00:00 2001 From: Tanay Pant <7481165+tanay1337@users.noreply.github.com> Date: Sun, 7 Feb 2021 21:44:20 +0100 Subject: [PATCH] :sparkles: Add Peekalink node (#1411) * :sparkles: Add Peekalink node * :zap: Small improvements Co-authored-by: ricardo --- .../credentials/PeekalinkApi.credentials.ts | 18 ++++ .../nodes/Peekalink/GenericFunctions.ts | 47 ++++++++ .../nodes/Peekalink/Peekalink.node.ts | 101 ++++++++++++++++++ .../nodes-base/nodes/Peekalink/peekalink.png | Bin 0 -> 2453 bytes packages/nodes-base/package.json | 2 + 5 files changed, 168 insertions(+) create mode 100644 packages/nodes-base/credentials/PeekalinkApi.credentials.ts create mode 100644 packages/nodes-base/nodes/Peekalink/GenericFunctions.ts create mode 100644 packages/nodes-base/nodes/Peekalink/Peekalink.node.ts create mode 100644 packages/nodes-base/nodes/Peekalink/peekalink.png diff --git a/packages/nodes-base/credentials/PeekalinkApi.credentials.ts b/packages/nodes-base/credentials/PeekalinkApi.credentials.ts new file mode 100644 index 000000000..5d4edf3f6 --- /dev/null +++ b/packages/nodes-base/credentials/PeekalinkApi.credentials.ts @@ -0,0 +1,18 @@ +import { + ICredentialType, + NodePropertyTypes, +} from 'n8n-workflow'; + +export class PeekalinkApi implements ICredentialType { + name = 'peekalinkApi'; + displayName = 'Peekalink API'; + documentationUrl = 'peekalink'; + properties = [ + { + displayName: 'API Key', + name: 'apiKey', + type: 'string' as NodePropertyTypes, + default: '', + }, + ]; +} diff --git a/packages/nodes-base/nodes/Peekalink/GenericFunctions.ts b/packages/nodes-base/nodes/Peekalink/GenericFunctions.ts new file mode 100644 index 000000000..8e1c339fd --- /dev/null +++ b/packages/nodes-base/nodes/Peekalink/GenericFunctions.ts @@ -0,0 +1,47 @@ +import { + OptionsWithUri, +} from 'request'; + +import { + IExecuteFunctions, + IExecuteSingleFunctions, + IHookFunctions, + ILoadOptionsFunctions, +} from 'n8n-core'; + +import { + IDataObject, +} from 'n8n-workflow'; + +export async function peekalinkApiRequest(this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, method: string, resource: string, body: any = {}, qs: IDataObject = {}, uri?: string, option: IDataObject = {}): Promise { // tslint:disable-line:no-any + try { + const credentials = this.getCredentials('peekalinkApi'); + if (credentials === undefined) { + throw new Error('No credentials got returned!'); + } + let options: OptionsWithUri = { + headers: { + 'X-API-Key': credentials.apiKey, + }, + method, + qs, + body, + uri: uri || `https://api.peekalink.io${resource}`, + json: true, + }; + + options = Object.assign({}, options, option); + + return await this.helpers.request!(options); + } catch (error) { + + if (error.response && error.response.body && error.response.body.message) { + // Try to return the error prettier + const errorBody = error.response.body; + throw new Error(`Peekalink error response [${error.statusCode}]: ${errorBody.message}`); + } + + // Expected error data did not get returned so throw the actual error + throw error; + } +} diff --git a/packages/nodes-base/nodes/Peekalink/Peekalink.node.ts b/packages/nodes-base/nodes/Peekalink/Peekalink.node.ts new file mode 100644 index 000000000..adcaf4c90 --- /dev/null +++ b/packages/nodes-base/nodes/Peekalink/Peekalink.node.ts @@ -0,0 +1,101 @@ +import { + IExecuteFunctions, +} from 'n8n-core'; + +import { + IDataObject, + INodeExecutionData, + INodeType, + INodeTypeDescription, +} from 'n8n-workflow'; + +import { + peekalinkApiRequest, +} from './GenericFunctions'; + +export class Peekalink implements INodeType { + description: INodeTypeDescription = { + displayName: 'Peekalink', + name: 'peekalink', + icon: 'file:peekalink.png', + group: ['output'], + version: 1, + subtitle: '={{$parameter["operation"]', + description: 'Consume the Peekalink API', + defaults: { + name: 'Peekalink', + color: '#00ade8', + }, + inputs: ['main'], + outputs: ['main'], + credentials: [ + { + name: 'peekalinkApi', + required: true, + }, + ], + properties: [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + options: [ + { + name: 'Is available', + value: 'isAvailable', + description: 'Check whether preview for a given link is available', + }, + { + name: 'Preview', + value: 'preview', + description: 'Return the preview for a link', + }, + ], + default: 'preview', + description: 'The operation to perform.', + }, + { + displayName: 'URL', + name: 'url', + type: 'string', + default: '', + description: '', + required: true, + }, + ], + }; + + async execute(this: IExecuteFunctions): Promise { + const items = this.getInputData(); + const returnData: IDataObject[] = []; + const length = items.length as unknown as number; + const qs: IDataObject = {}; + let responseData; + const operation = this.getNodeParameter('operation', 0) as string; + + for (let i = 0; i < length; i++) { + if (operation === 'isAvailable') { + const url = this.getNodeParameter('url', i) as string; + const body: IDataObject = { + link: url, + }; + + responseData = await peekalinkApiRequest.call(this, 'POST', `/is-available/`, body); + } + if (operation === 'preview') { + const url = this.getNodeParameter('url', i) as string; + const body: IDataObject = { + link: url, + }; + + responseData = await peekalinkApiRequest.call(this, 'POST', `/`, body); + } + if (Array.isArray(responseData)) { + returnData.push.apply(returnData, responseData as IDataObject[]); + } else { + returnData.push(responseData as IDataObject); + } + } + return [this.helpers.returnJsonArray(returnData)]; + } +} diff --git a/packages/nodes-base/nodes/Peekalink/peekalink.png b/packages/nodes-base/nodes/Peekalink/peekalink.png new file mode 100644 index 0000000000000000000000000000000000000000..dc2e8426ff1c672f17f2453a4d7cf4d8b16bc630 GIT binary patch literal 2453 zcmV;G32OF%lX?Q#*k)>T)#v{iSyx;j(0-En7~sU2tR=#-NLl&aJViYNpULcnl~1i~%c z38-8oB2E>O5JGNmbnSN5FYX7o>(;5Zx>`^~L;)eY)6VW}pZ)N@ZxT=-2_#sauW<4~Aa&GkzIeNKy=;7wie&BwR+tW)F=;7w0n^!pdfqS`%n-3V+t_bCKGu@A0)Ws{r zJ-*T{ce{DTUq0X#;2}}q5y?eA$-z@1!yw7RFv)o2>t3IeJyHZaUkp1>GOf$=n;n(y zwotBBON2zdQM-^^G zR$vq~w*U{h`RH?j9wJ$IMlvzXmEyZ_>93|^{t0F0Nnq!uIkNF!c-DWXQt#^SQ~2A* zwYa|16}of`v;uu37mppwn{`?Wd$@G%bg_*q2Q10LQzApZmkH{#y=q*EZot*ur*JK* z7T2R{aAQXmZbp{lHox@iJKIzN91e%m!z;=d?KBIWiD5E5t87xyu-WJ*Ip`y~=p~BV zo{Trew1C>*jL$x4!j(RtOdpq9)eqkwlPd{dy_O_N! zq!5_ni{p)`h&P~yaazuizv6AZF23S7_j%4MtN&$udMXl3BgF|uRK#~qxw&s6$~SiL zig2G>h#to2>FDvL6`jaR(8VhT>$FD&MtBm5our){A?ccDB;(J6;n_C^h^((a{P+)j zM2<(?{Qr2`R8o?)K$K`jN}?61i58>_ERZFbp-3=6nPATMw4SSOMONS&CWd~?E5?1U z2TxBnE)F{qRJJ2Q(O)VQc)(me?$nDFQeAOE3h_x+BqmuwLtBuVXn|Bbq=xi)UAIZf-t^;=P9$$HN zvO2qxDMX7X>=RKqFcvy-9H%{i{!8?kbyxN@;_B`?T>H2de|J7Osyzap4n?Ne5GAIt zOHARDWEwg~WJ9cw!jU8j@yQpr36iNlyvXUi1QUu9jHpbuEgP@CDb5s3?LSM$(C7vR z`UI{=sr-C8%kfIM#0Gwf4Gw6=>HXqMTgMxgBDnZb>KN$p{`Y*WZoTdx8$+9Md9NC* z)4qWkN56}^_UhJS6t<^PAQBsRDK${j5{1Mh z3dus7fWzT%R7utV=bkn@PH)xG4%8o|9~}N6bkW)ZGuG!>ut9FYdpS<%$;Ry#U0%Xo zSu8Z|G!4yOS!n_bq>0a8S*oLkN#|HqZ2aPlGSm0VD-2jt-GSF?JFwtnJLc8t5Za)_ zoJK8zPHTSeK5bn6tE-DmSW{redW8k7)9w!6BfhvRT4ZCctkKJx4kr}EW3Ma$ePvAw zt2834)QA<81}v@az-zU7EI8!?ds>U2CJh45w7I`ZR+M+*tr8O)(0OKXisS!%?ui%eLPZ=TYg z+9$FN9blbi_OyV3mLyt}Jgv7>W%!ZzaiIp=iMADHp(b$%A#DLJv*qDsyh1@ zv7w@#4i!_QaYKR4ZHoG_6y{OTQ<*=sLHj>P zHdbpqi;LbWpt%i!XEd0@9AwTbi@v9qRvYkoITJ%24-PZlkxvblRj^v?$i@LJetIJZ zo^AUeka2pB>z+QLAC<`7EHz?vu?cGnEh*DEe?W690$N%TaPESCLrd^kZ9;I9*5x46 zVS$U&E6R-%{;JPvWr-1CWyT+T-S11Gl}aPR%8dABr2$K74EmYw$L9(w>vV*QMJM!K zGu@BRwY;j64izW#SWu_e%yd6K7YjT8R6FL^>xDDjkI%K}1RWRW*6T2@zJ0??_v3T1 zu%Qjwm+W2aBh9UMeqEgDUi=~!HdyV4Z2U6FtMA4?W(BD=-GR+*2xxBedD8kn-jTut T{q1mO00000NkvXXu0mjfUC6iC literal 0 HcmV?d00001 diff --git a/packages/nodes-base/package.json b/packages/nodes-base/package.json index 851e13e54..30f82f133 100644 --- a/packages/nodes-base/package.json +++ b/packages/nodes-base/package.json @@ -164,6 +164,7 @@ "dist/credentials/PagerDutyApi.credentials.js", "dist/credentials/PagerDutyOAuth2Api.credentials.js", "dist/credentials/PayPalApi.credentials.js", + "dist/credentials/PeekalinkApi.credentials.js", "dist/credentials/PhantombusterApi.credentials.js", "dist/credentials/PipedriveApi.credentials.js", "dist/credentials/PipedriveOAuth2Api.credentials.js", @@ -410,6 +411,7 @@ "dist/nodes/PagerDuty/PagerDuty.node.js", "dist/nodes/PayPal/PayPal.node.js", "dist/nodes/PayPal/PayPalTrigger.node.js", + "dist/nodes/Peekalink/Peekalink.node.js", "dist/nodes/Phantombuster/Phantombuster.node.js", "dist/nodes/Pipedrive/Pipedrive.node.js", "dist/nodes/Pipedrive/PipedriveTrigger.node.js",