[ActivityPub] Fix issues concerning Activity URIs
And some other minor bugs.
This commit is contained in:
parent
d71eea1ba4
commit
af0366ed58
@ -180,6 +180,14 @@ class ActivityPubPlugin extends Plugin
|
||||
$acceptHeaders
|
||||
);
|
||||
|
||||
// v3
|
||||
$m->connect(
|
||||
'activity/:id',
|
||||
['action' => 'apNotice'],
|
||||
['id' => '[0-9]+'],
|
||||
);
|
||||
|
||||
// v2
|
||||
$m->connect(
|
||||
'notice/:id',
|
||||
['action' => 'apNotice'],
|
||||
|
@ -53,11 +53,12 @@ class apNoticeAction extends ManagedAction
|
||||
try {
|
||||
$notice = Notice::getByID($this->trimmed('id'));
|
||||
} catch (Exception $e) {
|
||||
ActivityPubReturn::error('Invalid Notice URI.', 404);
|
||||
ActivityPubReturn::error('Invalid Activity URI.', 404);
|
||||
}
|
||||
|
||||
if (!$notice->isLocal()) {
|
||||
ActivityPubReturn::error("This is not a local notice.", 403);
|
||||
// We have no authority on the requested activity.
|
||||
ActivityPubReturn::error("This is not a local activity.", 403);
|
||||
}
|
||||
|
||||
$res = Activitypub_notice::notice_to_array($notice);
|
||||
|
@ -54,7 +54,7 @@ class ActivityPubQueueHandler extends QueueHandler
|
||||
public function handle($notice): bool
|
||||
{
|
||||
if (!($notice instanceof Notice)) {
|
||||
common_log(LOG_ERR, "Got a bogus notice, not distributing");
|
||||
common_log(LOG_ERR, 'Got a bogus notice, not distributing');
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -74,7 +74,7 @@ class ActivityPubQueueHandler extends QueueHandler
|
||||
);
|
||||
|
||||
// Handling a Create?
|
||||
if (ActivityUtils::compareVerbs($notice->verb, [ActivityVerb::POST])) {
|
||||
if (ActivityUtils::compareVerbs($notice->verb, [ActivityVerb::POST, ActivityVerb::SHARE])) {
|
||||
return $this->handle_create($profile, $notice, $other);
|
||||
}
|
||||
|
||||
@ -143,7 +143,7 @@ class ActivityPubQueueHandler extends QueueHandler
|
||||
|
||||
// That was it
|
||||
$postman = new Activitypub_postman($profile, $other);
|
||||
$postman->announce($repeated_notice);
|
||||
$postman->announce($notice, $repeated_notice);
|
||||
}
|
||||
|
||||
// either made the announce or found nothing to repeat
|
||||
@ -160,7 +160,7 @@ class ActivityPubQueueHandler extends QueueHandler
|
||||
* Notify remote users when their notices get favourited.
|
||||
*
|
||||
* @param Profile $profile of local user doing the faving
|
||||
* @param Notice $notice Notice being favored
|
||||
* @param Notice $notice_liked Notice being favored
|
||||
* @return bool return value
|
||||
* @throws HTTP_Request2_Exception
|
||||
* @throws InvalidUrlException
|
||||
@ -168,10 +168,10 @@ class ActivityPubQueueHandler extends QueueHandler
|
||||
*/
|
||||
public function onEndFavorNotice(Profile $profile, Notice $notice, $other)
|
||||
{
|
||||
$notice = $notice->getParent();
|
||||
if ($notice->reply_to) {
|
||||
$notice_liked = $notice->getParent();
|
||||
if ($notice_liked->reply_to) {
|
||||
try {
|
||||
$parent_notice = $notice->getParent();
|
||||
$parent_notice = $notice_liked->getParent();
|
||||
|
||||
try {
|
||||
$other[] = Activitypub_profile::from_profile($parent_notice->getProfile());
|
||||
@ -189,7 +189,7 @@ class ActivityPubQueueHandler extends QueueHandler
|
||||
// This is not a reply to something (has no parent)
|
||||
} catch (NoResultException $e) {
|
||||
// Parent author's profile not found! Complain louder?
|
||||
common_log(LOG_ERR, "Parent notice's author not found: ".$e->getMessage());
|
||||
common_log(LOG_ERR, "Parent notice's author not found: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@ -242,7 +242,7 @@ class ActivityPubQueueHandler extends QueueHandler
|
||||
// This is not a reply to something (has no parent)
|
||||
} catch (NoResultException $e) {
|
||||
// Parent author's profile not found! Complain louder?
|
||||
common_log(LOG_ERR, "Parent notice's author not found: ".$e->getMessage());
|
||||
common_log(LOG_ERR, "Parent notice's author not found: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -331,7 +331,7 @@ class Activitypub_inbox_handler
|
||||
private function handle_like()
|
||||
{
|
||||
$notice = ActivityPubPlugin::grab_notice_from_url($this->object);
|
||||
Fave::addNew($this->actor, $notice);
|
||||
Activitypub_like::addNew($this->activity['id'], $this->actor, $notice);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -390,7 +390,7 @@ class Activitypub_inbox_handler
|
||||
*/
|
||||
private function handle_undo_like()
|
||||
{
|
||||
$notice = ActivityPubPlugin::grab_notice_from_url($this->object['object']);
|
||||
$notice = ActivityPubPlugin::grab_notice_from_url($this->activity['id']);
|
||||
Fave::removeEntry($this->actor, $notice);
|
||||
}
|
||||
|
||||
@ -402,7 +402,7 @@ class Activitypub_inbox_handler
|
||||
*/
|
||||
private function handle_announce()
|
||||
{
|
||||
$object_notice = ActivityPubPlugin::grab_notice_from_url($this->object);
|
||||
$object_notice->repeat($this->actor, 'ActivityPub');
|
||||
$notice = ActivityPubPlugin::grab_notice_from_url($this->object);
|
||||
Activitypub_announce::repeat($this->activity['id'], $this->actor, $notice);
|
||||
}
|
||||
}
|
||||
|
@ -41,13 +41,16 @@ class Activitypub_announce
|
||||
*
|
||||
* @param Profile $actor
|
||||
* @param Notice $notice
|
||||
* @param Notice $repeat_of
|
||||
* @return array pretty array to be used in a response
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
*/
|
||||
public static function announce_to_array(Profile $actor, Notice $notice): array
|
||||
{
|
||||
public static function announce_to_array(
|
||||
Profile $actor,
|
||||
Notice $notice,
|
||||
Notice $repeat_of
|
||||
): array {
|
||||
$actor_uri = $actor->getUri();
|
||||
$notice_url = Activitypub_notice::getUrl($notice);
|
||||
|
||||
$to = [common_local_url('apActorFollowers', ['id' => $actor->getID()])];
|
||||
foreach ($notice->getAttentionProfiles() as $to_profile) {
|
||||
@ -58,13 +61,48 @@ class Activitypub_announce
|
||||
|
||||
$res = [
|
||||
'@context' => 'https://www.w3.org/ns/activitystreams',
|
||||
'id' => common_root_url().'share_from_'.urlencode($actor_uri).'_to_'.urlencode($notice_url),
|
||||
"type" => "Announce",
|
||||
"actor" => $actor_uri,
|
||||
"object" => $notice_url,
|
||||
"to" => $to,
|
||||
"cc" => $cc
|
||||
'id' => Activitypub_notice::getUri($notice),
|
||||
'type' => 'Announce',
|
||||
'actor' => $actor_uri,
|
||||
'object' => Activitypub_notice::getUri($repeat_of),
|
||||
'to' => $to,
|
||||
'cc' => $cc,
|
||||
];
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function for posting a repeat of an existing message.
|
||||
*
|
||||
* @param string $uri
|
||||
* @param Profile $actor Profile which is doing the repeat
|
||||
* @param Notice $target
|
||||
* @return Notice
|
||||
*/
|
||||
public static function repeat(string $uri, Profile $actor, Notice $target): Notice
|
||||
{
|
||||
// TRANS: Message used to repeat a notice. RT is the abbreviation of 'retweet'.
|
||||
// TRANS: %1$s is the repeated user's name, %2$s is the repeated notice.
|
||||
$content = sprintf(
|
||||
_('RT @%1$s %2$s'),
|
||||
$actor->getNickname(),
|
||||
$target->getContent()
|
||||
);
|
||||
|
||||
$options = [
|
||||
'source' => 'ActivityPub',
|
||||
'uri' => $uri,
|
||||
'is_local' => ($actor->isLocal() ? Notice::LOCAL_PUBLIC : Notice::REMOTE),
|
||||
'repeat_of' => $target->getParent()->getID(),
|
||||
'scope' => $target->getScope(),
|
||||
];
|
||||
|
||||
// Scope is same as this one's
|
||||
return Notice::saveNew(
|
||||
$actor->getID(),
|
||||
$content,
|
||||
'ActivityPub',
|
||||
$options
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ class Activitypub_create
|
||||
{
|
||||
$res = [
|
||||
'@context' => 'https://www.w3.org/ns/activitystreams',
|
||||
'id' => $object['id'] . '/create',
|
||||
'id' => $object['id'] . '#create',
|
||||
'type' => 'Create',
|
||||
'directMessage' => $directMessage,
|
||||
'to' => $object['to'],
|
||||
|
@ -48,7 +48,7 @@ class Activitypub_delete
|
||||
{
|
||||
$res = [
|
||||
'@context' => 'https://www.w3.org/ns/activitystreams',
|
||||
'id' => $object.'/delete',
|
||||
'id' => $object . '#delete',
|
||||
'type' => 'Delete',
|
||||
'to' => ['https://www.w3.org/ns/activitystreams#Public'],
|
||||
'actor' => $actor,
|
||||
|
@ -39,20 +39,73 @@ class Activitypub_like
|
||||
/**
|
||||
* Generates an ActivityPub representation of a Like
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @param string $actor Actor URI
|
||||
* @param string $object Notice URI
|
||||
* @param Notice $notice Notice URI
|
||||
* @return array pretty array to be used in a response
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
*/
|
||||
public static function like_to_array($actor, $object)
|
||||
public static function like_to_array(string $actor, Notice $notice): array
|
||||
{
|
||||
$res = [
|
||||
'@context' => 'https://www.w3.org/ns/activitystreams',
|
||||
'id' => common_root_url().'like_from_'.urlencode($actor).'_to_'.urlencode($object),
|
||||
"type" => "Like",
|
||||
"actor" => $actor,
|
||||
"object" => $object
|
||||
'id' => Activitypub_notice::getUri($notice),
|
||||
'type' => 'Like',
|
||||
'actor' => $actor,
|
||||
'object' => Activitypub_notice::getUri($notice->getParent()),
|
||||
];
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a favorite record.
|
||||
*
|
||||
* @param string $uri
|
||||
* @param Profile $actor the local or remote Profile who favorites
|
||||
* @param Notice $target the notice that is favorited
|
||||
* @return Notice record on success
|
||||
* @throws AlreadyFulfilledException
|
||||
* @throws ClientException
|
||||
* @throws NoticeSaveException
|
||||
* @throws ServerException
|
||||
*/
|
||||
public static function addNew(string $uri, Profile $actor, Notice $target): Notice
|
||||
{
|
||||
if (Fave::existsForProfile($target, $actor)) {
|
||||
// TRANS: Client error displayed when trying to mark a notice as favorite that already is a favorite.
|
||||
throw new AlreadyFulfilledException(_m('You have already favorited this!'));
|
||||
}
|
||||
|
||||
$act = new Activity();
|
||||
$act->type = ActivityObject::ACTIVITY;
|
||||
$act->verb = ActivityVerb::FAVORITE;
|
||||
$act->time = time();
|
||||
$act->id = $uri;
|
||||
$act->title = _m('Favor');
|
||||
// TRANS: Message that is the "content" of a favorite (%1$s is the actor's nickname, %2$ is the favorited
|
||||
// notice's nickname and %3$s is the content of the favorited notice.)
|
||||
$act->content = sprintf(
|
||||
_m('%1$s favorited something by %2$s: %3$s'),
|
||||
$actor->getNickname(),
|
||||
$target->getProfile()->getNickname(),
|
||||
$target->getRendered()
|
||||
);
|
||||
$act->actor = $actor->asActivityObject();
|
||||
$act->target = $target->asActivityObject();
|
||||
$act->objects = [clone($act->target)];
|
||||
|
||||
$url = common_local_url('AtomPubShowFavorite', ['profile'=>$actor->id, 'notice'=>$target->id]);
|
||||
$act->selfLink = $url;
|
||||
$act->editLink = $url;
|
||||
|
||||
$options = [
|
||||
'source' => 'ActivityPub',
|
||||
'uri' => $act->id,
|
||||
'url' => $url,
|
||||
'is_local' => ($actor->isLocal() ? Notice::LOCAL_PUBLIC : Notice::REMOTE),
|
||||
'scope' => $target->getScope(),
|
||||
];
|
||||
|
||||
// saveActivity will in turn also call Fave::saveActivityObject
|
||||
return Notice::saveActivity($act, $actor, $options);
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ class Activitypub_notice
|
||||
* @throws Exception
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
*/
|
||||
public static function notice_to_array($notice)
|
||||
public static function notice_to_array(Notice $notice): array
|
||||
{
|
||||
$profile = $notice->getProfile();
|
||||
$attachments = [];
|
||||
@ -81,10 +81,10 @@ class Activitypub_notice
|
||||
|
||||
$item = [
|
||||
'@context' => 'https://www.w3.org/ns/activitystreams',
|
||||
'id' => self::getUrl($notice),
|
||||
'id' => self::getUri($notice),
|
||||
'type' => 'Note',
|
||||
'published' => str_replace(' ', 'T', $notice->getCreated()) . 'Z',
|
||||
'url' => self::getUrl($notice),
|
||||
'url' => $notice->getUrl(),
|
||||
'attributedTo' => $profile->getUri(),
|
||||
'to' => $to,
|
||||
'cc' => $cc,
|
||||
@ -97,7 +97,7 @@ class Activitypub_notice
|
||||
|
||||
// Is this a reply?
|
||||
if (!empty($notice->reply_to)) {
|
||||
$item['inReplyTo'] = self::getUrl(Notice::getById($notice->reply_to));
|
||||
$item['inReplyTo'] = self::getUri(Notice::getById($notice->reply_to));
|
||||
}
|
||||
|
||||
// Do we have a location for this notice?
|
||||
@ -207,9 +207,9 @@ class Activitypub_notice
|
||||
}
|
||||
|
||||
/* Reject notice if it is too long (without the HTML)
|
||||
if (Notice::contentTooLong($content)) {
|
||||
throw new Exception('That\'s too long. Maximum notice size is %d character.');
|
||||
}*/
|
||||
if (Notice::contentTooLong($content)) {
|
||||
throw new Exception('That\'s too long. Maximum notice size is %d character.');
|
||||
}*/
|
||||
|
||||
// Attachments (first part)
|
||||
$attachments = [];
|
||||
@ -253,7 +253,7 @@ class Activitypub_notice
|
||||
* @throws Exception if invalid ActivityPub object
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
*/
|
||||
public static function validate_note($object)
|
||||
public static function validate_note(array $object): bool
|
||||
{
|
||||
if (!isset($object['id'])) {
|
||||
common_debug('ActivityPub Notice Validator: Rejected because Object ID was not specified.');
|
||||
@ -290,7 +290,7 @@ class Activitypub_notice
|
||||
* @throws Exception
|
||||
* @author Bruno Casteleiro <brunoccast@fc.up.pt>
|
||||
*/
|
||||
public static function getUrl(Notice $notice): string
|
||||
public static function getUri(Notice $notice): string
|
||||
{
|
||||
if ($notice->isLocal()) {
|
||||
return common_local_url('apNotice', ['id' => $notice->getID()]);
|
||||
|
@ -43,7 +43,7 @@ class Activitypub_reject
|
||||
* @param array $object
|
||||
* @return array pretty array to be used in a response
|
||||
*/
|
||||
public static function reject_to_array($object)
|
||||
public static function reject_to_array(array $object): array
|
||||
{
|
||||
$res = [
|
||||
'@context' => 'https://www.w3.org/ns/activitystreams',
|
||||
|
@ -40,15 +40,15 @@ class Activitypub_tag
|
||||
* Generates a pretty tag from a Tag object
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @param array Tag $tag
|
||||
* @param string $tag
|
||||
* @return array pretty array to be used in a response
|
||||
*/
|
||||
public static function tag_to_array($tag)
|
||||
public static function tag_to_array(string $tag): array
|
||||
{
|
||||
$res = [
|
||||
'@context' => 'https://www.w3.org/ns/activitystreams',
|
||||
'name' => $tag,
|
||||
'url' => common_local_url('tag', ['tag' => $tag])
|
||||
'url' => common_local_url('tag', ['tag' => $tag]),
|
||||
];
|
||||
return $res;
|
||||
}
|
||||
|
@ -43,11 +43,11 @@ class Activitypub_undo
|
||||
* @param array $object
|
||||
* @return array pretty array to be used in a response
|
||||
*/
|
||||
public static function undo_to_array($object)
|
||||
public static function undo_to_array(array $object): array
|
||||
{
|
||||
$res = [
|
||||
'@context' => 'https://www.w3.org/ns/activitystreams',
|
||||
'id' => $object['id'].'/undo',
|
||||
'id' => $object['id'] . '#undo',
|
||||
'type' => 'Undo',
|
||||
'actor' => $object['actor'],
|
||||
'object' => $object
|
||||
@ -63,7 +63,7 @@ class Activitypub_undo
|
||||
* @throws Exception
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
*/
|
||||
public static function validate_object($object)
|
||||
public static function validate_object(array $object): bool
|
||||
{
|
||||
if (!is_array($object)) {
|
||||
throw new Exception('Invalid Object Format for Undo Activity.');
|
||||
|
@ -141,8 +141,8 @@ class Activitypub_postman
|
||||
Activitypub_follow::follow_to_array(
|
||||
$this->actor_uri,
|
||||
$this->to[0]->getUrl()
|
||||
)
|
||||
);
|
||||
)
|
||||
);
|
||||
$res = $this->send(json_encode($data, JSON_UNESCAPED_SLASHES), $this->to[0]->get_inbox());
|
||||
$res_body = json_decode($res->getBody(), true);
|
||||
|
||||
@ -174,8 +174,8 @@ class Activitypub_postman
|
||||
$this->to[0]->getUrl(),
|
||||
$this->actor_uri,
|
||||
$id
|
||||
)
|
||||
);
|
||||
)
|
||||
);
|
||||
$res = $this->send(json_encode($data, JSON_UNESCAPED_SLASHES), $this->to[0]->get_inbox());
|
||||
$res_body = json_decode($res->getBody(), true);
|
||||
|
||||
@ -199,18 +199,18 @@ class Activitypub_postman
|
||||
* @throws Exception
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
*/
|
||||
public function like($notice)
|
||||
public function like(Notice $notice): void
|
||||
{
|
||||
$data = Activitypub_like::like_to_array(
|
||||
$this->actor_uri,
|
||||
Activitypub_notice::getUrl($notice)
|
||||
);
|
||||
$notice
|
||||
);
|
||||
$data = json_encode($data, JSON_UNESCAPED_SLASHES);
|
||||
|
||||
foreach ($this->to_inbox() as $inbox) {
|
||||
$res = $this->send($data, $inbox);
|
||||
|
||||
// accummulate errors for later use, if needed
|
||||
// accumulate errors for later use, if needed
|
||||
if (!($res->getStatus() == 200 || $res->getStatus() == 202 || $res->getStatus() == 409)) {
|
||||
$res_body = json_decode($res->getBody(), true);
|
||||
$errors[] = isset($res_body['error']) ?
|
||||
@ -237,9 +237,9 @@ class Activitypub_postman
|
||||
$data = Activitypub_undo::undo_to_array(
|
||||
Activitypub_like::like_to_array(
|
||||
$this->actor_uri,
|
||||
Activitypub_notice::getUrl($notice)
|
||||
)
|
||||
);
|
||||
$notice
|
||||
)
|
||||
);
|
||||
$data = json_encode($data, JSON_UNESCAPED_SLASHES);
|
||||
|
||||
foreach ($this->to_inbox() as $inbox) {
|
||||
@ -273,7 +273,7 @@ class Activitypub_postman
|
||||
$data = Activitypub_create::create_to_array(
|
||||
$this->actor_uri,
|
||||
Activitypub_notice::notice_to_array($notice)
|
||||
);
|
||||
);
|
||||
$data = json_encode($data, JSON_UNESCAPED_SLASHES);
|
||||
|
||||
foreach ($this->to_inbox() as $inbox) {
|
||||
@ -327,14 +327,16 @@ class Activitypub_postman
|
||||
* Send a Announce notification to remote instances
|
||||
*
|
||||
* @param Notice $notice
|
||||
* @param Notice $repeat_of
|
||||
* @throws HTTP_Request2_Exception
|
||||
* @throws Exception
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
*/
|
||||
public function announce($notice)
|
||||
public function announce(Notice $notice, Notice $repeat_of): void
|
||||
{
|
||||
$data = json_encode(Activitypub_announce::announce_to_array($this->actor, $notice),
|
||||
JSON_UNESCAPED_SLASHES);
|
||||
$data = json_encode(
|
||||
Activitypub_announce::announce_to_array($this->actor, $notice, $repeat_of),
|
||||
JSON_UNESCAPED_SLASHES
|
||||
);
|
||||
|
||||
foreach ($this->to_inbox() as $inbox) {
|
||||
$res = $this->send($data, $inbox);
|
||||
@ -365,8 +367,8 @@ class Activitypub_postman
|
||||
{
|
||||
$data = Activitypub_delete::delete_to_array(
|
||||
$notice->getProfile()->getUri(),
|
||||
Activitypub_notice::getUrl($notice)
|
||||
);
|
||||
Activitypub_notice::getUri($notice)
|
||||
);
|
||||
$errors = [];
|
||||
$data = json_encode($data, JSON_UNESCAPED_SLASHES);
|
||||
foreach ($this->to_inbox() as $inbox) {
|
||||
|
Loading…
Reference in New Issue
Block a user