Merge pull request #53 from nextcloud-gmbh/activitypub/document/image

Caching Image
pull/59/head
Maxence Lange 2018-11-27 15:35:21 -01:00 zatwierdzone przez GitHub
commit d81134130a
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
34 zmienionych plików z 1968 dodań i 269 usunięć

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

@ -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',

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

114
lib/Cron/Cache.php 100644
Wyświetl plik

@ -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) {
}
}
}

Wyświetl plik

@ -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
*

Wyświetl plik

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

Wyświetl plik

@ -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
*

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

@ -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'])

Wyświetl plik

@ -0,0 +1,8 @@
<?php
namespace OCA\Social\Exceptions;
class CacheContentException extends \Exception {
}

Wyświetl plik

@ -0,0 +1,8 @@
<?php
namespace OCA\Social\Exceptions;
class CacheContentSizeException extends \Exception {
}

Wyświetl plik

@ -0,0 +1,8 @@
<?php
namespace OCA\Social\Exceptions;
class CacheDocumentDoesNotExistException extends \Exception {
}

Wyświetl plik

@ -0,0 +1,8 @@
<?php
namespace OCA\Social\Exceptions;
class UrlCloudException extends \Exception {
}

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

@ -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()
]
);
}
}

Wyświetl plik

@ -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(),
[
]
);
}
}

Wyświetl plik

@ -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()

Wyświetl plik

@ -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(),

Wyświetl plik

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

Wyświetl plik

@ -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) {

Wyświetl plik

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

Wyświetl plik

@ -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
*/

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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