new Search endpoint

Signed-off-by: Maxence Lange <maxence@artificial-owl.com>
pull/295/head
Maxence Lange 2019-01-06 12:13:05 -01:00
rodzic 3ef7737d14
commit 833d19617b
6 zmienionych plików z 302 dodań i 5 usunięć

Wyświetl plik

@ -83,6 +83,8 @@ return [
['name' => 'Local#globalActorAvatar', 'url' => '/api/v1/global/actor/avatar', 'verb' => 'GET'],
['name' => 'Local#globalAccountsSearch', 'url' => '/api/v1/global/accounts/search', 'verb' => 'GET'],
['name' => 'Local#search', 'url' => '/api/v1/search', 'verb' => 'GET'],
['name' => 'Local#documentsCache', 'url' => '/api/v1/documents/cache', 'verb' => 'POST'],
['name' => 'Queue#asyncWithToken', 'url' => CurlService::ASYNC_TOKEN, 'verb' => 'POST'],

Wyświetl plik

@ -47,6 +47,7 @@ use OCA\Social\Service\FollowService;
use OCA\Social\Service\MiscService;
use OCA\Social\Service\NoteService;
use OCA\Social\Service\PostService;
use OCA\Social\Service\SearchService;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
@ -82,6 +83,9 @@ class LocalController extends Controller {
/** @var NoteService */
private $noteService;
/** @var SearchService */
private $searchService;
/** @var AccountService */
private $accountService;
@ -106,14 +110,15 @@ class LocalController extends Controller {
* @param FollowService $followService
* @param PostService $postService
* @param NoteService $noteService
* @param SearchService $searchService
* @param DocumentService $documentService
* @param MiscService $miscService
*/
public function __construct(
IRequest $request, $userId, AccountService $accountService,
CacheActorService $cacheActorService, FollowService $followService,
PostService $postService, NoteService $noteService, DocumentService $documentService,
MiscService $miscService
PostService $postService, NoteService $noteService, SearchService $searchService,
DocumentService $documentService, MiscService $miscService
) {
parent::__construct(Application::APP_NAME, $request);
@ -121,6 +126,7 @@ class LocalController extends Controller {
$this->cacheActorService = $cacheActorService;
$this->accountService = $accountService;
$this->noteService = $noteService;
$this->searchService = $searchService;
$this->postService = $postService;
$this->followService = $followService;
$this->documentService = $documentService;
@ -211,7 +217,6 @@ class LocalController extends Controller {
/**
* @NoCSRFRequired
* @NoAdminRequired
*
* @param int $since
@ -318,7 +323,6 @@ class LocalController extends Controller {
}
/**
* Get timeline
*
@ -606,6 +610,30 @@ class LocalController extends Controller {
}
/** // TODO - remove this tag
*
* @NoCSRFRequired
* @NoAdminRequired
*
* @param string $search
*
* @return DataResponse
* @throws Exception
*/
public function search(string $search): DataResponse {
$search = trim($search);
$this->initViewer();
$result = [
'accounts' => $this->searchService->searchAccounts($search),
'hashtags' => $this->searchService->searchHashtags($search),
'content' => $this->searchService->searchStreamContent($search)
];
return $this->success($result);
}
/**
* @NoAdminRequired
*

Wyświetl plik

@ -198,7 +198,19 @@ class CoreRequestBuilder {
* @param string $hashtag
*/
protected function limitToHashtag(IQueryBuilder &$qb, string $hashtag) {
$this->limitToDBField($qb, 'hashtag', $hashtag);
$this->limitToDBField($qb, 'hashtag', $hashtag, false);
}
/**
* Limit the request to the ActorId
*
* @param IQueryBuilder $qb
* @param string $hashtag
*/
protected function searchInHashtag(IQueryBuilder &$qb, string $hashtag) {
$dbConn = $this->dbConnection;
$this->searchInDBField($qb, 'hashtag', '%' . $dbConn->escapeLikeParameter($hashtag) . '%');
}

Wyświetl plik

@ -34,6 +34,7 @@ namespace OCA\Social\Db;
use daita\MySmallPhpTools\Traits\TArrayTools;
use DateTime;
use OCA\Social\Exceptions\FollowDoesNotExistException;
use OCA\Social\Exceptions\HashtagDoesNotExistException;
use OCA\Social\Model\ActivityPub\Activity\Follow;
use OCP\DB\QueryBuilder\IQueryBuilder;
@ -96,5 +97,48 @@ class HashtagsRequest extends HashtagsRequestBuilder {
}
/**
* @param string $hashtag
*
* @return array
* @throws HashtagDoesNotExistException
*/
public function getHashtag(string $hashtag): array {
$qb = $this->getHashtagsSelectSql();
$this->limitToHashtag($qb, $hashtag);
$cursor = $qb->execute();
$data = $cursor->fetch();
$cursor->closeCursor();
if ($data === false) {
throw new HashtagDoesNotExistException();
}
return $this->parseHashtagsSelectSql($data);
}
/**
* @param string $hashtag
*
* @return array
*/
public function searchHashtags(string $hashtag): array {
$qb = $this->getHashtagsSelectSql();
$this->searchInHashtag($qb, $hashtag);
$hashtags = [];
$cursor = $qb->execute();
while ($data = $cursor->fetch()) {
$hashtags[] = $this->parseHashtagsSelectSql($data);
}
$cursor->closeCursor();
return $hashtags;
}
}

Wyświetl plik

@ -123,6 +123,27 @@ class HashtagService {
}
/**
* @param string $hashtag
*
* @return array
* @throws HashtagDoesNotExistException
*/
public function getHashtag(string $hashtag): array {
return $this->hashtagsRequest->getHashtag($hashtag);
}
/**
* @param string $hashtag
*
* @return array
*/
public function searchHashtags(string $hashtag): array {
return $this->hashtagsRequest->searchHashtags($hashtag);
}
/**
* @param int $timestamp
*

Wyświetl plik

@ -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;
}
}
}