Skip to content

Commit

Permalink
add support for downloading avatars from gravatar
Browse files Browse the repository at this point in the history
adding support for gravatar to the current social providers/services.
because gravatar relies on email instead of the x-socialprofile carddav
field, this requires re-working the current abstraction for how social
providers work.

also in this change is improved support for when a contact card has
multiple fields of the same type (as might be common with email) thus
they all can be checked for profile photos if one of them doesn't result
in a valid photo

Signed-off-by: leith abdulla <online-nextcloud@eleith.com>
  • Loading branch information
eleith committed Nov 1, 2020
1 parent 247b727 commit 296ebf7
Show file tree
Hide file tree
Showing 14 changed files with 644 additions and 146 deletions.
1 change: 1 addition & 0 deletions css/icons.scss
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
@include icon-black-white('twitter', 'contacts', 2); // “twitter (fab)” by fontawesome.com is licensed under CC BY 4.0. (https://fontawesome.com/icons/twitter?style=brands)
@include icon-black-white('diaspora', 'contacts', 2); // “diaspora (fab)” by fontawesome.com is licensed under CC BY 4.0. (https://fontawesome.com/icons/diaspora?style=brands)
@include icon-black-white('xing', 'contacts', 2); // “xing (fab)” by fontawesome.com is licensed under CC BY 4.0. (https://fontawesome.com/icons/xing?style=brands)
@include icon-black-white('gravatar', 'contacts', 2); // “wordpress (fab)” by fontawesome.com is licensed under CC BY 4.0. (https://fontawesome.com/icons/wordpress?style=brands)

.icon-up-force-white {
// using #fffffe to trick the accessibility dark theme icon invert
Expand Down
1 change: 1 addition & 0 deletions img/gravatar.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
59 changes: 26 additions & 33 deletions lib/Service/Social/CompositeSocialProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,19 @@ public function __construct(InstagramProvider $instagramProvider,
TwitterProvider $twitterProvider,
TumblrProvider $tumblrProvider,
DiasporaProvider $diasporaProvider,
XingProvider $xingProvider) {
XingProvider $xingProvider,
GravatarProvider $gravatarProvider) {

// This determines the priority of known providers
$this->providers = [
'instagram' => $instagramProvider,
'mastodon' => $mastodonProvider,
'twitter' => $twitterProvider,
'facebook' => $facebookProvider,
'tumblr' => $tumblrProvider,
'diaspora' => $diasporaProvider,
'xing' => $xingProvider,
$instagramProvider->name => $instagramProvider,
$mastodonProvider->name => $mastodonProvider,
$twitterProvider->name => $twitterProvider,
$facebookProvider->name => $facebookProvider,
$tumblrProvider->name => $tumblrProvider,
$diasporaProvider->name => $diasporaProvider,
$xingProvider->name => $xingProvider,
$gravatarProvider->name => $gravatarProvider
];
}

Expand All @@ -60,40 +62,31 @@ public function getSupportedNetworks() : array {
return array_keys($this->providers);
}


/**
* generate download url for a social entry
*
* @param array socialEntries all social data from the contact
* @param String network the choice which network to use (fallback: take first available)
* @param array contact all social data from the contact
* @param String network the choice which network to use
*
* @returns String the url to the requested information or null in case of errors
* @returns ISocialProvider if provider of 'network' is found, otherwise null
*/
public function getSocialConnector(array $socialEntries, string $network) : ?string {
public function getSocialConnector(string $network) : ?ISocialProvider {
$connector = null;
$selection = $this->providers;
// check if dedicated network selected
if (isset($this->providers[$network])) {
$selection = [$network => $this->providers[$network]];
$connector = $this->providers[$network];
}
return $connector;
}

// check selected providers in order
foreach ($selection as $type => $socialProvider) {

// search for this network in user's profile
foreach ($socialEntries as $socialEntry) {
if (strtolower($type) === strtolower($socialEntry['type'])) {
$profileId = $socialProvider->cleanupId($socialEntry['value']);
if (!is_null($profileId)) {
$connector = $socialProvider->getImageUrl($profileId);
}
break;
}
}
if ($connector) {
break;
}
}
return ($connector);
/**
* generate download url for a social entry
*
* @param array contact all social data from the contact
*
* @return ISocialProvider[] all social providers
*/
public function getSocialConnectors() : array {
return array_values($this->providers);
}
}
103 changes: 86 additions & 17 deletions lib/Service/Social/DiasporaProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,41 +30,67 @@ class DiasporaProvider implements ISocialProvider {
/** @var IClientService */
private $httpClient;

/** @var boolean */
/** @var bool */
private $looping;

/** @var string */
public $name = "diaspora";

public function __construct(IClientService $httpClient) {
$this->httpClient = $httpClient->NewClient();
$this->looping = false;
}

/**
* Returns the profile-id
* Returns if this provider supports this contact
*
* @param {string} the value from the contact's x-socialprofile
* @param {array} contact info
*
* @return string
* @return bool
*/
public function cleanupId(string $candidate):string {
try {
if (strpos($candidate, 'http') !== 0) {
$user_server = explode('@', $candidate);
$candidate = 'https://' . array_pop($user_server) . '/public/' . array_pop($user_server) . '.atom';
}
} catch (Exception $e) {
$candidate = null;
}
return $candidate;
public function supportsContact(array $contact):bool {
$socialprofiles = $contact['X-SOCIALPROFILE'];
$supports = false;
if(isset($socialprofiles)) {
foreach($socialprofiles as $profile) {
if ($profile['type'] == $this->name) {
$supports = true;
break;
}
}
}
return $supports;
}

/**
* Returns all possible profile-picture urls
*
* @param {array} contact information
*
* @return array
*/
public function getImageUrls(array $contact):array {
$profileIds = $this->getProfileIds($contact);
$urls = array();

foreach($profileIds as $profileId) {
$url = $this->getImageUrl($profileId);
if (isset($url)) {
$urls[] = $url;
}
}

return $urls;
}

/**
* Returns the profile-picture url
*
* @param {string} profileId the profile-id
*
* @return string|null
*/
public function getImageUrl(string $profileUrl):?string {
protected function getImageUrl(string $profileUrl):?string {
try {
$result = $this->httpClient->get($profileUrl);
$htmlResult = $result->getBody();
Expand All @@ -82,8 +108,51 @@ public function getImageUrl(string $profileUrl):?string {
}
}
return null;
} catch (Exception $e) {
} catch (\Exception $e) {
return null;
}
}

/**
* Returns all possible profile ids for contact
*
* @param {array} contact information
*
* @return array
*/
protected function getProfileIds($contact):array {
$socialprofiles = $contact['X-SOCIALPROFILE'];
$profileIds = array();

if(isset($socialprofiles)) {
foreach($socialprofiles as $profile) {
if (strtolower($profile['type']) == $this->name) {
$profileId = $this->cleanupId($profile['value']);
if (isset($profileId)) {
$profileIds[] = $profileId;
}
}
}
}
return $profileIds;
}

/**
* Returns the profile-id
*
* @param {string} the value from the contact's x-socialprofile
*
* @return string
*/
protected function cleanupId(string $candidate):?string {
try {
if (strpos($candidate, 'http') !== 0) {
$user_server = explode('@', $candidate);
$candidate = 'https://' . array_pop($user_server) . '/public/' . array_pop($user_server) . '.atom';
}
} catch (Exception $e) {
$candidate = null;
}
return $candidate;
}
}
67 changes: 58 additions & 9 deletions lib/Service/Social/FacebookProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,60 @@ class FacebookProvider implements ISocialProvider {
/** @var IClientService */
private $httpClient;

/** @var string */
public $name = "facebook";

public function __construct(IClientService $httpClient) {
$this->httpClient = $httpClient->NewClient();
}


/**
* Returns if this provider supports this contact
*
* @param {array} contact info
*
* @return bool
*/
public function supportsContact(array $contact):bool {
$socialprofiles = $contact['X-SOCIALPROFILE'];
$supports = false;
if(isset($socialprofiles)) {
foreach($socialprofiles as $profile) {
if (strtolower($profile['type']) == $this->name) {
$supports = true;
break;
}
}
}
return $supports;
}

/**
* Returns the profile-picture url
*
* @param {array} contact information
*
* @return array
*/
public function getImageUrls(array $contact):array {
$profileIds = $this->getProfileIds($contact);
$urls = array();
foreach($profileIds as $profileId) {
$recipe = 'https://graph.facebook.com/{socialId}/picture?width=720';
$connector = str_replace("{socialId}", $profileId, $recipe);
$urls[] = $connector;
}
return $urls;
}

/**
* Returns the profile-id
*
* @param {string} the value from the contact's x-socialprofile
*
* @return string
*/
public function cleanupId(string $candidate):string {
protected function cleanupId(string $candidate):string {
$candidate = basename($candidate);
if (!is_numeric($candidate)) {
$candidate = $this->findFacebookId($candidate);
Expand All @@ -50,16 +92,23 @@ public function cleanupId(string $candidate):string {
}

/**
* Returns the profile-picture url
* Returns all possible profile ids for contact
*
* @param {string} profileId the profile-id
* @param {array} contact information
*
* @return string
* @return array of string profile ids
*/
public function getImageUrl(string $profileId):string {
$recipe = 'https://graph.facebook.com/{socialId}/picture?width=720';
$connector = str_replace("{socialId}", $profileId, $recipe);
return $connector;
protected function getProfileIds($contact):array {
$socialprofiles = $contact['X-SOCIALPROFILE'];
$profileIds = array();
if(isset($socialprofiles)) {
foreach($socialprofiles as $profile) {
if (strtolower($profile['type']) == $this->name) {
$profileIds[] = $this->cleanupId($profile['value']);
}
}
}
return $profileIds;
}

/**
Expand Down
Loading

0 comments on commit 296ebf7

Please sign in to comment.