Working with the Mastodon API in BoxLang

So remember a long time ago (Tuesday), when I blogged about using the Bluesky API with BoxLang? As expected, I’m following that up today with a look at using the Mastodon APIs. Personally, I’m down to just two social networks, Bluesky and Mastodon. Originally I was using Mastodon a lot more, but I’ve been vibing with Bluesky more lately so I tend to check it more often. That being said, whenever I release a new blog post, I’ve got an automated process to post to both, so I thought I should cover both for BoxLang as well.

Even better… I already did this in ColdFusion! Way back in October 2023, I blogged about the topic and even shared a simple ColdFusion component for it. That made ‘translating’ to BoxLang even easier.

Auth

As a refresher, authentication with Mastodon is simpler. In your profile, you go into your developer settings and create a token. That’s it. All you need along with that is the server your account runs on. So I specified too environment variables for this, MASTO_TOKEN and MASTO_SERVER. I verified it like so:

MASTO_TOKEN = server.system.environment?.MASTO_TOKEN ?: ''; MASTO_SERVER = server.system.environment?.MASTO_SERVER ?: '';  if(MASTO_TOKEN == "" || MASTO_SERVER == "") { 	println('Ensure the Mastodon token env vars are set: MASTO_TOKEN and MASTO_SERVER'); 	abort; } 

Posting Messages

As I said, you don’t need anything more than that token, so posting a toot (message) is as simple as:

toot = 'Hello World from BoxLang, #now()#';  bx:http url='https://#MASTO_SERVER#/api/v1/statuses' method='post' result='result' {     bx:httpparam type='header' name='Authorization' value='Bearer #MASTO_TOKEN#';     bx:httpparam type='formfield' name='status' value=toot; } 

Literally, that’s it. You get a large post object back you can inspect if need be.

Using Images

How about images? Like Bluesky, they’ve got a different endpoint for that. Here’s an example sending up a cat picture.

bx:http url='https://#MASTO_SERVER#/api/v2/media' method='post' result='result' {     bx:httpparam type='header' name='Authorization' value='Bearer #MASTO_TOKEN#';     bx:httpparam type='file' name='file' file=expandPath('./cat1.jpg'); }  mediaOb = result.filecontent.fromJSON(); 

This returns a media object where all you need is the id, and to add it to your post, it’s one line of code:

toot = 'Hello World from BoxLang, #now()#, with an image.';  bx:http url='https://#MASTO_SERVER#/api/v1/statuses' method='post' result='result' {     bx:httpparam type='header' name='Authorization' value='Bearer #MASTO_TOKEN#';     bx:httpparam type='formfield' name='status' value=toot; 	bx:httpparam type='formfield' name='media_ids[]' value=mediaOb.id; } 

Here’s a complete script showing this in action:

MASTO_TOKEN = server.system.environment?.MASTO_TOKEN ?: ''; MASTO_SERVER = server.system.environment?.MASTO_SERVER ?: '';  if(MASTO_TOKEN == "" || MASTO_SERVER == "") { 	println('Ensure the Mastodon token env vars are set: MASTO_TOKEN and MASTO_SERVER'); 	abort; }   toot = 'Hello World from BoxLang, #now()#';  bx:http url='https://#MASTO_SERVER#/api/v1/statuses' method='post' result='result' {     bx:httpparam type='header' name='Authorization' value='Bearer #MASTO_TOKEN#';     bx:httpparam type='formfield' name='status' value=toot; }  dump(result.fileContent);  // test with media  bx:http url='https://#MASTO_SERVER#/api/v2/media' method='post' result='result' {     bx:httpparam type='header' name='Authorization' value='Bearer #MASTO_TOKEN#';     bx:httpparam type='file' name='file' file=expandPath('./cat1.jpg'); }  mediaOb = result.filecontent.fromJSON(); toot = 'Hello World from BoxLang, #now()#, with an image.';  bx:http url='https://#MASTO_SERVER#/api/v1/statuses' method='post' result='result' {     bx:httpparam type='header' name='Authorization' value='Bearer #MASTO_TOKEN#';     bx:httpparam type='formfield' name='status' value=toot; 	bx:httpparam type='formfield' name='media_ids[]' value=mediaOb.id; }  dump(result.fileContent.fromJSON()); 

I turned this into a BoxLang class. It’s a bit different from the Bluesky one in terms of API shape and I may address that at some point, but for now, here’s that class:

class {  	property name="token" type="string"; 	property name="server" type="string";  	public function uploadMedia(required string path) { 		checkAuth();  		bx:http url='https://#variables.server#/api/v2/media' method='post' result='result' { 			bx:httpparam type='header' name='Authorization' value='Bearer #variables.token#'; 			bx:httpparam type='file' name='file' file=path; 		}  		return result.fileContent.fromJSON();  	}  	public function post(required string toot, image="") { 		checkAuth();  		bx:http url='https://#variables.server#/api/v1/statuses' method='post' result='result' {			 			bx:httpparam type='header' name='Authorization' value='Bearer #variables.token#'; 			bx:httpparam type='formfield' name='status' value=toot; 			if(image !== '') { 				imageOb = uploadMedia(image); 				bx:httpparam type='formfield' name='media_ids[]' value=imageOb.id; 			} 		}  		return result.fileContent.fromJSON();  	}  	/* 	* Utility function to ensure auth is set.  	*/ 	private function checkAuth() { 		if(variables.token == "" || variables.server == "") { 			throw("Component initialized with blank, or missing, handle and password values."); 		} 	} } 

And an example using it:

masto = new mastodon(token=MASTO_TOKEN, server=MASTO_SERVER);  post = masto.post("Hello from the API, promise this is the last(ish) test."); dump(post);  // now with an image test post = masto.post("Honest, this should be the last test. Really.",expandPath('./cat1.jpg')); dump(post);  println('done'); 

Here’s my most recent test on one of my cooler bot accounts:

Post by @dragonhoards@mastodon.social
View on Mastodon

Fairly simple, right? If you take this along with the code from the previous post, you could easily automate posting to both in a few lines of code.

As before, you can find these samples in the BoxLang demos repo here: https://github.com/ortus-boxlang/bx-demos/tree/master/scripting Look for test_mastodon.bxs, test_mastodon2.bxs, and mastodon.bx. Enjoy!

Raymond Camden

Posted in: JavaScript

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.