Skip to content

Instantly share code, notes, and snippets.

@jdormit
Last active March 12, 2022 04:23
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jdormit/1049324b95e5096be20ee9ad1d749104 to your computer and use it in GitHub Desktop.
Save jdormit/1049324b95e5096be20ee9ad1d749104 to your computer and use it in GitHub Desktop.
Notes about an ActivityPub implementation for Wordpress

Technical details

The plugin will do two things: set up an ActivityPub server running on the Wordpress instance, and transform the Wordpress web interface (both admin and public, e.g. comments) into an ActivityPub client.

Objects and collections

I want to offload as much of the object storage as possible to existing Wordpress capabilities. This means that instead of storing separate objects for blog posts, comments, users, etc., the server translates the data already in the WP database to the correct JSON representation on-demand when it needs to interact with these objects. However, there may be some additional metadata that the server needs to associate with the existing representations, which can be done using linking tables (post_id -> recipients, etc.).

Collections (inboxes, outboxes, likes, follows, etc.) will probably need to have their own tables in the DB, since there’s not an obvious analog to these in classic WP.

I want the object created by the plugin to be compatible with Mastodon, which may inform the way they look (object types, etc.).

Actions and responses

user publishes a blog post

The client posts a Create activity to the user’s outbox. The object of this activity is the blog post. The server constructs and attaches an appropriate Actor derived from the WP user. The server translates the blog post into a Post object, copying the appropriate recipients (those @-mentioned in the blog post, followers, etc.). The server posts the activity to the inboxes of the recipients.

user posts a comment

The client posts a Create activity to the user’s outbox. The object of this activity is the comment. The server constructs and attaches an appropriate Actor derived from the WP user. The server translates the comment into a Comment object, copying the appropriate recipients (those @-mentioned in the comment, etc.) and adding an “inReplyTo” that references the blog post or the parent comment. The server posts the activity to the inboxes of the recipients.

commentor w/ just name and email posts a comment

The client should ask the commentor if they want to authenticate to an existing ActivityPub Actor (Mastodon account, etc.). If yes, see “commentor authenticated to ActivityPub identity posts a comment”. Otherwise, the server constructs an ActivityPub identity on this server (@email_address@this_server.com) and posts the Create activity as detailed above using that Actor. This means that commentors with the same email will always comment as the same Actor, which is desirable.

anonymous commentor posts a comment

One way to handle this would be to have a catch-all Actor, @anonymous@this_server.com. There could be other ways.

commentor authenticates to an existing ActivityPub identity

I’ll need to write authentication logic for each supported ActivityPub app (Mastodon, PeerTube, etc.). Once authentication is successful, the client stores the auth token and identity in a cookie (put a “remember me” button). The server looks up the Actor associated with that identity and uses that Actor to post the comment as described above.

commentor authenticated to ActivityPub identity posts a comment

See above.

actor (user/commentor/other) likes a blog post

The client posts a Like activity with the blog post as its object to the Actor’s outbox. If the Actor is managed by this server, the server posts the Like to the relevant inboxes.

actor likes a comment

Same as for a blog post.

actor follows a blog

The typical Follow flow goes like this: the client posts a Follow activity to the Actor’s outbox. When the server recieves a Follow in its outbox, it sends the Follow to the relevant inbox (the inbox of the actor that is the object of the Follow). When a server recieves a Follow in its inbox, it sends either an Accept or a Reject to the inbox of the sending server (and if it Accepts, it adds the new follower to the followed Actor’s follers collections). When a server receives an Accept, it adds the followed Actor to the following Actor’s following collecion.

The problem in this case is that there isn’t an actual Actor representing the blog as a whole in my current model. One solution would be to have an Actor for the blog and call it a day, but I don’t really like that - it makes more sense for Actors to be individual people.

A better solution IMO would be to have the server maintain a followers collection for the blog as a whole without having an Actor for the blog. Then whenever a user publishes a new blog post it goes out to the blog’s followers as well as the user’s followers.

actor shares a post

The client posts an Announce activity to the Actor’s outbox. If this server manages the outbox, the server posts the Announce to the relevant inboxes. When the server receives an Announce in its inbox, it adds the activity to the target object’s shares collection.

actor shares a comment

Same as sharing a post.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment