diff options
author | Richard Steinmetz <richard@steinmetz.cloud> | 2023-01-09 10:01:16 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-01-09 10:01:16 +0100 |
commit | e9253b41c5c3b09eeea4da0139cd085d7b300b12 (patch) | |
tree | 7306e7eba72683489214af4cbba6343915770bd6 | |
parent | 219b8442b0cb07c10381bc5878a37de054833d97 (diff) | |
parent | 706e9d5bd29f245ba0ff014d54efd21a39d65bb7 (diff) |
Merge pull request #3170 from nextcloud/backport/3152/stable5.0
[stable5.0] use Mastodon API instead of scraping
-rw-r--r-- | lib/Service/Social/MastodonProvider.php | 50 | ||||
-rw-r--r-- | tests/unit/Service/Social/MastodonProviderTest.php | 39 |
2 files changed, 56 insertions, 33 deletions
diff --git a/lib/Service/Social/MastodonProvider.php b/lib/Service/Social/MastodonProvider.php index 99eb5a58..a5db02a3 100644 --- a/lib/Service/Social/MastodonProvider.php +++ b/lib/Service/Social/MastodonProvider.php @@ -62,7 +62,6 @@ class MastodonProvider implements ISocialProvider { public function getImageUrls(array $contact):array { $profileIds = $this->getProfileIds($contact); $urls = []; - foreach ($profileIds as $profileId) { $url = $this->getImageUrl($profileId); if (isset($url)) { @@ -82,21 +81,15 @@ class MastodonProvider implements ISocialProvider { public function getImageUrl(string $profileUrl):?string { try { $result = $this->httpClient->get($profileUrl); - - $htmlResult = new \DOMDocument(); - $htmlResult->loadHTML($result->getBody()); - $img = $htmlResult->getElementById('profile_page_avatar'); - if (!is_null($img)) { - return $img->getAttribute('data-original'); - } - return null; + $jsonResult = json_decode($result->getBody()); + return $jsonResult->avatar; } catch (\Exception $e) { return null; } } /** - * Returns all possible profile ids for contact + * Returns all possible profile URI for contact by searching the mastodon instance * * @param {array} contact information * @@ -108,9 +101,21 @@ class MastodonProvider implements ISocialProvider { if (isset($socialprofiles)) { foreach ($socialprofiles as $profile) { if (strtolower($profile['type']) == $this->name) { - $profileId = $this->cleanupId($profile['value']); - if (isset($profileId)) { - $profileIds[] = $profileId; + $masto_user_server = $this->cleanupId($profile['value']); + if (isset($masto_user_server)) { + try { + [$masto_user, $masto_server] = $masto_user_server; + # search for user on Mastodon + $search = $masto_server . '/api/v2/search?q=' . $masto_user; + $result = $this->httpClient->get($search); + $jsonResult = json_decode($result->getBody()); + # take first search result + $masto_id = $jsonResult->accounts[0]->id; + $profileId = $masto_server . "/api/v1/accounts/" . $masto_id; + $profileIds[] = $profileId; + } catch (\Exception $e) { + continue; + } } } } @@ -123,18 +128,25 @@ class MastodonProvider implements ISocialProvider { * * @param {string} the value from the contact's x-socialprofile * - * @return string + * @return array username and server instance */ - protected function cleanupId(string $candidate):?string { + protected function cleanupId(string $candidate):?array { $candidate = preg_replace('/^' . preg_quote('x-apple:', '/') . '/', '', $candidate); try { + $user_server = explode('@', $candidate); if (strpos($candidate, 'http') !== 0) { - $user_server = explode('@', $candidate); - $candidate = 'https://' . array_pop($user_server) . '/@' . array_pop($user_server); + $masto_server = "https://" . array_pop($user_server); + $masto_user = array_pop($user_server); + } else { + $masto_user = array_pop($user_server); + $masto_server = array_pop($user_server); + } + if ((empty($masto_server)) || (empty($masto_user))) { + return null; } + return array($masto_user, $masto_server); } catch (\Exception $e) { - $candidate = null; + return null; } - return $candidate; } } diff --git a/tests/unit/Service/Social/MastodonProviderTest.php b/tests/unit/Service/Social/MastodonProviderTest.php index 9611bf6b..db1d6fc3 100644 --- a/tests/unit/Service/Social/MastodonProviderTest.php +++ b/tests/unit/Service/Social/MastodonProviderTest.php @@ -90,20 +90,33 @@ class MastodonProviderTest extends TestCase { $contactWithSocial = [ 'X-SOCIALPROFILE' => [ ["value" => "user1@cloud1", "type" => "mastodon"], - ["value" => "user2@cloud2", "type" => "mastodon"] + ["value" => "@user2@cloud2", "type" => "mastodon"], + ["value" => "https://cloud3/@user3", "type" => "mastodon"], + ["value" => "https://cloud/wrongSyntax", "type" => "mastodon"], + ["value" => "@wrongSyntax", "type" => "mastodon"], + ["value" => "wrongSyntax", "type" => "mastodon"] ] ]; $contactWithSocialUrls = [ - "https://cloud1/@user1", - "https://cloud2/@user2", + "https://cloud1/api/v2/search?q=user1", + "https://cloud2/api/v2/search?q=user2", + "https://cloud3//api/v2/search?q=user3", + "https://cloud1/api/v1/accounts/1", + "https://cloud2/api/v1/accounts/2", + "https://cloud3//api/v1/accounts/3" ]; - $contactWithSocialHtml = [ - '<html><profile id="profile_page_avatar" data-original="user1.jpg" /></html>', - '<html><profile id="profile_page_avatar" data-original="user2.jpg" /></html>' + $contactWithSocialApi = [ + '{"accounts":[{"id":"1","username":"user1"}]}', + '{"accounts":[{"id":"2","username":"user2"}]}', + '{"accounts":[{"id":"3","username":"user3"}]}', + '{"id":"1","avatar":"user1.jpg"}', + '{"id":"2","avatar":"user2.jpg"}', + '{"id":"3","avatar":"user3.jpg"}' ]; $contactWithSocialImgs = [ "user1.jpg", - "user2.jpg" + "user2.jpg", + "user3.jpg" ]; $contactWithoutSocial = [ @@ -113,19 +126,19 @@ class MastodonProviderTest extends TestCase { ] ]; $contactWithoutSocialUrls = []; - $contactWithoutSocialHtml = []; + $contactWithoutSocialApi = []; $contactWithoutSocialImgs = []; return [ 'contact with mastodon fields' => [ $contactWithSocial, - $contactWithSocialHtml, + $contactWithSocialApi, $contactWithSocialUrls, $contactWithSocialImgs ], 'contact without mastodon fields' => [ $contactWithoutSocial, - $contactWithoutSocialHtml, + $contactWithoutSocialApi, $contactWithoutSocialUrls, $contactWithoutSocialImgs ] @@ -135,9 +148,9 @@ class MastodonProviderTest extends TestCase { /** * @dataProvider dataProviderGetImageUrls */ - public function testGetImageUrls($contact, $htmls, $urls, $imgs) { + public function testGetImageUrls($contact, $api, $urls, $imgs) { if (count($urls)) { - $this->response->method("getBody")->willReturnOnConsecutiveCalls(...$htmls); + $this->response->method("getBody")->willReturnOnConsecutiveCalls(...$api); $this->client ->expects($this->exactly(count($urls))) ->method("get") @@ -146,8 +159,6 @@ class MastodonProviderTest extends TestCase { }, $urls)) ->willReturn($this->response); } - - $result = $this->provider->getImageUrls($contact); $this->assertEquals($imgs, $result); } |