Filtering RSS to HTTP

I’m trying to figure out what I would need to filter by newest post, and to make it so that it won’t post again unless there’s new content. Below, you can see what I have currently setup from an example I’ve found, but every time I run the workflow it returns an error that items[0].json is not iterable. I am trying to use this workflow.

filter javascript code

const newItems = [];

for (const item of items[0].json) {
     newItems.push(`- [${item.reason}] => ${item.subject.title} @ ${item.subject.url.replace('api.','').replace('/repos','')}`);
  }

return [{json: {reportMessage: `${newItems.join('\r\n')}`, hasNotifications: items[0].json.length > 0}}];

My workflow

An example of what I’m looking to end up with/TLDR:

Hey @Fenton,

Can you share the input data for your Function node? You maybe getting this error due to incorrect data structure.

Sorry for the late response and thanks for tackling my issue!

{
  "nodes": [
    {
      "parameters": {},
      "name": "Start",
      "type": "n8n-nodes-base.start",
      "typeVersion": 1,
      "position": [
        -640,
        580
      ]
    },
    {
      "parameters": {
        "url": "https://www.guilded.gg/blPAzkAE/blog/5aa19971-2b9a-46f3-a891-8097d513c2e0/rss.xml"
      },
      "name": "RSS Feed Read",
      "type": "n8n-nodes-base.rssFeedRead",
      "position": [
        -680,
        450
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "requestMethod": "POST",
        "url": "URLHERE",
        "responseFormat": "=json",
        "jsonParameters": "={{true}}",
        "options": {
          "bodyContentType": "raw"
        },
        "bodyParametersJson": "={\n\"embeds\":[\n{\n\"author\":{\n\"name\":\"Latest from test\",\n\"url\":\"https://www.guilded.gg/blog\",\n\"icon_url\":\"https://theme.zdassets.com/theme_assets/9580103/07defec28cdc4dca22ce6e2154b1c2299346fe5f.png\"\n},\n\"title\":\"{{$node[\"RSS Feed Read\"].json[\"title\"]}}\",\n\"url\":\"{{$node[\"RSS Feed Read\"].json[\"link\"]}}\",\n\"description\":\"{{$node[\"RSS Feed Read\"].json[\"contentSnippet\"]}}\",\n\"footer\":{\n\"text\":\"{{$node[\"RSS Feed Read\"].json[\"pubDate\"]}}\"\n}\n}\n]\n}"
      },
      "name": "HTTP Request",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        100,
        510
      ]
    },
    {
      "parameters": {
        "functionCode": "const newItems = [];\n\nfor (const item of items[0].json) {\n     newItems.push(`- [${item.reason}] => ${item.subject.title} @ ${item.subject.url.replace('api.','').replace('/repos','')}`);\n  }\n\nreturn [{json: {reportMessage: `${newItems.join('\\r\\n')}`, hasNotifications: items[0].json.length > 0}}];\n"
      },
      "name": "Function",
      "type": "n8n-nodes-base.function",
      "position": [
        -260,
        320
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "functionCode": "const date = new Date(new Date().setMinutes(new Date().getMinutes() - (1))).toISOString()\nreturn [{json: {since: date}}];"
      },
      "name": "@Get Date 1 min ago",
      "type": "n8n-nodes-base.function",
      "position": [
        -550,
        300
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "triggerTimes": {
          "item": [
            {
              "mode": "everyX",
              "value": 1,
              "unit": "minutes"
            }
          ]
        }
      },
      "name": "Cron1",
      "type": "n8n-nodes-base.cron",
      "position": [
        -810,
        380
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "conditions": {
          "boolean": [
            {
              "value1": "={{$node[\"Function\"].json[\"hasNotifications\"]}}",
              "value2": true
            }
          ]
        }
      },
      "name": "IF1",
      "type": "n8n-nodes-base.if",
      "position": [
        -90,
        320
      ],
      "typeVersion": 1
    }
  ],
  "connections": {
    "RSS Feed Read": {
      "main": [
        [
          {
            "node": "@Get Date 1 min ago",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Function": {
      "main": [
        [
          {
            "node": "IF1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "@Get Date 1 min ago": {
      "main": [
        [
          {
            "node": "Function",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Cron1": {
      "main": [
        [
          {
            "node": "RSS Feed Read",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF1": {
      "main": [
        [
          {
            "node": "HTTP Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Thanks for sharing the workflow!

You’re using a Function node to calculate time, and another one to transform data. The Function node that you’re using to transform data uses item[0].json instead of items. The former points to an individual item, and from what I could understand from your code, you want to iterate through all the items. Since items[0].json is not an error, you get the error. The other thing that I’ve noticed is that the code refers to values that are not present in your workflow eg. subject.title.

Instead of connecting the Function node after the @Get Date 1 ago node, I suggest you connect it right after the RSS Feed Read node. This is because it will allow you to refer to the items, without specifying the node (this is what your current node does).

You can also use the Date and Time node to calculate the time, instead of using a Function node.

Out of curiosity, what exactly is your workflow supposed to do?

1 Like

Hello, hopefully I can fare with this and mark that answer as a solution momentarily, but for an end result id just like it to post a new webhook whenever it detects new RSS content.

Since RSS is not a trigger, you will have to make requests to it at a regular interval, check if the content is new, and then post the new content. This is the concept of pooling. You can read more about it, and learn how you can implement it in n8n in this blogpost: Creating triggers for n8n workflows using polling ⏲