Merge branch 'dev' into 'actor_outbox'
Dev See merge request dansup/ActivityPub!25
This commit is contained in:
commit
5911b077ca
@ -20,7 +20,6 @@
|
||||
* @category Plugin
|
||||
* @package GNUsocial
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @author Daniel Supernault <danielsupernault@gmail.com>
|
||||
* @copyright 2018 Free Software Foundation http://fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link https://www.gnu.org/software/social/
|
||||
@ -30,7 +29,7 @@ if (!defined('GNUSOCIAL')) {
|
||||
}
|
||||
|
||||
// Ensure proper timezone
|
||||
date_default_timezone_set('UTC');
|
||||
date_default_timezone_set('GMT');
|
||||
|
||||
// Import required files by the plugin
|
||||
require_once __DIR__ . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php';
|
||||
@ -106,8 +105,8 @@ class ActivityPubPlugin extends Plugin
|
||||
// Look for a local notice (unfortunately GNU Social doesn't
|
||||
// provide this functionality natively)
|
||||
try {
|
||||
$candidate = Notice::getByID(intval(substr($url, strlen(common_local_url('shownotice', ['notice' => ''])))));
|
||||
if ($candidate->getUrl() == $url) { // Sanity check
|
||||
$candidate = Notice::getByID(intval(substr($url, (strlen(common_local_url('apNotice', ['id' => 0]))-1))));
|
||||
if (common_local_url('apNotice', ['id' => $candidate->getID()]) === $url) { // Sanity check
|
||||
return $candidate;
|
||||
} else {
|
||||
common_debug('ActivityPubPlugin Notice Grabber: '.$candidate->getUrl(). ' is different of '.$url);
|
||||
@ -151,49 +150,49 @@ class ActivityPubPlugin extends Plugin
|
||||
['nickname' => Nickname::DISPLAY_FMT],
|
||||
'apActorProfile'
|
||||
);
|
||||
|
||||
ActivityPubURLMapperOverwrite::variable(
|
||||
$m,
|
||||
'notice/:id',
|
||||
['id' => '[0-9]+'],
|
||||
'apNotice'
|
||||
);
|
||||
}
|
||||
|
||||
// No .json here for convenience purposes on Notice grabber
|
||||
$m->connect(
|
||||
'note/:id',
|
||||
['action' => 'apNotice'],
|
||||
['id' => '[0-9]+']
|
||||
);
|
||||
|
||||
$m->connect(
|
||||
'user/:id/liked.json',
|
||||
['action' => 'apActorLiked'],
|
||||
['id' => '[0-9]+']
|
||||
);
|
||||
['action' => 'apActorLiked'],
|
||||
['id' => '[0-9]+']
|
||||
);
|
||||
|
||||
$m->connect(
|
||||
'user/:id/followers.json',
|
||||
['action' => 'apActorFollowers'],
|
||||
['id' => '[0-9]+']
|
||||
);
|
||||
['action' => 'apActorFollowers'],
|
||||
['id' => '[0-9]+']
|
||||
);
|
||||
|
||||
$m->connect(
|
||||
'user/:id/following.json',
|
||||
['action' => 'apActorFollowing'],
|
||||
['id' => '[0-9]+']
|
||||
);
|
||||
['action' => 'apActorFollowing'],
|
||||
['id' => '[0-9]+']
|
||||
);
|
||||
|
||||
$m->connect(
|
||||
'user/:id/inbox.json',
|
||||
['action' => 'apInbox'],
|
||||
['id' => '[0-9]+']
|
||||
);
|
||||
['action' => 'apInbox'],
|
||||
['id' => '[0-9]+']
|
||||
);
|
||||
|
||||
$m->connect(
|
||||
'user/:id/outbox.json',
|
||||
['action' => 'apActorOutbox'],
|
||||
['id' => '[0-9]+']
|
||||
);
|
||||
['action' => 'apActorOutbox'],
|
||||
['id' => '[0-9]+']
|
||||
);
|
||||
|
||||
$m->connect(
|
||||
'inbox.json',
|
||||
['action' => 'apInbox']
|
||||
);
|
||||
['action' => 'apInbox']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -206,7 +205,7 @@ class ActivityPubPlugin extends Plugin
|
||||
{
|
||||
$versions[] = [ 'name' => 'ActivityPub',
|
||||
'version' => GNUSOCIAL_VERSION,
|
||||
'author' => 'Diogo Cordeiro, Daniel Supernault',
|
||||
'author' => 'Diogo Cordeiro',
|
||||
'homepage' => 'https://www.gnu.org/software/social/',
|
||||
'rawdescription' => 'Adds ActivityPub Support'];
|
||||
|
||||
@ -214,8 +213,7 @@ class ActivityPubPlugin extends Plugin
|
||||
}
|
||||
|
||||
/**
|
||||
* Dummy string on AccountProfileBlock stating that ActivityPub is active
|
||||
* this is more of a placeholder for eventual useful stuff ._.
|
||||
* Adds an indicator on Remote ActivityPub profiles.
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @return boolean hook return value
|
||||
@ -226,8 +224,8 @@ class ActivityPubPlugin extends Plugin
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
$aprofile = Activitypub_profile::getKV('profile_id', $profile->id);
|
||||
} catch (NoResultException $e) {
|
||||
$aprofile = Activitypub_profile::from_profile($profile);
|
||||
} catch (Exception $e) {
|
||||
// Not a remote ActivityPub_profile! Maybe some other network
|
||||
// that has imported a non-local user (e.g.: OStatus)?
|
||||
return true;
|
||||
@ -278,7 +276,7 @@ class ActivityPubPlugin extends Plugin
|
||||
}
|
||||
|
||||
// Look for profile URLs, with or without scheme:
|
||||
$urls = array();
|
||||
$urls = [];
|
||||
if (preg_match('!^https?://((?:\w+\.)*\w+(?:\w+\-\w+)*\.\w+(?:/\w+)+)$!', $arg)) {
|
||||
$urls[] = $arg;
|
||||
}
|
||||
@ -336,7 +334,7 @@ class ActivityPubPlugin extends Plugin
|
||||
*/
|
||||
public static function extractUrlMentions($text, $preMention='@')
|
||||
{
|
||||
$wmatches = array();
|
||||
$wmatches = [];
|
||||
// In the regexp below we need to match / _before_ URL_REGEX_VALID_PATH_CHARS because it otherwise gets merged
|
||||
// with the TLD before (but / is in URL_REGEX_VALID_PATH_CHARS anyway, it's just its positioning that is important)
|
||||
$result = preg_match_all(
|
||||
@ -386,7 +384,7 @@ class ActivityPubPlugin extends Plugin
|
||||
*/
|
||||
public function onEndFindMentions(Profile $sender, $text, &$mentions)
|
||||
{
|
||||
$matches = array();
|
||||
$matches = [];
|
||||
|
||||
foreach (self::extractWebfingerIds($text, '@') as $wmatch) {
|
||||
list($target, $pos) = $wmatch;
|
||||
@ -547,7 +545,7 @@ class ActivityPubPlugin extends Plugin
|
||||
try {
|
||||
$other = Activitypub_profile::from_profile($other);
|
||||
} catch (Exception $e) {
|
||||
return true;
|
||||
return true; // Let other plugin handle this instead
|
||||
}
|
||||
|
||||
$postman = new Activitypub_postman($profile, array($other));
|
||||
@ -574,7 +572,7 @@ class ActivityPubPlugin extends Plugin
|
||||
try {
|
||||
$other = Activitypub_profile::from_profile($other);
|
||||
} catch (Exception $e) {
|
||||
return true;
|
||||
return true; // Let other plugin handle this instead
|
||||
}
|
||||
|
||||
$postman = new Activitypub_postman($profile, array($other));
|
||||
@ -585,7 +583,7 @@ class ActivityPubPlugin extends Plugin
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify remote users when their notices get favorited.
|
||||
* Notify remote users when their notices get favourited.
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @param Profile $profile of local user doing the faving
|
||||
@ -600,7 +598,7 @@ class ActivityPubPlugin extends Plugin
|
||||
return true;
|
||||
}
|
||||
|
||||
$other = array();
|
||||
$other = [];
|
||||
try {
|
||||
$other[] = Activitypub_profile::from_profile($notice->getProfile());
|
||||
} catch (Exception $e) {
|
||||
@ -644,7 +642,7 @@ class ActivityPubPlugin extends Plugin
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify remote users when their notices get de-favorited.
|
||||
* Notify remote users when their notices get de-favourited.
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @param Profile $profile of local user doing the de-faving
|
||||
@ -659,7 +657,7 @@ class ActivityPubPlugin extends Plugin
|
||||
return true;
|
||||
}
|
||||
|
||||
$other = array();
|
||||
$other = [];
|
||||
try {
|
||||
$other[] = Activitypub_profile::from_profile($notice->getProfile());
|
||||
} catch (Exception $e) {
|
||||
@ -718,7 +716,7 @@ class ActivityPubPlugin extends Plugin
|
||||
return true;
|
||||
}
|
||||
|
||||
$other = array();
|
||||
$other = [];
|
||||
|
||||
foreach ($notice->getAttentionProfiles() as $to_profile) {
|
||||
try {
|
||||
@ -765,44 +763,12 @@ class ActivityPubPlugin extends Plugin
|
||||
{
|
||||
assert($notice->id > 0); // Ignore if not a valid notice
|
||||
|
||||
$profile = Profile::getKV($notice->profile_id);
|
||||
$profile = $notice->getProfile();
|
||||
|
||||
if (!$profile->isLocal()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$other = array();
|
||||
try {
|
||||
$other[] = Activitypub_profile::from_profile($notice->getProfile());
|
||||
} catch (Exception $e) {
|
||||
// Local user can be ignored
|
||||
}
|
||||
foreach ($notice->getAttentionProfiles() as $to_profile) {
|
||||
try {
|
||||
$other[] = Activitypub_profile::from_profile($to_profile);
|
||||
} catch (Exception $e) {
|
||||
// Local user can be ignored
|
||||
}
|
||||
}
|
||||
|
||||
// Is Announce
|
||||
if ($notice->isRepeat()) {
|
||||
$repeated_notice = Notice::getKV('id', $notice->repeat_of);
|
||||
if ($repeated_notice instanceof Notice) {
|
||||
try {
|
||||
$other[] = Activitypub_profile::from_profile($repeated_notice->getProfile());
|
||||
} catch (Exception $e) {
|
||||
// Local user can be ignored
|
||||
}
|
||||
|
||||
$postman = new Activitypub_postman($profile, $other);
|
||||
|
||||
// That was it
|
||||
$postman->announce($repeated_notice);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Ignore for activity/non-post-verb notices
|
||||
if (method_exists('ActivityUtils', 'compareVerbs')) {
|
||||
$is_post_verb = ActivityUtils::compareVerbs(
|
||||
@ -816,7 +782,16 @@ class ActivityPubPlugin extends Plugin
|
||||
return true;
|
||||
}
|
||||
|
||||
// Create
|
||||
$other = [];
|
||||
foreach ($notice->getAttentionProfiles() as $mention) {
|
||||
try {
|
||||
$other[] = Activitypub_profile::from_profile($mention);
|
||||
} catch (Exception $e) {
|
||||
// Local user can be ignored
|
||||
}
|
||||
}
|
||||
|
||||
// Is a reply?
|
||||
if ($notice->reply_to) {
|
||||
try {
|
||||
$other[] = Activitypub_profile::from_profile($notice->getParent()->getProfile());
|
||||
@ -824,10 +799,9 @@ class ActivityPubPlugin extends Plugin
|
||||
// Local user can be ignored
|
||||
}
|
||||
try {
|
||||
$mentions = $notice->getParent()->getAttentionProfiles();
|
||||
foreach ($mentions as $to_profile) {
|
||||
foreach ($notice->getParent()->getAttentionProfiles() as $mention) {
|
||||
try {
|
||||
$other[] = Activitypub_profile::from_profile($to_profile);
|
||||
$other[] = Activitypub_profile::from_profile($mention);
|
||||
} catch (Exception $e) {
|
||||
// Local user can be ignored
|
||||
}
|
||||
@ -839,10 +813,27 @@ class ActivityPubPlugin extends Plugin
|
||||
common_log(LOG_ERR, "Parent notice's author not found: ".$e->getMessage());
|
||||
}
|
||||
}
|
||||
$postman = new Activitypub_postman($profile, $other);
|
||||
|
||||
// Is an Announce?
|
||||
if ($notice->isRepeat()) {
|
||||
$repeated_notice = Notice::getKV('id', $notice->repeat_of);
|
||||
if ($repeated_notice instanceof Notice) {
|
||||
try {
|
||||
$other[] = Activitypub_profile::from_profile($repeated_notice->getProfile());
|
||||
} catch (Exception $e) {
|
||||
// Local user can be ignored
|
||||
}
|
||||
|
||||
// That was it
|
||||
$postman = new Activitypub_postman($profile, $other);
|
||||
$postman->announce($repeated_notice);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// That was it
|
||||
$postman->create($notice);
|
||||
$postman = new Activitypub_postman($profile, $other);
|
||||
$postman->create_note($notice);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -40,10 +40,14 @@ We use [SemVer](http://semver.org/) for versioning. For the versions available,
|
||||
## Credits
|
||||
|
||||
* **[Diogo Cordeiro](https://www.diogo.site/)**
|
||||
* **[Daniel Supernault](https://github.com/dansup)**
|
||||
|
||||
See also the list of [contributors](https://git.gnu.io/gnu/GS-ActivityPub-Plugin/contributors) who participated in this project.
|
||||
|
||||
## Extra special thanks
|
||||
|
||||
* **[Daniel Supernault](https://github.com/dansup)**
|
||||
* **[Mikael Nordfeldth](https://mmn-o.se/)**
|
||||
|
||||
## License
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
|
@ -20,7 +20,6 @@
|
||||
* @category Plugin
|
||||
* @package GNUsocial
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @author Daniel Supernault <danielsupernault@gmail.com>
|
||||
* @copyright 2018 Free Software Foundation http://fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link https://www.gnu.org/software/social/
|
||||
@ -108,7 +107,7 @@ class apActorFollowersAction extends ManagedAction
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a list of followers for a given profile.
|
||||
* Generates a list of stalkers for a given profile.
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @param Profile $profile
|
||||
@ -116,7 +115,7 @@ class apActorFollowersAction extends ManagedAction
|
||||
* @param int32 $limit
|
||||
* @return Array of URIs
|
||||
*/
|
||||
public function generate_followers($profile, $since, $limit)
|
||||
public static function generate_followers($profile, $since, $limit)
|
||||
{
|
||||
/* Fetch Followers */
|
||||
try {
|
||||
@ -130,6 +129,7 @@ class apActorFollowersAction extends ManagedAction
|
||||
while ($sub->fetch()) {
|
||||
$subs[] = ActivityPubPlugin::actor_uri($sub);
|
||||
}
|
||||
|
||||
return $subs;
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,6 @@
|
||||
* @category Plugin
|
||||
* @package GNUsocial
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @author Daniel Supernault <danielsupernault@gmail.com>
|
||||
* @copyright 2018 Free Software Foundation http://fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link https://www.gnu.org/software/social/
|
||||
@ -108,7 +107,7 @@ class apActorFollowingAction extends ManagedAction
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a list of people following given profile.
|
||||
* Generates the list of those a given profile is stalking.
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @param Profile $profile
|
||||
|
@ -20,7 +20,6 @@
|
||||
* @category Plugin
|
||||
* @package GNUsocial
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @author Daniel Supernault <danielsupernault@gmail.com>
|
||||
* @copyright 2018 Free Software Foundation http://fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link https://www.gnu.org/software/social/
|
||||
|
@ -20,7 +20,6 @@
|
||||
* @category Plugin
|
||||
* @package GNUsocial
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @author Daniel Supernault <danielsupernault@gmail.com>
|
||||
* @copyright 2018 Free Software Foundation http://fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link https://www.gnu.org/software/social/
|
||||
|
@ -20,7 +20,6 @@
|
||||
* @category Plugin
|
||||
* @package GNUsocial
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @author Daniel Supernault <danielsupernault@gmail.com>
|
||||
* @copyright 2018 Free Software Foundation http://fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link https://www.gnu.org/software/social/
|
||||
|
@ -20,7 +20,6 @@
|
||||
* @category Plugin
|
||||
* @package GNUsocial
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @author Daniel Supernault <danielsupernault@gmail.com>
|
||||
* @copyright 2018 Free Software Foundation http://fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link https://www.gnu.org/software/social/
|
||||
@ -55,16 +54,50 @@ class apInboxAction extends ManagedAction
|
||||
ActivityPubReturn::error('Only POST requests allowed.');
|
||||
}
|
||||
|
||||
common_debug('ActivityPub Shared Inbox: Received a POST request.');
|
||||
common_debug('ActivityPub Inbox: Received a POST request.');
|
||||
$data = file_get_contents('php://input');
|
||||
common_debug('ActivityPub Shared Inbox: Request contents: '.$data);
|
||||
common_debug('ActivityPub Inbox: Request contents: '.$data);
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
|
||||
if (!isset($data['actor'])) {
|
||||
ActivityPubReturn::error('Actor not found in the request.');
|
||||
}
|
||||
|
||||
$actor = ActivityPub_explorer::get_profile_from_url($data['actor']);
|
||||
$actor_public_key = new Activitypub_rsa();
|
||||
$actor_public_key = $actor_public_key->ensure_public_key($actor);
|
||||
|
||||
common_debug('ActivityPub Inbox: HTTP Signature: Validation will now start!');
|
||||
|
||||
$headers = $this->get_all_headers();
|
||||
common_debug('ActivityPub Inbox: Request Headers: '.print_r($headers, true));
|
||||
|
||||
// TODO: Validate HTTP Signature, if it fails, attempt once with profile update
|
||||
|
||||
common_debug('ActivityPub Inbox: HTTP Signature: Authorized request. Will now start the inbox handler.');
|
||||
|
||||
try {
|
||||
new Activitypub_inbox_handler($data);
|
||||
new Activitypub_inbox_handler($data, $actor);
|
||||
ActivityPubReturn::answer();
|
||||
} catch (Exception $e) {
|
||||
ActivityPubReturn::error($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all HTTP header key/values as an associative array for the current request.
|
||||
*
|
||||
* @author PHP Manual Contributed Notes <joyview@gmail.com>
|
||||
* @return string[string] The HTTP header key/value pairs.
|
||||
*/
|
||||
private function get_all_headers()
|
||||
{
|
||||
$headers = [];
|
||||
foreach ($_SERVER as $name => $value) {
|
||||
if (substr($name, 0, 5) == 'HTTP_') {
|
||||
$headers[strtolower(str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5))))))] = $value;
|
||||
}
|
||||
}
|
||||
return $headers;
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,6 @@
|
||||
* @category Plugin
|
||||
* @package GNUsocial
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @author Daniel Supernault <danielsupernault@gmail.com>
|
||||
* @copyright 2018 Free Software Foundation http://fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link https://www.gnu.org/software/social/
|
||||
|
@ -20,7 +20,6 @@
|
||||
* @category Plugin
|
||||
* @package GNUsocial
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @author Daniel Supernault <danielsupernault@gmail.com>
|
||||
* @copyright 2018 Free Software Foundation http://fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link https://www.gnu.org/software/social/
|
||||
@ -50,10 +49,7 @@ class Activitypub_accept extends Managed_DataObject
|
||||
public static function accept_to_array($object)
|
||||
{
|
||||
$res = [
|
||||
'@context' => [
|
||||
'https://www.w3.org/ns/activitystreams',
|
||||
'https://w3id.org/security/v1'
|
||||
],
|
||||
'@context' => 'https://www.w3.org/ns/activitystreams',
|
||||
'id' => common_root_url().'accept_follow_from_'.urlencode($object['actor']).'_to_'.urlencode($object['object']),
|
||||
'type' => 'Accept',
|
||||
'actor' => $object['object'],
|
||||
|
@ -20,7 +20,6 @@
|
||||
* @category Plugin
|
||||
* @package GNUsocial
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @author Daniel Supernault <danielsupernault@gmail.com>
|
||||
* @copyright 2018 Free Software Foundation http://fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link https://www.gnu.org/software/social/
|
||||
@ -50,10 +49,7 @@ class Activitypub_announce extends Managed_DataObject
|
||||
public static function announce_to_array($actor, $object)
|
||||
{
|
||||
$res = [
|
||||
'@context' => [
|
||||
'https://www.w3.org/ns/activitystreams',
|
||||
'https://w3id.org/security/v1'
|
||||
],
|
||||
'@context' => 'https://www.w3.org/ns/activitystreams',
|
||||
"type" => "Announce",
|
||||
"actor" => $actor,
|
||||
"object" => $object
|
||||
|
@ -20,7 +20,6 @@
|
||||
* @category Plugin
|
||||
* @package GNUsocial
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @author Daniel Supernault <danielsupernault@gmail.com>
|
||||
* @copyright 2018 Free Software Foundation http://fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link https://www.gnu.org/software/social/
|
||||
@ -50,10 +49,7 @@ class Activitypub_attachment extends Managed_DataObject
|
||||
public static function attachment_to_array($attachment)
|
||||
{
|
||||
$res = [
|
||||
'@context' => [
|
||||
'https://www.w3.org/ns/activitystreams',
|
||||
'https://w3id.org/security/v1'
|
||||
],
|
||||
'@context' => 'https://www.w3.org/ns/activitystreams',
|
||||
'type' => 'Document',
|
||||
'mediaType' => $attachment->mimetype,
|
||||
'url' => $attachment->getUrl(),
|
||||
|
@ -20,7 +20,6 @@
|
||||
* @category Plugin
|
||||
* @package GNUsocial
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @author Daniel Supernault <danielsupernault@gmail.com>
|
||||
* @copyright 2018 Free Software Foundation http://fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link https://www.gnu.org/software/social/
|
||||
@ -51,10 +50,7 @@ class Activitypub_create extends Managed_DataObject
|
||||
public static function create_to_array($actor, $object)
|
||||
{
|
||||
$res = [
|
||||
'@context' => [
|
||||
'https://www.w3.org/ns/activitystreams',
|
||||
'https://w3id.org/security/v1'
|
||||
],
|
||||
'@context' => 'https://www.w3.org/ns/activitystreams',
|
||||
'id' => $object['id'].'/create',
|
||||
'type' => 'Create',
|
||||
'to' => $object['to'],
|
||||
|
@ -20,7 +20,6 @@
|
||||
* @category Plugin
|
||||
* @package GNUsocial
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @author Daniel Supernault <danielsupernault@gmail.com>
|
||||
* @copyright 2018 Free Software Foundation http://fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link https://www.gnu.org/software/social/
|
||||
@ -50,10 +49,7 @@ class Activitypub_delete extends Managed_DataObject
|
||||
public static function delete_to_array($actor, $object)
|
||||
{
|
||||
$res = [
|
||||
'@context' => [
|
||||
'https://www.w3.org/ns/activitystreams',
|
||||
'https://w3id.org/security/v1'
|
||||
],
|
||||
'@context' => 'https://www.w3.org/ns/activitystreams',
|
||||
'id' => $object.'/delete',
|
||||
'type' => 'Delete',
|
||||
'actor' => $actor,
|
||||
|
@ -20,7 +20,6 @@
|
||||
* @category Plugin
|
||||
* @package GNUsocial
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @author Daniel Supernault <danielsupernault@gmail.com>
|
||||
* @copyright 2018 Free Software Foundation http://fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link https://www.gnu.org/software/social/
|
||||
|
@ -20,7 +20,6 @@
|
||||
* @category Plugin
|
||||
* @package GNUsocial
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @author Daniel Supernault <danielsupernault@gmail.com>
|
||||
* @copyright 2018 Free Software Foundation http://fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link https://www.gnu.org/software/social/
|
||||
@ -51,10 +50,7 @@ class Activitypub_follow extends Managed_DataObject
|
||||
public static function follow_to_array($actor, $object)
|
||||
{
|
||||
$res = [
|
||||
'@context' => [
|
||||
'https://www.w3.org/ns/activitystreams',
|
||||
'https://w3id.org/security/v1'
|
||||
],
|
||||
'@context' => 'https://www.w3.org/ns/activitystreams',
|
||||
'id' => common_root_url().'follow_from_'.urlencode($actor).'_to_'.urlencode($object),
|
||||
'type' => 'Follow',
|
||||
'actor' => $actor,
|
||||
|
@ -20,7 +20,6 @@
|
||||
* @category Plugin
|
||||
* @package GNUsocial
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @author Daniel Supernault <danielsupernault@gmail.com>
|
||||
* @copyright 2018 Free Software Foundation http://fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link https://www.gnu.org/software/social/
|
||||
@ -51,10 +50,7 @@ class Activitypub_like extends Managed_DataObject
|
||||
public static function like_to_array($actor, $object)
|
||||
{
|
||||
$res = [
|
||||
'@context' => [
|
||||
'https://www.w3.org/ns/activitystreams',
|
||||
'https://w3id.org/security/v1'
|
||||
],
|
||||
'@context' => 'https://www.w3.org/ns/activitystreams',
|
||||
'id' => common_root_url().'like_from_'.urlencode($actor).'_to_'.urlencode($object),
|
||||
"type" => "Like",
|
||||
"actor" => $actor,
|
||||
|
@ -20,7 +20,6 @@
|
||||
* @category Plugin
|
||||
* @package GNUsocial
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @author Daniel Supernault <danielsupernault@gmail.com>
|
||||
* @copyright 2018 Free Software Foundation http://fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link https://www.gnu.org/software/social/
|
||||
@ -51,10 +50,7 @@ class Activitypub_mention_tag extends Managed_DataObject
|
||||
public static function mention_tag_to_array_from_values($href, $name)
|
||||
{
|
||||
$res = [
|
||||
'@context' => [
|
||||
'https://www.w3.org/ns/activitystreams',
|
||||
'https://w3id.org/security/v1'
|
||||
],
|
||||
'@context' => 'https://www.w3.org/ns/activitystreams',
|
||||
"type" => "Mention",
|
||||
"href" => $href,
|
||||
"name" => $name
|
||||
|
@ -19,7 +19,6 @@
|
||||
*
|
||||
* @category Plugin
|
||||
* @package GNUsocial
|
||||
* @author Daniel Supernault <danielsupernault@gmail.com>
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @copyright 2018 Free Software Foundation http://fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
@ -72,11 +71,8 @@ class Activitypub_notice extends Managed_DataObject
|
||||
$to[]= 'https://www.w3.org/ns/activitystreams#Public';
|
||||
|
||||
$item = [
|
||||
'@context' => [
|
||||
'https://www.w3.org/ns/activitystreams',
|
||||
'https://w3id.org/security/v1'
|
||||
],
|
||||
'id' => $notice->getUrl(),
|
||||
'@context' => 'https://www.w3.org/ns/activitystreams',
|
||||
'id' => common_local_url('apNotice', ['id' => $notice->getID()]),
|
||||
'type' => 'Note',
|
||||
'published' => str_replace(' ', 'T', $notice->getCreated()).'Z',
|
||||
'url' => $notice->getUrl(),
|
||||
@ -93,7 +89,7 @@ class Activitypub_notice extends Managed_DataObject
|
||||
|
||||
// Is this a reply?
|
||||
if (!empty($notice->reply_to)) {
|
||||
$item['inReplyTo'] = Notice::getById($notice->reply_to)->getUrl();
|
||||
$item['inReplyTo'] = common_local_url('apNotice', ['id' => $notice->getID()]);
|
||||
$item['inReplyToAtomUri'] = Notice::getById($notice->reply_to)->getUrl();
|
||||
}
|
||||
|
||||
@ -124,7 +120,6 @@ class Activitypub_notice extends Managed_DataObject
|
||||
$id = $object['id']; // int32
|
||||
$url = $object['url']; // string
|
||||
$content = $object['content']; // string
|
||||
$cc = $object['cc']; // array|string
|
||||
|
||||
// possible keys: ['inReplyTo', 'latitude', 'longitude', 'attachment']
|
||||
$settings = [];
|
||||
@ -192,43 +187,41 @@ class Activitypub_notice extends Managed_DataObject
|
||||
if (isset($settings['inReplyTo'])) {
|
||||
try {
|
||||
$inReplyTo = ActivityPubPlugin::grab_notice_from_url($settings['inReplyTo']);
|
||||
$act->context->replyToID = $inReplyTo->getUri();
|
||||
$act->context->replyToUrl = $inReplyTo->getUrl();
|
||||
} catch (Exception $e) {
|
||||
throw new Exception('Invalid Object inReplyTo value: '.$e->getMessage());
|
||||
// It failed to grab, maybe we got this note from another source
|
||||
// (e.g.: OStatus) that handles this differently or we really
|
||||
// failed to get it...
|
||||
// Welp, nothing that we can do about, let's
|
||||
// just fake we don't have such notice.
|
||||
}
|
||||
$act->context->replyToID = $inReplyTo->getUri();
|
||||
$act->context->replyToUrl = $inReplyTo->getUrl();
|
||||
} else {
|
||||
$inReplyTo = null;
|
||||
}
|
||||
|
||||
$discovery = new Activitypub_explorer;
|
||||
|
||||
// Generate Cc objects
|
||||
$cc_profiles = [];
|
||||
if (is_array($cc)) {
|
||||
// Remove duplicates from Cc actors set
|
||||
array_unique($cc);
|
||||
foreach ($cc as $cc_url) {
|
||||
try {
|
||||
$cc_profiles = array_merge($cc_profiles, $discovery->lookup($cc_url));
|
||||
} catch (Exception $e) {
|
||||
// Invalid actor found, just let it go. // TODO: Fallback to OStatus
|
||||
// Mentions
|
||||
$mentions = [];
|
||||
if (isset($object['tag']) && is_array($object['tag'])) {
|
||||
foreach ($object['tag'] as $tag) {
|
||||
if ($tag['type'] == 'Mention') {
|
||||
$mentions[] = $tag['href'];
|
||||
}
|
||||
}
|
||||
} elseif (empty($cc) || in_array($cc, ACTIVITYPUB_PUBLIC_TO)) {
|
||||
// No need to do anything else at this point, let's just break out the if
|
||||
} else {
|
||||
}
|
||||
$mentions_profiles = [];
|
||||
$discovery = new Activitypub_explorer;
|
||||
foreach ($mentions as $mention) {
|
||||
try {
|
||||
$cc_profiles = $discovery->lookup($cc);
|
||||
$mentions_profiles[] = $discovery->lookup($mention)[0];
|
||||
} catch (Exception $e) {
|
||||
// Invalid actor found, just let it go. // TODO: Fallback to OStatus
|
||||
}
|
||||
}
|
||||
|
||||
unset($discovery);
|
||||
|
||||
foreach ($cc_profiles as $cp) {
|
||||
$act->context->attention[ActivityPubPlugin::actor_uri($cp)] = 'http://activitystrea.ms/schema/1.0/person';
|
||||
foreach ($mentions_profiles as $mp) {
|
||||
$act->context->attention[ActivityPubPlugin::actor_uri($mp)] = 'http://activitystrea.ms/schema/1.0/person';
|
||||
}
|
||||
|
||||
// Add location if that is set
|
||||
|
@ -20,7 +20,6 @@
|
||||
* @category Plugin
|
||||
* @package GNUsocial
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @author Daniel Supernault <danielsupernault@gmail.com>
|
||||
* @copyright 2018 Free Software Foundation http://fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link https://www.gnu.org/software/social/
|
||||
|
@ -20,7 +20,6 @@
|
||||
* @category Plugin
|
||||
* @package GNUsocial
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @author Daniel Supernault <danielsupernault@gmail.com>
|
||||
* @copyright 2018 Free Software Foundation http://fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link https://www.gnu.org/software/social/
|
||||
@ -96,10 +95,7 @@ class Activitypub_profile extends Managed_DataObject
|
||||
$public_key = $rsa->ensure_public_key($profile);
|
||||
unset($rsa);
|
||||
$res = [
|
||||
'@context' => [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
"https://w3id.org/security/v1"
|
||||
],
|
||||
'@context' => 'https://www.w3.org/ns/activitystreams',
|
||||
'id' => $uri,
|
||||
'type' => 'Person',
|
||||
'following' => common_local_url('apActorFollowing', ['id' => $id]),
|
||||
@ -242,9 +238,13 @@ class Activitypub_profile extends Managed_DataObject
|
||||
*/
|
||||
private static function create_from_local_profile(Profile $profile)
|
||||
{
|
||||
$url = $profile->getURL();
|
||||
$url = $profile->getUri();
|
||||
$inboxes = Activitypub_explorer::get_actor_inboxes_uri($url);
|
||||
|
||||
if ($inboxes == null) {
|
||||
throw new Exception('This is not an ActivityPub user thus AProfile is politely refusing to proceed.');
|
||||
}
|
||||
|
||||
$aprofile->created = $aprofile->modified = common_sql_now();
|
||||
|
||||
$aprofile = new Activitypub_profile;
|
||||
@ -413,4 +413,57 @@ class Activitypub_profile extends Managed_DataObject
|
||||
// TRANS: Exception. %s is a webfinger address.
|
||||
throw new Exception(sprintf(_m('Could not find a valid profile for "%s".'), $addr));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update remote user profile in local instance
|
||||
* Depends on do_update
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @param array $res remote response
|
||||
* @return Profile remote Profile object
|
||||
*/
|
||||
public static function update_profile($aprofile, $res)
|
||||
{
|
||||
// ActivityPub Profile
|
||||
$aprofile->uri = $res['id'];
|
||||
$aprofile->nickname = $res['preferredUsername'];
|
||||
$aprofile->fullname = isset($res['name']) ? $res['name'] : null;
|
||||
$aprofile->bio = isset($res['summary']) ? substr(strip_tags($res['summary']), 0, 1000) : null;
|
||||
$aprofile->inboxuri = $res['inbox'];
|
||||
$aprofile->sharedInboxuri = isset($res['endpoints']['sharedInbox']) ? $res['endpoints']['sharedInbox'] : $res['inbox'];
|
||||
|
||||
$profile = $aprofile->local_profile();
|
||||
|
||||
$profile->modified = $aprofile->modified = common_sql_now();
|
||||
|
||||
$fields = [
|
||||
'uri' => 'profileurl',
|
||||
'nickname' => 'nickname',
|
||||
'fullname' => 'fullname',
|
||||
'bio' => 'bio'
|
||||
];
|
||||
|
||||
foreach ($fields as $af => $pf) {
|
||||
$profile->$pf = $aprofile->$af;
|
||||
}
|
||||
|
||||
// Profile
|
||||
$profile->update();
|
||||
$aprofile->update();
|
||||
|
||||
// Public Key
|
||||
Activitypub_rsa::update_public_key($profile, $res['publicKey']['publicKeyPem']);
|
||||
|
||||
// Avatar
|
||||
if (isset($res['icon']['url'])) {
|
||||
try {
|
||||
Activitypub_explorer::update_avatar($profile, $res['icon']['url']);
|
||||
} catch (Exception $e) {
|
||||
// Let the exception go, it isn't a serious issue
|
||||
common_debug('An error ocurred while grabbing remote avatar'.$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return $profile;
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,6 @@
|
||||
* @category Plugin
|
||||
* @package GNUsocial
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @author Daniel Supernault <danielsupernault@gmail.com>
|
||||
* @copyright 2018 Free Software Foundation http://fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link https://www.gnu.org/software/social/
|
||||
@ -50,10 +49,7 @@ class Activitypub_reject extends Managed_DataObject
|
||||
public static function reject_to_array($object)
|
||||
{
|
||||
$res = [
|
||||
'@context' => [
|
||||
'https://www.w3.org/ns/activitystreams',
|
||||
'https://w3id.org/security/v1'
|
||||
],
|
||||
'@context' => 'https://www.w3.org/ns/activitystreams',
|
||||
"type" => "Reject",
|
||||
"object" => $object
|
||||
];
|
||||
|
@ -20,7 +20,6 @@
|
||||
* @category Plugin
|
||||
* @package GNUsocial
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @author Daniel Supernault <danielsupernault@gmail.com>
|
||||
* @copyright 2018 Free Software Foundation http://fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link https://www.gnu.org/software/social/
|
||||
@ -84,16 +83,15 @@ class Activitypub_rsa extends Managed_DataObject
|
||||
return $apRSA->private_key;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Guarantees a Public Key for a given profile.
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @param Profile $profile
|
||||
* @return string The public key
|
||||
* @throws Exception It should never occur
|
||||
* @throws ServerException It should never occur, but if so, we break everything!
|
||||
*/
|
||||
public function ensure_public_key($profile)
|
||||
public function ensure_public_key($profile, $fetch = true)
|
||||
{
|
||||
$this->profile_id = $profile->getID();
|
||||
$apRSA = self::getKV('profile_id', $this->profile_id);
|
||||
@ -103,7 +101,14 @@ class Activitypub_rsa extends Managed_DataObject
|
||||
self::generate_keys($this->private_key, $this->public_key);
|
||||
$this->store_keys();
|
||||
} else {
|
||||
throw new Exception('No Keys for this Profile. That\'s odd.');
|
||||
// This should never happen, but try to recover!
|
||||
if ($fetch) {
|
||||
$res = Activitypub_explorer::get_remote_user_activity(ActivityPubPlugin::actor_uri($profile));
|
||||
Activitypub_rsa::update_public_key($profile, $res['publicKey']['publicKeyPem']);
|
||||
return ensure_public_key($profile, false);
|
||||
} else {
|
||||
throw new ServerException('Activitypub_rsa: Failed to find keys for given profile. That should have not happened!');
|
||||
}
|
||||
}
|
||||
}
|
||||
return $apRSA->public_key;
|
||||
@ -121,7 +126,6 @@ class Activitypub_rsa extends Managed_DataObject
|
||||
$this->created = $this->modified = common_sql_now();
|
||||
$ok = $this->insert();
|
||||
if ($ok === false) {
|
||||
$profile->query('ROLLBACK');
|
||||
throw new ServerException('Cannot save ActivityPub RSA.');
|
||||
}
|
||||
}
|
||||
@ -152,4 +156,23 @@ class Activitypub_rsa extends Managed_DataObject
|
||||
$public_key = $pubKey["key"];
|
||||
unset($pubKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update public key.
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @param Profile $profile
|
||||
* @param string $public_key
|
||||
*/
|
||||
public static function update_public_key($profile, $public_key)
|
||||
{
|
||||
// Public Key
|
||||
$apRSA = new Activitypub_rsa();
|
||||
$apRSA->profile_id = $profile->getID();
|
||||
$apRSA->public_key = $public_key;
|
||||
$apRSA->modified = common_sql_now();
|
||||
if(!$apRSA->update()) {
|
||||
$apRSA->insert();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,6 @@
|
||||
* @category Plugin
|
||||
* @package GNUsocial
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @author Daniel Supernault <danielsupernault@gmail.com>
|
||||
* @copyright 2018 Free Software Foundation http://fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link https://www.gnu.org/software/social/
|
||||
@ -50,10 +49,7 @@ class Activitypub_tag extends Managed_DataObject
|
||||
public static function tag_to_array($tag)
|
||||
{
|
||||
$res = [
|
||||
'@context' => [
|
||||
'https://www.w3.org/ns/activitystreams',
|
||||
'https://w3id.org/security/v1'
|
||||
],
|
||||
'@context' => 'https://www.w3.org/ns/activitystreams',
|
||||
'name' => $tag,
|
||||
'url' => common_local_url('tag', ['tag' => $tag])
|
||||
];
|
||||
|
@ -20,7 +20,6 @@
|
||||
* @category Plugin
|
||||
* @package GNUsocial
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @author Daniel Supernault <danielsupernault@gmail.com>
|
||||
* @copyright 2018 Free Software Foundation http://fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link https://www.gnu.org/software/social/
|
||||
@ -50,10 +49,7 @@ class Activitypub_undo extends Managed_DataObject
|
||||
public static function undo_to_array($object)
|
||||
{
|
||||
$res = [
|
||||
'@context' => [
|
||||
'https://www.w3.org/ns/activitystreams',
|
||||
'https://w3id.org/security/v1'
|
||||
],
|
||||
'@context' => 'https://www.w3.org/ns/activitystreams',
|
||||
'id' => $object['id'].'/undo',
|
||||
'type' => 'Undo',
|
||||
'actor' => $object['actor'],
|
||||
|
104
daemons/update_activitypub_profiles.php
Executable file
104
daemons/update_activitypub_profiles.php
Executable file
@ -0,0 +1,104 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
/**
|
||||
* GNU social - a federating social network
|
||||
*
|
||||
* ActivityPubPlugin implementation for GNU Social
|
||||
*
|
||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @category Plugin
|
||||
* @package GNUsocial
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @copyright 2018 Free Software Foundation http://fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link https://www.gnu.org/software/social/
|
||||
*/
|
||||
|
||||
define('INSTALLDIR', realpath(__DIR__ . '/../../..'));
|
||||
|
||||
$shortoptions = 'u:af';
|
||||
$longoptions = ['uri=', 'all', 'force'];
|
||||
|
||||
$helptext = <<<END_OF_HELP
|
||||
update_activitypub_profiles.php [options]
|
||||
Refetch / update ActivityPub RSA keys, profile info and avatars. Useful if you
|
||||
do something like accidentally delete your avatars directory when
|
||||
you have no backup.
|
||||
|
||||
-u --uri ActivityPub profile URI to update
|
||||
-a --all update all
|
||||
|
||||
END_OF_HELP;
|
||||
|
||||
require_once INSTALLDIR.'/scripts/commandline.inc';
|
||||
|
||||
$quiet = have_option('q', 'quiet');
|
||||
|
||||
if (!$quiet) {
|
||||
echo "ActivityPub Profiles updater will now start!\n";
|
||||
echo "Summoning Diogo Cordeiro, Richard Stallman and Chuck Norris to help us with this task!\n";
|
||||
}
|
||||
|
||||
if (have_option('u', 'uri')) {
|
||||
$uri = get_option_value('u', 'uri');
|
||||
$discovery = new Activitypub_explorer();
|
||||
$discovery = $discovery->lookup($uri);
|
||||
if (empty($discovery)) {
|
||||
echo "Bad URI\n";
|
||||
exit(1);
|
||||
}
|
||||
$user = $discovery->lookup($uri)[0];
|
||||
try {
|
||||
$res = Activitypub_explorer::get_remote_user_activity($uri);
|
||||
} catch (Exception $e) {
|
||||
echo $e->getMessage()."\n";
|
||||
exit(1);
|
||||
}
|
||||
if (!$quiet) {
|
||||
echo "Updated ".Activitypub_profile::update_profile($user, $res)->getBestName()."\n";
|
||||
}
|
||||
} else if (!have_option('a', 'all')) {
|
||||
show_help();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$user = new Activitypub_profile();
|
||||
$cnt = $user->find();
|
||||
if (!empty($cnt)) {
|
||||
if (!$quiet) {
|
||||
echo "Found {$cnt} ActivityPub profiles:\n";
|
||||
}
|
||||
} else {
|
||||
if (have_option('u', 'uri')) {
|
||||
if (!$quiet) {
|
||||
echo "Couldn't find an existing ActivityPub profile with that URI.\n";
|
||||
}
|
||||
} else {
|
||||
if (!$quiet) {
|
||||
echo "Couldn't find any existing ActivityPub profiles.\n";
|
||||
}
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
while ($user->fetch()) {
|
||||
try {
|
||||
$res = Activitypub_explorer::get_remote_user_activity($user->uri);
|
||||
if (!$quiet) {
|
||||
echo "Updated ".Activitypub_profile::update_profile($user, $res)->getBestName()."\n";
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
// let it go
|
||||
}
|
||||
}
|
@ -20,7 +20,6 @@
|
||||
* @category Plugin
|
||||
* @package GNUsocial
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @author Daniel Supernault <danielsupernault@gmail.com>
|
||||
* @copyright 2018 Free Software Foundation http://fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link https://www.gnu.org/software/social/
|
||||
|
@ -20,7 +20,6 @@
|
||||
* @category Plugin
|
||||
* @package GNUsocial
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @author Daniel Supernault <danielsupernault@gmail.com>
|
||||
* @copyright 2018 Free Software Foundation http://fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link https://www.gnu.org/software/social/
|
||||
@ -204,7 +203,7 @@ class Activitypub_explorer
|
||||
common_debug('ActivityPub Explorer: Trying to grab a remote actor for '.$url);
|
||||
if (!isset($this->temp_res)) {
|
||||
$client = new HTTPClient();
|
||||
$headers = array();
|
||||
$headers = [];
|
||||
$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);
|
||||
@ -259,10 +258,10 @@ class Activitypub_explorer
|
||||
// Avatar
|
||||
if (isset($res['icon']['url'])) {
|
||||
try {
|
||||
$this->_store_avatar($profile, $res['icon']['url']);
|
||||
$this->update_avatar($profile, $res['icon']['url']);
|
||||
} catch (Exception $e) {
|
||||
// Let the exception go, it isn't a serious issue
|
||||
common_debug('An error ocurred while grabbing remote avatar'.$e->getMessage());
|
||||
common_debug('ActivityPub Explorer: An error ocurred while grabbing remote avatar: '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@ -278,7 +277,7 @@ class Activitypub_explorer
|
||||
* @return Avatar The Avatar we have on disk.
|
||||
* @throws Exception in various failure cases
|
||||
*/
|
||||
private function _store_avatar(Profile $profile, $url)
|
||||
public static function update_avatar(Profile $profile, $url)
|
||||
{
|
||||
common_debug('ActivityPub Explorer: Started grabbing remote avatar from: '.$url);
|
||||
if (!filter_var($url, FILTER_VALIDATE_URL)) {
|
||||
@ -388,7 +387,7 @@ class Activitypub_explorer
|
||||
public static function get_actor_inboxes_uri($url)
|
||||
{
|
||||
$client = new HTTPClient();
|
||||
$headers = array();
|
||||
$headers = [];
|
||||
$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);
|
||||
@ -416,7 +415,7 @@ class Activitypub_explorer
|
||||
private function travel_collection($url)
|
||||
{
|
||||
$client = new HTTPClient();
|
||||
$headers = array();
|
||||
$headers = [];
|
||||
$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);
|
||||
@ -439,4 +438,27 @@ class Activitypub_explorer
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a remote user array from its URL (this function is only used for
|
||||
* profile updating and shall not be used for anything else)
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @param string $url User's url
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function get_remote_user_activity($url)
|
||||
{
|
||||
$client = new HTTPClient();
|
||||
$headers = [];
|
||||
$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 (Activitypub_explorer::validate_remote_response($res)) {
|
||||
common_debug('ActivityPub Explorer: Found a valid remote actor for '.$url);
|
||||
return $res;
|
||||
}
|
||||
throw new Exception('ActivityPub Explorer: Failed to get activity.');
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,6 @@
|
||||
* @category Plugin
|
||||
* @package GNUsocial
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @author Daniel Supernault <danielsupernault@gmail.com>
|
||||
* @copyright 2018 Free Software Foundation http://fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link https://www.gnu.org/software/social/
|
||||
@ -49,8 +48,9 @@ class Activitypub_inbox_handler
|
||||
*
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @param Array $activity Activity we are receiving
|
||||
* @param Profile $actor_profile Actor originating the activity
|
||||
*/
|
||||
public function __construct($activity)
|
||||
public function __construct($activity, $actor_profile = null)
|
||||
{
|
||||
$this->activity = $activity;
|
||||
$this->object = $activity['object'];
|
||||
@ -59,7 +59,11 @@ class Activitypub_inbox_handler
|
||||
$this->validate_activity();
|
||||
|
||||
// Get Actor's Profile
|
||||
$this->actor = ActivityPub_explorer::get_profile_from_url($this->activity['actor']);
|
||||
if (!is_null($actor_profile)) {
|
||||
$this->actor = $actor_profile;
|
||||
} else {
|
||||
$this->actor = ActivityPub_explorer::get_profile_from_url($this->activity['actor']);
|
||||
}
|
||||
|
||||
// Handle the Activity
|
||||
$this->process();
|
||||
@ -98,7 +102,7 @@ class Activitypub_inbox_handler
|
||||
case 'Like':
|
||||
case 'Announce':
|
||||
if (!filter_var($this->object, FILTER_VALIDATE_URL)) {
|
||||
throw new Exception("Object is not a valid Object URI for Activity.");
|
||||
throw new Exception('Object is not a valid Object URI for Activity.');
|
||||
}
|
||||
break;
|
||||
case 'Undo':
|
||||
|
@ -20,7 +20,6 @@
|
||||
* @category Plugin
|
||||
* @package GNUsocial
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @author Daniel Supernault <danielsupernault@gmail.com>
|
||||
* @copyright 2018 Free Software Foundation http://fsf.org
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link https://www.gnu.org/software/social/
|
||||
@ -60,27 +59,37 @@ class Activitypub_postman
|
||||
* @param Profile $from Profile of sender
|
||||
* @param Array of Activitypub_profile $to destinataries
|
||||
*/
|
||||
public function __construct($from, $to = [])
|
||||
public function __construct($from, $to)
|
||||
{
|
||||
$this->actor = $from;
|
||||
$discovery = new Activitypub_explorer();
|
||||
$this->to = $to;
|
||||
$followers = apActorFollowersAction::generate_followers($this->actor, 0, null);
|
||||
foreach ($followers as $sub) {
|
||||
try {
|
||||
$to[]= Activitypub_profile::from_profile($discovery->lookup($sub)[0]);
|
||||
} catch (Exception $e) {
|
||||
// Not an ActivityPub Remote Follower, let it go
|
||||
}
|
||||
}
|
||||
unset($discovery);
|
||||
|
||||
$this->actor_uri = ActivityPubPlugin::actor_uri($this->actor);
|
||||
|
||||
$actor_private_key = new Activitypub_rsa();
|
||||
$actor_private_key = $actor_private_key->get_private_key($this->actor);
|
||||
|
||||
$context = new Context([
|
||||
'keys' => [$this->actor_uri."#public-key" => $actor_private_key],
|
||||
'keys' => [$this->actor_uri.'#public-key' => $actor_private_key],
|
||||
'algorithm' => 'rsa-sha256',
|
||||
'headers' => ['(request-target)', 'date', 'content-type', 'accept', 'user-agent'],
|
||||
]);
|
||||
|
||||
$this->to = $to;
|
||||
$this->headers = [
|
||||
'content-type' => 'application/activity+json',
|
||||
'accept' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
|
||||
'user-agent' => 'GNUSocialBot v0.1 - https://gnu.io/social',
|
||||
'date' => date('D, d M Y h:i:s') . ' GMT'
|
||||
'date' => gmdate('D, d M Y H:i:s \G\M\T', time())
|
||||
];
|
||||
|
||||
$handlerStack = GuzzleHttpSignatures::defaultHandlerFromContext($context);
|
||||
@ -228,15 +237,12 @@ class Activitypub_postman
|
||||
* @author Diogo Cordeiro <diogo@fc.up.pt>
|
||||
* @param Notice $notice
|
||||
*/
|
||||
public function create($notice)
|
||||
public function create_note($notice)
|
||||
{
|
||||
$data = Activitypub_create::create_to_array(
|
||||
$this->actor_uri,
|
||||
Activitypub_notice::notice_to_array($notice)
|
||||
);
|
||||
if (isset($notice->reply_to)) {
|
||||
$data["object"]["reply_to"] = $notice->getParent()->getUrl();
|
||||
}
|
||||
$data = json_encode($data, JSON_UNESCAPED_SLASHES);
|
||||
|
||||
foreach ($this->to_inbox() as $inbox) {
|
||||
|
Reference in New Issue
Block a user