]> git.mxchange.org Git - friendica.git/commitdiff
New delivery module for ap
authorMichael <heluecht@pirati.ca>
Mon, 17 Sep 2018 21:13:08 +0000 (21:13 +0000)
committerMichael <heluecht@pirati.ca>
Mon, 17 Sep 2018 21:13:08 +0000 (21:13 +0000)
mod/display.php
src/Model/Item.php
src/Model/Term.php
src/Protocol/ActivityPub.php
src/Worker/APDelivery.php [new file with mode: 0644]
src/Worker/Delivery.php
src/Worker/Notifier.php

index 047f752c9859e1aa0fd8e0b5d687d1d4bb6e6221..1b4508c18d96982251d01e9f4c939edcc3052bbe 100644 (file)
@@ -80,7 +80,7 @@ function display_init(App $a)
        if (ActivityPub::isRequest()) {
                $wall_item = Item::selectFirst(['id', 'uid'], ['guid' => $item['guid'], 'wall' => true]);
                if ($wall_item['uid'] == 180) {
-                       $data = ActivityPub::createActivityFromItem($wall_item['id']);
+                       $data = ActivityPub::createObjectFromItemID($wall_item['id']);
                        echo json_encode($data);
                        exit();
                }
index b9cc6c2b9a33c57a053146f27f2e72efbee23886..e590c0c5c56ed3aaefd2b2412da7e42127a2ee68 100644 (file)
@@ -2851,7 +2851,7 @@ class Item extends BaseObject
        }
 
        // returns an array of contact-ids that are allowed to see this object
-       private static function enumeratePermissions($obj)
+       public static function enumeratePermissions($obj)
        {
                $allow_people = expand_acl($obj['allow_cid']);
                $allow_groups = Group::expand(expand_acl($obj['allow_gid']));
index a81241cb42af31298fe95bea2d64753d3d04c79f..262312532995c1b1b2753fc0c5dcc311e7ef0a20 100644 (file)
@@ -33,6 +33,17 @@ class Term
                return $tag_text;
        }
 
+       public static function tagArrayFromItemId($itemid)
+       {
+               $condition = ['otype' => TERM_OBJ_POST, 'oid' => $itemid, 'type' => [TERM_HASHTAG, TERM_MENTION]];
+               $tags = DBA::select('term', ['type', 'term', 'url'], $condition);
+               if (!DBA::isResult($tags)) {
+                       return [];
+               }
+
+               return DBA::toArray($tags);
+       }
+
        public static function fileTextFromItemId($itemid)
        {
                $file_text = '';
index 9fb22b2bd9e18a3c4af93ec0b435a4cfbd6bc46c..c148e26c691b7a0f1ca184724231a4dee13346e2 100644 (file)
@@ -13,6 +13,7 @@ use Friendica\Core\Protocol;
 use Friendica\Model\Conversation;
 use Friendica\Model\Contact;
 use Friendica\Model\Item;
+use Friendica\Model\Term;
 use Friendica\Model\User;
 use Friendica\Util\DateTimeFormat;
 use Friendica\Util\Crypto;
@@ -153,6 +154,111 @@ class ActivityPub
                return $data;
        }
 
+       public static function createPermissionBlockForItem($item)
+       {
+               $data = ['to' => [], 'cc' => []];
+
+               $terms = Term::tagArrayFromItemId($item['id']);
+
+               if (!$item['private']) {
+                       $data['to'][] = self::PUBLIC;
+                       $data['cc'][] = System::baseUrl() . '/followers/' . $item['author-nick'];
+
+                       foreach ($terms as $term) {
+                               if ($term['type'] != TERM_MENTION) {
+                                       continue;
+                               }
+                               $profile = Probe::uri($term['url'], Protocol::ACTIVITYPUB);
+                               if ($profile['network'] == Protocol::ACTIVITYPUB) {
+                                       $data['cc'][] = $profile['url'];
+                               }
+                       }
+               } else {
+                       $receiver_list = Item::enumeratePermissions($item);
+
+                       $mentioned = [];
+
+                       foreach ($terms as $term) {
+                               if ($term['type'] != TERM_MENTION) {
+                                       continue;
+                               }
+                               $cid = Contact::getIdForURL($term['url'], $item['uid']);
+                               if (!empty($cid) && in_array($cid, $receiver_list)) {
+                                       $contact = DBA::selectFirst('contact', ['url'], ['id' => $cid, 'network' => Protocol::ACTIVITYPUB]);
+                                       $data['to'][] = $contact['url'];
+                               }
+                       }
+
+                       foreach ($receiver_list as $receiver) {
+                               $contact = DBA::selectFirst('contact', ['url'], ['id' => $receiver, 'network' => Protocol::ACTIVITYPUB]);
+                               $data['cc'][] = $contact['url'];
+                       }
+
+                       if (empty($data['to'])) {
+                               $data['to'] = $data['cc'];
+                               unset($data['cc']);
+                       }
+               }
+
+               return $data;
+       }
+
+       public static function fetchTargetInboxes($item)
+       {
+               $inboxes = [];
+
+               $terms = Term::tagArrayFromItemId($item['id']);
+               if (!$item['private']) {
+                       $contacts = DBA::select('contact', ['notify', 'batch'], ['uid' => $item['uid'], 'network' => Protocol::ACTIVITYPUB]);
+                       while ($contact = DBA::fetch($contacts)) {
+                               $contact = defaults($contact, 'batch', $contact['notify']);
+                               $inboxes[$contact] = $contact;
+                       }
+                       DBA::close($contacts);
+
+                       foreach ($terms as $term) {
+                               if ($term['type'] != TERM_MENTION) {
+                                       continue;
+                               }
+                               $profile = Probe::uri($term['url'], Protocol::ACTIVITYPUB);
+                               if ($profile['network'] == Protocol::ACTIVITYPUB) {
+                                       $target = defaults($profile, 'batch', $profile['notify']);
+                                       $inboxes[$target] = $target;
+                               }
+                       }
+               } else {
+                       $receiver_list = Item::enumeratePermissions($item);
+
+                       $mentioned = [];
+
+                       foreach ($terms as $term) {
+                               if ($term['type'] != TERM_MENTION) {
+                                       continue;
+                               }
+                               $cid = Contact::getIdForURL($term['url'], $item['uid']);
+                               if (!empty($cid) && in_array($cid, $receiver_list)) {
+                                       $contact = DBA::selectFirst('contact', ['url'], ['id' => $cid, 'network' => Protocol::ACTIVITYPUB]);
+                                       $profile = Probe::uri($contact['url'], Protocol::ACTIVITYPUB);
+                                       if ($profile['network'] == Protocol::ACTIVITYPUB) {
+                                               $target = defaults($profile, 'batch', $profile['notify']);
+                                               $inboxes[$target] = $target;
+                                       }
+                               }
+                       }
+
+                       foreach ($receiver_list as $receiver) {
+                               $contact = DBA::selectFirst('contact', ['url'], ['id' => $receiver, 'network' => Protocol::ACTIVITYPUB]);
+                               $profile = Probe::uri($contact['url'], Protocol::ACTIVITYPUB);
+                               if ($profile['network'] == Protocol::ACTIVITYPUB) {
+                                       $target = defaults($profile, 'batch', $profile['notify']);
+                                       $inboxes[$target] = $target;
+                               }
+                       }
+               }
+
+               return $inboxes;
+       }
+
        public static function createActivityFromItem($item_id)
        {
                $item = Item::selectFirst([], ['id' => $item_id]);
@@ -177,13 +283,34 @@ class ActivityPub
                        'toot' => 'http://joinmastodon.org/ns#']]];
 
                $data['type'] = 'Create';
-               $data['id'] = $item['uri'] . '/activity';
+               $data['id'] = $item['uri'] . '#activity';
                $data['actor'] = $item['author-link'];
-               $data['to'] = 'https://www.w3.org/ns/activitystreams#Public';
+               $data = array_merge($data, ActivityPub::createPermissionBlockForItem($item));
+
                $data['object'] = self::createNote($item);
                return $data;
        }
 
+       public static function createObjectFromItemID($item_id)
+       {
+               $item = Item::selectFirst([], ['id' => $item_id]);
+
+               if (!DBA::isResult($item)) {
+                       return false;
+               }
+
+               $data = ['@context' => ['https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1',
+                       ['Emoji' => 'toot:Emoji', 'Hashtag' => 'as:Hashtag', 'atomUri' => 'ostatus:atomUri',
+                       'conversation' => 'ostatus:conversation', 'inReplyToAtomUri' => 'ostatus:inReplyToAtomUri',
+                       'ostatus' => 'http://ostatus.org#', 'sensitive' => 'as:sensitive',
+                       'toot' => 'http://joinmastodon.org/ns#']]];
+
+               $data = array_merge($data, self::createNote($item));
+
+
+               return $data;
+       }
+
        public static function createNote($item)
        {
                $data = [];
@@ -203,9 +330,7 @@ class ActivityPub
 
                $data['context'] = $data['conversation'] = $conversation_uri;
                $data['actor'] = $item['author-link'];
-               if (!$item['private']) {
-                       $data['to'] = 'https://www.w3.org/ns/activitystreams#Public';
-               }
+               $data = array_merge($data, ActivityPub::createPermissionBlockForItem($item));
                $data['published'] = DateTimeFormat::utc($item["created"]."+00:00", DateTimeFormat::ATOM);
                $data['updated'] = DateTimeFormat::utc($item["edited"]."+00:00", DateTimeFormat::ATOM);
                $data['attributedTo'] = $item['author-link'];
diff --git a/src/Worker/APDelivery.php b/src/Worker/APDelivery.php
new file mode 100644 (file)
index 0000000..b7e881c
--- /dev/null
@@ -0,0 +1,28 @@
+<?php
+/**
+ * @file src/Worker/APDelivery.php
+ */
+namespace Friendica\Worker;
+
+use Friendica\BaseObject;
+use Friendica\Protocol\ActivityPub;
+use Friendica\Model\Item;
+
+class APDelivery extends BaseObject
+{
+       public static function execute($cmd, $item_id, $inbox)
+       {
+               logger('Invoked: ' . $cmd . ': ' . $item_id . ' to ' . $inbox, LOGGER_DEBUG);
+
+               if ($cmd == Delivery::MAIL) {
+               } elseif ($cmd == Delivery::SUGGESTION) {
+               } elseif ($cmd == Delivery::RELOCATION) {
+               } else {
+                       $item = Item::selectFirst(['uid'], ['id' => $item_id]);
+                       $data = ActivityPub::createActivityFromItem($item_id);
+                       ActivityPub::transmit($data, $inbox, $item['uid']);
+               }
+
+               return;
+       }
+}
index 8ee00af63031d02df0bae4aa2f062d77cf4532fc..e0a5c09c270d48ec72a8379d880a44c6d82c8fcf 100644 (file)
@@ -15,7 +15,6 @@ use Friendica\Model\Item;
 use Friendica\Model\Queue;
 use Friendica\Model\User;
 use Friendica\Protocol\DFRN;
-use Friendica\Protocol\ActivityPub;
 use Friendica\Protocol\Diaspora;
 use Friendica\Protocol\Email;
 
@@ -166,10 +165,6 @@ class Delivery extends BaseObject
 
                switch ($contact['network']) {
 
-                       case Protocol::ACTIVITYPUB:
-                               self::deliverActivityPub($cmd, $contact, $owner, $items, $target_item, $public_message, $top_level, $followup);
-                               break;
-
                        case Protocol::DFRN:
                                self::deliverDFRN($cmd, $contact, $owner, $items, $target_item, $public_message, $top_level, $followup);
                                break;
@@ -388,80 +383,6 @@ class Delivery extends BaseObject
                logger('Unknown mode ' . $cmd . ' for ' . $loc);
        }
 
-       /**
-        * @brief Deliver content via ActivityPub
-q       *
-        * @param string  $cmd            Command
-        * @param array   $contact        Contact record of the receiver
-        * @param array   $owner          Owner record of the sender
-        * @param array   $items          Item record of the content and the parent
-        * @param array   $target_item    Item record of the content
-        * @param boolean $public_message Is the content public?
-        * @param boolean $top_level      Is it a thread starter?
-        * @param boolean $followup       Is it an answer to a remote post?
-        */
-       private static function deliverActivityPub($cmd, $contact, $owner, $items, $target_item, $public_message, $top_level, $followup)
-       {
-               // We don't treat Forum posts as "wall-to-wall" to be able to post them via ActivityPub
-               $walltowall = $top_level && ($owner['id'] != $items[0]['contact-id']) & ($owner['account-type'] != Contact::ACCOUNT_TYPE_COMMUNITY);
-
-               if ($public_message) {
-                       $loc = 'public batch ' . $contact['batch'];
-               } else {
-                       $loc = $contact['addr'];
-               }
-
-               logger('Deliver ' . $target_item["guid"] . ' via ActivityPub to ' . $loc);
-
-//             if (Config::get('system', 'dfrn_only') || !Config::get('system', 'diaspora_enabled')) {
-//                     return;
-//             }
-               if ($cmd == self::MAIL) {
-//                     ActivityPub::sendMail($target_item, $owner, $contact);
-                       return;
-               }
-
-               if ($cmd == self::SUGGESTION) {
-                       return;
-               }
-//             if (!$contact['pubkey'] && !$public_message) {
-//                     logger('No public key, no delivery.');
-//                     return;
-//             }
-               if (($target_item['deleted']) && (($target_item['uri'] === $target_item['parent-uri']) || $followup)) {
-                       // top-level retraction
-                       logger('ActivityPub retract: ' . $loc);
-//                     ActivityPub::sendRetraction($target_item, $owner, $contact, $public_message);
-                       return;
-               } elseif ($cmd == self::RELOCATION) {
-//                     ActivityPub::sendAccountMigration($owner, $contact, $owner['uid']);
-                       return;
-               } elseif ($followup) {
-                       // send comments and likes to owner to relay
-                       logger('ActivityPub followup: ' . $loc);
-                       $data = ActivityPub::createActivityFromItem($target_item['id']);
-                       ActivityPub::transmit($data, $contact['notify'], $owner['uid']);
-//                     ActivityPub::sendFollowup($target_item, $owner, $contact, $public_message);
-                       return;
-               } elseif ($target_item['uri'] !== $target_item['parent-uri']) {
-                       // we are the relay - send comments, likes and relayable_retractions to our conversants
-                       logger('ActivityPub relay: ' . $loc);
-                       $data = ActivityPub::createActivityFromItem($target_item['id']);
-                       ActivityPub::transmit($data, $contact['notify'], $owner['uid']);
-//                     ActivityPub::sendRelay($target_item, $owner, $contact, $public_message);
-                       return;
-               } elseif ($top_level && !$walltowall) {
-                       // currently no workable solution for sending walltowall
-                       logger('ActivityPub status: ' . $loc);
-                       $data = ActivityPub::createActivityFromItem($target_item['id']);
-                       ActivityPub::transmit($data, $contact['notify'], $owner['uid']);
-//                     ActivityPub::sendStatus($target_item, $owner, $contact, $public_message);
-                       return;
-               }
-
-               logger('Unknown mode ' . $cmd . ' for ' . $loc);
-       }
-
        /**
         * @brief Deliver content via mail
         *
index 6a371861866890736932494b68736f506b001b46..693a9e343d55f7ff5a34f9fbe4e0b8c158614ebd 100644 (file)
@@ -16,6 +16,7 @@ use Friendica\Model\Item;
 use Friendica\Model\PushSubscriber;
 use Friendica\Model\User;
 use Friendica\Network\Probe;
+use Friendica\Protocol\ActivityPub;
 use Friendica\Protocol\Diaspora;
 use Friendica\Protocol\OStatus;
 use Friendica\Protocol\Salmon;
@@ -363,9 +364,9 @@ class Notifier
                                }
 
                                // It only makes sense to distribute answers to OStatus messages to Friendica and OStatus - but not Diaspora
-                               $networks = [Protocol::ACTIVITYPUB, Protocol::OSTATUS, Protocol::DFRN];
+                               $networks = [Protocol::OSTATUS, Protocol::DFRN];
                        } else {
-                               $networks = [Protocol::ACTIVITYPUB, Protocol::OSTATUS, Protocol::DFRN, Protocol::DIASPORA, Protocol::MAIL];
+                               $networks = [Protocol::OSTATUS, Protocol::DFRN, Protocol::DIASPORA, Protocol::MAIL];
                        }
                } else {
                        $public_message = false;
@@ -413,6 +414,14 @@ class Notifier
                        }
                }
 
+               $inboxes = ActivityPub::fetchTargetInboxes($target_item);
+               foreach ($inboxes as $inbox) {
+                       logger('Deliver ' . $item_id .' to ' . $inbox .' via ActivityPub', LOGGER_DEBUG);
+
+                       Worker::add(['priority' => $a->queue['priority'], 'created' => $a->queue['created'], 'dont_fork' => true],
+                                       'APDelivery', $cmd, $item_id, $inbox);
+               }
+
                // send salmon slaps to mentioned remote tags (@foo@example.com) in OStatus posts
                // They are especially used for notifications to OStatus users that don't follow us.
                if (!Config::get('system', 'dfrn_only') && count($url_recipients) && ($public_message || $push_notify) && $normal_mode) {
@@ -448,7 +457,7 @@ class Notifier
                                }
                        }
 
-                       $condition = ['network' => [Protocol::DFRN, Protocol::ACTIVITYPUB], 'uid' => $owner['uid'], 'blocked' => false,
+                       $condition = ['network' => Protocol::DFRN, 'uid' => $owner['uid'], 'blocked' => false,
                                'pending' => false, 'archive' => false, 'rel' => [Contact::FOLLOWER, Contact::FRIEND]];
 
                        $r2 = DBA::toArray(DBA::select('contact', ['id', 'name', 'network'], $condition));