by Darius Kazemi, Dec 10, 2019
When I'm developing for ActivityPub it can be helpful to have a way to send an arbitrary JSON payload from a remote server. I wrote an application in Glitch that:
Create
ActvityMy actual use case is: I'm trying to make my software compatible with some new-to-me federated software. I do a curl request to get the JSON for a message from their software, and then copy/paste it into the compose box in this tool, sometimes editing it lightly. I hit send, and the object is now sent to my subscribed user.
This way I don't need to create accounts on other tools in order to send test messages to my instance. It's great for debugging ActivityPub bugs too, you can very quickly iterate on how an Object should be composed in order to get what you want.
Click here to remix this project on Glitch (aka clone it).
Click "Show" in the upper left and open in a new window. After a brief "wake-up" period, you should see a simple web form and if you look at the URL bar there will be an automatically generated subdomain at the glitch.me
domain. Take note of this, and go back to the editor and select the .env
file from the file list on the left. You'll see this:
USER=
PASS=
DOMAIN=
Put a username and a password in there. For the domain, enter the full subdomain and domain but without the protocol portion. It should look something like this now:
USER=admin
PASS=MyAmazingPassword
DOMAIN=funny-name.glitch.me
The content of the .env
file is kept secret even from people who remix your project, so this is where we store our admin password. The SQLite database that contains all of the information for this little server lives in a special directory called .data/
, which is likewise kept secret from prying eyes. If you need to access the database directly, click on "Tools" at the bottom of the file tree, then "Full Page Console", and then cd .data
and sqlite3 bot-node.db
.
Next, create a test account by entering a username under "Create Account" and then giving it your admin user/pass when prompted. You should now have an ActivityPub actor that can be found at either https://YOUR_SUBDOMAIN.glitch.me/u/YOUR_USERNAME
or by searching most AP-compatible software for @YOUR_USERNAME@YOUR_SUBDOMAIN.glitch.me
.
Write down the API key that it gives you, along with the username. You'll need this to send future messages. (I did it this way so that if you wanted to give a secondary user an account to play around with but not your admin password, you can just give them a username and API key that you create for them.)
Search for the account from your ActivityPub software of choice and send a follow request. This server should acknowledge and Accept the follow.
The moment of truth! Put the username and the API key in the "Send Message To Followers" field. Then drop in some valid JSON for the object you're going to send. A good test message is:
{
"@context": ["https://www.w3.org/ns/activitystreams"],
"type": "Note",
"content": "Hello world."
}
(The above object will be given a to
field plus some other necessities. See below for more.)
There is also a link right in the form to a gist that I maintain of various object formats seen in the wild.
When you send a raw JSON payload, it sends one Create Activity for each follower. This is what it sends as the Create Event wrapper:
{
"@context":"https://www.w3.org/ns/activitystreams",
"id":"https://YOUR_DOMAIN/m/SOME_GUID",
"type":"Create",
"actor":"https://YOUR_DOMAIN/u/USER_NAME",
"to":["https://SOME_FOLLOWER"],
"object": { YOUR_RAW_JSON }
}
Note that nothing is sent to https://www.w3.org/ns/activitystreams#Public
by default because this is a debugging tool and this stuff probably shouldn't show up in the public timelines of instances that have them.
No matter what JSON you send, the tool will overwrite or create couple of fields.
id
is given a unique and dereferencable url (you can make a request to the url and get the object JSON back)published
is given the current timestamp as an ISO 8601 stringattributedTo
is given the url of your actor that is sending the objectto
is an array of a single string, which is the url of the follower it's being sent tocontent
is unescapedOf course if you need to make any adjustments, you have the code! The stuff you care about is in routes/api.js
and specifically the rawMessage()
function is what creates the message and its wrapper.
Copyright (c) 2019 Darius Kazemi. Licensed under the MIT license.