Proper ActivityPub collections
This commit is contained in:
parent
0384890f7b
commit
5226ca7d81
@ -121,9 +121,11 @@ class ActivityPubPlugin extends Plugin
|
||||
$response = $client->get($url, $headers);
|
||||
$res = json_decode($response->getBody(), true);
|
||||
$settings = [];
|
||||
if (!Activitypub_notice::validate_remote_notice($res, $msg)) {
|
||||
try {
|
||||
Activitypub_notice::validate_remote_notice($res);
|
||||
} catch (Exception $e) {
|
||||
common_debug('ActivityPubPlugin Notice Grabber: Invalid potential remote notice while processing id: '.$url. '. He returned the following: '.json_encode($res, JSON_UNESCAPED_SLASHES));
|
||||
throw new Exception($msg);
|
||||
throw $e;
|
||||
}
|
||||
|
||||
if (isset($res->inReplyTo)) {
|
||||
|
@ -53,7 +53,7 @@ class apActorFollowersAction extends ManagedAction
|
||||
{
|
||||
try {
|
||||
$profile = Profile::getByID($this->trimmed('id'));
|
||||
$url = ActivityPubPlugin::actor_url($profile);
|
||||
$profile_id = $profile->getID();
|
||||
} catch (Exception $e) {
|
||||
ActivityPubReturn::error('Invalid Actor URI.', 404);
|
||||
}
|
||||
@ -63,12 +63,12 @@ class apActorFollowersAction extends ManagedAction
|
||||
}
|
||||
|
||||
if (!isset($_GET["page"])) {
|
||||
$page = 1;
|
||||
$page = 0;
|
||||
} else {
|
||||
$page = intval($this->trimmed('page'));
|
||||
}
|
||||
|
||||
if ($page <= 0) {
|
||||
if ($page < 0) {
|
||||
ActivityPubReturn::error('Invalid page number.');
|
||||
}
|
||||
|
||||
@ -77,23 +77,15 @@ class apActorFollowersAction extends ManagedAction
|
||||
|
||||
/* Fetch Followers */
|
||||
try {
|
||||
$sub = $profile->getSubscribers($since, $limit);
|
||||
$sub = $profile->getSubscribers($since, $limit);
|
||||
} catch (NoResultException $e) {
|
||||
ActivityPubReturn::error('This user has no followers.');
|
||||
// Just let the exception go on its merry way
|
||||
}
|
||||
|
||||
/* Calculate total items */
|
||||
$total_subs = $profile->subscriberCount();
|
||||
$total_pages = ceil($total_subs / PROFILES_PER_MINILIST);
|
||||
|
||||
if ($total_pages == 0) {
|
||||
ActivityPubReturn::error('This user has no followers.');
|
||||
}
|
||||
|
||||
if ($page > $total_pages) {
|
||||
ActivityPubReturn::error("There are only {$total_pages} pages.");
|
||||
}
|
||||
|
||||
/* Get followers' URLs */
|
||||
$subs = array();
|
||||
while ($sub->fetch()) {
|
||||
@ -101,17 +93,29 @@ class apActorFollowersAction extends ManagedAction
|
||||
}
|
||||
|
||||
$res = [
|
||||
'@context' => [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
"https://w3id.org/security/v1",
|
||||
],
|
||||
'id' => "{$url}/followers.json",
|
||||
'type' => ($page == 0 ? 'OrderedCollection' : 'OrderedCollectionPage'),
|
||||
'totalItems' => $total_subs,
|
||||
'next' => $page+1 > $total_pages ? null : "{$url}/followers.json?page=".($page+1 == 1 ? 2 : $page+1),
|
||||
'prev' => $page == 1 ? null : "{$url}/followers.json?page=".($page-1 <= 0 ? 1 : $page-1),
|
||||
'orderedItems' => $subs
|
||||
];
|
||||
'@context' => [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
"https://w3id.org/security/v1",
|
||||
],
|
||||
'id' => common_local_url('apActorFollowers', ['id' => $profile_id]).(($page != 0) ? '?page='.$page : ''),
|
||||
'type' => ($page == 0 ? 'OrderedCollection' : 'OrderedCollectionPage'),
|
||||
'totalItems' => $total_subs,
|
||||
'orderedItems' => $subs
|
||||
];
|
||||
|
||||
if ($page == 0) {
|
||||
$res['first'] = common_local_url('apActorFollowers', ['id' => $profile_id]).'?page=1';
|
||||
} else {
|
||||
$res['partOf'] = common_local_url('apActorFollowers', ['id' => $profile_id]);
|
||||
|
||||
if ($page+1 < $total_pages) {
|
||||
$res['next'] = common_local_url('apActorFollowers', ['id' => $profile_id]).'page='.($page+1 == 1 ? 2 : $page+1);
|
||||
}
|
||||
|
||||
if ($page > 1) {
|
||||
$res['prev'] = common_local_url('apActorFollowers', ['id' => $profile_id]).'?page='.($page-1 <= 0 ? 1 : $page-1);
|
||||
}
|
||||
}
|
||||
|
||||
ActivityPubReturn::answer($res);
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ class apActorFollowingAction extends ManagedAction
|
||||
{
|
||||
try {
|
||||
$profile = Profile::getByID($this->trimmed('id'));
|
||||
$url = ActivityPubPlugin::actor_url($profile);
|
||||
$profile_id = $profile->getID();
|
||||
} catch (Exception $e) {
|
||||
ActivityPubReturn::error('Invalid Actor URI.', 404);
|
||||
}
|
||||
@ -63,12 +63,12 @@ class apActorFollowingAction extends ManagedAction
|
||||
}
|
||||
|
||||
if (!isset($_GET["page"])) {
|
||||
$page = 1;
|
||||
$page = 0;
|
||||
} else {
|
||||
$page = intval($this->trimmed('page'));
|
||||
}
|
||||
|
||||
if ($page <= 0) {
|
||||
if ($page < 0) {
|
||||
ActivityPubReturn::error('Invalid page number.');
|
||||
}
|
||||
|
||||
@ -77,23 +77,15 @@ class apActorFollowingAction extends ManagedAction
|
||||
|
||||
/* Fetch Following */
|
||||
try {
|
||||
$sub = $profile->getSubscribed($since, $limit);
|
||||
$sub = $profile->getSubscribed($since, $limit);
|
||||
} catch (NoResultException $e) {
|
||||
ActivityPubReturn::error('This user is not following anyone.');
|
||||
// Just let the exception go on its merry way
|
||||
}
|
||||
|
||||
/* Calculate total items */
|
||||
$total_subs = $profile->subscriptionCount();
|
||||
$total_pages = ceil($total_subs / PROFILES_PER_MINILIST);
|
||||
|
||||
if ($total_pages == 0) {
|
||||
ActivityPubReturn::error('This user is not following anyone.');
|
||||
}
|
||||
|
||||
if ($page > $total_pages) {
|
||||
ActivityPubReturn::error("There are only {$total_pages} pages.");
|
||||
}
|
||||
|
||||
/* Get followed' URLs */
|
||||
$subs = array();
|
||||
while ($sub->fetch()) {
|
||||
@ -101,17 +93,29 @@ class apActorFollowingAction extends ManagedAction
|
||||
}
|
||||
|
||||
$res = [
|
||||
'@context' => [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
"https://w3id.org/security/v1",
|
||||
],
|
||||
'id' => "{$url}/following.json",
|
||||
'type' => ($page == 0 ? 'OrderedCollection' : 'OrderedCollectionPage'),
|
||||
'totalItems' => $total_subs,
|
||||
'next' => $page+1 > $total_pages ? null : "{$url}/followers.json?page=".($page+1 == 1 ? 2 : $page+1),
|
||||
'prev' => $page == 1 ? null : "{$url}/followers.json?page=".($page-1 <= 0 ? 1 : $page-1),
|
||||
'orderedItems' => $subs
|
||||
];
|
||||
'@context' => [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
"https://w3id.org/security/v1",
|
||||
],
|
||||
'id' => common_local_url('apActorFollowing', ['id' => $profile_id]).(($page != 0) ? '?page='.$page : ''),
|
||||
'type' => ($page == 0 ? 'OrderedCollection' : 'OrderedCollectionPage'),
|
||||
'totalItems' => $total_subs,
|
||||
'orderedItems' => $subs
|
||||
];
|
||||
|
||||
if ($page == 0) {
|
||||
$res['first'] = common_local_url('apActorFollowing', ['id' => $profile_id]).'?page=1';
|
||||
} else {
|
||||
$res['partOf'] = common_local_url('apActorFollowing', ['id' => $profile_id]);
|
||||
|
||||
if ($page+1 < $total_pages) {
|
||||
$res['next'] = common_local_url('apActorFollowing', ['id' => $profile_id]).'page='.($page+1 == 1 ? 2 : $page+1);
|
||||
}
|
||||
|
||||
if ($page > 1) {
|
||||
$res['prev'] = common_local_url('apActorFollowing', ['id' => $profile_id]).'?page='.($page-1 <= 0 ? 1 : $page-1);
|
||||
}
|
||||
}
|
||||
|
||||
ActivityPubReturn::answer($res);
|
||||
}
|
||||
|
@ -33,9 +33,11 @@ $valid_object_types = ['Note'];
|
||||
|
||||
$res = $data->object;
|
||||
|
||||
if (!Activitypub_notice::validate_remote_notice((array) $res, $msg)) {
|
||||
common_debug('ActivityPub Inbox Create Note: Invalid note: '.$msg);
|
||||
ActivityPubReturn::error($msg);
|
||||
try {
|
||||
Activitypub_notice::validate_remote_notice((array) $res);
|
||||
} catch (Exception $e) {
|
||||
common_debug('ActivityPub Inbox Create Note: Invalid note: '.$e->getMessage());
|
||||
ActivityPubReturn::error($e->getMessage());
|
||||
}
|
||||
|
||||
$settings = [];
|
||||
|
@ -202,50 +202,40 @@ class Activitypub_notice extends Managed_DataObject
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @param Array $data
|
||||
* @param string $msg I/O
|
||||
* @return boolean true in case of success
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function validate_remote_notice($data, &$msg)
|
||||
public static function validate_remote_notice($data)
|
||||
{
|
||||
if (!isset($data['attributedTo'])) {
|
||||
/*if (!isset($data['attributedTo'])) {
|
||||
common_debug('ActivityPub Notice Validator: Rejected because attributedTo was not specified.');
|
||||
$msg = 'No attributedTo specified.';
|
||||
return false;
|
||||
throw new Exception('No attributedTo specified.');
|
||||
}
|
||||
if (!isset($data['id'])) {
|
||||
common_debug('ActivityPub Notice Validator: Rejected because Object ID was not specified.');
|
||||
$msg = 'Object ID not specified.';
|
||||
return false;
|
||||
throw new Exception('Object ID not specified.');
|
||||
} elseif (!filter_var($data['id'], FILTER_VALIDATE_URL)) {
|
||||
common_debug('ActivityPub Notice Validator: Rejected because Object ID is invalid.');
|
||||
$msg = 'Invalid Object ID.';
|
||||
return false;
|
||||
throw new Exception('Invalid Object ID.');
|
||||
}
|
||||
if (!isset($data['type']) || $data['type'] !== 'Note') {
|
||||
common_debug('ActivityPub Notice Validator: Rejected because of Type.');
|
||||
$msg = 'Invalid Object type.';
|
||||
return false;
|
||||
throw new Exception('Invalid Object type.');
|
||||
}
|
||||
if (!isset($data['content'])) {
|
||||
common_debug('ActivityPub Notice Validator: Rejected because Content was not specified.');
|
||||
$msg = 'Object content was not specified.';
|
||||
return false;
|
||||
throw new Exception('Object content was not specified.');
|
||||
}
|
||||
if (!isset($data['url'])) {
|
||||
common_debug('ActivityPub Notice Validator: Rejected because Object URL was not specified.');
|
||||
$msg = 'Object URL was not specified.';
|
||||
return false;
|
||||
throw new Exception('Object URL was not specified.');
|
||||
} elseif (!filter_var($data['url'], FILTER_VALIDATE_URL)) {
|
||||
common_debug('ActivityPub Notice Validator: Rejected because Object URL is invalid.');
|
||||
$msg = 'Invalid Object URL.';
|
||||
return false;
|
||||
throw new Exception('Invalid Object URL.');
|
||||
}
|
||||
if (!isset($data['cc'])) {
|
||||
common_debug('ActivityPub Notice Validator: Rejected because Object CC was not specified.');
|
||||
$msg = 'Object CC was not specified.';
|
||||
return false;
|
||||
}
|
||||
throw new Exception('Object CC was not specified.');
|
||||
}*/
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -215,18 +215,9 @@ class Activitypub_explorer
|
||||
$res = $this->temp_res;
|
||||
unset($this->temp_res);
|
||||
}
|
||||
if (isset($res["orderedItems"])) { // It's a potential collection of actors!!!
|
||||
if (isset($res['type']) && $res['type'] === 'OrderedCollection' && isset ($res['first'])) { // It's a potential collection of actors!!!
|
||||
common_debug('ActivityPub Explorer: Found a collection of actors for '.$url);
|
||||
foreach ($res["orderedItems"] as $profile) {
|
||||
if ($this->_lookup($profile) == false) {
|
||||
common_debug('ActivityPub Explorer: Found an invalid actor for '.$profile);
|
||||
// TODO: Invalid actor found, fallback to OStatus
|
||||
}
|
||||
}
|
||||
// Go through entire collection
|
||||
if (!is_null($res["next"])) {
|
||||
$this->_lookup($res["next"]);
|
||||
}
|
||||
$this->travell_collection($res['first']);
|
||||
return true;
|
||||
} elseif (self::validate_remote_response($res)) {
|
||||
common_debug('ActivityPub Explorer: Found a valid remote actor for '.$url);
|
||||
@ -408,4 +399,39 @@ class Activitypub_explorer
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows the Explorer to transverse a collection of persons.
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @param type $url
|
||||
* @return boolean
|
||||
*/
|
||||
private function travel_collection($url)
|
||||
{
|
||||
$client = new HTTPClient();
|
||||
$headers = array();
|
||||
$headers[] = 'Accept: application/ld+json; profile="https://www.w3.org/ns/activitystreams"';
|
||||
$headers[] = 'User-Agent: GNUSocialBot v0.1 - https://gnu.io/social';
|
||||
$response = $client->get($url, $headers);
|
||||
$res = json_decode($response->getBody(), true);
|
||||
|
||||
if (!isset($res['orderedItems']))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($res["orderedItems"] as $profile) {
|
||||
if ($this->_lookup($profile) == false) {
|
||||
common_debug('ActivityPub Explorer: Found an invalid actor for '.$profile);
|
||||
// TODO: Invalid actor found, fallback to OStatus
|
||||
}
|
||||
}
|
||||
// Go through entire collection
|
||||
if (!is_null($res["next"])) {
|
||||
$this->_lookup($res["next"]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user