# About the project and this document

## What is this document?

This is a technical Google Summer of Code Project Report describing briefly what I did from April 23 to August 6.

The whole code I wrote during this period is available here. The API documentation is available here.

This document helps understanding what was done in a simple and informal way, highlighting the most relevant parts, why some decisions were made and what I've learned with it.

The following document is intended to be reasonably self contained and capable of quickstarting anyone in the world of ActivityPub implementation, yet not replacing the official standard specification.

From April 23 to May 14 I had to familiarize myself with the Activity Pub standard and GNU social's plugins/events API and community.

## What is GNU social?

GNU social is a social communication software used in federated social networks.

## ActivityPub?

In order to achieve said decentralization, a variety of standards on how communication between different pieces of software in a federated context should be done were created, such as OStatus. ActivityPub, however, is the newest and covers parts left out of OStatus's specification, namely app/client development.

### Benefits

- The tendency is that newer software will focus in the implementation of the ActivityPub Protocol (as it is newer and considered to be simpler) instead of OStatus, given that, it is important for GNU social to support it in order to stay updated and relevant in an even larger fediverse;
- It will simplify app/client development which is not covered by the OStatus's specification and is becoming more and more relevant, with the increase of smartphone users.

## Why a plugin?

### Unix tools design philosophy

GNU social is true to the Unix-philosophy of small programs to do a small job.

> - Compact and concise input syntax, making full use of ASCII repertoire to minimise keystrokes
> - Output format should be simple and easily usable as input for other programs
> - Programs can be joined together in “pipes” and “scripts” to solve more complex problems
> - Each tool originally performed a simple single function
> - Prefer reusing existing tools with minor extension to rewriting a new tool from scratch
> - The main user-interface software (“shell”) is a normal replaceable program without special privileges
> - Support for automating routine tasks

As so the project aims at building a plugin that will implement the ActivityPub Protocol in GNU social.

# So how does ActivityPub work?

The ActivityPub protocol is a decentralized social networking protocol based upon the ActivityStreams 2.0 data format. It provides a client to server API for creating, updating and deleting content, as well as a federated server to server API for delivering notifications and content.

> Note: You are advised to read (at least) the standard overview before continuing.

## Actor

Actor is the user doing a change in the fediverse and are identified by an URI. In GNU social they have the following format: `https://myinstance.net/user/{id}`. Thus allowing users to change their usernames (or nicknames).

## Objects

Objects are our building blocks for the bigger concept of Activity. The plugin has the following objects:

- Actors are defined by the profile object which can be found here.
- Error which can be found here.
- Tag which can be found here.
- Mention Tag which can be found here.
- Notice which can be found here.
- Attachment which can be found here.

> Note: Tags, Attachment and Image are ("minor") objects and, usually, wrapped by ("major") objects.

## Activities

Wrappers allow to give additional information on a given object. The implemented wrappers are the following:

- Create which can be found here.
- Announce which can be found here.
- Delete which can be found here.
- Undo which can be found here.
- Accept which can be found here.
- Reject which can be found here.
- Like which can be found here.
- Follow which can be found here.

By wrapping an object with one of those we are able to perform an action in name of a given Actor.

# And how does the plugin work?

For the plugin I decided to create two key components.

## The Explorer

Defined in this file it is responsable for grabbing remote users and creating an identity for those in the local instance. It is higly related with Activitypub_profile.php.

## The Postman

This guy does the magic of `publishing` the `activities` (thus the name ActivityPub!) to remote instances, he kinda is the responsable for the federation provided by this plugin. Its code is here.

### Becoming familiar with GNU social's events

We just know what and when to deliver something thanks to GNU social's events.

#### Events the plugin is handling

##### Discovery Events

- Find remote profiles from mentions in texts (onEndFindMentions)
- Allow to reference a remote profile (onStartCommandGetProfile)
- Allow to reference a remote profile (onStartGetProfileUri)

##### Delivery Events

- Notify remote instance of subscription (onEndSubscribe)
- Notify remote instance when a subscription is canceled (onEndUnsubscribe)
- Notify remote instances when a notice is liked (onEndFavorNotice)
- Notify remote instances when a notice like is reverted (onEndDisfavorNotice)
- Notify remote instances when a notice is deleted (onEndDeleteOwnNotice)
- Notify remote instances when a notice is created (onStartNoticeDistribute)

These are not the only events this plugin is listening to, but are the most relevant. All these events hooks can be found here.

# Hold on, if you have a Postman then there sure is an inbox, right?

Two actually! :)

Fediverse is similar to the real world in some aspects. And one of those is that people, sometimes, share the same "building". A list of some public GNU social instances is available here.

Well, if two people live in the same place then our Postman doesn't have to "travel" twice! Thus the concept of `shared inbox`.

Lets start with the inbox. An inbox is where we, I mean, the Postman publishes our Activity.

By now you should have already realized that Activities are just verbs wrapping objects thus basically forming a phrase: `Actor` `verb` `Object` `to Attention Actor(s)`.

Well, for each `Attention actor` we deliver the same `Actor` `verb` `Object`.

Since it is the same message and frequently for people residing in the same server we can obviously reduce a lot of traffic and processing power here.

The Explorer hands the Postman the sharedInbox address always that it is possible.

- Inbox Handler code is here.

# Our plugin also is a collector

The following collections have been implemented:

- Followers
- Following
- Liked
- Outbox

Collections are lists. And lists are very important in the world of fediverse both for Server to Server and Client to Server.

# What is left to do?

This plugin fulfills and even exceeds what I've originally proposed to do during this summer (hooray!). But there is still room for further development and improvement!

## Todo

- Finish implementing Client to Server
- Implement a Circuit Breaker
- Redis caching of collections
- Queues

# So, that was it?

Not really, this document doesn't describe the implementation of HTTP Signatures, the internal representation of ActivityPub Actors, nor the details of Activity Streams or even the particularities of integrating this in GNU social (I'm looking at you OStatus plugin). As stated in the beginning of this document, the whole code and documentation is available above, this was just meant to make the reading easier.

## I'm interested in implementing ActivityPub on my program and reading this really helped me! Is there something else that I should know of that wasn't mentioned in the article?

Be sure to know HTTP Status Codes and to start soon with the Test-driven development.

And, obviously, follow rigorously the ActivityPub specification!

If you need help you can contact me or Daniel Supernault directly or, even better, join the W3C social IRC channel (#social@irc.w3.org), you will definitely find us both there! :)

# Final Words

GSoC was a wonderful experience for me. I now feel more comfortable with the GNU social’s codebase. I learned a lot of useful stuff like ActivityPub, ActivityStreams, HTTP Signatures, PSR and Redis as well as software engineering concepts like Circuit Breakers. I've also learned more about Git and how libre and open source software development is done and organized.

I will try my best to regularly contribute to GNU social and other projects.

Thanks to Daniel Supernault and Mikael Nordfeldth for such a wonderful experience and the knowledge.

# Testimonials

> You're active, persistent and productive. Keep it up and we'll all have a great summer of code!