diff --git a/config/dbstructure.config.php b/config/dbstructure.config.php index 415e389b6b..3c2b81352b 100755 --- a/config/dbstructure.config.php +++ b/config/dbstructure.config.php @@ -253,6 +253,9 @@ return [ "pending" => ["type" => "boolean", "not null" => "1", "default" => "1", "comment" => ""], "deleted" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Contact has been deleted"], "rating" => ["type" => "tinyint", "not null" => "1", "default" => "0", "comment" => ""], + "unsearchable" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Contact prefers to not be searchable"], + "sensitive" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Contact posts sensitive content"], + "baseurl" => ["type" => "varchar(255)", "default" => "", "comment" => "baseurl of the contact"], "reason" => ["type" => "text", "comment" => ""], "closeness" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "99", "comment" => ""], "info" => ["type" => "mediumtext", "comment" => ""], diff --git a/database.sql b/database.sql index 07d4e2f280..7dc24b6038 100644 --- a/database.sql +++ b/database.sql @@ -210,6 +210,9 @@ CREATE TABLE IF NOT EXISTS `contact` ( `pending` boolean NOT NULL DEFAULT '1' COMMENT '', `deleted` boolean NOT NULL DEFAULT '0' COMMENT 'Contact has been deleted', `rating` tinyint NOT NULL DEFAULT 0 COMMENT '', + `unsearchable` boolean NOT NULL DEFAULT '0' COMMENT 'Contact prefers to not be searchable', + `sensitive` boolean NOT NULL DEFAULT '0' COMMENT 'Contact posts sensitive content', + `baseurl` varchar(255) DEFAULT '' COMMENT 'baseurl of the contact', `reason` text COMMENT '', `closeness` tinyint unsigned NOT NULL DEFAULT 99 COMMENT '', `info` mediumtext COMMENT '', diff --git a/src/Model/APContact.php b/src/Model/APContact.php index b027d6c478..6d50582e68 100644 --- a/src/Model/APContact.php +++ b/src/Model/APContact.php @@ -270,10 +270,7 @@ class APContact extends BaseObject } // Update the gcontact table - // These two fields don't exist in the gcontact table - unset($contact_fields['forum']); - unset($contact_fields['prv']); - DBA::update('gcontact', $contact_fields, ['nurl' => Strings::normaliseLink($url)]); + GContact::updateFromPublicContactURL($url); Logger::log('Updated profile for ' . $url, Logger::DEBUG); diff --git a/src/Model/Contact.php b/src/Model/Contact.php index c980482dee..20dfc4d352 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -1400,6 +1400,7 @@ class Contact extends BaseObject 'request' => defaults($data, 'request', ''), 'confirm' => defaults($data, 'confirm', ''), 'poco' => defaults($data, 'poco', ''), + 'baseurl' => defaults($data, 'baseurl', ''), 'name-date' => DateTimeFormat::utcNow(), 'uri-date' => DateTimeFormat::utcNow(), 'avatar-date' => DateTimeFormat::utcNow(), @@ -1453,7 +1454,7 @@ class Contact extends BaseObject self::updateAvatar($data['photo'], $uid, $contact_id); } - $fields = ['url', 'nurl', 'addr', 'alias', 'name', 'nick', 'keywords', 'location', 'about', 'avatar-date', 'pubkey']; + $fields = ['url', 'nurl', 'addr', 'alias', 'name', 'nick', 'keywords', 'location', 'about', 'avatar-date', 'pubkey', 'baseurl']; $contact = DBA::selectFirst('contact', $fields, ['id' => $contact_id]); // This condition should always be true @@ -1467,7 +1468,8 @@ class Contact extends BaseObject 'url' => $data['url'], 'nurl' => Strings::normaliseLink($data['url']), 'name' => $data['name'], - 'nick' => $data['nick'] + 'nick' => $data['nick'], + 'baseurl' => $data['baseurl'] ]; if (!empty($data['keywords'])) { @@ -1820,7 +1822,7 @@ class Contact extends BaseObject */ $fields = ['avatar', 'uid', 'name', 'nick', 'url', 'addr', 'batch', 'notify', - 'poll', 'request', 'confirm', 'poco', 'network', 'alias']; + 'poll', 'request', 'confirm', 'poco', 'network', 'alias', 'baseurl']; $contact = DBA::selectFirst('contact', $fields, ['id' => $id]); if (!DBA::isResult($contact)) { return false; @@ -1849,7 +1851,7 @@ class Contact extends BaseObject // make sure to not overwrite existing values with blank entries foreach ($ret as $key => $val) { - if (!isset($contact[$key])) { + if (!array_key_exists($key, $contact)) { unset($ret[$key]); } elseif (($contact[$key] != '') && ($val == '')) { $ret[$key] = $contact[$key]; @@ -2082,6 +2084,7 @@ class Contact extends BaseObject 'name' => $ret['name'], 'nick' => $ret['nick'], 'network' => $ret['network'], + 'baseurl' => $ret['baseurl'], 'protocol' => $protocol, 'pubkey' => $ret['pubkey'], 'rel' => $new_relation, diff --git a/src/Model/GContact.php b/src/Model/GContact.php index 4fb766193f..7da5f18e94 100644 --- a/src/Model/GContact.php +++ b/src/Model/GContact.php @@ -873,20 +873,20 @@ class GContact * @brief Updates the gcontact entry from a given public contact url * * @param string $url contact url - * @return void + * @return integer gcontact id * @throws \Friendica\Network\HTTPException\InternalServerErrorException * @throws \ImagickException */ public static function updateFromPublicContactURL($url) { - self::updateFromPublicContact(['nurl' => Strings::normaliseLink($url)]); + return self::updateFromPublicContact(['nurl' => Strings::normaliseLink($url)]); } /** * @brief Helper function for updateFromPublicContactID and updateFromPublicContactURL * * @param array $condition contact condition - * @return void + * @return integer gcontact id * @throws \Friendica\Network\HTTPException\InternalServerErrorException * @throws \ImagickException */ @@ -894,19 +894,18 @@ class GContact { $fields = ['name', 'nick', 'url', 'nurl', 'location', 'about', 'keywords', 'gender', 'bd', 'contact-type', 'network', 'addr', 'notify', 'alias', 'archive', 'term-date', - 'created', 'updated', 'avatar', 'success_update', 'failure_update', 'forum', 'prv']; + 'created', 'updated', 'avatar', 'success_update', 'failure_update', 'forum', 'prv', + 'baseurl', 'sensitive', 'unsearchable']; + $contact = DBA::selectFirst('contact', $fields, array_merge($condition, ['uid' => 0, 'network' => Protocol::FEDERATED])); if (!DBA::isResult($contact)) { - return; + return 0; } - // These fields cannot be updated, since they don't exist in the contact table - // hide, nsfw, server_url - // "connect" does exist, but seems to contain the same as "addr" - $fields = ['name', 'nick', 'url', 'nurl', 'location', 'about', 'keywords', 'gender', 'generation', 'birthday', 'contact-type', 'network', 'addr', 'notify', 'alias', 'archived', 'archive_date', - 'created', 'updated', 'photo', 'last_contact', 'last_failure', 'community', 'connect']; + 'created', 'updated', 'photo', 'last_contact', 'last_failure', 'community', 'connect', + 'server_url', 'nsfw', 'hide', 'id']; $old_gcontact = DBA::selectFirst('gcontact', $fields, ['nurl' => $contact['nurl']]); $do_insert = !DBA::isResult($old_gcontact); @@ -917,6 +916,12 @@ class GContact $gcontact = $contact; // These fields are having different names but the same content + $gcontact['server_url'] = $gcontact['baseurl']; + unset($gcontact['baseurl']); + $gcontact['nsfw'] = $gcontact['sensitive']; + unset($gcontact['sensitive']); + $gcontact['hide'] = $gcontact['unsearchable']; + unset($gcontact['unsearchable']); $gcontact['archived'] = $gcontact['archive']; unset($gcontact['archive']); $gcontact['archive_date'] = $gcontact['term-date']; @@ -958,8 +963,10 @@ class GContact if (!$do_insert) { DBA::update('gcontact', $gcontact, ['nurl' => $contact['nurl']], $old_gcontact); + return $old_gcontact['id']; } elseif (!$gcontact['archived']) { DBA::insert('gcontact', $gcontact); + return DBA::lastInsertId(); } } diff --git a/src/Network/Probe.php b/src/Network/Probe.php index a3fe3ca336..5c20cc071f 100644 --- a/src/Network/Probe.php +++ b/src/Network/Probe.php @@ -17,7 +17,6 @@ use Friendica\Core\Logger; use Friendica\Core\Protocol; use Friendica\Core\System; use Friendica\Database\DBA; -use Friendica\Model\Contact; use Friendica\Model\Profile; use Friendica\Protocol\ActivityPub; use Friendica\Protocol\Email; @@ -396,114 +395,6 @@ class Probe // Only store into the cache if the value seems to be valid if (!in_array($data['network'], [Protocol::PHANTOM, Protocol::MAIL])) { Cache::set('Probe::uri:' . $network . ':' . $uri, $data, Cache::DAY); - - /// @todo temporary fix - we need a real contact update function that updates only changing fields - /// The biggest problem is the avatar picture that could have a reduced image size. - /// It should only be updated if the existing picture isn't existing anymore. - /// We only update the contact when it is no probing for a specific network. - if (($data['network'] != Protocol::FEED) - && ($network == '') - && $data['name'] - && $data['nick'] - && $data['url'] - && $data['addr'] - && $data['poll'] - ) { - $fields = [ - 'name' => $data['name'], - 'nick' => $data['nick'], - 'url' => $data['url'], - 'addr' => $data['addr'], - 'photo' => $data['photo'], - 'keywords' => $data['keywords'], - 'location' => $data['location'], - 'about' => $data['about'], - 'notify' => $data['notify'], - 'network' => $data['network'], - 'server_url' => $data['baseurl'] - ]; - - // This doesn't cover the case when a community isn't a community anymore - if (!empty($data['community']) && $data['community']) { - $fields['community'] = $data['community']; - $fields['contact-type'] = Contact::TYPE_COMMUNITY; - } - - $fieldnames = []; - - foreach ($fields as $key => $val) { - if (empty($val)) { - unset($fields[$key]); - } else { - $fieldnames[] = $key; - } - } - - $fields['updated'] = DateTimeFormat::utcNow(); - - $condition = ['nurl' => Strings::normaliseLink($data['url'])]; - - $old_fields = DBA::selectFirst('gcontact', $fieldnames, $condition); - - // When the gcontact doesn't exist, the value "true" will trigger an insert. - // In difference to the public contacts we want to have every contact - // in the world in our global contacts. - if (!$old_fields) { - $old_fields = true; - - // These values have to be set only on insert - $fields['photo'] = $data['photo']; - $fields['created'] = DateTimeFormat::utcNow(); - } - - DBA::update('gcontact', $fields, $condition, $old_fields); - - $fields = [ - 'name' => $data['name'], - 'nick' => $data['nick'], - 'url' => $data['url'], - 'addr' => $data['addr'], - 'alias' => $data['alias'], - 'keywords' => $data['keywords'], - 'location' => $data['location'], - 'about' => $data['about'], - 'batch' => $data['batch'], - 'notify' => $data['notify'], - 'poll' => $data['poll'], - 'request' => $data['request'], - 'confirm' => $data['confirm'], - 'poco' => $data['poco'], - 'network' => $data['network'], - 'pubkey' => $data['pubkey'], - 'priority' => $data['priority'], - 'writable' => true, - 'rel' => Contact::SHARING - ]; - - $fieldnames = []; - - foreach ($fields as $key => $val) { - if (empty($val)) { - unset($fields[$key]); - } else { - $fieldnames[] = $key; - } - } - - $condition = ['nurl' => Strings::normaliseLink($data['url']), 'self' => false, 'uid' => 0]; - - // "$old_fields" will return a "false" when the contact doesn't exist. - // This won't trigger an insert. This is intended, since we only need - // public contacts for everyone we store items from. - // We don't need to store every contact on the planet. - $old_fields = DBA::selectFirst('contact', $fieldnames, $condition); - - $fields['name-date'] = DateTimeFormat::utcNow(); - $fields['uri-date'] = DateTimeFormat::utcNow(); - $fields['success_update'] = DateTimeFormat::utcNow(); - - DBA::update('contact', $fields, $condition, $old_fields); - } } return $data; diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php index 41aed2fe3b..101942642e 100644 --- a/src/Protocol/ActivityPub/Processor.php +++ b/src/Protocol/ActivityPub/Processor.php @@ -612,6 +612,7 @@ class Processor Logger::log('Updating profile for ' . $activity['object_id'], Logger::DEBUG); APContact::getByURL($activity['object_id'], true); +// Contact::updateFromProbe($activity['object_id'], $network = '', $force = false) } /** diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php index a5deb490b0..4c5f20c63e 100644 --- a/src/Protocol/DFRN.php +++ b/src/Protocol/DFRN.php @@ -1742,6 +1742,11 @@ class DFRN (strtotime($contact['avatar-date']) > strtotime($contact_old['avatar-date']) || ($author['avatar'] != $contact_old['avatar'])) ); + // Update the "hidden" status in the public contact + // @todo Updating the contact with all fields and update the gcontact from that + $condition = ['uid' => 0, 'nurl' => Strings::normaliseLink($contact_old['url'])]; + DBA::update('contact', ['unsearchable' => $hide], $condition, true); + /* * The generation is a sign for the reliability of the provided data. * It is used in the socgraph.php to prevent that old contact data diff --git a/src/Protocol/Diaspora.php b/src/Protocol/Diaspora.php index f7d94256ee..31d9efa18f 100644 --- a/src/Protocol/Diaspora.php +++ b/src/Protocol/Diaspora.php @@ -2258,8 +2258,8 @@ class Diaspora $fields = ['name' => $name, 'location' => $location, 'name-date' => DateTimeFormat::utcNow(), 'about' => $about, 'gender' => $gender, - 'addr' => $author, 'nick' => $nick, - 'keywords' => $keywords]; + 'addr' => $author, 'nick' => $nick, 'keywords' => $keywords, + 'unsearchable' => !$searchable, 'sensitive' => $nsfw]; if (!empty($birthday)) { $fields['bd'] = $birthday;