If I understand correctly, ActivityPub implementation on Lemmy is just starting and is mostly dormant (which isn’t a dig on any of the developers since no one is getting paid to implement it). But is this because it’s hard to implement? Lack of knowledge? Or simply that no one has had the time to actually start implementing it? When we do get started, how big a project is it expected to be?

  • mariusor@lemmy.ml
    link
    fedilink
    arrow-up
    3
    ·
    5 years ago

    I’m not a lemmy dev, and I have no rust knowledge, but I can provide some of the issues I encountered while implementing activitypub libraries in Go.

    The biggest issue in the begining was the Json-LD representation of ActivityPub, which allows a property to have different typed values: it can be a URL, a list of URLs, a single Object or a list of Objects. In Go, this is possible by using custom Json marshaling/unmarshaling and some hand-wavy interface usage. I’m not sure how well Rust fares in this respect, but it might be a solved problem already if there’s a jsonld crate somewhere.

    The grammar/structure of the objects themselves is trivial and only requires one to create the types that represent the different activity streams vocabulary entities: Objects at the lowest level, Actors (which are just an alias for objects), Activities which are objects with a couple of extra properties. Some of the specific Object/Activity types have different structures, but again, nothing super complicated. I suspect this is a solved problem in the projects OP already mentioned in their other post.

    Exposing the ActivityPub end-points. This is not super complicated, mainly each Actor (which is the AP representatoin of a user or, in the case of lemmy, a community) must have an end-point where other AP services can reach it. This Actor also needs outbox and inbox collection endpoints, which can be queried by external clients/services.

    Implementing the Server to Server AcitivtyPub interactions (what is colloquially called “federating”). This is still work in progress for me, and probably this is where the major work will happen for Lemmy too. Basically an S2S interaction consists of a server (lemmy) disseminating a new post (let’s say) to the other servers. In AP grammar this means that a “Note”, “Article” object - in the case of self posts, or a “Page” object for links gets wrapped in a “Create” activity and gets dispatched to other servers.

    First issue: you need to build a recipients list for the activity. The way this is being done is not very well documented, if at all. There is a Public namespace which should send to all servers that the current one has knowledge about. There are specific lists of recipients in the forms of an Actor’s followers (eg, all members of a community) or other actor collections, or just specific actors. (Think of a mail’s recipients list, and it’s basically the same, except for the public namespace).

    Second issue: authorizing the requests to the other servers. This is generally being done by using the HTTP-Signatures mechanism. Every actors needs public/private keys, that are used for signing the requests to other servers. This is probably also a solved case for rust.

    Then there’s user discovery. Which you need when your server receives an activity from somewhere else. You need to load the Actor that created the activity and load their public key to validate the request’s http-signature.

    In mastodon land, user discovery is being done by using web-finger. On my project I use plain ActiviytPub with a custom end-point for actors.

    Now, all of this was a very light explanation of how/what’s needed to dispatch a single post from lemmy. ActivityPub has a number of other activity types that need to be implemented: Like/Dislike for voting, Update/Delete for content editing/deleting, Follow/Accept/Reject for community/user following, Announce for admin/user announcements, etc.

    Each of these most probably will require custom logic - which unfortunatelly is documented only at the most superficial level in the ActivityPub spec, and much is left to the implementors.

    So, in conclusion, this is no trivial amount of work, probably the devs have documented some of these steps in their issue tracker and maybe that’s a good place to start looking for low hanging fruit.

    Good luck. :)

    • mariusor@lemmy.ml
      link
      fedilink
      arrow-up
      2
      ·
      5 years ago

      Another thing which I forgot to mention is computing/storing the scores for the posts.

      In my implementation I have a real dumb way of doing it, where I just count the number of Likes/Dislikes on an item that represents the object and display that. The problem with this is that you need to load the collection that stores these on each object you want to display (eg: https://federated.id/objects/8592f693-d43f-4713-ba0c-86314520b787/likes ), which is very slow on a post with a lot of comments.

      Probably a better way to do it would be to add a “Score” property to the objects (yeah, I forgot to mention that ActivityPub supports extensions :D) which would expose the precomputed score. I will probably get to adding that, but not anytime soon to be honest.