Signed-off-by: Maxence Lange <maxence@artificial-owl.com>
pull/20/head
Maxence Lange 2018-11-12 21:57:32 -01:00
rodzic 6d2d8f9565
commit f4a93ec743
13 zmienionych plików z 805 dodań i 189 usunięć

Wyświetl plik

@ -0,0 +1,100 @@
<?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\FollowsRequest;
use OCA\Social\Model\ActivityPub\ACore;
use OCA\Social\Model\ActivityPub\Person;
use OCA\Social\Model\ActivityPub\Follow;
use OCA\Social\Model\ActivityPub\OrderedCollection;
use OCA\Social\Service\ICoreService;
use OCA\Social\Service\MiscService;
class FollowService implements ICoreService {
/** @var FollowsRequest */
private $followsRequest;
/** @var MiscService */
private $miscService;
/**
* NoteService constructor.
*
* @param FollowsRequest $followsRequest
* @param MiscService $miscService
*/
public function __construct(FollowsRequest $followsRequest, MiscService $miscService) {
$this->followsRequest = $followsRequest;
$this->miscService = $miscService;
}
/**
* @param Person $actor
*
* @return OrderedCollection
*/
public function getFollowers(Person $actor): OrderedCollection {
$collection = new OrderedCollection();
$collection->setId($actor->getFollowers());
$collection->setTotalItems(20);
$collection->setFirst('...');
return $collection;
}
/**
* This method is called when saving the Follow object
*
* @param ACore $follow
*
* @throws Exception
*/
public function save(ACore $follow) {
/** @var Follow $follow */
if ($follow->getMetaBool('Undo') === false) {
$this->followsRequest->save($follow);
} else {
$this->followsRequest->delete($follow);
}
}
}

Wyświetl plik

@ -34,10 +34,12 @@ use Exception;
use OC\User\NoUserException;
use OCA\Social\Db\NotesRequest;
use OCA\Social\Exceptions\ActorDoesNotExistException;
use OCA\Social\Model\ActivityPub\Core;
use OCA\Social\Exceptions\RequestException;
use OCA\Social\Model\ActivityPub\ACore;
use OCA\Social\Model\ActivityPub\Note;
use OCA\Social\Model\ActivityPub\Person;
use OCA\Social\Model\InstancePath;
use OCA\Social\Service\ActivityPubService;
use OCA\Social\Service\ActivityService;
use OCA\Social\Service\ActorService;
use OCA\Social\Service\ConfigService;
use OCA\Social\Service\CurlService;
@ -53,6 +55,9 @@ class NoteService implements ICoreService {
/** @var ActorService */
private $actorService;
/** @var PersonService */
private $personService;
/** @var CurlService */
private $curlService;
@ -68,17 +73,18 @@ class NoteService implements ICoreService {
*
* @param NotesRequest $notesRequest
* @param ActorService $actorService
* @param PersonService $personService
* @param CurlService $curlService
* @param ConfigService $configService
* @param MiscService $miscService
*/
public function __construct(
NotesRequest $notesRequest, ActorService $actorService,
CurlService $curlService, ConfigService $configService,
MiscService $miscService
NotesRequest $notesRequest, ActorService $actorService, PersonService $personService,
CurlService $curlService, ConfigService $configService, MiscService $miscService
) {
$this->notesRequest = $notesRequest;
$this->actorService = $actorService;
$this->personService = $personService;
$this->curlService = $curlService;
$this->configService = $configService;
$this->miscService = $miscService;
@ -102,7 +108,7 @@ class NoteService implements ICoreService {
$note->setAttributedTo(
$this->configService->getRoot() . '@' . $actor->getPreferredUsername()
);
$note->setTo(ActivityPubService::TO_PUBLIC);
$note->setTo(ActivityService::TO_PUBLIC);
$note->setContent($content);
$note->saveAs($this);
@ -113,19 +119,43 @@ class NoteService implements ICoreService {
/**
* @param Note $note
* @param string $to
* @param int $type
* @param string $account
*
* @throws RequestException
*/
public function assignTo(Note $note, string $to, int $type) {
$note->addToArray($to);
public function assignTo(Note $note, string $account) {
if ($account === '') {
return;
}
$actor = $this->personService->getFromAccount($account);
$note->addToArray($actor->getId());
$note->addTag(
[
'type' => 'Mention',
'href' => $to
'href' => $actor->getId()
]
);
$note->addInstancePath(new InstancePath($to, $type));
$note->addInstancePath(new InstancePath($actor->getInbox()));
}
/**
* @param Note $note
* @param array $accounts
*
* @throws RequestException
*/
public function assignToArray(Note $note, array $accounts) {
if ($accounts === []) {
return;
}
foreach ($accounts as $account) {
$this->assignTo($note, $account);
}
}
@ -134,6 +164,10 @@ class NoteService implements ICoreService {
* @param string $replyTo
*/
public function replyTo(Note $note, string $replyTo) {
if ($replyTo === '') {
return;
}
$note->setInReplyTo($replyTo);
$note->addInstancePath(new InstancePath($replyTo));
}
@ -142,13 +176,44 @@ class NoteService implements ICoreService {
/**
* This method is called when saving the Note object
*
* @param Core $note
* @param ACore $note
*
* @throws Exception
*/
public function save(Core $note) {
public function save(ACore $note) {
/** @var Note $note */
$this->notesRequest->create($note);
$this->notesRequest->save($note);
}
/**
* @param string $userId
*
* @return Note[]
*/
public function getTimeline(): array {
return $this->notesRequest->getPublicNotes();
}
/**
* @param Person $actor
*
* @return Note[]
*/
public function getNotesForActor(Person $actor): array {
$privates = $this->getPrivateNotesForActor($actor);
return $privates;
}
/**
* @param Person $actor
*
* @return Note[]
*/
private function getPrivateNotesForActor(Person $actor): array {
return $this->notesRequest->getNotesForActorId($actor->getId());
}
}

Wyświetl plik

@ -0,0 +1,143 @@
<?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 daita\MySmallPhpTools\Traits\TArrayTools;
use Exception;
use OCA\Social\Db\CacheActorsRequest;
use OCA\Social\Exceptions\CacheActorDoesNotExistException;
use OCA\Social\Exceptions\RequestException;
use OCA\Social\Model\ActivityPub\ACore;
use OCA\Social\Model\ActivityPub\Person;
use OCA\Social\Model\InstancePath;
use OCA\Social\Service\ICoreService;
use OCA\Social\Service\InstanceService;
use OCA\Social\Service\MiscService;
/**
* Class PersonService
*
* @package OCA\Social\Service\ActivityPub
*/
class PersonService implements ICoreService {
use TArrayTools;
/** @var CacheActorsRequest */
private $cacheActorsRequest;
/** @var InstanceService */
private $instanceService;
/** @var MiscService */
private $miscService;
/**
* UndoService constructor.
*
* @param CacheActorsRequest $cacheActorsRequest
* @param InstanceService $instanceService
* @param MiscService $miscService
*/
public function __construct(
CacheActorsRequest $cacheActorsRequest, InstanceService $instanceService,
MiscService $miscService
) {
$this->cacheActorsRequest = $cacheActorsRequest;
$this->instanceService = $instanceService;
$this->miscService = $miscService;
}
/**
* @param string $account
*
* @return Person
* @throws RequestException
* @throws Exception
*/
public function getFromAccount(string $account): Person {
try {
$actor = $this->cacheActorsRequest->getFromAccount($account);
} catch (CacheActorDoesNotExistException $e) {
$object = $this->instanceService->retrieveAccount($account);
$actor = new Person();
$actor->import($object);
$actor->setAccount($account);
$actor->setPreferredUsername($this->get('preferredUsername', $object, ''));
$actor->setPublicKey($this->get('publicKey.publicKeyPem', $object));
$actor->setSharedInbox($this->get('endpoints.sharedInbox', $object));
$this->save($actor);
}
return $actor;
}
/**
* This method is called when saving the Follow object
*
* @param ACore $person
*
* @throws Exception
*/
public function save(ACore $person) {
/** @var Person $person */
$this->cacheActorsRequest->save($person);
}
// /**
// * @param Person $actor
// * @param int $type
// *
// * @return string
// */
// public function getPathFromActor(Person $actor, int $type) {
// switch ($type) {
// case InstancePath::INBOX:
// return parse_url($actor->getInbox(), PHP_URL_PATH);
// }
//
// return '';
// }
}

Wyświetl plik

@ -0,0 +1,66 @@
<?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\Model\ActivityPub\ACore;
use OCA\Social\Service\ICoreService;
use OCA\Social\Service\MiscService;
class UndoService implements ICoreService {
/** @var MiscService */
private $miscService;
/**
* UndoService constructor.
*
* @param MiscService $miscService
*/
public function __construct(MiscService $miscService) {
$this->miscService = $miscService;
}
/**
* @param ACore $undo
*
* @throws Exception
*/
public function save(ACore $undo) {
}
}

Wyświetl plik

@ -31,21 +31,32 @@ namespace OCA\Social\Service;
use daita\MySmallPhpTools\Model\Request;
use daita\MySmallPhpTools\Traits\TArrayTools;
use DateTime;
use Exception;
use OC\User\NoUserException;
use OCA\Social\Db\ActorsRequest;
use OCA\Social\Exceptions\ActorDoesNotExistException;
use OCA\Social\Exceptions\RequestException;
use OCA\Social\Model\ActivityPub\ActivityCreate;
use OCA\Social\Model\ActivityPub\Actor;
use OCA\Social\Model\ActivityPub\Core;
use OCA\Social\Exceptions\UnknownItemException;
use OCA\Social\Model\ActivityPub\ACore;
use OCA\Social\Model\ActivityPub\Activity;
use OCA\Social\Model\ActivityPub\Person;
use OCA\Social\Model\InstancePath;
use OCA\Social\Service\ActivityPub\FollowService;
use OCA\Social\Service\ActivityPub\NoteService;
use OCA\Social\Service\ActivityPub\PersonService;
use OCA\Social\Service\ActivityPub\UndoService;
use OCP\IRequest;
class ActivityPubService {
class ActivityService {
use TArrayTools;
const REQUEST_INBOX = 1;
const CONTEXT_ACTIVITYSTREAMS = 'https://www.w3.org/ns/activitystreams';
const CONTEXT_SECURITY = 'https://w3id.org/security/v1';
@ -60,6 +71,18 @@ class ActivityPubService {
/** @var ActorService */
private $actorService;
/** @var PersonService */
private $personService;
/** @var NoteService */
private $noteService;
/** @var UndoService */
private $undoService;
/** @var FollowService */
private $followService;
/** @var InstanceService */
private $instanceService;
@ -74,22 +97,33 @@ class ActivityPubService {
/**
* ActivityPubService constructor.
* ActivityService constructor.
*
* @param ActorsRequest $actorsRequest
* @param CurlService $curlService
* @param ActorService $actorService
* @param PersonService $personService
* @param NoteService $noteService
* @param UndoService $undoService
* @param FollowService $followService
* @param InstanceService $instanceService
* @param ConfigService $configService
* @param MiscService $miscService
*/
public function __construct(
ActorsRequest $actorsRequest, CurlService $curlService, ActorService $actorService,
InstanceService $instanceService, ConfigService $configService, MiscService $miscService
PersonService $personService, NoteService $noteService, UndoService $undoService,
FollowService $followService,
InstanceService $instanceService, ConfigService $configService,
MiscService $miscService
) {
$this->curlService = $curlService;
$this->actorsRequest = $actorsRequest;
$this->actorService = $actorService;
$this->personService = $personService;
$this->noteService = $noteService;
$this->undoService = $undoService;
$this->followService = $followService;
$this->instanceService = $instanceService;
$this->configService = $configService;
$this->miscService = $miscService;
@ -105,22 +139,24 @@ class ActivityPubService {
/**
* @param string $userId
*
* @param Core $item
* @param Core $activity
* @param ACore $item
* @param int $type
* @param ACore $activity
*
* @return array
* @throws ActorDoesNotExistException
* @throws NoUserException
* @throws RequestException
*/
public function createActivity($userId, Core $item, Core &$activity = null): array {
public function createActivity($userId, ACore $item, int $type, ACore &$activity = null
): array {
$activity = new Activity(true);
$activity = new ActivityCreate(true);
// $this->activityStreamsService->initCore($activity);
$actor = $this->actorService->getActorFromUserId($userId);
$activity->setObject($item);
$activity->setId($item->getId() . '/activity');
$activity->addInstancePaths($item->getInstancePaths());
// if ($item->getToArray() !== []) {
@ -129,30 +165,30 @@ class ActivityPubService {
// $activity->setTo($item->getTo());
// }
$actor = $this->actorService->getActorFromUserId($userId);
$activity->setActor($actor);
$activity->setObject($item);
$this->setupCore($activity);
$result = $this->request($activity);
$result = $this->request($activity, $type);
return $result;
}
/**
* @param Core $activity
* @param ACore $activity
*
* @return array
* @throws RequestException
*/
public function request(Core $activity) {
public function request(ACore $activity, int $type) {
$hosts = $this->instanceService->getInstancesFromActivity($activity);
$result = [];
foreach ($hosts as $host) {
foreach ($host->getInstancePaths() as $path) {
$result[] = $this->generateRequest($host->getAddress(), $path, $activity);
$result[] = $this->generateRequest($host->getAddress(), $path, $type, $activity);
}
}
@ -163,23 +199,24 @@ class ActivityPubService {
/**
* @param string $address
* @param InstancePath $path
* @param Core $activity
* @param ACore $activity
*
* @return Request[]
* @throws RequestException
*/
public function generateRequest(string $address, InstancePath $path, Core $activity): array {
public function generateRequest(string $address, InstancePath $path, int $type, ACore $activity
): array {
$document = json_encode($activity);
$date = date(self::DATE_FORMAT);
$date = gmdate(self::DATE_FORMAT);
//$date = str_replace('UTC', 'GMT', $date);
$localActor = $activity->getActor();
$remoteActor = $this->getRemoteActor($path->getUri());
// $remoteActor = $this->getRemoteActor($path->getUri());
$remotePath = $this->actorService->getPathFromActor($remoteActor, $path->getType());
// $remotePath = $this->personService->getPathFromActor($remoteActor, $path->getType());
$localActorLink =
$this->configService->getRoot() . '@' . $localActor->getPreferredUsername();
$signature = "(request-target): post " . $remotePath . "\nhost: " . $address
$signature = "(request-target): post " . $path->getPath() . "\nhost: " . $address
. "\ndate: " . $date;
openssl_sign($signature, $signed, $localActor->getPrivateKey(), OPENSSL_ALGO_SHA256);
@ -189,7 +226,11 @@ class ActivityPubService {
'keyId="' . $localActorLink . '",headers="(request-target) host date",signature="'
. $signed . '"';
$request = new Request($remotePath, Request::TYPE_POST);
if ($type === self::REQUEST_INBOX) {
$requestType = Request::TYPE_POST;
}
$request = new Request($path->getPath(), $requestType);
$request->addHeader('Host: ' . $address);
$request->addHeader('Date: ' . $date);
$request->addHeader('Signature: ' . $header);
@ -245,11 +286,11 @@ class ActivityPubService {
/**
* @param string $uriId
*
* @return Actor
* @return Person
* @throws RequestException
*/
private function getRemoteActor(string $uriId) {
$actor = $this->actorService->getFromUri($uriId);
$actor = $this->personService->getFromAccount($uriId);
return $actor;
}
@ -284,7 +325,7 @@ class ActivityPubService {
$signatureHeader = $request->getHeader('Signature');
$sign = $this->parseSignatureHeader($signatureHeader);
$this->miscService->mustContains(['keyId', 'headers', 'signature'], $sign);
$this->mustContains(['keyId', 'headers', 'signature'], $sign);
$keyId = $sign['keyId'];
$headers = $sign['headers'];
@ -360,9 +401,9 @@ class ActivityPubService {
/**
* @param Core $activity
* @param ACore $activity
*/
private function setupCore(Core $activity) {
private function setupCore(ACore $activity) {
// $this->initCore($activity);
if ($activity->isTopLevel()) {
@ -379,4 +420,46 @@ class ActivityPubService {
}
}
/**
* @param ACore $activity
*
* @throws UnknownItemException
*/
public function save(Acore $activity) {
if ($activity->gotObject()) {
$this->save($activity->getObject());
}
switch ($activity->getType()) {
// case 'Activity':
// $service = $this;
// break;
case 'Undo':
$service = $this->undoService;
break;
case 'Follow':
$service = $this->followService;
break;
case 'Note':
$service = $this->noteService;
break;
default:
throw new UnknownItemException();
}
try {
$service->save($activity);
} catch (Exception $e) {
$this->miscService->log(
2, 'Cannot save ' . $activity->getType() . ': ' . $e->getMessage()
);
}
}
}

Wyświetl plik

@ -34,32 +34,29 @@ use daita\MySmallPhpTools\Traits\TArrayTools;
use Exception;
use OC\User\NoUserException;
use OCA\Social\Db\ActorsRequest;
use OCA\Social\Db\CacheActorsRequest;
use OCA\Social\Exceptions\AccountAlreadyExistsException;
use OCA\Social\Exceptions\ActorDoesNotExistException;
use OCA\Social\Exceptions\CacheActorDoesNotExistException;
use OCA\Social\Exceptions\RequestException;
use OCA\Social\Model\ActivityPub\Actor;
use OCA\Social\Model\ActivityPub\Person;
use OCA\Social\Model\InstancePath;
/**
* Class ActorService
*
* @package OCA\Social\Service
*/
class ActorService {
use TArrayTools;
/** @var InstanceService */
private $instanceService;
/** @var ConfigService */
private $configService;
/** @var ActorsRequest */
private $actorsRequest;
/** @var CacheActorsRequest */
private $cacheActorsRequest;
/** @var MiscService */
private $miscService;
@ -68,20 +65,14 @@ class ActorService {
* ActorService constructor.
*
* @param ActorsRequest $actorsRequest
* @param CacheActorsRequest $cacheActorsRequest
* @param InstanceService $instanceService
* @param ConfigService $configService
* @param MiscService $miscService
*/
public function __construct(
ActorsRequest $actorsRequest,
CacheActorsRequest $cacheActorsRequest, InstanceService $instanceService,
ConfigService $configService, MiscService $miscService
ActorsRequest $actorsRequest, ConfigService $configService, MiscService $miscService
) {
$this->configService = $configService;
$this->instanceService = $instanceService;
$this->actorsRequest = $actorsRequest;
$this->cacheActorsRequest = $cacheActorsRequest;
$this->miscService = $miscService;
}
@ -89,11 +80,11 @@ class ActorService {
/**
* @param string $username
*
* @return Actor
* @return Person
* @throws ActorDoesNotExistException
*/
public function getActor(string $username): Actor {
public function getActor(string $username): Person {
$actor = $this->actorsRequest->getFromUsername($username);
return $actor;
@ -103,11 +94,11 @@ class ActorService {
/**
* @param string $userId
*
* @return Actor
* @return Person
* @throws ActorDoesNotExistException
* @throws NoUserException
*/
public function getActorFromUserId(string $userId): Actor {
public function getActorFromUserId(string $userId): Person {
$this->miscService->confirmUserId($userId);
$actor = $this->actorsRequest->getFromUserId($userId);
@ -115,67 +106,6 @@ class ActorService {
}
/**
* @param string $uriId
*
* @return Actor
* @throws RequestException
* @throws Exception
*/
public function getFromUri(string $uriId) {
try {
$cache = $this->cacheActorsRequest->getFromUrl($uriId);
return $this->generateActor($cache->getActor());
} catch (CacheActorDoesNotExistException $e) {
$object = $this->instanceService->retrieveObject($uriId);
$actor = $this->generateActor($object);
$this->cacheActorsRequest->create($actor, $object);
return $actor;
}
}
/**
* @param Actor $actor
* @param int $type
*
* @return string
*/
public function getPathFromActor(Actor $actor, int $type) {
switch ($type) {
case InstancePath::INBOX:
return parse_url($actor->getInbox(), PHP_URL_PATH);
}
return '';
}
/**
* @param array $object
*
* @return Actor
*/
public function generateActor(array $object) {
$actor = new Actor();
$actor->setId($this->get('id', $object));
$actor->setFollowers($this->get('followers', $object));
$actor->setFollowing($this->get('following', $object));
$actor->setInbox($this->get('inbox', $object));
$actor->setOutbox($this->get('outbox', $object));
$actor->setPublicKey($object['publicKey']['publicKeyPem']);
$actor->setPreferredUsername($this->get('preferredUsername', $object));
$actor->setAccount('@' . $actor->getPreferredUsername() . '@' . $object['_address']);
// $actor->setSharedInbox($this->get(''))
return $actor;
}
/**
@ -215,7 +145,7 @@ class ActorService {
$this->configService->setCoreValue('public_webfinger', 'social/lib/webfinger.php');
$actor = new Actor();
$actor = new Person();
$actor->setUserId($userId);
$actor->setPreferredUsername($username);
@ -233,10 +163,11 @@ class ActorService {
return;
}
/**
* @param Actor $actor
* @param Person $actor
*/
private function generateKeys(Actor &$actor) {
private function generateKeys(Person &$actor) {
$res = openssl_pkey_new(
[
"digest_alg" => "rsa",

Wyświetl plik

@ -29,25 +29,29 @@ declare(strict_types=1);
namespace OCA\Social\Service;
use daita\MySmallPhpTools\Traits\TPathTools;
use OCA\Social\AppInfo\Application;
use OCP\IConfig;
use OCP\IRequest;
use OCP\IURLGenerator;
use OCP\PreConditionNotMetException;
/**
* Class ConfigService
*
* @package OCA\Social\Service
*/
class ConfigService {
use TPathTools;
/** @var array */
public $defaults = [
];
// public $serviceTypes = [
// [
// 'id' => 'mastodon',
// 'name' => 'Mastodon (OAuth2)'
// ]
// ];
/** @var string */
private $userId;
@ -57,6 +61,9 @@ class ConfigService {
/** @var IRequest */
private $request;
/** @var IURLGenerator */
private $urlGenerator;
/** @var MiscService */
private $miscService;
@ -67,15 +74,17 @@ class ConfigService {
* @param string $userId
* @param IConfig $config
* @param IRequest $request
* @param IURLGenerator $urlGenerator
* @param MiscService $miscService
*/
public function __construct(
$userId, IConfig $config, IRequest $request,
$userId, IConfig $config, IRequest $request, IURLGenerator $urlGenerator,
MiscService $miscService
) {
$this->userId = $userId;
$this->config = $config;
$this->request = $request;
$this->urlGenerator = $urlGenerator;
$this->miscService = $miscService;
}
@ -202,9 +211,12 @@ class ConfigService {
/**
* @return string
* // TODO: improve this !
*/
public function getRoot(): string {
return 'https://test.artificial-owl.com/apps/social/';
// $this->urlGenerator->linkToRoute('social.Navigation.navigate');
return $this->withoutEndSlash($this->getSystemValue('overwrite.cli.url'), false, false)
. '/apps/social/';
}
@ -215,7 +227,7 @@ class ConfigService {
* @return string
*/
public function generateId(string $path = '', $generateId = true): string {
$this->miscService->formatPath($path);
$path = $this->withoutBeginSlash($this->withEndSlash($path));
$id = $this->getRoot() . $path;
if ($generateId === true) {

Wyświetl plik

@ -114,11 +114,10 @@ class CurlService {
*/
private function generateCurlRequest(Request $request) {
$url = 'https://' . $request->getAddress() . $request->getParsedUrl();
// echo 'curl: ' . $request->getUrl() . "\n";
if ($request->getType() !== Request::TYPE_GET) {
$curl = curl_init($url);
} else {
$curl = curl_init($url . '?' . $request->getDataBody());
$curl = curl_init($url . '?' . $request->getUrlData());
}
return $curl;

Wyświetl plik

@ -30,10 +30,10 @@ declare(strict_types=1);
namespace OCA\Social\Service;
use OCA\Social\Model\ActivityPub\Core;
use OCA\Social\Model\ActivityPub\ACore;
interface ICoreService {
public function save(Core $core);
public function save(ACore $core);
}

Wyświetl plik

@ -0,0 +1,123 @@
<?php
declare(strict_types=1);
/**
* Nextcloud - Social Support
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Social\Service;
use daita\MySmallPhpTools\Traits\TArrayTools;
use OCA\Social\Exceptions\UnknownItemException;
use OCA\Social\Model\ActivityPub\ACore;
use OCA\Social\Model\ActivityPub\Activity;
use OCA\Social\Model\ActivityPub\Follow;
use OCA\Social\Model\ActivityPub\Note;
use OCA\Social\Model\ActivityPub\Undo;
class ImportService {
use TArrayTools;
/** @var MiscService */
private $miscService;
/**
* ActorService constructor.
*
* @param MiscService $miscService
*/
public function __construct(MiscService $miscService) {
$this->miscService = $miscService;
}
/**
* @param string $json
*
* @return ACore
* @throws UnknownItemException
*/
public function import(string $json) {
$data = json_decode($json, true);
$activity = $this->createItem($data, null);
return $activity;
}
/**
* @param array $data
* @param ACore $root
*
* @return ACore
* @throws UnknownItemException
*/
private function createItem(array $data, $root = null): ACore {
$isTopLevel = ($root === null);
switch ($this->get('type', $data)) {
case 'Create':
$item = new Activity($isTopLevel);
break;
case 'Note':
$item = new Note($isTopLevel);
break;
case 'Follow':
$item = new Follow($isTopLevel);
break;
case 'Undo':
$item = new Undo($isTopLevel);
break;
default:
throw new UnknownItemException();
}
if ($root instanceof ACore) {
$item->setMetaAll($root->getMetaAll());
}
$item->import($data);
try {
$object = $this->createItem($this->getArray('object', $data, []), $item);
$item->setObject($object);
} catch (UnknownItemException $e) {
}
return $item;
}
}

Wyświetl plik

@ -30,15 +30,22 @@ declare(strict_types=1);
namespace OCA\Social\Service;
use daita\MySmallPhpTools\Exceptions\ArrayNotFoundException;
use daita\MySmallPhpTools\Model\Request;
use daita\MySmallPhpTools\Traits\TArrayTools;
use daita\MySmallPhpTools\Traits\TPathTools;
use OCA\Social\Exceptions\RequestException;
use OCA\Social\Model\ActivityPub\Core;
use OCA\Social\Model\ActivityPub\ACore;
use OCA\Social\Model\Instance;
use OCA\Social\Model\InstancePath;
class InstanceService {
use TPathTools;
use TArrayTools;
/** @var ConfigService */
private $configService;
@ -65,6 +72,32 @@ class InstanceService {
}
/**
* @param string $account
*
* @return mixed
* @throws RequestException
*/
public function retrieveAccount(string $account) {
$account = $this->withoutBeginAt($account);
list($username, $host) = explode('@', $account);
$request = new Request('/.well-known/webfinger');
$request->addData('resource', 'acct:' . $account);
$request->setAddress($host);
$result = $this->curlService->request($request);
try {
$link = $this->extractArray('rel', 'self', $this->getArray('links', $result));
} catch (ArrayNotFoundException $e) {
throw new RequestException();
}
return $this->retrieveObject($this->get('href', $link, ''));
}
/**
* @param $id
*
@ -73,7 +106,6 @@ class InstanceService {
*/
public function retrieveObject($id) {
$url = parse_url($id);
$request = new Request($url['path'], Request::TYPE_GET);
$request->setAddress($url['host']);
@ -84,12 +116,13 @@ class InstanceService {
/**
* @param Core $activity
* @param ACore $activity
*
* @return Instance[]
*/
public function getInstancesFromActivity(Core $activity): array {
public function getInstancesFromActivity(ACore $activity): array {
$instances = [];
foreach ($activity->getInstancePaths() as $instancePath) {
$this->addInstances($instancePath, $instances);
// $uriIds[] = $to;
@ -105,6 +138,7 @@ class InstanceService {
*/
private function addInstances(InstancePath $instancePath, array &$instances) {
$address = $this->getHostFromUriId($instancePath->getUri());
if ($address === '') {
return;
}

Wyświetl plik

@ -27,14 +27,22 @@ declare(strict_types=1);
*
*/
namespace OCA\Social\Service;
use Exception;
use OC\User\NoUserException;
use OCA\Social\AppInfo\Application;
use OCP\ILogger;
use OCP\IUserManager;
/**
* Class MiscService
*
* @package OCA\Social\Service
*/
class MiscService {
@ -71,47 +79,6 @@ class MiscService {
}
/**
* @param array $keys
* @param array $arr
*
* @throws Exception
*/
public function mustContains(array $keys, array $arr) {
foreach ($keys as $key) {
if (!array_key_exists($key, $arr)) {
throw new Exception('missing elements');
}
}
}
public static function noEndSlash($path) {
if (substr($path, -1) === '/') {
$path = substr($path, 0, -1);
}
return $path;
}
/**
* @param string $path
*/
public function formatPath(string &$path) {
if ($path === '') {
return;
}
if (substr($path, 0, 1) === '/') {
$path = substr($path, 1);
}
if (substr($path, -1) !== '/') {
$path .= '/';
}
}
/**
* @param string $userId
*

Wyświetl plik

@ -0,0 +1,93 @@
<?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 OC\User\NoUserException;
use OCA\Social\Exceptions\ActorDoesNotExistException;
use OCA\Social\Exceptions\RequestException;
use OCA\Social\Model\ActivityPub\ACore;
use OCA\Social\Model\InstancePath;
use OCA\Social\Model\Post;
use OCA\Social\Service\ActivityPub\NoteService;
class PostService {
/** @var NoteService */
private $noteService;
/** @var ActivityService */
private $activityService;
/** @var MiscService */
private $miscService;
/**
* PostService constructor.
*
* @param NoteService $noteService
* @param ActivityService $activityService
* @param MiscService $miscService
*/
public function __construct(
NoteService $noteService, ActivityService $activityService, MiscService $miscService
) {
$this->noteService = $noteService;
$this->activityService = $activityService;
$this->miscService = $miscService;
}
/**
* @param Post $post
* @param ACore $activity
*
* @return array
* @throws ActorDoesNotExistException
* @throws NoUserException
* @throws RequestException
*/
public function createPost(Post $post, ACore &$activity = null) {
$note =
$this->noteService->generateNote($post->getUserId(), $post->getContent());
$this->noteService->assignToArray($note, $post->getTo());
$this->noteService->replyTo($note, $post->getReplyTo());
return $this->activityService->createActivity(
$post->getUserId(), $note, ActivityService::REQUEST_INBOX, $activity
);
}
}