gnusocial.rocks/soc/2018/index.html

332 lines
24 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>ActivityPub plugin - Tech Report - GNU social Summer of Code 2018</title>
<link rel="icon" href="../../favicon.png">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://www.diogo.site/projects/excalibur_template/assets/css/main.css">
<style>
@page {
size: A4 portraint;
}
@page :blank {
@top-center { content: "This page is intentionally left blank." }
}
h1 {
page-break-before: always;
}
h1, h2, h3, h4, h5 {
page-break-after: avoid;
}
table, figure {
page-break-inside: avoid;
}
@page:right{
@bottom-right {
content: "Page " counter(page) " of " counter(pages);
}
}
</style>
</head>
<body>
<header id="header">
<nav id="side-menu">
<label for="show-menu" id="menu-button">Menu</label>
<input id="show-menu" role="button" type="checkbox">
<ul id="menu">
<li><a href="../"><strong>&larr; GS GSoC</strong></a></li>
<li><a href="#about">About</a></li>
<li><a href="#activitypub">ActivityPub</a></li>
<li><a href="#plugin-workflow">Plugin Workflow</a></li>
<li><a href="#inboxes">Inboxes</a></li>
<li><a href="#collections">Collections</a></li>
<li><a href="#acknowledgements">Acknowledgements</a></li>
<li><a href="#testimonials">Testimonials</a></li>
</ul>
</nav>
<h1>ActivityPub plugin for GNU social</h1>
<p>Developed by <strong><a href="https://www.diogo.site/">Diogo Cordeiro</a></strong> during <strong><a href="https://summerofcode.withgoogle.com/archive/2018/projects/5289876471676928/">Google Summer of Code 2018</a></strong></p>
<p>Mentored by <a href="https://github.com/dansup">Daniel Supernault</a> and <a href="https://mmn-o.se/">Mikael Nordfeldth</a></p>
</header>
<article id="about">
<h1><a href="#about">About the project and this document</a></h1>
<h2>What is this document?</h2>
<p>This is a technical Google Summer of Code Project Report describing
briefly what I did from April 23 to August 6.
</p>
<p>The whole code I wrote during this period is available
<a href="https://notabug.org/diogo/gnu-social-activitypub-plugin/src/6fbf37b7fee8c73271a47089a4f4a70304cf15a2">here</a>.
The API documentation is available
<a href="https://notabug.org/diogo/gnu-social-activitypub-plugin-doc/src/7188c0039793969417b4be912615125658f69377">here</a>.
</p>
<p>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.
</p>
<p>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.
</p>
<p>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.
</p>
<h2>What is GNU social?</h2>
<p>GNU social is a social communication software used in federated
social networks.
</p>
<h2>ActivityPub?</h2>
<p>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. <a href="https://www.w3.org/TR/activitypub/">ActivityPub</a>, however,
is the newest and covers parts left out of OStatus's specification, namely
app/client development.
</p>
<h3>Benefits</h3>
<ul>
<li>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 <a href="https://en.wikipedia.org/wiki/Fediverse">fediverse</a>;
</li>
<li>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.
</li>
</ul>
<h2>Why a plugin?</h2>
<h3 id="unix-tools-design-philosophy">Unix tools design philosophy</h3>
<p>GNU social is true to the Unix-philosophy of small programs to do a
small job.
</p>
<blockquote>
<ul>
<li>Compact and concise input syntax, making full use of ASCII repertoire to minimise keystrokes</li>
<li>Output format should be simple and easily usable as input for other programs</li>
<li>Programs can be joined together in “pipes” and “scripts” to solve more complex problems</li>
<li>Each tool originally performed a simple single function</li>
<li>Prefer reusing existing tools with minor extension to rewriting a new tool from scratch</li>
<li>The main user-interface software (“shell”) is a normal replaceable program without special privileges</li>
<li>Support for automating routine tasks</li>
</ul>
<footer>- Brian W. Kernighan, Rob Pike: The Unix Programming Environment. Prentice-Hall, 1984.</footer>
</blockquote>
<p>As so the project aims at building a plugin that will
implement the ActivityPub Protocol in GNU social.
</p>
</article>
<article id="activitypub">
<h1><a href="#activitypub">So how does ActivityPub work?</a></h1>
<p>The ActivityPub protocol is a decentralized social networking
protocol based upon the <a href="https://www.w3.org/TR/activitystreams-core/">ActivityStreams</a> 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.
</p>
<img src="https://www.w3.org/TR/activitypub/illustration/tutorial-2.png">
<blockquote>
<p><strong>Note:</strong> You are advised to read (at least) the <a href="https://www.w3.org/TR/activitypub/#Overview">standard
overview</a> before continuing.
</p>
</blockquote>
<h2>Actor</h2>
<p>Actor is the user doing a change in the fediverse and are identified by an URI.
In GNU social they have the following format:
<code>https://myinstance.net/user/{id}</code>. Thus allowing users to change their
usernames (or nicknames).
</p>
<h2 id="objects">Objects</h2>
<p>Objects are our building blocks for the bigger concept of Activity.
The plugin has the following objects:
</p>
<ul>
<li>Actors are defined by the <a href="https://notabug.org/diogo/gnu-social-activitypub-plugin-doc/src/7188c0039793969417b4be912615125658f69377/objects_and_activities.md#profile">profile object</a> which can be found <a href="https://notabug.org/diogo/gnu-social-activitypub-plugin/src/6fbf37b7fee8c73271a47089a4f4a70304cf15a2/classes/Activitypub_profile.php">here</a>.</li>
<li><a href="https://notabug.org/diogo/gnu-social-activitypub-plugin-doc/src/7188c0039793969417b4be912615125658f69377/objects_and_activities.md#Error">Error</a> which can be found <a href="https://notabug.org/diogo/gnu-social-activitypub-plugin/src/6fbf37b7fee8c73271a47089a4f4a70304cf15a2/classes/Activitypub_error.php">here</a>.</li>
<li><a href="https://notabug.org/diogo/gnu-social-activitypub-plugin-doc/src/7188c0039793969417b4be912615125658f69377/objects_and_activities.md#Tag">Tag</a> which can be found <a href="https://notabug.org/diogo/gnu-social-activitypub-plugin/src/6fbf37b7fee8c73271a47089a4f4a70304cf15a2/classes/Activitypub_tag.php">here</a>.</li>
<li><a href="https://notabug.org/diogo/gnu-social-activitypub-plugin-doc/src/7188c0039793969417b4be912615125658f69377/objects_and_activities.md#Mention">Mention Tag</a> which can be found <a href="https://notabug.org/diogo/gnu-social-activitypub-plugin/src/6fbf37b7fee8c73271a47089a4f4a70304cf15a2/classes/Activitypub_mention_tag.php">here</a>.</li>
<li><a href="https://notabug.org/diogo/gnu-social-activitypub-plugin-doc/src/7188c0039793969417b4be912615125658f69377/objects_and_activities.md#Notice">Notice</a> which can be found <a href="https://notabug.org/diogo/gnu-social-activitypub-plugin/src/6fbf37b7fee8c73271a47089a4f4a70304cf15a2/classes/Activitypub_notice.php">here</a>.</li>
<li><a href="https://notabug.org/diogo/gnu-social-activitypub-plugin-doc/src/7188c0039793969417b4be912615125658f69377/objects_and_activities.md#Attachment">Attachment</a> which can be found <a href="https://notabug.org/diogo/gnu-social-activitypub-plugin/src/6fbf37b7fee8c73271a47089a4f4a70304cf15a2/classes/Activitypub_attachment.php">here</a>.</li>
</ul>
<blockquote>
<p><strong>Note:</strong> Tags, Attachment and Image are ("minor")
objects and, usually, wrapped by ("major") objects.
</p>
</blockquote>
<h2>Activities</h2>
<p>Wrappers allow to give additional information on a given object.
The implemented wrappers are the following:
</p>
<ul>
<li><a href="https://notabug.org/diogo/gnu-social-activitypub-plugin-doc/src/7188c0039793969417b4be912615125658f69377/objects_and_activities.md#Create">Create</a> which can be found <a href="https://notabug.org/diogo/gnu-social-activitypub-plugin/src/6fbf37b7fee8c73271a47089a4f4a70304cf15a2/classes/Activitypub_create.php">here</a>.</li>
<li><a href="https://notabug.org/diogo/gnu-social-activitypub-plugin-doc/src/7188c0039793969417b4be912615125658f69377/objects_and_activities.md#Announce">Announce</a> which can be found <a href="https://notabug.org/diogo/gnu-social-activitypub-plugin/src/6fbf37b7fee8c73271a47089a4f4a70304cf15a2/classes/Activitypub_announce.php">here</a>.</li>
<li><a href="https://notabug.org/diogo/gnu-social-activitypub-plugin-doc/src/7188c0039793969417b4be912615125658f69377/objects_and_activities.md#Delete">Delete</a> which can be found <a href="https://notabug.org/diogo/gnu-social-activitypub-plugin/src/6fbf37b7fee8c73271a47089a4f4a70304cf15a2/classes/Activitypub_delete.php">here</a>.</li>
<li><a href="https://notabug.org/diogo/gnu-social-activitypub-plugin-doc/src/7188c0039793969417b4be912615125658f69377/objects_and_activities.md#Undo">Undo</a> which can be found <a href="https://notabug.org/diogo/gnu-social-activitypub-plugin/src/6fbf37b7fee8c73271a47089a4f4a70304cf15a2/classes/Activitypub_undo.php">here</a>.</li>
<li><a href="https://notabug.org/diogo/gnu-social-activitypub-plugin-doc/src/7188c0039793969417b4be912615125658f69377/objects_and_activities.md#Accept">Accept</a> which can be found <a href="https://notabug.org/diogo/gnu-social-activitypub-plugin/src/6fbf37b7fee8c73271a47089a4f4a70304cf15a2/classes/Activitypub_accept.php">here</a>.</li>
<li><a href="https://notabug.org/diogo/gnu-social-activitypub-plugin-doc/src/7188c0039793969417b4be912615125658f69377/objects_and_activities.md#Reject">Reject</a> which can be found <a href="https://notabug.org/diogo/gnu-social-activitypub-plugin/src/6fbf37b7fee8c73271a47089a4f4a70304cf15a2/classes/Activitypub_reject.php">here</a>.</li>
<li><a href="https://notabug.org/diogo/gnu-social-activitypub-plugin-doc/src/7188c0039793969417b4be912615125658f69377/objects_and_activities.md#Like">Like</a> which can be found <a href="https://notabug.org/diogo/gnu-social-activitypub-plugin/src/6fbf37b7fee8c73271a47089a4f4a70304cf15a2/classes/Activitypub_like.php">here</a>.</li>
<li><a href="https://notabug.org/diogo/gnu-social-activitypub-plugin-doc/src/7188c0039793969417b4be912615125658f69377/objects_and_activities.md#Follow">Follow</a> which can be found <a href="https://notabug.org/diogo/gnu-social-activitypub-plugin/src/6fbf37b7fee8c73271a47089a4f4a70304cf15a2/classes/Activitypub_follow.php">here</a>.</li>
</ul>
<p>By wrapping an <a href="#objects">object</a> with one of those we are
able to perform an action in name of a given Actor.
</p>
</article>
<article id="plugin-workflow">
<h1><a href="#plugin-workflow">And how does the plugin work?</a></h1>
<p>For the plugin I decided to create two key components.</p>
<h2 id="explorer">The Explorer</h2>
<p>Defined in this <a href="https://notabug.org/diogo/gnu-social-activitypub-plugin/src/6fbf37b7fee8c73271a47089a4f4a70304cf15a2/utils/explorer.php">file</a> it is responsable for grabbing remote users and creating an identity for those in the local instance. It is higly related with <a href="https://notabug.org/diogo/gnu-social-activitypub-plugin/src/6fbf37b7fee8c73271a47089a4f4a70304cf15a2/classes/Activitypub_profile.php">Activitypub_profile.php</a>.</p>
<h2 id="postman">The Postman</h2>
<p>This guy does the magic of <code>publishing</code> the <code>activities</code>
(thus the name ActivityPub!) to remote instances, he kinda is the
responsable for the federation provided by this plugin. Its code is <a href="https://notabug.org/diogo/gnu-social-activitypub-plugin/src/6fbf37b7fee8c73271a47089a4f4a70304cf15a2/utils/postman.php">here</a>.
</p>
<h3>Becoming familiar with GNU social's events</h3>
<p>We just know what and when to deliver something thanks to <a href="https://git.gnu.io/gnu/gnu-social/blob/nightly/EVENTS.txt">GNU social's events</a>.</p>
<h4>Events the plugin is handling</h4>
<div class="tasks">
<h5>Discovery Events</h5>
<ul>
<li>Find remote profiles from mentions in texts (<em>onEndFindMentions)</em></li>
<li>Allow to reference a remote profile (<em>onStartCommandGetProfile)</em></li>
<li>Allow to reference a remote profile (<em>onStartGetProfileUri)</em></li>
</ul>
<h5>Delivery Events</h5>
<ul>
<li>Notify remote instance of subscription (<em>onEndSubscribe</em>)</li>
<li>Notify remote instance when a subscription is canceled (<em>onEndUnsubscribe</em>)</li>
<li>Notify remote instances when a notice is liked (<em>onEndFavorNotice</em>)</li>
<li>Notify remote instances when a notice like is reverted (<em>onEndDisfavorNotice</em>)</li>
<li>Notify remote instances when a notice is deleted (<em>onEndDeleteOwnNotice</em>)</li>
<li>Notify remote instances when a notice is created (<em>onStartNoticeDistribute</em>)</li>
</ul>
</div>
<p>These are not the only events this plugin is listening to, but are
the most relevant. All these events hooks can be found <a href="https://notabug.org/diogo/gnu-social-activitypub-plugin/src/6fbf37b7fee8c73271a47089a4f4a70304cf15a2/ActivityPubPlugin.php">here</a>.
</p>
</article>
<article id="inboxes">
<h1><a href="#inboxes">Hold on, if you have a Postman then there sure is an inbox, right?</a></h1>
<p>Two actually! :)</p>
<p>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 <a href="https://gnu.io/social/try/">here</a>.
</p>
<p>Well, if two people live in the same place then our <a href="#postman">Postman</a> doesn't have to "travel" twice! Thus
the concept of <code><a href="https://www.w3.org/TR/activitypub/#shared-inbox-delivery">shared inbox</a></code>.
</p>
<p>Lets start with the <a href="https://www.w3.org/TR/activitypub/#inbox">inbox</a>. An
inbox is where we, I mean, the <a href="#postman">Postman</a> publishes
our Activity.
</p>
<p>By now you should have already realized that Activities are just
verbs wrapping objects thus basically forming a phrase:
<code>Actor</code> <code>verb</code> <code>Object</code> <code>to Attention Actor(s)</code>.
</p>
<p>Well, for each <code>Attention actor</code> we deliver the same
<code>Actor</code> <code>verb</code> <code>Object</code>.
</p>
<p>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.
</p>
<p>The <a href="#postman">Explorer</a> hands the <a href="#postman">Postman</a> the sharedInbox address always that
it is possible.
</p>
<ul>
<li>
<p>Inbox Handler code is <a href="https://notabug.org/diogo/gnu-social-activitypub-plugin/src/6fbf37b7fee8c73271a47089a4f4a70304cf15a2/utils/inbox_handler.php">here</a>.</p>
</li>
</ul>
</article>
<article id="collections">
<h1><a href="#collections">Our plugin also is a collector</a></h1>
<p>The following collections have been implemented:</p>
<div class="tasks">
<ul>
<li><a href="https://notabug.org/diogo/gnu-social-activitypub-plugin/src/6fbf37b7fee8c73271a47089a4f4a70304cf15a2/actions/apactorfollowers.php">Followers</a></li>
<li><a href="https://notabug.org/diogo/gnu-social-activitypub-plugin/src/6fbf37b7fee8c73271a47089a4f4a70304cf15a2/actions/apactorfollowing.php">Following</a></li>
<li><a href="https://notabug.org/diogo/gnu-social-activitypub-plugin/src/6fbf37b7fee8c73271a47089a4f4a70304cf15a2/actions/apactorliked.php">Liked</a></li>
<li><a href="https://notabug.org/diogo/gnu-social-activitypub-plugin/src/6fbf37b7fee8c73271a47089a4f4a70304cf15a2/actions/apactoroutbox.php">Outbox</a></li>
</ul>
</div>
<p>Collections are lists. And lists are very important in the world of
fediverse both for <a href="https://www.w3.org/TR/activitypub/#server-to-server-interactions">Server
to Server</a> and <a href="https://www.w3.org/TR/activitypub/#client-to-server-interactions">Client
to Server</a>.
</p>
</article>
<article id="todo">
<h1><a href="#todo">What is left to do?</a></h1>
<p>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!
</p>
<h2>Todo</h2>
<ul>
<li>Finish implementing Client to Server</li>
<li>Implement a Circuit Breaker</li>
<li>Redis caching of collections</li>
<li>Queues</li>
</ul>
</article>
<article id="left-out">
<h1><a href="#left-out">So, that was it?</a></h1>
<p>Not really, this document doesn't describe the implementation of
<a href="https://notabug.org/diogo/gnu-social-activitypub-plugin/src/6fbf37b7fee8c73271a47089a4f4a70304cf15a2/classes/Activitypub_rsa.php">
HTTP Signatures</a>, 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.
</p>
<h2>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?
</h2>
<p>Be sure to know <a href="https://www.restapitutorial.com/httpstatuscodes.html">HTTP Status Codes</a>
and to start soon with the <a href="https://en.wikipedia.org/wiki/Test-driven_development">Test-driven development</a>.
</p>
<p>And, obviously, follow rigorously the ActivityPub specification!</p>
<p>If you need help you can <a href="https://www.diogo.site/#contact">contact me</a>
or Daniel Supernault directly or, even better, join the
<a href="irc://irc.w3.org:6665/social">W3C social IRC channel (#social@irc.w3.org)</a>,
you will definitely find us both there! :)
</p>
<article id="acknowledgements">
<h1><a href="#acknowledgements">Final Words</a></h1>
<p>GSoC was a wonderful experience for me. I now feel more comfortable
with the GNU socials 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.
</p>
<p>I will try my best to regularly contribute to GNU social and other
projects.
</p>
<p>Thanks to Daniel Supernault and Mikael Nordfeldth for such a
wonderful experience and the knowledge.
</p>
</article>
<article id="testimonials">
<h1><a href="https://www.diogo.site/testimonials.html">Testimonials</a></h1>
<blockquote>
<p style="margin:0">You're active, persistent and productive. Keep it up and we'll all have a great summer of code!</p>
<footer>- Mikael Nordfeldth, GNU social Maintainer (2018) on my first GSoC evaluation</footer>
</blockquote>
<a href="https://mastodon.social/@dansup/100331648394320885"><img src="images/testimonial1.png"></a>
<a href="https://mastodon.social/@dansup/100353565526207146"><img src="images/testimonial2.png"></a>
<a href="https://mastodon.social/@dansup/100416797627457542"><img src="images/testimonial3.png"></a>
</article>
</article>
</body>
</html>