diff options
author | Maxence Lange <maxence@artificial-owl.com> | 2019-02-21 08:38:04 -0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-02-21 08:38:04 -0100 |
commit | 8a92d5680abfa80302dafb421699ceb0d0aa74fc (patch) | |
tree | a1f6bae5384f7f7b01385ed31c39297fc7a63b8c /lib/Service | |
parent | 2f085055cb987e255e86996b49a09a0b1fd12ff0 (diff) | |
parent | aeacebd776a468be247c0502c95fde9db5c1b579 (diff) |
Merge branch 'master' into feature/noid/announce
Diffstat (limited to 'lib/Service')
-rw-r--r-- | lib/Service/AccountService.php | 1 | ||||
-rw-r--r-- | lib/Service/CacheDocumentService.php | 8 | ||||
-rw-r--r-- | lib/Service/CurlService.php | 33 | ||||
-rw-r--r-- | lib/Service/HashtagService.php | 233 | ||||
-rw-r--r-- | lib/Service/NoteService.php | 52 | ||||
-rw-r--r-- | lib/Service/PostService.php | 1 | ||||
-rw-r--r-- | lib/Service/SearchService.php | 190 |
7 files changed, 500 insertions, 18 deletions
diff --git a/lib/Service/AccountService.php b/lib/Service/AccountService.php index 497b732b..13dde24d 100644 --- a/lib/Service/AccountService.php +++ b/lib/Service/AccountService.php @@ -161,6 +161,7 @@ class AccountService { * @throws NoUserException * @throws SocialAppConfigException * @throws UrlCloudException + * @throws ItemUnknownException */ public function getActorFromUserId(string $userId, bool $create = false): Person { $this->miscService->confirmUserId($userId); diff --git a/lib/Service/CacheDocumentService.php b/lib/Service/CacheDocumentService.php index 8f5c3fe0..cf861a2f 100644 --- a/lib/Service/CacheDocumentService.php +++ b/lib/Service/CacheDocumentService.php @@ -33,6 +33,7 @@ namespace OCA\Social\Service; use daita\MySmallPhpTools\Exceptions\MalformedArrayException; use daita\MySmallPhpTools\Model\Request; use daita\MySmallPhpTools\Traits\TArrayTools; +use daita\MySmallPhpTools\Traits\TStringTools; use Exception; use OCA\Social\Exceptions\CacheContentException; use OCA\Social\Exceptions\CacheContentMimeTypeException; @@ -52,6 +53,7 @@ class CacheDocumentService { use TArrayTools; + use TStringTools; /** @var IAppData */ @@ -103,11 +105,7 @@ class CacheDocumentService { */ public function saveRemoteFileToCache(string $url, &$mime = '') { - $filename = sprintf( - '%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 0xffff), mt_rand(0, 0xffff), - mt_rand(0, 0xffff), mt_rand(0, 0xfff) | 0x4000, mt_rand(0, 0x3fff) | 0x8000, - mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff) - ); + $filename = $this->uuid(); // creating a path aa/bb/cc/dd/ from the filename aabbccdd-0123-[...] $path = chunk_split(substr($filename, 0, 8), 2, '/'); diff --git a/lib/Service/CurlService.php b/lib/Service/CurlService.php index cc257464..8499bc3b 100644 --- a/lib/Service/CurlService.php +++ b/lib/Service/CurlService.php @@ -90,21 +90,15 @@ class CurlService { /** * @param string $account * - * @return Person - * @throws InvalidOriginException + * @return array * @throws InvalidResourceException - * @throws MalformedArrayException - * @throws RedundancyLimitException * @throws RequestContentException - * @throws RetrieveAccountFormatException * @throws RequestNetworkException * @throws RequestResultSizeException * @throws RequestServerException - * @throws SocialAppConfigException - * @throws ItemUnknownException * @throws RequestResultNotJsonException */ - public function retrieveAccount(string $account): Person { + public function webfingerAccount(string $account): array { $account = $this->withoutBeginAt($account); // we consider an account is like an email @@ -122,6 +116,29 @@ class CurlService { $request->setAddress($host); $result = $this->request($request); + return $result; + } + + + /** + * @param string $account + * + * @return Person + * @throws InvalidOriginException + * @throws InvalidResourceException + * @throws MalformedArrayException + * @throws RedundancyLimitException + * @throws RequestContentException + * @throws RetrieveAccountFormatException + * @throws RequestNetworkException + * @throws RequestResultSizeException + * @throws RequestServerException + * @throws SocialAppConfigException + * @throws ItemUnknownException + */ + public function retrieveAccount(string $account): Person { + $result = $this->webfingerAccount($account); + try { $link = $this->extractArray('rel', 'self', $this->getArray('links', $result)); } catch (ArrayNotFoundException $e) { diff --git a/lib/Service/HashtagService.php b/lib/Service/HashtagService.php new file mode 100644 index 00000000..cf1b8e7e --- /dev/null +++ b/lib/Service/HashtagService.php @@ -0,0 +1,233 @@ +<?php +declare(strict_types=1); + + +/** + * Nextcloud - Social Support + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Maxence Lange <maxence@artificial-owl.com> + * @copyright 2018, Maxence Lange <maxence@artificial-owl.com> + * @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 <http://www.gnu.org/licenses/>. + * + */ + + +namespace OCA\Social\Service; + + +use daita\MySmallPhpTools\Traits\TArrayTools; +use OCA\Social\Db\HashtagsRequest; +use OCA\Social\Db\NotesRequest; +use OCA\Social\Exceptions\HashtagDoesNotExistException; + + +class HashtagService { + + + const TREND_1H = 3600; + const TREND_12H = 43200; + const TREND_1D = 86400; + const TREND_3D = 259200; + const TREND_10D = 864000; + + + use TArrayTools; + + + /** @var HashtagsRequest */ + private $hashtagsRequest; + + /** @var NotesRequest */ + private $notesRequest; + + /** @var ConfigService */ + private $configService; + + /** @var MiscService */ + private $miscService; + + + /** + * ImportService constructor. + * + * @param HashtagsRequest $hashtagsRequest + * @param NotesRequest $notesRequest + * @param ConfigService $configService + * @param MiscService $miscService + */ + public function __construct( + HashtagsRequest $hashtagsRequest, NotesRequest $notesRequest, ConfigService $configService, + MiscService $miscService + ) { + $this->hashtagsRequest = $hashtagsRequest; + $this->notesRequest = $notesRequest; + $this->configService = $configService; + $this->miscService = $miscService; + } + + /* + * note: trend is: + * [ + * '1h' => x, + * '12h' => x, + * '1d' => x, + * '3d' => x, + * '10d' => x + * ] + */ + + /** + * + */ + public function manageHashtags(): int { + $current = $this->hashtagsRequest->getAll(); + + $time = time(); + $hashtags = [ + '1h' => $this->getTrendSince($time - self::TREND_1H), + '12h' => $this->getTrendSince($time - self::TREND_12H), + '1d' => $this->getTrendSince($time - self::TREND_1D), + '3d' => $this->getTrendSince($time - self::TREND_3D), + '10d' => $this->getTrendSince($time - self::TREND_10D) + ]; + + $count = 0; + $formatted = $this->formatTrend($hashtags); + foreach ($formatted as $hashtag => $trend) { + $count++; + try { + $this->getFromList($current, $hashtag); + $this->hashtagsRequest->update($hashtag, $trend); + } catch (HashtagDoesNotExistException $e) { + $this->hashtagsRequest->save($hashtag, $trend); + } + } + + return $count; + } + + + /** + * @param string $hashtag + * + * @return array + * @throws HashtagDoesNotExistException + */ + public function getHashtag(string $hashtag): array { + if (substr($hashtag, 0, 1) !== '#') { + $hashtag = '#' . $hashtag; + } + + return $this->hashtagsRequest->getHashtag($hashtag); + } + + + /** + * @param string $hashtag + * + * @return array + */ + public function searchHashtags(string $hashtag): array { + return $this->hashtagsRequest->searchHashtags($hashtag); + } + + + /** + * @param int $timestamp + * + * @return array + */ + private function getTrendSince(int $timestamp): array { + $result = []; + + $notes = $this->notesRequest->getNotesSince($timestamp); + foreach ($notes as $note) { + + foreach ($note->getHashtags() as $hashtag) { + if (array_key_exists($hashtag, $result)) { + $result[$hashtag]++; + } else { + $result[$hashtag] = 1; + } + } + } + + return $result; + } + + + /** + * @param array $hashtags + * + * @return array + */ + private function formatTrend(array $hashtags): array { + $trends = []; + foreach (end($hashtags) as $hashtag => $count) { + $trends[$hashtag] = []; + } + + $all = array_keys($trends); + $periods = array_keys($hashtags); + foreach ($all as $hashtag) { + foreach ($periods as $period) { + $count = $this->countFromList($hashtags[$period], $hashtag); + $trends[$hashtag][$period] = $count; + } + } + + return $trends; + } + + + /** + * @param array $list + * @param string $hashtag + * + * @return int + */ + private function countFromList(array $list, string $hashtag): int { + foreach ($list as $key => $count) { + if ($key === $hashtag) { + return $count; + } + } + + return 0; + } + + + /** + * @param array $list + * @param string $hashtag + * + * @return array + * @throws HashtagDoesNotExistException + */ + private function getFromList(array $list, string $hashtag): array { + foreach ($list as $item) { + if ($this->get('hashtag', $item, '') === $hashtag) { + return $item; + } + } + + throw new HashtagDoesNotExistException(); + } +} + diff --git a/lib/Service/NoteService.php b/lib/Service/NoteService.php index 8e444523..a4d432a3 100644 --- a/lib/Service/NoteService.php +++ b/lib/Service/NoteService.php @@ -212,7 +212,8 @@ class NoteService { $note->addTag( [ 'type' => 'Mention', - 'href' => $actor->getId() + 'href' => $actor->getId(), + 'name' => '@' . $account ] ); @@ -222,14 +223,30 @@ class NoteService { /** * @param Note $note + * @param string $hashtag + */ + public function addHashtag(Note $note, string $hashtag) { + try { + $note->addTag( + [ + 'type' => 'Hashtag', + 'href' => $this->configService->getCloudAddress() . '/tag/' . strtolower( + $hashtag + ), + 'name' => '#' . $hashtag + ] + ); + } catch (SocialAppConfigException $e) { + } + } + + + /** + * @param Note $note * @param string $type * @param array $accounts */ public function addRecipients(Note $note, string $type, array $accounts) { - if ($accounts === []) { - return; - } - foreach ($accounts as $account) { $this->addRecipient($note, $type, $account); } @@ -238,6 +255,18 @@ class NoteService { /** * @param Note $note + * @param array $hashtags + */ + public function addHashtags(Note $note, array $hashtags) { + $note->setHashtags($hashtags); + foreach ($hashtags as $hashtag) { + $this->addHashtag($note, $hashtag); + } + } + + + /** + * @param Note $note * @param string $replyTo * * @throws InvalidOriginException @@ -356,6 +385,19 @@ class NoteService { /** + * @param Person $actor + * @param string $hashtag + * @param int $since + * @param int $limit + * + * @return Note[] + */ + public function getStreamLocalTag(Person $actor, string $hashtag, int $since = 0, int $limit = 5): array { + return $this->notesRequest->getStreamTag($actor, $hashtag, $since, $limit); + } + + + /** * @param int $since * @param int $limit * diff --git a/lib/Service/PostService.php b/lib/Service/PostService.php index 89c0f603..817ddc40 100644 --- a/lib/Service/PostService.php +++ b/lib/Service/PostService.php @@ -104,6 +104,7 @@ class PostService { $this->noteService->replyTo($note, $post->getReplyTo()); $this->noteService->addRecipients($note, $post->getType(), $post->getTo()); + $this->noteService->addHashtags($note, $post->getHashtags()); $result = $this->activityService->createActivity($post->getActor(), $note, $activity); $this->accountService->cacheLocalActorDetailCount($post->getActor()); diff --git a/lib/Service/SearchService.php b/lib/Service/SearchService.php new file mode 100644 index 00000000..e30d9b81 --- /dev/null +++ b/lib/Service/SearchService.php @@ -0,0 +1,190 @@ +<?php +declare(strict_types=1); + + +/** + * Nextcloud - Social Support + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Maxence Lange <maxence@artificial-owl.com> + * @copyright 2018, Maxence Lange <maxence@artificial-owl.com> + * @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 <http://www.gnu.org/licenses/>. + * + */ + + +namespace OCA\Social\Service; + + +use daita\MySmallPhpTools\Traits\TArrayTools; +use Exception; + + +class SearchService { + + + use TArrayTools; + + + const SEARCH_ACCOUNTS = 1; + const SEARCH_HASHTAGS = 2; + const SEARCH_CONTENT = 4; + const SEARCH_ALL = 7; + + + /** @var CacheActorService */ + private $cacheActorService; + + /** @var HashtagService */ + private $hashtagService; + + /** @var ConfigService */ + private $configService; + + /** @var MiscService */ + private $miscService; + + + /** + * ImportService constructor. + * + * @param CacheActorService $cacheActorService + * @param HashtagService $hashtagService + * @param ConfigService $configService + * @param MiscService $miscService + */ + public function __construct( + CacheActorService $cacheActorService, HashtagService $hashtagService, + ConfigService $configService, MiscService $miscService + ) { + $this->cacheActorService = $cacheActorService; + $this->hashtagService = $hashtagService; + $this->configService = $configService; + $this->miscService = $miscService; + } + + + /** + * @param string $search + * + * @return array + */ + public function searchAccounts(string $search): array { + $result = [ + 'exact' => null, + 'result' => [] + ]; + + $type = $this->getTypeFromSearch($search); + if ($search === '' || !$type & self::SEARCH_ACCOUNTS) { + return $result; + } + + if (substr($search, 0, 1) === '@') { + $search = substr($search, 1); + } + + try { + $exact = $this->cacheActorService->getFromAccount($search); + $exact->setCompleteDetails(true); + $result['exact'] = $exact; + } catch (Exception $e) { + } + + try { + $accounts = $this->cacheActorService->searchCachedAccounts($search); + $result['result'] = $accounts; + } catch (Exception $e) { + } + + return $result; + } + + + /** + * @param string $search + * + * @return array + */ + public function searchHashtags(string $search): array { + $result = [ + 'exact' => null, + 'result' => [] + ]; + + $type = $this->getTypeFromSearch($search); + if ($search === '' || !$type & self::SEARCH_HASHTAGS) { + return $result; + } + + try { + $exact = $this->hashtagService->getHashtag($search); + $result['exact'] = $exact; + } catch (Exception $e) { + } + + try { + $hashtags = $this->hashtagService->searchHashtags($search); + $result['result'] = $hashtags; + } catch (Exception $e) { + } + + return $result; + } + + + /** + * @param string $search + * + * @return array + */ + public function searchStreamContent(string $search): array { + $result = []; + + $type = $this->getTypeFromSearch($search); + if ($search === '' || !$type & self::SEARCH_CONTENT) { + return $result; + } + + return $result; + } + + + /** + * @param string $search + * + * @return int + */ + private function getTypeFromSearch(string $search): int { + $char = substr($search, 0, 1); + switch ($char) { + case '@': + return self::SEARCH_ACCOUNTS; + break; + + case '#': + return self::SEARCH_HASHTAGS; + break; + + default: + return self::SEARCH_ALL; + } + } + +} + |