From b8b5ba4e79cd346205b8b0b89a8a288b0eca9d39 Mon Sep 17 00:00:00 2001 From: neomaking Date: Wed, 16 Oct 2019 22:53:30 +0200 Subject: [PATCH 1/5] Add Discord Webhook node --- .../credentials/DiscordApi.credentials.ts | 18 ++ .../DiscordWebhook/DiscordWebhook.node.ts | 185 ++++++++++++++++++ .../nodes/DiscordWebhook/discord.png | Bin 0 -> 2365 bytes packages/nodes-base/package.json | 4 +- 4 files changed, 206 insertions(+), 1 deletion(-) create mode 100644 packages/nodes-base/credentials/DiscordApi.credentials.ts create mode 100644 packages/nodes-base/nodes/DiscordWebhook/DiscordWebhook.node.ts create mode 100644 packages/nodes-base/nodes/DiscordWebhook/discord.png diff --git a/packages/nodes-base/credentials/DiscordApi.credentials.ts b/packages/nodes-base/credentials/DiscordApi.credentials.ts new file mode 100644 index 000000000..96bd2fb2e --- /dev/null +++ b/packages/nodes-base/credentials/DiscordApi.credentials.ts @@ -0,0 +1,18 @@ +import { + ICredentialType, + NodePropertyTypes, +} from 'n8n-workflow'; + + +export class DiscordApi implements ICredentialType { + name = 'discordApi'; + displayName = 'Discord API'; + properties = [ + { + displayName: 'Webhook URI', + name: 'webhookUri', + type: 'string' as NodePropertyTypes, + default: '', + }, + ]; +} diff --git a/packages/nodes-base/nodes/DiscordWebhook/DiscordWebhook.node.ts b/packages/nodes-base/nodes/DiscordWebhook/DiscordWebhook.node.ts new file mode 100644 index 000000000..08266f9ca --- /dev/null +++ b/packages/nodes-base/nodes/DiscordWebhook/DiscordWebhook.node.ts @@ -0,0 +1,185 @@ +import { IExecuteFunctions } from 'n8n-core'; +import { + IDataObject, + INodeTypeDescription, + INodeExecutionData, + INodeType, +} from 'n8n-workflow'; + +interface Attachment { + fields: { + item?: object[]; + }; +} + +export class DiscordWebhook implements INodeType { + description: INodeTypeDescription = { + displayName: 'Discord Webhook', + name: 'discordwebhook', + icon: 'file:discord.png', + group: ['output'], + version: 1, + subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}', + description: 'Sends data to Discord', + defaults: { + name: 'Discord Webhook', + color: '#BB2244', + }, + inputs: ['main'], + outputs: ['main'], + credentials: [ + { + name: 'discordApi', + required: true, + } + ], + properties: [ + { + displayName: 'Resource', + name: 'resource', + type: 'options', + options: [ + { + name: 'Message', + value: 'message', + }, + ], + default: 'message', + description: 'The resource to operate on.', + }, + + + + // ---------------------------------- + // operations + // ---------------------------------- + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'message', + ], + }, + }, + options: [ + { + name: 'Post', + value: 'post', + description: 'Post a message into a channel', + }, + ], + default: 'post', + description: 'The operation to perform.', + }, + + // ---------------------------------- + // message + // ---------------------------------- + + // ---------------------------------- + // message:post + // ---------------------------------- + { + displayName: 'Text', + name: 'text', + type: 'string', + typeOptions: { + alwaysOpenEditWindow: true, + }, + default: '', + displayOptions: { + show: { + operation: [ + 'post' + ], + resource: [ + 'message', + ], + }, + }, + description: 'The text to send.', + } + ], + }; + + + + async execute(this: IExecuteFunctions): Promise { + const items = this.getInputData(); + const returnData: IDataObject[] = []; + + const credentials = this.getCredentials('discordApi'); + + if (credentials === undefined) { + throw new Error('No credentials got returned!'); + } + + let operation: string; + let resource: string; + let requestMethod = 'POST'; + + // For Post + let body: IDataObject; + // For Query string + let qs: IDataObject; + + for (let i = 0; i < items.length; i++) { + body = {}; + qs = {}; + + resource = this.getNodeParameter('resource', i) as string; + operation = this.getNodeParameter('operation', i) as string; + + if (resource === 'message') { + if (operation === 'post') { + // ---------------------------------- + // message:post + // ---------------------------------- + + requestMethod = 'POST'; + body.content = this.getNodeParameter('text', i) as string; + + const attachments = this.getNodeParameter('attachments', i, []) as unknown as Attachment[]; + + // The node does save the fields data differently than the API + // expects so fix the data befre we send the request + for (const attachment of attachments) { + if (attachment.fields !== undefined) { + if (attachment.fields.item !== undefined) { + // Move the field-content up + // @ts-ignore + attachment.fields = attachment.fields.item; + } else { + // If it does not have any items set remove it + delete attachment.fields; + } + } + } + body['attachments'] = attachments; + } + } else { + throw new Error(`The resource "${resource}" is not known!`); + } + + const options = { + method: requestMethod, + body, + qs, + uri: `${credentials.webhookUri}`, + headers: { + 'content-type': 'application/json; charset=utf-8' + }, + json: true + }; + + const responseData = await this.helpers.request(options); + + returnData.push(responseData as IDataObject); + } + + return [this.helpers.returnJsonArray(returnData)]; + } +} diff --git a/packages/nodes-base/nodes/DiscordWebhook/discord.png b/packages/nodes-base/nodes/DiscordWebhook/discord.png new file mode 100644 index 0000000000000000000000000000000000000000..f42e5500f21ff870076eb989b3787c7b6fe329f1 GIT binary patch literal 2365 zcmV-D3BvY?P)tKn%{z!-onf7_xSyttmKrX z;^F1?+~M`;>-c()+}Ymry2R{$liiV`;p*-AjGo}i((t&#>(AElskY~uspD96)e`rQ zh5!Hvk4Z#9RCt{2oolyqJP?M7R1Qk1mTKwY{r^Am)v7*t zEeiw!fj}S-2m}IwKp+rEpyRFB%&Fpb)XKNr<(xA#uNdd~ZmWs#_@Ic`OAtZyp`|um zZyA7xsxGHaaNtIZM@KhyYx~O(qi+Bfhh%sFvVhPEVHP?_V6S0J} zRWU|*ZWf`Cs|GRVbCXEK)wI@pxz$*<*1ZbEyo5g3;vU<5`*jD%pR!=(K8G>6KpjD#S{S@v*!2?WmEC}19C zeNL$#~D?3oxpgZdakWhbm?2n9sC*#z6dL?YJkKW5m(x>O*p!8cLD|_n#hZj!hw<10HZE*{GSFIs{uv@Vfh2v$lt&Kqux>VsjYm6PCp|_6i^IEzWC73h^Iec z;w$K9q?%U8O~um2s-2M#1q_3lml2<(g^$;B;JdOzUx$01<@bSP27B4;p`B4Wb8OH2 z=}g6p6oM<_?CHNFm?zREzmu6d+8Jes57Unuk?{VL(Wg)P2;#}!RJw@N&nPY!H$9~& z>bYX$HSWY^EkYbLp`Ve6yJIUkL=VE{yLM!|3FjFZk=Vb{Do0S~iv0VVx1Hzok>r& zN|S7}YG#yJ09|hkZ>^;}8*Vc5USb7kW|Z9i(PeD4>rVa%Suz~STj*vKTWN0R!?)|P zvtp9fqr~r_nURV|!p?}&sijV9mi0%8rK6eA6Bp}v4m*i%I$Ic$$yOE`pqG(gNx7s| zO|;#v!_NFDi+O3^&KRR?OK$T$LG}zNZp#vqW;Dv@VwC#izQ+`=YY}~0v_x!AJSC0{ z(90<6K+g#4#?Z?9{65DMP6k&|GFPvjs%E~Jke+)Sk#1o`m#t|8aQpdeZ6T*gt<2ob4B*lAkdKvX^k^j?0 zXas0(tC~GlO^H`mn&%FKjMhAied`2$)H5;mtP^4-0j!qO{Z{jgtG#QX9hn}ib0a;2 znQ;5jJfn5}FPb*ora|xKmCz`kfzjG|Q=;Y%zSo}sSQv|>d0g$Uup38w|F@LWn}E}- z|E|JaE4_?Zu(rA+j8NkI+GH;dLxc;~GU81u&HDgMbo;CKJjCk%lGeY-IUi;Bm zLF(Q^7CK_K4^C{tJpVK%n0~v-Jyd=b;Wyi~_Y4d&O1w?S{qs;NLEPS-WX{EHde7+V zO4c(gR@%(!o9kcvR=PO$(>+HpqCAUEx46}Ew{dYl6VCAKQv_n)+(}Z4X5w>X8y<1J z;qh#Ulo31e^L-RO_IZ#HO40k=JV|6t+MPQ-r+h{r9$5~pZK#0{U@_t)7z*?< z5{Jx$Bab}&LE{#-s4JcZ&tRK67ZCItspC^(3mmM6Y%ymaY{K)NvGei6QRcqH|EWLb zAicS>frJO`T{_9U-6P%(_1$FSj+dJ}k4zYjnum~Y(hi{ui`dwd4~EZ`V@5N# zs8Ru3#-9v-mu9c=IgB?^#(yYmKF`B*#%DP3A7UqruxRq|lX4nGzolTAEAL8c`qNr! z0Xc%S3mAbB7?&ep1V&(7j(`yufpIwkMqmWS

yo5g3;vU>qgcku{Anx`#Z^Z(NdK z^bZy*V4UZ-N=crMO&F|zai-s#<>6suhHC|klG7tPg$gSk=ebhBI4XIja*>B+T}HV- zR4~r-lkBf^PTOR}_f^3-oc&CTUWX3C5s*q4(^)F={p$X3>Nh2sU-CJ6BnjRRH;{YH z8cal_N%iTGz5W=ar-~oL7nJC8nk&*COZL)fhA#QT8)iYYw8LgkOu>rDPM$6&rXS8>uDT6byI@0I9!pZg6A$Y6Ff5C{YU jfj}S-2m}IwKug#EvX7ZV_!qZ$00000NkvXXu0mjfs?MLh literal 0 HcmV?d00001 diff --git a/packages/nodes-base/package.json b/packages/nodes-base/package.json index c7d380907..e48c7ca9f 100644 --- a/packages/nodes-base/package.json +++ b/packages/nodes-base/package.json @@ -51,7 +51,8 @@ "dist/credentials/TelegramApi.credentials.js", "dist/credentials/TrelloApi.credentials.js", "dist/credentials/TwilioApi.credentials.js", - "dist/credentials/TypeformApi.credentials.js" + "dist/credentials/TypeformApi.credentials.js", + "dist/credentials/DiscordApi.credentials.js" ], "nodes": [ "dist/nodes/ActiveCampaign/ActiveCampaign.node.js", @@ -64,6 +65,7 @@ "dist/nodes/Chargebee/ChargebeeTrigger.node.js", "dist/nodes/Cron.node.js", "dist/nodes/Dropbox/Dropbox.node.js", + "dist/nodes/DiscordWebhook/DiscordWebhook.node.js", "dist/nodes/EditImage.node.js", "dist/nodes/EmailReadImap.node.js", "dist/nodes/EmailSend.node.js", From 027ce90f896426e84077009a324a3d1922d2250c Mon Sep 17 00:00:00 2001 From: neomaking Date: Sun, 20 Oct 2019 13:22:57 +0200 Subject: [PATCH 2/5] Handling error and kicking out unused code --- .../DiscordWebhook/DiscordWebhook.node.ts | 43 ++++++------------- 1 file changed, 13 insertions(+), 30 deletions(-) diff --git a/packages/nodes-base/nodes/DiscordWebhook/DiscordWebhook.node.ts b/packages/nodes-base/nodes/DiscordWebhook/DiscordWebhook.node.ts index 08266f9ca..0fb514778 100644 --- a/packages/nodes-base/nodes/DiscordWebhook/DiscordWebhook.node.ts +++ b/packages/nodes-base/nodes/DiscordWebhook/DiscordWebhook.node.ts @@ -6,12 +6,6 @@ import { INodeType, } from 'n8n-workflow'; -interface Attachment { - fields: { - item?: object[]; - }; -} - export class DiscordWebhook implements INodeType { description: INodeTypeDescription = { displayName: 'Discord Webhook', @@ -23,7 +17,7 @@ export class DiscordWebhook implements INodeType { description: 'Sends data to Discord', defaults: { name: 'Discord Webhook', - color: '#BB2244', + color: '#7289da', }, inputs: ['main'], outputs: ['main'], @@ -110,6 +104,7 @@ export class DiscordWebhook implements INodeType { async execute(this: IExecuteFunctions): Promise { const items = this.getInputData(); const returnData: IDataObject[] = []; + let responseData; const credentials = this.getCredentials('discordApi'); @@ -123,12 +118,9 @@ export class DiscordWebhook implements INodeType { // For Post let body: IDataObject; - // For Query string - let qs: IDataObject; for (let i = 0; i < items.length; i++) { body = {}; - qs = {}; resource = this.getNodeParameter('resource', i) as string; operation = this.getNodeParameter('operation', i) as string; @@ -141,24 +133,6 @@ export class DiscordWebhook implements INodeType { requestMethod = 'POST'; body.content = this.getNodeParameter('text', i) as string; - - const attachments = this.getNodeParameter('attachments', i, []) as unknown as Attachment[]; - - // The node does save the fields data differently than the API - // expects so fix the data befre we send the request - for (const attachment of attachments) { - if (attachment.fields !== undefined) { - if (attachment.fields.item !== undefined) { - // Move the field-content up - // @ts-ignore - attachment.fields = attachment.fields.item; - } else { - // If it does not have any items set remove it - delete attachment.fields; - } - } - } - body['attachments'] = attachments; } } else { throw new Error(`The resource "${resource}" is not known!`); @@ -167,7 +141,6 @@ export class DiscordWebhook implements INodeType { const options = { method: requestMethod, body, - qs, uri: `${credentials.webhookUri}`, headers: { 'content-type': 'application/json; charset=utf-8' @@ -175,7 +148,17 @@ export class DiscordWebhook implements INodeType { json: true }; - const responseData = await this.helpers.request(options); + try { + responseData = await this.helpers.request(options); + } catch (error) { + if (error.statusCode === 429) { + // Return API Rate Limit error + throw new Error(`You are rate limited, please retry in ${error.response.body.retry_after} ms.`); + } + + // If it's another error code then return the JSON response + throw error; + } returnData.push(responseData as IDataObject); } From f2af8d706dfe7c52438af6aa2b34d04eb3b84ac8 Mon Sep 17 00:00:00 2001 From: neomaking Date: Sun, 20 Oct 2019 22:14:42 +0200 Subject: [PATCH 3/5] Handling rating limit of Discord Webhook API --- .../nodes/DiscordWebhook/DiscordWebhook.node.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/nodes-base/nodes/DiscordWebhook/DiscordWebhook.node.ts b/packages/nodes-base/nodes/DiscordWebhook/DiscordWebhook.node.ts index 0fb514778..1587b56c0 100644 --- a/packages/nodes-base/nodes/DiscordWebhook/DiscordWebhook.node.ts +++ b/packages/nodes-base/nodes/DiscordWebhook/DiscordWebhook.node.ts @@ -152,12 +152,15 @@ export class DiscordWebhook implements INodeType { responseData = await this.helpers.request(options); } catch (error) { if (error.statusCode === 429) { - // Return API Rate Limit error - throw new Error(`You are rate limited, please retry in ${error.response.body.retry_after} ms.`); + // Waiting rating limit + setTimeout(async () => { + responseData = await this.helpers.request(options) + }, + error.response.body.retry_after); + }else { + // If it's another error code then return the JSON response + throw error; } - - // If it's another error code then return the JSON response - throw error; } returnData.push(responseData as IDataObject); From f033e4c886ab5ac102e21d10b364d5e4e15c22d2 Mon Sep 17 00:00:00 2001 From: neomaking Date: Sun, 20 Oct 2019 23:26:58 +0200 Subject: [PATCH 4/5] Refactored into simple Discord node so it can be extended later --- .../credentials/DiscordApi.credentials.ts | 18 ---- .../Discord.node.ts} | 94 ++++++------------ .../{DiscordWebhook => Discord}/discord.png | Bin packages/nodes-base/package.json | 5 +- 4 files changed, 33 insertions(+), 84 deletions(-) delete mode 100644 packages/nodes-base/credentials/DiscordApi.credentials.ts rename packages/nodes-base/nodes/{DiscordWebhook/DiscordWebhook.node.ts => Discord/Discord.node.ts} (62%) rename packages/nodes-base/nodes/{DiscordWebhook => Discord}/discord.png (100%) diff --git a/packages/nodes-base/credentials/DiscordApi.credentials.ts b/packages/nodes-base/credentials/DiscordApi.credentials.ts deleted file mode 100644 index 96bd2fb2e..000000000 --- a/packages/nodes-base/credentials/DiscordApi.credentials.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { - ICredentialType, - NodePropertyTypes, -} from 'n8n-workflow'; - - -export class DiscordApi implements ICredentialType { - name = 'discordApi'; - displayName = 'Discord API'; - properties = [ - { - displayName: 'Webhook URI', - name: 'webhookUri', - type: 'string' as NodePropertyTypes, - default: '', - }, - ]; -} diff --git a/packages/nodes-base/nodes/DiscordWebhook/DiscordWebhook.node.ts b/packages/nodes-base/nodes/Discord/Discord.node.ts similarity index 62% rename from packages/nodes-base/nodes/DiscordWebhook/DiscordWebhook.node.ts rename to packages/nodes-base/nodes/Discord/Discord.node.ts index 1587b56c0..6015a2bf1 100644 --- a/packages/nodes-base/nodes/DiscordWebhook/DiscordWebhook.node.ts +++ b/packages/nodes-base/nodes/Discord/Discord.node.ts @@ -6,27 +6,21 @@ import { INodeType, } from 'n8n-workflow'; -export class DiscordWebhook implements INodeType { +export class Discord implements INodeType { description: INodeTypeDescription = { - displayName: 'Discord Webhook', - name: 'discordwebhook', + displayName: 'Discord', + name: 'discord', icon: 'file:discord.png', group: ['output'], version: 1, - subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}', + subtitle: '={{$parameter["resource"]}}', description: 'Sends data to Discord', defaults: { - name: 'Discord Webhook', + name: 'Discord', color: '#7289da', }, inputs: ['main'], outputs: ['main'], - credentials: [ - { - name: 'discordApi', - required: true, - } - ], properties: [ { displayName: 'Resource', @@ -34,41 +28,14 @@ export class DiscordWebhook implements INodeType { type: 'options', options: [ { - name: 'Message', - value: 'message', + name: 'Webhook', + value: 'webhook', }, ], - default: 'message', + default: 'webhook', description: 'The resource to operate on.', }, - - - // ---------------------------------- - // operations - // ---------------------------------- - { - displayName: 'Operation', - name: 'operation', - type: 'options', - displayOptions: { - show: { - resource: [ - 'message', - ], - }, - }, - options: [ - { - name: 'Post', - value: 'post', - description: 'Post a message into a channel', - }, - ], - default: 'post', - description: 'The operation to perform.', - }, - // ---------------------------------- // message // ---------------------------------- @@ -76,6 +43,23 @@ export class DiscordWebhook implements INodeType { // ---------------------------------- // message:post // ---------------------------------- + { + displayName: 'Webhook URL', + name: 'webhookUri', + type: 'string', + typeOptions: { + alwaysOpenEditWindow: true, + }, + default: '', + displayOptions: { + show: { + resource: [ + 'webhook', + ], + }, + }, + description: 'The webhook url', + }, { displayName: 'Text', name: 'text', @@ -86,11 +70,8 @@ export class DiscordWebhook implements INodeType { default: '', displayOptions: { show: { - operation: [ - 'post' - ], resource: [ - 'message', + 'webhook', ], }, }, @@ -106,13 +87,6 @@ export class DiscordWebhook implements INodeType { const returnData: IDataObject[] = []; let responseData; - const credentials = this.getCredentials('discordApi'); - - if (credentials === undefined) { - throw new Error('No credentials got returned!'); - } - - let operation: string; let resource: string; let requestMethod = 'POST'; @@ -120,20 +94,14 @@ export class DiscordWebhook implements INodeType { let body: IDataObject; for (let i = 0; i < items.length; i++) { + const webhookUri = this.getNodeParameter('webhookUri', i) as string; body = {}; resource = this.getNodeParameter('resource', i) as string; - operation = this.getNodeParameter('operation', i) as string; - if (resource === 'message') { - if (operation === 'post') { - // ---------------------------------- - // message:post - // ---------------------------------- - - requestMethod = 'POST'; - body.content = this.getNodeParameter('text', i) as string; - } + if (resource === 'webhook') { + requestMethod = 'POST'; + body.content = this.getNodeParameter('text', i) as string; } else { throw new Error(`The resource "${resource}" is not known!`); } @@ -141,7 +109,7 @@ export class DiscordWebhook implements INodeType { const options = { method: requestMethod, body, - uri: `${credentials.webhookUri}`, + uri: `${webhookUri}`, headers: { 'content-type': 'application/json; charset=utf-8' }, diff --git a/packages/nodes-base/nodes/DiscordWebhook/discord.png b/packages/nodes-base/nodes/Discord/discord.png similarity index 100% rename from packages/nodes-base/nodes/DiscordWebhook/discord.png rename to packages/nodes-base/nodes/Discord/discord.png diff --git a/packages/nodes-base/package.json b/packages/nodes-base/package.json index e48c7ca9f..b932531a1 100644 --- a/packages/nodes-base/package.json +++ b/packages/nodes-base/package.json @@ -51,8 +51,7 @@ "dist/credentials/TelegramApi.credentials.js", "dist/credentials/TrelloApi.credentials.js", "dist/credentials/TwilioApi.credentials.js", - "dist/credentials/TypeformApi.credentials.js", - "dist/credentials/DiscordApi.credentials.js" + "dist/credentials/TypeformApi.credentials.js" ], "nodes": [ "dist/nodes/ActiveCampaign/ActiveCampaign.node.js", @@ -65,7 +64,7 @@ "dist/nodes/Chargebee/ChargebeeTrigger.node.js", "dist/nodes/Cron.node.js", "dist/nodes/Dropbox/Dropbox.node.js", - "dist/nodes/DiscordWebhook/DiscordWebhook.node.js", + "dist/nodes/Discord/Discord.node.js", "dist/nodes/EditImage.node.js", "dist/nodes/EmailReadImap.node.js", "dist/nodes/EmailSend.node.js", From 117cca0505343e5c3b3335d46130628060c213a5 Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Wed, 30 Oct 2019 14:56:58 +0100 Subject: [PATCH 5/5] :zap: Remove parameter and improve retry functionality --- .../nodes-base/nodes/Discord/Discord.node.ts | 88 ++++++------------- 1 file changed, 27 insertions(+), 61 deletions(-) diff --git a/packages/nodes-base/nodes/Discord/Discord.node.ts b/packages/nodes-base/nodes/Discord/Discord.node.ts index 6015a2bf1..fcd701f27 100644 --- a/packages/nodes-base/nodes/Discord/Discord.node.ts +++ b/packages/nodes-base/nodes/Discord/Discord.node.ts @@ -1,3 +1,4 @@ +import { get } from 'lodash'; import { IExecuteFunctions } from 'n8n-core'; import { IDataObject, @@ -13,7 +14,6 @@ export class Discord implements INodeType { icon: 'file:discord.png', group: ['output'], version: 1, - subtitle: '={{$parameter["resource"]}}', description: 'Sends data to Discord', defaults: { name: 'Discord', @@ -22,27 +22,6 @@ export class Discord implements INodeType { inputs: ['main'], outputs: ['main'], properties: [ - { - displayName: 'Resource', - name: 'resource', - type: 'options', - options: [ - { - name: 'Webhook', - value: 'webhook', - }, - ], - default: 'webhook', - description: 'The resource to operate on.', - }, - - // ---------------------------------- - // message - // ---------------------------------- - - // ---------------------------------- - // message:post - // ---------------------------------- { displayName: 'Webhook URL', name: 'webhookUri', @@ -51,14 +30,7 @@ export class Discord implements INodeType { alwaysOpenEditWindow: true, }, default: '', - displayOptions: { - show: { - resource: [ - 'webhook', - ], - }, - }, - description: 'The webhook url', + description: 'The webhook url.', }, { displayName: 'Text', @@ -68,13 +40,6 @@ export class Discord implements INodeType { alwaysOpenEditWindow: true, }, default: '', - displayOptions: { - show: { - resource: [ - 'webhook', - ], - }, - }, description: 'The text to send.', } ], @@ -85,10 +50,8 @@ export class Discord implements INodeType { async execute(this: IExecuteFunctions): Promise { const items = this.getInputData(); const returnData: IDataObject[] = []; - let responseData; - let resource: string; - let requestMethod = 'POST'; + const requestMethod = 'POST'; // For Post let body: IDataObject; @@ -97,14 +60,7 @@ export class Discord implements INodeType { const webhookUri = this.getNodeParameter('webhookUri', i) as string; body = {}; - resource = this.getNodeParameter('resource', i) as string; - - if (resource === 'webhook') { - requestMethod = 'POST'; - body.content = this.getNodeParameter('text', i) as string; - } else { - throw new Error(`The resource "${resource}" is not known!`); - } + body.content = this.getNodeParameter('text', i) as string; const options = { method: requestMethod, @@ -116,22 +72,32 @@ export class Discord implements INodeType { json: true }; - try { - responseData = await this.helpers.request(options); - } catch (error) { - if (error.statusCode === 429) { - // Waiting rating limit - setTimeout(async () => { - responseData = await this.helpers.request(options) - }, - error.response.body.retry_after); - }else { - // If it's another error code then return the JSON response - throw error; + let maxTries = 5; + do { + try { + await this.helpers.request(options); + break; + } catch (error) { + if (error.statusCode === 429) { + // Waiting rating limit + await new Promise((resolve) => { + setTimeout(async () => { + resolve(); + }, get(error, 'response.body.retry_after', 150)); + }); + } else { + // If it's another error code then return the JSON response + throw error; + } } + + } while (--maxTries); + + if (maxTries <= 0) { + throw new Error('Could not send message. Max. amount of rate-limit retries got reached.'); } - returnData.push(responseData as IDataObject); + returnData.push({success: true}); } return [this.helpers.returnJsonArray(returnData)];