X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FProtocol%2FActivityPub%2FProcessor.php;h=b7ddc09f61b0856e5e5b760c39a81ff715a790d5;hb=7dadc7f6dc0b1e68bfa5937b3a3fa3fd9cdcacd1;hp=ecbecb9551b5b8f5ad1ece9cb95f0caa6b5ba1ad;hpb=09cf32926d50c1142e2c0e95dd417d518587d38c;p=friendica.git diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php index ecbecb9551..b7ddc09f61 100644 --- a/src/Protocol/ActivityPub/Processor.php +++ b/src/Protocol/ActivityPub/Processor.php @@ -1,6 +1,6 @@ $uriid]; $data['type'] = Post\Media::UNKNOWN; $data['url'] = $attachment['url']; - $data['mimetype'] = $attachment['mediaType']; + $data['mimetype'] = $attachment['mediaType'] ?? null; $data['height'] = $attachment['height'] ?? null; + $data['width'] = $attachment['width'] ?? null; $data['size'] = $attachment['size'] ?? null; $data['preview'] = $attachment['image'] ?? null; $data['description'] = $attachment['name'] ?? null; @@ -178,6 +180,35 @@ class Processor } Item::update($item, ['uri' => $activity['id']]); + + if ($activity['object_type'] == 'as:Event') { + $posts = Post::select(['event-id', 'uid'], ["`uri` = ? AND `event-id` > ?", $activity['id'], 0]); + while ($post = DBA::fetch($posts)) { + self::updateEvent($post['event-id'], $activity); + } + } + } + + /** + * Update an existing event + * + * @param int $event_id + * @param array $activity + */ + private static function updateEvent(int $event_id, array $activity) + { + $event = DBA::selectFirst('event', [], ['id' => $event_id]); + + $event['edited'] = DateTimeFormat::utc($activity['updated']); + $event['summary'] = HTML::toBBCode($activity['name']); + $event['desc'] = HTML::toBBCode($activity['content']); + $event['start'] = $activity['start-time']; + $event['finish'] = $activity['end-time']; + $event['nofinish'] = empty($event['finish']); + $event['location'] = $activity['location']; + + Logger::info('Updating event', ['uri' => $activity['id'], 'id' => $event_id]); + Event::store($event); } /** @@ -256,6 +287,8 @@ class Processor $item['post-type'] = Item::PT_IMAGE; } elseif ($activity['object_type'] == 'as:Page') { $item['post-type'] = Item::PT_PAGE; + } elseif ($activity['object_type'] == 'as:Question') { + $item['post-type'] = Item::PT_POLL; } elseif ($activity['object_type'] == 'as:Video') { $item['post-type'] = Item::PT_VIDEO; } else { @@ -273,7 +306,7 @@ class Processor } else { // 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']; + $item['causer-id'] = $item['owner-id']; Logger::info('Use actor as causer.', ['id' => $item['owner-id'], 'actor' => $item['owner-link']]); } @@ -286,8 +319,12 @@ class Processor $item['uri'] = $activity['id']; - $item['created'] = DateTimeFormat::utc($activity['published']); - $item['edited'] = DateTimeFormat::utc($activity['updated']); + if (empty($activity['published']) || empty($activity['updated'])) { + DI::logger()->notice('published or updated keys are empty for activity', ['activity' => $activity, 'callstack' => System::callstack(10)]); + } + + $item['created'] = DateTimeFormat::utc($activity['published'] ?? 'now'); + $item['edited'] = DateTimeFormat::utc($activity['updated'] ?? 'now'); $guid = $activity['sc:identifier'] ?: self::getGUIDByURL($item['uri']); $item['guid'] = $activity['diaspora:guid'] ?: $guid; @@ -395,6 +432,8 @@ class Processor * * @param array $activity Activity array * @param array $item + * + * @return int event id * @throws \Exception */ public static function createEvent($activity, $item) @@ -405,7 +444,6 @@ class Processor $event['finish'] = $activity['end-time']; $event['nofinish'] = empty($event['finish']); $event['location'] = $activity['location']; - $event['adjust'] = $activity['adjust'] ?? true; $event['cid'] = $item['contact-id']; $event['uid'] = $item['uid']; $event['uri'] = $item['uri']; @@ -418,14 +456,16 @@ class Processor $event['direction'] = $item['direction']; $event['source'] = $item['source']; - $condition = ['uri' => $item['uri'], 'uid' => $item['uid']]; - $ev = DBA::selectFirst('event', ['id'], $condition); + $ev = DBA::selectFirst('event', ['id'], ['uri' => $item['uri'], 'uid' => $item['uid']]); if (DBA::isResult($ev)) { $event['id'] = $ev['id']; } $event_id = Event::store($event); + Logger::info('Event was stored', ['id' => $event_id]); + + return $event_id; } /** @@ -455,10 +495,10 @@ class Processor } if (!empty($activity['emojis'])) { - $content = self::replaceEmojis($content, $activity['emojis']); + $content = self::replaceEmojis($item['uri-id'], $content, $activity['emojis']); } - $content = self::convertMentions($content); + $content = self::addMentionLinks($content, $activity['tags']); if (!empty($activity['source'])) { $item['body'] = $activity['source']; @@ -602,7 +642,28 @@ class Processor continue; } - if (DI::pConfig()->get($receiver, 'system', 'accept_only_sharer', false) && ($receiver != 0) && ($item['gravity'] == GRAVITY_PARENT)) { + if (!($item['isForum'] ?? false) && ($receiver != 0) && ($item['gravity'] == GRAVITY_PARENT) && !Contact::isSharingByURL($activity['author'], $receiver)) { + if ($item['post-reason'] == Item::PR_BCC) { + Logger::info('Top level post via BCC from a non sharer, ignoring', ['uid' => $receiver, 'contact' => $item['contact-id']]); + continue; + } + if (!empty($activity['thread-children-type']) && in_array($activity['thread-children-type'], Receiver::ACTIVITY_TYPES)) { + Logger::info('Top level post from thread completion from a non sharer had been initiated via an activity, ignoring', + ['type' => $activity['thread-children-type'], 'user' => $item['uid'], 'causer' => $item['causer-link'], 'author' => $activity['author'], 'url' => $item['uri']]); + continue; + } + } + + $is_forum = false; + + if ($receiver != 0) { + $user = User::getById($receiver, ['account-type']); + if (!empty($user['account-type'])) { + $is_forum = ($user['account-type'] == User::ACCOUNT_TYPE_COMMUNITY); + } + } + + if (!$is_forum && DI::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') || ($item['isForum'] ?? false))) { @@ -618,7 +679,9 @@ class Processor } if (($item['gravity'] != GRAVITY_ACTIVITY) && ($activity['object_type'] == 'as:Event')) { - self::createEvent($activity, $item); + $event_id = self::createEvent($activity, $item); + + $item = Event::getItemArrayForImportedId($event_id, $item); } $item_id = Item::insert($item); @@ -737,7 +800,7 @@ class Processor $title = $matches[3]; } - $title = trim(HTML::toPlaintext(BBCode::convert($title, false, BBCode::API, true), 0)); + $title = trim(BBCode::toPlaintext($title)); if (strlen($title) > 20) { $title = substr($title, 0, 20) . '...'; @@ -830,6 +893,10 @@ class Processor $ldactivity['thread-completion'] = Contact::getIdForURL($actor); } + if (!empty($child['type'])) { + $ldactivity['thread-children-type'] = $child['type']; + } + if (!empty($relay_actor) && !self::acceptIncomingMessage($ldactivity, $object['id'])) { return ''; } @@ -903,7 +970,7 @@ class Processor $cid = Contact::getIdForURL($activity['actor'], $uid); if (!empty($cid)) { self::switchContact($cid); - DBA::update('contact', ['hub-verify' => $activity['id'], 'protocol' => Protocol::ACTIVITYPUB], ['id' => $cid]); + Contact::update(['hub-verify' => $activity['id'], 'protocol' => Protocol::ACTIVITYPUB], ['id' => $cid]); } $item = ['author-id' => Contact::getIdForURL($activity['actor']), @@ -923,7 +990,7 @@ class Processor } if (empty($contact)) { - DBA::update('contact', ['hub-verify' => $activity['id'], 'protocol' => Protocol::ACTIVITYPUB], ['id' => $cid]); + Contact::update(['hub-verify' => $activity['id'], 'protocol' => Protocol::ACTIVITYPUB], ['id' => $cid]); } Logger::notice('Follow user ' . $uid . ' from contact ' . $cid . ' with id ' . $activity['id']); @@ -1002,7 +1069,7 @@ class Processor } $condition = ['id' => $cid]; - DBA::update('contact', $fields, $condition); + Contact::update($fields, $condition); Logger::info('Accept contact request', ['contact' => $cid, 'user' => $uid]); } @@ -1028,9 +1095,12 @@ class Processor self::switchContact($cid); - if (DBA::exists('contact', ['id' => $cid, 'rel' => Contact::SHARING])) { + $contact = Contact::getById($cid, ['rel']); + if ($contact['rel'] == Contact::SHARING) { Contact::remove($cid); Logger::info('Rejected contact request - contact removed', ['contact' => $cid, 'user' => $uid]); + } elseif ($contact['rel'] == Contact::FRIEND) { + Contact::update(['rel' => Contact::FOLLOWER], ['id' => $cid]); } else { Logger::info('Rejected contact request', ['contact' => $cid, 'user' => $uid]); } @@ -1093,7 +1163,7 @@ class Processor return; } - Contact::removeFollower($owner, $contact); + Contact::removeFollower($contact); Logger::info('Undo following request', ['contact' => $cid, 'user' => $uid]); } @@ -1185,4 +1255,38 @@ class Processor return implode('', $kept_mentions); } + + /** + * Adds links to string mentions + * + * @param string $body + * @param array $tags + * @return string + */ + protected static function addMentionLinks(string $body, array $tags): string + { + // This prevents links to be added again to Pleroma-style mention links + $body = self::normalizeMentionLinks($body); + + $body = BBCode::performWithEscapedTags($body, ['url'], function ($body) use ($tags) { + foreach ($tags as $tag) { + if (empty($tag['name']) || empty($tag['type']) || empty($tag['href']) || !in_array($tag['type'], ['Mention', 'Hashtag'])) { + continue; + } + + $hash = substr($tag['name'], 0, 1); + $name = substr($tag['name'], 1); + if (!in_array($hash, Tag::TAG_CHARACTER)) { + $hash = ''; + $name = $tag['name']; + } + + $body = str_replace($tag['name'], $hash . '[url=' . $tag['href'] . ']' . $name . '[/url]', $body); + } + + return $body; + }); + + return $body; + } }