Fetch Peertube Outbox activities

For some usages, you may use an instance without having to configure many items.

For instance, if you want to fetch some public activities, you don’t need to have a fully-configured server instance. Indeed, you don’t need any configuration at all.

Fetch an Outbox

use ActivityPhp\Server;

// Create a server instance
$server = new Server();

$handle = 'nickname@example.org';

// Get an actor's outbox as an OrderedCollection
$outbox = $server->outbox($handle);

// Prepare a stack
$pages = [];

// Browse first page
$page = $outbox->getPage($outbox->get()->first);

// Browse all pages and get public actvities
$pages[] = $page;
while ($page->next !== null) {
    $page = $outbox->getPage($page->next);
    $pages[] = $page;
}

And that’s it, you have an array containing all pages.

Therefore, if you test this implementation on a real world ActivityPub-powered application like Peertube, you would have something like:

Exception: Property "uuid" is not defined. Type="Video", Class="\ActivityPhp\Type\Extended\Object\Video"

Indeed, Peertube (and others like Mastodon) extends the ActivityPub object model to fit their needs.

So, in order to fetch Peertube’s activities, we need to extend our base models with Peertube dialect.


Define Peertube’s dialect

We will only partially implement peertube’s model.

After a step-by-step exceptions analysis, we’ve collected all attributes that are specific.

use ActivityPhp\Type;
use ActivityPhp\Type\Core\ObjectType;
use ActivityPhp\Type\Core\Link as BaseLink;
use ActivityPhp\Type\Extended\Actor\Person as BasePerson;
use ActivityPhp\Type\Extended\Object\Image as BaseImage;
use ActivityPhp\Type\Extended\Object\Video as BaseVideo;

// User
class Person extends BasePerson
{
    protected $uuid;            // Peertube specific
    protected $publicKey;       // Peertube specific
}

// Channel
class Group extends Person
{
    protected $support;         // Peertube specific    
}

class Video extends BaseVideo
{
    protected $uuid;            // Peertube specific
    protected $category;        // Peertube specific
    protected $language;        // Peertube specific
    protected $views;           // Peertube specific
    protected $sensitive;       // Peertube specific
    protected $waitTranscoding; // Peertube specific
    protected $state;           // Peertube specific
    protected $commentsEnabled; // Peertube specific
    protected $support;         // Peertube specific
    protected $subtitleLanguage;// Peertube specific
    protected $likes;           // Peertube specific
    protected $dislikes;        // Peertube specific
    protected $shares;          // Peertube specific
    protected $comments;        // Peertube specific
    protected $licence;         // Peertube specific
}

class Image extends BaseImage
{
    protected $width;           // Peertube specific
    protected $height;          // Peertube specific
}

class Link extends BaseLink
{
    protected $fps;             // Peertube specific
    protected $mimeType;        // Peertube specific
    protected $size;            // Peertube specific
}

// Create a new Type
class HashTag extends ObjectType
{
    protected $type = 'HashTag';// Peertube specific
}

If you need to implement a specific dialect, just have a look at our ActivityStreams types. Then, you may see which properties are already defined:

use ActivityPhp\Type;

print_r(
    Type::create('Video')->getProperties()
);

This will output all normalized ActivityPub’s properties for a type.

Array
(
    [0] => type
    [1] => id
    [2] => attachment
    [3] => attributedTo
    [4] => audience
    [5] => content
    [6] => context
    [7] => contentMap
    [8] => name
    [9] => nameMap
    [10] => endTime
    [11] => generator
    [12] => icon
    [13] => image
    [14] => inReplyTo
    [15] => location
    [16] => preview
    [17] => published
    [18] => replies
    [19] => startTime
    [20] => summary
    [21] => summaryMap
    [22] => tag
    [23] => updated
    [24] => url
    [25] => to
    [26] => bto
    [27] => cc
    [28] => bcc
    [29] => mediaType
    [30] => duration
    [31] => source
)

After that, we push all new definitions into our pool:

// Add custom definitions to override defaults or introduce new ones
Type::add('Group',   Group::class);
Type::add('HashTag', HashTag::class); # new one
Type::add('Image',   Image::class);
Type::add('Link',    Link::class);
Type::add('Person',  Person::class);
Type::add('Video',   Video::class);

And now we can work with Peertube’s objects!


Fetch Peertube Outbox activities

Below, a complete script to work with Peertube’s objects. It browses all outbox pages, collect all activities and display a list of activities and their videos names.

use ActivityPhp\Type;
use ActivityPhp\Server;

/* ------------------------------------------------------------------
 | We'll use the following definitions to fit PeerTube's dialect 
   ------------------------------------------------------------------ */
use ActivityPhp\Type\Core\ObjectType;
use ActivityPhp\Type\Core\Link as BaseLink;
use ActivityPhp\Type\Extended\Actor\Person as BasePerson;
use ActivityPhp\Type\Extended\Object\Image as BaseImage;
use ActivityPhp\Type\Extended\Object\Video as BaseVideo;

// User
class Person extends BasePerson
{
    protected $uuid;            // Peertube specific
    protected $publicKey;       // Peertube specific
}

// Channel
class Group extends Person
{
    protected $support;         // Peertube specific    
}

class Video extends BaseVideo
{
    protected $uuid;            // Peertube specific
    protected $category;        // Peertube specific
    protected $language;        // Peertube specific
    protected $views;           // Peertube specific
    protected $sensitive;       // Peertube specific
    protected $waitTranscoding; // Peertube specific
    protected $state;           // Peertube specific
    protected $commentsEnabled; // Peertube specific
    protected $support;         // Peertube specific
    protected $subtitleLanguage;// Peertube specific
    protected $likes;           // Peertube specific
    protected $dislikes;        // Peertube specific
    protected $shares;          // Peertube specific
    protected $comments;        // Peertube specific
    protected $licence;         // Peertube specific
}

class Image extends BaseImage
{
    protected $width;           // Peertube specific
    protected $height;          // Peertube specific
}

class Link extends BaseLink
{
    protected $fps;             // Peertube specific
    protected $mimeType;        // Peertube specific
    protected $size;            // Peertube specific
}

// Create a new Type
class HashTag extends ObjectType
{
    protected $type = 'HashTag';// Peertube specific
}

// Add custom definitions to override defaults or introduce new ones
Type::add('Group',   Group::class);
Type::add('HashTag', HashTag::class); # new one
Type::add('Image',   Image::class);
Type::add('Link',    Link::class);
Type::add('Person',  Person::class);
Type::add('Video',   Video::class);


/* ------------------------------------------------------------------
 | Now we can use an instance with a PeerTube flavor
   ------------------------------------------------------------------ */

// Create a server instance
$server = new Server();

$handle = 'nickname@example.org';

// Get an actor's outbox as an OrderedCollection
$outbox = $server->outbox($handle);

// Prepare a stack
$pages = [];

// Browse first page
$page = $outbox->getPage($outbox->get()->first);

// Browse all pages and get public actvities
$pages[] = $page;
while ($page->next !== null) {
    $page = $outbox->getPage($page->next);
    $pages[] = $page;
}

// Now we can work with pages
foreach ($pages as $page) {
    foreach ($page->orderedItems as $item) {
        echo sprintf(
            "Type=%s, Name=%s\n",
            $item->type,            // Activity type
            $item->object->name     // Video name
        );
    }
}

Read more


Edit this document on GitHub