X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FProtocol%2FActivityPub%2FProcessor.php;h=c38cba28f187419258727c62693323538b5edc03;hb=f78c1480135b9445d94a815fbfcc138f1a4dea58;hp=6d94b1b49ee7166503f3b4baa19131f23fe65b65;hpb=b2c29715519b1712abce6acb592caedbc8ac8710;p=friendica.git diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php index 6d94b1b49e..c38cba28f1 100644 --- a/src/Protocol/ActivityPub/Processor.php +++ b/src/Protocol/ActivityPub/Processor.php @@ -65,7 +65,7 @@ class Processor * @param array $implicit_mentions List of profile URLs to skip * @return string with tags */ - private static function constructTagString($tags, $sensitive, array $implicit_mentions) + private static function constructTagString(array $tags, $sensitive) { if (empty($tags)) { return ''; @@ -73,7 +73,7 @@ class Processor $tag_text = ''; foreach ($tags as $tag) { - if (in_array(defaults($tag, 'type', ''), ['Mention', 'Hashtag']) && !in_array($tag['href'], $implicit_mentions)) { + if (in_array(defaults($tag, 'type', ''), ['Mention', 'Hashtag'])) { if (!empty($tag_text)) { $tag_text .= ','; } @@ -129,7 +129,7 @@ class Processor */ public static function updateItem($activity) { - $item = Item::selectFirst(['uri', 'parent-uri', 'gravity'], ['uri' => $activity['id']]); + $item = Item::selectFirst(['uri', 'thr-parent', 'gravity'], ['uri' => $activity['id']]); if (!DBA::isResult($item)) { Logger::warning('Unknown item', ['uri' => $activity['id']]); return; @@ -137,28 +137,12 @@ class Processor $item['changed'] = DateTimeFormat::utcNow(); $item['edited'] = $activity['updated']; - $item['title'] = HTML::toBBCode($activity['name']); - $item['content-warning'] = HTML::toBBCode($activity['summary']); - - $content = HTML::toBBCode($activity['content']); - $content = self::replaceEmojis($content, $activity['emojis']); - $content = self::convertMentions($content); - - $implicit_mentions = []; - if (($item['parent-uri'] != $item['uri']) && ($item['gravity'] == GRAVITY_COMMENT)) { - $parent = Item::selectFirst(['id', 'author-link', 'alias'], ['uri' => $item['parent-uri']]); - if (!DBA::isResult($parent)) { - Logger::warning('Unknown parent item.', ['uri' => $item['parent-uri']]); - return; - } - $implicit_mentions = self::getImplicitMentionList($parent); - $content = self::removeImplicitMentionsFromBody($content, $implicit_mentions); + $item = self::processContent($activity, $item); + if (empty($item)) { + return; } - $item['body'] = $content; - $item['tag'] = self::constructTagString($activity['tags'], $activity['sensitive'], $implicit_mentions); - Item::update($item, ['uri' => $activity['id']]); } @@ -173,7 +157,7 @@ class Processor { $item = []; $item['verb'] = ACTIVITY_POST; - $item['parent-uri'] = $activity['reply-to-id']; + $item['thr-parent'] = $activity['reply-to-id']; if ($activity['reply-to-id'] == $activity['id']) { $item['gravity'] = GRAVITY_PARENT; @@ -220,7 +204,7 @@ class Processor { $item = []; $item['verb'] = $verb; - $item['parent-uri'] = $activity['object_id']; + $item['thr-parent'] = $activity['object_id']; $item['gravity'] = GRAVITY_ACTIVITY; $item['object-type'] = ACTIVITY_OBJ_NOTE; @@ -263,6 +247,62 @@ class Processor Logger::log('Event '.$event_id.' was stored', Logger::DEBUG); } + /** + * Process the content + * + * @param array $activity Activity array + * @param array $item + * @return array|bool Returns the item array or false if there was an unexpected occurrence + * @throws \Exception + */ + private static function processContent($activity, $item) + { + $item['title'] = HTML::toBBCode($activity['name']); + + if (!empty($activity['source'])) { + $item['body'] = $activity['source']; + } else { + $content = HTML::toBBCode($activity['content']); + $content = self::replaceEmojis($content, $activity['emojis']); + $content = self::convertMentions($content); + + if (($item['thr-parent'] != $item['uri']) && ($item['gravity'] == GRAVITY_COMMENT)) { + $item_private = !in_array(0, $activity['item_receiver']); + $parent = Item::selectFirst(['id', 'private', 'author-link', 'alias'], ['uri' => $item['thr-parent']]); + if (!DBA::isResult($parent)) { + Logger::warning('Unknown parent item.', ['uri' => $item['thr-parent']]); + return false; + } + if ($item_private && !$parent['private']) { + Logger::warning('Item is private but the parent is not. Dropping.', ['item-uri' => $item['uri'], 'thr-parent' => $item['thr-parent']]); + return false; + } + + $potential_implicit_mentions = self::getImplicitMentionList($parent); + $content = self::removeImplicitMentionsFromBody($content, $potential_implicit_mentions); + $activity['tags'] = self::convertImplicitMentionsInTags($activity['tags'], $potential_implicit_mentions); + } + $item['content-warning'] = HTML::toBBCode($activity['summary']); + $item['body'] = $content; + + if (($activity['object_type'] == 'as:Video') && !empty($activity['alternate-url'])) { + $item['body'] .= "\n[video]" . $activity['alternate-url'] . '[/video]'; + } + } + + $item['tag'] = self::constructTagString($activity['tags'], $activity['sensitive']); + + $item['location'] = $activity['location']; + + if (!empty($item['latitude']) && !empty($item['longitude'])) { + $item['coord'] = $item['latitude'] . ' ' . $item['longitude']; + } + + $item['app'] = $activity['generator']; + + return $item; + } + /** * Creates an item post * @@ -275,8 +315,8 @@ class Processor { /// @todo What to do with $activity['context']? - if (($item['gravity'] != GRAVITY_PARENT) && !Item::exists(['uri' => $item['parent-uri']])) { - Logger::log('Parent ' . $item['parent-uri'] . ' not found, message will be discarded.', Logger::DEBUG); + if (($item['gravity'] != GRAVITY_PARENT) && !Item::exists(['uri' => $item['thr-parent']])) { + Logger::info('Parent not found, message will be discarded.', ['thr-parent' => $item['thr-parent']]); return; } @@ -289,59 +329,27 @@ class Processor $item['owner-link'] = $activity['actor']; $item['owner-id'] = Contact::getIdForURL($activity['actor'], 0, true); } else { - Logger::log('Ignoring actor because of thread completion.', Logger::DEBUG); + Logger::info('Ignoring actor because of thread completion.'); $item['owner-link'] = $item['author-link']; $item['owner-id'] = $item['author-id']; } $item['uri'] = $activity['id']; - $content = HTML::toBBCode($activity['content']); - $content = self::replaceEmojis($content, $activity['emojis']); - $content = self::convertMentions($content); - - $implicit_mentions = []; - - if (($item['parent-uri'] != $item['uri']) && ($item['gravity'] == GRAVITY_COMMENT)) { - $item_private = !in_array(0, $activity['item_receiver']); - $parent = Item::selectFirst(['id', 'private', 'author-link', 'alias'], ['uri' => $item['parent-uri']]); - if (!DBA::isResult($parent)) { - return; - } - if ($item_private && !$parent['private']) { - Logger::log('Item ' . $item['uri'] . ' is private but the parent ' . $item['parent-uri'] . ' is not. So we drop it.'); - return; - } - - $implicit_mentions = self::getImplicitMentionList($parent); - $content = self::removeImplicitMentionsFromBody($content, $implicit_mentions); - } $item['created'] = $activity['published']; $item['edited'] = $activity['updated']; $item['guid'] = $activity['diaspora:guid']; - $item['title'] = HTML::toBBCode($activity['name']); - $item['content-warning'] = HTML::toBBCode($activity['summary']); - $item['body'] = $content; - - if (($activity['object_type'] == 'as:Video') && !empty($activity['alternate-url'])) { - $item['body'] .= "\n[video]" . $activity['alternate-url'] . '[/video]'; - } - $item['location'] = $activity['location']; - - if (!empty($item['latitude']) && !empty($item['longitude'])) { - $item['coord'] = $item['latitude'] . ' ' . $item['longitude']; + $item = self::processContent($activity, $item); + if (empty($item)) { + return; } - $item['tag'] = self::constructTagString($activity['tags'], $activity['sensitive'], $implicit_mentions); - $item['app'] = $activity['generator']; $item['plink'] = defaults($activity, 'alternate-url', $item['uri']); $item = self::constructAttachList($activity['attachments'], $item); - if (!empty($activity['source'])) { - $item['body'] = $activity['source']; - } + $stored = false; foreach ($activity['receiver'] as $receiver) { $item['uid'] = $receiver; @@ -356,14 +364,23 @@ class Processor } $item_id = Item::insert($item); - Logger::log('Storing for user ' . $item['uid'] . ': ' . $item_id); + if ($item_id) { + Logger::info('Item insertion successful', ['user' => $item['uid'], 'item_id' => $item_id]); + } else { + Logger::notice('Item insertion aborted', ['user' => $item['uid']]); + } + + if ($item['uid'] == 0) { + $stored = $item_id; + } } - if (!$item['private'] && ($item['gravity'] == GRAVITY_PARENT) && ($item['author-link'] != $item['owner-link'])) { + // Store send a follow request for every reshare - but only when the item had been stored + if ($stored && !$item['private'] && ($item['gravity'] == GRAVITY_PARENT) && ($item['author-link'] != $item['owner-link'])) { $author = APContact::getByURL($item['owner-link'], false); // We send automatic follow requests for reshared messages. (We don't need though for forum posts) if ($author['type'] != 'Group') { - Logger::log('Send follow request for ' . $item['uri'] . ' to ' . $item['author-link'], Logger::DEBUG); + Logger::log('Send follow request for ' . $item['uri'] . ' (' . $stored . ') to ' . $item['author-link'], Logger::DEBUG); ActivityPub\Transmitter::sendFollowObject($item['uri'], $item['author-link']); } } @@ -651,22 +668,34 @@ class Processor */ private static function getImplicitMentionList(array $parent) { - $parent_terms = Term::tagArrayFromItemId($parent['id'], [TERM_MENTION]); + if (Config::get('system', 'disable_implicit_mentions')) { + return []; + } + + $parent_terms = Term::tagArrayFromItemId($parent['id'], [Term::MENTION, Term::IMPLICIT_MENTION]); - $implicit_mentions = [ - $parent['author-link'] - ]; + $parent_author = Contact::getDetailsByURL($parent['author-link'], 0); - if ($parent['alias']) { + $implicit_mentions = []; + if (empty($parent_author)) { + Logger::notice('Author public contact unknown.', ['author-link' => $parent['author-link'], 'item-id' => $parent['id']]); + } else { + $implicit_mentions[] = $parent_author['url']; + $implicit_mentions[] = $parent_author['nurl']; + $implicit_mentions[] = $parent_author['alias']; + } + + if (!empty($parent['alias'])) { $implicit_mentions[] = $parent['alias']; } foreach ($parent_terms as $term) { - $contact = Contact::getDetailsByURL($term['url']); - - $implicit_mentions[] = $contact['url']; - $implicit_mentions[] = $contact['nurl']; - $implicit_mentions[] = $contact['alias']; + $contact = Contact::getDetailsByURL($term['url'], 0); + if (!empty($contact)) { + $implicit_mentions[] = $contact['url']; + $implicit_mentions[] = $contact['nurl']; + $implicit_mentions[] = $contact['alias']; + } } return $implicit_mentions; @@ -676,16 +705,20 @@ class Processor * Strips from the body prepended implicit mentions * * @param string $body - * @param array $implicit_mentions List of profile URLs + * @param array $potential_mentions * @return string */ - private static function removeImplicitMentionsFromBody($body, array $implicit_mentions) + private static function removeImplicitMentionsFromBody($body, array $potential_mentions) { + if (Config::get('system', 'disable_implicit_mentions')) { + return $body; + } + $kept_mentions = []; // Extract one prepended mention at a time from the body - while(preg_match('#^(@\[url=([^\]]+)].*?\[\/url]\s)(.*)#mi', $body, $matches)) { - if (!in_array($matches[2], $implicit_mentions) ) { + while(preg_match('#^(@\[url=([^\]]+)].*?\[\/url]\s)(.*)#is', $body, $matches)) { + if (!in_array($matches[2], $potential_mentions) ) { $kept_mentions[] = $matches[1]; } @@ -697,4 +730,24 @@ class Processor return implode('', $kept_mentions); } + + private static function convertImplicitMentionsInTags($activity_tags, array $potential_mentions) + { + if (Config::get('system', 'disable_implicit_mentions')) { + return $activity_tags; + } + + foreach ($activity_tags as $index => $tag) { + if (in_array($tag['href'], $potential_mentions)) { + $activity_tags[$index]['name'] = preg_replace( + '/' . preg_quote(Term::TAG_CHARACTER[Term::MENTION], '/') . '/', + Term::TAG_CHARACTER[Term::IMPLICIT_MENTION], + $activity_tags[$index]['name'], + 1 + ); + } + } + + return $activity_tags; + } }