Posting to Mastodon from Drafts (Native Action Service)

I realize this is probably a big ask, but I was wondering how possible it’d be to see native services integration for actions with Mastodon in the near future. I’m not a developer - so what I’m about to speculate might be BS - but I would think it’d be pretty easy given how thoroughly documented Mastodon’s API is + perhaps even that the infrastructure, itself is coded in Ruby?

1 Like

I would love to see this as well! I recently stopped posting on Twitter and switched to Mastodon instead. I sorely miss being able to compose longer storms of microblogs from Drafts.

If this feature does get implemented, I hope the CW (content warning) feature is available via the native action as well.

Although I have one question: due to Mastodon’s decentralized nature, different instances can and often do have different technical limitations (e.g. different character count limits). Would this pose difficulties for implementing this feature?

1 Like

Due to its decentralized nature, Mastodon isn’t a great fit for native service integration.

It is pretty easy to work with the API directly in script, however. I made up an example action to post a status update to Mastodon:

Read the description for details on configuration. You will have to create an application in your Mastodon account, and enter the token you obtain and base URL of your Mastodon instance the first time you run the action.

This is a basic example to post a public status update. There are other options you can send with a status, which could be reviewed in the /statuses API documentation and easily modified in the script.


Ah yeah I didn’t think about that… But thank you so much! Day made yet again! <3

Thank you for the great example Action, @agiletortoise ! :slight_smile:

I’m modifying the Tweet Storm example Action to build a Mastodon version. I wanted to add two new features:

  • Mastodon’s CW (content warning)
  • the ability to directly reply to another status using Drafts

I succeeded at the first, but failed at the second. I hope someone could help me with debugging.


Here’s an abridged version of the implementation:

I used two Prompt action steps for the user to input

  • the warning text for CW
  • the link to the status to reply to, which contains the status ID at the end

So I parsed the two template tags, and matched for the ID at the end of the link:

const contentWarning = draft.processTemplate("[[cw_text]]");
const link = draft.processTemplate("[[link_text]]");
var inReplyTo = link.match(/\d+$/);

Then included contentWarning and inReplyTo in the POST request. Curiously, the content warning text works perfectly, but the status does not reply to another status and appears as a standalone status.

Here’s the complete Drafts Action file: Dropbox - Toot.draftsAction - Simplify your life. I would really appreciate any help!

1 Like

I’d add some alert calls in there to troubleshoot and make sure you are setting valid ID values.

1 Like

Thank you for the tip! <3

I did try to debug the script before posting, but I still could not understand what was wrong. Here’s what I did:

var inReplyTo = link.match(/\d+/); // match the ID at the end of the link

/*other stuff going on*/

alert(inReplyTo); // verify the value of `inReplyTo` just before the POST request

/*making the POST request*/

alert(json.in_reply_to_id); // parse the ID of the parent status from the JSON response immediately after the POST request

The first alert returns the correct ID, while the second alert returns null, which makes sense because the status indeed isn’t replying to another status.

I don’t have time to more fully troubleshoot, but I did test a modification of my example above with a hard-coded in_reply_to_id value, and it worked as expected.

Are you trying to set this up to post a thread that is a reply to an existing toot? That seems to be what you are trying to setup, not just to post a new thread, which is what the Tweet Storm action does.

Have you tried with different target reply IDs? I don’t know if Mastodon has option to not allow replies to certain types of statues, or similar that might affect the outcome. Docs are not real detailed.


Thank you for the time and patience, I really appreciate it!

Indeed, I was hoping to incorporate this into the existing Tweet Storm action, i.e. if a link is provided during the Prompt step, reply to the linked status; otherwise post as new status/new thread.

During the testing, I was always replying to my own public statuses. Also, since hard-coding the ID works, that should rule out this possibility.

Again, thank you for helping a noob out! :smiley:

Update: I managed to work around the issue.

I have zero idea why it didn’t work, but here’s the workaround: instead of using var inReplyTo = link.match(/\d+$/) to match the ID at the end of the link, directly input the ID during the Prompt step (by pasting the link first and manually delete everything before the ID).

Description of the previous script, which didn’t work:

  1. Prompt for link, which contains the ID at the end
  2. Regex match the ID at the end
  3. Using alert(), I verified that the ID was indeed matched
  4. Make POST request

Description of the new script, which works:

  1. Prompt for ID (paste the link and manually delete all the chars before the ID)
  2. Make POST request

I would appreciate it if anyone can provide some insight and tell me what went wrong. Meanwhile, I’m glad the script now functions correctly!

1 Like

Followed the instructions, set up my app on my Mastodon account, got the access token, entered it and the base URL the first time I ran the script. Script failed, and now if I delete it and reinstall, I do not get the option to add the token and URL again.

1 Like

Weird how I just joined so I could write the same thing. I don’t recall ever getting a prompt for that info, but I may be recalling poorly. Uninstalling and reinstalling the action did not help.

Try forgetting the credentials.

Oddly enough, it appears to have worked, though the feedback in app said it didn’t.

Had the same problem, same solution (forget the credentials) and I think the problem was that I missed the trailing ‘/’ in the URL the first time. But @agiletortoise , I got an error that suggests that this bit of code:

const host = credential.getValue(“host”);
const token = credential.getValue(“token”);

// make post
if (!host.endsWith(“/”)) {
host += “/”

doesn’t work because host is a const and thus can’t be appended to.