summaryrefslogtreecommitdiffstats
path: root/lib/Service
diff options
context:
space:
mode:
authorMaxence Lange <maxence@artificial-owl.com>2019-02-21 08:38:04 -0100
committerGitHub <noreply@github.com>2019-02-21 08:38:04 -0100
commit8a92d5680abfa80302dafb421699ceb0d0aa74fc (patch)
treea1f6bae5384f7f7b01385ed31c39297fc7a63b8c /lib/Service
parent2f085055cb987e255e86996b49a09a0b1fd12ff0 (diff)
parentaeacebd776a468be247c0502c95fde9db5c1b579 (diff)
Merge branch 'master' into feature/noid/announce
Diffstat (limited to 'lib/Service')
-rw-r--r--lib/Service/AccountService.php1
-rw-r--r--lib/Service/CacheDocumentService.php8
-rw-r--r--lib/Service/CurlService.php33
-rw-r--r--lib/Service/HashtagService.php233
-rw-r--r--lib/Service/NoteService.php52
-rw-r--r--lib/Service/PostService.php1
-rw-r--r--lib/Service/SearchService.php190
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;
+ }
+ }
+
+}
+