]> git.mxchange.org Git - friendica.git/blobdiff - src/Protocol/ActivityPub/Processor.php
Merge pull request #7570 from nupplaphil/bug/friendica-7298
[friendica.git] / src / Protocol / ActivityPub / Processor.php
index 045c48a4c1ced304920444f465f559bd6973d65a..7639d0f2a325d97ee6dc3ea6a9f2fb48a4f0d6b4 100644 (file)
@@ -8,6 +8,7 @@ use Friendica\Database\DBA;
 use Friendica\Content\Text\BBCode;
 use Friendica\Content\Text\HTML;
 use Friendica\Core\Config;
+use Friendica\Core\PConfig;
 use Friendica\Core\Logger;
 use Friendica\Core\Protocol;
 use Friendica\Model\Contact;
@@ -110,7 +111,11 @@ class Processor
                                        continue;
                                }
 
-                               $item['body'] .= "\n[img]" . $attach['url'] . '[/img]';
+                               if (empty($attach['name'])) {
+                                       $item['body'] .= "\n[img]" . $attach['url'] . '[/img]';
+                               } else {
+                                       $item['body'] .= "\n[img=" . $attach['url'] . ']' . $attach['name'] . '[/img]';
+                               }
                        } else {
                                if (!empty($item["attach"])) {
                                        $item["attach"] .= ',';
@@ -142,7 +147,7 @@ class Processor
                }
 
                $item['changed'] = DateTimeFormat::utcNow();
-               $item['edited'] = $activity['updated'];
+               $item['edited'] = DateTimeFormat::utc($activity['updated']);
 
                $item = self::processContent($activity, $item);
                if (empty($item)) {
@@ -198,6 +203,43 @@ class Processor
                Item::delete(['uri' => $activity['object_id'], 'owner-id' => $owner]);
        }
 
+       /**
+        * Prepare the item array for an activity
+        *
+        * @param array $activity Activity array
+        * @throws \Friendica\Network\HTTPException\InternalServerErrorException
+        * @throws \ImagickException
+        */
+       public static function addTag($activity)
+       {
+               if (empty($activity['object_content']) || empty($activity['object_id'])) {
+                       return;
+               }
+
+               foreach ($activity['receiver'] as $receiver) {
+                       $item = Item::selectFirst(['id', 'tag', 'origin', 'author-link'], ['uri' => $activity['target_id'], 'uid' => $receiver]);
+                       if (!DBA::isResult($item)) {
+                               // We don't fetch missing content for this purpose
+                               continue;
+                       }
+
+                       if (($item['author-link'] != $activity['actor']) && !$item['origin']) {
+                               Logger::info('Not origin, not from the author, skipping update', ['id' => $item['id'], 'author' => $item['author-link'], 'actor' => $activity['actor']]);
+                               continue;
+                       }
+
+                       // To-Do:
+                       // - Check if "blocktag" is set
+                       // - Check if actor is a contact
+
+                       if (!stristr($item['tag'], trim($activity['object_content']))) {
+                               $tag = $item['tag'] . (strlen($item['tag']) ? ',' : '') . '#[url=' . $activity['object_id'] . ']'. $activity['object_content'] . '[/url]';
+                               Item::update(['tag' => $tag], ['id' => $item['id']]);
+                               Logger::info('Tagged item', ['id' => $item['id'], 'tag' => $activity['object_content'], 'uri' => $activity['target_id'], 'actor' => $activity['actor']]);
+                       }
+               }
+       }
+
        /**
         * Prepare the item array for an activity
         *
@@ -333,20 +375,28 @@ class Processor
                $item['private'] = !in_array(0, $activity['receiver']);
                $item['author-link'] = $activity['author'];
                $item['author-id'] = Contact::getIdForURL($activity['author'], 0, true);
+               $item['owner-link'] = $activity['actor'];
+               $item['owner-id'] = Contact::getIdForURL($activity['actor'], 0, true);
 
-               if (empty($activity['thread-completion'])) {
-                       $item['owner-link'] = $activity['actor'];
-                       $item['owner-id'] = Contact::getIdForURL($activity['actor'], 0, true);
-               } else {
-                       Logger::info('Ignoring actor because of thread completion.');
+               $isForum = false;
+
+               if (!empty($activity['thread-completion'])) {
+                       // Store the original actor in the "causer" fields to enable the check for ignored or blocked contacts
+                       $item['causer-link'] = $item['owner-link'];
+                       $item['causer-id'] = $item['owner-id'];
+
+                       Logger::info('Ignoring actor because of thread completion.', ['actor' => $item['owner-link']]);
                        $item['owner-link'] = $item['author-link'];
                        $item['owner-id'] = $item['author-id'];
+               } else {
+                       $actor = APContact::getByURL($item['owner-link'], false);
+                       $isForum = ($actor['type'] == 'Group');
                }
 
                $item['uri'] = $activity['id'];
 
-               $item['created'] = $activity['published'];
-               $item['edited'] = $activity['updated'];
+               $item['created'] = DateTimeFormat::utc($activity['published']);
+               $item['edited'] = DateTimeFormat::utc($activity['updated']);
                $item['guid'] = $activity['diaspora:guid'];
 
                $item = self::processContent($activity, $item);
@@ -362,7 +412,12 @@ class Processor
 
                foreach ($activity['receiver'] as $receiver) {
                        $item['uid'] = $receiver;
-                       $item['contact-id'] = Contact::getIdForURL($activity['author'], $receiver, true);
+
+                       if ($isForum) {
+                               $item['contact-id'] = Contact::getIdForURL($activity['actor'], $receiver, true);
+                       } else {
+                               $item['contact-id'] = Contact::getIdForURL($activity['author'], $receiver, true);
+                       }
 
                        if (($receiver != 0) && empty($item['contact-id'])) {
                                $item['contact-id'] = Contact::getIdForURL($activity['author'], 0, true);
@@ -373,6 +428,21 @@ class Processor
                                continue;
                        }
 
+                       if (PConfig::get($receiver, 'system', 'accept_only_sharer', false) && ($receiver != 0) && ($item['gravity'] == GRAVITY_PARENT)) {
+                               $skip = !Contact::isSharingByURL($activity['author'], $receiver);
+
+                               if ($skip && (($activity['type'] == 'as:Announce') || $isForum)) {
+                                       $skip = !Contact::isSharingByURL($activity['actor'], $receiver);
+                               }
+
+                               if ($skip) {
+                                       Logger::info('Skipping post', ['uid' => $receiver, 'url' => $item['uri']]);
+                                       continue;
+                               }
+
+                               Logger::info('Accepting post', ['uid' => $receiver, 'url' => $item['uri']]);
+                       }
+
                        if ($activity['object_type'] == 'as:Event') {
                                self::createEvent($activity, $item);
                        }
@@ -405,8 +475,8 @@ class Processor
         *
         * @param array $activity Activity data
         * @param array $item     item array
+        * @return int|bool New mail table row id or false on error
         * @throws \Friendica\Network\HTTPException\InternalServerErrorException
-        * @throws \ImagickException
         */
        private static function postMail($activity, $item)
        {
@@ -460,33 +530,53 @@ class Processor
                }
                $msg['body'] = $item['body'];
 
-                Mail::insert($msg);
+               return Mail::insert($msg);
        }
 
        /**
         * Fetches missing posts
         *
-        * @param $url
-        * @param $child
+        * @param string $url message URL
+        * @param array $child activity array with the child of this message
+        * @return boolean success
         * @throws \Friendica\Network\HTTPException\InternalServerErrorException
         */
-       private static function fetchMissingActivity($url, $child)
+       public static function fetchMissingActivity($url, $child = [])
        {
-               if (Config::get('system', 'ostatus_full_threads')) {
-                       return;
+               if (!empty($child['receiver'])) {
+                       $uid = ActivityPub\Receiver::getFirstUserFromReceivers($child['receiver']);
+               } else {
+                       $uid = 0;
                }
 
-               $uid = ActivityPub\Receiver::getFirstUserFromReceivers($child['receiver']);
-
                $object = ActivityPub::fetchContent($url, $uid);
                if (empty($object)) {
                        Logger::log('Activity ' . $url . ' was not fetchable, aborting.');
-                       return;
+                       return false;
                }
 
                if (empty($object['id'])) {
                        Logger::log('Activity ' . $url . ' has got not id, aborting. ' . json_encode($object));
-                       return;
+                       return false;
+               }
+
+               if (!empty($child['author'])) {
+                       $actor = $child['author'];
+               } elseif (!empty($object['actor'])) {
+                       $actor = $object['actor'];
+               } elseif (!empty($object['attributedTo'])) {
+                       $actor = $object['attributedTo'];
+               } else {
+                       // Shouldn't happen
+                       $actor = '';
+               }
+
+               if (!empty($object['published'])) {
+                       $published = $object['published'];
+               } elseif (!empty($child['published'])) {
+                       $published = $child['published'];
+               } else {
+                       $published = DateTimeFormat::utcNow();
                }
 
                $activity = [];
@@ -495,9 +585,9 @@ class Processor
                $activity['id'] = $object['id'];
                $activity['to'] = defaults($object, 'to', []);
                $activity['cc'] = defaults($object, 'cc', []);
-               $activity['actor'] = $child['author'];
+               $activity['actor'] = $actor;
                $activity['object'] = $object;
-               $activity['published'] = defaults($object, 'published', $child['published']);
+               $activity['published'] = $published;
                $activity['type'] = 'Create';
 
                $ldactivity = JsonLD::compact($activity);
@@ -506,6 +596,8 @@ class Processor
 
                ActivityPub\Receiver::processActivity($ldactivity);
                Logger::log('Activity ' . $url . ' had been fetched and processed.');
+
+               return true;
        }
 
        /**
@@ -530,7 +622,7 @@ class Processor
                        DBA::update('contact', ['hub-verify' => $activity['id'], 'protocol' => Protocol::ACTIVITYPUB], ['id' => $cid]);
                        $contact = DBA::selectFirst('contact', [], ['id' => $cid, 'network' => Protocol::NATIVE_SUPPORT]);
                } else {
-                       $contact = false;
+                       $contact = [];
                }
 
                $item = ['author-id' => Contact::getIdForURL($activity['actor']),
@@ -541,7 +633,11 @@ class Processor
                // Ensure that the contact has got the right network type
                self::switchContact($item['author-id']);
 
-               Contact::addRelationship($owner, $contact, $item, '', false, $note);
+               $result = Contact::addRelationship($owner, $contact, $item, false, $note);
+               if ($result === true) {
+                       ActivityPub\Transmitter::sendContactAccept($item['author-link'], $item['author-id'], $owner['uid']);
+               }
+
                $cid = Contact::getIdForURL($activity['actor'], $uid);
                if (empty($cid)) {
                        return;
@@ -567,7 +663,7 @@ class Processor
                }
 
                Logger::log('Updating profile for ' . $activity['object_id'], Logger::DEBUG);
-               APContact::getByURL($activity['object_id'], true);
+               Contact::updateFromProbeByURL($activity['object_id'], true);
        }
 
        /**