kopia lustrzana https://github.com/nextcloud/social
commit
d81134130a
|
@ -345,6 +345,13 @@
|
|||
<notnull>true</notnull>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<name>icon_id</name>
|
||||
<type>text</type>
|
||||
<length>127</length>
|
||||
<notnull>true</notnull>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<name>summary</name>
|
||||
<type>text</type>
|
||||
|
@ -374,5 +381,85 @@
|
|||
</declaration>
|
||||
</table>
|
||||
|
||||
<table>
|
||||
<name>*dbprefix*social_cache_documents</name>
|
||||
<declaration>
|
||||
|
||||
<field>
|
||||
<name>id</name>
|
||||
<type>string</type>
|
||||
<length>127</length>
|
||||
<notnull>true</notnull>
|
||||
<primary>true</primary>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<name>type</name>
|
||||
<type>text</type>
|
||||
<length>31</length>
|
||||
<notnull>true</notnull>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<name>media_type</name>
|
||||
<type>text</type>
|
||||
<length>63</length>
|
||||
<notnull>true</notnull>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<name>mime_type</name>
|
||||
<type>text</type>
|
||||
<length>63</length>
|
||||
<notnull>true</notnull>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<name>url</name>
|
||||
<type>text</type>
|
||||
<length>127</length>
|
||||
<notnull>true</notnull>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<name>local_copy</name>
|
||||
<type>text</type>
|
||||
<length>127</length>
|
||||
<notnull>true</notnull>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<name>public</name>
|
||||
<type>boolean</type>
|
||||
<notnull>true</notnull>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<name>error</name>
|
||||
<type>integer</type>
|
||||
<length>1</length>
|
||||
<notnull>true</notnull>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<name>creation</name>
|
||||
<type>timestamp</type>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<name>caching</name>
|
||||
<type>timestamp</type>
|
||||
</field>
|
||||
|
||||
<index>
|
||||
<name>unique_url</name>
|
||||
<unique>true</unique>
|
||||
<field>
|
||||
<name>url</name>
|
||||
</field>
|
||||
</index>
|
||||
</declaration>
|
||||
</table>
|
||||
|
||||
</database>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<name>Social</name>
|
||||
<summary>🎉 Nextcloud becomes part of the federated social networks!</summary>
|
||||
<description><![CDATA[test]]></description>
|
||||
<version>0.0.37</version>
|
||||
<version>0.0.43</version>
|
||||
<licence>agpl</licence>
|
||||
<author mail="maxence@artificial-owl.com">Maxence Lange</author>
|
||||
<author mail="jus@bitgrid.net">Julius Härtl</author>
|
||||
|
@ -26,7 +26,12 @@
|
|||
</navigation>
|
||||
</navigations>
|
||||
|
||||
<background-jobs>
|
||||
<job>OCA\Social\Cron\Cache</job>
|
||||
</background-jobs>
|
||||
|
||||
<commands>
|
||||
<command>OCA\Social\Command\CacheRefresh</command>
|
||||
<command>OCA\Social\Command\NoteCreate</command>
|
||||
</commands>
|
||||
|
||||
|
|
|
@ -20,8 +20,9 @@ return [
|
|||
'name' => 'Navigation#account', 'url' => '/account/{path}', 'verb' => 'GET',
|
||||
'requirements' => ['path' => '.+'], 'defaults' => ['path' => '']
|
||||
],
|
||||
// ['name' => 'Navigation#public', 'url' => '/{username}', 'verb' => 'GET'],
|
||||
|
||||
['name' => 'Navigation#public', 'url' => '/{username}', 'verb' => 'GET'],
|
||||
['name' => 'Navigation#documentGet', 'url' => '/document/get', 'verb' => 'GET'],
|
||||
['name' => 'Navigation#documentGetPublic', 'url' => '/document/public', 'verb' => 'GET'],
|
||||
|
||||
// ['name' => 'Account#create', 'url' => '/local/account/{username}', 'verb' => 'POST'],
|
||||
['name' => 'Account#info', 'url' => '/local/account/{username}', 'verb' => 'GET'],
|
||||
|
@ -47,7 +48,9 @@ return [
|
|||
['name' => 'Local#accountsSearch', 'url' => '/api/v1/accounts/search', 'verb' => 'GET'],
|
||||
['name' => 'Local#accountFollow', 'url' => '/api/v1/account/follow', 'verb' => 'PUT'],
|
||||
['name' => 'Local#accountUnfollow', 'url' => '/api/v1/account/follow', 'verb' => 'DELETE'],
|
||||
['name' => 'Local#accountInfo', 'url' => '/api/v1/account/info', 'verb' => 'GET'],
|
||||
['name' => 'Local#actorInfo', 'url' => '/api/v1/actor/info', 'verb' => 'GET'],
|
||||
['name' => 'Local#documentsCache', 'url' => '/api/v1/documents/cache', 'verb' => 'POST'],
|
||||
|
||||
[
|
||||
'name' => 'Config#setCloudAddress', 'url' => '/api/v1/config/cloudAddress',
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
<?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\Command;
|
||||
|
||||
|
||||
use Exception;
|
||||
use OC\Core\Command\Base;
|
||||
use OCA\Social\Service\ActivityPub\DocumentService;
|
||||
use OCA\Social\Service\ActivityPub\PersonService;
|
||||
use OCA\Social\Service\ActorService;
|
||||
use OCA\Social\Service\ConfigService;
|
||||
use OCA\Social\Service\MiscService;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
|
||||
class CacheRefresh extends Base {
|
||||
|
||||
|
||||
/** @var ActorService */
|
||||
private $actorService;
|
||||
|
||||
/** @var PersonService */
|
||||
private $personService;
|
||||
|
||||
/** @var DocumentService */
|
||||
private $documentService;
|
||||
|
||||
/** @var ConfigService */
|
||||
private $configService;
|
||||
|
||||
/** @var MiscService */
|
||||
private $miscService;
|
||||
|
||||
|
||||
/**
|
||||
* CacheUpdate constructor.
|
||||
*
|
||||
* @param ActorService $actorService
|
||||
* @param PersonService $personService
|
||||
* @param DocumentService $documentService
|
||||
* @param ConfigService $configService
|
||||
* @param MiscService $miscService
|
||||
*/
|
||||
public function __construct(
|
||||
ActorService $actorService, PersonService $personService, DocumentService $documentService,
|
||||
ConfigService $configService, MiscService $miscService
|
||||
) {
|
||||
parent::__construct();
|
||||
|
||||
$this->actorService = $actorService;
|
||||
$this->personService = $personService;
|
||||
$this->documentService = $documentService;
|
||||
$this->configService = $configService;
|
||||
$this->miscService = $miscService;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
protected function configure() {
|
||||
parent::configure();
|
||||
$this->setName('social:cache:refresh')
|
||||
->setDescription('Update the cache');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output) {
|
||||
|
||||
$result = $this->actorService->manageCacheLocalActors();
|
||||
$output->writeLn($result . ' local accounts regenerated');
|
||||
|
||||
$result = $this->personService->manageCacheRemoteActors();
|
||||
$output->writeLn($result . ' remote accounts updated');
|
||||
|
||||
$result = $this->documentService->manageCacheDocuments();
|
||||
$output->writeLn($result . ' documents cached');
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -37,6 +37,7 @@ use OCA\Social\AppInfo\Application;
|
|||
use OCA\Social\Exceptions\InvalidResourceException;
|
||||
use OCA\Social\Model\ActivityPub\ACore;
|
||||
use OCA\Social\Model\Post;
|
||||
use OCA\Social\Service\ActivityPub\DocumentService;
|
||||
use OCA\Social\Service\ActivityPub\FollowService;
|
||||
use OCA\Social\Service\ActivityPub\NoteService;
|
||||
use OCA\Social\Service\ActivityPub\PersonService;
|
||||
|
@ -78,6 +79,9 @@ class LocalController extends Controller {
|
|||
/** @var NoteService */
|
||||
private $noteService;
|
||||
|
||||
/** @var DocumentService */
|
||||
private $documentService;
|
||||
|
||||
/** @var MiscService */
|
||||
private $miscService;
|
||||
|
||||
|
@ -92,12 +96,14 @@ class LocalController extends Controller {
|
|||
* @param ActorService $actorService
|
||||
* @param PostService $postService
|
||||
* @param NoteService $noteService
|
||||
* @param DocumentService $documentService
|
||||
* @param MiscService $miscService
|
||||
*/
|
||||
public function __construct(
|
||||
IRequest $request, $userId, PersonService $personService,
|
||||
FollowService $followService, ActorService $actorService,
|
||||
PostService $postService, NoteService $noteService,
|
||||
DocumentService $documentService,
|
||||
MiscService $miscService
|
||||
) {
|
||||
parent::__construct(Application::APP_NAME, $request);
|
||||
|
@ -109,6 +115,7 @@ class LocalController extends Controller {
|
|||
$this->followService = $followService;
|
||||
$this->postService = $postService;
|
||||
$this->noteService = $noteService;
|
||||
$this->documentService = $documentService;
|
||||
$this->miscService = $miscService;
|
||||
}
|
||||
|
||||
|
@ -179,6 +186,9 @@ class LocalController extends Controller {
|
|||
* @NoAdminRequired
|
||||
* @NoSubAdminRequired
|
||||
*
|
||||
* @param int $since
|
||||
* @param int $limit
|
||||
*
|
||||
* @return DataResponse
|
||||
*/
|
||||
public function streamHome(int $since = 0, int $limit = 5): DataResponse {
|
||||
|
@ -343,6 +353,29 @@ class LocalController extends Controller {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* // TODO: Delete the NoCSRF check
|
||||
*
|
||||
* @NoCSRFRequired
|
||||
* @NoAdminRequired
|
||||
* @NoSubAdminRequired
|
||||
*
|
||||
* @param string $account
|
||||
*
|
||||
* @return DataResponse
|
||||
*/
|
||||
public function accountInfo(string $account): DataResponse {
|
||||
try {
|
||||
$actor = $this->personService->getFromAccount($account);
|
||||
|
||||
return $this->success(['account' => $actor]);
|
||||
} catch (Exception $e) {
|
||||
return $this->fail($e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* // TODO: Delete the NoCSRF check
|
||||
|
@ -365,4 +398,35 @@ class LocalController extends Controller {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* // TODO: Delete the NoCSRF check
|
||||
*
|
||||
* @NoCSRFRequired
|
||||
* @NoAdminRequired
|
||||
* @NoSubAdminRequired
|
||||
*
|
||||
* @param array $documents
|
||||
*
|
||||
* @return DataResponse
|
||||
*/
|
||||
public function documentsCache(array $documents): DataResponse {
|
||||
try {
|
||||
$cached = [];
|
||||
foreach ($documents as $id) {
|
||||
try {
|
||||
|
||||
$document = $this->documentService->cacheRemoteDocument($id);
|
||||
$cached[] = $document;
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
}
|
||||
|
||||
return $this->success($cached);
|
||||
} catch (Exception $e) {
|
||||
return $this->fail($e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -32,16 +32,22 @@ namespace OCA\Social\Controller;
|
|||
|
||||
use daita\MySmallPhpTools\Traits\TArrayTools;
|
||||
use daita\MySmallPhpTools\Traits\Nextcloud\TNCDataResponse;
|
||||
use Exception;
|
||||
use OC\Files\Node\File;
|
||||
use OC\Files\SimpleFS\SimpleFile;
|
||||
use OC\User\NoUserException;
|
||||
use OCA\Social\AppInfo\Application;
|
||||
use OCA\Social\Exceptions\AccountAlreadyExistsException;
|
||||
use OCA\Social\Exceptions\SocialAppConfigException;
|
||||
use OCA\Social\Service\ActivityPub\DocumentService;
|
||||
use OCA\Social\Service\ActorService;
|
||||
use OCA\Social\Service\ConfigService;
|
||||
use OCA\Social\Service\MiscService;
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\AppFramework\Http\FileDisplayResponse;
|
||||
use OCP\AppFramework\Http\RedirectResponse;
|
||||
use OCP\AppFramework\Http\Response;
|
||||
use OCP\AppFramework\Http\Template\PublicTemplateResponse;
|
||||
use OCP\AppFramework\Http\TemplateResponse;
|
||||
use OCP\IConfig;
|
||||
|
@ -68,6 +74,8 @@ class NavigationController extends Controller {
|
|||
/** @var ActorService */
|
||||
private $actorService;
|
||||
|
||||
private $documentService;
|
||||
|
||||
/** @var ConfigService */
|
||||
private $configService;
|
||||
|
||||
|
@ -85,14 +93,15 @@ class NavigationController extends Controller {
|
|||
* @param IConfig $config
|
||||
* @param IURLGenerator $urlGenerator
|
||||
* @param ActorService $actorService
|
||||
* @param DocumentService $documentService
|
||||
* @param ConfigService $configService
|
||||
* @param MiscService $miscService
|
||||
* @param IL10N $l10n
|
||||
*/
|
||||
public function __construct(
|
||||
IRequest $request, $userId, IConfig $config, IURLGenerator $urlGenerator,
|
||||
ActorService $actorService, ConfigService $configService, MiscService $miscService,
|
||||
IL10N $l10n
|
||||
ActorService $actorService, DocumentService $documentService, ConfigService $configService,
|
||||
MiscService $miscService, IL10N $l10n
|
||||
) {
|
||||
parent::__construct(Application::APP_NAME, $request);
|
||||
|
||||
|
@ -101,6 +110,7 @@ class NavigationController extends Controller {
|
|||
$this->urlGenerator = $urlGenerator;
|
||||
|
||||
$this->actorService = $actorService;
|
||||
$this->documentService = $documentService;
|
||||
$this->configService = $configService;
|
||||
$this->miscService = $miscService;
|
||||
$this->l10n = $l10n;
|
||||
|
@ -130,13 +140,18 @@ class NavigationController extends Controller {
|
|||
$data['serverData']['cloudAddress'] = $this->configService->getCloudAddress();
|
||||
} catch (SocialAppConfigException $e) {
|
||||
$data['serverData']['setup'] = true;
|
||||
$data['serverData']['isAdmin'] = \OC::$server->getGroupManager()->isAdmin($this->userId);
|
||||
$data['serverData']['isAdmin'] = \OC::$server->getGroupManager()
|
||||
->isAdmin($this->userId);
|
||||
if ($data['serverData']['isAdmin']) {
|
||||
$cloudAddress = $this->request->getParam('cloudAddress');
|
||||
if ($cloudAddress !== null) {
|
||||
$this->configService->setCloudAddress($cloudAddress);
|
||||
} else {
|
||||
$data['serverData']['cliUrl'] = $this->config->getSystemValue('overwrite.cli.url', \OC::$server->getURLGenerator()->getBaseUrl());
|
||||
$data['serverData']['cliUrl'] = $this->config->getSystemValue(
|
||||
'overwrite.cli.url', \OC::$server->getURLGenerator()
|
||||
->getBaseUrl()
|
||||
);
|
||||
|
||||
return new TemplateResponse(Application::APP_NAME, 'main', $data);
|
||||
}
|
||||
}
|
||||
|
@ -153,8 +168,6 @@ class NavigationController extends Controller {
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Display the navigation page of the Social app.
|
||||
*
|
||||
|
@ -237,4 +250,54 @@ class NavigationController extends Controller {
|
|||
return $page;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* // TODO: Delete the NoCSRF check
|
||||
*
|
||||
* @NoCSRFRequired
|
||||
* @NoAdminRequired
|
||||
* @NoSubAdminRequired
|
||||
*
|
||||
* @param string $id
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function documentGet(string $id): Response {
|
||||
|
||||
try {
|
||||
$file = $this->documentService->getFromCache($id);
|
||||
|
||||
return new FileDisplayResponse($file);
|
||||
} catch (Exception $e) {
|
||||
return $this->fail($e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* // TODO: Delete the NoCSRF check
|
||||
*
|
||||
* @PublicPage
|
||||
* @NoCSRFRequired
|
||||
* @NoAdminRequired
|
||||
* @NoSubAdminRequired
|
||||
*
|
||||
* @param string $id
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function documentGetPublic(string $id): Response {
|
||||
|
||||
try {
|
||||
$file = $this->documentService->getFromCache($id, true);
|
||||
|
||||
return new FileDisplayResponse($file);
|
||||
} catch (Exception $e) {
|
||||
return $this->fail($e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
<?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\Cron;
|
||||
|
||||
|
||||
use Exception;
|
||||
use OC\BackgroundJob\TimedJob;
|
||||
use OCA\Social\AppInfo\Application;
|
||||
use OCA\Social\Service\ActivityPub\DocumentService;
|
||||
use OCA\Social\Service\ActivityPub\PersonService;
|
||||
use OCA\Social\Service\ActorService;
|
||||
use OCA\Social\Service\ConfigService;
|
||||
use OCA\Social\Service\MiscService;
|
||||
use OCP\AppFramework\QueryException;
|
||||
|
||||
|
||||
/**
|
||||
* Class Cache
|
||||
*
|
||||
* @package OCA\Social\Cron
|
||||
*/
|
||||
class Cache extends TimedJob {
|
||||
|
||||
|
||||
/** @var ActorService */
|
||||
private $actorService;
|
||||
|
||||
/** @var PersonService */
|
||||
private $personService;
|
||||
|
||||
/** @var DocumentService */
|
||||
private $documentService;
|
||||
|
||||
/** @var ConfigService */
|
||||
private $configService;
|
||||
|
||||
/** @var MiscService */
|
||||
private $miscService;
|
||||
|
||||
|
||||
/**
|
||||
* Cache constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->setInterval(12 * 60); // 12 minutes
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param mixed $argument
|
||||
*
|
||||
* @throws QueryException
|
||||
*/
|
||||
protected function run($argument) {
|
||||
$app = new Application();
|
||||
$c = $app->getContainer();
|
||||
|
||||
$this->actorService = $c->query(ActorService::class);
|
||||
$this->personService = $c->query(PersonService::class);
|
||||
$this->documentService = $c->query(DocumentService::class);
|
||||
$this->configService = $c->query(ConfigService::class);
|
||||
$this->miscService = $c->query(MiscService::class);
|
||||
|
||||
$this->manageCache();
|
||||
}
|
||||
|
||||
|
||||
private function manageCache() {
|
||||
try {
|
||||
$this->actorService->manageCacheLocalActors();
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
|
||||
try {
|
||||
$this->personService->manageCacheRemoteActors();
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
|
||||
try {
|
||||
$this->documentService->manageCacheDocuments();
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -64,7 +64,7 @@ class ActorsRequest extends ActorsRequestBuilder {
|
|||
*/
|
||||
public function create(Person $actor): string {
|
||||
|
||||
$id = $this->configService->getUrlRoot() . '@' . $actor->getPreferredUsername();
|
||||
$id = $this->configService->getUrlSocial() . '@' . $actor->getPreferredUsername();
|
||||
|
||||
try {
|
||||
$qb = $this->getActorsInsertSql();
|
||||
|
@ -161,6 +161,24 @@ class ActorsRequest extends ActorsRequestBuilder {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Person[]
|
||||
* @throws SocialAppConfigException
|
||||
*/
|
||||
public function getAll(): array {
|
||||
$qb = $this->getActorsSelectSql();
|
||||
|
||||
$accounts = [];
|
||||
$cursor = $qb->execute();
|
||||
while ($data = $cursor->fetch()) {
|
||||
$accounts[] = $this->parseActorsSelectSql($data);
|
||||
}
|
||||
$cursor->closeCursor();
|
||||
|
||||
return $accounts;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $search
|
||||
*
|
||||
|
|
|
@ -109,10 +109,10 @@ class ActorsRequestBuilder extends CoreRequestBuilder {
|
|||
* @throws SocialAppConfigException
|
||||
*/
|
||||
protected function parseActorsSelectSql($data): Person {
|
||||
$root = $this->configService->getUrlRoot();
|
||||
$root = $this->configService->getUrlSocial();
|
||||
|
||||
$actor = new Person();
|
||||
$actor->import($data);
|
||||
$actor->importFromDatabase($data);
|
||||
$actor->setInbox($actor->getId() . '/inbox')
|
||||
->setOutbox($actor->getId() . '/outbox')
|
||||
->setFollowers($actor->getId() . '/followers')
|
||||
|
@ -122,7 +122,7 @@ class ActorsRequestBuilder extends CoreRequestBuilder {
|
|||
->setAccount(
|
||||
$actor->getPreferredUsername() . '@' . $this->configService->getCloudAddress(true)
|
||||
);
|
||||
$actor->setUrlRoot($root)
|
||||
$actor->setUrlSocial($root)
|
||||
->setUrl($actor->getId());
|
||||
|
||||
return $actor;
|
||||
|
|
|
@ -30,15 +30,20 @@ declare(strict_types=1);
|
|||
namespace OCA\Social\Db;
|
||||
|
||||
|
||||
use DateTime;
|
||||
use Exception;
|
||||
use OCA\Social\Exceptions\CacheActorDoesNotExistException;
|
||||
use OCA\Social\Model\ActivityPub\Person;
|
||||
use OCA\Social\Service\ConfigService;
|
||||
use OCA\Social\Service\MiscService;
|
||||
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||
use OCP\IDBConnection;
|
||||
|
||||
class CacheActorsRequest extends CacheActorsRequestBuilder {
|
||||
|
||||
|
||||
const CACHE_TTL = 60 * 24; // 1d
|
||||
|
||||
/**
|
||||
* CacheActorsRequest constructor.
|
||||
*
|
||||
|
@ -78,7 +83,17 @@ class CacheActorsRequest extends CacheActorsRequestBuilder {
|
|||
->setValue('name', $qb->createNamedParameter($actor->getName()))
|
||||
->setValue('summary', $qb->createNamedParameter($actor->getSummary()))
|
||||
->setValue('public_key', $qb->createNamedParameter($actor->getPublicKey()))
|
||||
->setValue('source', $qb->createNamedParameter($actor->getSource()));
|
||||
->setValue('source', $qb->createNamedParameter($actor->getSource()))
|
||||
->setValue(
|
||||
'creation',
|
||||
$qb->createNamedParameter(new DateTime('now'), IQueryBuilder::PARAM_DATE)
|
||||
);
|
||||
|
||||
if ($actor->gotIcon()) {
|
||||
$iconId = $actor->getIcon()
|
||||
->getId();
|
||||
$qb->setValue('icon_id', $qb->createNamedParameter($iconId));
|
||||
}
|
||||
|
||||
$qb->execute();
|
||||
|
||||
|
@ -86,30 +101,6 @@ class CacheActorsRequest extends CacheActorsRequestBuilder {
|
|||
}
|
||||
|
||||
|
||||
// /**
|
||||
// * get Cached value about an Actor, based on the account.
|
||||
// *
|
||||
// * @param string $account
|
||||
// *
|
||||
// * @return CacheActor
|
||||
// * @throws CacheActorDoesNotExistException
|
||||
// */
|
||||
// public function getFromAccount(string $account): CacheActor {
|
||||
// $qb = $this->getCacheActorsSelectSql();
|
||||
// $this->limitToAccount($qb, $account);
|
||||
//
|
||||
// $cursor = $qb->execute();
|
||||
// $data = $cursor->fetch();
|
||||
// $cursor->closeCursor();
|
||||
//
|
||||
// if ($data === false) {
|
||||
// throw new CacheActorDoesNotExistException();
|
||||
// }
|
||||
//
|
||||
// return $this->parseCacheActorsSelectSql($data);
|
||||
// }
|
||||
|
||||
|
||||
/**
|
||||
* get Cached version of an Actor, based on the UriId
|
||||
*
|
||||
|
@ -121,6 +112,7 @@ class CacheActorsRequest extends CacheActorsRequestBuilder {
|
|||
public function getFromId(string $id): Person {
|
||||
$qb = $this->getCacheActorsSelectSql();
|
||||
$this->limitToIdString($qb, $id);
|
||||
$this->leftJoinCacheDocuments($qb, 'icon_id');
|
||||
|
||||
$cursor = $qb->execute();
|
||||
$data = $cursor->fetch();
|
||||
|
@ -145,6 +137,7 @@ class CacheActorsRequest extends CacheActorsRequestBuilder {
|
|||
public function getFromAccount(string $account): Person {
|
||||
$qb = $this->getCacheActorsSelectSql();
|
||||
$this->limitToAccount($qb, $account);
|
||||
$this->leftJoinCacheDocuments($qb, 'icon_id');
|
||||
|
||||
$cursor = $qb->execute();
|
||||
$data = $cursor->fetch();
|
||||
|
@ -166,6 +159,7 @@ class CacheActorsRequest extends CacheActorsRequestBuilder {
|
|||
public function searchAccounts(string $search): array {
|
||||
$qb = $this->getCacheActorsSelectSql();
|
||||
$this->searchInAccount($qb, $search);
|
||||
$this->leftJoinCacheDocuments($qb, 'icon_id');
|
||||
|
||||
$accounts = [];
|
||||
$cursor = $qb->execute();
|
||||
|
@ -178,6 +172,26 @@ class CacheActorsRequest extends CacheActorsRequestBuilder {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Person[]
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getRemoteActorsToUpdate(): array {
|
||||
$qb = $this->getCacheActorsSelectSql();
|
||||
$this->limitToLocal($qb, false);
|
||||
$this->limitToCreation($qb, self::CACHE_TTL);
|
||||
|
||||
$update = [];
|
||||
$cursor = $qb->execute();
|
||||
while ($data = $cursor->fetch()) {
|
||||
$update[] = $this->parseCacheActorsSelectSql($data);
|
||||
}
|
||||
$cursor->closeCursor();
|
||||
|
||||
return $update;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* delete cached version of an Actor, based on the UriId
|
||||
*
|
||||
|
|
|
@ -31,7 +31,7 @@ namespace OCA\Social\Db;
|
|||
|
||||
|
||||
use daita\MySmallPhpTools\Traits\TArrayTools;
|
||||
use OCA\Social\Model\ActivityPub\Cache\CacheActor;
|
||||
use OCA\Social\Exceptions\InvalidResourceException;
|
||||
use OCA\Social\Model\ActivityPub\Person;
|
||||
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||
|
||||
|
@ -110,7 +110,14 @@ class CacheActorsRequestBuilder extends CoreRequestBuilder {
|
|||
*/
|
||||
protected function parseCacheActorsSelectSql(array $data): Person {
|
||||
$actor = new Person();
|
||||
$actor->import($data);
|
||||
$actor->importFromDatabase($data);
|
||||
|
||||
try {
|
||||
$icon = $this->parseCacheDocumentsLeftJoin($data);
|
||||
$icon->setParent($actor);
|
||||
$actor->setIcon($icon);
|
||||
} catch (InvalidResourceException $e) {
|
||||
}
|
||||
|
||||
return $actor;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,165 @@
|
|||
<?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\Db;
|
||||
|
||||
|
||||
use DateTime;
|
||||
use Exception;
|
||||
use OCA\Social\Exceptions\CacheDocumentDoesNotExistException;
|
||||
use OCA\Social\Model\ActivityPub\Document;
|
||||
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||
|
||||
class CacheDocumentsRequest extends CacheDocumentsRequestBuilder {
|
||||
|
||||
|
||||
const CACHE_TTL = 15; // 15 min
|
||||
|
||||
|
||||
/**
|
||||
* insert cache about an Actor in database.
|
||||
*
|
||||
* @param Document $document
|
||||
*/
|
||||
public function save(Document $document) {
|
||||
$qb = $this->getCacheDocumentsInsertSql();
|
||||
$qb->setValue('id', $qb->createNamedParameter($document->getId()))
|
||||
->setValue('type', $qb->createNamedParameter($document->getType()))
|
||||
->setValue('url', $qb->createNamedParameter($document->getUrl()))
|
||||
->setValue('media_type', $qb->createNamedParameter($document->getMediaType()))
|
||||
->setValue('mime_type', $qb->createNamedParameter($document->getMimeType()))
|
||||
->setValue('error', $qb->createNamedParameter($document->getError()))
|
||||
->setValue('local_copy', $qb->createNamedParameter($document->getLocalCopy()))
|
||||
->setValue('public', $qb->createNamedParameter(($document->isPublic()) ? '1' : '0'))
|
||||
->setValue(
|
||||
'creation',
|
||||
$qb->createNamedParameter(new DateTime('now'), IQueryBuilder::PARAM_DATE)
|
||||
);
|
||||
$qb->execute();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Document $document
|
||||
*/
|
||||
public function initCaching(Document $document) {
|
||||
$qb = $this->getCacheDocumentsUpdateSql();
|
||||
$this->limitToIdString($qb, $document->getId());
|
||||
$qb->set(
|
||||
'caching', $qb->createNamedParameter(new DateTime('now'), IQueryBuilder::PARAM_DATE)
|
||||
);
|
||||
|
||||
$qb->execute();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Document $document
|
||||
*/
|
||||
public function endCaching(Document $document) {
|
||||
$qb = $this->getCacheDocumentsUpdateSql();
|
||||
$this->limitToIdString($qb, $document->getId());
|
||||
$qb->set('local_copy', $qb->createNamedParameter($document->getLocalCopy()));
|
||||
$qb->set('error', $qb->createNamedParameter($document->getError()));
|
||||
|
||||
$qb->execute();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
*
|
||||
* @return Document
|
||||
* @throws CacheDocumentDoesNotExistException
|
||||
*/
|
||||
public function getBySource(string $url) {
|
||||
$qb = $this->getCacheDocumentsSelectSql();
|
||||
$this->limitToUrl($qb, $url);
|
||||
|
||||
$cursor = $qb->execute();
|
||||
$data = $cursor->fetch();
|
||||
$cursor->closeCursor();
|
||||
|
||||
if ($data === false) {
|
||||
throw new CacheDocumentDoesNotExistException();
|
||||
}
|
||||
|
||||
return $this->parseCacheDocumentsSelectSql($data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $id
|
||||
*
|
||||
* @param bool $public
|
||||
*
|
||||
* @return Document
|
||||
* @throws CacheDocumentDoesNotExistException
|
||||
*/
|
||||
public function getById(string $id, bool $public = false) {
|
||||
$qb = $this->getCacheDocumentsSelectSql();
|
||||
$this->limitToIdString($qb, $id);
|
||||
|
||||
if ($public === true) {
|
||||
$this->limitToPublic($qb);
|
||||
}
|
||||
|
||||
$cursor = $qb->execute();
|
||||
$data = $cursor->fetch();
|
||||
$cursor->closeCursor();
|
||||
|
||||
if ($data === false) {
|
||||
throw new CacheDocumentDoesNotExistException();
|
||||
}
|
||||
|
||||
return $this->parseCacheDocumentsSelectSql($data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Document[]
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getNotCachedDocuments() {
|
||||
$qb = $this->getCacheDocumentsSelectSql();
|
||||
$this->limitToDBFieldEmpty($qb, 'local_copy');
|
||||
$this->limitToCaching($qb, self::CACHE_TTL);
|
||||
|
||||
$documents = [];
|
||||
$cursor = $qb->execute();
|
||||
while ($data = $cursor->fetch()) {
|
||||
$documents[] = $this->parseCacheDocumentsSelectSql($data);
|
||||
}
|
||||
$cursor->closeCursor();
|
||||
|
||||
return $documents;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
<?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\Db;
|
||||
|
||||
|
||||
use daita\MySmallPhpTools\Traits\TArrayTools;
|
||||
use OCA\Social\Model\ActivityPub\Document;
|
||||
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||
|
||||
class CacheDocumentsRequestBuilder extends CoreRequestBuilder {
|
||||
|
||||
|
||||
use TArrayTools;
|
||||
|
||||
|
||||
/**
|
||||
* Base of the Sql Insert request
|
||||
*
|
||||
* @return IQueryBuilder
|
||||
*/
|
||||
protected function getCacheDocumentsInsertSql(): IQueryBuilder {
|
||||
$qb = $this->dbConnection->getQueryBuilder();
|
||||
$qb->insert(self::TABLE_CACHE_DOCUMENTS);
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Base of the Sql Update request
|
||||
*
|
||||
* @return IQueryBuilder
|
||||
*/
|
||||
protected function getCacheDocumentsUpdateSql(): IQueryBuilder {
|
||||
$qb = $this->dbConnection->getQueryBuilder();
|
||||
$qb->update(self::TABLE_CACHE_DOCUMENTS);
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Base of the Sql Select request for Shares
|
||||
*
|
||||
* @return IQueryBuilder
|
||||
*/
|
||||
protected function getCacheDocumentsSelectSql(): IQueryBuilder {
|
||||
$qb = $this->dbConnection->getQueryBuilder();
|
||||
|
||||
/** @noinspection PhpMethodParametersCountMismatchInspection */
|
||||
$qb->select(
|
||||
'cd.id', 'cd.type', 'cd.media_type', 'cd.mime_type', 'cd.url', 'cd.local_copy',
|
||||
'cd.public', 'cd.error', 'cd.creation', 'cd.caching'
|
||||
)
|
||||
->from(self::TABLE_CACHE_DOCUMENTS, 'cd');
|
||||
|
||||
$this->defaultSelectAlias = 'cd';
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Base of the Sql Delete request
|
||||
*
|
||||
* @return IQueryBuilder
|
||||
*/
|
||||
protected function getCacheDocumentsDeleteSql(): IQueryBuilder {
|
||||
$qb = $this->dbConnection->getQueryBuilder();
|
||||
$qb->delete(self::TABLE_CACHE_DOCUMENTS);
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
* @return Document
|
||||
*/
|
||||
protected function parseCacheDocumentsSelectSql(array $data): Document {
|
||||
$document = new Document();
|
||||
$document->importFromDatabase($data);
|
||||
|
||||
return $document;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -27,24 +27,38 @@ declare(strict_types=1);
|
|||
*
|
||||
*/
|
||||
|
||||
|
||||
namespace OCA\Social\Db;
|
||||
|
||||
|
||||
use DateInterval;
|
||||
use DateTime;
|
||||
use Doctrine\DBAL\Query\QueryBuilder;
|
||||
use Exception;
|
||||
use OCA\Social\Exceptions\InvalidResourceException;
|
||||
use OCA\Social\Model\ActivityPub\Document;
|
||||
use OCA\Social\Model\ActivityPub\Image;
|
||||
use OCA\Social\Model\ActivityPub\Person;
|
||||
use OCA\Social\Service\ConfigService;
|
||||
use OCA\Social\Service\MiscService;
|
||||
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||
use OCP\IDBConnection;
|
||||
|
||||
|
||||
/**
|
||||
* Class CoreRequestBuilder
|
||||
*
|
||||
* @package OCA\Social\Db
|
||||
*/
|
||||
class CoreRequestBuilder {
|
||||
|
||||
|
||||
const TABLE_SERVER_ACTORS = 'social_server_actors';
|
||||
const TABLE_SERVER_NOTES = 'social_server_notes';
|
||||
const TABLE_SERVER_FOLLOWS = 'social_server_follows';
|
||||
|
||||
const TABLE_CACHE_ACTORS = 'social_cache_actors';
|
||||
const TABLE_CACHE_DOCUMENTS = 'social_cache_documents';
|
||||
|
||||
|
||||
/** @var IDBConnection */
|
||||
|
@ -134,6 +148,16 @@ class CoreRequestBuilder {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Limit the request to the ActorId
|
||||
*
|
||||
* @param IQueryBuilder $qb
|
||||
*/
|
||||
protected function limitToPublic(IQueryBuilder &$qb) {
|
||||
$this->limitToDBFieldInt($qb, 'public', 1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Limit the request to the ActorId
|
||||
*
|
||||
|
@ -191,6 +215,38 @@ class CoreRequestBuilder {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Limit the request to the creation
|
||||
*
|
||||
* @param IQueryBuilder $qb
|
||||
* @param int $delay
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function limitToCreation(IQueryBuilder &$qb, int $delay = 0) {
|
||||
$date = new DateTime('now');
|
||||
$date->sub(new DateInterval('PT' . $delay . 'M'));
|
||||
|
||||
$this->limitToDBFieldDateTime($qb, 'creation', $date);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Limit the request to the creation
|
||||
*
|
||||
* @param IQueryBuilder $qb
|
||||
* @param int $delay
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function limitToCaching(IQueryBuilder &$qb, int $delay = 0) {
|
||||
$date = new DateTime('now');
|
||||
$date->sub(new DateInterval('PT' . $delay . 'M'));
|
||||
|
||||
$this->limitToDBFieldDateTime($qb, 'caching', $date);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Limit the request to the url
|
||||
*
|
||||
|
@ -299,7 +355,7 @@ class CoreRequestBuilder {
|
|||
* @param bool $cs - case sensitive
|
||||
* @param string $alias
|
||||
*/
|
||||
private function limitToDBField(
|
||||
protected function limitToDBField(
|
||||
IQueryBuilder &$qb, string $field, string $value, bool $cs = true, string $alias = ''
|
||||
) {
|
||||
$expr = $qb->expr();
|
||||
|
@ -326,7 +382,7 @@ class CoreRequestBuilder {
|
|||
* @param string $field
|
||||
* @param int $value
|
||||
*/
|
||||
private function limitToDBFieldInt(IQueryBuilder &$qb, string $field, int $value) {
|
||||
protected function limitToDBFieldInt(IQueryBuilder &$qb, string $field, int $value) {
|
||||
$expr = $qb->expr();
|
||||
$pf = ($qb->getType() === QueryBuilder::SELECT) ? $this->defaultSelectAlias . '.' : '';
|
||||
$field = $pf . $field;
|
||||
|
@ -335,12 +391,42 @@ class CoreRequestBuilder {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param IQueryBuilder $qb
|
||||
* @param string $field
|
||||
*/
|
||||
protected function limitToDBFieldEmpty(IQueryBuilder &$qb, string $field) {
|
||||
$expr = $qb->expr();
|
||||
$pf = ($qb->getType() === QueryBuilder::SELECT) ? $this->defaultSelectAlias . '.' : '';
|
||||
$field = $pf . $field;
|
||||
|
||||
$qb->andWhere($expr->eq($field, $qb->createNamedParameter('')));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param IQueryBuilder $qb
|
||||
* @param string $field
|
||||
* @param DateTime $date
|
||||
*/
|
||||
protected function limitToDBFieldDateTime(IQueryBuilder &$qb, string $field, DateTime $date) {
|
||||
$expr = $qb->expr();
|
||||
$pf = ($qb->getType() === QueryBuilder::SELECT) ? $this->defaultSelectAlias . '.' : '';
|
||||
$field = $pf . $field;
|
||||
|
||||
$orX = $expr->orX();
|
||||
$orX->add($expr->lte($field, $qb->createNamedParameter($date, IQueryBuilder::PARAM_DATE)));
|
||||
$orX->add($expr->isNull($field));
|
||||
$qb->andWhere($orX);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param IQueryBuilder $qb
|
||||
* @param string $field
|
||||
* @param array $values
|
||||
*/
|
||||
private function limitToDBFieldArray(IQueryBuilder &$qb, string $field, array $values) {
|
||||
protected function limitToDBFieldArray(IQueryBuilder &$qb, string $field, array $values) {
|
||||
$expr = $qb->expr();
|
||||
$pf = ($qb->getType() === QueryBuilder::SELECT) ? $this->defaultSelectAlias . '.' : '';
|
||||
$field = $pf . $field;
|
||||
|
@ -363,7 +449,7 @@ class CoreRequestBuilder {
|
|||
* @param string $field
|
||||
* @param string $value
|
||||
*/
|
||||
private function searchInDBField(IQueryBuilder &$qb, string $field, string $value) {
|
||||
protected function searchInDBField(IQueryBuilder &$qb, string $field, string $value) {
|
||||
$expr = $qb->expr();
|
||||
|
||||
$pf = ($qb->getType() === QueryBuilder::SELECT) ? $this->defaultSelectAlias . '.' : '';
|
||||
|
@ -425,7 +511,7 @@ class CoreRequestBuilder {
|
|||
}
|
||||
|
||||
$actor = new Person();
|
||||
$actor->import($new);
|
||||
$actor->importFromDatabase($new);
|
||||
|
||||
if ($actor->getType() !== Person::TYPE) {
|
||||
throw new InvalidResourceException();
|
||||
|
@ -434,6 +520,62 @@ class CoreRequestBuilder {
|
|||
return $actor;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param IQueryBuilder $qb
|
||||
* @param string $fieldDocumentId
|
||||
*/
|
||||
protected function leftJoinCacheDocuments(IQueryBuilder &$qb, string $fieldDocumentId) {
|
||||
if ($qb->getType() !== QueryBuilder::SELECT) {
|
||||
return;
|
||||
}
|
||||
|
||||
$expr = $qb->expr();
|
||||
$pf = $this->defaultSelectAlias;
|
||||
|
||||
// /** @noinspection PhpMethodParametersCountMismatchInspection */
|
||||
$qb->selectAlias('cd.id', 'cachedocument_id')
|
||||
->selectAlias('cd.type', 'cachedocument_type')
|
||||
->selectAlias('cd.mime_type', 'cachedocument_mime_type')
|
||||
->selectAlias('cd.media_type', 'cachedocument_media_type')
|
||||
->selectAlias('cd.url', 'cachedocument_url')
|
||||
->selectAlias('cd.local_copy', 'cachedocument_local_copy')
|
||||
->selectAlias('cd.caching', 'cachedocument_caching')
|
||||
->selectAlias('cd.public', 'cachedocument_public')
|
||||
->selectAlias('cd.error', 'cachedocument_error')
|
||||
->selectAlias('ca.creation', 'cachedocument_creation')
|
||||
->leftJoin(
|
||||
$this->defaultSelectAlias, CoreRequestBuilder::TABLE_CACHE_DOCUMENTS, 'cd',
|
||||
$expr->eq($pf . '.' . $fieldDocumentId, 'cd.id')
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
* @return Document
|
||||
* @throws InvalidResourceException
|
||||
*/
|
||||
protected function parseCacheDocumentsLeftJoin(array $data): Document {
|
||||
$new = [];
|
||||
|
||||
foreach ($data as $k => $v) {
|
||||
if (substr($k, 0, 14) === 'cachedocument_') {
|
||||
$new[substr($k, 14)] = $v;
|
||||
}
|
||||
}
|
||||
$document = new Document();
|
||||
|
||||
$document->importFromDatabase($new);
|
||||
|
||||
if ($document->getType() !== Image::TYPE) {
|
||||
throw new InvalidResourceException();
|
||||
}
|
||||
|
||||
return $document;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -160,6 +160,7 @@ class NotesRequestBuilder extends CoreRequestBuilder {
|
|||
protected function parseNotesSelectSql($data): Note {
|
||||
$dTime = new DateTime($this->get('published_time', $data, 'yesterday'));
|
||||
|
||||
// TODO - use $note->importFromDatabase() ?
|
||||
$note = new Note();
|
||||
$note->setId($data['id'])
|
||||
->setTo($data['to'])
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
<?php
|
||||
|
||||
namespace OCA\Social\Exceptions;
|
||||
|
||||
class CacheContentException extends \Exception {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?php
|
||||
|
||||
namespace OCA\Social\Exceptions;
|
||||
|
||||
class CacheContentSizeException extends \Exception {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?php
|
||||
|
||||
namespace OCA\Social\Exceptions;
|
||||
|
||||
class CacheDocumentDoesNotExistException extends \Exception {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?php
|
||||
|
||||
namespace OCA\Social\Exceptions;
|
||||
|
||||
class UrlCloudException extends \Exception {
|
||||
|
||||
}
|
||||
|
|
@ -31,8 +31,10 @@ namespace OCA\Social\Model\ActivityPub;
|
|||
|
||||
|
||||
use daita\MySmallPhpTools\Traits\TArrayTools;
|
||||
use daita\MySmallPhpTools\Traits\TPathTools;
|
||||
use JsonSerializable;
|
||||
use OCA\Social\Exceptions\ActivityCantBeVerifiedException;
|
||||
use OCA\Social\Exceptions\UrlCloudException;
|
||||
use OCA\Social\Model\InstancePath;
|
||||
use OCA\Social\Service\ICoreService;
|
||||
|
||||
|
@ -41,6 +43,7 @@ abstract class ACore implements JsonSerializable {
|
|||
|
||||
|
||||
use TArrayTools;
|
||||
use TPathTools;
|
||||
|
||||
|
||||
const CONTEXT_ACTIVITYSTREAMS = 'https://www.w3.org/ns/activitystreams';
|
||||
|
@ -48,7 +51,10 @@ abstract class ACore implements JsonSerializable {
|
|||
|
||||
|
||||
/** @var string */
|
||||
private $root = '';
|
||||
private $urlSocial = '';
|
||||
|
||||
/** @var string */
|
||||
private $urlCloud = '';
|
||||
|
||||
// /** @var bool */
|
||||
// private $isTopLevel = false;
|
||||
|
@ -101,6 +107,9 @@ abstract class ACore implements JsonSerializable {
|
|||
/** @var string */
|
||||
private $actorId = '';
|
||||
|
||||
/** @var Document */
|
||||
private $icon = null;
|
||||
|
||||
/** @var ACore */
|
||||
private $object = null;
|
||||
|
||||
|
@ -155,14 +164,27 @@ abstract class ACore implements JsonSerializable {
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function generateUniqueId(string $base) {
|
||||
/**
|
||||
* @param string $base
|
||||
*
|
||||
* @throws UrlCloudException
|
||||
*/
|
||||
public function generateUniqueId(string $base = '') {
|
||||
if ($this->getUrlCloud() === '') {
|
||||
throw new UrlCloudException();
|
||||
}
|
||||
|
||||
if ($base !== '') {
|
||||
$base = $this->withoutEndSlash($this->withBeginSlash($base));
|
||||
}
|
||||
|
||||
$uuid = 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)
|
||||
);
|
||||
|
||||
$this->setId($base . '/' . $uuid);
|
||||
$this->setId($this->getUrlCloud() . $base . '/' . $uuid);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -178,9 +200,10 @@ abstract class ACore implements JsonSerializable {
|
|||
* @return ACore
|
||||
*/
|
||||
public function setType(string $type): ACore {
|
||||
if ($type !== '') {
|
||||
$this->type = $type;
|
||||
}
|
||||
// if ($type !== '') {
|
||||
$this->type = $type;
|
||||
|
||||
// }
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@ -343,8 +366,8 @@ abstract class ACore implements JsonSerializable {
|
|||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getUrlRoot(): string {
|
||||
return $this->root;
|
||||
public function getUrlSocial(): string {
|
||||
return $this->urlSocial;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -352,8 +375,27 @@ abstract class ACore implements JsonSerializable {
|
|||
*
|
||||
* @return ACore
|
||||
*/
|
||||
public function setUrlRoot(string $path): ACore {
|
||||
$this->root = $path;
|
||||
public function setUrlSocial(string $path): ACore {
|
||||
$this->urlSocial = $path;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getUrlCloud(): string {
|
||||
return $this->urlCloud;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
*
|
||||
* @return ACore
|
||||
*/
|
||||
public function setUrlCloud(string $path): ACore {
|
||||
$this->urlCloud = $path;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@ -568,6 +610,36 @@ abstract class ACore implements JsonSerializable {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function gotIcon(): bool {
|
||||
if ($this->icon === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Document
|
||||
*/
|
||||
public function getIcon(): Document {
|
||||
return $this->icon;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Document $icon
|
||||
*
|
||||
* @return ACore
|
||||
*/
|
||||
public function setIcon(Document $icon): ACore {
|
||||
$this->icon = $icon;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
|
@ -623,7 +695,6 @@ abstract class ACore implements JsonSerializable {
|
|||
return $this;
|
||||
}
|
||||
|
||||
|
||||
return $this->getParent()
|
||||
->getRoot($chain);
|
||||
}
|
||||
|
@ -792,6 +863,23 @@ abstract class ACore implements JsonSerializable {
|
|||
* @param array $data
|
||||
*/
|
||||
public function import(array $data) {
|
||||
$this->setId($this->get('id', $data, ''));
|
||||
$this->setType($this->get('type', $data, ''));
|
||||
$this->setUrl($this->get('url', $data, ''));
|
||||
$this->setSummary($this->get('summary', $data, ''));
|
||||
$this->setToArray($this->getArray('to', $data, []));
|
||||
$this->setCcArray($this->getArray('cc', $data, []));
|
||||
$this->setPublished($this->get('published', $data, ''));
|
||||
$this->setActorId($this->get('actor', $data, ''));
|
||||
$this->setObjectId($this->get('object', $data, ''));
|
||||
$this->setLocal(($this->getInt('local', $data, 0) === 1));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*/
|
||||
public function importFromDatabase(array $data) {
|
||||
$this->setId($this->get('id', $data, ''));
|
||||
$this->setType($this->get('type', $data, ''));
|
||||
$this->setUrl($this->get('url', $data, ''));
|
||||
|
@ -821,7 +909,7 @@ abstract class ACore implements JsonSerializable {
|
|||
|
||||
$this->addEntry('id', $this->getId());
|
||||
$this->addEntry('type', $this->getType());
|
||||
$this->addEntry('url', $this->getId());
|
||||
$this->addEntry('url', $this->getUrl());
|
||||
|
||||
$this->addEntry('to', $this->getTo());
|
||||
$this->addEntryArray('to', $this->getToArray());
|
||||
|
@ -850,11 +938,17 @@ abstract class ACore implements JsonSerializable {
|
|||
$this->addEntry('object', $this->getObjectId());
|
||||
}
|
||||
|
||||
if ($this->gotIcon()) {
|
||||
$this->addEntryItem('icon', $this->getIcon());
|
||||
}
|
||||
|
||||
if ($this->isCompleteDetails()) {
|
||||
$this->addEntry('source', $this->getSource());
|
||||
}
|
||||
|
||||
$this->addEntryBool('local', $this->isLocal());
|
||||
if ($this->isLocal()) {
|
||||
$this->addEntryBool('local', $this->isLocal());
|
||||
}
|
||||
|
||||
return $this->getEntries();
|
||||
}
|
||||
|
|
|
@ -1,157 +0,0 @@
|
|||
<?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\Model\ActivityPub\Cache;
|
||||
|
||||
|
||||
class CacheActor {
|
||||
|
||||
/** @var int */
|
||||
private $id;
|
||||
|
||||
/** @var string */
|
||||
private $account = '';
|
||||
|
||||
/** @var string */
|
||||
private $url;
|
||||
|
||||
/** @var array */
|
||||
private $actor = [];
|
||||
|
||||
/** @var int */
|
||||
private $creation = 0;
|
||||
|
||||
|
||||
/**
|
||||
* CacheActor constructor.
|
||||
*
|
||||
* @param int $id
|
||||
*/
|
||||
public function __construct($id = 0) {
|
||||
$this->id = $id;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getId(): int {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
*
|
||||
* @return CacheActor
|
||||
*/
|
||||
public function setId(int $id): CacheActor {
|
||||
$this->account = $id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getAccount(): string {
|
||||
return $this->account;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $account
|
||||
*
|
||||
* @return CacheActor
|
||||
*/
|
||||
public function setAccount(string $account): CacheActor {
|
||||
$this->account = $account;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getUrl(): string {
|
||||
return $this->url;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
*
|
||||
* @return CacheActor
|
||||
*/
|
||||
public function setUrl(string $url): CacheActor {
|
||||
$this->url = $url;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getActor(): array {
|
||||
return $this->actor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $actor
|
||||
*
|
||||
* @return CacheActor
|
||||
*/
|
||||
public function setActor(array $actor): CacheActor {
|
||||
$this->actor = $actor;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getCreation(): int {
|
||||
return $this->creation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $creation
|
||||
*
|
||||
* @return CacheActor
|
||||
*/
|
||||
public function setCreation(int $creation): CacheActor {
|
||||
$this->creation = $creation;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,246 @@
|
|||
<?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\Model\ActivityPub;
|
||||
|
||||
|
||||
use DateTime;
|
||||
use JsonSerializable;
|
||||
use OCA\Social\Exceptions\UrlCloudException;
|
||||
|
||||
|
||||
/**
|
||||
* Class Document
|
||||
*
|
||||
* @package OCA\Social\Model\ActivityPub
|
||||
*/
|
||||
class Document extends ACore implements JsonSerializable {
|
||||
|
||||
|
||||
const TYPE = 'Document';
|
||||
|
||||
|
||||
/** @var string */
|
||||
private $mediaType = '';
|
||||
|
||||
/** @var string */
|
||||
private $mimeType = '';
|
||||
|
||||
/** @var string */
|
||||
private $localCopy = '';
|
||||
|
||||
/** @var int */
|
||||
private $caching = 0;
|
||||
|
||||
/** @var bool */
|
||||
private $public = false;
|
||||
|
||||
/** @var int */
|
||||
private $error = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Document constructor.
|
||||
*
|
||||
* @param ACore $parent
|
||||
*/
|
||||
public function __construct($parent = null) {
|
||||
parent::__construct($parent);
|
||||
|
||||
$this->setType(self::TYPE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getMediaType(): string {
|
||||
return $this->mediaType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $mediaType
|
||||
*
|
||||
* @return ACore
|
||||
*/
|
||||
public function setMediaType(string $mediaType): ACore {
|
||||
$this->mediaType = $mediaType;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getMimeType(): string {
|
||||
return $this->mimeType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $mimeType
|
||||
*
|
||||
* @return ACore
|
||||
*/
|
||||
public function setMimeType(string $mimeType): ACore {
|
||||
$this->mimeType = $mimeType;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getLocalCopy(): string {
|
||||
return $this->localCopy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $localCopy
|
||||
*
|
||||
* @return Document
|
||||
*/
|
||||
public function setLocalCopy(string $localCopy): Document {
|
||||
$this->localCopy = $localCopy;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isPublic(): bool {
|
||||
return $this->public;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $public
|
||||
*
|
||||
* @return Document
|
||||
*/
|
||||
public function setPublic(bool $public): Document {
|
||||
$this->public = $public;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getError(): int {
|
||||
return $this->error;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $error
|
||||
*
|
||||
* @return Document
|
||||
*/
|
||||
public function setError(int $error): Document {
|
||||
$this->error = $error;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getCaching(): int {
|
||||
return $this->caching;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $caching
|
||||
*
|
||||
* @return Document
|
||||
*/
|
||||
public function setCaching(int $caching): Document {
|
||||
$this->caching = $caching;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
* @throws UrlCloudException
|
||||
*/
|
||||
public function import(array $data) {
|
||||
parent::import($data);
|
||||
|
||||
$this->setMediaType($this->get('mediaType', $data, ''));
|
||||
|
||||
if ($this->getId() === '') {
|
||||
$this->generateUniqueId('/documents/g');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*/
|
||||
public function importFromDatabase(array $data) {
|
||||
parent::importFromDatabase($data);
|
||||
|
||||
$this->setPublic(($this->getInt('public', $data, 0) === 1) ? true : false);
|
||||
$this->setError($this->getInt('error', $data, 0));
|
||||
$this->setLocalCopy($this->get('local_copy', $data, ''));
|
||||
$this->setMediaType($this->get('media_type', $data, ''));
|
||||
$this->setMimeType($this->get('mime_type', $data, ''));
|
||||
|
||||
if ($this->get('caching', $data, '') === '') {
|
||||
$this->setCaching(0);
|
||||
} else {
|
||||
$date = new DateTime($this->get('caching', $data, ''));
|
||||
$this->setCaching($date->getTimestamp());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function jsonSerialize(): array {
|
||||
return array_merge(
|
||||
parent::jsonSerialize(),
|
||||
[
|
||||
'mediaType' => $this->getMediaType(),
|
||||
'mimeType' => $this->getMimeType(),
|
||||
'localCopy' => $this->getLocalCopy()
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
<?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\Model\ActivityPub;
|
||||
|
||||
|
||||
use JsonSerializable;
|
||||
use OCA\Social\Exceptions\UrlCloudException;
|
||||
|
||||
|
||||
/**
|
||||
* Class Image
|
||||
*
|
||||
* @package OCA\Social\Model\ActivityPub
|
||||
*/
|
||||
class Image extends Document implements JsonSerializable {
|
||||
|
||||
|
||||
const TYPE = 'Image';
|
||||
|
||||
|
||||
/**
|
||||
* Image constructor.
|
||||
*
|
||||
* @param ACore $parent
|
||||
*/
|
||||
public function __construct($parent = null) {
|
||||
parent::__construct($parent);
|
||||
|
||||
$this->setType(self::TYPE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
* @throws UrlCloudException
|
||||
*/
|
||||
public function import(array $data) {
|
||||
parent::import($data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function jsonSerialize(): array {
|
||||
return array_merge(
|
||||
parent::jsonSerialize(),
|
||||
[
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -199,7 +199,6 @@ class Note extends ACore implements JsonSerializable {
|
|||
public function import(array $data) {
|
||||
parent::import($data);
|
||||
|
||||
$this->setSummary($this->get('summary', $data, ''));
|
||||
$this->setInReplyTo($this->get('inReplyTo', $data, ''));
|
||||
$this->setAttributedTo($this->get('attributedTo', $data, ''));
|
||||
$this->setSensitive($this->getBool('sensitive', $data, false));
|
||||
|
@ -219,7 +218,7 @@ class Note extends ACore implements JsonSerializable {
|
|||
parent::jsonSerialize(),
|
||||
[
|
||||
'content' => $this->getContent(),
|
||||
'attributedTo' => $this->getUrlRoot() . $this->getAttributedTo(),
|
||||
'attributedTo' => $this->getUrlSocial() . $this->getAttributedTo(),
|
||||
'inReplyTo' => $this->getInReplyTo(),
|
||||
'sensitive' => $this->isSensitive(),
|
||||
'conversation' => $this->getConversation()
|
||||
|
|
|
@ -32,6 +32,7 @@ namespace OCA\Social\Model\ActivityPub;
|
|||
|
||||
|
||||
use JsonSerializable;
|
||||
use OCA\Social\Exceptions\UrlCloudException;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -340,9 +341,44 @@ class Person extends ACore implements JsonSerializable {
|
|||
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
* @throws UrlCloudException
|
||||
*/
|
||||
public function import(array $data) {
|
||||
parent::import($data);
|
||||
$this->setPreferredUsername($this->get('preferredUsername', $data, ''))
|
||||
->setPublicKey($this->get('publicKey.publicKeyPem', $data))
|
||||
->setSharedInbox($this->get('endpoints.sharedInbox', $data))
|
||||
->setName($this->get('name', $data, ''))
|
||||
->setAccount($this->get('account', $data, ''))
|
||||
->setInbox($this->get('inbox', $data, ''))
|
||||
->setOutbox($this->get('outbox', $data, ''))
|
||||
->setFollowers($this->get('followers', $data, ''))
|
||||
->setFollowing($this->get('following', $data, ''))
|
||||
->setFeatured($this->get('featured', $data, ''));
|
||||
|
||||
$icon = new Image($this);
|
||||
$icon->setUrlCloud($this->getUrlCloud());
|
||||
$icon->import($this->getArray('icon', $data, []));
|
||||
|
||||
if ($icon->getType() === Image::TYPE) {
|
||||
$this->setIcon($icon);
|
||||
}
|
||||
|
||||
|
||||
// ->setCreation($this->getInt('creation', $data, 0));
|
||||
|
||||
// if ($this->getPreferredUsername() === '') {
|
||||
// $this->setType('Invalid');
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*/
|
||||
public function importFromDatabase(array $data) {
|
||||
parent::importFromDatabase($data);
|
||||
$this->setPreferredUsername($this->get('preferred_username', $data, ''))
|
||||
->setName($this->get('name', $data, ''))
|
||||
->setAccount($this->get('account', $data, ''))
|
||||
|
@ -370,8 +406,8 @@ class Person extends ACore implements JsonSerializable {
|
|||
parent::jsonSerialize(),
|
||||
[
|
||||
'aliases' => [
|
||||
$this->getUrlRoot() . '@' . $this->getPreferredUsername(),
|
||||
$this->getUrlRoot() . 'users/' . $this->getPreferredUsername()
|
||||
$this->getUrlSocial() . '@' . $this->getPreferredUsername(),
|
||||
$this->getUrlSocial() . 'users/' . $this->getPreferredUsername()
|
||||
],
|
||||
'preferredUsername' => $this->getPreferredUsername(),
|
||||
'name' => $this->getName(),
|
||||
|
|
|
@ -0,0 +1,161 @@
|
|||
<?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\ActivityPub;
|
||||
|
||||
|
||||
use Exception;
|
||||
use OCA\Social\Db\CacheDocumentsRequest;
|
||||
use OCA\Social\Exceptions\CacheContentException;
|
||||
use OCA\Social\Exceptions\CacheContentSizeException;
|
||||
use OCA\Social\Exceptions\CacheDocumentDoesNotExistException;
|
||||
use OCA\Social\Model\ActivityPub\ACore;
|
||||
use OCA\Social\Model\ActivityPub\Document;
|
||||
use OCA\Social\Service\CacheService;
|
||||
use OCA\Social\Service\MiscService;
|
||||
use OCP\Files\NotPermittedException;
|
||||
use OCP\Files\SimpleFS\ISimpleFile;
|
||||
|
||||
|
||||
class DocumentService implements ICoreService {
|
||||
|
||||
|
||||
/** @var CacheDocumentsRequest */
|
||||
private $cacheDocumentsRequest;
|
||||
|
||||
/** @var CacheService */
|
||||
private $cacheService;
|
||||
|
||||
/** @var MiscService */
|
||||
private $miscService;
|
||||
|
||||
|
||||
/**
|
||||
* DocumentService constructor.
|
||||
*
|
||||
* @param CacheDocumentsRequest $cacheDocumentsRequest
|
||||
* @param CacheService $cacheService
|
||||
* @param MiscService $miscService
|
||||
*/
|
||||
public function __construct(
|
||||
CacheDocumentsRequest $cacheDocumentsRequest, CacheService $cacheService,
|
||||
MiscService $miscService
|
||||
) {
|
||||
$this->cacheDocumentsRequest = $cacheDocumentsRequest;
|
||||
$this->cacheService = $cacheService;
|
||||
$this->miscService = $miscService;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $id
|
||||
* @param bool $public
|
||||
*
|
||||
* @return Document
|
||||
* @throws CacheDocumentDoesNotExistException
|
||||
* @throws NotPermittedException
|
||||
*/
|
||||
public function cacheRemoteDocument(string $id, bool $public = false) {
|
||||
$document = $this->cacheDocumentsRequest->getById($id, $public);
|
||||
if ($document->getLocalCopy() !== '') {
|
||||
return $document;
|
||||
}
|
||||
|
||||
// TODO - ignore this if getCaching is older than 15 minutes
|
||||
if ($document->getCaching() > (time() - (CacheDocumentsRequest::CACHE_TTL * 60))) {
|
||||
return $document;
|
||||
}
|
||||
|
||||
$this->cacheDocumentsRequest->initCaching($document);
|
||||
|
||||
try {
|
||||
$localCopy = $this->cacheService->saveRemoteFileToCache($document->getUrl(), $mime);
|
||||
$document->setMimeType($mime);
|
||||
$document->setLocalCopy($localCopy);
|
||||
$this->cacheDocumentsRequest->endCaching($document);
|
||||
} catch (CacheContentSizeException $e) {
|
||||
$this->cacheDocumentsRequest->endCaching($document);
|
||||
} catch (CacheContentException $e) {
|
||||
}
|
||||
|
||||
return $document;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $id
|
||||
*
|
||||
* @param bool $public
|
||||
*
|
||||
* @return ISimpleFile
|
||||
* @throws CacheContentException
|
||||
* @throws CacheDocumentDoesNotExistException
|
||||
* @throws NotPermittedException
|
||||
*/
|
||||
public function getFromCache(string $id, bool $public = false) {
|
||||
$document = $this->cacheRemoteDocument($id, $public);
|
||||
|
||||
return $this->cacheService->getContentFromCache($document->getLocalCopy());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return int
|
||||
* @throws CacheDocumentDoesNotExistException
|
||||
* @throws NotPermittedException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function manageCacheDocuments(): int {
|
||||
$update = $this->cacheDocumentsRequest->getNotCachedDocuments();
|
||||
|
||||
foreach ($update as $item) {
|
||||
$this->cacheRemoteDocument($item->getId());
|
||||
}
|
||||
|
||||
return sizeof($update);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param ACore $item
|
||||
*/
|
||||
public function parse(ACore $item) {
|
||||
// TODO: Implement parse() method.
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ACore $item
|
||||
*/
|
||||
public function delete(ACore $item) {
|
||||
// TODO: Implement delete() method.
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -34,7 +34,9 @@ namespace OCA\Social\Service\ActivityPub;
|
|||
use Exception;
|
||||
use OCA\Social\Db\FollowsRequest;
|
||||
use OCA\Social\Exceptions\ActorDoesNotExistException;
|
||||
use OCA\Social\Exceptions\CacheActorDoesNotExistException;
|
||||
use OCA\Social\Exceptions\FollowDoesNotExistException;
|
||||
use OCA\Social\Exceptions\InvalidResourceException;
|
||||
use OCA\Social\Exceptions\RequestException;
|
||||
use OCA\Social\Exceptions\SocialAppConfigException;
|
||||
use OCA\Social\Model\ActivityPub\ACore;
|
||||
|
@ -96,14 +98,17 @@ class FollowService implements ICoreService {
|
|||
* @param Person $actor
|
||||
* @param string $account
|
||||
*
|
||||
* @throws ActorDoesNotExistException
|
||||
* @throws RequestException
|
||||
* @throws SocialAppConfigException
|
||||
* @throws ActorDoesNotExistException
|
||||
* @throws CacheActorDoesNotExistException
|
||||
* @throws InvalidResourceException
|
||||
*/
|
||||
public function followAccount(Person $actor, string $account) {
|
||||
$remoteActor = $this->personService->getFromAccount($account);
|
||||
$follow = new Follow();
|
||||
$follow->generateUniqueId($this->configService->getCloudAddress());
|
||||
$follow->setUrlCloud($this->configService->getCloudAddress());
|
||||
$follow->generateUniqueId();
|
||||
$follow->setActorId($actor->getId());
|
||||
$follow->setObjectId($remoteActor->getId());
|
||||
|
||||
|
@ -124,6 +129,8 @@ class FollowService implements ICoreService {
|
|||
* @param Person $actor
|
||||
* @param string $account
|
||||
*
|
||||
* @throws CacheActorDoesNotExistException
|
||||
* @throws InvalidResourceException
|
||||
* @throws RequestException
|
||||
*/
|
||||
public function unfollowAccount(Person $actor, string $account) {
|
||||
|
|
|
@ -126,7 +126,7 @@ class NoteService implements ICoreService {
|
|||
$note->setId($this->configService->generateId('@' . $actor->getPreferredUsername()));
|
||||
$note->setPublished(date("c"));
|
||||
$note->setAttributedTo(
|
||||
$this->configService->getUrlRoot() . '@' . $actor->getPreferredUsername()
|
||||
$this->configService->getUrlSocial() . '@' . $actor->getPreferredUsername()
|
||||
);
|
||||
|
||||
$this->setRecipient($note, $actor, $type);
|
||||
|
|
|
@ -34,11 +34,16 @@ namespace OCA\Social\Service\ActivityPub;
|
|||
use daita\MySmallPhpTools\Traits\TArrayTools;
|
||||
use Exception;
|
||||
use OCA\Social\Db\CacheActorsRequest;
|
||||
use OCA\Social\Db\CacheDocumentsRequest;
|
||||
use OCA\Social\Exceptions\CacheActorDoesNotExistException;
|
||||
use OCA\Social\Exceptions\CacheDocumentDoesNotExistException;
|
||||
use OCA\Social\Exceptions\InvalidResourceException;
|
||||
use OCA\Social\Exceptions\RequestException;
|
||||
use OCA\Social\Exceptions\SocialAppConfigException;
|
||||
use OCA\Social\Exceptions\UrlCloudException;
|
||||
use OCA\Social\Model\ActivityPub\ACore;
|
||||
use OCA\Social\Model\ActivityPub\Person;
|
||||
use OCA\Social\Service\ConfigService;
|
||||
use OCA\Social\Service\ICoreService;
|
||||
use OCA\Social\Service\InstanceService;
|
||||
use OCA\Social\Service\MiscService;
|
||||
|
@ -58,9 +63,15 @@ class PersonService implements ICoreService {
|
|||
/** @var CacheActorsRequest */
|
||||
private $cacheActorsRequest;
|
||||
|
||||
/** @var CacheDocumentsRequest */
|
||||
private $cacheDocumentsRequest;
|
||||
|
||||
/** @var InstanceService */
|
||||
private $instanceService;
|
||||
|
||||
/** @var ConfigService */
|
||||
private $configService;
|
||||
|
||||
/** @var MiscService */
|
||||
private $miscService;
|
||||
|
||||
|
@ -69,15 +80,19 @@ class PersonService implements ICoreService {
|
|||
* UndoService constructor.
|
||||
*
|
||||
* @param CacheActorsRequest $cacheActorsRequest
|
||||
* @param CacheDocumentsRequest $cacheDocumentsRequest
|
||||
* @param InstanceService $instanceService
|
||||
* @param ConfigService $configService
|
||||
* @param MiscService $miscService
|
||||
*/
|
||||
public function __construct(
|
||||
CacheActorsRequest $cacheActorsRequest, InstanceService $instanceService,
|
||||
MiscService $miscService
|
||||
CacheActorsRequest $cacheActorsRequest, CacheDocumentsRequest $cacheDocumentsRequest,
|
||||
InstanceService $instanceService, ConfigService $configService, MiscService $miscService
|
||||
) {
|
||||
$this->cacheActorsRequest = $cacheActorsRequest;
|
||||
$this->cacheDocumentsRequest = $cacheDocumentsRequest;
|
||||
$this->instanceService = $instanceService;
|
||||
$this->configService = $configService;
|
||||
$this->miscService = $miscService;
|
||||
}
|
||||
|
||||
|
@ -108,6 +123,8 @@ class PersonService implements ICoreService {
|
|||
* @return Person
|
||||
* @throws InvalidResourceException
|
||||
* @throws RequestException
|
||||
* @throws SocialAppConfigException
|
||||
* @throws UrlCloudException
|
||||
*/
|
||||
public function getFromId(string $id, bool $refresh = false): Person {
|
||||
|
||||
|
@ -125,19 +142,8 @@ class PersonService implements ICoreService {
|
|||
$actor = $this->cacheActorsRequest->getFromId($id);
|
||||
} catch (CacheActorDoesNotExistException $e) {
|
||||
$object = $this->instanceService->retrieveObject($id);
|
||||
$actor = new Person();
|
||||
$actor->import($object);
|
||||
$actor->setSource(json_encode($object, JSON_UNESCAPED_SLASHES));
|
||||
|
||||
$actor->setPreferredUsername($this->get('preferredUsername', $object, ''));
|
||||
$actor->setPublicKey($this->get('publicKey.publicKeyPem', $object));
|
||||
$actor->setSharedInbox($this->get('endpoints.sharedInbox', $object));
|
||||
$actor = $this->generateActorFromObject($object);
|
||||
$actor->setAccount($actor->getPreferredUsername() . '@' . $this->get('_host', $object));
|
||||
|
||||
if ($actor->getType() !== Person::TYPE) {
|
||||
throw new InvalidResourceException();
|
||||
}
|
||||
|
||||
try {
|
||||
$this->parse($actor);
|
||||
} catch (Exception $e) {
|
||||
|
@ -158,6 +164,8 @@ class PersonService implements ICoreService {
|
|||
* @throws InvalidResourceException
|
||||
* @throws RequestException
|
||||
* @throws CacheActorDoesNotExistException
|
||||
* @throws SocialAppConfigException
|
||||
* @throws UrlCloudException
|
||||
*/
|
||||
public function getFromAccount(string $account, bool $retrieve = true): Person {
|
||||
|
||||
|
@ -169,19 +177,8 @@ class PersonService implements ICoreService {
|
|||
}
|
||||
|
||||
$object = $this->instanceService->retrieveAccount($account);
|
||||
|
||||
$actor = new Person();
|
||||
$actor->import($object);
|
||||
|
||||
$actor = $this->generateActorFromObject($object);
|
||||
$actor->setAccount($account);
|
||||
$actor->setPreferredUsername($this->get('preferredUsername', $object, ''));
|
||||
$actor->setPublicKey($this->get('publicKey.publicKeyPem', $object));
|
||||
$actor->setSharedInbox($this->get('endpoints.sharedInbox', $object));
|
||||
|
||||
if ($actor->getType() !== Person::TYPE) {
|
||||
throw new InvalidResourceException();
|
||||
}
|
||||
|
||||
try {
|
||||
$this->parse($actor);
|
||||
} catch (Exception $e) {
|
||||
|
@ -193,6 +190,40 @@ class PersonService implements ICoreService {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $object
|
||||
*
|
||||
* @return Person
|
||||
* @throws InvalidResourceException
|
||||
* @throws SocialAppConfigException
|
||||
* @throws UrlCloudException
|
||||
*/
|
||||
private function generateActorFromObject(array $object) {
|
||||
|
||||
$actor = new Person();
|
||||
$actor->setUrlCloud($this->configService->getCloudAddress());
|
||||
$actor->import($object);
|
||||
|
||||
if ($actor->getType() !== Person::TYPE) {
|
||||
throw new InvalidResourceException();
|
||||
}
|
||||
|
||||
$actor->setSource(json_encode($object, JSON_UNESCAPED_SLASHES));
|
||||
// $actor->setPreferredUsername($this->get('preferredUsername', $object, ''));
|
||||
// $actor->setPublicKey($this->get('publicKey.publicKeyPem', $object));
|
||||
// $actor->setSharedInbox($this->get('endpoints.sharedInbox', $object));
|
||||
// $actor->setAccount($actor->getPreferredUsername() . '@' . $this->get('_host', $object));
|
||||
//
|
||||
// $icon = new Image($actor);
|
||||
// $icon->setUrlCloud($this->configService->getCloudAddress());
|
||||
// $icon->import($this->getArray('icon', $object, []));
|
||||
// if ($icon->getType() === Image::TYPE) {
|
||||
// $actor->setIcon($icon);
|
||||
// }
|
||||
//
|
||||
return $actor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $search
|
||||
*
|
||||
|
@ -216,10 +247,40 @@ class PersonService implements ICoreService {
|
|||
return;
|
||||
}
|
||||
|
||||
if ($person->gotIcon()) {
|
||||
try {
|
||||
$icon = $this->cacheDocumentsRequest->getBySource(
|
||||
$person->getIcon()
|
||||
->getUrl()
|
||||
);
|
||||
$person->setIcon($icon);
|
||||
} catch (CacheDocumentDoesNotExistException $e) {
|
||||
$this->cacheDocumentsRequest->save($person->getIcon());
|
||||
}
|
||||
}
|
||||
|
||||
$this->cacheActorsRequest->save($person);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
* @return int
|
||||
*/
|
||||
public function manageCacheRemoteActors(): int {
|
||||
$update = $this->cacheActorsRequest->getRemoteActorsToUpdate();
|
||||
|
||||
foreach ($update as $item) {
|
||||
try {
|
||||
$this->getFromId($item->getId(), true);
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
}
|
||||
|
||||
return sizeof($update);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param ACore $item
|
||||
*/
|
||||
|
|
|
@ -309,7 +309,7 @@ class ActivityService {
|
|||
$localActor = $this->getActorFromItem($activity);
|
||||
|
||||
$localActorLink =
|
||||
$this->configService->getUrlRoot() . '@' . $localActor->getPreferredUsername();
|
||||
$this->configService->getUrlSocial() . '@' . $localActor->getPreferredUsername();
|
||||
$signature = "(request-target): post " . $path->getPath() . "\nhost: " . $path->getAddress()
|
||||
. "\ndate: " . $date;
|
||||
|
||||
|
|
|
@ -128,18 +128,6 @@ class ActorService {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $search
|
||||
*
|
||||
* @deprecated - used !?
|
||||
* @return Person[]
|
||||
* @throws SocialAppConfigException
|
||||
*/
|
||||
public function searchLocalAccounts(string $search): array {
|
||||
return $this->actorsRequest->searchFromUsername($search);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Method should be called by the frontend and will generate a fresh Social account for
|
||||
* the user, using the userId and the username.
|
||||
|
@ -234,4 +222,22 @@ class ActorService {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
* @return int
|
||||
*/
|
||||
public function manageCacheLocalActors(): int {
|
||||
$update = $this->actorsRequest->getAll();
|
||||
|
||||
foreach ($update as $item) {
|
||||
try {
|
||||
$this->cacheLocalActorByUsername($item->getPreferredUsername(), true);
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
}
|
||||
|
||||
return sizeof($update);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,170 @@
|
|||
<?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 Exception;
|
||||
use OCA\Social\Exceptions\CacheContentException;
|
||||
use OCA\Social\Exceptions\CacheContentSizeException;
|
||||
use OCP\Files\IAppData;
|
||||
use OCP\Files\NotFoundException;
|
||||
use OCP\Files\NotPermittedException;
|
||||
use OCP\Files\SimpleFS\ISimpleFile;
|
||||
|
||||
|
||||
class CacheService {
|
||||
|
||||
|
||||
const ERROR_MAX_SIZE = 1;
|
||||
|
||||
|
||||
/** @var IAppData */
|
||||
private $appData;
|
||||
|
||||
/** @var ConfigService */
|
||||
private $configService;
|
||||
|
||||
/** @var MiscService */
|
||||
private $miscService;
|
||||
|
||||
|
||||
/**
|
||||
* CacheService constructor.
|
||||
*
|
||||
* @param IAppData $appData
|
||||
* @param ConfigService $configService
|
||||
* @param MiscService $miscService
|
||||
*/
|
||||
public function __construct(
|
||||
IAppData $appData, ConfigService $configService, MiscService $miscService
|
||||
) {
|
||||
$this->appData = $appData;
|
||||
$this->configService = $configService;
|
||||
$this->miscService = $miscService;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
*
|
||||
* @param string $mime
|
||||
*
|
||||
* @return string
|
||||
* @throws CacheContentException
|
||||
* @throws NotPermittedException
|
||||
* @throws CacheContentSizeException
|
||||
*/
|
||||
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)
|
||||
);
|
||||
|
||||
// creating a path aa/bb/cc/dd/ from the filename aabbccdd-0123-[...]
|
||||
$path = chunk_split(substr($filename, 0, 8), 2, '/');
|
||||
|
||||
try {
|
||||
$folder = $this->appData->getFolder($path);
|
||||
} catch (NotFoundException $e) {
|
||||
$folder = $this->appData->newFolder($path);
|
||||
}
|
||||
|
||||
$content = $this->retrieveContent($url);
|
||||
|
||||
// TODO - get mime type in a better way.
|
||||
// To get the mime type, we create a temp file
|
||||
$tmpFile = tmpfile();
|
||||
$tmpPath = stream_get_meta_data($tmpFile)['uri'];
|
||||
fwrite($tmpFile, $content);
|
||||
$mime = mime_content_type($tmpPath);
|
||||
fclose($tmpFile);
|
||||
|
||||
$cache = $folder->newFile($filename);
|
||||
$cache->putContent($content);
|
||||
|
||||
return $path . $filename;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
*
|
||||
* @return ISimpleFile
|
||||
* @throws CacheContentException
|
||||
*/
|
||||
public function getContentFromCache(string $path) {
|
||||
|
||||
$pos = strrpos($path, '/');
|
||||
$dir = substr($path, 0, $pos);
|
||||
$filename = substr($path, $pos + 1);
|
||||
|
||||
try {
|
||||
$file = $this->appData->getFolder($dir)
|
||||
->getFile($filename);
|
||||
|
||||
return $file;
|
||||
} catch (Exception $e) {
|
||||
throw new CacheContentException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
*
|
||||
* @return string
|
||||
* @throws CacheContentException
|
||||
* @throws CacheContentSizeException
|
||||
*/
|
||||
public function retrieveContent(string $url) {
|
||||
$maxSize =
|
||||
$this->configService->getAppValueInt(ConfigService::SOCIAL_MAX_SIZE) * 1024 * 1024;
|
||||
|
||||
$fd = fopen($url, "r");
|
||||
if ($fd === false) {
|
||||
throw new CacheContentException();
|
||||
}
|
||||
|
||||
$content = '';
|
||||
while (!feof($fd)) {
|
||||
$content .= fread($fd, 4096);
|
||||
if (strlen($content) > $maxSize) {
|
||||
throw new CacheContentSizeException();
|
||||
}
|
||||
}
|
||||
fclose($fd);
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -52,10 +52,12 @@ class ConfigService {
|
|||
|
||||
|
||||
const SOCIAL_ADDRESS = 'address';
|
||||
const SOCIAL_MAX_SIZE = 'max_size';
|
||||
|
||||
/** @var array */
|
||||
public $defaults = [
|
||||
self::SOCIAL_ADDRESS => ''
|
||||
self::SOCIAL_ADDRESS => '',
|
||||
self::SOCIAL_MAX_SIZE => 25
|
||||
];
|
||||
|
||||
/** @var string */
|
||||
|
@ -111,6 +113,22 @@ class ConfigService {
|
|||
return $this->config->getAppValue(Application::APP_NAME, $key, $defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a value by key
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getAppValueInt(string $key): int {
|
||||
$defaultValue = null;
|
||||
if (array_key_exists($key, $this->defaults)) {
|
||||
$defaultValue = $this->defaults[$key];
|
||||
}
|
||||
|
||||
return (int)$this->config->getAppValue(Application::APP_NAME, $key, $defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a value by key
|
||||
*
|
||||
|
@ -211,13 +229,11 @@ class ConfigService {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param bool $host
|
||||
* @param string $cloudAddress
|
||||
*
|
||||
* @return string
|
||||
* @throws SocialAppConfigException
|
||||
*/
|
||||
public function setCloudAddress(string $cloudAddress) {
|
||||
// TODO: Validate
|
||||
$this->setAppValue(self::SOCIAL_ADDRESS, $cloudAddress);
|
||||
}
|
||||
|
||||
|
@ -249,10 +265,12 @@ class ConfigService {
|
|||
|
||||
|
||||
/**
|
||||
* // TODO - check the Apps folder
|
||||
*
|
||||
* @return string
|
||||
* @throws SocialAppConfigException
|
||||
*/
|
||||
public function getUrlRoot(): string {
|
||||
public function getUrlSocial(): string {
|
||||
return $this->getCloudAddress() . '/apps/social/';
|
||||
}
|
||||
|
||||
|
@ -267,7 +285,7 @@ class ConfigService {
|
|||
public function generateId(string $path = '', $generateId = true): string {
|
||||
$path = $this->withoutBeginSlash($this->withEndSlash($path));
|
||||
|
||||
$id = $this->getUrlRoot() . $path;
|
||||
$id = $this->getUrlSocial() . $path;
|
||||
if ($generateId === true) {
|
||||
$id .= time() . crc32(uniqid());
|
||||
}
|
||||
|
|
|
@ -33,14 +33,18 @@ namespace OCA\Social\Service;
|
|||
|
||||
use daita\MySmallPhpTools\Traits\TArrayTools;
|
||||
use Exception;
|
||||
use OCA\Social\Exceptions\SocialAppConfigException;
|
||||
use OCA\Social\Exceptions\UnknownItemException;
|
||||
use OCA\Social\Exceptions\UrlCloudException;
|
||||
use OCA\Social\Model\ActivityPub\ACore;
|
||||
use OCA\Social\Model\ActivityPub\Activity\Accept;
|
||||
use OCA\Social\Model\ActivityPub\Activity\Create;
|
||||
use OCA\Social\Model\ActivityPub\Activity\Delete;
|
||||
use OCA\Social\Model\ActivityPub\Activity\Reject;
|
||||
use OCA\Social\Model\ActivityPub\Activity\Tombstone;
|
||||
use OCA\Social\Model\ActivityPub\Document;
|
||||
use OCA\Social\Model\ActivityPub\Follow;
|
||||
use OCA\Social\Model\ActivityPub\Image;
|
||||
use OCA\Social\Model\ActivityPub\Note;
|
||||
use OCA\Social\Model\ActivityPub\Activity\Undo;
|
||||
use OCA\Social\Service\ActivityPub\DeleteService;
|
||||
|
@ -67,6 +71,8 @@ class ImportService {
|
|||
/** @var DeleteService */
|
||||
private $deleteService;
|
||||
|
||||
private $configService;
|
||||
|
||||
/** @var MiscService */
|
||||
private $miscService;
|
||||
|
||||
|
@ -78,17 +84,18 @@ class ImportService {
|
|||
* @param UndoService $undoService
|
||||
* @param FollowService $followService
|
||||
* @param DeleteService $deleteService
|
||||
* @param ConfigService $configService
|
||||
* @param MiscService $miscService
|
||||
*/
|
||||
public function __construct(
|
||||
NoteService $noteService, UndoService $undoService, FollowService $followService,
|
||||
DeleteService $deleteService,
|
||||
MiscService $miscService
|
||||
DeleteService $deleteService, ConfigService $configService, MiscService $miscService
|
||||
) {
|
||||
$this->noteService = $noteService;
|
||||
$this->undoService = $undoService;
|
||||
$this->followService = $followService;
|
||||
$this->deleteService = $deleteService;
|
||||
$this->configService = $configService;
|
||||
$this->miscService = $miscService;
|
||||
}
|
||||
|
||||
|
@ -98,6 +105,8 @@ class ImportService {
|
|||
*
|
||||
* @return ACore
|
||||
* @throws UnknownItemException
|
||||
* @throws UrlCloudException
|
||||
* @throws SocialAppConfigException
|
||||
*/
|
||||
public function import(string $json) {
|
||||
$data = json_decode($json, true);
|
||||
|
@ -113,6 +122,8 @@ class ImportService {
|
|||
*
|
||||
* @return ACore
|
||||
* @throws UnknownItemException
|
||||
* @throws UrlCloudException
|
||||
* @throws SocialAppConfigException
|
||||
*/
|
||||
private function createItem(array $data, $root = null): ACore {
|
||||
|
||||
|
@ -133,6 +144,10 @@ class ImportService {
|
|||
$item = new Note($root);
|
||||
break;
|
||||
|
||||
case Image::TYPE:
|
||||
$item = new Image($root);
|
||||
break;
|
||||
|
||||
case Follow::TYPE:
|
||||
$item = new Follow($root);
|
||||
break;
|
||||
|
@ -153,6 +168,7 @@ class ImportService {
|
|||
throw new UnknownItemException();
|
||||
}
|
||||
|
||||
$item->setUrlCloud($this->configService->getCloudAddress());
|
||||
$item->import($data);
|
||||
$item->setSource(json_encode($data, JSON_UNESCAPED_SLASHES));
|
||||
|
||||
|
@ -162,6 +178,13 @@ class ImportService {
|
|||
} catch (UnknownItemException $e) {
|
||||
}
|
||||
|
||||
try {
|
||||
/** @var Document $icon */
|
||||
$icon = $this->createItem($this->getArray('icon', $data, []), $item);
|
||||
$item->setIcon($icon);
|
||||
} catch (UnknownItemException $e) {
|
||||
}
|
||||
|
||||
return $item;
|
||||
}
|
||||
|
||||
|
@ -205,6 +228,10 @@ class ImportService {
|
|||
$service = $this->followService;
|
||||
break;
|
||||
|
||||
// case Image::TYPE:
|
||||
// $service = $this->imageService;
|
||||
// break;
|
||||
|
||||
case Note::TYPE:
|
||||
$service = $this->noteService;
|
||||
break;
|
||||
|
|
Ładowanie…
Reference in New Issue