X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FProtocol%2FOStatus.php;h=fe8f060aa3fffdf68ca6da5205fd5b08516c5467;hb=341d8860d15cd2224a3595dfa3c553b03658ef60;hp=74a055265db795502f20e01bea8e40f6bd4622e5;hpb=f81164de7a5758fe387f188137ece9e9acf8a9e1;p=friendica.git diff --git a/src/Protocol/OStatus.php b/src/Protocol/OStatus.php index 74a055265d..fe8f060aa3 100644 --- a/src/Protocol/OStatus.php +++ b/src/Protocol/OStatus.php @@ -1,6 +1,6 @@ $contact["id"]], $current); + Contact::update($contact, ['id' => $contact["id"]], $current); if (!empty($author["author-avatar"]) && ($author["author-avatar"] != $current['avatar'])) { - Logger::log("Update profile picture for contact ".$contact["id"], Logger::DEBUG); + Logger::info("Update profile picture for contact ".$contact["id"]); Contact::updateAvatar($contact["id"], $author["author-avatar"]); } // Ensure that we are having this contact (with uid=0) - $cid = Contact::getIdForURL($aliaslink, 0, false); + $cid = Contact::getIdForURL($aliaslink); if ($cid) { $fields = ['url', 'nurl', 'name', 'nick', 'alias', 'about', 'location']; @@ -232,7 +230,7 @@ class OStatus 'about' => $contact["about"], 'location' => $contact["location"], 'success_update' => DateTimeFormat::utcNow(), 'last-update' => DateTimeFormat::utcNow()]; - DBA::update('contact', $fields, ['id' => $cid], $old_contact); + Contact::update($fields, ['id' => $cid], $old_contact); // Update the avatar if (!empty($author["author-avatar"])) { @@ -314,7 +312,7 @@ class OStatus */ public static function import($xml, array $importer, array &$contact, &$hub) { - self::process($xml, $importer, $contact, $hub); + self::process($xml, $importer, $contact, $hub, false, true, Conversation::PUSH); } /** @@ -331,14 +329,14 @@ class OStatus * @throws \Friendica\Network\HTTPException\InternalServerErrorException * @throws \ImagickException */ - private static function process($xml, array $importer, array &$contact = null, &$hub, $stored = false, $initialize = true) + private static function process($xml, array $importer, array &$contact = null, &$hub, $stored = false, $initialize = true, $direction = Conversation::UNKNOWN) { if ($initialize) { self::$itemlist = []; self::$conv_list = []; } - Logger::log('Import OStatus message for user ' . $importer['uid'], Logger::DEBUG); + Logger::info('Import OStatus message for user ' . $importer['uid']); if ($xml == "") { return false; @@ -364,7 +362,7 @@ class OStatus foreach ($hub_attributes as $hub_attribute) { if ($hub_attribute->name == "href") { $hub = $hub_attribute->textContent; - Logger::log("Found hub ".$hub, Logger::DEBUG); + Logger::info("Found hub ".$hub); } } } @@ -399,6 +397,7 @@ class OStatus $header["protocol"] = Conversation::PARCEL_SALMON; $header["source"] = $xml2; + $header["direction"] = $direction; } elseif (!$initialize) { return false; } @@ -441,27 +440,27 @@ class OStatus if (in_array($item["verb"], [Activity::O_UNFAVOURITE, Activity::UNFAVORITE])) { // Ignore "Unfavorite" message - Logger::log("Ignore unfavorite message ".print_r($item, true), Logger::DEBUG); + Logger::info("Ignore unfavorite message ", ['item' => $item]); continue; } // Deletions come with the same uri, so we check for duplicates after processing deletions - if (Item::exists(['uid' => $importer["uid"], 'uri' => $item["uri"]])) { - Logger::log('Post with URI '.$item["uri"].' already existed for user '.$importer["uid"].'.', Logger::DEBUG); + if (Post::exists(['uid' => $importer["uid"], 'uri' => $item["uri"]])) { + Logger::info('Post with URI '.$item["uri"].' already existed for user '.$importer["uid"].'.'); continue; } else { - Logger::log('Processing post with URI '.$item["uri"].' for user '.$importer["uid"].'.', Logger::DEBUG); + Logger::info('Processing post with URI '.$item["uri"].' for user '.$importer["uid"].'.'); } if ($item["verb"] == Activity::JOIN) { // ignore "Join" messages - Logger::log("Ignore join message ".print_r($item, true), Logger::DEBUG); + Logger::info("Ignore join message ", ['item' => $item]); continue; } if ($item["verb"] == "http://mastodon.social/schema/1.0/block") { // ignore mastodon "block" messages - Logger::log("Ignore block message ".print_r($item, true), Logger::DEBUG); + Logger::info("Ignore block message ", ['item' => $item]); continue; } @@ -472,42 +471,45 @@ class OStatus if ($item["verb"] == Activity::O_UNFOLLOW) { $dummy = null; - Contact::removeFollower($importer, $contact, $item, $dummy); + Contact::removeFollower($contact); continue; } if ($item["verb"] == Activity::FAVORITE) { $orig_uri = $xpath->query("activity:object/atom:id", $entry)->item(0)->nodeValue; - Logger::log("Favorite ".$orig_uri." ".print_r($item, true)); + Logger::notice("Favorite", ['uri' => $orig_uri, 'item' => $item]); $item["verb"] = Activity::LIKE; - $item["parent-uri"] = $orig_uri; + $item["thr-parent"] = $orig_uri; $item["gravity"] = GRAVITY_ACTIVITY; $item["object-type"] = Activity\ObjectType::NOTE; } // http://activitystrea.ms/schema/1.0/rsvp-yes if (!in_array($item["verb"], [Activity::POST, Activity::LIKE, Activity::SHARE])) { - Logger::log("Unhandled verb ".$item["verb"]." ".print_r($item, true), Logger::DEBUG); + Logger::info("Unhandled verb", ['verb' => $item["verb"], 'item' => $item]); } self::processPost($xpath, $entry, $item, $importer); if ($initialize && (count(self::$itemlist) > 0)) { - if (self::$itemlist[0]['uri'] == self::$itemlist[0]['parent-uri']) { + if (self::$itemlist[0]['uri'] == self::$itemlist[0]['thr-parent']) { + $uid = self::$itemlist[0]['uid']; // We will import it everytime, when it is started by our contacts - $valid = Contact::isSharingByURL(self::$itemlist[0]['author-link'], self::$itemlist[0]['uid']); + $valid = Contact::isSharingByURL(self::$itemlist[0]['author-link'], $uid); if (!$valid) { // If not, then it depends on this setting - $valid = ((self::$itemlist[0]['uid'] == 0) || !DI::pConfig()->get(self::$itemlist[0]['uid'], 'system', 'accept_only_sharer', false)); + $valid = !$uid || DI::pConfig()->get($uid, 'system', 'accept_only_sharer') != Item::COMPLETION_NONE; + if ($valid) { - Logger::log("Item with uri ".self::$itemlist[0]['uri']." will be imported due to the system settings.", Logger::DEBUG); + Logger::info("Item with uri ".self::$itemlist[0]['uri']." will be imported due to the system settings."); } } else { - Logger::log("Item with uri ".self::$itemlist[0]['uri']." belongs to a contact (".self::$itemlist[0]['contact-id']."). It will be imported.", Logger::DEBUG); + Logger::info("Item with uri ".self::$itemlist[0]['uri']." belongs to a contact (".self::$itemlist[0]['contact-id']."). It will be imported."); } - if ($valid) { + + if ($valid && DI::pConfig()->get($uid, 'system', 'accept_only_sharer') != Item::COMPLETION_LIKE) { // Never post a thread when the only interaction by our contact was a like $valid = false; $verbs = [Activity::POST, Activity::SHARE]; @@ -517,15 +519,11 @@ class OStatus } } if ($valid) { - Logger::log("Item with uri ".self::$itemlist[0]['uri']." will be imported since the thread contains posts or shares.", Logger::DEBUG); + Logger::info("Item with uri ".self::$itemlist[0]['uri']." will be imported since the thread contains posts or shares."); } } } else { - // But we will only import complete threads - $valid = Item::exists(['uid' => $importer["uid"], 'uri' => self::$itemlist[0]['parent-uri']]); - if ($valid) { - Logger::log("Item with uri ".self::$itemlist[0]["uri"]." belongs to parent ".self::$itemlist[0]['parent-uri']." of user ".$importer["uid"].". It will be imported.", Logger::DEBUG); - } + $valid = true; } if ($valid) { @@ -538,27 +536,20 @@ class OStatus } } foreach (self::$itemlist as $item) { - $found = Item::exists(['uid' => $importer["uid"], 'uri' => $item["uri"]]); + $found = Post::exists(['uid' => $importer["uid"], 'uri' => $item["uri"]]); if ($found) { - Logger::log("Item with uri ".$item["uri"]." for user ".$importer["uid"]." already exists.", Logger::DEBUG); + Logger::notice("Item with uri ".$item["uri"]." for user ".$importer["uid"]." already exists."); } elseif ($item['contact-id'] < 0) { - Logger::log("Item with uri ".$item["uri"]." is from a blocked contact.", Logger::DEBUG); + Logger::notice("Item with uri ".$item["uri"]." is from a blocked contact."); } else { - // We are having duplicated entries. Hopefully this solves it. - if (DI::lock()->acquire('ostatus_process_item_insert')) { - $ret = Item::insert($item); - DI::lock()->release('ostatus_process_item_insert'); - Logger::log("Item with uri ".$item["uri"]." for user ".$importer["uid"].' stored. Return value: '.$ret); - } else { - $ret = Item::insert($item); - Logger::log("We couldn't lock - but tried to store the item anyway. Return value is ".$ret); - } + $ret = Item::insert($item); + Logger::info("Item with uri ".$item["uri"]." for user ".$importer["uid"].' stored. Return value: '.$ret); } } } self::$itemlist = []; } - Logger::log('Processing done for post with URI '.$item["uri"].' for user '.$importer["uid"].'.', Logger::DEBUG); + Logger::info('Processing done for post with URI '.$item["uri"].' for user '.$importer["uid"].'.'); } return true; } @@ -573,14 +564,14 @@ class OStatus private static function deleteNotice(array $item) { $condition = ['uid' => $item['uid'], 'author-id' => $item['author-id'], 'uri' => $item['uri']]; - if (!Item::exists($condition)) { - Logger::log('Item from '.$item['author-link'].' with uri '.$item['uri'].' for user '.$item['uid']." wasn't found. We don't delete it."); + if (!Post::exists($condition)) { + Logger::notice('Item from '.$item['author-link'].' with uri '.$item['uri'].' for user '.$item['uid']." wasn't found. We don't delete it."); return; } Item::markForDeletion($condition); - Logger::log('Deleted item with uri '.$item['uri'].' for user '.$item['uid']); + Logger::notice('Deleted item with uri '.$item['uri'].' for user '.$item['uid']); } /** @@ -627,7 +618,7 @@ class OStatus if (is_object($inreplyto->item(0))) { foreach ($inreplyto->item(0)->attributes as $attributes) { if ($attributes->name == "ref") { - $item["parent-uri"] = $attributes->textContent; + $item["thr-parent"] = $attributes->textContent; } if ($attributes->name == "href") { $related = $attributes->textContent; @@ -685,11 +676,6 @@ class OStatus $item["body"] .= $add_body; - // Only add additional data when there is no picture in the post - if (!strstr($item["body"], '[/img]')) { - $item["body"] = PageInfo::searchAndAppendToBody($item["body"]); - } - Tag::storeFromBody($item['uri-id'], $item['body']); // Mastodon Content Warning @@ -708,16 +694,16 @@ class OStatus self::fetchConversation($item['conversation-href'], $item['conversation-uri']); } - if (isset($item["parent-uri"])) { - if (!Item::exists(['uid' => $importer["uid"], 'uri' => $item['parent-uri']])) { + if (isset($item["thr-parent"])) { + if (!Post::exists(['uid' => $importer["uid"], 'uri' => $item['thr-parent']])) { if ($related != '') { - self::fetchRelated($related, $item["parent-uri"], $importer); + self::fetchRelated($related, $item["thr-parent"], $importer); } } else { - Logger::log('Reply with URI '.$item["uri"].' already existed for user '.$importer["uid"].'.', Logger::DEBUG); + Logger::info('Reply with URI '.$item["uri"].' already existed for user '.$importer["uid"].'.'); } } else { - $item["parent-uri"] = $item["uri"]; + $item["thr-parent"] = $item["uri"]; $item["gravity"] = GRAVITY_PARENT; } @@ -745,15 +731,16 @@ class OStatus self::$conv_list[$conversation] = true; - $curlResult = DI::httpRequest()->get($conversation, false, ['accept_content' => 'application/atom+xml, text/html']); + $curlResult = DI::httpClient()->get($conversation, HttpClientAccept::ATOM_XML); - if (!$curlResult->isSuccess()) { + if (!$curlResult->isSuccess() || empty($curlResult->getBody())) { return; } $xml = ''; - if (stristr($curlResult->getHeader(), 'Content-Type: application/atom+xml')) { + if ($curlResult->inHeader('Content-Type') && + in_array('application/atom+xml', $curlResult->getHeader('Content-Type'))) { $xml = $curlResult->getBody(); } @@ -774,7 +761,7 @@ class OStatus } } if ($file != '') { - $conversation_atom = DI::httpRequest()->get($attribute['href']); + $conversation_atom = DI::httpClient()->get($attribute['href'], HttpClientAccept::ATOM_XML); if ($conversation_atom->isSuccess()) { $xml = $conversation_atom->getBody(); @@ -820,6 +807,7 @@ class OStatus $conv_data = []; $conv_data['protocol'] = Conversation::PARCEL_SPLIT_CONVERSATION; + $conv_data['direction'] = Conversation::PULL; $conv_data['network'] = Protocol::OSTATUS; $conv_data['uri'] = XML::getFirstNodeValue($xpath, 'atom:id/text()', $entry); @@ -860,13 +848,7 @@ class OStatus $conv_data['source'] = $doc2->saveXML(); - $condition = ['item-uri' => $conv_data['uri'],'protocol' => Conversation::PARCEL_FEED]; - if (DBA::exists('conversation', $condition)) { - Logger::log('Delete deprecated entry for URI '.$conv_data['uri'], Logger::DEBUG); - DBA::delete('conversation', ['item-uri' => $conv_data['uri']]); - } - - Logger::log('Store conversation data for uri '.$conv_data['uri'], Logger::DEBUG); + Logger::info('Store conversation data for uri '.$conv_data['uri']); Conversation::insert($conv_data); } } @@ -885,13 +867,15 @@ class OStatus */ private static function fetchSelf($self, array &$item) { - $condition = ['`item-uri` = ? AND `protocol` IN (?, ?)', $self, Conversation::PARCEL_DFRN, Conversation::PARCEL_SALMON]; + $condition = ['item-uri' => $self, 'protocol' => [Conversation::PARCEL_DFRN, + Conversation::PARCEL_DIASPORA_DFRN, Conversation::PARCEL_LOCAL_DFRN, + Conversation::PARCEL_DIRECT, Conversation::PARCEL_SALMON]]; if (DBA::exists('conversation', $condition)) { - Logger::log('Conversation '.$item['uri'].' is already stored.', Logger::DEBUG); + Logger::info('Conversation '.$item['uri'].' is already stored.'); return; } - $curlResult = DI::httpRequest()->get($self); + $curlResult = DI::httpClient()->get($self, HttpClientAccept::ATOM_XML); if (!$curlResult->isSuccess()) { return; @@ -906,8 +890,9 @@ class OStatus $item["protocol"] = Conversation::PARCEL_SALMON; $item["source"] = $xml; + $item["direction"] = Conversation::PULL; - Logger::log('Conversation '.$item['uri'].' is now fetched.', Logger::DEBUG); + Logger::info('Conversation '.$item['uri'].' is now fetched.'); } /** @@ -922,32 +907,35 @@ class OStatus */ private static function fetchRelated($related, $related_uri, $importer) { - $condition = ['`item-uri` = ? AND `protocol` IN (?, ?)', $related_uri, Conversation::PARCEL_DFRN, Conversation::PARCEL_SALMON]; + $condition = ['item-uri' => $related_uri, 'protocol' => [Conversation::PARCEL_DFRN, + Conversation::PARCEL_DIASPORA_DFRN, Conversation::PARCEL_LOCAL_DFRN, + Conversation::PARCEL_DIRECT, Conversation::PARCEL_SALMON]]; $conversation = DBA::selectFirst('conversation', ['source', 'protocol'], $condition); if (DBA::isResult($conversation)) { $stored = true; $xml = $conversation['source']; - if (self::process($xml, $importer, $contact, $hub, $stored, false)) { - Logger::log('Got valid cached XML for URI '.$related_uri, Logger::DEBUG); + if (self::process($xml, $importer, $contact, $hub, $stored, false, Conversation::PULL)) { + Logger::info('Got valid cached XML for URI '.$related_uri); return; } if ($conversation['protocol'] == Conversation::PARCEL_SALMON) { - Logger::log('Delete invalid cached XML for URI '.$related_uri, Logger::DEBUG); + Logger::info('Delete invalid cached XML for URI '.$related_uri); DBA::delete('conversation', ['item-uri' => $related_uri]); } } $stored = false; - $curlResult = DI::httpRequest()->get($related, false, ['accept_content' => 'application/atom+xml, text/html']); + $curlResult = DI::httpClient()->get($related, HttpClientAccept::ATOM_XML); - if (!$curlResult->isSuccess()) { + if (!$curlResult->isSuccess() || empty($curlResult->getBody())) { return; } $xml = ''; - if (stristr($curlResult->getHeader(), 'Content-Type: application/atom+xml')) { - Logger::log('Directly fetched XML for URI ' . $related_uri, Logger::DEBUG); + if ($curlResult->inHeader('Content-Type') && + in_array('application/atom+xml', $curlResult->getHeader('Content-Type'))) { + Logger::info('Directly fetched XML for URI ' . $related_uri); $xml = $curlResult->getBody(); } @@ -969,10 +957,10 @@ class OStatus } } if ($atom_file != '') { - $curlResult = DI::httpRequest()->get($atom_file); + $curlResult = DI::httpClient()->get($atom_file, HttpClientAccept::ATOM_XML); if ($curlResult->isSuccess()) { - Logger::log('Fetched XML for URI ' . $related_uri, Logger::DEBUG); + Logger::info('Fetched XML for URI ' . $related_uri); $xml = $curlResult->getBody(); } } @@ -981,10 +969,10 @@ class OStatus // Workaround for older GNU Social servers if (($xml == '') && strstr($related, '/notice/')) { - $curlResult = DI::httpRequest()->get(str_replace('/notice/', '/api/statuses/show/', $related) . '.atom'); + $curlResult = DI::httpClient()->get(str_replace('/notice/', '/api/statuses/show/', $related) . '.atom', HttpClientAccept::ATOM_XML); if ($curlResult->isSuccess()) { - Logger::log('GNU Social workaround to fetch XML for URI ' . $related_uri, Logger::DEBUG); + Logger::info('GNU Social workaround to fetch XML for URI ' . $related_uri); $xml = $curlResult->getBody(); } } @@ -992,10 +980,10 @@ class OStatus // Even more worse workaround for GNU Social ;-) if ($xml == '') { $related_guess = self::convertHref($related_uri); - $curlResult = DI::httpRequest()->get(str_replace('/notice/', '/api/statuses/show/', $related_guess) . '.atom'); + $curlResult = DI::httpClient()->get(str_replace('/notice/', '/api/statuses/show/', $related_guess) . '.atom', HttpClientAccept::ATOM_XML); if ($curlResult->isSuccess()) { - Logger::log('GNU Social workaround 2 to fetch XML for URI ' . $related_uri, Logger::DEBUG); + Logger::info('GNU Social workaround 2 to fetch XML for URI ' . $related_uri); $xml = $curlResult->getBody(); } } @@ -1006,15 +994,15 @@ class OStatus $conversation = DBA::selectFirst('conversation', ['source'], $condition); if (DBA::isResult($conversation)) { $stored = true; - Logger::log('Got cached XML from conversation for URI '.$related_uri, Logger::DEBUG); + Logger::info('Got cached XML from conversation for URI '.$related_uri); $xml = $conversation['source']; } } if ($xml != '') { - self::process($xml, $importer, $contact, $hub, $stored, false); + self::process($xml, $importer, $contact, $hub, $stored, false, Conversation::PULL); } else { - Logger::log("XML couldn't be fetched for URI: ".$related_uri." - href: ".$related, Logger::DEBUG); + Logger::info("XML couldn't be fetched for URI: ".$related_uri." - href: ".$related); } return; } @@ -1080,7 +1068,7 @@ class OStatus if (is_object($inreplyto->item(0))) { foreach ($inreplyto->item(0)->attributes as $attributes) { if ($attributes->name == "ref") { - $item["parent-uri"] = $attributes->textContent; + $item["thr-parent"] = $attributes->textContent; } } } @@ -1110,7 +1098,9 @@ class OStatus if (($item["object-type"] == Activity\ObjectType::QUESTION) || ($item["object-type"] == Activity\ObjectType::EVENT) ) { - $item["body"] .= "\n" . PageInfo::getFooterFromUrl($attribute['href']); + Post\Media::insert(['uri-id' => $item['uri-id'], 'type' => Post\Media::UNKNOWN, + 'url' => $attribute['href'], 'mimetype' => $attribute['type'] ?? null, + 'size' => $attribute['length'] ?? null, 'description' => $attribute['title'] ?? null]); } break; case "ostatus:conversation": @@ -1125,25 +1115,21 @@ class OStatus if ($filetype == 'image') { $link_data['add_body'] .= "\n[img]".$attribute['href'].'[/img]'; } else { - if (!empty($item["attach"])) { - $item["attach"] .= ','; - } else { - $item["attach"] = ''; - } - if (!isset($attribute['length'])) { - $attribute['length'] = "0"; - } - $item["attach"] .= '[attach]href="'.$attribute['href'].'" length="'.$attribute['length'].'" type="'.$attribute['type'].'" title="'.($attribute['title'] ?? '') .'"[/attach]'; + Post\Media::insert(['uri-id' => $item['uri-id'], 'type' => Post\Media::DOCUMENT, + 'url' => $attribute['href'], 'mimetype' => $attribute['type'], + 'size' => $attribute['length'] ?? null, 'description' => $attribute['title'] ?? null]); } break; case "related": if ($item["object-type"] != Activity\ObjectType::BOOKMARK) { - if (!isset($item["parent-uri"])) { - $item["parent-uri"] = $attribute['href']; + if (!isset($item["thr-parent"])) { + $item["thr-parent"] = $attribute['href']; } $link_data['related'] = $attribute['href']; } else { - $item["body"] .= "\n" . PageInfo::getFooterFromUrl($attribute['href']); + Post\Media::insert(['uri-id' => $item['uri-id'], 'type' => Post\Media::UNKNOWN, + 'url' => $attribute['href'], 'mimetype' => $attribute['type'] ?? null, + 'size' => $attribute['length'] ?? null, 'description' => $attribute['title'] ?? null]); } break; case "self": @@ -1190,23 +1176,6 @@ class OStatus } } - /** - * Checks if the current post is a reshare - * - * @param array $item The item array of thw post - * - * @return string The guid if the post is a reshare - */ - public static function getResharedGuid(array $item) - { - $reshared = Item::getShareArray($item); - if (empty($reshared['guid']) || !empty($reshared['comment'])) { - return ''; - } - - return $reshared['guid']; - } - /** * Cleans the body of a post if it contains picture links * @@ -1215,7 +1184,7 @@ class OStatus * @return string The cleaned body * @throws \Friendica\Network\HTTPException\InternalServerErrorException */ - public static function formatPicturePost($body) + public static function formatPicturePost($body, $uriid) { $siteinfo = BBCode::getAttachedData($body); @@ -1227,7 +1196,7 @@ class OStatus } // Is it a remote picture? Then make a smaller preview here - $preview = ProxyUtils::proxifyUrl($preview, false, ProxyUtils::SIZE_SMALL); + $preview = Post\Link::getByLink($uriid, $preview, Proxy::SIZE_SMALL); // Is it a local picture? Then make it smaller here $preview = str_replace(["-0.jpg", "-0.png"], ["-2.jpg", "-2.png"], $preview); @@ -1292,7 +1261,7 @@ class OStatus XML::addElement($doc, $root, "id", DI::baseUrl() . "/profile/" . $owner["nick"]); XML::addElement($doc, $root, "title", $title); XML::addElement($doc, $root, "subtitle", sprintf("Updates from %s on %s", $owner["name"], DI::config()->get('config', 'sitename'))); - XML::addElement($doc, $root, "logo", $owner["photo"]); + XML::addElement($doc, $root, "logo", User::getAvatarUrl($owner, Proxy::SIZE_SMALL)); XML::addElement($doc, $root, "updated", DateTimeFormat::utcNow(DateTimeFormat::ATOM)); $author = self::addAuthor($doc, $owner, true); @@ -1397,25 +1366,19 @@ class OStatus } } - $arr = explode('[/attach],', $item['attach']); - if (count($arr)) { - foreach ($arr as $r) { - $matches = false; - $cnt = preg_match('|\[attach\]href=\"(.*?)\" length=\"(.*?)\" type=\"(.*?)\" title=\"(.*?)\"|', $r, $matches); - if ($cnt) { - $attributes = ["rel" => "enclosure", - "href" => $matches[1], - "type" => $matches[3]]; + foreach (Post\Media::getByURIId($item['uri-id'], [Post\Media::DOCUMENT, Post\Media::TORRENT, Post\Media::UNKNOWN]) as $attachment) { + $attributes = ['rel' => 'enclosure', + 'href' => $attachment['url'], + 'type' => $attachment['mimetype']]; - if (intval($matches[2])) { - $attributes["length"] = intval($matches[2]); - } - if (trim($matches[4]) != "") { - $attributes["title"] = trim($matches[4]); - } - XML::addElement($doc, $root, "link", "", $attributes); - } + if (!empty($attachment['size'])) { + $attributes['length'] = intval($attachment['size']); + } + if (!empty($attachment['description'])) { + $attributes['title'] = $attachment['description']; } + + XML::addElement($doc, $root, 'link', '', $attributes); } } @@ -1444,7 +1407,7 @@ class OStatus XML::addElement($doc, $author, "name", $owner["nick"]); XML::addElement($doc, $author, "email", $owner["addr"]); if ($show_profile) { - XML::addElement($doc, $author, "summary", BBCode::convert($owner["about"], false, BBCode::OSTATUS)); + XML::addElement($doc, $author, "summary", BBCode::convertForUriId($owner['uri-id'], $owner["about"], BBCode::OSTATUS)); } $attributes = ["rel" => "alternate", "type" => "text/html", "href" => $owner["url"]]; @@ -1453,25 +1416,25 @@ class OStatus $attributes = [ "rel" => "avatar", "type" => "image/jpeg", // To-Do? - "media:width" => 300, - "media:height" => 300, - "href" => $owner["photo"]]; + "media:width" => Proxy::PIXEL_SMALL, + "media:height" => Proxy::PIXEL_SMALL, + "href" => User::getAvatarUrl($owner, Proxy::SIZE_SMALL)]; XML::addElement($doc, $author, "link", "", $attributes); if (isset($owner["thumb"])) { $attributes = [ "rel" => "avatar", "type" => "image/jpeg", // To-Do? - "media:width" => 80, - "media:height" => 80, - "href" => $owner["thumb"]]; + "media:width" => Proxy::PIXEL_THUMB, + "media:height" => Proxy::PIXEL_THUMB, + "href" => User::getAvatarUrl($owner, Proxy::SIZE_THUMB)]; XML::addElement($doc, $author, "link", "", $attributes); } XML::addElement($doc, $author, "poco:preferredUsername", $owner["nick"]); XML::addElement($doc, $author, "poco:displayName", $owner["name"]); if ($show_profile) { - XML::addElement($doc, $author, "poco:note", BBCode::convert($owner["about"], false, BBCode::OSTATUS)); + XML::addElement($doc, $author, "poco:note", BBCode::convertForUriId($owner['uri-id'], $owner["about"], BBCode::OSTATUS)); if (trim($owner["location"]) != "") { $element = $doc->createElement("poco:address"); @@ -1552,17 +1515,6 @@ class OStatus */ private static function entry(DOMDocument $doc, array $item, array $owner, $toplevel = false) { - $xml = null; - - $repeated_guid = self::getResharedGuid($item); - if ($repeated_guid != "") { - $xml = self::reshareEntry($doc, $item, $owner, $repeated_guid, $toplevel); - } - - if ($xml) { - return $xml; - } - if ($item["verb"] == Activity::LIKE) { return self::likeEntry($doc, $item, $owner, $toplevel); } elseif (in_array($item["verb"], [Activity::FOLLOW, Activity::O_UNFOLLOW])) { @@ -1572,94 +1524,6 @@ class OStatus } } - /** - * Adds a source entry to the XML document - * - * @param DOMDocument $doc XML document - * @param array $contact Array of the contact that is added - * - * @return \DOMElement Source element - * @throws \Exception - */ - private static function sourceEntry(DOMDocument $doc, array $contact) - { - $source = $doc->createElement("source"); - XML::addElement($doc, $source, "id", $contact["poll"]); - XML::addElement($doc, $source, "title", $contact["name"]); - XML::addElement($doc, $source, "link", "", ["rel" => "alternate", "type" => "text/html", "href" => $contact["alias"]]); - XML::addElement($doc, $source, "link", "", ["rel" => "self", "type" => "application/atom+xml", "href" => $contact["poll"]]); - XML::addElement($doc, $source, "icon", $contact["photo"]); - XML::addElement($doc, $source, "updated", DateTimeFormat::utc($contact["success_update"]."+00:00", DateTimeFormat::ATOM)); - - return $source; - } - - /** - * Adds an entry element with reshared content - * - * @param DOMDocument $doc XML document - * @param array $item Data of the item that is to be posted - * @param array $owner Contact data of the poster - * @param string $repeated_guid guid - * @param bool $toplevel Is it for en entry element (false) or a feed entry (true)? - * - * @return bool Entry element - * @throws \Friendica\Network\HTTPException\InternalServerErrorException - * @throws \ImagickException - */ - private static function reshareEntry(DOMDocument $doc, array $item, array $owner, $repeated_guid, $toplevel) - { - if (($item['gravity'] != GRAVITY_PARENT) && (Strings::normaliseLink($item["author-link"]) != Strings::normaliseLink($owner["url"]))) { - Logger::log("OStatus entry is from author ".$owner["url"]." - not from ".$item["author-link"].". Quitting.", Logger::DEBUG); - } - - $entry = self::entryHeader($doc, $owner, $item, $toplevel); - - $condition = ['uid' => $owner["uid"], 'guid' => $repeated_guid, 'private' => [Item::PUBLIC, Item::UNLISTED], - 'network' => [Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS]]; - $repeated_item = Item::selectFirst([], $condition); - if (!DBA::isResult($repeated_item)) { - return false; - } - - $contact = Contact::getByURL($repeated_item['author-link']) ?: $owner; - - $title = $owner["nick"]." repeated a notice by ".$contact["nick"]; - - self::entryContent($doc, $entry, $item, $owner, $title, Activity::SHARE, false); - - $as_object = $doc->createElement("activity:object"); - - XML::addElement($doc, $as_object, "activity:object-type", ActivityNamespace::ACTIVITY_SCHEMA . "activity"); - - self::entryContent($doc, $as_object, $repeated_item, $owner, "", "", false); - - $author = self::addAuthor($doc, $contact, false); - $as_object->appendChild($author); - - $as_object2 = $doc->createElement("activity:object"); - - XML::addElement($doc, $as_object2, "activity:object-type", self::constructObjecttype($repeated_item)); - - $title = sprintf("New comment by %s", $contact["nick"]); - - self::entryContent($doc, $as_object2, $repeated_item, $owner, $title); - - $as_object->appendChild($as_object2); - - self::entryFooter($doc, $as_object, $item, $owner, false); - - $source = self::sourceEntry($doc, $contact); - - $as_object->appendChild($source); - - $entry->appendChild($as_object); - - self::entryFooter($doc, $entry, $item, $owner, true); - - return $entry; - } - /** * Adds an entry element with a "like" * @@ -1675,7 +1539,7 @@ class OStatus private static function likeEntry(DOMDocument $doc, array $item, array $owner, $toplevel) { if (($item['gravity'] != GRAVITY_PARENT) && (Strings::normaliseLink($item["author-link"]) != Strings::normaliseLink($owner["url"]))) { - Logger::log("OStatus entry is from author ".$owner["url"]." - not from ".$item["author-link"].". Quitting.", Logger::DEBUG); + Logger::info("OStatus entry is from author ".$owner["url"]." - not from ".$item["author-link"].". Quitting."); } $entry = self::entryHeader($doc, $owner, $item, $toplevel); @@ -1683,7 +1547,7 @@ class OStatus $verb = ActivityNamespace::ACTIVITY_SCHEMA . "favorite"; self::entryContent($doc, $entry, $item, $owner, "Favorite", $verb, false); - $parent = Item::selectFirst([], ['uri' => $item["thr-parent"], 'uid' => $item["uid"]]); + $parent = Post::selectFirst([], ['uri' => $item["thr-parent"], 'uid' => $item["uid"]]); if (DBA::isResult($parent)) { $as_object = $doc->createElement("activity:object"); @@ -1824,12 +1688,12 @@ class OStatus private static function noteEntry(DOMDocument $doc, array $item, array $owner, $toplevel) { if (($item['gravity'] != GRAVITY_PARENT) && (Strings::normaliseLink($item["author-link"]) != Strings::normaliseLink($owner["url"]))) { - Logger::log("OStatus entry is from author ".$owner["url"]." - not from ".$item["author-link"].". Quitting.", Logger::DEBUG); + Logger::info("OStatus entry is from author ".$owner["url"]." - not from ".$item["author-link"].". Quitting."); } if (!$toplevel) { if (!empty($item['title'])) { - $title = BBCode::convert($item['title'], false, BBCode::OSTATUS); + $title = BBCode::convertForUriId($item['uri-id'], $item['title'], BBCode::OSTATUS); } else { $title = sprintf("New note by %s", $owner["nick"]); } @@ -1867,6 +1731,7 @@ class OStatus if ($owner['contact-type'] == Contact::TYPE_COMMUNITY) { $contact = Contact::getByURL($item['author-link']) ?: $owner; + $contact['nickname'] = $contact['nickname'] ?? $contact['nick']; $author = self::addAuthor($doc, $contact, false); $entry->appendChild($author); } @@ -1911,13 +1776,14 @@ class OStatus XML::addElement($doc, $entry, "id", $item["uri"]); XML::addElement($doc, $entry, "title", html_entity_decode($title, ENT_QUOTES, 'UTF-8')); - $body = self::formatPicturePost($item['body']); + $body = Post\Media::addAttachmentsToBody($item['uri-id'], $item['body']); + $body = self::formatPicturePost($body, $item['uri-id']); if (!empty($item['title'])) { $body = "[b]".$item['title']."[/b]\n\n".$body; } - $body = BBCode::convert($body, false, BBCode::OSTATUS); + $body = BBCode::convertForUriId($item['uri-id'], $body, BBCode::OSTATUS); XML::addElement($doc, $entry, "content", $body, ["type" => "html"]); @@ -1951,34 +1817,37 @@ class OStatus $mentioned = []; if ($item['gravity'] != GRAVITY_PARENT) { - $parent = Item::selectFirst(['guid', 'author-link', 'owner-link'], ['id' => $item['parent']]); - $parent_item = (($item['thr-parent']) ? $item['thr-parent'] : $item['parent-uri']); + $parent = Post::selectFirst(['guid', 'author-link', 'owner-link'], ['id' => $item['parent']]); - $thrparent = Item::selectFirst(['guid', 'author-link', 'owner-link', 'plink'], ['uid' => $owner["uid"], 'uri' => $parent_item]); + $thrparent = Post::selectFirst(['guid', 'author-link', 'owner-link', 'plink'], ['uid' => $owner['uid'], 'uri' => $item['thr-parent']]); if (DBA::isResult($thrparent)) { - $mentioned[$thrparent["author-link"]] = $thrparent["author-link"]; - $mentioned[$thrparent["owner-link"]] = $thrparent["owner-link"]; - $parent_plink = $thrparent["plink"]; + $mentioned[$thrparent['author-link']] = $thrparent['author-link']; + $mentioned[$thrparent['owner-link']] = $thrparent['owner-link']; + $parent_plink = $thrparent['plink']; + } elseif (DBA::isResult($parent)) { + $mentioned[$parent['author-link']] = $parent['author-link']; + $mentioned[$parent['owner-link']] = $parent['owner-link']; + $parent_plink = DI::baseUrl() . '/display/' . $parent['guid']; } else { - $mentioned[$parent["author-link"]] = $parent["author-link"]; - $mentioned[$parent["owner-link"]] = $parent["owner-link"]; - $parent_plink = DI::baseUrl()."/display/".$parent["guid"]; + DI::logger()->notice('Missing parent and thr-parent for child item', ['item' => $item]); } - $attributes = [ - "ref" => $parent_item, - "href" => $parent_plink]; - XML::addElement($doc, $entry, "thr:in-reply-to", "", $attributes); + if (isset($parent_plink)) { + $attributes = [ + 'ref' => $item['thr-parent'], + 'href' => $parent_plink]; + XML::addElement($doc, $entry, 'thr:in-reply-to', '', $attributes); - $attributes = [ - "rel" => "related", - "href" => $parent_plink]; - XML::addElement($doc, $entry, "link", "", $attributes); + $attributes = [ + 'rel' => 'related', + 'href' => $parent_plink]; + XML::addElement($doc, $entry, 'link', '', $attributes); + } } if (intval($item['parent']) > 0) { - $conversation_href = $conversation_uri = str_replace('/objects/', '/context/', $item['parent-uri']); + $conversation_href = $conversation_uri = str_replace('/objects/', '/context/', $item['thr-parent']); if (isset($parent_item)) { $conversation = DBA::selectFirst('conversation', ['conversation-uri', 'conversation-href'], ['item-uri' => $parent_item]); @@ -2118,7 +1987,7 @@ class OStatus if ((time() - strtotime($owner['last-item'])) < 15*60) { $result = DI::cache()->get($cachekey); if (!$nocache && !is_null($result)) { - Logger::log('Feed duration: ' . number_format(microtime(true) - $stamp, 3) . ' - ' . $owner_nick . ' - ' . $filter . ' - ' . $previous_created . ' (cached)', Logger::DEBUG); + Logger::info('Feed duration: ' . number_format(microtime(true) - $stamp, 3) . ' - ' . $owner_nick . ' - ' . $filter . ' - ' . $previous_created . ' (cached)'); $last_update = $result['last_update']; return $result['feed']; } @@ -2129,7 +1998,7 @@ class OStatus } $check_date = DateTimeFormat::utc($last_update); - $authorid = Contact::getIdForURL($owner["url"], 0, false); + $authorid = Contact::getIdForURL($owner["url"]); $condition = ["`uid` = ? AND `received` > ? AND NOT `deleted` AND `private` != ? AND `visible` AND `wall` AND `parent-network` IN (?, ?)", @@ -2149,12 +2018,12 @@ class OStatus $params = ['order' => ['received' => true], 'limit' => $max_items]; if ($filter === 'posts') { - $ret = Item::selectThread([], $condition, $params); + $ret = Post::selectThread([], $condition, $params); } else { - $ret = Item::select([], $condition, $params); + $ret = Post::select([], $condition, $params); } - $items = Item::inArray($ret); + $items = Post::toArray($ret); $doc = new DOMDocument('1.0', 'utf-8'); $doc->formatOutput = true; @@ -2183,7 +2052,7 @@ class OStatus $msg = ['feed' => $feeddata, 'last_update' => $last_update]; DI::cache()->set($cachekey, $msg, Duration::QUARTER_HOUR); - Logger::log('Feed duration: ' . number_format(microtime(true) - $stamp, 3) . ' - ' . $owner_nick . ' - ' . $filter . ' - ' . $previous_created, Logger::DEBUG); + Logger::info('Feed duration: ' . number_format(microtime(true) - $stamp, 3) . ' - ' . $owner_nick . ' - ' . $filter . ' - ' . $previous_created); return $feeddata; } @@ -2218,14 +2087,13 @@ class OStatus * Checks if the given contact url does support OStatus * * @param string $url profile url - * @param boolean $update Update the profile * @return boolean * @throws \Friendica\Network\HTTPException\InternalServerErrorException * @throws \ImagickException */ - public static function isSupportedByContactUrl($url, $update = false) + public static function isSupportedByContactUrl($url) { - $probe = Probe::uri($url, Protocol::OSTATUS, 0, !$update); + $probe = Probe::uri($url, Protocol::OSTATUS); return $probe['network'] == Protocol::OSTATUS; } }