Poco and gcontact (mostly) removed

This commit is contained in:
Michael 2020-08-01 16:15:18 +00:00
parent a9a9f7d51d
commit 0c73531da1
34 changed files with 370 additions and 2032 deletions

View file

@ -33,7 +33,6 @@ use Friendica\DI;
use Friendica\Model\Contact;
use Friendica\Model\Conversation;
use Friendica\Model\Event;
use Friendica\Model\GContact;
use Friendica\Model\Item;
use Friendica\Model\ItemURI;
use Friendica\Model\Mail;
@ -1686,21 +1685,6 @@ class DFRN
if (!empty($pcid)) {
Contact::updateAvatar($pcid, $author['avatar']);
}
/*
* 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
* that was relayed over several servers can overwrite contact
* data that we received directly.
*/
$poco["generation"] = 2;
$poco["photo"] = $author["avatar"];
$poco["hide"] = $hide;
$poco["contact-type"] = $contact["contact-type"];
$gcid = GContact::update($poco);
GContact::link($gcid, $importer["importer_uid"], $contact["id"]);
}
return $author;
@ -1943,15 +1927,6 @@ class DFRN
$old = $r[0];
// Update the gcontact entry
$relocate["server_url"] = preg_replace("=(https?://)(.*)/profile/(.*)=ism", "$1$2", $relocate["url"]);
$fields = ['name' => $relocate["name"], 'photo' => $relocate["avatar"],
'url' => $relocate["url"], 'nurl' => Strings::normaliseLink($relocate["url"]),
'addr' => $relocate["addr"], 'connect' => $relocate["addr"],
'notify' => $relocate["notify"], 'server_url' => $relocate["server_url"]];
DBA::update('gcontact', $fields, ['nurl' => Strings::normaliseLink($old["url"])]);
// Update the contact table. We try to find every entry.
$fields = ['name' => $relocate["name"], 'avatar' => $relocate["avatar"],
'url' => $relocate["url"], 'nurl' => Strings::normaliseLink($relocate["url"]),

View file

@ -34,7 +34,6 @@ use Friendica\Database\DBA;
use Friendica\DI;
use Friendica\Model\Contact;
use Friendica\Model\Conversation;
use Friendica\Model\GContact;
use Friendica\Model\Item;
use Friendica\Model\ItemURI;
use Friendica\Model\Mail;
@ -1656,7 +1655,7 @@ class Diaspora
// Update the profile
self::receiveProfile($importer, $data->profile);
// change the technical stuff in contact and gcontact
// change the technical stuff in contact
$data = Probe::uri($new_handle);
if ($data['network'] == Protocol::PHANTOM) {
Logger::log('Account for '.$new_handle." couldn't be probed.");
@ -1671,14 +1670,6 @@ class Diaspora
DBA::update('contact', $fields, ['addr' => $old_handle]);
$fields = ['url' => $data['url'], 'nurl' => Strings::normaliseLink($data['url']),
'name' => $data['name'], 'nick' => $data['nick'],
'addr' => $data['addr'], 'connect' => $data['addr'],
'notify' => $data['notify'], 'photo' => $data['photo'],
'server_url' => $data['baseurl'], 'network' => $data['network']];
DBA::update('gcontact', $fields, ['addr' => $old_handle]);
Logger::log('Contacts are updated.');
return true;
@ -1702,8 +1693,6 @@ class Diaspora
}
DBA::close($contacts);
DBA::delete('gcontact', ['addr' => $author]);
Logger::log('Removed contacts for ' . $author);
return true;
@ -2438,18 +2427,6 @@ class Diaspora
DBA::update('contact', $fields, ['id' => $contact['id']]);
// @todo Update the public contact, then update the gcontact from that
$gcontact = ["url" => $contact["url"], "network" => Protocol::DIASPORA, "generation" => 2,
"photo" => $image_url, "name" => $name, "location" => $location,
"about" => $about, "birthday" => $birthday,
"addr" => $author, "nick" => $nick, "keywords" => $keywords,
"hide" => !$searchable, "nsfw" => $nsfw];
$gcid = GContact::update($gcontact);
GContact::link($gcid, $importer["uid"], $contact["id"]);
Logger::log("Profile of contact ".$contact["id"]." stored for user ".$importer["uid"], Logger::DEBUG);
return true;

View file

@ -34,7 +34,6 @@ use Friendica\DI;
use Friendica\Model\APContact;
use Friendica\Model\Contact;
use Friendica\Model\Conversation;
use Friendica\Model\GContact;
use Friendica\Model\Item;
use Friendica\Model\ItemURI;
use Friendica\Model\Tag;
@ -240,15 +239,6 @@ class OStatus
Contact::updateAvatar($cid, $author["author-avatar"]);
}
}
$contact["generation"] = 2;
$contact["hide"] = false; // OStatus contacts are never hidden
if (!empty($author["author-avatar"])) {
$contact["photo"] = $author["author-avatar"];
}
$gcid = GContact::update($contact);
GContact::link($gcid, $contact["uid"], $contact["id"]);
} elseif (empty($contact["network"]) || ($contact["network"] != Protocol::DFRN)) {
$contact = [];
}

View file

@ -1,486 +0,0 @@
<?php
/**
* @copyright Copyright (C) 2020, Friendica
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
namespace Friendica\Protocol;
use Exception;
use Friendica\Content\Text\HTML;
use Friendica\Core\Logger;
use Friendica\Core\Protocol;
use Friendica\Core\Worker;
use Friendica\Database\DBA;
use Friendica\DI;
use Friendica\Model\GContact;
use Friendica\Model\GServer;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\Strings;
/**
*
* @todo Move GNU Social URL schemata (http://server.tld/user/number) to http://server.tld/username
* @todo Fetch profile data from profile page for Redmatrix users
* @todo Detect if it is a forum
*/
class PortableContact
{
const DISABLED = 0;
const USERS = 1;
const USERS_GCONTACTS = 2;
const USERS_GCONTACTS_FALLBACK = 3;
/**
* Fetch POCO data
*
* @param integer $cid Contact ID
* @param integer $uid User ID
* @param integer $zcid Global Contact ID
* @param integer $url POCO address that should be polled
*
* Given a contact-id (minimum), load the PortableContacts friend list for that contact,
* and add the entries to the gcontact (Global Contact) table, or update existing entries
* if anything (name or photo) has changed.
* We use normalised urls for comparison which ignore http vs https and www.domain vs domain
*
* Once the global contact is stored add (if necessary) the contact linkage which associates
* the given uid, cid to the global contact entry. There can be many uid/cid combinations
* pointing to the same global contact id.
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function loadWorker($cid, $uid = 0, $zcid = 0, $url = null)
{
// Call the function "load" via the worker
Worker::add(PRIORITY_LOW, 'FetchPoCo', (int)$cid, (int)$uid, (int)$zcid, $url);
}
/**
* Fetch POCO data from the worker
*
* @param integer $cid Contact ID
* @param integer $uid User ID
* @param integer $zcid Global Contact ID
* @param integer $url POCO address that should be polled
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function load($cid, $uid, $zcid, $url)
{
if ($cid) {
if (!$url || !$uid) {
$contact = DBA::selectFirst('contact', ['poco', 'uid'], ['id' => $cid]);
if (DBA::isResult($contact)) {
$url = $contact['poco'];
$uid = $contact['uid'];
}
}
if (!$uid) {
return;
}
}
if (!$url) {
return;
}
$url = $url . (($uid) ? '/@me/@all?fields=displayName,urls,photos,updated,network,aboutMe,currentLocation,tags,contactType,generation' : '?fields=displayName,urls,photos,updated,network,aboutMe,currentLocation,tags,contactType,generation');
Logger::log('load: ' . $url, Logger::DEBUG);
$fetchresult = DI::httpRequest()->fetchFull($url);
$s = $fetchresult->getBody();
Logger::log('load: returns ' . $s, Logger::DATA);
Logger::log('load: return code: ' . $fetchresult->getReturnCode(), Logger::DEBUG);
if (($fetchresult->getReturnCode() > 299) || (! $s)) {
return;
}
$j = json_decode($s, true);
Logger::debug('load', ['json' => $j]);
if (!isset($j['entry'])) {
return;
}
$total = 0;
foreach ($j['entry'] as $entry) {
$total ++;
$profile_url = '';
$profile_photo = '';
$connect_url = '';
$name = '';
$network = '';
$updated = DBA::NULL_DATETIME;
$location = '';
$about = '';
$keywords = '';
$contact_type = -1;
$generation = 0;
if (!empty($entry['displayName'])) {
$name = $entry['displayName'];
}
if (isset($entry['urls'])) {
foreach ($entry['urls'] as $url) {
if ($url['type'] == 'profile') {
$profile_url = $url['value'];
continue;
}
if ($url['type'] == 'webfinger') {
$connect_url = str_replace('acct:', '', $url['value']);
continue;
}
}
}
if (isset($entry['photos'])) {
foreach ($entry['photos'] as $photo) {
if ($photo['type'] == 'profile') {
$profile_photo = $photo['value'];
continue;
}
}
}
if (isset($entry['updated'])) {
$updated = date(DateTimeFormat::MYSQL, strtotime($entry['updated']));
}
if (isset($entry['network'])) {
$network = $entry['network'];
}
if (isset($entry['currentLocation'])) {
$location = $entry['currentLocation'];
}
if (isset($entry['aboutMe'])) {
$about = HTML::toBBCode($entry['aboutMe']);
}
if (isset($entry['generation']) && ($entry['generation'] > 0)) {
$generation = ++$entry['generation'];
}
if (isset($entry['tags'])) {
foreach ($entry['tags'] as $tag) {
$keywords = implode(", ", $tag);
}
}
if (isset($entry['contactType']) && ($entry['contactType'] >= 0)) {
$contact_type = $entry['contactType'];
}
$gcontact = ["url" => $profile_url,
"name" => $name,
"network" => $network,
"photo" => $profile_photo,
"about" => $about,
"location" => $location,
"keywords" => $keywords,
"connect" => $connect_url,
"updated" => $updated,
"contact-type" => $contact_type,
"generation" => $generation];
try {
$gcontact = GContact::sanitize($gcontact);
$gcid = GContact::update($gcontact);
GContact::link($gcid, $uid, $cid, $zcid);
} catch (Exception $e) {
Logger::log($e->getMessage(), Logger::DEBUG);
}
}
Logger::log("load: loaded $total entries", Logger::DEBUG);
$condition = ["`cid` = ? AND `uid` = ? AND `zcid` = ? AND `updated` < UTC_TIMESTAMP - INTERVAL 2 DAY", $cid, $uid, $zcid];
DBA::delete('glink', $condition);
}
/**
* Returns a list of all known servers
* @return array List of server urls
* @throws Exception
*/
public static function serverlist()
{
$r = q(
"SELECT `url`, `site_name` AS `displayName`, `network`, `platform`, `version` FROM `gserver`
WHERE `network` IN ('%s', '%s', '%s') AND NOT `failed`
ORDER BY `last_contact`
LIMIT 1000",
DBA::escape(Protocol::DFRN),
DBA::escape(Protocol::DIASPORA),
DBA::escape(Protocol::OSTATUS)
);
if (!DBA::isResult($r)) {
return false;
}
return $r;
}
/**
* Fetch server list from remote servers and adds them when they are new.
*
* @param string $poco URL to the POCO endpoint
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
private static function fetchServerlist($poco)
{
$curlResult = DI::httpRequest()->get($poco . "/@server");
if (!$curlResult->isSuccess()) {
return;
}
$serverlist = json_decode($curlResult->getBody(), true);
if (!is_array($serverlist)) {
return;
}
foreach ($serverlist as $server) {
$server_url = str_replace("/index.php", "", $server['url']);
$r = q("SELECT `nurl` FROM `gserver` WHERE `nurl` = '%s'", DBA::escape(Strings::normaliseLink($server_url)));
if (!DBA::isResult($r)) {
Logger::log("Call server check for server ".$server_url, Logger::DEBUG);
Worker::add(PRIORITY_LOW, 'UpdateGServer', $server_url);
}
}
}
public static function discoverSingleServer($id)
{
$server = DBA::selectFirst('gserver', ['poco', 'nurl', 'url', 'network'], ['id' => $id]);
if (!DBA::isResult($server)) {
return false;
}
// Discover new servers out there (Works from Friendica version 3.5.2)
self::fetchServerlist($server["poco"]);
// Fetch all users from the other server
$url = $server["poco"] . "/?fields=displayName,urls,photos,updated,network,aboutMe,currentLocation,tags,contactType,generation";
Logger::info("Fetch all users from the server " . $server["url"]);
$curlResult = DI::httpRequest()->get($url);
if ($curlResult->isSuccess() && !empty($curlResult->getBody())) {
$data = json_decode($curlResult->getBody(), true);
if (!empty($data)) {
self::discoverServer($data, 2);
}
if (DI::config()->get('system', 'poco_discovery') >= self::USERS_GCONTACTS) {
$timeframe = DI::config()->get('system', 'poco_discovery_since');
if ($timeframe == 0) {
$timeframe = 30;
}
$updatedSince = date(DateTimeFormat::MYSQL, time() - $timeframe * 86400);
// Fetch all global contacts from the other server (Not working with Redmatrix and Friendica versions before 3.3)
$url = $server["poco"]."/@global?updatedSince=".$updatedSince."&fields=displayName,urls,photos,updated,network,aboutMe,currentLocation,tags,contactType,generation";
$success = false;
$curlResult = DI::httpRequest()->get($url);
if ($curlResult->isSuccess() && !empty($curlResult->getBody())) {
Logger::info("Fetch all global contacts from the server " . $server["nurl"]);
$data = json_decode($curlResult->getBody(), true);
if (!empty($data)) {
$success = self::discoverServer($data);
}
}
if (!$success && !empty($data) && DI::config()->get('system', 'poco_discovery') >= self::USERS_GCONTACTS_FALLBACK) {
Logger::info("Fetch contacts from users of the server " . $server["nurl"]);
self::discoverServerUsers($data, $server);
}
}
return true;
} else {
// If the server hadn't replied correctly, then force a sanity check
GServer::check($server["url"], $server["network"], true);
return false;
}
}
private static function discoverServerUsers(array $data, array $server)
{
if (!isset($data['entry'])) {
return;
}
foreach ($data['entry'] as $entry) {
$username = '';
if (isset($entry['urls'])) {
foreach ($entry['urls'] as $url) {
if ($url['type'] == 'profile') {
$profile_url = $url['value'];
$path_array = explode('/', parse_url($profile_url, PHP_URL_PATH));
$username = end($path_array);
}
}
}
if ($username != '') {
Logger::log('Fetch contacts for the user ' . $username . ' from the server ' . $server['nurl'], Logger::DEBUG);
// Fetch all contacts from a given user from the other server
$url = $server['poco'] . '/' . $username . '/?fields=displayName,urls,photos,updated,network,aboutMe,currentLocation,tags,contactType,generation';
$curlResult = DI::httpRequest()->get($url);
if ($curlResult->isSuccess()) {
$data = json_decode($curlResult->getBody(), true);
if (!empty($data)) {
self::discoverServer($data, 3);
}
}
}
}
}
private static function discoverServer(array $data, $default_generation = 0)
{
if (empty($data['entry'])) {
return false;
}
$success = false;
foreach ($data['entry'] as $entry) {
$profile_url = '';
$profile_photo = '';
$connect_url = '';
$name = '';
$network = '';
$updated = DBA::NULL_DATETIME;
$location = '';
$about = '';
$keywords = '';
$contact_type = -1;
$generation = $default_generation;
if (!empty($entry['displayName'])) {
$name = $entry['displayName'];
}
if (isset($entry['urls'])) {
foreach ($entry['urls'] as $url) {
if ($url['type'] == 'profile') {
$profile_url = $url['value'];
continue;
}
if ($url['type'] == 'webfinger') {
$connect_url = str_replace('acct:' , '', $url['value']);
continue;
}
}
}
if (isset($entry['photos'])) {
foreach ($entry['photos'] as $photo) {
if ($photo['type'] == 'profile') {
$profile_photo = $photo['value'];
continue;
}
}
}
if (isset($entry['updated'])) {
$updated = date(DateTimeFormat::MYSQL, strtotime($entry['updated']));
}
if (isset($entry['network'])) {
$network = $entry['network'];
}
if (isset($entry['currentLocation'])) {
$location = $entry['currentLocation'];
}
if (isset($entry['aboutMe'])) {
$about = HTML::toBBCode($entry['aboutMe']);
}
if (isset($entry['generation']) && ($entry['generation'] > 0)) {
$generation = ++$entry['generation'];
}
if (isset($entry['contactType']) && ($entry['contactType'] >= 0)) {
$contact_type = $entry['contactType'];
}
if (isset($entry['tags'])) {
foreach ($entry['tags'] as $tag) {
$keywords = implode(", ", $tag);
}
}
if ($generation > 0) {
$success = true;
Logger::log("Store profile ".$profile_url, Logger::DEBUG);
$gcontact = ["url" => $profile_url,
"name" => $name,
"network" => $network,
"photo" => $profile_photo,
"about" => $about,
"location" => $location,
"keywords" => $keywords,
"connect" => $connect_url,
"updated" => $updated,
"contact-type" => $contact_type,
"generation" => $generation];
try {
$gcontact = GContact::sanitize($gcontact);
GContact::update($gcontact);
} catch (Exception $e) {
Logger::log($e->getMessage(), Logger::DEBUG);
}
Logger::log("Done for profile ".$profile_url, Logger::DEBUG);
}
}
return $success;
}
}