diff --git a/packages/nodes-base/nodes/RssFeedRead/RssFeedReadTrigger.node.json b/packages/nodes-base/nodes/RssFeedRead/RssFeedReadTrigger.node.json new file mode 100644 index 0000000000..96c41459f9 --- /dev/null +++ b/packages/nodes-base/nodes/RssFeedRead/RssFeedReadTrigger.node.json @@ -0,0 +1,13 @@ +{ + "node": "n8n-nodes-base.rssFeedReadTrigger", + "nodeVersion": "1.0", + "codexVersion": "1.0", + "categories": ["Core Nodes"], + "resources": { + "primaryDocumentation": [ + { + "url": "https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.rssfeedreadtrigger/" + } + ] + } +} diff --git a/packages/nodes-base/nodes/RssFeedRead/RssFeedReadTrigger.node.ts b/packages/nodes-base/nodes/RssFeedRead/RssFeedReadTrigger.node.ts new file mode 100644 index 0000000000..9f7c00ae64 --- /dev/null +++ b/packages/nodes-base/nodes/RssFeedRead/RssFeedReadTrigger.node.ts @@ -0,0 +1,89 @@ +import type { + IDataObject, + INodeExecutionData, + INodeType, + INodeTypeDescription, + IPollFunctions, +} from 'n8n-workflow'; +import { NodeOperationError } from 'n8n-workflow'; +import Parser from 'rss-parser'; +import moment from 'moment'; + +export class RssFeedReadTrigger implements INodeType { + description: INodeTypeDescription = { + displayName: 'RSS Feed Trigger', + name: 'rssFeedReadTrigger', + icon: 'fa:rss', + group: ['trigger'], + version: 1, + description: 'Starts a workflow when an RSS feed is updated', + subtitle: '={{$parameter["event"]}}', + defaults: { + name: 'RSS Feed Trigger', + color: '#b02020', + }, + polling: true, + inputs: [], + outputs: ['main'], + properties: [ + { + displayName: 'Feed URL', + name: 'feedUrl', + type: 'string', + default: 'https://blog.n8n.io/rss/', + required: true, + description: 'URL of the RSS feed to poll', + }, + ], + }; + + async poll(this: IPollFunctions): Promise { + const pollData = this.getWorkflowStaticData('node'); + const feedUrl = this.getNodeParameter('feedUrl') as string; + + const now = moment().utc().format(); + const startDate = (pollData.lastTimeChecked as string) || now; + + const endDate = now; + + if (!feedUrl) { + throw new NodeOperationError(this.getNode(), 'The parameter "URL" has to be set!'); + } + + const parser = new Parser(); + + let feed: Parser.Output; + try { + feed = await parser.parseURL(feedUrl); + } catch (error) { + if (error.code === 'ECONNREFUSED') { + throw new NodeOperationError( + this.getNode(), + `It was not possible to connect to the URL. Please make sure the URL "${feedUrl}" it is valid!`, + ); + } + + throw new NodeOperationError(this.getNode(), error as Error); + } + + const returnData: IDataObject[] = []; + + if (feed.items) { + if (this.getMode() === 'manual') { + return [this.helpers.returnJsonArray(feed.items[0])]; + } + feed.items.forEach((item) => { + if (Date.parse(item.isoDate as string) >= Date.parse(startDate)) { + returnData.push(item); + } + }); + } + pollData.lastTimeChecked = endDate; + + if (Array.isArray(returnData) && returnData.length !== 0) { + return [this.helpers.returnJsonArray(returnData)]; + } + + return null; + } +} diff --git a/packages/nodes-base/package.json b/packages/nodes-base/package.json index aa74c69db6..09598c57d0 100644 --- a/packages/nodes-base/package.json +++ b/packages/nodes-base/package.json @@ -684,6 +684,7 @@ "dist/nodes/RespondToWebhook/RespondToWebhook.node.js", "dist/nodes/Rocketchat/Rocketchat.node.js", "dist/nodes/RssFeedRead/RssFeedRead.node.js", + "dist/nodes/RssFeedRead/RssFeedReadTrigger.node.js", "dist/nodes/Rundeck/Rundeck.node.js", "dist/nodes/S3/S3.node.js", "dist/nodes/Salesforce/Salesforce.node.js",