Browse Source

AS: parse likes and reposts

pull/78/head v1.6.2
Aaron Parecki 3 years ago
parent
commit
ca9c8c02ef
No known key found for this signature in database GPG Key ID: 276C2817346D6056
4 changed files with 182 additions and 2 deletions
  1. +46
    -2
      lib/XRay/Formats/ActivityStreams.php
  2. +37
    -0
      tests/ActivityStreamsTest.php
  3. +48
    -0
      tests/data/activitystreams.example/like.json
  4. +51
    -0
      tests/data/activitystreams.example/repost.json

+ 46
- 2
lib/XRay/Formats/ActivityStreams.php View File

@ -34,6 +34,8 @@ class ActivityStreams extends Format {
return self::parseAsHCard($as2, $url, $http, $opts);
case 'Article':
case 'Note':
case 'Announce': // repost
case 'Like': // like
return self::parseAsHEntry($as2, $url, $http, $opts);
}
@ -62,6 +64,12 @@ class ActivityStreams extends Format {
$date = new DateTime($as2['published']);
$data['published'] = $date->format('c');
} catch(\Exception $e){}
} elseif(isset($as2['signature']['created'])) {
// Pull date from the signature if there isn't one in the activity
try {
$date = new DateTime($as2['signature']['created']);
$data['published'] = $date->format('c');
} catch(\Exception $e){}
}
if(isset($as2['name'])) {
@ -129,16 +137,52 @@ class ActivityStreams extends Format {
}
// Fetch the author info, which requires an HTTP request
$authorURL = false;
if(isset($as2['attributedTo']) && is_string($as2['attributedTo'])) {
$authorResponse = $http->get($as2['attributedTo'], ['Accept: application/activity+json,application/json']);
$authorURL = $as2['attributedTo'];
} elseif(isset($as2['actor']) && is_string($as2['actor'])) {
$authorURL = $as2['actor'];
}
if($authorURL) {
$authorResponse = $http->get($authorURL, ['Accept: application/activity+json,application/json']);
if($authorResponse && !empty($authorResponse['body'])) {
$authorProfile = json_decode($authorResponse['body'], true);
$author = self::parseAsHCard($authorProfile, $as2['attributedTo'], $http, $opts);
$author = self::parseAsHCard($authorProfile, $authorURL, $http, $opts);
if($author && !empty($author['data']))
$data['author'] = $author['data'];
}
}
// If this is a repost, fetch the reposted content
if($as2['type'] == 'Announce' && isset($as2['object']) && is_string($as2['object'])) {
$data['repost-of'] = [$as2['object']];
$reposted = $http->get($as2['object'], ['Accept: application/activity+json,application/json']);
if($reposted && !empty($reposted['body'])) {
$repostedData = json_decode($reposted['body'], true);
if($repostedData) {
$repost = self::parse($repostedData, $as2['object'], $http, $opts);
if($repost) {
$refs[$as2['object']] = $repost;
}
}
}
}
// If this is a like, fetch the liked post
if($as2['type'] == 'Like' && isset($as2['object']) && is_string($as2['object'])) {
$data['like-of'] = [$as2['object']];
$liked = $http->get($as2['object'], ['Accept: application/activity+json,application/json']);
if($liked && !empty($liked['body'])) {
$likedData = json_decode($liked['body'], true);
if($likedData) {
$like = self::parse($likedData, $as2['object'], $http, $opts);
if($like) {
$refs[$as2['object']] = $like;
}
}
}
}
$data['post-type'] = PostType::discover($data);
$response = [

+ 37
- 0
tests/ActivityStreamsTest.php View File

@ -173,4 +173,41 @@ class ActivityStreamsTest extends PHPUnit_Framework_TestCase {
$this->assertArrayNotHasKey('name', $data['data']);
}
public function testRepost() {
$url = 'http://activitystreams.example/repost.json';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals('activity+json', $data['source-format']);
$this->assertEquals('repost', $data['data']['post-type']);
$this->assertArrayNotHasKey('content', $data['data']);
$this->assertArrayNotHasKey('name', $data['data']);
$this->assertEquals('Gargron', $data['data']['author']['nickname']);
$this->assertEquals(['http://activitystreams.example/note.json'], $data['data']['repost-of']);
$this->assertArrayHasKey('http://activitystreams.example/note.json', $data['data']['refs']);
$this->assertEquals('This is the text content of an ActivityStreams note', $data['data']['refs']['http://activitystreams.example/note.json']['data']['content']['text']);
}
public function testLike() {
$url = 'http://activitystreams.example/like.json';
$response = $this->parse(['url' => $url]);
$body = $response->getContent();
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($body, true);
$this->assertEquals('activity+json', $data['source-format']);
$this->assertEquals('like', $data['data']['post-type']);
$this->assertArrayNotHasKey('content', $data['data']);
$this->assertArrayNotHasKey('name', $data['data']);
$this->assertEquals('Gargron', $data['data']['author']['nickname']);
$this->assertEquals(['http://activitystreams.example/note.json'], $data['data']['like-of']);
$this->assertArrayHasKey('http://activitystreams.example/note.json', $data['data']['refs']);
$this->assertEquals('This is the text content of an ActivityStreams note', $data['data']['refs']['http://activitystreams.example/note.json']['data']['content']['text']);
}
}

+ 48
- 0
tests/data/activitystreams.example/like.json View File

@ -0,0 +1,48 @@
HTTP/1.1 200 OK
Server: Apache
Date: Wed, 30 Jul 2018 03:29:14 GMT
Content-Type: application/activity+json
Connection: keep-alive
{
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/v1",
{
"manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
"sensitive": "as:sensitive",
"movedTo": {
"@id": "as:movedTo",
"@type": "@id"
},
"Hashtag": "as:Hashtag",
"ostatus": "http://ostatus.org#",
"atomUri": "ostatus:atomUri",
"inReplyToAtomUri": "ostatus:inReplyToAtomUri",
"conversation": "ostatus:conversation",
"toot": "http://joinmastodon.org/ns#",
"Emoji": "toot:Emoji",
"focalPoint": {
"@container": "@list",
"@id": "toot:focalPoint"
},
"featured": {
"@id": "toot:featured",
"@type": "@id"
},
"schema": "http://schema.org#",
"PropertyValue": "schema:PropertyValue",
"value": "schema:value"
}
],
"id": "http://activitystreams.example/Gargron#likes/9165926",
"type": "Like",
"actor": "http://activitystreams.example/Gargron",
"object": "http://activitystreams.example/note.json",
"signature": {
"type": "RsaSignature2017",
"creator": "http://activitystreams.example/Gargron#main-key",
"created": "2018-07-31T02:35:52Z",
"signatureValue": "BPNSmAPsULjeyoA67QmlYOIJiOZJcoAcczl9326O2mqd4P40yu+IL7B6J2EbWGkXoJiP/Pd+cVV/8+Anpzmo994Xc39R8STE/QRzHuLPOf0ZNB/1xf2wqPqf5H74D8sehzOexcEGIy9vfdLmSI5bpBoU1S9ljhfC/18YwaC30eKD3gsqu4qnlNw6EgOfutKYrCBwOT2+pVvbH5D8eMFMZ//RGyWJw/DMRoW7m/8yOsGOmc+lOw6ufQpDfhEKp+MET2RbAfubMbsec6puPhXGgx9Lzl9T9s9j+Ile37juhX/miN990t7mx2RmjjYSSdXw2anRd7CaSnnXnwnpaGxEiQ=="
}
}

+ 51
- 0
tests/data/activitystreams.example/repost.json View File

@ -0,0 +1,51 @@
HTTP/1.1 200 OK
Server: Apache
Date: Wed, 30 Jul 2018 03:29:14 GMT
Content-Type: application/activity+json
Connection: keep-alive
{
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/v1",
{
"manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
"sensitive": "as:sensitive",
"movedTo": {
"@id": "as:movedTo",
"@type": "@id"
},
"Hashtag": "as:Hashtag",
"ostatus": "http://ostatus.org#",
"atomUri": "ostatus:atomUri",
"inReplyToAtomUri": "ostatus:inReplyToAtomUri",
"conversation": "ostatus:conversation",
"toot": "http://joinmastodon.org/ns#",
"Emoji": "toot:Emoji",
"focalPoint": {
"@container": "@list",
"@id": "toot:focalPoint"
},
"featured": {
"@id": "toot:featured",
"@type": "@id"
},
"schema": "http://schema.org#",
"PropertyValue": "schema:PropertyValue",
"value": "schema:value"
}
],
"id": "https://mastodon.social/users/Gargron/statuses/100470639549326850/activity",
"type": "Announce",
"actor": "http://activitystreams.example/Gargron",
"published": "2018-07-31T18:04:55Z",
"to": [
"https://www.w3.org/ns/activitystreams#Public"
],
"cc": [
"https://mastodon.social/users/tobypinder",
"https://mastodon.social/users/Gargron/followers"
],
"object": "http://activitystreams.example/note.json",
"atomUri": "https://mastodon.social/users/Gargron/statuses/100470639549326850/activity"
}

Loading…
Cancel
Save