Rss to Twitter with Image

Hey guys,
I have been able to setup Rss posts to twitter where I share new posts on my RSS to twitter.N8n is working very well with items like the post title and post links. However, my posts also have images and so far I have failed to embed an image from my rss to my twitter. Please help me.

Hi @Collin_Mutambo,

welcome to the community.
In order to use media within a Tweet it needs to be uploaded via a separate endpoint to Twitter. Unfortunately this seems to be not implemented in the current n8n Twitter node. It might be worth to propose this as a feature request.
Same applies for the other way round, if you like to get an image from a Tweet.

Thanks a lot @ixidion but it is actually already possible to post a tweet with an image. You just first have to download the image.

Here an example workflow:

{
  "nodes": [
    {
      "parameters": {
        "url": "https://media.giphy.com/media/IRFQYGCokErS0/giphy.gif",
        "responseFormat": "file",
        "options": {}
      },
      "name": "HTTP Request2",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        500,
        870
      ]
    },
    {
      "parameters": {
        "text": "this is a test tweet with image",
        "additionalFields": {
          "attachments": "data"
        }
      },
      "name": "Twitter2",
      "type": "n8n-nodes-base.twitter",
      "typeVersion": 1,
      "position": [
        870,
        870
      ],
      "credentials": {
        "twitterOAuth1Api": ""
      }
    }
  ],
  "connections": {
    "HTTP Request2": {
      "main": [
        [
          {
            "node": "Twitter2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
2 Likes

Jan,
Thanks for the reply. Looks like the image woulld have to be taken from a direct URL. When the image is part of the post items in an RSS feed, it becomes a bit tricky.

Then you need to transform the Feed-XML to JSON and afterwards you can get the Image-URL easily. XML-Node is your friend then.

1 Like

Hello,

Is it possible that you share your workflow please ?

How would I do that? Any workflow? Tried many times but failed

Hi @jan I haven’t had any luck with this. Looks like the rss feed image link just won’t get you a twitter image preview. Somehow this has failed for me. I get a the text post well from title and description in the rss feed, but image just posts a link on Twitter.

Did you check out the workflow above?

There it shows what you have to do. You have to download the image first with the HTTP Request node and add it as an attachment. If you say you get a link, it sounds to me like you are not doing as described. Because Twitter would like that never get a link it could display.

I tried this workflow. It doesnt work with my rss feed https://www.hot100.ug:1201/telegram/channel/radiosimba. I tried to extract the image link for the posts even using Feed-XML to json with no luck ? I added the rss feed to the XML node to try and transform to json. I get the error “ERROR: No json property “https://www.hot100.ug:1201/telegram/channel/radiosimba” does not exists on item!”

@jan Any pointers ? I got stuck.

Hey @Collin_Mutambo!

Are you receiving XML data from your RSS Feed? I tried to make a call to the link you shared but looks like it doesn’t work.

Can you share what data gets returned?

The RSS link had frozen and I restarted the feed. Its available now. However, when I insert the url of my rss feed in the Xml to Json node, I get the following error;

ERROR: No json property " https://www.hot100.ug:1201/telegram/channel/radiosimba" does not exists on item!

Error: No json property " https://www.hot100.ug:1201/telegram/channel/radiosimba" does not exists on item!
    at Object.execute (/usr/local/lib/node_modules/n8n/node_modules/n8n-nodes-base/dist/nodes/Xml.node.js:226:27)
    at Workflow.runNode (/usr/local/lib/node_modules/n8n/node_modules/n8n-workflow/dist/src/Workflow.js:490:37)
    at /usr/local/lib/node_modules/n8n/node_modules/n8n-core/dist/src/WorkflowExecute.js:370:62
    at /usr/local/lib/node_modules/n8n/node_modules/n8n-core/dist/src/WorkflowExecute.js:451:15
    at /usr/local/lib/node_modules/n8n/node_modules/p-cancelable/index.js:61:11
    at new Promise (<anonymous>)
    at new PCancelable (/usr/local/lib/node_modules/n8n/node_modules/p-cancelable/index.js:31:19)
    at WorkflowExecute.processRunExecutionData (/usr/local/lib/node_modules/n8n/node_modules/n8n-core/dist/src/WorkflowExecute.js:297:16)
    at WorkflowExecute.runPartialWorkflow (/usr/local/lib/node_modules/n8n/node_modules/n8n-core/dist/src/WorkflowExecute.js:134:21)
    at WorkflowRunnerProcess.runWorkflow (/usr/local/lib/node_modules/n8n/dist/src/WorkflowRunnerProcess.js:52:41)

Thanks! I am now getting a response.

The XML node accepts an XML data. The node won’t make the API call. It simply converts the data. You will have to use the HTTP Request node, with the Response Format set to ‘String’.

You can also use the RSS Feed Read node that gives you a JSON object that you can use.

Great. Thanks for the help. However, the json objects I am getting do not give me a direct image link, for example something like http://example.com/imagefile.jp but gives me a telegram post link (since my rss feed is sourced from my telegram channel). I am assuming a workflows like this;

{
  "name": "RSS TO ME",
  "nodes": [
    {
      "parameters": {},
      "name": "Start",
      "type": "n8n-nodes-base.start",
      "typeVersion": 1,
      "position": [
        250,
        300
      ]
    },
    {
      "parameters": {
        "url": "https://www.hot100.ug:1201/telegram/channel/radiosimba"
      },
      "name": "RSS Feed Read",
      "type": "n8n-nodes-base.rssFeedRead",
      "typeVersion": 1,
      "position": [
        150,
        140
      ]
    },
    {
      "parameters": {
        "triggerTimes": {
          "item": [
            {
              "mode": "everyX",
              "value": 5,
              "unit": "minutes"
            }
          ]
        }
      },
      "name": "Cron",
      "type": "n8n-nodes-base.cron",
      "typeVersion": 1,
      "position": [
        -50,
        140
      ]
    },
    {
      "parameters": {
        "functionCode": "const staticData = this.getWorkflowStaticData('global');\n\nlatestRead = staticData.latestRead;\n\nfor (let item of items) {\n  item.json.latestRead = latestRead || '1970-01-01';\n}\n\nreturn items;"
      },
      "name": "Latest Read",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        350,
        140
      ]
    },
    {
      "parameters": {
        "functionCode": "const staticData = this.getWorkflowStaticData('global');\n\nif (items.length > 0) {\n  staticData.latestRead = items[0].json.isoDate || staticData.latestRead;\n}\n\n\nreturn items;"
      },
      "name": "Write Latest Read",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        750,
        40
      ]
    },
    {
      "parameters": {
        "conditions": {
          "number": [
            {
              "value1": "={{new Date($node[\"Latest Read\"].data[\"latestRead\"]).getTime()}}",
              "value2": "={{new Date($node[\"RSS Feed Read\"].data[\"isoDate\"]).getTime()}}"
            }
          ]
        }
      },
      "name": "IF",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        550,
        140
      ]
    },
    {
      "parameters": {
        "functionCode": "let emailText = '';\n\nfor (let item of items) {\n  emailText += `${item.json.title}\\n${item.json.link}\\n\\n`;\n}\n\nreturn [{json: {emailText}}];"
      },
      "name": "Function",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        750,
        240
      ]
    },
    {
      "parameters": {
        "fromEmail": "[email protected]",
        "toEmail": "[email protected]",
        "subject": "=Facebook Updates",
        "text": "={{$node[\"Latest Read\"].json[\"content\"]}}",
        "html": "={{$node[\"Latest Read\"].json[\"content\"]}}",
        "attachments": "=",
        "options": {}
      },
      "name": "Send Email",
      "type": "n8n-nodes-base.emailSend",
      "typeVersion": 1,
      "position": [
        950,
        90
      ],
      "credentials": {
        "smtp": "Radio Simba Email"
      }
    },
    {
      "parameters": {
        "chatId": "-1001385013517",
        "text": "={{$node[\"RSS Feed Read\"].json[\"content\"]}} {{$node[\"RSS Feed Read\"].json[\"guid\"]}}",
        "additionalFields": {}
      },
      "name": "Telegram",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1,
      "position": [
        1240,
        60
      ],
      "credentials": {
        "telegramApi": "simba telegram bot"
      }
    },
    {
      "parameters": {
        "text": "={{ ($node[\"RSS Feed Read\"].json[\"contentSnippet\"]) .slice(0, 250) + '... '  + ' ' +$node[\"RSS Feed Read\"].json[\"guid\"]}}",
        "additionalFields": {}
      },
      "name": "Twitter",
      "type": "n8n-nodes-base.twitter",
      "typeVersion": 1,
      "position": [
        1050,
        240
      ],
      "credentials": {
        "twitterOAuth1Api": "Simba Updates"
      }
    },
    {
      "parameters": {
        "url": "https://www.hot100.ug:1201/telegram/channel/radiosimba"
      },
      "name": "RSS Feed Read1",
      "type": "n8n-nodes-base.rssFeedRead",
      "typeVersion": 1,
      "position": [
        150,
        580
      ]
    },
    {
      "parameters": {
        "url": "={{$node[\"RSS Feed Read\"].parameter[\"url\"]}}",
        "responseFormat": "string",
        "options": {}
      },
      "name": "HTTP Request",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        400,
        560
      ]
    },
    {
      "parameters": {
        "text": "={{ ($node[\"RSS Feed Read\"].json[\"contentSnippet\"]) .slice(0, 250) + '... '  + ' ' +$node[\"RSS Feed Read\"].json[\"guid\"]}}",
        "additionalFields": {
          "attachments": "data"
        }
      },
      "name": "Twitter1",
      "type": "n8n-nodes-base.twitter",
      "typeVersion": 1,
      "position": [
        660,
        570
      ],
      "credentials": {
        "twitterOAuth1Api": "Simba Updates"
      }
    }
  ],
  "connections": {
    "RSS Feed Read": {
      "main": [
        [
          {
            "node": "Latest Read",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Latest Read": {
      "main": [
        [
          {
            "node": "IF",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF": {
      "main": [
        [
          {
            "node": "Function",
            "type": "main",
            "index": 0
          },
          {
            "node": "Write Latest Read",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Cron": {
      "main": [
        [
          {
            "node": "RSS Feed Read",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Function": {
      "main": [
        [
          {
            "node": "Twitter",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "RSS Feed Read1": {
      "main": [
        [
          {
            "node": "HTTP Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request": {
      "main": [
        [
          {
            "node": "Twitter1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": true,
  "settings": {},
  "id": "5"
}

I’ve created a workflow that might help. This workflow uses the RSS Read node to get information from your RSS URL. Next, I am using the HTML Extract node to extract the image source. I found out that not all the posts have an image. So I am using an IF node to check if image is present or not. If there is an image (false branch of the IF node), we make an HTTP Request to download the image. The next step you will have to take is to add the Twitter node and as suggested earlier, select the Attachments option.

{
  "nodes": [
    {
      "parameters": {
        "url": "https://www.hot100.ug:1201/telegram/channel/radiosimba"
      },
      "name": "RSS Feed Read",
      "type": "n8n-nodes-base.rssFeedRead",
      "typeVersion": 1,
      "position": [
        -30,
        380
      ]
    },
    {
      "parameters": {
        "dataPropertyName": "content",
        "extractionValues": {
          "values": [
            {
              "key": "image",
              "cssSelector": "img",
              "returnValue": "attribute",
              "attribute": "src"
            }
          ]
        },
        "options": {}
      },
      "name": "Extract Image",
      "type": "n8n-nodes-base.htmlExtract",
      "typeVersion": 1,
      "position": [
        170,
        380
      ]
    },
    {
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{$json[\"image\"]}}",
              "operation": "isEmpty"
            }
          ]
        }
      },
      "name": "Is no image?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        350,
        390
      ]
    },
    {
      "parameters": {
        "url": "={{$json[\"image\"]}}",
        "responseFormat": "file",
        "options": {}
      },
      "name": "Fetch image",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        540,
        470
      ]
    }
  ],
  "connections": {
    "RSS Feed Read": {
      "main": [
        [
          {
            "node": "Extract Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Image": {
      "main": [
        [
          {
            "node": "Is no image?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is no image?": {
      "main": [
        null,
        [
          {
            "node": "Fetch image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Hope this helps!

Looking good. I get the following error in the IF node

Problem executing workflow

There was a problem executing the workflow:
"compareOperationFunctions[compareData.operation] is not a function"

Secondly, each post has its own image. Should I have a seperate workflow for each --Image and Text part of the post ?

OK, I changed the IF node operation to NOT CONTAINS and that corrected. But that leaves the twitter node with the error;

There was a problem executing the workflow:
"No binary data set. So file can not be written!"

Hey Colin,

Are you connecting the Twitter node with the right output of the IF node? If there are any nodes in between the IF node and the Twitter node, is the binary data still accessible by the Twitter node?

This is the workflow I have. The text part works perfect. I connected two arrows from rss feed with one for the text posts and the other for the image section. I get the error There was a problem executing the workflow:
"No binary data set. So file can not be written!"

{
  "name": "RSS TO IMAGE",
  "nodes": [
    {
      "parameters": {},
      "name": "Start",
      "type": "n8n-nodes-base.start",
      "typeVersion": 1,
      "position": [
        250,
        300
      ]
    },
    {
      "parameters": {
        "url": "https://www.hot100.ug:1201/telegram/channel/radiosimba"
      },
      "name": "RSS Feed Read",
      "type": "n8n-nodes-base.rssFeedRead",
      "typeVersion": 1,
      "position": [
        150,
        140
      ]
    },
    {
      "parameters": {
        "triggerTimes": {
          "item": [
            {
              "mode": "everyX",
              "value": 5,
              "unit": "minutes"
            }
          ]
        }
      },
      "name": "Cron",
      "type": "n8n-nodes-base.cron",
      "typeVersion": 1,
      "position": [
        -50,
        140
      ]
    },
    {
      "parameters": {
        "functionCode": "const staticData = this.getWorkflowStaticData('global');\n\nlatestRead = staticData.latestRead;\n\nfor (let item of items) {\n  item.json.latestRead = latestRead || '1970-01-01';\n}\n\nreturn items;"
      },
      "name": "Latest Read",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        350,
        140
      ]
    },
    {
      "parameters": {
        "functionCode": "const staticData = this.getWorkflowStaticData('global');\n\nif (items.length > 0) {\n  staticData.latestRead = items[0].json.isoDate || staticData.latestRead;\n}\n\n\nreturn items;"
      },
      "name": "Write Latest Read",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        750,
        40
      ]
    },
    {
      "parameters": {
        "conditions": {
          "number": [
            {
              "value1": "={{new Date($node[\"Latest Read\"].data[\"latestRead\"]).getTime()}}",
              "value2": "={{new Date($node[\"RSS Feed Read\"].data[\"isoDate\"]).getTime()}}"
            }
          ]
        }
      },
      "name": "IF",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        550,
        140
      ]
    },
    {
      "parameters": {
        "functionCode": "let emailText = '';\n\nfor (let item of items) {\n  emailText += `${item.json.title}\\n${item.json.link}\\n\\n`;\n}\n\nreturn [{json: {emailText}}];"
      },
      "name": "Function",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        750,
        240
      ]
    },
    {
      "parameters": {
        "text": "={{ ($node[\"RSS Feed Read\"].json[\"contentSnippet\"]) .slice(0, 250) + '... '  + ' ' +$node[\"RSS Feed Read\"].json[\"guid\"]}}",
        "additionalFields": {
          "attachments": "data"
        }
      },
      "name": "Twitter",
      "type": "n8n-nodes-base.twitter",
      "typeVersion": 1,
      "position": [
        1050,
        270
      ],
      "credentials": {
        "twitterOAuth1Api": "Simba Updates"
      }
    },
    {
      "parameters": {
        "dataPropertyName": "content",
        "extractionValues": {
          "values": [
            {
              "key": "image",
              "cssSelector": "img",
              "returnValue": "attribute",
              "attribute": "src"
            }
          ]
        },
        "options": {}
      },
      "name": "Extract Image",
      "type": "n8n-nodes-base.htmlExtract",
      "typeVersion": 1,
      "position": [
        550,
        590
      ]
    },
    {
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{$json[\"image\"]}}",
              "operation": "notContains"
            }
          ]
        }
      },
      "name": "Is no image?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        730,
        600
      ]
    },
    {
      "parameters": {
        "url": "={{$json[\"image\"]}}",
        "responseFormat": "file",
        "options": {}
      },
      "name": "Fetch image",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        920,
        680
      ]
    }
  ],
  "connections": {
    "RSS Feed Read": {
      "main": [
        [
          {
            "node": "Extract Image",
            "type": "main",
            "index": 0
          },
          {
            "node": "Latest Read",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Latest Read": {
      "main": [
        [
          {
            "node": "IF",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF": {
      "main": [
        [
          {
            "node": "Function",
            "type": "main",
            "index": 0
          },
          {
            "node": "Write Latest Read",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Cron": {
      "main": [
        [
          {
            "node": "RSS Feed Read",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Function": {
      "main": [
        [
          {
            "node": "Twitter",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Image": {
      "main": [
        [
          {
            "node": "Is no image?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is no image?": {
      "main": [
        [
          {
            "node": "Fetch image",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "Fetch image": {
      "main": [
        [
          {
            "node": "Twitter",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {},
  "id": "12"
}