A GitHub Action that creates messages (toots) on your Mastodon account from a RSS/Atom/JSON feed's items.
This should be a simple way to POSSE — Publish (on your) Own Site, Syndicate Elsewhere — content from your blog to your Mastodon account.
[!NOTE] It currently supports JSON Feed, with support for RSS and Atom planned.
I recommend to try first with an action requiring a manual action with the workflow_dispatch
event, and set testMode: true
, to test the settings.
Here's a minimal version, with only required inputs:
name: Create toots from feed items
on:
workflow_dispatch:
jobs:
Feed2Mastodon:
runs-on: ubuntu-latest
steps:
# Checkout the repository to restore previous cache
- name: Checkout
uses: actions/checkout@v3
# Look for new toots to create from items in the JSON feed
- name: Feed to Mastodon
uses: nhoizey/github-action-feed-to-mastodon@v2
with:
feedUrl: "https://example.com/feed.json"
mastodonInstance: "https://mastodon.social"
mastodonToken: ${{ secrets.MASTODON_TOKEN }}
testMode: true
# Make sure files are up to date if other commits have been pushed in the mean time
- name: Pull any changes from Git
run: git pull
# Push changes in the cache files to the repository
# See https://github.com/stefanzweifel/git-auto-commit-action#readme
- name: Commit and push
uses: stefanzweifel/git-auto-commit-action@v4
You can then enhance your action with the schedule
event, for example to automate creation of a toot every Monday at 8am (Crontab Guru: https://crontab.guru/#0_8_*_*_1).
Replace:
on:
workflow_dispatch:
With:
on:
schedule:
- cron: "0 8 * * 1"
When everything works perfectly, you can remove the testMode
input, or set it to false
.
There are 3 required inputs, used in the examples above, but also some optional inputs — with default values — to fine tune when and how toots are created:
input | required? | default | description |
---|---|---|---|
feedUrl |
Yes | URL of the feed to fetch | |
mastodonInstance |
Yes | The root URL of the Mastodon instance where the toot should be created | |
mastodonToken |
Yes | Your access token for the Mastodon API, get it from /settings/applications/new on your instance, and use an encrypted secrets to hide it |
|
nbTootsPerItem |
No | 1 | Number of toots that can be created from the same item |
itemChoiceStrategy |
No | "random" |
Strategy to choose the item to toot when multiple are available in the list of least tooted items. The following values can be used: "random" , "newest" (the most recent item), "oldest" (the oldest item) |
globalDelayToots |
No | 1440 (1 day) | Delay (in minutes) between any toot from this feed |
delayTootsSameItem |
No | 129600 (90 days) | Delay (in minutes) between any toot for the same item from this feed (used only if nbTootsPerItem > 1 ) |
cacheDirectory |
No | "cache" |
Path to the directory where cache files are stored |
cacheFile |
No | "feed-to-mastodon.json" |
Name of the JSON file caching data from the feed and toots |
cacheTimestampFile |
No | "feed-to-mastodon-timestamp.json" |
Name of the JSON file caching the timestamp of the last toot |
ignoreFirstRun |
No | true | Items collected when the feed is fetched the first time won't be used as toots. This aims to prevent flooding Mastodon, as these items may have already been shared another way, manual or automated. If nbTootsPerItem is set to more than 1, only the first toot is ignored. |
testMode |
No | false | Activates a mode for tests, where mentions are removed (@ replaced by $ ) |
tootVisibility |
No | "public" |
Toot visibility. The following values can be used: "public" (visible for all), "unlisted" (opted-out of discovery features), "private" (followers only), "direct" (visible only for mentioned users) |
logFeedItemContent |
No | false | Log the content of the feed item that will be used to create the toot |
instanceType |
No | "mastodon" |
Type of instance, to adapt API calls (values: "mastodon" or "pixelfed" ) |
The action sets an output that you can use in following steps of your own action:
output | description |
---|---|
tootUrl |
URL of the toot that was created |
There are 2 JSON files in the cache:
cacheFile
keeps a copy of all items from the feed, and for each item
cacheTimestampFile
keeps track of the timestamp of the last toot create by the actionWarning Make sure to have steps "Checkout", "Pull" and "Commit and push" in your action, this is how the cache files are synchronized each time the action runs.
The cache prevents creating the same toot multiple times if you set nbTootsPerItem
to 1 (which is the default).
If you set nbTootsPerItem
to a value larger than 1, the action will chose an item among the ones that have the least toots. The choice is based on the itemChoiceStrategy
input.
[!TIP] Once issue #7 fixed, you'll be able to set
nbTootsPerItem
to-1
to remove any limit.
In particular, any new item in the feed won't have existing toots, so it will be tooted first when the action runs, if all previous items already have at least one toot.
[!CAUTION] If you use this action in multiple actions in the same repository, make sure you set different cache files.
[!TIP] Once issue #9 fixed, the cache file default name will be based on the feed's URL.
The properties this action uses from a JSON Feed item are:
url
is used as the item id in the cache filecontent_text
is used as the content of the tootdate_published
(RFC 3339 format)language
is used to set the language of the tootattachments
is a non empty array, each image attachment (mime_type
starts with image/
) is added to the toot, with its description defined by _alt_text
if it exists, or title
.Here's an example JSON feed with one single item, with only the properties that are either required by the JSON Feed 1.1 specification, or useful for this action:
{
"version": "https://jsonfeed.org/version/1.1",
"title": "Photos - Nicolas Hoizey",
"items": [
{
"id": "https://nicolas-hoizey.photo/galleries/travels/europe/the-netherlands/arnhem/the-blacksmith/",
"url": "https://nicolas-hoizey.photo/galleries/travels/europe/the-netherlands/arnhem/the-blacksmith/",
"language": "en",
"date_published": "2014-07-12T13:07:00Z",
"content_text": "“The Blacksmith”\n\nShot in the amazing Openluchtmuseum (Open Air Museum) near Arnhem, in The Netherlands.\n\n📅 12th July 2014\n\n📸 Sony RX100 Mark III\n🎞️ ISO 3200, ƒ/2.8, 1/80s\n\n#Travels #Europe #TheNetherlands #Arnhem #Photo #Photography #PhotoOfTheDay #DailyPhoto\n\n🔎 https://nicolas-hoizey.photo/galleries/travels/europe/the-netherlands/arnhem/the-blacksmith/",
"attachments": [
{
"url": "https://nicolas-hoizey.photo/photos/the-blacksmith/small.jpg",
"mime_type": "image/jpeg",
"title": "The blacksmith",
"_alt_text": "A blacksmith in his workshop, working with his anvil"
}
]
}
]
}
Pixelfed v1 API is based on the mastodon v1 API, with a few differences listed in the documentation
An (undocumentated) difference is that the visibility
option is not supported, and trying to create a toot with a visibility
option generates an error.
If you want to use this action with a Pixelfed instance, you have to set the optional instanceType
input to "pixelfed"
.
Read the dedicated docs.
If you want to see what's happening in the action, you can enable additional debug logs: Enabling step debug logging
The scripts and documentation in this project are released under the MIT License.