Proper AP Notices (fixed #46)
Explorer now works both for local and remote URIs Fixed various serious errors (most of them in Explorer and some in AP Profiles)
This commit is contained in:
@@ -34,6 +34,9 @@ require_once __DIR__ . DIRECTORY_SEPARATOR . "utils" . DIRECTORY_SEPARATOR . "di
|
|||||||
require_once __DIR__ . DIRECTORY_SEPARATOR . "utils" . DIRECTORY_SEPARATOR . "explorer.php";
|
require_once __DIR__ . DIRECTORY_SEPARATOR . "utils" . DIRECTORY_SEPARATOR . "explorer.php";
|
||||||
require_once __DIR__ . DIRECTORY_SEPARATOR . "utils" . DIRECTORY_SEPARATOR . "postman.php";
|
require_once __DIR__ . DIRECTORY_SEPARATOR . "utils" . DIRECTORY_SEPARATOR . "postman.php";
|
||||||
|
|
||||||
|
// So that this isn't hardcoded everywhere
|
||||||
|
define('ACTIVITYPUB_BASE_INSTANCE_URI', common_root_url()."index.php/user/");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @category Plugin
|
* @category Plugin
|
||||||
* @package GNUsocial
|
* @package GNUsocial
|
||||||
@@ -54,7 +57,7 @@ class ActivityPubPlugin extends Plugin
|
|||||||
public static function actor_uri($profile)
|
public static function actor_uri($profile)
|
||||||
{
|
{
|
||||||
if ($profile->isLocal()) {
|
if ($profile->isLocal()) {
|
||||||
return common_root_url()."index.php/user/".$profile->getID();
|
return ACTIVITYPUB_BASE_INSTANCE_URI.$profile->getID();
|
||||||
} else {
|
} else {
|
||||||
return $profile->getUri();
|
return $profile->getUri();
|
||||||
}
|
}
|
||||||
@@ -74,46 +77,30 @@ class ActivityPubPlugin extends Plugin
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get remote user's ActivityPub_profile via a identifier
|
* Returns a notice from its URL since GNU Social doesn't provide
|
||||||
|
* this functionality
|
||||||
*
|
*
|
||||||
* @author GNU Social
|
|
||||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @param string $arg A remote user identifier
|
* @param string $url Notice's URL
|
||||||
* @return Activitypub_profile|null Valid profile in success | null otherwise
|
* @return Notice The Notice object
|
||||||
|
* @throws Exception This function or provides a Notice or fails with exception
|
||||||
*/
|
*/
|
||||||
public static function pull_remote_profile($arg)
|
public static function get_local_notice_from_url($url)
|
||||||
{
|
{
|
||||||
if (preg_match('!^((?:\w+\.)*\w+@(?:\w+\.)*\w+(?:\w+\-\w+)*\.\w+)$!', $arg)) {
|
try {
|
||||||
// webfinger lookup
|
return Notice::getByUri($data->object->inReplyTo);
|
||||||
|
} catch (Exception $e) {
|
||||||
try {
|
try {
|
||||||
return Activitypub_profile::ensure_web_finger($arg);
|
$candidate = Notice::getByID(intval(substr($url, strlen(common_local_url('shownotice', ['notice' => ''])))));
|
||||||
|
if ($candidate->getUrl() == $url) {
|
||||||
|
return $candidate;
|
||||||
|
} else {
|
||||||
|
throw new Exception("Notice not found.");
|
||||||
|
}
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
common_log(LOG_ERR, 'Webfinger lookup failed for ' .
|
throw new Exception("Notice not found.");
|
||||||
$arg . ': ' . $e->getMessage());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Look for profile URLs, with or without scheme:
|
|
||||||
$urls = array();
|
|
||||||
if (preg_match('!^https?://((?:\w+\.)*\w+(?:\w+\-\w+)*\.\w+(?:/\w+)+)$!', $arg)) {
|
|
||||||
$urls[] = $arg;
|
|
||||||
}
|
|
||||||
if (preg_match('!^((?:\w+\.)*\w+(?:\w+\-\w+)*\.\w+(?:/\w+)+)$!', $arg)) {
|
|
||||||
$schemes = array('http', 'https');
|
|
||||||
foreach ($schemes as $scheme) {
|
|
||||||
$urls[] = "$scheme://$arg";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($urls as $url) {
|
|
||||||
try {
|
|
||||||
return Activitypub_profile::get_from_uri($url);
|
|
||||||
} catch (Exception $e) {
|
|
||||||
common_log(LOG_ERR, 'Profile lookup failed for ' .
|
|
||||||
$arg . ': ' . $e->getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -127,18 +114,18 @@ class ActivityPubPlugin extends Plugin
|
|||||||
ActivityPubURLMapperOverwrite::overwrite_variable(
|
ActivityPubURLMapperOverwrite::overwrite_variable(
|
||||||
$m,
|
$m,
|
||||||
'user/:id',
|
'user/:id',
|
||||||
['action' => 'showstream'],
|
['action' => 'showstream'],
|
||||||
['id' => '[0-9]+'],
|
['id' => '[0-9]+'],
|
||||||
'apActorProfile'
|
'apActorProfile'
|
||||||
);
|
);
|
||||||
|
|
||||||
// Special route for webfinger purposes
|
// Special route for webfinger purposes
|
||||||
ActivityPubURLMapperOverwrite::overwrite_variable(
|
ActivityPubURLMapperOverwrite::overwrite_variable(
|
||||||
$m,
|
$m,
|
||||||
':nickname',
|
':nickname',
|
||||||
['action' => 'showstream'],
|
['action' => 'showstream'],
|
||||||
['nickname' => Nickname::DISPLAY_FMT],
|
['nickname' => Nickname::DISPLAY_FMT],
|
||||||
'apActorProfile'
|
'apActorProfile'
|
||||||
);
|
);
|
||||||
|
|
||||||
$m->connect(
|
$m->connect(
|
||||||
@@ -234,6 +221,49 @@ class ActivityPubPlugin extends Plugin
|
|||||||
* WebFinger Events *
|
* WebFinger Events *
|
||||||
********************************************************/
|
********************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get remote user's ActivityPub_profile via a identifier
|
||||||
|
*
|
||||||
|
* @author GNU Social
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
|
* @param string $arg A remote user identifier
|
||||||
|
* @return Activitypub_profile|null Valid profile in success | null otherwise
|
||||||
|
*/
|
||||||
|
public static function pull_remote_profile($arg)
|
||||||
|
{
|
||||||
|
if (preg_match('!^((?:\w+\.)*\w+@(?:\w+\.)*\w+(?:\w+\-\w+)*\.\w+)$!', $arg)) {
|
||||||
|
// webfinger lookup
|
||||||
|
try {
|
||||||
|
return Activitypub_profile::ensure_web_finger($arg);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
common_log(LOG_ERR, 'Webfinger lookup failed for ' .
|
||||||
|
$arg . ': ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look for profile URLs, with or without scheme:
|
||||||
|
$urls = array();
|
||||||
|
if (preg_match('!^https?://((?:\w+\.)*\w+(?:\w+\-\w+)*\.\w+(?:/\w+)+)$!', $arg)) {
|
||||||
|
$urls[] = $arg;
|
||||||
|
}
|
||||||
|
if (preg_match('!^((?:\w+\.)*\w+(?:\w+\-\w+)*\.\w+(?:/\w+)+)$!', $arg)) {
|
||||||
|
$schemes = array('http', 'https');
|
||||||
|
foreach ($schemes as $scheme) {
|
||||||
|
$urls[] = "$scheme://$arg";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($urls as $url) {
|
||||||
|
try {
|
||||||
|
return Activitypub_profile::fromUri($url);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
common_log(LOG_ERR, 'Profile lookup failed for ' .
|
||||||
|
$arg . ': ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Webfinger matches: @user@example.com or even @user--one.george_orwell@1984.biz
|
* Webfinger matches: @user@example.com or even @user--one.george_orwell@1984.biz
|
||||||
*
|
*
|
||||||
@@ -357,7 +387,7 @@ class ActivityPubPlugin extends Plugin
|
|||||||
$url = "$scheme://$target";
|
$url = "$scheme://$target";
|
||||||
$this->log(LOG_INFO, "Checking profile address '$url'");
|
$this->log(LOG_INFO, "Checking profile address '$url'");
|
||||||
try {
|
try {
|
||||||
$aprofile = Activitypub_profile::get_from_uri($url);
|
$aprofile = Activitypub_profile::fromUri($url);
|
||||||
$profile = $aprofile->local_profile();
|
$profile = $aprofile->local_profile();
|
||||||
$displayName = !empty($profile->nickname) && mb_strlen($profile->nickname) < mb_strlen($target) ?
|
$displayName = !empty($profile->nickname) && mb_strlen($profile->nickname) < mb_strlen($target) ?
|
||||||
$profile->nickname : $target;
|
$profile->nickname : $target;
|
||||||
@@ -432,7 +462,7 @@ class ActivityPubPlugin extends Plugin
|
|||||||
{
|
{
|
||||||
$aprofile = Activitypub_profile::getKV('profile_id', $profile->id);
|
$aprofile = Activitypub_profile::getKV('profile_id', $profile->id);
|
||||||
if ($aprofile instanceof Activitypub_profile) {
|
if ($aprofile instanceof Activitypub_profile) {
|
||||||
$uri = $aprofile->get_uri();
|
$uri = $aprofile->getUri();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -449,27 +479,9 @@ class ActivityPubPlugin extends Plugin
|
|||||||
*/
|
*/
|
||||||
public function onStartGetProfileFromURI($uri, &$profile)
|
public function onStartGetProfileFromURI($uri, &$profile)
|
||||||
{
|
{
|
||||||
// Don't want to do Web-based discovery on our own server,
|
|
||||||
// so we check locally first. This duplicates the functionality
|
|
||||||
// in the Profile class, since the plugin always runs before
|
|
||||||
// that local lookup, but since we return false it won't run double.
|
|
||||||
|
|
||||||
$user = User::getKV('uri', $uri);
|
|
||||||
if ($user instanceof User) {
|
|
||||||
$profile = $user->getProfile();
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
$group = User_group::getKV('uri', $uri);
|
|
||||||
if ($group instanceof User_group) {
|
|
||||||
$profile = $group->getProfile();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now, check remotely
|
|
||||||
try {
|
try {
|
||||||
$aprofile = Activitypub_profile::get_from_uri($uri);
|
$explorer = new Activitypub_explorer();
|
||||||
$profile = $aprofile->local_profile();
|
$profile = $explorer->lookup($uri)[0];
|
||||||
return false;
|
return false;
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
return true; // It's not an ActivityPub profile as far as we know, continue event handling
|
return true; // It's not an ActivityPub profile as far as we know, continue event handling
|
||||||
|
@@ -58,6 +58,10 @@ class apActorFollowersAction extends ManagedAction
|
|||||||
ActivityPubReturn::error('Invalid Actor URI.', 404);
|
ActivityPubReturn::error('Invalid Actor URI.', 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!$profile->isLocal()) {
|
||||||
|
ActivityPubReturn::error("This is not a local user.");
|
||||||
|
}
|
||||||
|
|
||||||
if (!isset($_GET["page"])) {
|
if (!isset($_GET["page"])) {
|
||||||
$page = 1;
|
$page = 1;
|
||||||
} else {
|
} else {
|
||||||
@@ -93,7 +97,7 @@ class apActorFollowersAction extends ManagedAction
|
|||||||
/* Get followers' URLs */
|
/* Get followers' URLs */
|
||||||
$subs = array();
|
$subs = array();
|
||||||
while ($sub->fetch()) {
|
while ($sub->fetch()) {
|
||||||
$subs[] = $sub->profileurl;
|
$subs[] = ActivityPubPlugin::actor_uri($sub);
|
||||||
}
|
}
|
||||||
|
|
||||||
$res = [
|
$res = [
|
||||||
|
@@ -58,6 +58,10 @@ class apActorFollowingAction extends ManagedAction
|
|||||||
ActivityPubReturn::error('Invalid Actor URI.', 404);
|
ActivityPubReturn::error('Invalid Actor URI.', 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!$profile->isLocal()) {
|
||||||
|
ActivityPubReturn::error("This is not a local user.");
|
||||||
|
}
|
||||||
|
|
||||||
if (!isset($_GET["page"])) {
|
if (!isset($_GET["page"])) {
|
||||||
$page = 1;
|
$page = 1;
|
||||||
} else {
|
} else {
|
||||||
@@ -93,7 +97,7 @@ class apActorFollowingAction extends ManagedAction
|
|||||||
/* Get followed' URLs */
|
/* Get followed' URLs */
|
||||||
$subs = array();
|
$subs = array();
|
||||||
while ($sub->fetch()) {
|
while ($sub->fetch()) {
|
||||||
$subs[] = $sub->profileurl;
|
$subs[] = ActivityPubPlugin::actor_uri($sub);
|
||||||
}
|
}
|
||||||
|
|
||||||
$res = [
|
$res = [
|
||||||
|
@@ -57,6 +57,10 @@ class apActorInboxAction extends ManagedAction
|
|||||||
ActivityPubReturn::error('Invalid Actor URI.', 404);
|
ActivityPubReturn::error('Invalid Actor URI.', 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!$profile->isLocal()) {
|
||||||
|
ActivityPubReturn::error("This is not a local user.");
|
||||||
|
}
|
||||||
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||||
ActivityPubReturn::error("C2S not implemented just yet.");
|
ActivityPubReturn::error("C2S not implemented just yet.");
|
||||||
}
|
}
|
||||||
|
@@ -58,6 +58,10 @@ class apActorLikedAction extends ManagedAction
|
|||||||
ActivityPubReturn::error('Invalid Actor URI.', 404);
|
ActivityPubReturn::error('Invalid Actor URI.', 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!$profile->isLocal()) {
|
||||||
|
ActivityPubReturn::error("This is not a local user.");
|
||||||
|
}
|
||||||
|
|
||||||
$limit = intval($this->trimmed('limit'));
|
$limit = intval($this->trimmed('limit'));
|
||||||
$since_id = intval($this->trimmed('since_id'));
|
$since_id = intval($this->trimmed('since_id'));
|
||||||
$max_id = intval($this->trimmed('max_id'));
|
$max_id = intval($this->trimmed('max_id'));
|
||||||
|
@@ -30,7 +30,7 @@ if (!defined('GNUSOCIAL')) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Notice::getByUri($data->object->id)->repeat($actor_profile, "ActivityPub");
|
ActivityPubPlugin::get_local_notice_from_url($data->object->id)->repeat($actor_profile, "ActivityPub");
|
||||||
ActivityPubReturn::answer("Notice repeated successfully.");
|
ActivityPubReturn::answer("Notice repeated successfully.");
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
ActivityPubReturn::error($e->getMessage(), 403);
|
ActivityPubReturn::error($e->getMessage(), 403);
|
||||||
|
@@ -32,8 +32,10 @@ if (!defined('GNUSOCIAL')) {
|
|||||||
$valid_object_types = array("Note");
|
$valid_object_types = array("Note");
|
||||||
|
|
||||||
// Validate data
|
// Validate data
|
||||||
if (!isset($data->id)) {
|
if (!isset($data->object->id)) {
|
||||||
ActivityPubReturn::error("Id not specified.");
|
ActivityPubReturn::error("Object ID not specified.");
|
||||||
|
} elseif (!filter_var($data->object->id, FILTER_VALIDATE_URL)) {
|
||||||
|
ActivityPubReturn::error("Invalid Object ID.");
|
||||||
}
|
}
|
||||||
if (!(isset($data->object->type) && in_array($data->object->type, $valid_object_types))) {
|
if (!(isset($data->object->type) && in_array($data->object->type, $valid_object_types))) {
|
||||||
ActivityPubReturn::error("Invalid Object type.");
|
ActivityPubReturn::error("Invalid Object type.");
|
||||||
@@ -60,19 +62,19 @@ $act->actor = $actor_profile->asActivityObject();
|
|||||||
$act->context = new ActivityContext();
|
$act->context = new ActivityContext();
|
||||||
|
|
||||||
// Is this a reply?
|
// Is this a reply?
|
||||||
if (isset($data->object->reply_to)) {
|
if (isset($data->object->inReplyTo)) {
|
||||||
try {
|
try {
|
||||||
$reply_to = Notice::getByUri($data->object->reply_to);
|
$inReplyTo = ActivityPubPlugin::get_local_notice_from_url($data->object->inReplyTo);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
ActivityPubReturn::error("Invalid Object reply_to value.");
|
ActivityPubReturn::error("Invalid Object inReplyTo value.");
|
||||||
}
|
}
|
||||||
$act->context->replyToID = $reply_to->getUri();
|
$act->context->replyToID = $inReplyTo->getUri();
|
||||||
$act->context->replyToUrl = $reply_to->getUrl();
|
$act->context->replyToUrl = $inReplyTo->getUrl();
|
||||||
} else {
|
} else {
|
||||||
$reply_to = null;
|
$inReplyTo = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$act->context->attention = common_get_attentions($content, $actor_profile, $reply_to);
|
$act->context->attention = common_get_attentions($content, $actor_profile, $inReplyTo);
|
||||||
|
|
||||||
$discovery = new Activitypub_explorer;
|
$discovery = new Activitypub_explorer;
|
||||||
if ($to_profiles == "https://www.w3.org/ns/activitystreams#Public") {
|
if ($to_profiles == "https://www.w3.org/ns/activitystreams#Public") {
|
||||||
@@ -86,22 +88,43 @@ if (is_array($data->object->to)) {
|
|||||||
try {
|
try {
|
||||||
$to_profiles = array_merge($to_profiles, $discovery->lookup($to_url));
|
$to_profiles = array_merge($to_profiles, $discovery->lookup($to_url));
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
// XXX: Invalid actor found, not sure how we handle those
|
// Invalid actor found, just let it go.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} elseif (empty($data->object->to) || in_array($data->object->to, $public_to)) {
|
} elseif (empty($data->object->to) || in_array($data->object->to, $public_to)) {
|
||||||
// No need to do anything else at this point, let's just break out the if
|
// No need to do anything else at this point, let's just break out the if
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
$to_profiles[]= $discovery->lookup($data->object->to);
|
$to_profiles = array_merge($to_profiles, $discovery->lookup($data->object->to));
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
ActivityPubReturn::error("Invalid Actor.", 404);
|
// Invalid actor found, just let it go.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Generate Cc objects
|
||||||
|
if (isset($data->object->cc) && is_array($data->object->cc)) {
|
||||||
|
// Remove duplicates from Cc actors set
|
||||||
|
array_unique($data->object->to);
|
||||||
|
foreach ($data->object->cc as $cc_url) {
|
||||||
|
try {
|
||||||
|
$to_profiles = array_merge($to_profiles, $discovery->lookup($cc_url));
|
||||||
|
} catch (Exception $e) {
|
||||||
|
// Invalid actor found, just let it go.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} elseif (empty($data->object->cc) || in_array($data->object->cc, $public_to)) {
|
||||||
|
// No need to do anything else at this point, let's just break out the if
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
$to_profiles = array_merge($to_profiles, $discovery->lookup($data->object->cc));
|
||||||
|
} catch (Exception $e) {
|
||||||
|
// Invalid actor found, just let it go.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unset($discovery);
|
unset($discovery);
|
||||||
|
|
||||||
foreach ($to_profiles as $to) {
|
foreach ($to_profiles as $tp) {
|
||||||
$act->context->attention[ActivityPubPlugin::actor_uri($to)] = "http://activitystrea.ms/schema/1.0/person";
|
$act->context->attention[ActivityPubPlugin::actor_uri($tp)] = "http://activitystrea.ms/schema/1.0/person";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reject notice if it is too long (without the HTML)
|
// Reject notice if it is too long (without the HTML)
|
||||||
@@ -116,7 +139,7 @@ ToSelector::fillActivity($this, $act, $options);
|
|||||||
|
|
||||||
$actobj = new ActivityObject();
|
$actobj = new ActivityObject();
|
||||||
$actobj->type = ActivityObject::NOTE;
|
$actobj->type = ActivityObject::NOTE;
|
||||||
$actobj->content = common_render_content($content, $actor_profile, $reply_to);
|
$actobj->content = common_render_content($content, $actor_profile, $inReplyTo);
|
||||||
|
|
||||||
// Finally add the activity object to our activity
|
// Finally add the activity object to our activity
|
||||||
$act->objects[] = $actobj;
|
$act->objects[] = $actobj;
|
||||||
|
@@ -30,7 +30,7 @@ if (!defined('GNUSOCIAL')) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$notice = Notice::getByUri($data->object->id);
|
$notice = ActivityPubPlugin::get_local_notice_from_url($data->object->id);
|
||||||
$notice_to_array = Activitypub_notice::notice_to_array($notice);
|
$notice_to_array = Activitypub_notice::notice_to_array($notice);
|
||||||
$notice->deleteAs($actor_profile);
|
$notice->deleteAs($actor_profile);
|
||||||
ActivityPubReturn::answer(Activitypub_delete::delete_to_array($notice_to_array));
|
ActivityPubReturn::answer(Activitypub_delete::delete_to_array($notice_to_array));
|
||||||
|
@@ -34,8 +34,13 @@ if (!isset($data->object->id)) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Fave::addNew($actor_profile, Notice::getByUri($data->object->id));
|
try {
|
||||||
ActivityPubReturn::answer(Activitypub_like::like_to_array(Activitypub_notice::notice_to_array($data->actor, json_decode($data->object))));
|
$object_notice = ActivityPubPlugin::get_local_notice_from_url($data->object->id);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
ActivityPubReturn::error("Invalid Object ID value.");
|
||||||
|
}
|
||||||
|
Fave::addNew($actor_profile, $object_notice);
|
||||||
|
ActivityPubReturn::answer(Activitypub_like::like_to_array($data->actor, Activitypub_notice::notice_to_array($object_notice)));
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
ActivityPubReturn::error($e->getMessage(), 403);
|
ActivityPubReturn::error($e->getMessage(), 403);
|
||||||
}
|
}
|
||||||
|
@@ -41,14 +41,14 @@ case "Like":
|
|||||||
if (!isset($data->object->object->id)) {
|
if (!isset($data->object->object->id)) {
|
||||||
ActivityPubReturn::error("Notice ID was not specified.");
|
ActivityPubReturn::error("Notice ID was not specified.");
|
||||||
}
|
}
|
||||||
Fave::removeEntry($actor_profile, Notice::getByUri($data->object->object->id));
|
Fave::removeEntry($actor_profile, ActivityPubPlugin::get_local_notice_from_url($data->object->object->id));
|
||||||
// Notice disfavorited successfully.
|
// Notice disfavorited successfully.
|
||||||
ActivityPubReturn::answer(
|
ActivityPubReturn::answer(
|
||||||
Activitypub_undo::undo_to_array(
|
Activitypub_undo::undo_to_array(
|
||||||
Activitypub_like::like_to_array(
|
Activitypub_like::like_to_array(
|
||||||
Activitypub_notice::notice_to_array(
|
Activitypub_notice::notice_to_array(
|
||||||
$actor_profile->getUrl(),
|
$actor_profile->getUrl(),
|
||||||
$data->object->object
|
$data->object->object
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@@ -34,7 +34,6 @@ if (!defined('GNUSOCIAL')) {
|
|||||||
*
|
*
|
||||||
* @category Plugin
|
* @category Plugin
|
||||||
* @package GNUsocial
|
* @package GNUsocial
|
||||||
* @author Daniel Supernault <danielsupernault@gmail.com>
|
|
||||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||||
* @link http://www.gnu.org/software/social/
|
* @link http://www.gnu.org/software/social/
|
||||||
@@ -44,13 +43,13 @@ class Activitypub_notice extends Managed_DataObject
|
|||||||
/**
|
/**
|
||||||
* Generates a pretty notice from a Notice object
|
* Generates a pretty notice from a Notice object
|
||||||
*
|
*
|
||||||
* @author Daniel Supernault <danielsupernault@gmail.com>
|
|
||||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @param Notice $notice
|
* @param Notice $notice
|
||||||
* @return pretty array to be used in a response
|
* @return pretty array to be used in a response
|
||||||
*/
|
*/
|
||||||
public static function notice_to_array($notice)
|
public static function notice_to_array($notice)
|
||||||
{
|
{
|
||||||
|
$profile = $notice->getProfile();
|
||||||
$attachments = array();
|
$attachments = array();
|
||||||
foreach ($notice->attachments() as $attachment) {
|
foreach ($notice->attachments() as $attachment) {
|
||||||
$attachments[] = Activitypub_attachment::attachment_to_array($attachment);
|
$attachments[] = Activitypub_attachment::attachment_to_array($attachment);
|
||||||
@@ -63,7 +62,7 @@ class Activitypub_notice extends Managed_DataObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$to = array();
|
$to = [];
|
||||||
foreach ($notice->getAttentionProfiles() as $to_profile) {
|
foreach ($notice->getAttentionProfiles() as $to_profile) {
|
||||||
$to[] = $to_profile->getUri();
|
$to[] = $to_profile->getUri();
|
||||||
}
|
}
|
||||||
@@ -72,18 +71,20 @@ class Activitypub_notice extends Managed_DataObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
$item = [
|
$item = [
|
||||||
'id' => $notice->getUri(),
|
'id' => $notice->getUrl(),
|
||||||
'type' => 'Note',
|
'type' => 'Note',
|
||||||
'actor' => $notice->getProfile()->getUrl(),
|
'inReplyTo' => empty($notice->reply_to) ? null : Notice::getById($notice->reply_to)->getUrl(),
|
||||||
'published' => $notice->getCreated(),
|
'published' => $notice->getCreated(),
|
||||||
'to' => $to,
|
'url' => $notice->getUrl(),
|
||||||
'content' => $notice->getContent(),
|
'atributedTo' => ActivityPubPlugin::actor_uri($profile),
|
||||||
'url' => $notice->getUrl(),
|
'to' => $to,
|
||||||
'reply_to' => empty($notice->reply_to) ? null : Notice::getById($notice->reply_to)->getUri(),
|
'atomUri' => $notice->getUrl(),
|
||||||
'is_local' => $notice->isLocal(),
|
'inReplyToAtomUri' => empty($notice->reply_to) ? null : Notice::getById($notice->reply_to)->getUrl(),
|
||||||
'conversation' => $notice->getConversationUrl(),
|
'conversation' => $notice->getConversationUrl(),
|
||||||
'attachment' => $attachments,
|
'content' => $notice->getContent(),
|
||||||
'tag' => $tags
|
'is_local' => $notice->isLocal(),
|
||||||
|
'attachment' => $attachments,
|
||||||
|
'tag' => $tags
|
||||||
];
|
];
|
||||||
|
|
||||||
return $item;
|
return $item;
|
||||||
|
@@ -41,6 +41,18 @@ if (!defined('GNUSOCIAL')) {
|
|||||||
class Activitypub_profile extends Managed_DataObject
|
class Activitypub_profile extends Managed_DataObject
|
||||||
{
|
{
|
||||||
public $__table = 'Activitypub_profile';
|
public $__table = 'Activitypub_profile';
|
||||||
|
public $uri; // text() not_null
|
||||||
|
public $profile_id; // int(4) primary_key not_null
|
||||||
|
public $inboxuri; // text() not_null
|
||||||
|
public $sharedInboxuri; // text()
|
||||||
|
public $nickname; // varchar(64) multiple_key not_null
|
||||||
|
public $fullname; // text()
|
||||||
|
public $profileurl; // text()
|
||||||
|
public $homepage; // text()
|
||||||
|
public $bio; // text() multiple_key
|
||||||
|
public $location; // text()
|
||||||
|
public $created; // datetime() not_null
|
||||||
|
public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return table definition for Schema setup and DB_DataObject usage.
|
* Return table definition for Schema setup and DB_DataObject usage.
|
||||||
@@ -108,7 +120,7 @@ class Activitypub_profile extends Managed_DataObject
|
|||||||
'liked' => common_local_url("apActorLiked", array("id" => $id)),
|
'liked' => common_local_url("apActorLiked", array("id" => $id)),
|
||||||
'inbox' => common_local_url("apActorInbox", array("id" => $id)),
|
'inbox' => common_local_url("apActorInbox", array("id" => $id)),
|
||||||
'preferredUsername' => $profile->getNickname(),
|
'preferredUsername' => $profile->getNickname(),
|
||||||
'name' => $profile->getFullname(),
|
'name' => $profile->getBestName(),
|
||||||
'summary' => ($desc = $profile->getDescription()) == null ? "" : $desc,
|
'summary' => ($desc = $profile->getDescription()) == null ? "" : $desc,
|
||||||
'url' => $profile->getUrl(),
|
'url' => $profile->getUrl(),
|
||||||
'manuallyApprovesFollowers' => false,
|
'manuallyApprovesFollowers' => false,
|
||||||
@@ -280,11 +292,33 @@ class Activitypub_profile extends Managed_DataObject
|
|||||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
* @return string URI
|
* @return string URI
|
||||||
*/
|
*/
|
||||||
public function get_uri()
|
public function getUri()
|
||||||
{
|
{
|
||||||
return $this->uri;
|
return $this->uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter for url property
|
||||||
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
|
* @return string URL
|
||||||
|
*/
|
||||||
|
public function getUrl()
|
||||||
|
{
|
||||||
|
return $this->getUri();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter for id property
|
||||||
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
|
* @return int32
|
||||||
|
*/
|
||||||
|
public function getID()
|
||||||
|
{
|
||||||
|
return $this->profile_id;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensures a valid Activitypub_profile when provided with a valid URI.
|
* Ensures a valid Activitypub_profile when provided with a valid URI.
|
||||||
*
|
*
|
||||||
@@ -293,7 +327,7 @@ class Activitypub_profile extends Managed_DataObject
|
|||||||
* @return Activitypub_profile
|
* @return Activitypub_profile
|
||||||
* @throws Exception if it isn't possible to return an Activitypub_profile
|
* @throws Exception if it isn't possible to return an Activitypub_profile
|
||||||
*/
|
*/
|
||||||
public static function get_from_uri($url)
|
public static function fromUri($url)
|
||||||
{
|
{
|
||||||
$explorer = new Activitypub_explorer();
|
$explorer = new Activitypub_explorer();
|
||||||
$profiles_found = $explorer->lookup($url);
|
$profiles_found = $explorer->lookup($url);
|
||||||
@@ -331,7 +365,7 @@ class Activitypub_profile extends Managed_DataObject
|
|||||||
throw new Exception(_m('Not a valid webfinger address (via cache).'));
|
throw new Exception(_m('Not a valid webfinger address (via cache).'));
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return self::get_from_uri($uri);
|
return self::fromUri($uri);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
common_log(LOG_ERR, sprintf(__METHOD__ . ': Webfinger address cache inconsistent with database, did not find Activitypub_profile uri==%s', $uri));
|
common_log(LOG_ERR, sprintf(__METHOD__ . ': Webfinger address cache inconsistent with database, did not find Activitypub_profile uri==%s', $uri));
|
||||||
self::cacheSet(sprintf('activitypub_profile:webfinger:%s', $addr), false);
|
self::cacheSet(sprintf('activitypub_profile:webfinger:%s', $addr), false);
|
||||||
@@ -372,8 +406,8 @@ class Activitypub_profile extends Managed_DataObject
|
|||||||
$profileUrl = $hints['profileurl'];
|
$profileUrl = $hints['profileurl'];
|
||||||
try {
|
try {
|
||||||
common_log(LOG_INFO, "Discovery on acct:$addr with profile URL $profileUrl");
|
common_log(LOG_INFO, "Discovery on acct:$addr with profile URL $profileUrl");
|
||||||
$aprofile = self::get_from_uri($hints['profileurl']);
|
$aprofile = self::fromUri($hints['profileurl']);
|
||||||
self::cacheSet(sprintf('activitypub_profile:webfinger:%s', $addr), $aprofile->get_uri());
|
self::cacheSet(sprintf('activitypub_profile:webfinger:%s', $addr), $aprofile->getUri());
|
||||||
return $aprofile;
|
return $aprofile;
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
common_log(LOG_WARNING, "Failed creating profile from profile URL '$profileUrl': " . $e->getMessage());
|
common_log(LOG_WARNING, "Failed creating profile from profile URL '$profileUrl': " . $e->getMessage());
|
||||||
|
@@ -49,11 +49,17 @@ class ProfileObjectTest extends TestCase
|
|||||||
/* Test get_inbox() */
|
/* Test get_inbox() */
|
||||||
$this->assertTrue($aprofile->sharedInboxuri == $aprofile->get_inbox());
|
$this->assertTrue($aprofile->sharedInboxuri == $aprofile->get_inbox());
|
||||||
|
|
||||||
/* Test get_uri() */
|
/* Test getUri() */
|
||||||
$this->assertTrue($aprofile->uri == $aprofile->get_uri());
|
$this->assertTrue($aprofile->uri == $aprofile->getUri());
|
||||||
|
|
||||||
/* Test get_from_uri() */
|
/* Test getUrl() */
|
||||||
$this->assertTrue($this->compare_aprofiles($aprofile, \Activitypub_profile::get_from_uri($aprofile->uri)));
|
$this->assertTrue($profile->getUrl() == $aprofile->getUrl());
|
||||||
|
|
||||||
|
/* Test getID() */
|
||||||
|
$this->assertTrue($profile->getID() == $aprofile->getID());
|
||||||
|
|
||||||
|
/* Test fromUri() */
|
||||||
|
$this->assertTrue($this->compare_aprofiles($aprofile, \Activitypub_profile::fromUri($aprofile->uri)));
|
||||||
|
|
||||||
/* Remove Remote User Test 1 */
|
/* Remove Remote User Test 1 */
|
||||||
$old_id = $profile->getID();
|
$old_id = $profile->getID();
|
||||||
@@ -124,20 +130,28 @@ class ProfileObjectTest extends TestCase
|
|||||||
|
|
||||||
private function compare_aprofiles(\Activitypub_profile $a, \Activitypub_profile $b)
|
private function compare_aprofiles(\Activitypub_profile $a, \Activitypub_profile $b)
|
||||||
{
|
{
|
||||||
if (($av = $a->get_uri()) != ($bv = $b->get_uri())) {
|
if (($av = $a->getUri()) != ($bv = $b->getUri())) {
|
||||||
throw new Exception('Compare AProfiles 1 Fail: $a: '.$av.' is different from $b: '.$bv);
|
throw new Exception('Compare AProfiles 1 Fail: $a: '.$av.' is different from $b: '.$bv);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (($av = $a->profile_id) != ($bv = $b->profile_id)) {
|
if (($av = $a->getUrl()) != ($bv = $b->getUrl())) {
|
||||||
throw new Exception('Compare AProfiles 2 Fail: $a: '.$av.' is different from $b: '.$bv);
|
throw new Exception('Compare AProfiles 2 Fail: $a: '.$av.' is different from $b: '.$bv);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (($av = $a->inboxuri) != ($bv = $b->inboxuri)) {
|
if (($av = $a->getID()) != ($bv = $b->getID())) {
|
||||||
throw new Exception('Compare AProfiles 3 Fail: $a: '.$av.' is different from $b: '.$bv);
|
throw new Exception('Compare AProfiles 3 Fail: $a: '.$av.' is different from $b: '.$bv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (($av = $a->profile_id) != ($bv = $b->profile_id)) {
|
||||||
|
throw new Exception('Compare AProfiles 4 Fail: $a: '.$av.' is different from $b: '.$bv);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($av = $a->inboxuri) != ($bv = $b->inboxuri)) {
|
||||||
|
throw new Exception('Compare AProfiles 5 Fail: $a: '.$av.' is different from $b: '.$bv);
|
||||||
|
}
|
||||||
|
|
||||||
if (($av = $a->sharedInboxuri) != ($bv = $b->sharedInboxuri)) {
|
if (($av = $a->sharedInboxuri) != ($bv = $b->sharedInboxuri)) {
|
||||||
throw new Exception('Compare AProfiles 1 Fail: $a: '.$av.' is different from $b: '.$bv);
|
throw new Exception('Compare AProfiles 6 Fail: $a: '.$av.' is different from $b: '.$bv);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@@ -16,8 +16,8 @@ use HttpSignatures\GuzzleHttpSignatures;
|
|||||||
class HTTPSignatureTest extends TestCase
|
class HTTPSignatureTest extends TestCase
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var Context
|
* @var Context
|
||||||
*/
|
*/
|
||||||
private $context;
|
private $context;
|
||||||
/**
|
/**
|
||||||
* @var Client
|
* @var Client
|
||||||
|
@@ -32,7 +32,7 @@ if (!defined('GNUSOCIAL')) {
|
|||||||
/**
|
/**
|
||||||
* ActivityPub's own Explorer
|
* ActivityPub's own Explorer
|
||||||
*
|
*
|
||||||
* Allows to discovery new (or the same) ActivityPub profiles
|
* Allows to discovery new (or the same) Profiles (both local or remote)
|
||||||
*
|
*
|
||||||
* @category Plugin
|
* @category Plugin
|
||||||
* @package GNUsocial
|
* @package GNUsocial
|
||||||
@@ -55,6 +55,7 @@ class Activitypub_explorer
|
|||||||
*/
|
*/
|
||||||
public function lookup($url)
|
public function lookup($url)
|
||||||
{
|
{
|
||||||
|
common_debug("Explorer started now looking for ".$url);
|
||||||
$this->discovered_actor_profiles = array();
|
$this->discovered_actor_profiles = array();
|
||||||
|
|
||||||
return $this->_lookup($url);
|
return $this->_lookup($url);
|
||||||
@@ -95,9 +96,6 @@ class Activitypub_explorer
|
|||||||
$headers[] = 'Accept: application/ld+json; profile="https://www.w3.org/ns/activitystreams"';
|
$headers[] = 'Accept: application/ld+json; profile="https://www.w3.org/ns/activitystreams"';
|
||||||
$headers[] = 'User-Agent: GNUSocialBot v0.1 - https://gnu.io/social';
|
$headers[] = 'User-Agent: GNUSocialBot v0.1 - https://gnu.io/social';
|
||||||
$response = $client->get($url, $headers);
|
$response = $client->get($url, $headers);
|
||||||
if (!$response->isOk()) {
|
|
||||||
throw new Exception("Invalid Actor URL.");
|
|
||||||
}
|
|
||||||
$res = json_decode($response->getBody(), JSON_UNESCAPED_SLASHES);
|
$res = json_decode($response->getBody(), JSON_UNESCAPED_SLASHES);
|
||||||
if (self::validate_remote_response($res)) {
|
if (self::validate_remote_response($res)) {
|
||||||
$this->temp_res = $res;
|
$this->temp_res = $res;
|
||||||
@@ -108,7 +106,7 @@ class Activitypub_explorer
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a local user profiles from its URL and joins it on
|
* Get a local user profile from its URL and joins it on
|
||||||
* $this->discovered_actor_profiles
|
* $this->discovered_actor_profiles
|
||||||
*
|
*
|
||||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
@@ -117,6 +115,11 @@ class Activitypub_explorer
|
|||||||
*/
|
*/
|
||||||
private function grab_local_user($uri, $online = false)
|
private function grab_local_user($uri, $online = false)
|
||||||
{
|
{
|
||||||
|
if ($online) {
|
||||||
|
common_debug("Explorer is searching locally for ".$uri. " online.");
|
||||||
|
} else {
|
||||||
|
common_debug("Explorer is searching locally for ".$uri. " offline.");
|
||||||
|
}
|
||||||
// Ensure proper remote URI
|
// Ensure proper remote URI
|
||||||
// If an exception occurs here it's better to just leave everything
|
// If an exception occurs here it's better to just leave everything
|
||||||
// break than to continue processing
|
// break than to continue processing
|
||||||
@@ -126,14 +129,31 @@ class Activitypub_explorer
|
|||||||
|
|
||||||
// Try standard ActivityPub route
|
// Try standard ActivityPub route
|
||||||
// Is this a known filthy little mudblood?
|
// Is this a known filthy little mudblood?
|
||||||
$aprofile = Activitypub_profile::getKV("uri", $uri);
|
$aprofile = self::get_aprofile_by_url($uri);
|
||||||
if ($aprofile instanceof Activitypub_profile) {
|
if ($aprofile instanceof Activitypub_profile) {
|
||||||
$profile = $aprofile->local_profile();
|
$profile = $aprofile->local_profile();
|
||||||
|
common_debug("Explorer found a local Aprofile for ".$uri);
|
||||||
// We found something!
|
// We found something!
|
||||||
$this->discovered_actor_profiles[]= $profile;
|
$this->discovered_actor_profiles[]= $profile;
|
||||||
unset($this->temp_res); // IMPORTANT to avoid _dangerous_ noise in the Explorer system
|
unset($this->temp_res); // IMPORTANT to avoid _dangerous_ noise in the Explorer system
|
||||||
return true;
|
return true;
|
||||||
|
} else {
|
||||||
|
common_debug("Explorer didn't find a local Aprofile for ".$uri);
|
||||||
|
// Well, maybe it is a pure blood?
|
||||||
|
// Iff, we are in the same instance:
|
||||||
|
$ACTIVITYPUB_BASE_INSTANCE_URI_length = strlen(ACTIVITYPUB_BASE_INSTANCE_URI);
|
||||||
|
if (substr($uri, 0, $ACTIVITYPUB_BASE_INSTANCE_URI_length) == ACTIVITYPUB_BASE_INSTANCE_URI) {
|
||||||
|
try {
|
||||||
|
$profile = Profile::getByID(intval(substr($uri, $ACTIVITYPUB_BASE_INSTANCE_URI_length)));
|
||||||
|
|
||||||
|
// We found something!
|
||||||
|
$this->discovered_actor_profiles[]= $profile;
|
||||||
|
unset($this->temp_res); // IMPORTANT to avoid _dangerous_ noise in the Explorer system
|
||||||
|
return true;
|
||||||
|
} catch (Exception $e) {
|
||||||
|
// Let the exception go on its merry way.
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If offline grabbing failed, attempt again with online resources
|
// If offline grabbing failed, attempt again with online resources
|
||||||
@@ -154,15 +174,13 @@ class Activitypub_explorer
|
|||||||
*/
|
*/
|
||||||
private function grab_remote_user($url)
|
private function grab_remote_user($url)
|
||||||
{
|
{
|
||||||
|
common_debug("Explorer is grabbing a remote profile for ".$url);
|
||||||
if (!isset($this->temp_res)) {
|
if (!isset($this->temp_res)) {
|
||||||
$client = new HTTPClient();
|
$client = new HTTPClient();
|
||||||
$headers = array();
|
$headers = array();
|
||||||
$headers[] = 'Accept: application/ld+json; profile="https://www.w3.org/ns/activitystreams"';
|
$headers[] = 'Accept: application/ld+json; profile="https://www.w3.org/ns/activitystreams"';
|
||||||
$headers[] = 'User-Agent: GNUSocialBot v0.1 - https://gnu.io/social';
|
$headers[] = 'User-Agent: GNUSocialBot v0.1 - https://gnu.io/social';
|
||||||
$response = $client->get($url, $headers);
|
$response = $client->get($url, $headers);
|
||||||
if (!$response->isOk()) {
|
|
||||||
throw new Exception("Invalid Actor URL.");
|
|
||||||
}
|
|
||||||
$res = json_decode($response->getBody(), JSON_UNESCAPED_SLASHES);
|
$res = json_decode($response->getBody(), JSON_UNESCAPED_SLASHES);
|
||||||
} else {
|
} else {
|
||||||
$res = $this->temp_res;
|
$res = $this->temp_res;
|
||||||
@@ -234,6 +252,32 @@ class Activitypub_explorer
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a ActivityPub Profile from it's uri
|
||||||
|
* Unfortunately GNU Social cache is not truly reliable when handling
|
||||||
|
* potential ActivityPub remote profiles, as so it is important to use
|
||||||
|
* this hacky workaround (at least for now)
|
||||||
|
*
|
||||||
|
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||||
|
* @param string $v URL
|
||||||
|
* @return boolean|Activitypub_profile false if fails | Aprofile object if successful
|
||||||
|
*/
|
||||||
|
public static function get_aprofile_by_url($v)
|
||||||
|
{
|
||||||
|
$i = Managed_DataObject::getcached("Activitypub_profile", "uri", $v);
|
||||||
|
if (empty($i)) { // false = cache miss
|
||||||
|
$i = new Activitypub_profile;
|
||||||
|
$result = $i->get("uri", $v);
|
||||||
|
if ($result) {
|
||||||
|
// Hit!
|
||||||
|
$i->encache();
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $i;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a valid actor profile url returns its inboxes
|
* Given a valid actor profile url returns its inboxes
|
||||||
*
|
*
|
||||||
|
@@ -168,12 +168,12 @@ class Activitypub_postman
|
|||||||
public function create($notice)
|
public function create($notice)
|
||||||
{
|
{
|
||||||
$data = Activitypub_create::create_to_array(
|
$data = Activitypub_create::create_to_array(
|
||||||
$notice->getUri(),
|
$notice->getUrl(),
|
||||||
ActivityPubPlugin::actor_uri($this->actor),
|
ActivityPubPlugin::actor_uri($this->actor),
|
||||||
Activitypub_notice::notice_to_array($notice)
|
array_merge(Activitypub_notice::notice_to_array($notice), ['cc' => common_local_url('apActorFollowers', ['id' => $this->actor->getID()]),])
|
||||||
);
|
);
|
||||||
if (isset($notice->reply_to)) {
|
if (isset($notice->reply_to)) {
|
||||||
$data["object"]["reply_to"] = $notice->getParent()->getUri();
|
$data["object"]["reply_to"] = $notice->getParent()->getUrl();
|
||||||
}
|
}
|
||||||
$this->client->setBody(json_encode($data));
|
$this->client->setBody(json_encode($data));
|
||||||
foreach ($this->to_inbox() as $inbox) {
|
foreach ($this->to_inbox() as $inbox) {
|
||||||
|
Reference in New Issue
Block a user