Automating message cross-posting between social networks
For over a month now I've been actively using IFTTT for cross-posting to social networks. I want to share how I got there and what tricks I resorted to in order to achieve cross-posting close to what I need.
I write on social networks for myself, not for work. And it's convenient for me to write from the place where I spend my time, so SMM software didn't suit me — it's expensive, and on top of that it requires writing from a different place.
Mostly I spend my time on Twitter and Telegram, I post photos on Instagram, and recently I also started doing a podcast on Anchor. Some messages are more convenient to write in one network, some — in another. Besides, I'd like to have at least some control over my messages, so as not to lose them in an instant because of some corporation's decision. That's why I also joined the decentralized social network, the Fediverse, and set up my own personal Friendica, where I simply duplicate my posts from other social networks.
When choosing a solution for joining the Fediverse, I settled on Friendica, because it's in PHP, which I work with every day at work, and if needed I can modify the engine to suit me and deploy it on shared hosting. The only thing I don't like about Friendica is that it doesn't allow guests to leave comments, but since it's more of a backup solution, that's not a critical problem. The other apps I tried or looked at had more critical drawbacks for me.
Many people are switching to decentralized social networks because they don't want corporations tracking them, analyzing them, knowing everything about them. That doesn't really bother me, I've come to terms with it, but what bothers me more is that a corporation can at any time delete all my messages, all my history.
Copying messages by hand is too much of a hassle for me and too costly in terms of time, so I started looking in detail at solutions for automatically posting messages between social networks.
For the past few years I'd been using the free IFTTT plan, which let me use ready-made applets and have three of my own, in which only two steps could be chained together. That was enough to automatically post from Instagram and Twitter to Telegram, sometimes not in the format I needed. And that was even enough to duplicate all of it to Friendica, but I wanted more control. I wanted to be able to set the format for all the messages being forwarded, and I wanted to make longer posts in Telegram that would get trimmed and sent to Twitter without coming back into Telegram again and creating duplication. The free IFTTT plan wasn't enough for that, so I started looking at alternatives.
First I looked at the local ApiX-Drive, which is geared toward business clients. They have a lot of cool integrations that businesses need, but for now there's no Twitter integration. As I already said, for business there's a pile of SMM solutions that post to the needed social networks the right way, so automation services usually don't focus much on social networks, because their clients need that from them less. And I'm not ready to pay 19 dollars a month, for now, for cross-posting messages to personal microblogs. So ApiX-Drive had to be set aside.
Then I started studying n8n in detail, which a colleague at work recommended to me. The service itself is open source and you can run it on your own for free if you have the skills and a computer for it. First I tried the cloud version of the service, which costs 20 dollars a month, but gives the first month free. The service has the integrations I need and is very flexible, it lets you flexibly do complex things in automation. But almost immediately I hit a wall: from Twitter it only pulls messages trimmed to 140 characters. In theory, in the API request you can pass a parameter that forces full messages to be returned, or change the API version, which is even more complex. But for that you have to modify the source code, so the cloud version didn't work and I needed to bring the service up on a local machine.
I couldn't get a Node.js-based service running locally on Windows 10. If I worked with Node.js professionally or ran a UNIX-like operating system, then maybe I would have managed it. And even on Windows I would have managed it after many hours of digging through manuals and searching for advice on forums, but I didn't want to spend a heap of time on that. Keeping such a service on a local machine isn't an option, you need to rent a server to host the Node.js app on, and that's again hours or days of time spent learning how to host something like that. I tried poking around in free Node.js hosting services, but it was all somehow overcomplicated, and burning that much time wasn't worth it, and I didn't feel like it, so I gave up on n8n.
It's worth noting that only in n8n did I see the ability to turn a chain of tweets from Twitter into a single post and send it to other places already as one such message. The functionality is neat, so over time I'll dig into n8n some more. Maybe something will change that will let me use it cheaply and more simply for getting full messages from Twitter. n8n also has local storage, which makes it easier to control duplication and the looping of message forwarding between several networks.
I also tried Integromat, but on its free plan there was no Twitter, and 9 dollars a month isn't cheap either, and I had no desire to pay right away without a trial. I looked at Zapier, which I use at work for backing up messages from Slack to Evernote, but it turned out to have no Telegram integration. Although I'll say more about Zapier at the end — their free plan is sometimes a real lifesaver.
As a result, I came back to IFTTT, looked at their paid pricing plan, and took the risk of paying for it.
IFTTT has been on the market for quite a while, and from the very start they were geared toward individual enthusiasts rather than business, so their Twitter integration is well set up. I didn't follow the service much; I know they introduced new pricing last fall, and before that it was more affordable, but back then I didn't really need complex automatic forwarding. At first they made the cost of the plan 10 dollars a month, but now the minimum plan is 4 dollars, which is a stretch but suits personal blogging.
The IFTTT Pro plan let me create applets that can perform several actions at once — sending from one service to several others on a single trigger. The paid plan also lets you filter the data that comes in from the trigger, and make requests to get additional accompanying data. But IFTTT lacks additional data storage to have control over what's already been sent or received, so you have to resort to some contortions.
I needed to somehow keep track that a message coming in from Twitter hadn't been sent there earlier via IFTTT. The ability to additionally get the latest messages from Telegram, which the paid plan provides, could help with that. But that only works for text messages. If an image or a link was sent in Twitter, then they'll come in from Twitter already in the form of shortened t.co links, and if there's no text, a message that was earlier forwarded from Telegram to Twitter will get re-posted into Telegram again.
To prevent duplication of messages during cross-posting, I had to use a hack in the form of an invisible zero-length character, the zero-width non-joiner (ZWNJ). I simply started adding this character to the end of all tweets sent via IFTTT, and then I just ignore tweets that have this character. I know this character has a different purpose, but I don't write messages in languages that use this character, so it suits me. And for retweets I simply don't perform this check.
The ability to manually process the messages being forwarded let me more cleanly trim long messages that don't fit in a single tweet. Automatically they just got cut off at the last allowed character, and the ellipsis character simply broke a word off in the middle. Manually, though, I managed to find the start of the last run of non-letter characters before the limit, and put the ellipsis in place of the first one.
You also have to take into account that the length of shortened links in Twitter is 23 characters, and with the space and the invisible character that's already 25 additional characters, so if the text gets trimmed and a link to another network follows it, then the limit becomes 255 characters instead of 280.
Message filtering is done in TypeScript, which those who write in JavaScript can write in without any particular trouble. For me the problem was only that some functions that are in the latest versions of JS are missing.
Below I'll go over the logic of each of the filters in detail and provide their code that I wrote.
The first thing I made was forwarding messages from Telegram to Twitter and Friendica. Here everything is fairly simple. Adding the invisible character and trimming a long message after a word, not in the middle of a word, which I talked about above.
If a message is short enough, then I don't want to annoy readers on Twitter with a link to the original message in Telegram, so I simply forward the message. But if a message doesn't fit within the 280-character limit, then I trim the text with a limit of 255 characters and then place a link to the original message in Telegram.
At the beginning there's another hack for messages that consist of only a link without text. You just can't add the invisible character before those, because Telegram will destroy it, so first I add the invisible character and a space before the first link, and then I replace space invisible-character space with invisible-character space, so as not to have two spaces if there was some text before the link.
Next comes forwarding photos from Telegram to Twitter and Friendica. IFTTT doesn't work very well with albums. Each photo from an album will be forwarded as a separate message, and the comment on the album will be added only to the first image. For now I have to remember not to post albums in the Telegram channel and keep a closer eye on n8n. Although an extra request to Telegram would make it possible to ignore the other images in the album. But I'd like to have the ability to send albums to other places, although I don't want it all that much — it's not needed often.
When sending an image to Twitter you have to take into account that the image itself will also become a link, so the text limits decrease to 255 and 230, respectively. Otherwise the rest of the logic is the same; only the attribute names change.
The main tricks come up when forwarding new tweets to other places. IFTTT can't react immediately to a new tweet appearing and simply does a regular check every 5 minutes.
First I extract the text from the tweet that goes up to the first link, and then I compare that text with the beginnings of the latest messages and photo descriptions that are in the Telegram channel. If posts in Telegram start with the tweet's text, then forwarding of such a message is stopped. In my case there's no point to this logic, because I use the hack with the invisible character, but I'd written it before that and it's a shame to delete it, and it might even come in handy for someone here.
A plus of IFTTT is that the system takes into account tweets you send to yourself in reply when you make a chain of tweets in a thread. Some systems — Friendica, for one — ignore such tweets. So I had to turn off automatic reading of tweets in Friendica and post them via IFTTT, because Friendica loses all tweets written in reply to oneself. At the same time Friendica displays very nice retweets. IFTTT can't make such retweets, because it reads insufficient data about the author of the tweet you're retweeting.
I had to make an additional hack in Friendica. There I turned on reading and copying of tweets and retweets from Twitter, and in the code itself I added an early return in the method that's supposed to process tweets you wrote yourself. This way Friendica itself now duplicates retweets from Twitter, and in IFTTT in the filter I forbade sending retweets to Friendica. The right thing would be to figure out in more detail the plugin that interacts with Twitter in Friendica and add a setting, but that all takes time, so for now I simply added one line to the code and now the method that's supposed to copy non-retweets from Twitter doesn't fire. Maybe in the future I'll do it the right way.
It's a shame Friendica can't process comments on retweets, it only takes the tweet with the comment, rather than processing the retweet being commented on. A comment without the thing being commented on usually makes no sense. For now I have to remember and put up with the fact that retweets of quote-retweets go to Friendica without the main content.
Next, in the IFTTT filter, after the retweet check comes that check for the invisible character, and if it's there, then I cancel sending to Telegram and Friendica. And at the very end, for Telegram I replace newline characters with the corresponding HTML tag, because Telegram ignores newline characters and for formatting messages via the API requires HTML markup.
Instagram has its own complications, though at the same time it's simpler, because from it you only have to read new photos and you don't have to send anything new to it. Sending a photo to Instagram is a painstaking process, where you have to edit the photo accordingly and pick hashtags. And that's where the complication is.
You have to add a lot of tags on Instagram so that the photo can be found and seen by others who aren't subscribed to you. Although some will say that, on the contrary, tags shouldn't be added so that the post is automatically shown to others, but Instagram's algorithms keep changing, and I'm used to adding tags to every photo.
It's only on Instagram that tags are the norm, people are used to them there, and some of them only make sense on Instagram. But in other places that number of hashtags will be annoying. Twitter has a limit on message length in the first place, and you can't send that many on it, and on Telegram and Friendica I simply don't want to see all those tags and don't want to show them to others.
So first, in the filter, I find the first hashtag and keep only the text up to it. The logic is the same as how I removed the text up to the first link when sending from Twitter. After the text I always add, on a new line, a link to the original post on Instagram, because I'm not against new subscribers there.
When limiting message length for Twitter I use a limit of 230 characters, because a tweet will always have within it shortened links to Instagram and to the photo itself in Twitter.
Since the text changes and the original isn't sent, for Friendica I have to set and assemble the entire body for the web request anew.
Recently I started recording a podcast with reviews of TV series episodes. And I decided to also automate the publishing of links to new episodes on social networks. In the case of Telegram, posting the whole mp3 file with the episode, because IFTTT has an action for sending an mp3 to Telegram.
And here IFTTT disappointed me again, because it turned out that the service doesn't read the XML tag enclosure from the podcast RSS, and it's that very tag that contains the link to the mp3 file. The advice that you can do the RSS reading on Zapier and from it make a web request to IFTTT quickly turned up via Google. But now webhooks in Zapier have become available only in the paid plans, and from the free plan such requests can't be made.
I wrote about the problem to IFTTT support and asked them to add the ability to read the content of the enclosure tag. They replied that they passed the request on to the developers. Now we'll see whether they ever add a way to get a file link from RSS without hacks.
After brief reflection I worked out how to generate a new RSS via Zapier, which I then process in IFTTT. Zapier reads the podcast RSS and, when a new episode is present, adds it to its own RSS, with the link to the episode replaced by the link to the mp3 file, the title replaced by the link to the episode, and the author replaced by the title.
The link to the mp3 is quite large and complex, so I'm not sure it won't get spoiled if it's written into the title field, but the link to the episode is fairly short and nothing will happen to it in the title. The podcast author is always me, I don't need the information in that field, but the title won't hurt when publishing to Friendica.
The episode titles themselves I don't forward to social networks, because there it's only the name of the series and the number of its episode, by which the podcast is found in various podcast-listening services. There's no point forwarding the title text to social networks.
But the text from the description is there, because in it I write in my own words what the podcast episode is about, but after the description come the standard links that have to be shown to those who listen to the podcast in listening services. Those links don't need to be posted to social networks anymore, because in social networks I post a link to the episode anyway, after which there will be the episode with the full description that includes those links.
So first I split the text into lines and select all lines up to the first line that contains a link within it. Then I glue the lines back together with a newline character, and for Telegram with the corresponding HTML tag. Here you also have to watch that there are no other HTML tags besides <br> in the podcast episode description, otherwise in Friendica escaped text gets sent and the tags become text.
For Friendica I again have to rewrite the entire webhook body, because it's not the original text being sent. It's worth noting that in Friendica, from the passed link to the podcast episode it makes a post with an attachment, into which it automatically pulls the embed code from the link to the Anchor service, where I host the podcast, and on its own displays a web player in which you can listen to the podcast without following the link.
For the podcast I also made a separate page on Facebook and I post to it with a description and a link to the podcast episode. Facebook doesn't allow automatic posting to a personal profile and I'm not active on this network, so in the previous applets I didn't interact with it at all.
You can see the result of these automations at the links below.
Twitter: https://twitter.com/Abysim
Telegram channel: https://t.me/AbysimFeed
Instagram: https://www.instagram.com/abysim.whitelion/
Friendica: https://whitelion.me
Podcast on Anchor: https://anchor.fm/abysim
Podcast page on Facebook: https://www.facebook.com/serialni.dumky